pupa-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] Multiboot


From: Jeroen Dekkers
Subject: Re: [PATCH] Multiboot
Date: Sun, 16 Nov 2003 16:31:06 +0100
User-agent: Mutt/1.5.4i

On Sat, Nov 15, 2003 at 10:25:57PM +0100, Yoshinori K. Okuji wrote:
> I'd like you to ask these changes on your patch:
> 
> * Rename pupa_multi_boot to pupa_multiboot_boot.
> * Add what features in Multiboot are not supported at the moment as comments.

Done. 

Marco annoyed me about some lines being longer than 80 chars so
I changed that too.

Jeroen Dekkers

2003-11-13  Jeroen Dekkers  <address@hidden>

        * conf/i386-pc.rmk (pkgdata_MODULES): Add _multiboot.mod.
        (_multiboot_mod_SOURCES): New variable.
        (_multiboot_mod_CFLAGS): Likewise.
        * loader/i386/pc/multiboot.c: New file.
        * include/pupa/i386/pc/multiboot.h: Likewise.
        * kern/i386/pc/startup.S: Include pupa/machine/multiboot.h.
        (pupa_multiboot_real_boot): New function.
        * include/pupa/i386/pc/loader.h: Include pupa/machine/multiboot.h.
        (pupa_multiboot_real_boot): New prototype.
        (pupa_rescue_cmd_multiboot): Likewise
        (pupa_rescue_cmd_module): Likewise.

        * kern/loader.c (pupa_loader_set): Continue when
        pupa_loader_unload_func() fails.
        (pupa_loader_unset): New function.
        * include/pupa/loader.h (pupa_loader_unset): New prototype.

        * kern/misc.c (pupa_stpcpy): New function.
        * include/pupa/misc.h (pupa_stpcpy): New prototype.

