source: patches/powerpc-utils_1.1.3-fixes-2.patch @ 3ef83ab

clfs-3.0.0-systemdsystemd
Last change on this file since 3ef83ab was f2b4aa3, checked in by Jim Gifford <clfs@…>, 18 years ago

r3499@server (orig r1599): ken | 2006-05-14 14:04:50 -0700
Add missing ppc64/ppc patches.

  • Property mode set to 100644
File size: 21.4 KB
RevLine 
[f2b4aa3]1Submitted By: Ken Moffat <ken@linuxfromscratch.org>
2Date: 2005-11-23
3Initial Package Version: 1.1.3
4Upstream Status: Package is maintained by debian, this cherry-picks
5Origin: From debian 1.1.3-18.diff, edited
6Description: Makes it work on New World, fixes compile error, updated to
7 allow -m32 to be passed via EXTRACFLAGS in multilib.
8
9 Some of the debian powerpc-utils_1.1.3-18.diff, but only the parts relevant
10to nvsetenv and nvsetvol - the remainder may be useful on an Old World Mac,
11but they are no use on New World.  The -D_GNU_SOURCE apparently helps on
12powerpc64.  I've also removed bogus messages advising you to update your
13headers when IOC_NVRAM_SYNC isn't defined : it hasn't existed for a long
14time.  Finally, I ran the nvsetenv.sgml through docbook2txt -man to get a
15proper man page, because most people won't have docbook utils installed.
16
17diff -Nuar pmac-utils.orig/Makefile pmac-utils/Makefile
18--- pmac-utils.orig/Makefile    1998-07-21 14:22:28.000000000 +0100
19+++ pmac-utils/Makefile 2005-11-17 15:16:52.000000000 +0000
20@@ -22,8 +22,8 @@
21 
22 SGMLMAN        = sgml2txt -man
23 CC     = gcc -Wall -Wstrict-prototypes
24-CFLAGS = -O2 -fsigned-char
25-LDFLAGS = -s
26+CFLAGS = $(EXTRACFLAGS) -O2 -fsigned-char -D_GNU_SOURCE
27+LDFLAGS =
28 INSTALL        = /usr/bin/install -c
29 SOUND_INC = -I.
30 
31@@ -42,8 +42,12 @@
32 mousemode:
33        $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $@.c
34 
35-nvsetenv:
36+nvsetenv: nvsetenv.c nwnvsetenv.c
37+       $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $@.c nwnvsetenv.c
38+
39+nvsetvol:
40        $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $@.c
41+
42 
43 nvvideo:
44        $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $@.c
45diff -Nuar pmac-utils.orig/nvsetenv.8 pmac-utils/nvsetenv.8
46--- pmac-utils.orig/nvsetenv.8  1970-01-01 01:00:00.000000000 +0100
47+++ pmac-utils/nvsetenv.8       2005-11-17 20:39:47.000000000 +0000
48@@ -0,0 +1,256 @@
49+.if n .ds Q \&"
50+.if t .ds Q ``
51+.if n .ds U \&"
52+.if t .ds U ''
53+.TH "NVSETENV" 8
54+.tr \&
55+.nr bi 0
56+.nr ll 0
57+.nr el 0
58+.de DS
59+..
60+.de DE
61+..
62+.de Pp
63+.ie \\n(ll>0 \{\
64+.ie \\n(bi=1 \{\
65+.nr bi 0
66+.if \\n(t\\n(ll=0 \{.IP \\(bu\}
67+.if \\n(t\\n(ll=1 \{.IP \\n+(e\\n(el.\}
68+.\}
69+.el .sp
70+.\}
71+.el \{\
72+.ie \\nh=1 \{\
73+.LP
74+.nr h 0
75+.\}
76+.el .PP
77+.\}
78+..
79+.SH NAME
80+
81+.Pp
82+\fBnvsetenv\fP - change/view Open Firmware environment variables
83+.Pp
84+.SH SYNOPSIS
85+
86+.Pp
87+\fBnvsetenv
88+\f(CR[\fP\fIvariable\fP \f(CR[\fP\fIvalue\fP\f(CR\fB]]\fP\fP\fP
89+.Pp
90+.SH DESCRIPTION
91+
92+.Pp
93+\fBnvsetenv\fP is a program to adjust or view the Open Firmware (OF)
94+boot parameters stored in non-volatile (battery-powered) RAM.
95+\fBnvsetenv\fP will show the current values of all OF's environment
96+variables when no parameters are given.
97+.Pp
98+.SH OPTIONS
99+
100+.Pp
101+.nr ll +1
102+.nr t\n(ll 2
103+.if \n(ll>1 .RS
104+.IP "\fIvariable\fP"
105+.nr bi 1
106+.Pp
107+nvsetenv will show current value of an OF's
108+variable, if no value is given
109+.IP "\fIvariable value\fP"
110+.nr bi 1
111+.Pp
112+nvsetenv will set \fIvariable\fP to
113+\fIvalue\fP
114+.if \n(ll>1 .RE
115+.nr ll -1
116+.Pp
117+.SH EXAMPLES
118+
119+.Pp
120+This example will set the boot device to the first SCSI disk on the
121+internal SCSI bus, using /vmlinux as boot image, trying to
122+use the third partition as root partition.
123+.DS
124+.sp
125+.ft RR
126+.nf
127+        > nvsetenv boot-device  \&"scsi-int/sd@0:0\&"
128+        > nvsetenv boot-file    \&" /vmlinux root=/dev/sda3\&"
129+.DE
130+.fi
131+.ec
132+.ft P
133+.sp
134+.Pp
135+Alternatives boot devices are:
136+.DS
137+.sp
138+.ft RR
139+.nf
140+        scsi/sd@1:0             SCSI disk at ID 1
141+        ata/ata-disk@0:0        Internal IDE disk
142+.DE
143+.fi
144+.ec
145+.ft P
146+.sp
147+.Pp
148+You can also boot from a floppy, you need a XCOFF-format kernel image
149+(in this example: vmlinux.coff), copied to a HFS format high-density
150+(1.44Mb) floppy.
151+.DS
152+.sp
153+.ft RR
154+.nf
155+        > nvsetenv boot-device  \&"fd:vmlinux.coff\&"
156+        > nvsetenv boot-file    \&" root=/dev/sda3\&"
157+.DE
158+.fi
159+.ec
160+.ft P
161+.sp
162+
163+To return to MacOS, do:
164+.DS
165+.sp
166+.ft RR
167+.nf
168+        > nvsetenv boot-device  \&"/AAPL,ROM\&"
169+.DE
170+.fi
171+.ec
172+.ft P
173+.sp
174+.Pp
175+Valid values for \&"input-devices\&" are:
176+.DS
177+.sp
178+.ft RR
179+.nf
180+        ttya                    Modem serial port
181+        ttyb                    Printer serial port
182+        kbd                     Keyboard
183+        enet                    Ethernet interface
184+.DE
185+.fi
186+.ec
187+.ft P
188+.sp
189+.Pp
190+Valid values for \&"output-devices\&" are (machine and/or OF dependent):
191+.DS
192+.sp
193+.ft RR
194+.nf
195+        screen                  Screen display (newer machines)
196+        /chaos/control          Screen display (7500, 7600 and 8500)
197+        /bandit/ATY,264GT-B     Screen display (6500)
198+.DE
199+.fi
200+.ec
201+.ft P
202+.sp
203+.Pp
204+OF is not designed to wait for your hard disk to spin up
205+(remember MacOS boots from ROM).
206+Use the following setting to have OF retry to boot from your disk
207+until is has spun up:
208+.DS
209+.sp
210+.ft RR
211+.nf
212+        > nvsetenv boot-command \&"begin ['] boot catch 1000 ms cr again\&"
213+.DE
214+.fi
215+.ec
216+.ft P
217+.sp
218+.Pp
219+You only have to append an \&"S\&" to the \&"boot-file\&" variable to boot
220+Linux in single user mode.
221+.Pp
222+You can use install your own nvramrc patch using the following command:
223+.DS
224+.sp
225+.ft RR
226+.nf
227+        > nvsetenv nvramrc \&"`cat file.patch`\&"
228+.DE
229+.fi
230+.ec
231+.ft P
232+.sp
233+
234+(please note the backticks!), or:
235+.DS
236+.sp
237+.ft RR
238+.nf
239+        > nvsetenv nvramrc \&"$(cat file.patch)\&"
240+.DE
241+.fi
242+.ec
243+.ft P
244+.sp
245+.Pp
246+.SH FILES
247+
248+.Pp
249+.nr ll +1
250+.nr t\n(ll 2
251+.if \n(ll>1 .RS
252+.IP "\fI/dev/nvram\fP"
253+.nr bi 1
254+.Pp
255+character device with major number 10
256+and minor number 144
257+.IP "\fI/proc/cpuinfo\fP"
258+.nr bi 1
259+.Pp
260+to identify New/Old-World machines
261+.if \n(ll>1 .RE
262+.nr ll -1
263+.Pp
264+.SH SEE ALSO
265+
266+.Pp
267+macos(8)
268+.Pp
269+.SH AUTHORS
270+
271+.Pp
272+.DS
273+.sp
274+.ft RR
275+.nf
276+Paul Mackerras <paulus@cs.anu.edu.au> (program)
277+.DE
278+.fi
279+.ec
280+.ft P
281+.sp
282+
283+.DS
284+.sp
285+.ft RR
286+.nf
287+Richard van Hees <R.M.vanHees@phys.uu.nl> (documentation)
288+.DE
289+.fi
290+.ec
291+.ft P
292+.sp
293+
294+.DS
295+.sp
296+.ft RR
297+.nf
298+Klaus Halfmann  <halfmann@libra.de> (NewWorld code)
299+.DE
300+.fi
301+.ec
302+.ft P
303+.sp
304+.Pp
305diff -Nuar pmac-utils.orig/nvsetenv.c pmac-utils/nvsetenv.c
306--- pmac-utils.orig/nvsetenv.c  1997-04-28 14:29:05.000000000 +0100
307+++ pmac-utils/nvsetenv.c       2005-11-17 14:57:57.000000000 +0000
308@@ -1,15 +1,32 @@
309+/*     nvsetnv.c
310+
311+       used to set the Envenrioment variables in power macs NVram.
312+       Decides via /proc/cpuinfo which type of machine is used.
313+
314+               Copyright (C) 1996-1998 by Paul Mackerras.
315+       nwcode: Copyright (C) 2000      by Klaus Halfmann
316+
317+       see README for details
318+*/
319+
320 #include <stdio.h>
321 #include <stdlib.h>
322 #include <string.h>
323 #include <unistd.h>
324 #include <fcntl.h>
325+#include <sys/ioctl.h>
326+#include <asm/nvram.h>
327+#ifndef IOC_NVRAM_SYNC
328+#define IOC_NVRAM_SYNC _IO('p', 0x43)
329+#endif
330 
331-#define NVSTART        0x1800
332-#define NVSIZE 0x800
333+#define NVSTART                0x1800  // Start of the NVRam OF partition
334+#define NVSIZE         0x800   // Size of of the NVRam
335 #define MXSTRING        128
336 #define N_NVVARS       (int)(sizeof(nvvars) / sizeof(nvvars[0]))
337+#define NVMAGIC                0x1275
338 
339-static int nvfd, nvstr_used;
340+static int  nvstr_used;
341 static char nvstrbuf[NVSIZE];
342 
343 struct nvram {
344@@ -24,12 +41,13 @@
345     unsigned long  vals[1];
346 };
347 
348-union {
349-    struct nvram nv;
350-    char c[NVSIZE];
351-    unsigned short s[NVSIZE/2];
352-} nvbuf;
353+typedef union {
354+    struct nvram       nv;
355+    char               c[NVSIZE];
356+    unsigned short     s[NVSIZE/2];
357+} nvbuftype;
358 
359+nvbuftype nvbuf;
360 
361 enum nvtype {
362     boolean,
363@@ -70,16 +88,21 @@
364     {"boot-command", string},
365 };
366 
367+       // Calculated number of variables
368+#define N_NVVARS       (int)(sizeof(nvvars) / sizeof(nvvars[0]))
369+
370 union nvval {
371-    unsigned long word_val;
372-    char *str_val;
373+    unsigned long      word_val;
374+    char               *str_val;
375 } nvvals[32];
376 
377-int
378-nvcsum( void )
379+extern int checkNewWorld(void);                // from nwnvsetenv
380+extern int nvNew(int ac, char** av, int nfd);  // from nwnvsetenv
381+
382+int nvcsum( void )
383 {
384-    int i;
385-    unsigned c;
386+    int        i;
387+    unsigned   c;
388     
389     c = 0;
390     for (i = 0; i < NVSIZE/2; ++i)
391@@ -89,28 +112,29 @@
392     return c & 0xffff;
393 }
394 
395-void
396-nvload( void )
397+static void nvload( int nvfd )
398 {
399     int s;
400 
401     if (lseek(nvfd, NVSTART, 0) < 0
402        || read(nvfd, &nvbuf, NVSIZE) != NVSIZE) {
403-       perror("Error reading /dev/nvram");
404+       perror("Error reading nvram device");
405        exit(EXIT_FAILURE);
406     }
407+    if (nvbuf.nv.magic != NVMAGIC)
408+       (void) fprintf(stderr, "Warning: Bad magic number %x\n",
409+                        nvbuf.nv.magic);
410     s = nvcsum();
411     if (s != 0xffff)
412        (void) fprintf(stderr, "Warning: checksum error (%x) on nvram\n",
413                      s ^ 0xffff);
414 }
415 
416-void
417-nvstore(void)
418+static void nvstore(int nvfd)
419 {
420     if (lseek(nvfd, NVSTART, 0) < 0
421        || write(nvfd, &nvbuf, NVSIZE) != NVSIZE) {
422-       perror("Error writing /dev/nvram");
423+       perror("Error writing nvram device");
424        exit(EXIT_FAILURE);
425     }
426 }
427@@ -145,8 +169,7 @@
428     }
429 }
430 
431-void
432-nvpack( void )
433+void nvpack( void )
434 {
435     int     i, vi;
436     size_t  off, len;
437@@ -184,7 +207,7 @@
438     nvbuf.nv.cksum = (unsigned short int) (~nvcsum());
439 }
440 
441-void
442+static void
443 print_var(int i, int indent)
444 {
445     char *p;
446@@ -207,8 +230,7 @@
447     (void) printf("\n");
448 }
449 
450-void
451-parse_val(int i, char *str)
452+void parse_val(int i, char *str)
453 {
454     char *endp;
455 
456@@ -238,12 +260,38 @@
457     }
458 }
459 
460-int
461-main(int ac, char **av)
462+
463+void nvOld(int ac, char** av, int i, int nvfd)
464+{
465+    nvload(nvfd);
466+    nvunpack();
467+
468+    switch (ac) {
469+    case 1:
470+       for (i = 0; i < N_NVVARS; ++i) {
471+           (void) printf("%-16s", nvvars[i].name);
472+           print_var(i, 16);
473+       }
474+       break;
475+
476+    case 2:
477+       print_var(i, 0);
478+       break;
479+       
480+    case 3:
481+       parse_val(i, av[2]);
482+       nvpack();
483+       nvstore(nvfd);
484+       break;
485+    }
486+}
487+
488+int main(int ac, char **av)
489 {
490-    int i = 0, l, print;
491+    int i = 0, l, print, nvfd, newWorld;
492 
493     l = (int) strlen(av[0]);
494+    // print when no value is set OR we are aclled as <xxx>printenv
495     print = (int) (ac <= 2 ||
496                   (l > 8 && strcmp(&av[0][l-8], "printenv") == 0));
497     if (print != 0 && ac > 2) {
498@@ -255,7 +303,9 @@
499        exit(EXIT_FAILURE);
500     }
501 
502-    if (ac >= 2) {
503+    newWorld = checkNewWorld();
504+   
505+    if (!newWorld && ac >= 2) {
506        for (i = 0; i < N_NVVARS; ++i)
507            if (strcmp(av[1], nvvars[i].name) == 0)
508                break;
509@@ -266,33 +316,21 @@
510        }
511     }
512 
513-    nvfd = open("/dev/nvram", ac <= 2 ? O_RDONLY: O_RDWR);
514+    nvfd = open("/dev/misc/nvram", ac <= 2 ? O_RDONLY: O_RDWR);
515     if (nvfd < 0) {
516-       perror("Couldn't open /dev/nvram");
517+      nvfd = open("/dev/nvram", ac <= 2 ? O_RDONLY: O_RDWR);
518+      if (nvfd < 0) {
519+       perror("Couldn't open nvram device");
520        exit(EXIT_FAILURE);
521-    }
522-    nvload();
523-    nvunpack();
524-
525-    switch (ac) {
526-    case 1:
527-       for (i = 0; i < N_NVVARS; ++i) {
528-           (void) printf("%-16s", nvvars[i].name);
529-           print_var(i, 16);
530-       }
531-       break;
532-
533-    case 2:
534-       print_var(i, 0);
535-       break;
536-       
537-    case 3:
538-       parse_val(i, av[2]);
539-       nvpack();
540-       nvstore();
541-       break;
542+      }
543     }
544 
545+    if (newWorld)
546+       nvNew(ac, av, nvfd);
547+    else
548+       nvOld(ac, av, i, nvfd);
549+   
550+    (void) ioctl(nvfd, IOC_NVRAM_SYNC);
551     (void) close(nvfd);
552     exit(EXIT_SUCCESS);
553 }
554diff -Nuar pmac-utils.orig/nvsetvol.8 pmac-utils/nvsetvol.8
555--- pmac-utils.orig/nvsetvol.8  1970-01-01 01:00:00.000000000 +0100
556+++ pmac-utils/nvsetvol.8       2005-11-17 21:37:20.000000000 +0000
557@@ -0,0 +1,27 @@
558+.TH NVSETVOL 8 "16th February 2003"
559+
560+.SH NAME
561+nvsetvol \- tool for changing startup volume of PowerMac machines
562+
563+.SH SYNOPSIS
564+.B nvsetvol
565+[
566+.B volume
567+]
568+
569+.SH DESCRIPTION
570+.B nvsetvol
571+queries and sets the base volume of a PowerMac machine.  With no options,
572+.B nvsetvol
573+displays the current volume; with a numerical argument, it sets the volume.
574+The
575+.B volume
576+argument should be a number from 0 to 255.  0 will turn off the annoying
577+startup chime.
578+
579+.SH AUTHOR
580+.B nvsetvol
581+was written by Matteo Frigo <athena@fftw.org>.
582+
583+This manual page was written by Daniel Jacobowitz <dan@debian.org> for the
584+Debian GNU/Linux distribution.
585diff -Nuar pmac-utils.orig/nvsetvol.c pmac-utils/nvsetvol.c
586--- pmac-utils.orig/nvsetvol.c  1970-01-01 01:00:00.000000000 +0100
587+++ pmac-utils/nvsetvol.c       2005-11-17 21:43:16.000000000 +0000
588@@ -0,0 +1,110 @@
589+/* set volume of the startup chime in the PowerMac nvram.
590+
591+   Written by Matteo Frigo <athena@fftw.org>.
592+   $Id: nvsetvol.c,v 1.1 2003/01/11 11:26:30 athena Exp $
593+
594+   This program is in the public domain.
595+*/
596+
597+/* The volume is stored as a byte at address 8 in the parameter ram. */
598+
599+#include <string.h>
600+#include <stdio.h>
601+#include <stdlib.h>
602+#include <sys/types.h>
603+#include <sys/stat.h>
604+#include <unistd.h>
605+#include <fcntl.h>
606+#include <sys/ioctl.h>
607+#include <asm/nvram.h>
608+#ifndef IOC_NVRAM_SYNC
609+#define IOC_NVRAM_SYNC _IO('p', 0x43)
610+#endif
611+
612+typedef struct {
613+     unsigned char sig;
614+     unsigned char cksum;
615+     unsigned short len;
616+     char name[12];
617+} header;
618+
619+void die(const char *s) __attribute__((noreturn));
620+void die(const char *s)
621+{
622+     perror(s);
623+     exit(1);
624+}
625+
626+void seek_pram(int fd, int offset)
627+{
628+     if (lseek(fd, offset, SEEK_SET) < 0)
629+         die("lseek");
630+}
631+
632+// MSch: only works for newworld - oldworld have XPRAM at offset 0x1300 fixed.
633+
634+int find_pram(int fd, int *size)
635+{
636+     header buf;
637+     int offset = 0;
638+     int rc = 0;
639+     while((rc = read(fd, &buf, sizeof(header))) == sizeof(header)) {
640+         int sz = buf.len * 16;
641+         // what's the sig in char?
642+         // if (buf.sig == 0x1275) fprintf(stderr, "sig at offset %d rc %d buf.len %d buf.name %s \n", offset, rc, buf.len, buf.name);
643+         // if (buf.sig == 0x5a) fprintf(stderr, "sig at offset %x rc %d buf.len %x buf.name %s \n", offset, rc, buf.len, buf.name);
644+         // if (sz) fprintf(stderr, "offset %x rc %d sig %x buf.len %x buf.name %s \n", offset, rc, buf.sig, buf.len, buf.name);
645+         if (!strncmp(buf.name, "APL,MacOS75", 11)) {
646+              *size = sz - sizeof(header);
647+              // fprintf(stderr, "XPRAM offset %x size %x\n", offset + sizeof(header), *size);
648+              return offset + sizeof(header);
649+         }
650+         if (sz)
651+           offset += sz;
652+          else
653+            offset += sizeof(header);
654+         seek_pram(fd, offset);
655+     }
656+     // no Core99 style PRAM found - just assume hard coded values as set in kernel:
657+     // XPRAM 0x1300
658+     // NR    0x1400
659+     // OF    0x1800
660+     // TODO: use ioctl to get PRAM offset
661+     // fprintf(stderr, "no NW PRAM found, assuming OW XPRAM offset 0x1300 size 0x100\n");
662+     *size = 0x100;
663+     return (0x1300);
664+     die("no PRAM found");
665+}
666+
667+#define VOLADDR 8
668+
669+int main(int argc, char *argv[])
670+{
671+     int fd, offset, size;
672+     char *buf;
673+
674+     fd = open("/dev/nvram", O_RDWR);
675+     if (fd < 0) die("can't open /dev/nvram");
676+     
677+     offset = find_pram(fd, &size);
678+     buf = malloc(size);
679+     if (!buf) die("can't malloc()");
680+
681+     seek_pram(fd, offset);
682+     if (read(fd, buf, size) != size)
683+         die("error reading /dev/nvram");
684+
685+     printf("current volume is %d\n", (unsigned char) buf[VOLADDR]);
686+     
687+     if (argc > 1) {
688+         buf[VOLADDR] = atoi(argv[1]);
689+
690+         seek_pram(fd, offset);
691+         if (write(fd, buf, size) != size)
692+              die("error writing /dev/nvram");
693+         printf("new volume is %d\n", (unsigned char) buf[VOLADDR]);
694+     }
695+     ioctl(fd, IOC_NVRAM_SYNC);
696+     close(fd);
697+     return 0;
698+}
699diff -Nuar pmac-utils.orig/nwnvsetenv.c pmac-utils/nwnvsetenv.c
700--- pmac-utils.orig/nwnvsetenv.c        1970-01-01 01:00:00.000000000 +0100
701+++ pmac-utils/nwnvsetenv.c     2005-11-17 21:37:27.000000000 +0000
702@@ -0,0 +1,261 @@
703+/*     nwnvsetnv.c
704+
705+       used to set the Envenrioment variables in power macs NVram.
706+       This is for the NewWorld nvram only
707+
708+       nwcode: Copyright (C) 2000      by Klaus Halfmann
709+
710+       see README for details
711+*/
712+#include <stdio.h>
713+#include <stdlib.h>
714+
715+#define __USE_GNU      // need strnlen
716+
717+#include <string.h>
718+#include <unistd.h>
719+#include <fcntl.h>
720+
721+// #define MXSTRING        128:
722+// #define N_NVVARS    (int)(sizeof(nvvars) / sizeof(nvvars[0]))
723+// #define NVMAGIC             0x1275
724+
725+/* CHRP NVRAM header */
726+typedef struct {
727+  unsigned char                signature;
728+  unsigned char                cksum;
729+  unsigned short       len;
730+  char                 name[12];
731+  // unsigned char data[0];
732+} chrp_header;
733+
734+/* Check in proc/cpuinfo if this is a new world machine */
735+
736+int checkNewWorld(void)
737+{
738+    FILE* cpuf = fopen("/proc/cpuinfo","r");
739+    char  buf[256]; // "pmac-generation    : NewWolrd|OldWorld
740+    int          result = 0, found = 0;
741+
742+    if (!cpuf) {
743+       perror("Couldn't open /proc/cpuinfo");
744+       exit(EXIT_FAILURE);
745+    }
746+
747+    while (NULL != fgets(buf, 255, cpuf))
748+    {
749+       if (!strncmp(buf, "pmac-generation" ,15))
750+       {
751+           char* index = strchr(buf, ':') + 2;
752+           if (!index) // ???
753+               continue;
754+           result = !strncmp(index,"NewWorld",8);
755+           found = 1;
756+           break;
757+       }
758+    }
759+    fclose(cpuf);
760+
761+    /* Some kernels don't have pmac-generation ( <= 2.2.15 and earlier 2.3.x ) */
762+    /* Look for AAPL in /proc/device-tree/compatible instead. */
763+    if (!found) {
764+       cpuf = fopen("/proc/device-tree/compatible", "r");
765+       if(!cpuf)
766+           return 0;
767+       
768+       fgets(buf, 255, cpuf);
769+       fclose(cpuf);
770+       if (strncmp(buf, "AAPL", 4) != 0)
771+           result = 1;
772+    }
773+
774+    return result; // assume OldWorld
775+}
776+
777+/* seek NVRAM until common (OF) part
778+   return the lenght of the part in case of sucess,
779+         0 otherwise.
780+   chrph is set to the value of the "coommon" blocek eventually found
781+   *nvstart is set to the seekpoint where common block starts.
782+*/
783+   
784+int nvscan(int nvfd, chrp_header* chrph, int* nvstart)
785+{
786+    int                start = 0;
787+   
788+    while (read(nvfd, chrph, sizeof(chrp_header)) == sizeof(chrp_header))
789+    {
790+       int size = chrph->len * 0x10 - sizeof(chrp_header);     
791+       if (!strncmp(chrph->name, "common", 7))
792+       {
793+           *nvstart = start;
794+           return size; // seeked upto start
795+       }
796+       if (lseek(nvfd, size, SEEK_CUR) < 0)
797+          break;
798+       start += size + sizeof(chrp_header);
799+    }
800+    fprintf(stderr,"No common Block found\n");
801+    exit(EXIT_FAILURE);
802+}
803+
804+static char* nvload( int nvfd , int nvsize)
805+{
806+    char* nvbuf = malloc(nvsize);
807+
808+    if (!nvbuf) {
809+       perror("Error allocating buffer");
810+       exit(EXIT_FAILURE);
811+    }
812+    if (read(nvfd, nvbuf, nvsize) != nvsize) {
813+       perror("Error reading /dev/nvram");
814+       exit(EXIT_FAILURE);
815+    }
816+    return nvbuf;
817+}
818+
819+static void
820+print_vars(char* nvbuf, int nvsize)
821+{
822+    int i = 0;
823+
824+    while (i < nvsize)
825+    {
826+       int size = strnlen(nvbuf, nvsize);
827+       if (size == 0)
828+           break;
829+       printf("%s\n",nvbuf);
830+       nvbuf += (size + 1);    // count 0-byte, too
831+    }
832+}
833+
834+/* move memory around to insert the value.
835+ *
836+ * @param nvbufend     byte AFTER the end of the buffer
837+ * @param varsize      length of the variable name
838+ * @param buf          byte where varaible NAME starts
839+ * @param newval       new value to replace old one
840+ * @param foundsize    lenght of varible + '=' + value
841+ * @param equalpos     position relative to buf where '=' was found
842+ */
843+static void
844+insert_val (char* nvbufend, int varsize,   char* buf,
845+           char* newval,   int foundsize, int equalpos)
846+{
847+    int        oldlen  = foundsize - equalpos -1; // account for the '='
848+    int                newlen  = strlen(newval);
849+    char*      valpos  = buf + varsize + 1;
850+    int        delta   = newlen - oldlen;
851+
852+    if (delta > 0) // expand mem
853+       memmove(valpos + newlen,
854+               valpos + oldlen, (nvbufend - valpos - newlen));
855+    else if (delta < 0) // shrink mem
856+    {
857+       memmove(valpos + newlen,
858+               valpos + oldlen, (nvbufend - valpos - oldlen));
859+       memset (nvbufend + delta, 0, -delta );
860+    }
861+    strncpy(valpos, newval, newlen);
862+}
863+
864+/* return position where variable is found,
865+ * newval may be null.
866+ */
867+
868+static char* set_var(char* nvbuf, int nvsize, char* varname, char* newval)
869+{
870+    int i =0;
871+    int varsize = strlen(varname);
872+    int equalpos;
873+    while (i < nvsize)
874+    {
875+       char* buf = &nvbuf[i];
876+       int foundsize = strnlen(buf, nvsize -i);
877+       if (foundsize == 0)
878+           break;
879+       equalpos = (int) (strchr(buf, '=') - buf);
880+       if (equalpos == varsize &&
881+           !strncmp(buf, varname, equalpos))
882+       {
883+           if (newval) // set the value
884+               insert_val(nvbuf + nvsize, varsize, buf,
885+                          newval, foundsize, equalpos);
886+           return buf;
887+       }
888+       i += foundsize + 1;     // count 0-byte, too
889+    }
890+    return NULL;
891+}
892+
893+static void
894+print_var(char* nvbuf, int nvsize, char* varname)
895+{
896+    char* buf = set_var(nvbuf, nvsize, varname, NULL);
897+    if (buf)
898+       printf("%s\n",buf);
899+}
900+
901+/* This fucntion is not used here, it is left
902+   her for the curious */
903+
904+unsigned short chrp_checksum(chrp_header* hdr, char* nvbuf, int nvsize)
905+{
906+    unsigned char*     ptr = (unsigned char*) &hdr->len;
907+    unsigned char*     end = ptr + sizeof(chrp_header);
908+    unsigned short     sum = hdr->signature;
909+       // this in fact skips the checksum
910+    for (; ptr < end; ptr++)
911+       sum += *ptr;
912+    while (sum > 0xFF)
913+       sum = (sum & 0xFF) + (sum>>8);
914+    return sum;
915+}                                                                                                 
916+
917+static void
918+nvstore(int nvfd, chrp_header* chrph, char* nvbuf, int nvstart, int nvsize)
919+{
920+    // mmh, the checksum is calculated for the header only
921+    // since we did not modify the header we can just ignore it.
922+    ssize_t written;
923+    ssize_t seek =  nvstart + sizeof(chrp_header);
924+    written = lseek(nvfd, seek, SEEK_SET);
925+    if (written != seek)
926+    {
927+       fprintf(stderr,"Error seeking /dev/nvram\n");
928+       exit(EXIT_FAILURE);
929+    }
930+    written = write(nvfd, nvbuf, nvsize);
931+    if (written != nvsize)
932+    {
933+       fprintf(stderr,"Error writing /dev/nvram %x %x\n", nvsize, seek);
934+       exit(EXIT_FAILURE);
935+    }
936+}
937+
938+/* print / set the New World NVRAM */
939+
940+void nvNew(int ac, char** av, int nvfd)
941+{
942+    int                nvsize, nvstart;
943+    chrp_header                chrph;
944+    char*              nvbuf;
945+
946+    nvsize = nvscan(nvfd, &chrph, &nvstart);
947+    nvbuf  = nvload(nvfd, nvsize);
948+
949+    switch (ac) {
950+    case 1:
951+       print_vars(nvbuf, nvsize);
952+       break;
953+
954+    case 2:
955+       print_var(nvbuf, nvsize, av[1]);
956+       break;
957+       
958+    case 3:
959+       set_var(nvbuf, nvsize, av[1], av[2]);
960+       nvstore(nvfd, &chrph, nvbuf, nvstart, nvsize);
961+       break;
962+    }
963+}
Note: See TracBrowser for help on using the repository browser.