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