Index: kern/loader.c
===================================================================
RCS file: /cvsroot/pupa/pupa/kern/loader.c,v
retrieving revision 1.2
diff -u -p -r1.2 loader.c
--- kern/loader.c       17 Jan 2003 02:52:05 -0000      1.2
+++ kern/loader.c       16 Nov 2003 12:52:48 -0000
@@ -1,6 +1,7 @@
 /*
  *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
  *  Copyright (C) 2002  Yoshinori K. Okuji <address@hidden>
+ *  Copyright (C) 2003  Jeroen Dekkers <address@hidden>
  *
  *  PUPA is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -32,13 +33,24 @@ pupa_loader_set (pupa_err_t (*boot) (voi
                 pupa_err_t (*unload) (void))
 {
   if (pupa_loader_loaded && pupa_loader_unload_func)
-    if (pupa_loader_unload_func () != PUPA_ERR_NONE)
-      return;
+    pupa_loader_unload_func ();
   
   pupa_loader_boot_func = boot;
   pupa_loader_unload_func = unload;
 
   pupa_loader_loaded = 1;
+}
+
+void
+pupa_loader_unset(void)
+{
+  if (pupa_loader_loaded && pupa_loader_unload_func)
+    pupa_loader_unload_func ();
+  
+  pupa_loader_boot_func = 0;
+  pupa_loader_unload_func = 0;
+
+  pupa_loader_loaded = 0;
 }
 
 pupa_err_t
Index: kern/misc.c
===================================================================
RCS file: /cvsroot/pupa/pupa/kern/misc.c,v
retrieving revision 1.4
diff -u -p -r1.4 misc.c
--- kern/misc.c 29 Oct 2003 18:44:30 -0000      1.4
+++ kern/misc.c 16 Nov 2003 12:52:48 -0000
@@ -71,6 +71,19 @@ pupa_strncpy (char *dest, const char *sr
 }
 
 char *
+pupa_stpcpy (char *dest, const char *src)
+{
+  char *d = dest;
+  const char *s = src;
+
+  do
+    *d++ = *s;
+  while (*s++ != '\0');
+
+  return d - 1;
+}
+
+char *
 pupa_strcat (char *dest, const char *src)
 {
   char *p = dest;
Index: conf/i386-pc.mk
===================================================================
RCS file: /cvsroot/pupa/pupa/conf/i386-pc.mk,v
retrieving revision 1.9
diff -u -p -r1.9 i386-pc.mk
--- conf/i386-pc.mk     29 Oct 2003 18:44:26 -0000      1.9
+++ conf/i386-pc.mk     16 Nov 2003 12:52:48 -0000
@@ -403,7 +403,7 @@ genmoddep-util_genmoddep.d: util/genmodd
 
 # Modules.
 pkgdata_MODULES = _chain.mod _linux.mod fat.mod ext2.mod normal.mod hello.mod \
-       vga.mod font.mod
+       vga.mod font.mod _multiboot.mod
 
 # For _chain.mod.
 _chain_mod_SOURCES = loader/i386/pc/chainloader.c
@@ -750,6 +750,45 @@ font_mod-font_manager.d: font/manager.c
 -include font_mod-font_manager.d
 
 font_mod_CFLAGS = $(COMMON_CFLAGS)
+
+# For _multiboot.mod.
+_multiboot_mod_SOURCES = loader/i386/pc/multiboot.c
+CLEANFILES += _multiboot.mod mod-_multiboot.o mod-_multiboot.c 
pre-_multiboot.o _multiboot_mod-loader_i386_pc_multiboot.o def-_multiboot.lst 
und-_multiboot.lst
+MOSTLYCLEANFILES += _multiboot_mod-loader_i386_pc_multiboot.d
+DEFSYMFILES += def-_multiboot.lst
+UNDSYMFILES += und-_multiboot.lst
+
+_multiboot.mod: pre-_multiboot.o mod-_multiboot.o
+       -rm -f $@
+       $(LD) -r -o $@ $^
+       $(STRIP) --strip-unneeded -K pupa_mod_init -K pupa_mod_fini -R .note -R 
.comment $@
+
+pre-_multiboot.o: _multiboot_mod-loader_i386_pc_multiboot.o
+       -rm -f $@
+       $(LD) -r -o $@ $^
+
+mod-_multiboot.o: mod-_multiboot.c
+       $(CC) $(CPPFLAGS) $(CFLAGS) $(_multiboot_mod_CFLAGS) -c -o $@ $<
+
+mod-_multiboot.c: moddep.lst genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh '_multiboot' $< > $@ || (rm -f $@; exit 1)
+
+def-_multiboot.lst: pre-_multiboot.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 _multiboot/' 
> $@
+
+und-_multiboot.lst: pre-_multiboot.o
+       echo '_multiboot' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+_multiboot_mod-loader_i386_pc_multiboot.o: loader/i386/pc/multiboot.c
+       $(CC) -Iloader/i386/pc -I$(srcdir)/loader/i386/pc $(CPPFLAGS) $(CFLAGS) 
$(_multiboot_mod_CFLAGS) -c -o $@ $<
+
+_multiboot_mod-loader_i386_pc_multiboot.d: loader/i386/pc/multiboot.c
+       set -e;           $(CC) -Iloader/i386/pc -I$(srcdir)/loader/i386/pc 
$(CPPFLAGS) $(CFLAGS) $(_multiboot_mod_CFLAGS) -M $<          | sed 
's,multiboot\.o[ :]*,_multiboot_mod-loader_i386_pc_multiboot.o $@ : ,g' > $@;   
  [ -s $@ ] || rm -f $@
+
+-include _multiboot_mod-loader_i386_pc_multiboot.d
+
+_multiboot_mod_CFLAGS = $(COMMON_CFLAGS)
 CLEANFILES += moddep.lst
 pkgdata_DATA += moddep.lst
 moddep.lst: $(DEFSYMFILES) $(UNDSYMFILES) genmoddep
Index: conf/i386-pc.rmk
===================================================================
RCS file: /cvsroot/pupa/pupa/conf/i386-pc.rmk,v
retrieving revision 1.9
diff -u -p -r1.9 i386-pc.rmk
--- conf/i386-pc.rmk    29 Oct 2003 18:44:27 -0000      1.9
+++ conf/i386-pc.rmk    16 Nov 2003 12:52:48 -0000
@@ -62,7 +62,7 @@ genmoddep_SOURCES = util/genmoddep.c
 
 # Modules.
 pkgdata_MODULES = _chain.mod _linux.mod fat.mod ext2.mod normal.mod hello.mod \
-       vga.mod font.mod
+       vga.mod font.mod _multiboot.mod
 
 # For _chain.mod.
 _chain_mod_SOURCES = loader/i386/pc/chainloader.c
@@ -97,3 +97,7 @@ vga_mod_CFLAGS = $(COMMON_CFLAGS)
 # For font.mod.
 font_mod_SOURCES = font/manager.c
 font_mod_CFLAGS = $(COMMON_CFLAGS)
+
+# For _multiboot.mod.
+_multiboot_mod_SOURCES = loader/i386/pc/multiboot.c
+_multiboot_mod_CFLAGS = $(COMMON_CFLAGS)
Index: include/pupa/loader.h
===================================================================
RCS file: /cvsroot/pupa/pupa/include/pupa/loader.h,v
retrieving revision 1.2
diff -u -p -r1.2 loader.h
--- include/pupa/loader.h       17 Jan 2003 02:52:04 -0000      1.2
+++ include/pupa/loader.h       16 Nov 2003 12:52:48 -0000
@@ -2,6 +2,7 @@
 /*
  *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
  *  Copyright (C) 2002  Yoshinori K. Okuji <address@hidden>
+ *  Copyright (C) 2003  Jeroen Dekkers <address@hidden>
  *
  *  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
@@ -31,6 +32,7 @@ extern pupa_size_t EXPORT_VAR(pupa_os_ar
 
 void EXPORT_FUNC(pupa_loader_set) (pupa_err_t (*boot) (void),
                                   pupa_err_t (*unload) (void));
+void EXPORT_FUNC(pupa_loader_unset) (void);
 
 pupa_err_t EXPORT_FUNC(pupa_loader_boot) (void);
 
Index: include/pupa/misc.h
===================================================================
RCS file: /cvsroot/pupa/pupa/include/pupa/misc.h,v
retrieving revision 1.3
diff -u -p -r1.3 misc.h
--- include/pupa/misc.h 29 Oct 2003 18:44:29 -0000      1.3
+++ include/pupa/misc.h 16 Nov 2003 12:52:48 -0000
@@ -32,6 +32,7 @@
 void *EXPORT_FUNC(pupa_memmove) (void *dest, const void *src, pupa_size_t n);
 char *EXPORT_FUNC(pupa_strcpy) (char *dest, const char *src);
 char *EXPORT_FUNC(pupa_strncpy) (char *dest, const char *src, int c);
+char *EXPORT_FUNC(pupa_stpcpy) (char *dest, const char *src);
 char *EXPORT_FUNC(pupa_strcat) (char *dest, const char *src);
 
 
Index: include/pupa/i386/pc/loader.h
===================================================================
RCS file: /cvsroot/pupa/pupa/include/pupa/i386/pc/loader.h,v
retrieving revision 1.3
diff -u -p -r1.3 loader.h
--- include/pupa/i386/pc/loader.h       20 Jan 2003 04:13:46 -0000      1.3
+++ include/pupa/i386/pc/loader.h       16 Nov 2003 12:52:48 -0000
@@ -1,6 +1,7 @@
 /*
  *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
  *  Copyright (C) 2002  Yoshinori K. Okuji <address@hidden>
+ *  Copyright (C) 2003  Jeroen Dekkers <address@hidden>
  *
  *  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
@@ -22,6 +23,7 @@
 
 #include <pupa/types.h>
 #include <pupa/symbol.h>
+#include <pupa/machine/multiboot.h>
 
 extern pupa_uint32_t EXPORT_VAR(pupa_linux_prot_size);
 extern char *EXPORT_VAR(pupa_linux_tmp_addr);
@@ -33,10 +35,17 @@ void EXPORT_FUNC(pupa_linux_boot_bzimage
 /* This is an asm part of the chainloader.  */
 void EXPORT_FUNC(pupa_chainloader_real_boot) (int drive, void *part_addr) 
