diff -urp mb_boot_tv-1.0.9/loader_init.c mb_boot_tv-1.0.10/loader_init.c --- mb_boot_tv-1.0.9/loader_init.c 2007-10-20 15:57:09.000000000 -0400 +++ mb_boot_tv-1.0.10/loader_init.c 2007-11-26 19:47:30.000000000 -0500 @@ -90,6 +90,82 @@ void shax(unsigned char *result, unsigne SHA1Result(&context,result); } + +#define EFI_PAGE_SHIFT 12 +#define NextEFIMemoryDescriptor(Ptr,Size) ((EFI_MEMORY_DESCRIPTOR *) (((UINT8 *) Ptr) + Size)) + +/* uint64 is not present in fprint so fake it*/ +UINT32 hi32(UINT64 u_value64) +{ + return( u_value64 >> 32 ); +} +UINT32 lo32(UINT64 u_value64) +{ + return( (UINT32)u_value64 ); +} + +void quirk_fixup_efi_memmap(boot_params_t *bp) +{ + /* November 26, 2007 -- Scott Davilla (davilla@4pi.com) + The appletv efi firmware has a bug that effects linux kernel when + booting from efi. Three EFI RunTime Services Code/Data segments overlap + a declared free ememory segment. This can cause code/data overwrites + and result in unknown crashes/hangs when running linux. + This brute force patch checks for the overlap and adjusts the free + memory area. The match values might change in the future if Apple + releases new boot firmware so beware if this breaks in the future. + + Also the orignal EFI_MEMORY_DESCRIPTOR structure is defined as under + the EFI runtime so it's assumed alignment (8 byte) is wrong for + Mach-0 (4 byte) so it need a uint32 pad after "Type" or bad things happen + */ + + int num_maps, i; + UINT64 bgn, end; + EFI_MEMORY_DESCRIPTOR *md, *p; + + num_maps = bp->s.efi_mem_map_size/bp->s.efi_mem_desc_size; + + for (i = 0, p = (EFI_MEMORY_DESCRIPTOR*)bp->s.efi_mem_map; i < num_maps; i++) { + md = p; + + bgn = md->PhysicalStart; + end = md->PhysicalStart + (md->NumberOfPages << EFI_PAGE_SHIFT); + + /* + printk("mem%02d: type=%d, ", i, md->Type ); + printk("attr=0x%08X%08X\n", hi32(md->Attribute), lo32(md->Attribute) ); + printk(" range=[0x%08X%08X-", hi32(bgn), lo32(bgn) ); + printk("0x%08X%08X], ", hi32(end), lo32(end) ); + printk("%dMB\n", lo32(md->NumberOfPages >> (20 - EFI_PAGE_SHIFT)) ); + */ + + // find problem free memory segment */ + if ( (bgn == 0x000000000b66e000ULL) & (end == 0x000000000d9c4000ULL) ) { + UINT64 new_bgn, new_end, new_pages; + + printk(" found memory overlap\n"); + printk(" memory range=[0x%08X%08X-", hi32(bgn), lo32(bgn) ); + printk("0x%08X%08X]\n", hi32(end), lo32(end) ); + + new_bgn = 0x000000000b6bf000ULL; + new_pages = (end - new_bgn) / (1 << EFI_PAGE_SHIFT); + + new_end = new_bgn + (new_pages << EFI_PAGE_SHIFT); + printk(" fixed memory overlap\n"); + printk(" memory range=[0x%08X%08X-", hi32(new_bgn), lo32(new_bgn) ); + printk("0x%08X%08X]\n", hi32(new_end), lo32(new_end) ); + + + md->PhysicalStart = new_bgn; + md->NumberOfPages = new_pages; + + } + + p = NextEFIMemoryDescriptor(p, bp->s.efi_mem_desc_size); + } +} + #define KERNEL_BUFFER 0x400000 #define BOOT_PARAM_MEMSIZE 16384 @@ -132,12 +208,16 @@ uint8_t *kc=(uint8_t *)k; printk("efi_mem_desc_size 0x%08X\n", bp->s.efi_mem_desc_size); printk("efi_mem_desc_ver 0x%08X\n", bp->s.efi_mem_desc_ver); printk("efi_sys_tbl 0x%08X\n", bp->s.efi_sys_tbl); + //printk("wait 1 seconds so I can see these\n\n\n\n"); + //sleep(1); + quirk_fixup_efi_memmap(bp); + //sleep(5); + //printk("wait 5 seconds so I can see these\n\n\n\n"); EFI_SYSTEM_TABLE *system_table = (EFI_SYSTEM_TABLE *) bootparms->efi_sys_tbl; EFI_RUNTIME_SERVICES *runtime = (EFI_RUNTIME_SERVICES *) system_table->RuntimeServices; start_kernel(kd.kentry, bp); - } @@ -150,11 +230,15 @@ void loader_init(unsigned int args) kdesc_t kd; memdesc_t imem, mmem; + //sleep(10); + bootparms = (boot_parms *)args; vmode.width = bootparms->video.rowb / 4; vmode.height = bootparms->video.height; + /* initial clear of the video screen */ MEMSET(bootparms->video.addr, vmode.width * vmode.height *4, 0x00); + vmode.xmargin = 0; VIDEO_CURSOR_POSX = 0; VIDEO_CURSOR_POSY = 0; @@ -164,8 +248,8 @@ void loader_init(unsigned int args) printk("FB Start 0x%08X, with %d height %d rowb %d depth %d\n", bootparms->video.addr, bootparms->video.width, bootparms ->video.height, bootparms->video.rowb, bootparms->video.depth); { - extern void do_main(void); - do_main(); + extern void do_main(void); + do_main(); } printk("etherboot code returned\n"); diff -urp mb_boot_tv-1.0.9/main/diskboot.c mb_boot_tv-1.0.10/main/diskboot.c --- mb_boot_tv-1.0.9/main/diskboot.c 2007-04-26 07:03:07.000000000 -0400 +++ mb_boot_tv-1.0.10/main/diskboot.c 2007-11-02 19:13:04.000000000 -0400 @@ -32,9 +32,14 @@ disk_read_file (char *name, int *size) strcpy(namebuf,name); + //printk("disk_read_file:namebuf=%s\n", namebuf); - if (ext2fs_open (namebuf, &fd)) + ret = ext2fs_open( namebuf, &fd); + if (ret) { + printk("disk_read_file:ext2fs_open failed, %d\n", ret); + /*if (ext2fs_open (namebuf, &fd)) {*/ return NULL; + } sz = (uint32_t) ext2fs_len (fd); @@ -59,6 +64,8 @@ diskboot (char *config, int len, int all int kernel_len, ramdisk_len; int trynetboot = 0; + //printk("diskboot:config=%s\n", config); + parse_config (config, len, kernel, options, ramdisk, &trynetboot, NULL); if (allowed_trynetwork && trynetboot) @@ -106,7 +113,7 @@ diskboot (char *config, int len, int all disk_close (); - sleep (2); + //sleep (2); boot_kernel (kernel_buf, kernel_len, ramdisk_buf, ramdisk_len, options); printk ("booting failed\n"); @@ -127,58 +134,60 @@ try_disk_boot (int trynetwork) int len; - if (disk_open (0)) - { + if (disk_open (0)) { printk ("Failed to open disk\n"); return; - } + } - if (efi_find_partitions (p, &n)) - { + //printk("try_disk_boot:max partitions=%d\n", n); + + if (efi_find_partitions (p, &n)) { disk_close (); printk ("Failed to find an EFI GPT\n"); return; - } + } - for (i = 0; i < n; ++i) - { + //printk("try_disk_boot:max partitions=%d\n", n); + for (i = 0; i < n; ++i) { partition_set (&p[i]); - if (ext2fs_fs_open ()) - { + if (ext2fs_fs_open ()) { printk ("part%d: no ext2fs filesystem\n", i); continue; - } + } - config = disk_read_file (BOOTCONF, &len); + //config = disk_read_file ("/tmpboot" BOOTCONF, &len); + //if (!config) { + // config = disk_read_file (BOOTCONF, &len); + //} else { + // printk ("part%d: /tmpboot" BOOTCONF " found\n", i); + //} - if (!config) - { + config = disk_read_file (BOOTCONF, &len); + if (!config) { config = disk_read_file ("/boot" BOOTCONF, &len); - if (config) - { + if (config) { printk ("part%d: /boot" BOOTCONF " found\n", i); - } - } - else - { + } + } else { printk ("part%d: " BOOTCONF " found\n", i); - } + } - if (!config) - { + if (!config) { printk ("part%d: can't open " BOOTCONF " or /boot" BOOTCONF "\n", i); ext2fs_fs_close (); continue; - } - + } + //printk("try_disk_boot:config=%s, %d\n", config, len); + //sleep(60); diskboot (config, len, trynetwork); - + //sleep(60); ext2fs_fs_close (); + //printk("try_disk_boot:break\n"); break; } diff -urp mb_boot_tv-1.0.9/main/efi.c mb_boot_tv-1.0.10/main/efi.c --- mb_boot_tv-1.0.9/main/efi.c 2007-04-26 07:03:07.000000000 -0400 +++ mb_boot_tv-1.0.10/main/efi.c 2007-11-02 17:15:46.000000000 -0400 @@ -422,8 +422,11 @@ efi_find_partitions (struct partition *p printf (" part%d", *num); (*num)++; - if (!n == *num) + if (!n == *num) { + printf("\n"); + printf("efi_find_partitions:!n == *num, %d, %d\n", !n, *num); break; + } } printf ("\n"); diff -urp mb_boot_tv-1.0.9/main/main.c mb_boot_tv-1.0.10/main/main.c --- mb_boot_tv-1.0.9/main/main.c 2007-05-17 15:44:30.000000000 -0400 +++ mb_boot_tv-1.0.10/main/main.c 2007-11-02 12:53:52.000000000 -0400 @@ -132,7 +132,9 @@ parse_config (char *config, int len, cha printk ("kernel: %s\n", kernel); printk ("options: %s\n", options); printk ("ramdisk: %s\n", ramdisk); - if (trynetboot) + + + if (trynetboot) { printk ("trynetboot: %d\n", *trynetboot); } diff -urp mb_boot_tv-1.0.9/types.h mb_boot_tv-1.0.10/types.h --- mb_boot_tv-1.0.9/types.h 2007-04-19 19:06:13.000000000 -0400 +++ mb_boot_tv-1.0.10/types.h 2007-10-27 16:27:55.000000000 -0400 @@ -110,6 +110,7 @@ typedef UINT64 EFI_VIRTUAL_ADDR typedef struct { UINT32 Type; // Field size is 32 bits followed by 32 bit pad + UINT32 Pad; EFI_PHYSICAL_ADDRESS PhysicalStart; // Field size is 64 bits EFI_VIRTUAL_ADDRESS VirtualStart; // Field size is 64 bits UINT64 NumberOfPages; // Field size is 64 bits diff -urp mb_boot_tv-1.0.9/version-micro mb_boot_tv-1.0.10/version-micro --- mb_boot_tv-1.0.9/version-micro 2007-05-17 15:44:31.000000000 -0400 +++ mb_boot_tv-1.0.10/version-micro 2007-10-27 12:04:19.000000000 -0400 @@ -1 +1 @@ -9 +10