[hatari-devel] NetBSD loader for Hatari |
[ Thread Index | Date Index | More lists.tuxfamily.org/hatari-devel Archives ]
Hi,
attached is a loader for NetBSD, ported from AraNYM that i just wrote yesterday ;)
It behaves similar like the ---lilo loader, taking the kernel name from the configuration file, but it does not append any kernel commandline parameters (since there basically aren't any; the arguments specified in the configuration file are parsed manually and just reflect a few options of the loadbsd program).
Symbols are available to the internal NetBSD debugger (DDB), but not yet to the Hatari debugger. For that to work, i guess a separate tool would be needed to extract a Symbol.map from the elf image. Or better yet, integrate that into the loader, but that would need some work.
I've done only a few tests with it so far, but it seems to behave almost the same as running loadbsd from EmuTOS or TOS 4.04. That means, the kernel still crashes at some point ;) But i think, having a loader in Hatari makes debugging things easier, since you don't have to create a boot floppy, and startup EmuTOS first. And of course decompressing the kernel is much faster on the host than from emulated code.
Reset/reboot code isn't tested yet, since that would require to get at least to some boot prompt. Maybe needs some rework compared to linux, since the kernel relocates itself in memory, so you can't use the same entry point as when initiallly loading it.
|
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b459c0dc..8b499354 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -9,7 +9,7 @@ set(SOURCES ncr5380.c paths.c psg.c printer.c resolution.c rs232.c reset.c rtc.c scandir.c scc.c stMemory.c screen.c screenConvert.c screenSnapShot.c shortcut.c sound.c spec512.c statusbar.c str.c tos.c utils.c - vdi.c vme.c inffile.c video.c wavFormat.c xbios.c ymFormat.c lilo.c) + vdi.c vme.c inffile.c video.c wavFormat.c xbios.c ymFormat.c lilo.c netbsd.c) # Disk image code is shared with the hmsa tool, so we put it into a library: add_library(Floppy createBlankImage.c dim.c msa.c st.c zip.c) diff --git a/src/configuration.c b/src/configuration.c index 9f386c85..18d10f2b 100644 --- a/src/configuration.c +++ b/src/configuration.c @@ -431,6 +431,15 @@ static const struct Config_Tag configs_Lilo[] = { NULL , Error_Tag, NULL } }; +/* Used to load/save NetBSD options, names are same as with Aranym */ +static const struct Config_Tag configs_Netbsd[] = +{ + { "Args", String_Tag, ConfigureParams.Netbsd.szCommandLine }, + { "Kernel", String_Tag, ConfigureParams.Netbsd.szKernelFileName }, + { "HaltOnReboot", Bool_Tag, &ConfigureParams.Netbsd.bHaltOnReboot }, + { NULL , Error_Tag, NULL } +}; + /* Used to load/save RS232 options */ static const struct Config_Tag configs_Rs232[] = { @@ -758,6 +767,13 @@ void Configuration_SetDefault(void) ConfigureParams.Lilo.bKernelToFastRam = true; ConfigureParams.Lilo.bHaltOnReboot = true; + /* Set defaults for NetBSD */ + strcpy(ConfigureParams.Netbsd.szCommandLine, "-b"); + File_MakePathBuf(ConfigureParams.Netbsd.szKernelFileName, + sizeof(ConfigureParams.Netbsd.szKernelFileName), + Paths_GetDataDir(), "netbsd.gz", NULL); + ConfigureParams.Lilo.bHaltOnReboot = true; + /* Set defaults for System */ ConfigureParams.System.nMachineType = MACHINE_ST; ConfigureParams.System.nCpuLevel = 0; @@ -893,6 +909,8 @@ void Configuration_Apply(bool bReset) File_MakeAbsoluteName(ConfigureParams.Lilo.szKernelSymbols); if (strlen(ConfigureParams.Lilo.szRamdiskFileName) > 0) File_MakeAbsoluteName(ConfigureParams.Lilo.szRamdiskFileName); + if (strlen(ConfigureParams.Netbsd.szKernelFileName) > 0) + File_MakeAbsoluteName(ConfigureParams.Netbsd.szKernelFileName); File_CleanFileName(ConfigureParams.HardDisk.szHardDiskDirectories[0]); File_MakeAbsoluteName(ConfigureParams.HardDisk.szHardDiskDirectories[0]); File_MakeAbsoluteName(ConfigureParams.Memory.szMemoryCaptureFileName); @@ -1029,6 +1047,7 @@ void Configuration_Load(const char *psFileName) Configuration_LoadSection(psFileName, configs_Ide, "[IDE]"); Configuration_LoadSection(psFileName, configs_Rom, "[ROM]"); Configuration_LoadSection(psFileName, configs_Lilo, "[LILO]"); + Configuration_LoadSection(psFileName, configs_Netbsd, "[NETBSD]"); Configuration_LoadSection(psFileName, configs_Rs232, "[RS232]"); Configuration_LoadSection(psFileName, configs_Printer, "[Printer]"); Configuration_LoadSection(psFileName, configs_Midi, "[Midi]"); @@ -1086,6 +1105,7 @@ void Configuration_Save(void) Configuration_SaveSection(sConfigFileName, configs_Ide, "[IDE]"); Configuration_SaveSection(sConfigFileName, configs_Rom, "[ROM]"); Configuration_SaveSection(sConfigFileName, configs_Lilo, "[LILO]"); + Configuration_SaveSection(sConfigFileName, configs_Netbsd, "[NETBSD]"); Configuration_SaveSection(sConfigFileName, configs_Rs232, "[RS232]"); Configuration_SaveSection(sConfigFileName, configs_Printer, "[Printer]"); Configuration_SaveSection(sConfigFileName, configs_Midi, "[Midi]"); @@ -1108,6 +1128,7 @@ void Configuration_MemorySnapShot_Capture(bool bSave) MemorySnapShot_Store(ConfigureParams.Lilo.szKernelFileName, sizeof(ConfigureParams.Lilo.szKernelFileName)); MemorySnapShot_Store(ConfigureParams.Lilo.szRamdiskFileName, sizeof(ConfigureParams.Lilo.szRamdiskFileName)); + MemorySnapShot_Store(ConfigureParams.Netbsd.szKernelFileName, sizeof(ConfigureParams.Netbsd.szKernelFileName)); MemorySnapShot_Store(&ConfigureParams.Memory.STRamSize_KB, sizeof(ConfigureParams.Memory.STRamSize_KB)); MemorySnapShot_Store(&ConfigureParams.Memory.TTRamSize_KB, sizeof(ConfigureParams.Memory.TTRamSize_KB)); diff --git a/src/includes/configuration.h b/src/includes/configuration.h index e29b77e0..170b94d4 100644 --- a/src/includes/configuration.h +++ b/src/includes/configuration.h @@ -64,6 +64,15 @@ typedef struct } CNF_LILO; +/* NetBSD configuration */ +typedef struct +{ + char szCommandLine[256]; /* bootinfo CL_SIZE */ + char szKernelFileName[FILENAME_MAX]; + bool bHaltOnReboot; +} CNF_NETBSD; + + /* Sound configuration */ typedef struct { @@ -427,6 +436,7 @@ typedef struct CNF_IDEDEV Ide[MAX_IDE_DEVS]; CNF_ROM Rom; CNF_LILO Lilo; + CNF_NETBSD Netbsd; CNF_RS232 RS232; CNF_PRINTER Printer; CNF_MIDI Midi; diff --git a/src/includes/netbsd.h b/src/includes/netbsd.h new file mode 100644 index 00000000..4497b205 --- /dev/null +++ b/src/includes/netbsd.h @@ -0,0 +1,18 @@ +/* + Hatari - netbsd.h + + This file is distributed under the GNU General Public License, version 2 + or at your option any later version. Read the file gpl.txt for details. +*/ + +#ifndef NETBSD_H +#define NETBSD_H + +extern bool bUseNetbsd; + +/** + * return true if Linux loading succeeds + */ +extern bool netbsd_init(void); + +#endif /* NETBSD_H */ diff --git a/src/netbsd.c b/src/netbsd.c new file mode 100644 index 00000000..b0502e2b --- /dev/null +++ b/src/netbsd.c @@ -0,0 +1,657 @@ +/* + NetBSD/m68k OS loader + + Adaption from ARAnyM (bootos_netbsd.cpp) to Hatari (C) 2002 Thorsten Otto + + This file is distributed under the GNU General Public License, version 2 + or at your option any later version. Read the file gpl.txt for details. +*/ + +#include "main.h" +#include "configuration.h" +#include "file.h" +#include "netbsd.h" +#include "log.h" +#include "tos.h" /* TosAddress */ +#include "stMemory.h" /* STRam etc */ +#include "symbols.h" +#include <stdint.h> +#include <SDL_endian.h> +#include "newcpu.h" + +bool bUseNetbsd; + +#define NETBSD_DEBUG 0 +#if NETBSD_DEBUG +#define Dprintf(a) printf a +#else +#define Dprintf(a) +#endif + +/*--- Rip from elf.h ---*/ + +/* Type for a 16-bit quantity. */ +typedef uint16_t Elf32_Half; + +/* Types for signed and unsigned 32-bit quantities. */ +typedef uint32_t Elf32_Word; +typedef int32_t Elf32_Sword; + +/* Types for signed and unsigned 64-bit quantities. */ +typedef uint64_t Elf32_Xword; +typedef int64_t Elf32_Sxword; + +/* Type of addresses. */ +typedef uint32_t Elf32_Addr; + +/* Type of file offsets. */ +typedef uint32_t Elf32_Off; + +/* Type for section indices, which are 16-bit quantities. */ +typedef uint16_t Elf32_Section; + +/* Type for version symbol information. */ +typedef Elf32_Half Elf32_Versym; + + +/* The ELF file header. This appears at the start of every ELF file. */ + +#define EI_NIDENT (16) + +typedef struct +{ + unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ + Elf32_Half e_type; /* Object file type */ + Elf32_Half e_machine; /* Architecture */ + Elf32_Word e_version; /* Object file version */ + Elf32_Addr e_entry; /* Entry point virtual address */ + Elf32_Off e_phoff; /* Program header table file offset */ + Elf32_Off e_shoff; /* Section header table file offset */ + Elf32_Word e_flags; /* Processor-specific flags */ + Elf32_Half e_ehsize; /* ELF header size in bytes */ + Elf32_Half e_phentsize; /* Program header table entry size */ + Elf32_Half e_phnum; /* Program header table entry count */ + Elf32_Half e_shentsize; /* Section header table entry size */ + Elf32_Half e_shnum; /* Section header table entry count */ + Elf32_Half e_shstrndx; /* Section header string table index */ +} Elf32_Ehdr; + +/* Program segment header. */ + +typedef struct +{ + Elf32_Word p_type; /* Segment type */ + Elf32_Off p_offset; /* Segment file offset */ + Elf32_Addr p_vaddr; /* Segment virtual address */ + Elf32_Addr p_paddr; /* Segment physical address */ + Elf32_Word p_filesz; /* Segment size in file */ + Elf32_Word p_memsz; /* Segment size in memory */ + Elf32_Word p_flags; /* Segment flags */ + Elf32_Word p_align; /* Segment alignment */ +} Elf32_Phdr; + +#define EI_MAG0 0 /* File identification byte 0 index */ +#define ELFMAG "\177ELF" +#define SELFMAG 4 +#define ET_EXEC 2 /* Executable file */ +#define EM_68K 4 /* Motorola m68k family */ +#define EV_CURRENT 1 /* Current version */ + +/* + * Section Headers + */ +typedef struct { + Elf32_Word sh_name; /* section name (.shstrtab index) */ + Elf32_Word sh_type; /* section type */ + Elf32_Word sh_flags; /* section flags */ + Elf32_Addr sh_addr; /* virtual address */ + Elf32_Off sh_offset; /* file offset */ + Elf32_Word sh_size; /* section size */ + Elf32_Word sh_link; /* link to another */ + Elf32_Word sh_info; /* misc info */ + Elf32_Word sh_addralign; /* memory alignment */ + Elf32_Word sh_entsize; /* table entry size */ +} Elf32_Shdr; + +/* sh_type */ +#define SHT_NULL 0 /* Section header table entry unused */ +#define SHT_PROGBITS 1 /* Program information */ +#define SHT_SYMTAB 2 /* Symbol table */ +#define SHT_STRTAB 3 /* String table */ +#define SHT_RELA 4 /* Relocation information w/ addend */ +#define SHT_HASH 5 /* Symbol hash table */ +#define SHT_DYNAMIC 6 /* Dynamic linking information */ +#define SHT_NOTE 7 /* Auxiliary information */ +#define SHT_NOBITS 8 /* No space allocated in file image */ +#define SHT_REL 9 /* Relocation information w/o addend */ +#define SHT_SHLIB 10 /* Reserved, unspecified semantics */ +#define SHT_DYNSYM 11 /* Symbol table for dynamic linker */ +#define SHT_NUM 12 + +#define SHT_LOOS 0x60000000 /* Operating system specific range */ +#define SHT_HIOS 0x6fffffff +#define SHT_LOPROC 0x70000000 /* Processor-specific range */ +#define SHT_HIPROC 0x7fffffff +#define SHT_LOUSER 0x80000000 /* Application-specific range */ +#define SHT_HIUSER 0xffffffff + +/* sh_flags */ +#define SHF_WRITE 0x1 /* Section contains writable data */ +#define SHF_ALLOC 0x2 /* Section occupies memory */ +#define SHF_EXECINSTR 0x4 /* Section contains executable insns */ + +#define SHF_MASKOS 0x0f000000 /* Operating system specific values */ +#define SHF_MASKPROC 0xf0000000 /* Processor-specific values */ + +/* end of rip from elf.h */ + +/* + * Values for 'bootflags'. + * Note: These must match the values NetBSD uses! + */ +#define ATARI_68000 1 /* 68000 CPU */ +#define ATARI_68010 (1<<1) /* 68010 CPU */ +#define ATARI_68020 (1<<2) /* 68020 CPU */ +#define ATARI_68030 (1<<3) /* 68030 CPU */ +#define ATARI_68040 (1<<4) /* 68040 CPU */ +#define ATARI_68060 (1<<6) /* 68060 CPU */ +#define ATARI_TT (1L<<11) /* This is a TT030 */ +#define ATARI_FALCON (1L<<12) /* This is a Falcon */ +#define ATARI_HADES (1L<<13) /* This is a Hades */ +#define ATARI_MILAN (1L<<14) /* This is a Milan */ + +#define ATARI_CLKBROKEN (1<<16) /* GEMDOS has faulty year base */ + +#define ATARI_ANYCPU (ATARI_68000|ATARI_68010|ATARI_68020|ATARI_68030|ATARI_68040|ATARI_68060) +#define ATARI_ANYMACH (ATARI_TT|ATARI_FALCON|ATARI_HADES|ATARI_MILAN) + +/* + * Definitions for boothowto + * Note: These must match the values NetBSD uses! + */ +#define RB_AUTOBOOT 0x00 +#define RB_ASKNAME 0x01 +#define RB_SINGLE 0x02 +#define RB_KDB 0x40 + + +/*--- Other defines ---*/ + +#undef PAGE_SIZE +#define PAGE_SIZE 8192 + +#define M68K_EMUL_RESET 0x7102 + +/* Start address of kernel in Atari RAM */ +#define KERNEL_START PAGE_SIZE + +/*--- Structures ---*/ + +struct atari_bootinfo { + uint32_t kp; /* 00: Kernel load address */ + uint32_t ksize; /* 04: Size of loaded kernel */ + uint32_t entry; /* 08: Kernel entry point */ + uint32_t stmem_size; /* 12: Size of st-ram */ + uint32_t ttmem_size; /* 16: Size of tt-ram */ + uint32_t bootflags; /* 20: Various boot flags */ + uint32_t boothowto; /* 24: How to boot */ + uint32_t ttmem_start; /* 28: Start of tt-ram */ + uint32_t esym_loc; /* 32: End of symbol table */ +}; + +static struct atari_bootinfo bi; + +static bool netbsd_load(void); +static void *load_file(const char *filename, uint32_t *length); +static bool check_kernel(void *kernel, Elf32_Addr *offset); +static bool set_machine_type(void); + + +/* NetBSD/m68k loader */ + +bool netbsd_init(void) +{ + uint8_t *ROMBaseHost = &RomMem[TosAddress]; + + if (!ConfigureParams.System.bMMU || ConfigureParams.Memory.STRamSize_KB < 8*1024) { + Log_AlertDlg(LOG_FATAL, "NetBSD requires MMU and at least 8MB of RAM!"); + return false; + } + /* RESET + Linux/m68k boot */ + ROMBaseHost[0x0000] = 0x4e; /* reset */ + ROMBaseHost[0x0001] = 0x70; + ROMBaseHost[0x0002] = 0x4e; /* jmp <abs.addr> */ + ROMBaseHost[0x0003] = 0xf9; + + /* TODO: ROM + 0x30 is Linux reset address on AB40, 0x4 on Falcon/TT */ +#if 0 + if (!(ConfigureParams.Log.bNatFeats && ConfigureParams.Netbsd.bHaltOnReboot)) { + /* set up a minimal OS for successful Linux/m68k reboot */ + ROMBaseHost[0x0030] = 0x46; /* move.w #$2700,sr */ + ROMBaseHost[0x0031] = 0xfc; + ROMBaseHost[0x0032] = 0x27; + ROMBaseHost[0x0033] = 0x00; + ROMBaseHost[0x0034] = 0x4e; /* reset */ + ROMBaseHost[0x0035] = 0x70; + ROMBaseHost[0x0036] = M68K_EMUL_RESET >> 8; + ROMBaseHost[0x0037] = M68K_EMUL_RESET & 0xff; + } else { + /* quit Hatari with NatFeats when Linux/m68k tries to reboot */ + ROMBaseHost[0x0030] = 0x48; /* pea.l NF_SHUTDOWN(pc) */ + ROMBaseHost[0x0031] = 0x7a; + ROMBaseHost[0x0032] = 0x00; + ROMBaseHost[0x0033] = 0x0c; + ROMBaseHost[0x0034] = 0x59; /* subq.l #4,sp */ + ROMBaseHost[0x0035] = 0x8f; + ROMBaseHost[0x0036] = 0x73; /* NF_ID */ + ROMBaseHost[0x0037] = 0x00; + ROMBaseHost[0x0038] = 0x2f; /* move.l d0,-(sp) */ + ROMBaseHost[0x0039] = 0x00; + ROMBaseHost[0x003a] = 0x59; /* subq.l #4,sp */ + ROMBaseHost[0x003b] = 0x8f; + ROMBaseHost[0x003c] = 0x73; /* NF_CALL */ + ROMBaseHost[0x003d] = 0x01; + ROMBaseHost[0x003e] = 'N'; /* "NF_SHUTDOWN" */ + ROMBaseHost[0x003f] = 'F'; + ROMBaseHost[0x0040] = '_'; + ROMBaseHost[0x0041] = 'S'; + ROMBaseHost[0x0042] = 'H'; + ROMBaseHost[0x0043] = 'U'; + ROMBaseHost[0x0044] = 'T'; + ROMBaseHost[0x0045] = 'D'; + ROMBaseHost[0x0046] = 'O'; + ROMBaseHost[0x0047] = 'W'; + ROMBaseHost[0x0048] = 'N'; + ROMBaseHost[0x0049] = 0; + } +#endif + return netbsd_load(); +} + +/*--- Private functions ---*/ + +static bool netbsd_load(void) +{ + const char *kernel_s = ConfigureParams.Netbsd.szKernelFileName; + Elf32_Addr kernel_offset; + bool loaded; + + void *kernel = NULL; + uint32_t kernel_length = 0; + + /* Load the kernel */ + kernel = load_file(kernel_s, &kernel_length); + if (!kernel) { + Log_AlertDlg(LOG_FATAL, "NetBSD: error loading NetBSD kernel:\n'%s'", kernel_s); + return false; + } + + /* Check the kernel */ + loaded = check_kernel(kernel, &kernel_offset); + + /* Kernel copied in Atari RAM, we can free them */ + free(kernel); + + if (loaded) { + } else { + Log_AlertDlg(LOG_FATAL, "NetBSD: error setting up kernel!"); + } + return true; +} + +static void *load_file(const char *filename, uint32_t *length) +{ + void *buffer = NULL; + long nFileLength = 0; + + if (strlen(filename) == 0) { + Dprintf(("NetBSD: empty filename\n")); + return NULL; + } + +#ifdef HAVE_LIBZ + buffer = File_ZlibRead(filename, &nFileLength); +#else + buffer = File_ReadAsIs(filename, &nFileLength); +#endif + *length = nFileLength; + + if (buffer) { + Dprintf(("NetBSD: (uncompressed) '%s' size: %d bytes\n", + filename, *length)); + } + return buffer; +} + +/** + * Load given kernel code to suitable memory area, + * and update bootinfo accordingly. + * Return true for success + */ +static bool check_kernel(void *kernel, Elf32_Addr *kernel_offset) +{ + /* map Hatari variables to Aranym code */ + const uint32_t RAMSize = 1024 * ConfigureParams.Memory.STRamSize_KB; + uint8_t *RAMBaseHost = STRam; + + const uint32_t FastRAMBase = 0x01000000; + + /* TODO: separate FastRAM setting for kernel & ramdisk? */ + const uint32_t FastRAMSize = TTmemory ? 1024 * ConfigureParams.Memory.TTRamSize_KB : 0; + + Elf32_Ehdr *kexec_elf; /* header of kernel executable */ + Elf32_Phdr *kernel_phdrs; + Elf32_Addr min_addr = 0xffffffff, max_addr = 0; + Elf32_Addr kernel_size; + Elf32_Addr mem_ptr; + Elf32_Addr symsize, symstart; + uint32_t *tmp; + int i; + int debug_flag; + int no_symbols; + int stmem_only; + char *ptr; + + bi.boothowto = RB_SINGLE; + debug_flag = 0; + no_symbols = 0; + stmem_only = 0; + + /* NetBSD does not seem to have a way to pass arguments to the kernel, + but we handle a few that loadbsd does */ + ptr = ConfigureParams.Netbsd.szCommandLine; + while (*ptr != '\0') + { + while (*ptr == ' ') + ptr++; + if (*ptr == '-') + { + ++ptr; + switch (*ptr) + { + case 'a': /* autoboot: Boot up to multi-user mode. */ + bi.boothowto &= ~(RB_SINGLE); + bi.boothowto |= RB_AUTOBOOT; + break; + case 'b': /* Ask for root device to use. */ + bi.boothowto |= RB_ASKNAME; + break; + case 'd': /* Enter kernel debugger. */ + bi.boothowto |= RB_KDB; + break; + case 'D': /* printout debug information while loading */ + debug_flag = 1; + break; + case 'N': + no_symbols = 1; /* No symbols must be loaded. */ + break; + case 's': + stmem_only = 1; + break; + } + } + while (*ptr != '\0' && *ptr != ' ') + ptr++; + } + + if (!set_machine_type()) { + return false; + } + + kexec_elf = (Elf32_Ehdr *) kernel; + if (memcmp(&kexec_elf->e_ident[EI_MAG0], ELFMAG, SELFMAG) != 0 || + SDL_SwapBE16(kexec_elf->e_type) != ET_EXEC || + SDL_SwapBE16(kexec_elf->e_machine) != EM_68K || + SDL_SwapBE32(kexec_elf->e_version) != EV_CURRENT) { + fprintf(stderr, "NetBSD: Invalid ELF header contents in kernel\n"); + return false; + } + + /*--- Copy the kernel at start of RAM ---*/ + + /* Load the program headers */ + kernel_phdrs = (Elf32_Phdr *) (((char *) kexec_elf) + SDL_SwapBE32(kexec_elf->e_phoff)); + + /* calculate the total required amount of memory */ + Dprintf(("NetBSD: kexec_elf->e_phnum = 0x%08x\n", SDL_SwapBE16(kexec_elf->e_phnum))); + + for (i = 0; i < SDL_SwapBE16(kexec_elf->e_phnum); i++) { + if (debug_flag) + { + printf("NetBSD: kernel_phdrs[%d].p_vaddr = 0x%08x\n", i, SDL_SwapBE32(kernel_phdrs[i].p_vaddr)); + printf("NetBSD: kernel_phdrs[%d].p_offset = 0x%08x\n", i, SDL_SwapBE32(kernel_phdrs[i].p_offset)); + printf("NetBSD: kernel_phdrs[%d].p_filesz = 0x%08x\n", i, SDL_SwapBE32(kernel_phdrs[i].p_filesz)); + printf("NetBSD: kernel_phdrs[%d].p_memsz = 0x%08x\n", i, SDL_SwapBE32(kernel_phdrs[i].p_memsz)); + } + + if (min_addr > SDL_SwapBE32(kernel_phdrs[i].p_vaddr)) { + min_addr = SDL_SwapBE32(kernel_phdrs[i].p_vaddr); + } + if (max_addr < SDL_SwapBE32(kernel_phdrs[i].p_vaddr) + SDL_SwapBE32(kernel_phdrs[i].p_memsz)) { + max_addr = SDL_SwapBE32(kernel_phdrs[i].p_vaddr) + SDL_SwapBE32(kernel_phdrs[i].p_memsz); + } + } + + kernel_size = max_addr - min_addr; + Dprintf(("NetBSD: kernel_size = %u\n", kernel_size)); + Dprintf(("NetBSD: %d kB ST-RAM, %d kB TT-RAM\n", + ConfigureParams.Memory.STRamSize_KB, + ConfigureParams.Memory.TTRamSize_KB)); + + /* + * look for symbols and calculate the size + * XXX: This increases the load time by a factor 2 for gzipped + * images! + */ + symsize = 0; + symstart = 0; + if (!no_symbols) + { + Elf32_Shdr *shdr = (Elf32_Shdr *) ((char *) kexec_elf + SDL_SwapBE32(kexec_elf->e_shoff)); + for (i = 0; i < SDL_SwapBE16(kexec_elf->e_shnum); i++) + { + if (SDL_SwapBE32(shdr[i].sh_type) == SHT_SYMTAB || SDL_SwapBE32(shdr[i].sh_type) == SHT_STRTAB) + { + if (shdr[i].sh_offset != 0) + { + Elf32_Addr size = SDL_SwapBE32(shdr[i].sh_size); + size = (size + 3) & -4; + symsize += size; + } + } + } + } + + if (symsize != 0) + { + symstart = kernel_size; + kernel_size += symsize + sizeof(*kexec_elf) + SDL_SwapBE16(kexec_elf->e_shnum) * sizeof(Elf32_Shdr); + } + + /* + * Note: the kernel copies itself to ST-RAM upon startup, + * so there is no point in loading it into FastRAM first + */ + if (KERNEL_START + kernel_size > RAMSize) { + fprintf(stderr, "NetBSD: kernel of size %x does not fit in RAM of size %x\n", kernel_size, RAMSize); + return false; + } + + *kernel_offset = 0; + mem_ptr = KERNEL_START; + int segments = SDL_SwapBE16(kexec_elf->e_phnum); + Dprintf(("NetBSD: copying %d segments to %s...\n", segments, + "ST-RAM")); + for (i = 0; i < segments; i++) { + Elf32_Word segment_length; + Elf32_Addr segment_ptr; + Elf32_Off segment_offset; + + segment_offset = SDL_SwapBE32(kernel_phdrs[i].p_offset); + segment_length = SDL_SwapBE32(kernel_phdrs[i].p_filesz); + + if (segment_offset == 0xffffffffu) { + fprintf(stderr, "NetBSD: Failed to seek to segment %d\n", i); + return false; + } + segment_ptr = SDL_SwapBE32(kernel_phdrs[i].p_vaddr); + + if (debug_flag) + { + printf("NetBSD: Copying segment %d: 0x%08x,0x%08x to 0x%08x-0x%08x\n", i, segment_offset, segment_length, *kernel_offset + mem_ptr + segment_ptr, *kernel_offset + mem_ptr + segment_ptr + segment_length); + } + memcpy(RAMBaseHost + mem_ptr + segment_ptr, (char *) kexec_elf + segment_offset, segment_length); + } + + /* + * Read symbols and strings + */ + if (symsize != 0) + { + unsigned char *p, *symtab; + int nhdrs; + Elf32_Shdr *shp; + Elf32_Addr size; + + symtab = RAMBaseHost + KERNEL_START + symstart; + + p = symtab + sizeof(*kexec_elf); + nhdrs = SDL_SwapBE16(kexec_elf->e_shnum); + memcpy(p, (char *) kexec_elf + SDL_SwapBE32(kexec_elf->e_shoff), nhdrs * sizeof(*shp)); + shp = (Elf32_Shdr*)p; + p += nhdrs * sizeof(*shp); + for (i = 0; i < nhdrs; i++) + { + if (SDL_SwapBE32(shp[i].sh_type) == SHT_SYMTAB || SDL_SwapBE32(shp[i].sh_type) == SHT_STRTAB) + { + if (shp[i].sh_offset != 0) + { + /* Get the symbol table. */ + size = SDL_SwapBE32(shp[i].sh_size); + if (debug_flag) + { + uint32_t pmem = (uint32_t)(p - RAMBaseHost); + printf("NetBSD: Copying %s: 0x%08x,0x%08x to 0x%08x-0x%08x\n", SDL_SwapBE32(shp[i].sh_type) == SHT_SYMTAB ? "symbol table" : "symbol strings", + SDL_SwapBE32(shp[i].sh_offset), size, pmem, pmem + SDL_SwapBE32(shp[i].sh_size)); + } + memcpy(p, (char *) kexec_elf + SDL_SwapBE32(shp[i].sh_offset), size); + shp[i].sh_offset = SDL_SwapBE32(p - symtab); + size = (size + 3) & -4; + p += size; + } + } + } + kexec_elf->e_shoff = SDL_SwapBE32(sizeof(*kexec_elf)); + memcpy(symtab, kexec_elf, sizeof(*kexec_elf)); + } + + /*--- Create the bootinfo structure ---*/ + + /* Machine type, memory banks */ + bi.kp = *kernel_offset + KERNEL_START; + bi.ksize = kernel_size; + bi.entry = SDL_SwapBE32(kexec_elf->e_entry); + bi.stmem_size = RAMSize; + bi.ttmem_size = stmem_only ? 0 : FastRAMSize; + bi.ttmem_start = FastRAMBase; + bi.esym_loc = symsize ? kernel_size : 0; + + if (debug_flag) + { + printf("Machine info:\n"); + printf("ST-RAM size\t: %10d bytes\n", bi.stmem_size); + printf("TT-RAM size\t: %10d bytes\n", bi.ttmem_size); + printf("TT-RAM start\t: 0x%08x\n", bi.ttmem_start); + printf("Cpu-type\t: 0x%08x\n", bi.bootflags); + printf("Kernel loadaddr\t: 0x%08x\n", bi.kp); + printf("Kernel size\t: %10d (0x%x) bytes\n", bi.ksize, bi.ksize); + printf("Kernel entry\t: 0x%08x\n", bi.entry); + printf("Kernel esym\t: 0x%08x\n", bi.esym_loc); + } + + /*--- Init SP & PC ---*/ + tmp = (uint32_t *)RAMBaseHost; + tmp[0] = SDL_SwapBE32(*kernel_offset + KERNEL_START); /* SP */ + tmp[1] = SDL_SwapBE32(0x00e00000); /* PC = ROMBase */ + + uint8_t *ROMBaseHost = &RomMem[0x00e00000]; + + /* fill in the jmp address at start of ROM, to the kernel entry point */ + tmp = (uint32_t *)ROMBaseHost; + tmp[1] = SDL_SwapBE32(bi.kp + bi.entry); + + /* + * the BSD kernel wants values into the following registers: + * d0: ttmem-size + * d1: stmem-size + * d2: cputype + * d3: boothowto + * d4: length of loaded kernel + * d5: start of fastram + * a0: start of loaded kernel + * a1: end of symbols (esym) + * All other registers zeroed for possible future requirements. + */ + regs.regs[0] = bi.ttmem_size; + regs.regs[1] = bi.stmem_size; + regs.regs[2] = bi.bootflags; + regs.regs[3] = bi.boothowto; + regs.regs[4] = bi.ksize; + regs.regs[5] = bi.ttmem_start; + regs.regs[6] = 0; + regs.regs[7] = 0; + regs.regs[8] = bi.kp; + regs.regs[9] = bi.esym_loc; + regs.regs[10] = 0; + regs.regs[11] = 0; + regs.regs[12] = 0; + regs.regs[13] = 0; + regs.regs[14] = 0; + + /* beware: make sure those register values remain valid until M68000_Start() is called */ + + Dprintf(("NetBSD: OK\n")); + + return true; +} + +/** + * Set machine type settings to bootinfo based on Hatari configuration + * Return true for success + */ +static bool set_machine_type(void) +{ + bi.bootflags = 0; + + switch (ConfigureParams.System.nMachineType) { + case MACHINE_FALCON: + bi.bootflags |= ATARI_FALCON; + break; + case MACHINE_TT: + bi.bootflags |= ATARI_TT; + break; + case MACHINE_STE: + case MACHINE_MEGA_STE: + break; + case MACHINE_ST: + case MACHINE_MEGA_ST: + break; + } + + switch(ConfigureParams.System.nCpuLevel) { + case 3: + bi.bootflags |= ATARI_68030; + break; + case 4: + bi.bootflags |= ATARI_68040; + break; + case 5: + bi.bootflags |= ATARI_68060; + break; + default: + Log_AlertDlg(LOG_FATAL, "NetBSD: BSD requires at least 030 CPU (for MMU), not 0%d0!", + ConfigureParams.System.nCpuLevel); + return false; + } + return true; +} diff --git a/src/options.c b/src/options.c index 2037c876..4aee8036 100644 --- a/src/options.c +++ b/src/options.c @@ -46,6 +46,7 @@ const char Options_fileid[] = "Hatari options.c"; #include "stMemory.h" #include "tos.h" #include "lilo.h" +#include "netbsd.h" bool bLoadAutoSave; /* Load autosave memory snapshot at startup */ @@ -189,6 +190,7 @@ enum { OPT_DEBUG, OPT_EXCEPTIONS, OPT_LILO, + OPT_NETBSD, OPT_BIOSINTERCEPT, OPT_CONOUT, OPT_DISASM, @@ -477,6 +479,7 @@ static const opt_t HatariOptions[] = { { OPT_EXCEPTIONS, NULL, "--debug-except", "<flags>", "Exceptions invoking debugger, see '--debug-except help'" }, { OPT_LILO, NULL, "--lilo", "<x>", "Boot Linux (see manual page)" }, + { OPT_NETBSD, NULL, "--netbsd", NULL, "Boot NetBSD (see manual page)" }, { OPT_BIOSINTERCEPT, NULL, "--bios-intercept", "<bool>", "Enable/disable XBIOS command parsing support" }, { OPT_CONOUT, NULL, "--conout", @@ -2129,6 +2132,14 @@ bool Opt_ParseParameters(int argc, const char * const argv[]) break; } + case OPT_NETBSD: { + bLoadAutoSave = false; + bUseNetbsd = true; + bUseTos = false; + ConfigureParams.HardDisk.bUseHardDiskDirectories = false; + break; + } + case OPT_BIOSINTERCEPT: ok = Opt_Bool(argv[++i], OPT_BIOSINTERCEPT, &bBiosIntercept); Log_Printf(LOG_DEBUG, "XBIOS 11/20/255 Hatari versions %sabled: " diff --git a/src/tos.c b/src/tos.c index c5006798..e980e0dc 100644 --- a/src/tos.c +++ b/src/tos.c @@ -35,6 +35,7 @@ const char TOS_fileid[] = "Hatari tos.c"; #include "str.h" #include "tos.h" #include "lilo.h" +#include "netbsd.h" #include "vdi.h" #include "falcon/dsp.h" #include "clocks_timings.h" @@ -1276,6 +1277,13 @@ int TOS_InitImage(void) if (!lilo_init()) return -1; } + else if (bUseNetbsd) + { + TosSize = 0; + /* load NetBSD */ + if (!netbsd_init()) + return -1; + } else if (!bUseTos) { /* Load test program (has to be done after memory has been cleared) */
Mail converted by MHonArc 2.6.19+ | http://listengine.tuxfamily.org/ |