Browse Source

Removed the Etherboot-specific ELF-image code and replaced it with a

generic ELF loader, to be used by the multiboot code.
tags/v0.9.3
Michael Brown 18 years ago
parent
commit
7ad1c2eaa8
4 changed files with 134 additions and 222 deletions
  1. 0
    136
      src/arch/i386/core/elf.c
  2. 130
    0
      src/image/elf.c
  3. 4
    2
      src/include/elf.h
  4. 0
    84
      src/include/elf_boot.h

+ 0
- 136
src/arch/i386/core/elf.c View File

@@ -1,136 +0,0 @@
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);
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
-}

+ 130
- 0
src/image/elf.c View File

@@ -0,0 +1,130 @@
1
+/*
2
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+/**
20
+ * @file
21
+ *
22
+ * ELF image format
23
+ *
24
+ */
25
+
26
+#include <errno.h>
27
+#include <elf.h>
28
+#include <gpxe/uaccess.h>
29
+#include <gpxe/segment.h>
30
+
31
+typedef Elf32_Ehdr	Elf_Ehdr;
32
+typedef Elf32_Phdr	Elf_Phdr;
33
+typedef Elf32_Off	Elf_Off;
34
+
35
+/** An ELF file */
36
+struct elf {
37
+	/** ELF file image */
38
+	userptr_t image;
39
+	/** Length of ELF file image */
40
+	size_t len;
41
+};
42
+
43
+/**
44
+ * Load ELF segment into memory
45
+ *
46
+ * @v elf		ELF file
47
+ * @v phdr		ELF program header
48
+ * @ret rc		Return status code
49
+ */
50
+static int elf_load_segment ( struct elf *elf, Elf_Phdr *phdr ) {
51
+	physaddr_t dest;
52
+	userptr_t buffer;
53
+	int rc;
54
+
55
+	/* Do nothing for non-PT_LOAD segments */
56
+	if ( phdr->p_type != PT_LOAD )
57
+		return 0;
58
+
59
+	/* Check segment lies within image */
60
+	if ( ( phdr->p_offset + phdr->p_filesz ) > elf->len ) {
61
+		DBG ( "ELF segment outside ELF file\n" );
62
+		return -ENOEXEC;
63
+	}
64
+
65
+	/* Find start address: use physical address for preference,
66
+	 * fall back to virtual address if no physical address
67
+	 * supplied.
68
+	 */
69
+	dest = phdr->p_paddr;
70
+	if ( ! dest )
71
+		dest = phdr->p_vaddr;
72
+	if ( ! dest ) {
73
+		DBG ( "ELF segment loads to physical address 0\n" );
74
+		return -ENOEXEC;
75
+	}
76
+	buffer = phys_to_user ( dest );
77
+
78
+	DBG ( "ELF loading segment [%lx,%lx) to [%lx,%lx,%lx)\n",
79
+	      phdr->p_offset, ( phdr->p_offset + phdr->p_filesz ),
80
+	      phdr->p_paddr, ( phdr->p_paddr + phdr->p_filesz ),
81
+	      ( phdr->p_paddr + phdr->p_memsz ) );
82
+
83
+	/* Verify and prepare segment */
84
+	if ( ( rc = prep_segment ( buffer, phdr->p_filesz,
85
+				   phdr->p_memsz ) ) != 0 ) {
86
+		DBG ( "ELF could not prepare segment: %s\n", strerror ( rc ) );
87
+		return rc;
88
+	}
89
+
90
+	/* Copy image to segment */
91
+	copy_user ( buffer, 0, elf->image, phdr->p_offset, phdr->p_filesz );
92
+
93
+	return 0;
94
+}
95
+
96
+/**
97
+ * Load ELF image into memory
98
+ *
99
+ * @v elf		ELF file
100
+ * @ret rc		Return status code
101
+ */
102
+int elf_load ( struct elf *elf ) {
103
+	Elf_Ehdr ehdr;
104
+	Elf_Phdr phdr;
105
+	Elf_Off phoff;
106
+	unsigned int phnum;
107
+	int rc;
108
+
109
+	/* Read ELF header */
110
+	copy_from_user ( &ehdr, elf->image, 0, sizeof ( ehdr ) );
111
+	if ( memcmp ( &ehdr.e_ident[EI_MAG0], ELFMAG, SELFMAG ) != 0 ) {
112
+		DBG ( "Invalid ELF signature\n" );
113
+		return -ENOEXEC;
114
+	}
115
+
116
+	/* Read ELF program headers */
117
+	for ( phoff = ehdr.e_phoff , phnum = ehdr.e_phnum ; phnum ;
118
+	      phoff += ehdr.e_phentsize, phnum-- ) {
119
+		if ( phoff > elf->len ) {
120
+			DBG ( "ELF program header %d outside ELF image\n",
121
+			      phnum );
122
+			return -ENOEXEC;
123
+		}
124
+		copy_from_user ( &phdr, elf->image, phoff, sizeof ( phdr ) );
125
+		if ( ( rc = elf_load_segment ( elf, &phdr ) ) != 0 )
126
+			return rc;
127
+	}
128
+
129
+	return 0;
130
+}

+ 4
- 2
src/include/elf.h View File

@@ -121,6 +121,7 @@
121 121
 #define ELFMAG3		'F'
122 122
 
123 123
 #define ELFMAG		"\177ELF"
124
+#define	SELFMAG		4
124 125
 
125 126
 #define EI_CLASS	4	/* File class byte index */
126 127
 #define ELFCLASSNONE	0	/* Invalid class */
@@ -141,6 +142,9 @@
141 142
 #define ELF32_PHDR_SIZE (8*4)	/* Size of an elf program header */
142 143
 
143 144
 #ifndef ASSEMBLY
145
+
146
+#include <stdint.h>
147
+
144 148
 /*
145 149
  * ELF definitions common to all 32-bit architectures.
146 150
  */
@@ -229,6 +233,4 @@ typedef struct {
229 233
 
230 234
 #endif /* ASSEMBLY */
231 235
 
232
-#include "elf_boot.h"
233
-
234 236
 #endif /* ELF_H */

+ 0
- 84
src/include/elf_boot.h View File

@@ -1,84 +0,0 @@
1
-#ifndef ELF_BOOT_H 
2
-#define ELF_BOOT_H 
3
-
4
-
5
-/* This defines the structure of a table of parameters useful for ELF
6
- * bootable images.  These parameters are all passed and generated
7
- * by the bootloader to the booted image.  For simplicity and
8
- * consistency the Elf Note format is reused.
9
- *
10
- * All of the information must be Position Independent Data.
11
- * That is it must be safe to relocate the whole ELF boot parameter
12
- * block without changing the meaning or correctnes of the data.
13
- * Additionally it must be safe to permute the order of the ELF notes
14
- * to any possible permutation without changing the meaning or correctness
15
- * of the data.
16
- *
17
- */
18
-
19
-#define ELF_BHDR_MAGIC		0x0E1FB007
20
-
21
-#ifndef ASSEMBLY
22
-#include <stdint.h>
23
-typedef uint16_t Elf_Half;
24
-typedef uint32_t Elf_Word;
25
-
26
-typedef struct Elf_Bhdr
27
-{
28
-	Elf_Word b_signature; /* "0x0E1FB007" */
29
-	Elf_Word b_size;
30
-	Elf_Half b_checksum;
31
-	Elf_Half b_records;
32
-} Elf_Bhdr;
33
-
34
-typedef struct Elf_Nhdr
35
-{
36
-	Elf_Word n_namesz;		/* Length of the note's name.  */
37
-	Elf_Word n_descsz;		/* Length of the note's descriptor.  */
38
-	Elf_Word n_type;		/* Type of the note.  */
39
-} Elf_Nhdr;
40
-
41
-#endif /* ASSEMBLY */
42
-
43
-/* Standardized Elf image notes for booting... The name for all of these is ELFBoot */
44
-#define ELF_NOTE_BOOT		"ELFBoot"
45
-
46
-#define EIN_PROGRAM_NAME	0x00000001
47
-/* The program in this ELF file */
48
-#define EIN_PROGRAM_VERSION	0x00000002
49
-/* The version of the program in this ELF file */
50
-#define EIN_PROGRAM_CHECKSUM	0x00000003
51
-/* ip style checksum of the memory image. */
52
-
53
-
54
-/* Notes that are passed to a loaded image */
55
-/* For standard notes n_namesz must be zero */
56
-#define EBN_FIRMWARE_TYPE	0x00000001
57
-/* ASCIZ name of the platform firmware. */
58
-#define EBN_BOOTLOADER_NAME	0x00000002
59
-/* This specifies just the ASCIZ name of the bootloader */
60
-#define EBN_BOOTLOADER_VERSION	0x00000003
61
-/* This specifies the version of the bootloader as an ASCIZ string */
62
-#define EBN_COMMAND_LINE	0x00000004
63
-/* This specifies a command line that can be set by user interaction,
64
- * and is provided as a free form ASCIZ string to the loaded image.
65
- */
66
-#define EBN_NOP			0x00000005
67
-/* A note nop note has no meaning, useful for inserting explicit padding */
68
-#define EBN_LOADED_IMAGE	0x00000006
69
-/* An ASCIZ string naming the loaded image */
70
-
71
-
72
-/* Etherboot specific notes */
73
-#define EB_PARAM_NOTE		"Etherboot"
74
-#define EB_IA64_SYSTAB		0x00000001
75
-#define EB_IA64_MEMMAP		0x00000002
76
-#define EB_IA64_FPSWA		0x00000003
77
-#define EB_IA64_CONINFO		0x00000004
78
-#define EB_BOOTP_DATA		0x00000005
79
-#define EB_HEADER		0x00000006
80
-#define EB_IA64_IMAGE_HANDLE	0x00000007
81
-#define EB_I386_MEMMAP		0x00000008
82
-
83
-
84
-#endif /* ELF_BOOT_H */

Loading…
Cancel
Save