]> Zhao Yanbai Git Server - minix.git/commitdiff
boot: Add multiboot support
authorArun Thomas <arun@minix3.org>
Fri, 24 Jun 2011 15:20:25 +0000 (17:20 +0200)
committerArun Thomas <arun@minix3.org>
Fri, 24 Jun 2011 15:21:51 +0000 (17:21 +0200)
Not yet fully spec-compliant; work in progress

31 files changed:
boot/boot/Makefile
boot/boot/boot.c
boot/boot/boothead.s
boot/boot/bootimage.c
commands/mkimage/Makefile [new file with mode: 0644]
commands/mkimage/mkimage.c [new file with mode: 0644]
drivers/log/Makefile
drivers/memory/Makefile
drivers/tty/Makefile
include/arch/i386/Makefile
include/arch/i386/multiboot.h [moved from kernel/arch/i386/multiboot.h with 99% similarity]
kernel/arch/i386/arch_system.c
kernel/arch/i386/kernel_elf.lds [new file with mode: 0644]
kernel/arch/i386/klib.S
kernel/arch/i386/klib16.S
kernel/arch/i386/mpx.S
kernel/arch/i386/multiboot.S
kernel/arch/i386/pre_init.c
lib/libexec/exec_elf.c
servers/ds/Makefile
servers/init/Makefile
servers/mfs/Makefile
servers/pfs/Makefile
servers/pm/Makefile
servers/rs/Makefile
servers/sched/Makefile
servers/vfs/Makefile
servers/vm/Makefile
share/mk/Makefile
share/mk/minix.bootprog.mk [new file with mode: 0644]
tools/Makefile

index c2432003d5d9999bf889c15a9571eec34e50b03e..8a4c53770d58dc1a692a76d1c52a0fe0fbf9af33 100644 (file)
@@ -11,7 +11,10 @@ LIBDIR?=     /usr/lib/i86
 PROG=  boot
 
 SRCS=          boothead.s boot.c bootimage.c rawfs.c
-.PATH: ${.CURDIR}/..
+# Need exec_elf.c from libexec
+SRCS+=         exec_elf.c
+.PATH: ${.CURDIR}/.. ${MINIXSRCDIR}/lib/libexec
+
 CPPFLAGS+=     -I${MINIXSRCDIR} -I${.CURDIR} -I${.CURDIR}/..
 
 DPADD+=        ${LIBSYS}       # for kprintf, kmalloc
index 6337030987dc664570fded22edb45f4063164b76..cec2f29bc7e303513900a52103985377ce46ffad 100644 (file)
@@ -500,6 +500,9 @@ struct biosdev {
        int device, primary, secondary;
 } bootdev, tmpdev;
 
+/* Device number in multiboot format <drive, part1, part2, part3> */
+u32_t mbdev;
+
 static int get_master(char *master, struct part_entry **table, u32_t pos)
 /* Read a master boot sector and its partition table. */
 {
@@ -1225,6 +1228,11 @@ dev_t name2dev(char *name)
                }
        }
 
+       mbdev = (u32_t)tmpdev.device << 24
+           | (u32_t)tmpdev.primary << 16
+           | (u32_t)tmpdev.secondary << 8
+           | 0xff;
+
        /* Look the name up on the boot device for the UNIX device number. */
        if (fsok == -1) fsok= r_super(&block_size) != 0;
        if (fsok) {
index 0c7a348f55b58e938d273c3a22363cf31f6ba810..01e203067f1a53e78272d8f7bd2da3c9de53e93b 100644 (file)
@@ -35,6 +35,9 @@
 
        ESC         =     0x1B  ! Escape character
 
+       MB_BOOT_MAGIC   =         0x2BADB002    ! Multiboot BootLoader Magic
+       MULTIBOOT_STRUCT_ADDR   =       0x9500  ! Multiboot Struct's Location
+
 ! Imported variables and functions:
 .extern _caddr, _daddr, _runsize, _edata, _end ! Runtime environment
 .extern _device                                        ! BIOS device number
@@ -45,6 +48,7 @@
 .extern _mem_entries                           ! Free memory E820 list entries
 .extern _cdbooted                              ! Whether we booted from CD
 .extern _cddevice                              ! Whether we booted from CD
+.extern _do_multiboot                          ! Whether we are multibooting
 
 .text
 
@@ -1157,22 +1161,26 @@ minix386:
        mov     p_gdt_desc+2, ax
        movb    p_gdt_desc+4, dl ! Set base of global descriptor table
 
+       cmp     _do_multiboot, #1
+       je      set_monss
+
        mov     ax, 12(bp)
        mov     dx, 14(bp)      ! Kernel ds (absolute address)
        mov     p_ds_desc+2, ax
        movb    p_ds_desc+4, dl ! Set base of kernel data segment
 
+       mov     ax, 8(bp)
+       mov     dx, 10(bp)      ! Kernel cs (absolute address)
+       mov     p_cs_desc+2, ax
+       movb    p_cs_desc+4, dl
+
+set_monss:
        mov     dx, ss          ! Monitor ss
        xor     ax, ax          ! dx:ax = Monitor stack segment
        call    seg2abs         ! Minix starts with the stack of the monitor
        mov     p_ss_desc+2, ax
        movb    p_ss_desc+4, dl
 
-       mov     ax, 8(bp)
-       mov     dx, 10(bp)      ! Kernel cs (absolute address)
-       mov     p_cs_desc+2, ax
-       movb    p_cs_desc+4, dl
-
        mov     dx, cs          ! Monitor cs
        xor     ax, ax          ! dx:ax = Monitor code segment
        call    seg2abs
@@ -1207,13 +1215,29 @@ noret386:
        push    6(bp)
        push    4(bp)           ! 32 bit far address to kernel entry point
 
+       cmp     _do_multiboot, #1
+       je      multiboot
+
+       call    real2prot       ! Switch to protected mode
+       mov     ax, #DS_SELECTOR ! Kernel data
+       mov     ds, ax
+       mov     ax, #ES_SELECTOR ! Flat 4 Gb
+       mov     es, ax
+
+       .data1  o32             ! Make a far call to the kernel
+       retf
+
+multiboot:
        call    real2prot       ! Switch to protected mode
        mov     ax, #DS_SELECTOR ! Kernel data
        mov     ds, ax
        mov     ax, #ES_SELECTOR ! Flat 4 Gb
        mov     es, ax
-       .data1  o32             ! Make a far call to the kernel
-       retf
+!      mov     fs, ax
+!      mov     gs, ax
+       mov     bx, #MULTIBOOT_STRUCT_ADDR
+       .data1  o32             ! Make a far call to the kernel
+       retf
 
 ! Minix-86 returns here on a halt or reboot.
 ret86:
index f2274176d24fd9d12c9af21085b09e11ccaf0983..2ab16272e3af403a0581cc9d701fbc14259c2caf 100644 (file)
@@ -8,6 +8,7 @@
 #include <stddef.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/param.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <limits.h>
 #include "image.h"
 #include "boot.h"
 
+#include <machine/multiboot.h>
+#include <machine/elf.h>
+
+
 static int block_size = 0;
 static int verboseboot = VERBOSEBOOT_QUIET;
 
@@ -40,6 +45,7 @@ extern int serial_line;
 extern u16_t vid_port;         /* Video i/o port. */
 extern u32_t vid_mem_base;     /* Video memory base address. */
 extern u32_t vid_mem_size;     /* Video memory size. */
+extern u32_t mbdev;            /* Device number in multiboot format */
 
 #define click_shift    clck_shft       /* 7 char clash with click_size. */
 
@@ -82,9 +88,17 @@ int n_procs;                 /* Number of processes. */
 #define P_SIZ_OFF      0       /* Process' sizes into kernel data. */
 #define P_INIT_OFF     4       /* Init cs & sizes into fs data. */
 
+/* Where multiboot info struct goes in memory */
+#define MULTIBOOT_INFO_ADDR 0x9500
 
 #define between(a, c, z)       ((unsigned) ((c) - (a)) <= ((z) - (a)))
 
+char *select_image(char *image);
+size_t strspn(const char *string, const char *in);
+char * strpbrk(register const char *string, register const char *brk);
+char * strtok(register char *string, const char *separators);
+char * strdup(const char *s1);
+
 void pretty_image(const char *image)
 /* Pretty print the name of the image to load.  Translate '/' and '_' to
  * space, first letter goes uppercase.  An 'r' before a digit prints as
@@ -141,6 +155,7 @@ unsigned click_shift;
 unsigned click_size;   /* click_size = Smallest kernel memory object. */
 unsigned k_flags;      /* Not all kernels are created equal. */
 u32_t reboot_code;     /* Obsolete reboot code return pointer. */
+int do_multiboot;
 
 int params2params(char *params, size_t psize)
 /* Repackage the environment settings for the kernel. */
@@ -262,7 +277,7 @@ static u32_t proc_size(const struct image_header *hdr)
        return len >> SECTOR_SHIFT;
 }
 
