17
17
18
18
#define NVRAM_MAGIC "FLSH"
19
19
20
+ /**
21
+ * struct brcm_nvram - driver state internal struct
22
+ *
23
+ * @dev: NVMEM device pointer
24
+ * @nvmem_size: Size of the whole space available for NVRAM
25
+ * @data: NVRAM data copy stored to avoid poking underlaying flash controller
26
+ * @data_len: NVRAM data size
27
+ * @padding_byte: Padding value used to fill remaining space
28
+ * @cells: Array of discovered NVMEM cells
29
+ * @ncells: Number of elements in cells
30
+ */
20
31
struct brcm_nvram {
21
32
struct device * dev ;
22
- void __iomem * base ;
33
+ size_t nvmem_size ;
34
+ uint8_t * data ;
35
+ size_t data_len ;
36
+ uint8_t padding_byte ;
23
37
struct nvmem_cell_info * cells ;
24
38
int ncells ;
25
39
};
@@ -36,10 +50,47 @@ static int brcm_nvram_read(void *context, unsigned int offset, void *val,
36
50
size_t bytes )
37
51
{
38
52
struct brcm_nvram * priv = context ;
39
- u8 * dst = val ;
53
+ size_t to_copy ;
54
+
55
+ if (offset + bytes > priv -> data_len )
56
+ to_copy = max_t (ssize_t , (ssize_t )priv -> data_len - offset , 0 );
57
+ else
58
+ to_copy = bytes ;
59
+
60
+ memcpy (val , priv -> data + offset , to_copy );
61
+
62
+ memset ((uint8_t * )val + to_copy , priv -> padding_byte , bytes - to_copy );
63
+
64
+ return 0 ;
65
+ }
66
+
67
+ static int brcm_nvram_copy_data (struct brcm_nvram * priv , struct platform_device * pdev )
68
+ {
69
+ struct resource * res ;
70
+ void __iomem * base ;
71
+
72
+ base = devm_platform_get_and_ioremap_resource (pdev , 0 , & res );
73
+ if (IS_ERR (base ))
74
+ return PTR_ERR (base );
75
+
76
+ priv -> nvmem_size = resource_size (res );
77
+
78
+ priv -> padding_byte = readb (base + priv -> nvmem_size - 1 );
79
+ for (priv -> data_len = priv -> nvmem_size ;
80
+ priv -> data_len ;
81
+ priv -> data_len -- ) {
82
+ if (readb (base + priv -> data_len - 1 ) != priv -> padding_byte )
83
+ break ;
84
+ }
85
+ WARN (priv -> data_len > SZ_128K , "Unexpected (big) NVRAM size: %zu B\n" , priv -> data_len );
86
+
87
+ priv -> data = devm_kzalloc (priv -> dev , priv -> data_len , GFP_KERNEL );
88
+ if (!priv -> data )
89
+ return - ENOMEM ;
90
+
91
+ memcpy_fromio (priv -> data , base , priv -> data_len );
40
92
41
- while (bytes -- )
42
- * dst ++ = readb (priv -> base + offset ++ );
93
+ bcm47xx_nvram_init_from_iomem (base , priv -> data_len );
43
94
44
95
return 0 ;
45
96
}
@@ -67,8 +118,13 @@ static int brcm_nvram_add_cells(struct brcm_nvram *priv, uint8_t *data,
67
118
size_t len )
68
119
{
69
120
struct device * dev = priv -> dev ;
70
- char * var , * value , * eq ;
121
+ char * var , * value ;
122
+ uint8_t tmp ;
71
123
int idx ;
124
+ int err = 0 ;
125
+
126
+ tmp = priv -> data [len - 1 ];
127
+ priv -> data [len - 1 ] = '\0' ;
72
128
73
129
priv -> ncells = 0 ;
74
130
for (var = data + sizeof (struct brcm_nvram_header );
@@ -78,67 +134,68 @@ static int brcm_nvram_add_cells(struct brcm_nvram *priv, uint8_t *data,
78
134
}
79
135
80
136
priv -> cells = devm_kcalloc (dev , priv -> ncells , sizeof (* priv -> cells ), GFP_KERNEL );
81
- if (!priv -> cells )
82
- return - ENOMEM ;
137
+ if (!priv -> cells ) {
138
+ err = - ENOMEM ;
139
+ goto out ;
140
+ }
83
141
84
142
for (var = data + sizeof (struct brcm_nvram_header ), idx = 0 ;
85
143
var < (char * )data + len && * var ;
86
144
var = value + strlen (value ) + 1 , idx ++ ) {
145
+ char * eq , * name ;
146
+
87
147
eq = strchr (var , '=' );
88
148
if (!eq )
89
149
break ;
90
150
* eq = '\0' ;
151
+ name = devm_kstrdup (dev , var , GFP_KERNEL );
152
+ * eq = '=' ;
153
+ if (!name ) {
154
+ err = - ENOMEM ;
155
+ goto out ;
156
+ }
91
157
value = eq + 1 ;
92
158
93
- priv -> cells [idx ].name = devm_kstrdup (dev , var , GFP_KERNEL );
94
- if (!priv -> cells [idx ].name )
95
- return - ENOMEM ;
159
+ priv -> cells [idx ].name = name ;
96
160
priv -> cells [idx ].offset = value - (char * )data ;
97
161
priv -> cells [idx ].bytes = strlen (value );
98
162
priv -> cells [idx ].np = of_get_child_by_name (dev -> of_node , priv -> cells [idx ].name );
99
- if (!strcmp (var , "et0macaddr" ) ||
100
- !strcmp (var , "et1macaddr" ) ||
101
- !strcmp (var , "et2macaddr" )) {
163
+ if (!strcmp (name , "et0macaddr" ) ||
164
+ !strcmp (name , "et1macaddr" ) ||
165
+ !strcmp (name , "et2macaddr" )) {
102
166
priv -> cells [idx ].raw_len = strlen (value );
103
167
priv -> cells [idx ].bytes = ETH_ALEN ;
104
168
priv -> cells [idx ].read_post_process = brcm_nvram_read_post_process_macaddr ;
105
169
}
106
170
}
107
171
108
- return 0 ;
172
+ out :
173
+ priv -> data [len - 1 ] = tmp ;
174
+ return err ;
109
175
}
110
176
111
177
static int brcm_nvram_parse (struct brcm_nvram * priv )
112
178
{
179
+ struct brcm_nvram_header * header = (struct brcm_nvram_header * )priv -> data ;
113
180
struct device * dev = priv -> dev ;
114
- struct brcm_nvram_header header ;
115
- uint8_t * data ;
116
181
size_t len ;
117
182
int err ;
118
183
119
- memcpy_fromio (& header , priv -> base , sizeof (header ));
120
-
121
- if (memcmp (header .magic , NVRAM_MAGIC , 4 )) {
184
+ if (memcmp (header -> magic , NVRAM_MAGIC , 4 )) {
122
185
dev_err (dev , "Invalid NVRAM magic\n" );
123
186
return - EINVAL ;
124
187
}
125
188
126
- len = le32_to_cpu (header .len );
127
-
128
- data = kzalloc (len , GFP_KERNEL );
129
- if (!data )
130
- return - ENOMEM ;
131
-
132
- memcpy_fromio (data , priv -> base , len );
133
- data [len - 1 ] = '\0' ;
134
-
135
- err = brcm_nvram_add_cells (priv , data , len );
136
- if (err ) {
137
- dev_err (dev , "Failed to add cells: %d\n" , err );
138
- return err ;
189
+ len = le32_to_cpu (header -> len );
190
+ if (len > priv -> nvmem_size ) {
191
+ dev_err (dev , "NVRAM length (%zd) exceeds mapped size (%zd)\n" , len ,
192
+ priv -> nvmem_size );
193
+ return - EINVAL ;
139
194
}
140
195
141
- kfree (data );
196
+ err = brcm_nvram_add_cells (priv , priv -> data , len );
197
+ if (err )
198
+ dev_err (dev , "Failed to add cells: %d\n" , err );
142
199
143
200
return 0 ;
144
201
}
@@ -150,7 +207,6 @@ static int brcm_nvram_probe(struct platform_device *pdev)
150
207
.reg_read = brcm_nvram_read ,
151
208
};
152
209
struct device * dev = & pdev -> dev ;
153
- struct resource * res ;
154
210
struct brcm_nvram * priv ;
155
211
int err ;
156
212
@@ -159,21 +215,19 @@ static int brcm_nvram_probe(struct platform_device *pdev)
159
215
return - ENOMEM ;
160
216
priv -> dev = dev ;
161
217
162
- priv -> base = devm_platform_get_and_ioremap_resource ( pdev , 0 , & res );
163
- if (IS_ERR ( priv -> base ) )
164
- return PTR_ERR ( priv -> base ) ;
218
+ err = brcm_nvram_copy_data ( priv , pdev );
219
+ if (err )
220
+ return err ;
165
221
166
222
err = brcm_nvram_parse (priv );
167
223
if (err )
168
224
return err ;
169
225
170
- bcm47xx_nvram_init_from_iomem (priv -> base , resource_size (res ));
171
-
172
226
config .dev = dev ;
173
227
config .cells = priv -> cells ;
174
228
config .ncells = priv -> ncells ;
175
229
config .priv = priv ;
176
- config .size = resource_size ( res ) ;
230
+ config .size = priv -> nvmem_size ;
177
231
178
232
return PTR_ERR_OR_ZERO (devm_nvmem_register (dev , & config ));
179
233
}
0 commit comments