]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
2003-01-17 Yoshinori K. Okuji <okuji@enbug.org>
authorokuji <okuji@localhost>
Fri, 17 Jan 2003 02:52:05 +0000 (02:52 +0000)
committerokuji <okuji@localhost>
Fri, 17 Jan 2003 02:52:05 +0000 (02:52 +0000)
* include/pupa/i386/pc/linux.h: New file.
* loader/i386/pc/linux.c: Likewise.

* loader/i386/pc/chainloader.c (pupa_chainloader_boot_sector):
Removed.
(pupa_chainloader_unload): Return PUPA_ERR_NONE.
(pupa_rescue_cmd_chainloader): Read the image to 0x7C00 instead
of PUPA_CHAINLOADER_BOOT_SECTOR.

* kern/i386/pc/startup.S: Include pupa/machine/linux.h.
(pupa_linux_prot_size): New variable.
(pupa_linux_tmp_addr): Likewise.
(pupa_linux_real_addr): Likewise.
(pupa_linux_boot_zimage): New function.
(pupa_linux_boot_bzimage): Likewise.

* kern/i386/pc/init.c (struct mem_region): New structure.
(MAX_REGIONS): New macro.
(mem_regions): New variable.
(num_regions): Likewise.
(pupa_os_area_addr): Likewise.
(pupa_os_area_size): Likewise.
(pupa_lower_mem): Likewise.
(pupa_upper_mem): Likewise.
(add_mem_region): New function.
(compact_mem_regions): Likewise.
(pupa_machine_init): Set PUPA_LOWER_MEM and PUPA_UPPER_MEM to
the size of the conventional memory and that of so-called upper
memory (before the first memory hole).
Instead of adding each found region to free memory, use
add_mem_region and add them after removing overlaps.
Also, add only 1/4 of the upper memory to free memory. The rest
is used for loading OS images. Maybe this is ad hoc, but this
makes it much easier to relocate OS images when booting.

* kern/rescue.c (pupa_rescue_cmd_module): Removed.
(pupa_enter_rescue_mode): Don't register initrd and module.

* kern/mm.c: Include pupa/dl.h.

* kern/main.c: Include pupa/file.h and pupa/device.h.

* kern/loader.c (pupa_loader_load_module_func): Removed.
(pupa_loader_load_module): Likewise.

* kern/dl.c (pupa_dl_load): Use the suffix ``.mod'' instead of
``.o''.

* include/pupa/i386/pc/loader.h (pupa_linux_prot_size): Declared.
(pupa_linux_tmp_addr): Likewise.
(pupa_linux_real_addr): Likewise.
(pupa_linux_boot_zimage): Likewise.
(pupa_linux_boot_bzimage): Likewise.

* include/pupa/i386/pc/init.h (pupa_lower_mem): Declared.
(pupa_upper_mem): Likewise.
(pupa_gate_a20): Don't export, because turning off Gate A20 in a
module is too dangerous.

* include/pupa/loader.h (pupa_os_area_addr): Declared.
(pupa_os_area_size): Likewise.
(pupa_loader_set): Remove the first argument. Loader doesn't
manage modules or initrd any longer.
(pupa_loader_load_module): Removed.

* conf/i386-pc.rmk (pkgdata_MODULES): Added linux.mod.
(linux_mod_SOURCES): New variable.
(linux_mod_CFLAGS): Likewise.

17 files changed:
ChangeLog
NEWS
conf/i386-pc.mk
conf/i386-pc.rmk
include/grub/i386/pc/init.h
include/grub/i386/pc/linux.h [new file with mode: 0644]
include/grub/i386/pc/loader.h
include/grub/loader.h
kern/dl.c
kern/i386/pc/init.c
kern/i386/pc/startup.S
kern/loader.c
kern/main.c
kern/mm.c
kern/rescue.c
loader/i386/pc/chainloader.c
loader/i386/pc/linux.c [new file with mode: 0644]

index e6ffba2c4f5bf26c539a207bc7fcb5ad4948c9cf..6b977b68552ddfca1f337d05145b4a2f12df6116 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,74 @@
+2003-01-17  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * include/pupa/i386/pc/linux.h: New file.
+       * loader/i386/pc/linux.c: Likewise.
+       
+       * loader/i386/pc/chainloader.c (pupa_chainloader_boot_sector):
+       Removed.
+       (pupa_chainloader_unload): Return PUPA_ERR_NONE.
+       (pupa_rescue_cmd_chainloader): Read the image to 0x7C00 instead
+       of PUPA_CHAINLOADER_BOOT_SECTOR.
+
+       * kern/i386/pc/startup.S: Include pupa/machine/linux.h.
+       (pupa_linux_prot_size): New variable.
+       (pupa_linux_tmp_addr): Likewise.
+       (pupa_linux_real_addr): Likewise.
+       (pupa_linux_boot_zimage): New function.
+       (pupa_linux_boot_bzimage): Likewise.
+
+       * kern/i386/pc/init.c (struct mem_region): New structure.
+       (MAX_REGIONS): New macro.
+       (mem_regions): New variable.
+       (num_regions): Likewise.
+       (pupa_os_area_addr): Likewise.
+       (pupa_os_area_size): Likewise.
+       (pupa_lower_mem): Likewise.
+       (pupa_upper_mem): Likewise.
+       (add_mem_region): New function.
+       (compact_mem_regions): Likewise.
+       (pupa_machine_init): Set PUPA_LOWER_MEM and PUPA_UPPER_MEM to
+       the size of the conventional memory and that of so-called upper
+       memory (before the first memory hole).
+       Instead of adding each found region to free memory, use
+       add_mem_region and add them after removing overlaps.
+       Also, add only 1/4 of the upper memory to free memory. The rest
+       is used for loading OS images. Maybe this is ad hoc, but this
+       makes it much easier to relocate OS images when booting.
+
+       * kern/rescue.c (pupa_rescue_cmd_module): Removed.
+       (pupa_enter_rescue_mode): Don't register initrd and module.
+
+       * kern/mm.c: Include pupa/dl.h.
+
+       * kern/main.c: Include pupa/file.h and pupa/device.h.
+
+       * kern/loader.c (pupa_loader_load_module_func): Removed.
+       (pupa_loader_load_module): Likewise.
+
+       * kern/dl.c (pupa_dl_load): Use the suffix ``.mod'' instead of
+       ``.o''.
+
+       * include/pupa/i386/pc/loader.h (pupa_linux_prot_size): Declared.
+       (pupa_linux_tmp_addr): Likewise.
+       (pupa_linux_real_addr): Likewise.
+       (pupa_linux_boot_zimage): Likewise.
+       (pupa_linux_boot_bzimage): Likewise.
+
+       * include/pupa/i386/pc/init.h (pupa_lower_mem): Declared.
+       (pupa_upper_mem): Likewise.
+       (pupa_gate_a20): Don't export, because turning off Gate A20 in a
+       module is too dangerous.
+
+       * include/pupa/loader.h (pupa_os_area_addr): Declared.
+       (pupa_os_area_size): Likewise.
+       (pupa_loader_set): Remove the first argument. Loader doesn't
+       manage modules or initrd any longer.
+       (pupa_loader_load_module): Removed.
+
+       * conf/i386-pc.rmk (pkgdata_MODULES): Added linux.mod.
+       (linux_mod_SOURCES): New variable.
+       (linux_mod_CFLAGS): Likewise.
+
 2003-01-07  Yoshinori K. Okuji  <okuji@enbug.org>
 
        * util/i386/pc/pupa-setup.c (setup): Convert the endianness of
