/* * Boot Variables - a program to display and change Open Firmware * variables under MacOS. * * This file and the accompanying resource file (bootvars.rsrc) are * Copyright (C) 1996 Paul Mackerras. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ /* * 12-28-96 Michael Tesch: * Modified to support a config file & AppleEvent beginnings. * Added an auto-reboot feature. * Added some error reporting stuff. * * 12 January 97 Fred Dushin * Re-wrote gui elements in gui.cp module. * Put some types and defines in bootvars header file * Added #includes for all prototypes. */ #include "bootvars.h" // added fadushin #include #include // for memcpy() and memset() short *item_vars; int nvitems; int file_io; int config_file; short fsRefNum; char reboot; buffer nvbuf; int nv_access_method; asm void eieio() { eieio blr } int nvreadb(unsigned adr) { switch (nv_access_method) { default: *NVADRS = adr >> 5; eieio(); return NVDATA[(adr & 0x1f) << 4]; case 1: return NVDATA_OHARE[(adr & 0x1fff) << 4]; } } void nvwriteb(unsigned adr, int v) { switch (nv_access_method) { default: *NVADRS = adr >> 5; eieio(); NVDATA[(adr & 0x1f) << 4] = v; break; case 1: NVDATA_OHARE[(adr & 0x1fff) << 4] = v; break; } eieio(); } /* If it's a powerbase, we'll read 0 from nvram location 0. But location 0 might have 0 in it anyway, so we write something else and see if it sticks. The read of location 0x1fff is just to make sure that the bus signals get set to something different before we see whether the write to location 0 worked or not. If you don't do that, you can read back what you've written just because of the capacitance of the bus lines - they will tend to hold the last value driven on to them. The write of 0 to location 0 is to restore what was there before. */ void nvinit( void ) { //unsigned char x; int x; //SysBeep( 30 ); nv_access_method = 0; if ( nvreadb(0) != 0 ){ return; } nvwriteb(0, 0xaa); nvreadb(0x1fff); x = nvreadb(0); nvwriteb(0, 0); if (x == 0xaa){ return; } nv_access_method = 1; //SysBeep( 30 ); } int nvcsum() { int i; unsigned c; c = 0; for (i = 0; i < NVSIZE/2; ++i) c += nvbuf.s[i]; c = (c & 0xffff) + (c >> 16); c += (c >> 16); return c & 0xffff; } int nvload() { int i; int s; FILE *f; long len; if( config_file ) { // read from already open macos file... len = NVSIZE; i = FSRead(fsRefNum, &len, nvbuf.c); if( len != NVSIZE ) error_dial( i, "\pread error a" ); len = 1; i = FSRead(fsRefNum, &len, &reboot); if( len != 1 ) error_dial( i, "\pread error b" ); i = FSClose(fsRefNum); if( i ) error_dial( i, "\pclose after read error" ); fsRefNum = config_file = 0; } else if ((f = fopen("nvram", "rb")) != 0) { fread(nvbuf.c, 1, NVSIZE, f); fclose(f); file_io = 1; } else { for (i = 0; i < NVSIZE; ++i) nvbuf.c[i] = nvreadb(i + NVSTART); } s = nvcsum(); return s == 0xffff; } void nvstore() { int i; FILE *f; long len; if( config_file ) { // write to already open macos file... len = NVSIZE; i = FSWrite(fsRefNum, &len, nvbuf.c); if( len != NVSIZE ) error_dial( i, "\pwrite error a" ); len = 1; i = FSWrite(fsRefNum, &len, &reboot); if( len != 1 ) error_dial( i, "\pwrite error b" ); i = FSClose(fsRefNum); if( i ) error_dial( i, "\pclose after write error" ); fsRefNum = config_file = 0; } else if (file_io) { if ((f = fopen("nvram", "wb")) != 0) { fwrite(nvbuf.c, 1, NVSIZE, f); fclose(f); } } else { for (i = 0; i < NVSIZE; ++i) nvwriteb(i + NVSTART, nvbuf.c[i]); } } nvvar nvvars[] = { "little-endian?", boolean, /* 0 */ "real-mode?", boolean, "auto-boot?", boolean, "diag-switch?", boolean, "fcode-debug?", boolean, "oem-banner?", boolean, /* 5 */ "oem-logo?", boolean, "use-nvramrc?", boolean, "real-base", word, "real-size", word, "virt-base", word, /* 10 */ "virt-size", word, "load-base", word, "pci-probe-list", word, "screen-#columns", word, "screen-#rows", word, /* 15 */ "selftest-#megs", word, "boot-device", string, "boot-file", string, "diag-device", string, "diag-file", string, /* 20 */ "input-device", string, "output-device", string, "oem-banner", string, "oem-logo", string, "nvramrc", string, /* 25 */ "boot-command", string, }; #define N_NVVARS (sizeof(nvvars) / sizeof(nvvars[0])) // added fadushin (because above macro won't work for extern declarations) size_t getNumNVVars() { return N_NVVARS; } nvval nvvals[N_NVVARS]; unsigned char nvstrbuf[NVSIZE]; int nvstr_used; // reads the nvbuf data, and copies it into the local buffer (nvvals) void nvunpack() { int i; unsigned long bmask; int vi, off, len; nvstr_used = 0; bmask = 0x80000000; vi = 0; for (i = 0; i < N_NVVARS; ++i) { switch (nvvars[i].type) { case boolean: nvvals[i].word_val = (nvbuf.nv.bits & bmask)? 1: 0; bmask >>= 1; break; case word: nvvals[i].word_val = nvbuf.nv.vals[vi++]; break; case string: off = nvbuf.nv.vals[vi] >> 16; len = nvbuf.nv.vals[vi++] & 0xffff; if (off < NVSTART + sizeof(struct nvram) || off >= NVSTART + NVSIZE || len > NVSTART + NVSIZE - off) { len = 0; off = NVSTART; } nvvals[i].str_val = nvstrbuf + nvstr_used + 1; nvvals[i].word_val = len; nvstrbuf[nvstr_used] = len < 255? len: 255; memcpy(nvvals[i].str_val, nvbuf.c + off - NVSTART, len); nvvals[i].str_val[len] = 0; nvstr_used += len + 2; break; } } } // copies&organizes all the buffered states into the nvbuf structure. void nvpack() { int i, off, len, vi; unsigned long bmask; bmask = 0x80000000; vi = 0; off = NVSIZE; nvbuf.nv.bits = 0; for (i = 0; i < N_NVVARS; ++i) { switch (nvvars[i].type) { case boolean: if (nvvals[i].word_val) nvbuf.nv.bits |= bmask; bmask >>= 1; break; case word: nvbuf.nv.vals[vi++] = nvvals[i].word_val; break; case string: len = nvvals[i].word_val; if (len > off - (NVSTART + sizeof(struct nvram))) len = 0; off -= len; memcpy(nvbuf.c + off, nvvals[i].str_val, len); nvbuf.nv.vals[vi++] = ((off + NVSTART) << 16) + len; break; } } nvbuf.nv.magic = 0x1275; nvbuf.nv.cksum = 0; nvbuf.nv.end_vals = NVSTART + (unsigned) &nvbuf.nv.vals[vi] - (unsigned) &nvbuf; nvbuf.nv.start_strs = off + NVSTART; memset(&nvbuf.c[nvbuf.nv.end_vals - NVSTART], 0, nvbuf.nv.start_strs - nvbuf.nv.end_vals); nvbuf.nv.cksum = ~nvcsum(); }