diff -ur arcboot-0.3.6/common/subarch.h arcboot-0.3.6-elf64/common/subarch.h --- arcboot-0.3.6/common/subarch.h 2003-04-26 16:45:36.000000000 -0700 +++ arcboot-0.3.6-elf64/common/subarch.h 2004-02-01 00:48:30.000000000 -0800 @@ -12,6 +12,7 @@ /* supported subarches */ #define IP22 0 +#define IP32 1 /* * Reserve this memory for loading kernel @@ -31,6 +32,10 @@ .base = 0x88002000, .reserved = 0x800000, }, + { /* IP32 */ + .base = 0x80002000, + .reserved = 0x800000, + }, }; /* we filter these out of the command line */ diff -ur arcboot-0.3.6/ext2load/Makefile arcboot-0.3.6-elf64/ext2load/Makefile --- arcboot-0.3.6/ext2load/Makefile 2003-04-26 16:39:07.000000000 -0700 +++ arcboot-0.3.6-elf64/ext2load/Makefile 2004-01-31 15:33:00.000000000 -0800 @@ -40,4 +40,4 @@ sed -e "s/@@LOADADDR@@/$$LOADADDR/" <$< >$@ clean: - rm -f $(TARGETS) *.a *.o tags + rm -f $(TARGETS) *.a *.o tags ld.script diff -ur arcboot-0.3.6/ext2load/loader.c arcboot-0.3.6-elf64/ext2load/loader.c --- arcboot-0.3.6/ext2load/loader.c 2003-04-26 17:01:00.000000000 -0700 +++ arcboot-0.3.6-elf64/ext2load/loader.c 2004-02-01 00:51:19.000000000 -0800 @@ -27,6 +27,14 @@ CHAR *OSLoadPartition = NULL; CHAR *OSLoadFilename = NULL; CHAR *OSLoadOptions = NULL; +static int is64=0; + + +typedef union { + unsigned char e_ident[EI_NIDENT]; + Elf32_Ehdr header32; + Elf64_Ehdr header64; +} Elf_Ehdr; static void Wait(const char *prompt) { @@ -170,23 +178,39 @@ } -void LoadProgramSegments(ext2_file_t file, Elf32_Ehdr * header) +void LoadProgramSegments(ext2_file_t file, Elf_Ehdr * header) { int idx; Boolean loaded = False; - Elf32_Phdr *segment, *segments; - size_t size = header->e_phentsize * header->e_phnum; + void *segments; + size_t size; errcode_t status; + if (header->e_ident[EI_CLASS] == ELFCLASS32) + size = (size_t) (header->header32.e_phentsize * + header->header32.e_phnum); + else + size = (size_t) (header->header64.e_phentsize * + header->header64.e_phnum); + if (size <= 0) Fatal("No program segments\n\r"); segments = malloc(size); if (segments == NULL) Fatal("Cannot allocate memory for segment headers\n\r"); + else + printf("Allocated 0x%x bytes for segments\n\r",size); - status = - ext2fs_file_lseek(file, header->e_phoff, EXT2_SEEK_SET, NULL); + if (header->e_ident[EI_CLASS] == ELFCLASS32) { + status = ext2fs_file_lseek(file, + (ext2_off_t) header->header32.e_phoff, + EXT2_SEEK_SET, NULL); + } else { + status = ext2fs_file_lseek(file, + (ext2_off_t) header->header64.e_phoff, + EXT2_SEEK_SET, NULL); + } if (status != 0) { print_ext2fs_error(status); Fatal("Cannot seek to program segment headers\n\r"); @@ -198,48 +222,98 @@ Fatal("Cannot read program segment headers\n\r"); } - segment = segments; - for (idx = 0; idx < header->e_phnum; idx++) { - if (segment->p_type == PT_LOAD) { - printf - ("Loading program segment %u at 0x%x, size = 0x%x\n\r", - idx + 1, KSEG0ADDR(segment->p_vaddr), - segment->p_filesz); - - status = - ext2fs_file_lseek(file, segment->p_offset, - EXT2_SEEK_SET, NULL); - if (status != 0) { + if(header->e_ident[EI_CLASS] == ELFCLASS32) { + Elf32_Phdr* segment=(Elf32_Phdr*)segments; + printf("Loading 32-bit executable\n\r"); + for (idx = 0; idx < header->header32.e_phnum; idx++) { + if (segment->p_type == PT_LOAD) { + printf + ("Loading program segment %u at 0x%x, offset=0x%x, size = 0x%x\n\r", + idx + 1, KSEG0ADDR(segment->p_vaddr), + segment->p_offset, segment->p_filesz); + + status = + ext2fs_file_lseek(file, segment->p_offset, + EXT2_SEEK_SET, NULL); + if (status != 0) { + print_ext2fs_error(status); + Fatal("Cannot seek to program segment\n\r"); + } + + status = ext2fs_file_read(file, + (void *) (KSEG0ADDR( + segment->p_vaddr)), + segment->p_filesz, NULL); + if (status != 0) { print_ext2fs_error(status); - Fatal("Cannot seek to program segment\n\r"); - } + Fatal("Cannot read program segment\n\r"); + } + + size = segment->p_memsz - segment->p_filesz; + if (size > 0) { + printf + ("Zeroing memory at 0x%x, size = 0x%x\n\r", + (KSEG0ADDR(segment->p_vaddr + + segment->p_filesz)), size); + memset((void *) + (KSEG0ADDR(segment-> + p_vaddr + segment->p_filesz)), 0, size); + } + + loaded = True; + } + + segment = + (Elf32_Phdr *) (((char *) segment) + + header->header32.e_phentsize); + } + } else { + Elf64_Phdr* segment=(Elf64_Phdr*)segments; + is64=1; + printf("Loading 64-bit executable\n\r"); + for (idx = 0; idx < header->header64.e_phnum; idx++) { + if (segment->p_type == PT_LOAD) { + printf + ("Loading program segment %u at 0x%x, offset=0x%lx %lx, size = 0x%lx %lx\n\r", + idx + 1, KSEG0ADDR(segment->p_vaddr), + (long)(segment->p_offset>>32),(long)(segment->p_offset&0xffffffff), + (long)(segment->p_filesz>>32),(long)(segment->p_filesz&0xffffffff)); + + status = + ext2fs_file_lseek(file, segment->p_offset, + EXT2_SEEK_SET, NULL); + if (status != 0) { + print_ext2fs_error(status); + Fatal("Cannot seek to program segment\n\r"); + } - status = ext2fs_file_read(file, + status = ext2fs_file_read(file, (void *) (KSEG0ADDR( segment->p_vaddr)), segment->p_filesz, NULL); - if (status != 0) { + if (status != 0) { print_ext2fs_error(status); Fatal("Cannot read program segment\n\r"); - } + } - size = segment->p_memsz - segment->p_filesz; - if (size > 0) { - printf - ("Zeroing memory at 0x%x, size = 0x%x\n\r", - (KSEG0ADDR(segment->p_vaddr + - segment->p_filesz)), size); - memset((void *) + size = segment->p_memsz - segment->p_filesz; + if (size > 0) { + printf + ("Zeroing memory at 0x%x, size = 0x%x\n\r", + (KSEG0ADDR(segment->p_vaddr + + segment->p_filesz)), size); + memset((void *) (KSEG0ADDR(segment-> p_vaddr + segment->p_filesz)), 0, size); - } + } - loaded = True; - } + loaded = True; + } - segment = - (Elf32_Phdr *) (((char *) segment) + - header->e_phentsize); + segment = + (Elf64_Phdr *) (((char *) segment) + + header->header64.e_phentsize); + } } if (!loaded) @@ -249,9 +323,10 @@ } -ULONG LoadKernelFile(ext2_file_t file) +Elf64_Addr LoadKernelFile(ext2_file_t file) { - Elf32_Ehdr header; + Elf_Ehdr header; + Elf64_Addr entry; errcode_t status; status = @@ -264,8 +339,9 @@ if (memcmp(&(header.e_ident[EI_MAG0]), ELFMAG, SELFMAG) != 0) Fatal("Not an ELF file\n\r"); - if (header.e_ident[EI_CLASS] != ELFCLASS32) - Fatal("Not a 32-bit file\n\r"); + if (header.e_ident[EI_CLASS] != ELFCLASS32 && + header.e_ident[EI_CLASS] != ELFCLASS64) + Fatal("Not a 32-bit or 64-bit file\n\r"); if (header.e_ident[EI_DATA] != ELFDATA2MSB) Fatal("Not a big-endian file\n\r"); @@ -273,20 +349,33 @@ if (header.e_ident[EI_VERSION] != EV_CURRENT) Fatal("Wrong ELF version\n\r"); - if (header.e_type != ET_EXEC) + if (header.e_ident[EI_CLASS]==ELFCLASS32) { + if (header.header32.e_type != ET_EXEC) + Fatal("Not an executable file\n\r"); + + if (header.header32.e_machine != EM_MIPS) + Fatal("Unsupported machine type\n\r"); + + if (header.header32.e_version != EV_CURRENT) + Fatal("Wrong ELF version\n\r"); + + entry = (Elf64_Addr) header.header32.e_entry; + } else { + if (header.header64.e_type != ET_EXEC) Fatal("Not an executable file\n\r"); - if (header.e_machine != EM_MIPS) + if (header.header64.e_machine != EM_MIPS) Fatal("Unsupported machine type\n\r"); - if (header.e_version != EV_CURRENT) + if (header.header64.e_version != EV_CURRENT) Fatal("Wrong ELF version\n\r"); + entry = header.header64.e_entry; + } + LoadProgramSegments(file, &header); - printf("Starting kernel; entry point = 0x%lx\n\r", - ((ULONG) KSEG0ADDR(header.e_entry))); - return KSEG0ADDR(header.e_entry); + return entry; } @@ -320,7 +409,7 @@ return True; } -ULONG LoadKernel(const char *partition, const char *filename) +Elf64_Addr LoadKernel(const char *partition, const char *filename) { ext2_file_t file; @@ -337,12 +426,26 @@ printf("%u: %s\n\r", i, argv[i]); } +void _start64(LONG argc, CHAR * argv[], CHAR * envp[], + unsigned long long *addr) +{ + asm volatile (".set mips4\n" + "\t.set noreorder\n" + "\tld $2, 0($7)\n" + "\tj $2\n" + "\tnop\n" + "\t.set noreorder\n" + "\t.set mips0"); +} + void _start(LONG argc, CHAR *argv[], CHAR *envp[]) { CHAR** nargv; CHAR** params; int nargc, nopt; - void (*kernel_entry)(int argc, CHAR * argv[], CHAR * envp[]); + + Elf32_Addr kernel_entry32; + Elf64_Addr kernel_entry64; /* Print identification */ printf(ANSI_CLEAR "\n\rarcsboot: ARCS Linux ext2fs loader " @@ -393,17 +496,29 @@ } } printf("Loading %s from %s\n\r",(params) ? params[0] : OSLoadFilename, OSLoadPartition); - kernel_entry = LoadKernel(OSLoadPartition, OSLoadFilename); + kernel_entry64 = LoadKernel(OSLoadPartition, OSLoadFilename); + kernel_entry32 = (Elf32_Addr) kernel_entry64; #if DEBUG printf("Command line after config file: \n\r"); printCmdLine(nargc, nargv); + printf("Kernel entry: 0x%lx %lx\n\r", + (long)(kernel_entry64>>32),(long)(kernel_entry64&0xffffffff)); Wait("\n\r--- Debug: press to boot kernel ---"); #endif - ArcFlushAllCaches(); - if( kernel_entry ) - (*kernel_entry)(nargc ,nargv, envp); - else + if( kernel_entry64 ) { + if(is64==0){ + printf("Starting 32-bit kernel\n\r"); + ArcFlushAllCaches(); + ((void (*)(int argc, CHAR * argv[], CHAR * envp[])) + kernel_entry32)(nargc ,nargv, envp); + } else { + printf("Starting 64-bit kernel\n\r"); + ArcFlushAllCaches(); + _start64(nargc ,nargv, envp, &kernel_entry64); + } + } else { printf("Invalid kernel entry NULL\n\r"); + } /* Not likely to get back here in a functional state, but what the heck */ Wait("\n\r--- Press to restart ---");