david/ipxe
david
/
ipxe
Archived
1
0
Fork 0
This repository has been archived on 2020-12-06. You can view files and clone it, but cannot push or open issues or pull requests.
ipxe/src/arch/i386/core/elf.c

136 lines
3.5 KiB
C

#include "etherboot.h"
#include "elf.h"
#define NAME "Etherboot"
#if defined(PCBIOS)
#define FIRMWARE "PCBIOS"
#endif
#if defined(LINUXBIOS)
#define FIRMWARE "LinuxBIOS"
#endif
#if !defined(FIRMWARE)
#error "No BIOS selected"
#endif
#define SZ(X) ((sizeof(X)+3) & ~3)
#define CP(D,S) (memcpy(&(D), &(S), sizeof(S)))
struct elf_notes {
/* The note header */
struct Elf_Bhdr hdr;
/* First the Fixed sized entries that must be well aligned */
/* Pointer to bootp data */
Elf_Nhdr nf1;
char nf1_name[SZ(EB_PARAM_NOTE)];
uint32_t nf1_bootp_data;
/* Pointer to ELF header */
Elf_Nhdr nf2;
char nf2_name[SZ(EB_PARAM_NOTE)];
uint32_t nf2_header;
/* A copy of the i386 memory map */
Elf_Nhdr nf3;
char nf3_name[SZ(EB_PARAM_NOTE)];
struct meminfo nf3_meminfo;
/* Then the variable sized data string data where alignment does not matter */
/* The bootloader name */
Elf_Nhdr nv1;
char nv1_desc[SZ(NAME)];
/* The bootloader version */
Elf_Nhdr nv2;
char nv2_desc[SZ(VERSION)];
/* The firmware type */
Elf_Nhdr nv3;
char nv3_desc[SZ(FIRMWARE)];
/* Name of the loaded image */
Elf_Nhdr nv4;
char nv4_loaded_image[128];
/* An empty command line */
Elf_Nhdr nv5;
char nv5_cmdline[SZ("")];
};
#define ELF_NOTE_COUNT (3 + 5)
static struct elf_notes notes;
struct Elf_Bhdr *prepare_boot_params(void *header)
{
memset(&notes, 0, sizeof(notes));
notes.hdr.b_signature = ELF_BHDR_MAGIC;
notes.hdr.b_size = sizeof(notes);
notes.hdr.b_checksum = 0;
notes.hdr.b_records = ELF_NOTE_COUNT;
/* Initialize the fixed length entries. */
notes.nf1.n_namesz = sizeof(EB_PARAM_NOTE);
notes.nf1.n_descsz = sizeof(notes.nf1_bootp_data);
notes.nf1.n_type = EB_BOOTP_DATA;
CP(notes.nf1_name, EB_PARAM_NOTE);
notes.nf1_bootp_data = virt_to_phys(BOOTP_DATA_ADDR);
notes.nf2.n_namesz = sizeof(EB_PARAM_NOTE);
notes.nf2.n_descsz = sizeof(notes.nf2_header);
notes.nf2.n_type = EB_HEADER;
CP(notes.nf2_name, EB_PARAM_NOTE);
notes.nf2_header = virt_to_phys(header);
notes.nf3.n_namesz = sizeof(EB_PARAM_NOTE);
notes.nf3.n_descsz = sizeof(notes.nf3_meminfo);
notes.nf3.n_type = EB_I386_MEMMAP;
CP(notes.nf3_name, EB_PARAM_NOTE);
memcpy(&notes.nf3_meminfo, &meminfo, sizeof(meminfo));
/* Initialize the variable length entries */
notes.nv1.n_namesz = 0;
notes.nv1.n_descsz = sizeof(NAME);
notes.nv1.n_type = EBN_BOOTLOADER_NAME;
CP(notes.nv1_desc, NAME);
notes.nv2.n_namesz = 0;
notes.nv2.n_descsz = sizeof(VERSION);
notes.nv2.n_type = EBN_BOOTLOADER_VERSION;
CP(notes.nv2_desc, VERSION);
notes.nv3.n_namesz = 0;
notes.nv3.n_descsz = sizeof(FIRMWARE);
notes.nv3.n_type = EBN_FIRMWARE_TYPE;
CP(notes.nv3_desc, FIRMWARE);
/* Attempt to pass the name of the loaded image */
notes.nv4.n_namesz = 0;
notes.nv4.n_descsz = sizeof(notes.nv4_loaded_image);
notes.nv4.n_type = EBN_LOADED_IMAGE;
memcpy(&notes.nv4_loaded_image, KERNEL_BUF, sizeof(notes.nv4_loaded_image));
/* Pass an empty command line for now */
notes.nv5.n_namesz = 0;
notes.nv5.n_descsz = sizeof("");
notes.nv5.n_type = EBN_COMMAND_LINE;
CP(notes.nv5_cmdline, "");
notes.hdr.b_checksum = ipchksum(&notes, sizeof(notes));
/* Like UDP invert a 0 checksum to show that a checksum is present */
if (notes.hdr.b_checksum == 0) {
notes.hdr.b_checksum = 0xffff;
}
return &notes.hdr;
}
int elf_start(unsigned long machine __unused_i386, unsigned long entry, unsigned long params)
{
#if defined(CONFIG_X86_64)
if (machine == EM_X86_64) {
return xstart_lm(entry, params);
}
#endif
return xstart32(entry, params);
}