diff --git a/NEWS b/NEWS
index ad72cbd42cfb62049d7ea289ce5429b498d4064a..974707acc02f2d1d09617261d391f34acb5efecb 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -13,6 +13,8 @@ New in 0.7:
 * New commands, "prefix", "insmod", "rmmod" and "lsmod" are added into
   the rescue mode to manipulate PUPA modules.
 
+* Linux support is added. Initrd is not support yet.
+
 
 New in 0.6 - 2002-12-27, Yoshinori K. Okuji:
 
index 3744d0894ae3e26432d9be77d19298e199309bec..af2ae41405eaae2f078443e36f8786f68f5aa0e5 100644 (file)
@@ -393,7 +393,7 @@ genmoddep-util_genmoddep.d: util/genmoddep.c
 
 
 # Modules.
-pkgdata_MODULES = chain.mod fat.mod
+pkgdata_MODULES = chain.mod fat.mod linux.mod
 
 # For chain.mod.
 chain_mod_SOURCES = loader/i386/pc/chainloader.c
@@ -472,6 +472,45 @@ fat_mod-fs_fat.d: fs/fat.c
 -include fat_mod-fs_fat.d
 
 fat_mod_CFLAGS = $(COMMON_CFLAGS)
+
+# For linux.mod.
+linux_mod_SOURCES = loader/i386/pc/linux.c
+CLEANFILES += linux.mod mod-linux.o mod-linux.c pre-linux.o linux_mod-loader_i386_pc_linux.o def-linux.lst und-linux.lst
+MOSTLYCLEANFILES += linux_mod-loader_i386_pc_linux.d
+DEFSYMFILES += def-linux.lst
+UNDSYMFILES += und-linux.lst
+
+linux.mod: pre-linux.o mod-linux.o
+       -rm -f $@
+       $(LD) -r -o $@ $^
+       $(STRIP) --strip-unneeded -K pupa_mod_init -K pupa_mod_fini -R .note -R .comment $@
+
+pre-linux.o: linux_mod-loader_i386_pc_linux.o
+       -rm -f $@
+       $(LD) -r -o $@ $^
+
+mod-linux.o: mod-linux.c
+       $(CC) $(CPPFLAGS) $(CFLAGS) $(linux_mod_CFLAGS) -c -o $@ $<
+
+mod-linux.c: moddep.lst genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'linux' $< > $@ || (rm -f $@; exit 1)
+
+def-linux.lst: pre-linux.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 linux/' > $@
+
+und-linux.lst: pre-linux.o
+       echo 'linux' > $@
+       $(NM) -u -P -p $< >> $@
+
+linux_mod-loader_i386_pc_linux.o: loader/i386/pc/linux.c
+       $(CC) -Iloader/i386/pc -I$(srcdir)/loader/i386/pc $(CPPFLAGS) $(CFLAGS) $(linux_mod_CFLAGS) -c -o $@ $<
+
+linux_mod-loader_i386_pc_linux.d: loader/i386/pc/linux.c
+       set -e;           $(CC) -Iloader/i386/pc -I$(srcdir)/loader/i386/pc $(CPPFLAGS) $(CFLAGS) $(linux_mod_CFLAGS) -M $<       | sed 's,linux\.o[ :]*,linux_mod-loader_i386_pc_linux.o $@ : ,g' > $@;          [ -s $@ ] || rm -f $@
+
+-include linux_mod-loader_i386_pc_linux.d
+
+linux_mod_CFLAGS = $(COMMON_CFLAGS)
 CLEANFILES += moddep.lst
 pkgdata_DATA += moddep.lst
 moddep.lst: $(DEFSYMFILES) $(UNDSYMFILES) genmoddep
index cfa6550d7a587492b52cb6b6629cd422511815da..132f4189d8fbb54ad113217f7bd730ac91613c32 100644 (file)
@@ -60,7 +60,7 @@ pupa_setup_SOURCES = util/i386/pc/pupa-setup.c util/i386/pc/biosdisk.c \
 genmoddep_SOURCES = util/genmoddep.c
 
 # Modules.
-pkgdata_MODULES = chain.mod fat.mod
+pkgdata_MODULES = chain.mod fat.mod linux.mod
 
 # For chain.mod.
 chain_mod_SOURCES = loader/i386/pc/chainloader.c
