Author: emaste
Date: Thu Mar 27 18:23:02 2014
New Revision: 263822
URL: http://svnweb.freebsd.org/changeset/base/263822

Log:
  amd64: Parse the EFI memory map if present
  
  With this change (and loader.efi from the projects/uefi branch) we can now
  boot under qemu using the OVMF UEFI firmware image with the limitation
  that a serial console is required.
  
  (This is largely r246337 from the projects/uefi branch.)
  
  Sponsored by: The FreeBSD Foundation

Modified:
  head/sys/amd64/amd64/machdep.c
  head/sys/amd64/include/metadata.h

Modified: head/sys/amd64/amd64/machdep.c
==============================================================================
--- head/sys/amd64/amd64/machdep.c      Thu Mar 27 16:55:12 2014        
(r263821)
+++ head/sys/amd64/amd64/machdep.c      Thu Mar 27 18:23:02 2014        
(r263822)
@@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/callout.h>
 #include <sys/cons.h>
 #include <sys/cpu.h>
+#include <sys/efi.h>
 #include <sys/eventhandler.h>
 #include <sys/exec.h>
 #include <sys/imgact.h>
@@ -1431,10 +1432,105 @@ bios_add_smap_entries(struct bios_smap *
        }
 }
 
+#define efi_next_descriptor(ptr, size) \
+       ((struct efi_md *)(((uint8_t *) ptr) + size))
+
+static void
+add_efi_map_entries(struct efi_map_header *efihdr, vm_paddr_t *physmap,
+    int *physmap_idx)
+{
+       struct efi_md *map, *p;
+       const char *type;
+       size_t efisz;
+       int ndesc, i;
+
+       static const char *types[] = {
+               "Reserved",
+               "LoaderCode",
+               "LoaderData",
+               "BootServicesCode",
+               "BootServicesData",
+               "RuntimeServicesCode",
+               "RuntimeServicesData",
+               "ConventionalMemory",
+               "UnusableMemory",
+               "ACPIReclaimMemory",
+               "ACPIMemoryNVS",
+               "MemoryMappedIO",
+               "MemoryMappedIOPortSpace",
+               "PalCode"
+       };
+
+       /*
+        * Memory map data provided by UEFI via the GetMemoryMap
+        * Boot Services API.
+        */
+       efisz = (sizeof(struct efi_map_header) + 0xf) & ~0xf;
+       map = (struct efi_md *)((uint8_t *)efihdr + efisz); 
+
+       if (efihdr->descriptor_size == 0)
+               return;
+       ndesc = efihdr->memory_size / efihdr->descriptor_size;
+
+       if (boothowto & RB_VERBOSE)
+               printf("%23s %12s %12s %8s %4s\n",
+                   "Type", "Physical", "Virtual", "#Pages", "Attr");
+
+       for (i = 0, p = map; i < ndesc; i++,
+           p = efi_next_descriptor(p, efihdr->descriptor_size)) {
+               if (boothowto & RB_VERBOSE) {
+                       if (p->md_type <= EFI_MD_TYPE_PALCODE)
+                               type = types[p->md_type];
+                       else
+                               type = "<INVALID>";
+                       printf("%23s %012lx %12p %08lx ", type, p->md_phys,
+                           p->md_virt, p->md_pages);
+                       if (p->md_attr & EFI_MD_ATTR_UC)
+                               printf("UC ");
+                       if (p->md_attr & EFI_MD_ATTR_WC)
+                               printf("WC ");
+                       if (p->md_attr & EFI_MD_ATTR_WT)
+                               printf("WT ");
+                       if (p->md_attr & EFI_MD_ATTR_WB)
+                               printf("WB ");
+                       if (p->md_attr & EFI_MD_ATTR_UCE)
+                               printf("UCE ");
+                       if (p->md_attr & EFI_MD_ATTR_WP)
+                               printf("WP ");
+                       if (p->md_attr & EFI_MD_ATTR_RP)
+                               printf("RP ");
+                       if (p->md_attr & EFI_MD_ATTR_XP)
+                               printf("XP ");
+                       if (p->md_attr & EFI_MD_ATTR_RT)
+                               printf("RUNTIME");
+                       printf("\n");
+               }
+
+               switch (p->md_type) {
+               case EFI_MD_TYPE_CODE:
+               case EFI_MD_TYPE_DATA:
+               case EFI_MD_TYPE_BS_CODE:
+               case EFI_MD_TYPE_BS_DATA:
+               case EFI_MD_TYPE_FREE:
+                       /*
+                        * We're allowed to use any entry with these types.
+                        */
+                       break;
+               default:
+                       continue;
+               }
+
+               if (!add_physmap_entry(p->md_phys, (p->md_pages * PAGE_SIZE),
+                   physmap, physmap_idx))
+                       break;
+       }
+}
+
 static void
 native_parse_memmap(caddr_t kmdp, vm_paddr_t *physmap, int *physmap_idx)
 {
        struct bios_smap *smap;
+       struct efi_map_header *efihdr;
        u_int32_t size;
 
        /*
@@ -1445,13 +1541,19 @@ native_parse_memmap(caddr_t kmdp, vm_pad
         * ie: an int32_t immediately precedes smap.
         */
 
+       efihdr = (struct efi_map_header *)preload_search_info(kmdp,
+           MODINFO_METADATA | MODINFOMD_EFI_MAP);
        smap = (struct bios_smap *)preload_search_info(kmdp,
            MODINFO_METADATA | MODINFOMD_SMAP);
-       if (smap == NULL)
-               panic("No BIOS smap info from loader!");
-       size = *((u_int32_t *)smap - 1);
+       if (efihdr == NULL && smap == NULL)
+               panic("No BIOS smap or EFI map info from loader!");
 
-       bios_add_smap_entries(smap, size, physmap, physmap_idx);
+       if (efihdr != NULL) {
+               add_efi_map_entries(efihdr, physmap, physmap_idx);
+       } else {
+               size = *((u_int32_t *)smap - 1);
+               bios_add_smap_entries(smap, size, physmap, physmap_idx);
+       }
 }
 
 /*

Modified: head/sys/amd64/include/metadata.h
==============================================================================
--- head/sys/amd64/include/metadata.h   Thu Mar 27 16:55:12 2014        
(r263821)
+++ head/sys/amd64/include/metadata.h   Thu Mar 27 18:23:02 2014        
(r263822)
@@ -32,5 +32,12 @@
 #define        MODINFOMD_SMAP          0x1001
 #define        MODINFOMD_SMAP_XATTR    0x1002
 #define        MODINFOMD_DTBP          0x1003
+#define        MODINFOMD_EFI_MAP       0x1004
+
+struct efi_map_header {                                                        
+       size_t          memory_size;
+       size_t          descriptor_size;
+       uint32_t        descriptor_version;
+};
 
 #endif /* !_MACHINE_METADATA_H_ */
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to