Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / SLOF / lib / libnvram / envvar.c
1 /******************************************************************************
2  * Copyright (c) 2004, 2008 IBM Corporation
3  * All rights reserved.
4  * This program and the accompanying materials
5  * are made available under the terms of the BSD License
6  * which accompanies this distribution, and is available at
7  * http://www.opensource.org/licenses/bsd-license.php
8  *
9  * Contributors:
10  *     IBM Corporation - initial implementation
11  *****************************************************************************/
12
13 #include <stdint.h>
14 #include "../libc/include/stdio.h"
15 #include "../libc/include/string.h"
16 #include "../libc/include/stdlib.h"
17 #include "nvram.h"
18
19 /* returns the offset of the first byte after the searched envvar */
20 static int get_past_env_pos(partition_t part, char *envvar)
21 {
22         int offset, len;
23         static char temp[256];
24         uint8_t data;
25
26         offset=part.addr;
27
28         memset(temp, 0, 256);
29
30         do {
31                 len=0;
32                 while((data=nvram_read_byte(offset++)) && len < 256) {
33                         temp[len++]=data;
34                 }
35                 if (!strncmp(envvar, temp, strlen(envvar))) {
36                         return offset;
37                 }
38         } while (len);
39
40         return -1;
41 }
42
43 /**
44  * @param partition name of the envvar partition
45  * @param envvar name of the environment variable
46  * @return pointer to temporary string containing the value of envvar
47  */
48
49 char *get_env(partition_t part, char *envvar)
50 {
51         static char temp[256+1];
52         int len, offset;
53         uint8_t data;
54
55         DEBUG("get_env %s... ", envvar);
56         if(!part.addr) {
57                 /* ERROR: No environment variable partition */
58                 DEBUG("invalid partition.\n");
59                 return NULL;
60         }
61
62         offset=part.addr;
63
64         do {
65                 len=0;
66                 while((data=nvram_read_byte(offset++)) && len < 256) {
67                         temp[len++]=data;
68                 }
69                 temp[len]=0;
70
71                 if (!strncmp(envvar, temp, strlen(envvar))) {
72                         int pos=0;
73                         while (temp[pos]!='=' && pos < len) pos++;
74                         // DEBUG("value='%s'\n", temp+pos+1); 
75                         return temp+pos+1;
76                 }
77         } while (len);
78
79         DEBUG("not found\n");
80         return NULL;
81 }
82
83 static int find_last_envvar(partition_t part)
84 {
85         uint8_t last, current;
86         int offset;
87
88         offset=part.addr;
89
90         last=nvram_read_byte(part.addr);
91
92         for (offset=part.addr; offset<(int)(part.addr+part.len); offset++) {
93                 current=nvram_read_byte(offset);
94                 if(!last && !current)
95                         return offset;
96
97                 last=current;
98         }
99
100         return -1;
101 }
102
103 int add_env(partition_t part, char *envvar, char *value)
104 {
105         int freespace, last, len, offset;
106         unsigned int i;
107
108         /* Find offset where we can write */
109         last = find_last_envvar(part);
110
111         /* How much space do we have left? */
112         freespace = part.addr+part.len-last;
113
114         /* how long is the entry we want to write? */
115         len = strlen(envvar) + strlen(value) + 2;
116
117         if(freespace<len) {
118                 // TODO try to increase partition size
119                 return -1;
120         }
121
122         offset=last;
123
124         for(i=0; i<strlen(envvar); i++)
125                 nvram_write_byte(offset++, envvar[i]);
126
127         nvram_write_byte(offset++, '=');
128
129         for(i=0; i<strlen(value); i++)
130                 nvram_write_byte(offset++, value[i]);
131
132         return 0;
133 }
134
135 int del_env(partition_t part, char *envvar)
136 {
137         int last, current, pos, i;
138         char *buffer;
139
140         if(!part.addr)
141                 return -1;
142
143         last=find_last_envvar(part);
144         current = pos = get_past_env_pos(part, envvar);
145         
146         // TODO is this really required?
147         /* go back to non-0 value */
148         current--;
149
150         while (nvram_read_byte(current))
151                 current--;
152
153         // TODO is this required?
154         current++;
155
156         buffer=get_nvram_buffer(last-pos);
157
158         for (i=0; i<last-pos; i++)
159                 buffer[i]=nvram_read_byte(i+pos);
160
161         for (i=0; i<last-pos; i++)
162                 nvram_write_byte(i+current, buffer[i]);
163
164         free_nvram_buffer(buffer);
165
166         erase_nvram(last, current+last-pos);
167
168         return 0;
169 }
170
171 int set_env(partition_t part, char *envvar, char *value)
172 {
173         char *oldvalue, *buffer;
174         int last, current, buffersize, i;
175
176         DEBUG("set_env %lx[%lx]: %s=%s\n", part.addr, part.len, envvar, value);
177
178         if(!part.addr)
179                 return -1;
180
181         /* Check whether the environment variable exists already */
182         oldvalue = get_env(part, envvar);
183
184         if(oldvalue==NULL)
185                 return add_env(part, envvar, value);
186
187
188         /* The value did not change. So we succeeded! */
189         if(!strncmp(oldvalue, value, strlen(value)+1))
190                 return 0;
191
192         /* we need to overwrite environment variables, back them up first */
193
194         // DEBUG("overwriting existing environment variable\n");
195
196         /* allocate a buffer */
197         last=find_last_envvar(part);
198         current=get_past_env_pos(part, envvar);
199         buffersize = last - current;
200         buffer=get_nvram_buffer(buffersize);
201         if(!buffer)
202                 return -1;
203
204         for (i=0; i<buffersize; i++) {
205                 buffer[i] = nvram_read_byte(current+i);
206         }
207
208         /* walk back until the = */
209         while (nvram_read_byte(current)!='=') {
210                 current--;
211         }
212
213         /* Start at envvar= */
214         current++;
215
216         /* Write the new value */
217         for(i=0; i<(int)strlen(value); i++) {
218                 nvram_write_byte(current++, value[i]);
219         }
220         
221         /* Write end of string marker */
222         nvram_write_byte(current++, 0);
223
224         /* Copy back the buffer */
225         for (i=0; i<buffersize; i++) {
226                 nvram_write_byte(current++, buffer[i]);
227         }
228
229         free_nvram_buffer(buffer);
230
231         /* If the new environment variable content is shorter than the old one,
232          * we need to erase the rest of the bytes 
233          */
234
235         if (current<last) {
236                 for(i=current; i<last; i++) {
237                         nvram_write_byte(i, 0);
238                 }
239         }
240
241         return 0; /* success */
242 }
243