Martin Michlmayr <[EMAIL PROTECTED]> wrote:

Hi,

>> Patch attached, applies on top of the previous one.
>
> Yep, that works.  Can you send it to Guido and #452798

Both patches attached.
 - first one for 64bit kernel support, though it looks like it wasn't
   needed after all?
 - second one for proper initrd loading, actually using malloc() to
   get a suitable memory area

JB.

-- 
 Julien BLACHE <[EMAIL PROTECTED]>  |  Debian, because code matters more 
 Debian & GNU/Linux Developer        |       <http://www.debian.org>
 Public key available on <http://www.jblache.org> - KeyID: F5D6 5169 
 GPG Fingerprint : 935A 79F1 C8B3 3521 FD62 7CC7 CD61 4FD7 F5D6 5169 

diff -ru orig/arcboot/tip22/tftpload.c arcboot-0.3.8.9/tip22/tftpload.c
--- orig/arcboot/tip22/tftpload.c	2007-11-21 15:05:14.000000000 +0000
+++ arcboot-0.3.8.9/tip22/tftpload.c	2007-11-25 14:22:56.000000000 +0000
@@ -30,6 +30,8 @@
 extern void* __rd_start;
 extern void* __rd_end;
 
+static int is64 = 0;
+
 static void Wait(const char *prompt)
 {
 	int ch;
@@ -235,7 +237,7 @@
 	return kernel_end;
 }
 
-static ULONG CopyKernel(ULONG* kernel_end)
+static Elf64_Addr CopyKernel(ULONG *kernel_end)
 {
 	Elf32_Ehdr *header = (Elf32_Ehdr*)offset2addr(0L);
 	Elf64_Ehdr *header64 = (Elf64_Ehdr*)header;
@@ -257,10 +259,11 @@
 
 		(*kernel_end) = CopyProgramSegments32(header);
 
-		printf("Starting kernel; entry point = 0x%lx\n\r",
-		       ((ULONG) KSEG0ADDR(header->e_entry)));
-		return KSEG0ADDR(header->e_entry);
+		printf("ELF32 kernel entry point = 0x%lx\n\r", (ULONG)header->e_entry);
+		return (Elf64_Addr) header->e_entry;
 	} else if (header->e_ident[EI_CLASS] == ELFCLASS64) {
+		is64 = 1;
+
 		if (header64->e_ident[EI_DATA] != ELFDATA2MSB)
 			Fatal("Not a big-endian file\n\r");
 		if (header64->e_ident[EI_VERSION] != EV_CURRENT)
@@ -274,9 +277,9 @@
 
 		(*kernel_end) = CopyProgramSegments64(header64);
 
-		printf("Starting kernel; entry point = 0x%lx\n\r",
-		       ((ULONG) KSEG0ADDR(header64->e_entry)));
-		return KSEG0ADDR(header64->e_entry);
+		printf("ELF64 kernel entry point = 0x%lx %lx\n\r",
+		       (ULONG)(header64->e_entry >> 32), (ULONG)(header64->e_entry & 0xffffffff));
+		return header64->e_entry;
 	} else
 		Fatal("Neither an ELF32 nor an ELF64 kernel\n\r");
 
@@ -290,6 +293,20 @@
 			rd_start, rd_vaddr, rd_size);
 }
 
