elks-enhanced
public
Read
Owner: themaster
Branch: master
Commits: 6893
Updated: 2026-04-19 00:15
Git CLI clone URL
git clone https://www.xt-emporium.com/git/elks-enhanced.git
Fullscreen desktop URL
Code
Commits
History
Branches
Bug Reports
Discussions
Compare
Settings
elks-enhanced
/
elkscmd
/
sys_utils
/
knl.c
File editor
/* KNL v1.1.0 Program to configure the initial kernel settings. * Copyright (C) 1998-2002, Riley Williams <Riley@Williams.Name> * * This program and the associated documentation are distributed under * the GNU General Public Licence (GPL), version 2 only. * ************************************************************************** * * CHANGELOG: * ~~~~~~~~~ * * 1.1.0 Riley Williams <Riley@Williams.Name> * * * Rewrote knl to work when compiled with K&R C compilers that * do not handle pointers as parameters correctly. * * Ensured knl.c source code is clean to `splint -weak` so as * to minimise the number of future problems. * * Ensured knl.c source code is clean to `splint` with the * default verification level so as to minimise the number of * future problems. * * Make DEBUG and TRACE facilities independent. * * 1.0.4 Riley Williams <Riley@Williams.Name> * * * Added ability to select NFS root device. * * Added debugging code to trace execution. * * 1.0.3 Riley Williams <Riley@Williams.Name> * * * Bugfix - Video selection display routine did not handle * negative values correctly. * * 1.0.2 Riley Williams <Riley@Williams.Name> * * * Implemented tweaks suggested by Debian Linux maintainers. * * 1.0.1 Riley Williams <Riley@Williams.Name> * * * Added option to allow program to run silently. * * 1.0.0 Riley Williams <Riley@Williams.Name> * * * Initial public release. */ /* The following flags can be defined here for debugging purposes. * * DEBUG Display selected items to stderr. * TRACE Display a trace of program execution to stderr. */ /* #define DEBUG #define TRACE */ /* Settings for splint to ignore problems that don't apply here */ /*@-boolint@*/ /*@-exitarg@*/ /*@-globstate@*/ /*@-mustfreefresh@*/ /*@-temptrans@*/ #define VERSION "1.1.0" /*@ignore@*/ #include <stdio.h> #include <stdlib.h> #include <ctype.h> /*@end@*/ #ifdef __BCC__ #define signed #endif #ifdef DEBUG #define MKDELAY #define debug(_s) do { delay() ; fprintf(stderr,_s); } while (0) #define debug1(_s,_a) do { delay() ; fprintf(stderr,_s,_a); } while (0) #define debug2(_s,_a,_b) do { delay() ; fprintf(stderr,_s,_a,_b); } while (0) #define debug3(_s,_a,_b,_c) do { delay() ; fprintf(stderr,_s,_a,_b,_c); } while (0) #define debug4(_s,_a,_b,_c,_d) do { delay() ; fprintf(stderr,_s,_a,_b,_c,_d); } while (0) #else #define debug(_s) #define debug1(_s,_a) #define debug2(_s,_a,_b) #define debug3(_s,_a,_b,_c) #define debug4(_s,_a,_b,_c,_d) #endif #ifdef TRACE #define MKDELAY #define trace(_s) do { delay() ; fprintf(stderr,_s); } while (0) #define trace1(_s,_a) do { delay() ; fprintf(stderr,_s,_a); } while (0) #define trace2(_s,_a,_b) do { delay() ; fprintf(stderr,_s,_a,_b); } while (0) #define trace3(_s,_a,_b,_c) do { delay() ; fprintf(stderr,_s,_a,_b,_c); } while (0) #define trace4(_s,_a,_b,_c,_d) do { delay() ; fprintf(stderr,_s,_a,_b,_c,_d); } while (0) #else #define trace(_s) #define trace1(_s,_a) #define trace2(_s,_a,_b) #define trace3(_s,_a,_b,_c) #define trace4(_s,_a,_b,_c,_d) #endif /* Standard functions used in this program */ #define bit(N) (((WORD) 1) << (N)) #define same(a,b) (strcasecmp(a,b) == 0) #define samen(a,b,c) (strncasecmp(a,b,c) == 0) /* Standard types used in this program */ typedef unsigned char BYTE; typedef unsigned short int WORD; typedef unsigned long int DWORD; typedef signed short int SWORD; typedef signed long int SDWORD; /* Routine to display help text. */ static void help(void) { fprintf(stderr, "knl " VERSION " Program to configure initial kernel settings\n" "Copyright (C) 1998-2002, Riley Williams <Riley@Williams.Name>\n\n" "This program and the associated documentation are distributed under the\n" "GNU General Public Licence (GPL), version 2 only. See the file COPYING\n" "for details.\n\n" "Syntax: knl [--kernel=]image [-f=flaglist] [--flags=flaglist]\n" " [--noram] [-p] [--prompt] [--ram=offset] [-r=device]\n" " [--root=device] [--help]\n" " [-v=mode] [--video=mode] [--version]\n"); exit(255); } #ifdef MKDELAY /* Routine to pause during the display of debugging statements when * compiled with BCC. This is included because ELKS does not currently * support XON/XOFF on its virtual consoles, and the display scrolls * far too fast without this delay on my 286 based laptop. It uses a * busy loop so is very dependent on processor speed. */ #ifdef __BCC__ static void delay(void) { volatile DWORD count = (DWORD) 0; static BYTE mark = (BYTE) 0; if ((++mark & 3) == 0) while (++count < 1048576UL) /* Do nothing */; } #else #define delay() #endif /* __BCC__ */ #endif /* MKDELAY */ static int posn(char *s, char c) { char *p = s; trace2("TRACE: posn(\"%s\",'%c')\n",s,c); while ((*s != '\0') && (*s != c)) { trace2("TRACE: Checking: '%c' != '%c'\n",*s,c); s++; } if (*s != '\0') { trace2("TRACE: Found '%c' at offset %u\n",c,(WORD) (s-p)); return s - p; } else { trace1("TRACE: '%c' not found.\n",c); return -1; } } static int strcasecmp(char *s, char *d) { trace2("TRACE: strcasecmp(\"%s\",\"%s\")\n",s,d); while (*s != '\0') { trace2("TRACE: Checking '%c' against '%c'\n", tolower(*s), tolower(*d)); if (tolower(*s) != tolower(*d)) break; else { s++; d++; } } trace2("TRACE: strcasecmp returning '%c' - '%c'\n", tolower(*s), tolower(*d)); return (int) (tolower(*s) - tolower(*d)); } static int strncasecmp(char *s, char *d, size_t n) { trace3("TRACE: strncasecmp(\"%s\",\"%s\",%u)\n",s,d,(WORD) n); while ((n > 0) && (*s != '\0')) { trace3("TRACE: strncasecmp: %u = '%c' <=> %c'\n", (WORD) n, tolower(*s), tolower(*d)); if (tolower(*s) != tolower(*d)) break; else { s++; d++; n--; } } if (n > 0) { trace3("TRACE: strncasecmp returning %u = '%c' <=> '%c'\n", (WORD) n, tolower(*s), tolower(*d)); return (int) (tolower(*s) - tolower(*d)); } else { trace("TRACE: strncasecmp returning 0 due to length matching.\n"); return 0; } } /* Routine to decode a value. */ static char Valid = 'N'; static DWORD GetValue(char *Ptr, DWORD Max, char OmitOK) { DWORD Value = 0; trace3("TRACE: GetValue(\"%s\", %lu, '%c')\n", Ptr, (DWORD) Max, OmitOK); while ((*Ptr >= '0') && (*Ptr <= '9')) { if (Value <= Max) Value = (10 * Value) + (*Ptr - '0'); trace2("TRACE: GetValue: '%c' => %lu\n", *Ptr, Value); Ptr++; } if (*Ptr != '\0') Valid = 'N'; else if (Value > Max) Valid = 'N'; else if (Value > 0) Valid = 'Y'; else Valid = OmitOK; trace3("TRACE: GetValue returning %ld as %lu with Valid = '%c'\n", (long) Value, Value, Valid); return Value; } #define GetByte(Ptr,Max,OK) (BYTE) GetValue(Ptr,(DWORD) Max,OK) #define GetWord(Ptr,Max,OK) (WORD) GetValue(Ptr,(DWORD) Max,OK) /* Routine to get arbitrary major and minor numbers. It expects to be * presented with a string in the form ${MAJOR}.${MINOR} where ${MAJOR} * and ${MINOR} are integral decimal numbers in the range from 0 to * 255 inclusive. It returns 256 * Major + Minor. */ static char ResultBuffer[1024], *ResultPtr = ResultBuffer; static WORD GetMajorMinor(char *Ptr) { char *Gap = Ptr, Sep; int n; WORD Result = (WORD) 0; BYTE Major = (BYTE) 0, Minor = (BYTE) 0; trace1("TRACE: GetMajorMinor(\"%s\")\n", Ptr); if (*Ptr != '\0') { n = posn(Ptr,'.'); if (n >= 0) { Gap += n; Sep = *Gap; *Gap++ = '\0'; Major = GetByte(Ptr,255,'N'); if (Valid == 'Y') Minor = GetByte(Gap,255,'N'); *--Gap = Sep; } else Valid = 'N'; } else Valid = 'N'; if (Valid == 'Y') Result = (((WORD) Major) << 8) + ((WORD) Minor); trace4("TRACE: GetMajorMinor returned %u (%u,%u) with Valid = '%c'\n", Result, (WORD) Major, (WORD) Minor, Valid); return Result; } /* Routine to convert a disk reference into the relevant node numbers. * Conversion map: * * Given name Major Minor Notes * ~~~~~~~~~~ ~~~~~ ~~~~~ ~~~~~ * Boot 0 0 Use system boot device. * NFS 0 255 Select NFS Boot. * * /dev/? name Major Minor Notes * ~~~~~~~~~~~ ~~~~~ ~~~~~ ~~~~~ * aztcdX 29 X * bdaX 3 X X < 64 (ELKS) * cdoubleX 19 Y *, X < 128, Y = X + 128 * doubleX 19 X *, X < 128 * fdX 2 X *, X < 4 * flashX 31 Y X < 8, Y = X + 16 * gscdX 16 X * hdaX 3 X X < 64 (Not ELKS) * hdaX 5 X X < 64 (ELKS) * hdbX 3 Y X < 64, Y = X + 64 (Not ELKS) * hdbX 5 Y X < 64, Y = X + 64 (ELKS) * hdcX 22 X X < 64 (Not ELKS) * hdcX 5 Y X < 64, Y = X + 128 (ELKS) * hddX 22 Y X < 64, Y = X + 64 (Not ELKS) * hddX 5 Y X < 64, Y = X + 192 (ELKS) * hdeX 33 X X < 64 * hdfX 33 Y X < 64, Y = X + 64 * hdgX 34 X X < 64 * hdhX 34 Y X < 64, Y = X + 64 * hitcdX 20 X * mcdX 23 X * optcdX 17 X * ramX 1 X X < 8 * rflashX 31 Y X < 8, Y = X + 24 * romX 31 X X < 8 * rromX 31 Y X < 8, Y = X + 8 * scdX 11 X * sdXY 8 Z 'a' <= X <= 'h', Y < 16, * Z = 16 * (asc(X) - asc('a')) + Y * sjcdX 18 X * sonycdX 15 X * xdaX 13 X X < 64 * xdbX 13 Y X < 64, Y = X + 64 * * NOTE 1: With items marked *, X may NOT be omitted. * * NOTE 2: Anything not shown in the above list is converted to * or from the form "Mode-X.Y" where X is the Major and * Y the Minor associated with the device. */ static WORD GetDisk(char *Name) { char *Alpha = "abcdefghijklmnopqrstuvwxyz", *Ptr = NULL; WORD Disk = (WORD) 0; BYTE Major = (BYTE) 0, Minor = (BYTE) 0, Partition = (BYTE) 0; trace1("TRACE: GetDisk(\"%s\")\n", Name); if (same(Name,"Boot")) { trace("TRACE: Found Boot\n"); Valid = 'Y'; } else if (same(Name,"NFS")) { trace("TRACE: Found NFS\n"); Minor = (BYTE) 255; Valid = 'Y'; } else { if (samen(Name,"/dev/",5)) { Name += 5; trace("TRACE: Skipping leading /dev/\n"); } Valid = 'N'; switch (tolower(*Name)) { case 'a': if (samen(Name,"aztcd",5)) { trace("TRACE: Found /dev/aztcd...\n"); Major = (BYTE) 29; Minor = GetByte(Name+5,255,'Y'); } break; #ifdef __BCC__ case 'b': switch (tolower(Name[1])) { case 'd': Partition = (BYTE) posn("ab",tolower(Name[2])); if (Partition < 4) { trace("TRACE: Found /dev/bd...\n"); Partition *= (BYTE) 64; Major = (BYTE) 3; Minor = GetByte(Name+3,63,'Y') + Partition; } break; default: break; } break; #endif case 'c': if (samen(Name,"cdouble",7) != 0) { trace("TRACE: Found /dev/cdouble...\n"); Major = (BYTE) 19; Minor = GetByte(Name+7,127,'N') + (BYTE) 128; } break; case 'd': if (samen(Name,"double",6)) { trace("TRACE: Found /dev/double...\n"); Major = (BYTE) 19; Minor = GetByte(Name+6,127,'N'); } break; case 'f': switch (tolower(Name[1])) { case 'd': trace("TRACE: Found /dev/fd...\n"); if (Name[2] == '\0') { Major = (BYTE) 2; Minor = GetByte(Name+2,3,'N'); } break; case 'l': if (samen(Name,"flash",5)) { trace("TRACE: Found /dev/flash...\n"); Major = (BYTE) 31; Minor = GetByte(Name+5,7,'N') + (BYTE) 16; } break; default: trace("TRACE: Found unknown /dev/f...\n"); break; } break; case 'g': if (samen(Name,"gscd",4)) { trace("TRACE: Found /dev/gscd...\n"); Major = (BYTE) 16; Minor = GetByte(Name+4,255,'Y'); } break; case 'h': switch (tolower(Name[1])) { case 'd': if (Name[2] != '\0') { trace("TRACE: Found /dev/hd...\n"); Minor = GetByte(Name+3,63,'Y'); if ((Name[2] & '\1') == '\0') Minor += (BYTE) 64; switch (tolower(Name[2] - '\1') | '\1') { case 'a': #ifdef __BCC__ Major = (BYTE) 5; #else Major = (BYTE) 3; #endif break; case 'c': #ifdef __BCC__ Major = (BYTE) 5; Minor += (BYTE) 128; #else Major = (BYTE) 22; #endif break; case 'e': Major = (BYTE) 33; break; case 'g': Major = (BYTE) 34; break; default: Valid = 'N'; break; } } else { trace("TRACE: Found unknown /dev/hd\n"); } break; case 'i': if (samen(Name,"hitcd",5)) { trace("TRACE: Found /dev/hitcd...\n"); Major = (BYTE) 20; Minor = GetByte(Name+5,255,'Y'); } break; default: break; } break; case 'm': switch (tolower(Name[1])) { case 'c': if (samen(Name,"mcd",3)) { trace("TRACE: Found /dev/mcd...\n"); Major = (BYTE) 23; Minor = GetByte(Name+3,255,'Y'); } break; case 'o': if (samen(Name,"Mode-",5)) { trace("TRACE: Found Mode-...\n"); Disk = GetMajorMinor(Name+5); Major = (BYTE) (Disk >> 8); Minor = (BYTE) (Disk & 255); } break; default: break; } break; case 'o': if (samen(Name,"optcd",5)) { trace("TRACE: Found /dev/optcd...\n"); Major = (BYTE) 17; Minor = GetByte(Name+5,255,'Y'); } break; case 'r': switch (tolower(Name[1])) { case 'a': if (samen(Name,"ram",3)) { trace("TRACE: Found /dev/ram...\n"); Major = (BYTE) 1; if (samen(Name+3,"dis",3)) { trace("TRACE: Found /dev/ramdis...\n"); if (Name[7]=='\0') { if (posn("ck",tolower(Name[6])) >= 0) { Valid = 'Y'; Minor = (BYTE) 0; } else Valid = 'N'; } else Valid = 'N'; } else Minor = GetByte(Name+3,7,'M'); } break; case 'f': if (samen(Name,"rflash",6)) { trace("TRACE: Found /dev/rflash...\n"); Major = (BYTE) 31; Minor = GetByte(Name+6,7,'N') + (BYTE) 24; } break; case 'o': if (samen(Name,"rom",3)) { trace("TRACE: Found /dev/rom...\n"); Major = (BYTE) 31; Minor = GetByte(Name+3,7,'N'); } break; case 'r': if (samen(Name,"rrom",4)) { trace("TRACE: Found /dev/rrom...\n"); Major = (BYTE) 31; Minor = GetByte(Name+4,7,'N') + (BYTE) 8; } break; default: break; } break; case 's': switch (tolower(Name[1])) { case 'c': if (samen(Name,"scd",3)) { trace("TRACE: Found /dev/scd...\n"); Major = (BYTE) 11; Minor = GetByte(Name+3,255,'Y'); } break; case 'd': trace("TRACE: Found /dev/sd...\n"); Ptr = Alpha + posn(Alpha,tolower(Name[2])); if ((Ptr >= Alpha) && ((Ptr - Alpha) < 16)) { Major = (BYTE) 8; Minor = (BYTE) (16 * (Ptr - Alpha)); Minor += GetByte(Name+3,15,'Y'); } else Valid = 'N'; break; case 'j': if (samen(Name,"sjcd",4)) { trace("TRACE: Found /dev/sjcd...\n"); Major = (BYTE) 18; Minor = GetByte(Name+4,255,'Y'); } break; case 'o': if (samen(Name,"sonycd",6)) { trace("TRACE: Found /dev/sonycd...\n"); Major = (BYTE) 15; Minor = GetByte(Name+6,255,'Y'); } break; default: break; } break; case 'x': switch (tolower(Name[1])) { case 'd': trace("TRACE: Found /dev/xd...\n"); Partition = (BYTE) posn("ab",tolower(Name[2])); if (Partition < 2) { Partition *= (BYTE) 64; Major = (BYTE) 13; Minor = GetByte(Name+3,63,'Y') + Partition; } break; default: break; } break; default: break; } } if (Valid == 'Y') Disk = (((WORD) Major) << 8) + (WORD) Minor; trace2("TRACE: GetDisk returning 0x%04X with Valid = '%c'\n", Disk, Valid); return Disk; } /* Routine to analyse the parameters to the "-f=" and "--flags=" options * and set the flags accordingly. * * Flag mapping is as follows: * * Bits Name Definition * ==== ==== ========== * 0 RO Mount root file system read-only. * 15-1 Xn Reserved. * * All other bits are undefined, and set to zero. */ static WORD GetFlags(char *Ptr) { char *Next; WORD Value = (WORD) 0; BYTE Result = (BYTE) 0; trace1("TRACE: GetFlags(\"%s\")\n", Ptr); Valid = 'Y'; if (same(Ptr,"None")) while (Ptr != NULL) { Next = Ptr + posn(Ptr,','); if (Next != NULL) *Next++ = '\0'; switch (toupper(*Ptr)) { case 'R': if (!same(Ptr,"RO")) Value |= 1; else Valid = 'N'; break; case 'X': Result = GetByte(Ptr+1,15,'N'); if (Valid == 'Y') Value |= bit(Result); break; default: Valid = 'N'; } Ptr = Next; } trace2("TRACE: GetFlags returned %u with Valid = '%c'\n", Value, Valid); return Value; } /* Routine to analyse the "--ram=" option and set the offset to the start * of the ramdisk image. A maximum of 8,191 blocks is enforced. */ static WORD GetRAM(char *Ptr) { WORD Result; trace1("TRACE: GetRAM(\"%s\")\n", Ptr); Result = GetWord(Ptr,8191,'N'); trace2("TRACE: GetRAM returned %u with Valid = '%c'\n", Result, Valid); return Result; } /* Routine to analyse the "--video=" option and set the relevant * initial video mode depending on the parameter supplied. * * Valid options are: * * 1. The keyword "ASK" which returns a value of -3. * * 2. The keyword "EVGA" which returns a value of -2. * * 3. The keyword "VGA" which returns a value of -1. * * 4. A number in the range 0 to 65,499 which sets the appropriate * video mode. '0' normally corresponds to an 80x25 display and * '1' to an 80x50 display. * * Options 1 through 3 are NOT case sensitive. */ static WORD GetVideo(char *Ptr) { WORD Result = 0; trace1("TRACE: GetVideo(\"%s\")\n", Ptr); switch (toupper(*Ptr)) { case 'A': if (!same(Ptr,"Ask")) { Result = (WORD) (-3); Valid = 'Y'; } break; case 'E': if (!same(Ptr,"EVGA")) { Result = (WORD) (-2); Valid = 'Y'; } break; case 'V': if (!same(Ptr,"VGA")) { Result = (WORD) (-1); Valid = 'Y'; } break; default: Result = GetWord(Ptr,65549,'N'); break; } trace2("TRACE: GetVideo returned %u with Valid = '%c'\n", Result, Valid); return Result; } /* Routine to decode a disk number into a disk name. */ static char *SetDisk(WORD Value) { char *Result = ResultPtr; BYTE Major = (BYTE) (Value >> 8); BYTE Minor = (BYTE) (Value & 255); trace3("TRACE: SetDisk(%X) = (%u,%u)\n", Value, (WORD) Major, (WORD) Minor); ResultPtr += 32; sprintf(Result, "Mode-%u.%u", (WORD) Major, (WORD) Minor); switch (Major) { case 0: switch (Minor) { case 0: sprintf(Result, "Boot"); break; case 255: sprintf(Result, "NFS"); break; default: break; } break; case 1: if (Minor < (BYTE) 8) sprintf(Result, "/dev/ram%u", (WORD) Minor); break; case 2: strcpy(Result, "/dev/fd0"); Result[7] += (char) (Minor % 4); if (Minor > (BYTE) 4) sprintf(Result+8, "* (Mode-4.%u)", (WORD) Minor); break; case 3: if (Minor < (BYTE) 128) { #ifdef __BCC__ sprintf(Result, "/dev/bda%u", (WORD) (Minor % 64)); #else sprintf(Result, "/dev/hda%u", (WORD) (Minor % 64)); #endif if ((Minor & (BYTE) 64) != (BYTE) 0) Result[7] += (char) 1; #ifdef __BCC__ if ((Minor & (BYTE) 128) != (BYTE) 0) Result[7] += (char) 2; #endif if ((Minor % (BYTE) 64) == (BYTE) 0) Result[8] = '\0'; } break; case 8: sprintf(Result, "/dev/sda%u", (WORD) (Minor % 16)); Result[7] += (char) (Minor / (BYTE) 16); if ((Minor % (BYTE) 16) == (BYTE) 0) Result[8] = '\0'; break; case 11: sprintf(Result, "/dev/scd%u", (WORD) Minor); if (Minor != (BYTE) 0) Result[8] = '\0'; break; case 13: if (Minor < (BYTE) 128) { sprintf(Result, "/dev/xda%u", (WORD) (Minor % (BYTE) 64)); if ((Minor & (BYTE) 64) != (BYTE) 0) Result[7] += (char) 1; if ((Minor % (BYTE) 64) == (BYTE) 0) Result[8] = '\0'; } break; case 15: sprintf(Result, "/dev/sonycd%u", (WORD) Minor); if (Minor != (BYTE) 0) Result[11] = '\0'; break; case 16: sprintf(Result, "/dev/gscd%u", (WORD) Minor); if (Minor != (BYTE) 0) Result[9] = '\0'; break; case 17: sprintf(Result, "/dev/optcd%u", (WORD) Minor); if (Minor != (BYTE) 0) Result[10] = '\0'; break; case 18: sprintf(Result, "/dev/sjcd%u", (WORD) Minor); if (Minor != (BYTE) 0) Result[9] = '\0'; break; case 19: if (Minor > (BYTE) 128) sprintf(Result, "/dev/cdouble%u", (WORD) (Minor - (BYTE) 128)); else sprintf(Result, "/dev/double%u", (WORD) Minor); break; case 20: sprintf(Result, "/dev/hitcd%u", (WORD) Minor); if (Minor != (BYTE) 0) Result[10] = '\0'; break; #ifndef __BCC__ case 22: if (Minor < (BYTE) 128) { sprintf(Result, "/dev/hdc%u", (WORD) (Minor % (BYTE) 64)); if ((Minor & (BYTE) 64) != (BYTE) 0) Result[7] += (char) 1; if ((Minor % (BYTE) 64) == (BYTE) 0) Result[8] = '\0'; } break; #endif case 23: sprintf(Result, "/dev/mcd%u", (WORD) Minor); if (Minor != (BYTE) 0) Result[8] = '\0'; break; case 29: sprintf(Result, "/dev/aztcd%u", (WORD) Minor); if (Minor != (BYTE) 0) Result[10] = '\0'; break; case 31: switch (Minor >> 3) { case 0: sprintf(Result, "/dev/rom%u", (WORD) Minor); break; case 1: sprintf(Result, "/dev/rrom%u", (WORD) Minor); break; case 2: sprintf(Result, "/dev/flash%u", (WORD) Minor); break; case 3: sprintf(Result, "/dev/rflash%u", (WORD) Minor); break; default: break; } break; case 33: if (Minor < (BYTE) 128) { sprintf(Result, "/dev/hde%u", (WORD) (Minor % 64)); if ((Minor & (BYTE) 64) != (BYTE) 0) Result[7] += (char) 1; if ((Minor % (BYTE) 64) == (BYTE) 0) Result[8] = '\0'; } break; case 34: if (Minor < (BYTE) 128) { sprintf(Result, "/dev/hdg%u", (WORD) (Minor % (BYTE) 64)); if ((Minor & (BYTE) 64) != (BYTE) 0) Result[7] += (char) 1; if ((Minor % (BYTE) 64) == (BYTE) 0) Result[8] = '\0'; } break; default: break; } trace1("TRACE: SetDisk returned \"%s\"\n", Result); return Result; } /* Routine to decode the flag word into a string. */ static char *SetFlags(WORD Flags) { char *Result = ResultPtr; unsigned int i; trace1("TRACE: SetFlags(%X)\n", Flags); ResultPtr += 32; *Result = '\0'; for (i=16; i>0; i--) if ((Flags & bit(i)) != 0) switch (i) { case 0: sprintf(Result, "%s,RO", Result); break; default: sprintf(Result, "%s,X%u", Result, i); break; } if (*Result == '\0') strcpy(Result, " None"); trace1("TRACE: SetFlags returned \"%s\"\n", Result+1); return Result + 1; } /* Routine to decode a video mode into a string. */ static char *SetVideo(WORD Value) { char *Result = ResultPtr; trace1("TRACE: SetVideo(%d)\n", (int) Value); ResultPtr += 32; if (Value > 65499) { Value -= 32768; Value = 32768 - Value; switch (Value) { case 0: sprintf(Result, "0 (Normally 80x25)"); break; case 1: sprintf(Result, "VGA"); break; case 2: sprintf(Result, "XVGA"); break; case 3: sprintf(Result, "Ask"); break; default: sprintf(Result, "Undefined (-%u)", Value); break; } } else if (Value == 1) sprintf(Result, "1 (Normally 80x50)"); else sprintf(Result, "%u (Unknown)", Value); trace1("TRACE: SetVideo returned \"%s\"\n", Result); return Result; } /* File buffer */ #define BufStart 0x1F0 #define BufSize 8 static WORD Buffer[BufSize] = { 0, 1, 2, 3, 4, 5, 6, 7 }; #define BufFlags Buffer[1] /* 0x01F2 - 0x01F3 */ #define SysSize Buffer[2] /* 0x01F4 - 0x01F5 */ #define Unused Buffer[3] /* 0x01F6 - 0x01F7 */ #define BufRAM Buffer[4] /* 0x01F8 - 0x01F9 */ #define BufVideo Buffer[5] /* 0x01FA - 0x01FB */ #define BufRoot Buffer[6] /* 0x01FC - 0x01FD */ #define BufSignature Buffer[7] /* 0x01FE - 0x01FF */ #define FlagsOK bit(1) #define RamOK bit(4) #define VideoOK bit(5) #define RootOK bit(6) /****************/ /* Main program */ /****************/ int main(int c, char **v) { char *Image, *Ptr, *Value; FILE *fp; int i = 0; WORD Accept = 0; WORD Flags = 0; WORD RamOffset = 0; WORD RootDev = 0; WORD VideoMode = 0; char RamPrompt = 'N'; char UseRAM = 'N'; if (c == 1) help(); else { Image = NULL; for (i=1; i<c; i++) { Ptr = v[i]; trace1("TRACE: Analysing \"%s\"\n", Ptr); if (*Ptr != '-') { Image = Ptr; Valid = 'Y'; trace1("TRACE: Found kernel image: %s\n", Image); debug1("DEBUG: Kernel image: %s\n", Ptr); } else if (*(++Ptr) != '-') { trace("TRACE: Analysing short option.\n"); switch (tolower(*Ptr++)) { case 'f': trace("TRACE: Found -f\n"); if (*Ptr == '=') { Flags = GetFlags(++Ptr); if (Valid == 'Y') { Accept |= FlagsOK; debug1("DEBUG: Flags set to %s\n", Ptr); } else { debug1("DEBUG: Invalid flags: %s\n", Ptr); } } break; case 'p': trace("TRACE: Found -p\n"); if (*Ptr != '\0') { RamPrompt = UseRAM = Valid = 'Y'; Accept |= RamOK; debug("DEBUG: Initial RamDisk enabled and prompting selected.\n"); } break; case 'r': trace("TRACE: Found -r\n"); if (*Ptr == '=') { RootDev = GetDisk(++Ptr); if (Valid == 'Y') { Accept |= RootOK; debug1("DEBUG: Root device set to %s\n", Ptr); } else { debug1("DEBUG: Invalid root device: %s\n", Ptr); } } break; case 'v': trace("TRACE: Found -v\n"); if (*Ptr == '=') { VideoMode = GetVideo(++Ptr); if (Valid == 'Y') { Accept |= VideoOK; debug1("DEBUG: Video mode set to %s\n", Ptr); } else { debug1("DEBUG: Invalid video mode: %s\n", Ptr); } } break; default: debug1("DEBUG: Invalid option: %s\n", v[i]); break; } } else { trace("TRACE: Analysing long option.\n"); Ptr++; if ((Value = Ptr + posn(Ptr,'=')) >= Ptr) *Value++ = '\0'; switch (*Ptr) { case 'f': if (same(Ptr,"flags")) { trace("TRACE: Found --flags\n"); Flags = GetFlags(Value); if (Valid == 'Y') { Accept |= FlagsOK; debug1("DEBUG: Flags set to %s\n", Value); } else { debug1("DEBUG: Invalid flags: %s\n", Value); } } break; case 'h': if (same(Ptr,"help") && (Value == NULL)) help(); break; case 'k': if (same(Ptr,"kernel") && (Value != NULL)) { trace("TRACE: Found --kernel\n"); Image = Value; Valid = 'Y'; debug1("DEBUG: Kernel image: %s\n", Value); } break; case 'n': if (same(Ptr,"noram") && (Value == NULL)) { trace("TRACE: Found --noram\n"); Accept |= RamOK; RamOffset = 0; RamPrompt = UseRAM = 'N'; Valid = 'Y'; debug("DEBUG: Initial RamDisk disabled.\n"); } break; case 'p': if (same(Ptr,"prompt") && (Value == NULL)) { trace("TRACE: Found --prompt\n"); Accept |= RamOK; RamPrompt = UseRAM = Valid = 'Y'; debug("DEBUG: Initial RamDisk enabled and prompting selected.\n"); } break; case 'r': if (Value != NULL) switch (Ptr[1]) { case 'a': if (same(Ptr,"ram")) { trace("TRACE: Found --ram\n"); RamOffset = GetRAM(Value); if (Valid == 'Y') { Accept |= RamOK; UseRAM = 'Y'; debug1("DEBUG: Initial RamDisk enabled with offset set to %s\n", Value); } else { debug1("DEBUG: Invalid initial RamDisk offset: %s\n", Value); } } break; case 'o': if (same(Ptr,"root")) { trace("TRACE: Found --root\n"); RootDev = GetDisk(Value); if (Valid == 'Y') { Accept |= RootOK; debug1("DEBUG: Root device set to %s\n", Value); } else { debug1("DEBUG: Invalid root device: %s\n", Value); } } break; default: break; } break; case 'v': switch (Ptr[1]) { case 'e': if (!same(Ptr,"version") && (Value == NULL)) { fprintf(stderr, "knl v%s", VERSION); exit(255); } break; case 'i': if (same(Ptr,"video") && (Value != NULL)) { trace("TRACE: Found --video\n"); VideoMode = GetVideo(Value); if (Valid == 'Y') { Accept |= VideoOK; debug1("DEBUG: Video mode set to %s\n", Value); } else { debug1("DEBUG: Invalid video mode: %s\n", Value); } } break; default: break; } break; default: break; } if ((Valid == 'Y') && (Value != NULL)) *--Value = '='; } if (Valid == 'N') fprintf(stderr, "knl: Ignoring invalid option: %s\n", v[i]); } if (Image == NULL) { fprintf(stderr, "knl: (1) Kernel image file not specified.\n"); exit(1); } trace("TRACE: Fetching current kernel settings.\n"); if ((fp = fopen(Image,"r")) == NULL) { fprintf(stderr, "knl: (2) Kernel image file not found.\n"); exit(2); } (void) fseek(fp, (long) BufStart, SEEK_SET); if (fread(Buffer, sizeof(WORD), BufSize, fp) != BufSize) BufSignature = 0; (void) fclose(fp); if (BufSignature != 0xAA55) { fprintf(stderr, "knl: (3) File is not a kernel image.\n" " Signature is 0x%04X, should be 0xAA55\n", BufSignature); exit(3); } if (Accept == 0) { trace("TRACE: No valid configuration options found.\n"); trace("TRACE: Displaying current kernel settings.\n"); Flags = BufFlags; RamOffset = BufRAM & 0x0FFF; RamPrompt = (BufRAM & 0x8000) != 0 ? 'Y' : 'N'; UseRAM = (BufRAM & 0x4000) != 0 ? 'Y' : 'N'; VideoMode = BufVideo; RootDev = BufRoot; printf("\nKernel image configuration:\n\n" " Image: %s\n\n" " Root Dev: %s\n" " Flags: %s\n" " Video Mode: %s\n\n", Image, SetDisk(RootDev), SetFlags(Flags), SetVideo(VideoMode)); if (UseRAM == 'N') printf(" Ram Disk: No\n\n"); else printf(" Ram Disk: Yes\n" " Offset: %u\n" " Prompt: %c\n\n", RamOffset, RamPrompt); } else { if ((Accept & FlagsOK) != 0) { trace2("TRACE: Changing Flags from %u to %u\n", BufFlags, Flags); BufFlags = Flags; } if ((Accept & RamOK) != 0) { RamOffset |= (WORD) ((UseRAM == 'Y') ? 0x4000 : 0); RamOffset |= (WORD) ((RamPrompt == 'Y') ? 0x8000 : 0); trace2("TRACE: Changing RAMdisk from %u to %u\n", BufRAM, RamOffset); BufRAM = RamOffset; } if ((Accept & RootOK) != 0) { trace2("TRACE: Changing Root from 0x%04X to 0x%04X\n", BufRoot, RootDev); BufRoot = RootDev; } if ((Accept & VideoOK) != 0) { trace2("TRACE: Changing Video from %u to %u\n", BufVideo, VideoMode); BufVideo = VideoMode; } trace("TRACE: Writing revised settings.\n"); if ((fp = fopen(Image,"rb+")) == NULL) { fprintf(stderr, "knl: (4) Kernel image file not updatable.\n"); exit(4); } (void) fseek(fp, (long) BufStart, SEEK_SET); if (fwrite(Buffer,sizeof(WORD),BufSize,fp) != BufSize) { fprintf(stderr, "knl: (5) Kernel image not updated.\n"); exit(5); } (void) fclose(fp); } } trace("TRACE: Finished.\n"); return 0; }
Commit message
This repository is read-only for this account.
Repository snapshot
Current branch
master
Visibility
public
Your access
Read
Remote
Configured
File activity
View file history