@@ -69,3 +69,7 @@ chain_mod_CFLAGS = $(COMMON_CFLAGS)
 # For fat.mod.
 fat_mod_SOURCES = fs/fat.c
 fat_mod_CFLAGS = $(COMMON_CFLAGS)
+
+# For linux.mod.
+linux_mod_SOURCES = loader/i386/pc/linux.c
+linux_mod_CFLAGS = $(COMMON_CFLAGS)
index cb9128607235f28302b223f49888f4ed81b5a9a0..e6396ee0c35ced804bf9851e41bb13433474354e 100644 (file)
 #include <pupa/types.h>
 #include <pupa/symbol.h>
 
+/* FIXME: Should these be declared in memory.h?  */
+extern pupa_size_t EXPORT_VAR(pupa_lower_mem);
+extern pupa_size_t EXPORT_VAR(pupa_upper_mem);
+
 /* Get the memory size in KB. If EXTENDED is zero, return conventional
    memory, otherwise return extended memory.  */
 pupa_uint16_t pupa_get_memsize (int extended);
@@ -45,6 +49,6 @@ pupa_uint32_t pupa_get_mmap_entry (struct pupa_machine_mmap_entry *entry,
                                   pupa_uint32_t cont);
 
 /* Turn on/off Gate A20.  */
-void EXPORT_FUNC(pupa_gate_a20) (int on);
+void pupa_gate_a20 (int on);
 
 #endif /* ! PUPA_INIT_MACHINE_HEADER */
diff --git a/include/grub/i386/pc/linux.h b/include/grub/i386/pc/linux.h
new file mode 100644 (file)
index 0000000..942b09d
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 1999,2000,2001,2002  Free Software Foundation, Inc.
+ *  Copyright (C) 2003  Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  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_LINUX_MACHINE_HEADER
+#define PUPA_LINUX_MACHINE_HEADER      1
+
+#define PUPA_LINUX_MAGIC_SIGNATURE     0x53726448      /* "HdrS" */
+#define PUPA_LINUX_DEFAULT_SETUP_SECTS 4
+#define PUPA_LINUX_FLAG_CAN_USE_HEAP   0x80
+#define PUPA_LINUX_INITRD_MAX_ADDRESS  0x38000000
+#define PUPA_LINUX_MAX_SETUP_SECTS     64
+#define PUPA_LINUX_BOOT_LOADER_TYPE    0x72
+#define PUPA_LINUX_HEAP_END_OFFSET     (0x9000 - 0x200)
+
+#define PUPA_LINUX_BZIMAGE_ADDR                0x100000
+#define PUPA_LINUX_ZIMAGE_ADDR         0x10000
+#define PUPA_LINUX_OLD_REAL_MODE_ADDR  0x90000
+#define PUPA_LINUX_SETUP_STACK         0x9000
+
+#define PUPA_LINUX_FLAG_BIG_KERNEL     0x1
+
+/* Linux's video mode selection support. Actually I hate it!  */
+#define PUPA_LINUX_VID_MODE_NORMAL     0xFFFF
+#define PUPA_LINUX_VID_MODE_EXTENDED   0xFFFE
+#define PUPA_LINUX_VID_MODE_ASK                0xFFFD
+
+#define PUPA_LINUX_CL_OFFSET           0x9000
+#define PUPA_LINUX_CL_END_OFFSET       0x90FF
+#define PUPA_LINUX_SETUP_MOVE_SIZE     0x9100
+#define PUPA_LINUX_CL_MAGIC            0xA33F
+
+#ifndef ASM_FILE
+
+/* For the Linux/i386 boot protocol version 2.03.  */
+struct linux_kernel_header
+{ 
+  pupa_uint8_t code1[0x0020];
+  pupa_uint16_t cl_magic;              /* Magic number 0xA33F */
+  pupa_uint16_t cl_offset;             /* The offset of command line */
+  pupa_uint8_t code2[0x01F1 - 0x0020 - 2 - 2];
+  pupa_uint8_t setup_sects;            /* The size of the setup in sectors */
+  pupa_uint16_t root_flags;            /* If the root is mounted readonly */
+  pupa_uint16_t syssize;               /* obsolete */
+  pupa_uint16_t swap_dev;              /* obsolete */
+  pupa_uint16_t ram_size;              /* obsolete */
+  pupa_uint16_t vid_mode;              /* Video mode control */
+  pupa_uint16_t root_dev;              /* Default root device number */
+  pupa_uint16_t boot_flag;             /* 0xAA55 magic number */
+  pupa_uint16_t jump;                  /* Jump instruction */
+  pupa_uint32_t header;                        /* Magic signature "HdrS" */
+  pupa_uint16_t version;               /* Boot protocol version supported */
+  pupa_uint32_t realmode_swtch;                /* Boot loader hook */
+  pupa_uint32_t start_sys;             /* Points to kernel version string */
+  pupa_uint8_t type_of_loader;         /* Boot loader identifier */
+  pupa_uint8_t loadflags;              /* Boot protocol option flags */
+  pupa_uint16_t setup_move_size;       /* Move to high memory size */
+  pupa_uint32_t code32_start;          /* Boot loader hook */
+  pupa_uint32_t ramdisk_image;         /* initrd load address */
+  pupa_uint32_t ramdisk_size;          /* initrd size */
+  pupa_uint32_t bootsect_kludge;       /* obsolete */
+  pupa_uint16_t heap_end_ptr;          /* Free memory after setup end */
+  pupa_uint16_t pad1;                  /* Unused */
+  char *cmd_line_ptr;                  /* Points to the kernel command line */
+} __attribute__ ((packed));
+
+#endif /* ! ASM_FILE */
+
+#endif /* ! PUPA_LINUX_MACHINE_HEADER */
index d2dcc91363c162e70156754bac578faa5286bce3..b81a65c1d44f50969aa55d5c11daf442266b16b4 100644 (file)
 #include <pupa/types.h>
 #include <pupa/symbol.h>
 
