3
used to set the Envenrioment variables in power macs NVram.
4
This is for the NewWorld nvram only
6
nwcode: Copyright (C) 2000 by Klaus Halfmann
13
#define __USE_GNU // need strnlen
19
// #define MXSTRING 128:
20
// #define N_NVVARS (int)(sizeof(nvvars) / sizeof(nvvars[0]))
21
// #define NVMAGIC 0x1275
23
/* CHRP NVRAM header */
25
unsigned char signature;
29
// unsigned char data[0];
32
/* Check in proc/cpuinfo if this is a new world machine */
34
int checkNewWorld(void)
36
FILE* cpuf = fopen("/proc/cpuinfo","r");
37
char buf[256]; // "pmac-generation : NewWolrd|OldWorld
38
int result = 0, found = 0;
41
perror("Couldn't open /proc/cpuinfo");
45
while (NULL != fgets(buf, 255, cpuf))
47
if (!strncmp(buf, "pmac-generation" ,15))
49
char* index = strchr(buf, ':') + 2;
52
result = !strncmp(index,"NewWorld",8);
59
/* Some kernels don't have pmac-generation ( <= 2.2.15 and earlier 2.3.x ) */
60
/* Look for AAPL in /proc/device-tree/compatible instead. */
62
cpuf = fopen("/proc/device-tree/compatible", "r");
66
fgets(buf, 255, cpuf);
68
if (strncmp(buf, "AAPL", 4) != 0)
72
return result; // assume OldWorld
75
/* seek NVRAM until common (OF) part
76
return the lenght of the part in case of sucess,
78
chrph is set to the value of the "coommon" blocek eventually found
79
*nvstart is set to the seekpoint where common block starts.
82
int nvscan(int nvfd, chrp_header* chrph, int* nvstart)
86
while (read(nvfd, chrph, sizeof(chrp_header)) == sizeof(chrp_header))
88
int size = chrph->len * 0x10 - sizeof(chrp_header);
89
if (!strncmp(chrph->name, "common", 7))
92
return size; // seeked upto start
94
if (lseek(nvfd, size, SEEK_CUR) < 0)
96
start += size + sizeof(chrp_header);
98
fprintf(stderr,"No common Block found\n");
102
static char* nvload( int nvfd , int nvsize)
104
char* nvbuf = malloc(nvsize);
107
perror("Error allocating buffer");
110
if (read(nvfd, nvbuf, nvsize) != nvsize) {
111
perror("Error reading /dev/nvram");
118
print_vars(char* nvbuf, int nvsize)
124
int size = strnlen(nvbuf, nvsize);
127
printf("%s\n",nvbuf);
128
nvbuf += (size + 1); // count 0-byte, too
132
/* move memory around to insert the value.
134
* @param nvbufend byte AFTER the end of the buffer
135
* @param varsize length of the variable name
136
* @param buf byte where varaible NAME starts
137
* @param newval new value to replace old one
138
* @param foundsize lenght of varible + '=' + value
139
* @param equalpos position relative to buf where '=' was found
142
insert_val (char* nvbufend, int varsize, char* buf,
143
char* newval, int foundsize, int equalpos)
145
int oldlen = foundsize - equalpos -1; // account for the '='
146
int newlen = strlen(newval);
147
char* valpos = buf + varsize + 1;
148
int delta = newlen - oldlen;
150
if (delta > 0) // expand mem
151
memmove(valpos + newlen,
152
valpos + oldlen, (nvbufend - valpos - newlen));
153
else if (delta < 0) // shrink mem
155
memmove(valpos + newlen,
156
valpos + oldlen, (nvbufend - valpos - oldlen));
157
memset (nvbufend + delta, 0, -delta );
159
strncpy(valpos, newval, newlen);
162
/* return position where variable is found,
163
* newval may be null.
166
static char* set_var(char* nvbuf, int nvsize, char* varname, char* newval)
169
int varsize = strlen(varname);
173
char* buf = &nvbuf[i];
174
int foundsize = strnlen(buf, nvsize -i);
177
equalpos = (int) (strchr(buf, '=') - buf);
178
if (equalpos == varsize &&
179
!strncmp(buf, varname, equalpos))
181
if (newval) // set the value
182
insert_val(nvbuf + nvsize, varsize, buf,
183
newval, foundsize, equalpos);
186
i += foundsize + 1; // count 0-byte, too
192
print_var(char* nvbuf, int nvsize, char* varname)
194
char* buf = set_var(nvbuf, nvsize, varname, NULL);
199
/* This fucntion is not used here, it is left
200
her for the curious */
202
unsigned short chrp_checksum(chrp_header* hdr, char* nvbuf, int nvsize)
204
unsigned char* ptr = (unsigned char*) &hdr->len;
205
unsigned char* end = ptr + sizeof(chrp_header);
206
unsigned short sum = hdr->signature;
207
// this in fact skips the checksum
208
for (; ptr < end; ptr++)
211
sum = (sum & 0xFF) + (sum>>8);
216
nvstore(int nvfd, chrp_header* chrph, char* nvbuf, int nvstart, int nvsize)
218
// mmh, the checksum is calculated for the header only
219
// since we did not modify the header we can just ignore it.
221
ssize_t seek = nvstart + sizeof(chrp_header);
222
written = lseek(nvfd, seek, SEEK_SET);
225
fprintf(stderr,"Error seeking /dev/nvram\n");
228
written = write(nvfd, nvbuf, nvsize);
229
if (written != nvsize)
231
fprintf(stderr,"Error writing /dev/nvram %x %x\n", nvsize, seek);
236
/* print / set the New World NVRAM */
238
void nvNew(int ac, char** av, int nvfd)
244
nvsize = nvscan(nvfd, &chrph, &nvstart);
245
nvbuf = nvload(nvfd, nvsize);
249
print_vars(nvbuf, nvsize);
253
print_var(nvbuf, nvsize, av[1]);
257
set_var(nvbuf, nvsize, av[1], av[2]);
258
nvstore(nvfd, &chrph, nvbuf, nvstart, nvsize);