3 Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 This file include all platform action which can be customized
23 #include "BdsPlatform.h"
25 #define IS_PCI_ISA_PDECODE(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA_PDECODE, 0)
27 extern BOOLEAN gConnectAllHappened
;
28 extern USB_CLASS_FORMAT_DEVICE_PATH gUsbClassKeyboardDevicePath
;
30 EFI_GUID
*gTableGuidArray
[] = {
31 &gEfiAcpi20TableGuid
, &gEfiAcpiTableGuid
, &gEfiSmbiosTableGuid
, &gEfiMpsTableGuid
35 // BDS Platform Functions
39 GetSystemTablesFromHob (
45 Find GUID'ed HOBs that contain EFI_PHYSICAL_ADDRESS of ACPI, SMBIOS, MPs tables
55 EFI_PEI_HOB_POINTERS GuidHob
;
56 EFI_PEI_HOB_POINTERS HobStart
;
57 EFI_PHYSICAL_ADDRESS
*Table
;
63 HobStart
.Raw
= GetHobList ();
65 // Iteratively add ACPI Table, SMBIOS Table, MPS Table to EFI System Table
67 for (Index
= 0; Index
< sizeof (gTableGuidArray
) / sizeof (*gTableGuidArray
); ++Index
) {
68 GuidHob
.Raw
= GetNextGuidHob (gTableGuidArray
[Index
], HobStart
.Raw
);
69 if (GuidHob
.Raw
!= NULL
) {
70 Table
= GET_GUID_HOB_DATA (GuidHob
.Guid
);
73 // Check if Mps Table/Smbios Table/Acpi Table exists in E/F seg,
74 // According to UEFI Spec, we should make sure Smbios table,
75 // ACPI table and Mps tables kept in memory of specified type
77 ConvertSystemTable(gTableGuidArray
[Index
], (VOID
**)&Table
);
78 gBS
->InstallConfigurationTable (gTableGuidArray
[Index
], (VOID
*)Table
);
92 EFI_MEMORY_DESCRIPTOR
*MemMap
;
93 EFI_MEMORY_DESCRIPTOR
*MemMapPtr
;
95 UINTN MapKey
, DescriptorSize
;
97 UINT32 DescriptorVersion
;
103 Status
= gBS
->GetMemoryMap (&MemMapSize
, MemMap
, &MapKey
, &DescriptorSize
, &DescriptorVersion
);
104 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
105 MemMapSize
+= EFI_PAGE_SIZE
;
106 Status
= gBS
->AllocatePool (EfiBootServicesData
, MemMapSize
, &MemMap
);
107 ASSERT (Status
== EFI_SUCCESS
);
108 Status
= gBS
->GetMemoryMap (&MemMapSize
, MemMap
, &MapKey
, &DescriptorSize
, &DescriptorVersion
);
109 ASSERT (Status
== EFI_SUCCESS
);
112 ASSERT (DescriptorVersion
== EFI_MEMORY_DESCRIPTOR_VERSION
);
114 for (Index
= 0; Index
< MemMapSize
/ DescriptorSize
; Index
++) {
115 Bytes
= LShiftU64 (MemMap
->NumberOfPages
, 12);
116 DEBUG ((EFI_D_ERROR
, "%lX-%lX %lX %lX %X\n",
117 MemMap
->PhysicalStart
,
118 MemMap
->PhysicalStart
+ Bytes
- 1,
119 MemMap
->NumberOfPages
,
121 (UINTN
)MemMap
->Type
));
122 MemMap
= (EFI_MEMORY_DESCRIPTOR
*)((UINTN
)MemMap
+ DescriptorSize
);
125 gBS
->FreePool (MemMapPtr
);
135 EFI_PEI_HOB_POINTERS GuidHob
;
137 MEMORY_DESC_HOB MemoryDescHob
;
139 EFI_PHYSICAL_ADDRESS Memory
;
140 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor
;
142 GuidHob
.Raw
= GetFirstGuidHob (&gLdrMemoryDescriptorGuid
);
143 if (GuidHob
.Raw
== NULL
) {
144 DEBUG ((EFI_D_ERROR
, "Fail to get gEfiLdrMemoryDescriptorGuid from GUID HOB LIST!\n"));
147 Table
= GET_GUID_HOB_DATA (GuidHob
.Guid
);
149 DEBUG ((EFI_D_ERROR
, "Fail to get gEfiLdrMemoryDescriptorGuid from GUID HOB LIST!\n"));
152 MemoryDescHob
.MemDescCount
= *(UINTN
*)Table
;
153 MemoryDescHob
.MemDesc
= *(EFI_MEMORY_DESCRIPTOR
**)((UINTN
)Table
+ sizeof(UINTN
));
156 // Add ACPINVS, ACPIReclaim, and Reserved memory to MemoryMap
158 for (Index
= 0; Index
< MemoryDescHob
.MemDescCount
; Index
++) {
159 if (MemoryDescHob
.MemDesc
[Index
].PhysicalStart
< 0x100000) {
162 if (MemoryDescHob
.MemDesc
[Index
].PhysicalStart
>= 0x100000000ULL
) {
165 if ((MemoryDescHob
.MemDesc
[Index
].Type
== EfiReservedMemoryType
) ||
166 (MemoryDescHob
.MemDesc
[Index
].Type
== EfiRuntimeServicesData
) ||
167 (MemoryDescHob
.MemDesc
[Index
].Type
== EfiRuntimeServicesCode
) ||
168 (MemoryDescHob
.MemDesc
[Index
].Type
== EfiACPIReclaimMemory
) ||
169 (MemoryDescHob
.MemDesc
[Index
].Type
== EfiACPIMemoryNVS
)) {
170 DEBUG ((EFI_D_ERROR
, "PhysicalStart - 0x%016lx, ", MemoryDescHob
.MemDesc
[Index
].PhysicalStart
));
171 DEBUG ((EFI_D_ERROR
, "PageNumber - 0x%016lx, ", MemoryDescHob
.MemDesc
[Index
].NumberOfPages
));
172 DEBUG ((EFI_D_ERROR
, "Attribute - 0x%016lx, ", MemoryDescHob
.MemDesc
[Index
].Attribute
));
173 DEBUG ((EFI_D_ERROR
, "Type - 0x%08x\n", MemoryDescHob
.MemDesc
[Index
].Type
));
174 if ((MemoryDescHob
.MemDesc
[Index
].Type
== EfiRuntimeServicesData
) ||
175 (MemoryDescHob
.MemDesc
[Index
].Type
== EfiRuntimeServicesCode
)) {
177 // For RuntimeSevicesData and RuntimeServicesCode, they are BFV or DxeCore.
178 // The memory type is assigned in EfiLdr
180 Status
= gDS
->GetMemorySpaceDescriptor (MemoryDescHob
.MemDesc
[Index
].PhysicalStart
, &Descriptor
);
181 if (EFI_ERROR (Status
)) {
184 if (Descriptor
.GcdMemoryType
!= EfiGcdMemoryTypeReserved
) {
186 // BFV or tested DXE core
191 // Untested DXE Core region, free and remove
193 Status
= gDS
->FreeMemorySpace (
194 MemoryDescHob
.MemDesc
[Index
].PhysicalStart
,
195 LShiftU64 (MemoryDescHob
.MemDesc
[Index
].NumberOfPages
, EFI_PAGE_SHIFT
)
197 if (EFI_ERROR (Status
)) {
198 DEBUG ((EFI_D_ERROR
, "FreeMemorySpace fail - %r!\n", Status
));
201 Status
= gDS
->RemoveMemorySpace (
202 MemoryDescHob
.MemDesc
[Index
].PhysicalStart
,
203 LShiftU64 (MemoryDescHob
.MemDesc
[Index
].NumberOfPages
, EFI_PAGE_SHIFT
)
205 if (EFI_ERROR (Status
)) {
206 DEBUG ((EFI_D_ERROR
, "RemoveMemorySpace fail - %r!\n", Status
));
211 // Convert Runtime type to BootTime type
213 if (MemoryDescHob
.MemDesc
[Index
].Type
== EfiRuntimeServicesData
) {
214 MemoryDescHob
.MemDesc
[Index
].Type
= EfiBootServicesData
;
216 MemoryDescHob
.MemDesc
[Index
].Type
= EfiBootServicesCode
;
220 // PassThrough, let below code add and alloate.
224 // ACPI or reserved memory
226 Status
= gDS
->AddMemorySpace (
227 EfiGcdMemoryTypeSystemMemory
,
228 MemoryDescHob
.MemDesc
[Index
].PhysicalStart
,
229 LShiftU64 (MemoryDescHob
.MemDesc
[Index
].NumberOfPages
, EFI_PAGE_SHIFT
),
230 MemoryDescHob
.MemDesc
[Index
].Attribute
232 if (EFI_ERROR (Status
)) {
233 DEBUG ((EFI_D_ERROR
, "AddMemorySpace fail - %r!\n", Status
));
234 if ((MemoryDescHob
.MemDesc
[Index
].Type
== EfiACPIReclaimMemory
) ||
235 (MemoryDescHob
.MemDesc
[Index
].Type
== EfiACPIMemoryNVS
)) {
237 // For EfiACPIReclaimMemory and EfiACPIMemoryNVS, it must success.
238 // For EfiReservedMemoryType, there maybe overlap. So skip check here.
240 // ASSERT_EFI_ERROR (Status);
245 Memory
= MemoryDescHob
.MemDesc
[Index
].PhysicalStart
;
246 Status
= gBS
->AllocatePages (
248 (EFI_MEMORY_TYPE
)MemoryDescHob
.MemDesc
[Index
].Type
,
249 (UINTN
)MemoryDescHob
.MemDesc
[Index
].NumberOfPages
,
252 if (EFI_ERROR (Status
)) {
253 DEBUG ((EFI_D_ERROR
, "AllocatePages fail - %r!\n", Status
));
255 // For the page added, it must be allocated.
257 // ASSERT_EFI_ERROR (Status);
266 DisableUsbLegacySupport(
272 Disabble the USB legacy Support in all Ehci and Uhci.
273 This function assume all PciIo handles have been created in system.
284 EFI_HANDLE
*HandleArray
;
285 UINTN HandleArrayCount
;
287 EFI_PCI_IO_PROTOCOL
*PciIo
;
296 // Find the usb host controller
298 Status
= gBS
->LocateHandleBuffer (
300 &gEfiPciIoProtocolGuid
,
305 if (!EFI_ERROR (Status
)) {
306 for (Index
= 0; Index
< HandleArrayCount
; Index
++) {
307 Status
= gBS
->HandleProtocol (
309 &gEfiPciIoProtocolGuid
,
312 if (!EFI_ERROR (Status
)) {
314 // Find the USB host controller controller
316 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, 0x09, 3, &Class
);
317 if (!EFI_ERROR (Status
)) {
318 if ((PCI_CLASS_SERIAL
== Class
[2]) &&
319 (PCI_CLASS_SERIAL_USB
== Class
[1])) {
320 if (PCI_IF_UHCI
== Class
[0]) {
322 // Found the UHCI, then disable the legacy support
325 Status
= PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0xC0, 1, &Command
);
326 } else if (PCI_IF_EHCI
== Class
[0]) {
328 // Found the EHCI, then disable the legacy support
330 Status
= PciIo
->Mem
.Read (
334 (UINT64
) 0x08, //EHC_HCCPARAMS_OFFSET
339 ExtendCap
= (HcCapParams
>> 8) & 0xFF;
341 // Disable the SMI in USBLEGCTLSTS firstly
343 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, ExtendCap
+ 0x4, 1, &Value
);
345 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, ExtendCap
+ 0x4, 1, &Value
);
348 // Get EHCI Ownership from legacy bios
350 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, ExtendCap
, 1, &Value
);
351 Value
|= (0x1 << 24);
352 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, ExtendCap
, 1, &Value
);
358 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, ExtendCap
, 1, &Value
);
360 if ((Value
& 0x01010000) == 0x01000000) {
372 gBS
->FreePool (HandleArray
);
386 Platform Bds init. Incude the platform firmware vendor, revision
397 GetSystemTablesFromHob ();
402 // Append Usb Keyboard short form DevicePath into "ConInDev"
404 BdsLibUpdateConsoleVariable (
406 (EFI_DEVICE_PATH_PROTOCOL
*) &gUsbClassKeyboardDevicePath
,
412 GetPciExpressBaseAddressForRootBridge (
413 IN UINTN HostBridgeNumber
,
414 IN UINTN RootBridgeNumber
419 This routine is to get PciExpress Base Address for this RootBridge
422 HostBridgeNumber - The number of HostBridge
423 RootBridgeNumber - The number of RootBridge
426 UINT64 - PciExpressBaseAddress for this HostBridge and RootBridge
430 EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION
*PciExpressBaseAddressInfo
;
434 EFI_PEI_HOB_POINTERS GuidHob
;
437 // Get PciExpressAddressInfo Hob
439 PciExpressBaseAddressInfo
= NULL
;
441 GuidHob
.Raw
= GetFirstGuidHob (&gEfiPciExpressBaseAddressGuid
);
442 if (GuidHob
.Raw
!= NULL
) {
443 PciExpressBaseAddressInfo
= GET_GUID_HOB_DATA (GuidHob
.Guid
);
444 BufferSize
= GET_GUID_HOB_DATA_SIZE (GuidHob
.Guid
);
450 // Search the PciExpress Base Address in the Hob for current RootBridge
452 Number
= (UINT32
)(BufferSize
/ sizeof(EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION
));
453 for (Index
= 0; Index
< Number
; Index
++) {
454 if ((PciExpressBaseAddressInfo
[Index
].HostBridgeNumber
== HostBridgeNumber
) &&
455 (PciExpressBaseAddressInfo
[Index
].RootBridgeNumber
== RootBridgeNumber
)) {
456 return PciExpressBaseAddressInfo
[Index
].PciExpressBaseAddress
;
461 // Do not find the PciExpress Base Address in the Hob
467 PatchPciRootBridgeDevicePath (
468 IN UINTN HostBridgeNumber
,
469 IN UINTN RootBridgeNumber
,
470 IN PLATFORM_ROOT_BRIDGE_DEVICE_PATH
*RootBridge
473 UINT64 PciExpressBase
;
475 PciExpressBase
= GetPciExpressBaseAddressForRootBridge (HostBridgeNumber
, RootBridgeNumber
);
477 DEBUG ((EFI_D_INFO
, "Get PciExpress Address from Hob: 0x%X\n", PciExpressBase
));
479 if (PciExpressBase
!= 0) {
480 RootBridge
->PciRootBridge
.HID
= EISA_PNP_ID(0x0A08);
500 EFI_SUCCESS - Connect RootBridge successfully.
501 EFI_STATUS - Connect RootBridge fail.
506 EFI_HANDLE RootHandle
;
509 // Patch Pci Root Bridge Device Path
511 PatchPciRootBridgeDevicePath (0, 0, &gPlatformRootBridge0
);
514 // Make all the PCI_IO protocols on PCI Seg 0 show up
516 BdsLibConnectDevicePath (gPlatformRootBridges
[0]);
518 Status
= gBS
->LocateDevicePath (
519 &gEfiDevicePathProtocolGuid
,
520 &gPlatformRootBridges
[0],
523 DEBUG ((EFI_D_INFO
, "Pci Root bridge handle is 0x%X\n", RootHandle
));
525 if (EFI_ERROR (Status
)) {
529 Status
= gBS
->ConnectController (RootHandle
, NULL
, NULL
, FALSE
);
530 if (EFI_ERROR (Status
)) {
538 PrepareLpcBridgeDevicePath (
539 IN EFI_HANDLE DeviceHandle
545 Add IsaKeyboard to ConIn,
546 add IsaSerial to ConOut, ConIn, ErrOut.
551 DeviceHandle - Handle of PCIIO protocol.
555 EFI_SUCCESS - LPC bridge is added to ConOut, ConIn, and ErrOut.
556 EFI_STATUS - No LPC bridge is added.
561 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
562 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
565 Status
= gBS
->HandleProtocol (
567 &gEfiDevicePathProtocolGuid
,
570 if (EFI_ERROR (Status
)) {
573 TempDevicePath
= DevicePath
;
578 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnpPs2KeyboardDeviceNode
);
580 BdsLibUpdateConsoleVariable (VarConsoleInp
, DevicePath
, NULL
);
585 DevicePath
= TempDevicePath
;
586 gPnp16550ComPortDeviceNode
.UID
= 0;
588 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
);
589 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
590 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
592 BdsLibUpdateConsoleVariable (VarConsoleOut
, DevicePath
, NULL
);
593 BdsLibUpdateConsoleVariable (VarConsoleInp
, DevicePath
, NULL
);
594 BdsLibUpdateConsoleVariable (VarErrorOut
, DevicePath
, NULL
);
599 DevicePath
= TempDevicePath
;
600 gPnp16550ComPortDeviceNode
.UID
= 1;
602 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
);
603 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
604 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
606 BdsLibUpdateConsoleVariable (VarConsoleOut
, DevicePath
, NULL
);
607 BdsLibUpdateConsoleVariable (VarConsoleInp
, DevicePath
, NULL
);
608 BdsLibUpdateConsoleVariable (VarErrorOut
, DevicePath
, NULL
);
615 IN EFI_DEVICE_PATH_PROTOCOL
*PciDevicePath
,
616 OUT EFI_DEVICE_PATH_PROTOCOL
**GopDevicePath
621 EFI_HANDLE PciDeviceHandle
;
622 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
623 EFI_DEVICE_PATH_PROTOCOL
*TempPciDevicePath
;
624 UINTN GopHandleCount
;
625 EFI_HANDLE
*GopHandleBuffer
;
627 if (PciDevicePath
== NULL
|| GopDevicePath
== NULL
) {
628 return EFI_INVALID_PARAMETER
;
632 // Initialize the GopDevicePath to be PciDevicePath
634 *GopDevicePath
= PciDevicePath
;
635 TempPciDevicePath
= PciDevicePath
;
637 Status
= gBS
->LocateDevicePath (
638 &gEfiDevicePathProtocolGuid
,
642 if (EFI_ERROR (Status
)) {
647 // Try to connect this handle, so that GOP dirver could start on this
648 // device and create child handles with GraphicsOutput Protocol installed
649 // on them, then we get device paths of these child handles and select
650 // them as possible console device.
652 gBS
->ConnectController (PciDeviceHandle
, NULL
, NULL
, FALSE
);
654 Status
= gBS
->LocateHandleBuffer (
656 &gEfiGraphicsOutputProtocolGuid
,
661 if (!EFI_ERROR (Status
)) {
663 // Add all the child handles as possible Console Device
665 for (Index
= 0; Index
< GopHandleCount
; Index
++) {
666 Status
= gBS
->HandleProtocol (GopHandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
*)&TempDevicePath
);
667 if (EFI_ERROR (Status
)) {
673 GetDevicePathSize (PciDevicePath
) - END_DEVICE_PATH_LENGTH
676 // In current implementation, we only enable one of the child handles
677 // as console device, i.e. sotre one of the child handle's device
678 // path to variable "ConOut"
679 // In futhure, we could select all child handles to be console device
682 *GopDevicePath
= TempDevicePath
;
685 // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()
686 // Add the integrity GOP device path.
688 BdsLibUpdateConsoleVariable (VarConsoleOutDev
, NULL
, PciDevicePath
);
689 BdsLibUpdateConsoleVariable (VarConsoleOutDev
, TempDevicePath
, NULL
);
692 gBS
->FreePool (GopHandleBuffer
);
699 PreparePciVgaDevicePath (
700 IN EFI_HANDLE DeviceHandle
706 Add PCI VGA to ConOut.
711 DeviceHandle - Handle of PCIIO protocol.
715 EFI_SUCCESS - PCI VGA is added to ConOut.
716 EFI_STATUS - No PCI VGA device is added.
721 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
722 EFI_DEVICE_PATH_PROTOCOL
*GopDevicePath
;
725 GopDevicePath
= NULL
;
726 Status
= gBS
->HandleProtocol (
728 &gEfiDevicePathProtocolGuid
,
731 if (EFI_ERROR (Status
)) {
735 GetGopDevicePath (DevicePath
, &GopDevicePath
);
736 DevicePath
= GopDevicePath
;
738 BdsLibUpdateConsoleVariable (VarConsoleOut
, DevicePath
, NULL
);
744 PreparePciSerialDevicePath (
745 IN EFI_HANDLE DeviceHandle
751 Add PCI Serial to ConOut, ConIn, ErrOut.
756 DeviceHandle - Handle of PCIIO protocol.
760 EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut.
761 EFI_STATUS - No PCI Serial device is added.
766 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
769 Status
= gBS
->HandleProtocol (
771 &gEfiDevicePathProtocolGuid
,
774 if (EFI_ERROR (Status
)) {
778 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
779 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
781 BdsLibUpdateConsoleVariable (VarConsoleOut
, DevicePath
, NULL
);
782 BdsLibUpdateConsoleVariable (VarConsoleInp
, DevicePath
, NULL
);
783 BdsLibUpdateConsoleVariable (VarErrorOut
, DevicePath
, NULL
);
789 DetectAndPreparePlatformPciDevicePath (
790 BOOLEAN DetectVgaOnly
796 Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
800 DetectVgaOnly - Only detect VGA device if it's TRUE.
804 EFI_SUCCESS - PCI Device check and Console variable update successfully.
805 EFI_STATUS - PCI Device check or Console variable update fail.
811 EFI_HANDLE
*HandleBuffer
;
813 EFI_PCI_IO_PROTOCOL
*PciIo
;
817 // Start to check all the PciIo to find all possible device
821 Status
= gBS
->LocateHandleBuffer (
823 &gEfiPciIoProtocolGuid
,
828 if (EFI_ERROR (Status
)) {
832 for (Index
= 0; Index
< HandleCount
; Index
++) {
833 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiPciIoProtocolGuid
, (VOID
*)&PciIo
);
834 if (EFI_ERROR (Status
)) {
839 // Check for all PCI device
841 Status
= PciIo
->Pci
.Read (
845 sizeof (Pci
) / sizeof (UINT32
),
848 if (EFI_ERROR (Status
)) {
852 if (!DetectVgaOnly
) {
854 // Here we decide whether it is LPC Bridge
856 if ((IS_PCI_LPC (&Pci
)) ||
857 ((IS_PCI_ISA_PDECODE (&Pci
)) && (Pci
.Hdr
.VendorId
== 0x8086) && (Pci
.Hdr
.DeviceId
== 0x7110))) {
859 // Add IsaKeyboard to ConIn,
860 // add IsaSerial to ConOut, ConIn, ErrOut
862 DEBUG ((EFI_D_INFO
, "Find the LPC Bridge device\n"));
863 PrepareLpcBridgeDevicePath (HandleBuffer
[Index
]);
867 // Here we decide which Serial device to enable in PCI bus
869 if (IS_PCI_16550SERIAL (&Pci
)) {
871 // Add them to ConOut, ConIn, ErrOut.
873 DEBUG ((EFI_D_INFO
, "Find the 16550 SERIAL device\n"));
874 PreparePciSerialDevicePath (HandleBuffer
[Index
]);
880 // Here we decide which VGA device to enable in PCI bus
882 if (IS_PCI_VGA (&Pci
)) {
884 // Add them to ConOut.
886 DEBUG ((EFI_D_INFO
, "Find the VGA device\n"));
887 PreparePciVgaDevicePath (HandleBuffer
[Index
]);
892 gBS
->FreePool (HandleBuffer
);
898 PlatformBdsConnectConsole (
899 IN BDS_CONSOLE_CONNECT_ENTRY
*PlatformConsole
905 Connect the predefined platform default console device. Always try to find
906 and enable the vga device if have.
910 PlatformConsole - Predfined platform default console device array.
914 EFI_SUCCESS - Success connect at least one ConIn and ConOut
915 device, there must have one ConOut device is
918 EFI_STATUS - Return the status of
919 BdsLibConnectAllDefaultConsoles ()
925 EFI_DEVICE_PATH_PROTOCOL
*VarConout
;
926 EFI_DEVICE_PATH_PROTOCOL
*VarConin
;
927 UINTN DevicePathSize
;
930 // Connect RootBridge
932 ConnectRootBridge ();
934 VarConout
= BdsLibGetVariableAndSize (
936 &gEfiGlobalVariableGuid
,
939 VarConin
= BdsLibGetVariableAndSize (
941 &gEfiGlobalVariableGuid
,
945 if (VarConout
== NULL
|| VarConin
== NULL
) {
947 // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
949 DetectAndPreparePlatformPciDevicePath (FALSE
);
952 // Have chance to connect the platform default console,
953 // the platform default console is the minimue device group
954 // the platform should support
956 for (Index
= 0; PlatformConsole
[Index
].DevicePath
!= NULL
; ++Index
) {
958 // Update the console variable with the connect type
960 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_IN
) == CONSOLE_IN
) {
961 BdsLibUpdateConsoleVariable (VarConsoleInp
, PlatformConsole
[Index
].DevicePath
, NULL
);
963 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_OUT
) == CONSOLE_OUT
) {
964 BdsLibUpdateConsoleVariable (VarConsoleOut
, PlatformConsole
[Index
].DevicePath
, NULL
);
966 if ((PlatformConsole
[Index
].ConnectType
& STD_ERROR
) == STD_ERROR
) {
967 BdsLibUpdateConsoleVariable (VarErrorOut
, PlatformConsole
[Index
].DevicePath
, NULL
);
972 // Only detect VGA device and add them to ConOut
974 DetectAndPreparePlatformPciDevicePath (TRUE
);
978 // The ConIn devices connection will start the USB bus, should disable all
979 // Usb legacy support firstly.
980 // Caution: Must ensure the PCI bus driver has been started. Since the
981 // ConnectRootBridge() will create all the PciIo protocol, it's safe here now
983 Status
= DisableUsbLegacySupport();
986 // Connect the all the default console with current cosole variable
988 Status
= BdsLibConnectAllDefaultConsoles ();
989 if (EFI_ERROR (Status
)) {
997 PlatformBdsConnectSequence (
1002 Routine Description:
1004 Connect with predeined platform connect sequence,
1005 the OEM/IBV can customize with their own connect sequence.
1022 // Here we can get the customized platform connect sequence
1023 // Notes: we can connect with new variable which record the
1024 // last time boots connect device path sequence
1026 while (gPlatformConnectSequence
[Index
] != NULL
) {
1028 // Build the platform boot option
1030 BdsLibConnectDevicePath (gPlatformConnectSequence
[Index
]);
1037 PlatformBdsGetDriverOption (
1038 IN OUT LIST_ENTRY
*BdsDriverLists
1042 Routine Description:
1044 Load the predefined driver option, OEM/IBV can customize this
1045 to load their own drivers
1049 BdsDriverLists - The header of the driver option link list.
1062 // Here we can get the customized platform driver option
1064 while (gPlatformDriverOption
[Index
] != NULL
) {
1066 // Build the platform boot option
1068 BdsLibRegisterNewOption (BdsDriverLists
, gPlatformDriverOption
[Index
], NULL
, L
"DriverOrder");
1075 PlatformBdsDiagnostics (
1076 IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel
,
1077 IN BOOLEAN QuietBoot
,
1078 IN BASEM_MEMORY_TEST BaseMemoryTest
1082 Routine Description:
1084 Perform the platform diagnostic, such like test memory. OEM/IBV also
1085 can customize this fuction to support specific platform diagnostic.
1089 MemoryTestLevel - The memory test intensive level
1091 QuietBoot - Indicate if need to enable the quiet boot
1093 BaseMemoryTest - A pointer to BdsMemoryTest()
1104 // Here we can decide if we need to show
1105 // the diagnostics screen
1106 // Notes: this quiet boot code should be remove
1107 // from the graphic lib
1110 Status
= EnableQuietBoot (PcdGetPtr(PcdLogoFile
));
1111 if (EFI_ERROR (Status
)) {
1112 DisableQuietBoot ();
1117 // Perform system diagnostic
1119 Status
= BaseMemoryTest (MemoryTestLevel
);
1120 if (EFI_ERROR (Status
)) {
1121 DisableQuietBoot ();
1127 // Perform system diagnostic
1129 Status
= BaseMemoryTest (MemoryTestLevel
);
1134 PlatformBdsPolicyBehavior (
1135 IN OUT LIST_ENTRY
*DriverOptionList
,
1136 IN OUT LIST_ENTRY
*BootOptionList
,
1137 IN PROCESS_CAPSULES ProcessCapsules
,
1138 IN BASEM_MEMORY_TEST BaseMemoryTest
1142 Routine Description:
1144 The function will excute with as the platform policy, current policy
1145 is driven by boot mode. IBV/OEM can customize this code for their specific
1150 DriverOptionList - The header of the driver option link list
1152 BootOptionList - The header of the boot option link list
1162 EFI_EVENT UserInputDurationTime
;
1165 EFI_BOOT_MODE BootMode
;
1168 // Init the time out value
1170 Timeout
= PcdGet16 (PcdPlatformBootTimeOut
);
1173 // Load the driver option as the driver option list
1175 PlatformBdsGetDriverOption (DriverOptionList
);
1178 // Get current Boot Mode
1180 Status
= BdsLibGetBootMode (&BootMode
);
1181 DEBUG ((EFI_D_ERROR
, "Boot Mode:%x\n", BootMode
));
1184 // Go the different platform policy with different boot mode
1185 // Notes: this part code can be change with the table policy
1187 ASSERT (BootMode
== BOOT_WITH_FULL_CONFIGURATION
);
1189 // Connect platform console
1191 Status
= PlatformBdsConnectConsole (gPlatformConsole
);
1192 if (EFI_ERROR (Status
)) {
1194 // Here OEM/IBV can customize with defined action
1196 PlatformBdsNoConsoleAction ();
1199 // Create a 300ms duration event to ensure user has enough input time to enter Setup
1201 Status
= gBS
->CreateEvent (
1206 &UserInputDurationTime
1208 ASSERT (Status
== EFI_SUCCESS
);
1209 Status
= gBS
->SetTimer (UserInputDurationTime
, TimerRelative
, 3000000);
1210 ASSERT (Status
== EFI_SUCCESS
);
1212 // Memory test and Logo show
1214 PlatformBdsDiagnostics (IGNORE
, TRUE
, BaseMemoryTest
);
1217 // Perform some platform specific connect sequence
1219 PlatformBdsConnectSequence ();
1222 // Give one chance to enter the setup if we
1223 // have the time out
1225 // BUGBUG: hard code timeout to 5 second to show logo in graphic mode.
1228 PlatformBdsEnterFrontPage (Timeout
, FALSE
);
1232 //BdsLibConnectAll ();
1233 //BdsLibEnumerateAllBootOption (BootOptionList);
1236 // Please uncomment above ConnectAll and EnumerateAll code and remove following first boot
1237 // checking code in real production tip.
1239 // In BOOT_WITH_FULL_CONFIGURATION boot mode, should always connect every device
1240 // and do enumerate all the default boot options. But in development system board, the boot mode
1241 // cannot be BOOT_ASSUMING_NO_CONFIGURATION_CHANGES because the machine box
1242 // is always open. So the following code only do the ConnectAll and EnumerateAll at first boot.
1244 Status
= BdsLibBuildOptionFromVar (BootOptionList
, L
"BootOrder");
1245 if (EFI_ERROR(Status
)) {
1247 // If cannot find "BootOrder" variable, it may be first boot.
1248 // Try to connect all devices and enumerate all boot options here.
1250 BdsLibConnectAll ();
1251 BdsLibEnumerateAllBootOption (BootOptionList
);
1255 // To give the User a chance to enter Setup here, if user set TimeOut is 0.
1256 // BDS should still give user a chance to enter Setup
1257 // Check whether the user input after the duration time has expired
1259 gBS
->WaitForEvent (1, &UserInputDurationTime
, &Index
);
1260 gBS
->CloseEvent (UserInputDurationTime
);
1261 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
1263 if (!EFI_ERROR (Status
)) {
1265 // Enter Setup if user input
1268 PlatformBdsEnterFrontPage (Timeout
, FALSE
);
1277 PlatformBdsBootSuccess (
1278 IN BDS_COMMON_OPTION
*Option
1282 Routine Description:
1284 Hook point after a boot attempt succeeds. We don't expect a boot option to
1285 return, so the EFI 1.0 specification defines that you will default to an
1286 interactive mode and stop processing the BootOrder list in this case. This
1287 is alos a platform implementation and can be customized by IBV/OEM.
1291 Option - Pointer to Boot Option that succeeded to boot.
1302 // If Boot returned with EFI_SUCCESS and there is not in the boot device
1303 // select loop then we need to pop up a UI and wait for user input.
1305 TmpStr
= Option
->StatusString
;
1306 if (TmpStr
!= NULL
) {
1307 BdsLibOutputStrings (gST
->ConOut
, TmpStr
, Option
->Description
, L
"\n\r", NULL
);
1308 gBS
->FreePool (TmpStr
);
1314 PlatformBdsBootFail (
1315 IN BDS_COMMON_OPTION
*Option
,
1316 IN EFI_STATUS Status
,
1317 IN CHAR16
*ExitData
,
1318 IN UINTN ExitDataSize
1322 Routine Description:
1324 Hook point after a boot attempt fails.
1328 Option - Pointer to Boot Option that failed to boot.
1330 Status - Status returned from failed boot.
1332 ExitData - Exit data returned from failed boot.
1334 ExitDataSize - Exit data size returned from failed boot.
1345 // If Boot returned with failed status then we need to pop up a UI and wait
1348 TmpStr
= Option
->StatusString
;
1349 if (TmpStr
!= NULL
) {
1350 BdsLibOutputStrings (gST
->ConOut
, TmpStr
, Option
->Description
, L
"\n\r", NULL
);
1351 gBS
->FreePool (TmpStr
);
1357 PlatformBdsNoConsoleAction (
1362 Routine Description:
1364 This function is remained for IBV/OEM to do some platform action,
1365 if there no console device can be connected.
1373 EFI_SUCCESS - Direct return success now.
1381 ConvertSystemTable (
1382 IN EFI_GUID
*TableGuid
,
1387 Routine Description:
1388 Convert ACPI Table /Smbios Table /MP Table if its location is lower than Address:0x100000
1390 As in legacy Bios, ACPI/Smbios/MP table is required to place in E/F Seg,
1391 So here we just check if the range is E/F seg,
1392 and if Not, assume the Memory type is EfiACPIReclaimMemory/EfiACPIMemoryNVS
1395 TableGuid - Guid of the table
1396 Table - pointer to the table
1399 EFI_SUCEESS - Convert Table successfully
1409 // If match acpi guid (1.0, 2.0, or later), Convert ACPI table according to version.
1411 AcpiHeader
= (VOID
*)(UINTN
)(*(UINT64
*)(*Table
));
1413 if (CompareGuid(TableGuid
, &gEfiAcpiTableGuid
) || CompareGuid(TableGuid
, &gEfiAcpi20TableGuid
)){
1414 if (((EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER
*)AcpiHeader
)->Reserved
== 0x00){
1416 // If Acpi 1.0 Table, then RSDP structure doesn't contain Length field, use structure size
1418 AcpiTableLen
= sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER
);
1419 } else if (((EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER
*)AcpiHeader
)->Reserved
>= 0x02){
1421 // If Acpi 2.0 or later, use RSDP Length fied.
1423 AcpiTableLen
= ((EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER
*)AcpiHeader
)->Length
;
1426 // Invalid Acpi Version, return
1428 return EFI_UNSUPPORTED
;
1430 Status
= ConvertAcpiTable (AcpiTableLen
, Table
);
1435 // If matches smbios guid, convert Smbios table.
1437 if (CompareGuid(TableGuid
, &gEfiSmbiosTableGuid
)){
1438 Status
= ConvertSmbiosTable (Table
);
1443 // If the table is MP table?
1445 if (CompareGuid(TableGuid
, &gEfiMpsTableGuid
)){
1446 Status
= ConvertMpsTable (Table
);
1450 return EFI_UNSUPPORTED
;
1461 Routine Description:
1462 Convert RSDP of ACPI Table if its location is lower than Address:0x100000
1464 As in legacy Bios, ACPI table is required to place in E/F Seg,
1465 So here we just check if the range is E/F seg,
1466 and if Not, assume the Memory type is EfiACPIReclaimMemory/EfiACPIMemoryNVS
1469 TableLen - Acpi RSDP length
1470 Table - pointer to the table
1473 EFI_SUCEESS - Convert Table successfully
1481 EFI_PHYSICAL_ADDRESS BufferPtr
;
1484 AcpiTableOri
= (VOID
*)(UINTN
)(*(UINT64
*)(*Table
));
1485 if (((UINTN
)AcpiTableOri
< 0x100000) && ((UINTN
)AcpiTableOri
> 0xE0000)) {
1486 BufferPtr
= EFI_SYSTEM_TABLE_MAX_ADDRESS
;
1487 Status
= gBS
->AllocatePages (
1490 EFI_SIZE_TO_PAGES(TableLen
),
1493 ASSERT_EFI_ERROR (Status
);
1494 AcpiTableNew
= (VOID
*)(UINTN
)BufferPtr
;
1495 CopyMem (AcpiTableNew
, AcpiTableOri
, TableLen
);
1497 AcpiTableNew
= AcpiTableOri
;
1500 // Change configuration table Pointer
1502 *Table
= AcpiTableNew
;
1508 ConvertSmbiosTable (
1513 Routine Description:
1515 Convert Smbios Table if the Location of the SMBios Table is lower than Addres 0x100000
1517 As in legacy Bios, Smbios table is required to place in E/F Seg,
1518 So here we just check if the range is F seg,
1519 and if Not, assume the Memory type is EfiACPIMemoryNVS/EfiRuntimeServicesData
1521 Table - pointer to the table
1524 EFI_SUCEESS - Convert Table successfully
1529 SMBIOS_TABLE_ENTRY_POINT
*SmbiosTableNew
;
1530 SMBIOS_TABLE_ENTRY_POINT
*SmbiosTableOri
;
1532 UINT32 SmbiosEntryLen
;
1534 EFI_PHYSICAL_ADDRESS BufferPtr
;
1536 SmbiosTableNew
= NULL
;
1537 SmbiosTableOri
= NULL
;
1540 // Get Smibos configuration Table
1542 SmbiosTableOri
= (SMBIOS_TABLE_ENTRY_POINT
*)(UINTN
)(*(UINT64
*)(*Table
));
1544 if ((SmbiosTableOri
== NULL
) ||
1545 ((UINTN
)SmbiosTableOri
> 0x100000) ||
1546 ((UINTN
)SmbiosTableOri
< 0xF0000)){
1550 // Relocate the Smibos memory
1552 BufferPtr
= EFI_SYSTEM_TABLE_MAX_ADDRESS
;
1553 if (SmbiosTableOri
->SmbiosBcdRevision
!= 0x21) {
1554 SmbiosEntryLen
= SmbiosTableOri
->EntryPointLength
;
1557 // According to Smbios Spec 2.4, we should set entry point length as 0x1F if version is 2.1
1559 SmbiosEntryLen
= 0x1F;
1561 BufferLen
= SmbiosEntryLen
+ SYS_TABLE_PAD(SmbiosEntryLen
) + SmbiosTableOri
->TableLength
;
1562 Status
= gBS
->AllocatePages (
1565 EFI_SIZE_TO_PAGES(BufferLen
),
1568 ASSERT_EFI_ERROR (Status
);
1569 SmbiosTableNew
= (SMBIOS_TABLE_ENTRY_POINT
*)(UINTN
)BufferPtr
;
1576 // Get Smbios Structure table address, and make sure the start address is 32-bit align
1578 BufferPtr
+= SmbiosEntryLen
+ SYS_TABLE_PAD(SmbiosEntryLen
);
1580 (VOID
*)(UINTN
)BufferPtr
,
1581 (VOID
*)(UINTN
)(SmbiosTableOri
->TableAddress
),
1582 SmbiosTableOri
->TableLength
1584 SmbiosTableNew
->TableAddress
= (UINT32
)BufferPtr
;
1585 SmbiosTableNew
->IntermediateChecksum
= 0;
1586 SmbiosTableNew
->IntermediateChecksum
=
1587 CalculateCheckSum8 ((UINT8
*)SmbiosTableNew
+ 0x10, SmbiosEntryLen
-0x10);
1589 // Change the SMBIOS pointer
1591 *Table
= SmbiosTableNew
;
1602 Routine Description:
1604 Convert MP Table if the Location of the SMBios Table is lower than Addres 0x100000
1606 As in legacy Bios, MP table is required to place in E/F Seg,
1607 So here we just check if the range is E/F seg,
1608 and if Not, assume the Memory type is EfiACPIMemoryNVS/EfiRuntimeServicesData
1610 Table - pointer to the table
1613 EFI_SUCEESS - Convert Table successfully
1620 EFI_LEGACY_MP_TABLE_FLOATING_POINTER
*MpsFloatingPointerOri
;
1621 EFI_LEGACY_MP_TABLE_FLOATING_POINTER
*MpsFloatingPointerNew
;
1622 EFI_LEGACY_MP_TABLE_HEADER
*MpsTableOri
;
1623 EFI_LEGACY_MP_TABLE_HEADER
*MpsTableNew
;
1627 EFI_PHYSICAL_ADDRESS BufferPtr
;
1630 // Get MP configuration Table
1632 MpsFloatingPointerOri
= (EFI_LEGACY_MP_TABLE_FLOATING_POINTER
*)(UINTN
)(*(UINT64
*)(*Table
));
1633 if (!(((UINTN
)MpsFloatingPointerOri
<= 0x100000) &&
1634 ((UINTN
)MpsFloatingPointerOri
>= 0xF0000))){
1638 // Get Floating pointer structure length
1640 FPLength
= MpsFloatingPointerOri
->Length
* 16;
1641 Data32
= FPLength
+ SYS_TABLE_PAD (FPLength
);
1642 MpsTableOri
= (EFI_LEGACY_MP_TABLE_HEADER
*)(UINTN
)(MpsFloatingPointerOri
->PhysicalAddress
);
1643 if (MpsTableOri
!= NULL
) {
1644 Data32
+= MpsTableOri
->BaseTableLength
;
1645 Data32
+= MpsTableOri
->ExtendedTableLength
;
1646 if (MpsTableOri
->OemTablePointer
!= 0x00) {
1647 Data32
+= SYS_TABLE_PAD (Data32
);
1648 Data32
+= MpsTableOri
->OemTableSize
;
1656 BufferPtr
= EFI_SYSTEM_TABLE_MAX_ADDRESS
;
1657 Status
= gBS
->AllocatePages (
1660 EFI_SIZE_TO_PAGES(Data32
),
1663 ASSERT_EFI_ERROR (Status
);
1664 MpsFloatingPointerNew
= (EFI_LEGACY_MP_TABLE_FLOATING_POINTER
*)(UINTN
)BufferPtr
;
1665 CopyMem (MpsFloatingPointerNew
, MpsFloatingPointerOri
, FPLength
);
1667 // If Mp Table exists
1669 if (MpsTableOri
!= NULL
) {
1671 // Get Mps table length, including Ext table
1673 BufferPtr
= BufferPtr
+ FPLength
+ SYS_TABLE_PAD (FPLength
);
1674 MpsTableNew
= (EFI_LEGACY_MP_TABLE_HEADER
*)(UINTN
)BufferPtr
;
1675 CopyMem (MpsTableNew
, MpsTableOri
, MpsTableOri
->BaseTableLength
+ MpsTableOri
->ExtendedTableLength
);
1677 if ((MpsTableOri
->OemTableSize
!= 0x0000) && (MpsTableOri
->OemTablePointer
!= 0x0000)){
1678 BufferPtr
+= MpsTableOri
->BaseTableLength
+ MpsTableOri
->ExtendedTableLength
;
1679 BufferPtr
+= SYS_TABLE_PAD (BufferPtr
);
1680 OemTableNew
= (VOID
*)(UINTN
)BufferPtr
;
1681 OemTableOri
= (VOID
*)(UINTN
)MpsTableOri
->OemTablePointer
;
1682 CopyMem (OemTableNew
, OemTableOri
, MpsTableOri
->OemTableSize
);
1683 MpsTableNew
->OemTablePointer
= (UINT32
)(UINTN
)OemTableNew
;
1685 MpsTableNew
->Checksum
= 0;
1686 MpsTableNew
->Checksum
= CalculateCheckSum8 ((UINT8
*)MpsTableNew
, MpsTableOri
->BaseTableLength
);
1687 MpsFloatingPointerNew
->PhysicalAddress
= (UINT32
)(UINTN
)MpsTableNew
;
1688 MpsFloatingPointerNew
->Checksum
= 0;
1689 MpsFloatingPointerNew
->Checksum
= CalculateCheckSum8 ((UINT8
*)MpsFloatingPointerNew
, FPLength
);
1692 // Change the pointer
1694 *Table
= MpsFloatingPointerNew
;
1700 Lock the ConsoleIn device in system table. All key
1701 presses will be ignored until the Password is typed in. The only way to
1702 disable the password is to type it in to a ConIn device.
1704 @param Password Password used to lock ConIn device.
1706 @retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully.
1707 @retval EFI_UNSUPPORTED Password not found
1716 return EFI_UNSUPPORTED
;
1720 This function locks platform flash that is not allowed to be updated during normal boot path.
1721 The flash layout is platform specific.
1726 PlatformBdsLockNonUpdatableFlash (