public inbox for linux-ia64@vger.kernel.org
 help / color / mirror / Atom feed
From: Bill Nottingham <notting@redhat.com>
To: linux-ia64@vger.kernel.org
Subject: [Linux-ia64] initrd suport for ELI, kernel
Date: Thu, 01 Jun 2000 21:19:28 +0000	[thread overview]
Message-ID: <marc-linux-ia64-105590678205112@msgid-missing> (raw)

[-- 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

             reply	other threads:[~2000-06-01 21:19 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2000-06-01 21:19 Bill Nottingham [this message]
2000-06-01 21:26 ` [Linux-ia64] initrd suport for ELI, kernel Johannes Erdfelt
2000-06-01 21:50 ` Bill Nottingham

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=marc-linux-ia64-105590678205112@msgid-missing \
    --to=notting@redhat.com \
    --cc=linux-ia64@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox