From a5ffe9661782d312309f1c3e6b830030876d4109 Mon Sep 17 00:00:00 2001 From: okuji Date: Mon, 6 Jan 2003 00:01:35 +0000 Subject: [PATCH] 2003-01-06 Yoshinori K. Okuji * util/i386/pc/pupa-setup.c: Include pupa/machine/kernel.h. (setup): Configure the installed partition information and the dl prefix. * loader/i386/pc/chainloader.c (my_mod): New variable. (pupa_chainloader_unload): New function. (pupa_rescue_cmd_chainloader): Refer itself. (PUPA_MOD_INIT): Save its own module in MY_MOD. * kern/i386/pc/startup.S (install_partition): Removed. (version_string): Likewise. (config_file): Likewise. (pupa_install_dos_part): New variable. (pupa_install_bsd_part): Likewise. (pupa_prefix): Likewise. (pupa_chainloader_real_boot): Call pupa_dl_unload_all. * kern/i386/pc/init.c: Include pupa/machine/kernel.h, pupa/dl.h and pupa/misc.h. (make_install_device): New function. (pupa_machine_init): Set the dl prefix. * kern/rescue.c: Include pupa/rescue.h and pupa/dl.h. (buf): Renamed to ... (linebuf): ... this. (pupa_rescue_cmd_prefix): New function. (pupa_rescue_cmd_insmod): Likewise. (pupa_rescue_cmd_rmmod): Likewise. (pupa_rescue_cmd_lsmod): Likewise. (pupa_enter_rescue_mode): Register new commands: prefix, insmod, rmmod and lsmod. * kern/mm.c (pupa_memalign): If failed even after invalidating disk caches, unload unneeded modules and retry. * kern/misc.c (pupa_memmove): New function. (pupa_memcpy): Removed. (pupa_strcpy): New function. (pupa_itoa): Made static. * kern/dl.c (pupa_dl_iterate): New function. (pupa_dl_ref): Likewise. (pupa_dl_unref): Likewise. (pupa_dl_unload): Return if succeeded or not. (pupa_dl_unload_unneeded): New function. (pupa_dl_unload_all): Likewise. (pupa_dl_init): Renamed to ... (pupa_dl_set_prefix): ... this. (pupa_dl_get_prefix): New function. * include/pupa/i386/pc/kernel.h: Include pupa/types.h. (PUPA_KERNEL_MACHINE_INSTALL_DOS_PART): New macro. (PUPA_KERNEL_MACHINE_INSTALL_BSD_PART): Likewise. (PUPA_KERNEL_MACHINE_PREFIX): Likewise. (pupa_install_dos_part): Declared. (pupa_install_bsd_part): Likewise. (pupa_prefix): Likewise. (pupa_boot_drive): Likewise. * include/pupa/types.h: Fix a typo. * include/pupa/misc.h (pupa_memcpy): New macro. Just an alias to pupa_memmove. (pupa_memmove): Declared. (pupa_strcpy): Likewise. * include/pupa/dl.h (PUPA_MOD_INIT): Change the prototype. Now pupa_mod_init takes one argument, its own module. (pupa_dl_unload_unneeded): Declared. (pupa_dl_unload_all): Likewise. (pupa_dl_ref): Likewise. (pupa_dl_unref): Likewise. (pupa_dl_iterate): Likewise. (pupa_dl_init): Renamed to ... (pupa_dl_set_prefix): ... this. (pupa_dl_get_prefix): Declared. * fs/fat.c [!PUPA_UTIL] (my_mod): New variable. (pupa_fat_dir) [!PUPA_UTIL]: Prevent the fat module from being unloaded. (pupa_fat_open) [!PUPA_UTIL]: Refer itself if succeeded. (pupa_fat_close) [!PUPA_UTIL]: Unrefer itself. * configure.ac (tmp_CFLAGS): Added -Wshadow, -Wpointer-arith, -Wmissing-prototypes, -Wundef and -Wstrict-prototypes. --- ChangeLog | 88 ++++++++++++++++++++++++++ NEWS | 4 ++ configure | 3 +- configure.ac | 3 +- fs/fat.c | 63 ++++++++++++++---- include/grub/dl.h | 16 +++-- include/grub/i386/pc/kernel.h | 24 +++++++ include/grub/misc.h | 6 +- include/grub/types.h | 2 +- kern/dl.c | 96 ++++++++++++++++++++++++---- kern/i386/pc/init.c | 28 ++++++++ kern/i386/pc/startup.S | 27 ++++---- kern/misc.c | 58 +++++++++++++---- kern/mm.c | 21 ++++-- kern/rescue.c | 116 ++++++++++++++++++++++++++++++++-- loader/i386/pc/chainloader.c | 35 +++++++--- util/i386/pc/grub-setup.c | 42 +++++++++++- 17 files changed, 553 insertions(+), 79 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2b4e8264f..dd835ed2e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,91 @@ +2003-01-06 Yoshinori K. Okuji + + * util/i386/pc/pupa-setup.c: Include pupa/machine/kernel.h. + (setup): Configure the installed partition information and the + dl prefix. + + * loader/i386/pc/chainloader.c (my_mod): New variable. + (pupa_chainloader_unload): New function. + (pupa_rescue_cmd_chainloader): Refer itself. + (PUPA_MOD_INIT): Save its own module in MY_MOD. + + * kern/i386/pc/startup.S (install_partition): Removed. + (version_string): Likewise. + (config_file): Likewise. + (pupa_install_dos_part): New variable. + (pupa_install_bsd_part): Likewise. + (pupa_prefix): Likewise. + (pupa_chainloader_real_boot): Call pupa_dl_unload_all. + + * kern/i386/pc/init.c: Include pupa/machine/kernel.h, pupa/dl.h + and pupa/misc.h. + (make_install_device): New function. + (pupa_machine_init): Set the dl prefix. + + * kern/rescue.c: Include pupa/rescue.h and pupa/dl.h. + (buf): Renamed to ... + (linebuf): ... this. + (pupa_rescue_cmd_prefix): New function. + (pupa_rescue_cmd_insmod): Likewise. + (pupa_rescue_cmd_rmmod): Likewise. + (pupa_rescue_cmd_lsmod): Likewise. + (pupa_enter_rescue_mode): Register new commands: prefix, insmod, + rmmod and lsmod. + + * kern/mm.c (pupa_memalign): If failed even after invalidating + disk caches, unload unneeded modules and retry. + + * kern/misc.c (pupa_memmove): New function. + (pupa_memcpy): Removed. + (pupa_strcpy): New function. + (pupa_itoa): Made static. + + * kern/dl.c (pupa_dl_iterate): New function. + (pupa_dl_ref): Likewise. + (pupa_dl_unref): Likewise. + (pupa_dl_unload): Return if succeeded or not. + (pupa_dl_unload_unneeded): New function. + (pupa_dl_unload_all): Likewise. + (pupa_dl_init): Renamed to ... + (pupa_dl_set_prefix): ... this. + (pupa_dl_get_prefix): New function. + + * include/pupa/i386/pc/kernel.h: Include pupa/types.h. + (PUPA_KERNEL_MACHINE_INSTALL_DOS_PART): New macro. + (PUPA_KERNEL_MACHINE_INSTALL_BSD_PART): Likewise. + (PUPA_KERNEL_MACHINE_PREFIX): Likewise. + (pupa_install_dos_part): Declared. + (pupa_install_bsd_part): Likewise. + (pupa_prefix): Likewise. + (pupa_boot_drive): Likewise. + + * include/pupa/types.h: Fix a typo. + + * include/pupa/misc.h (pupa_memcpy): New macro. Just an alias to + pupa_memmove. + (pupa_memmove): Declared. + (pupa_strcpy): Likewise. + + * include/pupa/dl.h (PUPA_MOD_INIT): Change the prototype. Now + pupa_mod_init takes one argument, its own module. + (pupa_dl_unload_unneeded): Declared. + (pupa_dl_unload_all): Likewise. + (pupa_dl_ref): Likewise. + (pupa_dl_unref): Likewise. + (pupa_dl_iterate): Likewise. + (pupa_dl_init): Renamed to ... + (pupa_dl_set_prefix): ... this. + (pupa_dl_get_prefix): Declared. + + * fs/fat.c [!PUPA_UTIL] (my_mod): New variable. + (pupa_fat_dir) [!PUPA_UTIL]: Prevent the fat module from being + unloaded. + (pupa_fat_open) [!PUPA_UTIL]: Refer itself if succeeded. + (pupa_fat_close) [!PUPA_UTIL]: Unrefer itself. + + * configure.ac (tmp_CFLAGS): Added -Wshadow, -Wpointer-arith, + -Wmissing-prototypes, -Wundef and -Wstrict-prototypes. + 2003-01-03 Yoshinori K. Okuji * util/i386/pc/pupa-setup.c (setup): Define the internal diff --git a/NEWS b/NEWS index 3944a66f0..ad72cbd42 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,10 @@ New in 0.7: * New utility, ``pupa-setup''. This sets up PUPA to make it bootable from a real disk. +* New commands, "prefix", "insmod", "rmmod" and "lsmod" are added into + the rescue mode to manipulate PUPA modules. + + New in 0.6 - 2002-12-27, Yoshinori K. Okuji: * The chainloader and the FAT filesystem are modularized. diff --git a/configure b/configure index 9c619bbc8..51c69c0fd 100644 --- a/configure +++ b/configure @@ -2069,7 +2069,8 @@ echo "$as_me: error: GCC is required" >&2;} if test "x$default_CFLAGS" = xyes; then # debug flags. - tmp_CFLAGS="-Wall -W -g" + tmp_CFLAGS="-Wall -W -Wshadow -Wpointer-arith -Wmissing-prototypes \ + -Wundef -Wstrict-prototypes -g" # optimization flags. echo "$as_me:$LINENO: checking whether optimization for size works" >&5 diff --git a/configure.ac b/configure.ac index 6e63db47c..c26fe4e94 100644 --- a/configure.ac +++ b/configure.ac @@ -45,7 +45,8 @@ test "x$GCC" = xyes || AC_MSG_ERROR([GCC is required]) if test "x$default_CFLAGS" = xyes; then # debug flags. - tmp_CFLAGS="-Wall -W -g" + tmp_CFLAGS="-Wall -W -Wshadow -Wpointer-arith -Wmissing-prototypes \ + -Wundef -Wstrict-prototypes -g" # optimization flags. AC_CACHE_CHECK([whether optimization for size works], size_flag, [ diff --git a/fs/fat.c b/fs/fat.c index 045c04b6c..49b89f5b5 100644 --- a/fs/fat.c +++ b/fs/fat.c @@ -126,6 +126,10 @@ struct pupa_fat_data pupa_uint32_t cur_cluster; }; +#ifndef PUPA_UTIL +static pupa_dl_t my_mod; +#endif + static int log2 (unsigned x) { @@ -675,13 +679,17 @@ static pupa_err_t pupa_fat_dir (pupa_device_t device, const char *path, int (*hook) (const char *filename, int dir)) { - struct pupa_fat_data *data; + struct pupa_fat_data *data = 0; pupa_disk_t disk = device->disk; char *p = (char *) path; + +#ifndef PUPA_UTIL + pupa_dl_ref (my_mod); +#endif data = pupa_fat_mount (disk); if (! data) - return pupa_errno; + goto fail; do { @@ -689,19 +697,30 @@ pupa_fat_dir (pupa_device_t device, const char *path, } while (p && pupa_errno == PUPA_ERR_NONE); + fail: + pupa_free (data); + +#ifndef PUPA_UTIL + pupa_dl_unref (my_mod); +#endif + return pupa_errno; } static pupa_err_t pupa_fat_open (pupa_file_t file, const char *name) { - struct pupa_fat_data *data; + struct pupa_fat_data *data = 0; char *p = (char *) name; + +#ifndef PUPA_UTIL + pupa_dl_ref (my_mod); +#endif data = pupa_fat_mount (file->device->disk); if (! data) - return pupa_errno; + goto fail; do { @@ -723,7 +742,13 @@ pupa_fat_open (pupa_file_t file, const char *name) return PUPA_ERR_NONE; fail: + pupa_free (data); + +#ifndef PUPA_UTIL + pupa_dl_unref (my_mod); +#endif + return pupa_errno; } @@ -738,6 +763,11 @@ static pupa_err_t pupa_fat_close (pupa_file_t file) { pupa_free (file->data); + +#ifndef PUPA_UTIL + pupa_dl_unref (my_mod); +#endif + return pupa_errno; } @@ -752,19 +782,26 @@ static struct pupa_fs pupa_fat_fs = }; #ifdef PUPA_UTIL -void pupa_fat_init (void) -#else -PUPA_MOD_INIT -#endif +void +pupa_fat_init (void) { pupa_fs_register (&pupa_fat_fs); } -#ifdef PUPA_UTIL -void pupa_fat_fini (void) -#else -PUPA_MOD_FINI -#endif +void +pupa_fat_fini (void) { pupa_fs_unregister (&pupa_fat_fs); } +#else /* ! PUPA_UTIL */ +PUPA_MOD_INIT +{ + pupa_fs_register (&pupa_fat_fs); + my_mod = mod; +} + +PUPA_MOD_FINI +{ + pupa_fs_unregister (&pupa_fat_fs); +} +#endif /* ! PUPA_UTIL */ diff --git a/include/grub/dl.h b/include/grub/dl.h index 2763497ed..954160180 100644 --- a/include/grub/dl.h +++ b/include/grub/dl.h @@ -26,9 +26,9 @@ #include #define PUPA_MOD_INIT \ -static void pupa_mod_init (void) __attribute__ ((unused)); \ +static void pupa_mod_init (pupa_dl_t mod) __attribute__ ((unused)); \ static void \ -pupa_mod_init (void) +pupa_mod_init (pupa_dl_t mod) #define PUPA_MOD_FINI \ static void pupa_mod_fini (void) __attribute__ ((unused)); \ @@ -65,7 +65,7 @@ struct pupa_dl int ref_count; pupa_dl_dep_t dep; pupa_dl_segment_t segment; - void (*init) (void); + void (*init) (struct pupa_dl *mod); void (*fini) (void); }; typedef struct pupa_dl *pupa_dl_t; @@ -73,12 +73,18 @@ typedef struct pupa_dl *pupa_dl_t; pupa_dl_t EXPORT_FUNC(pupa_dl_load_file) (const char *filename); pupa_dl_t EXPORT_FUNC(pupa_dl_load) (const char *name); pupa_dl_t pupa_dl_load_core (void *addr, pupa_size_t size); -void EXPORT_FUNC(pupa_dl_unload) (pupa_dl_t mod); +int EXPORT_FUNC(pupa_dl_unload) (pupa_dl_t mod); +void pupa_dl_unload_unneeded (void); +void pupa_dl_unload_all (void); +int EXPORT_FUNC(pupa_dl_ref) (pupa_dl_t mod); +int EXPORT_FUNC(pupa_dl_unref) (pupa_dl_t mod); +void EXPORT_FUNC(pupa_dl_iterate) (int (*hook) (pupa_dl_t mod)); pupa_dl_t EXPORT_FUNC(pupa_dl_get) (const char *name); pupa_err_t EXPORT_FUNC(pupa_dl_register_symbol) (const char *name, void *addr, pupa_dl_t mod); void *EXPORT_FUNC(pupa_dl_resolve_symbol) (const char *name); -void pupa_dl_init (const char *dir); +void pupa_dl_set_prefix (const char *dir); +const char *pupa_dl_get_prefix (void); int pupa_arch_dl_check_header (void *ehdr, pupa_size_t size); pupa_err_t pupa_arch_dl_relocate_symbols (pupa_dl_t mod, void *ehdr); diff --git a/include/grub/i386/pc/kernel.h b/include/grub/i386/pc/kernel.h index d6928d3c7..e7a785a05 100644 --- a/include/grub/i386/pc/kernel.h +++ b/include/grub/i386/pc/kernel.h @@ -20,10 +20,34 @@ #ifndef KERNEL_MACHINE_HEADER #define KERNEL_MACHINE_HEADER 1 +#include + /* The offset of PUPA_TOTAL_MODULE_SIZE. */ #define PUPA_KERNEL_MACHINE_TOTAL_MODULE_SIZE 0x8 /* The offset of PUPA_KERNEL_IMAGE_SIZE. */ #define PUPA_KERNEL_MACHINE_KERNEL_IMAGE_SIZE 0xc +/* The offset of PUPA_INSTALL_DOS_PART. */ +#define PUPA_KERNEL_MACHINE_INSTALL_DOS_PART 0x10 + +/* The offset of PUPA_INSTALL_BSD_PART. */ +#define PUPA_KERNEL_MACHINE_INSTALL_BSD_PART 0x14 + +/* The offset of PUPA_PREFIX. */ +#define PUPA_KERNEL_MACHINE_PREFIX 0x18 + +/* The DOS partition number of the installed partition. */ +extern pupa_int32_t pupa_install_dos_part; + +/* The BSD partition number of the installed partition. */ +extern pupa_int32_t pupa_install_bsd_part; + +/* The prefix which points to the directory where PUPA modules and its + configuration file are located. */ +extern char pupa_prefix[]; + +/* The boot BIOS drive number. */ +extern pupa_int32_t pupa_boot_drive; + #endif /* ! KERNEL_MACHINE_HEADER */ diff --git a/include/grub/misc.h b/include/grub/misc.h index fa2832245..a5c6835b8 100644 --- a/include/grub/misc.h +++ b/include/grub/misc.h @@ -25,7 +25,11 @@ #include #include -void *EXPORT_FUNC(pupa_memcpy) (void *dest, const void *src, pupa_size_t n); +/* XXX: If pupa_memmove is too slow, we must implement pupa_memcpy. */ +#define pupa_memcpy(d,s,n) pupa_memmove ((d), (s), (n)) + +void *EXPORT_FUNC(pupa_memmove) (void *dest, const void *src, pupa_size_t n); +char *EXPORT_FUNC(pupa_strcpy) (char *dest, const char *src); int EXPORT_FUNC(pupa_memcmp) (const void *s1, const void *s2, pupa_size_t n); int EXPORT_FUNC(pupa_strcmp) (const char *s1, const char *s2); char *EXPORT_FUNC(pupa_strchr) (const char *s, int c); diff --git a/include/grub/types.h b/include/grub/types.h index 0dda38486..b2d4482d0 100644 --- a/include/grub/types.h +++ b/include/grub/types.h @@ -69,7 +69,7 @@ typedef unsigned long long pupa_uint64_t; #endif /* Misc types. */ -#if PUPA_HOST_SIZE_OF_VOID_P == 8 +#if PUPA_HOST_SIZEOF_VOID_P == 8 typedef pupa_uint64_t pupa_addr_t; typedef pupa_uint64_t pupa_off_t; typedef pupa_uint64_t pupa_size_t; diff --git a/kern/dl.c b/kern/dl.c index c22c98403..8bf0cdeba 100644 --- a/kern/dl.c +++ b/kern/dl.c @@ -109,6 +109,16 @@ pupa_dl_get (const char *name) return 0; } +void +pupa_dl_iterate (int (*hook) (pupa_dl_t mod)) +{ + pupa_dl_list_t l; + + for (l = pupa_dl_head; l; l = l->next) + if (hook (l->mod)) + break; +} + struct pupa_symbol @@ -345,9 +355,9 @@ pupa_dl_resolve_symbols (pupa_dl_t mod, Elf_Ehdr *e) return pupa_errno; if (pupa_strcmp (name, "pupa_mod_init") == 0) - mod->init = (void (*) ()) sym->st_value; + mod->init = (void (*) (pupa_dl_t)) sym->st_value; else if (pupa_strcmp (name, "pupa_mod_fini") == 0) - mod->fini = (void (*) ()) sym->st_value; + mod->fini = (void (*) (void)) sym->st_value; break; case STT_SECTION: @@ -372,7 +382,7 @@ static void pupa_dl_call_init (pupa_dl_t mod) { if (mod->init) - (mod->init) (); + (mod->init) (mod); } static pupa_err_t @@ -428,6 +438,8 @@ pupa_dl_resolve_dependencies (pupa_dl_t mod, Elf_Ehdr *e) m = pupa_dl_load (name); if (! m) return pupa_errno; + + pupa_dl_ref (m); dep = (pupa_dl_dep_t) pupa_malloc (sizeof (*dep)); if (! dep) @@ -444,6 +456,24 @@ pupa_dl_resolve_dependencies (pupa_dl_t mod, Elf_Ehdr *e) return PUPA_ERR_NONE; } +int +pupa_dl_ref (pupa_dl_t mod) +{ + return ++mod->ref_count; +} + +int +pupa_dl_unref (pupa_dl_t mod) +{ + int ret; + + ret = --mod->ref_count; + if (ret <= 0) + pupa_dl_unload (mod); + + return ret; +} + /* Load a module from core memory. */ pupa_dl_t pupa_dl_load_core (void *addr, pupa_size_t size) @@ -513,6 +543,7 @@ pupa_dl_load_file (const char *filename) goto failed; mod = pupa_dl_load_core (core, size); + mod->ref_count = 0; failed: pupa_file_close (file); @@ -532,10 +563,7 @@ pupa_dl_load (const char *name) mod = pupa_dl_get (name); if (mod) - { - mod->ref_count++; - return mod; - } + return mod; if (! pupa_dl_dir) pupa_fatal ("module dir is not initialized yet"); @@ -559,14 +587,14 @@ pupa_dl_load (const char *name) } /* Unload the module MOD. */ -void +int pupa_dl_unload (pupa_dl_t mod) { pupa_dl_dep_t dep, depn; pupa_dl_segment_t seg, segn; - if (--mod->ref_count > 0) - return; + if (mod->ref_count > 0) + return 0; if (mod->fini) (mod->fini) (); @@ -577,7 +605,7 @@ pupa_dl_unload (pupa_dl_t mod) for (dep = mod->dep; dep; dep = depn) { depn = dep->next; - pupa_dl_unload (dep->mod); + pupa_dl_unref (dep->mod); pupa_free (dep); } @@ -590,10 +618,54 @@ pupa_dl_unload (pupa_dl_t mod) pupa_free (mod->name); pupa_free (mod); + return 1; +} + +/* Unload unneeded modules. */ +void +pupa_dl_unload_unneeded (void) +{ + /* Because pupa_dl_remove modifies the list of modules, this + implementation is tricky. */ + pupa_dl_list_t p = pupa_dl_head; + + while (p) + { + if (pupa_dl_unload (p->mod)) + { + p = pupa_dl_head; + continue; + } + + p = p->next; + } +} + +/* Unload all modules. */ +void +pupa_dl_unload_all (void) +{ + while (pupa_dl_head) + { + pupa_dl_list_t p; + + pupa_dl_unload_unneeded (); + + /* Force to decrement the ref count. This will purge pre-loaded + modules and manually inserted modules. */ + for (p = pupa_dl_head; p; p = p->next) + p->mod->ref_count--; + } } void -pupa_dl_init (const char *dir) +pupa_dl_set_prefix (const char *dir) { pupa_dl_dir = (char *) dir; } + +const char * +pupa_dl_get_prefix (void) +{ + return pupa_dl_dir; +} diff --git a/kern/i386/pc/init.c b/kern/i386/pc/init.c index 012ec99a4..604cc29b2 100644 --- a/kern/i386/pc/init.c +++ b/kern/i386/pc/init.c @@ -23,8 +23,33 @@ #include #include #include +#include #include #include +#include +#include + +static char * +make_install_device (void) +{ + /* XXX: This should be enough. */ + char dev[100]; + + pupa_sprintf (dev, "(%cd%u", + (pupa_boot_drive & 0x80) ? 'h' : 'f', + pupa_boot_drive & 0x7f); + + if (pupa_install_dos_part >= 0) + pupa_sprintf (dev + pupa_strlen (dev), ",%u", pupa_install_dos_part); + + if (pupa_install_bsd_part >= 0) + pupa_sprintf (dev + pupa_strlen (dev), ",%c", pupa_install_bsd_part + 'a'); + + pupa_sprintf (dev + pupa_strlen (dev), ")%s", pupa_prefix); + pupa_strcpy (pupa_prefix, dev); + + return pupa_prefix; +} void pupa_machine_init (void) @@ -112,4 +137,7 @@ pupa_machine_init (void) /* The memory system was initialized, thus register built-in devices. */ pupa_biosdisk_init (); + + /* Initialize the prefix. */ + pupa_dl_set_prefix (make_install_device ()); } diff --git a/kern/i386/pc/startup.S b/kern/i386/pc/startup.S index 0fdc65681..a1f12cf23 100644 --- a/kern/i386/pc/startup.S +++ b/kern/i386/pc/startup.S @@ -87,18 +87,18 @@ VARIABLE(pupa_total_module_size) .long 0 VARIABLE(pupa_kernel_image_size) .long 0 -VARIABLE(install_partition) - .long 0xFFFFFF -VARIABLE(version_string) - .string PACKAGE_VERSION -VARIABLE(config_file) - .string "/boot/pupa/puparc" +VARIABLE(pupa_install_dos_part) + .long 0xFFFFFFFF +VARIABLE(pupa_install_bsd_part) + .long 0xFFFFFFFF +VARIABLE(pupa_prefix) + .string "/boot/pupa" /* - * Leave some breathing room for the config file name. + * Leave some breathing room for the prefix. */ - . = EXT_C(start) + 0x70 + . = EXT_C(start) + 0x50 /* the real mode code continues... */ codestart: @@ -261,13 +261,16 @@ FUNCTION(pupa_halt) */ FUNCTION(pupa_chainloader_real_boot) - /* no need to save anything */ + pushl %edx + pushl %eax - /* ESI must point to a partition table entry */ - movl %edx, %esi + call EXT_C(pupa_dl_unload_all) /* set up to pass boot drive */ - movl %eax, %edx + popl %edx + + /* ESI must point to a partition table entry */ + popl %esi /* Turn off Gate A20 */ xorl %eax, %eax diff --git a/kern/misc.c b/kern/misc.c index 3ddd3aada..b765948f5 100644 --- a/kern/misc.c +++ b/kern/misc.c @@ -26,17 +26,53 @@ #include void * -pupa_memcpy (void *dest, const void *src, pupa_size_t n) +pupa_memmove (void *dest, const void *src, pupa_size_t n) { char *d = (char *) dest; - char *s = (char *) src; - - while (n--) - *d++ = *s++; + const char *s = (const char *) src; + + if (d < s) + while (n--) + *d++ = *s++; + else + { + d += n; + s += n; + + while (n--) + *--d = *--s; + } return dest; } +char * +pupa_strcpy (char *dest, const char *src) +{ + char *p = dest; + + while ((*p++ = *src++) != '\0') + ; + + return dest; +} + +#if 0 +char * +pupa_strcat (char *dest, const char *src) +{ + char *p = dest; + + while (*p) + p++; + + while ((*p++ = *src++) != '\0') + ; + + return dest; +} +#endif + int pupa_printf (const char *fmt, ...) { @@ -237,7 +273,7 @@ pupa_memset (void *s, int c, pupa_size_t n) pupa_size_t pupa_strlen (const char *s) { - char *p = (char *) s; + const char *p = s; while (*p) p++; @@ -262,7 +298,7 @@ pupa_reverse (char *str) } } -char * +static char * pupa_itoa (char *str, int c, unsigned n) { unsigned base = (c == 'x') ? 16 : 10; @@ -292,15 +328,15 @@ pupa_vsprintf (char *str, const char *fmt, va_list args) { char c; int count = 0; - auto void write_char (char c); + auto void write_char (char ch); auto void write_str (const char *s); - void write_char (char c) + void write_char (char ch) { if (str) - *str++ = c; + *str++ = ch; else - pupa_putchar (c); + pupa_putchar (ch); count++; } diff --git a/kern/mm.c b/kern/mm.c index 9b888b62b..5f8e6c9fe 100644 --- a/kern/mm.c +++ b/kern/mm.c @@ -195,7 +195,7 @@ pupa_memalign (pupa_size_t align, pupa_size_t size) { pupa_mm_region_t r; pupa_size_t n = ((size + PUPA_MM_ALIGN - 1) >> PUPA_MM_ALIGN_LOG2) + 1; - int first = 1; + int count = 0; align = (align >> PUPA_MM_ALIGN_LOG2); if (align == 0) @@ -212,14 +212,25 @@ pupa_memalign (pupa_size_t align, pupa_size_t size) return p; } - /* If failed, invalidate disk caches to increase free memory. */ - if (first) + /* If failed, increase free memory somehow. */ + switch (count) { + case 0: + /* Invalidate disk caches. */ pupa_disk_cache_invalidate_all (); - first = 0; + count++; + goto again; + + case 1: + /* Unload unneeded modules. */ + pupa_dl_unload_unneeded (); + count++; goto again; - } + default: + break; + } + pupa_error (PUPA_ERR_OUT_OF_MEMORY, "out of memory"); return 0; } diff --git a/kern/rescue.c b/kern/rescue.c index 29aecb8a7..abec35034 100644 --- a/kern/rescue.c +++ b/kern/rescue.c @@ -19,6 +19,7 @@ */ #include +#include #include #include #include @@ -26,6 +27,7 @@ #include #include #include +#include #include #define PUPA_RESCUE_BUF_SIZE 256 @@ -40,7 +42,7 @@ struct pupa_rescue_command }; typedef struct pupa_rescue_command *pupa_rescue_command_t; -static char buf[PUPA_RESCUE_BUF_SIZE]; +static char linebuf[PUPA_RESCUE_BUF_SIZE]; static pupa_rescue_command_t pupa_rescue_command_list; @@ -85,7 +87,7 @@ pupa_rescue_get_command_line (const char *prompt) int pos = 0; pupa_printf (prompt); - pupa_memset (buf, 0, PUPA_RESCUE_BUF_SIZE); + pupa_memset (linebuf, 0, PUPA_RESCUE_BUF_SIZE); while ((c = PUPA_TERM_ASCII_CHAR (pupa_getkey ())) != '\n' && c != '\r') { @@ -93,7 +95,7 @@ pupa_rescue_get_command_line (const char *prompt) { if (pos < PUPA_RESCUE_BUF_SIZE - 1) { - buf[pos++] = c; + linebuf[pos++] = c; pupa_putchar (c); } } @@ -101,7 +103,7 @@ pupa_rescue_get_command_line (const char *prompt) { if (pos > 0) { - buf[--pos] = 0; + linebuf[--pos] = 0; pupa_putchar (c); pupa_putchar (' '); pupa_putchar (c); @@ -475,6 +477,7 @@ pupa_rescue_cmd_testload (int argc, char *argv[]) } #endif +/* dump ADDRESS [SIZE] */ static void pupa_rescue_cmd_dump (int argc, char *argv[]) { @@ -501,6 +504,99 @@ pupa_rescue_cmd_dump (int argc, char *argv[]) } } +/* prefix [DIR] */ +static void +pupa_rescue_cmd_prefix (int argc, char *argv[]) +{ + static char prefix[100]; + + if (argc == 0) + pupa_printf ("%s\n", pupa_dl_get_prefix ()); + else + { + if (pupa_strlen (argv[0]) >= sizeof (prefix)) + { + pupa_error (PUPA_ERR_BAD_ARGUMENT, "too long prefix"); + return; + } + + pupa_strcpy (prefix, argv[0]); + pupa_dl_set_prefix (prefix); + } +} + +/* insmod MODULE */ +static void +pupa_rescue_cmd_insmod (int argc, char *argv[]) +{ + char *p; + pupa_dl_t mod; + + if (argc == 0) + { + pupa_error (PUPA_ERR_BAD_ARGUMENT, "no module specified"); + return; + } + + p = pupa_strchr (argv[0], '/'); + if (! p) + mod = pupa_dl_load (argv[0]); + else + mod = pupa_dl_load_file (argv[0]); + + if (mod) + pupa_dl_ref (mod); +} + +/* rmmod MODULE */ +static void +pupa_rescue_cmd_rmmod (int argc, char *argv[]) +{ + pupa_dl_t mod; + + if (argc == 0) + { + pupa_error (PUPA_ERR_BAD_ARGUMENT, "no module specified"); + return; + } + + mod = pupa_dl_get (argv[0]); + if (! mod) + { + pupa_error (PUPA_ERR_BAD_ARGUMENT, "no such module"); + return; + } + + pupa_dl_unref (mod); +} + +/* lsmod */ +static void +pupa_rescue_cmd_lsmod (int argc __attribute__ ((unused)), + char *argv[] __attribute__ ((unused))) +{ + auto int print_module (pupa_dl_t mod); + + int print_module (pupa_dl_t mod) + { + pupa_dl_dep_t dep; + + pupa_printf ("%s\t%d\t\t", mod->name, mod->ref_count); + for (dep = mod->dep; dep; dep = dep->next) + { + if (dep != mod->dep) + pupa_putchar (','); + + pupa_printf ("%s", dep->mod->name); + } + pupa_putchar ('\n'); + return 0; + } + + pupa_printf ("Name\tRef Count\tDependencies\n"); + pupa_dl_iterate (print_module); +} + /* Enter the rescue mode. */ void pupa_enter_rescue_mode (void) @@ -518,13 +614,21 @@ pupa_enter_rescue_mode (void) pupa_rescue_register_command ("module", pupa_rescue_cmd_module, "load an OS module"); pupa_rescue_register_command ("root", pupa_rescue_cmd_root, - "set a root device"); + "set the root device"); pupa_rescue_register_command ("dump", pupa_rescue_cmd_dump, "dump memory"); + pupa_rescue_register_command ("prefix", pupa_rescue_cmd_prefix, + "set the prefix"); + pupa_rescue_register_command ("insmod", pupa_rescue_cmd_insmod, + "insert a module"); + pupa_rescue_register_command ("rmmod", pupa_rescue_cmd_rmmod, + "remove a module"); + pupa_rescue_register_command ("lsmod", pupa_rescue_cmd_lsmod, + "show loaded modules"); while (1) { - char *line = buf; + char *line = linebuf; char *name; int n; pupa_rescue_command_t cmd; diff --git a/loader/i386/pc/chainloader.c b/loader/i386/pc/chainloader.c index 911f795d9..cfcc88dbb 100644 --- a/loader/i386/pc/chainloader.c +++ b/loader/i386/pc/chainloader.c @@ -35,6 +35,8 @@ /* Allocate space statically, because this is very small anyway. */ static char pupa_chainloader_boot_sector[PUPA_DISK_SECTOR_SIZE]; +static pupa_dl_t my_mod; + static pupa_err_t pupa_chainloader_boot (void) { @@ -75,13 +77,21 @@ pupa_chainloader_boot (void) return PUPA_ERR_NONE; } +static pupa_err_t +pupa_chainloader_unload (void) +{ + pupa_dl_unref (my_mod); +} + static void pupa_rescue_cmd_chainloader (int argc, char *argv[]) { - pupa_file_t file; + pupa_file_t file = 0; pupa_uint16_t signature; int force = 0; + pupa_dl_ref (my_mod); + if (argc > 0 && pupa_strcmp (argv[0], "--force") == 0) { force = 1; @@ -92,12 +102,12 @@ pupa_rescue_cmd_chainloader (int argc, char *argv[]) if (argc == 0) { pupa_error (PUPA_ERR_BAD_ARGUMENT, "no file specified"); - return; + goto fail; } file = pupa_file_open (argv[0]); if (! file) - return; + goto fail; /* Read the first block. */ if (pupa_file_read (file, pupa_chainloader_boot_sector, @@ -106,20 +116,28 @@ pupa_rescue_cmd_chainloader (int argc, char *argv[]) if (pupa_errno == PUPA_ERR_NONE) pupa_error (PUPA_ERR_BAD_OS, "too small"); - pupa_file_close (file); - return; + goto fail; } /* Check the signature. */ signature = *((pupa_uint16_t *) (pupa_chainloader_boot_sector + PUPA_DISK_SECTOR_SIZE - 2)); if (signature != pupa_le_to_cpu16 (0xaa55) && ! force) - pupa_error (PUPA_ERR_BAD_OS, "invalid signature"); + { + pupa_error (PUPA_ERR_BAD_OS, "invalid signature"); + goto fail; + } pupa_file_close (file); + pupa_loader_set (0, pupa_chainloader_boot, pupa_chainloader_unload); + return; + + fail: - if (pupa_errno == PUPA_ERR_NONE) - pupa_loader_set (0, pupa_chainloader_boot, 0); + if (file) + pupa_file_close (file); + + pupa_dl_unref (my_mod); } static const char loader_name[] = "chainloader"; @@ -129,6 +147,7 @@ PUPA_MOD_INIT pupa_rescue_register_command (loader_name, pupa_rescue_cmd_chainloader, "load another boot loader"); + my_mod = mod; } PUPA_MOD_FINI diff --git a/util/i386/pc/grub-setup.c b/util/i386/pc/grub-setup.c index b4b123c44..cada26e0f 100644 --- a/util/i386/pc/grub-setup.c +++ b/util/i386/pc/grub-setup.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -74,6 +75,8 @@ setup (const char *prefix, const char *dir, pupa_uint8_t *boot_drive; pupa_uint32_t *kernel_sector; struct boot_blocklist *first_block, *block; + pupa_int32_t *install_dos_part, *install_bsd_part; + char *install_prefix; char *tmp_img; int i; unsigned long first_sector; @@ -172,7 +175,14 @@ setup (const char *prefix, const char *dir, first_block = (struct boot_blocklist *) (core_img + PUPA_DISK_SECTOR_SIZE - sizeof (*block)); - + + install_dos_part = (pupa_int32_t *) (core_img + PUPA_DISK_SECTOR_SIZE + + PUPA_KERNEL_MACHINE_INSTALL_DOS_PART); + install_bsd_part = (pupa_int32_t *) (core_img + PUPA_DISK_SECTOR_SIZE + + PUPA_KERNEL_MACHINE_INSTALL_BSD_PART); + install_prefix = (core_img + PUPA_DISK_SECTOR_SIZE + + PUPA_KERNEL_MACHINE_PREFIX); + /* Open the root device and the destination device. */ root_dev = pupa_device_open (root); if (! root_dev) @@ -227,6 +237,19 @@ setup (const char *prefix, const char *dir, block->start = 0; block->len = 0; block->segment = 0; + + /* Embed information about the installed location. */ + if (root_dev->disk->partition) + { + *install_dos_part + = pupa_cpu_to_le32 (root_dev->disk->partition->dos_part); + *install_bsd_part + = pupa_cpu_to_le32 (root_dev->disk->partition->bsd_part); + } + else + *install_dos_part = *install_bsd_part = pupa_cpu_to_le32 (-1); + + strcpy (install_prefix, prefix); /* Write the core image onto the disk. */ if (pupa_disk_write (dest_dev->disk, 1, 0, core_size, core_img)) @@ -363,14 +386,27 @@ setup (const char *prefix, const char *dir, else *boot_drive = 0xFF; - /* Write the first sector of the core image onto the disk. */ + /* Embed information about the installed location. */ + if (root_dev->disk->partition) + { + *install_dos_part + = pupa_cpu_to_le32 (root_dev->disk->partition->dos_part); + *install_bsd_part + = pupa_cpu_to_le32 (root_dev->disk->partition->bsd_part); + } + else + *install_dos_part = *install_bsd_part = pupa_cpu_to_le32 (-1); + + strcpy (install_prefix, prefix); + + /* Write the first two sectors of the core image onto the disk. */ core_path = pupa_util_get_path (dir, core_file); pupa_util_info ("opening the core image `%s'", core_path); fp = fopen (core_path, "r+b"); if (! fp) pupa_util_error ("Cannot open `%s'", core_path); - pupa_util_write_image (core_img, PUPA_DISK_SECTOR_SIZE, fp); + pupa_util_write_image (core_img, PUPA_DISK_SECTOR_SIZE * 2, fp); fclose (fp); free (core_path);