From c1d05e93be1238091f56ecfd8cd0d44439148495 Mon Sep 17 00:00:00 2001 From: Greg Haerr Date: Tue, 12 Nov 2024 19:59:16 -0800 Subject: [PATCH 1/7] Allocate space for and read two sectors for /bootopts --- elks/arch/i86/boot/setup.S | 24 +++++++++++++----------- elks/include/linuxmt/config.h | 29 ++++++++++++++++------------- elks/init/main.c | 4 ++-- elkscmd/rootfs_template/bootopts | 4 ++-- 4 files changed, 33 insertions(+), 28 deletions(-) diff --git a/elks/arch/i86/boot/setup.S b/elks/arch/i86/boot/setup.S index dbcde606b..3a9350041 100644 --- a/elks/arch/i86/boot/setup.S +++ b/elks/arch/i86/boot/setup.S @@ -946,7 +946,10 @@ putc: push %ax #ifdef CONFIG_BOOTOPTS // -// load /bootopts for FAT filesystem boot +// load /bootopts file for FAT filesystem boot +// If size > 512 bytes, both sectors must be contiguous. +// This is currently guaranteed by using a 1K /bootopts in +// distribution images, as later edits will remain contiguous. // // Uses previous boot sector's BPB contents for disk geometry // and previous boot sector's buffer which still holds root directory sector. @@ -990,20 +993,19 @@ bootopts: xor %bp,%bp mov root_dev,%al // Physical Device Address - mov $0xD6,%ah // Read Data - mov $512,%bx - test $0x10,%al // Check Floppy Disk or Hard Disk + mov $0xD6,%ah // Read Data + mov $1024,%bx // 1K bytes + test $0x10,%al // Check Floppy Disk or Hard Disk jz pc98_int1b #ifdef CONFIG_IMG_FD1232 - mov $1024,%bx - mov $0x03,%ch // 1024 Bytes per sector - inc %dl // sector number for PC_98 Floppy Disk + mov $0x03,%ch // 1024 Bytes per sector + inc %dl // sector number for PC_98 Floppy Disk #else - mov $0x02,%ch // 512 Bytes per sector - inc %dl // sector number for PC_98 Floppy Disk + mov $0x02,%ch // 512 Bytes per sector + inc %dl // sector number for PC_98 Floppy Disk #endif pc98_int1b: - int $0x1B // BIOS disk interrupt + int $0x1B // BIOS disk interrupt pop %bp #else mov $INITSEG,%ax @@ -1013,7 +1015,7 @@ pc98_int1b: mov $DEF_OPTSEG,%ax // ES:BX = DEF_OPTSEG:0 mov %ax,%es xor %bx,%bx - mov $0x0201,%ax // BIOS read disk, 1 sector + mov $0x0202,%ax // BIOS read disk, 2 sectors int $0x13 // BIOS disk interrupt #endif diff --git a/elks/include/linuxmt/config.h b/elks/include/linuxmt/config.h index 16a28b342..2454da521 100644 --- a/elks/include/linuxmt/config.h +++ b/elks/include/linuxmt/config.h @@ -137,30 +137,33 @@ #define DMASEGEND DMASEG /* no DMASEG buffer */ #endif +/* Define segment locations of low memory, must not overlap */ + #ifdef CONFIG_ROMCODE #define DMASEG 0x80 /* start of floppy sector buffer */ #define KERNEL_DATA DMASEGEND /* kernel data segment */ #define SETUP_DATA CONFIG_ROM_SETUP_DATA -#endif -#if (defined(CONFIG_ARCH_IBMPC) || defined(CONFIG_ARCH_8018X)) && !defined(CONFIG_ROMCODE) -/* Define segment locations of low memory, must not overlap */ -#define OPTSEGSZ 0x200 /* max size of /bootopts file (512 bytes max) */ -#define DEF_OPTSEG 0x50 /* 0x200 bytes boot options at lowest usable ram */ -#define REL_INITSEG 0x70 /* 0x200 bytes setup data */ -#define DMASEG 0x90 /* start of floppy sector buffer */ +#else /* !CONFIG_ROMCODE */ + +#ifdef CONFIG_ARCH_IBMPC +#define OPTSEGSZ 0x400 /* max size of /bootopts file (1024 bytes max) */ +#define DEF_OPTSEG 0x50 /* 0x400 bytes boot options at lowest usable ram */ +#define REL_INITSEG 0x90 /* 0x200 bytes setup data */ +#define DMASEG 0xB0 /* start of floppy sector buffer */ #define REL_SYSSEG DMASEGEND /* kernel code segment */ #define SETUP_DATA REL_INITSEG #endif -#if defined(CONFIG_ARCH_PC98) && !defined(CONFIG_ROMCODE) -/* Define segment locations of low memory, must not overlap */ -#define OPTSEGSZ 0x200 /* max size of /bootopts file (512 bytes max) */ -#define DEF_OPTSEG 0x60 /* 0x200 bytes boot options at lowest usable ram */ -#define REL_INITSEG 0x80 /* 0x200 bytes setup data */ -#define DMASEG 0xA0 /* start of floppy sector buffer */ +#ifdef CONFIG_ARCH_PC98 +#define OPTSEGSZ 0x400 /* max size of /bootopts file (1024 bytes max) */ +#define DEF_OPTSEG 0x60 /* 0x400 bytes boot options at lowest usable ram */ +#define REL_INITSEG 0xA0 /* 0x200 bytes setup data */ +#define DMASEG 0xC0 /* start of floppy sector buffer */ #define REL_SYSSEG DMASEGEND /* kernel code segment */ #define SETUP_DATA REL_INITSEG #endif +#endif /* !CONFIG_ROMCODE */ + #endif diff --git a/elks/init/main.c b/elks/init/main.c index 612035bfe..4c11eefad 100644 --- a/elks/init/main.c +++ b/elks/init/main.c @@ -440,8 +440,8 @@ static int INITPROC parse_options(void) fmemcpyb(options, kernel_ds, 0, DEF_OPTSEG, sizeof(options)); #pragma GCC diagnostic ignored "-Wstrict-aliasing" - /* check file starts with ## and max len 511 bytes*/ - if (*(unsigned short *)options != 0x2323 || options[OPTSEGSZ-1]) + /* check file starts with ##, one or two sectors, max 1023 bytes */ + if (*(unsigned short *)options != 0x2323 || (options[511] && options[OPTSEGSZ-1])) return 0; next = line; diff --git a/elkscmd/rootfs_template/bootopts b/elkscmd/rootfs_template/bootopts index 3114650fe..f4796ff34 100644 --- a/elkscmd/rootfs_template/bootopts +++ b/elkscmd/rootfs_template/bootopts @@ -1,4 +1,4 @@ -## max 511 bytes +## ELKS /bootopts boot options file, max 1023 bytes #TZ=MDT6 #LOCALIP=10.0.2.16 #HOSTNAME=elks16 @@ -11,7 +11,7 @@ #task=16 buf=64 cache=8 file=64 inode=96 heap=44000 # std #task=6 buf=8 cache=4 file=20 inode=24 heap=15000 n # min w/no rc.sys #sync=30 -#init=/bin/init 3 n # muser serial no rc.sys +#init=/bin/init 3 n # multiuser serial no rc.sys #init=/bin/sash #root=df0 #root=hda1 ro From 8fb102dba3a2f705b9a71a949a5d94f3a14fe029 Mon Sep 17 00:00:00 2001 From: Greg Haerr Date: Tue, 12 Nov 2024 21:15:49 -0800 Subject: [PATCH 2/7] Free up six bytes in MINIX boot sector Also for speed read only one sector for superblock --- bootblocks/boot_minix.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/bootblocks/boot_minix.c b/bootblocks/boot_minix.c index a47941a09..210950e1e 100644 --- a/bootblocks/boot_minix.c +++ b/bootblocks/boot_minix.c @@ -22,6 +22,7 @@ static byte_t sb_block [BLOCK_SIZE]; // super block block buffer #define sb_data ((struct super_block *)sb_block) +static char linux[] = "/linux"; static int i_now; static int i_boot; static int loadaddr; @@ -82,10 +83,10 @@ void load_prog () load_file (); for (int d = 0; d < BLOCK_SIZE /*(int)i_data->i_size*/; d += DIRENT_SIZE) { - if (!strcmp ((char *)(d_dir + 2 + d), "linux")) { + if (!strcmp ((char *)(d_dir + 2 + d), linux+1)) { i_boot = i_now = (*(int *)(d_dir + d)) - 1; if (i_boot == -1) continue; - puts ("/linux"); + puts (linux); loadaddr = LOADSEG << 4; load_file(); continue; @@ -121,7 +122,7 @@ static int strcmp (const char * s, const char * d) static void load_super () { - disk_read (2, 2, sb_block, seg_data ()); + disk_read (2, 1, sb_block, seg_data ()); /* if (sb_data->s_log_zone_size) { From 422da1b19ba3c0a4560d1e1699b35c7e9d98d8ec Mon Sep 17 00:00:00 2001 From: Greg Haerr Date: Tue, 12 Nov 2024 22:12:56 -0800 Subject: [PATCH 3/7] Release /bootopts buffers from kernel data segment and low memory Also release setup data segment (REL_INITSEG) to main memory --- elks/arch/i86/boot/setup.S | 10 ++++------ elks/arch/i86/drivers/block/directfd.c | 4 ++-- elks/arch/i86/kernel/system.c | 3 ++- elks/include/linuxmt/config.h | 14 ++++++++------ elks/include/linuxmt/kernel.h | 1 + elks/init/main.c | 11 ++++++++++- 6 files changed, 27 insertions(+), 16 deletions(-) diff --git a/elks/arch/i86/boot/setup.S b/elks/arch/i86/boot/setup.S index 3a9350041..b80f4029d 100644 --- a/elks/arch/i86/boot/setup.S +++ b/elks/arch/i86/boot/setup.S @@ -7,10 +7,9 @@ ! both setup.s and system has been loaded by the bootblock. ! ! This code asks the bios for memory/disk/other parameters, and -! puts them in a "safe" place: INITSEG:0-INITSEG:01FF, ie where the -! boot-block used to be. It is then up to the protected mode -! system to read them from there before the area is overwritten -! for buffer-blocks. +! puts them in a "safe" place: REL_INITSEG:0-REL_INITSEG:01FF, ie where +! the boot-block used to be. It is then up to the kernel to read them +! from there before the area is released to the main memory allocator. ! ! Move PS/2 aux init code to psaux.c ! (troyer@saifr00.cfsat.Honeywell.COM) 03Oct92 @@ -36,7 +35,7 @@ ! ! index ! ... -! 4: display page +! 4: display page, 1 byte UNUSED ! 6: video mode, 1 byte ! 7: screen_cols, 1 byte ! 8: video data, 2 bytes @@ -899,7 +898,6 @@ novga: mov %al,14 // CGA 25 rows mov $0x0f,%ah int $0x10 - mov %bx,4 // bh = display page mov %ax,6 // al = video mode, ah = window width call getcpu // implemented in cputype.S diff --git a/elks/arch/i86/drivers/block/directfd.c b/elks/arch/i86/drivers/block/directfd.c index 5d860b9e5..394ae8335 100644 --- a/elks/arch/i86/drivers/block/directfd.c +++ b/elks/arch/i86/drivers/block/directfd.c @@ -1204,7 +1204,7 @@ static void DFPROC redo_fd_request(void) numsectors = req->rq_nr_sectors; #ifdef CONFIG_TRACK_CACHE use_cache = (command == FD_READ) && (req->rq_errors < 4) - && (SETUP_CPU_TYPE != 7 || running_qemu); /* disable cache on 32-bit systems */ + && (arch_cpu != 7 || running_qemu); /* disable cache on 32-bit systems */ if (use_cache) { /* full track caching only if cache large enough */ if (CACHE_FULL_TRACK && floppy->sect < CACHE_SIZE) @@ -1453,7 +1453,7 @@ static int DFPROC get_fdc_version(void) } switch (reply_buffer[0]) { case 0x80: - if (SETUP_CPU_TYPE > 5) { /* 80286 CPU PC/AT or better */ + if (arch_cpu > 5) { /* 80286 CPU PC/AT or better */ type = FDC_TYPE_8272PC_AT; name = "8272A (PC/AT)"; } else { diff --git a/elks/arch/i86/kernel/system.c b/elks/arch/i86/kernel/system.c index 7278b683b..d5bc30807 100644 --- a/elks/arch/i86/kernel/system.c +++ b/elks/arch/i86/kernel/system.c @@ -15,6 +15,7 @@ seg_t membase, memend; /* start and end segment of available main memory */ unsigned int heapsize; /* max size of kernel near heap */ byte_t sys_caps; /* system capabilities bits */ +unsigned char arch_cpu; /* CPU type from cputype.S */ unsigned int INITPROC setup_arch(void) { @@ -65,10 +66,10 @@ unsigned int INITPROC setup_arch(void) } #endif + arch_cpu = SETUP_CPU_TYPE; #ifdef SYS_CAPS sys_caps = SYS_CAPS; /* custom system capabilities */ #else - byte_t arch_cpu = SETUP_CPU_TYPE; if (arch_cpu > 5) /* 80286+ IBM PC/AT capabilities or Unknown CPU */ sys_caps = CAP_ALL; debug("arch %d sys_caps %02x\n", arch_cpu, sys_caps); diff --git a/elks/include/linuxmt/config.h b/elks/include/linuxmt/config.h index 2454da521..30b601a6c 100644 --- a/elks/include/linuxmt/config.h +++ b/elks/include/linuxmt/config.h @@ -13,14 +13,16 @@ #define CONFIG_MSDOS_PARTITION 1 /* support DOS HD partitions */ #define CONFIG_FS_DEV 1 /* support FAT /dev folder */ -#ifdef CONFIG_ARCH_IBMPC -#define MAX_SERIAL 4 /* max number of serial tty devices*/ - /* - * Setup data - normally queried by startup setup.S code, but can - * be overridden for embedded systems with less overhead. - * See setup.S for more details. + * SETUP_ defines are initialzied by setup.S and queried only during kernel init. + * The REL_INITSEG segment is released at end of kernel init. For later use the + * value must be copied, as afterwards setupb/setupw will return incorrect data. + * These defines are overridden for ROM based systems w/o setup code. + * See setup.S for setupb/setupw offsets. */ + +#ifdef CONFIG_ARCH_IBMPC +#define MAX_SERIAL 4 /* max number of serial tty devices*/ #define SETUP_VID_COLS setupb(7) /* BIOS video # columns */ #define SETUP_VID_LINES setupb(14) /* BIOS video # lines */ #define SETUP_CPU_TYPE setupb(0x20) /* processor type */ diff --git a/elks/include/linuxmt/kernel.h b/elks/include/linuxmt/kernel.h index 61dbd368f..a307895cf 100644 --- a/elks/include/linuxmt/kernel.h +++ b/elks/include/linuxmt/kernel.h @@ -18,6 +18,7 @@ #define structof(p,t,m) ((t *) ((char *) (p) - offsetof (t,m))) extern char running_qemu; +extern unsigned char arch_cpu; extern dev_t dev_console; extern int debug_level; diff --git a/elks/init/main.c b/elks/init/main.c index 4c11eefad..bc2ea9b8c 100644 --- a/elks/init/main.c +++ b/elks/init/main.c @@ -211,7 +211,7 @@ static void INITPROC kernel_init(void) static void INITPROC kernel_banner(seg_t init, seg_t extra) { #ifdef CONFIG_ARCH_IBMPC - printk("PC/%cT class cpu %d, ", (sys_caps & CAP_PC_AT) ? 'A' : 'X', SETUP_CPU_TYPE); + printk("PC/%cT class cpu %d, ", (sys_caps & CAP_PC_AT) ? 'A' : 'X', arch_cpu); #endif #ifdef CONFIG_ARCH_PC98 @@ -267,7 +267,16 @@ static void INITPROC do_init_task(void) sys_dup(num); /* open stderr*/ //} + #ifdef CONFIG_BOOTOPTS + /* Release kernel data associated with /bootopts parsing */ + heap_add(options, OPTSEGSZ); + + /* Release /bootopts load segment (DEF_OPTSEG) and setup.S data segment (REL_INITSEG). + * Must not use SETUP_xxx setupw/setupb after this. + */ + seg_add(DEF_OPTSEG, DMASEG); + /* pass argc/argv/env array to init_command */ /* unset special sys_wait4() processing if pid 1 not /bin/init*/ From ab261130c5080f615de8b793c3bc7d54044034e4 Mon Sep 17 00:00:00 2001 From: Greg Haerr Date: Tue, 12 Nov 2024 23:26:07 -0800 Subject: [PATCH 4/7] Release kernel data and low memory associated with /bootopts and setup processing --- elks/init/main.c | 150 ++++++++++++++++++++++++----------------------- 1 file changed, 76 insertions(+), 74 deletions(-) diff --git a/elks/init/main.c b/elks/init/main.c index bc2ea9b8c..b1ead6449 100644 --- a/elks/init/main.c +++ b/elks/init/main.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -27,20 +28,11 @@ #define ENV 1 /* allow environ variables as bootopts*/ #define DEBUG 0 /* display parsing at boot*/ -#include - #define MAX_INIT_ARGS 6 /* max # arguments to /bin/init or init= program */ #define MAX_INIT_ENVS 12 /* max # environ variables passed to /bin/init */ #define MAX_INIT_SLEN 80 /* max # words of args + environ passed to /bin/init */ #define MAX_UMB 3 /* max umb= segments in /bootopts */ -#define STR(x) __STRING(x) -/* bootopts error message are duplicated below so static here for space */ -char errmsg_initargs[] = "init args > " STR(MAX_INIT_ARGS) "\n"; -char errmsg_initenvs[] = "init envs > " STR(MAX_INIT_ENVS) "\n"; -char errmsg_initslen[] = "init words > " STR(MAX_INIT_SLEN) "\n"; - -int root_mountflags; struct netif_parms netif_parms[MAX_ETHS] = { /* NOTE: The order must match the defines in netstat.h: * ETH_NE2K, ETH_WD, ETH_EL3 */ @@ -49,11 +41,11 @@ struct netif_parms netif_parms[MAX_ETHS] = { { EL3_IRQ, EL3_PORT, 0, EL3_FLAGS }, }; seg_t kernel_cs, kernel_ds; +int root_mountflags; int tracing; int nr_ext_bufs, nr_xms_bufs, nr_map_bufs; char running_qemu; static int boot_console; -static segext_t umbtotal; static char bininit[] = "/bin/init"; static char binshell[] = "/bin/sh"; #ifdef CONFIG_SYS_NO_BININIT @@ -66,24 +58,29 @@ static char *init_command = bininit; /* * Parse /bootopts startup options */ -static char opts; -static int args = 2; /* room for argc and av[0] */ -static int envs; -static int argv_slen; -#ifdef CONFIG_SYS_NO_BININIT -static char *argv_init[MAX_INIT_SLEN] = { NULL, binshell, NULL }; -#else -/* argv_init doubles as sptr data for sys_execv later*/ -static char *argv_init[MAX_INIT_SLEN] = { NULL, bininit, NULL }; -#endif +#define STR(x) __STRING(x) +/* bootopts error message are duplicated below so static here for space */ +char errmsg_initargs[] = "init args > " STR(MAX_INIT_ARGS) "\n"; +char errmsg_initenvs[] = "init envs > " STR(MAX_INIT_ENVS) "\n"; +char errmsg_initslen[] = "init words > " STR(MAX_INIT_SLEN) "\n"; + +/* this entire structure is released to kernel heap after /bootopts parsing */ +static struct { + int hasopts; + int args; + int envs; + int argv_slen; + char *argv_init[MAX_INIT_SLEN]; /* argv_init doubles as sptr data for sys_execv */ + struct umbseg { /* save umb= lines during /bootopts parse */ + seg_t base; + segext_t len; + } umbseg[MAX_UMB], *nextumb; + segext_t umbtotal; + unsigned char options[OPTSEGSZ]; #if ENV -static char *envp_init[MAX_INIT_ENVS]; + char *envp_init[MAX_INIT_ENVS]; #endif -static struct umbseg { /* saves umb= lines during /bootopts parse */ - seg_t base; - segext_t len; -} umbseg[MAX_UMB], *nextumb = umbseg; -static unsigned char options[OPTSEGSZ]; +} opts; extern int boot_rootdev; static char * INITPROC root_dev_name(int dev); @@ -110,10 +107,19 @@ void start_kernel(void) setsp(&task->t_regs.ax); /* change to idle task stack */ kernel_init(); /* continue init running on idle task stack */ - /* fork and run procedure init_task() as task #1*/ + /* fork and setup procedure init_task() to run as task #1 */ kfork_proc(init_task); wake_up_process(&task[1]); +#ifdef CONFIG_BOOTOPTS + /* Release /bootopts load segment (DEF_OPTSEG) and setup data segment (REL_INITSEG) */ + seg_add(DEF_OPTSEG, DMASEG); + + /* Let init_task run, then release kernel data associated with /bootopts parsing */ + schedule(); + heap_add(&opts, sizeof(opts)); +#endif + /* * We are now the idle task. We won't run unless no other process can run. * The idle task always runs with _gint_count == 1 (switched from user mode syscall) @@ -139,7 +145,10 @@ static void INITPROC early_kernel_init(void) #endif ROOT_DEV = SETUP_ROOT_DEV; /* default root device from boot loader */ #ifdef CONFIG_BOOTOPTS - opts = parse_options(); /* parse options found in /bootops */ + opts.nextumb = opts.umbseg; /* init static structure variables */ + opts.args = 2; /* room for argc and av[0] */ + opts.argv_init[1] = init_command; + opts.hasopts = parse_options(); /* parse options found in /bootops */ #endif /* create near heap at end of kernel bss */ @@ -151,11 +160,11 @@ static void INITPROC early_kernel_init(void) #ifdef CONFIG_BOOTOPTS struct umbseg *p; /* now able to add umb memory segments */ - for (p = umbseg; p < &umbseg[MAX_UMB]; p++) { + for (p = opts.umbseg; p < &opts.umbseg[MAX_UMB]; p++) { if (p->base) { debug("umb segment from %x to %x\n", p->base, p->base + p->len); seg_add(p->base, p->base + p->len); - umbtotal += p->len; + opts.umbtotal += p->len; } } #endif @@ -191,7 +200,7 @@ static void INITPROC kernel_init(void) #ifdef CONFIG_BOOTOPTS finalize_options(); - if (!opts) printk("/bootopts not found or bad format/size\n"); + if (!opts.hasopts) printk("/bootopts not found or bad format/size\n"); #endif #ifdef CONFIG_FARTEXT_KERNEL @@ -234,7 +243,7 @@ static void INITPROC kernel_banner(seg_t init, seg_t extra) #endif printk("data %x end %x top %x %u+%u+%uK free\n", kernel_ds, membase, memend, (int) ((memend - membase) >> 6), - extra >> 6, umbtotal >> 6); + extra >> 6, opts.umbtotal >> 6); } static void INITPROC try_exec_process(const char *path) @@ -269,14 +278,6 @@ static void INITPROC do_init_task(void) #ifdef CONFIG_BOOTOPTS - /* Release kernel data associated with /bootopts parsing */ - heap_add(options, OPTSEGSZ); - - /* Release /bootopts load segment (DEF_OPTSEG) and setup.S data segment (REL_INITSEG). - * Must not use SETUP_xxx setupw/setupb after this. - */ - seg_add(DEF_OPTSEG, DMASEG); - /* pass argc/argv/env array to init_command */ /* unset special sys_wait4() processing if pid 1 not /bin/init*/ @@ -284,7 +285,7 @@ static void INITPROC do_init_task(void) current->ppid = 1; /* turns off auto-child reaping*/ /* run /bin/init or init= command, normally no return*/ - run_init_process_sptr(init_command, (char *)argv_init, argv_slen); + run_init_process_sptr(init_command, (char *)opts.argv_init, opts.argv_slen); #else try_exec_process(init_command); #endif /* CONFIG_BOOTOPTS */ @@ -417,10 +418,10 @@ static void INITPROC parse_umb(char *line) do { base = (seg_t)simple_strtol(p+1, 16); if((p = strchr(p+1, ':'))) { - if (nextumb < &umbseg[MAX_UMB]) { - nextumb->len = (segext_t)simple_strtol(p+1, 16); - nextumb->base = base; - nextumb++; + if (opts.nextumb < &opts.umbseg[MAX_UMB]) { + opts.nextumb->len = (segext_t)simple_strtol(p+1, 16); + opts.nextumb->base = base; + opts.nextumb++; } } } while((p = strchr(p+1, ','))); @@ -442,15 +443,16 @@ static void INITPROC parse_umb(char *line) */ static int INITPROC parse_options(void) { - char *line = (char *)options; + char *line = (char *)opts.options; char *next; /* copy /bootopts loaded by boot loader at 0050:0000*/ - fmemcpyb(options, kernel_ds, 0, DEF_OPTSEG, sizeof(options)); + fmemcpyb(opts.options, kernel_ds, 0, DEF_OPTSEG, sizeof(opts.options)); #pragma GCC diagnostic ignored "-Wstrict-aliasing" /* check file starts with ##, one or two sectors, max 1023 bytes */ - if (*(unsigned short *)options != 0x2323 || (options[511] && options[OPTSEGSZ-1])) + if (*(unsigned short *)opts.options != 0x2323 || + (opts.options[511] && opts.options[OPTSEGSZ-1])) return 0; next = line; @@ -510,7 +512,7 @@ static int INITPROC parse_options(void) } if (!strncmp(line,"init=",5)) { line += 5; - init_command = argv_init[1] = line; + init_command = opts.argv_init[1] = line; continue; } if (!strncmp(line,"ne0=",4)) { @@ -574,14 +576,14 @@ static int INITPROC parse_options(void) * Then check if it's an environment variable or an init argument. */ if (!strchr(line,'=')) { /* no '=' means init argument*/ - if (args < MAX_INIT_ARGS) - argv_init[args++] = line; + if (opts.args < MAX_INIT_ARGS) + opts.argv_init[opts.args++] = line; else printk(errmsg_initargs); } #if ENV else { - if (envs < MAX_INIT_ENVS) - envp_init[envs++] = line; + if (opts.envs < MAX_INIT_ENVS) + opts.envp_init[opts.envs++] = line; else printk(errmsg_initenvs); } #endif @@ -596,54 +598,54 @@ static void INITPROC finalize_options(void) #if ENV /* set ROOTDEV environment variable for rc.sys fsck*/ - if (envs + running_qemu < MAX_INIT_ENVS) { - envp_init[envs++] = root_dev_name(ROOT_DEV); + if (opts.envs + running_qemu < MAX_INIT_ENVS) { + opts.envp_init[opts.envs++] = root_dev_name(ROOT_DEV); if (running_qemu) - envp_init[envs++] = (char *)"QEMU=1"; + opts.envp_init[opts.envs++] = (char *)"QEMU=1"; } else printk(errmsg_initenvs); #endif #if DEBUG printk("args: "); - for (i=1; i sizeof(argv_init)) + /*opts.argv_init[opts.args+2+opts.envs] = NULL;*/ + opts.argv_slen = q - (char *)opts.argv_init; + if (opts.argv_slen > sizeof(opts.argv_init)) panic(errmsg_initslen); } From 8ac43408c7bc765edfcbb53b3c14312c5290e062 Mon Sep 17 00:00:00 2001 From: Greg Haerr Date: Tue, 12 Nov 2024 23:50:17 -0800 Subject: [PATCH 5/7] Cleanup --- elks/init/main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/elks/init/main.c b/elks/init/main.c index b1ead6449..a02913ddf 100644 --- a/elks/init/main.c +++ b/elks/init/main.c @@ -46,6 +46,7 @@ int tracing; int nr_ext_bufs, nr_xms_bufs, nr_map_bufs; char running_qemu; static int boot_console; +static segext_t umbtotal; static char bininit[] = "/bin/init"; static char binshell[] = "/bin/sh"; #ifdef CONFIG_SYS_NO_BININIT @@ -75,7 +76,6 @@ static struct { seg_t base; segext_t len; } umbseg[MAX_UMB], *nextumb; - segext_t umbtotal; unsigned char options[OPTSEGSZ]; #if ENV char *envp_init[MAX_INIT_ENVS]; @@ -164,7 +164,7 @@ static void INITPROC early_kernel_init(void) if (p->base) { debug("umb segment from %x to %x\n", p->base, p->base + p->len); seg_add(p->base, p->base + p->len); - opts.umbtotal += p->len; + umbtotal += p->len; } } #endif @@ -243,7 +243,7 @@ static void INITPROC kernel_banner(seg_t init, seg_t extra) #endif printk("data %x end %x top %x %u+%u+%uK free\n", kernel_ds, membase, memend, (int) ((memend - membase) >> 6), - extra >> 6, opts.umbtotal >> 6); + extra >> 6, umbtotal >> 6); } static void INITPROC try_exec_process(const char *path) From f5c159c46580490e931dff3ec36c1b03b2c99742 Mon Sep 17 00:00:00 2001 From: Greg Haerr Date: Wed, 13 Nov 2024 12:41:28 -0800 Subject: [PATCH 6/7] Revert change releasing option buffers by idle task - not safe --- elks/init/main.c | 102 +++++++++++++++++++++++------------------------ 1 file changed, 50 insertions(+), 52 deletions(-) diff --git a/elks/init/main.c b/elks/init/main.c index a02913ddf..4757f0282 100644 --- a/elks/init/main.c +++ b/elks/init/main.c @@ -65,21 +65,27 @@ char errmsg_initargs[] = "init args > " STR(MAX_INIT_ARGS) "\n"; char errmsg_initenvs[] = "init envs > " STR(MAX_INIT_ENVS) "\n"; char errmsg_initslen[] = "init words > " STR(MAX_INIT_SLEN) "\n"; +#ifdef CONFIG_SYS_NO_BININIT +static char *argv_init[MAX_INIT_SLEN] = { NULL, binshell, NULL }; +#else +/* argv_init doubles as sptr data for sys_execv later*/ +static char *argv_init[MAX_INIT_SLEN] = { NULL, bininit, NULL }; +#endif +static char hasopts; +static int args = 2; /* room for argc and av[0] */ +static int envs; +static int argv_slen; +#if ENV +static char *envp_init[MAX_INIT_ENVS]; +#endif + /* this entire structure is released to kernel heap after /bootopts parsing */ static struct { - int hasopts; - int args; - int envs; - int argv_slen; - char *argv_init[MAX_INIT_SLEN]; /* argv_init doubles as sptr data for sys_execv */ - struct umbseg { /* save umb= lines during /bootopts parse */ + struct umbseg { /* save umb= lines during /bootopts parse */ seg_t base; segext_t len; } umbseg[MAX_UMB], *nextumb; - unsigned char options[OPTSEGSZ]; -#if ENV - char *envp_init[MAX_INIT_ENVS]; -#endif + unsigned char options[OPTSEGSZ]; /* near data parsing buffer */ } opts; extern int boot_rootdev; @@ -111,15 +117,6 @@ void start_kernel(void) kfork_proc(init_task); wake_up_process(&task[1]); -#ifdef CONFIG_BOOTOPTS - /* Release /bootopts load segment (DEF_OPTSEG) and setup data segment (REL_INITSEG) */ - seg_add(DEF_OPTSEG, DMASEG); - - /* Let init_task run, then release kernel data associated with /bootopts parsing */ - schedule(); - heap_add(&opts, sizeof(opts)); -#endif - /* * We are now the idle task. We won't run unless no other process can run. * The idle task always runs with _gint_count == 1 (switched from user mode syscall) @@ -129,7 +126,7 @@ void start_kernel(void) #ifdef CONFIG_TIMER_INT0F int0F(); /* simulate timer interrupt hooked on IRQ 7 */ #else - idle_halt(); /* halt until interrupt to save power */ + idle_halt(); /* halt until interrupt to save poer */ #endif } } @@ -146,9 +143,7 @@ static void INITPROC early_kernel_init(void) ROOT_DEV = SETUP_ROOT_DEV; /* default root device from boot loader */ #ifdef CONFIG_BOOTOPTS opts.nextumb = opts.umbseg; /* init static structure variables */ - opts.args = 2; /* room for argc and av[0] */ - opts.argv_init[1] = init_command; - opts.hasopts = parse_options(); /* parse options found in /bootops */ + hasopts = parse_options(); /* parse options found in /bootops */ #endif /* create near heap at end of kernel bss */ @@ -200,7 +195,7 @@ static void INITPROC kernel_init(void) #ifdef CONFIG_BOOTOPTS finalize_options(); - if (!opts.hasopts) printk("/bootopts not found or bad format/size\n"); + if (!hasopts) printk("/bootopts not found or bad format/size\n"); #endif #ifdef CONFIG_FARTEXT_KERNEL @@ -276,8 +271,11 @@ static void INITPROC do_init_task(void) sys_dup(num); /* open stderr*/ //} - #ifdef CONFIG_BOOTOPTS + /* Release options parsing buffers and setup data seg */ + heap_add(&opts, sizeof(opts)); + seg_add(DEF_OPTSEG, DMASEG); /* DEF_OPTSEG through REL_INITSEG */ + /* pass argc/argv/env array to init_command */ /* unset special sys_wait4() processing if pid 1 not /bin/init*/ @@ -285,7 +283,7 @@ static void INITPROC do_init_task(void) current->ppid = 1; /* turns off auto-child reaping*/ /* run /bin/init or init= command, normally no return*/ - run_init_process_sptr(init_command, (char *)opts.argv_init, opts.argv_slen); + run_init_process_sptr(init_command, (char *)argv_init, argv_slen); #else try_exec_process(init_command); #endif /* CONFIG_BOOTOPTS */ @@ -512,7 +510,7 @@ static int INITPROC parse_options(void) } if (!strncmp(line,"init=",5)) { line += 5; - init_command = opts.argv_init[1] = line; + init_command = argv_init[1] = line; continue; } if (!strncmp(line,"ne0=",4)) { @@ -576,14 +574,14 @@ static int INITPROC parse_options(void) * Then check if it's an environment variable or an init argument. */ if (!strchr(line,'=')) { /* no '=' means init argument*/ - if (opts.args < MAX_INIT_ARGS) - opts.argv_init[opts.args++] = line; + if (args < MAX_INIT_ARGS) + argv_init[args++] = line; else printk(errmsg_initargs); } #if ENV else { - if (opts.envs < MAX_INIT_ENVS) - opts.envp_init[opts.envs++] = line; + if (envs < MAX_INIT_ENVS) + envp_init[envs++] = line; else printk(errmsg_initenvs); } #endif @@ -598,54 +596,54 @@ static void INITPROC finalize_options(void) #if ENV /* set ROOTDEV environment variable for rc.sys fsck*/ - if (opts.envs + running_qemu < MAX_INIT_ENVS) { - opts.envp_init[opts.envs++] = root_dev_name(ROOT_DEV); + if (envs + running_qemu < MAX_INIT_ENVS) { + envp_init[envs++] = root_dev_name(ROOT_DEV); if (running_qemu) - opts.envp_init[opts.envs++] = (char *)"QEMU=1"; + envp_init[envs++] = (char *)"QEMU=1"; } else printk(errmsg_initenvs); #endif #if DEBUG printk("args: "); - for (i=1; i sizeof(opts.argv_init)) + /*argv_init[args+2+envs] = NULL;*/ + argv_slen = q - (char *)argv_init; + if (argv_slen > sizeof(argv_init)) panic(errmsg_initslen); } From 3def02fb16207a7e3dae7f7d94d257841d78e1ec Mon Sep 17 00:00:00 2001 From: Greg Haerr Date: Wed, 13 Nov 2024 13:03:21 -0800 Subject: [PATCH 7/7] Cleanup --- elks/arch/i86/boot/setup.S | 4 ++-- elks/include/linuxmt/config.h | 4 ++-- elks/init/main.c | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/elks/arch/i86/boot/setup.S b/elks/arch/i86/boot/setup.S index b80f4029d..f7e13eaf0 100644 --- a/elks/arch/i86/boot/setup.S +++ b/elks/arch/i86/boot/setup.S @@ -946,8 +946,8 @@ putc: push %ax // // load /bootopts file for FAT filesystem boot // If size > 512 bytes, both sectors must be contiguous. -// This is currently guaranteed by using a 1K /bootopts in -// distribution images, as later edits will remain contiguous. +// This is currently guaranteed by providing a 1K /bootopts in +// distribution images, so later edits will remain contiguous. // // Uses previous boot sector's BPB contents for disk geometry // and previous boot sector's buffer which still holds root directory sector. diff --git a/elks/include/linuxmt/config.h b/elks/include/linuxmt/config.h index 30b601a6c..836d1fd22 100644 --- a/elks/include/linuxmt/config.h +++ b/elks/include/linuxmt/config.h @@ -15,8 +15,8 @@ /* * SETUP_ defines are initialzied by setup.S and queried only during kernel init. - * The REL_INITSEG segment is released at end of kernel init. For later use the - * value must be copied, as afterwards setupb/setupw will return incorrect data. + * The REL_INITSEG segment is released at end of kernel init. If used later any + * values must be copied, as afterwards setupb/setupw will return incorrect data. * These defines are overridden for ROM based systems w/o setup code. * See setup.S for setupb/setupw offsets. */ diff --git a/elks/init/main.c b/elks/init/main.c index 4757f0282..dfcb8dca5 100644 --- a/elks/init/main.c +++ b/elks/init/main.c @@ -113,7 +113,7 @@ void start_kernel(void) setsp(&task->t_regs.ax); /* change to idle task stack */ kernel_init(); /* continue init running on idle task stack */ - /* fork and setup procedure init_task() to run as task #1 */ + /* fork and setup procedure init_task() to run as task #1 on reschedule */ kfork_proc(init_task); wake_up_process(&task[1]); @@ -126,7 +126,7 @@ void start_kernel(void) #ifdef CONFIG_TIMER_INT0F int0F(); /* simulate timer interrupt hooked on IRQ 7 */ #else - idle_halt(); /* halt until interrupt to save poer */ + idle_halt(); /* halt until interrupt to save power */ #endif } } @@ -619,16 +619,16 @@ static void INITPROC finalize_options(void) /* convert argv array to stack array for sys_execv*/ args--; - argv_init[0] = (char *)args; /* 0 = argc*/ + argv_init[0] = (char *)args; /* 0 = argc*/ char *q = (char *)&argv_init[args+2+envs+1]; - for (i=1; i<=args; i++) { /* 1..argc = av*/ + for (i=1; i<=args; i++) { /* 1..argc = av*/ char *p = argv_init[i]; char *savq = q; while ((*q++ = *p++) != 0) ; argv_init[i] = (char *)(savq - (char *)argv_init); } - /*argv_init[args+1] = NULL;*/ /* argc+1 = 0*/ + /*argv_init[args+1] = NULL;*/ /* argc+1 = 0*/ #if ENV if (envs) { for (i=0; i