__attribute__ ((noreturn));
 
+/* The asm part of the multiboot loader.  */
+void EXPORT_FUNC(pupa_multiboot_real_boot) (pupa_addr_t entry, 
+                                           struct pupa_multiboot_info *mbi) 
+     __attribute__ ((noreturn));
+
 /* It is necessary to export these functions, because normal mode commands
    reuse rescue mode commands.  */
 void pupa_rescue_cmd_chainloader (int argc, char *argv[]);
 void pupa_rescue_cmd_linux (int argc, char *argv[]);
 void pupa_rescue_cmd_initrd (int argc, char *argv[]);
+void pupa_rescue_cmd_multiboot (int argc, char *argv[]);
+void pupa_rescue_cmd_module (int argc, char *argv[]);
 
 #endif /* ! PUPA_LOADER_MACHINE_HEADER */
Index: include/pupa/i386/pc/multiboot.h
===================================================================
RCS file: include/pupa/i386/pc/multiboot.h
diff -N include/pupa/i386/pc/multiboot.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ include/pupa/i386/pc/multiboot.h    16 Nov 2003 12:52:48 -0000
@@ -0,0 +1,184 @@
+/* multiboot.h - multiboot header file. */
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2003  Jeroen Dekkers  <address@hidden>
+ *
+ *  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; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef PUPA_MULTIBOOT_MACHINE_HEADER
+#define PUPA_MULTIBOOT_MACHINE_HEADER 1
+
+/* How many bytes from the start of the file we search for the header.  */
+#define PUPA_MB_SEARCH                 8192
+
+/* The magic field should contain this.  */
+#define PUPA_MB_MAGIC                  0x1BADB002
+
+/* This should be in %eax.  */
+#define PUPA_MB_MAGIC2                 0x2BADB002
+
+/* The bits in the required part of flags field we don't support.  */
+#define PUPA_MB_UNSUPPORTED            0x0000fffc
+
+/* Alignment of multiboot modules.  */
+#define PUPA_MB_MOD_ALIGN              0x00001000
+
+/* 
+ * Flags set in the 'flags' member of the multiboot header.
+ */
+
+/* Align all boot modules on i386 page (4KB) boundaries.  */
+#define PUPA_MB_PAGE_ALIGN             0x00000001
+
+/* Must pass memory information to OS.  */
+#define PUPA_MB_MEMORY_INFO            0x00000002
+
+/* Must pass video information to OS.  */
+#define PUPA_MB_VIDEO_MODE             0x00000004
+
+/* This flag indicates the use of the address fields in the header.  */
+#define PUPA_MB_AOUT_KLUDGE            0x00010000
+
+/*
+ *  Flags to be set in the 'flags' member of the multiboot info structure.
+ */
+
+/* is there basic lower/upper memory information? */
+#define PUPA_MB_INFO_MEMORY            0x00000001
+/* is there a boot device set? */
+#define PUPA_MB_INFO_BOOTDEV           0x00000002
+/* is the command-line defined? */
+#define PUPA_MB_INFO_CMDLINE           0x00000004
+/* are there modules to do something with? */
+#define PUPA_MB_INFO_MODS              0x00000008
+
+/* These next two are mutually exclusive */
+
+/* is there a symbol table loaded? */
+#define PUPA_MB_INFO_AOUT_SYMS         0x00000010
+/* is there an ELF section header table? */
+#define PUPA_MB_INFO_ELF_SHDR          0x00000020
+
+/* is there a full memory map? */
+#define PUPA_MB_INFO_MEM_MAP           0x00000040
+
+/* Is there drive info?  */
+#define PUPA_MB_INFO_DRIVE_INFO                0x00000080
+
+/* Is there a config table?  */
+#define PUPA_MB_INFO_CONFIG_TABLE      0x00000100
+
+/* Is there a boot loader name?  */
+#define PUPA_MB_INFO_BOOT_LOADER_NAME  0x00000200
+
+/* Is there a APM table?  */
+#define PUPA_MB_INFO_APM_TABLE         0x00000400
+
+/* Is there video information?  */
+#define PUPA_MB_INFO_VIDEO_INFO                0x00000800
+
+#ifndef ASM_FILE
+
+#include <pupa/types.h>
+
+struct pupa_multiboot_header
+{ 
+  /* Must be PUPA_MB_MAGIC - see above.  */
+  pupa_uint32_t magic;
+
+  /* Feature flags.  */
+  pupa_uint32_t flags;
+
+  /* The above fields plus this one must equal 0 mod 2^32. */
+  pupa_uint32_t checksum;
+  
+  /* These are only valid if PUPA_MB_AOUT_KLUDGE is set.  */
+  pupa_uint32_t header_addr;
+  pupa_uint32_t load_addr;
+  pupa_uint32_t load_end_addr;
+  pupa_uint32_t bss_end_addr;
+  pupa_uint32_t entry_addr;
+
+  /* These are only valid if PUPA_MB_VIDEO_MODE is set.  */
+  pupa_uint32_t mode_type;
+  pupa_uint32_t width;
+  pupa_uint32_t height;
+  pupa_uint32_t depth;
+};
+
+struct pupa_multiboot_info
+{
+  /* MultiBoot info version number */
+  pupa_uint32_t flags;
+  
+  /* Available memory from BIOS */
+  pupa_uint32_t mem_lower;
+  pupa_uint32_t mem_upper;
+  
+  /* "root" partition */
+  pupa_uint32_t boot_device;
+  
+  /* Kernel command line */
+  pupa_uint32_t cmdline;
+  
+  /* Boot-Module list */
+  pupa_uint32_t mods_count;
+  pupa_uint32_t mods_addr;
+  
+  pupa_uint32_t syms[4];
+  
+  /* Memory Mapping buffer */
+  pupa_uint32_t mmap_length;
+  pupa_uint32_t mmap_addr;
+  
+  /* Drive Info buffer */
+  pupa_uint32_t drives_length;
+  pupa_uint32_t drives_addr;
+  
+  /* ROM configuration table */
+  pupa_uint32_t config_table;
+  
+  /* Boot Loader Name */
+  pupa_uint32_t boot_loader_name;
+
+  /* APM table */
+  pupa_uint32_t apm_table;
+
+  /* Video */
+  pupa_uint32_t vbe_control_info;
+  pupa_uint32_t vbe_mode_info;
+  pupa_uint16_t vbe_mode;
+  pupa_uint16_t vbe_interface_seg;
+  pupa_uint16_t vbe_interface_off;
+  pupa_uint16_t vbe_interface_len;
+};
+
+struct pupa_mod_list
+{
+  /* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */
+  pupa_uint32_t mod_start;
+  pupa_uint32_t mod_end;
+  
+  /* Module command line */
+  pupa_uint32_t cmdline;
+  
+  /* padding to take it to 16 bytes (must be zero) */
+  pupa_uint32_t pad;
+};
+
+#endif /* ! ASM_FILE */
+
+#endif /* ! PUPA_MULTIBOOT_MACHINE_HEADER */
Index: kern/i386/pc/startup.S
===================================================================
RCS file: /cvsroot/pupa/pupa/kern/i386/pc/startup.S,v
retrieving revision 1.10
diff -u -p -r1.10 startup.S
--- kern/i386/pc/startup.S      12 Nov 2003 20:33:51 -0000      1.10
+++ kern/i386/pc/startup.S      16 Nov 2003 12:52:48 -0000
@@ -3,6 +3,7 @@
  *  Copyright (C) 1999,2000,2001,2002 Free Software Foundation, Inc.
  *  Copyright (C) 2002,2003  Yoshinori K. Okuji <address@hidden>
  *  Copyright (C) 2003 Marco Gerards <address@hidden>
