2 * Copyright (C) 2001-2003 Hewlett-Packard Co.
3 * Contributed by Stephane Eranian <eranian@hpl.hp.com>
5 * Copyright (C) 2001 Silicon Graphics, Inc.
6 * Contributed by Brent Casavant <bcasavan@sgi.com>
8 * This file is part of the ELILO, the EFI Linux boot loader.
10 * ELILO is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2, or (at your option)
15 * ELILO is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with ELILO; see the file COPYING. If not, write to the Free
22 * Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 * Please check out the elilo.txt for complete documentation on how
26 * to use this program.
37 #define LD_NAME L"plain_elf64"
39 #define PLAIN_MIN_BLOCK_SIZE sizeof(Elf64_Ehdr) /* see load_elf() for details */
41 #define SKIPBUFSIZE 2048 /* minimal default size of the skip buffer */
42 static CHAR8 *skip_buffer; /* used to skip over unneeded data */
43 static UINTN skip_bufsize;
44 static UINTN elf_is_big_endian; /* true if ELF file is big endian */
49 if(elf_is_big_endian) v = __ia64_swab64(v);
56 if(elf_is_big_endian) v = __ia64_swab32(v);
63 if(elf_is_big_endian) v = __ia64_swab16(v);
68 is_valid_header(Elf64_Ehdr *ehdr)
72 if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB) {
73 type = __ia64_swab16(ehdr->e_type);
74 machine = __ia64_swab16(ehdr->e_machine);
77 machine = ehdr->e_machine;
79 DBG_PRT((L"class=%d type=%d data=%d machine=%d\n",
80 ehdr->e_ident[EI_CLASS],
82 ehdr->e_ident[EI_DATA],
85 return ehdr->e_ident[EI_MAG0] == 0x7f
86 && ehdr->e_ident[EI_MAG1] == 'E'
87 && ehdr->e_ident[EI_MAG2] == 'L'
88 && ehdr->e_ident[EI_MAG3] == 'F'
89 && ehdr->e_ident[EI_CLASS] == ELFCLASS64
90 && type == ET_EXEC /* must be executable */
91 && machine == EM_IA_64 ? 0 : -1;
95 plain_probe(CHAR16 *kname)
101 UINTN size = sizeof(ehdr);
103 status = fops_open(kname, &fd);
104 if (EFI_ERROR(status)) return -1;
106 status = fops_read(fd, &ehdr, &size);
108 if (EFI_ERROR(status) || size != sizeof(ehdr)) goto error;
110 ret = is_valid_header(&ehdr);
117 * move skip bytes forward in the file
118 * this is required because we cannot assume fileops has
119 * seek() capabilities.
122 skip_bytes(fops_fd_t fd, UINTN curpos, UINTN newpos)
127 skip = newpos - curpos;
128 /* check if seek capability exists */
130 status = fops_seek(fd, newpos);
131 if (status == EFI_SUCCESS) return 0;
133 if (status != EFI_UNSUPPORTED) goto error;
135 /* unsupported case */
137 if (skip_buffer == NULL) {
138 skip_bufsize = MAX(skip, SKIPBUFSIZE);
139 skip_buffer= (CHAR8 *)alloc(skip_bufsize, EfiLoaderData);
140 if (skip_buffer == NULL) return -1;
143 n = skip > skip_bufsize? skip_bufsize : skip;
145 status = fops_read(fd, skip_buffer, &n);
146 if (EFI_ERROR(status)) goto error;
153 ERR_PRT((L"%s : cannot skip %d bytes\n", LD_NAME, n));
158 load_elf(fops_fd_t fd, kdesc_t *kd)
163 INTN ret = ELILO_LOAD_ERROR;
164 UINTN i, total_size = 0;
165 UINTN pages, size, bss_sz, osize;
167 VOID *low_addr = (VOID *)~0;
168 VOID *max_addr = (VOID *)0;
169 UINTN load_offset = 0;
170 UINTN paddr, memsz, filesz, poffs;
173 Print(L"Loading Linux... ");
177 status = fops_read(fd, &ehdr, &size);
178 if (EFI_ERROR(status) ||size < sizeof(ehdr)) return ELILO_LOAD_ERROR;
183 * do some sanity checking on the file
185 if (is_valid_header(&ehdr) == -1) {
186 ERR_PRT((L"%s : not an elf 64-bit file\n", LD_NAME));
187 return ELILO_LOAD_ERROR;
190 /* determine file endianess */
191 elf_is_big_endian = ehdr.e_ident[EI_DATA] == ELFDATA2MSB ? 1 : 0;
194 Print(L"ELF file is %s\n", elf_is_big_endian ? L"big endian" : L"little endian");
195 Print(L"Entry point 0x%lx\n", bswap64(ehdr.e_entry));
196 Print(L"%d program headers\n", bswap16(ehdr.e_phnum));
197 Print(L"%d segment headers\n", bswap16(ehdr.e_shnum));
200 phnum = bswap16(ehdr.e_phnum);
202 if (skip_bytes(fd, offs, bswap64(ehdr.e_phoff)) != 0) {
203 ERR_PRT((L"%s : skip tp %ld for phdrs failed", LD_NAME, offs));
204 return ELILO_LOAD_ERROR;
206 offs = bswap64(ehdr.e_phoff);
208 size = osize = phnum*sizeof(Elf64_Phdr);
210 DBG_PRT((L"%s : phdrs allocate %d bytes sizeof=%d entsize=%d\n", LD_NAME, size,sizeof(Elf64_Phdr), bswap16(ehdr.e_phentsize)));
212 phdrs = (Elf64_Phdr *)alloc(size, 0);
214 ERR_PRT((L"%s : allocate phdrs failed", LD_NAME));
215 return ELILO_LOAD_ERROR;
218 status = fops_read(fd, phdrs, &size);
219 if (EFI_ERROR(status) || size != osize) {
220 ERR_PRT((L"%s : load phdrs failed", LD_NAME, status));
225 * First pass to figure out:
226 * - lowest physical address
227 * - total memory footprint
229 for (i = 0; i < phnum; i++) {
231 paddr = bswap64(phdrs[i].p_paddr);
232 memsz = bswap64(phdrs[i].p_memsz);
234 DBG_PRT((L"Phdr %d paddr [0x%lx-0x%lx] offset %ld"
235 " filesz %ld memsz=%ld bss_sz=%ld p_type=%d\n",
238 paddr+bswap64(phdrs[i].p_filesz),
239 bswap64(phdrs[i].p_offset),
240 bswap64(phdrs[i].p_filesz),
242 memsz - bswap64(phdrs[i].p_filesz), bswap32(phdrs[i].p_type)));
244 if (bswap32(phdrs[i].p_type) != PT_LOAD) continue;
247 if (paddr < (UINTN)low_addr) low_addr = (VOID *)paddr;
249 if (paddr + memsz > (UINTN)max_addr)
250 max_addr = (VOID *)paddr + memsz;
253 if ((UINTN)low_addr & (EFI_PAGE_SIZE - 1)) {
254 ERR_PRT((L"%s : kernel low address 0x%lx not page aligned\n", LD_NAME, low_addr));
258 /* how many bytes are needed to hold the kernel */
259 total_size = (UINTN)max_addr - (UINTN)low_addr;
261 /* round up to get required number of pages */
262 pages = EFI_SIZE_TO_PAGES(total_size);
264 /* keep track of location where kernel ends for
265 * the initrd ramdisk (it will be put right after the kernel)
267 kd->kstart = low_addr;
268 kd->kend = low_addr+ (pages << EFI_PAGE_SHIFT);
271 * that's the kernel entry point (virtual address)
273 kd->kentry = (VOID *)bswap64(ehdr.e_entry);
275 if (((UINTN)kd->kentry >> 61) != 0) {
276 ERR_PRT((L"%s: <<ERROR>> entry point is a virtual address 0x%lx : not supported anymore\n", LD_NAME, kd->kentry));
280 Print(L"Lowest PhysAddr: 0x%lx\nTotalMemSize:%d bytes (%d pages)\n",
281 low_addr, total_size, pages);
282 Print(L"Kernel entry @ 0x%lx\n", kd->kentry);
286 * now allocate memory for the kernel at the exact requested spot
288 if (alloc_kmem(low_addr, pages) == -1) {
291 VERB_PRT(1, (L"%s : AllocatePages(%d, 0x%lx) for kernel failed\n", LD_NAME, pages, low_addr));
293 if (ia64_can_relocate() == 0) {
294 ERR_PRT((L"relocation is disabled, cannot load kernel"));
299 * could not allocate at requested spot, try to find a
300 * suitable location to relocate the kernel
302 * The maximum sized Itanium TLB translation entry is 256 MB.
303 * If we relocate the kernel by this amount we know for sure
304 * that alignment constraints will be satisified, regardless
305 * of the kernel used.
307 Print(L"Attempting to relocate kernel.\n");
308 if (find_kernel_memory(low_addr, max_addr, 256*MB, &new_addr) == -1) {
309 ERR_PRT((L"%s : find_kernel_memory(0x%lx, 0x%lx, 0x%lx, 0x%lx) failed\n", LD_NAME, low_addr, max_addr, 256*MB, &load_offset));
312 /* unsigned arithmetic */
313 load_offset = (UINTN) (new_addr - ROUNDDOWN((UINTN) low_addr,256*MB));
315 VERB_PRT(3, Print(L"low_addr=0x%lx new_addr=0x%lx offset=0x%lx", low_addr, new_addr, load_offset));
318 * correct various addesses for non-zero load_offset
320 low_addr = (VOID*) ((UINTN) low_addr + load_offset);
321 max_addr = (VOID*) ((UINTN) max_addr + load_offset);
322 kd->kstart = (VOID *) ((UINTN) kd->kstart + load_offset);
323 kd->kend = (VOID *) ((UINTN) kd->kend + load_offset);
324 kd->kentry = (VOID *) ((UINTN) kd->kentry + load_offset);
327 * try one last time to get memory for the kernel
329 if (alloc_kmem(low_addr, pages) == -1) {
330 ERR_PRT((L"%s : AllocatePages(%d, 0x%lx) for kernel failed\n", LD_NAME, pages, low_addr));
331 ERR_PRT((L"Relocation by 0x%lx bytes failed.\n", load_offset));
336 VERB_PRT(1, Print(L"Press any key to interrupt\n"));
339 * Walk through the program headers
340 * and actually load data into physical memory
342 for (i = 0; i < phnum; i++) {
345 * Check for pure loadable segment; ignore if not loadable
347 if (bswap32(phdrs[i].p_type) != PT_LOAD) continue;
349 poffs = bswap64(phdrs[i].p_offset);
353 VERB_PRT(3, Print(L"\noff=%ld poffs=%ld size=%ld\n", offs, poffs, size));
355 filesz = bswap64(phdrs[i].p_filesz);
357 * correct p_paddr for non-zero load offset
359 phdrs[i].p_paddr = (Elf64_Addr) ((UINTN) bswap64(phdrs[i].p_paddr) + load_offset);
362 * Move to the right position
364 if (size && skip_bytes(fd, offs, poffs) != 0) goto out_kernel;
367 * Keep track of current position in file
372 * How many BSS bytes to clear
374 bss_sz = bswap64(phdrs[i].p_memsz) - filesz;
377 Print(L"\nHeader #%d\n", i);
378 Print(L"offset %ld\n", poffs);
379 Print(L"Phys addr 0x%lx\n", phdrs[i].p_paddr); /* already endian adjusted */
380 Print(L"BSS size %ld bytes\n", bss_sz);
381 Print(L"skip=%ld offs=%ld\n", size, offs);
385 * Read actual segment into memory
387 ret = read_file(fd, filesz, (CHAR8 *)phdrs[i].p_paddr);
388 if (ret == ELILO_LOAD_ABORTED) goto load_abort;
389 if (ret == ELILO_LOAD_ERROR) goto out;
390 if (bswap32(phdrs[i].p_flags) & PF_X)
391 flush_dcache ((CHAR8 *)phdrs[i].p_paddr, filesz);
394 * update file position
401 if (bss_sz) Memset((VOID *) phdrs[i].p_paddr+filesz, 0, bss_sz);
407 return ELILO_LOAD_SUCCESS;
410 Print(L"..Aborted\n");
411 ret = ELILO_LOAD_ABORTED;
413 /* free kernel memory */
421 plain_load_kernel(CHAR16 *kname, kdesc_t *kd)
428 * Moving the open here simplifies the load_elf() error handling
430 status = fops_open(kname, &fd);
431 if (EFI_ERROR(status)) return ELILO_LOAD_ERROR;
433 Print(L"Loading %s...", kname);
435 ret = load_elf(fd, kd);
440 * if the skip buffer was ever used, free it
444 /* in case we come back */
450 loader_ops_t plain_loader={