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