//+++2004-09-11 // Copyright (C) 2004 Mike Rieker, Beverly, MA USA // // 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; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA //---2004-09-11 /************************************************************************/ /* */ /* This routine gets called by the hardware layer at boot time */ /* */ /* Its job is to read the loader parameter file, then load the */ /* kernel into memory. When it returns, the hardware layer will */ /* enable virtual memory then call the kernel. */ /* */ /* Although this routine calls stuff like oz_knl_iochan_create, */ /* oz_knl_iostart, oz_sys_image_load, they unlerlying routines are */ /* not the usual stuff. At this point, the computer is not in */ /* virtual memory mode, and does not have a 'current thread', etc. */ /* So many of the underlying kernel modules have been replaced with */ /* stripped-down versions. */ /* */ /************************************************************************/ #include #include "gzip.h" #include "ozone.h" #include "oz_io_console.h" #include "oz_io_disk.h" #include "oz_io_fs.h" #include "oz_knl_cache.h" #include "oz_knl_devio.h" #include "oz_knl_event.h" #include "oz_knl_handle.h" #include "oz_knl_image.h" #include "oz_knl_kmalloc.h" #include "oz_knl_lock.h" #include "oz_knl_logname.h" #include "oz_knl_logon.h" #include "oz_knl_lowipl.h" #include "oz_knl_phymem.h" #include "oz_knl_printk.h" #include "oz_knl_process.h" #include "oz_knl_quota.h" #include "oz_knl_sdata.h" #include "oz_knl_shuthand.h" #include "oz_knl_spte.h" #include "oz_knl_status.h" #include "oz_knl_thread.h" #include "oz_knl_userjob.h" #include "oz_ldr_loader.h" #include "oz_sys_dateconv.h" #include "oz_sys_io_fs.h" #include "oz_sys_misc.h" #include "oz_sys_thread.h" #include "oz_sys_xprintf.h" /************************************************************************/ /* */ /* Internal static data and routines */ /* */ /************************************************************************/ static int getcon_timeout = 5000; static OZ_Iochan *con_iochan = NULL; static OZ_Event *ctrlcy_event = NULL; static OZ_Event *event = NULL; static uLong phymem_count = 0; static volatile int ctrlcy_hit = 0; static char ctrlt_msg[256]; static char load_fs[OZ_DEVUNIT_NAMESIZE]; static int ctrlcy_enable (void); static void ctrlcy_ast (void *dummy, uLong status); static int ctrlt_enable (void); static void ctrlt_ast (void *dummy, uLong status); static OZ_Iochan *mount_boot_device (int readwrite); static void dism_boot_device (OZ_Iochan *load_iochan); static void crelogname (OZ_Logname *lognamtbl, uLong logvalatr, char *name, char *value); static int read_param_file (OZ_Iochan *iochan); static uLong copyfile (char *iname, char *oname); static uLong deletefile (char *name); static int dogzip (int gzipfc, char *iname, char *oname); static char *quadmemsize (uQuad size, char *buff); /************************************************************************/ /* */ /* Input: */ /* */ /* loadparams_p = points to load param block */ /* sysbaseva = base virtual address of system global area */ /* copied into oz_s_sysmem_baseva */ /* startphypage = (obsolete) */ /* phypages = (obsolete) */ /* tempmemsize = size of temporary non-paged pool */ /* tempmemaddr = address of temporary non-paged pool */ /* cacheareasize = some number of physical pages for temp cache */ /* cacheareabase = base physical page number */ /* ntempsptes = number of temp sptes available */ /* tempsptes = vpage mapped by first temp spte */ /* */ /* Output: */ /* */ /* *loadparams_p = quite possibly modified */ /* *kstacksize = kernel stack size (in bytes) */ /* *systempages = number of system pages */ /* */ /************************************************************************/ void *oz_ldr_start (OZ_Loadparams *loadparams_p, void *sysbaseva, OZ_Mempage startphypage, OZ_Mempage phypages, uLong tempmemsize, void *tempmemaddr, uLong *kstacksize, uLong *systempages, OZ_Mempage cacheareasize, OZ_Mempage cacheareabase, OZ_Mempage ntempsptes, OZ_Mempage tempsptes) { char param_filespec[256]; int i, j; uLong status, sts; OZ_Image *knlimage; OZ_IO_fs_open fs_open; OZ_Iochan *load_iochan; void *baseaddr, *startaddr; oz_s_inloader = 1; oz_hw_putcon (24, "\noz_ldr_start: starting\n"); // print a message before inhibiting softints oz_hw_cpu_setsoftint (0); // we're not pre-emptive anyway, but in case // ... some routine tests, we make it official oz_knl_printk ("%s\n", oz_sys_copyright); // print another message after softints inhibited oz_knl_sdata_init1 (); oz_s_cpucount = 1; oz_s_cpusavail = 1; oz_s_phymem_l1pages = 1; oz_s_phymem_l2pages = 1; oz_knl_printk ("oz_ldr_start: param block at %p\n", loadparams_p); oz_ldr_paramblock = *loadparams_p; oz_knl_printk ("oz_ldr_start: boot device %s\n", oz_ldr_paramblock.load_device); oz_knl_printk ("oz_ldr_start: boot fs template %s\n", oz_ldr_paramblock.load_fstemp); oz_knl_printk ("oz_ldr_start: boot directory %s\n", oz_ldr_paramblock.load_dir); oz_knl_printk ("oz_ldr_start: system virtual base address %p\n", sysbaseva); oz_knl_printk ("oz_ldr_start: page size %u\n", 1 << OZ_HW_L2PAGESIZE); oz_knl_printk ("oz_ldr_start: there are %u bytes of temp memory at %p\n", tempmemsize, tempmemaddr); oz_knl_printk ("oz_ldr_start: there are %u physical pages for cache at 0x%X\n", cacheareasize, cacheareabase); oz_knl_printk ("oz_ldr_start: there are %u temp sptes at page 0x%X (vaddr %p)\n", ntempsptes, tempsptes, OZ_HW_VPAGETOVADDR (tempsptes)); oz_s_sysmem_baseva = sysbaseva; OZ_KNL_NPPFREESIZ (tempmemsize, tempmemaddr); oz_knl_sdata_init2 (); phymem_count = cacheareasize; oz_ldr_phymem_init (cacheareasize, cacheareabase); oz_ldr_spte_init (ntempsptes, tempsptes); oz_knl_event_init (); oz_knl_handle_init (); oz_knl_event_create (13, "oz_ldr_loader", NULL, &event); oz_knl_event_create (8, "ctrl-C/Y", NULL, &ctrlcy_event); oz_knl_thread_cpuinit (); oz_knl_handletbl_create (); /* Initialize logical name tables for the drivers */ sts = oz_knl_logname_create (NULL, OZ_PROCMODE_KNL, NULL, NULL, OZ_LOGNAMATR_TABLE, 19, "OZ_SYSTEM_DIRECTORY", 0, NULL, &oz_s_systemdirectory); if (sts != OZ_SUCCESS) oz_crash ("oz_ldr_loader: error %u creating loader logical name directory"); sts = oz_knl_logname_create (oz_s_systemdirectory, OZ_PROCMODE_KNL, NULL, NULL, OZ_LOGNAMATR_TABLE, 15, "OZ_SYSTEM_TABLE", 0, NULL, &oz_s_systemtable); if (sts != OZ_SUCCESS) oz_crash ("oz_ldr_loader: error %u creating logical OZ_SYSTEM_TABLE in system directory", sts); crelogname (oz_s_systemtable, OZ_LOGVALATR_TERMINAL, "OZ_BOOT_DEV", oz_ldr_paramblock.load_device); crelogname (oz_s_systemtable, OZ_LOGVALATR_TERMINAL, "OZ_BOOT_DIR", oz_ldr_paramblock.load_dir); /* Initialize drivers that we will use */ oz_knl_printk ("oz_ldr_start: initializing device drivers\n"); oz_knl_devinit (); oz_knl_devdump (0); oz_knl_printk ("\n"); /* Should be able to assign I/O channel to console - If failure, */ /* set con_iochan to NULL so read routine will use oz_hw_getcon */ sts = oz_knl_iochan_crbynm ("console", OZ_LOCKMODE_CW, OZ_PROCMODE_KNL, NULL, &con_iochan); if (sts != OZ_SUCCESS) { oz_knl_printk ("oz_ldr_start: error %u assigning channel to console\n", sts); con_iochan = NULL; } /* Set up an control-C/control-Y handler and control-T handler */ else { if (ctrlcy_enable ()) oz_knl_printk ("oz_ldr_start: press control-C or control-Y to abort command\n"); ctrlt_msg[0] = 0; if (ctrlt_enable ()) oz_knl_printk ("oz_ldr_start: press control-T for thread status display\n"); } /* Read parameter modifications from console */ oz_knl_printk ("oz_ldr_start: type HELP for help, EXIT when done\n"); if ((con_iochan != NULL) && (getcon_timeout != 0)) { oz_knl_printk ("oz_ldr_start: first prompt will timeout in %d seconds\n", getcon_timeout / 1000); } read_param_from_con: while (!read_param_file (NULL)) {} // if a command is bad, just prompt again /* If no boot device defined, scan for it */ if (oz_ldr_paramblock.load_device[0] == 0) { ctrlcy_hit = 0; if (!oz_hw_bootscan (&ctrlcy_hit, ctrlcy_event, 0)) goto read_param_from_con; } /* Open the load_script file in the load directory and process it */ if (oz_ldr_paramblock.load_script[0] != 0) { load_iochan = mount_boot_device (1); if (load_iochan == NULL) goto read_param_from_con; memset (&fs_open, 0, sizeof fs_open); strcpy (param_filespec, oz_ldr_paramblock.load_dir); strcat (param_filespec, oz_ldr_paramblock.load_script); oz_knl_printk ("oz_ldr_start: reading parameter file %s\n\n", param_filespec); fs_open.name = param_filespec; fs_open.lockmode = OZ_LOCKMODE_PR; sts = oz_knl_io (load_iochan, OZ_IO_FS_OPEN, sizeof fs_open, &fs_open); if (sts != OZ_SUCCESS) { oz_knl_printk ("oz_ldr_start: error %u opening loader param file %s on device %s\n", sts, param_filespec, oz_ldr_paramblock.load_device); dism_boot_device (load_iochan); goto read_param_from_con; } i = read_param_file (load_iochan); // process commands from script file oz_knl_io (load_iochan, OZ_IO_FS_CLOSE, 0, NULL); // close script file dism_boot_device (load_iochan); // maybe script changed boot device, so dismount old one if (!i) goto read_param_from_con; // if error, read commands from console } /* If no boot device defined, scan for it (maybe load script reset it) */ if (oz_ldr_paramblock.load_device[0] == 0) { ctrlcy_hit = 0; if (!oz_hw_bootscan (&ctrlcy_hit, ctrlcy_event, 0)) goto read_param_from_con; } /* Mount boot device read-only */ load_iochan = mount_boot_device (0); if (load_iochan == NULL) goto read_param_from_con; /* Create logical name for loader to get the kernel */ strcpy (param_filespec, load_fs); strcat (param_filespec, ":"); strcat (param_filespec, oz_ldr_paramblock.load_dir); crelogname (oz_s_systemtable, OZ_LOGVALATR_TERMINAL, "OZ_IMAGE_DIR", param_filespec); /* Load kernel image */ oz_knl_printk ("oz_ldr_start: loading kernel image %s from %s\n", oz_ldr_paramblock.kernel_image, param_filespec); sts = oz_knl_image_load (OZ_PROCMODE_KNL, oz_ldr_paramblock.kernel_image, 1, 0, &baseaddr, &startaddr, &knlimage); if (sts != OZ_SUCCESS) { oz_knl_printk ("oz_ldr_start: error %u loading kernel image\n", sts); dism_boot_device (load_iochan); goto read_param_from_con; } oz_knl_printk ("oz_ldr_start: kernel image loaded, start address %p\n", startaddr); /* Dismount the load volume */ dism_boot_device (load_iochan); /* Shut down everything nicely */ oz_knl_shutdown (); /* Return values to hardware layer */ *loadparams_p = oz_ldr_paramblock; *kstacksize = oz_ldr_paramblock.kernel_stack_size; *systempages = oz_ldr_paramblock.system_pages; return (startaddr); } /************************************************************************/ /* */ /* Enable control-C/control-Y detection. Set ctrlcy_hit when hit. */ /* */ /************************************************************************/ static int ctrlcy_enable (void) { OZ_IO_console_ctrlchar ctrlcy; uLong sts; memset (&ctrlcy, 0, sizeof ctrlcy); ctrlcy.mask[0] = (1 << ('C' - '@')) | (1 << ('Y' - '@')); sts = oz_knl_iostart (con_iochan, OZ_PROCMODE_KNL, ctrlcy_ast, NULL, NULL, NULL, NULL, NULL, OZ_IO_CONSOLE_CTRLCHAR, sizeof ctrlcy, &ctrlcy); if (sts != OZ_STARTED) oz_knl_printk ("oz_ldr_start: error %u enabling ctrl-C/-Y detection\n", sts); return (sts == OZ_STARTED); } static void ctrlcy_ast (void *dummy, uLong status) { if (status == OZ_SUCCESS) { ctrlcy_hit = 1; oz_knl_event_set (ctrlcy_event, 1); } else if (status != OZ_ABORTED) oz_knl_printk ("oz_ldr_start: error %u ctrl-C/-Y completion\n", status); ctrlcy_enable (); } /************************************************************************/ /* */ /* Enable control-T detection. Call thread_dump when hit. */ /* */ /************************************************************************/ static int ctrlt_enable (void) { OZ_IO_console_ctrlchar ctrlt; uLong sts; memset (&ctrlt, 0, sizeof ctrlt); ctrlt.mask[0] = (1 << ('T' - '@')); sts = oz_knl_iostart (con_iochan, OZ_PROCMODE_KNL, ctrlt_ast, NULL, NULL, NULL, NULL, NULL, OZ_IO_CONSOLE_CTRLCHAR, sizeof ctrlt, &ctrlt); if (sts != OZ_STARTED) oz_knl_printk ("oz_ldr_start: error %u enabling ctrl-T detection\n", sts); return (sts == OZ_STARTED); } static void ctrlt_ast (void *dummy, uLong status) { if (status == OZ_SUCCESS) { oz_ldr_thread_dump (); oz_knl_printk ("%s", ctrlt_msg); } else if (status != OZ_ABORTED) oz_knl_printk ("oz_ldr_start: error %u ctrl-T completion\n", status); ctrlt_enable (); } /************************************************************************/ /* */ /* Mount the boot device */ /* */ /* Input: */ /* */ /* oz_ldr_paramblock.load_device = disk device to be mounted */ /* oz_ldr_paramblock.load_fstemp = filesystem template device */ /* */ /* Output: */ /* */ /* mount_boot_device = NULL : error */ /* else : filesystem I/O channel */ /* load_fs = filesystem device name */ /* logical OZ_BOOT_FS = filesystem device name */ /* */ /************************************************************************/ static OZ_Iochan *mount_boot_device (int readwrite) { uLong sts; OZ_IO_fs_mountvol fs_mountvol; OZ_Iochan *load_iochan; /* If template device string is null, the load device does not */ /* need mounting, it will accept OZ_IO_FS_OPEN calls as is */ if (oz_ldr_paramblock.load_fstemp[0] == 0) { strncpyz (load_fs, oz_ldr_paramblock.load_device, sizeof load_fs); oz_knl_printk ("oz_ldr_start: assigning channel to load device %s\n", load_fs); sts = oz_knl_iochan_crbynm (load_fs, readwrite ? OZ_LOCKMODE_CW : OZ_LOCKMODE_CR, OZ_PROCMODE_KNL, NULL, &load_iochan); if (sts != OZ_SUCCESS) { oz_knl_printk ("oz_ldr_start: error %u assigning channel to load device %s\n", sts, load_fs); return (NULL); } } /* Load_fstemp string supplied, assign I/O channel to template, then mount load device on it */ /* Mount it readonly, and don't bother with cache because we are just reading kernel into memory */ else { oz_knl_printk ("oz_ldr_start: mounting boot device %s on fs %s\n", oz_ldr_paramblock.load_device, oz_ldr_paramblock.load_fstemp); sts = oz_knl_iochan_crbynm (oz_ldr_paramblock.load_fstemp, readwrite ? OZ_LOCKMODE_CW : OZ_LOCKMODE_CR, OZ_PROCMODE_KNL, NULL, &load_iochan); if (sts != OZ_SUCCESS) { oz_knl_printk ("oz_ldr_start: error %u assigning channel to load fs template %s\n", sts, oz_ldr_paramblock.load_fstemp); return (NULL); } memset (&fs_mountvol, 0, sizeof fs_mountvol); fs_mountvol.devname = oz_ldr_paramblock.load_device; fs_mountvol.mountflags = OZ_FS_MOUNTFLAG_READONLY | OZ_FS_MOUNTFLAG_NOCACHE; if (readwrite) fs_mountvol.mountflags = 0; sts = oz_knl_io (load_iochan, OZ_IO_FS_MOUNTVOL, sizeof fs_mountvol, &fs_mountvol); if (sts != OZ_SUCCESS) { oz_knl_printk ("oz_ldr_start: error %u mounting load device %s on fs %s\n", sts, oz_ldr_paramblock.load_device, oz_ldr_paramblock.load_fstemp); oz_knl_iochan_increfc (load_iochan, -1); return (NULL); } strncpyz (load_fs, oz_knl_devunit_devname (oz_knl_iochan_getdevunit (load_iochan)), sizeof load_fs); oz_knl_printk ("oz_ldr_start: load device %s mounted as %s\n", oz_ldr_paramblock.load_device, load_fs); } /* Either way, create logical name OZ_BOOT_FS to point to resultant filesystem device */ crelogname (oz_s_systemtable, OZ_LOGVALATR_TERMINAL, "OZ_BOOT_FS", load_fs); oz_knl_printk ("oz_ldr_start: logical OZ_BOOT_FS assigned to %s\n", load_fs); return (load_iochan); } static void dism_boot_device (OZ_Iochan *load_iochan) { uLong sts; /* Dismount if there is a template device */ if (oz_ldr_paramblock.load_fstemp[0] != 0) { sts = oz_knl_io (load_iochan, OZ_IO_FS_DISMOUNT, 0, NULL); if (sts != OZ_SUCCESS) oz_knl_printk ("oz_ldr_start: error %u dismounting load volume\n", sts); } /* Anyway, deassign the i/o channel */ oz_knl_iochan_increfc (load_iochan, -1); } /************************************************************************/ /* */ /* Create logical name */ /* */ /************************************************************************/ static void crelogname (OZ_Logname *lognamtbl, uLong logvalatr, char *name, char *value) { uLong sts; OZ_Logvalue lnmvalue; lnmvalue.attr = logvalatr; lnmvalue.buff = value; sts = oz_knl_logname_create (lognamtbl, OZ_PROCMODE_KNL, NULL, NULL, 0, strlen (name), name, 1, &lnmvalue, NULL); if ((sts != OZ_SUCCESS) && (sts != OZ_SUPERSEDED)) { oz_crash ("oz_ldr_loader crelogname: error %u creating logical name %s", sts, name); } } /************************************************************************/ /* */ /* Read parameters and store in oz_ldr_paramblock */ /* */ /* Input: */ /* */ /* iochan = NULL : read from console terminal */ /* else : i/o channel of parameter file */ /* */ /* Output: */ /* */ /* results stored in oz_ldr_paramblock */ /* */ /************************************************************************/ #define COPY_SIZE 4096 static int read_param_file (OZ_Iochan *iochan) { char *argv[128], c, filenambuff[64], linebuf[256], *p, rnamebuff[OZ_FS_MAXFNLEN], *secattrstr, tempbuf[256]; int argc, i, j, s, usedup; OZ_Datebin now; OZ_IO_console_read console_read; OZ_IO_fs_create fs_create; OZ_IO_fs_getinfo1 fs_getinfo1; OZ_IO_fs_getsecattr fs_getsecattr; OZ_IO_fs_initvol fs_initvol; OZ_IO_fs_mountvol fs_mountvol; OZ_IO_fs_open fs_open; OZ_IO_fs_readblocks fs_readblocks; OZ_IO_fs_readdir fs_readdir; OZ_IO_fs_readrec fs_readrec; OZ_IO_fs_remove fs_remove; OZ_IO_fs_writeblocks fs_writeblocks; OZ_IO_fs_writeboot fs_writeboot; OZ_IO_fs_writerec fs_writerec; OZ_Iochan *fileiochan, *tempiochan; uLong count, linelen, sts, svbn, ul; ctrlcy_hit = 0; while (1) { if (ctrlcy_hit) return (0); /* Read a record either from console or from loader parameter file */ if (iochan == NULL) { /* If available use the console driver (so we will process */ /* timeout and so interrupts will be enabled during read) */ if (con_iochan != NULL) { memset (&console_read, 0, sizeof console_read); console_read.size = sizeof linebuf - 1; console_read.buff = linebuf; console_read.pmtsize = 16; console_read.pmtbuff = "\noz_ldr_start> "; console_read.rlen = &linelen; console_read.timeout = getcon_timeout; sts = oz_knl_io (con_iochan, OZ_IO_CONSOLE_READ, sizeof console_read, &console_read); if (sts == OZ_SUCCESS) linebuf[linelen] = 0; else if ((sts == OZ_TIMEDOUT) || (sts == OZ_ENDOFFILE)) { oz_knl_printk ("*EXIT*\n"); strcpy (linebuf, "EXIT"); } else { oz_knl_printk ("oz_ldr_start: error %u reading from console\n", sts); oz_knl_iochan_increfc (con_iochan, -1); con_iochan = NULL; getcon_timeout = 0; return (0); } } /* Otherwise, use hardware routine to read from console (which */ /* typically inhibits interrupts and has no timeout processing) */ if (con_iochan == NULL) { if (!oz_hw_getcon (sizeof linebuf, linebuf, 16, "\noz_ldr_start> ")) { oz_knl_printk ("*EXIT*\n"); strcpy (linebuf, "EXIT"); } } /* In any case, inhibit timeouts next time around - they only apply to the first prompt */ getcon_timeout = 0; } else { /* Reading from file, no timeout business */ memset (&fs_readrec, 0, sizeof fs_readrec); fs_readrec.size = sizeof linebuf - 1; fs_readrec.buff = linebuf; fs_readrec.trmsize = 1; fs_readrec.trmbuff = "\n"; fs_readrec.rlen = &linelen; sts = oz_knl_io (iochan, OZ_IO_FS_READREC, sizeof fs_readrec, &fs_readrec); if (sts != OZ_SUCCESS) { if (sts == OZ_ENDOFFILE) return (1); oz_knl_printk ("error %u reading parameter file\n", sts); return (0); } linebuf[linelen] = 0; oz_knl_printk ("> %s\n", linebuf); } /* Parse it up into an argc/argv array */ argc = 0; s = 1; for (i = 0; (c = linebuf[i]) != 0; i ++) { if ((c == '!') || (c == '#')) break; if (c > ' ') { if (c == '\\') { for (j = i; linebuf[j] != 0; j ++) linebuf[j] = linebuf[j+1]; if (linebuf[i] == 0) break; } if (s) { argv[argc++] = linebuf + i; s = 0; } } else { s = 1; linebuf[i] = 0; } } argv[argc] = NULL; /* Ignore blank lines */ if (argc == 0) continue; /* Process BARF command */ if (strcasecmp (argv[0], "BARF") == 0) { oz_crash ("BARFing"); } /* Process BOOTSCAN command */ if (strcasecmp (argv[0], "BOOTSCAN") == 0) { if ((argc != 1) && ((argc != 2) || (strcasecmp (argv[1], "-verbose") != 0))) { oz_knl_printk ("BOOTSCAN can have 1 option, -verbose\n"); return (0); } oz_knl_printk ("Scanning for boot device...\n"); ctrlcy_hit = 0; argc = oz_hw_bootscan (&ctrlcy_hit, ctrlcy_event, (argc == 2)); oz_knl_printk ("Scanning %s\n", argc ? "successful" : "failed"); if (argc) continue; return (0); } /* Process COPY command */ if (strcasecmp (argv[0], "COPY") == 0) { if (argc != 3) { oz_knl_printk ("COPY command requires 2 arguments: COPY \n"); oz_knl_printk (" for example: copy floppy.p0.oz_dfs:/ ide_pm.3.oz_dfs:/\n"); return (0); } sts = copyfile (argv[1], argv[2]); if (sts != OZ_SUCCESS) return (0); continue; } /* Process DELETE command */ if (strcasecmp (argv[0], "DELETE") == 0) { if (argc != 2) { oz_knl_printk ("DELETE command requires 1 argument: DELETE \n"); oz_knl_printk (" for example: delete floppy.p0.oz_dfs:/ozone/startup/commonstartup.cli\n"); return (0); } sts = deletefile (argv[1]); if (sts != OZ_SUCCESS) return (0); continue; } /* Process DEVICES command */ if (strcasecmp (argv[0], "DEVICES") == 0) { if ((argc == 1) || ((argc == 2) && (strcasecmp (argv[1], "-FULL") == 0))) oz_knl_devdump (argc == 2); else { oz_knl_printk ("DEVICES [-full]\n"); return (0); } continue; } /* Process DIR command */ if (strcasecmp (argv[0], "DIR") == 0) { if (argc != 2) { oz_knl_printk ("DIR command requires 1 argument: DIR \n"); oz_knl_printk (" for example: dir floppy.p0.oz_dfs:/\n"); return (0); } p = strchr (argv[1], ':'); if (p == NULL) { oz_knl_printk ("missing : in %s\n", argv[1]); return (0); } *p = 0; sts = oz_knl_iochan_crbynm (argv[1], OZ_LOCKMODE_CW, OZ_PROCMODE_KNL, NULL, &tempiochan); if (sts != OZ_SUCCESS) { oz_knl_printk ("error %u assigning channel to filesystem device %s\n", sts, argv[1]); return (0); } sts = oz_knl_iochan_crbynm (argv[1], OZ_LOCKMODE_CW, OZ_PROCMODE_KNL, NULL, &fileiochan); if (sts != OZ_SUCCESS) { oz_knl_printk ("error %u assigning second channel to filesystem device %s\n", sts, argv[1]); oz_knl_iochan_increfc (tempiochan, -1); return (0); } *(p ++) = ':'; memset (&fs_open, 0, sizeof fs_open); fs_open.name = p; fs_open.lockmode = OZ_LOCKMODE_CR; fs_open.rnamesize = sizeof rnamebuff; fs_open.rnamebuff = rnamebuff; rnamebuff[0] = 0; sts = oz_knl_io (tempiochan, OZ_IO_FS_OPEN, sizeof fs_open, &fs_open); if (sts != OZ_SUCCESS) { oz_knl_printk ("error %u opening directory %s\n", sts, argv[1]); oz_knl_iochan_increfc (tempiochan, -1); oz_knl_iochan_increfc (fileiochan, -1); return (0); } if (rnamebuff[0] == 0) strncpyz (rnamebuff, argv[1], sizeof rnamebuff); oz_knl_printk ("listing directory %s\n", rnamebuff); strcpy (filenambuff, p); i = strlen (filenambuff); memset (&fs_readdir, 0, sizeof fs_readdir); fs_readdir.filenamsize = sizeof filenambuff - i; fs_readdir.filenambuff = filenambuff + i; while ((sts = oz_knl_io (tempiochan, OZ_IO_FS_READDIR, sizeof fs_readdir, &fs_readdir)) == OZ_SUCCESS) { memset (&fs_open, 0, sizeof fs_open); fs_open.name = filenambuff; fs_open.lockmode = OZ_LOCKMODE_NL; sts = oz_knl_io (fileiochan, OZ_IO_FS_OPEN, sizeof fs_open, &fs_open); if (sts != OZ_SUCCESS) oz_knl_printk (" error %u opening file %s\n", sts, filenambuff); else { memset (&fs_getinfo1, 0, sizeof fs_getinfo1); sts = oz_knl_io (fileiochan, OZ_IO_FS_GETINFO1, sizeof fs_getinfo1, &fs_getinfo1); if (sts != OZ_SUCCESS) oz_knl_printk (" error %u getting attributes for %s\n", sts, filenambuff); else oz_knl_printk (" %6u.%-3u/%-6u %19.19t %s\n", fs_getinfo1.eofblock, fs_getinfo1.eofbyte, fs_getinfo1.hiblock, fs_getinfo1.modify_date, filenambuff + i); oz_knl_io (fileiochan, OZ_IO_FS_CLOSE, 0, NULL); } sts = OZ_ABORTEDBYCLI; if (ctrlcy_hit) break; } oz_knl_iochan_increfc (tempiochan, -1); oz_knl_iochan_increfc (fileiochan, -1); if (sts != OZ_ENDOFFILE) { oz_knl_printk ("error %u reading directory\n", sts); return (0); } oz_knl_printk ("end of directory\n"); continue; } /* Process DISMOUNT command */ if ((strcasecmp (argv[0], "DISM") == 0) || (strcasecmp (argv[0], "DISMOUNT") == 0)) { if (argc != 2) { oz_knl_printk ("DISMOUNT command requires 1 argument: DISMOUNT \n"); oz_knl_printk (" for example: dismount floppy.p0.oz_dfs\n"); return (0); } sts = oz_knl_iochan_crbynm (argv[1], OZ_LOCKMODE_CR, OZ_PROCMODE_KNL, NULL, &tempiochan); if (sts != OZ_SUCCESS) { oz_knl_printk ("error %u assigning channel to filesystem device %s\n", sts, argv[1]); return (0); } sts = oz_knl_io (tempiochan, OZ_IO_FS_DISMOUNT, 0, NULL); oz_knl_iochan_increfc (tempiochan, -1); if (sts != OZ_SUCCESS) { oz_knl_printk ("error %u dismounting fsdevice %s\n", sts, argv[1]); return (0); } oz_knl_printk ("fsdevice %s dismounted\n", argv[1]); continue; } /* Process DUMP command */ if (strcasecmp (argv[0], "DUMP") == 0) { if (argc != 4) { oz_knl_printk ("DUMP command requires 3 arguments: DUMP \n"); oz_knl_printk (" for example: dump floppy.p0.oz_dfs:/oz_loader_486.bb 4 1\n"); return (0); } /* Open input file */ p = strchr (argv[1], ':'); if (p == NULL) { oz_knl_printk ("missing : in %s\n", argv[1]); return (0); } *p = 0; sts = oz_knl_iochan_crbynm (argv[1], OZ_LOCKMODE_CR, OZ_PROCMODE_KNL, NULL, &tempiochan); if (sts != OZ_SUCCESS) { oz_knl_printk ("error %u assigning channel to %s\n", sts, argv[1]); return (0); } *(p ++) = ':'; memset (&fs_open, 0, sizeof fs_open); fs_open.name = p; fs_open.lockmode = OZ_LOCKMODE_CR; sts = oz_knl_io (tempiochan, OZ_IO_FS_OPEN, sizeof fs_open, &fs_open); if (sts != OZ_SUCCESS) { oz_knl_printk ("error %u opening file %s\n", sts, argv[1]); oz_knl_iochan_increfc (tempiochan, -1); return (0); } memset (&fs_getinfo1, 0, sizeof fs_getinfo1); sts = oz_knl_io (tempiochan, OZ_IO_FS_GETINFO1, sizeof fs_getinfo1, &fs_getinfo1); if ((sts != OZ_SUCCESS) && (sts != OZ_BADIOFUNC)) { oz_knl_printk ("error %u getting file %s size\n", sts, argv[1]); oz_knl_iochan_increfc (tempiochan, -1); return (0); } /* Get number of blocks and starting vbn */ count = oz_hw_atoi (argv[2], NULL); svbn = oz_hw_atoi (argv[3], NULL); p = OZ_KNL_NPPMALLOC (fs_getinfo1.blocksize); while (count > 0) { -- count; memset (&fs_readblocks, 0, sizeof fs_readblocks); fs_readblocks.size = fs_getinfo1.blocksize; fs_readblocks.buff = p; fs_readblocks.svbn = svbn ++; sts = oz_knl_io (tempiochan, OZ_IO_FS_READBLOCKS, sizeof fs_readblocks, &fs_readblocks); if (sts != OZ_SUCCESS) break; oz_knl_printk ("\nblock %u:\n", fs_readblocks.svbn); oz_knl_dumpmem (fs_readblocks.size, p); if (iochan == NULL) oz_knl_printkp ("block %u", fs_readblocks.svbn); if (ctrlcy_hit) break; } OZ_KNL_NPPFREE (p); oz_knl_iochan_increfc (tempiochan, -1); continue; } /* Process EXIT command */ if (strcasecmp (argv[0], "EXIT") == 0) return (1); /* Process EXTRA command */ if (strcasecmp (argv[0], "EXTRA") == 0) { int i, l; if (argc < 2) { oz_knl_printk ("EXTRA command requires at least 1 argument: EXTRA []\n"); return (0); } if (argc == 2) oz_ldr_extra (oz_knl_printk, argv[1], NULL); else { j = argc; for (i = 2; i < argc; i ++) j += strlen (argv[i]); p = OZ_KNL_NPPMALLOC (j); p[0] = 0; for (i = 2; i < argc;) { strcat (p, argv[i]); if (++ i < argc) strcat (p, " "); } i = oz_ldr_extra (oz_knl_printk, argv[1], p); OZ_KNL_NPPFREE (p); if (!i) return (0); } continue; } /* Process EXTRAS command */ if (strcasecmp (argv[0], "EXTRAS") == 0) { if (argc != 1) { oz_knl_printk ("EXTRAS command requires no arguments\n"); return (0); } oz_ldr_extras (oz_knl_printk, &ctrlcy_hit); continue; } /* Process GUNZIP/GZIP commands */ i = GZIP_FUNC_DUMMY; if (strcasecmp (argv[0], "GUNZIP") == 0) i = GZIP_FUNC_EXPAND; if (strcasecmp (argv[0], "GZIP") == 0) i = GZIP_FUNC_COMPRESS; if (i != GZIP_FUNC_DUMMY) { if (argc != 3) { oz_knl_printk ("GUNZIP/GZIP commands require two arguments, GUNZIP/GZIP \n"); return (0); } if (!dogzip (i, argv[1], argv[2])) return (0); continue; } /* Process HELP command */ if (strcasecmp (argv[0], "HELP") == 0) { oz_knl_printk ("\nCommands are:\n" " BARF - force access violation (ie, crash)\n" " BOOTSCAN - scan for boot device\n" " COPY - copy file or directory\n" " DELETE - delete file or directory\n" " DEVICES [-FULL] - list out devices\n" " DIR - list out directory\n" " DISMOUNT - dismount filesystem device\n" " DUMP - dump a file\n" " EXIT - continue boot process\n" " EXTRA - set extra name's value\n" " EXTRAS - list out all extras\n" " GUNZIP - GNU-unzip a file\n" " GZIP - GNU-zip a file\n" " HELP - print help message\n" " INIT