/* Support for ELF Boot Proposal as a boot image */ #include "config.h" #include "arch/common/elf_boot.h" #include "libopenbios/sys_info.h" #include "asm/io.h" #include "libopenbios/ipchecksum.h" #include "openbios-version.h" #define printf printk #define debug printk /* ELF image notes provide information to the loader who boots us */ /* This compiles and generates correct PT_NOTE segment for me. * If it doesn't, use assembly version below. */ struct elf_image_note { Elf_Nhdr hdr0; char name0[sizeof(ELF_NOTE_BOOT)]; char prog_name[sizeof(PROGRAM_NAME)]; Elf_Nhdr hdr1; char name1[sizeof(ELF_NOTE_BOOT)]; char version[sizeof(OPENBIOS_VERSION_STR)]; Elf_Nhdr hdr2; char name2[sizeof(ELF_NOTE_BOOT)]; unsigned short checksum; }; const struct elf_image_note elf_image_notes __attribute__ ((section (".note.ELFBoot"))) = { .hdr0 = { .n_namesz = sizeof(ELF_NOTE_BOOT), .n_descsz = sizeof(PROGRAM_NAME), .n_type = EIN_PROGRAM_NAME, }, .name0 = ELF_NOTE_BOOT, .prog_name = PROGRAM_NAME, .hdr1 = { .n_namesz = sizeof(ELF_NOTE_BOOT), .n_descsz = sizeof(OPENBIOS_VERSION_STR), .n_type = EIN_PROGRAM_VERSION, }, .name1 = ELF_NOTE_BOOT, .version = OPENBIOS_VERSION_STR, .hdr2 = { .n_namesz = sizeof(ELF_NOTE_BOOT), .n_descsz = sizeof(unsigned short), .n_type = EIN_PROGRAM_CHECKSUM, }, .name2 = ELF_NOTE_BOOT, .checksum = 0, /* to be computed by external tool */ }; /* This is refered by other files */ const char *program_name = elf_image_notes.prog_name; const char *program_version = elf_image_notes.version; #if 0 /* This tells the linker to make a PT_NOTE segment. * If the section is named just ".note", it will be * mixed up with useless .version notes generated by GCC. */ .section ".note.ELFBoot", "a" .align 4 .int 2f - 1f .int 4f - 3f .int EIN_PROGRAM_NAME 1: .asciz "ELFBoot" 2: .align 4 3: .asciz PROGRAM_NAME 4: .align 4 .int 2f - 1f .int 4f - 3f .int EIN_PROGRAM_VERSION 1: .asciz "ELFBoot" 2: .align 4 3: .asciz OPENBIOS_VERSION_STR 4: .align 4 .int 2f - 1f .int 4f - 3f .int EIN_PROGRAM_CHECKSUM 1: .asciz "ELFBoot" 2: .align 4 3: .short 0 4: #endif /* Collect information from the ELF bootloader * Note that we have to copy them to our own memory, * otherwise they might be overwritten afterward. */ void collect_elfboot_info(struct sys_info *info) { Elf_Bhdr *hdr = NULL; char *addr, *end; Elf_Nhdr *nhdr; char *desc; if (info->boot_type == ELF_BHDR_MAGIC) hdr = phys_to_virt(info->boot_data); else hdr = phys_to_virt(info->boot_arg); if (hdr->b_signature != ELF_BHDR_MAGIC) return; if (ipchksum(hdr, hdr->b_size) != 0) { printf("Broken ELF boot notes\n"); return; } addr = (char *) (hdr + 1); end = addr + hdr->b_size; while (addr < end) { nhdr = (Elf_Nhdr *) addr; addr += sizeof(Elf_Nhdr); addr += (nhdr->n_namesz + 3) & ~3; desc = addr; addr += (nhdr->n_descsz + 3) & ~3; if (nhdr->n_namesz == 0) { /* Standard notes */ switch (nhdr->n_type) { case EBN_FIRMWARE_TYPE: info->firmware = strdup(desc); break; case EBN_BOOTLOADER_NAME: debug("Bootloader: %s\n", desc); break; case EBN_BOOTLOADER_VERSION: debug("Version: %s\n", desc); break; case EBN_COMMAND_LINE: info->command_line = strdup(desc); break; case EBN_LOADED_IMAGE: debug("Image name: %s\n", desc); break; } } } }