aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc64/boot/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ppc64/boot/main.c')
-rw-r--r--arch/ppc64/boot/main.c80
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[];
32extern char _vmlinux_end[]; 32extern char _vmlinux_end[];
33extern char _initrd_start[]; 33extern char _initrd_start[];
34extern char _initrd_end[]; 34extern char _initrd_end[];
35extern unsigned long vmlinux_filesize;
36extern unsigned long vmlinux_memsize;
37 35
38struct addr_range { 36struct addr_range {
39 unsigned long addr; 37 unsigned long addr;
@@ -45,6 +43,7 @@ static struct addr_range vmlinuz = {0, 0, 0};
45static struct addr_range initrd = {0, 0, 0}; 43static struct addr_range initrd = {0, 0, 0};
46 44
47static char scratch[46912]; /* scratch space for gunzip, from zlib_inflate_workspacesize() */ 45static char scratch[46912]; /* scratch space for gunzip, from zlib_inflate_workspacesize() */
46static char elfheader[256];
48 47
49 48
50typedef void (*kernel_entry_t)( unsigned long, 49typedef void (*kernel_entry_t)( unsigned long,
@@ -78,6 +77,7 @@ static unsigned long try_claim(unsigned long size)
78void start(unsigned long a1, unsigned long a2, void *promptr) 77void 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();