소스 검색

[Settings] Expose SMBIOS via settings API

In particular, expose the system UUID as a setting ("smbios/uuid").
tags/v0.9.4
Michael Brown 16 년 전
부모
커밋
feade5da6e

+ 81
- 112
src/arch/i386/firmware/pcbios/smbios.c 파일 보기

@@ -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
-}

+ 158
- 0
src/arch/i386/firmware/pcbios/smbios_settings.c 파일 보기

@@ -0,0 +1,158 @@
1
+/*
2
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+#include <stdint.h>
20
+#include <string.h>
21
+#include <errno.h>
22
+#include <gpxe/settings.h>
23
+#include <gpxe/init.h>
24
+#include <gpxe/uuid.h>
25
+#include <smbios.h>
26
+
27
+/**
28
+ * Construct SMBIOS raw-data tag
29
+ *
30
+ * @v _type		SMBIOS structure type number
31
+ * @v _structure	SMBIOS structure data type
32
+ * @v _field		Field within SMBIOS structure data type
33
+ * @ret tag		SMBIOS setting tag
34
+ */
35
+#define SMBIOS_RAW_TAG( _type, _structure, _field )		\
36
+	( ( (_type) << 16 ) |					\
37
+	  ( offsetof ( _structure, _field ) << 8 ) |		\
38
+	  ( sizeof ( ( ( _structure * ) 0 )->_field ) ) )
39
+
40
+/**
41
+ * Construct SMBIOS string tag
42
+ *
43
+ * @v _type		SMBIOS structure type number
44
+ * @v _structure	SMBIOS structure data type
45
+ * @v _field		Field within SMBIOS structure data type
46
+ * @ret tag		SMBIOS setting tag
47
+ */
48
+#define SMBIOS_STRING_TAG( _type, _structure, _field )		\
49
+	( ( (_type) << 16 ) |					\
50
+	  ( offsetof ( _structure, _field ) << 8 ) )
51
+
52
+/**
53
+ * Store value of SMBIOS setting
54
+ *
55
+ * @v settings		Settings block
56
+ * @v setting		Setting to store
57
+ * @v data		Setting data, or NULL to clear setting
58
+ * @v len		Length of setting data
59
+ * @ret rc		Return status code
60
+ */
61
+static int smbios_store ( struct settings *settings __unused,
62
+			  struct setting *setting __unused,
63
+			  const void *data __unused, size_t len __unused ) {
64
+	/* Cannot write data into SMBIOS */
65
+	return -ENOTSUP;
66
+}
67
+
68
+/**
69
+ * Fetch value of SMBIOS setting
70
+ *
71
+ * @v settings		Settings block, or NULL to search all blocks
72
+ * @v setting		Setting to fetch
73
+ * @v data		Buffer to fill with setting data
74
+ * @v len		Length of buffer
75
+ * @ret len		Length of setting data, or negative error
76
+ */
77
+static int smbios_fetch ( struct settings *settings __unused,
78
+			  struct setting *setting,
79
+			  void *data, size_t len ) {
80
+	struct smbios_structure structure;
81
+	unsigned int tag_type;
82
+	unsigned int tag_offset;
83
+	unsigned int tag_len;
84
+	int rc;
85
+
86
+	/* Split tag into type, offset and length */
87
+	tag_type = ( setting->tag >> 16 );
88
+	tag_offset = ( ( setting->tag >> 8 ) & 0xff );
89
+	tag_len = ( setting->tag & 0xff );
90
+	if ( ! tag_type )
91
+		return -ENOENT;
92
+
93
+	/* Find SMBIOS structure */
94
+	if ( ( rc = find_smbios_structure ( tag_type, &structure ) ) != 0 )
95
+		return rc;
96
+
97
+	{
98
+		uint8_t buf[structure.header.len];
99
+
100
+		/* Read SMBIOS structure */
101
+		if ( ( rc = read_smbios_structure ( &structure, buf,
102
+						    sizeof ( buf ) ) ) != 0 )
103
+			return rc;
104
+
105
+		if ( tag_len == 0 ) {
106
+			/* String */
107
+			return read_smbios_string ( &structure,
108
+						    buf[tag_offset],
109
+						    data, len );
110
+		} else {
111
+			/* Raw data */
112
+			if ( len > tag_len )
113
+				len = tag_len;
114
+			memcpy ( data, &buf[tag_offset], len );
115
+			return tag_len;
116
+		}
117
+	}
118
+}
119
+
120
+/** SMBIOS settings operations */
121
+static struct settings_operations smbios_settings_operations = {
122
+	.store = smbios_store,
123
+	.fetch = smbios_fetch,
124
+};
125
+
126
+/** SMBIOS settings */
127
+static struct settings smbios_settings = {
128
+	.refcnt = NULL,
129
+	.name = "smbios",
130
+	.siblings = LIST_HEAD_INIT ( smbios_settings.siblings ),
131
+	.children = LIST_HEAD_INIT ( smbios_settings.children ),
132
+	.op = &smbios_settings_operations,
133
+};
134
+
135
+/** Initialise SMBIOS settings */
136
+static void smbios_init ( void ) {
137
+	int rc;
138
+
139
+	if ( ( rc = register_settings ( &smbios_settings, NULL ) ) != 0 ) {
140
+		DBG ( "SMBIOS could not register settings: %s\n",
141
+		      strerror ( rc ) );
142
+		return;
143
+	}
144
+}
145
+
146
+/** SMBIOS settings initialiser */
147
+struct init_fn smbios_init_fn __init_fn ( INIT_NORMAL ) = {
148
+	.initialise = smbios_init,
149
+};
150
+
151
+/** UUID setting obtained via SMBIOS */
152
+struct setting uuid_setting __setting = {
153
+	.name = "uuid",
154
+	.description = "UUID",
155
+	.tag = SMBIOS_RAW_TAG ( SMBIOS_TYPE_SYSTEM_INFORMATION,
156
+				struct smbios_system_information, uuid ),
157
+	.type = &setting_type_uuid,
158
+};

