Recent build changes have added a PT_NOTE entry to the kernel's ELF header. A perfectly valid change, but Alpha's aboot loader is none too bright about examining these headers. The following patch to aboot-1.0_pre20040408.tar.bz2 makes it so that only PT_LOAD entries are considered for loading, as well as several other changes required to get the damned thing to build again. --- aboot-1.0_pre20040408/Makefile +++ aboot-1.0_pre20040408/Makefile @@ -32,15 +32,15 @@ export # LOADADDR = 20000000 -ABOOT_LDFLAGS = -static -N -Taboot.lds +ABOOT_LDFLAGS = -static -N -Taboot.lds --relax CC = gcc TOP = $(shell pwd) ifeq ($(TESTING),) -CPPFLAGS = $(CFGDEFS) -I$(TOP)/include -CFLAGS = $(CPPFLAGS) -D__KERNEL__ -Os -Wall -fno-builtin -mno-fp-regs -ffixed-8 +CPPFLAGS = $(CFGDEFS) -I$(TOP)/include -I$(KSRC)/include +CFLAGS = $(CPPFLAGS) -D__KERNEL__ -Os -Wall -fno-builtin -mno-fp-regs else -CPPFLAGS = -DTESTING $(CFGDEFS) -I$(TOP)/include +CPPFLAGS = -DTESTING $(CFGDEFS) -I$(TOP)/include -I$(KSRC)/include CFLAGS = $(CPPFLAGS) -O -g3 -Wall -D__KERNEL__ -ffixed-8 endif ASFLAGS = $(CPPFLAGS) --- aboot-1.0_pre20040408/aboot.c +++ aboot-1.0_pre20040408/aboot.c @@ -19,7 +19,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include @@ -27,6 +26,7 @@ #include #include +#include #include #include @@ -37,16 +37,6 @@ #include "utils.h" #include "string.h" -#ifndef elf_check_arch -# define aboot_elf_check_arch(e) 1 -#else -# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) -# define aboot_elf_check_arch(e) elf_check_arch(e) -# else -# define aboot_elf_check_arch(e) elf_check_arch(e->e_machine) -# endif -#endif - struct bootfs * bfs = 0; /* filesystem to boot from */ char * dest_addr = 0; jmp_buf jump_buffer; @@ -83,77 +73,89 @@ static unsigned long entry_addr = START_ADDR; long first_block (const char *buf, long blocksize) { - struct elfhdr *elf; - struct elf_phdr *phdrs; + Elf64_Ehdr *elf; + Elf64_Phdr *phdrs; + int i, j; - elf = (struct elfhdr *) buf; + elf = (Elf64_Ehdr *) buf; - if (elf->e_ident[0] == 0x7f - && strncmp(elf->e_ident + 1, "ELF", 3) == 0) - { - int i; - /* looks like an ELF binary: */ - if (elf->e_type != ET_EXEC) { - printf("aboot: not an executable ELF file\n"); - return -1; - } - if (!aboot_elf_check_arch(elf)) { - printf("aboot: ELF executable not for this machine\n"); - return -1; - } - if (elf->e_phoff + elf->e_phnum * sizeof(*phdrs) > (unsigned) blocksize) { - printf("aboot: " - "ELF program headers not in first block (%ld)\n", - (long) elf->e_phoff); + if (elf->e_ident[0] != 0x7f + || elf->e_ident[1] != 'E' + || elf->e_ident[2] != 'L' + || elf->e_ident[3] != 'F') { + /* Fail silently, it might be a compressed file */ + return -1; + } + if (elf->e_ident[EI_CLASS] != ELFCLASS64 + || elf->e_ident[EI_DATA] != ELFDATA2LSB + || elf->e_machine != EM_ALPHA) { + printf("aboot: ELF executable not for this machine\n"); + return -1; + } + + /* Looks like an ELF binary. */ + if (elf->e_type != ET_EXEC) { + printf("aboot: not an executable ELF file\n"); + return -1; + } + + if (elf->e_phoff + elf->e_phnum * sizeof(*phdrs) + > (unsigned) blocksize) { + printf("aboot: ELF program headers not in first block (%ld)\n", + (long) elf->e_phoff); + return -1; + } + + phdrs = (struct elf_phdr *) (buf + elf->e_phoff); + chunks = malloc(sizeof(struct segment) * elf->e_phnum); + start_addr = phdrs[0].p_vaddr; /* assume they are sorted */ + entry_addr = elf->e_entry; + + for (i = j = 0; i < elf->e_phnum; ++i) { + int status; + + if (phdrs[i].p_type != PT_LOAD) + continue; + + chunks[j].addr = phdrs[i].p_vaddr; + chunks[j].offset = phdrs[i].p_offset; + chunks[j].size = phdrs[i].p_filesz; + printf("aboot: PHDR %d vaddr %#lx offset %#lx size %#lx\n", + i, chunks[j].addr, chunks[j].offset, chunks[j].size); + + status = check_memory(chunks[j].addr, chunks[j].size); + if (status) { + printf("aboot: Can't load kernel.\n" + " Memory at %lx - %lx (PHDR %i) " + "is %s\n", + chunks[j].addr, + chunks[j].addr + chunks[j].size - 1, + i, + (status == -ENOMEM) ? + "Not Found" : + "Busy (Reserved)"); return -1; } - phdrs = (struct elf_phdr *) (buf + elf->e_phoff); - chunks = malloc(sizeof(struct segment) * elf->e_phnum); - nchunks = elf->e_phnum; - start_addr = phdrs[0].p_vaddr; /* assume they are sorted */ - entry_addr = elf->e_entry; -#ifdef DEBUG - printf("aboot: %d program headers, start address %#lx, entry %#lx\n", - nchunks, start_addr, entry_addr); -#endif - for (i = 0; i < elf->e_phnum; ++i) { - int status; - - chunks[i].addr = phdrs[i].p_vaddr; - chunks[i].offset = phdrs[i].p_offset; - chunks[i].size = phdrs[i].p_filesz; -#ifdef DEBUG - printf("aboot: segment %d vaddr %#lx offset %#lx size %#lx\n", - i, chunks[i].addr, chunks[i].offset, chunks[i].size); -#endif - -#ifndef TESTING - status = check_memory(chunks[i].addr, chunks[i].size); - if (status) { + + if (phdrs[i].p_memsz > phdrs[i].p_filesz) { + if (bss_size > 0) { printf("aboot: Can't load kernel.\n" - " Memory at %lx - %lx (chunk %i) " - "is %s\n", - chunks[i].addr, - chunks[i].addr + chunks[i].size - 1, - i, - (status == -ENOMEM) ? - "Not Found" : - "Busy (Reserved)"); + " Multiple BSS segments" + " (PHDR %d)\n", i); return -1; } -#endif + + bss_start = (char *) (phdrs[i].p_vaddr + + phdrs[i].p_filesz); + bss_size = phdrs[i].p_memsz - phdrs[i].p_filesz; + } - bss_start = (char *) (phdrs[elf->e_phnum - 1].p_vaddr + - phdrs[elf->e_phnum - 1].p_filesz); - bss_size = (phdrs[elf->e_phnum - 1].p_memsz - - phdrs[elf->e_phnum - 1].p_filesz); -#ifdef DEBUG - printf("aboot: bss at 0x%p, size %#lx\n", bss_start, bss_size); -#endif - } else { - /* Fail silently, it might be a compressed file */ - return -1; + + j++; } + + nchunks = j; + printf("aboot: bss at 0x%p, size %#lx\n", bss_start, bss_size); return 0; } --- aboot-1.0_pre20040408/aboot.lds +++ aboot-1.0_pre20040408/aboot.lds @@ -1,22 +1,25 @@ OUTPUT_FORMAT("elf64-alpha") ENTRY(__start) +PHDRS { kernel PT_LOAD; } SECTIONS { . = 0x20000000; - .text : { *(.text) } + .text : { *(.text) } :kernel _etext = .; PROVIDE (etext = .); - .rodata : { *(.rodata) } - .data : { *(.data) CONSTRUCTORS } - .got : { *(.got) } - .sdata : { *(.sdata) } + .rodata : { *(.rodata*) } :kernel + .data : { *(.data*) } :kernel + .got : { *(.got) } :kernel + .sdata : { *(.sdata) } :kernel _edata = .; PROVIDE (edata = .); - .sbss : { *(.sbss) *(.scommon) } - .bss : { *(.bss) *(COMMON) } + .sbss : { *(.sbss) *(.scommon) } :kernel + .bss : { *(.bss) *(COMMON) } :kernel _end = . ; PROVIDE (end = .); + /DISCARD/ : { *(.eh_frame) } + .mdebug 0 : { *(.mdebug) } .note 0 : { *(.note) } .comment 0 : { *(.comment) } --- aboot-1.0_pre20040408/cons.c +++ aboot-1.0_pre20040408/cons.c @@ -82,7 +81,7 @@ cons_getenv(long index, char *envval, long maxlen) * allocated on the stack (which guaranteed to by 8 byte * aligned). */ - char * tmp = alloca(maxlen); + char tmp[maxlen]; long len; len = dispatch(CCB_GET_ENV, index, tmp, maxlen - 1); --- aboot-1.0_pre20040408/disk.c +++ aboot-1.0_pre20040408/disk.c @@ -113,7 +113,7 @@ int load_uncompressed (int fd) { long nread, nblocks; - unsigned char *buf; + char *buf; int i; buf = malloc(bfs->blocksize); @@ -131,7 +131,7 @@ load_uncompressed (int fd) for(i = 0; i < 16; i++) { for (j = 0; j < 16; j++) - printf("%02X ", buf[j+16*i]); + printf("%02X ", (unsigned char) buf[j+16*i]); for(j = 0; j < 16; j++) { c = buf[j+16*i]; printf("%c", (c >= ' ') ? c : ' '); --- aboot-1.0_pre20040408/head.S +++ aboot-1.0_pre20040408/head.S @@ -19,8 +19,7 @@ __start: .quad 0,0,0,0,0,0,0,0 1: br $27,2f 2: ldgp $29,0($27) - lda $27,main_ - jsr $26,($27),main_ + bsr $26,main_ !samegp call_pal PAL_halt .end __start @@ -170,4 +169,4 @@ run_kernel: mov $16,$27 mov $17,$30 jmp $31,($27) - .end run_kernel \ No newline at end of file + .end run_kernel