Moved from freebios
[coreboot.git] / src / mainboard / motorola / sandpoint / nvram / nvram.c
1 /* $Id$ */
2 /* Copyright 2000  AG Electronics Ltd. */
3 /* This code is distributed without warranty under the GPL v2 (see COPYING) */
4
5 #include <types.h>
6 #include <printk.h>
7 #include <stdlib.h>
8 #include "../nvram.h"
9
10 /* NVRAM layout
11  * 
12  * Environment variable record runs:
13  * [length]NAME=value[length]NAME=value[0]\0
14  * A deleted variable is:
15  * [length]\0AME=value
16  * 
17  * When memory is full, we compact.
18  * 
19  */
20 static nvram_device *nvram_dev = 0;
21 static unsigned char *nvram_buffer = 0;
22 static unsigned nvram_size = 0;
23 static u8 nvram_csum = 0;
24 #define NVRAM_INVALID (! nvram_dev)
25
26 static void update_device(unsigned i, unsigned char data)
27 {
28     if (i < nvram_size)
29     {
30         nvram_csum -= nvram_buffer[i];
31         nvram_buffer[i] = data;
32         nvram_dev->write_byte(nvram_dev, i, data);
33         nvram_csum += data;
34     }
35     else
36         printk_info("Offset %d out of range in nvram\n", i);
37 }
38
39 static void update_csum(void)
40 {
41     nvram_dev->write_byte(nvram_dev, nvram_size, nvram_csum);
42     if (nvram_dev->commit)
43         nvram_dev->commit(nvram_dev);
44 }
45
46 static void update_string_device(unsigned i, const unsigned char *data,
47                             unsigned len)
48 {
49     if (i + len < nvram_size)
50     {
51         unsigned j;
52         for(j = 0; j < len; j++)
53         {
54             nvram_csum -= nvram_buffer[i];
55             nvram_buffer[i] = *data;
56             nvram_dev->write_byte(nvram_dev, i, *data);
57             nvram_csum += *data;
58             data++;
59             i++;
60         }   
61     }
62     else
63         printk_info("Offset %d out of range in nvram\n", i + len);
64 }
65
66 int nvram_init (struct nvram_device *dev)
67 {
68     nvram_dev = dev;
69     
70     if (! nvram_size)
71         nvram_size = dev->size(dev) - 1;
72     printk_info("NVRAM size is %d\n", nvram_size);
73     if (!nvram_buffer)
74     {
75         unsigned i;
76         
77         nvram_buffer = malloc (nvram_size);
78         if (!nvram_buffer)
79             return -1;
80
81         nvram_csum = 0;
82         dev->read_block(dev, 0, nvram_buffer, nvram_size+1);
83         for(i = 0; i < nvram_size; i++)
84             nvram_csum += nvram_buffer[i];
85
86         if (nvram_csum != nvram_buffer[nvram_size])
87         {
88             printk_info("NVRAM checksum invalid - erasing\n");
89             //update_device(0, 0);
90             //update_csum();
91         }
92     }
93     printk_info("Initialised nvram\n");
94     return 0;
95 }
96
97 void nvram_clear(void)
98 {
99     printk_info("Erasing NVRAM\n");
100     update_device(0, 0);
101     update_csum();    
102 }
103