mirror of
https://github.com/xcat2/xNBA.git
synced 2024-12-15 15:51:44 +00:00
137 lines
3.5 KiB
C
137 lines
3.5 KiB
C
#include "etherboot.h"
|
|
#include "elf.h"
|
|
#include "memsizes.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(¬es, 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);
|
|
|
|
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(¬es.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(¬es.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(¬es, 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 ¬es.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);
|
|
}
|