acpi.c 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511
  1. /*++
  2. Copyright (c) 2014 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. acpi.c
  9. Abstract:
  10. This module implements support for installing ACPI tables into the EFI
  11. system table.
  12. Author:
  13. Evan Green 25-Mar-2014
  14. Environment:
  15. Firmware
  16. --*/
  17. //
  18. // ------------------------------------------------------------------- Includes
  19. //
  20. #include "ueficore.h"
  21. #include "efiimg.h"
  22. #include "fwvol.h"
  23. #include "fv2.h"
  24. #include <minoca/fw/acpitabs.h>
  25. #include <minoca/uefi/guid/acpi.h>
  26. //
  27. // ---------------------------------------------------------------- Definitions
  28. //
  29. #define EFI_ACPI_TABLE_ENTRY_MAGIC 0x62544145 // 'bTAE'
  30. #define EFI_ACPI_TABLE_EXPANSION_COUNT 0x10
  31. //
  32. // ------------------------------------------------------ Data Type Definitions
  33. //
  34. typedef struct _EFI_ACPI_COMMON_HEADER {
  35. UINT32 Signature;
  36. UINT32 Length;
  37. } EFI_ACPI_COMMON_HEADER, *PEFI_ACPI_COMMON_HEADER;
  38. typedef struct _EFI_ACPI_TABLE_ENTRY {
  39. UINT32 Magic;
  40. LIST_ENTRY ListEntry;
  41. EFI_ACPI_COMMON_HEADER *Table;
  42. EFI_PHYSICAL_ADDRESS PageAddress;
  43. UINTN NumberOfPages;
  44. UINTN Handle;
  45. } EFI_ACPI_TABLE_ENTRY, *PEFI_ACPI_TABLE_ENTRY;
  46. typedef struct _EFI_ACPI_CONTEXT {
  47. LIST_ENTRY TableList;
  48. UINTN CurrentHandle;
  49. UINTN TableCount;
  50. UINTN TableCapacity;
  51. PFADT Fadt;
  52. PFACS Facs;
  53. PRSDP Rsdp;
  54. PRSDT Rsdt;
  55. PXSDT Xsdt;
  56. PDESCRIPTION_HEADER Dsdt;
  57. } EFI_ACPI_CONTEXT, *PEFI_ACPI_CONTEXT;
  58. //
  59. // ----------------------------------------------- Internal Function Prototypes
  60. //
  61. EFI_STATUS
  62. EfipLocateFirmwareVolumeWithAcpiTables (
  63. EFI_FIRMWARE_VOLUME2_PROTOCOL **Instance
  64. );
  65. EFI_STATUS
  66. EfipAcpiInitializeTables (
  67. VOID
  68. );
  69. EFI_STATUS
  70. EfipSetAcpiTable (
  71. VOID *Table,
  72. BOOLEAN Checksum,
  73. UINTN *Handle
  74. );
  75. EFI_STATUS
  76. EfipAddAcpiTableToList (
  77. VOID *Table,
  78. BOOLEAN Checksum,
  79. UINTN *Handle
  80. );
  81. EFI_STATUS
  82. EfipRemoveAcpiTableFromList (
  83. UINTN Handle
  84. );
  85. VOID
  86. EfipAcpiDeleteTable (
  87. PEFI_ACPI_TABLE_ENTRY Table
  88. );
  89. EFI_STATUS
  90. EfipAcpiRemoveTableFromRsdt (
  91. PEFI_ACPI_TABLE_ENTRY Table,
  92. UINTN *TableCount,
  93. PDESCRIPTION_HEADER Rsdt,
  94. PDESCRIPTION_HEADER Xsdt
  95. );
  96. EFI_STATUS
  97. EfipAcpiFindTableByHandle (
  98. UINTN Handle,
  99. PLIST_ENTRY ListHead,
  100. PEFI_ACPI_TABLE_ENTRY *FoundEntry
  101. );
  102. EFI_STATUS
  103. EfipReallocateAcpiTableBuffer (
  104. VOID
  105. );
  106. EFI_STATUS
  107. EfipAcpiPublishTables (
  108. VOID
  109. );
  110. VOID
  111. EfipAcpiChecksumCommonTables (
  112. VOID
  113. );
  114. //
  115. // -------------------------------------------------------------------- Globals
  116. //
  117. EFI_GUID EfiAcpiTable1Guid = EFI_ACPI_10_TABLE_GUID;
  118. EFI_GUID EfiAcpiTableGuid = EFI_ACPI_20_TABLE_GUID;
  119. EFI_GUID EfiAcpiTableStorageFileGuid = EFI_ACPI_TABLE_STORAGE_FILE_GUID;
  120. //
  121. // Define the master EFI ACPI context.
  122. //
  123. EFI_ACPI_CONTEXT EfiAcpiContext;
  124. //
  125. // Define default values to stick in the table header. These can be overridden
  126. // by the platform. Note that once the FADT is installed, the values from that
  127. // header will overwrite values installed here.
  128. //
  129. CHAR8 *EfiAcpiDefaultOemId = "Minoca";
  130. UINT64 EfiAcpiDefaultOemTableId;
  131. UINT32 EfiAcpiDefaultOemRevision;
  132. UINT32 EfiAcpiDefaultCreatorId;
  133. UINT32 EfiAcpiDefaultCreatorRevision;
  134. //
  135. // ------------------------------------------------------------------ Functions
  136. //
  137. EFIAPI
  138. EFI_STATUS
  139. EfiAcpiDriverEntry (
  140. EFI_HANDLE ImageHandle,
  141. EFI_SYSTEM_TABLE *SystemTable
  142. )
  143. /*++
  144. Routine Description:
  145. This routine is the entry point into the ACPI driver.
  146. Arguments:
  147. ImageHandle - Supplies the driver image handle.
  148. SystemTable - Supplies a pointer to the EFI system table.
  149. Return Value:
  150. EFI status code.
  151. --*/
  152. {
  153. EFI_ACPI_COMMON_HEADER *CurrentTable;
  154. EFI_FIRMWARE_VOLUME2_PROTOCOL *FirmwareVolume;
  155. UINT32 FirmwareVolumeStatus;
  156. INTN Instance;
  157. UINTN Size;
  158. EFI_STATUS Status;
  159. UINTN TableHandle;
  160. UINTN TableSize;
  161. CurrentTable = NULL;
  162. Instance = 0;
  163. TableHandle = 0;
  164. Status = EfipAcpiInitializeTables();
  165. if (EFI_ERROR(Status)) {
  166. return Status;
  167. }
  168. Status = EfipLocateFirmwareVolumeWithAcpiTables(&FirmwareVolume);
  169. if (EFI_ERROR(Status)) {
  170. return EFI_SUCCESS;
  171. }
  172. while (Status == EFI_SUCCESS) {
  173. Status = FirmwareVolume->ReadSection(FirmwareVolume,
  174. &EfiAcpiTableStorageFileGuid,
  175. EFI_SECTION_RAW,
  176. Instance,
  177. (VOID **)&CurrentTable,
  178. &Size,
  179. &FirmwareVolumeStatus);
  180. if (!EFI_ERROR(Status)) {
  181. TableHandle = 0;
  182. TableSize = ((EFI_ACPI_COMMON_HEADER *)CurrentTable)->Length;
  183. ASSERT(Size >= TableSize);
  184. EfiAcpiChecksumTable(CurrentTable,
  185. TableSize,
  186. OFFSET_OF(DESCRIPTION_HEADER, Checksum));
  187. Status = EfiAcpiInstallTable(CurrentTable, TableSize, &TableHandle);
  188. EfiFreePool(CurrentTable);
  189. if (EFI_ERROR(Status)) {
  190. return EFI_ABORTED;
  191. }
  192. Instance += 1;
  193. CurrentTable = NULL;
  194. }
  195. }
  196. return EFI_SUCCESS;
  197. }
  198. EFIAPI
  199. EFI_STATUS
  200. EfiAcpiInstallTable (
  201. VOID *AcpiTableBuffer,
  202. UINTN AcpiTableBufferSize,
  203. UINTN *TableKey
  204. )
  205. /*++
  206. Routine Description:
  207. This routine installs an ACPI table into the RSDT/XSDT.
  208. Arguments:
  209. AcpiTableBuffer - Supplies a pointer to the buffer containing the ACPI
  210. table to insert.
  211. AcpiTableBufferSize - Supplies the size in bytes of the ACPI table buffer.
  212. TableKey - Supplies a pointer where a key will be returned that refers
  213. to the table.
  214. Return Value:
  215. EFI status code.
  216. --*/
  217. {
  218. EFI_STATUS Status;
  219. VOID *TableCopy;
  220. ASSERT(EfiAcpiContext.TableList.Next != NULL);
  221. if ((AcpiTableBuffer == NULL) || (TableKey == NULL) ||
  222. (((EFI_ACPI_COMMON_HEADER *)AcpiTableBuffer)->Length !=
  223. AcpiTableBufferSize)) {
  224. return EFI_INVALID_PARAMETER;
  225. }
  226. Status = EfiAllocatePool(EfiBootServicesData,
  227. AcpiTableBufferSize,
  228. (VOID **)&TableCopy);
  229. if (EFI_ERROR(Status)) {
  230. return Status;
  231. }
  232. EfiCopyMem(TableCopy, AcpiTableBuffer, AcpiTableBufferSize);
  233. *TableKey = 0;
  234. Status = EfipSetAcpiTable(TableCopy, TRUE, TableKey);
  235. if (!EFI_ERROR(Status)) {
  236. Status = EfipAcpiPublishTables();
  237. }
  238. EfiFreePool(TableCopy);
  239. return Status;
  240. }
  241. EFIAPI
  242. EFI_STATUS
  243. EfiAcpiUninstallTable (
  244. UINTN TableKey
  245. )
  246. /*++
  247. Routine Description:
  248. This routine uninstalls a previously install ACPI table.
  249. Arguments:
  250. TableKey - Supplies the key returned when the table was installed.
  251. Return Value:
  252. EFI status code.
  253. --*/
  254. {
  255. EFI_STATUS Status;
  256. ASSERT(EfiAcpiContext.TableList.Next != NULL);
  257. Status = EfipSetAcpiTable(NULL, FALSE, &TableKey);
  258. if (!EFI_ERROR(Status)) {
  259. Status = EfipAcpiPublishTables();
  260. }
  261. if (EFI_ERROR(Status)) {
  262. return EFI_NOT_FOUND;
  263. }
  264. return EFI_SUCCESS;
  265. }
  266. EFIAPI
  267. VOID
  268. EfiAcpiChecksumTable (
  269. VOID *Buffer,
  270. UINTN Size,
  271. UINTN ChecksumOffset
  272. )
  273. /*++
  274. Routine Description:
  275. This routine checksums an ACPI table.
  276. Arguments:
  277. Buffer - Supplies a pointer to the table to checksum.
  278. Size - Supplies the size of the table in bytes.
  279. ChecksumOffset - Supplies the offset of the 8 bit checksum field.
  280. Return Value:
  281. None.
  282. --*/
  283. {
  284. UINT8 *Pointer;
  285. UINT8 Sum;
  286. Sum = 0;
  287. Pointer = Buffer;
  288. Pointer[ChecksumOffset] = 0;
  289. while (Size != 0) {
  290. Sum = (UINT8)(Sum + *Pointer);
  291. Pointer += 1;
  292. Size -= 1;
  293. }
  294. Pointer = Buffer;
  295. Pointer[ChecksumOffset] = (UINT8)(0xFF - Sum + 1);
  296. return;
  297. }
  298. //
  299. // --------------------------------------------------------- Internal Functions
  300. //
  301. EFI_STATUS
  302. EfipLocateFirmwareVolumeWithAcpiTables (
  303. EFI_FIRMWARE_VOLUME2_PROTOCOL **Instance
  304. )
  305. /*++
  306. Routine Description:
  307. This routine returns the first instance of the firmware volume protocol
  308. that contains an ACPI table storage file.
  309. Arguments:
  310. Instance - Supplies a pointer where a pointer to the instance will be
  311. returned on success.
  312. Return Value:
  313. EFI status code.
  314. --*/
  315. {
  316. EFI_FV_FILE_ATTRIBUTES Attributes;
  317. EFI_FV_FILETYPE FileType;
  318. UINT32 FirmwareVolumeStatus;
  319. EFI_HANDLE *HandleBuffer;
  320. UINTN HandleCount;
  321. UINTN Index;
  322. UINTN Size;
  323. EFI_STATUS Status;
  324. EFI_FIRMWARE_VOLUME2_PROTOCOL *Volume;
  325. FirmwareVolumeStatus = 0;
  326. //
  327. // Get all the firmware volume handles.
  328. //
  329. Status = EfiLocateHandleBuffer(ByProtocol,
  330. &EfiFirmwareVolume2ProtocolGuid,
  331. NULL,
  332. &HandleCount,
  333. &HandleBuffer);
  334. if (EFI_ERROR(Status)) {
  335. return Status;
  336. }
  337. //
  338. // Loop through all the firmware volume handles looking for an ACPI
  339. // table storage file.
  340. //
  341. for (Index = 0; Index < HandleCount; Index += 1) {
  342. Status = EfiHandleProtocol(HandleBuffer[Index],
  343. &EfiFirmwareVolume2ProtocolGuid,
  344. (VOID **)&Volume);
  345. ASSERT(!EFI_ERROR(Status));
  346. //
  347. // See if it has an ACPI storage file.
  348. //
  349. Status = Volume->ReadFile(Volume,
  350. &EfiAcpiTableStorageFileGuid,
  351. NULL,
  352. &Size,
  353. &FileType,
  354. &Attributes,
  355. &FirmwareVolumeStatus);
  356. if (Status == EFI_SUCCESS) {
  357. *Instance = Volume;
  358. break;
  359. }
  360. }
  361. EfiFreePool(HandleBuffer);
  362. return Status;
  363. }
  364. EFI_STATUS
  365. EfipAcpiInitializeTables (
  366. VOID
  367. )
  368. /*++
  369. Routine Description:
  370. This routine creates the initial RSDP and XSDT tables.
  371. Arguments:
  372. None.
  373. Return Value:
  374. EFI status code.
  375. --*/
  376. {
  377. PEFI_ACPI_CONTEXT Context;
  378. UINT64 CurrentData;
  379. EFI_PHYSICAL_ADDRESS PageAddress;
  380. UINT8 *Pointer;
  381. UINTN RsdpTableSize;
  382. EFI_STATUS Status;
  383. UINTN TotalSize;
  384. Context = &EfiAcpiContext;
  385. INITIALIZE_LIST_HEAD(&(Context->TableList));
  386. Context->CurrentHandle = 1;
  387. RsdpTableSize = sizeof(RSDP);
  388. //
  389. // Allocate space for the initial RSDP below 4GB for 32-bit OSes.
  390. //
  391. PageAddress = 0xFFFFFFFF;
  392. Status = EfiAllocatePages(AllocateMaxAddress,
  393. EfiACPIReclaimMemory,
  394. EFI_SIZE_TO_PAGES(RsdpTableSize),
  395. &PageAddress);
  396. if (EFI_ERROR(Status)) {
  397. return EFI_OUT_OF_RESOURCES;
  398. }
  399. Pointer = (UINT8 *)(UINTN)PageAddress;
  400. EfiSetMem(Pointer, RsdpTableSize, 0);
  401. Context->Rsdp = (PRSDP)Pointer;
  402. //
  403. // Allocate space for the RSDT and XSDT below 4GB, again for historical
  404. // reasons.
  405. //
  406. Context->TableCapacity = EFI_ACPI_TABLE_EXPANSION_COUNT;
  407. TotalSize = sizeof(DESCRIPTION_HEADER) +
  408. (Context->TableCapacity * sizeof(UINT32)) +
  409. sizeof(DESCRIPTION_HEADER) +
  410. (Context->TableCapacity * sizeof(UINT64));
  411. PageAddress = 0xFFFFFFFF;
  412. Status = EfiAllocatePages(AllocateMaxAddress,
  413. EfiACPIReclaimMemory,
  414. EFI_SIZE_TO_PAGES(TotalSize),
  415. &PageAddress);
  416. if (EFI_ERROR(Status)) {
  417. EfiFreePages((EFI_PHYSICAL_ADDRESS)(UINTN)(Context->Rsdp),
  418. EFI_SIZE_TO_PAGES(RsdpTableSize));
  419. return EFI_OUT_OF_RESOURCES;
  420. }
  421. Pointer = (UINT8 *)(UINTN)PageAddress;
  422. EfiSetMem(Pointer, TotalSize, 0);
  423. Context->Rsdt = (PRSDT)Pointer;
  424. Pointer += sizeof(DESCRIPTION_HEADER) +
  425. (Context->TableCapacity * sizeof(UINT32));
  426. Context->Xsdt = (PXSDT)Pointer;
  427. //
  428. // Initialize the RSDP.
  429. //
  430. CurrentData = RSDP_SIGNATURE;
  431. EfiCopyMem(&(Context->Rsdp->Signature), &CurrentData, sizeof(UINT64));
  432. EfiCopyMem(&(Context->Rsdp->OemId),
  433. EfiAcpiDefaultOemId,
  434. sizeof(Context->Rsdp->OemId));
  435. Context->Rsdp->Revision = ACPI_20_RSDP_REVISION;
  436. Context->Rsdp->RsdtAddress = (UINT32)(UINTN)(Context->Rsdt);
  437. Context->Rsdp->Length = sizeof(RSDP);
  438. CurrentData = (UINT64)(UINTN)(Context->Xsdt);
  439. EfiCopyMem(&(Context->Rsdp->XsdtAddress), &CurrentData, sizeof(UINT64));
  440. EfiSetMem(Context->Rsdp->Reserved, sizeof(Context->Rsdp->Reserved), 0);
  441. //
  442. // Initialize the RSDT. Reserve the first entry for the FADT.
  443. //
  444. Context->TableCount = 1;
  445. Context->Rsdt->Header.Length = sizeof(DESCRIPTION_HEADER) + sizeof(UINT32);
  446. Context->Rsdt->Header.Signature = RSDT_SIGNATURE;
  447. Context->Rsdt->Header.Revision = ACPI_30_RSDT_REVISION;
  448. EfiCopyMem(&(Context->Rsdt->Header.OemId),
  449. EfiAcpiDefaultOemId,
  450. sizeof(Context->Rsdt->Header.OemId));
  451. CurrentData = EfiAcpiDefaultOemTableId;
  452. EfiCopyMem(&(Context->Rsdt->Header.OemTableId),
  453. &CurrentData,
  454. sizeof(UINT64));
  455. Context->Rsdt->Header.OemRevision = EfiAcpiDefaultOemRevision;
  456. Context->Rsdt->Header.CreatorId = EfiAcpiDefaultCreatorId;
  457. Context->Rsdt->Header.CreatorRevision = EfiAcpiDefaultCreatorRevision;
  458. //
  459. // Initialize the XSDT, again reserving the first entry for the FADT.
  460. //
  461. Context->TableCount = 1;
  462. Context->Rsdt->Header.Length = sizeof(DESCRIPTION_HEADER) + sizeof(UINT64);
  463. Context->Rsdt->Header.Signature = RSDT_SIGNATURE;
  464. Context->Rsdt->Header.Revision = ACPI_30_XSDT_REVISION;
  465. EfiCopyMem(&(Context->Rsdt->Header.OemId),
  466. EfiAcpiDefaultOemId,
  467. sizeof(Context->Rsdt->Header.OemId));
  468. CurrentData = EfiAcpiDefaultOemTableId;
  469. EfiCopyMem(&(Context->Rsdt->Header.OemTableId),
  470. &CurrentData,
  471. sizeof(UINT64));
  472. Context->Rsdt->Header.OemRevision = EfiAcpiDefaultOemRevision;
  473. Context->Rsdt->Header.CreatorId = EfiAcpiDefaultCreatorId;
  474. Context->Rsdt->Header.CreatorRevision = EfiAcpiDefaultCreatorRevision;
  475. EfipAcpiChecksumCommonTables();
  476. return EFI_SUCCESS;
  477. }
  478. EFI_STATUS
  479. EfipSetAcpiTable (
  480. VOID *Table,
  481. BOOLEAN Checksum,
  482. UINTN *Handle
  483. )
  484. /*++
  485. Routine Description:
  486. This routine adds, removes, or updates ACPI tables. If the address is
  487. not NULL and the handle is NULL, the table is added. If both the address
  488. and the handle is not NULL, the table is updated. If the address is NULL
  489. and the handle is not, the table is deleted.
  490. Arguments:
  491. Table - Supplies an optional pointer to the table to intall. If not
  492. supplied, the table is deleted.
  493. Checksum - Supplies a boolean indicating if the checksum should be
  494. recomputed.
  495. Handle - Supplies a pointer to the handle of the table.
  496. Return Value:
  497. EFI status code.
  498. --*/
  499. {
  500. UINTN SavedHandle;
  501. EFI_STATUS Status;
  502. ASSERT(Handle != NULL);
  503. //
  504. // If there is no handle, add the table.
  505. //
  506. if (*Handle == 0) {
  507. if (Table == NULL) {
  508. return EFI_INVALID_PARAMETER;
  509. }
  510. Status = EfipAddAcpiTableToList(Table, Checksum, Handle);
  511. //
  512. // There is a handle, update or delete the table.
  513. //
  514. } else {
  515. if (Table != NULL) {
  516. Status = EfipRemoveAcpiTableFromList(*Handle);
  517. if (EFI_ERROR(Status)) {
  518. return EFI_ABORTED;
  519. }
  520. //
  521. // Set the handle to replace the table at the same handle.
  522. //
  523. SavedHandle = EfiAcpiContext.CurrentHandle;
  524. EfiAcpiContext.CurrentHandle = *Handle;
  525. Status = EfipAddAcpiTableToList(Table, Checksum, Handle);
  526. EfiAcpiContext.CurrentHandle = SavedHandle;
  527. } else {
  528. Status = EfipRemoveAcpiTableFromList(*Handle);
  529. }
  530. }
  531. if (EFI_ERROR(Status)) {
  532. return EFI_ABORTED;
  533. }
  534. return EFI_SUCCESS;
  535. }
  536. EFI_STATUS
  537. EfipAddAcpiTableToList (
  538. VOID *Table,
  539. BOOLEAN Checksum,
  540. UINTN *Handle
  541. )
  542. /*++
  543. Routine Description:
  544. This routine adds an ACPI table to the table list. It detects the FACS,
  545. allocates the correct type of memory, and properly aligns the table.
  546. Arguments:
  547. Table - Supplies a pointer to the table to intall.
  548. Checksum - Supplies a boolean indicating if the checksum should be
  549. recomputed.
  550. Handle - Supplies a pointer to the handle of the table.
  551. Return Value:
  552. EFI status code.
  553. --*/
  554. {
  555. BOOLEAN AddToRsdt;
  556. UINT64 Buffer64;
  557. UINT32 *RsdtEntry;
  558. EFI_STATUS Status;
  559. PEFI_ACPI_TABLE_ENTRY TableEntry;
  560. UINT32 TableSignature;
  561. UINT32 TableSize;
  562. UINT32 *XsdtEntry;
  563. ASSERT((Table != NULL) && (Handle != NULL));
  564. AddToRsdt = TRUE;
  565. TableEntry = EfiCoreAllocateBootPool(sizeof(EFI_ACPI_TABLE_ENTRY));
  566. if (TableEntry == NULL) {
  567. return EFI_OUT_OF_RESOURCES;
  568. }
  569. TableEntry->Magic = EFI_ACPI_TABLE_ENTRY_MAGIC;
  570. TableSignature = ((EFI_ACPI_COMMON_HEADER *)Table)->Signature;
  571. TableSize = ((EFI_ACPI_COMMON_HEADER *)Table)->Length;
  572. //
  573. // Allocate a buffer for the table. All tables are allocated in the lower
  574. // 32 bits for backwards compatibility with 32-bit OSes.
  575. //
  576. TableEntry->PageAddress = 0xFFFFFFFF;
  577. TableEntry->NumberOfPages = EFI_SIZE_TO_PAGES(TableSize);
  578. //
  579. // The FACS is aligned on a 64-byte boundary and must be ACPI NVS memory.
  580. //
  581. if (TableSignature == FACS_SIGNATURE) {
  582. ASSERT((EFI_PAGE_SIZE % 64) == 0);
  583. Status = EfiAllocatePages(AllocateMaxAddress,
  584. EfiACPIMemoryNVS,
  585. TableEntry->NumberOfPages,
  586. &(TableEntry->PageAddress));
  587. //
  588. // Everything else is just ACPI reclaim memory.
  589. //
  590. } else {
  591. Status = EfiAllocatePages(AllocateMaxAddress,
  592. EfiACPIReclaimMemory,
  593. TableEntry->NumberOfPages,
  594. &(TableEntry->PageAddress));
  595. }
  596. if (EFI_ERROR(Status)) {
  597. EfiFreePool(TableEntry);
  598. return EFI_OUT_OF_RESOURCES;
  599. }
  600. TableEntry->Table = (VOID *)(UINTN)(TableEntry->PageAddress);
  601. EfiCopyMem(TableEntry->Table, Table, TableSize);
  602. TableEntry->Handle = EfiAcpiContext.CurrentHandle;
  603. EfiAcpiContext.CurrentHandle += 1;
  604. *Handle = TableEntry->Handle;
  605. //
  606. // Update some pointers depending on the table signature.
  607. //
  608. switch (TableSignature) {
  609. case FADT_SIGNATURE:
  610. AddToRsdt = FALSE;
  611. if (EfiAcpiContext.Fadt != NULL) {
  612. EfiFreePages(TableEntry->PageAddress, TableEntry->NumberOfPages);
  613. EfiFreePool(TableEntry);
  614. return EFI_ABORTED;
  615. }
  616. EfiAcpiContext.Fadt = (PFADT)(TableEntry->Table);
  617. if (EfiAcpiContext.Facs <= (PFACS)0xFFFFFFFF) {
  618. EfiAcpiContext.Fadt->FirmwareControlAddress =
  619. (UINT32)(UINTN)(EfiAcpiContext.Facs);
  620. } else {
  621. Buffer64 = (UINTN)(EfiAcpiContext.Facs);
  622. EfiCopyMem(&(EfiAcpiContext.Fadt->XFirmwareControl),
  623. &Buffer64,
  624. sizeof(UINT64));
  625. }
  626. EfiAcpiContext.Fadt->DsdtAddress = (UINT32)(UINTN)(EfiAcpiContext.Dsdt);
  627. Buffer64 = (UINTN)(EfiAcpiContext.Dsdt);
  628. EfiCopyMem(&(EfiAcpiContext.Fadt->XDsdt), &Buffer64, sizeof(UINT64));
  629. //
  630. // Copy the RSDP information to match the FADT OEM information.
  631. //
  632. ASSERT(EfiAcpiContext.Rsdp != NULL);
  633. EfiCopyMem(&(EfiAcpiContext.Rsdp->OemId),
  634. &(EfiAcpiContext.Fadt->Header.OemId),
  635. sizeof(EfiAcpiContext.Fadt->Header.OemId));
  636. //
  637. // Copy the RSDT OEM information to match the FADT.
  638. //
  639. ASSERT(EfiAcpiContext.Rsdt != NULL);
  640. EfiCopyMem(&(EfiAcpiContext.Rsdt->Header.OemId),
  641. &(EfiAcpiContext.Fadt->Header.OemId),
  642. sizeof(EfiAcpiContext.Fadt->Header.OemId));
  643. EfiCopyMem(&(EfiAcpiContext.Rsdt->Header.OemTableId),
  644. &(EfiAcpiContext.Fadt->Header.OemTableId),
  645. sizeof(EfiAcpiContext.Fadt->Header.OemTableId));
  646. EfiAcpiContext.Rsdt->Header.OemRevision =
  647. EfiAcpiContext.Fadt->Header.OemRevision;
  648. //
  649. // Copy over the XSDT OEM information to match the FADT as well.
  650. //
  651. ASSERT(EfiAcpiContext.Xsdt != NULL);
  652. EfiCopyMem(&(EfiAcpiContext.Xsdt->Header.OemId),
  653. &(EfiAcpiContext.Fadt->Header.OemId),
  654. sizeof(EfiAcpiContext.Fadt->Header.OemId));
  655. EfiCopyMem(&(EfiAcpiContext.Xsdt->Header.OemTableId),
  656. &(EfiAcpiContext.Fadt->Header.OemTableId),
  657. sizeof(EfiAcpiContext.Fadt->Header.OemTableId));
  658. EfiAcpiContext.Xsdt->Header.OemRevision =
  659. EfiAcpiContext.Fadt->Header.OemRevision;
  660. if (Checksum != FALSE) {
  661. EfiAcpiChecksumTable(TableEntry->Table,
  662. TableEntry->Table->Length,
  663. OFFSET_OF(DESCRIPTION_HEADER, Checksum));
  664. }
  665. break;
  666. case FACS_SIGNATURE:
  667. if (EfiAcpiContext.Facs != NULL) {
  668. EfiFreePages(TableEntry->PageAddress, TableEntry->NumberOfPages);
  669. EfiFreePool(TableEntry);
  670. return EFI_ABORTED;
  671. }
  672. //
  673. // The FACS is referenced by the FADT and is not part of the RSDT.
  674. //
  675. AddToRsdt = FALSE;
  676. EfiAcpiContext.Facs = (PFACS)(TableEntry->Table);
  677. if (EfiAcpiContext.Fadt != NULL) {
  678. if (EfiAcpiContext.Facs <= (PFACS)0xFFFFFFFF) {
  679. EfiAcpiContext.Fadt->FirmwareControlAddress =
  680. (UINT32)(UINTN)(TableEntry->Table);
  681. } else {
  682. Buffer64 = (UINTN)(TableEntry->Table);
  683. EfiCopyMem(&(EfiAcpiContext.Fadt->XFirmwareControl),
  684. &Buffer64,
  685. sizeof(UINT64));
  686. }
  687. //
  688. // Checksum the FADT.
  689. //
  690. EfiAcpiChecksumTable(EfiAcpiContext.Fadt,
  691. EfiAcpiContext.Fadt->Header.Length,
  692. OFFSET_OF(DESCRIPTION_HEADER, Checksum));
  693. }
  694. break;
  695. case DSDT_SIGNATURE:
  696. if (EfiAcpiContext.Dsdt != NULL) {
  697. EfiFreePages(TableEntry->PageAddress, TableEntry->NumberOfPages);
  698. EfiFreePool(TableEntry);
  699. return EFI_ABORTED;
  700. }
  701. //
  702. // The DSDT is referenced by the FADT and is not part of the RSDT.
  703. //
  704. AddToRsdt = FALSE;
  705. EfiAcpiContext.Dsdt = (PDESCRIPTION_HEADER)TableEntry->Table;
  706. if (EfiAcpiContext.Fadt != NULL) {
  707. EfiAcpiContext.Fadt->DsdtAddress =
  708. (UINT32)(UINTN)(EfiAcpiContext.Dsdt);
  709. Buffer64 = (UINT64)(UINTN)(EfiAcpiContext.Dsdt);
  710. EfiCopyMem(&(EfiAcpiContext.Fadt->XDsdt),
  711. &Buffer64,
  712. sizeof(UINT64));
  713. //
  714. // Checksum the FADT.
  715. //
  716. EfiAcpiChecksumTable(EfiAcpiContext.Fadt,
  717. EfiAcpiContext.Fadt->Header.Length,
  718. OFFSET_OF(DESCRIPTION_HEADER, Checksum));
  719. }
  720. break;
  721. //
  722. // The average joe table.
  723. //
  724. default:
  725. if (Checksum != FALSE) {
  726. EfiAcpiChecksumTable(TableEntry->Table,
  727. TableEntry->Table->Length,
  728. OFFSET_OF(DESCRIPTION_HEADER, Checksum));
  729. }
  730. break;
  731. }
  732. //
  733. // Add the table to the global list.
  734. //
  735. INSERT_BEFORE(&(TableEntry->ListEntry), &(EfiAcpiContext.TableList));
  736. //
  737. // Add this to the RSDT/XSDT.
  738. //
  739. if (AddToRsdt != FALSE) {
  740. if (EfiAcpiContext.TableCount >= EfiAcpiContext.TableCapacity) {
  741. Status = EfipReallocateAcpiTableBuffer();
  742. if (EFI_ERROR(Status)) {
  743. ASSERT(FALSE);
  744. return EFI_OUT_OF_RESOURCES;
  745. }
  746. }
  747. RsdtEntry = (UINT32 *)((UINT8 *)(EfiAcpiContext.Rsdt) +
  748. sizeof(DESCRIPTION_HEADER) +
  749. (EfiAcpiContext.TableCount *
  750. sizeof(UINT32)));
  751. XsdtEntry = (VOID *)((UINT8 *)(EfiAcpiContext.Xsdt) +
  752. sizeof(DESCRIPTION_HEADER) +
  753. EfiAcpiContext.TableCount *
  754. sizeof(UINT64));
  755. *RsdtEntry = (UINT32)(UINTN)(TableEntry->Table);
  756. EfiAcpiContext.Rsdt->Header.Length += sizeof(UINT32);
  757. Buffer64 = (UINTN)(TableEntry->Table);
  758. EfiCopyMem(XsdtEntry, &Buffer64, sizeof(UINT64));
  759. EfiAcpiContext.Xsdt->Header.Length += sizeof(UINT64);
  760. EfiAcpiContext.TableCount += 1;
  761. }
  762. EfipAcpiChecksumCommonTables();
  763. return EFI_SUCCESS;
  764. }
  765. EFI_STATUS
  766. EfipRemoveAcpiTableFromList (
  767. UINTN Handle
  768. )
  769. /*++
  770. Routine Description:
  771. This routine removes the table with the given handle.
  772. Arguments:
  773. Handle - Supplies the handle of the table to remove.
  774. Return Value:
  775. EFI Status code.
  776. --*/
  777. {
  778. EFI_STATUS Status;
  779. PEFI_ACPI_TABLE_ENTRY TableEntry;
  780. TableEntry = NULL;
  781. Status = EfipAcpiFindTableByHandle(Handle,
  782. &(EfiAcpiContext.TableList),
  783. &TableEntry);
  784. if (EFI_ERROR(Status)) {
  785. return EFI_NOT_FOUND;
  786. }
  787. EfipAcpiDeleteTable(TableEntry);
  788. return EFI_SUCCESS;
  789. }
  790. VOID
  791. EfipAcpiDeleteTable (
  792. PEFI_ACPI_TABLE_ENTRY Table
  793. )
  794. /*++
  795. Routine Description:
  796. This routine removes the given table from the ACPI list.
  797. Arguments:
  798. Table - Supplies a pointer to the table entry to remove.
  799. Return Value:
  800. EFI Status code.
  801. --*/
  802. {
  803. BOOLEAN RemoveFromRsdt;
  804. UINT32 TableSignature;
  805. RemoveFromRsdt = TRUE;
  806. ASSERT(Table->Table != NULL);
  807. TableSignature = Table->Table->Signature;
  808. if ((TableSignature == FACS_SIGNATURE) ||
  809. (TableSignature == DSDT_SIGNATURE)) {
  810. RemoveFromRsdt = FALSE;
  811. }
  812. if (TableSignature == FADT_SIGNATURE) {
  813. RemoveFromRsdt = FALSE;
  814. }
  815. if (RemoveFromRsdt != FALSE) {
  816. ASSERT((EfiAcpiContext.Rsdt != NULL) && (EfiAcpiContext.Xsdt != NULL));
  817. EfipAcpiRemoveTableFromRsdt(Table,
  818. &(EfiAcpiContext.TableCount),
  819. &(EfiAcpiContext.Rsdt->Header),
  820. &(EfiAcpiContext.Xsdt->Header));
  821. }
  822. switch (TableSignature) {
  823. case FADT_SIGNATURE:
  824. EfiAcpiContext.Fadt = NULL;
  825. break;
  826. case FACS_SIGNATURE:
  827. EfiAcpiContext.Facs = NULL;
  828. if (EfiAcpiContext.Fadt != NULL) {
  829. EfiAcpiContext.Fadt->FirmwareControlAddress = 0;
  830. EfiSetMem(&(EfiAcpiContext.Fadt->XFirmwareControl),
  831. sizeof(UINT64),
  832. 0);
  833. EfiAcpiChecksumTable(EfiAcpiContext.Fadt,
  834. EfiAcpiContext.Fadt->Header.Length,
  835. OFFSET_OF(DESCRIPTION_HEADER, Checksum));
  836. }
  837. break;
  838. case DSDT_SIGNATURE:
  839. EfiAcpiContext.Dsdt = NULL;
  840. if (EfiAcpiContext.Fadt != NULL) {
  841. EfiAcpiContext.Fadt->DsdtAddress = 0;
  842. EfiSetMem(&(EfiAcpiContext.Fadt->XDsdt), sizeof(UINT64), 0);
  843. EfiAcpiChecksumTable(EfiAcpiContext.Fadt,
  844. EfiAcpiContext.Fadt->Header.Length,
  845. OFFSET_OF(DESCRIPTION_HEADER, Checksum));
  846. }
  847. break;
  848. default:
  849. break;
  850. }
  851. //
  852. // Remove and free the table entry.
  853. //
  854. EfiFreePages(Table->PageAddress, Table->NumberOfPages);
  855. LIST_REMOVE(&(Table->ListEntry));
  856. Table->Magic = 0;
  857. EfiFreePool(Table);
  858. return;
  859. }
  860. EFI_STATUS
  861. EfipAcpiRemoveTableFromRsdt (
  862. PEFI_ACPI_TABLE_ENTRY Table,
  863. UINTN *TableCount,
  864. PDESCRIPTION_HEADER Rsdt,
  865. PDESCRIPTION_HEADER Xsdt
  866. )
  867. /*++
  868. Routine Description:
  869. This routine removes the given table from the RSDT and optionally from the
  870. XSDT.
  871. Arguments:
  872. Table - Supplies a pointer to the table entry to remove.
  873. TableCount - Supplies a pointer to the current number of tables. This value
  874. will be updated.
  875. Rsdt - Supplies a pointer to the RSDT to remove the table from.
  876. Xsdt - Supplies an optional pointer to the XSDT to remove the table from.
  877. Return Value:
  878. EFI Status code.
  879. --*/
  880. {
  881. UINTN Index;
  882. UINT32 *RsdtEntry;
  883. UINT64 Table64;
  884. VOID *XsdtEntry;
  885. for (Index = 0; Index < *TableCount; Index += 1) {
  886. RsdtEntry = (UINT32 *)((UINT8 *)Rsdt +
  887. sizeof(DESCRIPTION_HEADER) +
  888. (Index * sizeof(UINT32)));
  889. XsdtEntry = NULL;
  890. Table64 = 0;
  891. if (Xsdt != NULL) {
  892. XsdtEntry = (UINT64 *)((UINT8 *)Xsdt +
  893. sizeof(DESCRIPTION_HEADER) +
  894. (Index * sizeof(UINT64)));
  895. EfiCopyMem(&Table64, XsdtEntry, sizeof(UINT64));
  896. }
  897. //
  898. // Fix up the table if this is the right entry.
  899. //
  900. if ((*RsdtEntry == (UINT32)(UINTN)(Table->Table)) &&
  901. ((Xsdt == NULL) || (Table64 == (UINT64)(UINTN)(Table->Table)))) {
  902. EfiCopyMem(RsdtEntry,
  903. RsdtEntry + 1,
  904. (*TableCount - Index) * sizeof(UINT32));
  905. Rsdt->Length -= sizeof(UINT32);
  906. if (Xsdt != NULL) {
  907. EfiCopyMem(XsdtEntry,
  908. (UINT64 *)XsdtEntry + 1,
  909. (*TableCount - Index * sizeof(UINT64)));
  910. Xsdt->Length -= sizeof(UINT64);
  911. }
  912. break;
  913. //
  914. // Watch out for the end of the list, fail if the table wasn't found.
  915. //
  916. } else if (Index + 1 == *TableCount) {
  917. return EFI_INVALID_PARAMETER;
  918. }
  919. }
  920. EfiAcpiChecksumTable(Rsdt,
  921. Rsdt->Length,
  922. OFFSET_OF(DESCRIPTION_HEADER, Checksum));
  923. if (Xsdt != NULL) {
  924. EfiAcpiChecksumTable(Xsdt,
  925. Xsdt->Length,
  926. OFFSET_OF(DESCRIPTION_HEADER, Checksum));
  927. }
  928. *TableCount -= 1;
  929. return EFI_SUCCESS;
  930. }
  931. EFI_STATUS
  932. EfipAcpiFindTableByHandle (
  933. UINTN Handle,
  934. PLIST_ENTRY ListHead,
  935. PEFI_ACPI_TABLE_ENTRY *FoundEntry
  936. )
  937. /*++
  938. Routine Description:
  939. This routine finds the table entry with the given handle.
  940. Arguments:
  941. Handle - Supplies the handle of the table to find.
  942. ListHead - Supplies a pointer to the head of the list of table entries.
  943. FoundEntry - Supplies a pointer where a pointer to the found entry will be
  944. returned on success.
  945. Return Value:
  946. EFI_SUCCESS on success.
  947. EFI_NOT_FOUND if no table with the given handle exists.
  948. --*/
  949. {
  950. PLIST_ENTRY CurrentEntry;
  951. PEFI_ACPI_TABLE_ENTRY TableEntry;
  952. CurrentEntry = ListHead->Next;
  953. while (CurrentEntry != ListHead) {
  954. TableEntry = LIST_VALUE(CurrentEntry, EFI_ACPI_TABLE_ENTRY, ListEntry);
  955. ASSERT(TableEntry->Magic == EFI_ACPI_TABLE_ENTRY_MAGIC);
  956. if (TableEntry->Handle == Handle) {
  957. *FoundEntry = TableEntry;
  958. return EFI_SUCCESS;
  959. }
  960. CurrentEntry = CurrentEntry->Next;
  961. }
  962. return EFI_NOT_FOUND;
  963. }
  964. EFI_STATUS
  965. EfipReallocateAcpiTableBuffer (
  966. VOID
  967. )
  968. /*++
  969. Routine Description:
  970. This routine reallocates the RSDT and XSDT table arrays.
  971. Arguments:
  972. None.
  973. Return Value:
  974. EFI Status code.
  975. --*/
  976. {
  977. UINTN CopySize;
  978. UINT64 CurrentData;
  979. UINTN NewTableCount;
  980. EFI_ACPI_CONTEXT Original;
  981. EFI_PHYSICAL_ADDRESS PageAddress;
  982. UINT8 *Pointer;
  983. EFI_STATUS Status;
  984. UINTN TotalSize;
  985. EfiCopyMem(&Original, &EfiAcpiContext, sizeof(EFI_ACPI_CONTEXT));
  986. NewTableCount = Original.TableCapacity + EFI_ACPI_TABLE_EXPANSION_COUNT;
  987. TotalSize = sizeof(DESCRIPTION_HEADER) + (NewTableCount * sizeof(UINT32)) +
  988. sizeof(DESCRIPTION_HEADER) + (NewTableCount * sizeof(UINT64));
  989. //
  990. // Allocate memory in the lower 4GB.
  991. //
  992. PageAddress = 0xFFFFFFFF;
  993. Status = EfiAllocatePages(AllocateMaxAddress,
  994. EfiACPIReclaimMemory,
  995. EFI_SIZE_TO_PAGES(TotalSize),
  996. &PageAddress);
  997. if (EFI_ERROR(Status)) {
  998. return EFI_OUT_OF_RESOURCES;
  999. }
  1000. Pointer = (UINT8 *)(UINTN)PageAddress;
  1001. EfiSetMem(Pointer, TotalSize, 0);
  1002. EfiAcpiContext.Rsdt = (PRSDT)Pointer;
  1003. Pointer += sizeof(DESCRIPTION_HEADER) + (NewTableCount * sizeof(UINT32));
  1004. EfiAcpiContext.Xsdt = (PXSDT)Pointer;
  1005. //
  1006. // Update the RSDP to point to the new RSDT and XSDT.
  1007. //
  1008. ASSERT(EfiAcpiContext.Rsdp != NULL);
  1009. EfiAcpiContext.Rsdp->RsdtAddress = (UINT32)(UINTN)(EfiAcpiContext.Rsdt);
  1010. CurrentData = (UINTN)(EfiAcpiContext.Xsdt);
  1011. EfiCopyMem(&(EfiAcpiContext.Rsdp->XsdtAddress),
  1012. &CurrentData,
  1013. sizeof(UINT64));
  1014. //
  1015. // Copy the original structures to the new buffer.
  1016. //
  1017. CopySize = sizeof(DESCRIPTION_HEADER) +
  1018. (Original.TableCount * sizeof(UINT32));
  1019. EfiCopyMem(EfiAcpiContext.Rsdt, Original.Rsdt, CopySize);
  1020. CopySize = sizeof(DESCRIPTION_HEADER) +
  1021. (Original.TableCount * sizeof(UINT64));
  1022. EfiCopyMem(EfiAcpiContext.Xsdt, Original.Xsdt, CopySize);
  1023. //
  1024. // Free the original buffer.
  1025. //
  1026. TotalSize = sizeof(DESCRIPTION_HEADER) +
  1027. (Original.TableCapacity * sizeof(UINT32)) +
  1028. sizeof(DESCRIPTION_HEADER) +
  1029. (Original.TableCapacity * sizeof(UINT64));
  1030. EfiFreePages((EFI_PHYSICAL_ADDRESS)(UINTN)(Original.Rsdt),
  1031. EFI_SIZE_TO_PAGES(TotalSize));
  1032. EfiAcpiContext.TableCapacity = NewTableCount;
  1033. return EFI_SUCCESS;
  1034. }
  1035. EFI_STATUS
  1036. EfipAcpiPublishTables (
  1037. VOID
  1038. )
  1039. /*++
  1040. Routine Description:
  1041. This routine installs the ACPI tables as an EFI configuration table.
  1042. Arguments:
  1043. None.
  1044. Return Value:
  1045. None.
  1046. --*/
  1047. {
  1048. UINT32 *RsdtEntry;
  1049. EFI_STATUS Status;
  1050. UINT64 Value64;
  1051. VOID *XsdtEntry;
  1052. if (EfiAcpiContext.Fadt != NULL) {
  1053. RsdtEntry = (UINT32 *)((UINT8 *)(EfiAcpiContext.Rsdt) +
  1054. sizeof(DESCRIPTION_HEADER));
  1055. *RsdtEntry = (UINT32)(UINTN)(EfiAcpiContext.Fadt);
  1056. XsdtEntry = (VOID *)((UINT8 *)(EfiAcpiContext.Xsdt) +
  1057. sizeof(DESCRIPTION_HEADER));
  1058. Value64 = (UINT64)(UINTN)(EfiAcpiContext.Fadt);
  1059. EfiCopyMem(XsdtEntry, &Value64, sizeof(UINT64));
  1060. }
  1061. EfipAcpiChecksumCommonTables();
  1062. Status = EfiInstallConfigurationTable(&EfiAcpiTableGuid,
  1063. EfiAcpiContext.Rsdp);
  1064. if (EFI_ERROR(Status)) {
  1065. return EFI_ABORTED;
  1066. }
  1067. return EFI_SUCCESS;
  1068. }
  1069. VOID
  1070. EfipAcpiChecksumCommonTables (
  1071. VOID
  1072. )
  1073. /*++
  1074. Routine Description:
  1075. This routine recomputes the checksums on everyone's favorite ACPI tables.
  1076. Arguments:
  1077. None.
  1078. Return Value:
  1079. None.
  1080. --*/
  1081. {
  1082. UINTN Offset;
  1083. Offset = OFFSET_OF(DESCRIPTION_HEADER, Checksum);
  1084. EfiAcpiChecksumTable(EfiAcpiContext.Rsdp,
  1085. OFFSET_OF(RSDP, Length),
  1086. OFFSET_OF(RSDP, Checksum));
  1087. EfiAcpiChecksumTable(EfiAcpiContext.Rsdp,
  1088. sizeof(RSDP),
  1089. OFFSET_OF(RSDP, ExtendedChecksum));
  1090. EfiAcpiChecksumTable(EfiAcpiContext.Rsdt,
  1091. EfiAcpiContext.Rsdt->Header.Length,
  1092. Offset);
  1093. EfiAcpiChecksumTable(EfiAcpiContext.Xsdt,
  1094. EfiAcpiContext.Xsdt->Header.Length,
  1095. Offset);
  1096. return;
  1097. }