+extern pupa_uint32_t EXPORT_VAR(pupa_linux_prot_size);
+extern char *EXPORT_VAR(pupa_linux_tmp_addr);
+extern char *EXPORT_VAR(pupa_linux_real_addr);
+
+void EXPORT_FUNC(pupa_linux_boot_zimage) (void) __attribute__ ((noreturn));
+void EXPORT_FUNC(pupa_linux_boot_bzimage) (void) __attribute__ ((noreturn));
+
 /* This is an asm part of the chainloader.  */
 void EXPORT_FUNC(pupa_chainloader_real_boot) (int drive, void *part_addr) __attribute__ ((noreturn));
 
index ea2d049cd5ef9cd3ab1cdf8b0c97b2e25ade0072..7d190406da92078e5839d4871c891ca74a97f3b9 100644 (file)
 #include <pupa/err.h>
 #include <pupa/types.h>
 
-void EXPORT_FUNC(pupa_loader_set) (pupa_err_t (*load_module) (int argc,
-                                                             char *argv[]),
-                                  pupa_err_t (*boot) (void),
+extern pupa_addr_t EXPORT_VAR(pupa_os_area_addr);
+extern pupa_size_t EXPORT_VAR(pupa_os_area_size);
+
+void EXPORT_FUNC(pupa_loader_set) (pupa_err_t (*boot) (void),
                                   pupa_err_t (*unload) (void));
 
-pupa_err_t EXPORT_FUNC(pupa_loader_load_module) (int argc, char *argv[]);
 pupa_err_t EXPORT_FUNC(pupa_loader_boot) (void);
 
 #endif /* ! PUPA_LOADER_HEADER */
index 8bf0cdebaaffae4c3166e94a5ec32ba666f498ec..7066aded7a6948527f768fa6fbd3292f0d877789 100644 (file)
--- a/kern/dl.c
+++ b/kern/dl.c
@@ -569,11 +569,11 @@ pupa_dl_load (const char *name)
     pupa_fatal ("module dir is not initialized yet");
 
   filename = (char *) pupa_malloc (pupa_strlen (pupa_dl_dir) + 1
-                                  + pupa_strlen (name) + 3);
+                                  + pupa_strlen (name) + 4 + 1);
   if (! filename)
     return 0;
   
-  pupa_sprintf (filename, "%s/%s.o", pupa_dl_dir, name);
+  pupa_sprintf (filename, "%s/%s.mod", pupa_dl_dir, name);
   mod = pupa_dl_load_file (filename);
   pupa_free (filename);
 
index 604cc29b2c0bc33b84ad86c3acd819bb1318bfe6..7e0db5c03d4a5de8e2a4a5023148861854202a31 100644 (file)
 #include <pupa/err.h>
 #include <pupa/dl.h>
 #include <pupa/misc.h>
+#include <pupa/loader.h>
+
+struct mem_region
+{
+  pupa_addr_t addr;
+  pupa_size_t size;
+};
+
+#define MAX_REGIONS    32
+
+static struct mem_region mem_regions[MAX_REGIONS];
+static int num_regions;
+
+pupa_addr_t pupa_os_area_addr;
+pupa_size_t pupa_os_area_size;
+pupa_size_t pupa_lower_mem, pupa_upper_mem;
 
 static char *
 make_install_device (void)
@@ -51,32 +67,79 @@ make_install_device (void)
   return pupa_prefix;
 }
 
+/* Add a memory region.  */
+static void
+add_mem_region (pupa_addr_t addr, pupa_size_t size)
+{
+  if (num_regions == MAX_REGIONS)
+    /* Ignore.  */
+    return;
+
+  mem_regions[num_regions].addr = addr;
+  mem_regions[num_regions].size = size;
+  num_regions++;
+}
+
+/* Compact memory regions.  */
+static void
+compact_mem_regions (void)
+{
+  int i, j;
+
+  /* Sort them.  */
+  for (i = 0; i < num_regions - 1; i++)
+    for (j = i + 1; j < num_regions; j++)
+      if (mem_regions[i].addr > mem_regions[j].addr)
+       {
+         struct mem_region tmp = mem_regions[i];
+         mem_regions[i] = mem_regions[j];
+         mem_regions[j] = tmp;
+       }
+
+  /* Merge overlaps.  */
+  for (i = 0; i < num_regions - 1; i++)
+    if (mem_regions[i].addr + mem_regions[i].size >= mem_regions[i + 1].addr)
+      {
+       j = i + 1;
+       
+       if (mem_regions[i].addr + mem_regions[i].size
+           < mem_regions[j].addr + mem_regions[j].size)
+         mem_regions[i].size = (mem_regions[j].addr + mem_regions[j].size
+                                - mem_regions[i].addr);
+
+       pupa_memmove (mem_regions + j, mem_regions + j + 1,
+                     (num_regions - j - 1) * sizeof (struct mem_region));
+       i--;
+      }
+}
+
 void
 pupa_machine_init (void)
 {
   pupa_uint32_t cont;
   struct pupa_machine_mmap_entry *entry
     = (struct pupa_machine_mmap_entry *) PUPA_MEMORY_MACHINE_SCRATCH_ADDR;
-  pupa_size_t lower_mem = (pupa_get_memsize (0) << 10);
   pupa_addr_t end_addr = pupa_get_end_addr ();
-
+  int i;
+  
   /* Initialize the console as early as possible.  */
   pupa_console_init ();
   
+  pupa_lower_mem = pupa_get_memsize (0) << 10;
+  
   /* Sanity check.  */
-  if (lower_mem < PUPA_MEMORY_MACHINE_RESERVED_END)
+  if (pupa_lower_mem < PUPA_MEMORY_MACHINE_RESERVED_END)
     pupa_fatal ("too small memory");
   
   /* Turn on Gate A20 to access >1MB.  */
   pupa_gate_a20 (1);
 
   /* Add the lower memory into free memory.  */
-  if (lower_mem >= PUPA_MEMORY_MACHINE_RESERVED_END)
-    pupa_mm_init_region ((void *) PUPA_MEMORY_MACHINE_RESERVED_END,
-                        lower_mem - PUPA_MEMORY_MACHINE_RESERVED_END);
+  if (pupa_lower_mem >= PUPA_MEMORY_MACHINE_RESERVED_END)
+    add_mem_region (PUPA_MEMORY_MACHINE_RESERVED_END,
+                   pupa_lower_mem - PUPA_MEMORY_MACHINE_RESERVED_END);
   
-  pupa_mm_init_region ((void *) end_addr,
-                      PUPA_MEMORY_MACHINE_RESERVED_START - end_addr);
+  add_mem_region (end_addr, PUPA_MEMORY_MACHINE_RESERVED_START - end_addr);
 
   /* Check if pupa_get_mmap_entry works.  */
   cont = pupa_get_mmap_entry (entry, 0);
@@ -104,7 +167,7 @@ pupa_machine_init (void)
            len = ((addr + entry->len > 0xFFFFFFFF)
                   ? 0xFFFFFFFF - addr
                   : (pupa_size_t) entry->len);
-           pupa_mm_init_region ((void *) addr, len);
+           add_mem_region (addr, len);
          }
        
       next:
