Imported Upstream version 3.10
[debian/elilo] / x86_64 / system.c
index 0755ff4e2807dbb442a27785e4ae7cc931dd95c0..6874acc51aa32e2eea7b9d07231a06e916211624 100644 (file)
@@ -105,7 +105,10 @@ UINTN high_base_mem = 0x90000;
 UINTN high_ext_mem = 32 * 1024 * 1024;
 
 /* This starting address will hold true for all of the loader types for now */
-VOID *kernel_start = (VOID *)0x100000; /* 1M */
+VOID *kernel_start = (void *)DEFAULT_KERNEL_START;
+
+/* The kernel may load elsewhere if EFI firmware reserves kernel_start */
+VOID *kernel_load_address = DEFAULT_KERNEL_START; 
 
 VOID *initrd_start = NULL;
 UINTN initrd_size = 0;
@@ -139,16 +142,16 @@ sysdeps_initrd_get_addr(kdesc_t *kd, memdesc_t *imem)
        DBG_PRT((L"initrd_get_addr()\n"));
 
        if (!kd || !imem) {
-               ERR_PRT((L"kd=0x%x imem=0x%x", kd, imem));
+               ERR_PRT((L"kd="PTR_FMT" imem="PTR_FMT"", kd, imem));
                return -1;
        }
 
