Kaynağa Gözat

[nvo] Remove the non-volatile options fragment list

Since its implementation several years ago, no driver has used a
fragment list containing more than a single fragment.  Simplify the
NVO core and the drivers that use it by removing the whole concept of
the fragment list, and using a simple (address,length) pair instead.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 13 yıl önce
ebeveyn
işleme
1651d4f6d7

+ 24
- 49
src/core/nvo.c Dosyayı Görüntüle

43
 	uint8_t sum = 0;
43
 	uint8_t sum = 0;
44
 	unsigned int i;
44
 	unsigned int i;
45
 
45
 
46
-	for ( i = 0 ; i < nvo->total_len ; i++ ) {
46
+	for ( i = 0 ; i < nvo->len ; i++ ) {
47
 		sum += *(data++);
47
 		sum += *(data++);
48
 	}
48
 	}
49
 	return sum;
49
 	return sum;
56
  * @ret rc		Return status code
56
  * @ret rc		Return status code
57
  */
57
  */
58
 static int nvo_load ( struct nvo_block *nvo ) {
58
 static int nvo_load ( struct nvo_block *nvo ) {
59
-	void *data = nvo->data;
60
-	struct nvo_fragment *frag;
61
 	int rc;
59
 	int rc;
62
 
60
 
63
-	/* Read data a fragment at a time */
64
-	for ( frag = nvo->fragments ; frag->len ; frag++ ) {
65
-		if ( ( rc = nvs_read ( nvo->nvs, frag->address, data,
66
-				       frag->len ) ) != 0 ) {
67
-			DBGC ( nvo, "NVO %p could not read %zd bytes at "
68
-			       "%#04x\n", nvo, frag->len, frag->address );
69
-			return rc;
70
-		}
71
-		data += frag->len;
61
+	/* Read data */
62
+	if ( ( rc = nvs_read ( nvo->nvs, nvo->address, nvo->data,
63
+			       nvo->len ) ) != 0 ) {
64
+		DBGC ( nvo, "NVO %p could not read %zd bytes at %#04x: %s\n",
65
+		       nvo, nvo->len, nvo->address, strerror ( rc ) );
66
+		return rc;
72
 	}
67
 	}
73
 
68
 
74
 	DBGC ( nvo, "NVO %p loaded from non-volatile storage\n", nvo );
69
 	DBGC ( nvo, "NVO %p loaded from non-volatile storage\n", nvo );
82
  * @ret rc		Return status code
77
  * @ret rc		Return status code
83
  */
78
  */
84
 static int nvo_save ( struct nvo_block *nvo ) {
79
 static int nvo_save ( struct nvo_block *nvo ) {
85
-	void *data = nvo->data;
86
-	uint8_t *checksum = data;
87
-	struct nvo_fragment *frag;
80
+	uint8_t *checksum = nvo->data;
88
 	int rc;
81
 	int rc;
89
 
82
 
90
 	/* Recalculate checksum */
83
 	/* Recalculate checksum */
91
 	*checksum -= nvo_checksum ( nvo );
84
 	*checksum -= nvo_checksum ( nvo );
92
 
85
 
93
-	/* Write data a fragment at a time */
94
-	for ( frag = nvo->fragments ; frag->len ; frag++ ) {
95
-		if ( ( rc = nvs_write ( nvo->nvs, frag->address, data,
96
-					frag->len ) ) != 0 ) {
97
-			DBGC ( nvo, "NVO %p could not write %zd bytes at "
98
-			       "%#04x\n", nvo, frag->len, frag->address );
99
-			return rc;
100
-		}
101
-		data += frag->len;
86
+	/* Write data */
87
+	if ( ( rc = nvs_write ( nvo->nvs, nvo->address, nvo->data,
88
+				nvo->len ) ) != 0 ) {
89
+		DBGC ( nvo, "NVO %p could not write %zd bytes at %#04x: %s\n",
90
+		       nvo, nvo->len, nvo->address, strerror ( rc ) );
91
+		return rc;
102
 	}
92
 	}
103
 
93
 
104
 	DBGC ( nvo, "NVO %p saved to non-volatile storage\n", nvo );
94
 	DBGC ( nvo, "NVO %p saved to non-volatile storage\n", nvo );
120
 
110
 
121
 	/* Steal one byte for the checksum */
111
 	/* Steal one byte for the checksum */
122
 	options_data = ( nvo->data + 1 );
112
 	options_data = ( nvo->data + 1 );
123
-	options_len = ( nvo->total_len - 1 );
113
+	options_len = ( nvo->len - 1 );
124
 
114
 
125
 	/* If checksum fails, or options data starts with a zero,
115
 	/* If checksum fails, or options data starts with a zero,
126
 	 * assume the whole block is invalid.  This should capture the
116
 	 * assume the whole block is invalid.  This should capture the
130
 		DBGC ( nvo, "NVO %p has checksum %02x and initial byte %02x; "
120
 		DBGC ( nvo, "NVO %p has checksum %02x and initial byte %02x; "
131
 		       "assuming empty\n", nvo, nvo_checksum ( nvo ),
121
 		       "assuming empty\n", nvo, nvo_checksum ( nvo ),
132
 		       options_data[0] );
122
 		       options_data[0] );
133
-		memset ( nvo->data, 0, nvo->total_len );
123
+		memset ( nvo->data, 0, nvo->len );
134
 	}
124
 	}
135
 
125
 
136
 	dhcpopt_init ( &nvo->dhcpopts, options_data, options_len,
126
 	dhcpopt_init ( &nvo->dhcpopts, options_data, options_len,
198
  *
188
  *
199
  * @v nvo		Non-volatile options block
189
  * @v nvo		Non-volatile options block
200
  * @v nvs		Underlying non-volatile storage device
190
  * @v nvs		Underlying non-volatile storage device
201
- * @v fragments		List of option-containing fragments, or NULL
191
+ * @v address		Address within NVS device
192
+ * @v len		Length of non-volatile options data
202
  * @v refcnt		Containing object reference counter, or NULL
193
  * @v refcnt		Containing object reference counter, or NULL
203
  */
194
  */
204
 void nvo_init ( struct nvo_block *nvo, struct nvs_device *nvs,
195
 void nvo_init ( struct nvo_block *nvo, struct nvs_device *nvs,
205
-		struct nvo_fragment *fragments, struct refcnt *refcnt ) {
196
+		size_t address, size_t len, struct refcnt *refcnt ) {
206
 	nvo->nvs = nvs;
197
 	nvo->nvs = nvs;
207
-	nvo->fragments = fragments;
198
+	nvo->address = address;
199
+	nvo->len = len;
208
 	settings_init ( &nvo->settings, &nvo_settings_operations, refcnt, 0 );
200
 	settings_init ( &nvo->settings, &nvo_settings_operations, refcnt, 0 );
209
 }
201
 }
210
 
202
 
216
  * @ret rc		Return status code
208
  * @ret rc		Return status code
217
  */
209
  */
218
 int register_nvo ( struct nvo_block *nvo, struct settings *parent ) {
210
 int register_nvo ( struct nvo_block *nvo, struct settings *parent ) {
219
-	struct nvo_fragment *fragment = nvo->fragments;
220
 	int rc;
211
 	int rc;
221
 
212
 
222
-	/* Calculate total length of all fragments, if applicable */
223
-	if ( fragment ) {
224
-		for ( ; fragment->len ; fragment++ )
225
-			nvo->total_len += fragment->len;
226
-	} else {
227
-		nvo->total_len = nvo->nvs->size;
228
-	}
229
-
230
-	/* Allocate memory for options (and fragment list, if applicable) */
231
-	nvo->data = zalloc ( nvo->total_len +
232
-			     ( fragment ? 0 : ( 2 * sizeof ( *fragment ) ) ) );
213
+	/* Allocate memory for options */
214
+	nvo->data = zalloc ( nvo->len );
233
 	if ( ! nvo->data ) {
215
 	if ( ! nvo->data ) {
234
 		DBGC ( nvo, "NVO %p could not allocate %zd bytes\n",
216
 		DBGC ( nvo, "NVO %p could not allocate %zd bytes\n",
235
-		       nvo, nvo->total_len );
217
+		       nvo, nvo->len );
236
 		rc = -ENOMEM;
218
 		rc = -ENOMEM;
237
 		goto err_malloc;
219
 		goto err_malloc;
238
 	}
220
 	}
239
 
221
 
240
-	/* Create fragment list, if applicable */
241
-	if ( ! fragment ) {
242
-		fragment = ( nvo->data + nvo->total_len );
243
-		fragment->len = nvo->total_len;
244
-		nvo->fragments = fragment;
245
-	}
246
-
247
 	/* Read data from NVS */
222
 	/* Read data from NVS */
248
 	if ( ( rc = nvo_load ( nvo ) ) != 0 )
223
 	if ( ( rc = nvo_load ( nvo ) ) != 0 )
249
 		goto err_load;
224
 		goto err_load;

+ 3
- 8
src/drivers/net/etherfabric.c Dosyayı Görüntüle

1492
 	return rc;
1492
 	return rc;
1493
 }
1493
 }
1494
 
1494
 
1495
-/** Portion of EEPROM available for non-volatile options */
1496
-static struct nvo_fragment falcon_nvo_fragments[] = {
1497
-	{ 0x100, 0xf0 },
1498
-	{ 0, 0 }
1499
-};
1500
-
1501
 /*******************************************************************************
1495
 /*******************************************************************************
1502
  *
1496
  *
1503
  *
1497
  *
3277
 	}
3271
 	}
3278
 
3272
 
3279
 	/* If the device has EEPROM attached, then advertise NVO space */
3273
 	/* If the device has EEPROM attached, then advertise NVO space */
3280
-	if ( has_eeprom )
3281
-		nvo_init ( &efab->nvo, &efab->spi_eeprom.nvs, falcon_nvo_fragments,
3274
+	if ( has_eeprom ) {
3275
+		nvo_init ( &efab->nvo, &efab->spi_eeprom.nvs, 0x100, 0xf0,
3282
 			   &efab->netdev->refcnt );
3276
 			   &efab->netdev->refcnt );
3277
+	}
3283
 
3278
 
3284
 	return 0;
3279
 	return 0;
3285
 }
3280
 }

+ 4
- 12
src/drivers/net/myri10ge.c Dosyayı Görüntüle

183
 	 */
183
 	 */
184
 
184
 
185
 	struct nvs_device	nvs;
185
 	struct nvs_device	nvs;
186
-	struct nvo_fragment	nvo_fragment[2];
187
 	struct nvo_block	nvo;
186
 	struct nvo_block	nvo;
187
+	unsigned int		nvo_registered;
188
 
188
 
189
 	/* Cached PCI capability locations. */
189
 	/* Cached PCI capability locations. */
190
 
190
 
727
 	priv->nvs.read		= myri10ge_nvs_read;
727
 	priv->nvs.read		= myri10ge_nvs_read;
728
 	priv->nvs.write		= myri10ge_nvs_write;
728
 	priv->nvs.write		= myri10ge_nvs_write;
729
 
729
 
730
-	/* Build the NonVolatile storage fragment list.  We would like
731
-	   to use the whole last EEPROM block for this, but we must
732
-	   reduce the block size lest malloc fail in
733
-	   src/core/nvo.o. */
734
-
735
-	priv->nvo_fragment[0].address = nvo_fragment_pos;
736
-	priv->nvo_fragment[0].len     = 0x200;
737
-
738
 	/* Register the NonVolatile Options storage. */
730
 	/* Register the NonVolatile Options storage. */
739
 
731
 
740
 	nvo_init ( &priv->nvo,
732
 	nvo_init ( &priv->nvo,
741
 		   &priv->nvs,
733
 		   &priv->nvs,
742
-		   priv->nvo_fragment,
734
+		   nvo_fragment_pos, 0x200,
743
 		   & myri10ge_netdev (priv) -> refcnt );
735
 		   & myri10ge_netdev (priv) -> refcnt );
744
 	rc = register_nvo ( &priv->nvo,
736
 	rc = register_nvo ( &priv->nvo,
745
 			    netdev_settings ( myri10ge_netdev ( priv ) ) );
737
 			    netdev_settings ( myri10ge_netdev ( priv ) ) );
746
 	if ( rc ) {
738
 	if ( rc ) {
747
 		DBG ("register_nvo failed");
739
 		DBG ("register_nvo failed");
748
-		priv->nvo_fragment[0].len = 0;
749
 		return rc;
740
 		return rc;
750
 	}
741
 	}
751
 
742
 
743
+	priv->nvo_registered = 1;
752
 	DBG2 ( "NVO supported\n" );
744
 	DBG2 ( "NVO supported\n" );
753
 	return 0;
745
 	return 0;
754
 }
746
 }