@@ -121,20 +184,39 @@ pupa_machine_init (void)
       if (eisa_mmap)
        {
          if ((eisa_mmap & 0xFFFF) == 0x3C00)
-           pupa_mm_init_region ((void *) 0x100000,
-                                (eisa_mmap << 16) + 0x100000 * 15);
+           add_mem_region (0x100000, (eisa_mmap << 16) + 0x100000 * 15);
          else
            {
-             pupa_mm_init_region ((void *) 0x100000,
-                                  (eisa_mmap & 0xFFFF) << 10);
-             pupa_mm_init_region ((void *) 0x1000000, eisa_mmap << 16);
+             add_mem_region (0x100000, (eisa_mmap & 0xFFFF) << 10);
+             add_mem_region (0x1000000, eisa_mmap << 16);
            }
        }
       else
-       pupa_mm_init_region ((void *) 0x100000,
-                            (pupa_size_t) pupa_get_memsize (1) << 10);
+       add_mem_region (0x100000, pupa_get_memsize (1) << 10);
     }
 
+  compact_mem_regions ();
+
+  /* Add the memory regions to free memory, except for the region starting
+     from 1MB. This region is partially used for loading OS images.
+     For now, 1/4 of this is added to free memory.  */
+  for (i = 0; i < num_regions; i++)
+    if (mem_regions[i].addr == 0x100000)
+      {
+       pupa_size_t quarter = mem_regions[i].size >> 2;
+
+       pupa_upper_mem = mem_regions[i].size;
+       pupa_os_area_addr = mem_regions[i].addr;
+       pupa_os_area_size = mem_regions[i].size - quarter;
+       pupa_mm_init_region ((void *) (pupa_os_area_addr + pupa_os_area_size),
+                            quarter);
+      }
+    else
+      pupa_mm_init_region ((void *) mem_regions[i].addr, mem_regions[i].size);
+  
+  if (! pupa_os_area_addr)
+    pupa_fatal ("no upper memory");
+  
   /* The memory system was initialized, thus register built-in devices.  */
   pupa_biosdisk_init ();
 
index a1f12cf23e37665d8828a4523b522a89473114c0..cafcc3810fbe72f321eda808c687c3ff0c76ea3a 100644 (file)
@@ -49,7 +49,8 @@
 #include <pupa/machine/boot.h>
 #include <pupa/machine/memory.h>
 #include <pupa/machine/console.h>
-
+#include <pupa/machine/linux.h>
+       
 #define ABS(x) ((x) - EXT_C(start) + PUPA_BOOT_MACHINE_KERNEL_ADDR + 0x200)
        
        .file   "startup.S"
@@ -282,6 +283,71 @@ FUNCTION(pupa_chainloader_real_boot)
        .code32
 
 
