~ubuntu-branches/ubuntu/trusty/powerpc-utils/trusty

« back to all changes in this revision

Viewing changes to nwnvsetenv.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Jacobowitz
  • Date: 2001-07-15 22:15:13 UTC
  • Revision ID: james.westby@ubuntu.com-20010715221513-ptyrz3o919viteco
Tags: 1.1.3-5
* Be more aggressive about removing the diversion.
* Be more aggressive about actually documenting the problem.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*      nwnvsetnv.c
 
2
 
 
3
        used to set the Envenrioment variables in power macs NVram.
 
4
        This is for the NewWorld nvram only
 
5
 
 
6
        nwcode: Copyright (C) 2000      by Klaus Halfmann
 
7
 
 
8
        see README for details
 
9
*/
 
10
#include <stdio.h>
 
11
#include <stdlib.h>
 
12
 
 
13
#define __USE_GNU       // need strnlen
 
14
 
 
15
#include <string.h>
 
16
#include <unistd.h>
 
17
#include <fcntl.h>
 
18
 
 
19
// #define MXSTRING        128:
 
20
// #define N_NVVARS     (int)(sizeof(nvvars) / sizeof(nvvars[0]))
 
21
// #define NVMAGIC              0x1275
 
22
 
 
23
/* CHRP NVRAM header */
 
24
typedef struct {
 
25
  unsigned char         signature;
 
26
  unsigned char         cksum;
 
27
  unsigned short        len;
 
28
  char                  name[12];
 
29
  // unsigned char data[0];
 
30
} chrp_header;
 
31
 
 
32
/* Check in proc/cpuinfo if this is a new world machine */
 
33
 
 
34
int checkNewWorld(void)
 
35
{
 
36
    FILE* cpuf = fopen("/proc/cpuinfo","r");
 
37
    char  buf[256]; // "pmac-generation    : NewWolrd|OldWorld 
 
38
    int   result = 0, found = 0;
 
39
 
 
40
    if (!cpuf) {
 
41
        perror("Couldn't open /proc/cpuinfo");
 
42
        exit(EXIT_FAILURE);
 
43
    }
 
44
 
 
45
    while (NULL != fgets(buf, 255, cpuf))
 
46
    {
 
47
        if (!strncmp(buf, "pmac-generation" ,15))
 
48
        {
 
49
            char* index = strchr(buf, ':') + 2;
 
50
            if (!index) // ???
 
51
                continue;
 
52
            result = !strncmp(index,"NewWorld",8);
 
53
            found = 1;
 
54
            break;
 
55
        }
 
56
    }
 
57
    fclose(cpuf);
 
58
 
 
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. */
 
61
    if (!found) {
 
62
        cpuf = fopen("/proc/device-tree/compatible", "r");
 
63
        if(!cpuf)
 
64
            return 0;
 
65
        
 
66
        fgets(buf, 255, cpuf);
 
67
        fclose(cpuf);
 
68
        if (strncmp(buf, "AAPL", 4) != 0)
 
69
            result = 1;
 
70
    }
 
71
 
 
72
    return result; // assume OldWorld
 
73
}
 
74
 
 
75
/* seek NVRAM until common (OF) part 
 
76
   return the lenght of the part in case of sucess,
 
77
          0 otherwise.
 
78
   chrph is set to the value of the "coommon" blocek eventually found
 
79
   *nvstart is set to the seekpoint where common block starts.
 
80
*/
 
81
   
 
82
int nvscan(int nvfd, chrp_header* chrph, int* nvstart)
 
83
{
 
84
    int         start = 0;
 
85
    
 
86
    while (read(nvfd, chrph, sizeof(chrp_header)) == sizeof(chrp_header))
 
87
    {
 
88
        int size = chrph->len * 0x10 - sizeof(chrp_header);     
 
89
        if (!strncmp(chrph->name, "common", 7))
 
90
        {
 
91
            *nvstart = start;
 
92
            return size; // seeked upto start
 
93
        }
 
94
        if (lseek(nvfd, size, SEEK_CUR) < 0)
 
95
           break;
 
96
        start += size + sizeof(chrp_header);
 
97
    }
 
98
    fprintf(stderr,"No common Block found\n");
 
99
    exit(EXIT_FAILURE);
 
100
}
 
101
 
 
102
static char* nvload( int nvfd , int nvsize)
 
103
{
 
104
    char* nvbuf = malloc(nvsize);
 
105
 
 
106
    if (!nvbuf) {
 
107
        perror("Error allocating buffer");
 
108
        exit(EXIT_FAILURE);
 
109
    }
 
110
    if (read(nvfd, nvbuf, nvsize) != nvsize) {
 
111
        perror("Error reading /dev/nvram");
 
112
        exit(EXIT_FAILURE);
 
113
    }
 
114
    return nvbuf;
 
115
}
 
116
 
 
117
static void
 
118
print_vars(char* nvbuf, int nvsize)
 
