1 | /* |
---|
2 | * Copyright (C) 2008 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 | FILE_LICENCE ( GPL2_OR_LATER ); |
---|
20 | |
---|
21 | #include <errno.h> |
---|
22 | #include <elf.h> |
---|
23 | #include <gpxe/image.h> |
---|
24 | #include <gpxe/elf.h> |
---|
25 | #include <gpxe/features.h> |
---|
26 | #include <gpxe/init.h> |
---|
27 | |
---|
28 | /** |
---|
29 | * @file |
---|
30 | * |
---|
31 | * ELF bootable image |
---|
32 | * |
---|
33 | */ |
---|
34 | |
---|
35 | FEATURE ( FEATURE_IMAGE, "ELF", DHCP_EB_FEATURE_ELF, 1 ); |
---|
36 | |
---|
37 | struct image_type elfboot_image_type __image_type ( PROBE_NORMAL ); |
---|
38 | |
---|
39 | /** |
---|
40 | * Execute ELF image |
---|
41 | * |
---|
42 | * @v image ELF image |
---|
43 | * @ret rc Return status code |
---|
44 | */ |
---|
45 | static int elfboot_exec ( struct image *image ) { |
---|
46 | physaddr_t entry = image->priv.phys; |
---|
47 | |
---|
48 | /* An ELF image has no callback interface, so we need to shut |
---|
49 | * down before invoking it. |
---|
50 | */ |
---|
51 | shutdown ( SHUTDOWN_BOOT ); |
---|
52 | |
---|
53 | /* Jump to OS with flat physical addressing */ |
---|
54 | DBGC ( image, "ELF %p starting execution at %lx\n", image, entry ); |
---|
55 | __asm__ __volatile__ ( PHYS_CODE ( "call *%%edi\n\t" ) |
---|
56 | : : "D" ( entry ) |
---|
57 | : "eax", "ebx", "ecx", "edx", "esi", "ebp", |
---|
58 | "memory" ); |
---|
59 | |
---|
60 | DBGC ( image, "ELF %p returned\n", image ); |
---|
61 | |
---|
62 | /* It isn't safe to continue after calling shutdown() */ |
---|
63 | while ( 1 ) {} |
---|
64 | |
---|
65 | return -ECANCELED; /* -EIMPOSSIBLE, anyone? */ |
---|
66 | } |
---|
67 | |
---|
68 | /** |
---|
69 | * Load ELF image into memory |
---|
70 | * |
---|
71 | * @v image ELF file |
---|
72 | * @ret rc Return status code |
---|
73 | */ |
---|
74 | static int elfboot_load ( struct image *image ) { |
---|
75 | Elf32_Ehdr ehdr; |
---|
76 | static const uint8_t e_ident[] = { |
---|
77 | [EI_MAG0] = ELFMAG0, |
---|
78 | [EI_MAG1] = ELFMAG1, |
---|
79 | [EI_MAG2] = ELFMAG2, |
---|
80 | [EI_MAG3] = ELFMAG3, |
---|
81 | [EI_CLASS] = ELFCLASS32, |
---|
82 | [EI_DATA] = ELFDATA2LSB, |
---|
83 | [EI_VERSION] = EV_CURRENT, |
---|
84 | }; |
---|
85 | int rc; |
---|
86 | |
---|
87 | /* Read ELF header */ |
---|
88 | copy_from_user ( &ehdr, image->data, 0, sizeof ( ehdr ) ); |
---|
89 | if ( memcmp ( ehdr.e_ident, e_ident, sizeof ( e_ident ) ) != 0 ) { |
---|
90 | DBG ( "Invalid ELF identifier\n" ); |
---|
91 | return -ENOEXEC; |
---|
92 | } |
---|
93 | |
---|
94 | /* This is an ELF image, valid or otherwise */ |
---|
95 | if ( ! image->type ) |
---|
96 | image->type = &elfboot_image_type; |
---|
97 | |
---|
98 | /* Load the image using core ELF support */ |
---|
99 | if ( ( rc = elf_load ( image ) ) != 0 ) { |
---|
100 | DBGC ( image, "ELF %p could not load: %s\n", |
---|
101 | image, strerror ( rc ) ); |
---|
102 | return rc; |
---|
103 | } |
---|
104 | |
---|
105 | return 0; |
---|
106 | } |
---|
107 | |
---|
108 | /** ELF image type */ |
---|
109 | struct image_type elfboot_image_type __image_type ( PROBE_NORMAL ) = { |
---|
110 | .name = "ELF", |
---|
111 | .load = elfboot_load, |
---|
112 | .exec = elfboot_exec, |
---|
113 | }; |
---|