svn commit: r220311 - in head/sys/boot: common pc98/loader

Marcel Moolenaar marcel at FreeBSD.org
Sun Apr 3 22:31:51 UTC 2011


Author: marcel
Date: Sun Apr  3 22:31:51 2011
New Revision: 220311
URL: http://svn.freebsd.org/changeset/base/220311

Log:
  Add 2 new archsw interfaces:
  1.  arch_loadaddr - used by platform code to adjust the address at which
      the object gets loaded. Implement PC98 using this new interface instead
      of using conditional compilation. For ELF objects the ELF header is
      passed as the data pointer. For raw files it's the filename. Note that
      ELF objects are first considered as raw files.
  2.  arch_loadseg - used by platform code to keep track of actual segments,
      so that (instruction) caches can be flushed or translations can be
      created. Both the ELF header as well as the program header are passed
      to allow platform code to treat the kernel proper differently from any
      additional modules and to have all the relevant details of the loaded
      segment (e.g. protection).

Modified:
  head/sys/boot/common/bootstrap.h
  head/sys/boot/common/load_elf.c
  head/sys/boot/common/load_elf_obj.c
  head/sys/boot/common/module.c
  head/sys/boot/pc98/loader/main.c

Modified: head/sys/boot/common/bootstrap.h
==============================================================================
--- head/sys/boot/common/bootstrap.h	Sun Apr  3 22:21:40 2011	(r220310)
+++ head/sys/boot/common/bootstrap.h	Sun Apr  3 22:31:51 2011	(r220311)
@@ -296,6 +296,24 @@ struct arch_switch
     /* Perform ISA byte port I/O (only for systems with ISA) */
     int		(*arch_isainb)(int port);
     void	(*arch_isaoutb)(int port, int value);
+
+    /*
+     * Interface to adjust the load address according to the "object"
+     * being loaded.
+     */
+    uint64_t	(*arch_loadaddr)(u_int type, void *data, uint64_t addr);
+#define	LOAD_ELF	1	/* data points to the ELF header. */
+#define	LOAD_RAW	2	/* data points to the file name. */
+
+    /*
+     * Interface to inform MD code about a loaded (ELF) segment. This
+     * can be used to flush caches and/or set up translations.
+     */
+#ifdef __elfN
+    void	(*arch_loadseg)(Elf_Ehdr *eh, Elf_Phdr *ph, uint64_t delta);
+#else
+    void	(*arch_loadseg)(void *eh, void *ph, uint64_t delta);
+#endif
 };
 extern struct arch_switch archsw;
 

