mirror of
https://gitlab.com/qemu-project/openbios.git
synced 2024-02-13 08:34:06 +08:00
initial import of openbios--main--1.0--patch-26
git-svn-id: svn://coreboot.org/openbios/openbios-devel@1 f158a5a8-5612-0410-a976-696ce0be7e32
This commit is contained in:
297
modules/nvram.c
Normal file
297
modules/nvram.c
Normal file
@@ -0,0 +1,297 @@
|
||||
/*
|
||||
* Creation Date: <2003/12/01 00:26:13 samuel>
|
||||
* Time-stamp: <2004/01/07 19:59:53 samuel>
|
||||
*
|
||||
* <nvram.c>
|
||||
*
|
||||
* medium-level NVRAM handling
|
||||
*
|
||||
* Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2
|
||||
*
|
||||
*/
|
||||
|
||||
#include "openbios/config.h"
|
||||
#include "openbios/bindings.h"
|
||||
#include "openbios/nvram.h"
|
||||
|
||||
#define DEF_SYSTEM_SIZE 0xc10
|
||||
|
||||
#define NV_SIG_SYSTEM 0x70
|
||||
#define NV_SIG_FREE 0x7f
|
||||
|
||||
|
||||
typedef struct {
|
||||
uchar signature;
|
||||
uchar checksum;
|
||||
uchar len_hi;
|
||||
uchar len_lo;
|
||||
char name[12];
|
||||
char data[0];
|
||||
} nvpart_t;
|
||||
|
||||
static struct {
|
||||
char *data;
|
||||
int size;
|
||||
|
||||
nvpart_t *config;
|
||||
int config_size;
|
||||
} nvram;
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* generic */
|
||||
/************************************************************************/
|
||||
|
||||
static unsigned int
|
||||
nvpart_checksum( nvpart_t* hdr )
|
||||
{
|
||||
unsigned char *p = (char*)hdr;
|
||||
int i, val = p[0];
|
||||
|
||||
for( i=2; i<16; i++ ) {
|
||||
val += p[i];
|
||||
if( val > 255 )
|
||||
val = (val - 256 + 1) & 0xff;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline int
|
||||
nvpart_size( nvpart_t *p )
|
||||
{
|
||||
return (p->len_lo | ((int)p->len_hi<<8)) * 16;
|
||||
}
|
||||
|
||||
static int
|
||||
next_nvpart( nvpart_t **p )
|
||||
{
|
||||
nvpart_t *end = (nvpart_t*)(nvram.data + nvram.size);
|
||||
int len;
|
||||
|
||||
if( !*p ) {
|
||||
*p = (nvpart_t*)nvram.data;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if( !(len=nvpart_size(*p)) ) {
|
||||
printk("invalid nvram partition length\n");
|
||||
return -1;
|
||||
}
|
||||
*p = (nvpart_t*)((char*)*p + len);
|
||||
if( *p < end )
|
||||
return 1;
|
||||
if( *p == end )
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
create_free_part( char *ptr, int size )
|
||||
{
|
||||
nvpart_t *nvp = (nvpart_t*)ptr;
|
||||
memset( nvp, 0, size );
|
||||
|
||||
strncpy( nvp->name, "777777777777", sizeof(nvp->name) );
|
||||
nvp->signature = NV_SIG_FREE;
|
||||
nvp->len_hi = (size /16) >> 8;
|
||||
nvp->len_lo = size /16;
|
||||
nvp->checksum = nvpart_checksum(nvp);
|
||||
}
|
||||
|
||||
static int
|
||||
create_nv_part( int signature, char *name, int size )
|
||||
{
|
||||
nvpart_t *p = NULL;
|
||||
int fs;
|
||||
|
||||
while( next_nvpart(&p) > 0 ) {
|
||||
if( p->signature != NV_SIG_FREE )
|
||||
continue;
|
||||
|
||||
fs = nvpart_size( p );
|
||||
if( fs < size )
|
||||
size = fs;
|
||||
p->signature = signature;
|
||||
memset( p->name, 0, sizeof(p->name) );
|
||||
strncpy( p->name, name, sizeof(p->name) );
|
||||
p->len_hi = (size>>8)/16;
|
||||
p->len_lo = size/16;
|
||||
p->checksum = nvpart_checksum(p);
|
||||
if( fs > size ) {
|
||||
char *fp = (char*)p + size;
|
||||
create_free_part( fp, fs-size );
|
||||
}
|
||||
return size;
|
||||
}
|
||||
printk("create-failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
zap_nvram( void )
|
||||
{
|
||||
create_free_part( nvram.data, nvram.size );
|
||||
create_nv_part( NV_SIG_SYSTEM, "common", DEF_SYSTEM_SIZE );
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
show_partitions( void )
|
||||
{
|
||||
nvpart_t *p = NULL;
|
||||
char buf[13];
|
||||
|
||||
while( next_nvpart(&p) > 0 ) {
|
||||
memcpy( buf, p->name, sizeof(p->name) );
|
||||
buf[12] = 0;
|
||||
printk("[%02x] %-13s: %03x\n",
|
||||
p->signature, buf, nvpart_size(p));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
update_nvram( void )
|
||||
{
|
||||
PUSH( (ucell)nvram.config->data );
|
||||
PUSH( nvram.config_size );
|
||||
fword("nvram-store-configs");
|
||||
arch_nvram_put( nvram.data );
|
||||
}
|
||||
|
||||
static void
|
||||
nvconf_init( void )
|
||||
{
|
||||
int once=0;
|
||||
|
||||
/* initialize nvram structure completely */
|
||||
nvram.config = NULL;
|
||||
nvram.config_size = 0;
|
||||
|
||||
nvram.size = arch_nvram_size();
|
||||
nvram.data = malloc( nvram.size );
|
||||
arch_nvram_get( nvram.data );
|
||||
|
||||
bind_func( "update-nvram", update_nvram );
|
||||
|
||||
for( ;; ) {
|
||||
nvpart_t *p = NULL;
|
||||
int err;
|
||||
|
||||
while( (err=next_nvpart(&p)) > 0 ) {
|
||||
if( nvpart_checksum(p) != p->checksum ) {
|
||||
err = -1;
|
||||
break;
|
||||
}
|
||||
if( p->signature == NV_SIG_SYSTEM ) {
|
||||
nvram.config = p;
|
||||
nvram.config_size = nvpart_size(p) - 0x10;
|
||||
|
||||
if( !once++ ) {
|
||||
PUSH( (ucell)p->data );
|
||||
PUSH( nvram.config_size );
|
||||
fword("nvram-load-configs");
|
||||
}
|
||||
}
|
||||
}
|
||||
if( err || !nvram.config ) {
|
||||
printk("nvram error detected, zapping pram\n");
|
||||
zap_nvram();
|
||||
if( !once++ )
|
||||
fword("set-defaults");
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* nvram */
|
||||
/************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
uint mark_hi;
|
||||
uint mark_lo;
|
||||
} nvram_ibuf_t;
|
||||
|
||||
DECLARE_NODE( nvram, INSTALL_OPEN, sizeof(nvram_ibuf_t), "Tnvram" );
|
||||
|
||||
/* ( pos_lo pos_hi -- status ) */
|
||||
static void
|
||||
nvram_seek( nvram_ibuf_t *nd )
|
||||
{
|
||||
int pos_hi = POP();
|
||||
int pos_lo = POP();
|
||||
|
||||
/* printk("NVRAM: seek %08x %08x\n", pos_hi, pos_lo ); */
|
||||
nd->mark_lo = pos_lo;
|
||||
nd->mark_hi = pos_hi;
|
||||
|
||||
if( nd->mark_lo >= nvram.size ) {
|
||||
PUSH(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
/* 0=success, -1=failure (1=legacy success) */
|
||||
PUSH(0);
|
||||
}
|
||||
|
||||
/* ( addr len -- actual ) */
|
||||
static void
|
||||
nvram_read( nvram_ibuf_t *nd )
|
||||
{
|
||||
int len = POP();
|
||||
char *p = (char*)POP();
|
||||
int n=0;
|
||||
|
||||
while( nd->mark_lo < nvram.size && n < len ) {
|
||||
*p++ = nvram.data[nd->mark_lo++];
|
||||
n++;
|
||||
}
|
||||
PUSH(n);
|
||||
/* printk("NVRAM: read %08x %x -- %x\n", (int)p, len, n); */
|
||||
}
|
||||
|
||||
/* ( addr len -- actual ) */
|
||||
static void
|
||||
nvram_write( nvram_ibuf_t *nd )
|
||||
{
|
||||
int len = POP();
|
||||
char *p = (char*)POP();
|
||||
int n=0;
|
||||
|
||||
while( nd->mark_lo < nvram.size && n < len ) {
|
||||
nvram.data[nd->mark_lo++] = *p++;
|
||||
n++;
|
||||
}
|
||||
PUSH(n);
|
||||
/* printk("NVRAM: write %08x %x -- %x\n", (int)p, len, n ); */
|
||||
}
|
||||
|
||||
/* ( -- size ) */
|
||||
static void
|
||||
nvram_size( nvram_ibuf_t *nd )
|
||||
{
|
||||
PUSH( nvram.size );
|
||||
}
|
||||
|
||||
NODE_METHODS( nvram ) = {
|
||||
{ "size", (void*)nvram_size },
|
||||
{ "read", (void*)nvram_read },
|
||||
{ "write", (void*)nvram_write },
|
||||
{ "seek", (void*)nvram_seek },
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
nvram_init( void )
|
||||
{
|
||||
nvconf_init();
|
||||
|
||||
REGISTER_NODE( nvram );
|
||||
}
|
||||
Reference in New Issue
Block a user