|
|
1.1 root 1: /*
2: * Creation Date: <2003/12/01 00:26:13 samuel>
3: * Time-stamp: <2004/01/07 19:59:53 samuel>
4: *
5: * <nvram.c>
6: *
7: * medium-level NVRAM handling
8: *
9: * Copyright (C) 2003, 2004 Samuel Rydh ([email protected])
10: *
11: * This program is free software; you can redistribute it and/or
12: * modify it under the terms of the GNU General Public License
13: * version 2
14: *
15: */
16:
17: #include "config.h"
18: #include "libopenbios/bindings.h"
19: #include "arch/common/nvram.h"
20: #include "packages/nvram.h"
21:
22: //#define CONFIG_DEBUG_NVRAM 1
23:
24: #ifdef CONFIG_DEBUG_NVRAM
25: #define DPRINTF(fmt, args...) \
26: do { printk("NVRAM: " fmt , ##args); } while (0)
27: #else
28: #define DPRINTF(fmt, args...) do {} while(0)
29: #endif
30:
31: #define DEF_SYSTEM_SIZE 0xc10
32:
33: #define NV_SIG_SYSTEM 0x70
34: #define NV_SIG_FREE 0x7f
35:
36:
37: typedef struct {
38: unsigned char signature;
39: unsigned char checksum;
40: unsigned char len_hi;
41: unsigned char len_lo;
42: char name[12];
43: char data[0];
44: } nvpart_t;
45:
46: static struct {
47: char *data;
48: int size;
49:
50: nvpart_t *config;
51: int config_size;
52: } nvram;
53:
54:
55: /************************************************************************/
56: /* generic */
57: /************************************************************************/
58:
59: static unsigned int
60: nvpart_checksum( nvpart_t* hdr )
61: {
62: unsigned char *p = (unsigned char*)hdr;
63: int i, val = p[0];
64:
65: for( i=2; i<16; i++ ) {
66: val += p[i];
67: if( val > 255 )
68: val = (val - 256 + 1) & 0xff;
69: }
70: return val;
71: }
72:
73: static inline int
74: nvpart_size( nvpart_t *p )
75: {
76: return (p->len_lo | ((int)p->len_hi<<8)) * 16;
77: }
78:
79: static int
80: next_nvpart( nvpart_t **p )
81: {
82: nvpart_t *end = (nvpart_t*)(nvram.data + nvram.size);
83: int len;
84:
85: if( !*p ) {
86: *p = (nvpart_t*)nvram.data;
87: return 1;
88: }
89:
90: if( !(len=nvpart_size(*p)) ) {
91: printk("invalid nvram partition length\n");
92: return -1;
93: }
94: *p = (nvpart_t*)((char*)*p + len);
95: if( *p < end )
96: return 1;
97: if( *p == end )
98: return 0;
99: return -1;
100: }
101:
102: static void
103: create_free_part( char *ptr, int size )
104: {
105: nvpart_t *nvp = (nvpart_t*)ptr;
106: memset( nvp, 0, size );
107:
108: strncpy( nvp->name, "777777777777", sizeof(nvp->name) );
109: nvp->signature = NV_SIG_FREE;
110: nvp->len_hi = (size /16) >> 8;
111: nvp->len_lo = size /16;
112: nvp->checksum = nvpart_checksum(nvp);
113: }
114:
115: static int
116: create_nv_part( int signature, const char *name, int size )
117: {
118: nvpart_t *p = NULL;
119: int fs;
120:
121: while( next_nvpart(&p) > 0 ) {
122: if( p->signature != NV_SIG_FREE )
123: continue;
124:
125: fs = nvpart_size( p );
126: if( fs < size )
127: size = fs;
128: p->signature = signature;
129: memset( p->name, 0, sizeof(p->name) );
130: strncpy( p->name, name, sizeof(p->name) );
131: p->len_hi = (size>>8)/16;
132: p->len_lo = size/16;
133: p->checksum = nvpart_checksum(p);
134: if( fs > size ) {
135: char *fp = (char*)p + size;
136: create_free_part( fp, fs-size );
137: }
138: return size;
139: }
140: printk("create-failed\n");
141: return -1;
142: }
143:
144: static void
145: zap_nvram( void )
146: {
147: create_free_part( nvram.data, nvram.size );
148: create_nv_part( NV_SIG_SYSTEM, "common", DEF_SYSTEM_SIZE );
149: }
150:
151: #if 0
152: static void
153: show_partitions( void )
154: {
155: nvpart_t *p = NULL;
156: char buf[13];
157:
158: while( next_nvpart(&p) > 0 ) {
159: memcpy( buf, p->name, sizeof(p->name) );
160: buf[12] = 0;
161: printk("[%02x] %-13s: %03x\n",
162: p->signature, buf, nvpart_size(p));
163: }
164: }
165: #endif
166:
167: void
168: update_nvram( void )
169: {
170: PUSH( pointer2cell(nvram.config->data) );
171: PUSH( nvram.config_size );
172: fword("nvram-store-configs");
173: arch_nvram_put( nvram.data );
174: }
175:
176: void
177: nvconf_init( void )
178: {
179: int once=0;
180:
181: /* initialize nvram structure completely */
182: nvram.config = NULL;
183: nvram.config_size = 0;
184:
185: nvram.size = arch_nvram_size();
186: nvram.data = malloc( nvram.size );
187: arch_nvram_get( nvram.data );
188:
189: bind_func( "update-nvram", update_nvram );
190:
191: for( ;; ) {
192: nvpart_t *p = NULL;
193: int err;
194:
195: while( (err=next_nvpart(&p)) > 0 ) {
196: if( nvpart_checksum(p) != p->checksum ) {
197: err = -1;
198: break;
199: }
200: if( p->signature == NV_SIG_SYSTEM ) {
201: nvram.config = p;
202: nvram.config_size = nvpart_size(p) - 0x10;
203:
204: if( !once++ ) {
205: PUSH( pointer2cell(p->data) );
206: PUSH( nvram.config_size );
207: fword("nvram-load-configs");
208: }
209: }
210: }
211: if( err || !nvram.config ) {
212: printk("nvram error detected, zapping pram\n");
213: zap_nvram();
214: if( !once++ )
215: fword("set-defaults");
216: continue;
217: }
218: break;
219: }
220: }
221:
222:
223: /************************************************************************/
224: /* nvram */
225: /************************************************************************/
226:
227: typedef struct {
228: unsigned int mark_hi;
229: unsigned int mark_lo;
230: } nvram_ibuf_t;
231:
232: DECLARE_UNNAMED_NODE( nvram, INSTALL_OPEN, sizeof(nvram_ibuf_t ));
233:
234: /* ( pos_lo pos_hi -- status ) */
235: static void
236: nvram_seek( nvram_ibuf_t *nd )
237: {
238: int pos_hi = POP();
239: int pos_lo = POP();
240:
241: DPRINTF("seek %08x %08x\n", pos_hi, pos_lo );
242: nd->mark_lo = pos_lo;
243: nd->mark_hi = pos_hi;
244:
245: if( nd->mark_lo >= nvram.size ) {
246: PUSH(-1);
247: return;
248: }
249:
250: /* 0=success, -1=failure (1=legacy success) */
251: PUSH(0);
252: }
253:
254: /* ( addr len -- actual ) */
255: static void
256: nvram_read( nvram_ibuf_t *nd )
257: {
258: int len = POP();
259: char *p = (char*)cell2pointer(POP());
260: int n=0;
261:
262: while( nd->mark_lo < nvram.size && n < len ) {
263: *p++ = nvram.data[nd->mark_lo++];
264: n++;
265: }
266: PUSH(n);
267: DPRINTF("read %p %x -- %x\n", p, len, n);
268: }
269:
270: /* ( addr len -- actual ) */
271: static void
272: nvram_write( nvram_ibuf_t *nd )
273: {
274: int len = POP();
275: char *p = (char*)cell2pointer(POP());
276: int n=0;
277:
278: while( nd->mark_lo < nvram.size && n < len ) {
279: nvram.data[nd->mark_lo++] = *p++;
280: n++;
281: }
282: PUSH(n);
283: DPRINTF("write %p %x -- %x\n", p, len, n );
284: }
285:
286: /* ( -- size ) */
287: static void
288: nvram_size( __attribute__((unused)) nvram_ibuf_t *nd )
289: {
290: DPRINTF("nvram_size %d\n", nvram.size);
291: PUSH( nvram.size );
292: }
293:
294: NODE_METHODS( nvram ) = {
295: { "size", (void*)nvram_size },
296: { "read", (void*)nvram_read },
297: { "write", (void*)nvram_write },
298: { "seek", (void*)nvram_seek },
299: };
300:
301:
302: void
303: nvram_init( const char *path )
304: {
305: nvconf_init();
306:
307: REGISTER_NAMED_NODE( nvram, path );
308: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.