source: patches/powerpc-utils_1.1.3-fixes-1.patch@ 51f6764

clfs-1.2 clfs-2.1 clfs-3.0.0-systemd clfs-3.0.0-sysvinit systemd sysvinit
Last change on this file since 51f6764 was 69cde8d, checked in by Jim Gifford <clfs@…>, 19 years ago

Added: All patches needed for the book.

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