+void _start64(LONG argc, CHAR * argv[], CHAR * envp[],
+              unsigned long long *addr)
+{
+  __asm__ __volatile__(
+		       ".set push\n"
+		       "\t.set mips3\n"
+		       "\t.set noreorder\n"
+		       "\t.set noat\n"
+		       "\tld $1, 0($7)\n"
+		       "\tjr $1\n"
+		       "\t nop\n"
+		       "\t.set pop");
+}
+
 void _start(LONG argc, CHAR * argv[], CHAR * envp[])
 {
 	char* nargv[3];
@@ -298,7 +315,8 @@
 	ULONG kernel_end = 0L;
 	ULONG rd_size= ((char*)&__rd_end) - ((char*)&__rd_start);
 	char* rd_vaddr=NULL;
-	void (*kernel_entry)(int argc, CHAR * argv[], CHAR * envp[]);
+	Elf32_Addr kernel_entry32;
+	Elf64_Addr kernel_entry64;
 
 	/* Print identification */
 #if (SUBARCH == IP22)
@@ -316,7 +334,8 @@
 	printf("Embedded ramdisk image starts 0x%p, ends 0x%p\n\r", 
 			&__rd_start, &__rd_end);
 #endif
-	kernel_entry = (void (*)(int, CHAR *[], CHAR *[]))CopyKernel(&kernel_end);
+	kernel_entry64 = CopyKernel(&kernel_end);
+	kernel_entry32 = (Elf32_Addr) kernel_entry64;
 
 	/* align to page boundary */
 	rd_vaddr = (char*)(((kernel_end + PAGE_SIZE) / PAGE_SIZE ) * PAGE_SIZE);
@@ -344,10 +363,18 @@
 	Wait("\n\r--- Debug: press <spacebar> to boot kernel ---");
 #endif
 	/* Finally jump into the kernel */
-	ArcFlushAllCaches();
-	if( kernel_entry )
-		(*kernel_entry)(nargc ,nargv, envp);
-	else
+	if( kernel_entry64 ) {
+	  if (is64 == 0) {
+	    printf("Starting ELF32 kernel\n\r");
+	    ArcFlushAllCaches();
+	    ((void (*)(int argc, CHAR * argv[], CHAR * envp[]))
+	     kernel_entry32)(nargc ,nargv, envp);
+	  } else {
+	    printf("Starting ELF64 kernel\n\r");
+	    ArcFlushAllCaches();
+	    _start64(nargc, nargv, envp, &kernel_entry64);
+	  }
+	} else
 		printf("Invalid kernel entry NULL\n\r");
 
 	/* Not likely to get back here in a functional state, 
diff -u arcboot-0.3.8.9/tip22/tftpload.c arcboot-0.3.8.9/tip22/tftpload.c
--- arcboot-0.3.8.9/tip22/tftpload.c	2007-11-25 14:22:56.000000000 +0000
+++ arcboot-0.3.8.9/tip22/tftpload.c	2007-11-25 16:40:01.000000000 +0000
@@ -314,7 +314,7 @@
 	char argv_rd[128];	/* passed to the kernel on its commandline */
 	ULONG kernel_end = 0L;
 	ULONG rd_size= ((char*)&__rd_end) - ((char*)&__rd_start);
-	char* rd_vaddr=NULL;
+	ULONG rd_vaddr;
 	Elf32_Addr kernel_entry32;
 	Elf64_Addr kernel_entry64;
 
@@ -337,12 +337,18 @@
 	kernel_entry64 = CopyKernel(&kernel_end);
 	kernel_entry32 = (Elf32_Addr) kernel_entry64;
 
+	rd_vaddr = (ULONG)malloc(rd_size + PAGE_SIZE);
 	/* align to page boundary */
-	rd_vaddr = (char*)(((kernel_end + PAGE_SIZE) / PAGE_SIZE ) * PAGE_SIZE);
-	copyRamdisk( rd_vaddr, (char*)&__rd_start, rd_size);
+	rd_vaddr = (rd_vaddr + PAGE_SIZE) & ~(PAGE_SIZE - 1);
+
+#ifdef DEBUG
+	printf("rd_start=0x%lx rd_size=0x%lx\n\r", rd_vaddr, rd_size);
+#endif
+
+	copyRamdisk( (char *)rd_vaddr, (char*)&__rd_start, rd_size);
 
 	/* tell the kernel about the ramdisk */
-	sprintf(argv_rd, "rd_start=0x%p rd_size=0x%lx", rd_vaddr, rd_size);
+	sprintf(argv_rd, "rd_start=0x%lx rd_size=0x%lx", rd_vaddr, rd_size);
 
 	nargv[0] = argv[0];
 	nargv[1] = argv_rd;

Reply via email to