|  | @@ -18,10 +18,9 @@
 | 
		
	
		
			
			| 18 | 18 |  
 | 
		
	
		
			
			| 19 | 19 |  #include <stdint.h>
 | 
		
	
		
			
			| 20 | 20 |  #include <string.h>
 | 
		
	
		
			
			| 21 |  | -#include <stdio.h>
 | 
		
	
		
			
			| 22 | 21 |  #include <errno.h>
 | 
		
	
		
			
			|  | 22 | +#include <assert.h>
 | 
		
	
		
			
			| 23 | 23 |  #include <gpxe/uaccess.h>
 | 
		
	
		
			
			| 24 |  | -#include <gpxe/uuid.h>
 | 
		
	
		
			
			| 25 | 24 |  #include <realmode.h>
 | 
		
	
		
			
			| 26 | 25 |  #include <pnpbios.h>
 | 
		
	
		
			
			| 27 | 26 |  #include <smbios.h>
 | 
		
	
	
		
			
			|  | @@ -51,7 +50,7 @@ struct smbios_entry {
 | 
		
	
		
			
			| 51 | 50 |  	/** Checksum */
 | 
		
	
		
			
			| 52 | 51 |  	uint8_t checksum;
 | 
		
	
		
			
			| 53 | 52 |  	/** Length */
 | 
		
	
		
			
			| 54 |  | -	uint8_t length;
 | 
		
	
		
			
			|  | 53 | +	uint8_t len;
 | 
		
	
		
			
			| 55 | 54 |  	/** Major version */
 | 
		
	
		
			
			| 56 | 55 |  	uint8_t major;
 | 
		
	
		
			
			| 57 | 56 |  	/** Minor version */
 | 
		
	
	
		
			
			|  | @@ -67,7 +66,7 @@ struct smbios_entry {
 | 
		
	
		
			
			| 67 | 66 |  	/** DMI checksum */
 | 
		
	
		
			
			| 68 | 67 |  	uint8_t dmi_checksum;
 | 
		
	
		
			
			| 69 | 68 |  	/** Structure table length */
 | 
		
	
		
			
			| 70 |  | -	uint16_t smbios_length;
 | 
		
	
		
			
			|  | 69 | +	uint16_t smbios_len;
 | 
		
	
		
			
			| 71 | 70 |  	/** Structure table address */
 | 
		
	
		
			
			| 72 | 71 |  	physaddr_t smbios_address;
 | 
		
	
		
			
			| 73 | 72 |  	/** Number of SMBIOS structures */
 | 
		
	
	
		
			
			|  | @@ -86,49 +85,37 @@ struct smbios {
 | 
		
	
		
			
			| 86 | 85 |  	/** Start of SMBIOS structures */
 | 
		
	
		
			
			| 87 | 86 |  	userptr_t address;
 | 
		
	
		
			
			| 88 | 87 |  	/** Length of SMBIOS structures */ 
 | 
		
	
		
			
			| 89 |  | -	size_t length;
 | 
		
	
		
			
			|  | 88 | +	size_t len;
 | 
		
	
		
			
			| 90 | 89 |  	/** Number of SMBIOS structures */
 | 
		
	
		
			
			| 91 | 90 |  	unsigned int count;
 | 
		
	
		
			
			| 92 | 91 |  };
 | 
		
	
		
			
			| 93 | 92 |  
 | 
		
	
		
			
			| 94 |  | -/**
 | 
		
	
		
			
			| 95 |  | - * SMBIOS strings descriptor
 | 
		
	
		
			
			| 96 |  | - *
 | 
		
	
		
			
			| 97 |  | - * This is returned as part of the search for an SMBIOS structure, and
 | 
		
	
		
			
			| 98 |  | - * contains the information needed for extracting the strings within
 | 
		
	
		
			
			| 99 |  | - * the "unformatted" portion of the structure.
 | 
		
	
		
			
			| 100 |  | - */
 | 
		
	
		
			
			| 101 |  | -struct smbios_strings {
 | 
		
	
		
			
			| 102 |  | -	/** Start of strings data */
 | 
		
	
		
			
			| 103 |  | -	userptr_t data;
 | 
		
	
		
			
			| 104 |  | -	/** Length of strings data */
 | 
		
	
		
			
			| 105 |  | -	size_t length;
 | 
		
	
		
			
			|  | 93 | +/** SMBIOS entry point descriptor */
 | 
		
	
		
			
			|  | 94 | +static struct smbios smbios = {
 | 
		
	
		
			
			|  | 95 | +	.address = UNULL,
 | 
		
	
		
			
			| 106 | 96 |  };
 | 
		
	
		
			
			| 107 | 97 |  
 | 
		
	
		
			
			| 108 | 98 |  /**
 | 
		
	
		
			
			| 109 | 99 |   * Find SMBIOS
 | 
		
	
		
			
			| 110 | 100 |   *
 | 
		
	
		
			
			| 111 |  | - * @ret smbios		SMBIOS entry point descriptor, or NULL if not found
 | 
		
	
		
			
			|  | 101 | + * @ret rc		Return status code
 | 
		
	
		
			
			| 112 | 102 |   */
 | 
		
	
		
			
			| 113 |  | -static struct smbios * find_smbios ( void ) {
 | 
		
	
		
			
			| 114 |  | -	static struct smbios smbios = {
 | 
		
	
		
			
			| 115 |  | -		.address = UNULL,
 | 
		
	
		
			
			| 116 |  | -	};
 | 
		
	
		
			
			|  | 103 | +static int find_smbios ( void ) {
 | 
		
	
		
			
			| 117 | 104 |  	union {
 | 
		
	
		
			
			| 118 | 105 |  		struct smbios_entry entry;
 | 
		
	
		
			
			| 119 | 106 |  		uint8_t bytes[256]; /* 256 is maximum length possible */
 | 
		
	
		
			
			| 120 | 107 |  	} u;
 | 
		
	
		
			
			| 121 |  | -	unsigned int offset;
 | 
		
	
		
			
			|  | 108 | +	static unsigned int offset = 0;
 | 
		
	
		
			
			| 122 | 109 |  	size_t len;
 | 
		
	
		
			
			| 123 | 110 |  	unsigned int i;
 | 
		
	
		
			
			| 124 | 111 |  	uint8_t sum;
 | 
		
	
		
			
			| 125 | 112 |  
 | 
		
	
		
			
			| 126 |  | -	/* Return cached result if available */
 | 
		
	
		
			
			|  | 113 | +	/* Return cached result if avaiable */
 | 
		
	
		
			
			| 127 | 114 |  	if ( smbios.address != UNULL )
 | 
		
	
		
			
			| 128 |  | -		return &smbios;
 | 
		
	
		
			
			|  | 115 | +		return 0;
 | 
		
	
		
			
			| 129 | 116 |  
 | 
		
	
		
			
			| 130 | 117 |  	/* Try to find SMBIOS */
 | 
		
	
		
			
			| 131 |  | -	for ( offset = 0 ; offset < 0x10000 ; offset += 0x10 ) {
 | 
		
	
		
			
			|  | 118 | +	for ( ; offset < 0x10000 ; offset += 0x10 ) {
 | 
		
	
		
			
			| 132 | 119 |  
 | 
		
	
		
			
			| 133 | 120 |  		/* Read start of header and verify signature */
 | 
		
	
		
			
			| 134 | 121 |  		copy_from_real ( &u.entry, BIOS_SEG, offset,
 | 
		
	
	
		
			
			|  | @@ -137,7 +124,7 @@ static struct smbios * find_smbios ( void ) {
 | 
		
	
		
			
			| 137 | 124 |  			continue;
 | 
		
	
		
			
			| 138 | 125 |  
 | 
		
	
		
			
			| 139 | 126 |  		/* Read whole header and verify checksum */
 | 
		
	
		
			
			| 140 |  | -		len = u.entry.length;
 | 
		
	
		
			
			|  | 127 | +		len = u.entry.len;
 | 
		
	
		
			
			| 141 | 128 |  		copy_from_real ( &u.bytes, BIOS_SEG, offset, len );
 | 
		
	
		
			
			| 142 | 129 |  		for ( i = 0 , sum = 0 ; i < len ; i++ ) {
 | 
		
	
		
			
			| 143 | 130 |  			sum += u.bytes[i];
 | 
		
	
	
		
			
			|  | @@ -152,29 +139,27 @@ static struct smbios * find_smbios ( void ) {
 | 
		
	
		
			
			| 152 | 139 |  		DBG ( "Found SMBIOS entry point at %04x:%04x\n",
 | 
		
	
		
			
			| 153 | 140 |  		      BIOS_SEG, offset );
 | 
		
	
		
			
			| 154 | 141 |  		smbios.address = phys_to_user ( u.entry.smbios_address );
 | 
		
	
		
			
			| 155 |  | -		smbios.length = u.entry.smbios_length;
 | 
		
	
		
			
			|  | 142 | +		smbios.len = u.entry.smbios_len;
 | 
		
	
		
			
			| 156 | 143 |  		smbios.count = u.entry.smbios_count;
 | 
		
	
		
			
			| 157 |  | -		return &smbios;
 | 
		
	
		
			
			|  | 144 | +		return 0;
 | 
		
	
		
			
			| 158 | 145 |  	}
 | 
		
	
		
			
			| 159 | 146 |  
 | 
		
	
		
			
			| 160 | 147 |  	DBG ( "No SMBIOS found\n" );
 | 
		
	
		
			
			| 161 |  | -	return NULL;
 | 
		
	
		
			
			|  | 148 | +	return -ENODEV;
 | 
		
	
		
			
			| 162 | 149 |  }
 | 
		
	
		
			
			| 163 | 150 |  
 | 
		
	
		
			
			| 164 | 151 |  /**
 | 
		
	
		
			
			| 165 | 152 |   * Find SMBIOS strings terminator
 | 
		
	
		
			
			| 166 | 153 |   *
 | 
		
	
		
			
			| 167 |  | - * @v smbios		SMBIOS entry point descriptor
 | 
		
	
		
			
			| 168 | 154 |   * @v offset		Offset to start of strings
 | 
		
	
		
			
			| 169 | 155 |   * @ret offset		Offset to strings terminator, or 0 if not found
 | 
		
	
		
			
			| 170 | 156 |   */
 | 
		
	
		
			
			| 171 |  | -static size_t find_strings_terminator ( struct smbios *smbios,
 | 
		
	
		
			
			| 172 |  | -					size_t offset ) {
 | 
		
	
		
			
			| 173 |  | -	size_t max_offset = ( smbios->length - 2 );
 | 
		
	
		
			
			|  | 157 | +static size_t find_strings_terminator ( size_t offset ) {
 | 
		
	
		
			
			|  | 158 | +	size_t max_offset = ( smbios.len - 2 );
 | 
		
	
		
			
			| 174 | 159 |  	uint16_t nulnul;
 | 
		
	
		
			
			| 175 | 160 |  
 | 
		
	
		
			
			| 176 | 161 |  	for ( ; offset <= max_offset ; offset++ ) {
 | 
		
	
		
			
			| 177 |  | -		copy_from_user ( &nulnul, smbios->address, offset, 2 );
 | 
		
	
		
			
			|  | 162 | +		copy_from_user ( &nulnul, smbios.address, offset, 2 );
 | 
		
	
		
			
			| 178 | 163 |  		if ( nulnul == 0 )
 | 
		
	
		
			
			| 179 | 164 |  			return ( offset + 1 );
 | 
		
	
		
			
			| 180 | 165 |  	}
 | 
		
	
	
		
			
			|  | @@ -185,66 +170,52 @@ static size_t find_strings_terminator ( struct smbios *smbios,
 | 
		
	
		
			
			| 185 | 170 |   * Find specific structure type within SMBIOS
 | 
		
	
		
			
			| 186 | 171 |   *
 | 
		
	
		
			
			| 187 | 172 |   * @v type		Structure type to search for
 | 
		
	
		
			
			| 188 |  | - * @v structure		Buffer to fill in with structure
 | 
		
	
		
			
			| 189 |  | - * @v length		Length of buffer
 | 
		
	
		
			
			| 190 |  | - * @v strings		Strings descriptor to fill in, or NULL
 | 
		
	
		
			
			|  | 173 | + * @v structure		SMBIOS structure descriptor to fill in
 | 
		
	
		
			
			| 191 | 174 |   * @ret rc		Return status code
 | 
		
	
		
			
			| 192 | 175 |   */
 | 
		
	
		
			
			| 193 |  | -int find_smbios_structure ( unsigned int type, void *structure,
 | 
		
	
		
			
			| 194 |  | -			    size_t length, struct smbios_strings *strings ) {
 | 
		
	
		
			
			| 195 |  | -	struct smbios *smbios;
 | 
		
	
		
			
			| 196 |  | -	struct smbios_header header;
 | 
		
	
		
			
			| 197 |  | -	struct smbios_strings temp_strings;
 | 
		
	
		
			
			|  | 176 | +int find_smbios_structure ( unsigned int type,
 | 
		
	
		
			
			|  | 177 | +			    struct smbios_structure *structure ) {
 | 
		
	
		
			
			| 198 | 178 |  	unsigned int count = 0;
 | 
		
	
		
			
			| 199 | 179 |  	size_t offset = 0;
 | 
		
	
		
			
			| 200 | 180 |  	size_t strings_offset;
 | 
		
	
		
			
			| 201 | 181 |  	size_t terminator_offset;
 | 
		
	
		
			
			|  | 182 | +	int rc;
 | 
		
	
		
			
			| 202 | 183 |  
 | 
		
	
		
			
			| 203 |  | -	/* Locate SMBIOS entry point */
 | 
		
	
		
			
			| 204 |  | -	if ( ! ( smbios = find_smbios() ) )
 | 
		
	
		
			
			| 205 |  | -		return -ENOENT;
 | 
		
	
		
			
			| 206 |  | -
 | 
		
	
		
			
			| 207 |  | -	/* Ensure that we have a usable strings descriptor buffer */
 | 
		
	
		
			
			| 208 |  | -	if ( ! strings )
 | 
		
	
		
			
			| 209 |  | -		strings = &temp_strings;
 | 
		
	
		
			
			|  | 184 | +	/* Find SMBIOS */
 | 
		
	
		
			
			|  | 185 | +	if ( ( rc = find_smbios() ) != 0 )
 | 
		
	
		
			
			|  | 186 | +		return rc;
 | 
		
	
		
			
			| 210 | 187 |  
 | 
		
	
		
			
			| 211 | 188 |  	/* Scan through list of structures */
 | 
		
	
		
			
			| 212 |  | -	while ( ( ( offset + sizeof ( header ) ) < smbios->length ) &&
 | 
		
	
		
			
			| 213 |  | -		( count < smbios->count ) ) {
 | 
		
	
		
			
			|  | 189 | +	while ( ( ( offset + sizeof ( structure->header ) ) < smbios.len )
 | 
		
	
		
			
			|  | 190 | +		&& ( count < smbios.count ) ) {
 | 
		
	
		
			
			| 214 | 191 |  
 | 
		
	
		
			
			| 215 | 192 |  		/* Read next SMBIOS structure header */
 | 
		
	
		
			
			| 216 |  | -		copy_from_user ( &header, smbios->address, offset,
 | 
		
	
		
			
			| 217 |  | -				 sizeof ( header ) );
 | 
		
	
		
			
			|  | 193 | +		copy_from_user ( &structure->header, smbios.address, offset,
 | 
		
	
		
			
			|  | 194 | +				 sizeof ( structure->header ) );
 | 
		
	
		
			
			| 218 | 195 |  
 | 
		
	
		
			
			| 219 | 196 |  		/* Determine start and extent of strings block */
 | 
		
	
		
			
			| 220 |  | -		strings_offset = ( offset + header.length );
 | 
		
	
		
			
			| 221 |  | -		if ( strings_offset > smbios->length ) {
 | 
		
	
		
			
			|  | 197 | +		strings_offset = ( offset + structure->header.len );
 | 
		
	
		
			
			|  | 198 | +		if ( strings_offset > smbios.len ) {
 | 
		
	
		
			
			| 222 | 199 |  			DBG ( "SMBIOS structure at offset %zx with length "
 | 
		
	
		
			
			| 223 | 200 |  			      "%x extends beyond SMBIOS\n", offset,
 | 
		
	
		
			
			| 224 |  | -			      header.length );
 | 
		
	
		
			
			|  | 201 | +			      structure->header.len );
 | 
		
	
		
			
			| 225 | 202 |  			return -ENOENT;
 | 
		
	
		
			
			| 226 | 203 |  		}
 | 
		
	
		
			
			| 227 |  | -		terminator_offset =
 | 
		
	
		
			
			| 228 |  | -			find_strings_terminator ( smbios, strings_offset );
 | 
		
	
		
			
			|  | 204 | +		terminator_offset = find_strings_terminator ( strings_offset );
 | 
		
	
		
			
			| 229 | 205 |  		if ( ! terminator_offset ) {
 | 
		
	
		
			
			| 230 | 206 |  			DBG ( "SMBIOS structure at offset %zx has "
 | 
		
	
		
			
			| 231 | 207 |  			      "unterminated strings section\n", offset );
 | 
		
	
		
			
			| 232 | 208 |  			return -ENOENT;
 | 
		
	
		
			
			| 233 | 209 |  		}
 | 
		
	
		
			
			| 234 |  | -		strings->data = userptr_add ( smbios->address,
 | 
		
	
		
			
			| 235 |  | -					      strings_offset );
 | 
		
	
		
			
			| 236 |  | -		strings->length = ( terminator_offset - strings_offset );
 | 
		
	
		
			
			|  | 210 | +		structure->strings_len = ( terminator_offset - strings_offset);
 | 
		
	
		
			
			| 237 | 211 |  
 | 
		
	
		
			
			| 238 |  | -		DBG ( "SMBIOS structure at offset %zx has type %d, "
 | 
		
	
		
			
			| 239 |  | -		      "length %x, strings length %zx\n",
 | 
		
	
		
			
			| 240 |  | -		      offset, header.type, header.length, strings->length );
 | 
		
	
		
			
			|  | 212 | +		DBG ( "SMBIOS structure at offset %zx has type %d, length %x, "
 | 
		
	
		
			
			|  | 213 | +		      "strings length %zx\n", offset, structure->header.type,
 | 
		
	
		
			
			|  | 214 | +		      structure->header.len, structure->strings_len );
 | 
		
	
		
			
			| 241 | 215 |  
 | 
		
	
		
			
			| 242 | 216 |  		/* If this is the structure we want, return */
 | 
		
	
		
			
			| 243 |  | -		if ( header.type == type ) {
 | 
		
	
		
			
			| 244 |  | -			if ( length > header.length )
 | 
		
	
		
			
			| 245 |  | -				length = header.length;
 | 
		
	
		
			
			| 246 |  | -			copy_from_user ( structure, smbios->address,
 | 
		
	
		
			
			| 247 |  | -					 offset, length );
 | 
		
	
		
			
			|  | 217 | +		if ( structure->header.type == type ) {
 | 
		
	
		
			
			|  | 218 | +			structure->offset = offset;
 | 
		
	
		
			
			| 248 | 219 |  			return 0;
 | 
		
	
		
			
			| 249 | 220 |  		}
 | 
		
	
		
			
			| 250 | 221 |  
 | 
		
	
	
		
			
			|  | @@ -257,67 +228,65 @@ int find_smbios_structure ( unsigned int type, void *structure,
 | 
		
	
		
			
			| 257 | 228 |  	return -ENOENT;
 | 
		
	
		
			
			| 258 | 229 |  }
 | 
		
	
		
			
			| 259 | 230 |  
 | 
		
	
		
			
			|  | 231 | +/**
 | 
		
	
		
			
			|  | 232 | + * Copy SMBIOS structure
 | 
		
	
		
			
			|  | 233 | + *
 | 
		
	
		
			
			|  | 234 | + * @v structure		SMBIOS structure descriptor
 | 
		
	
		
			
			|  | 235 | + * @v data		Buffer to hold SMBIOS structure
 | 
		
	
		
			
			|  | 236 | + * @v len		Length of buffer
 | 
		
	
		
			
			|  | 237 | + * @ret rc		Return status code
 | 
		
	
		
			
			|  | 238 | + */
 | 
		
	
		
			
			|  | 239 | +int read_smbios_structure ( struct smbios_structure *structure,
 | 
		
	
		
			
			|  | 240 | +			    void *data, size_t len ) {
 | 
		
	
		
			
			|  | 241 | +
 | 
		
	
		
			
			|  | 242 | +	assert ( smbios.address != UNULL );
 | 
		
	
		
			
			|  | 243 | +
 | 
		
	
		
			
			|  | 244 | +	if ( len > structure->header.len )
 | 
		
	
		
			
			|  | 245 | +		len = structure->header.len;
 | 
		
	
		
			
			|  | 246 | +	copy_from_user ( data, smbios.address, structure->offset, len );
 | 
		
	
		
			
			|  | 247 | +	return 0;
 | 
		
	
		
			
			|  | 248 | +}
 | 
		
	
		
			
			|  | 249 | +
 | 
		
	
		
			
			| 260 | 250 |  /**
 | 
		
	
		
			
			| 261 | 251 |   * Find indexed string within SMBIOS structure
 | 
		
	
		
			
			| 262 | 252 |   *
 | 
		
	
		
			
			| 263 |  | - * @v strings		SMBIOS strings descriptor
 | 
		
	
		
			
			|  | 253 | + * @v structure		SMBIOS structure descriptor
 | 
		
	
		
			
			| 264 | 254 |   * @v index		String index
 | 
		
	
		
			
			| 265 |  | - * @v buffer		Buffer for string
 | 
		
	
		
			
			| 266 |  | - * @v length		Length of string buffer
 | 
		
	
		
			
			| 267 |  | - * @ret rc		Return status code
 | 
		
	
		
			
			|  | 255 | + * @v data		Buffer for string
 | 
		
	
		
			
			|  | 256 | + * @v len		Length of string buffer
 | 
		
	
		
			
			|  | 257 | + * @ret rc		Length of string, or negative error
 | 
		
	
		
			
			| 268 | 258 |   */
 | 
		
	
		
			
			| 269 |  | -int find_smbios_string ( struct smbios_strings *strings, unsigned int index,
 | 
		
	
		
			
			| 270 |  | -			 char *buffer, size_t length ) {
 | 
		
	
		
			
			| 271 |  | -	size_t offset = 0;
 | 
		
	
		
			
			|  | 259 | +int read_smbios_string ( struct smbios_structure *structure,
 | 
		
	
		
			
			|  | 260 | +			 unsigned int index, void *data, size_t len ) {
 | 
		
	
		
			
			|  | 261 | +	size_t strings_start = ( structure->offset + structure->header.len );
 | 
		
	
		
			
			|  | 262 | +	size_t strings_end = ( strings_start + structure->strings_len );
 | 
		
	
		
			
			|  | 263 | +	size_t offset;
 | 
		
	
		
			
			| 272 | 264 |  	size_t string_len;
 | 
		
	
		
			
			| 273 | 265 |  
 | 
		
	
		
			
			| 274 |  | -	/* Zero buffer.  This ensures that a valid NUL terminator is
 | 
		
	
		
			
			| 275 |  | -	 * always present (unless length==0).
 | 
		
	
		
			
			| 276 |  | -	 */
 | 
		
	
		
			
			| 277 |  | -	memset ( buffer, 0, length );
 | 
		
	
		
			
			| 278 |  | -	   
 | 
		
	
		
			
			|  | 266 | +	assert ( smbios.address != UNULL );
 | 
		
	
		
			
			|  | 267 | +
 | 
		
	
		
			
			| 279 | 268 |  	/* String numbers start at 1 (0 is used to indicate "no string") */
 | 
		
	
		
			
			| 280 | 269 |  	if ( ! index )
 | 
		
	
		
			
			| 281 |  | -		return 0;
 | 
		
	
		
			
			|  | 270 | +		return -ENOENT;
 | 
		
	
		
			
			| 282 | 271 |  
 | 
		
	
		
			
			| 283 |  | -	while ( offset < strings->length ) {
 | 
		
	
		
			
			|  | 272 | +	for ( offset = strings_start ; offset < strings_end ;
 | 
		
	
		
			
			|  | 273 | +	      offset += ( string_len + 1 ) ) {
 | 
		
	
		
			
			| 284 | 274 |  		/* Get string length.  This is known safe, since the
 | 
		
	
		
			
			| 285 | 275 |  		 * smbios_strings struct is constructed so as to
 | 
		
	
		
			
			| 286 | 276 |  		 * always end on a string boundary.
 | 
		
	
		
			
			| 287 | 277 |  		 */
 | 
		
	
		
			
			| 288 |  | -		string_len = strlen_user ( strings->data, offset );
 | 
		
	
		
			
			|  | 278 | +		string_len = strlen_user ( smbios.address,
 | 
		
	
		
			
			|  | 279 | +					   ( structure->offset + offset ) );
 | 
		
	
		
			
			| 289 | 280 |  		if ( --index == 0 ) {
 | 
		
	
		
			
			| 290 | 281 |  			/* Copy string, truncating as necessary. */
 | 
		
	
		
			
			| 291 |  | -			if ( string_len >= length )
 | 
		
	
		
			
			| 292 |  | -				string_len = ( length - 1 );
 | 
		
	
		
			
			| 293 |  | -			copy_from_user ( buffer, strings->data,
 | 
		
	
		
			
			| 294 |  | -					 offset, string_len );
 | 
		
	
		
			
			| 295 |  | -			return 0;
 | 
		
	
		
			
			|  | 282 | +			if ( len > string_len )
 | 
		
	
		
			
			|  | 283 | +				len = string_len;
 | 
		
	
		
			
			|  | 284 | +			copy_from_user ( data, smbios.address,
 | 
		
	
		
			
			|  | 285 | +					 ( structure->offset + offset ), len );
 | 
		
	
		
			
			|  | 286 | +			return string_len;
 | 
		
	
		
			
			| 296 | 287 |  		}
 | 
		
	
		
			
			| 297 |  | -		offset += ( string_len + 1 );
 | 
		
	
		
			
			| 298 | 288 |  	}
 | 
		
	
		
			
			| 299 | 289 |  
 | 
		
	
		
			
			| 300 | 290 |  	DBG ( "SMBIOS string index %d not found\n", index );
 | 
		
	
		
			
			| 301 | 291 |  	return -ENOENT;
 | 
		
	
		
			
			| 302 | 292 |  }
 | 
		
	
		
			
			| 303 |  | -
 | 
		
	
		
			
			| 304 |  | -/**
 | 
		
	
		
			
			| 305 |  | - * Get UUID from SMBIOS
 | 
		
	
		
			
			| 306 |  | - *
 | 
		
	
		
			
			| 307 |  | - * @v uuid		UUID to fill in
 | 
		
	
		
			
			| 308 |  | - * @ret rc		Return status code
 | 
		
	
		
			
			| 309 |  | - */
 | 
		
	
		
			
			| 310 |  | -int smbios_get_uuid ( union uuid *uuid ) {
 | 
		
	
		
			
			| 311 |  | -	struct smbios_system_information sysinfo;
 | 
		
	
		
			
			| 312 |  | -	int rc;
 | 
		
	
		
			
			| 313 |  | -
 | 
		
	
		
			
			| 314 |  | -	if ( ( rc = find_smbios_structure ( SMBIOS_TYPE_SYSTEM_INFORMATION,
 | 
		
	
		
			
			| 315 |  | -					    &sysinfo, sizeof ( sysinfo ),
 | 
		
	
		
			
			| 316 |  | -					    NULL ) ) != 0 )
 | 
		
	
		
			
			| 317 |  | -		return rc;
 | 
		
	
		
			
			| 318 |  | -
 | 
		
	
		
			
			| 319 |  | -	memcpy ( uuid, sysinfo.uuid, sizeof ( *uuid ) );
 | 
		
	
		
			
			| 320 |  | -	DBG ( "SMBIOS found UUID %s\n", uuid_ntoa ( uuid ) );
 | 
		
	
		
			
			| 321 |  | -
 | 
		
	
		
			
			| 322 |  | -	return 0;
 | 
		
	
		
			
			| 323 |  | -}
 |