ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / ppc / syslib / prep_nvram.c
1 /*
2  * arch/ppc/kernel/prep_nvram.c
3  *
4  * Copyright (C) 1998  Corey Minyard
5  *
6  * This reads the NvRAM on PReP compliant machines (generally from IBM or
7  * Motorola).  Motorola kept the format of NvRAM in their ROM, PPCBUG, the
8  * same, long after they had stopped producing PReP compliant machines.  So
9  * this code is useful in those cases as well.
10  *
11  */
12 #include <linux/init.h>
13 #include <linux/delay.h>
14 #include <linux/slab.h>
15 #include <linux/ioport.h>
16
17 #include <asm/sections.h>
18 #include <asm/segment.h>
19 #include <asm/io.h>
20 #include <asm/machdep.h>
21 #include <asm/prep_nvram.h>
22
23 static char nvramData[MAX_PREP_NVRAM];
24 static NVRAM_MAP *nvram=(NVRAM_MAP *)&nvramData[0];
25
26 unsigned char __prep prep_nvram_read_val(int addr)
27 {
28         outb(addr, PREP_NVRAM_AS0);
29         outb(addr>>8, PREP_NVRAM_AS1);
30         return inb(PREP_NVRAM_DATA);
31 }
32
33 void __prep prep_nvram_write_val(int           addr,
34                           unsigned char val)
35 {
36         outb(addr, PREP_NVRAM_AS0);
37         outb(addr>>8, PREP_NVRAM_AS1);
38         outb(val, PREP_NVRAM_DATA);
39 }
40
41 void __init init_prep_nvram(void)
42 {
43         unsigned char *nvp;
44         int  i;
45         int  nvramSize;
46
47         /*
48          * The following could fail if the NvRAM were corrupt but
49          * we expect the boot firmware to have checked its checksum
50          * before boot
51          */
52         nvp = (char *) &nvram->Header;
53         for (i=0; i<sizeof(HEADER); i++)
54         {
55                 *nvp = ppc_md.nvram_read_val(i);
56                 nvp++;
57         }
58
59         /*
60          * The PReP NvRAM may be any size so read in the header to
61          * determine how much we must read in order to get the complete
62          * GE area
63          */
64         nvramSize=(int)nvram->Header.GEAddress+nvram->Header.GELength;
65         if(nvramSize>MAX_PREP_NVRAM)
66         {
67                 /*
68                  * NvRAM is too large
69                  */
70                 nvram->Header.GELength=0;
71                 return;
72         }
73
74         /*
75          * Read the remainder of the PReP NvRAM
76          */
77         nvp = (char *) &nvram->GEArea[0];
78         for (i=sizeof(HEADER); i<nvramSize; i++)
79         {
80                 *nvp = ppc_md.nvram_read_val(i);
81                 nvp++;
82         }
83 }
84
85 __prep
86 char __prep *prep_nvram_get_var(const char *name)
87 {
88         char *cp;
89         int  namelen;
90
91         namelen = strlen(name);
92         cp = prep_nvram_first_var();
93         while (cp != NULL) {
94                 if ((strncmp(name, cp, namelen) == 0)
95                     && (cp[namelen] == '='))
96                 {
97                         return cp+namelen+1;
98                 }
99                 cp = prep_nvram_next_var(cp);
100         }
101
102         return NULL;
103 }
104
105 __prep
106 char __prep *prep_nvram_first_var(void)
107 {
108         if (nvram->Header.GELength == 0) {
109                 return NULL;
110         } else {
111                 return (((char *)nvram)
112                         + ((unsigned int) nvram->Header.GEAddress));
113         }
114 }
115
116 __prep
117 char __prep *prep_nvram_next_var(char *name)
118 {
119         char *cp;
120
121
122         cp = name;
123         while (((cp - ((char *) nvram->GEArea)) < nvram->Header.GELength)
124                && (*cp != '\0'))
125         {
126                 cp++;
127         }
128
129         /* Skip over any null characters. */
130         while (((cp - ((char *) nvram->GEArea)) < nvram->Header.GELength)
131                && (*cp == '\0'))
132         {
133                 cp++;
134         }
135
136         if ((cp - ((char *) nvram->GEArea)) < nvram->Header.GELength) {
137                 return cp;
138         } else {
139                 return NULL;
140         }
141 }