Merge from Etherboot 5.4
[people/oremanj/gpxe.git] / src / arch / i386 / core / elf.c
1 #include "etherboot.h"
2 #include "elf.h"
3 #include "memsizes.h"
4
5
6 #define NAME "Etherboot"
7
8 #if defined(PCBIOS)
9 #define FIRMWARE "PCBIOS"
10 #endif
11 #if defined(LINUXBIOS)
12 #define FIRMWARE "LinuxBIOS"
13 #endif
14 #if !defined(FIRMWARE)
15 #error "No BIOS selected"
16 #endif
17
18 #define SZ(X) ((sizeof(X)+3) & ~3)
19 #define CP(D,S) (memcpy(&(D), &(S), sizeof(S)))
20
21 struct elf_notes {
22         /* The note header */
23         struct Elf_Bhdr hdr;
24
25         /* First the Fixed sized entries that must be well aligned */
26
27         /* Pointer to bootp data */
28         Elf_Nhdr nf1;
29         char     nf1_name[SZ(EB_PARAM_NOTE)];
30         uint32_t nf1_bootp_data;
31
32         /* Pointer to ELF header */
33         Elf_Nhdr nf2;
34         char     nf2_name[SZ(EB_PARAM_NOTE)];
35         uint32_t nf2_header;
36
37         /* A copy of the i386 memory map */
38         Elf_Nhdr nf3;
39         char     nf3_name[SZ(EB_PARAM_NOTE)];
40         struct meminfo nf3_meminfo;
41
42         /* Then the variable sized data string data where alignment does not matter */
43
44         /* The bootloader name */
45         Elf_Nhdr nv1;
46         char     nv1_desc[SZ(NAME)];
47         /* The bootloader version */
48         Elf_Nhdr nv2;
49         char     nv2_desc[SZ(VERSION)];
50         /* The firmware type */
51         Elf_Nhdr nv3;
52         char     nv3_desc[SZ(FIRMWARE)];
53         /* Name of the loaded image */
54         Elf_Nhdr nv4;
55         char     nv4_loaded_image[128];
56         /* An empty command line */
57         Elf_Nhdr nv5;
58         char     nv5_cmdline[SZ("")];
59 };
60
61 #define ELF_NOTE_COUNT  (3 + 5)
62
63 static struct elf_notes notes;
64 struct Elf_Bhdr *prepare_boot_params(void *header)
65 {
66         memset(&notes, 0, sizeof(notes));
67         notes.hdr.b_signature = ELF_BHDR_MAGIC;
68         notes.hdr.b_size      = sizeof(notes);
69         notes.hdr.b_checksum  = 0;
70         notes.hdr.b_records   = ELF_NOTE_COUNT;
71
72         /* Initialize the fixed length entries. */
73         notes.nf1.n_namesz = sizeof(EB_PARAM_NOTE);
74         notes.nf1.n_descsz = sizeof(notes.nf1_bootp_data);
75         notes.nf1.n_type   = EB_BOOTP_DATA;
76         CP(notes.nf1_name,   EB_PARAM_NOTE);
77         notes.nf1_bootp_data = virt_to_phys(BOOTP_DATA_ADDR);
78
79         notes.nf2.n_namesz = sizeof(EB_PARAM_NOTE);
80         notes.nf2.n_descsz = sizeof(notes.nf2_header);
81         notes.nf2.n_type   = EB_HEADER;
82         CP(notes.nf2_name,   EB_PARAM_NOTE);
83         notes.nf2_header   = virt_to_phys(header);
84
85         notes.nf3.n_namesz = sizeof(EB_PARAM_NOTE);
86         notes.nf3.n_descsz = sizeof(notes.nf3_meminfo);
87         notes.nf3.n_type   = EB_I386_MEMMAP;
88         CP(notes.nf3_name,   EB_PARAM_NOTE);
89         memcpy(&notes.nf3_meminfo, &meminfo, sizeof(meminfo));
90
91         /* Initialize the variable length entries */
92         notes.nv1.n_namesz = 0;
93         notes.nv1.n_descsz = sizeof(NAME);
94         notes.nv1.n_type   = EBN_BOOTLOADER_NAME;
95         CP(notes.nv1_desc,   NAME);
96
97         notes.nv2.n_namesz = 0;
98         notes.nv2.n_descsz = sizeof(VERSION);
99         notes.nv2.n_type   = EBN_BOOTLOADER_VERSION;
100         CP(notes.nv2_desc,   VERSION);
101
102         notes.nv3.n_namesz = 0;
103         notes.nv3.n_descsz = sizeof(FIRMWARE);
104         notes.nv3.n_type   = EBN_FIRMWARE_TYPE;
105         CP(notes.nv3_desc,   FIRMWARE);
106
107         /* Attempt to pass the name of the loaded image */
108         notes.nv4.n_namesz = 0;
109         notes.nv4.n_descsz = sizeof(notes.nv4_loaded_image);
110         notes.nv4.n_type   = EBN_LOADED_IMAGE;
111         memcpy(&notes.nv4_loaded_image, KERNEL_BUF, sizeof(notes.nv4_loaded_image));
112
113         /* Pass an empty command line for now */
114         notes.nv5.n_namesz = 0;
115         notes.nv5.n_descsz = sizeof("");
116         notes.nv5.n_type   = EBN_COMMAND_LINE;
117         CP(notes.nv5_cmdline,   "");
118
119
120         notes.hdr.b_checksum = ipchksum(&notes, sizeof(notes));
121         /* Like UDP invert a 0 checksum to show that a checksum is present */
122         if (notes.hdr.b_checksum == 0) {
123                 notes.hdr.b_checksum = 0xffff;
124         }
125         return &notes.hdr;
126 }
127
128 int elf_start(unsigned long machine __unused_i386, unsigned long entry, unsigned long params)
129 {
130 #if defined(CONFIG_X86_64)
131         if (machine == EM_X86_64) {
132                 return xstart_lm(entry, params);
133         }
134 #endif
135         return xstart32(entry, params);
136 }