cvs diff: Diffing . Index: GNUmakerules =================================================================== RCS file: /n/fast/usr/lsrc/flux/CVS/oskit/boot/net/GNUmakerules,v retrieving revision 1.14.2.1 retrieving revision 1.14.2.2 diff -c -r1.14.2.1 -r1.14.2.2 *** GNUmakerules 1998/03/14 03:15:24 1.14.2.1 --- GNUmakerules 1998/03/14 04:14:45 1.14.2.2 *************** *** 44,49 **** --- 44,53 ---- -loskit_memdebug -loskit_c -loskit_lmm DEPENDLIBS = $(filter %.a, $(foreach DIR,$(LIBDIRS),$(wildcard $(DIR)/*))) + ## Debugging hint: set the -Ttext to 3MB or so so you can run GDB and + ## trace through the booted kernel (which presumably loads lower than + ## 3MB). Also, you can use the GDB `symbol-file' command to load the booted + ## kernel's symbols once you get inside of it. netboot: $(OBJDIR)/lib/multiboot.o $(OBJFILES) $(DEPENDLIBS) $(OBJDIR)/lib/crtn.o $(LD) -o $@ -Ttext 100000 -n $(LDFLAGS) $(OSKIT_LDFLAGS) \ $(OBJDIR)/lib/multiboot.o \ Index: NEWS =================================================================== RCS file: /n/fast/usr/lsrc/flux/CVS/oskit/boot/net/NEWS,v retrieving revision 1.3.2.1 retrieving revision 1.3.2.2 diff -c -r1.3.2.1 -r1.3.2.2 *** NEWS 1998/03/14 03:15:25 1.3.2.1 --- NEWS 1998/03/14 04:16:05 1.3.2.2 *************** *** 15,17 **** --- 15,26 ---- This simplifies the code and will enable us to work on Linux in the future. + 2.01 -> 2.02 + - Made it boot multiboot kernels now, not BSD ones. + This is mainly so we can pass them arbitrary command lines, which + will eventually include a "return address" so we can regain control + after the booted kernel exits. + A disadvantage is that thre isn't a multiboot-boot-adaptor yet, so + we can't glob a bunch of bmods together into a multiboot image like + we can for BSD images. + - Various cleanup, bugfixes, and reorganization Index: await.c =================================================================== RCS file: /n/fast/usr/lsrc/flux/CVS/oskit/boot/net/await.c,v retrieving revision 1.10.2.1 retrieving revision 1.10.2.2 diff -c -r1.10.2.1 -r1.10.2.2 *** await.c 1998/03/14 03:15:25 1.10.2.1 --- await.c 1998/03/14 04:14:45 1.10.2.2 *************** *** 17,23 **** #include "rpc.h" /* rpc_t */ #include "netboot.h" /* TIMEOUT */ #include "timer.h" /* currticks */ - #include "boot.h" /* kerninfo */ #include "await.h" /* AWAIT_foo */ --- 17,22 ---- Index: boot.h =================================================================== RCS file: /n/fast/usr/lsrc/flux/CVS/oskit/boot/net/boot.h,v retrieving revision 1.7 retrieving revision 1.7.2.1 diff -c -r1.7 -r1.7.2.1 *** boot.h 1997/10/21 00:06:27 1.7 --- boot.h 1998/03/14 04:14:45 1.7.2.1 *************** *** 21,57 **** #ifndef __BOOT_H_INCLUDED__ #define __BOOT_H_INCLUDED__ ! #include /* oskit_ */ ! #include "rpc.h" /* NFS_ */ struct kerninfo { ! union { ! struct { ! char *dirname; /* directory to mount */ ! unsigned char dirfh[NFS_FHSIZE]; /* file handle of dir */ ! char *name; /* file in dirname */ ! unsigned char fh[NFS_FHSIZE]; /* file handle */ ! } N; ! struct { ! /* disk stuff */ ! } D; ! } u; ! #define ki_dirname u.N.dirname ! #define ki_dirfh u.N.dirfh ! #define ki_name u.N.name ! #define ki_fh u.N.fh ! ! void *ki_imgaddr; /* where it is in memory */ ! int ki_imgsize; /* how big image is (NOT file size) */ ! ! /* These two are always the same right now. */ ! oskit_addr_t ki_ldaddr; /* load address */ ! oskit_addr_t ki_entry; /* entry point */ }; ! int getkernel_net(unsigned long myip, unsigned long srvip, unsigned long gwip, ! unsigned long netmask, char *myhostname, ! struct kerninfo *ki /* IN/OUT */); ! void loadkernel(struct kerninfo *kinfo); #endif /* __BOOT_H_INCLUDED__ */ --- 21,45 ---- #ifndef __BOOT_H_INCLUDED__ #define __BOOT_H_INCLUDED__ ! #include /* multiboot_header */ ! #include /* in_addr */ struct kerninfo { ! struct in_addr ki_ip; /* ip of server host, in host order */ ! char *ki_dirname; /* dir to mount */ ! char *ki_filename; /* file within dir */ ! ! struct multiboot_header ki_mbhdr; /* things like load address, entry */ ! ! void *ki_imgaddr; /* where it is in memory */ ! ! struct multiboot_info *ki_mbinfo; /* stuff we are passing to it */ }; + + #define kerninfo_imagesize(ki) (phystokv((ki)->ki_mbhdr.bss_end_addr) \ + - phystokv((ki)->ki_mbhdr.load_addr)) ! int getkernel_net(struct kerninfo *ki /* IN/OUT */); ! void loadkernel(struct kerninfo *ki); #endif /* __BOOT_H_INCLUDED__ */ Index: bootinfo.h =================================================================== RCS file: bootinfo.h diff -N bootinfo.h *** /tmp/cvs011255 Tue Mar 9 00:59:11 1999 --- /dev/null Mon Mar 8 14:37:46 1999 *************** *** 1,69 **** - /*- - * Copyright (C) 1994 by Rodney W. Grimes, Milwaukie, Oregon 97222 - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer as - * the first lines of this file unmodified. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Rodney W. Grimes. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY RODNEY W. GRIMES ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL RODNEY W. GRIMES BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $\Id: bootinfo.h,v 1.5 1995/05/30 08:00:26 rgrimes Exp $ - */ - - #ifndef _MACHINE_BOOTINFO_H_ - #define _MACHINE_BOOTINFO_H_ - - /* Only change the version number if you break compatibility. */ - #define BOOTINFO_VERSION 1 - - #define N_BIOS_GEOM 8 - - /* - * A zero bootinfo field often means that there is no info available. - * Flags are used to indicate the validity of fields where zero is a - * normal value. - */ - struct bootinfo { - unsigned int bi_version; - unsigned char *bi_kernelname; - struct nfs_diskless *bi_nfs_diskless; - /* End of fields that are always present. */ - #define bi_endcommon bi_n_bios_used - unsigned int bi_n_bios_used; - unsigned long bi_bios_geom[N_BIOS_GEOM]; - unsigned int bi_size; - unsigned char bi_memsizes_valid; - unsigned char bi_pad[3]; - unsigned long bi_basemem; - unsigned long bi_extmem; - unsigned long bi_symtab; - unsigned long bi_esymtab; - }; - - #ifdef KERNEL - extern struct bootinfo bootinfo; - #endif - - #endif /* !_MACHINE_BOOTINFO_H_ */ --- 0 ---- Index: boottype.h =================================================================== RCS file: boottype.h diff -N boottype.h *** /tmp/cvs011255 Tue Mar 9 00:59:11 1999 --- /dev/null Mon Mar 8 14:37:46 1999 *************** *** 1,34 **** - /* - * Copyright (c) 1995,1996,1997 The University of Utah and - * the Computer Systems Laboratory at the University of Utah (CSL). - * All rights reserved. - * - * Permission to use, copy, modify and distribute this software is hereby - * granted provided that (1) source code retains these copyright, permission, - * and disclaimer notices, and (2) redistributions including binaries - * reproduce the notices in supporting documentation, and (3) all advertising - * materials mentioning features or use of this software display the following - * acknowledgement: ``This product includes software developed by the - * Computer Systems Laboratory at the University of Utah.'' - * - * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS - * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF - * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * CSL requests users of this software to return to csl-dist@cs.utah.edu any - * improvements that they make and grant CSL redistribution rights. - */ - - #ifndef _BOOT_BSD_BOOTTYPE_H_ - #define _BOOT_BSD_BOOTTYPE_H_ - - #define BOOTTYPE_MACH 0 - #define BOOTTYPE_OLDBSD 1 - #define BOOTTYPE_NEWBSD 2 - - #ifndef ASSEMBLER - extern int boottype; - extern unsigned long boothowto, bootdev; - #endif - - #endif /* _BOOT_BSD_BOOTTYPE_H_ */ --- 0 ---- Index: do_boot.S =================================================================== RCS file: /n/fast/usr/lsrc/flux/CVS/oskit/boot/net/do_boot.S,v retrieving revision 1.4.2.1 retrieving revision 1.4.2.2 diff -c -r1.4.2.1 -r1.4.2.2 *** do_boot.S 1998/03/14 03:15:26 1.4.2.1 --- do_boot.S 1998/03/14 04:14:46 1.4.2.2 *************** *** 24,34 **** */ #include - #define NODEV -1 /* see freebsd */ - .globl EXT(boothowto), EXT(bsdbootinfo) - .globl EXT(kernel_tempstack) - .text /* --- 24,30 ---- *************** *** 36,41 **** --- 32,38 ---- * %esi where kernel is * %edi where kernel wants to be * %ecx how big kernel is + * %ebx addr of multiboot_info struct * %edx segment we should switch to */ ENTRY(do_boot) *************** *** 44,73 **** movw %dx,%es movw %dx,%fs movw %dx,%gs - - /* - * Switch to a new stack since the old one will get trashed - * when we copy the new image in. - */ movw %dx,%ss - movl EXT(kernel_tempstack),%esp - - /* - * Push the kernel args before we copy and trash "boothowto" etc. - * We call the kernel like this: - * (%eax)(boothowto, bootdev, 0, 0, 0, bsdbootinfo) - * That is what BSD expects. - */ - pushl EXT(bsdbootinfo) - pushl $0 - pushl $0 - pushl $0 - pushl $NODEV - pushl EXT(boothowto) - /* Copy the new kernel and jump in. */ rep movsb ! call *%eax ENTRY(do_boot_end) --- 41,51 ---- movw %dx,%es movw %dx,%fs movw %dx,%gs movw %dx,%ss rep movsb ! ! jmp *%eax ENTRY(do_boot_end) Index: getkernel_net.c =================================================================== RCS file: /n/fast/usr/lsrc/flux/CVS/oskit/boot/net/getkernel_net.c,v retrieving revision 1.7 retrieving revision 1.7.2.1 diff -c -r1.7 -r1.7.2.1 *** getkernel_net.c 1998/02/05 04:20:48 1.7 --- getkernel_net.c 1998/03/14 04:14:47 1.7.2.1 *************** *** 18,31 **** * CSL requests users of this software to return to csl-dist@cs.utah.edu any * improvements that they make and grant CSL redistribution rights. */ #include /* phystokv */ #include /* oskit_addr_t */ ! ! #include /* malloc_lmm */ #include /* printf */ #include /* assert */ #include /* exec_load */ - #include /* lmm_remove_free */ #include "netboot.h" /* NFS_READ_SIZE */ #include "ether.h" /* ARP_ */ --- 18,31 ---- * CSL requests users of this software to return to csl-dist@cs.utah.edu any * improvements that they make and grant CSL redistribution rights. */ + #include /* phystokv */ #include /* oskit_addr_t */ ! #include /* phys_mem_max */ #include /* printf */ #include /* assert */ + #include /* mustcalloc */ #include /* exec_load */ #include "netboot.h" /* NFS_READ_SIZE */ #include "ether.h" /* ARP_ */ *************** *** 33,47 **** #include "boot.h" ! #ifndef min #define min(a,b) ((a) < (b)? (a) : (b)) - #endif /* * Callback to read the kernel image from its src, in this case NFS. */ static int ! kimg_read(void *port, oskit_addr_t file_ofs, void *buf, oskit_size_t size, oskit_size_t *out_actual) { --- 33,50 ---- #include "boot.h" ! #undef min #define min(a,b) ((a) < (b)? (a) : (b)) + static int nfs_port; + static unsigned char dirfh[NFS_FHSIZE]; /* file handle of dir */ + static unsigned char filefh[NFS_FHSIZE]; /* file handle of file */ + /* * Callback to read the kernel image from its src, in this case NFS. */ static int ! kimg_read(void *handle_notused, oskit_addr_t file_ofs, void *buf, oskit_size_t size, oskit_size_t *out_actual) { *************** *** 56,62 **** offset = file_ofs; while (size > 0) { chunk_size = min(NFS_READ_SIZE, size); ! n = nfs_read(ARP_ROOTSERVER, (int)port, kinfo.ki_fh, offset, chunk_size, bufp); if (n < 0) { printf("Unable to read text: %s\n", nfs_strerror(n)); --- 59,65 ---- offset = file_ofs; while (size > 0) { chunk_size = min(NFS_READ_SIZE, size); ! n = nfs_read(ARP_ROOTSERVER, nfs_port, filefh, offset, chunk_size, bufp); if (n < 0) { printf("Unable to read text: %s\n", nfs_strerror(n)); *************** *** 75,209 **** } /* ! * Callback to figure out how big the kernel is. */ static int ! kimg_load_1(void *handle, ! oskit_addr_t file_ofs, oskit_size_t file_size, ! oskit_addr_t mem_addr, oskit_size_t mem_size, ! exec_sectype_t section_type) { #if 0 ! printf("** 1: file_ofs %x, file_size %x\n", file_ofs, file_size); ! printf("-- 1: mem_addr %x, mem_size %x\n", mem_addr, mem_size); ! printf("-- 1: sectype = %b\n", section_type, EXEC_SECTYPE_FORMAT); #endif if (!(section_type & EXEC_SECTYPE_ALLOC)) return 0; ! /* We incr by mem_size since we want to include the BSS. */ ! kinfo.ki_imgsize += mem_size; ! return 0; } /* ! * Callback to load the kernel for real. ! * Needs to read file_size bytes from handle at file_ofs and place it ! * in mem_addr. ! * If mem_size is greater than file_size, the remaining bytes are ! * zeroed. */ static int ! kimg_load_2(void *handle, ! oskit_addr_t file_ofs, oskit_size_t file_size, ! oskit_addr_t mem_addr, oskit_size_t mem_size, ! exec_sectype_t section_type) { ! static int offset = 0; ! oskit_size_t got; ! int err; #if 0 ! printf("** 2: file_ofs %x, file_size %x\n", file_ofs, file_size); ! printf("-- 2: mem_addr %x, mem_size %x\n", mem_addr, mem_size); ! printf("-- 2: sectype = %b\n", section_type, EXEC_SECTYPE_FORMAT); #endif ! if (!(section_type & EXEC_SECTYPE_ALLOC)) ! return 0; ! if ((err = kimg_read(handle, file_ofs, kinfo.ki_imgaddr + offset, ! file_size, &got)) != 0) ! return err; ! if (got != file_size) ! return EX_CORRUPT; ! offset += mem_size; return 0; } /* ! * Get the kernel and put it somewhere (not its final position.) ! * The kerninfo struct we get passed has the ki_dirname and ki_name * members filled in. ! * We fill in the rest. */ int ! getkernel_net(unsigned long myip, unsigned long srvip, unsigned long gwip, ! unsigned long netmask, char *myhostname, ! struct kerninfo *ki /* IN/OUT */) { int err; exec_info_t xinfo; ! int root_nfs_port; ! int root_mount_port; assert(ki->ki_dirname); ! assert(ki->ki_name); ! /* Lookup NFS/MOUNTD ports for ROOT using PORTMAP */ ! root_nfs_port = rpc_lookup(ARP_ROOTSERVER, PROG_NFS, 2); ! root_mount_port = rpc_lookup(ARP_ROOTSERVER, PROG_MOUNT, 1); ! if ((root_nfs_port == -1) || (root_mount_port == -1)) { ! printf("Unable to get root NFS/MOUNT ports\n"); ! return 0; } printf("Mounting %s...\n", ki->ki_dirname); ! err = nfs_mount(ARP_ROOTSERVER, root_mount_port, ! ki->ki_dirname, ki->ki_dirfh); if (err) { ! printf("Can't mount ROOT filesystem: %s\n", nfs_strerror(err)); ! return 0; } ! printf("Looking up %s...\n", ki->ki_name); ! err = nfs_lookup(ARP_ROOTSERVER, root_nfs_port, ki->ki_dirfh, ! (*ki->ki_name == '/') ? ki->ki_name+1 : ki->ki_name, ! ki->ki_fh); if (err) { ! netprintf("Can't lookup %s: %s\n", ki->ki_name, nfs_strerror(err)); ! return 0; } /* ! * First figure out how big the thing is, then load it all at once. */ ! printf("Loading %s...\n", ki->ki_name); ! if ((err = exec_load(kimg_read, kimg_load_1, (void *)root_nfs_port, ! &xinfo)) != 0) { ! printf("cannot load kernel image 1: %s\n", exec_strerror(err)); ! return 0; } ! /* We assume the entry is the same as the lowest text addr. */ ! xinfo.entry &= 0x00FFFFFF; ! ki->ki_ldaddr = xinfo.entry; ! ki->ki_entry = xinfo.entry; ! ! /* Reserve the memory where the kernel will eventually reside. */ ! lmm_remove_free(&malloc_lmm, ! (void *)phystokv(ki->ki_ldaddr), ki->ki_imgsize); ! ! ki->ki_imgaddr = mustcalloc(ki->ki_imgsize, 1); ! if ((err = exec_load(kimg_read, kimg_load_2, (void *)root_nfs_port, ! &xinfo)) != 0) { ! printf("cannot load kernel image 2: %s\n", exec_strerror(err)); ! return 0; } ! return 1; /* yay */ } --- 78,301 ---- } /* ! * Callback to load the kernel for real. ! * Copies data from the NFS file into ki->ki_imgaddr. */ static int ! kimg_load(void *handle, ! oskit_addr_t file_ofs, oskit_size_t file_size, ! oskit_addr_t mem_addr, oskit_size_t mem_size, ! exec_sectype_t section_type) { + struct kerninfo *ki = handle; + oskit_size_t got; + int err; + #if 0 ! printf("** load: file_ofs %x, file_size %x\n", file_ofs, file_size); ! printf("-- load: mem_addr %x, mem_size %x\n", mem_addr, mem_size); ! printf("-- load: sectype = %b\n", section_type, EXEC_SECTYPE_FORMAT); #endif if (!(section_type & EXEC_SECTYPE_ALLOC)) return 0; ! if ((err = kimg_read(ki, file_ofs, ! ki->ki_imgaddr + mem_addr - ki->ki_mbhdr.load_addr, ! file_size, &got)) != 0) ! return err; ! if (got != file_size) ! return EX_CORRUPT; ! return 0; } /* ! * Callback for the exec library that just tallys up the sizes. */ static int ! kimg_tally(void *handle, ! oskit_addr_t file_ofs, oskit_size_t file_size, ! oskit_addr_t mem_addr, oskit_size_t mem_size, ! exec_sectype_t section_type) { ! struct multiboot_header *h = handle; #if 0 ! printf("** tally: file_ofs %x, file_size %x\n", file_ofs, file_size); ! printf("-- tally: mem_addr %x, mem_size %x\n", mem_addr, mem_size); ! printf("-- tally: sectype = %b\n", section_type, EXEC_SECTYPE_FORMAT); #endif ! if (!(section_type & EXEC_SECTYPE_ALLOC)) ! return 0; ! assert(mem_size > 0); ! if (mem_addr < h->load_addr) ! h->load_addr = mem_addr; ! if (mem_addr+file_size > h->load_end_addr) ! h->load_end_addr = mem_addr+file_size; ! if (mem_addr+mem_size > h->bss_end_addr) ! h->bss_end_addr = mem_addr+mem_size; ! ! return 0; ! } ! ! /* ! * Look in the first MULTIBOOT_SEARCH bytes of the file for the ! * MultiBoot header and puts it in ki->ki_mbhdr; ! * ! * Returns 0 if found, 1 otherwise. ! */ ! static int ! find_multiboot_header(struct kerninfo *ki) ! { ! int err; ! int offset; ! char buf[NFS_READ_SIZE]; ! oskit_size_t got; ! int i; ! struct multiboot_header *h; ! ! for (offset = 0; offset < MULTIBOOT_SEARCH; offset += NFS_READ_SIZE) { ! err = kimg_read(ki, offset, buf, NFS_READ_SIZE, &got); ! if (err) ! return 1; ! for (i = 0; i < got - sizeof(*h); i += 4) { ! h = (struct multiboot_header *)&buf[i]; ! if (h->magic == MULTIBOOT_MAGIC ! && (h->magic + h->flags + h->checksum) == 0) { ! ki->ki_mbhdr = *h; ! return 0; ! } ! } ! } ! return 1; ! } + /* + * Fills in certain fields of the ki_mbhdr multiboot_header using + * the "executable interpreter" library. + * + * Returns 0 on success, 1 otherwise; + */ + static int + fill_in_multiboot_header(struct kerninfo *ki) + { + struct multiboot_header *h = &ki->ki_mbhdr; + struct exec_info xinfo; + int err; + + h->load_addr = 0xffffffff; + h->load_end_addr = 0; + h->bss_end_addr = 0; + + err = exec_load(kimg_read, kimg_tally, &ki->ki_mbhdr, &xinfo); + if (err) { + printf("Can't tally sections: %s.\n", exec_strerror(err)); + return 1; + } + h->entry = xinfo.entry; + return 0; } /* ! * Get the kernel and put it somewhere (not its final position). ! * The kerninfo struct we get passed has the ki_ip, ki_dirname, and ki_filename * members filled in. ! * We fill in the ki_mbhdr and ki_imgaddr parts. ! * ! * Returns 0 on success, 1 otherwise. */ int ! getkernel_net(struct kerninfo *ki /* IN/OUT */) { int err; exec_info_t xinfo; ! int mount_port; assert(ki->ki_dirname); ! assert(ki->ki_filename); ! /* ! * Lookup NFS/MOUNTD ports for ROOT using PORTMAP. ! */ ! nfs_port = rpc_lookup(ARP_ROOTSERVER, PROG_NFS, 2); ! mount_port = rpc_lookup(ARP_ROOTSERVER, PROG_MOUNT, 1); ! if (nfs_port == -1 || mount_port == -1) { ! printf("Can't get root NFS/MOUNT ports.\n"); ! return 1; } + /* + * NFS mount the directory. + */ printf("Mounting %s...\n", ki->ki_dirname); ! err = nfs_mount(ARP_ROOTSERVER, mount_port, ki->ki_dirname, dirfh); if (err) { ! printf("Can't mount ROOT filesystem: %s.\n", nfs_strerror(err)); ! return 1; } ! /* ! * Lookup the file. ! */ ! printf("Looking up %s...\n", ki->ki_filename); ! err = nfs_lookup(ARP_ROOTSERVER, nfs_port, dirfh, ki->ki_filename, ! filefh); if (err) { ! printf("Can't lookup %s: %s.\n", ! ki->ki_filename, nfs_strerror(err)); ! return 1; } /* ! * Look in the file for the MultiBoot header. */ ! if (find_multiboot_header(ki) != 0) { ! printf("Can't find MultiBoot header in image.\n"); ! return 1; ! } ! /* ! * Fill in the rest of the MultiBoot header, if needed. ! * Stuff like load address, bss size, etc. ! */ ! if (! (ki->ki_mbhdr.flags & MULTIBOOT_AOUT_KLUDGE) ! && fill_in_multiboot_header(ki) != 0) { ! printf("Can't fill in MultiBoot header.\n"); ! return 1; } ! /* ! * Do a bunch of checks on the kernel load ranges. ! */ ! assert(ki->ki_mbhdr.load_addr < ki->ki_mbhdr.load_end_addr); ! assert(ki->ki_mbhdr.load_end_addr < ki->ki_mbhdr.bss_end_addr); ! printf("Kernel will be at %08x-%08x text+data %d bss %d\n", ! ki->ki_mbhdr.load_addr, ki->ki_mbhdr.bss_end_addr, ! ki->ki_mbhdr.load_end_addr - ki->ki_mbhdr.load_addr, ! ki->ki_mbhdr.bss_end_addr - ki->ki_mbhdr.load_end_addr); ! if (ki->ki_mbhdr.load_addr < 0x1000) ! panic("kernel wants to be loaded too low!"); ! if (ki->ki_mbhdr.bss_end_addr > phys_mem_max) ! panic("kernel wants to be loaded beyond available physical memory!"); ! if ((ki->ki_mbhdr.load_addr < 0x100000) ! && (ki->ki_mbhdr.bss_end_addr > 0xa0000)) ! panic("kernel wants to be loaded on top of I/O space!"); ! ! /* ! * Now, read the whole thing in somewhere. ! * It will be copied into its final resting home later, ! * right before we jump in. ! */ ! printf("Loading %s...\n", ki->ki_filename); ! ki->ki_imgaddr = mustcalloc(kerninfo_imagesize(ki), 1); ! if ((err = exec_load(kimg_read, kimg_load, (void *)ki, &xinfo)) != 0) { ! printf("Can't load kernel image: %s.\n", exec_strerror(err)); ! return 1; } ! return 0; /* yay */ } Index: loadkernel.c =================================================================== RCS file: /n/fast/usr/lsrc/flux/CVS/oskit/boot/net/loadkernel.c,v retrieving revision 1.5.2.1 retrieving revision 1.5.2.2 diff -c -r1.5.2.1 -r1.5.2.2 *** loadkernel.c 1998/03/14 03:15:26 1.5.2.1 --- loadkernel.c 1998/03/14 04:14:47 1.5.2.2 *************** *** 27,32 **** --- 27,33 ---- #include /* cli/sti */ #include /* LINEAR_CS */ #include /* kvtophys */ + #include /* multiboot_info_dump */ #include /* mustmalloc */ #include /* memcpy */ #include /* printf */ *************** *** 36,49 **** extern char do_boot[], do_boot_end[]; void ! loadkernel(struct kerninfo *kinfo) { oskit_size_t stub_size; void *stub; struct far_pointer_32 ptr; oskit_addr_t copy_source; oskit_size_t copy_size; printf("Booting kernel...\n\n"); cli(); --- 37,53 ---- extern char do_boot[], do_boot_end[]; void ! loadkernel(struct kerninfo *ki) { + oskit_addr_t entry, load_addr; oskit_size_t stub_size; void *stub; struct far_pointer_32 ptr; oskit_addr_t copy_source; oskit_size_t copy_size; + multiboot_info_dump(ki->ki_mbinfo); + printf("Booting kernel...\n\n"); cli(); *************** *** 73,91 **** * * XXX the "mr" constraint for "ptr" should be "m" but GCC * says "inconsistent operand constraints." */ ! copy_source = kvtophys(kinfo->ki_imgaddr); ! copy_size = kinfo->ki_imgsize; ! if (copy_source > kinfo->ki_entry) { asm volatile(" cld ljmp %0 " : /* no outputs */ : "mr" (ptr), ! "a" (kinfo->ki_entry), "S" (copy_source), ! "D" (kinfo->ki_entry), "c" (copy_size), "d" (LINEAR_DS)); } else { --- 77,111 ---- * * XXX the "mr" constraint for "ptr" should be "m" but GCC * says "inconsistent operand constraints." + * + * Be careful what you put as the values for the registers in + * the asm's below. + * If you have too many indirections and whatnot then GCC + * will apparently run out of registers and won't be able to + * set, for example, %ebx to the desired value. + * The GCC chokeage looked like this for me: + * + * fixed or forbidden register was spilled. + * This may be due to a compiler bug or to impossible asm + * + * That is why I have load_addr and entry be local vars instead of + * just putting the expressions in the asm. */ ! copy_source = kvtophys(ki->ki_imgaddr); ! copy_size = kerninfo_imagesize(ki); ! entry = ki->ki_mbhdr.entry; ! load_addr = ki->ki_mbhdr.load_addr; ! if (copy_source > load_addr) { asm volatile(" cld ljmp %0 " : /* no outputs */ : "mr" (ptr), ! "a" (entry), "S" (copy_source), ! "D" (load_addr), "c" (copy_size), + "b" (kvtophys(ki->ki_mbinfo)), "d" (LINEAR_DS)); } else { *************** *** 94,103 **** ljmp %0 " : /* no outputs */ : "mr" (ptr), ! "a" (kinfo->ki_entry), "S" (copy_source + copy_size - 1), ! "D" (kinfo->ki_entry + copy_size - 1), "c" (copy_size), "d" (LINEAR_DS)); } } --- 114,124 ---- ljmp %0 " : /* no outputs */ : "mr" (ptr), ! "a" (entry), "S" (copy_source + copy_size - 1), ! "D" (load_addr + copy_size - 1), "c" (copy_size), + "b" (kvtophys(ki->ki_mbinfo)), "d" (LINEAR_DS)); } } Index: main.c =================================================================== RCS file: /n/fast/usr/lsrc/flux/CVS/oskit/boot/net/main.c,v retrieving revision 1.17.2.1 retrieving revision 1.17.2.2 diff -c -r1.17.2.1 -r1.17.2.2 *** main.c 1998/03/14 03:15:26 1.17.2.1 --- main.c 1998/03/14 04:14:47 1.17.2.2 *************** *** 31,90 **** #include /* assert */ #include /* ntohl */ #include /* fd_set_console */ #include - #include "boottype.h" /* boothowto */ #include "timer.h" /* TIMER_FREQ */ #include "driver.h" /* net_init */ #include "ether.h" /* arptable */ #include "gdt.h" /* copy_base_gdt */ #include "boot.h" /* kerninfo */ #include "netboot.h" /* netprintf */ - #include "../bsd/reboot.h" /* RB_ constants */ - void *kernel_tempstack; - struct bootinfo *bsdbootinfo; - struct kerninfo kinfo; - - unsigned long boothowto; - - static void - makeboothowto(int argc, char *argv[]) - { - int i; - - boothowto = 0; - for (i = 0; i < argc; i++) { - - #define FLAG(s, f) \ - if (strcmp(argv[i], #s) == 0) { \ - boothowto |= (f); \ - continue; \ - } - - FLAG(-a, RB_ASKNAME); - FLAG(-s, RB_SINGLE); - FLAG(-r, RB_DFLTROOT); - FLAG(-b, RB_HALT); - FLAG(-d, BSD_RB_KDB); - FLAG(-c, BSD_RB_CONFIG); - FLAG(-h, BSD_RB_SERIAL); - FLAG(-f, BSD_RB_FASTCONSOLE); - #undef FLAG - } - } - void main(int argc, char *argv[]) { ! char url[512]; ! printf("Netboot metakernel v2.01 (compiled %s)\n", __DATE__); - /* For now, use what we were booted with. */ - makeboothowto(argc, argv); - fd_set_console(); /* so stdin, etc work */ oskit_dev_init(); osenv_timer_register(bumpticks, TIMER_FREQ); --- 31,59 ---- #include /* assert */ #include /* ntohl */ #include /* fd_set_console */ + #include /* malloc_lmm */ + #include /* lmm_remove_free */ + #include /* boot_info */ #include #include "timer.h" /* TIMER_FREQ */ #include "driver.h" /* net_init */ #include "ether.h" /* arptable */ #include "gdt.h" /* copy_base_gdt */ #include "boot.h" /* kerninfo */ #include "netboot.h" /* netprintf */ void main(int argc, char *argv[]) { ! struct kerninfo kinfo; ! struct multiboot_info *mbi; ! char cmdline[512]; ! char *args; ! printf("Netboot metakernel v2.02 (compiled %s)\n", __DATE__); fd_set_console(); /* so stdin, etc work */ oskit_dev_init(); osenv_timer_register(bumpticks, TIMER_FREQ); *************** *** 99,148 **** * Figure out our rootserver, dir to mount, and file to load. * Then try to get it. */ reprompt: ! printf("\nTell me the kernel file name in ip:/dir/file form " ! "(\"quit\" to exit)\n"); ! printf("kernel name: "); ! fgets(url, 512, stdin); ! url[strlen(url) - 1] = '\0'; /* chop \n */ ! if (strcmp(url, "quit") == 0) exit(0); ! if (url[0] == '\0') goto reprompt; ! if (! parse_pseudo_url(url, ! &arptable[ARP_ROOTSERVER].ipaddr, ! &kinfo.ki_dirname, &kinfo.ki_name)) { ! printf("bad url, try again\n"); goto reprompt; } ! if (! getkernel_net(arptable[ARP_CLIENT].ipaddr, ! arptable[ARP_ROOTSERVER].ipaddr, ! arptable[ARP_GATEWAY].ipaddr, ! netmask, hostname, ! &kinfo)) { ! printf("can't get the kernel, try again\n"); goto reprompt; } - netprintf("Root server: %I, dir %s, file %s\r\n", - arptable[ARP_ROOTSERVER].ipaddr, - kinfo.ki_dirname, kinfo.ki_name); - - /* Fill in a bootinfo struct for BSD. */ - bsdbootinfo = (struct bootinfo *)mustcalloc(sizeof(struct bootinfo), 1); - bsdbootinfo->bi_version = BOOTINFO_VERSION; - bsdbootinfo->bi_kernelname = mustmalloc(strlen(kinfo.ki_name) + 1); - strcpy(bsdbootinfo->bi_kernelname, kinfo.ki_name); - bsdbootinfo->bi_size = sizeof(struct bootinfo); - - /* Allocate a non-conflicting stack for passing args to the kernel. */ - kernel_tempstack = mustmalloc(0x1000); - kernel_tempstack += 0x1000; /* * Clean some stuff up before we load the new image. * In particular we don't want the timer hammering it, * and don't want it using some bogus GDT (we may overwrite ours ! * with the new image.) */ net_shutdown(); osenv_timer_shutdown(); --- 68,136 ---- * Figure out our rootserver, dir to mount, and file to load. * Then try to get it. */ + printf("\nType \"help\" for help.\n\n"); reprompt: ! printf("NetBoot: "); ! fgets(cmdline, 512, stdin); ! cmdline[strlen(cmdline) - 1] = '\0'; /* chop \n */ ! if (strcmp(cmdline, "help") == 0) { ! printf("\nTell me the kernel file name and args in the form\n" ! "\t: [args]\n" ! "For example:\n" ! "\t155.22.33.44:/home/foo/kernel -f -h\n" ! "The directory must be an NFS exported directory.\n" ! "Type \"quit\" to exit.\n\n"); ! goto reprompt; ! } ! if (strcmp(cmdline, "quit") == 0) exit(0); ! if (cmdline[0] == '\0') goto reprompt; ! if (! parse_cmdline(cmdline, ! &kinfo.ki_ip.s_addr, ! &kinfo.ki_dirname, ! &kinfo.ki_filename, ! &args)) { ! printf("Bad command line, try again.\n"); goto reprompt; } ! netprintf("Root server: %I, dir: %s,\r\n" ! " file: %s, cmdline: `%s'\r\n", ! kinfo.ki_ip.s_addr, kinfo.ki_dirname, kinfo.ki_filename, ! args ? args : ""); ! memcpy(&arptable[ARP_ROOTSERVER].ipaddr, &kinfo.ki_ip.s_addr, ! sizeof arptable[ARP_ROOTSERVER].ipaddr); ! if (getkernel_net(&kinfo) != 0) { ! printf("Can't get the kernel, try again.\n"); goto reprompt; + } + + /* + * Reserve the memory where the kernel will eventually reside. + * Future malloc's, like the one for the multiboot_info struct + * we pass to the new kernel, will stay out of this region. + */ + lmm_remove_free(&malloc_lmm, + (void *)phystokv(kinfo.ki_mbhdr.load_addr), + kerninfo_imagesize(&kinfo)); + + /* + * Allocate and fill in a multiboot_info struct we will pass. + */ + mbi = kinfo.ki_mbinfo = mustcalloc(sizeof(struct multiboot_info), 1); + mbi->mem_lower = boot_info.mem_lower; + mbi->mem_upper = boot_info.mem_upper; + mbi->flags |= MULTIBOOT_MEMORY; + if (args) { + mbi->cmdline = kvtophys(strdup(args)); + mbi->flags |= MULTIBOOT_CMDLINE; } /* * Clean some stuff up before we load the new image. * In particular we don't want the timer hammering it, * and don't want it using some bogus GDT (we may overwrite ours ! * with the new image). */ net_shutdown(); osenv_timer_shutdown(); Index: misc.c =================================================================== RCS file: /n/fast/usr/lsrc/flux/CVS/oskit/boot/net/misc.c,v retrieving revision 1.10 retrieving revision 1.10.2.1 diff -c -r1.10 -r1.10.2.1 *** misc.c 1997/10/21 00:06:29 1.10 --- misc.c 1998/03/14 04:14:48 1.10.2.1 *************** *** 11,21 **** #include /* memcpy */ #include /* va_list */ #include /* putchar */ - #include /* isdigit */ - #include /* atol */ #include "netboot.h" - #include "driver.h" /* * Convert IP address from net to machine order --- 11,18 ---- *************** *** 31,52 **** *d = *(s+3); } - /* - * Set a default netmask for IP address - */ - void - default_netmask(unsigned long addr) - { - int net = addr >> 24; - - if (net <= 127) - netmask = 0xff000000; - else if (net < 192) - netmask = 0xffff0000; - else - netmask = 0xffffff00; - } - /************************************************************************** PRINTF and friends --- 28,33 ---- *************** *** 204,211 **** * Convert ascii ipaddr to long. * XXX should be changed to inet_addr. */ ! int ! setip(char *p, unsigned long *i) { unsigned long ip = 0; int val; --- 185,192 ---- * Convert ascii ipaddr to long. * XXX should be changed to inet_addr. */ ! static int ! setip(char *p, unsigned int *i) { unsigned long ip = 0; int val; *************** *** 232,250 **** } /* ! * Take the "pseudo url" url and set the IP, dir, and name components. ! * The url is modified and the dir and name pointers point into it. ! * The url looks like ip:/dir/file, eg 155.99.212.1:/tmp/foo */ int ! parse_pseudo_url(char *url, unsigned long *ip, char **dir, char **name) { ! char *p; ! if (! setip(url, ip)) return 0; ! p = strchr(url, ':'); if (! p) return 0; if (*++p != '/') --- 213,232 ---- } /* ! * Take the command line and set the IP, dir, and name components. ! * The cmdline is modified and things point into it. ! * The cmdline looks like "ip:/dir/file -foo bar", eg "155.99.212.1:/tmp/foo -l" */ int ! parse_cmdline(char *cmdline, unsigned int *ip, char **dir, char **name, ! char **rest) { ! char *p = cmdline; ! if (! setip(p, ip)) return 0; ! p = strchr(p, ':'); if (! p) return 0; if (*++p != '/') *************** *** 262,267 **** --- 244,258 ---- /* Allow the case ip:/foo; we might have just NULified that slash. */ if ((*dir)[0] == '\0') *dir = "/"; + + p = strchr(p, ' '); + if (! p) { + /* No command line args, ok. */ + *rest = NULL; + return 1; + } + *p++ = '\0'; + *rest = p; return 1; } Index: netboot.h =================================================================== RCS file: /n/fast/usr/lsrc/flux/CVS/oskit/boot/net/netboot.h,v retrieving revision 1.9 retrieving revision 1.9.2.1 diff -c -r1.9 -r1.9.2.1 *** netboot.h 1997/10/21 00:06:30 1.9 --- netboot.h 1998/03/14 04:14:48 1.9.2.1 *************** *** 9,15 **** #include #include - #include "bootinfo.h" /* struct bootinfo */ #include "boot.h" /* struct kerninfo */ #ifndef MAX_ARP_RETRIES --- 9,14 ---- *************** *** 35,46 **** #define MKIP(a,b,c,d) (((a)<<24) | ((b)<<16) | ((c)<<8) | (d)) void convert_ipaddr(void *d, void *s); - void default_netmask(unsigned long addr); char *netsprintf(char *buf, char *fmt, ...); void netprintf(char *fmt, ...); ! int parse_pseudo_url(char *url, unsigned long *ip, char **dir, char **name); ! int setip(char *p, unsigned long *i); ! ! extern void *kernel_tempstack; ! extern struct bootinfo *bsdbootinfo; ! extern struct kerninfo kinfo; --- 34,40 ---- #define MKIP(a,b,c,d) (((a)<<24) | ((b)<<16) | ((c)<<8) | (d)) void convert_ipaddr(void *d, void *s); char *netsprintf(char *buf, char *fmt, ...); void netprintf(char *fmt, ...); ! int parse_cmdline(char *cmdline, unsigned int *ip, char **dir, char **name, ! char **rest); Index: rpc.c =================================================================== RCS file: /n/fast/usr/lsrc/flux/CVS/oskit/boot/net/rpc.c,v retrieving revision 1.6 retrieving revision 1.6.2.1 diff -c -r1.6 -r1.6.2.1 *** rpc.c 1997/08/25 09:10:34 1.6 --- rpc.c 1998/03/14 04:14:49 1.6.2.1 *************** *** 170,176 **** { static char buf[64]; ! sprintf(buf, "RPC Error: (%ld,%ld,%ld)", ntohl(rpc->u.reply.rstatus), ntohl(rpc->u.reply.verifier), ntohl(rpc->u.reply.astatus)); --- 170,176 ---- { static char buf[64]; ! sprintf(buf, "RPC Error: (%d,%d,%d)", ntohl(rpc->u.reply.rstatus), ntohl(rpc->u.reply.verifier), ntohl(rpc->u.reply.astatus)); Index: udp.c =================================================================== RCS file: /n/fast/usr/lsrc/flux/CVS/oskit/boot/net/udp.c,v retrieving revision 1.8 retrieving revision 1.8.2.1 diff -c -r1.8 -r1.8.2.1 *** udp.c 1997/08/25 09:10:34 1.8 --- udp.c 1998/03/14 04:14:49 1.8.2.1 *************** *** 13,18 **** --- 13,19 ---- #include "await.h" #include "driver.h" #include "udp.h" + #include "ip.h" #include "ether.h" /**************************************************************************