758
 {
750
 {
759
 	/* Simply return if nonvolatile access is not supported. */
751
 	/* Simply return if nonvolatile access is not supported. */
760
 
752
 
761
-	if ( 0 == priv->nvo_fragment[0].len )
753
+	if ( 0 == priv->nvo_registered )
762
 		return;
754
 		return;
763
 
755
 
764
 	unregister_nvo ( &priv->nvo );
756
 	unregister_nvo ( &priv->nvo );

+ 7
- 11
src/drivers/net/natsemi.c Dosyayı Görüntüle

130
 	.write = natsemi_spi_write_bit,
130
 	.write = natsemi_spi_write_bit,
131
 };
131
 };
132
 
132
 
133
-/* It looks that this portion of EEPROM can be used for 
134
- * non-volatile stored options. Data sheet does not talk about this region.
135
- * Currently it is not working. But with some efforts it can.
136
- */
137
-static struct nvo_fragment natsemi_nvo_fragments[] = {
138
-	{ 0x0c, 0x68 },
139
-	{ 0, 0 }
140
-};
141
-
142
 /*
133
 /*
143
  * Set up for EEPROM access
134
  * Set up for EEPROM access
144
  *
135
  *
157
 	 */
148
 	 */
158
 	init_at93c46 ( &np->eeprom, 16 );
