+/**\r
+ Callback function to calculate SMBIOS table size, and allocate memory for SMBIOS table.\r
+ SMBIOS table will be copied into EfiReservedMemoryType memory in legacy boot path.\r
+\r
+ @param Event Event whose notification function is being invoked.\r
+ @param Context The pointer to the notification function's context,\r
+ which is implementation-dependent.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+InstallSmbiosEventCallback (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ SMBIOS_TABLE_ENTRY_POINT *EntryPointStructure;\r
+ \r
+ //\r
+ // Get SMBIOS table from EFI configuration table\r
+ //\r
+ Status = EfiGetSystemConfigurationTable (\r
+ &gEfiSmbiosTableGuid,\r
+ &mRuntimeSmbiosEntryPoint\r
+ );\r
+ if ((EFI_ERROR (Status)) || (mRuntimeSmbiosEntryPoint == NULL)) {\r
+ return;\r
+ }\r
+ \r
+ EntryPointStructure = (SMBIOS_TABLE_ENTRY_POINT *) mRuntimeSmbiosEntryPoint;\r
+\r
+ //\r
+ // Allocate memory for SMBIOS Entry Point Structure.\r
+ // CSM framework spec requires SMBIOS table below 4GB in EFI_TO_COMPATIBILITY16_BOOT_TABLE.\r
+ //\r
+ if (mReserveSmbiosEntryPoint == 0) {\r
+ //\r
+ // Entrypoint structure with fixed size is allocated only once.\r
+ //\r
+ mReserveSmbiosEntryPoint = SIZE_4GB - 1;\r
+ Status = gBS->AllocatePages (\r
+ AllocateMaxAddress,\r
+ EfiReservedMemoryType,\r
+ EFI_SIZE_TO_PAGES ((UINTN) (EntryPointStructure->EntryPointLength)),\r
+ &mReserveSmbiosEntryPoint\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ mReserveSmbiosEntryPoint = 0;\r
+ return;\r
+ }\r
+ DEBUG ((EFI_D_INFO, "Allocate memory for Smbios Entry Point Structure\n"));\r
+ }\r
+ \r
+ if ((mStructureTableAddress != 0) && \r
+ (mStructureTablePages < EFI_SIZE_TO_PAGES ((UINT32)EntryPointStructure->TableLength))) {\r
+ //\r
+ // If original buffer is not enough for the new SMBIOS table, free original buffer and re-allocate\r
+ //\r
+ gBS->FreePages (mStructureTableAddress, mStructureTablePages);\r
+ mStructureTableAddress = 0;\r
+ mStructureTablePages = 0;\r
+ DEBUG ((EFI_D_INFO, "Original size is not enough. Re-allocate the memory.\n"));\r
+ }\r
+ \r
+ if (mStructureTableAddress == 0) {\r
+ //\r
+ // Allocate reserved memory below 4GB.\r
+ // Smbios spec requires the structure table is below 4GB.\r
+ //\r
+ mStructureTableAddress = SIZE_4GB - 1;\r
+ mStructureTablePages = EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength);\r
+ Status = gBS->AllocatePages (\r
+ AllocateMaxAddress,\r
+ EfiReservedMemoryType,\r
+ mStructureTablePages,\r
+ &mStructureTableAddress\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->FreePages (\r
+ mReserveSmbiosEntryPoint, \r
+ EFI_SIZE_TO_PAGES ((UINTN) (EntryPointStructure->EntryPointLength))\r
+ );\r
+ mReserveSmbiosEntryPoint = 0;\r
+ mStructureTableAddress = 0;\r
+ mStructureTablePages = 0;\r
+ return;\r
+ }\r
+ DEBUG ((EFI_D_INFO, "Allocate memory for Smbios Structure Table\n"));\r
+ }\r
+}\r
+\r
+/**\r
+ Callback function to toggle EndOfDxe status. NULL pointer detection needs\r
+ this status to decide if it's necessary to change attributes of page 0.\r
+\r
+ @param Event Event whose notification function is being invoked.\r
+ @param Context The pointer to the notification function's context,\r
+ which is implementation-dependent.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+ToggleEndOfDxeStatus (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ mEndOfDxe = TRUE;\r
+ return;\r
+}\r
+\r