1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
|
/* Support for ELF Boot Proposal as a boot image */
#include "openbios/config.h"
#include "elf_boot.h"
#include "sys_info.h"
#include "asm/io.h"
#include "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 *name, *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);
name = addr;
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;
}
}
}
}
|