Modified: head/sys/boot/common/load_elf.c
==============================================================================
--- head/sys/boot/common/load_elf.c	Sun Apr  3 22:21:40 2011	(r220310)
+++ head/sys/boot/common/load_elf.c	Sun Apr  3 22:31:51 2011	(r220311)
@@ -97,7 +97,6 @@ __elfN(loadfile)(char *filename, u_int64
     struct elf_file		ef;
     Elf_Ehdr 			*ehdr;
     int				err;
-    u_int			pad;
     ssize_t			bytes_read;
 
     fp = NULL;
@@ -157,12 +156,6 @@ __elfN(loadfile)(char *filename, u_int64
 	/* Looks OK, got ahead */
 	ef.kernel = 0;
 
-	/* Page-align the load address */
-	pad = (u_int)dest & PAGE_MASK;
-	if (pad != 0) {
-	    pad = PAGE_SIZE - pad;
-	    dest += pad;
-	}
     } else if (ehdr->e_type == ET_EXEC) {
 	/* Looks like a kernel */
 	if (kfp != NULL) {
@@ -173,7 +166,7 @@ __elfN(loadfile)(char *filename, u_int64
 	/* 
 	 * Calculate destination address based on kernel entrypoint 	
 	 */
-	dest = ehdr->e_entry;
+	dest = (ehdr->e_entry & ~PAGE_MASK);
 	if (dest == 0) {
 	    printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: not a kernel (maybe static binary?)\n");
 	    err = EPERM;
@@ -186,6 +179,11 @@ __elfN(loadfile)(char *filename, u_int64
 	goto oerr;
     }
 
+    if (archsw.arch_loadaddr != NULL)
+	dest = archsw.arch_loadaddr(LOAD_ELF, ehdr, dest);
+    else
+	dest = roundup(dest, PAGE_SIZE);
+
     /* 
      * Ok, we think we should handle this.
      */
@@ -202,7 +200,7 @@ __elfN(loadfile)(char *filename, u_int64
 
 #ifdef ELF_VERBOSE
     if (ef.kernel)
-	printf("%s entry at 0x%jx\n", filename, (uintmax_t)dest);
+	printf("%s entry at 0x%jx\n", filename, (uintmax_t)ehdr->e_entry);
 #else
     printf("%s ", filename);
 #endif
@@ -362,6 +360,9 @@ __elfN(loadimage)(struct preloaded_file 
 	printf("\n");
 #endif
 
+	if (archsw.arch_loadseg != NULL)
+	    archsw.arch_loadseg(ehdr, phdr + i, off);
+
 	if (firstaddr == 0 || firstaddr > (phdr[i].p_vaddr + off))
 	    firstaddr = phdr[i].p_vaddr + off;
 	if (lastaddr == 0 || lastaddr < (phdr[i].p_vaddr + off + phdr[i].p_memsz))

Modified: head/sys/boot/common/load_elf_obj.c
==============================================================================
--- head/sys/boot/common/load_elf_obj.c	Sun Apr  3 22:21:40 2011	(r220310)
+++ head/sys/boot/common/load_elf_obj.c	Sun Apr  3 22:31:51 2011	(r220311)
@@ -144,8 +144,10 @@ __elfN(obj_loadfile)(char *filename, u_i
 		goto oerr;
 	}
 
-	/* Page-align the load address */
-	dest = roundup(dest, PAGE_SIZE);
+	if (archsw.arch_loadaddr != NULL)
+		dest = archsw.arch_loadaddr(LOAD_ELF, hdr, dest);
+	else
+		dest = roundup(dest, PAGE_SIZE);
 
 	/*
 	 * Ok, we think we should handle this.

Modified: head/sys/boot/common/module.c
==============================================================================
--- head/sys/boot/common/module.c	Sun Apr  3 22:21:40 2011	(r220310)
+++ head/sys/boot/common/module.c	Sun Apr  3 22:31:51 2011	(r220311)
@@ -275,6 +275,9 @@ file_load(char *filename, vm_offset_t de
     int error;
     int i;
 
+    if (archsw.arch_loadaddr != NULL)
+	dest = archsw.arch_loadaddr(LOAD_RAW, filename, dest);
+
     error = EFTYPE;
     for (i = 0, fp = NULL; file_formats[i] && fp == NULL; i++) {
 	error = (file_formats[i]->l_load)(filename, loadaddr, &fp);
@@ -352,9 +355,6 @@ file_loadraw(char *type, char *name)
     char			*cp;
     int				fd, got;
     vm_offset_t			laddr;
-#ifdef PC98
-    struct stat			st;
-#endif
 
     /* We can't load first */
     if ((file_findfile(NULL, NULL)) == NULL) {
@@ -369,20 +369,15 @@ file_loadraw(char *type, char *name)
 	return(CMD_ERROR);
     }
     name = cp;
-    
+
     if ((fd = open(name, O_RDONLY)) < 0) {
 	sprintf(command_errbuf, "can't open '%s': %s", name, strerror(errno));
 	free(name);
 	return(CMD_ERROR);
     }
 
-#ifdef PC98
-    /* We cannot use 15M-16M area on pc98. */
-    if (loadaddr < 0x1000000 &&
-	fstat(fd, &st) == 0 &&
-	(st.st_size == -1 || loadaddr + st.st_size > 0xf00000))
-	loadaddr = 0x1000000;
-#endif
+    if (archsw.arch_loadaddr != NULL)
+	loadaddr = archsw.arch_loadaddr(LOAD_RAW, name, loadaddr);
 
     laddr = loadaddr;
     for (;;) {
@@ -489,14 +484,6 @@ mod_loadkld(const char *kldname, int arg
 	;
 
     do {
-#ifdef PC98
-	/* We cannot use 15M-16M area on pc98. */
-	struct stat st;
-	if (loadaddr < 0x1000000 &&
-	    stat(filename, &st) == 0 &&
-	    (st.st_size == -1 || loadaddr + st.st_size > 0xf00000))
-	    loadaddr = 0x1000000;
-#endif
 	err = file_load(filename, loadaddr, &fp);
 	if (err)
 	    break;

Modified: head/sys/boot/pc98/loader/main.c
==============================================================================
--- head/sys/boot/pc98/loader/main.c	Sun Apr  3 22:21:40 2011	(r220310)
+++ head/sys/boot/pc98/loader/main.c	Sun Apr  3 22:31:51 2011	(r220311)
@@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$");
 #include <string.h>
 #include <machine/bootinfo.h>
 #include <machine/psl.h>
+#include <sys/param.h>
 #include <sys/reboot.h>
 
 #include "bootstrap.h"
@@ -77,6 +78,21 @@ extern char end[];
 static void *heap_top;
 static void *heap_bottom;
 
+static uint64_t
+pc98_loadaddr(u_int type, void *data, uint64_t addr)
+{
+	struct stat st;
+
+	if (type == LOAD_ELF)
+		return (roundup(addr, PAGE_SIZE));
+
+	/* We cannot use 15M-16M area on pc98. */
+	if (type == LOAD_RAW && addr < 0x1000000 && stat(data, &st) == 0 &&
+	    (st.st_size == -1 || addr + st.st_size > 0xf00000))
+		addr = 0x1000000;
+	return (addr);
+}
+
 int
 main(void)
 {
@@ -160,6 +176,7 @@ main(void)
     archsw.arch_readin = i386_readin;
     archsw.arch_isainb = isa_inb;
     archsw.arch_isaoutb = isa_outb;
+    archsw.arch_loadaddr = pc98_loadaddr;
 
     /*
      * March through the device switch probing for things.


More information about the svn-src-all mailing list