ppc64: Quickfix for pointer2cell() and cell2pointer()
[openbios/afaerber.git] / packages / nvram.c
blob3182edf588185571f0fb06831c12903d1e7ce3e6
1 /*
2 * Creation Date: <2003/12/01 00:26:13 samuel>
3 * Time-stamp: <2004/01/07 19:59:53 samuel>
5 * <nvram.c>
7 * medium-level NVRAM handling
9 * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
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
17 #include "config.h"
18 #include "libopenbios/bindings.h"
19 #include "arch/common/nvram.h"
20 #include "packages/nvram.h"
22 //#define CONFIG_DEBUG_NVRAM 1
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
31 #define DEF_SYSTEM_SIZE 0xc10
33 #define NV_SIG_SYSTEM 0x70
34 #define NV_SIG_FREE 0x7f
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;
46 static struct {
47 char *data;
48 int size;
50 nvpart_t *config;
51 int config_size;
52 } nvram;
55 /************************************************************************/
56 /* generic */
57 /************************************************************************/
59 static unsigned int
60 nvpart_checksum( nvpart_t* hdr )
62 unsigned char *p = (unsigned char*)hdr;
63 int i, val = p[0];
65 for( i=2; i<16; i++ ) {
66 val += p[i];
67 if( val > 255 )
68 val = (val - 256 + 1) & 0xff;
70 return val;
73 static inline int
74 nvpart_size( nvpart_t *p )
76 return (p->len_lo | ((int)p->len_hi<<8)) * 16;
79 static int
80 next_nvpart( nvpart_t **p )
82 nvpart_t *end = (nvpart_t*)(nvram.data + nvram.size);
83 int len;
85 if( !*p ) {
86 *p = (nvpart_t*)nvram.data;
87 return 1;
90 if( !(len=nvpart_size(*p)) ) {
91 printk("invalid nvram partition length\n");
92 return -1;
94 *p = (nvpart_t*)((char*)*p + len);
95 if( *p < end )
96 return 1;
97 if( *p == end )
98 return 0;
99 return -1;
102 static void
103 create_free_part( char *ptr, int size )
105 nvpart_t *nvp = (nvpart_t*)ptr;
106 memset( nvp, 0, size );
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);
115 static int
116 create_nv_part( int signature, const char *name, int size )
118 nvpart_t *p = NULL;
119 int fs;
121 while( next_nvpart(&p) > 0 ) {
122 if( p->signature != NV_SIG_FREE )
123 continue;
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 );
138 return size;
140 printk("create-failed\n");
141 return -1;
144 static void
145 zap_nvram( void )
147 create_free_part( nvram.data, nvram.size );
148 create_nv_part( NV_SIG_SYSTEM, "common", DEF_SYSTEM_SIZE );
151 #if 0
152 static void
153 show_partitions( void )
155 nvpart_t *p = NULL;
156 char buf[13];
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));
165 #endif
167 void
168 update_nvram( void )
170 PUSH( pointer2cell(nvram.config->data) );
171 PUSH( nvram.config_size );
172 fword("nvram-store-configs");
173 arch_nvram_put( nvram.data );
176 void
177 nvconf_init( void )
179 int once=0;
181 /* initialize nvram structure completely */
182 nvram.config = NULL;
183 nvram.config_size = 0;
185 nvram.size = arch_nvram_size();
186 nvram.data = malloc( nvram.size );
187 arch_nvram_get( nvram.data );
189 bind_func( "update-nvram", update_nvram );
191 for( ;; ) {
192 nvpart_t *p = NULL;
193 int err;
195 while( (err=next_nvpart(&p)) > 0 ) {
196 if( nvpart_checksum(p) != p->checksum ) {
197 err = -1;
198 break;
200 if( p->signature == NV_SIG_SYSTEM ) {
201 nvram.config = p;
202 nvram.config_size = nvpart_size(p) - 0x10;
204 if( !once++ ) {
205 PUSH( pointer2cell(p->data) );
206 PUSH( nvram.config_size );
207 fword("nvram-load-configs");
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;
218 break;
223 /************************************************************************/
224 /* nvram */
225 /************************************************************************/
227 typedef struct {
228 unsigned int mark_hi;
229 unsigned int mark_lo;
230 } nvram_ibuf_t;
232 DECLARE_UNNAMED_NODE( nvram, INSTALL_OPEN, sizeof(nvram_ibuf_t ));
234 /* ( pos_lo pos_hi -- status ) */
235 static void
236 nvram_seek( nvram_ibuf_t *nd )
238 int pos_hi = POP();
239 int pos_lo = POP();
241 DPRINTF("seek %08x %08x\n", pos_hi, pos_lo );
242 nd->mark_lo = pos_lo;
243 nd->mark_hi = pos_hi;
245 if( nd->mark_lo >= nvram.size ) {
246 PUSH(-1);
247 return;
250 /* 0=success, -1=failure (1=legacy success) */
251 PUSH(0);
254 /* ( addr len -- actual ) */
255 static void
256 nvram_read( nvram_ibuf_t *nd )
258 int len = POP();
259 char *p = (char*)cell2pointer(POP());
260 int n=0;
262 while( nd->mark_lo < nvram.size && n < len ) {
263 *p++ = nvram.data[nd->mark_lo++];
264 n++;
266 PUSH(n);
267 DPRINTF("read %p %x -- %x\n", p, len, n);
270 /* ( addr len -- actual ) */
271 static void
272 nvram_write( nvram_ibuf_t *nd )
274 int len = POP();
275 char *p = (char*)cell2pointer(POP());
276 int n=0;
278 while( nd->mark_lo < nvram.size && n < len ) {
279 nvram.data[nd->mark_lo++] = *p++;
280 n++;
282 PUSH(n);
283 DPRINTF("write %p %x -- %x\n", p, len, n );
286 /* ( -- size ) */
287 static void
288 nvram_size( __attribute__((unused)) nvram_ibuf_t *nd )
290 DPRINTF("nvram_size %d\n", nvram.size);
291 PUSH( nvram.size );
294 NODE_METHODS( nvram ) = {
295 { "size", (void*)nvram_size },
296 { "read", (void*)nvram_read },
297 { "write", (void*)nvram_write },
298 { "seek", (void*)nvram_seek },
302 void
303 nvram_init( const char *path )
305 nvconf_init();
307 REGISTER_NAMED_NODE( nvram, path );