* 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-06 Yoshinori K. Okuji <okuji@enbug.org>
+
+ * 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 <okuji@enbug.org>
* util/i386/pc/pupa-setup.c (setup): Define the internal
* 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.
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
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, [
pupa_uint32_t cur_cluster;
};
+#ifndef PUPA_UTIL
+static pupa_dl_t my_mod;
+#endif
+
static int
log2 (unsigned x)
{
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
{
}
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
{
return PUPA_ERR_NONE;
fail:
+
pupa_free (data);
+
+#ifndef PUPA_UTIL
+ pupa_dl_unref (my_mod);
+#endif
+
return pupa_errno;
}
pupa_fat_close (pupa_file_t file)
{
pupa_free (file->data);
+
+#ifndef PUPA_UTIL
+ pupa_dl_unref (my_mod);
+#endif
+
return pupa_errno;
}
};
#ifdef PUPA_UTIL
-void pupa_fat_init (void)
-#else
+void
+pupa_fat_init (void)
+{
+ pupa_fs_register (&pupa_fat_fs);
+}
+
+void
+pupa_fat_fini (void)
+{
+ pupa_fs_unregister (&pupa_fat_fs);
+}
+#else /* ! PUPA_UTIL */
PUPA_MOD_INIT
-#endif
{
pupa_fs_register (&pupa_fat_fs);
+ my_mod = mod;
}
-#ifdef PUPA_UTIL
-void pupa_fat_fini (void)
-#else
PUPA_MOD_FINI
-#endif
{
pupa_fs_unregister (&pupa_fat_fs);
}
+#endif /* ! PUPA_UTIL */
#include <pupa/types.h>
#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)); \
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;
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);
#ifndef KERNEL_MACHINE_HEADER
#define KERNEL_MACHINE_HEADER 1
+#include <pupa/types.h>
+
/* 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 */
#include <pupa/types.h>
#include <pupa/symbol.h>
-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);
#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;
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;
+}
+
\f
struct pupa_symbol
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:
pupa_dl_call_init (pupa_dl_t mod)
{
if (mod->init)
- (mod->init) ();
+ (mod->init) (mod);
}
static pupa_err_t
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)
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)
goto failed;
mod = pupa_dl_load_core (core, size);
+ mod->ref_count = 0;
failed:
pupa_file_close (file);
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");
}
/* 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) ();
for (dep = mod->dep; dep; dep = depn)
{
depn = dep->next;
- pupa_dl_unload (dep->mod);
+ pupa_dl_unref (dep->mod);
pupa_free (dep);
}
pupa_free (mod->name);
pupa_free (mod);
+ return 1;
}
+/* Unload unneeded modules. */
void
-pupa_dl_init (const char *dir)
+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_set_prefix (const char *dir)
{
pupa_dl_dir = (char *) dir;
}
+
+const char *
+pupa_dl_get_prefix (void)
+{
+ return pupa_dl_dir;
+}
#include <pupa/machine/memory.h>
#include <pupa/machine/console.h>
#include <pupa/machine/biosdisk.h>
+#include <pupa/machine/kernel.h>
#include <pupa/types.h>
#include <pupa/err.h>
+#include <pupa/dl.h>
+#include <pupa/misc.h>
+
+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)
/* The memory system was initialized, thus register built-in devices. */
pupa_biosdisk_init ();
+
+ /* Initialize the prefix. */
+ pupa_dl_set_prefix (make_install_device ());
}
.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:
*/
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
#include <pupa/term.h>
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, ...)
{
pupa_size_t
pupa_strlen (const char *s)
{
- char *p = (char *) s;
+ const char *p = s;
while (*p)
p++;
}
}
-char *
+static char *
pupa_itoa (char *str, int c, unsigned n)
{
unsigned base = (c == 'x') ? 16 : 10;
{
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++;
}
{
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)
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;
}
*/
#include <pupa/kernel.h>
+#include <pupa/rescue.h>
#include <pupa/term.h>
#include <pupa/misc.h>
#include <pupa/disk.h>
#include <pupa/mm.h>
#include <pupa/err.h>
#include <pupa/loader.h>
+#include <pupa/dl.h>
#include <pupa/machine/partition.h>
#define PUPA_RESCUE_BUF_SIZE 256
};
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;
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')
{
{
if (pos < PUPA_RESCUE_BUF_SIZE - 1)
{
- buf[pos++] = c;
+ linebuf[pos++] = c;
pupa_putchar (c);
}
}
{
if (pos > 0)
{
- buf[--pos] = 0;
+ linebuf[--pos] = 0;
pupa_putchar (c);
pupa_putchar (' ');
pupa_putchar (c);
}
#endif
+/* dump ADDRESS [SIZE] */
static void
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)
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;
/* 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)
{
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;
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,
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";
pupa_rescue_register_command (loader_name,
pupa_rescue_cmd_chainloader,
"load another boot loader");
+ my_mod = mod;
}
PUPA_MOD_FINI
#include <pupa/machine/partition.h>
#include <pupa/machine/util/biosdisk.h>
#include <pupa/machine/boot.h>
+#include <pupa/machine/kernel.h>
#include <stdio.h>
#include <unistd.h>
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;
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)
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))
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);