119
{
 
120
    int i = 0;
 
121
 
 
122
    while (i < nvsize)
 
123
    {
 
124
        int size = strnlen(nvbuf, nvsize);
 
125
        if (size == 0)
 
126
            break;
 
127
        printf("%s\n",nvbuf);
 
128
        nvbuf += (size + 1);    // count 0-byte, too
 
129
    }
 
130
}
 
131
 
 
132
/* move memory around to insert the value.
 
133
 *
 
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
 
140
 */
 
141
static void 
 
142
insert_val (char* nvbufend, int varsize,   char* buf, 
 
143
            char* newval,   int foundsize, int equalpos)
 
144
{
 
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;
 
149
 
 
150
    if (delta > 0) // expand mem
 
151
        memmove(valpos + newlen,
 
152
                valpos + oldlen, (nvbufend - valpos - newlen));
 
153
    else if (delta < 0) // shrink mem
 
154
    {
 
155
        memmove(valpos + newlen, 
 
156
                valpos + oldlen, (nvbufend - valpos - oldlen));
 
157
        memset (nvbufend + delta, 0, -delta );
 
158
    }
 
159
    strncpy(valpos, newval, newlen);
 
160
}
 
161
 
 
162
/* return position where variable is found,
 
163
 * newval may be null.
 
164
 */
 
165
 
 
166
static char* set_var(char* nvbuf, int nvsize, char* varname, char* newval)
 
167
{
 
168
    int i =0;
 
169
    int varsize = strlen(varname);
 
170
    int equalpos;
 
171
    while (i < nvsize)
 
172
    {
 
173
        char* buf = &nvbuf[i];
 
174
        int foundsize = strnlen(buf, nvsize -i);
 
175
        if (foundsize == 0)
 
176
            break;
 
177
        equalpos = (int) (strchr(buf, '=') - buf);
 
178
        if (equalpos == varsize &&
 
179
            !strncmp(buf, varname, equalpos))
 
180
        {
 
181
            if (newval) // set the value 
 
182
                insert_val(nvbuf + nvsize, varsize, buf, 
 
183
                           newval, foundsize, equalpos);
 
184
            return buf;
 
185
        }
 
186
        i += foundsize + 1;     // count 0-byte, too
 
187
    }
 
188
    return NULL;
 
189
}
 
190
 
 
191
static void
 
192
print_var(char* nvbuf, int nvsize, char* varname)
 
193
{
 
194
    char* buf = set_var(nvbuf, nvsize, varname, NULL);
 
195
    if (buf)
 
196
        printf("%s\n",buf);
 
197
}
 
198
 
 
199
/* This fucntion is not used here, it is left
 
200
   her for the curious */
 
201
 
 
202
unsigned short chrp_checksum(chrp_header* hdr, char* nvbuf, int nvsize)
 
203
{
 
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++)
 
209
        sum += *ptr;
 
210
    while (sum > 0xFF)
 
211
        sum = (sum & 0xFF) + (sum>>8);
 
212
    return sum;
 
213
}                                                                                                 
 
214
 
 
215
static void
 
216
nvstore(int nvfd, chrp_header* chrph, char* nvbuf, int nvstart, int nvsize)
 
217
{
 
218
    // mmh, the checksum is calculated for the header only
 
219
    // since we did not modify the header we can just ignore it.
 
220
    ssize_t written;
 
221
    ssize_t seek =  nvstart + sizeof(chrp_header);
 
222
    written = lseek(nvfd, seek, SEEK_SET);
 
223
    if (written != seek)
 
224
    {
 
225
        fprintf(stderr,"Error seeking /dev/nvram\n");
 
226
        exit(EXIT_FAILURE);
 
227
    }
 
228
    written = write(nvfd, nvbuf, nvsize);
 
229
    if (written != nvsize)
 
230
    {
 
231
        fprintf(stderr,"Error writing /dev/nvram %x %x\n", nvsize, seek);
 
232
        exit(EXIT_FAILURE);
 
233
    }
 
234
}
 
235
 
 
236
/* print / set the New World NVRAM */
 
237
 
 
238
void nvNew(int ac, char** av, int nvfd)
 
239
{
 
240
    int                 nvsize, nvstart;
 
241
    chrp_header         chrph;
 
242
    char*               nvbuf;
 
243
 
 
244
    nvsize = nvscan(nvfd, &chrph, &nvstart);
 
245
    nvbuf  = nvload(nvfd, nvsize);
 
246
 
 
247
    switch (ac) {
 
248
    case 1:
 
249
        print_vars(nvbuf, nvsize);
 
250
        break;
 
251
 
 
252
    case 2:
 
253
        print_var(nvbuf, nvsize, av[1]);
 
254
        break;
 
255
        
 
256
    case 3:
 
257
        set_var(nvbuf, nvsize, av[1], av[2]);
 
258
        nvstore(nvfd, &chrph, nvbuf, nvstart, nvsize);
 
259
        break;
 
260
    }
 
261
}