acpi.c 36 KB

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