149
 	init_at93c46 ( &np->eeprom, 16 );
159
 	np->eeprom.bus = &np->spibit.bus;
150
 	np->eeprom.bus = &np->spibit.bus;
160
-	np->nvo.nvs = &np->eeprom.nvs;
161
-	np->nvo.fragments = natsemi_nvo_fragments;
151
+
152
+	/* It looks that this portion of EEPROM can be used for
153
+	 * non-volatile stored options. Data sheet does not talk about
154
+	 * this region.  Currently it is not working. But with some
155
+	 * efforts it can.
156
+	 */
157
+	nvo_init ( &np->nvo, &np->eeprom.nvs, 0x0c, 0x68, NULL );
162
 }
158
 }
163
 
159
 
164
 /**
160
 /**

+ 7
- 13
src/drivers/net/rtl8139.c Dosyayı Görüntüle

251
 	.write = rtl_spi_write_bit,
251
 	.write = rtl_spi_write_bit,
252
 };
252
 };
253
 
253
 
254
-/** Portion of EEPROM available for non-volatile stored options
255
- *
256
- * We use offset 0x40 (i.e. address 0x20), length 0x40.  This block is
257
- * marked as VPD in the rtl8139 datasheets, so we use it only if we
258
- * detect that the card is not supporting VPD.
259
- */
260
-static struct nvo_fragment rtl_nvo_fragments[] = {
261
-	{ 0x20, 0x40 },
262
-	{ 0, 0 }
263
-};
264
-
265
 /**
254
 /**
266
  * Set up for EEPROM access
255
  * Set up for EEPROM access
267
  *
256
  *
288
 	}
277
 	}
289
 	rtl->eeprom.bus = &rtl->spibit.bus;
278
 	rtl->eeprom.bus = &rtl->spibit.bus;
290
 
279
 
291
-	/* Initialise space for non-volatile options, if available */
280
+	/* Initialise space for non-volatile options, if available
281
+	 *
282
+	 * We use offset 0x40 (i.e. address 0x20), length 0x40.  This
283
+	 * block is marked as VPD in the rtl8139 datasheets, so we use
284
+	 * it only if we detect that the card is not supporting VPD.
285
+	 */
292
 	vpd = ( inw ( rtl->ioaddr + Config1 ) & VPDEnable );