+ 1
- 0
src/arch/i386/include/bits/errfile.h 파일 보기

@@ -12,6 +12,7 @@
12 12
 #define ERRFILE_smbios		( ERRFILE_ARCH | ERRFILE_CORE | 0x00030000 )
13 13
 #define ERRFILE_biosint		( ERRFILE_ARCH | ERRFILE_CORE | 0x00040000 )
14 14
 #define ERRFILE_int13		( ERRFILE_ARCH | ERRFILE_CORE | 0x00050000 )
15
+#define ERRFILE_smbios_settings	( ERRFILE_ARCH | ERRFILE_CORE | 0x00060000 )
15 16
 
16 17
 #define ERRFILE_bootsector     ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00000000 )
17 18
 #define ERRFILE_bzimage	       ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00010000 )

+ 0
- 10
src/arch/i386/include/bits/uuid.h 파일 보기

@@ -1,10 +0,0 @@
1
-#ifndef _I386_UUID_H
2
-#define _I386_UUID_H
3
-
4
-#include <smbios.h>
5
-
6
-static inline int get_uuid ( union uuid *uuid ) {
7
-	return smbios_get_uuid ( uuid );
8
-}
9
-
10
-#endif /* _I386_UUID_H */

+ 16
- 7
src/arch/i386/include/smbios.h 파일 보기

@@ -13,11 +13,21 @@ struct smbios_header {
13 13
 	/** Type */
14 14
 	uint8_t type;
15 15
 	/** Length */
16
-	uint8_t length;
16
+	uint8_t len;
17 17
 	/** Handle */
18 18
 	uint16_t handle;
19 19
 } __attribute__ (( packed ));
20 20
 
21
+/** SMBIOS structure descriptor */
22
+struct smbios_structure {
23
+	/** Copy of SMBIOS structure header */
24
+	struct smbios_header header;
25
+	/** Offset of structure within SMBIOS */
26
+	size_t offset;
27
+	/** Length of strings section */
28
+	size_t strings_len;
29
+};
30
+
21 31
 /** SMBIOS system information structure */
