Home | History | Annotate | Download | only in EfiLdr
      1 /*++
      2 
      3 Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
      4 This program and the accompanying materials
      5 are licensed and made available under the terms and conditions of the BSD License
      6 which accompanies this distribution.  The full text of the license may be found at
      7 http://opensource.org/licenses/bsd-license.php
      8 
      9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     11 
     12 Module Name:
     13   Support.c
     14 
     15 Abstract:
     16 
     17 Revision History:
     18 
     19 --*/
     20 #include "EfiLdr.h"
     21 
     22 EFI_STATUS
     23 EfiAddMemoryDescriptor(
     24   UINTN                 *NoDesc,
     25   EFI_MEMORY_DESCRIPTOR *Desc,
     26   EFI_MEMORY_TYPE       Type,
     27   EFI_PHYSICAL_ADDRESS  BaseAddress,
     28   UINT64                NoPages,
     29   UINT64                Attribute
     30   )
     31 {
     32   UINTN  NumberOfDesc;
     33   UINT64 Temp;
     34   UINTN  Index;
     35 
     36   if (NoPages == 0) {
     37     return EFI_SUCCESS;
     38   }
     39 
     40   //
     41   // See if the new memory descriptor needs to be carved out of an existing memory descriptor
     42   //
     43 
     44   NumberOfDesc = *NoDesc;
     45   for (Index = 0; Index < NumberOfDesc; Index++) {
     46 
     47     if (Desc[Index].Type == EfiConventionalMemory) {
     48 
     49       Temp = DivU64x32 ((BaseAddress - Desc[Index].PhysicalStart), EFI_PAGE_SIZE) + NoPages;
     50 
     51       if ((Desc[Index].PhysicalStart < BaseAddress) && (Desc[Index].NumberOfPages >= Temp)) {
     52         if (Desc[Index].NumberOfPages > Temp) {
     53           Desc[*NoDesc].Type          = EfiConventionalMemory;
     54           Desc[*NoDesc].PhysicalStart = BaseAddress + MultU64x32 (NoPages, EFI_PAGE_SIZE);
     55           Desc[*NoDesc].NumberOfPages = Desc[Index].NumberOfPages - Temp;
     56           Desc[*NoDesc].VirtualStart  = 0;
     57           Desc[*NoDesc].Attribute     = Desc[Index].Attribute;
     58           *NoDesc = *NoDesc + 1;
     59         }
     60         Desc[Index].NumberOfPages = Temp - NoPages;
     61       }
     62 
     63       if ((Desc[Index].PhysicalStart == BaseAddress) && (Desc[Index].NumberOfPages == NoPages)) {
     64         Desc[Index].Type      = Type;
     65         Desc[Index].Attribute = Attribute;
     66         return EFI_SUCCESS;
     67       }
     68 
     69       if ((Desc[Index].PhysicalStart == BaseAddress) && (Desc[Index].NumberOfPages > NoPages)) {
     70         Desc[Index].NumberOfPages -= NoPages;
     71         Desc[Index].PhysicalStart += MultU64x32 (NoPages, EFI_PAGE_SIZE);
     72       }
     73     }
     74   }
     75 
     76   //
     77   // Add the new memory descriptor
     78   //
     79 
     80   Desc[*NoDesc].Type          = Type;
     81   Desc[*NoDesc].PhysicalStart = BaseAddress;
     82   Desc[*NoDesc].NumberOfPages = NoPages;
     83   Desc[*NoDesc].VirtualStart  = 0;
     84   Desc[*NoDesc].Attribute     = Attribute;
     85   *NoDesc = *NoDesc + 1;
     86 
     87   return EFI_SUCCESS;
     88 }
     89 
     90 UINTN
     91 FindSpace (
     92   UINTN                       NoPages,
     93   IN UINTN                    *NumberOfMemoryMapEntries,
     94   IN EFI_MEMORY_DESCRIPTOR    *EfiMemoryDescriptor,
     95   EFI_MEMORY_TYPE             Type,
     96   UINT64                      Attribute
     97   )
     98 {
     99   EFI_PHYSICAL_ADDRESS        MaxPhysicalStart;
    100   UINT64                      MaxNoPages;
    101   UINTN                       Index;
    102   EFI_MEMORY_DESCRIPTOR       *CurrentMemoryDescriptor;
    103 
    104   MaxPhysicalStart = 0;
    105   MaxNoPages       = 0;
    106   CurrentMemoryDescriptor = NULL;
    107   for (Index = 0; Index < *NumberOfMemoryMapEntries; Index++) {
    108     if (EfiMemoryDescriptor[Index].PhysicalStart + LShiftU64(EfiMemoryDescriptor[Index].NumberOfPages, EFI_PAGE_SHIFT) <= 0x100000) {
    109       continue;
    110     }
    111     if ((EfiMemoryDescriptor[Index].Type == EfiConventionalMemory) &&
    112         (EfiMemoryDescriptor[Index].NumberOfPages >= NoPages)) {
    113       if (EfiMemoryDescriptor[Index].PhysicalStart > MaxPhysicalStart) {
    114         if (EfiMemoryDescriptor[Index].PhysicalStart + LShiftU64(EfiMemoryDescriptor[Index].NumberOfPages, EFI_PAGE_SHIFT) <= 0x100000000ULL) {
    115           MaxPhysicalStart = EfiMemoryDescriptor[Index].PhysicalStart;
    116           MaxNoPages       = EfiMemoryDescriptor[Index].NumberOfPages;
    117           CurrentMemoryDescriptor = &EfiMemoryDescriptor[Index];
    118         }
    119       }
    120     }
    121     if ((EfiMemoryDescriptor[Index].Type == EfiReservedMemoryType) ||
    122         (EfiMemoryDescriptor[Index].Type >= EfiACPIReclaimMemory) ) {
    123       continue;
    124     }
    125     if ((EfiMemoryDescriptor[Index].Type == EfiRuntimeServicesCode) ||
    126         (EfiMemoryDescriptor[Index].Type == EfiRuntimeServicesData)) {
    127       break;
    128     }
    129   }
    130 
    131   if (MaxPhysicalStart == 0) {
    132     return 0;
    133   }
    134 
    135   if (MaxNoPages != NoPages) {
    136     CurrentMemoryDescriptor->NumberOfPages = MaxNoPages - NoPages;
    137     EfiMemoryDescriptor[*NumberOfMemoryMapEntries].Type          = Type;
    138     EfiMemoryDescriptor[*NumberOfMemoryMapEntries].PhysicalStart = MaxPhysicalStart + LShiftU64(MaxNoPages - NoPages, EFI_PAGE_SHIFT);
    139     EfiMemoryDescriptor[*NumberOfMemoryMapEntries].NumberOfPages = NoPages;
    140     EfiMemoryDescriptor[*NumberOfMemoryMapEntries].VirtualStart  = 0;
    141     EfiMemoryDescriptor[*NumberOfMemoryMapEntries].Attribute     = Attribute;
    142     *NumberOfMemoryMapEntries = *NumberOfMemoryMapEntries + 1;
    143   } else {
    144     CurrentMemoryDescriptor->Type      = Type;
    145     CurrentMemoryDescriptor->Attribute = Attribute;
    146   }
    147 
    148   return (UINTN)(MaxPhysicalStart + LShiftU64(MaxNoPages - NoPages, EFI_PAGE_SHIFT));
    149 }
    150 
    151 VOID
    152 GenMemoryMap (
    153   UINTN                 *NumberOfMemoryMapEntries,
    154   EFI_MEMORY_DESCRIPTOR *EfiMemoryDescriptor,
    155   BIOS_MEMORY_MAP       *BiosMemoryMap
    156   )
    157 {
    158   UINT64                BaseAddress;
    159   UINT64                Length;
    160   EFI_MEMORY_TYPE       Type;
    161   UINTN                 Index;
    162   UINTN                 Attr;
    163   UINT64                Ceiling;
    164 
    165   Ceiling = 0xFFFFFFFF;
    166   for (Index = 0; Index < BiosMemoryMap->MemoryMapSize / sizeof(BIOS_MEMORY_MAP_ENTRY); Index++) {
    167 
    168     switch (BiosMemoryMap->MemoryMapEntry[Index].Type) {
    169     case (INT15_E820_AddressRangeMemory):
    170       Type = EfiConventionalMemory;
    171       Attr = EFI_MEMORY_WB;
    172       break;
    173     case (INT15_E820_AddressRangeReserved):
    174       Type = EfiReservedMemoryType;
    175       Attr = EFI_MEMORY_UC;
    176       break;
    177     case (INT15_E820_AddressRangeACPI):
    178       Type = EfiACPIReclaimMemory;
    179       Attr = EFI_MEMORY_WB;
    180       break;
    181     case (INT15_E820_AddressRangeNVS):
    182       Type = EfiACPIMemoryNVS;
    183       Attr = EFI_MEMORY_UC;
    184       break;
    185     default:
    186       // We should not get here, according to ACPI 2.0 Spec.
    187       // BIOS behaviour of the Int15h, E820h
    188       Type = EfiReservedMemoryType;
    189       Attr = EFI_MEMORY_UC;
    190       break;
    191     }
    192     if (Type == EfiConventionalMemory) {
    193       BaseAddress = BiosMemoryMap->MemoryMapEntry[Index].BaseAddress;
    194       Length      = BiosMemoryMap->MemoryMapEntry[Index].Length;
    195       if (BaseAddress & EFI_PAGE_MASK) {
    196         Length      = Length + (BaseAddress & EFI_PAGE_MASK) - EFI_PAGE_SIZE;
    197         BaseAddress = LShiftU64 (RShiftU64 (BaseAddress, EFI_PAGE_SHIFT) + 1, EFI_PAGE_SHIFT);
    198       }
    199     } else {
    200       BaseAddress = BiosMemoryMap->MemoryMapEntry[Index].BaseAddress;
    201       Length      = BiosMemoryMap->MemoryMapEntry[Index].Length + (BaseAddress & EFI_PAGE_MASK);
    202       BaseAddress = LShiftU64 (RShiftU64 (BaseAddress, EFI_PAGE_SHIFT), EFI_PAGE_SHIFT);
    203       if (Length & EFI_PAGE_MASK) {
    204         Length = LShiftU64 (RShiftU64 (Length, EFI_PAGE_SHIFT) + 1, EFI_PAGE_SHIFT);
    205       }
    206       //
    207       // Update Memory Ceiling
    208       //
    209       if ((BaseAddress >= 0x100000) && (BaseAddress < 0x100000000ULL)) {
    210         if (Ceiling > BaseAddress) {
    211           Ceiling = BaseAddress;
    212         }
    213       }
    214     }
    215     EfiAddMemoryDescriptor (
    216       NumberOfMemoryMapEntries,
    217       EfiMemoryDescriptor,
    218       Type,
    219       (EFI_PHYSICAL_ADDRESS)BaseAddress,
    220       RShiftU64 (Length, EFI_PAGE_SHIFT),
    221       Attr
    222       );
    223   }
    224 
    225   //
    226   // Update MemoryMap according to Ceiling
    227   //
    228   for (Index = 0; Index < *NumberOfMemoryMapEntries; Index++) {
    229     if ((EfiMemoryDescriptor[Index].Type == EfiConventionalMemory) &&
    230         (EfiMemoryDescriptor[Index].PhysicalStart > 0x100000) &&
    231         (EfiMemoryDescriptor[Index].PhysicalStart < 0x100000000ULL)) {
    232       if (EfiMemoryDescriptor[Index].PhysicalStart >= Ceiling) {
    233         EfiMemoryDescriptor[Index].Type = EfiReservedMemoryType;
    234       }
    235     }
    236   }
    237 }
    238