Ver código fonte

Add the concept of a fragment list for non-volatile stored options.

tags/v0.9.3
Michael Brown 17 anos atrás
pai
commit
cc9bcb99a0
3 arquivos alterados com 135 adições e 39 exclusões
  1. 98
    31
      src/core/nvo.c
  2. 12
    5
      src/drivers/net/etherfabric.c
  3. 25
    3
      src/include/gpxe/nvo.h

+ 98
- 31
src/core/nvo.c Ver arquivo

@@ -28,79 +28,146 @@
28 28
  *
29 29
  */
30 30
 
31
-static size_t nvo_options_len ( struct nvs_options *nvo ) {
31
+/**
32
+ * Calculate total length of non-volatile stored options
33
+ *
34
+ * @v nvo		Non-volatile options block
35
+ * @ret total_len	Total length of all fragments
36
+ */
37
+static size_t nvo_total_len ( struct nvo_block *nvo ) {
38
+	struct nvo_fragment *fragment = nvo->fragments;
39
+	size_t total_len = 0;
40
+
41
+	for ( ; fragment->len ; fragment++ ) {
42
+		total_len += fragment->len;
43
+	}
44
+
45
+	return total_len;
46
+}
47
+
48
+/**
49
+ * Read non-volatile stored options from non-volatile storage device
50
+ *
51
+ * @v nvo		Non-volatile options block
52
+ * @ret rc		Return status code
53
+ */
54
+static int nvo_read ( struct nvo_block *nvo ) {
55
+	struct nvo_fragment *fragment = nvo->fragments;
56
+	void *data = nvo->options->data;
57
+	int rc;
58
+
59
+	for ( ; fragment->len ; fragment++ ) {
60
+		if ( ( rc = nvs_read ( nvo->nvs, fragment->address,
61
+				       data, fragment->len ) ) != 0 ) {
62
+			DBG ( "NVO %p could not read %zd bytes at %#04x\n",
63
+			      nvo, fragment->len, fragment->address );
64
+			return rc;
65
+		}
66
+		data += fragment->len;
67
+	}
68
+	
69
+	return 0;
70
+}
71
+
72
+/**
73
+ * Parse stored options
74
+ *
75
+ * @v nvo		Non-volatile options block
76
+ * @v total_len		Total length of options data
77
+ *
78
+ * Verifies that the options data is valid, and configures the DHCP
79
+ * options block.  If the data is not valid, it is replaced with an
80
+ * empty options block.
81
+ */
82
+static void nvo_init_dhcp ( struct nvo_block *nvo, size_t total_len ) {
83
+	struct dhcp_option_block *options = nvo->options;
32 84
 	struct dhcp_option *option;
33 85
 	uint8_t sum;
34 86
 	unsigned int i;
35
-	size_t len;
36 87
 
37
-	for ( sum = 0, i = 0 ; i < nvo->nvs->size ; i++ ) {
38
-		sum += * ( ( uint8_t * ) ( nvo->options->data + i ) );
88
+	/* Steal one byte for the checksum */
89
+	options->max_len = ( total_len - 1 );
90
+
91
+	/* Verify checksum over whole block */
92
+	for ( sum = 0, i = 0 ; i < total_len ; i++ ) {
93
+		sum += * ( ( uint8_t * ) ( options->data + i ) );
39 94
 	}
40 95
 	if ( sum != 0 ) {
41 96
 		DBG ( "NVO %p has bad checksum %02x; assuming empty\n",
42 97
 		      nvo, sum );
43
-		return 0;
98
+		goto empty;
44 99
 	}
45 100
 
46
-	option = nvo->options->data;
101
+	/* Check that we don't just have a block full of zeroes */
102
+	option = options->data;
47 103
 	if ( option->tag == DHCP_PAD ) {
48 104
 		DBG ( "NVO %p has bad start; assuming empty\n", nvo );
49
-		return 0;
105
+		goto empty;
50 106
 	}
51 107
 	
52
-	option = find_dhcp_option ( nvo->options, DHCP_END );
108
+	/* Search for the DHCP_END tag */
109
+	options->len = options->max_len;
110
+	option = find_dhcp_option ( options, DHCP_END );
53 111
 	if ( ! option ) {
54 112
 		DBG ( "NVO %p has no end tag; assuming empty\n", nvo );
55
-		return 0;
113
+		goto empty;
56 114
 	}
57 115
 
58
-	len = ( ( void * ) option - nvo->options->data + 1 );
116
+	/* Set correct length of DHCP options */
117
+	options->len = ( ( void * ) option - options->data + 1 );
59 118
 	DBG ( "NVO %p contains %zd bytes of options (maximum %zd)\n",
60
-	      nvo, len, nvo->nvs->size );
119
+	      nvo, options->len, options->max_len );
120
+	return;
61 121
 
62
-	return len;
122
+ empty:
123
+	/* No options found; initialise an empty options block */
124
+	option = options->data;
125
+	option->tag = DHCP_END;
126
+	options->len = 1;
127
+	return;
63 128
 }
64 129
 
65
-int nvo_register ( struct nvs_options *nvo ) {
66
-	struct dhcp_option *option;
130
+/**
131
+ * Register non-volatile stored options
132
+ *
133
+ * @v nvo		Non-volatile options block
134
+ * @ret rc		Return status code
135
+ */
136
+int nvo_register ( struct nvo_block *nvo ) {
137
+	size_t total_len;
67 138
 	int rc;
68 139
 
69
-	nvo->options = alloc_dhcp_options ( nvo->nvs->size );
140
+	/* Allocate memory for options and read in from NVS */
141
+	total_len = nvo_total_len ( nvo );
142
+	nvo->options = alloc_dhcp_options ( total_len );
70 143
 	if ( ! nvo->options ) {
71 144
 		DBG ( "NVO %p could not allocate %zd bytes\n",
72
-		      nvo, nvo->nvs->size );
145
+		      nvo, total_len );
73 146
 		rc = -ENOMEM;
74 147
 		goto err;
75 148
 	}
76 149
 
77
-	if ( ( rc = nvo->nvs->read ( nvo->nvs, 0, nvo->options->data,
78
-				     nvo->nvs->size ) ) != 0 ) {
79
-		DBG ( "NVO %p could not read [0,%zd)\n",
80
-		      nvo, nvo->nvs->size );
150
+	if ( ( rc = nvo_read ( nvo ) ) != 0 )
81 151
 		goto err;
82
-	}
83
-
84
-	nvo->options->len = nvo->options->max_len;
85
-	nvo->options->len = nvo_options_len ( nvo );
86
-	if ( ! nvo->options->len ) {
87
-		option = nvo->options->data;
88
-		option->tag = DHCP_END;
89
-		nvo->options->len = 1;
90
-	}
91 152
 
153
+	/* Verify and register options */
154
+	nvo_init_dhcp ( nvo, total_len );
92 155
 	register_dhcp_options ( nvo->options );
93 156
 
94 157
 	return 0;
95 158
 	
96 159
  err:
97
-	
98 160
 	free_dhcp_options ( nvo->options );
99 161
 	nvo->options = NULL;
100 162
 	return rc;
101 163
 }
102 164
 
103
-void nvo_unregister ( struct nvs_options *nvo ) {
165
+/**
166
+ * Unregister non-volatile stored options
167
+ *
168
+ * @v nvo		Non-volatile options block
169
+ */
170
+void nvo_unregister ( struct nvo_block *nvo ) {
104 171
 	if ( nvo->options ) {
105 172
 		unregister_dhcp_options ( nvo->options );
106 173
 		free_dhcp_options ( nvo->options );

+ 12
- 5
src/drivers/net/etherfabric.c Ver arquivo

@@ -23,6 +23,7 @@
23 23
 #include <gpxe/bitbash.h>
24 24
 #include <gpxe/i2c.h>
25 25
 #include <gpxe/spi.h>
26
+#include <gpxe/nvo.h>
26 27
 #include "timer.h"
27 28
 #define dma_addr_t unsigned long
28 29
 #include "etherfabric.h"
@@ -217,6 +218,9 @@ struct efab_nic {
217 218
 	struct spi_bus spi;
218 219
 	struct spi_device falcon_flash;
219 220
 	struct spi_device falcon_eeprom;
221
+
222
+	/** Non-volatile options */
223
+	struct nvo_block nvo;
220 224
 };
221 225
 
222 226
 /**************************************************************************
@@ -2304,6 +2308,11 @@ static void falcon_init_spi ( struct efab_nic *efab ) {
2304 2308
 /** Offset of MAC address within EEPROM or Flash */
2305 2309
 #define FALCON_MAC_ADDRESS_OFFSET(port) ( 0x310 + 0x08 * (port) )
2306 2310
 
2311
+static struct nvo_fragment falcon_eeprom_fragments[] = {
2312
+	{ 0, 0x100 },
2313
+	{ 0, 0 }
2314
+};
2315
+
2307 2316
 /**
2308 2317
  * Read MAC address from EEPROM
2309 2318
  *
@@ -2972,12 +2981,10 @@ static int falcon_init_nic ( struct efab_nic *efab ) {
2972 2981
 
2973 2982
 	/* Register non-volatile storage */
2974 2983
 	if ( efab->has_eeprom ) {
2975
-		/*
2976
-		efab->nvs.op = &falcon_nvs_operations;
2977
-		efab->nvs.len = 0x100;
2978
-		if ( nvs_register ( &efab->nvs ) != 0 )
2984
+		efab->nvo.nvs = &efab->falcon_eeprom.nvs;
2985
+		efab->nvo.fragments = falcon_eeprom_fragments;
2986
+		if ( nvo_register ( &efab->nvo ) != 0 )
2979 2987
 			return 0;
2980
-		*/
2981 2988
 	}
2982 2989
 
2983 2990
 	return 1;

+ 25
- 3
src/include/gpxe/nvo.h Ver arquivo

@@ -7,15 +7,37 @@
7 7
  *
8 8
  */
9 9
 
10
+#include <stdint.h>
11
+
10 12
 struct nvs_device;
11 13
 struct dhcp_option_block;
12 14
 
13
-struct nvs_options {
15
+/**
16
+ * A fragment of a non-volatile storage device used for stored options
17
+ */
18
+struct nvo_fragment {
19
+	/** Starting address of fragment within NVS device */
20
+	unsigned int address;
21
+	/** Length of fragment */
22
+	size_t len;
23
+};
24
+
25
+/**
26
+ * A block of non-volatile stored options
27
+ */
28
+struct nvo_block {
29
+	/** Underlying non-volatile storage device */
14 30
 	struct nvs_device *nvs;
31
+	/** List of option-containing fragments
32
+	 *
33
+	 * The list is terminated by a fragment with a length of zero.
34
+	 */
35
+	struct nvo_fragment *fragments;
36
+	/** DHCP options block */
15 37
 	struct dhcp_option_block *options;
16 38
 };
17 39
 
18
-extern int nvo_register ( struct nvs_options *nvo );
19
-extern void nvo_unregister ( struct nvs_options *nvo );
40
+extern int nvo_register ( struct nvo_block *nvo );
41
+extern void nvo_unregister ( struct nvo_block *nvo );
20 42
 
21 43
 #endif /* _GPXE_NVO_H */

Carregando…
Cancelar
Salvar