+ *  Copyright (C) 2003 Jeroen Dekkers <address@hidden>
  *
  *  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
@@ -52,6 +53,7 @@
 #include <pupa/machine/console.h>
 #include <pupa/machine/linux.h>
 #include <pupa/machine/kernel.h>
+#include <pupa/machine/multiboot.h>
                
 #define ABS(x) ((x) - EXT_C(start) + PUPA_BOOT_MACHINE_KERNEL_ADDR + 0x200)
        
@@ -621,6 +623,29 @@ linux_setup_seg:
        .code32
 
                
+/*
+ * This starts the multiboot kernel.
+ */
+
+FUNCTION(pupa_multiboot_real_boot)
+       /* Push the entry address on the stack.  */
+       pushl   %eax
+       /* Move the address of the multiboot information structure to ebx.  */
+       movl    %edx,%ebx
+       
+       /* Unload all modules and stop the floppy driver.  */
+       call    EXT_C(pupa_dl_unload_all)
+       call    EXT_C(pupa_stop_floppy)
+
+       /* Interrupts should be disabled.  */
+       cli
+       
+       /* Move the magic value into eax and jump to the kernel.  */
+       movl    $PUPA_MB_MAGIC2,%eax
+       popl    %ecx
+       jmp     *%ecx
+       
+       
 /*
  *   int pupa_biosdisk_rw_int13_extensions (int ah, int drive, void *dap)
  *
Index: loader/i386/pc/multiboot.c
===================================================================
RCS file: loader/i386/pc/multiboot.c
diff -N loader/i386/pc/multiboot.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ loader/i386/pc/multiboot.c  16 Nov 2003 12:52:48 -0000
@@ -0,0 +1,356 @@
+/* multiboot.c - boot a multiboot OS image. */
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2003  Jeroen Dekkers  <address@hidden>
+ *
+ *  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; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* 
+ *  FIXME: The following features from the Multiboot specification still
+ *         need to be implemented:
+ *  - VBE support
+ *  - boot device
+ *  - symbol table
+ *  - memory map
+ *  - drives table
+ *  - ROM configuration table
+ *  - APM table
+ */
+
+#include <pupa/loader.h>
+#include <pupa/machine/loader.h>
+#include <pupa/machine/multiboot.h>
+#include <pupa/machine/init.h>
+#include <pupa/elf.h>
+#include <pupa/file.h>
+#include <pupa/err.h>
+#include <pupa/rescue.h>
+#include <pupa/dl.h>
+#include <pupa/mm.h>
+#include <pupa/misc.h>
+
+static pupa_dl_t my_mod;
+static struct pupa_multiboot_info *mbi;
+static pupa_addr_t entry;
+
+static pupa_err_t
+pupa_multiboot_boot (void)
+{
+  pupa_multiboot_real_boot (entry, mbi);
+
+  /* Not reached.  */
+  return PUPA_ERR_NONE;
+}
+
+static pupa_err_t
+pupa_multiboot_unload (void)
+{
+  if (mbi)
+    {
+      int i;
+      for (i = 0; i < mbi->mods_count; i++)
+       {
+         pupa_free ((void *)
+                    ((struct pupa_mod_list *) mbi->mods_addr)[i].mod_start);
+         pupa_free ((void *)
+                    ((struct pupa_mod_list *) mbi->mods_addr)[i].cmdline);
+       }
+      pupa_free ((void *) mbi->mods_addr);
+      pupa_free ((void *) mbi->cmdline);
+      pupa_free (mbi);
+    }
+
+
+  mbi = 0;
+  pupa_dl_unref (my_mod);
+
+  return PUPA_ERR_NONE;
+}
+
+void
+pupa_rescue_cmd_multiboot (int argc, char *argv[])
+{
+  pupa_file_t file = 0;
+  char buffer[PUPA_MB_SEARCH], *cmdline = 0, *p;
+  struct pupa_multiboot_header *header;
+  pupa_ssize_t len;
+  int i;
+  Elf32_Ehdr *ehdr;
+
+  pupa_dl_ref (my_mod);
+
+  pupa_loader_unset();
+    
+  if (argc == 0)
+    {
+      pupa_error (PUPA_ERR_BAD_ARGUMENT, "No kernel specified");
+      goto fail;
+    }
+
+  file = pupa_file_open (argv[0]);
+  if (!file)
+    {
+      pupa_error (PUPA_ERR_BAD_ARGUMENT, "Couldn't open file");
+      goto fail;
+    }
+
+  len = pupa_file_read (file, buffer, PUPA_MB_SEARCH);
+  if (len < 32)
+    {
+      pupa_error (PUPA_ERR_BAD_OS, "File too small");
+      goto fail;
+    }
+
+  /* Look for the multiboot header in the buffer.  The header should
+     be at least 12 bytes and aligned on a 4-byte boundary.  */
+  for (header = (struct pupa_multiboot_header *) buffer; 
+       ((char *) header <= buffer + len - 12) || (header = 0);
+       (char *)header += 4)
+    {
+      if (header->magic == PUPA_MB_MAGIC 
+         && !(header->magic + header->flags + header->checksum))
+         break;
+    }
+  
+  if (header == 0)
+    {
+      pupa_error (PUPA_ERR_BAD_ARGUMENT, "No multiboot header found");
+      goto fail;
+    }
+
+  if (header->flags & PUPA_MB_UNSUPPORTED)
+    {
+      pupa_error (PUPA_ERR_UNKNOWN_OS, "Unsupported flag: 0x%x", 
header->flags);
+      goto fail;
+    }
+
+  ehdr = (Elf32_Ehdr *) buffer;
+
+  if (!((ehdr->e_ident[EI_MAG0] == ELFMAG0) 
+       && (ehdr->e_ident[EI_MAG1] == ELFMAG1)
+       && (ehdr->e_ident[EI_MAG2] == ELFMAG2) 
+       && (ehdr->e_ident[EI_MAG3] == ELFMAG3)
+       && (ehdr->e_ident[EI_CLASS] == ELFCLASS32) 
+       && (ehdr->e_ident[EI_DATA] == ELFDATA2LSB)
+       && (ehdr->e_ident[EI_VERSION] == EV_CURRENT) 
+       && (ehdr->e_type == ET_EXEC) && (ehdr->e_machine == EM_386) 
+       && (ehdr->e_version == EV_CURRENT)))
+    {
+      pupa_error (PUPA_ERR_UNKNOWN_OS, "No valid ELF header found");
+      goto fail;
+    }
+
+  /* FIXME: Should we support program headers at strange locations?  */
+  if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > PUPA_MB_SEARCH)
+    {
+      pupa_error (PUPA_ERR_UNKNOWN_OS, "Program header at a too high offset");
+      goto fail;
+    }
+
+  entry = ehdr->e_entry;
+
+  /* Load every loadable segment in memory.  */
+  for (i = 0; i < ehdr->e_phnum; i++)
+    {
+      Elf32_Phdr *phdr;
+      phdr = (Elf32_Phdr *) (buffer + ehdr->e_phoff + i * ehdr->e_phentsize);
+
+      if (phdr->p_type == PT_LOAD)
+       {
+         /* The segment should fit in the area reserved for the OS.  */
+         if ((phdr->p_paddr < pupa_os_area_addr) 
+             || (phdr->p_paddr + phdr->p_memsz
+                 > pupa_os_area_addr + pupa_os_area_size))
+           {
+             pupa_error (PUPA_ERR_BAD_OS, 
+                         "Segment doesn't fit in memory reserved for the OS");
+             goto fail;
+           }
+         
+         if (pupa_file_seek (file, phdr->p_offset) == -1)
+           {
+             pupa_error (PUPA_ERR_BAD_OS, "Invalid offset in program header");
+             goto fail;
+           }
+
+         if (pupa_file_read (file, (void *) phdr->p_paddr, phdr->p_filesz) 
+             != (pupa_ssize_t) phdr->p_filesz)
+           {
+             pupa_error (PUPA_ERR_BAD_OS, "Couldn't read segment from file");
+             goto fail;
+           }
+
+         if (phdr->p_filesz < phdr->p_memsz)
+           pupa_memset ((char *) phdr->p_paddr + phdr->p_filesz, 0, 
+                        phdr->p_memsz - phdr->p_filesz);
+       }
+    }
+
+  mbi = pupa_malloc (sizeof (struct pupa_multiboot_info));
+  if (!mbi)
+    goto fail;
+
+  mbi->flags = PUPA_MB_INFO_MEMORY;
+
+  /* Convert from bytes to kilobytes.  */
+  mbi->mem_lower = pupa_lower_mem / 1024;
+  mbi->mem_upper = pupa_upper_mem / 1024;
+
+  for (i = 0, len = 0; i < argc; i++)
+    len += pupa_strlen (argv[i]) + 1;
+  
+  cmdline = p = pupa_malloc (len);
+  if (!cmdline)
+    goto fail;
+  
+  for (i = 0; i < argc; i++)
+    {
+      p = pupa_stpcpy (p, argv[i]);
+      *(p++) = ' ';
+    }
+  
+  /* Remove the space after the last word.  */
+  *(--p) = '\0';
+  
+  mbi->flags |= PUPA_MB_INFO_CMDLINE;
+  mbi->cmdline = (pupa_uint32_t) cmdline;
+
+  mbi->flags |= PUPA_MB_INFO_BOOT_LOADER_NAME;
+  mbi->boot_loader_name = (pupa_uint32_t) pupa_strdup (PACKAGE_STRING);
+
+  pupa_loader_set (pupa_multiboot_boot, pupa_multiboot_unload);
+
+ fail:
+  if (file)
+    pupa_file_close (file);
+
+  if (pupa_errno != PUPA_ERR_NONE)
+    {
+      pupa_free (cmdline);
+      pupa_free (mbi);
+      pupa_dl_unref (my_mod);
+    }
+}
+
+
+void
+pupa_rescue_cmd_module  (int argc, char *argv[])
+{
+  pupa_file_t file = 0;
+  pupa_ssize_t size, len = 0;
+  char *module = 0, *cmdline = 0, *p;
+  int i;
+
+  if (argc == 0)
+    {
+      pupa_error (PUPA_ERR_BAD_ARGUMENT, "No module specified");
+      goto fail;
+    }
+
+  if (!mbi)
+    {
+      pupa_error (PUPA_ERR_BAD_ARGUMENT, 
+                 "You need to load the multiboot kernel first");
+      goto fail;
+    }
+
+  file = pupa_file_open (argv[0]);
+  if (!file)
+    goto fail;
+
+  size = pupa_file_size (file);
+  module = pupa_memalign (PUPA_MB_MOD_ALIGN, size);
+  if (!module)
+    goto fail;
+
+  if (pupa_file_read (file, module, size) != size)
+    {
+      pupa_error (PUPA_ERR_FILE_READ_ERROR, "Couldn't read file");
+      goto fail;
+    }
+  
+  for (i = 0; i < argc; i++)
+    len += pupa_strlen (argv[i]) + 1;
+  
+  cmdline = p = pupa_malloc (len);
+  if (!cmdline)
+    goto fail;
+  
+  for (i = 0; i < argc; i++)
+    {
+      p = pupa_stpcpy (p, argv[i]);
+      *(p++) = ' ';
+    }
+  
+  /* Remove the space after the last word.  */
+  *(--p) = '\0';
+
+  if (mbi->flags & PUPA_MB_INFO_MODS)
+    {
+      struct pupa_mod_list *modlist = (struct pupa_mod_list *) mbi->mods_addr;
+
+      modlist = pupa_realloc (modlist, (mbi->mods_count + 1) 
+                                      * sizeof (struct pupa_mod_list));
+      if (!modlist)
+       goto fail;
+      mbi->mods_addr = (pupa_uint32_t) modlist;
+      modlist += mbi->mods_count;
+      modlist->mod_start = (pupa_uint32_t) module;
+      modlist->mod_end = (pupa_uint32_t) module + size;
+      modlist->cmdline = (pupa_uint32_t) cmdline;
+      modlist->pad = 0;
+      mbi->mods_count++;
+    }
+  else
+    {
+      struct pupa_mod_list *modlist = pupa_malloc (sizeof (struct 
pupa_mod_list));
+      if (!modlist)
+       goto fail;
+      modlist->mod_start = (pupa_uint32_t) module;
+      modlist->mod_end = (pupa_uint32_t) module + size;
+      modlist->cmdline = (pupa_uint32_t) cmdline;
+      modlist->pad = 0;
+      mbi->mods_count = 1;
+      mbi->mods_addr = (pupa_uint32_t) modlist;
+      mbi->flags |= PUPA_MB_INFO_MODS;
+    }
+
+ fail:
+  if (file)
+    pupa_file_close (file);
+
+  if (pupa_errno != PUPA_ERR_NONE)
+    {
+      pupa_free (module);
+      pupa_free (cmdline);
+    }
+}
+
+
+PUPA_MOD_INIT
+{
+  pupa_rescue_register_command ("multiboot", pupa_rescue_cmd_multiboot,
+                               "load a multiboot kernel");
+  pupa_rescue_register_command ("module", pupa_rescue_cmd_module,
+                               "load a multiboot module");
+  my_mod = mod;
+}
+
+PUPA_MOD_FINI
+{
+  pupa_rescue_unregister_command ("multiboot");
+  pupa_rescue_unregister_command ("module");
+}




reply via email to

[Prev in Thread] Current Thread [Next in Thread]