22 32
 struct smbios_system_information {
23 33
 	/** SMBIOS structure header */
@@ -39,13 +49,12 @@ struct smbios_system_information {
39 49
 /** SMBIOS system information structure type */
40 50
 #define SMBIOS_TYPE_SYSTEM_INFORMATION 1
41 51
 
42
-struct smbios_strings;
43 52
 extern int find_smbios_structure ( unsigned int type,
44
-				   void *structure, size_t length,
45
-				   struct smbios_strings *strings );
46
-extern int find_smbios_string ( struct smbios_strings *strings,
53
+				   struct smbios_structure *structure );
54
+extern int read_smbios_structure ( struct smbios_structure *structure,
55
+				   void *data, size_t len );
56
+extern int read_smbios_string ( struct smbios_structure *structure,
47 57
 				unsigned int index,
48
-				char *buffer, size_t length );
49
-extern int smbios_get_uuid ( union uuid *uuid );
58
+				void *data, size_t len );
50 59
 
51 60
 #endif /* _SMBIOS_H */

+ 65
- 4
src/core/settings.c 파일 보기

@@ -27,6 +27,7 @@
27 27
 #include <gpxe/in.h>
28 28
 #include <gpxe/vsprintf.h>
29 29
 #include <gpxe/dhcp.h>
30
+#include <gpxe/uuid.h>
30 31
 #include <gpxe/settings.h>
31 32
 
32 33
 /** @file
@@ -487,6 +488,26 @@ unsigned long fetch_uintz_setting ( struct settings *settings,
487 488
 	return value;
488 489
 }
489 490
 
491
+/**
492
+ * Fetch value of UUID setting
493
+ *
494
+ * @v settings		Settings block, or NULL to search all blocks
495
+ * @v setting		Setting to fetch
496
+ * @v uuid		UUID to fill in
497
+ * @ret len		Length of setting, or negative error
498
+ */
499
+int fetch_uuid_setting ( struct settings *settings, struct setting *setting,
500
+			 union uuid *uuid ) {
501
+	int len;
502
+
503
+	len = fetch_setting ( settings, setting, uuid, sizeof ( *uuid ) );
504
+	if ( len < 0 )
505
+		return len;
506
+	if ( len != sizeof ( *uuid ) )
507
+		return -ERANGE;
508
+	return len;
509
+}
510
+
490 511
 /**
491 512
  * Compare two settings
492 513
  *
@@ -752,11 +773,11 @@ static int storef_ipv4 ( struct settings *settings, struct setting *setting,
752 773
 static int fetchf_ipv4 ( struct settings *settings, struct setting *setting,
753 774
 			 char *buf, size_t len ) {
754 775
 	struct in_addr ipv4;
755
-	int rc;
776
+	int raw_len;
756 777
 
757
-	if ( ( rc = fetch_ipv4_setting ( settings, setting, &ipv4 ) ) < 0 )
758
-		return rc;
759
-	return snprintf ( buf, len, inet_ntoa ( ipv4 ) );
778
+	if ( ( raw_len = fetch_ipv4_setting ( settings, setting, &ipv4 ) ) < 0)
779
+		return raw_len;
780
+	return snprintf ( buf, len, "%s", inet_ntoa ( ipv4 ) );
760 781
 }
761 782
 
762 783
 /** An IPv4 address setting type */
@@ -985,6 +1006,46 @@ struct setting_type setting_type_hex __setting_type = {
985 1006
 	.fetchf = fetchf_hex,
986 1007
 };
987 1008
 
1009
+/**
1010
+ * Parse and store value of UUID setting
1011
+ *
1012
+ * @v settings		Settings block
1013
+ * @v setting		Setting to store
1014
+ * @v value		Formatted setting data
1015
+ * @ret rc		Return status code
1016
+ */
1017
+static int storef_uuid ( struct settings *settings __unused,
1018
+			 struct setting *setting __unused,
1019
+			 const char *value __unused ) {
1020
+	return -ENOTSUP;
1021
+}
1022
+
1023
+/**
1024
+ * Fetch and format value of UUID setting
1025
+ *
1026
+ * @v settings		Settings block, or NULL to search all blocks
1027
+ * @v setting		Setting to fetch
1028
+ * @v buf		Buffer to contain formatted value
1029
+ * @v len		Length of buffer
1030
+ * @ret len		Length of formatted value, or negative error
1031
+ */
1032
+static int fetchf_uuid ( struct settings *settings, struct setting *setting,
1033
+			 char *buf, size_t len ) {
1034
+	union uuid uuid;
1035
+	int raw_len;
1036
+
1037
+	if ( ( raw_len = fetch_uuid_setting ( settings, setting, &uuid ) ) < 0)
1038
+		return raw_len;
1039
+	return snprintf ( buf, len, "%s", uuid_ntoa ( &uuid ) );
1040
+}
1041
+
1042
+/** UUID setting type */
1043
+struct setting_type setting_type_uuid __setting_type = {
1044
+	.name = "uuid",
1045
+	.storef = storef_uuid,
1046
+	.fetchf = fetchf_uuid,
1047
+};
1048
+
988 1049
 /******************************************************************************
989 1050
  *
990 1051
  * Settings

+ 5
- 0
src/include/gpxe/settings.h 파일 보기

@@ -15,6 +15,7 @@
15 15
 
16 16
 struct settings;
17 17
 struct in_addr;
18
+union uuid;
18 19
 
19 20
 /** A setting */
20 21
 struct setting {
@@ -177,6 +178,8 @@ extern long fetch_intz_setting ( struct settings *settings,
177 178
 				 struct setting *setting );
178 179
 extern unsigned long fetch_uintz_setting ( struct settings *settings,
179 180
 					   struct setting *setting );
181
+extern int fetch_uuid_setting ( struct settings *settings,
182
+				struct setting *setting, union uuid *uuid );
180 183
 extern int setting_cmp ( struct setting *a, struct setting *b );
181 184
 
182 185
 extern struct settings * find_child_settings ( struct settings *parent,
@@ -198,6 +201,7 @@ extern struct setting_type setting_type_uint8 __setting_type;
198 201
 extern struct setting_type setting_type_uint16 __setting_type;
199 202
 extern struct setting_type setting_type_uint32 __setting_type;
200 203
 extern struct setting_type setting_type_hex __setting_type;
204
+extern struct setting_type setting_type_uuid __setting_type;
201 205
 
202 206
 extern struct setting ip_setting __setting;
203 207
 extern struct setting netmask_setting __setting;
@@ -210,6 +214,7 @@ extern struct setting username_setting __setting;
210 214
 extern struct setting password_setting __setting;
211 215
 extern struct setting priority_setting __setting;
212 216
 extern struct setting bios_drive_setting __setting;
217
+extern struct setting uuid_setting __setting;
213 218
 
214 219
 /**
215 220
  * Initialise a settings block

+ 0
- 3
src/include/gpxe/uuid.h 파일 보기

@@ -8,9 +8,6 @@
8 8
 
9 9
 #include <stdint.h>
10 10
 
11
-union uuid;
12
-#include <bits/uuid.h>
13
-
14 11
 /** A universally unique ID */
15 12
 union uuid {
16 13
 	/** Canonical form (00000000-0000-0000-0000-000000000000) */

+ 3
- 2
src/net/udp/dhcp.c 파일 보기

@@ -214,7 +214,7 @@ static int dhcpset_store ( struct settings *settings, struct setting *setting,
214 214
 }
215 215
 
216 216
 /**
217
- * Fetch value of setting
217
+ * Fetch value of DHCP setting
218 218
  *
219 219
  * @v settings		Settings block, or NULL to search all blocks
220 220
  * @v setting		Setting to fetch
@@ -517,7 +517,8 @@ int dhcp_create_request ( struct dhcp_packet *dhcppkt,
517 517
 
518 518
 	/* Add client UUID, if we have one.  Required for PXE. */
519 519
 	client_uuid.type = DHCP_CLIENT_UUID_TYPE;
520
-	if ( ( rc = get_uuid ( &client_uuid.uuid ) ) == 0 ) {
520
+	if ( ( rc = fetch_uuid_setting ( NULL, &uuid_setting,
521
+					 &client_uuid.uuid ) ) >= 0 ) {
521 522
 		if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_CLIENT_UUID,
522 523
 					    &client_uuid,
523 524
 					    sizeof ( client_uuid ) ) ) != 0 ) {

Loading…
취소
저장