[PATCH 1/4] Linux loader: add Aranym bootos_linux.cpp as lilo.c

[ Thread Index | Date Index | More lists.tuxfamily.org/hatari-devel Archives ]


bootos_linux.cpp as-is from Aranym commit 4825851105.
---
 src/lilo.c | 745 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 745 insertions(+)
 create mode 100644 src/lilo.c

diff --git a/src/lilo.c b/src/lilo.c
new file mode 100644
index 00000000..14d0e37e
--- /dev/null
+++ b/src/lilo.c
@@ -0,0 +1,745 @@
+/*
+	ROM / OS loader, Linux/m68k
+
+	ARAnyM (C) 2005-2008 Patrice Mandin
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "sysdeps.h"
+#include "cpu_emulation.h"
+#include "bootos_linux.h"
+#include "aranym_exception.h"
+#include "emul_op.h"
+
+#define DEBUG 1
+#include "debug.h"
+
+#include "SDL_compat.h"
+
+#ifdef ENABLE_LILO
+
+#ifdef HAVE_LIBZ
+#include <zlib.h>
+#endif
+
+/* linux specific include files */
+//#include <elf.h>
+#include <stdint.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 */
+
+/* end of rip from elf.h */
+
+/* #include <asm-m68k/bootinfo.h> */
+struct bi_record {
+    uint16 tag;			/* tag ID */
+    uint16 size;		/* size of record (in bytes) */
+    uint32 data[0];		/* data */
+};
+
+    /*
+     *  Tag Definitions
+     *
+     *  Machine independent tags start counting from 0x0000
+     *  Machine dependent tags start counting from 0x8000
+     */
+
+#define BI_LAST			0x0000	/* last record (sentinel) */
+#define BI_MACHTYPE		0x0001	/* machine type (u_long) */
+#define BI_CPUTYPE		0x0002	/* cpu type (u_long) */
+#define BI_FPUTYPE		0x0003	/* fpu type (u_long) */
+#define BI_MMUTYPE		0x0004	/* mmu type (u_long) */
+#define BI_MEMCHUNK		0x0005	/* memory chunk address and size */
+					/* (struct mem_info) */
+#define BI_RAMDISK		0x0006	/* ramdisk address and size */
+					/* (struct mem_info) */
+#define BI_COMMAND_LINE		0x0007	/* kernel command line parameters */
+					/* (string) */
+
+    /*
+     *  Atari-specific tags
+     */
+
+#define BI_ATARI_MCH_COOKIE	0x8000	/* _MCH cookie from TOS (u_long) */
+#define BI_ATARI_MCH_TYPE	0x8001	/* special machine type (u_long) */
+
+/* mch_type values */
+#define ATARI_MACH_AB40		3	/* Afterburner040 on Falcon */
+
+/* #include <asm-m68k/setup.h> */
+    /*
+     *  Linux/m68k Architectures
+     */
+
+#define MACH_ATARI    2
+
+    /*
+     *  CPU, FPU and MMU types
+     *
+     *  Note: we may rely on the following equalities:
+     *
+     *      CPU_68020 == MMU_68851
+     *      CPU_68030 == MMU_68030
+     *      CPU_68040 == FPU_68040 == MMU_68040
+     *      CPU_68060 == FPU_68060 == MMU_68060
+     */
+
+#define CPUB_68040     2
+#define CPU_68040      (1<<CPUB_68040)
+#define FPUB_68040     2                       /* Internal FPU */
+#define FPU_68040      (1<<FPUB_68040)
+#define MMUB_68040     2                       /* Internal MMU */
+#define MMU_68040      (1<<MMUB_68040)
+
+#ifdef PAGE_SIZE
+	/*	Might have been defined by vm_param.h. already, indirectly included by sysdeps.h */ 
+	#undef PAGE_SIZE
+#endif
+#define PAGE_SIZE 4096
+/*--- Defines ---*/
+
+#define MAXREAD_BLOCK_SIZE	(1<<20)	/* 1 MB */
+#define KERNEL_START		PAGE_SIZE	/* Start address of kernel in Atari RAM */
+#define RAMDISK_FS_START	0		/* Offset to start of fs in ramdisk file */
+
+#define MAX_BI_SIZE     (4096)
+
+#define GRANULARITY (256*1024) /* min unit for memory */
+#define ADD_CHUNK(start,siz)	\
+    {	\
+		unsigned long _start = (start);	\
+		unsigned long _size  = (siz) & ~(GRANULARITY-1);	\
+		\
+		if (_size > 0) {	\
+			bi.memory[bi.num_memory].addr = SDL_SwapBE32(_start);	\
+			bi.memory[bi.num_memory].size = SDL_SwapBE32(_size);	\
+			bi.num_memory++;	\
+		}	\
+	}
+
+/*--- Structures ---*/
+
+static union {
+	struct bi_record record;
+	unsigned char fake[MAX_BI_SIZE];
+} bi_union;
+
+#endif
+
+/*	Linux/m68k loader class */
+
+LinuxBootOs::LinuxBootOs(void) ARANYM_THROWS(AranymException)
+{
+	/* RESET + Linux/m68k boot */
+	ROMBaseHost[0x0000] = 0x4e;		/* reset */
+	ROMBaseHost[0x0001] = 0x70;
+	ROMBaseHost[0x0002] = 0x4e;		/* jmp <abs.addr> */
+	ROMBaseHost[0x0003] = 0xf9;
+
+	if (!halt_on_reboot) {
+		/* 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 {
+		/* code that shuts ARAnyM down 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;
+	}
+	init(true);
+}
+
+LinuxBootOs::~LinuxBootOs(void)
+{
+	cleanup();
+}
+
+void LinuxBootOs::reset(bool cold) ARANYM_THROWS(AranymException)
+{
+	init(cold);
+}
+
+/*--- Private functions ---*/
+
+void LinuxBootOs::cleanup(void)
+{
+	if (kernel!=NULL) {
+		free(kernel);
+		kernel=NULL;
+	}
+
+	if (ramdisk!=NULL) {
+		free(ramdisk);
+		ramdisk=NULL;
+	}
+}
+
+void LinuxBootOs::init(bool cold)
+{
+	kernel=ramdisk=NULL;
+	kernel_length=ramdisk_length=0;
+	bi_size = 0;
+	bi.ramdisk.addr = 0;
+	bi.ramdisk.size = 0;
+
+	UNUSED(cold);
+#ifdef ENABLE_LILO
+	/* Load the kernel */
+	kernel=loadFile(bx_options.lilo.kernel, &kernel_length);
+	if (kernel==NULL) {
+		throw AranymException("ARAnyM LILO: Error loading kernel '%s'", bx_options.lilo.kernel);
+	}
+
+	/* Load the ramdisk */
+	if (strlen(bx_options.lilo.ramdisk) > 0) {
+		ramdisk=loadFile(bx_options.lilo.ramdisk, &ramdisk_length);
+		if (ramdisk==NULL) {
+			infoprint("ARAnyM LILO: Error loading ramdisk '%s'", bx_options.lilo.ramdisk);
+		}
+	}
+
+	memset(RAMBaseHost, 0, RAMSize);
+	memset(FastRAMBaseHost, 0, FastRAMSize);
+
+	/* Check the kernel */
+	if (checkKernel()<0) {
+		cleanup();
+		throw AranymException("ARAnyM LILO: Error setting up kernel");
+	}
+
+	/* Kernel and ramdisk copied in Atari RAM, we can free it */
+	cleanup();
+#else
+	throw AranymException("ARAnyM LILO: not compiled in");
+#endif /* ENABLE_LILO */
+}
+
+void *LinuxBootOs::loadFile(const char *filename, unsigned long *length)
+{
+	void *buffer = NULL;
+
+#ifdef ENABLE_LILO
+
+#ifdef HAVE_LIBZ
+	unsigned long unc_len;
+	gzFile handle;
+#else
+	int handle;
+#endif
+
+	if (strlen(filename)==0) {
+		D(bug("lilo: empty finename"));
+		return NULL;
+	}
+
+	/* Try to open the file, libz takes care of non-gzipped files */
+#ifdef HAVE_LIBZ
+	handle = gzopen(filename, "rb");
+	if (handle == NULL)
+#else
+	handle = open(filename, O_RDONLY);
+	if (handle<0)
+#endif
+	{
+		D(bug("lilo: unable to open %s", filename));	
+		return NULL;
+	}
+
+#ifdef HAVE_LIBZ
+	/* Search the length of the uncompressed stream */
+	buffer = (char *)malloc(MAXREAD_BLOCK_SIZE);
+	if (buffer==NULL) {
+		D(bug("lilo: unable to allocate %d bytes", MAXREAD_BLOCK_SIZE));
+		gzclose(handle);
+		return NULL;
+	}
+
+	*length = 0;
+	unc_len = gzread(handle, buffer, MAXREAD_BLOCK_SIZE);
+	while (unc_len>0) {
+		*length += unc_len;
+		unc_len = gzread(handle, buffer, MAXREAD_BLOCK_SIZE);
+	}
+	// Avoid gzseek, it is often broken with LFS which we enable by
+	// default
+	gzrewind(handle);
+	D(bug("lilo: uncompressing '%s'", filename));
+	D(bug("lilo:  uncompressed length: %lu bytes", *length));
+
+	free(buffer);
+	buffer=NULL;
+#else
+	*length = lseek(handle, 0, SEEK_END);
+	lseek(handle, 0, SEEK_SET); 	
+#endif
+
+	buffer = (char *)malloc(*length);
+	if (buffer==NULL) {
+		D(bug("lilo: unable to allocate %ld bytes", *length));
+#ifdef HAVE_LIBZ
+		gzclose(handle);
+#else
+		close(handle);
+#endif
+		return NULL;
+	}
+
+#ifdef HAVE_LIBZ
+	gzread(handle, buffer, *length);
+	gzclose(handle);
+#else
+	read(handle, buffer, *length);
+	close(handle);
+#endif
+
+#else
+	UNUSED(filename);
+	UNUSED(length);
+#endif /* ENABLE_LILO */
+	return buffer;
+}
+
+int LinuxBootOs::checkKernel(void)
+{
+#ifdef ENABLE_LILO
+    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 kernel_offset;
+	int i;
+	const char *kname, *kernel_name="vmlinux";
+	bool load_to_fastram = bx_options.lilo.load_to_fastram && FastRAMSize > 0;
+
+	kexec_elf = (Elf32_Ehdr *) kernel;
+	if (memcmp( &kexec_elf->e_ident[EI_MAG0], ELFMAG, SELFMAG ) == 0) {
+		if ((SDL_SwapBE16(kexec_elf->e_type) != ET_EXEC) || (SDL_SwapBE16(kexec_elf->e_machine) != EM_68K) ||
+			(SDL_SwapBE32(kexec_elf->e_version) != EV_CURRENT)) {
+			bug("lilo: Invalid ELF header contents in kernel");
+			return -1;
+		}
+	}
+
+	/*--- 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 */
+	D(bug("lilo: kexec_elf->e_phnum=0x%08x",SDL_SwapBE16(kexec_elf->e_phnum)));
+
+	for (i=0; i<SDL_SwapBE16(kexec_elf->e_phnum); i++) {
+		D(bug("lilo: kernel_phdrs[%d].p_vaddr=0x%08x",i,SDL_SwapBE32(kernel_phdrs[i].p_vaddr)));
+		D(bug("lilo: kernel_phdrs[%d].p_offset=0x%08x",i,SDL_SwapBE32(kernel_phdrs[i].p_offset)));
+		D(bug("lilo: kernel_phdrs[%d].p_filesz=0x%08x",i,SDL_SwapBE32(kernel_phdrs[i].p_filesz)));
+		D(bug("lilo: kernel_phdrs[%d].p_memsz=0x%08x",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);
+		}
+	}
+
+	/* This is needed for newer linkers that include the header in
+		the first segment.  */
+	D(bug("lilo: min_addr=0x%08x",min_addr));
+	D(bug("lilo: max_addr=0x%08x",max_addr));
+
+	if (min_addr == 0) {
+		D(bug("lilo: new linker"));
+		D(bug("lilo:  kernel_phdrs[0].p_vaddr=0x%08x",SDL_SwapBE32(kernel_phdrs[0].p_vaddr)));
+		D(bug("lilo:  kernel_phdrs[0].p_offset=0x%08x",SDL_SwapBE32(kernel_phdrs[0].p_offset)));
+		D(bug("lilo:  kernel_phdrs[0].p_filesz=0x%08x",SDL_SwapBE32(kernel_phdrs[0].p_filesz)));
+		D(bug("lilo:  kernel_phdrs[0].p_memsz=0x%08x",SDL_SwapBE32(kernel_phdrs[0].p_memsz)));
+
+		min_addr = PAGE_SIZE;
+		/*kernel_phdrs[0].p_vaddr += PAGE_SIZE;*/
+		kernel_phdrs[0].p_vaddr = SDL_SwapBE32(SDL_SwapBE32(kernel_phdrs[0].p_vaddr) + PAGE_SIZE);
+		/*kernel_phdrs[0].p_offset += PAGE_SIZE;*/
+		kernel_phdrs[0].p_offset = SDL_SwapBE32(SDL_SwapBE32(kernel_phdrs[0].p_offset) + PAGE_SIZE);
+		/*kernel_phdrs[0].p_filesz -= PAGE_SIZE;*/
+		kernel_phdrs[0].p_filesz = SDL_SwapBE32(SDL_SwapBE32(kernel_phdrs[0].p_filesz) - PAGE_SIZE);
+		/*kernel_phdrs[0].p_memsz -= PAGE_SIZE;*/
+		kernel_phdrs[0].p_memsz = SDL_SwapBE32(SDL_SwapBE32(kernel_phdrs[0].p_memsz) - PAGE_SIZE);
+
+		D(bug("lilo: modified to:"));
+		D(bug("lilo:  kernel_phdrs[0].p_vaddr=0x%08x",SDL_SwapBE32(kernel_phdrs[0].p_vaddr)));
+		D(bug("lilo:  kernel_phdrs[0].p_offset=0x%08x",SDL_SwapBE32(kernel_phdrs[0].p_offset)));
+		D(bug("lilo:  kernel_phdrs[0].p_filesz=0x%08x",SDL_SwapBE32(kernel_phdrs[0].p_filesz)));
+		D(bug("lilo:  kernel_phdrs[0].p_memsz=0x%08x",SDL_SwapBE32(kernel_phdrs[0].p_memsz)));
+	}
+	kernel_size = max_addr - min_addr;
+	D(bug("lilo: kernel_size=%u",kernel_size));
+
+	if (load_to_fastram)
+	{
+		if (KERNEL_START + kernel_size > FastRAMSize)
+		{
+			bug("lilo: kernel of size %x does not fit in TT-RAM of size %x", kernel_size, FastRAMSize);
+			load_to_fastram = false;
+		}
+	}
+	if (!load_to_fastram)
+	{
+		if (KERNEL_START + kernel_size > RAMSize)
+		{
+			bug("lilo: kernel of size %x does not fit in RAM of size %x", kernel_size, RAMSize);
+			return -1;
+		}
+	}
+
+	if (load_to_fastram)
+		kernel_offset = FastRAMBase;
+	else
+		kernel_offset = 0;
+	mem_ptr = KERNEL_START;
+	for (i=0; i<SDL_SwapBE16(kexec_elf->e_phnum); 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 == 0xffffffffUL) {
+		    bug("lilo: Failed to seek to segment %d",i);
+			return -1;
+		}
+		segment_ptr = SDL_SwapBE32(kernel_phdrs[i].p_vaddr) - PAGE_SIZE;
+
+		if (load_to_fastram)
+			memcpy(FastRAMBaseHost + mem_ptr + segment_ptr, (char *) kexec_elf + segment_offset, segment_length);
+		else
+			memcpy(RAMBaseHost + mem_ptr + segment_ptr, (char *) kexec_elf + segment_offset, segment_length);
+
+	    D(bug("lilo: Copied segment %d: 0x%08x,0x%08x at 0x%08x",i,segment_offset,segment_length,kernel_offset+mem_ptr+segment_ptr));
+	}
+
+	/*--- Copy the ramdisk after kernel (and reserved bootinfo) ---*/
+	if (ramdisk && ramdisk_length) {
+		Elf32_Addr rd_start;
+		Elf32_Word rd_len;
+		Elf32_Off rd_offset;
+
+		if (load_to_fastram)
+			rd_offset = KERNEL_START + kernel_size + MAX_BI_SIZE;
+		else
+			rd_offset = 0;
+		rd_len = ramdisk_length - RAMDISK_FS_START;
+		if (FastRAMSize > rd_offset + rd_len) {
+			/* Load in FastRAM */
+			rd_start = FastRAMBase + FastRAMSize - rd_len;
+			memcpy(FastRAMBaseHost + rd_start - FastRAMBase, (unsigned char *)ramdisk + RAMDISK_FS_START, rd_len);
+		} else {
+			/* Load in ST-RAM */
+			if (load_to_fastram)
+				rd_offset = PAGE_SIZE;
+			else
+				rd_offset = KERNEL_START + kernel_size + MAX_BI_SIZE;
+			if (RAMSize < rd_offset + rd_len) {
+				bug("lilo: not enough memory to load ramdisk of size %u", rd_len);
+				return -1;
+			}
+			rd_start = RAMSize - rd_len;
+			memcpy(RAMBaseHost+rd_start, ((unsigned char *)ramdisk) + RAMDISK_FS_START, rd_len);
+		}
+
+		bi.ramdisk.addr = SDL_SwapBE32(rd_start);
+		bi.ramdisk.size = SDL_SwapBE32(rd_len);
+	    D(bug("lilo: Ramdisk at 0x%08x in RAM, length=0x%08x", rd_start, rd_len));
+	} else {
+		bi.ramdisk.addr = 0;
+		bi.ramdisk.size = 0;
+	    D(bug("lilo: No ramdisk"));
+	}
+
+	/*--- Create the bootinfo structure ---*/
+
+	/* Command line */
+	kname = kernel_name;
+    if (strncmp( kernel_name, "local:", 6 ) == 0) {
+		kname += 6;
+	}
+    if (strlen(bx_options.lilo.args) > CL_SIZE-1) {
+		bug("lilo: kernel command line too long");
+		return -1;
+    }
+	strcpy(bi.command_line, bx_options.lilo.args);
+    if (strlen(bi.command_line)+1+strlen(kname)+12 < CL_SIZE-1) {
+		if (*bi.command_line) {
+			strcat( bi.command_line, " " );
+		}
+		strcat( bi.command_line, "BOOT_IMAGE=" );
+		strcat( bi.command_line, kname );
+    } else
+    {
+		bug("lilo: kernel command line too long to include kernel name");
+    }
+
+    D(bug("lilo: config_file command line: %s", bx_options.lilo.args ));
+    D(bug("lilo: kernel command line: %s", bi.command_line ));
+
+	/* Machine type, memory banks */
+	bi.machtype = SDL_SwapBE32(MACH_ATARI);
+	bi.cputype = SDL_SwapBE32(CPU_68040);
+	bi.fputype = SDL_SwapBE32(FPU_68040);
+	bi.mmutype = SDL_SwapBE32(MMU_68040);
+	bi.mch_cookie = SDL_SwapBE32(0x00030000);
+	bi.mch_type = SDL_SwapBE32(ATARI_MACH_AB40);
+
+	bi.num_memory=0;
+	/* If loading to FastRAM switch the order of ST and Fast RAM */
+	if (!load_to_fastram)
+		ADD_CHUNK(0, RAMSize);
+	if (FastRAMSize>0) {
+		ADD_CHUNK(FastRAMBase, FastRAMSize);
+	}
+	if (load_to_fastram)
+		ADD_CHUNK(0, RAMSize);
+	bi.num_memory=SDL_SwapBE32(bi.num_memory);
+
+	if (!create_bootinfo()) {
+	    bug("lilo: Can not create bootinfo structure");
+		return -1;
+	}
+
+	/*--- Copy boot info in RAM ---*/
+	if (load_to_fastram)
+		memcpy(FastRAMBaseHost + KERNEL_START + kernel_size, &bi_union.record, bi_size);
+	else
+		memcpy(RAMBaseHost + KERNEL_START + kernel_size, &bi_union.record, bi_size);
+	D(bug("lilo: bootinfo at 0x%08x", kernel_offset + KERNEL_START + kernel_size));
+
+#if DEBUG
+	for (i=0; i<16; i++) {
+		uint32 *tmp;
+
+		if (load_to_fastram)
+			tmp = (uint32 *)((unsigned char *)FastRAMBaseHost + KERNEL_START + kernel_size);
+		else
+			tmp = (uint32 *)((unsigned char *)RAMBaseHost + KERNEL_START + kernel_size);
+		D(bug("lilo: bi_union.record[%d]=0x%08x",i, SDL_SwapBE32(tmp[i])));
+	}
+#endif
+
+	/*--- Init SP & PC ---*/
+	uint32 *tmp = (uint32 *)RAMBaseHost;
+	tmp[0] = SDL_SwapBE32(kernel_offset + KERNEL_START);	/* SP */
+	tmp[1] = SDL_SwapBE32(0x00e00000);		/* PC = ROMBase */
+	ROMBaseHost[4] = (kernel_offset + KERNEL_START) >> 24;
+	ROMBaseHost[5] = (kernel_offset + KERNEL_START) >> 16;
+	ROMBaseHost[6] = (kernel_offset + KERNEL_START) >>  8;
+	ROMBaseHost[7] = (kernel_offset + KERNEL_START) & 0xff;
+	
+	D(bug("lilo: ok"));
+
+	return 0;
+#else
+	return -1;
+#endif /* ENABLE_LILO */
+}
+
+    /*
+     *  Create the Bootinfo Structure
+     */
+
+int LinuxBootOs::create_bootinfo(void)
+{
+#ifdef ENABLE_LILO
+	unsigned int i;
+	struct bi_record *record;
+
+	/* Initialization */
+	bi_size = 0;
+
+	/* Generic tags */
+	if (!add_bi_record(BI_MACHTYPE, sizeof(bi.machtype), &bi.machtype))
+		return(0);
+	if (!add_bi_record(BI_CPUTYPE, sizeof(bi.cputype), &bi.cputype))
+		return(0);
+	if (!add_bi_record(BI_FPUTYPE, sizeof(bi.fputype), &bi.fputype))
+		return(0);
+	if (!add_bi_record(BI_MMUTYPE, sizeof(bi.mmutype), &bi.mmutype))
+		return(0);
+	for (i = 0; i < SDL_SwapBE32(bi.num_memory); i++) {
+		if (!add_bi_record(BI_MEMCHUNK, sizeof(bi.memory[i]), &bi.memory[i]))
+			return(0);
+	}
+	if (SDL_SwapBE32(bi.ramdisk.size)) {
+		if (!add_bi_record(BI_RAMDISK, sizeof(bi.ramdisk), &bi.ramdisk))
+			return(0);
+	}
+	if (!add_bi_string(BI_COMMAND_LINE, bi.command_line))
+		return(0);
+
+	/* Atari tags */
+	if (!add_bi_record(BI_ATARI_MCH_COOKIE, sizeof(bi.mch_cookie), &bi.mch_cookie))
+		return(0);
+	if (!add_bi_record(BI_ATARI_MCH_TYPE, sizeof(bi.mch_type), &bi.mch_type))
+		return(0);
+
+    /* Trailer */
+    record = (struct bi_record *)((char *)&bi_union.record+bi_size);
+    record->tag = SDL_SwapBE16(BI_LAST);
+    bi_size += sizeof(bi_union.record.tag);
+
+    return(1);
+#else
+	return(0);
+#endif /* ENABLE_LILO */
+}
+
+    /*
+     *  Add a Record to the Bootinfo Structure
+     */
+
+int LinuxBootOs::add_bi_record( unsigned short tag, unsigned short size, const void *data)
+{
+#ifdef ENABLE_LILO
+    struct bi_record *record;
+    u_short size2;
+
+    size2 = (sizeof(struct bi_record)+size+3)&-4;
+    if (bi_size+size2+sizeof(bi_union.record.tag) > MAX_BI_SIZE) {
+	bug("Can't add bootinfo record. Ask a wizard to enlarge me.");
+	return(0);
+    }
+    record = (struct bi_record *)((char *)&bi_union.record+bi_size);
+    record->tag = SDL_SwapBE16(tag);
+    record->size = SDL_SwapBE16(size2);
+    memcpy((char *)record + sizeof(struct bi_record), data, size);
+    bi_size += size2;
+
+#else
+	UNUSED(tag);
+	UNUSED(size);
+	UNUSED(data);
+#endif /* ENABLE_LILO */
+    return(1);
+}
+
+    /*
+     *  Add a String Record to the Bootinfo Structure
+     */
+
+int LinuxBootOs::add_bi_string(unsigned short tag, const char *s)
+{
+#ifdef ENABLE_LILO
+    return add_bi_record(tag, strlen(s)+1, (void *)s);
+#else
+	UNUSED(tag);
+	UNUSED(s);
+	return 0;
+#endif /* ENABLE_LILO */
+}
-- 
2.11.0


--------------676EC20B7BBD131CA1167E41--



Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/