summaryrefslogtreecommitdiffstats
path: root/qemu/roms/openbios/libopenbios/elf_info.c
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/roms/openbios/libopenbios/elf_info.c')
-rw-r--r--qemu/roms/openbios/libopenbios/elf_info.c151
1 files changed, 151 insertions, 0 deletions
diff --git a/qemu/roms/openbios/libopenbios/elf_info.c b/qemu/roms/openbios/libopenbios/elf_info.c
new file mode 100644
index 000000000..f7febef9d
--- /dev/null
+++ b/qemu/roms/openbios/libopenbios/elf_info.c
@@ -0,0 +1,151 @@
+/* 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;
+ }
+ }
+ }
+}