286
 	vpd = ( inw ( rtl->ioaddr + Config1 ) & VPDEnable );
293
 	if ( vpd ) {
287
 	if ( vpd ) {
294
 		DBGC ( rtl, "rtl8139 %p EEPROM in use for VPD; cannot use "
288
 		DBGC ( rtl, "rtl8139 %p EEPROM in use for VPD; cannot use "
295
 		       "for options\n", rtl );
289
 		       "for options\n", rtl );
296
 	} else {
290
 	} else {
297
-		nvo_init ( &rtl->nvo, &rtl->eeprom.nvs, rtl_nvo_fragments,
291
+		nvo_init ( &rtl->nvo, &rtl->eeprom.nvs, 0x20, 0x40,
298
 			   &netdev->refcnt );
292
 			   &netdev->refcnt );
299
 	}
293
 	}
300
 }
294
 }

+ 5
- 18
src/include/ipxe/nvo.h Dosyayı Görüntüle

16
 struct nvs_device;
16
 struct nvs_device;
17
 struct refcnt;
17
 struct refcnt;
18
 
18
 
19
-/**
20
- * A fragment of a non-volatile storage device used for stored options
21
- */
22
-struct nvo_fragment {
23
-	/** Starting address of fragment within NVS device */
24
-	unsigned int address;
25
-	/** Length of fragment */
26
-	size_t len;
27
-};
28
-
29
 /**
19
 /**
30
  * A block of non-volatile stored options
20
  * A block of non-volatile stored options
31
  */