+/*
+ * void pupa_linux_boot_zimage (void)
+ */
+VARIABLE(pupa_linux_prot_size)
+       .long   0
+VARIABLE(pupa_linux_tmp_addr)
+       .long   0
+VARIABLE(pupa_linux_real_addr)
+       .long   0
+       
+FUNCTION(pupa_linux_boot_zimage)
+       /* copy the kernel */
+       movl    EXT_C(pupa_linux_prot_size), %ecx
+       addl    $3, %ecx
+       shrl    $2, %ecx
+       movl    $PUPA_LINUX_BZIMAGE_ADDR, %esi
+       movl    $PUPA_LINUX_ZIMAGE_ADDR, %edi
+       cld
+       rep
+       movsl
+
+FUNCTION(pupa_linux_boot_bzimage)
+       call    EXT_C(pupa_dl_unload_all)
+       
+       movl    EXT_C(pupa_linux_real_addr), %ebx
+
+       /* copy the real mode code */
+       movl    EXT_C(pupa_linux_tmp_addr), %esi
+       movl    %ebx, %edi
+       movl    $PUPA_LINUX_SETUP_MOVE_SIZE, %ecx
+       cld
+       rep
+       movsb
+
+       /* change %ebx to the segment address */
+       shrl    $4, %ebx
+       movl    %ebx, %eax
+       addl    $0x20, %eax
+       movw    %ax, linux_setup_seg
+
+       /* XXX new stack pointer in safe area for calling functions */
+       movl    $0x4000, %esp
+       call    EXT_C(pupa_stop_floppy)
+
+       /* final setup for linux boot */
+       call    prot_to_real
+       .code16
+
+       cli
+       movw    %bx, %ss
+       movw    $PUPA_LINUX_SETUP_STACK, %sp
+
+       movw    %bx, %ds
+       movw    %bx, %es
+       movw    %bx, %fs
+       movw    %bx, %gs
+
+       /* ljmp */
+       .byte   0xea
+       .word   0
+linux_setup_seg:
+       .word   0
+       .code32
+
+               
 /*
  *  These next two routines, "real_to_prot" and "prot_to_real" are structured
  *  in a very specific way.  Be very careful when changing them.
index f7d8ebc89fa2b7b20c3cd452024646af39067902..65ee654bf4445259d79c9e83497fe35a504a675c 100644 (file)
 #include <pupa/mm.h>
 #include <pupa/err.h>
 
-static pupa_err_t (*pupa_loader_load_module_func) (int argc, char *argv[]);
 static pupa_err_t (*pupa_loader_boot_func) (void);
 static pupa_err_t (*pupa_loader_unload_func) (void);
 
 static int pupa_loader_loaded;
 
 void
-pupa_loader_set (pupa_err_t (*load_module) (int argc, char *argv[]),
-                pupa_err_t (*boot) (void),
+pupa_loader_set (pupa_err_t (*boot) (void),
                 pupa_err_t (*unload) (void))
 {
   if (pupa_loader_loaded && pupa_loader_unload_func)
     if (pupa_loader_unload_func () != PUPA_ERR_NONE)
       return;
   
-  pupa_loader_load_module_func = load_module;
   pupa_loader_boot_func = boot;
   pupa_loader_unload_func = unload;
 
   pupa_loader_loaded = 1;
 }
 
-pupa_err_t
-pupa_loader_load_module (int argc, char *argv[])
-{
-  if (! pupa_loader_loaded)
-    return pupa_error (PUPA_ERR_NO_KERNEL, "no loaded kernel");
-
-  if (! pupa_loader_load_module_func)
-    return pupa_error (PUPA_ERR_BAD_OS, "module not supported");
-
-  return pupa_loader_load_module_func (argc, argv);
-}
-
 pupa_err_t
 pupa_loader_boot (void)
 {
index 80eb6f7f18346f609bc5b0567c4d376e6ab84a6f..a870b84e4f2d802ae750376aac59e0f0b4a2b015 100644 (file)
@@ -25,6 +25,8 @@
 #include <pupa/dl.h>
 #include <pupa/term.h>
 #include <pupa/rescue.h>
+#include <pupa/file.h>
+#include <pupa/device.h>
 
 /* Return the end of the core image.  */
 pupa_addr_t
index 5f8e6c9fe9d6880fd882f4d0d5f695a32ae9a557..7ba30fcb01fb18edb3e27f29f51fdeec0342a974 100644 (file)
--- a/kern/mm.c
+++ b/kern/mm.c
@@ -24,6 +24,7 @@
 #include <pupa/err.h>
 #include <pupa/types.h>
 #include <pupa/disk.h>
+#include <pupa/dl.h>
 
 /* Magic words.  */
 #define PUPA_MM_FREE_MAGIC     0x2d3c2808
@@ -95,6 +96,10 @@ pupa_mm_init_region (void *addr, pupa_size_t size)
   pupa_mm_header_t h;
   pupa_mm_region_t r, *p, q;
 
+#if 0
+  pupa_printf ("%s:%d: addr=%p, size=%u\n", __FILE__, __LINE__, addr, size);
+#endif
+  
   /* If this region is too small, ignore it.  */
   if (size < PUPA_MM_ALIGN * 2)
     return;
index abec3503401528efa7f446e7d78c1efe5249fff9..36b197998a94c1b21240b1598b4a37cab469e1ff 100644 (file)
@@ -337,13 +337,6 @@ pupa_rescue_cmd_info (void)
 }
 #endif
 
-/* (module|initrd) FILE [ARGS] */
-static void
-pupa_rescue_cmd_module (int argc, char *argv[])
-{
-  pupa_loader_load_module (argc, argv);
-}
-
 /* root [DEVICE] */
 static void
 pupa_rescue_cmd_root (int argc, char *argv[])
@@ -607,12 +600,8 @@ pupa_enter_rescue_mode (void)
                                "show the contents of a file");
   pupa_rescue_register_command ("help", pupa_rescue_cmd_help,
                                "show this message");
-  pupa_rescue_register_command ("initrd", pupa_rescue_cmd_module,
-                               "load an initrd");
   pupa_rescue_register_command ("ls", pupa_rescue_cmd_ls,
                                "list devices or files");
