version 1.61, 2016/06/05 14:13:57 |
version 1.61.2.3, 2017/04/26 02:53:03 |
|
|
/* $NetBSD$ */ |
/* $NetBSD$ */ |
|
|
/*- |
/* |
* Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. |
* Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. |
* All rights reserved. |
* All rights reserved. |
* |
* |
|
|
*/ |
*/ |
|
|
/* |
/* |
* starts NetBSD a.out kernel |
* Starts a NetBSD ELF kernel. The low level startup is done in startprog.S. |
* needs lowlevel startup from startprog.S |
|
* This is a special version of exec.c to support use of XMS. |
* This is a special version of exec.c to support use of XMS. |
*/ |
*/ |
|
|
|
|
#ifdef SUPPORT_PS2 |
#ifdef SUPPORT_PS2 |
#include "biosmca.h" |
#include "biosmca.h" |
#endif |
#endif |
|
#ifdef EFIBOOT |
|
#include "efiboot.h" |
|
#undef DEBUG /* XXX */ |
|
#endif |
|
|
#define BOOT_NARGS 6 |
#define BOOT_NARGS 6 |
|
|
Line 148 static void module_add_common(const char |
|
Line 151 static void module_add_common(const char |
|
|
|
static void userconf_init(void); |
static void userconf_init(void); |
|
|
|
static void extract_device(const char *, char *, size_t); |
|
static void module_base_path(char *, size_t); |
|
static int module_open(boot_module_t *, int, const char *, const char *, |
|
bool); |
|
|
void |
void |
framebuffer_configure(struct btinfo_framebuffer *fb) |
framebuffer_configure(struct btinfo_framebuffer *fb) |
{ |
{ |
Line 193 module_add_common(const char *name, uint |
|
Line 201 module_add_common(const char *name, uint |
|
while (*name == ' ' || *name == '\t') |
while (*name == ' ' || *name == '\t') |
++name; |
++name; |
|
|
|
for (bm = boot_modules; bm != NULL; bm = bm->bm_next) |
|
if (bm->bm_type == type && strcmp(bm->bm_path, name) == 0) |
|
return; |
|
|
bm = alloc(sizeof(boot_module_t)); |
bm = alloc(sizeof(boot_module_t)); |
len = strlen(name) + 1; |
len = strlen(name) + 1; |
str = alloc(len); |
str = alloc(len); |
Line 260 common_load_kernel(const char *file, u_l |
|
Line 272 common_load_kernel(const char *file, u_l |
|
{ |
{ |
int fd; |
int fd; |
#ifdef XMS |
#ifdef XMS |
u_long xmsmem; |
u_long xmsmem; |
physaddr_t origaddr = loadaddr; |
physaddr_t origaddr = loadaddr; |
#endif |
#endif |
|
|
*extmem = getextmem(); |
*extmem = getextmem(); |
Line 269 common_load_kernel(const char *file, u_l |
|
Line 281 common_load_kernel(const char *file, u_l |
|
|
|
#ifdef XMS |
#ifdef XMS |
if ((getextmem1() == 0) && (xmsmem = checkxms())) { |
if ((getextmem1() == 0) && (xmsmem = checkxms())) { |
u_long kernsize; |
u_long kernsize; |
|
|
/* |
/* |
* With "CONSERVATIVE_MEMDETECT", extmem is 0 because |
* With "CONSERVATIVE_MEMDETECT", extmem is 0 because |
* getextmem() is getextmem1(). Without, the "smart" |
* getextmem() is getextmem1(). Without, the "smart" |
* methods could fail to report all memory as well. |
* methods could fail to report all memory as well. |
* xmsmem is a few kB less than the actual size, but |
* xmsmem is a few kB less than the actual size, but |
* better than nothing. |
* better than nothing. |
*/ |
*/ |
if (xmsmem > *extmem) |
if (xmsmem > *extmem) |
*extmem = xmsmem; |
*extmem = xmsmem; |
Line 343 common_load_kernel(const char *file, u_l |
|
Line 355 common_load_kernel(const char *file, u_l |
|
|
|
int |
int |
exec_netbsd(const char *file, physaddr_t loadaddr, int boothowto, int floppy, |
exec_netbsd(const char *file, physaddr_t loadaddr, int boothowto, int floppy, |
void (*callback)(void)) |
void (*callback)(void)) |
{ |
{ |
uint32_t boot_argv[BOOT_NARGS]; |
uint32_t boot_argv[BOOT_NARGS]; |
u_long marks[MARK_MAX]; |
u_long marks[MARK_MAX]; |
struct btinfo_symtab btinfo_symtab; |
struct btinfo_symtab btinfo_symtab; |
u_long extmem; |
u_long extmem; |
u_long basemem; |
u_long basemem; |
|
int error; |
|
#ifdef EFIBOOT |
|
int i; |
|
#endif |
|
|
#ifdef DEBUG |
#ifdef DEBUG |
printf("exec: file=%s loadaddr=0x%lx\n", |
printf("exec: file=%s loadaddr=0x%lx\n", file ? file : "NULL", |
file ? file : "NULL", loadaddr); |
loadaddr); |
#endif |
#endif |
|
|
BI_ALLOC(BTINFO_MAX); |
BI_ALLOC(BTINFO_MAX); |
Line 364 exec_netbsd(const char *file, physaddr_t |
|
Line 380 exec_netbsd(const char *file, physaddr_t |
|
|
|
memset(marks, 0, sizeof(marks)); |
memset(marks, 0, sizeof(marks)); |
|
|
if (common_load_kernel(file, &basemem, &extmem, loadaddr, floppy, marks)) |
error = common_load_kernel(file, &basemem, &extmem, loadaddr, floppy, |
|
marks); |
|
if (error) { |
|
errno = error; |
goto out; |
goto out; |
|
} |
|
#ifdef EFIBOOT |
|
/* adjust to the real load address */ |
|
marks[MARK_START] -= efi_loadaddr; |
|
marks[MARK_ENTRY] -= efi_loadaddr; |
|
marks[MARK_DATA] -= efi_loadaddr; |
|
/* MARK_NSYM */ |
|
marks[MARK_SYM] -= efi_loadaddr; |
|
marks[MARK_END] -= efi_loadaddr; |
|
#endif |
|
|
boot_argv[0] = boothowto; |
boot_argv[0] = boothowto; |
boot_argv[1] = 0; |
boot_argv[1] = 0; |
Line 378 exec_netbsd(const char *file, physaddr_t |
|
Line 407 exec_netbsd(const char *file, physaddr_t |
|
if (boot_modules_enabled) { |
if (boot_modules_enabled) { |
module_init(file); |
module_init(file); |
if (btinfo_modulelist) { |
if (btinfo_modulelist) { |
|
#ifdef EFIBOOT |
|
/* convert module loaded address to paddr */ |
|
struct bi_modulelist_entry *bim; |
|
bim = (void *)(btinfo_modulelist + 1); |
|
for (i = 0; i < btinfo_modulelist->num; i++, bim++) |
|
bim->base -= efi_loadaddr; |
|
btinfo_modulelist->endpa -= efi_loadaddr; |
|
#endif |
BI_ADD(btinfo_modulelist, BTINFO_MODULELIST, |
BI_ADD(btinfo_modulelist, BTINFO_MODULELIST, |
btinfo_modulelist_size); |
btinfo_modulelist_size); |
} |
} |
Line 405 exec_netbsd(const char *file, physaddr_t |
|
Line 442 exec_netbsd(const char *file, physaddr_t |
|
|
|
if (callback != NULL) |
if (callback != NULL) |
(*callback)(); |
(*callback)(); |
|
#ifdef EFIBOOT |
|
/* Copy bootinfo to safe arena. */ |
|
for (i = 0; i < bootinfo->nentries; i++) { |
|
struct btinfo_common *bi = (void *)(u_long)bootinfo->entry[i]; |
|
char *p = alloc(bi->len); |
|
memcpy(p, bi, bi->len); |
|
bootinfo->entry[i] = vtophys(p); |
|
} |
|
|
|
efi_kernel_start = marks[MARK_START]; |
|
efi_kernel_size = image_end - efi_loadaddr - efi_kernel_start; |
|
#endif |
startprog(marks[MARK_ENTRY], BOOT_NARGS, boot_argv, |
startprog(marks[MARK_ENTRY], BOOT_NARGS, boot_argv, |
x86_trunc_page(basemem*1024)); |
x86_trunc_page(basemem * 1024)); |
panic("exec returned"); |
panic("exec returned"); |
|
|
out: |
out: |
|
|
return -1; |
return -1; |
} |
} |
|
|
|
int |
|
count_netbsd(const char *file, u_long *rsz) |
|
{ |
|
u_long marks[MARK_MAX]; |
|
char kdev[64]; |
|
char base_path[64] = "/"; |
|
struct stat st; |
|
boot_module_t *bm; |
|
u_long sz; |
|
int err, fd; |
|
|
|
howto = AB_SILENT; |
|
|
|
memset(marks, 0, sizeof(marks)); |
|
if ((fd = loadfile(file, marks, COUNT_KERNEL | LOAD_NOTE)) == -1) |
|
return -1; |
|
close(fd); |
|
marks[MARK_END] = (((u_long) marks[MARK_END] + sizeof(int) - 1)) & |
|
(-sizeof(int)); |
|
sz = marks[MARK_END]; |
|
|
|
/* The modules must be allocated after the kernel */ |
|
if (boot_modules_enabled) { |
|
extract_device(file, kdev, sizeof(kdev)); |
|
module_base_path(base_path, sizeof(base_path)); |
|
|
|
/* If the root fs type is unusual, load its module. */ |
|
if (fsmod != NULL) |
|
module_add_common(fsmod, BM_TYPE_KMOD); |
|
|
|
for (bm = boot_modules; bm; bm = bm->bm_next) { |
|
fd = module_open(bm, 0, kdev, base_path, false); |
|
if (fd == -1) |
|
continue; |
|
sz = (sz + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); |
|
err = fstat(fd, &st); |
|
if (err == -1 || st.st_size == -1) { |
|
close(fd); |
|
continue; |
|
} |
|
sz += st.st_size; |
|
close(fd); |
|
} |
|
} |
|
|
|
*rsz = sz; |
|
return 0; |
|
} |
|
|
static void |
static void |
extract_device(const char *path, char *buf, size_t buflen) |
extract_device(const char *path, char *buf, size_t buflen) |
{ |
{ |
Line 430 extract_device(const char *path, char *b |
|
Line 528 extract_device(const char *path, char *b |
|
} |
} |
|
|
static const char * |
static const char * |
module_path(boot_module_t *bm, const char *kdev) |
module_path(boot_module_t *bm, const char *kdev, const char *base_path) |
{ |
{ |
static char buf[256]; |
static char buf[256]; |
char name_buf[256], dev_buf[64]; |
char name_buf[256], dev_buf[64]; |
Line 454 module_path(boot_module_t *bm, const cha |
|
Line 552 module_path(boot_module_t *bm, const cha |
|
p++; |
p++; |
extract_device(name, dev_buf, sizeof(dev_buf)); |
extract_device(name, dev_buf, sizeof(dev_buf)); |
snprintf(buf, sizeof(buf), "%s%s/%s/%s.kmod", |
snprintf(buf, sizeof(buf), "%s%s/%s/%s.kmod", |
dev_buf, module_base, p, p); |
dev_buf, base_path, p, p); |
} |
} |
} else { |
} else { |
/* device not specified; load from kernel device if known */ |
/* device not specified; load from kernel device if known */ |
Line 462 module_path(boot_module_t *bm, const cha |
|
Line 560 module_path(boot_module_t *bm, const cha |
|
snprintf(buf, sizeof(buf), "%s%s", kdev, name); |
snprintf(buf, sizeof(buf), "%s%s", kdev, name); |
else |
else |
snprintf(buf, sizeof(buf), "%s%s/%s/%s.kmod", |
snprintf(buf, sizeof(buf), "%s%s/%s/%s.kmod", |
kdev, module_base, name, name); |
kdev, base_path, name, name); |
} |
} |
|
|
return buf; |
return buf; |
} |
} |
|
|
static int |
static int |
module_open(boot_module_t *bm, int mode, const char *kdev, bool doload) |
module_open(boot_module_t *bm, int mode, const char *kdev, |
|
const char *base_path, bool doload) |
{ |
{ |
int fd; |
int fd; |
const char *path; |
const char *path; |
|
|
/* check the expanded path first */ |
/* check the expanded path first */ |
path = module_path(bm, kdev); |
path = module_path(bm, kdev, base_path); |
fd = open(path, mode); |
fd = open(path, mode); |
if (fd != -1) { |
if (fd != -1) { |
if ((howto & AB_SILENT) == 0 && doload) |
if ((howto & AB_SILENT) == 0 && doload) |
Line 496 module_open(boot_module_t *bm, int mode, |
|
Line 595 module_open(boot_module_t *bm, int mode, |
|
} |
} |
|
|
static void |
static void |
module_init(const char *kernel_path) |
module_base_path(char *buf, size_t bufsize) |
{ |
{ |
struct bi_modulelist_entry *bi; |
|
struct stat st; |
|
const char *machine; |
const char *machine; |
char kdev[64]; |
|
char *buf; |
|
boot_module_t *bm; |
|
ssize_t len; |
|
off_t off; |
|
int err, fd, nfail = 0; |
|
|
|
extract_device(kernel_path, kdev, sizeof(kdev)); |
|
|
|
switch (netbsd_elf_class) { |
switch (netbsd_elf_class) { |
case ELFCLASS32: |
case ELFCLASS32: |
Line 523 module_init(const char *kernel_path) |
|
Line 612 module_init(const char *kernel_path) |
|
} |
} |
if (netbsd_version / 1000000 % 100 == 99) { |
if (netbsd_version / 1000000 % 100 == 99) { |
/* -current */ |
/* -current */ |
snprintf(module_base, sizeof(module_base), |
snprintf(buf, bufsize, |
"/stand/%s/%d.%d.%d/modules", machine, |
"/stand/%s/%d.%d.%d/modules", machine, |
netbsd_version / 100000000, |
netbsd_version / 100000000, |
netbsd_version / 1000000 % 100, |
netbsd_version / 1000000 % 100, |
netbsd_version / 100 % 100); |
netbsd_version / 100 % 100); |
} else if (netbsd_version != 0) { |
} else if (netbsd_version != 0) { |
/* release */ |
/* release */ |
snprintf(module_base, sizeof(module_base), |
snprintf(buf, bufsize, |
"/stand/%s/%d.%d/modules", machine, |
"/stand/%s/%d.%d/modules", machine, |
netbsd_version / 100000000, |
netbsd_version / 100000000, |
netbsd_version / 1000000 % 100); |
netbsd_version / 1000000 % 100); |
} |
} |
|
} |
|
|
|
static void |
|
module_init(const char *kernel_path) |
|
{ |
|
struct bi_modulelist_entry *bi; |
|
struct stat st; |
|
char kdev[64]; |
|
char *buf; |
|
boot_module_t *bm; |
|
ssize_t len; |
|
off_t off; |
|
int err, fd, nfail = 0; |
|
|
|
extract_device(kernel_path, kdev, sizeof(kdev)); |
|
module_base_path(module_base, sizeof(module_base)); |
|
|
/* First, see which modules are valid and calculate btinfo size */ |
/* First, see which modules are valid and calculate btinfo size */ |
len = sizeof(struct btinfo_modulelist); |
len = sizeof(struct btinfo_modulelist); |
for (bm = boot_modules; bm; bm = bm->bm_next) { |
for (bm = boot_modules; bm; bm = bm->bm_next) { |
fd = module_open(bm, 0, kdev, false); |
fd = module_open(bm, 0, kdev, module_base, false); |
if (fd == -1) { |
if (fd == -1) { |
bm->bm_len = -1; |
bm->bm_len = -1; |
++nfail; |
++nfail; |
Line 576 module_init(const char *kernel_path) |
|
Line 681 module_init(const char *kernel_path) |
|
for (bm = boot_modules; bm; bm = bm->bm_next) { |
for (bm = boot_modules; bm; bm = bm->bm_next) { |
if (bm->bm_len == -1) |
if (bm->bm_len == -1) |
continue; |
continue; |
fd = module_open(bm, 0, kdev, true); |
fd = module_open(bm, 0, kdev, module_base, true); |
if (fd == -1) |
if (fd == -1) |
continue; |
continue; |
image_end = (image_end + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); |
image_end = (image_end + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); |
Line 670 exec_multiboot(const char *file, char *a |
|
Line 775 exec_multiboot(const char *file, char *a |
|
struct multiboot_info *mbi; |
struct multiboot_info *mbi; |
struct multiboot_module *mbm; |
struct multiboot_module *mbm; |
struct bi_modulelist_entry *bim; |
struct bi_modulelist_entry *bim; |
int i, len; |
int i, len; |
u_long marks[MARK_MAX]; |
u_long marks[MARK_MAX]; |
u_long extmem; |
u_long extmem; |
u_long basemem; |
u_long basemem; |
char *cmdline; |
char *cmdline; |
|
|
mbi = alloc(sizeof(struct multiboot_info)); |
mbi = alloc(sizeof(struct multiboot_info)); |
mbi->mi_flags = MULTIBOOT_INFO_HAS_MEMORY; |
mbi->mi_flags = MULTIBOOT_INFO_HAS_MEMORY; |
Line 721 exec_multiboot(const char *file, char *a |
|
Line 826 exec_multiboot(const char *file, char *a |
|
marks[MARK_NSYM], marks[MARK_SYM], marks[MARK_END]); |
marks[MARK_NSYM], marks[MARK_SYM], marks[MARK_END]); |
#endif |
#endif |
|
|
|
|
#if 0 |
#if 0 |
if (btinfo_symtab.nsym) { |
if (btinfo_symtab.nsym) { |
mbi->mi_flags |= MULTIBOOT_INFO_HAS_ELF_SYMS; |
mbi->mi_flags |= MULTIBOOT_INFO_HAS_ELF_SYMS; |
Line 732 exec_multiboot(const char *file, char *a |
|
Line 836 exec_multiboot(const char *file, char *a |
|
#endif |
#endif |
|
|
multiboot(marks[MARK_ENTRY], vtophys(mbi), |
multiboot(marks[MARK_ENTRY], vtophys(mbi), |
x86_trunc_page(mbi->mi_mem_lower*1024)); |
x86_trunc_page(mbi->mi_mem_lower * 1024)); |
panic("exec returned"); |
panic("exec returned"); |
|
|
out: |
out: |
dealloc(mbi, 0); |
dealloc(mbi, 0); |
return -1; |
return -1; |
} |
} |
|
|