| /* 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; |
| } |
| } |
| } |
| } |