1 /** @file 2 * 3 * Copyright (c) 2011-2015, ARM Limited. All rights reserved. 4 * Copyright (c) 2014 - 2016, AMD Inc. All rights reserved. 5 * 6 * This program and the accompanying materials 7 * are licensed and made available under the terms and conditions of the BSD License 8 * which accompanies this distribution. The full text of the license may be found at 9 * http://opensource.org/licenses/bsd-license.php 10 * 11 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 13 * 14 **/ 15 /** 16 17 Derived from: 18 ArmPkg/Application/LinuxLoader/LinuxLoaderHelper.c 19 20 **/ 21 22 23 #include <PiDxe.h> 24 #include <Library/HobLib.h> 25 #include <Library/TimerLib.h> 26 #include <Library/SerialPortLib.h> 27 28 #include "LinuxLoader.h" 29 30 STATIC CONST CHAR8 *mTokenList[] = { 31 /*"SEC",*/ 32 "PEI", 33 "DXE", 34 "BDS", 35 NULL 36 }; 37 38 VOID 39 PrintPerformance ( 40 VOID 41 ) 42 { 43 UINTN Key; 44 CONST VOID *Handle; 45 CONST CHAR8 *Token, *Module; 46 UINT64 Start, Stop, TimeStamp; 47 UINT64 Delta, TicksPerSecond, Milliseconds; 48 UINTN Index; 49 CHAR8 Buffer[100]; 50 UINTN CharCount; 51 BOOLEAN CountUp; 52 53 TicksPerSecond = GetPerformanceCounterProperties (&Start, &Stop); 54 if (Start < Stop) { 55 CountUp = TRUE; 56 } else { 57 CountUp = FALSE; 58 } 59 60 TimeStamp = 0; 61 Key = 0; 62 do { 63 Key = GetPerformanceMeasurement (Key, (CONST VOID **)&Handle, &Token, &Module, &Start, &Stop); 64 if (Key != 0) { 65 for (Index = 0; mTokenList[Index] != NULL; Index++) { 66 if (AsciiStriCmp (mTokenList[Index], Token) == 0) { 67 Delta = CountUp ? (Stop - Start) : (Start - Stop); 68 TimeStamp += Delta; 69 Milliseconds = DivU64x64Remainder (MultU64x32 (Delta, 1000), TicksPerSecond, NULL); 70 CharCount = AsciiSPrint (Buffer, sizeof (Buffer), "%6a %6ld ms\n", Token, Milliseconds); 71 SerialPortWrite ((UINT8 *) Buffer, CharCount); 72 break; 73 } 74 } 75 } 76 } while (Key != 0); 77 78 CharCount = AsciiSPrint (Buffer, sizeof (Buffer), "Total Time = %ld ms\n\n", 79 DivU64x64Remainder (MultU64x32 (TimeStamp, 1000), TicksPerSecond, NULL)); 80 SerialPortWrite ((UINT8 *) Buffer, CharCount); 81 } 82 83 STATIC 84 EFI_STATUS 85 InsertSystemMemoryResources ( 86 LIST_ENTRY *ResourceList, 87 EFI_HOB_RESOURCE_DESCRIPTOR *ResHob 88 ) 89 { 90 SYSTEM_MEMORY_RESOURCE *NewResource; 91 LIST_ENTRY *Link; 92 LIST_ENTRY *NextLink; 93 LIST_ENTRY AttachedResources; 94 SYSTEM_MEMORY_RESOURCE *Resource; 95 EFI_PHYSICAL_ADDRESS NewResourceEnd; 96 97 if (IsListEmpty (ResourceList)) { 98 NewResource = AllocateZeroPool (sizeof (SYSTEM_MEMORY_RESOURCE)); 99 NewResource->PhysicalStart = ResHob->PhysicalStart; 100 NewResource->ResourceLength = ResHob->ResourceLength; 101 InsertTailList (ResourceList, &NewResource->Link); 102 return EFI_SUCCESS; 103 } 104 105 InitializeListHead (&AttachedResources); 106 107 Link = ResourceList->ForwardLink; 108 ASSERT (Link != NULL); 109 while (Link != ResourceList) { 110 Resource = (SYSTEM_MEMORY_RESOURCE*)Link; 111 112 // Sanity Check. The resources should not overlapped. 113 ASSERT (!((ResHob->PhysicalStart >= Resource->PhysicalStart) && (ResHob->PhysicalStart < (Resource->PhysicalStart + Resource->ResourceLength)))); 114 ASSERT (!((ResHob->PhysicalStart + ResHob->ResourceLength - 1 >= Resource->PhysicalStart) && 115 ((ResHob->PhysicalStart + ResHob->ResourceLength - 1) < (Resource->PhysicalStart + Resource->ResourceLength)))); 116 117 // The new resource is attached after this resource descriptor 118 if (ResHob->PhysicalStart == Resource->PhysicalStart + Resource->ResourceLength) { 119 Resource->ResourceLength = Resource->ResourceLength + ResHob->ResourceLength; 120 121 NextLink = RemoveEntryList (&Resource->Link); 122 InsertTailList (&AttachedResources, &Resource->Link); 123 Link = NextLink; 124 } 125 // The new resource is attached before this resource descriptor 126 else if (ResHob->PhysicalStart + ResHob->ResourceLength == Resource->PhysicalStart) { 127 Resource->PhysicalStart = ResHob->PhysicalStart; 128 Resource->ResourceLength = Resource->ResourceLength + ResHob->ResourceLength; 129 130 NextLink = RemoveEntryList (&Resource->Link); 131 InsertTailList (&AttachedResources, &Resource->Link); 132 Link = NextLink; 133 } else { 134 Link = Link->ForwardLink; 135 } 136 } 137 138 if (!IsListEmpty (&AttachedResources)) { 139 // See if we can merge the attached resource with other resources 140 141 NewResource = (SYSTEM_MEMORY_RESOURCE*)GetFirstNode (&AttachedResources); 142 Link = RemoveEntryList (&NewResource->Link); 143 while (!IsListEmpty (&AttachedResources)) { 144 // Merge resources 145 Resource = (SYSTEM_MEMORY_RESOURCE*)Link; 146 147 // Ensure they overlap each other 148 ASSERT ( 149 ((NewResource->PhysicalStart >= Resource->PhysicalStart) && (NewResource->PhysicalStart < (Resource->PhysicalStart + Resource->ResourceLength))) || 150 (((NewResource->PhysicalStart + NewResource->ResourceLength) >= Resource->PhysicalStart) && ((NewResource->PhysicalStart + NewResource->ResourceLength) < (Resource->PhysicalStart + Resource->ResourceLength))) 151 ); 152 153 NewResourceEnd = MAX (NewResource->PhysicalStart + NewResource->ResourceLength, Resource->PhysicalStart + Resource->ResourceLength); 154 NewResource->PhysicalStart = MIN (NewResource->PhysicalStart, Resource->PhysicalStart); 155 NewResource->ResourceLength = NewResourceEnd - NewResource->PhysicalStart; 156 157 Link = RemoveEntryList (Link); 158 } 159 } else { 160 // None of the Resource of the list is attached to this ResHob. Create a new entry for it 161 NewResource = AllocateZeroPool (sizeof (SYSTEM_MEMORY_RESOURCE)); 162 NewResource->PhysicalStart = ResHob->PhysicalStart; 163 NewResource->ResourceLength = ResHob->ResourceLength; 164 } 165 InsertTailList (ResourceList, &NewResource->Link); 166 return EFI_SUCCESS; 167 } 168 169 EFI_STATUS 170 GetSystemMemoryResources ( 171 IN LIST_ENTRY *ResourceList 172 ) 173 { 174 EFI_HOB_RESOURCE_DESCRIPTOR *ResHob; 175 176 InitializeListHead (ResourceList); 177 178 // Find the first System Memory Resource Descriptor 179 ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR); 180 while ((ResHob != NULL) && (ResHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY)) { 181 ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, (VOID *)((UINTN)ResHob + ResHob->Header.HobLength)); 182 } 183 184 // Did not find any 185 if (ResHob == NULL) { 186 return EFI_NOT_FOUND; 187 } else { 188 InsertSystemMemoryResources (ResourceList, ResHob); 189 } 190 191 ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, (VOID *)((UINTN)ResHob + ResHob->Header.HobLength)); 192 while (ResHob != NULL) { 193 if (ResHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) { 194 InsertSystemMemoryResources (ResourceList, ResHob); 195 } 196 ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, (VOID *)((UINTN)ResHob + ResHob->Header.HobLength)); 197 } 198 199 return EFI_SUCCESS; 200 } 201