diff options
Diffstat (limited to 'arch/ppc64/boot/main.c')
-rw-r--r-- | arch/ppc64/boot/main.c | 80 |
1 files changed, 39 insertions, 41 deletions
diff --git a/arch/ppc64/boot/main.c b/arch/ppc64/boot/main.c index 0b95ccfb143c..7485dcbf80bc 100644 --- a/arch/ppc64/boot/main.c +++ b/arch/ppc64/boot/main.c | |||
@@ -32,8 +32,6 @@ extern char _vmlinux_start[]; | |||
32 | extern char _vmlinux_end[]; | 32 | extern char _vmlinux_end[]; |
33 | extern char _initrd_start[]; | 33 | extern char _initrd_start[]; |
34 | extern char _initrd_end[]; | 34 | extern char _initrd_end[]; |
35 | extern unsigned long vmlinux_filesize; | ||
36 | extern unsigned long vmlinux_memsize; | ||
37 | 35 | ||
38 | struct addr_range { | 36 | struct addr_range { |
39 | unsigned long addr; | 37 | unsigned long addr; |
@@ -45,6 +43,7 @@ static struct addr_range vmlinuz = {0, 0, 0}; | |||
45 | static struct addr_range initrd = {0, 0, 0}; | 43 | static struct addr_range initrd = {0, 0, 0}; |
46 | 44 | ||
47 | static char scratch[46912]; /* scratch space for gunzip, from zlib_inflate_workspacesize() */ | 45 | static char scratch[46912]; /* scratch space for gunzip, from zlib_inflate_workspacesize() */ |
46 | static char elfheader[256]; | ||
48 | 47 | ||
49 | 48 | ||
50 | typedef void (*kernel_entry_t)( unsigned long, | 49 | typedef void (*kernel_entry_t)( unsigned long, |
@@ -78,6 +77,7 @@ static unsigned long try_claim(unsigned long size) | |||
78 | void start(unsigned long a1, unsigned long a2, void *promptr) | 77 | void start(unsigned long a1, unsigned long a2, void *promptr) |
79 | { | 78 | { |
80 | unsigned long i; | 79 | unsigned long i; |
80 | int len; | ||
81 | kernel_entry_t kernel_entry; | 81 | kernel_entry_t kernel_entry; |
82 | Elf64_Ehdr *elf64; | 82 | Elf64_Ehdr *elf64; |
83 | Elf64_Phdr *elf64ph; | 83 | Elf64_Phdr *elf64ph; |
@@ -113,25 +113,45 @@ void start(unsigned long a1, unsigned long a2, void *promptr) | |||
113 | claim_base = PROG_START; | 113 | claim_base = PROG_START; |
114 | #endif | 114 | #endif |
115 | 115 | ||
116 | /* | 116 | vmlinuz.addr = (unsigned long)_vmlinux_start; |
117 | * Now we try to claim some memory for the kernel itself | 117 | vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start); |
118 | * our "vmlinux_memsize" is the memory footprint in RAM, _HOWEVER_, what | 118 | |
119 | * our Makefile stuffs in is an image containing all sort of junk including | 119 | /* gunzip the ELF header of the kernel */ |
120 | * an ELF header. We need to do some calculations here to find the right | 120 | if (*(unsigned short *)vmlinuz.addr == 0x1f8b) { |
121 | * size... In practice we add 1Mb, that is enough, but we should really | 121 | len = vmlinuz.size; |
122 | * consider fixing the Makefile to put a _raw_ kernel in there ! | 122 | gunzip(elfheader, sizeof(elfheader), |
123 | */ | 123 | (unsigned char *)vmlinuz.addr, &len); |
124 | vmlinux_memsize += ONE_MB; | 124 | } else |
125 | printf("Allocating 0x%lx bytes for kernel ...\n\r", vmlinux_memsize); | 125 | memcpy(elfheader, (const void *)vmlinuz.addr, sizeof(elfheader)); |
126 | vmlinux.addr = try_claim(vmlinux_memsize); | 126 | |
127 | elf64 = (Elf64_Ehdr *)elfheader; | ||
128 | if ( elf64->e_ident[EI_MAG0] != ELFMAG0 || | ||
129 | elf64->e_ident[EI_MAG1] != ELFMAG1 || | ||
130 | elf64->e_ident[EI_MAG2] != ELFMAG2 || | ||
131 | elf64->e_ident[EI_MAG3] != ELFMAG3 || | ||
132 | elf64->e_ident[EI_CLASS] != ELFCLASS64 || | ||
133 | elf64->e_ident[EI_DATA] != ELFDATA2MSB || | ||
134 | elf64->e_type != ET_EXEC || | ||
135 | elf64->e_machine != EM_PPC64 ) | ||
136 | { | ||
137 | printf("Error: not a valid PPC64 ELF file!\n\r"); | ||
138 | exit(); | ||
139 | } | ||
140 | |||
141 | elf64ph = (Elf64_Phdr *)((unsigned long)elf64 + | ||
142 | (unsigned long)elf64->e_phoff); | ||
143 | for(i=0; i < (unsigned int)elf64->e_phnum ;i++,elf64ph++) { | ||
144 | if (elf64ph->p_type == PT_LOAD && elf64ph->p_offset != 0) | ||
145 | break; | ||
146 | } | ||
147 | vmlinux.size = (unsigned long)elf64ph->p_filesz; | ||
148 | vmlinux.memsize = (unsigned long)elf64ph->p_memsz; | ||
149 | printf("Allocating 0x%lx bytes for kernel ...\n\r", vmlinux.memsize); | ||
150 | vmlinux.addr = try_claim(vmlinux.memsize); | ||
127 | if (vmlinux.addr == 0) { | 151 | if (vmlinux.addr == 0) { |
128 | printf("Can't allocate memory for kernel image !\n\r"); | 152 | printf("Can't allocate memory for kernel image !\n\r"); |
129 | exit(); | 153 | exit(); |
130 | } | 154 | } |
131 | vmlinuz.addr = (unsigned long)_vmlinux_start; | ||
132 | vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start); | ||
133 | vmlinux.size = PAGE_ALIGN(vmlinux_filesize); | ||
134 | vmlinux.memsize = vmlinux_memsize; | ||
135 | 155 | ||
136 | /* | 156 | /* |
137 | * Now we try to claim memory for the initrd (and copy it there) | 157 | * Now we try to claim memory for the initrd (and copy it there) |
@@ -155,11 +175,10 @@ void start(unsigned long a1, unsigned long a2, void *promptr) | |||
155 | 175 | ||
156 | /* Eventually gunzip the kernel */ | 176 | /* Eventually gunzip the kernel */ |
157 | if (*(unsigned short *)vmlinuz.addr == 0x1f8b) { | 177 | if (*(unsigned short *)vmlinuz.addr == 0x1f8b) { |
158 | int len; | ||
159 | printf("gunzipping (0x%lx <- 0x%lx:0x%0lx)...", | 178 | printf("gunzipping (0x%lx <- 0x%lx:0x%0lx)...", |
160 | vmlinux.addr, vmlinuz.addr, vmlinuz.addr+vmlinuz.size); | 179 | vmlinux.addr, vmlinuz.addr, vmlinuz.addr+vmlinuz.size); |
161 | len = vmlinuz.size; | 180 | len = vmlinuz.size; |
162 | gunzip((void *)vmlinux.addr, vmlinux.size, | 181 | gunzip((void *)vmlinux.addr, vmlinux.memsize, |
163 | (unsigned char *)vmlinuz.addr, &len); | 182 | (unsigned char *)vmlinuz.addr, &len); |
164 | printf("done 0x%lx bytes\n\r", len); | 183 | printf("done 0x%lx bytes\n\r", len); |
165 | } else { | 184 | } else { |
@@ -167,32 +186,11 @@ void start(unsigned long a1, unsigned long a2, void *promptr) | |||
167 | } | 186 | } |
168 | 187 | ||
169 | /* Skip over the ELF header */ | 188 | /* Skip over the ELF header */ |
170 | elf64 = (Elf64_Ehdr *)vmlinux.addr; | ||
171 | if ( elf64->e_ident[EI_MAG0] != ELFMAG0 || | ||
172 | elf64->e_ident[EI_MAG1] != ELFMAG1 || | ||
173 | elf64->e_ident[EI_MAG2] != ELFMAG2 || | ||
174 | elf64->e_ident[EI_MAG3] != ELFMAG3 || | ||
175 | elf64->e_ident[EI_CLASS] != ELFCLASS64 || | ||
176 | elf64->e_ident[EI_DATA] != ELFDATA2MSB || | ||
177 | elf64->e_type != ET_EXEC || | ||
178 | elf64->e_machine != EM_PPC64 ) | ||
179 | { | ||
180 | printf("Error: not a valid PPC64 ELF file!\n\r"); | ||
181 | exit(); | ||
182 | } | ||
183 | |||
184 | elf64ph = (Elf64_Phdr *)((unsigned long)elf64 + | ||
185 | (unsigned long)elf64->e_phoff); | ||
186 | for(i=0; i < (unsigned int)elf64->e_phnum ;i++,elf64ph++) { | ||
187 | if (elf64ph->p_type == PT_LOAD && elf64ph->p_offset != 0) | ||
188 | break; | ||
189 | } | ||
190 | #ifdef DEBUG | 189 | #ifdef DEBUG |
191 | printf("... skipping 0x%lx bytes of ELF header\n\r", | 190 | printf("... skipping 0x%lx bytes of ELF header\n\r", |
192 | (unsigned long)elf64ph->p_offset); | 191 | (unsigned long)elf64ph->p_offset); |
193 | #endif | 192 | #endif |
194 | vmlinux.addr += (unsigned long)elf64ph->p_offset; | 193 | vmlinux.addr += (unsigned long)elf64ph->p_offset; |
195 | vmlinux.size -= (unsigned long)elf64ph->p_offset; | ||
196 | 194 | ||
197 | flush_cache((void *)vmlinux.addr, vmlinux.size); | 195 | flush_cache((void *)vmlinux.addr, vmlinux.size); |
198 | 196 | ||
@@ -263,7 +261,7 @@ static void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) | |||
263 | s.avail_in = *lenp - i; | 261 | s.avail_in = *lenp - i; |
264 | s.next_out = dst; | 262 | s.next_out = dst; |
265 | s.avail_out = dstlen; | 263 | s.avail_out = dstlen; |
266 | r = zlib_inflate(&s, Z_FINISH); | 264 | r = zlib_inflate(&s, Z_FULL_FLUSH); |
267 | if (r != Z_OK && r != Z_STREAM_END) { | 265 | if (r != Z_OK && r != Z_STREAM_END) { |
268 | printf("inflate returned %d msg: %s\n\r", r, s.msg); | 266 | printf("inflate returned %d msg: %s\n\r", r, s.msg); |
269 | exit(); | 267 | exit(); |