-       VERB_PRT(3, Print(L"kstart=0x%x  kentry=0x%x  kend=0x%x\n", 
+       VERB_PRT(3, Print(L"kstart="PTR_FMT"  kentry="PTR_FMT"  kend="PTR_FMT"\n", 
                kd->kstart, kd->kentry, kd->kend));
 
        imem->start_addr = kd->kend;
 
-       VERB_PRT(3, Print(L"initrd start_addr=0x%x pgcnt=%d\n", 
+       VERB_PRT(3, Print(L"initrd start_addr="PTR_FMT" pgcnt=%d\n", 
                imem->start_addr, imem->pgcnt));
 
        return 0;
@@ -160,7 +163,7 @@ sysdeps_free_boot_params(boot_params_t *bp)
        mmap_desc_t md;
 
        ZeroMem(&md, sizeof md);
-       md.md = (VOID *)bp->s.efi_mem_map;
+       md.md = (VOID *)(UINT64)bp->s.efi_mem_map;
        free_memmap(&md);
 }
 
@@ -189,10 +192,11 @@ static INTN get_video_info(boot_params_t * bp) {
         EFI_GUID GopProtocol = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
         EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop_interface;
         EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Gop_info;
-        EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE   *Gop_mode;
-        EFI_HANDLE *Gop_handle;
+        EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE   *Gop_mode = NULL;
+        EFI_HANDLE *Gop_handle = NULL;
         EFI_STATUS efi_status;
-        UINTN size, size1;
+        UINTN size = 0;
+        UINTN size1;
         UINT8 i;
 
        efi_status = uefi_call_wrapper(
@@ -255,7 +259,7 @@ static INTN get_video_info(boot_params_t * bp) {
                return -1;
        }
                
-       bp->s.is_vga = 0x24;
+       bp->s.is_vga = 0x70;
        bp->s.orig_cursor_col = 0;
        bp->s.orig_cursor_row = 0;
        bp->s.orig_video_page = 0;
@@ -326,30 +330,56 @@ static INTN get_video_info(boot_params_t * bp) {
  * This code is based on a Linux kernel patch submitted by Edgar Hucek
  */
 
+/* Add a memory region to the e820 map */
+static void add_memory_region (struct e820entry *e820_map,
+                              int *e820_nr_map,
+                              unsigned long long start,
+                              unsigned long size,
+                              unsigned int type)
+{
+       int x = *e820_nr_map;
+
+       if (x == E820_MAX) {
+               Print(L"Too many entries in the memory map!\n");
+               return;
+       }
+
+       if ((x > 0) && e820_map[x-1].addr + e820_map[x-1].size == start
+           && e820_map[x-1].type == type)
+               e820_map[x-1].size += size;
+       else {
+               e820_map[x].addr = start;
+               e820_map[x].size = size;
+               e820_map[x].type = type;
+               (*e820_nr_map)++;
+       }
+}
+
 void fill_e820map(boot_params_t *bp, mmap_desc_t *mdesc)
 {
-       int nr_map, i;
+       int nr_map, e820_nr_map = 0, i;
        UINT64 start, end, size;
        EFI_MEMORY_DESCRIPTOR   *md, *p;
        struct e820entry *e820_map;
 
        nr_map = mdesc->map_size/mdesc->desc_size;
        e820_map = (struct e820entry *)bp->s.e820_map;
-       bp->s.e820_nrmap = nr_map;
                        
        for (i = 0, p = mdesc->md; i < nr_map; i++)
        {
                md = p;
                switch (md->Type) {
                case EfiACPIReclaimMemory:
-                       e820_map->addr = md->PhysicalStart;
-                       e820_map->size = md->NumberOfPages << EFI_PAGE_SHIFT;
-                       e820_map->type = E820_ACPI;
+                       add_memory_region(e820_map, &e820_nr_map,
+                                         md->PhysicalStart,
+                                         md->NumberOfPages << EFI_PAGE_SHIFT,
+                                         E820_ACPI);
                        break;
                case EfiRuntimeServicesCode:
-                       e820_map->addr = md->PhysicalStart;
-                       e820_map->size = md->NumberOfPages << EFI_PAGE_SHIFT;
-                       e820_map->type = E820_EXEC_CODE;
+                       add_memory_region(e820_map, &e820_nr_map,
+                                         md->PhysicalStart,
+                                         md->NumberOfPages << EFI_PAGE_SHIFT,
+                                         E820_EXEC_CODE);
                        break;
                case EfiRuntimeServicesData:
                case EfiReservedMemoryType:
@@ -357,9 +387,10 @@ void fill_e820map(boot_params_t *bp, mmap_desc_t *mdesc)
                case EfiMemoryMappedIOPortSpace:
                case EfiUnusableMemory:
                case EfiPalCode:
-                       e820_map->addr = md->PhysicalStart;
-                       e820_map->size = md->NumberOfPages << EFI_PAGE_SHIFT;
-                       e820_map->type = E820_RESERVED;
+                       add_memory_region(e820_map, &e820_nr_map,
+                                         md->PhysicalStart,
+                                         md->NumberOfPages << EFI_PAGE_SHIFT,
+                                         E820_RESERVED);
                        break;
                case EfiLoaderCode:
                case EfiLoaderData:
@@ -375,10 +406,11 @@ void fill_e820map(boot_params_t *bp, mmap_desc_t *mdesc)
                                        /* start < 640K
                                         * set memory map from start to 640K
                                         */
-                                       e820_map->addr = start;
-                                       e820_map->size = 0xA0000ULL-start;
-                                       e820_map->type = E820_RAM;
-                                       e820_map++;
+                                       add_memory_region(e820_map,
+                                                         &e820_nr_map,
+                                                         start,
+                                                         0xA0000ULL-start,
+                                                         E820_RAM);
                                }
                                if (end <= 0x100000ULL)
                                        continue;
@@ -388,27 +420,28 @@ void fill_e820map(boot_params_t *bp, mmap_desc_t *mdesc)
                                start = 0x100000ULL;
                                size = end - start;
                        }
-                       e820_map->addr = start;
-                       e820_map->size = size;
-                       e820_map->type = E820_RAM;
+                       add_memory_region(e820_map, &e820_nr_map,
+                                         start, size, E820_RAM);
                        break;
                case EfiACPIMemoryNVS:
-                       e820_map->addr = md->PhysicalStart;
-                       e820_map->size = md->NumberOfPages << EFI_PAGE_SHIFT;
-                       e820_map->type = E820_NVS;
+                       add_memory_region(e820_map, &e820_nr_map,
+                                         md->PhysicalStart,
+                                         md->NumberOfPages << EFI_PAGE_SHIFT,
+                                         E820_NVS);
                        break;
                default:
                        /* We should not hit this case */
-                       e820_map->addr = md->PhysicalStart;
-                       size = md->NumberOfPages << EFI_PAGE_SHIFT;
-                       e820_map->type = E820_RESERVED;
+                       add_memory_region(e820_map, &e820_nr_map,
+                                         md->PhysicalStart,
+                                         md->NumberOfPages << EFI_PAGE_SHIFT,
+                                         E820_RESERVED);
                        break;
                }
-               e820_map++;
                p = NextMemoryDescriptor(p, mdesc->desc_size); 
        }
-       
+       bp->s.e820_nrmap = e820_nr_map;
 }
+
 /*
  * x86_64 specific boot parameters initialization routine
  */
@@ -430,7 +463,7 @@ sysdeps_create_boot_params(
        DBG_PRT((L"fill_boot_params()\n"));
 
        if (!bp || !cmdline || !initrd || !cookie) {
-               ERR_PRT((L"bp=0x%x  cmdline=0x%x  initrd=0x%x cookie=0x%x",
+               ERR_PRT((L"bp="PTR_FMT"  cmdline="PTR_FMT"  initrd="PTR_FMT" cookie="PTR_FMT"",
                        bp, cmdline, initrd, cookie));
 
                if (param_start != NULL) {
@@ -464,10 +497,10 @@ sysdeps_create_boot_params(
         */
        bp->s.unused_1 = 0;
        bp->s.unused_2 = 0;
-       ZeroMem(bp->s.unused_3, sizeof bp->s.unused_3);
-       ZeroMem(bp->s.unused_4, sizeof bp->s.unused_4);
-       ZeroMem(bp->s.unused_51, sizeof bp->s.unused_51);
-       ZeroMem(bp->s.unused_52, sizeof bp->s.unused_52);
+       ZeroMem(&bp->s.unused_3, sizeof bp->s.unused_3);
+       ZeroMem(&bp->s.unused_4, sizeof bp->s.unused_4);
+       ZeroMem(&bp->s.unused_51, sizeof bp->s.unused_51);
+       ZeroMem(&bp->s.unused_52, sizeof bp->s.unused_52);
        bp->s.unused_6 = 0;
        bp->s.unused_7 = 0;
        ZeroMem(bp->s.unused_8, sizeof bp->s.unused_8);
@@ -517,7 +550,7 @@ sysdeps_create_boot_params(
         * Initial RAMdisk and root device stuff.
         */
 
-       DBG_PRT((L"initrd->start_addr=0x%x  initrd->pgcnt=%d\n",
+       DBG_PRT((L"initrd->start_addr="PTR_FMT"  initrd->pgcnt=%d\n",
                initrd->start_addr, initrd->pgcnt));
 
        /* These RAMdisk flags are not needed, just zero them. */
@@ -525,7 +558,7 @@ sysdeps_create_boot_params(
 
        if (initrd->start_addr && initrd->pgcnt) {
                /* %%TBD - This will probably have to be changed. */
-               bp->s.initrd_start = (UINT32)initrd->start_addr;
+               bp->s.initrd_start = (UINT32)(UINT64)initrd->start_addr;
                bp->s.initrd_size = (UINT32)(initrd->size);
                /*
                 * This is the RAMdisk root device for RedHat 2.2.x
@@ -564,12 +597,12 @@ sysdeps_create_boot_params(
        /*
         * EFI loader signature 
         */
-       CopyMem(bp->s.efi_loader_sig, EFI_LOADER_SIG, 4);
+       CopyMem(bp->s.efi_loader_sig, EFI_LOADER_SIG_X64, 4);
 
        /*
         * Kernel entry point.
         */
-       bp->s.kernel_start = (UINT32)kernel_start;
+       bp->s.kernel_start = (UINT32)(UINT64)kernel_start;
 
        /*
         * When changing stuff in the parameter structure compare
@@ -647,14 +680,14 @@ sysdeps_create_boot_params(
                CHECK_OFFSET(hd1_info, 0x90, L"");
                CHECK_OFFSET(mca_info_len, 0xA0, L"%xh");
                CHECK_OFFSET(mca_info_buf, 0xA2, L"");
-               CHECK_OFFSET(efi_sys_tbl, 0x1B8, L"%xh");
                CHECK_OFFSET(efi_loader_sig, 0x1C0, L"'%-4.4a'");
-               CHECK_OFFSET(efi_mem_desc_size, 0x1C4, L"%xh");
-               CHECK_OFFSET(efi_mem_desc_ver, 0x1C8, L"%xh");
-               CHECK_OFFSET(efi_mem_map_size, 0x1CC, L"%xh");
+               CHECK_OFFSET(efi_sys_tbl, 0x1C4, L"%xh");
+               CHECK_OFFSET(efi_mem_desc_size, 0x1C8, L"%xh");
+               CHECK_OFFSET(efi_mem_desc_ver, 0x1CC, L"%xh");
                CHECK_OFFSET(efi_mem_map, 0x1D0, L"%xh");
-               CHECK_OFFSET(loader_start, 0x1D8, L"%xh");
-               CHECK_OFFSET(loader_size, 0x1DC, L"%xh");
+               CHECK_OFFSET(efi_mem_map_size, 0x1D4, L"%xh");
+               CHECK_OFFSET(efi_sys_tbl_hi, 0x1D8, L"%xh");
+               CHECK_OFFSET(efi_mem_map_hi, 0x1DC, L"%xh");
                CHECK_OFFSET(alt_mem_k, 0x1E0, L"%xh");
                CHECK_OFFSET(setup_sectors, 0x1F1, L"%xh");
                CHECK_OFFSET(mount_root_rdonly, 0x1F2, L"%xh");
@@ -758,11 +791,13 @@ do_memmap:
                return -1;
        }
        *cookie = mdesc.cookie;
-       bp->s.efi_mem_map = (UINTN)mdesc.md;
+       bp->s.efi_mem_map = (UINT32)(unsigned long)mdesc.md;
        bp->s.efi_mem_map_size = mdesc.map_size;
        bp->s.efi_mem_desc_size = mdesc.desc_size;
        bp->s.efi_mem_desc_ver = mdesc.desc_version;
-       bp->s.efi_sys_tbl = (UINTN)systab;
+       bp->s.efi_sys_tbl = (UINT32)(unsigned long)systab;
+       bp->s.efi_mem_map_hi = (unsigned long)mdesc.md >> 32;
+       bp->s.efi_sys_tbl_hi = (unsigned long)systab >> 32;
        /* Now that we have EFI memory map, convert it to E820 map 
         * and update the bootparam accordingly
         */