21
  */
34
 	struct settings settings;
24
 	struct settings settings;
35
 	/** Underlying non-volatile storage device */
25
 	/** Underlying non-volatile storage device */
36
 	struct nvs_device *nvs;
26
 	struct nvs_device *nvs;
37
-	/** List of option-containing fragments
38
-	 *
39
-	 * The list is terminated by a fragment with a length of zero.
40
-	 */
41
-	struct nvo_fragment *fragments;
42
-	/** Total length of option-containing fragments */
43
-	size_t total_len;
27
+	/** Address within NVS device */
28
+	unsigned int address;
29
+	/** Length of options data */
30
+	size_t len;
44
 	/** Option-containing data */
31
 	/** Option-containing data */
45
 	void *data;
32
 	void *data;
46
 	/** DHCP options block */
33
 	/** DHCP options block */
48
 };
35
 };
49
 
36
 
50
 extern void nvo_init ( struct nvo_block *nvo, struct nvs_device *nvs,
37
 extern void nvo_init ( struct nvo_block *nvo, struct nvs_device *nvs,
51
-		       struct nvo_fragment *fragments, struct refcnt *refcnt );
38
+		       size_t address, size_t len, struct refcnt *refcnt );
52
 extern int register_nvo ( struct nvo_block *nvo, struct settings *parent );
39
 extern int register_nvo ( struct nvo_block *nvo, struct settings *parent );
53
 extern void unregister_nvo ( struct nvo_block *nvo );
40
 extern void unregister_nvo ( struct nvo_block *nvo );
54
 
41
 

Loading…
İptal
Kaydet