-off_t image_off, image_size;
+off_t image_off, image_sectors, image_bytes;
 u32_t (*vir2sec)(u32_t vsec);  /* Where is a sector on disk? */
 
 u32_t file_vir2sec(u32_t vsec)
@@ -379,7 +394,7 @@ int get_segment(u32_t *vsec, long *size, u32_t *addr, u32_t limit)
                        cnt= SECTOR_SIZE;
                }
                if (*addr + click_size > limit) 
-               { 
+               {
                        DEBUGEXTRA(("get_segment: out of memory; "
                                "addr=0x%lx; limit=0x%lx; size=%lx\n", 
                                *addr, limit, size));
@@ -444,6 +459,256 @@ static void restore_screen(void)
         }
 }
 
+int split_module_list(char *modules)
+{
+       int i;
+       char *c, *s;
+
+       for (s= modules, i= 1; (c= strrchr(s, ' ')) != NULL; i++) {
+           *c = '\0';
+       }
+
+       return i;
+}
+
+void exec_mb(char *kernel, char* modules)
+/* Get a Minix image into core, patch it up and execute. */
+{
+       int i;
+       static char hdr[SECTOR_SIZE];
+       char *buf;
+       u32_t vsec, addr, limit, n, totalmem = 0;
+       u16_t kmagic, mode;
+       char *console;
+       char params[SECTOR_SIZE];
+       extern char *sbrk(int);
+       char *verb;
+       u32_t text_vaddr, text_paddr, text_filebytes, text_membytes;
+       u32_t data_vaddr, data_paddr, data_filebytes, data_membytes;
+       u32_t pc;
+       u32_t text_offset, data_offset;
+       i32_t segsize;
+       int r;
+       u32_t cs, ds;
+       char *modstring, *mod;
+       multiboot_info_t *mbinfo;
+       multiboot_module_t *mbmodinfo;
+       u32_t mbinfo_size, mbmodinfo_size;
+       char *memvar;
+       memory *mp;
+       u32_t mod_cmdline_start, kernel_cmdline_start;
+       u32_t modstringlen;
+       int modnr;
+
+       /* The stack is pretty deep here, so check if heap and stack collide. */
+       (void) sbrk(0);
+
+       if ((verb= b_value(VERBOSEBOOTVARNAME)) != nil)
+               verboseboot = a2l(verb);
+
+       printf("\nLoading %s\n", kernel);
+
+       vsec= 0;                        /* Load this sector from kernel next. */
+       addr= mem[0].base;              /* Into this memory block. */
+       limit= mem[0].base + mem[0].size;
+       if (limit > caddr) limit= caddr;
+
+       /* set click size for get_segment */
+       click_size = PAGE_SIZE;
+
+       k_flags = K_KHIGH|K_BRET|K_MEML|K_INT86|K_RET|K_HDR
+           |K_HIGH|K_CHMEM|K_I386;
+
+       /* big kernels must be loaded into extended memory */
+       addr= mem[1].base;
+       limit= mem[1].base + mem[1].size;
+
+       /* Get first sector */
+       DEBUGEXTRA(("get_sector\n"));
+       if ((buf= get_sector(vsec++)) == nil) {
+           DEBUGEXTRA(("get_sector failed\n"));
+           return;
+       }
+       memcpy(hdr, buf, SECTOR_SIZE);
+
+       /* Get ELF header */
+       DEBUGEXTRA(("read_header_elf\n"));
+       r = read_header_elf(hdr, &text_vaddr, &text_paddr,
+                           &text_filebytes, &text_membytes,
+                           &data_vaddr, &data_paddr,
+                           &data_filebytes, &data_membytes,
+                           &pc, &text_offset, &data_offset);
+       if (r < 0) { errno= ENOEXEC; return; }
+
+       /* Read the text segment. */
+       addr = text_paddr;
+       segsize = (i32_t) text_filebytes;
+       vsec = text_offset / SECTOR_SIZE;
+       DEBUGEXTRA(("get_segment(0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
+                   vsec, segsize, addr, limit));
+       if (!get_segment(&vsec, &segsize, &addr, limit)) return;
+       DEBUGEXTRA(("get_segment done vsec=0x%lx size=0x%lx "
+                   "addr=0x%lx\n",
+                   vsec, segsize, addr));
+
+       /* Read the data segment. */
+       addr = data_paddr;
+       segsize = (i32_t) data_filebytes;
+       vsec = data_offset / SECTOR_SIZE;
+
+       DEBUGEXTRA(("get_segment(0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
+                   vsec, segsize, addr, limit));
+       if (!get_segment(&vsec, &segsize, &addr, limit)) return;
+       DEBUGEXTRA(("get_segment done vsec=0x%lx size=0x%lx "
+                   "addr=0x%lx\n",
+                   vsec, segsize, addr));
+
+       n = data_membytes - align(data_filebytes, click_size);
+
+       /* Zero out bss. */
+       DEBUGEXTRA(("\nraw_clear(0x%lx, 0x%lx); limit=0x%lx... ", addr, n, limit));
+       if (addr + n > limit) { errno= ENOMEM; return; }
+       raw_clear(addr, n);
+       DEBUGEXTRA(("done\n"));
+       addr+= n;
+
+       /* Check the kernel magic number. */
+       raw_copy(mon2abs(&kmagic),
+                data_paddr + MAGIC_OFF, sizeof(kmagic));
+       if (kmagic != KERNEL_D_MAGIC) {
+               printf("Kernel magic number is incorrect (0x%x@0x%lx)\n",
+                       kmagic, data_paddr + MAGIC_OFF);
+               errno= 0;
+               return;
+       }
+
+       /* Translate the boot parameters to what Minix likes best. */
+       DEBUGEXTRA(("params2params(0x%x, 0x%x)... ", params, sizeof(params)));
+       if (!params2params(params, sizeof(params))) { errno= 0; return; }
+       DEBUGEXTRA(("done\n"));
+
+       /* Create multiboot info struct */
+       mbinfo = malloc(sizeof(multiboot_info_t));
+       if (mbinfo == nil) { errno= ENOMEM; return; }
+       memset(mbinfo, 0, sizeof(multiboot_info_t));
+
+       /* Module info structs start where kernel ends */
+       mbinfo->mods_addr = addr;
+
+       modstring = strdup(modules);
+       if (modstring == nil) {errno = ENOMEM; return; }
+       modstringlen = strlen(modules);
+       mbinfo->mods_count = split_module_list(modules);
+
+       mbmodinfo_size = sizeof(multiboot_module_t) * mbinfo->mods_count;
+       mbmodinfo = malloc(mbmodinfo_size);
+       if (mbmodinfo == nil) { errno= ENOMEM; return; }
+       addr+= mbmodinfo_size;
+       addr= align(addr, click_size);
+
+       mod_cmdline_start = mbinfo->mods_addr + sizeof(multiboot_module_t) *
+           mbinfo->mods_count;
+
+       raw_copy(mod_cmdline_start, mon2abs(modules),
+                modstringlen+1);
+
+       mbmodinfo[0].cmdline = mod_cmdline_start;
+       modnr = 1;
+       for (i= 0; i < modstringlen; ++i) {
+           if (modules[i] == '\0') {
+               mbmodinfo[modnr].cmdline = mod_cmdline_start + i + 1;
+               ++modnr;
+           }
+       }
+
+       kernel_cmdline_start = mod_cmdline_start + modstringlen + 1;
+       mbinfo->cmdline = kernel_cmdline_start;
+       raw_copy(kernel_cmdline_start, mon2abs(kernel),
+                strlen(kernel)+1);
+
+       mbinfo->flags = MULTIBOOT_INFO_MODS|MULTIBOOT_INFO_CMDLINE|
+           MULTIBOOT_INFO_BOOTDEV|MULTIBOOT_INFO_MEMORY;
+
+       mbinfo->boot_device = mbdev;
+       mbinfo->mem_lower = mem[0].size/1024;
+       mbinfo->mem_upper = mem[1].size/1024;
+
+       for (i = 0, mod = strtok(modstring, " "); mod != nil;
+            mod = strtok(nil, " "), i++) {
+
+               mod = select_image(mod);
+               if (mod == nil) {errno = 0; return; }
+
+               mbmodinfo[i].mod_start = addr;
+               mbmodinfo[i].mod_end = addr + image_bytes;
+               mbmodinfo[i].pad = 0;
+
+               segsize= image_bytes;
+               vsec= 0;
+               DEBUGEXTRA(("get_segment(0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
+                      vsec, segsize, addr, limit));
+               if (!get_segment(&vsec, &segsize, &addr, limit)) return;
+               DEBUGEXTRA(("get_segment done vsec=0x%lx size=0x%lx "
+                      "addr=0x%lx\n",
+                      vsec, segsize, addr));
+               addr+= segsize;
+               addr= align(addr, click_size);
+       }
+       free(modstring);
+
+       DEBUGEXTRA(("modinfo raw_copy: dst 0x%lx src 0x%lx sz 0x%lx\n",
+           mbinfo->mods_addr, mon2abs(mbmodinfo),
+           mbmodinfo_size));
+       raw_copy(mbinfo->mods_addr, mon2abs(mbmodinfo),
+           mbmodinfo_size);
+       free(mbmodinfo);
+
+       raw_copy(MULTIBOOT_INFO_ADDR, mon2abs(mbinfo),
+                sizeof(multiboot_info_t));
+       free(mbinfo);
+
+       /* Run the trailer function just before starting Minix. */
+       DEBUGEXTRA(("run_trailer()... "));
+       if (!run_trailer()) { errno= 0; return; }
+       DEBUGEXTRA(("done\n"));
+
+       /* Set the video to the required mode. */
+       if ((console= b_value("console")) == nil || (mode= a2x(console)) == 0) {
+               mode= strcmp(b_value("chrome"), "color") == 0 ? COLOR_MODE :
+                                                               MONO_MODE;
+       }
+       DEBUGEXTRA(("set_mode(%d)... ", mode));
+       set_mode(mode);
+       DEBUGEXTRA(("done\n"));
+
+       /* Close the disk. */
+       DEBUGEXTRA(("dev_close()... "));
+       (void) dev_close();
+       DEBUGEXTRA(("done\n"));
+
+       /* Minix. */
+       cs = ds = text_paddr;
+       DEBUGEXTRA(("minix(0x%lx, 0x%lx, 0x%lx, 0x%x, 0x%x, 0x%lx)\n",
+               pc, cs, ds, params, sizeof(params), 0));
+       minix(pc, cs, ds, params, sizeof(params), 0);
+
+       if (!(k_flags & K_BRET)) {
+               extern u32_t reboot_code;
+               raw_copy(mon2abs(params), reboot_code, sizeof(params));
+       }
+       parse_code(params);
+
+       /* Return from Minix.  Things may have changed, so assume nothing. */
+       fsok= -1;
+       errno= 0;
+
+       /* Read leftover character, if any. */
+       scan_keyboard();
+
+       /* Restore screen contents. */
+       restore_screen();
+}
+
 void exec_image(char *image)
 /* Get a Minix image into core, patch it up and execute. */
 {
@@ -483,7 +748,7 @@ void exec_image(char *image)
        raw_clear(aout, PROCESS_MAX * A_MINHDR);
 
        /* Read the many different processes: */
-       for (i= 0; vsec < image_size; i++) {
+       for (i= 0; vsec < image_sectors; i++) {
                u32_t startaddr;
                startaddr = addr;
                if (i == PROCESS_MAX) {
@@ -778,7 +1043,7 @@ char *select_image(char *image)
                                                && numeric(size)) {
                        vir2sec= flat_vir2sec;
                        image_off= a2l(image);
-                       image_size= a2l(size);
+                       image_sectors= a2l(size);
                        strcpy(image, "Minix");
                        return image;
                }
@@ -790,6 +1055,8 @@ char *select_image(char *image)
        }
 
        r_stat(image_ino, &st);
+       image_bytes = st.st_size;
+
        if (!S_ISREG(st.st_mode)) {
                char *version= image + strlen(image);
                char dots[NAME_MAX + 1];
@@ -809,7 +1076,7 @@ char *select_image(char *image)
                r_stat(image_ino, &st);
        }
        vir2sec= file_vir2sec;
-       image_size= (st.st_size + SECTOR_SIZE - 1) >> SECTOR_SHIFT;
+       image_sectors= (st.st_size + SECTOR_SIZE - 1) >> SECTOR_SHIFT;
        return image;
 bail_out:
        free(image);
@@ -822,8 +1089,25 @@ void bootminix(void)
  */
 {
        char *image;
+       char *mb;
+       char *kernel;
+       /* FIXME: modules should come from environment */
+       char modules[] = "boot/ds boot/rs boot/pm boot/sched boot/vfs boot/memory boot/log boot/tty boot/mfs boot/vm boot/pfs boot/init";
+
+       if ((mb = b_value("mb")) != nil) {
+               do_multiboot = a2l(mb);
+               kernel = b_value("kernel");
+               if (kernel == nil) {
+                       printf("kernel not set\n");
+                       return;
+               }
+       }
 
-       if ((image= select_image(b_value("image"))) == nil) return;
+       if (do_multiboot) {
+               if ((kernel= select_image(b_value("kernel"))) == nil) return;
+       } else {
+               if ((image= select_image(b_value("image"))) == nil) return;
+       }
 
        if(serial_line >= 0) {
                char linename[2];
@@ -832,26 +1116,105 @@ void bootminix(void)
                b_setvar(E_VAR, SERVARNAME, linename);
        }
 
-       exec_image(image);
+       if (do_multiboot)
+               exec_mb(kernel, modules);
+       else
+               exec_image(image);
 
        switch (errno) {
        case ENOEXEC:
-               printf("%s contains a bad program header\n", image);
+               printf("%s contains a bad program header\n",
+                          do_multiboot ? kernel : image);
                break;
        case ENOMEM:
-               printf("Not enough memory to load %s\n", image);
+               printf("Not enough memory to load %s\n",
+                          do_multiboot ? kernel : image);
                break;
        case EIO:
-               printf("Unexpected EOF on %s\n", image);
+               printf("Unexpected EOF on %s\n",
+                          do_multiboot ? kernel : image);
        case 0:
                /* No error or error already reported. */;
        }
-       free(image);
+
+       if (do_multiboot)
+               free(kernel);
+       else
+               free(image);
 
        if(serial_line >= 0) 
                b_unset(SERVARNAME);
 }
 
+size_t
+strspn(const char *string, const char *in)
+{
+       register const char *s1, *s2;
+
+       for (s1 = string; *s1; s1++) {
+               for (s2 = in; *s2 && *s2 != *s1; s2++)
+                       /* EMPTY */ ;
+               if (*s2 == '\0')
+                       break;
+       }
+       return s1 - string;
+}
+
+char *
+strpbrk(register const char *string, register const char *brk)
+{
+       register const char *s1;
+
+       while (*string) {
+               for (s1 = brk; *s1 && *s1 != *string; s1++)
+                       /* EMPTY */ ;
+               if (*s1)
+                       return (char *)string;
+               string++;
+       }
+       return (char *)NULL;
+}
+
+char *
+strtok(register char *string, const char *separators)
+{
+       register char *s1, *s2;
+       static char *savestring = NULL;
+
+       if (string == NULL) {
+               string = savestring;
+               if (string == NULL) return (char *)NULL;
+       }
+
+       s1 = string + strspn(string, separators);
+       if (*s1 == '\0') {
+               savestring = NULL;
+               return (char *)NULL;
+       }
+
+       s2 = strpbrk(s1, separators);
+       if (s2 != NULL)
+               *s2++ = '\0';
+       savestring = s2;
+       return s1;
+}
+
+char *
+strdup(const char *s1)
+{
+       size_t len;
+       char *s2;
+
+       len= strlen(s1)+1;
+
+       s2= malloc(len);
+       if (s2 == NULL)
+               return NULL;
+       strcpy(s2, s1);
+
+       return s2;
+}
+
 /*
  * $PchId: bootimage.c,v 1.10 2002/02/27 19:39:09 philip Exp $
  */
diff --git a/commands/mkimage/Makefile b/commands/mkimage/Makefile
new file mode 100644 (file)
index 0000000..4ef271b
--- /dev/null
@@ -0,0 +1,13 @@
+
+NBSD_LIBC:= yes
+
+PROG=  mkimage
+SRCS=  mkimage.c
+MAN=
+
+CPPFLAGS+= -D_NETBSD_SOURCE
+
+DPADD+=        ${LIBELF}
+LDADD+=        -lelf
+
+.include <bsd.prog.mk>
diff --git a/commands/mkimage/mkimage.c b/commands/mkimage/mkimage.c
new file mode 100644 (file)
index 0000000..f89d561
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Update physical addresses of boot services
+ */
+
+#include <sys/param.h>
+
+#include <err.h>
+#include <fcntl.h>
+
+#include <gelf.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <getopt.h>
+
+#define BOOTPROG_LOAD_START 0x05000000ULL
+
+int nflag = 0;
+
+int stack_kbytes[] = {
+    /*  ds  rs    pm  sched  vfs  memory  log  tty  mfs  vm   pfs  init */
+       16, 8125, 32, 32, 16, 8, 32, 16, 128, 128, 128, 64
+};
+
+static void usage(void);
+
+GElf_Addr
+update_paddr(int nr, char *fname, GElf_Addr startaddr)
+{
+       int i, fd;
+       Elf *e;
+       size_t n;
+
+       GElf_Phdr phdr;
+       GElf_Addr endaddr = 0;
+
+       if ((fd = open(fname, O_RDWR, 0)) < 0)
+               err(EX_NOINPUT, "open \"%s\" failed", fname);
+
+       if ((e = elf_begin(fd, ELF_C_RDWR, NULL)) == NULL)
+               errx(EX_SOFTWARE, "elf_begin() failed: %s.", elf_errmsg(-1));
+
+       if (elf_kind(e) != ELF_K_ELF)
+               errx(EX_DATAERR, "\"%s\" is not an ELF object.", fname);
+
+       if (elf_getphdrnum(e, &n) != 0)
+               errx(EX_DATAERR, "elf_getphdrnum() failed: %s.", elf_errmsg(-1));
+
+       for (i = 0; i < n; i++) {
+               if (gelf_getphdr(e, i, &phdr) != &phdr)
+                       errx(EX_SOFTWARE, "getphdr() failed: %s.",
+                           elf_errmsg(-1));
+
+               if (phdr.p_type == PT_LOAD) {
+                       phdr.p_paddr = startaddr + phdr.p_vaddr;
+
+                       endaddr = round_page(phdr.p_paddr + phdr.p_memsz)
+                           + round_page(stack_kbytes[nr] * 1024);
+
+                       if (gelf_update_phdr(e, i, &phdr) < 0)
+                               errx(EX_SOFTWARE,
+                                   "gelf_update_phdr failed: %s.",
+                                   elf_errmsg(-1));
+               }
+
+       }
+
+       if (elf_update(e, ELF_C_WRITE) < 0)
+               errx(EX_SOFTWARE, "elf_update failed: %s.", elf_errmsg(-1));
+
+       (void) elf_end(e);
+       (void) close(fd);
+
+       return endaddr;
+
+}
+
+int
+main(int argc, char **argv)
+{
+       int i, ch;
+       GElf_Addr startaddr, endaddr;
+
+       startaddr = BOOTPROG_LOAD_START;
+
+       while ((ch = getopt(argc, argv, "n")) != -1) {
+               switch (ch) {
+               case 'n':
+                       nflag = 1;
+                       break;
+               case '?':
+               default:
+                       usage();
+                       exit(EX_USAGE);
+               }
+       }
+       argc -= optind;
+       argv += optind;
+
+       if (argc < 1)
+               usage();
+
+       if (elf_version(EV_CURRENT) == EV_NONE)
+               errx(EX_SOFTWARE, "ELF library intialization failed: %s",
+                   elf_errmsg(-1));
+
+       startaddr = BOOTPROG_LOAD_START;
+       for (i = 0; i < argc; i++) {
+               startaddr = update_paddr(i, argv[i], startaddr);
+       }
+
+       exit(EX_OK);
+}
+
+static void
+usage(void)
+{
+       (void) fprintf(stderr, "usage: %s [-n] elf1 elf2...\n", getprogname());
+}
index 57eb44376ad2711f8ffa56049434ffdd16dd9909..bab063bcf7338dca17beaab6b27eaf466546d006 100644 (file)
@@ -10,4 +10,4 @@ MAN=
 BINDIR?= /usr/sbin
 INSTALLFLAGS+= -S 32k
 
-.include <bsd.prog.mk>
+.include <minix.bootprog.mk>
index 7372f65142fb50dd2411ce8331b70fc4b82b89ce..4357ec74c4bac400dc0581a7c3ed0b4d675b0f95 100644 (file)
@@ -1,6 +1,4 @@
 # Makefile for memory driver (MEMORY)
-.include <bsd.own.mk>
-
 PROG=  memory
 SRCS=  memory.c imgrd.c
 
@@ -20,4 +18,4 @@ imgrd.d: touch-genfiles
 touch-genfiles:
        [ -e ${.CURDIR}/../ramdisk/image.c ] || touch -t 197001010000.00 ${.CURDIR}/../ramdisk/image.c
 
-.include <bsd.prog.mk>
+.include <minix.bootprog.mk>
index f4676b9de159fcc2e6c61087aacf3d01037c6c40..aaf1b8977fbd15e52e259667c539bc7a6d198205 100644 (file)
@@ -1,7 +1,5 @@
 # Makefile for terminal driver (TTY)
 
-.include <bsd.own.mk>
-
 PROG=  tty
 SRCS=  tty.c console.c keyboard.c pty.c rs232.c
 
@@ -18,5 +16,5 @@ SUBDIR= keymaps
 # Needs kernel/const.h, etc
 CPPFLAGS+=     -I${MINIXSRCDIR}
 
-.include <bsd.prog.mk>
+.include <minix.bootprog.mk>
 .include <bsd.subdir.mk>
index a5d660cfef5bd2547ca77ef633e8a1a10011a456..5637c78b0329695cf3036628639888881d7af7dd 100644 (file)
@@ -1,6 +1,6 @@
 INCSDIR= /usr/include/i386
 
-INCS+= _align.h asm.h mcontext.h param.h
+INCS+= _align.h asm.h mcontext.h multiboot.h param.h
 
 .include "../../../common/include/arch/i386/Makefile.inc"
 
similarity index 99%
rename from kernel/arch/i386/multiboot.h
rename to include/arch/i386/multiboot.h
index fa960e8613dc9949fdfe1fe91da0f61abd0cf12c..df2bafa372606df5dd2d4129f35961bfd30b2ac2 100644 (file)
@@ -15,7 +15,7 @@
 #define MULTIBOOT_AOUT_KLUDGE 0x00010000
 
 #define MULTIBOOT_FLAGS (MULTIBOOT_MEMORY_INFO | MULTIBOOT_PAGE_ALIGN)
-                                               
+
 /* consts used for Multiboot pre-init */
 
 #define MULTIBOOT_VIDEO_MODE_EGA 1
index 1cb68c52b8ab8d29e1778662aef6add8fdaf7e54..2c32b82c65cc3adaa82ec12b7360ca6436edae04 100644 (file)
@@ -25,7 +25,7 @@
 #include "oxpcie.h"
 #include "kernel/proc.h"
 #include "kernel/debug.h"
-#include "multiboot.h"
+#include <machine/multiboot.h>
 
 #include "glo.h"
 
diff --git a/kernel/arch/i386/kernel_elf.lds b/kernel/arch/i386/kernel_elf.lds
new file mode 100644 (file)
index 0000000..2e290f3
--- /dev/null
@@ -0,0 +1,43 @@
+OUTPUT_ARCH("i386")
+ENTRY(MINIX)
+SECTIONS
+{
+       . = 0x200000 + SIZEOF_HEADERS;
+       .text . : AT (ADDR(.text) - 0x0000) {
+               *(.text)
+               *(.text.*)
+               . = ALIGN(4096);
+       }
+       _etext = .;
+       etext = .;
+
+       .data . : AT (ADDR(.data) - 0x0000) {
+               _rodata = .;
+               /* kernel data starts with this magic number */
+               SHORT(0x526f);
+               *(.rodata)
+               *(.rodata.*)
+               _erodata = .;
+               *(.data)
+               *(.data.*)
+               . = ALIGN(4096);
+       }
+       _edata = .;
+
+       .bss . : AT (ADDR(.bss) - 0x0000) {
+               *(.bss)
+               *(.bss.*)
+               *(COMMON)
+       }
+       _end = .;
+       end = .;
+
+       /DISCARD/ :
+       {
+               *(.eh_frame)
+               *(.comment)
+               *(.comment.*)
+               *(.note)
+               *(.note.*)
+       }
+}
index c60046c646d78f9e370a97e246b7f8e115208ece..561c7e5eacf8e115dcb938525ca99b1b05fc0be6 100644 (file)
@@ -9,7 +9,7 @@
 #include "archconst.h"
 #include "kernel/const.h"
 #include "sconst.h"
-#include "multiboot.h"
+#include <machine/multiboot.h>
 
 /*
  * This file contains a number of assembly code utility routines needed by the
index 5cdad83af47fc873951cd26939abf153675c0e5d..36a0683cc78e213a2dda62fbc1775fb6a7e818b7 100644 (file)
@@ -8,7 +8,7 @@
 #include "archconst.h"
 #include "kernel/const.h"
 #include "sconst.h"
-#include "multiboot.h"
+#include <machine/multiboot.h>
 
 /*
  * This file contains a number of 16-bit assembly code utility routines needed by the
index 88fb81bb3576533afe11fa37bcbde64740f7cc64..deab7175b0bac32f2c01ad3ebb43203e03b52a2d 100644 (file)
@@ -53,7 +53,7 @@ begbss:
 #include "kernel/const.h"
 #include "kernel/proc.h"
 #include "sconst.h"
-#include "multiboot.h"
+#include <machine/multiboot.h>
 
 #include "arch_proto.h" /* K_STACK_SIZE */
 
@@ -84,9 +84,7 @@ MINIX:
 /* this is the entry point for the MINIX kernel */
 
 #if defined(__ELF__)
-       /* Check if Multibooting */
-       cmpl $MULTIBOOT_BOOTLOADER_MAGIC, %eax
-       je _C_LABEL(multiboot_init)
+       jmp _C_LABEL(multiboot_init)
 #endif
 
        jmp     over_flags      /* skip over the next few bytes */
index 5846a9ae210f5195d2f857de5a3313900c28174c..4fdd0973afcc3a2ecd69159c4c7ccc1b468c2204 100644 (file)
@@ -8,7 +8,7 @@
 #include "kernel/const.h"
 #include "kernel/proc.h"
 #include "sconst.h"
-#include "multiboot.h"
+#include <machine/multiboot.h>
 
 #define GDT_SET_ENTRY(selector, base, limit) \
        mov     %ebp, %edi; \
@@ -44,6 +44,8 @@ reload_cs:
        mov     %eax, %ds
        mov     %eax, %ss
        mov     %eax, %es
+       mov     %eax, %fs
+       mov     %eax, %gs
        
        mov     $(multiboot_stack + MULTIBOOT_STACK_SIZE), %esp
 
index 5746c5c4f2e84d3fd8d2b5124606139def297ff0..f84ce23e90c599fb3802aefce1c52a6323caf502 100644 (file)
@@ -17,7 +17,7 @@
 #include "string.h"
 #include "arch_proto.h"
 #include "libexec.h"
-#include "multiboot.h"
+#include <machine/multiboot.h>
 
 #define MULTIBOOT_VERBOSE 1
 
@@ -279,10 +279,6 @@ PRIVATE void get_parameters(multiboot_info_t *mbi)
                mb_set_param("memory", mem_value);
        }
        
-       /* FIXME: this is dummy value, 
-        * we can't get real image file name from multiboot */
-       mb_set_param("image", "boot/image_latest");
-       
        if (mbi->flags&MULTIBOOT_INFO_CMDLINE) {
                /* Override values with cmdline argument */
                p = mb_cmd_buff;
@@ -353,11 +349,9 @@ PRIVATE void mb_extract_image(multiboot_info_t mbi)
        mb_print("\nKernel:   ");
        mb_print_hex(trunc_page(text_paddr));
        mb_print("-");
-       mb_print_hex(trunc_page(data_paddr) + data_membytes + stack_bytes);
+       mb_print_hex(trunc_page(data_paddr) + data_membytes);
        mb_print(" Entry: ");
        mb_print_hex(pc);
-       mb_print(" Stack: ");
-       mb_print_hex(stack_bytes);
 #endif
 
        mb_module_info = ((multiboot_module_t *)mbi.mods_addr);
index 25d67e1f2cf352c7c0a9ef2bd4b7575ea12588e0..03e3dc8eb64984082a5f7f26fa29303ad1ce3146 100644 (file)
@@ -14,6 +14,8 @@
 /* Support only 32-bit ELF objects */
 #define __ELF_WORD_SIZE 32
 
+#define SECTOR_SIZE 512
+
 static int __elfN(check_header)(const Elf_Ehdr *hdr);
 
 int read_header_elf(
@@ -36,8 +38,6 @@ int read_header_elf(
   unsigned long seg_filebytes, seg_membytes;
   int i = 0;
 
-  assert(exec_hdr != NULL);
-
   *text_vaddr = *text_paddr = 0;
   *text_filebytes = *text_membytes = 0;
   *data_vaddr = *data_paddr = 0;
@@ -50,8 +50,8 @@ int read_header_elf(
      return ENOEXEC;
   }
 
-  if ((hdr->e_phoff > PAGE_SIZE) ||
-      (hdr->e_phoff + hdr->e_phentsize * hdr->e_phnum) > PAGE_SIZE) {
+  if ((hdr->e_phoff > SECTOR_SIZE) ||
+      (hdr->e_phoff + hdr->e_phentsize * hdr->e_phnum) > SECTOR_SIZE) {
      return ENOEXEC;
   }
 
@@ -60,21 +60,21 @@ int read_header_elf(
 #ifdef __NBSD_LIBC
       rounddown((uintptr_t)phdr, sizeof(Elf_Addr)) != (uintptr_t)phdr
 #else
-      !_minix_aligned(phdr, Elf_Addr)
+      !_minix_aligned(hdr->e_phoff, Elf_Addr)
 #endif
      ) {
      return ENOEXEC;
   }
 
 #if ELF_DEBUG
-  printf("Program header file offset (phoff): %d\n", hdr->e_phoff);
-  printf("Section header file offset (shoff): %d\n", hdr->e_shoff);
+  printf("Program header file offset (phoff): %ld\n", hdr->e_phoff);
+  printf("Section header file offset (shoff): %ld\n", hdr->e_shoff);
   printf("Program header entry size (phentsize): %d\n", hdr->e_phentsize);
   printf("Program header entry num (phnum): %d\n", hdr->e_phnum);
   printf("Section header entry size (shentsize): %d\n", hdr->e_shentsize);
   printf("Section header entry num (shnum): %d\n", hdr->e_shnum);
   printf("Section name strings index (shstrndx): %d\n", hdr->e_shstrndx);
-  printf("Entry Point: 0x%x\n", hdr->e_entry);
+  printf("Entry Point: 0x%lx\n", hdr->e_entry);
 #endif
 
   for (i = 0; i < hdr->e_phnum; i++) {
@@ -108,18 +108,17 @@ int read_header_elf(
   }
 
 #if ELF_DEBUG
-  printf("Text vaddr:     0x%x\n", *text_vaddr);
-  printf("Text paddr:     0x%x\n", *text_paddr);
-  printf("Text filebytes: 0x%x\n", *text_filebytes);
-  printf("Text membytes:  0x%x\n", *text_membytes);
-  printf("Data vaddr:     0x%x\n", *data_vaddr);
-  printf("Data paddr:     0x%x\n", *data_paddr);
-  printf("Data filebyte:  0x%x\n", *data_filebytes);
-  printf("Data membytes:  0x%x\n", *data_membytes);
-  printf("Tot bytes:      0x%x\n", *tot_bytes);
-  printf("PC:             0x%x\n", *pc);
-  printf("Text offset:    0x%x\n", *text_offset);
-  printf("Data offset:    0x%x\n", *data_offset);
+  printf("Text vaddr:     0x%lx\n", *text_vaddr);
+  printf("Text paddr:     0x%lx\n", *text_paddr);
+  printf("Text filebytes: 0x%lx\n", *text_filebytes);
+  printf("Text membytes:  0x%lx\n", *text_membytes);
+  printf("Data vaddr:     0x%lx\n", *data_vaddr);
+  printf("Data paddr:     0x%lx\n", *data_paddr);
+  printf("Data filebyte:  0x%lx\n", *data_filebytes);
+  printf("Data membytes:  0x%lx\n", *data_membytes);
+  printf("PC:             0x%lx\n", *pc);
+  printf("Text offset:    0x%lx\n", *text_offset);
+  printf("Data offset:    0x%lx\n", *data_offset);
 #endif
 
   return OK;
index fde1c87cbda4d9bb0f34118cc043f151807aa4a9..f59486e5abf31ca613d5fa9b28cd0a4af54a8e24 100644 (file)
@@ -10,4 +10,4 @@ MAN=
 BINDIR?= /usr/sbin
 INSTALLFLAGS+= -S 16k
 
-.include <bsd.prog.mk>
+.include <minix.bootprog.mk>
index 66cee87c33601be1d1de807f98d172d8533b8ee5..f48e32e3abadd178302fe6d9fea538ace84ad814 100644 (file)
@@ -7,4 +7,4 @@ MAN=
 BINDIR?= /usr/sbin
 INSTALLFLAGS+= -S 64k
 
-.include <bsd.prog.mk>
+.include <minix.bootprog.mk>
index 88bc62ac2e2d026344e454b05c1d8df33de5bdc7..e893c37b5caa4bb1bea3381f490bf044097dc7fc 100644 (file)
@@ -16,4 +16,4 @@ INSTALLFLAGS+=        -S 128k
 DEFAULT_NR_BUFS= 1024
 CPPFLAGS+= -DDEFAULT_NR_BUFS=${DEFAULT_NR_BUFS}
 
-.include <bsd.prog.mk>
+.include <minix.bootprog.mk>
index c36260425ef3b896cb612b05aff71f0243efc725..ac3312ba571a586c4483f874eabee63baf8b6cc1 100644 (file)
@@ -12,4 +12,4 @@ MAN=
 BINDIR?= /usr/sbin
 INSTALLFLAGS+= -S 128k
 
-.include <bsd.prog.mk>
+.include <minix.bootprog.mk>
index c1acafd783464914b78458680cb2cec81898b117..43f53c9766081d6980b803e75b9ece84617a20c5 100644 (file)
@@ -17,4 +17,4 @@ CPPFLAGS.misc.c+=     -I${MINIXSRCDIR}
 CPPFLAGS.schedule.c+=  -I${MINIXSRCDIR}
 CPPFLAGS.utility.c+=   -I${MINIXSRCDIR}
 
-.include <bsd.prog.mk>
+.include <minix.bootprog.mk>
index 6c86ba22facd99bb18b31cd6c3f743f0e64182d4..6a2e2837474cd268c3ddbc3844c454a3d39e29a0 100644 (file)
@@ -1,6 +1,4 @@
 # Makefile for Reincarnation Server (RS)
-.include <bsd.own.mk>
-
 PROG=  rs
 SRCS=  exec.c main.c request.c manager.c table.c utility.c memory.c error.c
 
@@ -14,4 +12,4 @@ INSTALLFLAGS+=        -S 8125k
 
 CPPFLAGS+=     -I${MINIXSRCDIR}
 
-.include <bsd.prog.mk>
+.include <minix.bootprog.mk>
index da3b08115daf0956519ac4fa70d67f983b696947..7d7afc9809cc1f450f7ffa434ce2830521969aed 100644 (file)
@@ -14,4 +14,4 @@ CPPFLAGS.main.c+=     -I${MINIXSRCDIR}
 CPPFLAGS.schedule.c+=  -I${MINIXSRCDIR}
 CPPFLAGS.utility.c+=   -I${MINIXSRCDIR}
 
-.include <bsd.prog.mk>
+.include <minix.bootprog.mk>
index 9989d9a8e1bd97167a7ae543ff8f815ff8d370a4..dfe9d197d2ac16faa8077464b4f05631dbf10e17 100644 (file)
@@ -14,4 +14,4 @@ MAN=
 BINDIR?= /usr/sbin
 INSTALLFLAGS+= -S 16k
 
-.include <bsd.prog.mk>
+.include <minix.bootprog.mk>
index ca6ef54d6e1157f205e0630ebd1bc3e571e23b23..f17b3929e0c178528ed3a06d9c58467d3162bfb7 100644 (file)
@@ -18,4 +18,4 @@ CPPFLAGS+= -I${.CURDIR} -I${.CURDIR}/arch/${ARCH}
 CPPFLAGS+=     -I${MINIXSRCDIR}
 
 .include "arch/${ARCH}/Makefile.inc"
-.include <bsd.prog.mk>
+.include <minix.bootprog.mk>
index 36de72ec8c358ca18b1d9a7e5c897213e602277f..740bc5ba070d649f77833bb83e0817871efec45b 100644 (file)
@@ -10,6 +10,9 @@ FILES=        bsd.ack.mk bsd.dep.mk bsd.files.mk \
        bsd.prog.mk bsd.subdir.mk bsd.sys.mk bsd.gcov.mk \
        sys.mk
 
+# MINIX-specific files
+FILES+= minix.bootprog.mk
+
 FILESDIR=/usr/share/mk
 .endif
 
diff --git a/share/mk/minix.bootprog.mk b/share/mk/minix.bootprog.mk
new file mode 100644 (file)
index 0000000..01a8001
--- /dev/null
@@ -0,0 +1,8 @@
+# MINIX-specific boot program options
+.include <bsd.own.mk>
+
+.if ${OBJECT_FMT} == "ELF"
+LDFLAGS+= -Wl,--section-start=.init=0x0
+.endif
+
+.include <bsd.prog.mk>
index 11c812220f79adf510e6540f289637e730c7b8c8..6c496e9a099535fe6c997962fcbb27e683dfc71f 100644 (file)
@@ -2,12 +2,15 @@
 .include <bsd.own.mk>
 .include "nbsd.config"
 
+.include <bsd.own.mk>
+
 u=/usr
 MDEC=  /usr/mdec
 GEN_FILES=     *.bak image kernel *.iso *.iso.gz cdfdimage rootimage src
 
 # Specify the programs that are part of the system image.
-PROGRAMS=      kernel \
+KERNEL= kernel
+PROGRAMS= \
        ../servers/ds/ds \
        ../servers/rs/rs \
        ../servers/pm/pm \
@@ -56,15 +59,17 @@ PAD_KERNEL_TEXT := cp ../kernel/kernel kernel
 PAD_KERNEL_TEXT := padtext ../kernel/kernel kernel
 .endif
 
-# for fast complie kernel and generate image, skip servers and drivers
-image_mb: includes
-       cd ../kernel && $(MAKE)
+.if ${OBJECT_FMT} == "ELF"
+image: includes services
        ${PAD_KERNEL_TEXT}
-       installboot -image $@ $(PROGRAMS)
-       
+       mkimage $(PROGRAMS)
+       cp ${KERNEL} ${PROGRAMS} /boot
+       strip ${KERNEL:T:S/^/\/boot\//} ${PROGRAMS:T:S/^/\/boot\//}
+.else
 image:  includes services
        ${PAD_KERNEL_TEXT}
-       installboot -image $@ $(PROGRAMS)
+       installboot -image $@ $(KERNEL) $(PROGRAMS)
+.endif
 
 # rebuild the program or system libraries
 includes:
@@ -94,9 +99,13 @@ libraries: includes
 bootable:
        exec su root mkboot bootable
 
+.if ${OBJECT_FMT} == "ELF"
+hdboot: image
+.else
 hdboot:        image
        exec sh mkboot $@
        @sync
+.endif
 
 fdboot:        image
        exec su root mkboot $@