|
|
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.