-  pupa_rescue_register_command ("module", pupa_rescue_cmd_module,
-                               "load an OS module");
   pupa_rescue_register_command ("root", pupa_rescue_cmd_root,
                                "set the root device");
   pupa_rescue_register_command ("dump", pupa_rescue_cmd_dump,
index cfcc88dbb88ea746d77e8709471fd60442f3f355..5562bb289fb776906f1ddd29dc4678efcf53b71e 100644 (file)
@@ -32,9 +32,6 @@
 #include <pupa/rescue.h>
 #include <pupa/dl.h>
 
-/* 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
@@ -81,6 +78,7 @@ static pupa_err_t
 pupa_chainloader_unload (void)
 {
   pupa_dl_unref (my_mod);
+  return PUPA_ERR_NONE;
 }
 
 static void
@@ -110,8 +108,8 @@ pupa_rescue_cmd_chainloader (int argc, char *argv[])
     goto fail;
 
   /* Read the first block.  */
-  if (pupa_file_read (file, pupa_chainloader_boot_sector,
-                     PUPA_DISK_SECTOR_SIZE) != PUPA_DISK_SECTOR_SIZE)
+  if (pupa_file_read (file, (char *) 0x7C00, PUPA_DISK_SECTOR_SIZE)
+      != PUPA_DISK_SECTOR_SIZE)
     {
       if (pupa_errno == PUPA_ERR_NONE)
        pupa_error (PUPA_ERR_BAD_OS, "too small");
@@ -120,8 +118,7 @@ pupa_rescue_cmd_chainloader (int argc, char *argv[])
     }
 
   /* Check the signature.  */
-  signature = *((pupa_uint16_t *) (pupa_chainloader_boot_sector
-                                  + PUPA_DISK_SECTOR_SIZE - 2));
+  signature = *((pupa_uint16_t *) (0x7C00 + PUPA_DISK_SECTOR_SIZE - 2));
   if (signature != pupa_le_to_cpu16 (0xaa55) && ! force)
     {
       pupa_error (PUPA_ERR_BAD_OS, "invalid signature");
@@ -129,7 +126,7 @@ pupa_rescue_cmd_chainloader (int argc, char *argv[])
     }
 
   pupa_file_close (file);
-  pupa_loader_set (0, pupa_chainloader_boot, pupa_chainloader_unload);
+  pupa_loader_set (pupa_chainloader_boot, pupa_chainloader_unload);
   return;
   
  fail:
diff --git a/loader/i386/pc/linux.c b/loader/i386/pc/linux.c
new file mode 100644 (file)
index 0000000..8dbffe8
--- /dev/null
@@ -0,0 +1,306 @@
+/* linux.c - boot Linux zImage or bzImage */
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 1999,2000,2001,2002  Free Software Foundation, Inc.
+ *  Copyright (C) 2003  Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  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.
+ */
+
+#include <pupa/loader.h>
+#include <pupa/machine/loader.h>
+#include <pupa/file.h>
+#include <pupa/err.h>
+#include <pupa/device.h>
+#include <pupa/disk.h>
+#include <pupa/misc.h>
+#include <pupa/types.h>
+#include <pupa/machine/init.h>
+#include <pupa/machine/memory.h>
+#include <pupa/rescue.h>
+#include <pupa/dl.h>
+#include <pupa/machine/linux.h>
+
+static pupa_dl_t my_mod;
+
+static int big_linux;
+static pupa_size_t linux_mem_size;
+static int loaded;
+
+static pupa_err_t
+pupa_linux_boot (void)
+{
+  if (big_linux)
+    pupa_linux_boot_bzimage ();
+  else
+    pupa_linux_boot_zimage ();
+
+  /* Never reach here.  */
+  return PUPA_ERR_NONE;
+}
+
+static pupa_err_t
+pupa_linux_unload (void)
+{
+  pupa_dl_unref (my_mod);
+  loaded = 0;
+  return PUPA_ERR_NONE;
+}
+
+static void
+pupa_rescue_cmd_linux (int argc, char *argv[])
+{
+  pupa_file_t file = 0;
+  struct linux_kernel_header lh;
+  pupa_uint8_t setup_sects;
+  pupa_size_t real_size, prot_size;
+  int i;
+  char *dest;
+
+  pupa_dl_ref (my_mod);
+  
+  if (argc == 0)
+    {
+      pupa_error (PUPA_ERR_BAD_ARGUMENT, "no kernel specified");
+      goto fail;
+    }
+
+  file = pupa_file_open (argv[0]);
+  if (! file)
+    goto fail;
+
+  if (pupa_file_size (file) > (pupa_ssize_t) pupa_os_area_size)
+    {
+      pupa_error (PUPA_ERR_OUT_OF_RANGE, "too big kernel");
+      goto fail;
+    }
+
+  if (pupa_file_read (file, (char *) &lh, sizeof (lh)) != sizeof (lh))
+    {
+      pupa_error (PUPA_ERR_READ_ERROR, "cannot read the linux header");
+      goto fail;
+    }
+
+  if (lh.boot_flag != pupa_cpu_to_le16 (0xaa55))
+    {
+      pupa_error (PUPA_ERR_BAD_OS, "invalid magic number");
+      goto fail;
+    }
+
+  if (lh.setup_sects > PUPA_LINUX_MAX_SETUP_SECTS)
+    {
+      pupa_error (PUPA_ERR_BAD_OS, "too many setup sectors");
+      goto fail;
+    }
+
+  big_linux = 0;
+  setup_sects = lh.setup_sects;
+  linux_mem_size = 0;
+  
+  if (lh.header == pupa_cpu_to_le32 (PUPA_LINUX_MAGIC_SIGNATURE)
+      && pupa_le_to_cpu16 (lh.version) >= 0x0200)
+    {
+      big_linux = (lh.loadflags & PUPA_LINUX_FLAG_BIG_KERNEL);
+      lh.type_of_loader = PUPA_LINUX_BOOT_LOADER_TYPE;
+      
+      /* Put the real mode part at as a high location as possible.  */
+      pupa_linux_real_addr = (char *) (pupa_lower_mem
+                                      - PUPA_LINUX_SETUP_MOVE_SIZE);
+      /* But it must not exceed the traditional area.  */
+      if (pupa_linux_real_addr > (char *) PUPA_LINUX_OLD_REAL_MODE_ADDR)
+       pupa_linux_real_addr = (char *) PUPA_LINUX_OLD_REAL_MODE_ADDR;
+      
+      if (pupa_le_to_cpu16 (lh.version) >= 0x0201)
+       {
+         lh.heap_end_ptr = pupa_cpu_to_le16 (PUPA_LINUX_HEAP_END_OFFSET);
+         lh.loadflags |= PUPA_LINUX_FLAG_CAN_USE_HEAP;
+       }
+      
+      if (pupa_le_to_cpu16 (lh.version) >= 0x0202)
+       lh.cmd_line_ptr = pupa_linux_real_addr + PUPA_LINUX_CL_OFFSET;
+      else
+       {
+         lh.cl_magic = pupa_cpu_to_le16 (PUPA_LINUX_CL_MAGIC);
+         lh.cl_offset = pupa_cpu_to_le16 (PUPA_LINUX_CL_OFFSET);
+         lh.setup_move_size = pupa_cpu_to_le16 (PUPA_LINUX_SETUP_MOVE_SIZE);
+       }
+    }
+  else
+    {
+      /* Your kernel is quite old...  */
+      lh.cl_magic = pupa_cpu_to_le16 (PUPA_LINUX_CL_MAGIC);
+      lh.cl_offset = pupa_cpu_to_le16 (PUPA_LINUX_CL_OFFSET);
+      
+      setup_sects = PUPA_LINUX_DEFAULT_SETUP_SECTS;
+      
+      pupa_linux_real_addr = (char *) PUPA_LINUX_OLD_REAL_MODE_ADDR;
+    }
+  
+  /* If SETUP_SECTS is not set, set it to the default (4).  */
+  if (! setup_sects)
+    setup_sects = PUPA_LINUX_DEFAULT_SETUP_SECTS;
+  
+  real_size = setup_sects << PUPA_DISK_SECTOR_BITS;
+  prot_size = pupa_file_size (file) - real_size - PUPA_DISK_SECTOR_SIZE;
+  
+  pupa_linux_tmp_addr = (char *) PUPA_LINUX_BZIMAGE_ADDR + prot_size;
+
+  if (! big_linux
+      && prot_size > (pupa_size_t) (pupa_linux_real_addr
+                                   - (char *) PUPA_LINUX_ZIMAGE_ADDR))
+    {
+      pupa_error (PUPA_ERR_BAD_OS, "too big zImage, use bzImage instead");
+      goto fail;
+    }
+  
+  if (pupa_linux_real_addr + PUPA_LINUX_SETUP_MOVE_SIZE
+      > (char *) pupa_lower_mem)
+    {
+      pupa_error (PUPA_ERR_OUT_OF_RANGE, "too small lower memory");
+      goto fail;
+    }
+
+  pupa_printf ("   [Linux-%s, setup=0x%x, size=0x%x]\n",
+              big_linux ? "bzImage" : "zImage", real_size, prot_size);
+
+  for (i = 1; i < argc; i++)
+    if (pupa_memcmp (argv[i], "vga=", 4) == 0)
+      {
+       /* Video mode selection support.  */
+       pupa_uint16_t vid_mode;
+       char *val = argv[i] + 4;
+
+       if (pupa_strcmp (val, "normal") == 0)
+         vid_mode = PUPA_LINUX_VID_MODE_NORMAL;
+       else if (pupa_strcmp (val, "ext") == 0)
+         vid_mode = PUPA_LINUX_VID_MODE_EXTENDED;
+       else if (pupa_strcmp (val, "ask") == 0)
+         vid_mode = PUPA_LINUX_VID_MODE_ASK;
+       else
+         vid_mode = (pupa_uint16_t) pupa_strtoul (val, 0, 0);
+
+       if (pupa_errno)
+         goto fail;
+
+       lh.vid_mode = pupa_cpu_to_le16 (vid_mode);
+      }
+    else if (pupa_memcmp (argv[i], "mem=", 4) == 0)
+      {
+       char *val = argv[i] + 4;
+         
+       linux_mem_size = pupa_strtoul (val, &val, 0);
+       
+       if (pupa_errno)
+         {
+           pupa_errno = PUPA_ERR_NONE;
+           linux_mem_size = 0;
+         }
+       else
+         {
+           int shift = 0;
+           
+           switch (pupa_tolower (val[0]))
+             {
+             case 'g':
+               shift += 10;
+             case 'm':
+               shift += 10;
+             case 'k':
+               shift += 10;
+             default:
+               break;
+             }
+
+           /* Check an overflow.  */
+           if (linux_mem_size > (~0UL >> shift))
+             linux_mem_size = 0;
+           else
+             linux_mem_size <<= shift;
+         }
+      }
+
+  /* Put the real mode code at the temporary address.  */
+  pupa_memmove (pupa_linux_tmp_addr, &lh, sizeof (lh));
+  pupa_file_read (file, pupa_linux_tmp_addr + sizeof (lh),
+                 real_size + PUPA_DISK_SECTOR_SIZE - sizeof (lh));
+
+  if (lh.header != pupa_cpu_to_le32 (PUPA_LINUX_MAGIC_SIGNATURE)
+      || pupa_le_to_cpu16 (lh.version) < 0x0200)
+    /* Clear the heap space.  */
+    pupa_memset (pupa_linux_tmp_addr
+                + ((setup_sects + 1) << PUPA_DISK_SECTOR_BITS),
+                0,
+                ((PUPA_LINUX_MAX_SETUP_SECTS - setup_sects - 1)
+                 << PUPA_DISK_SECTOR_BITS));
+
+  /* Copy kernel parameters.  */
+  for (i = 1, dest = pupa_linux_tmp_addr + PUPA_LINUX_CL_OFFSET;
+       i < argc
+        && dest + pupa_strlen (argv[i]) < (pupa_linux_tmp_addr
+                                           + PUPA_LINUX_CL_END_OFFSET);
+       i++, *dest++ = ' ')
+    {
+      pupa_strcpy (dest, argv[i]);
+      dest += pupa_strlen (argv[i]);
+    }
+
+  if (i != 1)
+    dest--;
+
+  *dest = '\0';
+
+  pupa_file_read (file, (char *) PUPA_LINUX_BZIMAGE_ADDR, prot_size);
+  
+  if (pupa_errno == PUPA_ERR_NONE)
+    {
+      pupa_linux_prot_size = prot_size;
+      pupa_loader_set (pupa_linux_boot, pupa_linux_unload);
+      loaded = 1;
+    }
+
+ fail:
+  
+  if (file)
+    pupa_file_close (file);
+
+  if (pupa_errno != PUPA_ERR_NONE)
+    {
+      pupa_dl_unref (my_mod);
+      loaded = 0;
+    }
+}
+
+static void
+pupa_rescue_cmd_initrd (int argc, char *argv[])
+{
+  pupa_error (PUPA_ERR_NOT_IMPLEMENTED_YET, "not implemented yet");
+}
+
+PUPA_MOD_INIT
+{
+  pupa_rescue_register_command ("linux",
+                               pupa_rescue_cmd_linux,
+                               "load linux");
+  pupa_rescue_register_command ("initrd",
+                               pupa_rescue_cmd_initrd,
+                               "load initrd");
+  my_mod = mod;
+}
+
+PUPA_MOD_FINI
+{
+  pupa_rescue_unregister_command ("linux");
+  pupa_rescue_unregister_command ("initrd");
+}