* [Linux-ia64] initrd suport for ELI, kernel
@ 2000-06-01 21:19 Bill Nottingham
2000-06-01 21:26 ` Johannes Erdfelt
2000-06-01 21:50 ` Bill Nottingham
0 siblings, 2 replies; 3+ messages in thread
From: Bill Nottingham @ 2000-06-01 21:19 UTC (permalink / raw)
To: linux-ia64
[-- Attachment #1: Type: text/plain, Size: 403 bytes --]
Here's some patches that add initrd support to ELI
and the kernel. To use, simply add:
initrd=<some file>
to your eli.cfg. The ELI code that loads the kernel is
shamelessly copied from the kernel loading code. This
currently loads the initrd directly after the kernel.
Current bugs:
- the kernel assumes the address passed to it for
the initrd is valid. We should probably check this.
Bill
[-- Attachment #2: eli-initrd.diff --]
[-- Type: text/plain, Size: 5964 bytes --]
diff -ru eli-0.3.0-old/eli.c eli-0.3.0/eli.c
--- eli-0.3.0-old/eli.c Thu Mar 2 15:56:24 2000
+++ eli-0.3.0/eli.c Tue May 30 16:43:30 2000
@@ -64,6 +64,8 @@
struct vector *vectors; /* physical address of vector table */
fpswa_interface_t *efi_fpswa; /* the fpswa interface which contains the revision and a physical pointer to the FPSWA function */
+ UINT64 initrd_start;
+ UINT64 initrd_size;
};
#define MAX_IMAGE_NAME 15
@@ -76,6 +78,7 @@
CHAR16 *filename;
CHAR16 *append;
CHAR16 *root;
+ CHAR16 *initrd;
};
struct boot_image *image_head = NULL, *image_tail = NULL, *default_image = NULL;
@@ -268,6 +271,9 @@
image->root = StrDuplicate(aToU(p2));
else
root = StrDuplicate(aToU(p2));
+ } else if (strncmpa(p1, "initrd",6) == 0) {
+ if (image)
+ image->initrd = StrDuplicate(aToU(p2));
} else if (strncmpa(p1, "read-only", 9) == 0) {
readonly = 1;
} else if (strncmpa(p1, "read-write", 10) == 0) {
@@ -308,7 +314,110 @@
}
INTN
-load_elf (EFI_FILE_HANDLE fs, CHAR16 *filename, EFI_SYSTEM_TABLE *systab, UINT64 *start_addr)
+load_ramdisk (EFI_FILE_HANDLE fs, CHAR16 *filename, EFI_SYSTEM_TABLE *systab, UINT64 start_addr, UINT64 *initrd_size)
+{
+ EFI_FILE_HANDLE file;
+ EFI_STATUS status;
+ INTN total_size = 0, size = 0;
+ UINTN pages;
+ EFI_FILE_INFO *initrd_info;
+
+ /*
+ * Reset the input interface, is this needed?
+ * I think this is a bug in the 10/20/99 release of EFI.
+ * but it seems to fix the problem with ReadKeyStroke() becoming
+ * blocking !
+ */
+ systab->ConIn->Reset(systab->ConIn, 1);
+
+ /* Open the file */
+ status = fs->Open(fs, &file, filename, EFI_FILE_MODE_READ, EFI_FILE_READ_ONLY);
+ if (EFI_ERROR(status)) {
+ Print(W2U(L"%s: open failed: %r\n"), filename, status);
+ return EFI_LOAD_ERROR;
+ }
+
+#ifdef DEBUG
+ Print(W2U(L"Open %s worked\n"), filename);
+#endif
+
+ initrd_info = LibFileInfo(file);
+ if (!initrd_info) {
+ Print(W2U(L"%s: couldn't read file info\n"),filename);
+ return EFI_LOAD_ERROR;
+ }
+
+ total_size = initrd_info->FileSize;
+ *initrd_size = total_size;
+
+ /* round up to get required number of pages */
+ pages = SIZE_TO_PAGES(total_size);
+
+ /* Make Buffer point to the requested physical address in memory */
+#ifdef BROKEN_EFI_FLOPPY
+ /*
+ * Early versions of EFI had troubles loading files
+ * from floppies in a single big request. Breaking
+ * the read down into chunks of 4KB fixed that
+ * problem. Once EFI is fixed, this is no longer
+ * needed.
+ */
+ {
+ EFI_PHYSICAL_ADDRESS buffer;
+ UINTN j = 0;
+
+ buffer = virt_to_phys(start_addr);
+ while (total_size > 0) {
+ CHAR8 helicopter[4] = { '|' , '/' , '-' , '\\' };
+ int x;
+
+ size = 4 * PAGE_SIZE;
+ if (size > total_size)
+ size = total_size;
+ status = fs->Read(file, &size, (VOID *)buffer);
+ if (EFI_ERROR(status)) {
+ Print(W2U(L"%s: read failed: %r\n"), filename, status);
+ BS->FreePages(start_addr, pages);
+ return EFI_LOAD_ERROR;
+ }
+
+ Print(W2U(L"%c\b"), helicopter[j++%4]);
+ buffer += size;
+ total_size -= size;
+
+ if (check_abort(systab) == EFI_SUCCESS)
+ goto load_abort;
+ }
+ }
+#else
+ size = total_size;
+ status = fs->Read(file, &size, (VOID *) virt_to_phys(start_addr));
+ if (EFI_ERROR(status)) {
+ Print(W2U(L"%s: read failed: %r\n"), filename, status);
+ BS->FreePages(start_addr, pages);
+ return EFI_LOAD_ERROR;
+ }
+ Print(W2U(L"-> %ld bytes\n"), size);
+#endif
+ fs->Close(file);
+
+ return EFI_SUCCESS;
+
+#ifdef BROKEN_EFI_FLOPPY
+load_abort:
+ Print(W2U(L"\nLoading aborted\n"));
+ status = BS->FreePages(start_addr, pages);
+ if (status != EFI_SUCCESS)
+ efi_perror(W2U(L"FreePages"), status);
+ else if (verbose)
+ Print(W2U(L"Freed %ld pages starting at 0x%lx\n"), pages, start_addr);
+ status = fs->Close(file);
+ return EFI_NOT_READY;
+#endif
+}
+
+INTN
+load_elf (EFI_FILE_HANDLE fs, CHAR16 *filename, EFI_SYSTEM_TABLE *systab, UINT64 *start_addr, UINT64 *end_addr)
{
Elf64_Ehdr ehdr;
Elf64_Phdr phdr;
@@ -501,6 +610,7 @@
}
fs->Close(file);
*start_addr = ehdr.e_entry;
+ *end_addr = max_addr;
return EFI_SUCCESS;
@@ -649,7 +759,8 @@
*/
static EFI_STATUS
create_boot_params (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab, CHAR16 *args,
- struct acpi_op *acpi_root, UINT64 start_addr)
+ struct acpi_op *acpi_root, UINT64 start_addr, UINT64 initrd_start,
+ UINT64 initrd_size)
{
UINTN num_pages, cookie, desc_size, cols, rows, args_size, map_size = 512;
SIMPLE_TEXT_OUTPUT_INTERFACE *conout;
@@ -744,6 +855,8 @@
bp->num_vectors = num_vectors;
bp->vectors = vectors;
+ bp->initrd_start = initrd_start;
+ bp->initrd_size = initrd_size;
/* fetch console parameters: */
conout = systab->ConOut;
@@ -970,6 +1083,9 @@
EFI_FILE_HANDLE fs;
EFI_STATUS status;
UINT64 start_addr;
+ UINT64 end_addr;
+ UINT64 initrd_start = 0;
+ UINT64 initrd_size = 0;
UINTN argc, i;
CHAR16 *argv[MAX_ARGS];
struct boot_image *boot_image;
@@ -1107,7 +1223,7 @@
Print(W2U(L"eli: booting `%s' with args=`%s' "), kernel_name, args);
#endif
- switch (load_elf(fs, kernel_name, systab, &start_addr)) {
+ switch (load_elf(fs, kernel_name, systab, &start_addr, &end_addr)) {
case EFI_SUCCESS:
break;
@@ -1118,9 +1234,20 @@
case EFI_LOAD_ERROR:
return EFI_LOAD_ERROR;
}
+ if (boot_image && boot_image->initrd) {
+ end_addr = (end_addr/PAGE_SIZE+1) * PAGE_SIZE;
+ switch (load_ramdisk(fs, boot_image->initrd, systab, end_addr, &initrd_size)) {
+ case EFI_SUCCESS:
+ initrd_start = end_addr;
+ break;
+ case EFI_OUT_OF_RESOURCES:
+ case EFI_LOAD_ERROR:
+ return EFI_LOAD_ERROR;
+ }
+ }
/* No console output permitted after create_boot_params()! */
- status = create_boot_params(image, systab, args, acpi_root, start_addr);
+ status = create_boot_params(image, systab, args, acpi_root, start_addr, initrd_start, initrd_size);
if (status != EFI_SUCCESS)
return status;
start_kernel(start_addr);
[-- Attachment #3: kernel-initrd.diff --]
[-- Type: text/plain, Size: 2497 bytes --]
diff -ru redhat/BUILD/linux/arch/ia64/kernel/setup.c lfoo/arch/ia64/kernel/setup.c
--- redhat/BUILD/linux/arch/ia64/kernel/setup.c Tue May 30 16:32:59 2000
+++ lfoo/arch/ia64/kernel/setup.c Tue May 30 16:36:18 2000
@@ -26,6 +26,9 @@
#include <linux/string.h>
#include <linux/threads.h>
#include <linux/console.h>
+#ifdef CONFIG_BLK_DEV_RAM
+#include <linux/blk.h>
+#endif
#include <asm/acpi-ext.h>
#include <asm/page.h>
@@ -125,11 +128,24 @@
* change APIs, they'd do things for the better. Grumble...
*/
bootmap_start = PAGE_ALIGN(__pa(&_end));
+ if (ia64_boot_param.initrd_size) {
+ bootmap_start = PAGE_ALIGN(bootmap_start+ia64_boot_param.initrd_size);
+ }
bootmap_size = init_bootmem(bootmap_start >> PAGE_SHIFT, max_pfn);
efi_memmap_walk(free_available_memory, 0);
reserve_bootmem(bootmap_start, bootmap_size);
+#ifdef CONFIG_BLK_DEV_INITRD
+ initrd_start = ia64_boot_param.initrd_start;
+ if (initrd_start) {
+ initrd_end = initrd_start+ia64_boot_param.initrd_size;
+ printk("Initial ramdisk at: 0x%p (%lu bytes)\n",
+ (void *) initrd_start, ia64_boot_param.initrd_size);
+ reserve_bootmem(virt_to_phys(initrd_start),
+ ia64_boot_param.initrd_size);
+ }
+#endif
#if 0
/* XXX fix me */
init_mm.start_code = (unsigned long) &_stext;
diff -ru redhat/BUILD/linux/arch/ia64/mm/init.c lfoo/arch/ia64/mm/init.c
--- redhat/BUILD/linux/arch/ia64/mm/init.c Tue May 30 16:32:59 2000
+++ lfoo/arch/ia64/mm/init.c Wed May 24 22:05:11 2000
@@ -179,6 +180,19 @@
}
printk ("Freeing unused kernel memory: %ldkB freed\n",
(&__init_end - &__init_begin) >> 10);
+}
+
+void
+free_initrd_mem(unsigned long start, unsigned long end)
+{
+ if (start < end)
+ printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
+ for (; start < end; start += PAGE_SIZE) {
+ clear_bit(PG_reserved, &mem_map[MAP_NR(start)].flags);
+ set_page_count(&mem_map[MAP_NR(start)], 1);
+ free_page(start);
+ ++totalram_pages;
+ }
}
void
diff -ru redhat/BUILD/linux/include/asm-ia64/system.h lfoo/include/asm-ia64/system.h
--- redhat/BUILD/linux/include/asm-ia64/system.h Tue May 30 16:33:01 2000
+++ lfoo/include/asm-ia64/system.h Thu May 25 16:47:59 2000
@@ -54,6 +54,8 @@
__u16 num_pci_vectors; /* number of ACPI derived PCI IRQ's*/
__u64 pci_vectors; /* physical address of PCI data (pci_vector_struct)*/
__u64 fpswa; /* physical address of the the fpswa interface */
+ __u64 initrd_start;
+ __u64 initrd_size;
} ia64_boot_param;
extern inline void
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [Linux-ia64] initrd suport for ELI, kernel
2000-06-01 21:19 [Linux-ia64] initrd suport for ELI, kernel Bill Nottingham
@ 2000-06-01 21:26 ` Johannes Erdfelt
2000-06-01 21:50 ` Bill Nottingham
1 sibling, 0 replies; 3+ messages in thread
From: Johannes Erdfelt @ 2000-06-01 21:26 UTC (permalink / raw)
To: linux-ia64
On Thu, Jun 01, 2000, Bill Nottingham <notting@redhat.com> wrote:
> Here's some patches that add initrd support to ELI
> and the kernel. To use, simply add:
>
> initrd=<some file>
>
> to your eli.cfg. The ELI code that loads the kernel is
> shamelessly copied from the kernel loading code. This
> currently loads the initrd directly after the kernel.
That's alright. I've checked the code into CVS.
> Current bugs:
> - the kernel assumes the address passed to it for
> the initrd is valid. We should probably check this.
A NULL check should be sufficient. Perhaps we should add a version field
to the boot structure so the kernel knows if the boot loader supports
certain fields and should thusly use them or not?
JE
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [Linux-ia64] initrd suport for ELI, kernel
2000-06-01 21:19 [Linux-ia64] initrd suport for ELI, kernel Bill Nottingham
2000-06-01 21:26 ` Johannes Erdfelt
@ 2000-06-01 21:50 ` Bill Nottingham
1 sibling, 0 replies; 3+ messages in thread
From: Bill Nottingham @ 2000-06-01 21:50 UTC (permalink / raw)
To: linux-ia64
[-- Attachment #1: Type: text/plain, Size: 245 bytes --]
Bill Nottingham (notting@redhat.com) said:
> Here's some patches that add initrd support to ELI
> and the kernel.
FYI, if you've got a recent toolchain, you need the
attached patch for gnu-efi for it to build correctly
(thanks David!).
Bill
[-- Attachment #2: gnu-efi.patch --]
[-- Type: text/plain, Size: 1220 bytes --]
2000-04-03 David Mosberger <davidm@hpl.hp.com>
* gnuefi/elf_ia64_efi.lds: Include .IA_64.unwind and
.IA_64.unwind_info in .data segment to avoid EFI load error
"ImageAddress: pointer outside of image" error due to the .dynsym
relocations against these sections.
* gnuefi/reloc_ia64.S: fixed typo: .space directive had constant
100 hardcoded instead of using MAX_FUNCTION_DESCRIPTORS
macro. Duh.
diff -urN gnu-efi-0.8/gnuefi/elf_ia64_efi.lds gnu-efi-pre0.9/gnuefi/elf_ia64_efi.lds
--- gnu-efi-0.8/gnuefi/elf_ia64_efi.lds Wed Sep 22 16:53:51 1999
+++ gnu-efi-pre0.9/gnuefi/elf_ia64_efi.lds Mon Apr 3 17:35:29 2000
@@ -27,6 +27,8 @@
*(.got.plt)
*(.got)
*(.plabel) /* data whose relocs we want to ignore */
+ *(.IA_64.unwind)
+ *(.IA_64.unwind_info)
/* the EFI loader doesn't seem to like a .bss section, so we stick
it all into .data: */
*(.sbss)
diff -urN gnu-efi-0.8/gnuefi/reloc_ia64.S gnu-efi-pre0.9/gnuefi/reloc_ia64.S
--- gnu-efi-0.8/gnuefi/reloc_ia64.S Thu Sep 23 21:54:21 1999
+++ gnu-efi-pre0.9/gnuefi/reloc_ia64.S Mon Apr 3 16:20:51 2000
@@ -204,5 +204,5 @@
.data
.align 16
fptr_mem_base:
- .space 100*16
+ .space MAX_FUNCTION_DESCRIPTORS*16
fptr_mem_limit:
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2000-06-01 21:50 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2000-06-01 21:19 [Linux-ia64] initrd suport for ELI, kernel Bill Nottingham
2000-06-01 21:26 ` Johannes Erdfelt
2000-06-01 21:50 ` Bill Nottingham
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox