[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/