From 2ef2b01e07c02db339f34004445734a2dbdd80e1 Mon Sep 17 00:00:00 2001 From: AJFISH Date: Sun, 6 Dec 2009 01:57:05 +0000 Subject: [PATCH] Adding support for BeagleBoard. ArmPkg - Supoprt for ARM specific things that can change as the architecture changes. Plus semihosting JTAG drivers. EmbeddedPkg - Generic support for an embeddded platform. Including a light weight command line shell. BeagleBoardPkg - Platform specifics for BeagleBoard. SD Card works, but USB has issues. Looks like a bug in the open source USB stack (Our internal stack works fine). git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@9518 6f19259b-4bc3-4df7-8a09-765794883524 --- ArmPkg/ArmPkg.dec | 36 + ArmPkg/ArmPkg.dsc | 61 + ArmPkg/Drivers/CpuDxe/CpuDxe.c | 154 ++ ArmPkg/Drivers/CpuDxe/CpuDxe.h | 91 + ArmPkg/Drivers/CpuDxe/CpuDxe.inf | 56 + ArmPkg/Drivers/CpuDxe/DebugSupport.c | 247 +++ ArmPkg/Drivers/CpuDxe/Exception.c | 238 +++ ArmPkg/Drivers/CpuDxe/ExceptionSupport.S | 152 ++ ArmPkg/Drivers/CpuDxe/ExceptionSupport.asm | 152 ++ ArmPkg/Drivers/DebugSupportDxe/DebugSupport.c | 119 ++ .../DebugSupportDxe/DebugSupportDxe.inf | 30 + ArmPkg/Filesystem/SemihostFs/Arm/SemihostFs.c | 526 ++++++ ArmPkg/Filesystem/SemihostFs/Arm/SemihostFs.h | 114 ++ ArmPkg/Filesystem/SemihostFs/SemihostFs.inf | 48 + ArmPkg/Include/AsmMacroIoLib.h | 236 +++ ArmPkg/Include/AsmMacroIoLib.inc | 74 + ArmPkg/Include/Chipset/ARM1176JZ-S.h | 111 ++ ArmPkg/Include/Chipset/ARM926EJ-S.h | 71 + ArmPkg/Include/Chipset/Cortex-A8.h | 104 ++ ArmPkg/Include/Library/ArmLib.h | 294 ++++ ArmPkg/Include/Library/SemihostLib.h | 100 ++ .../Library/UncachedMemoryAllocationLib.h | 665 ++++++++ ArmPkg/Include/Protocol/TimerDebugSupport.h | 59 + .../ArmCacheMaintenanceLib.c | 129 ++ .../ArmCacheMaintenanceLib.inf | 23 + ArmPkg/Library/ArmLib/Arm11/Arm11ArmLib.inf | 32 + .../Library/ArmLib/Arm11/Arm11ArmLibPrePi.inf | 32 + ArmPkg/Library/ArmLib/Arm11/Arm11Lib.c | 118 ++ ArmPkg/Library/ArmLib/Arm11/Arm11Support.S | 129 ++ ArmPkg/Library/ArmLib/Arm11/Arm11Support.asm | 133 ++ ArmPkg/Library/ArmLib/Arm9/Arm9ArmLib.inf | 32 + .../Library/ArmLib/Arm9/Arm9ArmLibPrePi.inf | 32 + .../ArmLib/Arm9/Arm9CacheInformation.c | 164 ++ ArmPkg/Library/ArmLib/Arm9/Arm9Lib.c | 118 ++ ArmPkg/Library/ArmLib/Arm9/Arm9Support.S | 128 ++ ArmPkg/Library/ArmLib/Arm9/Arm9Support.asm | 129 ++ .../Library/ArmLib/ArmCortexA/ArmCortexALib.c | 288 ++++ .../Library/ArmLib/ArmCortexA/ArmCortexALib.h | 45 + .../ArmLib/ArmCortexA/ArmCortexASupport.S | 140 ++ .../ArmLib/ArmCortexA/ArmCortexASupport.asm | 141 ++ .../ArmLib/ArmCortexA/ArmCortexArmLib.inf | 31 + .../ArmCortexA/ArmCortexArmLibPrePi.inf | 31 + ArmPkg/Library/ArmLib/Common/ArmLib.c | 60 + ArmPkg/Library/ArmLib/Common/ArmLibPrivate.h | 70 + ArmPkg/Library/ArmLib/Common/ArmLibSupport.S | 89 + .../Library/ArmLib/Common/ArmLibSupport.asm | 90 + .../ArmLib/Null/NullArmCacheInformation.c | 106 ++ ArmPkg/Library/ArmLib/Null/NullArmLib.c | 117 ++ ArmPkg/Library/ArmLib/Null/NullArmLib.inf | 26 + .../CompilerIntrinsicsLib/Arm/Llvm_int_lib.h | 83 + .../CompilerIntrinsicsLib/Arm/ashldi3.S | 38 + .../CompilerIntrinsicsLib/Arm/ashldi3.c | 83 + .../CompilerIntrinsicsLib/Arm/ashrdi3.S | 39 + .../CompilerIntrinsicsLib/Arm/ashrdi3.c | 84 + .../CompilerIntrinsicsLib/Arm/clzsi2.c | 96 ++ .../CompilerIntrinsicsLib/Arm/ctzsi2.c | 111 ++ .../Library/CompilerIntrinsicsLib/Arm/div.asm | 155 ++ .../CompilerIntrinsicsLib/Arm/divdi3.S | 48 + .../CompilerIntrinsicsLib/Arm/divdi3.c | 77 + .../CompilerIntrinsicsLib/Arm/divsi3.S | 33 + .../CompilerIntrinsicsLib/Arm/divsi3.c | 78 + .../CompilerIntrinsicsLib/Arm/lasr.asm | 41 + .../CompilerIntrinsicsLib/Arm/ldivmod.asm | 54 + .../CompilerIntrinsicsLib/Arm/llsl.asm | 43 + .../CompilerIntrinsicsLib/Arm/llsr.asm | 44 + .../CompilerIntrinsicsLib/Arm/lshrdi3.S | 38 + .../CompilerIntrinsicsLib/Arm/lshrdi3.c | 83 + .../CompilerIntrinsicsLib/Arm/memcpy.S | 35 + .../CompilerIntrinsicsLib/Arm/memcpy.asm | 40 + .../CompilerIntrinsicsLib/Arm/memcpy4.asm | 61 + .../CompilerIntrinsicsLib/Arm/memset.S | 35 + .../CompilerIntrinsicsLib/Arm/moddi3.S | 47 + .../CompilerIntrinsicsLib/Arm/moddi3.c | 77 + .../CompilerIntrinsicsLib/Arm/modsi3.S | 28 + .../CompilerIntrinsicsLib/Arm/modsi3.c | 70 + .../CompilerIntrinsicsLib/Arm/muldi3.S | 59 + .../CompilerIntrinsicsLib/Arm/muldi3.c | 98 ++ .../CompilerIntrinsicsLib/Arm/mullu.asm | 49 + .../CompilerIntrinsicsLib/Arm/switch.asm | 29 + .../CompilerIntrinsicsLib/Arm/switch16.S | 46 + .../CompilerIntrinsicsLib/Arm/switch32.S | 45 + .../CompilerIntrinsicsLib/Arm/switch8.S | 43 + .../CompilerIntrinsicsLib/Arm/switchu8.S | 43 + .../CompilerIntrinsicsLib/Arm/ucmpdi2.c | 82 + .../CompilerIntrinsicsLib/Arm/udivdi3.S | 28 + .../CompilerIntrinsicsLib/Arm/udivdi3.c | 71 + .../CompilerIntrinsicsLib/Arm/udivmoddi4.S | 243 +++ .../CompilerIntrinsicsLib/Arm/udivmoddi4.c | 287 ++++ .../CompilerIntrinsicsLib/Arm/udivsi3.S | 57 + .../CompilerIntrinsicsLib/Arm/udivsi3.c | 111 ++ .../CompilerIntrinsicsLib/Arm/uldiv.asm | 268 +++ .../CompilerIntrinsicsLib/Arm/umoddi3.S | 30 + .../CompilerIntrinsicsLib/Arm/umoddi3.c | 72 + .../CompilerIntrinsicsLib/Arm/umodsi3.S | 40 + .../CompilerIntrinsicsLib/Arm/umodsi3.c | 68 + .../CompilerIntrinsicsLib/Arm/uread.asm | 38 + .../CompilerIntrinsicsLib/Arm/uwrite.asm | 40 + .../CompilerIntrinsicsLib.inf | 92 + ArmPkg/Library/SemiHostingDebugLib/DebugLib.c | 258 +++ .../SemiHostingDebugLib.inf | 46 + .../SemiHostingSerialPortLib.inf | 35 + .../SemiHostingSerialPortLib/SerialPortLib.c | 144 ++ ArmPkg/Library/SemihostLib/Arm/SemihostLib.c | 221 +++ .../Library/SemihostLib/Arm/SemihostPrivate.h | 162 ++ ArmPkg/Library/SemihostLib/SemihostLib.inf | 32 + .../UncachedMemoryAllocationLib.c | 626 +++++++ .../UncachedMemoryAllocationLib.inf | 25 + BeagleBoardPkg/AppleBeagleBoardPkg.dsc | 366 ++++ BeagleBoardPkg/AppleBeagleBoardPkg.fdf | 303 ++++ BeagleBoardPkg/Bds/Bds.inf | 70 + BeagleBoardPkg/Bds/BdsEntry.c | 240 +++ BeagleBoardPkg/Bds/BdsEntry.h | 65 + BeagleBoardPkg/Bds/FirmwareVolume.c | 150 ++ BeagleBoardPkg/BeagleBoardPkg.dec | 65 + BeagleBoardPkg/BeagleBoardPkg.dsc | 415 +++++ BeagleBoardPkg/BeagleBoardPkg.fdf | 296 ++++ BeagleBoardPkg/ConfigurationHeader.dat | 41 + .../Debugger_scripts/rvi_boot_from_ram.inc | 21 + .../Debugger_scripts/rvi_convert_symbols.sh | 23 + BeagleBoardPkg/Debugger_scripts/rvi_dummy.axf | Bin 0 -> 7984 bytes .../Debugger_scripts/rvi_hw_setup.inc | 67 + .../Debugger_scripts/rvi_load_symbols.inc | 23 + .../Debugger_scripts/rvi_symbols_macros.inc | 194 +++ .../Debugger_scripts/rvi_unload_symbols.inc | 118 ++ .../Debugger_scripts/trace32_load_symbols.cmm | 211 +++ .../trace32_load_symbols_cygwin.cmm | 188 +++ BeagleBoardPkg/Flash/Flash.c | 748 +++++++++ BeagleBoardPkg/Flash/Flash.h | 118 ++ BeagleBoardPkg/Flash/Flash.inf | 36 + BeagleBoardPkg/Gpio/Gpio.c | 135 ++ BeagleBoardPkg/Gpio/Gpio.inf | 33 + .../Include/Library/BeagleBoardSystemLib.h | 36 + BeagleBoardPkg/Include/Library/OmapLib.h | 39 + BeagleBoardPkg/Include/Omap3530/Omap3530.h | 38 + .../Include/Omap3530/Omap3530Gpio.h | 131 ++ .../Include/Omap3530/Omap3530Gpmc.h | 107 ++ BeagleBoardPkg/Include/Omap3530/Omap3530I2c.h | 62 + .../Include/Omap3530/Omap3530Interrupt.h | 46 + .../Include/Omap3530/Omap3530MMCHS.h | 208 +++ .../Omap3530/Omap3530PadConfiguration.h | 298 ++++ .../Include/Omap3530/Omap3530Prcm.h | 164 ++ .../Include/Omap3530/Omap3530Timer.h | 82 + .../Include/Omap3530/Omap3530Uart.h | 53 + BeagleBoardPkg/Include/Omap3530/Omap3530Usb.h | 42 + BeagleBoardPkg/Include/TPS65950.h | 46 + .../InterruptDxe/HardwareInterrupt.c | 339 ++++ BeagleBoardPkg/InterruptDxe/InterruptDxe.inf | 56 + .../BeagleBoardSystemLib.c | 110 ++ .../BeagleBoardSystemLib.inf | 45 + .../BeagleBoardSystemLib/GoLittleEndian.S | 27 + .../BeagleBoardSystemLib/GoLittleEndian.asm | 27 + .../BeagleBoardTimerLib.inf | 46 + .../Library/BeagleBoardTimerLib/TimerLib.c | 102 ++ BeagleBoardPkg/Library/EblCmdLib/EblCmdLib.c | 42 + .../Library/EblCmdLib/EblCmdLib.inf | 49 + .../Library/GdbSerialLib/GdbSerialLib.c | 103 ++ .../Library/GdbSerialLib/GdbSerialLib.inf | 29 + BeagleBoardPkg/Library/OmapLib/OmapLib.c | 83 + BeagleBoardPkg/Library/OmapLib/OmapLib.inf | 25 + .../Library/ResetSystemLib/ResetSystemLib.c | 84 + .../Library/ResetSystemLib/ResetSystemLib.inf | 41 + .../Library/SerialPortLib/SerialPortLib.c | 124 ++ .../Library/SerialPortLib/SerialPortLib.inf | 44 + BeagleBoardPkg/MMCHSDxe/MMCHS.c | 1018 +++++++++++ BeagleBoardPkg/MMCHSDxe/MMCHS.h | 158 ++ BeagleBoardPkg/MMCHSDxe/MMCHS.inf | 39 + BeagleBoardPkg/PciEmulation/PciEmulation.c | 584 +++++++ BeagleBoardPkg/PciEmulation/PciEmulation.h | 305 ++++ BeagleBoardPkg/PciEmulation/PciEmulation.inf | 58 + BeagleBoardPkg/PciEmulation/PciRootBridgeIo.c | 306 ++++ BeagleBoardPkg/Sec/Arm/Macro.inc | 67 + BeagleBoardPkg/Sec/Arm/ModuleEntryPoint.S | 93 ++ BeagleBoardPkg/Sec/Arm/ModuleEntryPoint.asm | 95 ++ BeagleBoardPkg/Sec/Cache.c | 88 + BeagleBoardPkg/Sec/Clock.c | 70 + BeagleBoardPkg/Sec/PadConfiguration.c | 282 ++++ BeagleBoardPkg/Sec/Sec.c | 165 ++ BeagleBoardPkg/Sec/Sec.inf | 66 + BeagleBoardPkg/SmbusDxe/Smbus.c | 325 ++++ BeagleBoardPkg/SmbusDxe/Smbus.inf | 33 + BeagleBoardPkg/TPS65950Dxe/TPS65950.c | 116 ++ BeagleBoardPkg/TPS65950Dxe/TPS65950.inf | 36 + BeagleBoardPkg/TimerDxe/Timer.c | 239 +++ BeagleBoardPkg/TimerDxe/TimerDxe.inf | 60 + BeagleBoardPkg/Tools/GNUmakefile | 20 + BeagleBoardPkg/Tools/generate_image.c | 410 +++++ BeagleBoardPkg/build.sh | 127 ++ BeagleBoardPkg/readme.txt | 11 + EmbeddedPkg/DebugSupportDxe/DebugSupport.c | 119 ++ .../DebugSupportDxe/DebugSupportDxe.inf | 28 + EmbeddedPkg/Ebl/CmdTemplate.c | 65 + EmbeddedPkg/Ebl/Command.c | 978 +++++++++++ EmbeddedPkg/Ebl/Dir.c | 305 ++++ EmbeddedPkg/Ebl/Ebl.h | 194 +++ EmbeddedPkg/Ebl/Ebl.inf | 110 ++ EmbeddedPkg/Ebl/EfiDevice.c | 969 +++++++++++ EmbeddedPkg/Ebl/Hob.c | 232 +++ EmbeddedPkg/Ebl/HwDebug.c | 342 ++++ EmbeddedPkg/Ebl/HwIoDebug.c | 153 ++ EmbeddedPkg/Ebl/Main.c | 616 +++++++ EmbeddedPkg/Ebl/Network.c | 104 ++ EmbeddedPkg/Ebl/Script.c | 126 ++ EmbeddedPkg/EblExternCmd/EntryPointGlue.c | 152 ++ EmbeddedPkg/EblExternCmd/Main.c | 52 + .../EmbeddedMonotonicCounter.c | 82 + .../EmbeddedMonotonicCounter.inf | 29 + EmbeddedPkg/EmbeddedPkg.dec | 126 ++ EmbeddedPkg/EmbeddedPkg.dsc | 266 +++ EmbeddedPkg/EmbeddedPkg.fdf | 141 ++ EmbeddedPkg/GdbStub/Arm/Processor.c | 717 ++++++++ EmbeddedPkg/GdbStub/GdbStub.c | 1264 ++++++++++++++ EmbeddedPkg/GdbStub/GdbStub.inf | 78 + EmbeddedPkg/GdbStub/GdbStubInternal.h | 746 +++++++++ EmbeddedPkg/GdbStub/Ia32/Processor.c | 993 +++++++++++ EmbeddedPkg/GdbStub/SerialIo.c | 551 ++++++ EmbeddedPkg/GdbStub/X64/Processor.c | 963 +++++++++++ .../Library/EblAddExternalCommandLib.h | 122 ++ EmbeddedPkg/Include/Library/EblCmdLib.h | 48 + EmbeddedPkg/Include/Library/EblNetworkLib.h | 68 + EmbeddedPkg/Include/Library/EfiFileLib.h | 315 ++++ .../Include/Library/EfiResetSystemLib.h | 58 + EmbeddedPkg/Include/Library/GdbSerialLib.h | 107 ++ .../Include/Library/HalRuntimeServicesLib.h | 165 ++ EmbeddedPkg/Include/Library/PrePiLib.h | 766 +++++++++ .../Include/Library/RealTimeClockLib.h | 138 ++ .../Protocol/DebugSupportPeriodicCallback.h | 42 + EmbeddedPkg/Include/Protocol/EblAddCommand.h | 156 ++ EmbeddedPkg/Include/Protocol/EmbeddedDevice.h | 58 + .../Include/Protocol/EmbeddedExternalDevice.h | 94 ++ EmbeddedPkg/Include/Protocol/EmbeddedGpio.h | 167 ++ .../Include/Protocol/HardwareInterrupt.h | 151 ++ .../EblAddExternalCommandLib.c | 156 ++ .../EblAddExternalCommandLib.inf | 47 + .../Library/EblCmdLibNull/EblCmdLibNull.c | 28 + .../Library/EblCmdLibNull/EblCmdLibNull.inf | 45 + .../Library/EblNetworkLib/EblNetworkLib.c | 173 ++ .../Library/EblNetworkLib/EblNetworkLib.inf | 28 + EmbeddedPkg/Library/EfiFileLib/EfiFileLib.c | 1483 +++++++++++++++++ EmbeddedPkg/Library/EfiFileLib/EfiFileLib.inf | 64 + .../GdbSerialDebugPortLib.c | 187 +++ .../GdbSerialDebugPortLib.inf | 50 + .../Library/GdbSerialLib/GdbSerialLib.c | 262 +++ .../Library/GdbSerialLib/GdbSerialLib.inf | 47 + .../HalRuntimeServicesExampleLib/Capsule.c | 288 ++++ .../HalRuntimeServicesExampleLib/Mtc.c | 226 +++ .../ReportStatusCode.c | 198 +++ .../HalRuntimeServicesExampleLib/Reset.c | 63 + .../HalRuntimeServicesExampleLib/Rtc.c | 861 ++++++++++ .../HalRuntimeServicesExampleLib/Variable.c | 306 ++++ .../PrePiExtractGuidedSectionLib.c | 247 +++ .../PrePiExtractGuidedSectionLib.inf | 24 + EmbeddedPkg/Library/PrePiLib/FwVol.c | 841 ++++++++++ EmbeddedPkg/Library/PrePiLib/Hob.c | 808 +++++++++ EmbeddedPkg/Library/PrePiLib/Memory.c | 160 ++ EmbeddedPkg/Library/PrePiLib/PrePi.h | 44 + EmbeddedPkg/Library/PrePiLib/PrePiLib.c | 231 +++ EmbeddedPkg/Library/PrePiLib/PrePiLib.inf | 90 + .../Library/PrePiLib/ReportStatusCode.c | 327 ++++ .../Library/SemiHostingDebugLib/DebugLib.c | 258 +++ .../SemiHostingDebugLib.inf | 46 + .../SemiHostingSerialPortLib.inf | 35 + .../SemiHostingSerialPortLib/SerialPortLib.c | 145 ++ .../RealTimeClockLib.c | 175 ++ .../TemplateRealTimeClockLib.inf | 38 + .../TemplateResetSystemLib/ResetSystemLib.c | 103 ++ .../TemplateResetSystemLib.inf | 36 + .../TemplateSerialPortLib.c | 99 ++ .../TemplateSerialPortLib.inf | 37 + .../RealTimeClockRuntimeDxe/RealTimeClock.c | 158 ++ .../RealTimeClockRuntimeDxe.inf | 45 + .../ResetRuntimeDxe/ResetRuntimeDxe.inf | 51 + EmbeddedPkg/ResetRuntimeDxe/reset.c | 74 + EmbeddedPkg/SerialDxe/SerialDxe.inf | 54 + EmbeddedPkg/SerialDxe/SerialIo.c | 258 +++ .../SimpleTextInOutSerial/SimpleTextInOut.c | 671 ++++++++ .../SimpleTextInOutSerial.inf | 56 + EmbeddedPkg/TemplateBds/BdsEntry.c | 183 ++ EmbeddedPkg/TemplateBds/BdsEntry.h | 62 + EmbeddedPkg/TemplateBds/FirmwareVolume.c | 160 ++ EmbeddedPkg/TemplateBds/TemplateBds.inf | 68 + EmbeddedPkg/TemplateCpuDxe/Arm/Exception.c | 250 +++ EmbeddedPkg/TemplateCpuDxe/Arm/Exceptions.S | 158 ++ EmbeddedPkg/TemplateCpuDxe/Arm/Exceptions.asm | 152 ++ EmbeddedPkg/TemplateCpuDxe/CpuDxe.c | 323 ++++ EmbeddedPkg/TemplateCpuDxe/CpuDxe.h | 124 ++ EmbeddedPkg/TemplateCpuDxe/IA32/Exception.c | 183 ++ EmbeddedPkg/TemplateCpuDxe/TemplateCpuDxe.inf | 71 + EmbeddedPkg/TemplateCpuDxe/X64/Exception.c | 183 ++ EmbeddedPkg/TemplateMetronomeDxe/Metronome.c | 132 ++ .../TemplateMetronomeDxe.inf | 50 + EmbeddedPkg/TemplateSec/TemplateSec.c | 76 + EmbeddedPkg/TemplateSec/TemplateSec.inf | 66 + .../TemplateTimerDxe/TemplateTimerDxe.inf | 56 + EmbeddedPkg/TemplateTimerDxe/Timer.c | 373 +++++ 294 files changed, 47954 insertions(+) create mode 100644 ArmPkg/ArmPkg.dec create mode 100644 ArmPkg/ArmPkg.dsc create mode 100644 ArmPkg/Drivers/CpuDxe/CpuDxe.c create mode 100644 ArmPkg/Drivers/CpuDxe/CpuDxe.h create mode 100644 ArmPkg/Drivers/CpuDxe/CpuDxe.inf create mode 100644 ArmPkg/Drivers/CpuDxe/DebugSupport.c create mode 100644 ArmPkg/Drivers/CpuDxe/Exception.c create mode 100755 ArmPkg/Drivers/CpuDxe/ExceptionSupport.S create mode 100755 ArmPkg/Drivers/CpuDxe/ExceptionSupport.asm create mode 100644 ArmPkg/Drivers/DebugSupportDxe/DebugSupport.c create mode 100644 ArmPkg/Drivers/DebugSupportDxe/DebugSupportDxe.inf create mode 100644 ArmPkg/Filesystem/SemihostFs/Arm/SemihostFs.c create mode 100644 ArmPkg/Filesystem/SemihostFs/Arm/SemihostFs.h create mode 100644 ArmPkg/Filesystem/SemihostFs/SemihostFs.inf create mode 100644 ArmPkg/Include/AsmMacroIoLib.h create mode 100644 ArmPkg/Include/AsmMacroIoLib.inc create mode 100644 ArmPkg/Include/Chipset/ARM1176JZ-S.h create mode 100644 ArmPkg/Include/Chipset/ARM926EJ-S.h create mode 100644 ArmPkg/Include/Chipset/Cortex-A8.h create mode 100644 ArmPkg/Include/Library/ArmLib.h create mode 100644 ArmPkg/Include/Library/SemihostLib.h create mode 100644 ArmPkg/Include/Library/UncachedMemoryAllocationLib.h create mode 100644 ArmPkg/Include/Protocol/TimerDebugSupport.h create mode 100644 ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.c create mode 100644 ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.inf create mode 100644 ArmPkg/Library/ArmLib/Arm11/Arm11ArmLib.inf create mode 100644 ArmPkg/Library/ArmLib/Arm11/Arm11ArmLibPrePi.inf create mode 100644 ArmPkg/Library/ArmLib/Arm11/Arm11Lib.c create mode 100644 ArmPkg/Library/ArmLib/Arm11/Arm11Support.S create mode 100644 ArmPkg/Library/ArmLib/Arm11/Arm11Support.asm create mode 100644 ArmPkg/Library/ArmLib/Arm9/Arm9ArmLib.inf create mode 100755 ArmPkg/Library/ArmLib/Arm9/Arm9ArmLibPrePi.inf create mode 100644 ArmPkg/Library/ArmLib/Arm9/Arm9CacheInformation.c create mode 100644 ArmPkg/Library/ArmLib/Arm9/Arm9Lib.c create mode 100644 ArmPkg/Library/ArmLib/Arm9/Arm9Support.S create mode 100644 ArmPkg/Library/ArmLib/Arm9/Arm9Support.asm create mode 100644 ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexALib.c create mode 100644 ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexALib.h create mode 100644 ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexASupport.S create mode 100644 ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexASupport.asm create mode 100644 ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexArmLib.inf create mode 100644 ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexArmLibPrePi.inf create mode 100644 ArmPkg/Library/ArmLib/Common/ArmLib.c create mode 100644 ArmPkg/Library/ArmLib/Common/ArmLibPrivate.h create mode 100644 ArmPkg/Library/ArmLib/Common/ArmLibSupport.S create mode 100644 ArmPkg/Library/ArmLib/Common/ArmLibSupport.asm create mode 100644 ArmPkg/Library/ArmLib/Null/NullArmCacheInformation.c create mode 100644 ArmPkg/Library/ArmLib/Null/NullArmLib.c create mode 100644 ArmPkg/Library/ArmLib/Null/NullArmLib.inf create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/Llvm_int_lib.h create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashldi3.S create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashldi3.c create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashrdi3.S create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashrdi3.c create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/clzsi2.c create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/ctzsi2.c create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/div.asm create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/divdi3.S create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/divdi3.c create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/divsi3.S create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/divsi3.c create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/lasr.asm create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/ldivmod.asm create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/llsl.asm create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/llsr.asm create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/lshrdi3.S create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/lshrdi3.c create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/memcpy.S create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/memcpy.asm create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/memcpy4.asm create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/memset.S create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/moddi3.S create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/moddi3.c create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/modsi3.S create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/modsi3.c create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/muldi3.S create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/muldi3.c create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/mullu.asm create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch.asm create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch16.S create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch32.S create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch8.S create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/switchu8.S create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/ucmpdi2.c create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivdi3.S create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivdi3.c create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivmoddi4.S create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivmoddi4.c create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivsi3.S create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivsi3.c create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/uldiv.asm create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/umoddi3.S create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/umoddi3.c create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/umodsi3.S create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/umodsi3.c create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/uread.asm create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/Arm/uwrite.asm create mode 100644 ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf create mode 100644 ArmPkg/Library/SemiHostingDebugLib/DebugLib.c create mode 100644 ArmPkg/Library/SemiHostingDebugLib/SemiHostingDebugLib.inf create mode 100644 ArmPkg/Library/SemiHostingSerialPortLib/SemiHostingSerialPortLib.inf create mode 100644 ArmPkg/Library/SemiHostingSerialPortLib/SerialPortLib.c create mode 100644 ArmPkg/Library/SemihostLib/Arm/SemihostLib.c create mode 100644 ArmPkg/Library/SemihostLib/Arm/SemihostPrivate.h create mode 100644 ArmPkg/Library/SemihostLib/SemihostLib.inf create mode 100644 ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.c create mode 100644 ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.inf create mode 100644 BeagleBoardPkg/AppleBeagleBoardPkg.dsc create mode 100644 BeagleBoardPkg/AppleBeagleBoardPkg.fdf create mode 100644 BeagleBoardPkg/Bds/Bds.inf create mode 100644 BeagleBoardPkg/Bds/BdsEntry.c create mode 100644 BeagleBoardPkg/Bds/BdsEntry.h create mode 100644 BeagleBoardPkg/Bds/FirmwareVolume.c create mode 100644 BeagleBoardPkg/BeagleBoardPkg.dec create mode 100644 BeagleBoardPkg/BeagleBoardPkg.dsc create mode 100644 BeagleBoardPkg/BeagleBoardPkg.fdf create mode 100644 BeagleBoardPkg/ConfigurationHeader.dat create mode 100644 BeagleBoardPkg/Debugger_scripts/rvi_boot_from_ram.inc create mode 100755 BeagleBoardPkg/Debugger_scripts/rvi_convert_symbols.sh create mode 100755 BeagleBoardPkg/Debugger_scripts/rvi_dummy.axf create mode 100644 BeagleBoardPkg/Debugger_scripts/rvi_hw_setup.inc create mode 100644 BeagleBoardPkg/Debugger_scripts/rvi_load_symbols.inc create mode 100755 BeagleBoardPkg/Debugger_scripts/rvi_symbols_macros.inc create mode 100755 BeagleBoardPkg/Debugger_scripts/rvi_unload_symbols.inc create mode 100644 BeagleBoardPkg/Debugger_scripts/trace32_load_symbols.cmm create mode 100644 BeagleBoardPkg/Debugger_scripts/trace32_load_symbols_cygwin.cmm create mode 100644 BeagleBoardPkg/Flash/Flash.c create mode 100644 BeagleBoardPkg/Flash/Flash.h create mode 100644 BeagleBoardPkg/Flash/Flash.inf create mode 100644 BeagleBoardPkg/Gpio/Gpio.c create mode 100644 BeagleBoardPkg/Gpio/Gpio.inf create mode 100644 BeagleBoardPkg/Include/Library/BeagleBoardSystemLib.h create mode 100644 BeagleBoardPkg/Include/Library/OmapLib.h create mode 100644 BeagleBoardPkg/Include/Omap3530/Omap3530.h create mode 100644 BeagleBoardPkg/Include/Omap3530/Omap3530Gpio.h create mode 100644 BeagleBoardPkg/Include/Omap3530/Omap3530Gpmc.h create mode 100644 BeagleBoardPkg/Include/Omap3530/Omap3530I2c.h create mode 100644 BeagleBoardPkg/Include/Omap3530/Omap3530Interrupt.h create mode 100755 BeagleBoardPkg/Include/Omap3530/Omap3530MMCHS.h create mode 100644 BeagleBoardPkg/Include/Omap3530/Omap3530PadConfiguration.h create mode 100644 BeagleBoardPkg/Include/Omap3530/Omap3530Prcm.h create mode 100644 BeagleBoardPkg/Include/Omap3530/Omap3530Timer.h create mode 100644 BeagleBoardPkg/Include/Omap3530/Omap3530Uart.h create mode 100644 BeagleBoardPkg/Include/Omap3530/Omap3530Usb.h create mode 100644 BeagleBoardPkg/Include/TPS65950.h create mode 100644 BeagleBoardPkg/InterruptDxe/HardwareInterrupt.c create mode 100644 BeagleBoardPkg/InterruptDxe/InterruptDxe.inf create mode 100644 BeagleBoardPkg/Library/BeagleBoardSystemLib/BeagleBoardSystemLib.c create mode 100644 BeagleBoardPkg/Library/BeagleBoardSystemLib/BeagleBoardSystemLib.inf create mode 100644 BeagleBoardPkg/Library/BeagleBoardSystemLib/GoLittleEndian.S create mode 100755 BeagleBoardPkg/Library/BeagleBoardSystemLib/GoLittleEndian.asm create mode 100644 BeagleBoardPkg/Library/BeagleBoardTimerLib/BeagleBoardTimerLib.inf create mode 100755 BeagleBoardPkg/Library/BeagleBoardTimerLib/TimerLib.c create mode 100644 BeagleBoardPkg/Library/EblCmdLib/EblCmdLib.c create mode 100644 BeagleBoardPkg/Library/EblCmdLib/EblCmdLib.inf create mode 100644 BeagleBoardPkg/Library/GdbSerialLib/GdbSerialLib.c create mode 100644 BeagleBoardPkg/Library/GdbSerialLib/GdbSerialLib.inf create mode 100644 BeagleBoardPkg/Library/OmapLib/OmapLib.c create mode 100644 BeagleBoardPkg/Library/OmapLib/OmapLib.inf create mode 100644 BeagleBoardPkg/Library/ResetSystemLib/ResetSystemLib.c create mode 100644 BeagleBoardPkg/Library/ResetSystemLib/ResetSystemLib.inf create mode 100644 BeagleBoardPkg/Library/SerialPortLib/SerialPortLib.c create mode 100644 BeagleBoardPkg/Library/SerialPortLib/SerialPortLib.inf create mode 100644 BeagleBoardPkg/MMCHSDxe/MMCHS.c create mode 100755 BeagleBoardPkg/MMCHSDxe/MMCHS.h create mode 100644 BeagleBoardPkg/MMCHSDxe/MMCHS.inf create mode 100644 BeagleBoardPkg/PciEmulation/PciEmulation.c create mode 100644 BeagleBoardPkg/PciEmulation/PciEmulation.h create mode 100644 BeagleBoardPkg/PciEmulation/PciEmulation.inf create mode 100644 BeagleBoardPkg/PciEmulation/PciRootBridgeIo.c create mode 100755 BeagleBoardPkg/Sec/Arm/Macro.inc create mode 100755 BeagleBoardPkg/Sec/Arm/ModuleEntryPoint.S create mode 100755 BeagleBoardPkg/Sec/Arm/ModuleEntryPoint.asm create mode 100755 BeagleBoardPkg/Sec/Cache.c create mode 100644 BeagleBoardPkg/Sec/Clock.c create mode 100644 BeagleBoardPkg/Sec/PadConfiguration.c create mode 100755 BeagleBoardPkg/Sec/Sec.c create mode 100755 BeagleBoardPkg/Sec/Sec.inf create mode 100644 BeagleBoardPkg/SmbusDxe/Smbus.c create mode 100644 BeagleBoardPkg/SmbusDxe/Smbus.inf create mode 100644 BeagleBoardPkg/TPS65950Dxe/TPS65950.c create mode 100644 BeagleBoardPkg/TPS65950Dxe/TPS65950.inf create mode 100644 BeagleBoardPkg/TimerDxe/Timer.c create mode 100644 BeagleBoardPkg/TimerDxe/TimerDxe.inf create mode 100644 BeagleBoardPkg/Tools/GNUmakefile create mode 100644 BeagleBoardPkg/Tools/generate_image.c create mode 100755 BeagleBoardPkg/build.sh create mode 100644 BeagleBoardPkg/readme.txt create mode 100644 EmbeddedPkg/DebugSupportDxe/DebugSupport.c create mode 100644 EmbeddedPkg/DebugSupportDxe/DebugSupportDxe.inf create mode 100644 EmbeddedPkg/Ebl/CmdTemplate.c create mode 100644 EmbeddedPkg/Ebl/Command.c create mode 100644 EmbeddedPkg/Ebl/Dir.c create mode 100644 EmbeddedPkg/Ebl/Ebl.h create mode 100644 EmbeddedPkg/Ebl/Ebl.inf create mode 100644 EmbeddedPkg/Ebl/EfiDevice.c create mode 100644 EmbeddedPkg/Ebl/Hob.c create mode 100644 EmbeddedPkg/Ebl/HwDebug.c create mode 100644 EmbeddedPkg/Ebl/HwIoDebug.c create mode 100644 EmbeddedPkg/Ebl/Main.c create mode 100644 EmbeddedPkg/Ebl/Network.c create mode 100644 EmbeddedPkg/Ebl/Script.c create mode 100644 EmbeddedPkg/EblExternCmd/EntryPointGlue.c create mode 100644 EmbeddedPkg/EblExternCmd/Main.c create mode 100644 EmbeddedPkg/EmbeddedMonotonicCounter/EmbeddedMonotonicCounter.c create mode 100644 EmbeddedPkg/EmbeddedMonotonicCounter/EmbeddedMonotonicCounter.inf create mode 100644 EmbeddedPkg/EmbeddedPkg.dec create mode 100644 EmbeddedPkg/EmbeddedPkg.dsc create mode 100644 EmbeddedPkg/EmbeddedPkg.fdf create mode 100644 EmbeddedPkg/GdbStub/Arm/Processor.c create mode 100644 EmbeddedPkg/GdbStub/GdbStub.c create mode 100644 EmbeddedPkg/GdbStub/GdbStub.inf create mode 100644 EmbeddedPkg/GdbStub/GdbStubInternal.h create mode 100644 EmbeddedPkg/GdbStub/Ia32/Processor.c create mode 100644 EmbeddedPkg/GdbStub/SerialIo.c create mode 100644 EmbeddedPkg/GdbStub/X64/Processor.c create mode 100644 EmbeddedPkg/Include/Library/EblAddExternalCommandLib.h create mode 100644 EmbeddedPkg/Include/Library/EblCmdLib.h create mode 100644 EmbeddedPkg/Include/Library/EblNetworkLib.h create mode 100644 EmbeddedPkg/Include/Library/EfiFileLib.h create mode 100644 EmbeddedPkg/Include/Library/EfiResetSystemLib.h create mode 100644 EmbeddedPkg/Include/Library/GdbSerialLib.h create mode 100644 EmbeddedPkg/Include/Library/HalRuntimeServicesLib.h create mode 100644 EmbeddedPkg/Include/Library/PrePiLib.h create mode 100644 EmbeddedPkg/Include/Library/RealTimeClockLib.h create mode 100644 EmbeddedPkg/Include/Protocol/DebugSupportPeriodicCallback.h create mode 100644 EmbeddedPkg/Include/Protocol/EblAddCommand.h create mode 100644 EmbeddedPkg/Include/Protocol/EmbeddedDevice.h create mode 100644 EmbeddedPkg/Include/Protocol/EmbeddedExternalDevice.h create mode 100644 EmbeddedPkg/Include/Protocol/EmbeddedGpio.h create mode 100644 EmbeddedPkg/Include/Protocol/HardwareInterrupt.h create mode 100644 EmbeddedPkg/Library/EblAddExternalCommandLib/EblAddExternalCommandLib.c create mode 100644 EmbeddedPkg/Library/EblAddExternalCommandLib/EblAddExternalCommandLib.inf create mode 100644 EmbeddedPkg/Library/EblCmdLibNull/EblCmdLibNull.c create mode 100644 EmbeddedPkg/Library/EblCmdLibNull/EblCmdLibNull.inf create mode 100644 EmbeddedPkg/Library/EblNetworkLib/EblNetworkLib.c create mode 100644 EmbeddedPkg/Library/EblNetworkLib/EblNetworkLib.inf create mode 100644 EmbeddedPkg/Library/EfiFileLib/EfiFileLib.c create mode 100644 EmbeddedPkg/Library/EfiFileLib/EfiFileLib.inf create mode 100644 EmbeddedPkg/Library/GdbSerialDebugPortLib/GdbSerialDebugPortLib.c create mode 100644 EmbeddedPkg/Library/GdbSerialDebugPortLib/GdbSerialDebugPortLib.inf create mode 100644 EmbeddedPkg/Library/GdbSerialLib/GdbSerialLib.c create mode 100644 EmbeddedPkg/Library/GdbSerialLib/GdbSerialLib.inf create mode 100644 EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Capsule.c create mode 100644 EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Mtc.c create mode 100644 EmbeddedPkg/Library/HalRuntimeServicesExampleLib/ReportStatusCode.c create mode 100644 EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Reset.c create mode 100644 EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Rtc.c create mode 100644 EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Variable.c create mode 100644 EmbeddedPkg/Library/PrePiExtractGuidedSectionLib/PrePiExtractGuidedSectionLib.c create mode 100644 EmbeddedPkg/Library/PrePiExtractGuidedSectionLib/PrePiExtractGuidedSectionLib.inf create mode 100644 EmbeddedPkg/Library/PrePiLib/FwVol.c create mode 100644 EmbeddedPkg/Library/PrePiLib/Hob.c create mode 100644 EmbeddedPkg/Library/PrePiLib/Memory.c create mode 100644 EmbeddedPkg/Library/PrePiLib/PrePi.h create mode 100644 EmbeddedPkg/Library/PrePiLib/PrePiLib.c create mode 100644 EmbeddedPkg/Library/PrePiLib/PrePiLib.inf create mode 100644 EmbeddedPkg/Library/PrePiLib/ReportStatusCode.c create mode 100644 EmbeddedPkg/Library/SemiHostingDebugLib/DebugLib.c create mode 100644 EmbeddedPkg/Library/SemiHostingDebugLib/SemiHostingDebugLib.inf create mode 100644 EmbeddedPkg/Library/SemiHostingSerialPortLib/SemiHostingSerialPortLib.inf create mode 100644 EmbeddedPkg/Library/SemiHostingSerialPortLib/SerialPortLib.c create mode 100644 EmbeddedPkg/Library/TemplateRealTimeClockLib/RealTimeClockLib.c create mode 100644 EmbeddedPkg/Library/TemplateRealTimeClockLib/TemplateRealTimeClockLib.inf create mode 100644 EmbeddedPkg/Library/TemplateResetSystemLib/ResetSystemLib.c create mode 100644 EmbeddedPkg/Library/TemplateResetSystemLib/TemplateResetSystemLib.inf create mode 100644 EmbeddedPkg/Library/TemplateSerialPortLib/TemplateSerialPortLib.c create mode 100644 EmbeddedPkg/Library/TemplateSerialPortLib/TemplateSerialPortLib.inf create mode 100644 EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClock.c create mode 100644 EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf create mode 100644 EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf create mode 100644 EmbeddedPkg/ResetRuntimeDxe/reset.c create mode 100644 EmbeddedPkg/SerialDxe/SerialDxe.inf create mode 100644 EmbeddedPkg/SerialDxe/SerialIo.c create mode 100644 EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOut.c create mode 100644 EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOutSerial.inf create mode 100644 EmbeddedPkg/TemplateBds/BdsEntry.c create mode 100644 EmbeddedPkg/TemplateBds/BdsEntry.h create mode 100644 EmbeddedPkg/TemplateBds/FirmwareVolume.c create mode 100644 EmbeddedPkg/TemplateBds/TemplateBds.inf create mode 100644 EmbeddedPkg/TemplateCpuDxe/Arm/Exception.c create mode 100755 EmbeddedPkg/TemplateCpuDxe/Arm/Exceptions.S create mode 100755 EmbeddedPkg/TemplateCpuDxe/Arm/Exceptions.asm create mode 100644 EmbeddedPkg/TemplateCpuDxe/CpuDxe.c create mode 100644 EmbeddedPkg/TemplateCpuDxe/CpuDxe.h create mode 100644 EmbeddedPkg/TemplateCpuDxe/IA32/Exception.c create mode 100644 EmbeddedPkg/TemplateCpuDxe/TemplateCpuDxe.inf create mode 100644 EmbeddedPkg/TemplateCpuDxe/X64/Exception.c create mode 100644 EmbeddedPkg/TemplateMetronomeDxe/Metronome.c create mode 100644 EmbeddedPkg/TemplateMetronomeDxe/TemplateMetronomeDxe.inf create mode 100644 EmbeddedPkg/TemplateSec/TemplateSec.c create mode 100644 EmbeddedPkg/TemplateSec/TemplateSec.inf create mode 100644 EmbeddedPkg/TemplateTimerDxe/TemplateTimerDxe.inf create mode 100644 EmbeddedPkg/TemplateTimerDxe/Timer.c diff --git a/ArmPkg/ArmPkg.dec b/ArmPkg/ArmPkg.dec new file mode 100644 index 0000000000..9773f450e3 --- /dev/null +++ b/ArmPkg/ArmPkg.dec @@ -0,0 +1,36 @@ +#%HEADER% +[Defines] + DEC_SPECIFICATION = 0x00010005 + PACKAGE_NAME = ArmPkg + PACKAGE_GUID = 5CFBD99E-3C43-4E7F-8054-9CDEAFF7710F + PACKAGE_VERSION = 0.1 + +################################################################################ +# +# Include Section - list of Include Paths that are provided by this package. +# Comments are used for Keywords and Module Types. +# +# Supported Module Types: +# BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION +# +################################################################################ +[Includes.common] + Include # Root include for the package + +[LibraryClasses.common] + SemihostLib|Include/Library/Semihosting.h + +[Guids.common] + gArmTokenSpaceGuid = { 0xBB11ECFE, 0x820F, 0x4968, { 0xBB, 0xA6, 0xF7, 0x6A, 0xFE, 0x30, 0x25, 0x96 } } + +[Protocols.common] + gTimerDebugSupportProtocolGuid = { 0x68300561, 0x0197, 0x465d, { 0xb5, 0xa1, 0x28, 0xeb, 0xa1, 0x98, 0xdd, 0x0b } } + +[PcdsFeatureFlag.common] + gArmTokenSpaceGuid.PcdCpuDxeProduceDebugSupport|FALSE|BOOLEAN|0x00000001 + +[PcdsFixedAtBuild.common] + gArmTokenSpaceGuid.PcdArmUncachedMemoryMask|0x0000000080000000|UINT64|0x00000002 + gArmTokenSpaceGuid.PcdArmCacheOperationThreshold|1024|UINT32|0x00000003 + gArmTokenSpaceGuid.PcdCpuVectorBaseAddress|0xfff00000|UINT32|0x00000004 + gArmTokenSpaceGuid.PcdCpuResetAddress|0x00000000|UINT32|0x00000005 diff --git a/ArmPkg/ArmPkg.dsc b/ArmPkg/ArmPkg.dsc new file mode 100644 index 0000000000..ca4f4fa555 --- /dev/null +++ b/ArmPkg/ArmPkg.dsc @@ -0,0 +1,61 @@ +#%HEADER% +#/** @file +# +# ARM Package +# +#**/ + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + PLATFORM_NAME = ArmPkg + PLATFORM_GUID = 5CFBD99E-3C43-4E7F-8054-9CDEAFF7710F + PLATFORM_VERSION = 0.1 + DSC_SPECIFICATION = 0x00010005 + OUTPUT_DIRECTORY = Build/Arm + SUPPORTED_ARCHITECTURES = ARM + BUILD_TARGETS = DEBUG|RELEASE + SKUID_IDENTIFIER = DEFAULT + + +[LibraryClasses.common] + BaseLib|MdePkg/Library/BaseLib/BaseLib.inf + BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf + CacheMaintenanceLib|ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.inf + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf + TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf + UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf + UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf + UefiLib|MdePkg/Library/UefiLib/UefiLib.inf + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + + ArmLib|ArmPkg/Library/ArmLib/Null/NullArmLib.inf + SemihostLib|ArmPkg/Library/SemihostLib/SemihostLib.inf + UncachedMemoryAllocationLib|ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.inf + + +[Components.common] + ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.inf + ArmPkg/Library/ArmLib/Arm11/Arm11ArmLib.inf + ArmPkg/Library/ArmLib/Arm11/Arm11ArmLibPrePi.inf + ArmPkg/Library/ArmLib/Arm9/Arm9ArmLib.inf + ArmPkg/Library/ArmLib/Arm9/Arm9ArmLibPrePi.inf + ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexArmLib.inf + ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexArmLibPrePi.inf + ArmPkg/Library/ArmLib/Null/NullArmLib.inf + ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf + ArmPkg/Library/SemiHostingDebugLib/SemiHostingDebugLib.inf + ArmPkg/Library/SemiHostingSerialPortLib/SemiHostingSerialPortLib.inf + ArmPkg/Library/SemihostLib/SemihostLib.inf + ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.inf + + ArmPkg/Drivers/CpuDxe/CpuDxe.inf + ArmPkg/Drivers/DebugSupportDxe/DebugSupportDxe.inf + ArmPkg/Filesystem/SemihostFs/SemihostFs.inf diff --git a/ArmPkg/Drivers/CpuDxe/CpuDxe.c b/ArmPkg/Drivers/CpuDxe/CpuDxe.c new file mode 100644 index 0000000000..c57dac2f74 --- /dev/null +++ b/ArmPkg/Drivers/CpuDxe/CpuDxe.c @@ -0,0 +1,154 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "CpuDxe.h" + +EFI_STATUS +EFIAPI +CpuFlushCpuDataCache ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length, + IN EFI_CPU_FLUSH_TYPE FlushType + ) +{ + switch (FlushType) { + case EfiCpuFlushTypeWriteBack: + WriteBackDataCacheRange((VOID *)(UINTN)Start, (UINTN)Length); + break; + case EfiCpuFlushTypeInvalidate: + InvalidateDataCacheRange((VOID *)(UINTN)Start, (UINTN)Length); + break; + case EfiCpuFlushTypeWriteBackInvalidate: + WriteBackInvalidateDataCacheRange((VOID *)(UINTN)Start, (UINTN)Length); + break; + default: + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +CpuEnableInterrupt ( + IN EFI_CPU_ARCH_PROTOCOL *This + ) +{ + if (ArmProcessorMode() != ARM_PROCESSOR_MODE_IRQ) { + ArmEnableInterrupts(); + } + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +CpuDisableInterrupt ( + IN EFI_CPU_ARCH_PROTOCOL *This + ) +{ + if (ArmProcessorMode() != ARM_PROCESSOR_MODE_IRQ) { + ArmDisableInterrupts(); + } + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +CpuGetInterruptState ( + IN EFI_CPU_ARCH_PROTOCOL *This, + OUT BOOLEAN *State + ) +{ + if (State == NULL) { + return EFI_INVALID_PARAMETER; + } + + *State = ArmGetInterruptState(); + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +CpuInit ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_CPU_INIT_TYPE InitType + ) +{ + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +CpuRegisterInterruptHandler ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler + ) +{ + return RegisterInterruptHandler(InterruptType, InterruptHandler); +} + +EFI_STATUS +EFIAPI +CpuGetTimerValue ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN UINT32 TimerIndex, + OUT UINT64 *TimerValue, + OUT UINT64 *TimerPeriod OPTIONAL + ) +{ + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +CpuSetMemoryAttributes ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes + ) +{ + return EFI_UNSUPPORTED; +} + +// +// Globals used to initialize the protocol +// +EFI_HANDLE mCpuHandle = NULL; +EFI_CPU_ARCH_PROTOCOL mCpu = { + CpuFlushCpuDataCache, + CpuEnableInterrupt, + CpuDisableInterrupt, + CpuGetInterruptState, + CpuInit, + CpuRegisterInterruptHandler, + CpuGetTimerValue, + CpuSetMemoryAttributes, + 0, // NumberOfTimers + 4, // DmaBufferAlignment +}; + +EFI_STATUS +CpuDxeInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + InitializeExceptions(&mCpu); + return gBS->InstallMultipleProtocolInterfaces(&mCpuHandle, &gEfiCpuArchProtocolGuid, &mCpu, NULL); +} + diff --git a/ArmPkg/Drivers/CpuDxe/CpuDxe.h b/ArmPkg/Drivers/CpuDxe/CpuDxe.h new file mode 100644 index 0000000000..36133e11c3 --- /dev/null +++ b/ArmPkg/Drivers/CpuDxe/CpuDxe.h @@ -0,0 +1,91 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __CPU_DXE_ARM_EXCEPTION_H__ +#define __CPU_DXE_ARM_EXCEPTION_H__ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +/** + This function registers and enables the handler specified by InterruptHandler for a processor + interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the + handler for the processor interrupt or exception type specified by InterruptType is uninstalled. + The installed handler is called once for each processor interrupt or exception. + + @param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts + are enabled and FALSE if interrupts are disabled. + @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called + when a processor interrupt occurs. If this parameter is NULL, then the handler + will be uninstalled. + + @retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled. + @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was + previously installed. + @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not + previously installed. + @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported. + +**/ +EFI_STATUS +RegisterInterruptHandler ( + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler + ); + + +/** + This function registers and enables the handler specified by InterruptHandler for a processor + interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the + handler for the processor interrupt or exception type specified by InterruptType is uninstalled. + The installed handler is called once for each processor interrupt or exception. + + @param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts + are enabled and FALSE if interrupts are disabled. + @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called + when a processor interrupt occurs. If this parameter is NULL, then the handler + will be uninstalled. + + @retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled. + @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was + previously installed. + @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not + previously installed. + @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported. + +**/ +EFI_STATUS +RegisterDebuggerInterruptHandler ( + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler + ); + + +EFI_STATUS +InitializeExceptions ( + IN EFI_CPU_ARCH_PROTOCOL *Cpu + ); + +#endif // __CPU_DXE_ARM_EXCEPTION_H__ diff --git a/ArmPkg/Drivers/CpuDxe/CpuDxe.inf b/ArmPkg/Drivers/CpuDxe/CpuDxe.inf new file mode 100644 index 0000000000..314965ca4a --- /dev/null +++ b/ArmPkg/Drivers/CpuDxe/CpuDxe.inf @@ -0,0 +1,56 @@ +#%HEADER% +#/** @file +# +# DXE CPU driver +# +# Copyright (c) 2009, Apple Inc.
+# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ArmCpuDxe + FILE_GUID = B8D9777E-D72A-451F-9BDB-BAFB52A68415 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = CpuDxeInitialize + +[Sources.ARM] + CpuDxe.c + CpuDxe.h + DebugSupport.c + Exception.c + ExceptionSupport.asm | RVCT + ExceptionSupport.S | GCC + +[Packages] + ArmPkg/ArmPkg.dec + EmbeddedPkg/EmbeddedPkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseMemoryLib + CacheMaintenanceLib + UefiDriverEntryPoint + ArmLib + +[Protocols] + gEfiCpuArchProtocolGuid + gEfiDebugSupportPeriodicCallbackProtocolGuid + +[Pcd.common] + gArmTokenSpaceGuid.PcdCpuVectorBaseAddress + +[FeaturePcd.common] + gArmTokenSpaceGuid.PcdCpuDxeProduceDebugSupport + +[depex] + gHardwareInterruptProtocolGuid diff --git a/ArmPkg/Drivers/CpuDxe/DebugSupport.c b/ArmPkg/Drivers/CpuDxe/DebugSupport.c new file mode 100644 index 0000000000..b8a5584939 --- /dev/null +++ b/ArmPkg/Drivers/CpuDxe/DebugSupport.c @@ -0,0 +1,247 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +/** @file + DXE Cpu Driver. + + May need some porting work for platform specifics. + + Copyright (c) 2008, Apple Inc + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "CpuDxe.h" + +EFI_PERIODIC_CALLBACK gPeriodicCallBack = (EFI_PERIODIC_CALLBACK)NULL; + +EFI_DEBUG_SUPPORT_PERIODIC_CALLBACK_PROTOCOL *gDebugSupportCallback = NULL; + + +EFI_STATUS +EFIAPI +DebugSupportGetMaximumProcessorIndex ( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + OUT UINTN *MaxProcessorIndex + ) +/*++ + +Routine Description: This is a DebugSupport protocol member function. + +Arguments: + This - The DebugSupport instance + MaxProcessorIndex - The maximuim supported processor index + +Returns: + Always returns EFI_SUCCESS with *MaxProcessorIndex set to 0 + +--*/ +{ + *MaxProcessorIndex = 0; + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +DebugSupportRegisterPeriodicCallback ( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + IN UINTN ProcessorIndex, + IN EFI_PERIODIC_CALLBACK PeriodicCallback + ) +/*++ + +Routine Description: This is a DebugSupport protocol member function. + +Arguments: + This - The DebugSupport instance + ProcessorIndex - Which processor the callback applies to. + PeriodicCallback - Callback function + +Returns: + + EFI_SUCCESS + EFI_INVALID_PARAMETER - requested uninstalling a handler from a vector that has + no handler registered for it + EFI_ALREADY_STARTED - requested install to a vector that already has a handler registered. + + Other possible return values are passed through from UnHookEntry and HookEntry. + +--*/ +{ + if (ProcessorIndex != 0) { + return EFI_INVALID_PARAMETER; + } + + if ((gPeriodicCallBack != (EFI_PERIODIC_CALLBACK)NULL) && (PeriodicCallback != (EFI_PERIODIC_CALLBACK)NULL)) { + return EFI_ALREADY_STARTED; + } + + gPeriodicCallBack = PeriodicCallback; + + if (gDebugSupportCallback != NULL) { + // + // We can only update this protocol if the Register Protocol Notify has fired. If it fires + // after this call it will update with gPeriodicCallBack value. + // + gDebugSupportCallback->PeriodicCallback = gPeriodicCallBack; + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +DebugSupportRegisterExceptionCallback ( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + IN UINTN ProcessorIndex, + IN EFI_EXCEPTION_CALLBACK NewCallback, + IN EFI_EXCEPTION_TYPE ExceptionType + ) +/*++ + +Routine Description: + This is a DebugSupport protocol member function. + + This code executes in boot services context. + +Arguments: + This - The DebugSupport instance + ProcessorIndex - Which processor the callback applies to. + NewCallback - Callback function + ExceptionType - Which exception to hook + +Returns: + + EFI_SUCCESS + EFI_INVALID_PARAMETER - requested uninstalling a handler from a vector that has + no handler registered for it + EFI_ALREADY_STARTED - requested install to a vector that already has a handler registered. + + Other possible return values are passed through from UnHookEntry and HookEntry. + +--*/ +{ + if (ProcessorIndex != 0) { + return EFI_INVALID_PARAMETER; + } + + return RegisterDebuggerInterruptHandler (ExceptionType, NewCallback); +} + + +EFI_STATUS +EFIAPI +DebugSupportInvalidateInstructionCache ( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + IN UINTN ProcessorIndex, + IN VOID *Start, + IN UINT64 Length + ) +/*++ + +Routine Description: + This is a DebugSupport protocol member function. + Calls assembly routine to flush cache. + +Arguments: + This - The DebugSupport instance + ProcessorIndex - Which processor the callback applies to. + Start - Physical base of the memory range to be invalidated + Length - mininum number of bytes in instruction cache to invalidate + +Returns: + + EFI_SUCCESS - always return success + +--*/ +{ + if (ProcessorIndex != 0) { + return EFI_INVALID_PARAMETER; + } + + InvalidateInstructionCache(); + + return EFI_SUCCESS; +} + +// +// This is a global that is the actual interface +// +EFI_DEBUG_SUPPORT_PROTOCOL gDebugSupportProtocolInterface = { + IsaArm, // Fixme to be more generic + DebugSupportGetMaximumProcessorIndex, + DebugSupportRegisterPeriodicCallback, + DebugSupportRegisterExceptionCallback, + DebugSupportInvalidateInstructionCache +}; + + +VOID +EFIAPI +DebugSupportPeriodicCallbackEventProtocolNotify ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol (&gEfiDebugSupportPeriodicCallbackProtocolGuid, NULL, (VOID **)&gDebugSupportCallback); + if (!EFI_ERROR (Status)) { + gDebugSupportCallback->PeriodicCallback = gPeriodicCallBack; + } +} + +VOID *gRegistration = NULL; + + +EFI_DEBUG_SUPPORT_PROTOCOL * +InitilaizeDebugSupport ( + VOID + ) +{ + // RPN gEfiDebugSupportPeriodicCallbackProtocolGuid + EFI_STATUS Status; + EFI_EVENT Event; + + if (!FeaturePcdGet (PcdCpuDxeProduceDebugSupport)) { + // Don't include this code unless Feature Flag is set + return NULL; + } + + + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + DebugSupportPeriodicCallbackEventProtocolNotify, + NULL, + &Event + ); + ASSERT_EFI_ERROR (Status); + + Status = gBS->RegisterProtocolNotify (&gEfiDebugSupportPeriodicCallbackProtocolGuid, Event, &gRegistration); + ASSERT_EFI_ERROR (Status); + + // + // We assume the Timer must depend on our driver to register interrupts so we don't need to do + // a gBS->SignalEvent (Event) here to check to see if the protocol allready exists + // + + return &gDebugSupportProtocolInterface; +} diff --git a/ArmPkg/Drivers/CpuDxe/Exception.c b/ArmPkg/Drivers/CpuDxe/Exception.c new file mode 100644 index 0000000000..fa256e60f8 --- /dev/null +++ b/ArmPkg/Drivers/CpuDxe/Exception.c @@ -0,0 +1,238 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "CpuDxe.h" +#include + +VOID +ExceptionHandlersStart ( + VOID + ); + +VOID +ExceptionHandlersEnd ( + VOID + ); + +VOID +CommonExceptionEntry ( + VOID + ); + +VOID +AsmCommonExceptionEntry ( + VOID + ); + + +EFI_EXCEPTION_CALLBACK gExceptionHandlers[MAX_ARM_EXCEPTION + 1]; +EFI_EXCEPTION_CALLBACK gDebuggerExceptionHandlers[MAX_ARM_EXCEPTION + 1]; + + + +/** + This function registers and enables the handler specified by InterruptHandler for a processor + interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the + handler for the processor interrupt or exception type specified by InterruptType is uninstalled. + The installed handler is called once for each processor interrupt or exception. + + @param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts + are enabled and FALSE if interrupts are disabled. + @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called + when a processor interrupt occurs. If this parameter is NULL, then the handler + will be uninstalled. + + @retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled. + @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was + previously installed. + @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not + previously installed. + @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported. + +**/ +EFI_STATUS +RegisterInterruptHandler ( + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler + ) +{ + if (InterruptType > MAX_ARM_EXCEPTION) { + return EFI_UNSUPPORTED; + } + + if ((InterruptHandler != NULL) && (gExceptionHandlers[InterruptType] != NULL)) { + return EFI_ALREADY_STARTED; + } + + gExceptionHandlers[InterruptType] = InterruptHandler; + + return EFI_SUCCESS; +} + + +/** + This function registers and enables the handler specified by InterruptHandler for a processor + interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the + handler for the processor interrupt or exception type specified by InterruptType is uninstalled. + The installed handler is called once for each processor interrupt or exception. + + @param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts + are enabled and FALSE if interrupts are disabled. + @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called + when a processor interrupt occurs. If this parameter is NULL, then the handler + will be uninstalled. + + @retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled. + @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was + previously installed. + @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not + previously installed. + @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported. + +**/ +EFI_STATUS +RegisterDebuggerInterruptHandler ( + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler + ) +{ + if (InterruptType > MAX_ARM_EXCEPTION) { + return EFI_UNSUPPORTED; + } + + if ((InterruptHandler != NULL) && (gDebuggerExceptionHandlers[InterruptType] != NULL)) { + return EFI_ALREADY_STARTED; + } + + gDebuggerExceptionHandlers[InterruptType] = InterruptHandler; + + return EFI_SUCCESS; +} + + + +VOID +EFIAPI +CommonCExceptionHandler ( + IN EFI_EXCEPTION_TYPE ExceptionType, + IN OUT EFI_SYSTEM_CONTEXT SystemContext + ) +{ + BOOLEAN Dispatched = FALSE; + + if (ExceptionType <= MAX_ARM_EXCEPTION) { + if (gDebuggerExceptionHandlers[ExceptionType]) { + // + // If DebugSupport hooked the interrupt call the handler. This does not disable + // the normal handler. + // + gDebuggerExceptionHandlers[ExceptionType] (ExceptionType, SystemContext); + Dispatched = TRUE; + } + if (gExceptionHandlers[ExceptionType]) { + gExceptionHandlers[ExceptionType] (ExceptionType, SystemContext); + Dispatched = TRUE; + } + } + + if (Dispatched) { + // + // We did work so this was an expected ExceptionType + // + return; + } + + if (ExceptionType == EXCEPT_ARM_SOFTWARE_INTERRUPT) { + // + // ARM JTAG debuggers some times use this vector, so it is not an error to get one + // + return; + } + + // + // Code after here is the default exception handler... + // + DEBUG ((EFI_D_ERROR, "Exception %d from %08x\n", ExceptionType, SystemContext.SystemContextArm->PC)); + ASSERT (FALSE); + +} + + + +EFI_STATUS +InitializeExceptions ( + IN EFI_CPU_ARCH_PROTOCOL *Cpu + ) +{ + EFI_STATUS Status; + UINTN Offset; + UINTN Length; + UINTN Index; + BOOLEAN Enabled; + EFI_PHYSICAL_ADDRESS Base; + + // + // Disable interrupts + // + Cpu->GetInterruptState (Cpu, &Enabled); + Cpu->DisableInterrupt (Cpu); + + // + // Initialize the C entry points for interrupts + // + for (Index = 0; Index <= MAX_ARM_EXCEPTION; Index++) { + Status = RegisterInterruptHandler (Index, NULL); + ASSERT_EFI_ERROR (Status); + + Status = RegisterDebuggerInterruptHandler (Index, NULL); + ASSERT_EFI_ERROR (Status); + } + + // + // Copy an implementation of the ARM exception vectors to 0x0. + // + Length = (UINTN)ExceptionHandlersEnd - (UINTN)ExceptionHandlersStart; + + // + // Reserve space for the exception handlers + // + Base = (EFI_PHYSICAL_ADDRESS)PcdGet32 (PcdCpuVectorBaseAddress); + Status = gBS->AllocatePages (AllocateAddress, EfiBootServicesCode, EFI_SIZE_TO_PAGES (Length), &Base); + // If the request was for memory that's not in the memory map (which is often the case for 0x00000000 + // on embedded systems, for example, we don't want to hang up. So we'll check here for a status of + // EFI_NOT_FOUND, and continue in that case. + if (EFI_ERROR(Status) && (Status != EFI_NOT_FOUND)) { + ASSERT_EFI_ERROR (Status); + } + + CopyMem ((VOID *)(UINTN)PcdGet32 (PcdCpuVectorBaseAddress), (VOID *)ExceptionHandlersStart, Length); + + // + // Patch in the common Assembly exception handler + // + Offset = (UINTN)CommonExceptionEntry - (UINTN)ExceptionHandlersStart; + *(UINTN *) ((UINT8 *)(UINTN)PcdGet32 (PcdCpuVectorBaseAddress) + Offset) = (UINTN)AsmCommonExceptionEntry; + + // Flush Caches since we updated executable stuff + InvalidateInstructionCacheRange((VOID *)PcdGet32(PcdCpuVectorBaseAddress), Length); + + if (Enabled) { + // + // Restore interrupt state + // + Status = Cpu->EnableInterrupt (Cpu); + } + + return Status; +} diff --git a/ArmPkg/Drivers/CpuDxe/ExceptionSupport.S b/ArmPkg/Drivers/CpuDxe/ExceptionSupport.S new file mode 100755 index 0000000000..8574af6d71 --- /dev/null +++ b/ArmPkg/Drivers/CpuDxe/ExceptionSupport.S @@ -0,0 +1,152 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2008-2009 Apple Inc. All rights reserved. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + +.text +.align 3 + +.globl ASM_PFX(ExceptionHandlersStart) +.globl ASM_PFX(ExceptionHandlersEnd) +.globl ASM_PFX(CommonExceptionEntry) +.globl ASM_PFX(AsmCommonExceptionEntry) +.globl ASM_PFX(CommonCExceptionHandler) + +ASM_PFX(ExceptionHandlersStart): + +ASM_PFX(Reset): + b ASM_PFX(ResetEntry) + +ASM_PFX(UndefinedInstruction): + b ASM_PFX(UndefinedInstructionEntry) + +ASM_PFX(SoftwareInterrupt): + b ASM_PFX(SoftwareInterruptEntry) + +ASM_PFX(PrefetchAbort): + b ASM_PFX(PrefetchAbortEntry) + +ASM_PFX(DataAbort): + b ASM_PFX(DataAbortEntry) + +ASM_PFX(ReservedException): + b ASM_PFX(ReservedExceptionEntry) + +ASM_PFX(Irq): + b ASM_PFX(IrqEntry) + +ASM_PFX(Fiq): + b ASM_PFX(FiqEntry) + +ASM_PFX(ResetEntry): + stmfd sp!,{r0-r1} + mov r0,#0 + ldr r1,ASM_PFX(CommonExceptionEntry) + bx r1 + +ASM_PFX(UndefinedInstructionEntry): + stmfd sp!,{r0-r1} + mov r0,#1 + ldr r1,ASM_PFX(CommonExceptionEntry) + bx r1 + +ASM_PFX(SoftwareInterruptEntry): + stmfd sp!,{r0-r1} + mov r0,#2 + ldr r1,ASM_PFX(CommonExceptionEntry) + bx r1 + +ASM_PFX(PrefetchAbortEntry): + stmfd sp!,{r0-r1} + mov r0,#3 + sub lr,lr,#4 + ldr r1,ASM_PFX(CommonExceptionEntry) + bx r1 + +ASM_PFX(DataAbortEntry): + stmfd sp!,{r0-r1} + mov r0,#4 + sub lr,lr,#8 + ldr r1,ASM_PFX(CommonExceptionEntry) + bx r1 + +ASM_PFX(ReservedExceptionEntry): + stmfd sp!,{r0-r1} + mov r0,#5 + ldr r1,ASM_PFX(CommonExceptionEntry) + bx r1 + +ASM_PFX(IrqEntry): + stmfd sp!,{r0-r1} + mov r0,#6 + sub lr,lr,#4 + ldr r1,ASM_PFX(CommonExceptionEntry) + bx r1 + +ASM_PFX(FiqEntry): + stmfd sp!,{r0-r1} + mov r0,#7 + sub lr,lr,#4 + ldr r1,ASM_PFX(CommonExceptionEntry) + bx r1 + +ASM_PFX(CommonExceptionEntry): + .byte 0x12 + .byte 0x34 + .byte 0x56 + .byte 0x78 + +ASM_PFX(ExceptionHandlersEnd): + +ASM_PFX(AsmCommonExceptionEntry): + mrc p15, 0, r1, c6, c0, 2 @ Read IFAR + stmfd sp!,{r1} @ Store the IFAR + + mrc p15, 0, r1, c5, c0, 1 @ Read IFSR + stmfd sp!,{r1} @ Store the IFSR + + mrc p15, 0, r1, c6, c0, 0 @ Read DFAR + stmfd sp!,{r1} @ Store the DFAR + + mrc p15, 0, r1, c5, c0, 0 @ Read DFSR + stmfd sp!,{r1} @ Store the DFSR + + mrs r1,spsr @ Read SPSR (which is the pre-exception CPSR) + stmfd sp!,{r1} @ Store the SPSR + + stmfd sp!,{lr} @ Store the link register (which is the pre-exception PC) + stmfd sp,{sp,lr}^ @ Store user/system mode stack pointer and link register + nop @ Required by ARM architecture + sub sp,sp,#0x08 @ Adjust stack pointer + stmfd sp!,{r2-r12} @ Store general purpose registers + + ldr r3,[sp,#0x50] @ Read saved R1 from the stack (it was saved by the exception entry routine) + ldr r2,[sp,#0x4C] @ Read saved R0 from the stack (it was saved by the exception entry routine) + stmfd sp!,{r2-r3} @ Store general purpose registers R0 and R1 + + mov r1,sp @ Prepare System Context pointer as an argument for the exception handler + + sub sp,sp,#4 @ Adjust SP to preserve 8-byte alignment + bl ASM_PFX(CommonCExceptionHandler) @ Call exception handler + add sp,sp,#4 @ Adjust SP back to where we were + + ldr r2,[sp,#0x40] @ Load CPSR from context, in case it has changed + msr SPSR_cxsf,r2 @ Store it back to the SPSR to be restored when exiting this handler + + ldmfd sp!,{r0-r12} @ Restore general purpose registers + ldmia sp,{sp,lr}^ @ Restore user/system mode stack pointer and link register + nop @ Required by ARM architecture + add sp,sp,#0x08 @ Adjust stack pointer + ldmfd sp!,{lr} @ Restore the link register (which is the pre-exception PC) + add sp,sp,#0x1C @ Clear out the remaining stack space + movs pc,lr @ Return from exception + diff --git a/ArmPkg/Drivers/CpuDxe/ExceptionSupport.asm b/ArmPkg/Drivers/CpuDxe/ExceptionSupport.asm new file mode 100755 index 0000000000..d91720cff3 --- /dev/null +++ b/ArmPkg/Drivers/CpuDxe/ExceptionSupport.asm @@ -0,0 +1,152 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2008-2009 Apple Inc. All rights reserved. +// +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +//------------------------------------------------------------------------------ + + EXPORT ExceptionHandlersStart + EXPORT ExceptionHandlersEnd + EXPORT CommonExceptionEntry + EXPORT AsmCommonExceptionEntry + IMPORT CommonCExceptionHandler + + PRESERVE8 + AREA DxeExceptionHandlers, CODE, READONLY + +ExceptionHandlersStart + +Reset + b ResetEntry + +UndefinedInstruction + b UndefinedInstructionEntry + +SoftwareInterrupt + b SoftwareInterruptEntry + +PrefetchAbort + b PrefetchAbortEntry + +DataAbort + b DataAbortEntry + +ReservedException + b ReservedExceptionEntry + +Irq + b IrqEntry + +Fiq + b FiqEntry + +ResetEntry + stmfd SP!,{R0-R1} + mov R0,#0 + ldr R1,CommonExceptionEntry + bx R1 + +UndefinedInstructionEntry + stmfd SP!,{R0-R1} + mov R0,#1 + ldr R1,CommonExceptionEntry + bx R1 + +SoftwareInterruptEntry + stmfd SP!,{R0-R1} + mov R0,#2 + ldr R1,CommonExceptionEntry + bx R1 + +PrefetchAbortEntry + stmfd SP!,{R0-R1} + mov R0,#3 + SUB LR,LR,#4 + ldr R1,CommonExceptionEntry + bx R1 + +DataAbortEntry + stmfd SP!,{R0-R1} + mov R0,#4 + SUB LR,LR,#8 + ldr R1,CommonExceptionEntry + bx R1 + +ReservedExceptionEntry + stmfd SP!,{R0-R1} + mov R0,#5 + ldr R1,CommonExceptionEntry + bx R1 + +IrqEntry + stmfd SP!,{R0-R1} + mov R0,#6 + SUB LR,LR,#4 + ldr R1,CommonExceptionEntry + bx R1 + +FiqEntry + stmfd SP!,{R0-R1} + mov R0,#7 + SUB LR,LR,#4 + ldr R1,CommonExceptionEntry + bx R1 + +CommonExceptionEntry + dcd 0x12345678 + +ExceptionHandlersEnd + +AsmCommonExceptionEntry + mrc p15, 0, r1, c6, c0, 2 ; Read IFAR + stmfd SP!,{R1} ; Store the IFAR + + mrc p15, 0, r1, c5, c0, 1 ; Read IFSR + stmfd SP!,{R1} ; Store the IFSR + + mrc p15, 0, r1, c6, c0, 0 ; Read DFAR + stmfd SP!,{R1} ; Store the DFAR + + mrc p15, 0, r1, c5, c0, 0 ; Read DFSR + stmfd SP!,{R1} ; Store the DFSR + + mrs R1,SPSR ; Read SPSR (which is the pre-exception CPSR) + stmfd SP!,{R1} ; Store the SPSR + + stmfd SP!,{LR} ; Store the link register (which is the pre-exception PC) + stmfd SP,{SP,LR}^ ; Store user/system mode stack pointer and link register + nop ; Required by ARM architecture + SUB SP,SP,#0x08 ; Adjust stack pointer + stmfd SP!,{R2-R12} ; Store general purpose registers + + ldr R3,[SP,#0x50] ; Read saved R1 from the stack (it was saved by the exception entry routine) + ldr R2,[SP,#0x4C] ; Read saved R0 from the stack (it was saved by the exception entry routine) + stmfd SP!,{R2-R3} ; Store general purpose registers R0 and R1 + + mov R1,SP ; Prepare System Context pointer as an argument for the exception handler + + sub SP,SP,#4 ; Adjust SP to preserve 8-byte alignment + blx CommonCExceptionHandler ; Call exception handler + add SP,SP,#4 ; Adjust SP back to where we were + + ldr R2,[SP,#0x40] ; Load CPSR from context, in case it has changed + MSR SPSR_cxsf,R2 ; Store it back to the SPSR to be restored when exiting this handler + + ldmfd SP!,{R0-R12} ; Restore general purpose registers + ldm SP,{SP,LR}^ ; Restore user/system mode stack pointer and link register + nop ; Required by ARM architecture + add SP,SP,#0x08 ; Adjust stack pointer + ldmfd SP!,{LR} ; Restore the link register (which is the pre-exception PC) + add SP,SP,#0x1C ; Clear out the remaining stack space + movs PC,LR ; Return from exception + + END + + diff --git a/ArmPkg/Drivers/DebugSupportDxe/DebugSupport.c b/ArmPkg/Drivers/DebugSupportDxe/DebugSupport.c new file mode 100644 index 0000000000..26f4c387dc --- /dev/null +++ b/ArmPkg/Drivers/DebugSupportDxe/DebugSupport.c @@ -0,0 +1,119 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include + +#include +#include +#include + +EFI_STATUS +EFIAPI +DebugSupportGetMaximumProcessorIndex ( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + OUT UINTN *MaxProcessorIndex + ) +{ + if (MaxProcessorIndex == NULL) { + return EFI_INVALID_PARAMETER; + } + + *MaxProcessorIndex = 0; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +DebugSupportRegisterPeriodicCallback ( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + IN UINTN ProcessorIndex, + IN EFI_PERIODIC_CALLBACK PeriodicCallback + ) +{ + TIMER_DEBUG_SUPPORT_PROTOCOL *Timer; + EFI_STATUS Status; + + Status = gBS->LocateProtocol(&gTimerDebugSupportProtocolGuid, NULL, (VOID **)&Timer); + if (EFI_ERROR(Status)) { + return Status; + } + + Status = Timer->RegisterPeriodicCallback(Timer, PeriodicCallback); + + return Status; +} + +EFI_STATUS +EFIAPI +DebugSupportRegisterExceptionCallback ( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + IN UINTN ProcessorIndex, + IN EFI_EXCEPTION_CALLBACK ExceptionCallback, + IN EFI_EXCEPTION_TYPE ExceptionType + ) +{ + EFI_CPU_ARCH_PROTOCOL *Cpu; + EFI_STATUS Status; + + Status = gBS->LocateProtocol(&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu); + if (EFI_ERROR(Status)) { + return Status; + } + + Status = Cpu->RegisterInterruptHandler(Cpu, ExceptionType, (EFI_CPU_INTERRUPT_HANDLER)ExceptionCallback); + + return Status; +} + +EFI_STATUS +EFIAPI +DebugSupportInvalidateInstructionCache ( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + IN UINTN ProcessorIndex, + IN VOID *Start, + IN UINT64 Length + ) +{ + InvalidateInstructionCacheRange(Start, Length); + return EFI_SUCCESS; +} + +EFI_DEBUG_SUPPORT_PROTOCOL mDebugSupport = { + IsaArm, + DebugSupportGetMaximumProcessorIndex, + DebugSupportRegisterPeriodicCallback, + DebugSupportRegisterExceptionCallback, + DebugSupportInvalidateInstructionCache +}; + +EFI_STATUS +DebugSupportDxeInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle = NULL; + + ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiDebugSupportProtocolGuid); + Status = gBS->InstallMultipleProtocolInterfaces(&Handle, &gEfiDebugSupportProtocolGuid, &mDebugSupport, NULL); + + return Status; +} + diff --git a/ArmPkg/Drivers/DebugSupportDxe/DebugSupportDxe.inf b/ArmPkg/Drivers/DebugSupportDxe/DebugSupportDxe.inf new file mode 100644 index 0000000000..59f44879c4 --- /dev/null +++ b/ArmPkg/Drivers/DebugSupportDxe/DebugSupportDxe.inf @@ -0,0 +1,30 @@ +#%HEADER% +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ArmDebugSupportDxe + FILE_GUID = 2e7c151b-cbd8-4df6-a0e3-cde660067c6a + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = DebugSupportDxeInitialize + +[Sources.common] + DebugSupport.c + +[Packages] + ArmPkg/ArmPkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseMemoryLib + CacheMaintenanceLib + UefiDriverEntryPoint + ArmLib + +[Protocols] + gEfiCpuArchProtocolGuid + gEfiDebugSupportProtocolGuid + gTimerDebugSupportProtocolGuid + +[Depex] + TRUE \ No newline at end of file diff --git a/ArmPkg/Filesystem/SemihostFs/Arm/SemihostFs.c b/ArmPkg/Filesystem/SemihostFs/Arm/SemihostFs.c new file mode 100644 index 0000000000..0f1da65ba0 --- /dev/null +++ b/ArmPkg/Filesystem/SemihostFs/Arm/SemihostFs.c @@ -0,0 +1,526 @@ +/** @file + Support a Semi Host file system over a debuggers JTAG + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "SemihostFs.h" + + +EFI_SIMPLE_FILE_SYSTEM_PROTOCOL gSemihostFs = { + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION, + VolumeOpen +}; + +EFI_FILE gSemihostFsFile = { + EFI_FILE_PROTOCOL_REVISION, + FileOpen, + FileClose, + FileDelete, + FileRead, + FileWrite, + FileGetPosition, + FileSetPosition, + FileGetInfo, + FileSetInfo, + FileFlush +}; + +// +// Device path for SemiHosting. It contains our autogened Caller ID GUID. +// +typedef struct { + VENDOR_DEVICE_PATH Guid; + EFI_DEVICE_PATH_PROTOCOL End; +} SEMIHOST_DEVICE_PATH; + +SEMIHOST_DEVICE_PATH gDevicePath = { + { + { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, sizeof (VENDOR_DEVICE_PATH), 0 }, + EFI_CALLER_ID_GUID + }, + { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, sizeof (EFI_DEVICE_PATH_PROTOCOL), 0} +}; + +typedef struct { + LIST_ENTRY Link; + UINT64 Signature; + EFI_FILE File; + CHAR8 *FileName; + UINT32 Position; + UINT32 SemihostHandle; + BOOLEAN IsRoot; +} SEMIHOST_FCB; + +#define SEMIHOST_FCB_SIGNATURE SIGNATURE_32( 'S', 'H', 'F', 'C' ) +#define SEMIHOST_FCB_FROM_THIS(a) CR(a, SEMIHOST_FCB, File, SEMIHOST_FCB_SIGNATURE) +#define SEMIHOST_FCB_FROM_LINK(a) CR(a, SEMIHOST_FCB, Link, SEMIHOST_FCB_SIGNATURE); + +EFI_HANDLE gInstallHandle = NULL; +LIST_ENTRY gFileList = INITIALIZE_LIST_HEAD_VARIABLE (gFileList); + +SEMIHOST_FCB * +AllocateFCB ( + VOID + ) +{ + SEMIHOST_FCB *Fcb = AllocateZeroPool (sizeof (SEMIHOST_FCB)); + + if (Fcb != NULL) { + CopyMem (&Fcb->File, &gSemihostFsFile, sizeof (gSemihostFsFile)); + Fcb->Signature = SEMIHOST_FCB_SIGNATURE; + } + + return Fcb; +} + +VOID +FreeFCB ( + IN SEMIHOST_FCB *Fcb + ) +{ + // Remove Fcb from gFileList. + RemoveEntryList (&Fcb->Link); + + // To help debugging... + Fcb->Signature = 0; + + FreePool (Fcb); +} + + + +EFI_STATUS +VolumeOpen ( + IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This, + OUT EFI_FILE **Root + ) +{ + SEMIHOST_FCB *RootFcb = NULL; + + if (Root == NULL) { + return EFI_INVALID_PARAMETER; + } + + RootFcb = AllocateFCB (); + if (RootFcb == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + RootFcb->IsRoot = TRUE; + + InsertTailList (&gFileList, &RootFcb->Link); + + *Root = &RootFcb->File; + + return EFI_SUCCESS; +} + +EFI_STATUS +FileOpen ( + IN EFI_FILE *File, + OUT EFI_FILE **NewHandle, + IN CHAR16 *FileName, + IN UINT64 OpenMode, + IN UINT64 Attributes + ) +{ + SEMIHOST_FCB *FileFcb = NULL; + EFI_STATUS Status = EFI_SUCCESS; + UINT32 SemihostHandle; + CHAR8 *AsciiFileName; + CHAR8 *AsciiPtr; + UINTN Length; + UINT32 SemihostMode; + BOOLEAN IsRoot; + + if ((FileName == NULL) || (NewHandle == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // Semihost interface requires ASCII filesnames + Length = StrSize (FileName); + + AsciiFileName = AllocatePool (Length); + if (AsciiFileName == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + AsciiPtr = AsciiFileName; + + while (Length--) { + *AsciiPtr++ = *FileName++ & 0xFF; + } + + if ((AsciiStrCmp (AsciiFileName, "\\") == 0) || (AsciiStrCmp (AsciiFileName, "/") == 0) || (AsciiStrCmp (AsciiFileName, "") == 0)) { + // Opening '/', '\', or the NULL pathname is trying to open the root directory + IsRoot = TRUE; + + // Root directory node doesn't have a name. + FreePool (AsciiFileName); + AsciiFileName = NULL; + } else { + // Translate EFI_FILE_MODE into Semihosting mode + if (OpenMode & EFI_FILE_MODE_WRITE) { + SemihostMode = SEMIHOST_FILE_MODE_WRITE | SEMIHOST_FILE_MODE_BINARY; + } else if (OpenMode & EFI_FILE_MODE_READ) { + SemihostMode = SEMIHOST_FILE_MODE_READ | SEMIHOST_FILE_MODE_BINARY; + } else { + return EFI_UNSUPPORTED; + } + + // Add the creation flag if necessary + if (OpenMode & EFI_FILE_MODE_CREATE) { + SemihostMode |= SEMIHOST_FILE_MODE_CREATE; + } + + // Call the semihosting interface to open the file. + Status = SemihostFileOpen (AsciiFileName, SemihostMode, &SemihostHandle); + if (EFI_ERROR(Status)) { + return Status; + } + + IsRoot = FALSE; + } + + // Allocate a control block and fill it + FileFcb = AllocateFCB (); + if (FileFcb == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + FileFcb->FileName = AsciiFileName; + FileFcb->SemihostHandle = SemihostHandle; + FileFcb->Position = 0; + FileFcb->IsRoot = IsRoot; + + InsertTailList (&gFileList, &FileFcb->Link); + + *NewHandle = &FileFcb->File; + + return Status; +} + + +EFI_STATUS +FileClose ( + IN EFI_FILE *File + ) +{ + SEMIHOST_FCB *Fcb = NULL; + EFI_STATUS Status = EFI_SUCCESS; + + Fcb = SEMIHOST_FCB_FROM_THIS(File); + + if (Fcb->IsRoot == TRUE) { + FreeFCB (Fcb); + Status = EFI_SUCCESS; + } else { + Status = SemihostFileClose (Fcb->SemihostHandle); + if (!EFI_ERROR(Status)) { + FreePool (Fcb->FileName); + FreeFCB (Fcb); + } + } + + return Status; +} + +EFI_STATUS +FileDelete ( + IN EFI_FILE *File + ) +{ + SEMIHOST_FCB *Fcb = NULL; + EFI_STATUS Status; + CHAR8 *FileName; + UINTN NameSize; + + Fcb = SEMIHOST_FCB_FROM_THIS(File); + + // Get the filename from the Fcb + NameSize = AsciiStrLen (Fcb->FileName); + FileName = AllocatePool (NameSize + 1); + + AsciiStrCpy (FileName, Fcb->FileName); + + // Close the file if it's open. Disregard return status, + // since it might give an error if the file isn't open. + File->Close (File); + + // Call the semihost interface to delete the file. + Status = SemihostFileRemove (FileName); + + return Status; +} + +EFI_STATUS +FileRead ( + IN EFI_FILE *File, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + SEMIHOST_FCB *Fcb = NULL; + EFI_STATUS Status; + + Fcb = SEMIHOST_FCB_FROM_THIS(File); + + if (Fcb->IsRoot == TRUE) { + Status = EFI_UNSUPPORTED; + } else { + Status = SemihostFileRead (Fcb->SemihostHandle, BufferSize, Buffer); + if (!EFI_ERROR (Status)) { + Fcb->Position += *BufferSize; + } + } + + return Status; +} + +EFI_STATUS +FileWrite ( + IN EFI_FILE *File, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +{ + SEMIHOST_FCB *Fcb = NULL; + EFI_STATUS Status; + UINTN WriteSize = *BufferSize; + + Fcb = SEMIHOST_FCB_FROM_THIS(File); + + Status = SemihostFileWrite (Fcb->SemihostHandle, &WriteSize, Buffer); + + if (!EFI_ERROR(Status)) { + // Semihost write return the number of bytes *NOT* written. + *BufferSize -= WriteSize; + Fcb->Position += *BufferSize; + } + + return Status; +} + +EFI_STATUS +FileGetPosition ( + IN EFI_FILE *File, + OUT UINT64 *Position + ) +{ + SEMIHOST_FCB *Fcb = NULL; + + if (Position == NULL) { + return EFI_INVALID_PARAMETER; + } + + Fcb = SEMIHOST_FCB_FROM_THIS(File); + + *Position = Fcb->Position; + + return EFI_SUCCESS; +} + +EFI_STATUS +FileSetPosition ( + IN EFI_FILE *File, + IN UINT64 Position + ) +{ + SEMIHOST_FCB *Fcb = NULL; + UINT32 Length; + EFI_STATUS Status; + + Fcb = SEMIHOST_FCB_FROM_THIS(File); + + Status = SemihostFileLength (Fcb->SemihostHandle, &Length); + if (!EFI_ERROR(Status) && (Length < Position)) { + Position = Length; + } + + Status = SemihostFileSeek (Fcb->SemihostHandle, (UINT32)Position); + if (!EFI_ERROR(Status)) { + Fcb->Position = Position; + } + + return Status; +} + +STATIC +EFI_STATUS +GetFileInfo ( + IN SEMIHOST_FCB *Fcb, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + EFI_FILE_INFO *Info = NULL; + UINTN NameSize = 0; + UINTN ResultSize; + UINTN Index; + UINT32 Length; + EFI_STATUS Status; + + if (Fcb->IsRoot == TRUE) { + ResultSize = SIZE_OF_EFI_FILE_INFO + sizeof(CHAR16); + } else { + NameSize = AsciiStrLen (Fcb->FileName) + 1; + ResultSize = SIZE_OF_EFI_FILE_INFO + NameSize * sizeof (CHAR16); + } + + if (*BufferSize < ResultSize) { + *BufferSize = ResultSize; + return EFI_BUFFER_TOO_SMALL; + } + + Info = Buffer; + + // Zero out the structure + ZeroMem (Info, SIZE_OF_EFI_FILE_INFO); + + // Fill in the structure + Info->Size = ResultSize; + + if (Fcb->IsRoot == TRUE) { + Info->Attribute = EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY; + Info->FileName[0] = L'\0'; + } else { + Status = SemihostFileLength (Fcb->SemihostHandle, &Length); + if (EFI_ERROR(Status)) { + return Status; + } + + Info->FileSize = Length; + Info->PhysicalSize = Length; + + for (Index = 0; Index < NameSize; Index++) { + Info->FileName[Index] = Fcb->FileName[Index]; + } + } + + + *BufferSize = ResultSize; + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +GetFilesystemInfo ( + IN SEMIHOST_FCB *Fcb, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + EFI_FILE_SYSTEM_INFO *Info = NULL; + EFI_STATUS Status; + STATIC CHAR16 Label[] = L"SemihostFs"; + UINTN ResultSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize(Label); + + if(*BufferSize >= ResultSize) { + ZeroMem (Buffer, ResultSize); + Status = EFI_SUCCESS; + + Info = Buffer; + + Info->Size = ResultSize; + Info->ReadOnly = FALSE; + Info->VolumeSize = 0; + Info->FreeSpace = 0; + Info->BlockSize = 0; + + StrCpy (Info->VolumeLabel, Label); + } else { + Status = EFI_BUFFER_TOO_SMALL; + } + + *BufferSize = ResultSize; + return Status; +} + +EFI_STATUS +FileGetInfo ( + IN EFI_FILE *File, + IN EFI_GUID *InformationType, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + SEMIHOST_FCB *Fcb = NULL; + EFI_STATUS Status = EFI_UNSUPPORTED; + + Fcb = SEMIHOST_FCB_FROM_THIS(File); + + if (CompareGuid(InformationType, &gEfiFileSystemInfoGuid) != 0) { + Status = GetFilesystemInfo(Fcb, BufferSize, Buffer); + } else if (CompareGuid(InformationType, &gEfiFileInfoGuid) != 0) { + Status = GetFileInfo(Fcb, BufferSize, Buffer); + } + + return Status; +} + +EFI_STATUS +FileSetInfo ( + IN EFI_FILE *File, + IN EFI_GUID *InformationType, + IN UINTN BufferSize, + IN VOID *Buffer + ) +{ + return EFI_UNSUPPORTED; +} + +EFI_STATUS +FileFlush ( + IN EFI_FILE *File + ) +{ + return EFI_SUCCESS; +} + +EFI_STATUS +SemihostFsEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status = EFI_NOT_FOUND; + + if (SemihostConnectionSupported ()) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &gInstallHandle, + &gEfiSimpleFileSystemProtocolGuid, &gSemihostFs, + &gEfiDevicePathProtocolGuid, &gDevicePath, + NULL + ); + } + + return Status; +} + diff --git a/ArmPkg/Filesystem/SemihostFs/Arm/SemihostFs.h b/ArmPkg/Filesystem/SemihostFs/Arm/SemihostFs.h new file mode 100644 index 0000000000..f058d92e29 --- /dev/null +++ b/ArmPkg/Filesystem/SemihostFs/Arm/SemihostFs.h @@ -0,0 +1,114 @@ +/** @file + Support a Semi Host file system over a debuggers JTAG + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __SEMIHOST_FS_H__ +#define __SEMIHOST_FS_H__ + +EFI_STATUS +SemihostFsSupported( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +SemihostFsStart( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +SemihostFsStop( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +EFI_STATUS +VolumeOpen( + IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This, + OUT EFI_FILE **Root + ); + +EFI_STATUS +FileOpen( + IN EFI_FILE *File, + OUT EFI_FILE **NewHandle, + IN CHAR16 *FileName, + IN UINT64 OpenMode, + IN UINT64 Attributes + ); + +EFI_STATUS +FileClose( + IN EFI_FILE *File + ); + +EFI_STATUS +FileDelete( + IN EFI_FILE *File + ); + +EFI_STATUS +FileRead( + IN EFI_FILE *File, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ); + +EFI_STATUS +FileWrite( + IN EFI_FILE *File, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ); + +EFI_STATUS +FileGetPosition( + IN EFI_FILE *File, + OUT UINT64 *Position + ); + +EFI_STATUS +FileSetPosition( + IN EFI_FILE *File, + IN UINT64 Position + ); + +EFI_STATUS +FileGetInfo( + IN EFI_FILE *File, + IN EFI_GUID *InformationType, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ); + +EFI_STATUS +FileSetInfo( + IN EFI_FILE *File, + IN EFI_GUID *InformationType, + IN UINTN BufferSize, + IN VOID *Buffer + ); + +EFI_STATUS +FileFlush( + IN EFI_FILE *File + ); + +#endif // __SEMIHOST_FS_H__ + diff --git a/ArmPkg/Filesystem/SemihostFs/SemihostFs.inf b/ArmPkg/Filesystem/SemihostFs/SemihostFs.inf new file mode 100644 index 0000000000..7fca293d6f --- /dev/null +++ b/ArmPkg/Filesystem/SemihostFs/SemihostFs.inf @@ -0,0 +1,48 @@ +#%HEADER% +#/** @file +# Support a Semi Host file system over a debuggers JTAG +# +# Copyright (c) 2009, Apple, Inc. +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SemihostFs + FILE_GUID = C5B9C74A-6D72-4719-99AB-C59F199091EB + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = SemihostFsEntryPoint + + +[Sources.ARM] + Arm/SemihostFs.c + +[Packages] + MdePkg/MdePkg.dec + ArmPkg/ArmPkg.dec + +[LibraryClasses] + BaseLib + MemoryAllocationLib + SemihostLib + UefiDriverEntryPoint + UefiLib + +[Guids] + gEfiFileSystemInfoGuid + gEfiFileInfoGuid + gEfiFileSystemVolumeLabelInfoIdGuid + +[Protocols] + gEfiSimpleFileSystemProtocolGuid + gEfiDevicePathProtocolGuid + diff --git a/ArmPkg/Include/AsmMacroIoLib.h b/ArmPkg/Include/AsmMacroIoLib.h new file mode 100644 index 0000000000..aa3ed61632 --- /dev/null +++ b/ArmPkg/Include/AsmMacroIoLib.h @@ -0,0 +1,236 @@ +/** @file + Macros to work around lack of Apple support for LDR register, =expr + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#ifndef __MACRO_IO_LIB_H__ +#define __MACRO_IO_LIB_H__ + +#if defined(__APPLE__) + +// +// ldr reg, =expr does not work with current Apple tool chain. So do the work our selves +// + +// returns _Data in R0 and _Address in R1 +#define MmioWrite32(_Address, _Data) \ + ldr r1, [pc, #8] ; \ + ldr r0, [pc, #8] ; \ + str r0, [r1] ; \ + b 1f ; \ + .long (_Address) ; \ + .long (_Data) ; \ +1: + +// returns _Data in R0 and _Address in R1, and _OrData in r2 +#define MmioOr32(_Address, _OrData) \ + ldr r1, [pc, #16] ; \ + ldr r2, [pc, #16] ; \ + ldr r0, [r1] ; \ + orr r0, r0, r2 ; \ + str r0, [r1] ; \ + b 1f ; \ + .long (_Address) ; \ + .long (_OrData) ; \ +1: + +// returns _Data in R0 and _Address in R1, and _OrData in r2 +#define MmioAnd32(_Address, _AndData) \ + ldr r1, [pc, #16] ; \ + ldr r2, [pc, #16] ; \ + ldr r0, [r1] ; \ + and r0, r0, r2 ; \ + str r0, [r1] ; \ + b 1f ; \ + .long (_Address) ; \ + .long (_AndData) ; \ +1: + +// returns result in R0, _Address in R1, and _OrData in r2 +#define MmioAndThenOr32(_Address, _AndData, _OrData) \ + ldr r1, [pc, #24] ; \ + ldr r0, [r1] ; \ + ldr r2, [pc, #20] ; \ + and r0, r0, r2 ; \ + ldr r2, [pc, #16] ; \ + orr r0, r0, r2 ; \ + str r0, [r1] ; \ + b 1f ; \ + .long (_Address) ; \ + .long (_AndData) ; \ + .long (_OrData) ; \ +1: + +// returns _Data in _Reg and _Address in R1 +#define MmioWriteFromReg32(_Address, _Reg) \ + ldr r1, [pc, #4] ; \ + str _Reg, [r1] ; \ + b 1f ; \ + .long (_Address) ; \ +1: + + +// returns _Data in R0 and _Address in R1 +#define MmioRead32(_Address) \ + ldr r1, [pc, #4] ; \ + ldr r0, [r1] ; \ + b 1f ; \ + .long (_Address) ; \ +1: + +// returns _Data in Reg and _Address in R1 +#define MmioReadToReg32(_Address, _Reg) \ + ldr r1, [pc, #4] ; \ + ldr _Reg, [r1] ; \ + b 1f ; \ + .long (_Address) ; \ +1: + + +// load R0 with _Data +#define LoadConstant(_Data) \ + ldr r0, [pc, #0] ; \ + b 1f ; \ + .long (_Data) ; \ +1: + +// load _Reg with _Data +#define LoadConstantToReg(_Data, _Reg) \ + ldr _Reg, [pc, #0] ; \ + b 1f ; \ + .long (_Data) ; \ +1: + +// load _Reg with _Data if eq +#define LoadConstantToRegIfEq(_Data, _Reg) \ + ldreq _Reg, [pc, #0] ; \ + b 1f ; \ + .long (_Data) ; \ +1: + + +#elif defined (__GNUC__) + +#define MmioWrite32(Address, Data) \ + ldr r1, =Address ; \ + ldr r0, =Data ; \ + str r0, [r1] + +#define MmioOr32(Address, OrData) \ + ldr r1, =Address ; \ + ldr r2, =OrData ; \ + ldr r0, [r1] ; \ + orr r0, r0, r2 ; \ + str r0, [r1] + +#define MmioAnd32(Address, AndData) \ + ldr r1, =Address ; \ + ldr r2, =AndData ; \ + ldr r0, [r1] ; \ + and r0, r0, r2 ; \ + str r0, [r1] + +#define MmioAndThenOr32(Address, AndData, OrData) \ + ldr r1, =Address ; \ + ldr r0, [r1] ; \ + ldr r2, =AndData ; \ + and r0, r0, r2 ; \ + ldr r2, =OrData ; \ + orr r0, r0, r2 ; \ + str r0, [r1] + +#define MmioWriteFromReg32(Address, Reg) \ + ldr r1, =Address ; \ + str Reg, [r1] + +#define MmioRead32(Address) \ + ldr r1, =Address ; \ + ldr r0, [r1] + +#define MmioReadToReg32(Address, Reg) \ + ldr r1, =Address ; \ + ldr Reg, [r1] + +#define LoadConstant(Data) \ + ldr r0, =Data + +#define LoadConstantToReg(Data, Reg) \ + ldr Reg, =Data + +#else + +// +// Use ARM assembly macros, form armasam +// +// Less magic in the macros if ldr reg, =expr works +// + +// returns _Data in R0 and _Address in R1 + + + +#define MmioWrite32(Address, Data) MmioWrite32Macro Address, Data + + + + +// returns Data in R0 and Address in R1, and OrData in r2 +#define MmioOr32(Address, OrData) MmioOr32Macro Address, OrData + + +// returns _Data in R0 and _Address in R1, and _OrData in r2 + + +#define MmioAnd32(Address, AndData) MmioAnd32Macro Address, AndData + +// returns result in R0, _Address in R1, and _OrData in r2 + + +#define MmioAndThenOr32(Address, AndData, OrData) MmioAndThenOr32Macro Address, AndData, OrData + + +// returns _Data in _Reg and _Address in R1 + + +#define MmioWriteFromReg32(Address, Reg) MmioWriteFromReg32Macro Address, Reg + +// returns _Data in R0 and _Address in R1 + + +#define MmioRead32(Address) MmioRead32Macro Address + +// returns _Data in Reg and _Address in R1 + + +#define MmioReadToReg32(Address, Reg) MmioReadToReg32Macro Address, Reg + + +// load R0 with _Data + + +#define LoadConstant(Data) LoadConstantMacro Data + +// load _Reg with _Data + + +#define LoadConstantToReg(Data, Reg) LoadConstantToRegMacro Data, Reg + +// conditional load testing eq flag +#define LoadConstantToRegIfEq(Data, Reg) LoadConstantToRegIfEqMacro Data, Reg + + +#endif + + +#endif diff --git a/ArmPkg/Include/AsmMacroIoLib.inc b/ArmPkg/Include/AsmMacroIoLib.inc new file mode 100644 index 0000000000..23f3c44d6b --- /dev/null +++ b/ArmPkg/Include/AsmMacroIoLib.inc @@ -0,0 +1,74 @@ +;%HEADER% +;/** @file +; Macros to work around lack of Apple support for LDR register, =expr +; +; Copyright (c) 2009, Apple, Inc. All rights reserved. +; +;**/ + + + MACRO + MmioWrite32Macro $Address, $Data + ldr r1, = ($Address) + ldr r0, = ($Data) + str r0, [r1] + MEND + + MACRO + MmioOr32Macro $Address, $OrData + ldr r1, =($Address) + ldr r2, =($OrData) + ldr r0, [r1] + orr r0, r0, r2 + str r0, [r1] + MEND + + MACRO + MmioAnd32Macro $Address, $AndData + ldr r1, =($Address) + ldr r2, =($AndData) + ldr r0, [r1] + and r0, r0, r2 + str r0, [r1] + MEND + + MACRO + MmioAndThenOr32Macro $Address, $AndData, $OrData + ldr r1, =($Address) + ldr r0, [r1] + ldr r2, =($AndData) + and r0, r0, r2 + ldr r2, =($OrData) + orr r0, r0, r2 + str r0, [r1] + MEND + + MACRO + MmioWriteFromReg32Macro $Address, $Reg + ldr r1, =($Address) + str $Reg, [r1] + MEND + + MACRO + MmioRead32Macro $Address + ldr r1, =($Address) + ldr r0, [r1] + MEND + + MACRO + MmioReadToReg32Macro $Address, $Reg + ldr r1, =($Address) + ldr $Reg, [r1] + MEND + + MACRO + LoadConstantMacro $Data + ldr r0, =($Data) + MEND + + MACRO + LoadConstantToRegMacro $Data, $Reg + ldr $Reg, =($Data) + MEND + + END diff --git a/ArmPkg/Include/Chipset/ARM1176JZ-S.h b/ArmPkg/Include/Chipset/ARM1176JZ-S.h new file mode 100644 index 0000000000..2331f8effc --- /dev/null +++ b/ArmPkg/Include/Chipset/ARM1176JZ-S.h @@ -0,0 +1,111 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __ARM1176JZ_S_H__ +#define __ARM1176JZ_S_H__ + +// Domain Access Control Register +#define DOMAIN_ACCESS_CONTROL_MASK(a) (3UL << (2 * (a))) +#define DOMAIN_ACCESS_CONTROL_NONE(a) (0UL << (2 * (a))) +#define DOMAIN_ACCESS_CONTROL_CLIENT(a) (1UL << (2 * (a))) +#define DOMAIN_ACCESS_CONTROL_RESERVED(a) (2UL << (2 * (a))) +#define DOMAIN_ACCESS_CONTROL_MANAGER(a) (3UL << (2 * (a))) + +#define TRANSLATION_TABLE_SIZE (16 * 1024) +#define TRANSLATION_TABLE_ALIGNMENT (16 * 1024) +#define TRANSLATION_TABLE_ALIGNMENT_MASK (TRANSLATION_TABLE_ALIGNMENT - 1) + +#define TRANSLATION_TABLE_ENTRY_FOR_VIRTUAL_ADDRESS(table, address) ((UINT32 *)(table) + (((UINTN)(address)) >> 20)) + +// Translation table descriptor types +#define TT_DESCRIPTOR_TYPE_MASK ((1UL << 18) | (3UL << 0)) +#define TT_DESCRIPTOR_TYPE_PAGE_TABLE ((0UL << 18) | (1UL << 0)) +#define TT_DESCRIPTOR_TYPE_SECTION ((0UL << 18) | (2UL << 0)) +#define TT_DESCRIPTOR_TYPE_SUPERSECTION ((1UL << 18) | (2UL << 0)) + +// Section descriptor definitions +#define TT_DESCRIPTOR_SECTION_SIZE (0x00100000) + +#define TT_DESCRIPTOR_SECTION_NS_MASK (1UL << 19) +#define TT_DESCRIPTOR_SECTION_NS_SECURE (0UL << 19) +#define TT_DESCRIPTOR_SECTION_NS_NON_SECURE (1UL << 19) + +#define TT_DESCRIPTOR_SECTION_NG_MASK (1UL << 17) +#define TT_DESCRIPTOR_SECTION_NG_GLOBAL (0UL << 17) +#define TT_DESCRIPTOR_SECTION_NG_LOCAL (1UL << 17) + +#define TT_DESCRIPTOR_SECTION_S_MASK (1UL << 16) +#define TT_DESCRIPTOR_SECTION_S_NOT_SHARED (0UL << 16) +#define TT_DESCRIPTOR_SECTION_S_SHARED (1UL << 16) + +#define TT_DESCRIPTOR_SECTION_AP_MASK ((1UL << 15) | (3UL << 10)) +#define TT_DESCRIPTOR_SECTION_AP_NO_NO ((0UL << 15) | (0UL << 10)) +#define TT_DESCRIPTOR_SECTION_AP_RW_NO ((0UL << 15) | (1UL << 10)) +#define TT_DESCRIPTOR_SECTION_AP_RW_RO ((0UL << 15) | (2UL << 10)) +#define TT_DESCRIPTOR_SECTION_AP_RW_RW ((0UL << 15) | (3UL << 10)) +#define TT_DESCRIPTOR_SECTION_AP_RO_NO ((1UL << 15) | (1UL << 10)) +#define TT_DESCRIPTOR_SECTION_AP_RO_RO ((1UL << 15) | (3UL << 10)) + +#define TT_DESCRIPTOR_CACHE_POLICY_NON_CACHEABLE (0UL) +#define TT_DESCRIPTOR_CACHE_POLICY_WRITE_BACK_ALLOCATE (1UL) +#define TT_DESCRIPTOR_CACHE_POLICY_WRITE_THROUGH_NO_ALLOCATE (2UL) +#define TT_DESCRIPTOR_CACHE_POLICY_WRITE_BACK_NO_ALLOCATE (3UL) + +#define TT_DESCRIPTOR_OUTER_CACHE_POLICY_MASK ((1UL << 14) | (3UL << 12)) +#define TT_DESCRIPTOR_OUTER_CACHE_POLICY_NON_CACHEABLE ((1UL << 14) | (TT_DESCRIPTOR_CACHE_POLICY_NON_CACHEABLE << 12)) +#define TT_DESCRIPTOR_OUTER_CACHE_POLICY_WRITE_BACK_ALLOCATE ((1UL << 14) | (TT_DESCRIPTOR_CACHE_POLICY_WRITE_BACK_ALLOCATE << 12)) +#define TT_DESCRIPTOR_OUTER_CACHE_POLICY_WRITE_THROUGH_NO_ALLOCATE ((1UL << 14) | (TT_DESCRIPTOR_CACHE_POLICY_WRITE_THROUGH_NO_ALLOCATE << 12)) +#define TT_DESCRIPTOR_OUTER_CACHE_POLICY_WRITE_BACK_NO_ALLOCATE ((1UL << 14) | (TT_DESCRIPTOR_CACHE_POLICY_WRITE_BACK_NO_ALLOCATE << 12)) + +#define TT_DESCRIPTOR_INNER_CACHE_POLICY_MASK (3UL << 2) +#define TT_DESCRIPTOR_INNER_CACHE_POLICY_NON_CACHEABLE (TT_DESCRIPTOR_CACHE_POLICY_NON_CACHEABLE << 2) +#define TT_DESCRIPTOR_INNER_CACHE_POLICY_WRITE_BACK_ALLOCATE (TT_DESCRIPTOR_CACHE_POLICY_WRITE_BACK_ALLOCATE << 2) +#define TT_DESCRIPTOR_INNER_CACHE_POLICY_WRITE_THROUGH_NO_ALLOCATE (TT_DESCRIPTOR_CACHE_POLICY_WRITE_THROUGH_NO_ALLOCATE << 2) +#define TT_DESCRIPTOR_INNER_CACHE_POLICY_WRITE_BACK_NO_ALLOCATE (TT_DESCRIPTOR_CACHE_POLICY_WRITE_BACK_NO_ALLOCATE << 2) + +#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK (TT_DESCRIPTOR_OUTER_CACHE_POLICY_MASK | TT_DESCRIPTOR_INNER_CACHE_POLICY_MASK) +#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC (TT_DESCRIPTOR_OUTER_CACHE_POLICY_WRITE_THROUGH_NO_ALLOCATE | TT_DESCRIPTOR_INNER_CACHE_POLICY_WRITE_THROUGH_NO_ALLOCATE) +#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_NO_ALLOC (TT_DESCRIPTOR_OUTER_CACHE_POLICY_WRITE_BACK_NO_ALLOCATE | TT_DESCRIPTOR_INNER_CACHE_POLICY_WRITE_BACK_NO_ALLOCATE) +#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE (TT_DESCRIPTOR_OUTER_CACHE_POLICY_NON_CACHEABLE | TT_DESCRIPTOR_INNER_CACHE_POLICY_NON_CACHEABLE) +#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC (TT_DESCRIPTOR_OUTER_CACHE_POLICY_WRITE_BACK_ALLOCATE | TT_DESCRIPTOR_INNER_CACHE_POLICY_WRITE_BACK_ALLOCATE) + +#define TT_DESCRIPTOR_SECTION_DOMAIN_MASK (0x0FUL << 5) +#define TT_DESCRIPTOR_SECTION_DOMAIN(a) (((a) & 0x0FUL) << 5) + +#define TT_DESCRIPTOR_SECTION_BASE_ADDRESS_MASK (0xFFF00000) +#define TT_DESCRIPTOR_SECTION_BASE_ADDRESS(a) (a & TT_DESCRIPTOR_SECTION_BASE_ADDRESS_MASK) + +#define TT_DESCRIPTOR_SECTION_WRITE_BACK (TT_DESCRIPTOR_TYPE_SECTION | \ + TT_DESCRIPTOR_SECTION_NS_NON_SECURE | \ + TT_DESCRIPTOR_SECTION_NG_GLOBAL | \ + TT_DESCRIPTOR_SECTION_S_NOT_SHARED | \ + TT_DESCRIPTOR_SECTION_DOMAIN(0) | \ + TT_DESCRIPTOR_SECTION_AP_RW_RW | \ + TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC) +#define TT_DESCRIPTOR_SECTION_WRITE_THROUGH (TT_DESCRIPTOR_TYPE_SECTION | \ + TT_DESCRIPTOR_SECTION_NS_NON_SECURE | \ + TT_DESCRIPTOR_SECTION_NG_GLOBAL | \ + TT_DESCRIPTOR_SECTION_S_NOT_SHARED | \ + TT_DESCRIPTOR_SECTION_DOMAIN(0) | \ + TT_DESCRIPTOR_SECTION_AP_RW_RW | \ + TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC) +#define TT_DESCRIPTOR_SECTION_UNCACHED (TT_DESCRIPTOR_TYPE_SECTION | \ + TT_DESCRIPTOR_SECTION_NS_NON_SECURE | \ + TT_DESCRIPTOR_SECTION_NG_GLOBAL | \ + TT_DESCRIPTOR_SECTION_S_NOT_SHARED | \ + TT_DESCRIPTOR_SECTION_DOMAIN(0) | \ + TT_DESCRIPTOR_SECTION_AP_RW_RW | \ + TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE) + +#endif // __ARM1176JZ_S_H__ diff --git a/ArmPkg/Include/Chipset/ARM926EJ-S.h b/ArmPkg/Include/Chipset/ARM926EJ-S.h new file mode 100644 index 0000000000..799d60c392 --- /dev/null +++ b/ArmPkg/Include/Chipset/ARM926EJ-S.h @@ -0,0 +1,71 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __ARM926EJ_S_H__ +#define __ARM926EJ_S_H__ + +// Domain Access Control Register +#define DOMAIN_ACCESS_CONTROL_MASK(a) (3UL << (2 * (a))) +#define DOMAIN_ACCESS_CONTROL_NONE(a) (0UL << (2 * (a))) +#define DOMAIN_ACCESS_CONTROL_CLIENT(a) (1UL << (2 * (a))) +#define DOMAIN_ACCESS_CONTROL_RESERVED(a) (2UL << (2 * (a))) +#define DOMAIN_ACCESS_CONTROL_MANAGER(a) (3UL << (2 * (a))) + +#define TRANSLATION_TABLE_SIZE (16 * 1024) +#define TRANSLATION_TABLE_ALIGNMENT (16 * 1024) +#define TRANSLATION_TABLE_ALIGNMENT_MASK (TRANSLATION_TABLE_ALIGNMENT - 1) + +#define TRANSLATION_TABLE_ENTRY_FOR_VIRTUAL_ADDRESS(table, address) ((UINT32 *)(table) + (((UINTN)(address)) >> 20)) + +// Translation table descriptor types +#define TT_DESCRIPTOR_TYPE_MASK (3UL << 0) +#define TT_DESCRIPTOR_TYPE_FAULT (0UL << 0) +#define TT_DESCRIPTOR_TYPE_COARSE ((1UL << 0) | (1UL << 4)) +#define TT_DESCRIPTOR_TYPE_SECTION ((2UL << 0) | (1UL << 4)) +#define TT_DESCRIPTOR_TYPE_FINE ((3UL << 0) | (1UL << 4)) + +// Section descriptor definitions +#define TT_DESCRIPTOR_SECTION_SIZE (0x00100000) + +#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK (3UL << 2) +#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_UNCACHED_UNBUFFERED (0UL << 2) +#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_UNCACHED_BUFFERED (1UL << 2) +#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH (2UL << 2) +#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK (3UL << 2) + +#define TT_DESCRIPTOR_SECTION_ACCESS_PERMISSION_MASK (3UL << 10) +#define TT_DESCRIPTOR_SECTION_ACCESS_PERMISSION_NONE (1UL << 10) +#define TT_DESCRIPTOR_SECTION_ACCESS_PERMISSION_READ_ONLY (2UL << 10) +#define TT_DESCRIPTOR_SECTION_ACCESS_PERMISSION_READ_WRITE (3UL << 10) + +#define TT_DESCRIPTOR_SECTION_DOMAIN_MASK (0x0FUL << 5) +#define TT_DESCRIPTOR_SECTION_DOMAIN(a) (((a) & 0xF) << 5) + +#define TT_DESCRIPTOR_SECTION_BASE_ADDRESS_MASK (0xFFF00000) +#define TT_DESCRIPTOR_SECTION_BASE_ADDRESS(a) (a & TT_DESCRIPTOR_SECTION_BASE_ADDRESS_MASK) + +#define TT_DESCRIPTOR_SECTION_WRITE_BACK (TT_DESCRIPTOR_SECTION_ACCESS_PERMISSION_READ_WRITE | \ + TT_DESCRIPTOR_SECTION_DOMAIN(0) | \ + TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK | \ + TT_DESCRIPTOR_TYPE_SECTION) +#define TT_DESCRIPTOR_SECTION_WRITE_THROUGH (TT_DESCRIPTOR_SECTION_ACCESS_PERMISSION_READ_WRITE | \ + TT_DESCRIPTOR_SECTION_DOMAIN(0) | \ + TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH | \ + TT_DESCRIPTOR_TYPE_SECTION) +#define TT_DESCRIPTOR_SECTION_UNCACHED_UNBUFFERED (TT_DESCRIPTOR_SECTION_ACCESS_PERMISSION_READ_WRITE | \ + TT_DESCRIPTOR_SECTION_DOMAIN(0) | \ + TT_DESCRIPTOR_SECTION_CACHE_POLICY_UNCACHED_UNBUFFERED | \ + TT_DESCRIPTOR_TYPE_SECTION) + +#endif // __ARM926EJ_S_H__ diff --git a/ArmPkg/Include/Chipset/Cortex-A8.h b/ArmPkg/Include/Chipset/Cortex-A8.h new file mode 100644 index 0000000000..75ce397a79 --- /dev/null +++ b/ArmPkg/Include/Chipset/Cortex-A8.h @@ -0,0 +1,104 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __CORTEX_A8_H__ +#define __CORTEX_A8_H__ + +// Domain Access Control Register +#define DOMAIN_ACCESS_CONTROL_MASK(a) (3UL << (2 * (a))) +#define DOMAIN_ACCESS_CONTROL_NONE(a) (0UL << (2 * (a))) +#define DOMAIN_ACCESS_CONTROL_CLIENT(a) (1UL << (2 * (a))) +#define DOMAIN_ACCESS_CONTROL_RESERVED(a) (2UL << (2 * (a))) +#define DOMAIN_ACCESS_CONTROL_MANAGER(a) (3UL << (2 * (a))) + +#define TRANSLATION_TABLE_SIZE (16 * 1024) +#define TRANSLATION_TABLE_ALIGNMENT (16 * 1024) +#define TRANSLATION_TABLE_ALIGNMENT_MASK (TRANSLATION_TABLE_ALIGNMENT - 1) + +#define TRANSLATION_TABLE_ENTRY_FOR_VIRTUAL_ADDRESS(table, address) ((UINT32 *)(table) + (((UINTN)(address)) >> 20)) + +// Translation table descriptor types +#define TT_DESCRIPTOR_TYPE_MASK ((1UL << 18) | (3UL << 0)) +#define TT_DESCRIPTOR_TYPE_PAGE_TABLE ((0UL << 18) | (1UL << 0)) +#define TT_DESCRIPTOR_TYPE_SECTION ((0UL << 18) | (2UL << 0)) +#define TT_DESCRIPTOR_TYPE_SUPERSECTION ((1UL << 18) | (2UL << 0)) + +// Section descriptor definitions +#define TT_DESCRIPTOR_SECTION_SIZE (0x00100000) + +#define TT_DESCRIPTOR_SECTION_NS_MASK (1UL << 19) +#define TT_DESCRIPTOR_SECTION_NS_SECURE (0UL << 19) +#define TT_DESCRIPTOR_SECTION_NS_NON_SECURE (1UL << 19) + +#define TT_DESCRIPTOR_SECTION_NG_MASK (1UL << 17) +#define TT_DESCRIPTOR_SECTION_NG_GLOBAL (0UL << 17) +#define TT_DESCRIPTOR_SECTION_NG_LOCAL (1UL << 17) + +#define TT_DESCRIPTOR_SECTION_S_MASK (1UL << 16) +#define TT_DESCRIPTOR_SECTION_S_NOT_SHARED (0UL << 16) +#define TT_DESCRIPTOR_SECTION_S_SHARED (1UL << 16) + +#define TT_DESCRIPTOR_SECTION_AP_MASK ((1UL << 15) | (3UL << 10)) +#define TT_DESCRIPTOR_SECTION_AP_NO_NO ((0UL << 15) | (0UL << 10)) +#define TT_DESCRIPTOR_SECTION_AP_RW_NO ((0UL << 15) | (1UL << 10)) +#define TT_DESCRIPTOR_SECTION_AP_RW_RO ((0UL << 15) | (2UL << 10)) +#define TT_DESCRIPTOR_SECTION_AP_RW_RW ((0UL << 15) | (3UL << 10)) +#define TT_DESCRIPTOR_SECTION_AP_RO_NO ((1UL << 15) | (1UL << 10)) +#define TT_DESCRIPTOR_SECTION_AP_RO_RO ((1UL << 15) | (3UL << 10)) + +#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK ((3UL << 12) | (0UL << 3) | (0UL << 2)) +#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_STRONGLY_ORDERED ((0UL << 12) | (0UL << 3) | (0UL << 2)) +#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_SHAREABLE_DEVICE ((0UL << 12) | (0UL << 3) | (1UL << 2)) +#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC ((0UL << 12) | (1UL << 3) | (0UL << 2)) +#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_NO_ALLOC ((0UL << 12) | (1UL << 3) | (1UL << 2)) +#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE ((1UL << 12) | (0UL << 3) | (0UL << 2)) +#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC ((1UL << 12) | (1UL << 3) | (1UL << 2)) +#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_SHAREABLE_DEVICE ((2UL << 12) | (0UL << 3) | (0UL << 2)) + +#define TT_DESCRIPTOR_SECTION_DOMAIN_MASK (0x0FUL << 5) +#define TT_DESCRIPTOR_SECTION_DOMAIN(a) (((a) & 0x0FUL) << 5) + +#define TT_DESCRIPTOR_SECTION_BASE_ADDRESS_MASK (0xFFF00000) +#define TT_DESCRIPTOR_SECTION_BASE_ADDRESS(a) (a & TT_DESCRIPTOR_SECTION_BASE_ADDRESS_MASK) + +#define TT_DESCRIPTOR_SECTION_WRITE_BACK (TT_DESCRIPTOR_TYPE_SECTION | \ + TT_DESCRIPTOR_SECTION_NS_NON_SECURE | \ + TT_DESCRIPTOR_SECTION_NG_GLOBAL | \ + TT_DESCRIPTOR_SECTION_S_NOT_SHARED | \ + TT_DESCRIPTOR_SECTION_DOMAIN(0) | \ + TT_DESCRIPTOR_SECTION_AP_RW_RW | \ + TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC) +#define TT_DESCRIPTOR_SECTION_WRITE_THROUGH (TT_DESCRIPTOR_TYPE_SECTION | \ + TT_DESCRIPTOR_SECTION_NS_NON_SECURE | \ + TT_DESCRIPTOR_SECTION_NG_GLOBAL | \ + TT_DESCRIPTOR_SECTION_S_NOT_SHARED | \ + TT_DESCRIPTOR_SECTION_DOMAIN(0) | \ + TT_DESCRIPTOR_SECTION_AP_RW_RW | \ + TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC) +#define TT_DESCRIPTOR_SECTION_DEVICE (TT_DESCRIPTOR_TYPE_SECTION | \ + TT_DESCRIPTOR_SECTION_NS_NON_SECURE | \ + TT_DESCRIPTOR_SECTION_NG_GLOBAL | \ + TT_DESCRIPTOR_SECTION_S_NOT_SHARED | \ + TT_DESCRIPTOR_SECTION_DOMAIN(0) | \ + TT_DESCRIPTOR_SECTION_AP_RW_RW | \ + TT_DESCRIPTOR_SECTION_CACHE_POLICY_SHAREABLE_DEVICE) +#define TT_DESCRIPTOR_SECTION_UNCACHED (TT_DESCRIPTOR_TYPE_SECTION | \ + TT_DESCRIPTOR_SECTION_NS_NON_SECURE | \ + TT_DESCRIPTOR_SECTION_NG_GLOBAL | \ + TT_DESCRIPTOR_SECTION_S_NOT_SHARED | \ + TT_DESCRIPTOR_SECTION_DOMAIN(0) | \ + TT_DESCRIPTOR_SECTION_AP_RW_RW | \ + TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE) + +#endif // __CORTEX_A8_H__ diff --git a/ArmPkg/Include/Library/ArmLib.h b/ArmPkg/Include/Library/ArmLib.h new file mode 100644 index 0000000000..d68b334e2a --- /dev/null +++ b/ArmPkg/Include/Library/ArmLib.h @@ -0,0 +1,294 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __ARM_LIB__ +#define __ARM_LIB__ + +typedef enum { + ARM_CACHE_TYPE_WRITE_BACK, + ARM_CACHE_TYPE_UNKNOWN +} ARM_CACHE_TYPE; + +typedef enum { + ARM_CACHE_ARCHITECTURE_UNIFIED, + ARM_CACHE_ARCHITECTURE_SEPARATE, + ARM_CACHE_ARCHITECTURE_UNKNOWN +} ARM_CACHE_ARCHITECTURE; + +typedef struct { + ARM_CACHE_TYPE Type; + ARM_CACHE_ARCHITECTURE Architecture; + BOOLEAN DataCachePresent; + UINTN DataCacheSize; + UINTN DataCacheAssociativity; + UINTN DataCacheLineLength; + BOOLEAN InstructionCachePresent; + UINTN InstructionCacheSize; + UINTN InstructionCacheAssociativity; + UINTN InstructionCacheLineLength; +} ARM_CACHE_INFO; + +typedef enum { + ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED, + ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK, + ARM_MEMORY_REGION_ATTRIBUTE_WRITE_THROUGH, + ARM_MEMORY_REGION_ATTRIBUTE_DEVICE +} ARM_MEMORY_REGION_ATTRIBUTES; + +typedef struct { + UINT32 PhysicalBase; + UINT32 VirtualBase; + UINT32 Length; + ARM_MEMORY_REGION_ATTRIBUTES Attributes; +} ARM_MEMORY_REGION_DESCRIPTOR; + +typedef VOID (*CACHE_OPERATION)(VOID); +typedef VOID (*LINE_OPERATION)(UINTN); + +typedef enum { + ARM_PROCESSOR_MODE_USER = 0x10, + ARM_PROCESSOR_MODE_FIQ = 0x11, + ARM_PROCESSOR_MODE_IRQ = 0x12, + ARM_PROCESSOR_MODE_SUPERVISOR = 0x13, + ARM_PROCESSOR_MODE_ABORT = 0x17, + ARM_PROCESSOR_MODE_UNDEFINED = 0x1B, + ARM_PROCESSOR_MODE_SYSTEM = 0x1F, + ARM_PROCESSOR_MODE_MASK = 0x1F +} ARM_PROCESSOR_MODE; + +ARM_CACHE_TYPE +EFIAPI +ArmCacheType ( + VOID + ); + +ARM_CACHE_ARCHITECTURE +EFIAPI +ArmCacheArchitecture ( + VOID + ); + +VOID +EFIAPI +ArmCacheInformation ( + OUT ARM_CACHE_INFO *CacheInfo + ); + +BOOLEAN +EFIAPI +ArmDataCachePresent ( + VOID + ); + +UINTN +EFIAPI +ArmDataCacheSize ( + VOID + ); + +UINTN +EFIAPI +ArmDataCacheAssociativity ( + VOID + ); + +UINTN +EFIAPI +ArmDataCacheLineLength ( + VOID + ); + +BOOLEAN +EFIAPI +ArmInstructionCachePresent ( + VOID + ); + +UINTN +EFIAPI +ArmInstructionCacheSize ( + VOID + ); + +UINTN +EFIAPI +ArmInstructionCacheAssociativity ( + VOID + ); + +UINTN +EFIAPI +ArmInstructionCacheLineLength ( + VOID + ); + +UINT32 +EFIAPI +Cp15IdCode ( + VOID + ); + +UINT32 +EFIAPI +Cp15CacheInfo ( + VOID + ); + +VOID +EFIAPI +ArmInvalidateDataCache ( + VOID + ); + +VOID +EFIAPI +ArmCleanInvalidateDataCache ( + VOID + ); + +VOID +EFIAPI +ArmCleanDataCache ( + VOID + ); + +VOID +EFIAPI +ArmInvalidateInstructionCache ( + VOID + ); + +VOID +EFIAPI +ArmInvalidateDataCacheEntryByMVA ( + IN UINTN Address + ); + +VOID +EFIAPI +ArmCleanDataCacheEntryByMVA ( + IN UINTN Address + ); + +VOID +EFIAPI +ArmCleanInvalidateDataCacheEntryByMVA ( + IN UINTN Address + ); + +VOID +EFIAPI +ArmEnableDataCache ( + VOID + ); + +VOID +EFIAPI +ArmDisableDataCache ( + VOID + ); + +VOID +EFIAPI +ArmEnableInstructionCache ( + VOID + ); + +VOID +EFIAPI +ArmDisableInstructionCache ( + VOID + ); + +VOID +EFIAPI +ArmEnableMmu ( + VOID + ); + +VOID +EFIAPI +ArmDisableMmu ( + VOID + ); + +VOID +EFIAPI +ArmEnableInterrupts ( + VOID + ); + +UINTN +EFIAPI +ArmDisableInterrupts ( + VOID + ); + +BOOLEAN +EFIAPI +ArmGetInterruptState ( + VOID + ); + +VOID +EFIAPI +ArmInvalidateTlb ( + VOID + ); + +VOID +EFIAPI +ArmSetDomainAccessControl ( + IN UINT32 Domain + ); + +VOID +EFIAPI +ArmSetTranslationTableBaseAddress ( + IN VOID *TranslationTableBase + ); + +VOID +EFIAPI +ArmConfigureMmu ( + IN ARM_MEMORY_REGION_DESCRIPTOR *MemoryTable, + OUT VOID **TranslationTableBase OPTIONAL, + OUT UINTN *TranslationTableSize OPTIONAL + ); + +VOID +EFIAPI +ArmSwitchProcessorMode ( + IN ARM_PROCESSOR_MODE Mode + ); + +ARM_PROCESSOR_MODE +EFIAPI +ArmProcessorMode ( + VOID + ); + +VOID +EFIAPI +ArmEnableBranchPrediction ( + VOID + ); + +VOID +EFIAPI +ArmDisableBranchPrediction ( + VOID + ); + +#endif // __ARM_LIB__ diff --git a/ArmPkg/Include/Library/SemihostLib.h b/ArmPkg/Include/Library/SemihostLib.h new file mode 100644 index 0000000000..2c8b6ac7d8 --- /dev/null +++ b/ArmPkg/Include/Library/SemihostLib.h @@ -0,0 +1,100 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __SEMIHOSTING_H__ +#define __SEMIHOSTING_H__ + +/* + * + * Please refer to ARM RVDS 3.0 Compiler and Libraries Guide for more information + * about the semihosting interface. + * + */ + +#define SEMIHOST_FILE_MODE_READ (0 << 2) +#define SEMIHOST_FILE_MODE_WRITE (1 << 2) +#define SEMIHOST_FILE_MODE_APPEND (2 << 2) +#define SEMIHOST_FILE_MODE_CREATE (1 << 1) +#define SEMIHOST_FILE_MODE_BINARY (1 << 0) +#define SEMIHOST_FILE_MODE_ASCII (0 << 0) + +BOOLEAN +SemihostConnectionSupported ( + VOID + ); + +EFI_STATUS +SemihostFileOpen ( + IN CHAR8 *FileName, + IN UINT32 Mode, + OUT UINT32 *FileHandle + ); + +EFI_STATUS +SemihostFileSeek ( + IN UINT32 FileHandle, + IN UINT32 Offset + ); + +EFI_STATUS +SemihostFileRead ( + IN UINT32 FileHandle, + IN OUT UINT32 *Length, + OUT VOID *Buffer + ); + +EFI_STATUS +SemihostFileWrite ( + IN UINT32 FileHandle, + IN OUT UINT32 *Length, + IN VOID *Buffer + ); + +EFI_STATUS +SemihostFileClose ( + IN UINT32 FileHandle + ); + +EFI_STATUS +SemihostFileLength ( + IN UINT32 FileHandle, + OUT UINT32 *Length + ); + +EFI_STATUS +SemihostFileRemove ( + IN CHAR8 *FileName + ); + +CHAR8 +SemihostReadCharacter ( + VOID + ); + +VOID +SemihostWriteCharacter ( + IN CHAR8 Character + ); + +VOID +SemihostWriteString ( + IN CHAR8 *String + ); + +UINT32 +SemihostSystem ( + IN CHAR8 *CommandLine + ); + +#endif // __SEMIHOSTING_H__ diff --git a/ArmPkg/Include/Library/UncachedMemoryAllocationLib.h b/ArmPkg/Include/Library/UncachedMemoryAllocationLib.h new file mode 100644 index 0000000000..8a65fcc586 --- /dev/null +++ b/ArmPkg/Include/Library/UncachedMemoryAllocationLib.h @@ -0,0 +1,665 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __UNCACHED_MEMORY_ALLOCATION_LIB_H__ +#define __UNCACHED_MEMORY_ALLOCATION_LIB_H__ + +/** + Converts a cached or uncached address to a physical address suitable for use in SoC registers. + + @param VirtualAddress The pointer to convert. + + @return The physical address of the supplied virtual pointer. + +**/ +EFI_PHYSICAL_ADDRESS +ConvertToPhysicalAddress ( + IN VOID *VirtualAddress + ); + +/** + Converts a cached or uncached address to a cached address. + + @param Address The pointer to convert. + + @return The address of the cached memory location corresponding to the input address. + +**/ +VOID * +ConvertToCachedAddress ( + IN VOID *Address + ); + +/** + Converts a cached or uncached address to an uncached address. + + @param Address The pointer to convert. + + @return The address of the uncached memory location corresponding to the input address. + +**/ +VOID * +ConvertToUncachedAddress ( + IN VOID *Address + ); + +/** + Allocates one or more 4KB pages of type EfiBootServicesData. + + Allocates the number of 4KB pages of type EfiBootServicesData and returns a pointer to the + allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL + is returned. If there is not enough memory remaining to satisfy the request, then NULL is + returned. + + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocatePages ( + IN UINTN Pages + ); + +/** + Allocates one or more 4KB pages of type EfiRuntimeServicesData. + + Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer to the + allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL + is returned. If there is not enough memory remaining to satisfy the request, then NULL is + returned. + + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateRuntimePages ( + IN UINTN Pages + ); + +/** + Allocates one or more 4KB pages of type EfiReservedMemoryType. + + Allocates the number of 4KB pages of type EfiReservedMemoryType and returns a pointer to the + allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL + is returned. If there is not enough memory remaining to satisfy the request, then NULL is + returned. + + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateReservedPages ( + IN UINTN Pages + ); + +/** + Frees one or more 4KB pages that were previously allocated with one of the page allocation + functions in the Memory Allocation Library. + + Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer + must have been allocated on a previous call to the page allocation services of the Memory + Allocation Library. + If Buffer was not allocated with a page allocation function in the Memory Allocation Library, + then ASSERT(). + If Pages is zero, then ASSERT(). + + @param Buffer Pointer to the buffer of pages to free. + @param Pages The number of 4 KB pages to free. + +**/ +VOID +EFIAPI +UncachedFreePages ( + IN VOID *Buffer, + IN UINTN Pages + ); + +/** + Allocates one or more 4KB pages of type EfiBootServicesData at a specified alignment. + + Allocates the number of 4KB pages specified by Pages of type EfiBootServicesData with an + alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is + returned. If there is not enough memory at the specified alignment remaining to satisfy the + request, then NULL is returned. + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateAlignedPages ( + IN UINTN Pages, + IN UINTN Alignment + ); + +/** + Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment. + + Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData with an + alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is + returned. If there is not enough memory at the specified alignment remaining to satisfy the + request, then NULL is returned. + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateAlignedRuntimePages ( + IN UINTN Pages, + IN UINTN Alignment + ); + +/** + Allocates one or more 4KB pages of type EfiReservedMemoryType at a specified alignment. + + Allocates the number of 4KB pages specified by Pages of type EfiReservedMemoryType with an + alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is + returned. If there is not enough memory at the specified alignment remaining to satisfy the + request, then NULL is returned. + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateAlignedReservedPages ( + IN UINTN Pages, + IN UINTN Alignment + ); + +/** + Frees one or more 4KB pages that were previously allocated with one of the aligned page + allocation functions in the Memory Allocation Library. + + Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer + must have been allocated on a previous call to the aligned page allocation services of the Memory + Allocation Library. + If Buffer was not allocated with an aligned page allocation function in the Memory Allocation + Library, then ASSERT(). + If Pages is zero, then ASSERT(). + + @param Buffer Pointer to the buffer of pages to free. + @param Pages The number of 4 KB pages to free. + +**/ +VOID +EFIAPI +UncachedFreeAlignedPages ( + IN VOID *Buffer, + IN UINTN Pages + ); + +/** + Allocates a buffer of type EfiBootServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiBootServicesData and returns a + pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is + returned. If there is not enough memory remaining to satisfy the request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocatePool ( + IN UINTN AllocationSize + ); + +/** + Allocates a buffer of type EfiRuntimeServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData and returns + a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is + returned. If there is not enough memory remaining to satisfy the request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateRuntimePool ( + IN UINTN AllocationSize + ); + +/** + Allocates a buffer of type EfieservedMemoryType. + + Allocates the number bytes specified by AllocationSize of type EfieservedMemoryType and returns + a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is + returned. If there is not enough memory remaining to satisfy the request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateReservedPool ( + IN UINTN AllocationSize + ); + +/** + Allocates and zeros a buffer of type EfiBootServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, clears the + buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a + valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the + request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateZeroPool ( + IN UINTN AllocationSize + ); + +/** + Allocates and zeros a buffer of type EfiRuntimeServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, clears the + buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a + valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the + request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateRuntimeZeroPool ( + IN UINTN AllocationSize + ); + +/** + Allocates and zeros a buffer of type EfiReservedMemoryType. + + Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, clears the + buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a + valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the + request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateReservedZeroPool ( + IN UINTN AllocationSize + ); + +/** + Copies a buffer to an allocated buffer of type EfiBootServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, copies + AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the + allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there + is not enough memory remaining to satisfy the request, then NULL is returned. + If Buffer is NULL, then ASSERT(). + If AllocationSize is greater than (MAX_ADDRESS ? Buffer + 1), then ASSERT(). + + @param AllocationSize The number of bytes to allocate and zero. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ); + +/** + Copies a buffer to an allocated buffer of type EfiRuntimeServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, copies + AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the + allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there + is not enough memory remaining to satisfy the request, then NULL is returned. + If Buffer is NULL, then ASSERT(). + If AllocationSize is greater than (MAX_ADDRESS ? Buffer + 1), then ASSERT(). + + @param AllocationSize The number of bytes to allocate and zero. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateRuntimeCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ); + +/** + Copies a buffer to an allocated buffer of type EfiReservedMemoryType. + + Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, copies + AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the + allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there + is not enough memory remaining to satisfy the request, then NULL is returned. + If Buffer is NULL, then ASSERT(). + If AllocationSize is greater than (MAX_ADDRESS ? Buffer + 1), then ASSERT(). + + @param AllocationSize The number of bytes to allocate and zero. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateReservedCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ); + +/** + Frees a buffer that was previously allocated with one of the pool allocation functions in the + Memory Allocation Library. + + Frees the buffer specified by Buffer. Buffer must have been allocated on a previous call to the + pool allocation services of the Memory Allocation Library. + If Buffer was not allocated with a pool allocation function in the Memory Allocation Library, + then ASSERT(). + + @param Buffer Pointer to the buffer to free. + +**/ +VOID +EFIAPI +UncachedFreePool ( + IN VOID *Buffer + ); + +/** + Allocates a buffer of type EfiBootServicesData at a specified alignment. + + Allocates the number bytes specified by AllocationSize of type EfiBootServicesData with an + alignment specified by Alignment. The allocated buffer is returned. If AllocationSize is 0, + then a valid buffer of 0 size is returned. If there is not enough memory at the specified + alignment remaining to satisfy the request, then NULL is returned. + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + + @param AllocationSize The number of bytes to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateAlignedPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ); + +/** + Allocates a buffer of type EfiRuntimeServicesData at a specified alignment. + + Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData with an + alignment specified by Alignment. The allocated buffer is returned. If AllocationSize is 0, + then a valid buffer of 0 size is returned. If there is not enough memory at the specified + alignment remaining to satisfy the request, then NULL is returned. + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + + @param AllocationSize The number of bytes to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateAlignedRuntimePool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ); + +/** + Allocates a buffer of type EfieservedMemoryType at a specified alignment. + + Allocates the number bytes specified by AllocationSize of type EfieservedMemoryType with an + alignment specified by Alignment. The allocated buffer is returned. If AllocationSize is 0, + then a valid buffer of 0 size is returned. If there is not enough memory at the specified + alignment remaining to satisfy the request, then NULL is returned. + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + + @param AllocationSize The number of bytes to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateAlignedReservedPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ); + +/** + Allocates and zeros a buffer of type EfiBootServicesData at a specified alignment. + + Allocates the number bytes specified by AllocationSize of type EfiBootServicesData with an + alignment specified by Alignment, clears the buffer with zeros, and returns a pointer to the + allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there + is not enough memory at the specified alignment remaining to satisfy the request, then NULL is + returned. + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + + @param AllocationSize The number of bytes to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateAlignedZeroPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ); + +/** + Allocates and zeros a buffer of type EfiRuntimeServicesData at a specified alignment. + + Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData with an + alignment specified by Alignment, clears the buffer with zeros, and returns a pointer to the + allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there + is not enough memory at the specified alignment remaining to satisfy the request, then NULL is + returned. + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + + @param AllocationSize The number of bytes to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateAlignedRuntimeZeroPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ); + +/** + Allocates and zeros a buffer of type EfieservedMemoryType at a specified alignment. + + Allocates the number bytes specified by AllocationSize of type EfieservedMemoryType with an + alignment specified by Alignment, clears the buffer with zeros, and returns a pointer to the + allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there + is not enough memory at the specified alignment remaining to satisfy the request, then NULL is + returned. + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + + @param AllocationSize The number of bytes to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateAlignedReservedZeroPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ); + +/** + Copies a buffer to an allocated buffer of type EfiBootServicesData at a specified alignment. + + Allocates the number bytes specified by AllocationSize of type EfiBootServicesData type with an + alignment specified by Alignment. The allocated buffer is returned. If AllocationSize is 0, + then a valid buffer of 0 size is returned. If there is not enough memory at the specified + alignment remaining to satisfy the request, then NULL is returned. + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + + @param AllocationSize The number of bytes to allocate. + @param Buffer The buffer to copy to the allocated buffer. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateAlignedCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer, + IN UINTN Alignment + ); + +/** + Copies a buffer to an allocated buffer of type EfiRuntimeServicesData at a specified alignment. + + Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData type with an + alignment specified by Alignment. The allocated buffer is returned. If AllocationSize is 0, + then a valid buffer of 0 size is returned. If there is not enough memory at the specified + alignment remaining to satisfy the request, then NULL is returned. + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + + @param AllocationSize The number of bytes to allocate. + @param Buffer The buffer to copy to the allocated buffer. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateAlignedRuntimeCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer, + IN UINTN Alignment + ); + +/** + Copies a buffer to an allocated buffer of type EfiReservedMemoryType at a specified alignment. + + Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType type with an + alignment specified by Alignment. The allocated buffer is returned. If AllocationSize is 0, + then a valid buffer of 0 size is returned. If there is not enough memory at the specified + alignment remaining to satisfy the request, then NULL is returned. + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + + @param AllocationSize The number of bytes to allocate. + @param Buffer The buffer to copy to the allocated buffer. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateAlignedReservedCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer, + IN UINTN Alignment + ); + +/** + Frees a buffer that was previously allocated with one of the aligned pool allocation functions + in the Memory Allocation Library. + + Frees the buffer specified by Buffer. Buffer must have been allocated on a previous call to the + aligned pool allocation services of the Memory Allocation Library. + If Buffer was not allocated with an aligned pool allocation function in the Memory Allocation + Library, then ASSERT(). + + @param Buffer Pointer to the buffer to free. + +**/ +VOID +EFIAPI +UncachedFreeAlignedPool ( + IN VOID *Buffer + ); + +VOID +EFIAPI +UncachedSafeFreePool ( + IN VOID *Buffer + ); + +#endif // __UNCACHED_MEMORY_ALLOCATION_LIB_H__ diff --git a/ArmPkg/Include/Protocol/TimerDebugSupport.h b/ArmPkg/Include/Protocol/TimerDebugSupport.h new file mode 100644 index 0000000000..8ed9254176 --- /dev/null +++ b/ArmPkg/Include/Protocol/TimerDebugSupport.h @@ -0,0 +1,59 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __TIMERDEBUGSUPPORTPROTOCOL_H__ +#define __TIMERDEBUGSUPPORTPROTOCOL_H__ + +// +// Protocol GUID +// +#define TIMER_DEBUG_PROTOCOL_GUID { 0x68300561, 0x0197, 0x465d, { 0xb5, 0xa1, 0x28, 0xeb, 0xa1, 0x98, 0xdd, 0x0b } } + + + +// +// Protocol interface structure +// +typedef struct _TIMER_DEBUG_SUPPORT_PROTOCOL TIMER_DEBUG_SUPPORT_PROTOCOL; + + +typedef +EFI_STATUS +(EFIAPI *TIMER_DEBUG_SUPPORT_REGISTER_PERIODIC_CALLBACK) ( + IN TIMER_DEBUG_SUPPORT_PROTOCOL *This, + IN EFI_PERIODIC_CALLBACK PeriodicCallback + ) +/*++ + +Routine Description: + Register a periodic callback for debug support. + +Arguments: + This - pointer to protocol + PeriodicCallback - callback to be registered + +Returns: + EFI_SUCCESS - callback registered + +--*/ +; + +struct _TIMER_DEBUG_SUPPORT_PROTOCOL { + TIMER_DEBUG_SUPPORT_REGISTER_PERIODIC_CALLBACK RegisterPeriodicCallback; +}; + +extern EFI_GUID gTimerDebugSupportProtocolGuid; + +#endif // __TIMERDEBUGSUPPORTPROTOCOL_H__ + diff --git a/ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.c b/ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.c new file mode 100644 index 0000000000..7da6b42a92 --- /dev/null +++ b/ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.c @@ -0,0 +1,129 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +#include +#include +#include + +VOID +CacheRangeOperation ( + IN VOID *Start, + IN UINTN Length, + IN CACHE_OPERATION CacheOperation, + IN LINE_OPERATION LineOperation + ) +{ + UINTN ArmCacheLineLength = ArmDataCacheLineLength(); + UINTN ArmCacheLineAlignmentMask = ArmCacheLineLength - 1; + UINTN ArmCacheOperationThreshold = PcdGet32(PcdArmCacheOperationThreshold); + + if ((CacheOperation != NULL) && (Length >= ArmCacheOperationThreshold)) + { + CacheOperation(); + } + else + { + // Align address (rounding down) + UINTN AlignedAddress = (UINTN)Start - ((UINTN)Start & ArmCacheLineAlignmentMask); + UINTN EndAddress = (UINTN)Start + Length; + + // Perform the line operation on an address in each cache line + while (AlignedAddress < EndAddress) + { + LineOperation(AlignedAddress); + AlignedAddress += ArmCacheLineLength; + } + } +} + +VOID +EFIAPI +InvalidateInstructionCache ( + VOID + ) +{ + ArmCleanDataCache(); + ArmInvalidateInstructionCache(); +} + +VOID +EFIAPI +InvalidateDataCache ( + VOID + ) +{ + ArmInvalidateDataCache(); +} + +VOID * +EFIAPI +InvalidateInstructionCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + CacheRangeOperation(Address, Length, ArmCleanDataCache, ArmCleanDataCacheEntryByMVA); + ArmInvalidateInstructionCache(); + return Address; +} + +VOID +EFIAPI +WriteBackInvalidateDataCache ( + VOID + ) +{ + ArmCleanInvalidateDataCache(); +} + +VOID * +EFIAPI +WriteBackInvalidateDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + CacheRangeOperation(Address, Length, ArmCleanInvalidateDataCache, ArmCleanInvalidateDataCacheEntryByMVA); + return Address; +} + +VOID +EFIAPI +WriteBackDataCache ( + VOID + ) +{ + ArmCleanDataCache(); +} + +VOID * +EFIAPI +WriteBackDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + CacheRangeOperation(Address, Length, ArmCleanDataCache, ArmCleanDataCacheEntryByMVA); + return Address; +} + +VOID * +EFIAPI +InvalidateDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + CacheRangeOperation(Address, Length, NULL, ArmInvalidateDataCacheEntryByMVA); + return Address; +} diff --git a/ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.inf b/ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.inf new file mode 100644 index 0000000000..93b88f4ef0 --- /dev/null +++ b/ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.inf @@ -0,0 +1,23 @@ +#%HEADER% +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ArmCacheMaintenanceLib + FILE_GUID = 1A20BE1F-33AD-450C-B49A-7123FCA8B7F9 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = CacheMaintenanceLib + +[Sources.common] + ArmCacheMaintenanceLib.c + +[Packages] + ArmPkg/ArmPkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + ArmLib + BaseLib + +[FixedPcd] + gArmTokenSpaceGuid.PcdArmCacheOperationThreshold + diff --git a/ArmPkg/Library/ArmLib/Arm11/Arm11ArmLib.inf b/ArmPkg/Library/ArmLib/Arm11/Arm11ArmLib.inf new file mode 100644 index 0000000000..8042e4dd31 --- /dev/null +++ b/ArmPkg/Library/ArmLib/Arm11/Arm11ArmLib.inf @@ -0,0 +1,32 @@ +#%HEADER% +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = Arm11ArmLib + FILE_GUID = 00586300-0E06-4790-AC44-86C56ACBB942 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = ArmLib + +[Sources.common] + ../Common/ArmLibSupport.S | GCC + ../Common/ArmLibSupport.asm | RVCT + ../Common/ArmLib.c + + Arm11Support.S | GCC + Arm11Support.asm | RVCT + + Arm11Lib.c + ../Arm9/Arm9CacheInformation.c + +[Packages] + ArmPkg/ArmPkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + MemoryAllocationLib + +[Protocols] + gEfiCpuArchProtocolGuid + +[FixedPcd] + gArmTokenSpaceGuid.PcdArmCacheOperationThreshold diff --git a/ArmPkg/Library/ArmLib/Arm11/Arm11ArmLibPrePi.inf b/ArmPkg/Library/ArmLib/Arm11/Arm11ArmLibPrePi.inf new file mode 100644 index 0000000000..040179e445 --- /dev/null +++ b/ArmPkg/Library/ArmLib/Arm11/Arm11ArmLibPrePi.inf @@ -0,0 +1,32 @@ +#%HEADER% +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = Arm11ArmLib + FILE_GUID = 8dfb4ea2-3901-44f9-ae54-ca3d50362d2f + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = ArmLib + +[Sources.common] + ../Common/ArmLibSupport.S | GCC + ../Common/ArmLibSupport.asm | RVCT + ../Common/ArmLib.c + + Arm11Support.S | GCC + Arm11Support.asm | RVCT + + Arm11Lib.c + ../Arm9/Arm9CacheInformation.c + +[Packages] + ArmPkg/ArmPkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + PrePiLib + +[Protocols] + gEfiCpuArchProtocolGuid + +[FixedPcd] + gArmTokenSpaceGuid.PcdArmCacheOperationThreshold diff --git a/ArmPkg/Library/ArmLib/Arm11/Arm11Lib.c b/ArmPkg/Library/ArmLib/Arm11/Arm11Lib.c new file mode 100644 index 0000000000..3736904954 --- /dev/null +++ b/ArmPkg/Library/ArmLib/Arm11/Arm11Lib.c @@ -0,0 +1,118 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include + +VOID +FillTranslationTable ( + IN UINT32 *TranslationTable, + IN ARM_MEMORY_REGION_DESCRIPTOR *MemoryRegion + ) +{ + UINT32 *Entry; + UINTN Sections; + UINTN Index; + UINT32 Attributes; + UINT32 PhysicalBase = MemoryRegion->PhysicalBase; + + switch (MemoryRegion->Attributes) { + case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK: + Attributes = TT_DESCRIPTOR_SECTION_WRITE_BACK; + break; + case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_THROUGH: + Attributes = TT_DESCRIPTOR_SECTION_WRITE_THROUGH; + break; + case ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED: + default: + Attributes = TT_DESCRIPTOR_SECTION_UNCACHED; + break; + } + + Entry = TRANSLATION_TABLE_ENTRY_FOR_VIRTUAL_ADDRESS(TranslationTable, MemoryRegion->VirtualBase); + Sections = ((( MemoryRegion->Length - 1 ) / TT_DESCRIPTOR_SECTION_SIZE ) + 1 ); + + for (Index = 0; Index < Sections; Index++) + { + *Entry++ = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(PhysicalBase) | Attributes; + PhysicalBase += TT_DESCRIPTOR_SECTION_SIZE; + } +} + +VOID +EFIAPI +ArmConfigureMmu ( + IN ARM_MEMORY_REGION_DESCRIPTOR *MemoryTable, + OUT VOID **TranslationTableBase OPTIONAL, + OUT UINTN *TranslationTableSize OPTIONAL + ) +{ + VOID *TranslationTable; + + // Allocate pages for translation table. + TranslationTable = AllocatePages(EFI_SIZE_TO_PAGES(TRANSLATION_TABLE_SIZE + TRANSLATION_TABLE_ALIGNMENT)); + TranslationTable = (VOID *)(((UINTN)TranslationTable + TRANSLATION_TABLE_ALIGNMENT_MASK) & ~TRANSLATION_TABLE_ALIGNMENT_MASK); + + if (TranslationTableBase != NULL) { + *TranslationTableBase = TranslationTable; + } + + if (TranslationTableBase != NULL) { + *TranslationTableSize = TRANSLATION_TABLE_SIZE; + } + + ZeroMem(TranslationTable, TRANSLATION_TABLE_SIZE); + + ArmCleanInvalidateDataCache(); + ArmInvalidateInstructionCache(); + ArmInvalidateTlb(); + + ArmDisableDataCache(); + ArmDisableInstructionCache(); + ArmDisableMmu(); + + // Make sure nothing sneaked into the cache + ArmCleanInvalidateDataCache(); + ArmInvalidateInstructionCache(); + + while (MemoryTable->Length != 0) { + FillTranslationTable(TranslationTable, MemoryTable); + MemoryTable++; + } + + ArmSetTranslationTableBaseAddress(TranslationTable); + + ArmSetDomainAccessControl(DOMAIN_ACCESS_CONTROL_NONE(15) | + DOMAIN_ACCESS_CONTROL_NONE(14) | + DOMAIN_ACCESS_CONTROL_NONE(13) | + DOMAIN_ACCESS_CONTROL_NONE(12) | + DOMAIN_ACCESS_CONTROL_NONE(11) | + DOMAIN_ACCESS_CONTROL_NONE(10) | + DOMAIN_ACCESS_CONTROL_NONE( 9) | + DOMAIN_ACCESS_CONTROL_NONE( 8) | + DOMAIN_ACCESS_CONTROL_NONE( 7) | + DOMAIN_ACCESS_CONTROL_NONE( 6) | + DOMAIN_ACCESS_CONTROL_NONE( 5) | + DOMAIN_ACCESS_CONTROL_NONE( 4) | + DOMAIN_ACCESS_CONTROL_NONE( 3) | + DOMAIN_ACCESS_CONTROL_NONE( 2) | + DOMAIN_ACCESS_CONTROL_NONE( 1) | + DOMAIN_ACCESS_CONTROL_MANAGER(0)); + + ArmEnableInstructionCache(); + ArmEnableDataCache(); + ArmEnableMmu(); +} diff --git a/ArmPkg/Library/ArmLib/Arm11/Arm11Support.S b/ArmPkg/Library/ArmLib/Arm11/Arm11Support.S new file mode 100644 index 0000000000..eec8f20b4e --- /dev/null +++ b/ArmPkg/Library/ArmLib/Arm11/Arm11Support.S @@ -0,0 +1,129 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2008-2009 Apple Inc. All rights reserved. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + +.text +.align 2 +.globl ASM_PFX(ArmCleanInvalidateDataCache) +.globl ASM_PFX(ArmCleanDataCache) +.globl ASM_PFX(ArmInvalidateDataCache) +.globl ASM_PFX(ArmInvalidateInstructionCache) +.globl ASM_PFX(ArmInvalidateDataCacheEntryByMVA) +.globl ASM_PFX(ArmCleanDataCacheEntryByMVA) +.globl ASM_PFX(ArmCleanInvalidateDataCacheEntryByMVA) +.globl ASM_PFX(ArmEnableMmu) +.globl ASM_PFX(ArmDisableMmu) +.globl ASM_PFX(ArmEnableDataCache) +.globl ASM_PFX(ArmDisableDataCache) +.globl ASM_PFX(ArmEnableInstructionCache) +.globl ASM_PFX(ArmDisableInstructionCache) +.globl ASM_PFX(ArmEnableBranchPrediction) +.globl ASM_PFX(ArmDisableBranchPrediction) + +.set DC_ON, (0x1<<2) +.set IC_ON, (0x1<<12) +.set XP_ON, (0x1<<23) + +ASM_PFX(ArmInvalidateDataCacheEntryByMVA): + mcr p15, 0, r0, c7, c6, 1 @invalidate single data cache line + bx lr + + +ASM_PFX(ArmCleanDataCacheEntryByMVA): + mcr p15, 0, r0, c7, c10, 1 @clean single data cache line + bx lr + + +ASM_PFX(ArmCleanInvalidateDataCacheEntryByMVA): + mcr p15, 0, r0, c7, c14, 1 @clean and invalidate single data cache line + bx lr + + +ASM_PFX(ArmCleanDataCache): + mcr p15, 0, r0, c7, c10, 0 @ clean entire data cache + bx lr + + +ASM_PFX(ArmCleanInvalidateDataCache): + mcr p15, 0, r0, c7, c14, 0 @ clean and invalidate entire data cache + bx lr + + +ASM_PFX(ArmInvalidateDataCache): + mcr p15, 0, r0, c7, c6, 0 @ invalidate entire data cache + bx lr + + +ASM_PFX(ArmInvalidateInstructionCache): + mcr p15, 0, r0, c7, c5, 0 @invalidate entire instruction cache + mov R0,#0 + mcr p15,0,R0,c7,c5,4 @Flush Prefetch buffer + bx lr + +ASM_PFX(ArmEnableMmu): + mrc p15,0,R0,c1,c0,0 + orr R0,R0,#1 + mcr p15,0,R0,c1,c0,0 + bx LR + +ASM_PFX(ArmDisableMmu): + mrc p15,0,R0,c1,c0,0 + bic R0,R0,#1 + mcr p15,0,R0,c1,c0,0 + mov R0,#0 + mcr p15,0,R0,c7,c10,4 @Data synchronization barrier + mov R0,#0 + mcr p15,0,R0,c7,c5,4 @Flush Prefetch buffer + bx LR + +ASM_PFX(ArmEnableDataCache): + ldr R1,=DC_ON + mrc p15,0,R0,c1,c0,0 @Read control register configuration data + orr R0,R0,R1 @Set C bit + mcr p15,0,r0,c1,c0,0 @Write control register configuration data + bx LR + +ASM_PFX(ArmDisableDataCache): + ldr R1,=DC_ON + mrc p15,0,R0,c1,c0,0 @Read control register configuration data + bic R0,R0,R1 @Clear C bit + mcr p15,0,r0,c1,c0,0 @Write control register configuration data + bx LR + +ASM_PFX(ArmEnableInstructionCache): + ldr R1,=IC_ON + mrc p15,0,R0,c1,c0,0 @Read control register configuration data + orr R0,R0,R1 @Set I bit + mcr p15,0,r0,c1,c0,0 @Write control register configuration data + bx LR + +ASM_PFX(ArmDisableInstructionCache): + ldr R1,=IC_ON + mrc p15,0,R0,c1,c0,0 @Read control register configuration data + bic R0,R0,R1 @Clear I bit. + mcr p15,0,r0,c1,c0,0 @Write control register configuration data + bx LR + +ASM_PFX(ArmEnableBranchPrediction): + mrc p15, 0, r0, c1, c0, 0 + orr r0, r0, #0x00000800 + mcr p15, 0, r0, c1, c0, 0 + bx LR + +ASM_PFX(ArmDisableBranchPrediction): + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #0x00000800 + mcr p15, 0, r0, c1, c0, 0 + bx LR + +ASM_FUNCTION_REMOVE_IF_UNREFERENCED diff --git a/ArmPkg/Library/ArmLib/Arm11/Arm11Support.asm b/ArmPkg/Library/ArmLib/Arm11/Arm11Support.asm new file mode 100644 index 0000000000..e0be8f0c07 --- /dev/null +++ b/ArmPkg/Library/ArmLib/Arm11/Arm11Support.asm @@ -0,0 +1,133 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2008-2009 Apple Inc. All rights reserved. +// +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +//------------------------------------------------------------------------------ + + EXPORT ArmCleanInvalidateDataCache + EXPORT ArmCleanDataCache + EXPORT ArmInvalidateDataCache + EXPORT ArmInvalidateInstructionCache + EXPORT ArmInvalidateDataCacheEntryByMVA + EXPORT ArmCleanDataCacheEntryByMVA + EXPORT ArmCleanInvalidateDataCacheEntryByMVA + EXPORT ArmEnableMmu + EXPORT ArmDisableMmu + EXPORT ArmEnableDataCache + EXPORT ArmDisableDataCache + EXPORT ArmEnableInstructionCache + EXPORT ArmDisableInstructionCache + EXPORT ArmEnableBranchPrediction + EXPORT ArmDisableBranchPrediction + + +DC_ON EQU ( 0x1:SHL:2 ) +IC_ON EQU ( 0x1:SHL:12 ) +XP_ON EQU ( 0x1:SHL:23 ) + + + AREA ArmCacheLib, CODE, READONLY + PRESERVE8 + + +ArmInvalidateDataCacheEntryByMVA + mcr p15, 0, r0, c7, c6, 1 ; invalidate single data cache line + bx lr + + +ArmCleanDataCacheEntryByMVA + mcr p15, 0, r0, c7, c10, 1 ; clean single data cache line + bx lr + + +ArmCleanInvalidateDataCacheEntryByMVA + mcr p15, 0, r0, c7, c14, 1 ; clean and invalidate single data cache line + bx lr + + +ArmCleanDataCache + mcr p15, 0, r0, c7, c10, 0 ; clean entire data cache + bx lr + + +ArmCleanInvalidateDataCache + mcr p15, 0, r0, c7, c14, 0 ; clean and invalidate entire data cache + bx lr + + +ArmInvalidateDataCache + mcr p15, 0, r0, c7, c6, 0 ; invalidate entire data cache + bx lr + + +ArmInvalidateInstructionCache + mcr p15, 0, r0, c7, c5, 0 ;invalidate entire instruction cache + mov R0,#0 + mcr p15,0,R0,c7,c5,4 ;Flush Prefetch buffer + bx lr + +ArmEnableMmu + mrc p15,0,R0,c1,c0,0 + orr R0,R0,#1 + mcr p15,0,R0,c1,c0,0 + bx LR + +ArmDisableMmu + mrc p15,0,R0,c1,c0,0 + bic R0,R0,#1 + mcr p15,0,R0,c1,c0,0 + mov R0,#0 + mcr p15,0,R0,c7,c10,4 ;Data synchronization barrier + mov R0,#0 + mcr p15,0,R0,c7,c5,4 ;Flush Prefetch buffer + bx LR + +ArmEnableDataCache + LDR R1,=DC_ON + MRC p15,0,R0,c1,c0,0 ;Read control register configuration data + ORR R0,R0,R1 ;Set C bit + MCR p15,0,r0,c1,c0,0 ;Write control register configuration data + BX LR + +ArmDisableDataCache + LDR R1,=DC_ON + MRC p15,0,R0,c1,c0,0 ;Read control register configuration data + BIC R0,R0,R1 ;Clear C bit + MCR p15,0,r0,c1,c0,0 ;Write control register configuration data + BX LR + +ArmEnableInstructionCache + LDR R1,=IC_ON + MRC p15,0,R0,c1,c0,0 ;Read control register configuration data + ORR R0,R0,R1 ;Set I bit + MCR p15,0,r0,c1,c0,0 ;Write control register configuration data + BX LR + +ArmDisableInstructionCache + LDR R1,=IC_ON + MRC p15,0,R0,c1,c0,0 ;Read control register configuration data + BIC R0,R0,R1 ;Clear I bit. + MCR p15,0,r0,c1,c0,0 ;Write control register configuration data + BX LR + +ArmEnableBranchPrediction + mrc p15, 0, r0, c1, c0, 0 + orr r0, r0, #0x00000800 + mcr p15, 0, r0, c1, c0, 0 + bx LR + +ArmDisableBranchPrediction + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #0x00000800 + mcr p15, 0, r0, c1, c0, 0 + bx LR + + END diff --git a/ArmPkg/Library/ArmLib/Arm9/Arm9ArmLib.inf b/ArmPkg/Library/ArmLib/Arm9/Arm9ArmLib.inf new file mode 100644 index 0000000000..9a940394e2 --- /dev/null +++ b/ArmPkg/Library/ArmLib/Arm9/Arm9ArmLib.inf @@ -0,0 +1,32 @@ +#%HEADER% +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = Arm9ArmLib + FILE_GUID = 375D70D3-91E0-4374-A540-68BD959EB184 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = ArmLib + +[Sources.common] + ../Common/ArmLibSupport.S | GCC + ../Common/ArmLibSupport.asm | RVCT + ../Common/ArmLib.c + + Arm9Support.S | GCC + Arm9Support.asm | RVCT + + Arm9Lib.c + Arm9CacheInformation.c + +[Packages] + ArmPkg/ArmPkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + MemoryAllocationLib + +[Protocols] + gEfiCpuArchProtocolGuid + +[FixedPcd] + gArmTokenSpaceGuid.PcdArmCacheOperationThreshold diff --git a/ArmPkg/Library/ArmLib/Arm9/Arm9ArmLibPrePi.inf b/ArmPkg/Library/ArmLib/Arm9/Arm9ArmLibPrePi.inf new file mode 100755 index 0000000000..909ce27616 --- /dev/null +++ b/ArmPkg/Library/ArmLib/Arm9/Arm9ArmLibPrePi.inf @@ -0,0 +1,32 @@ +#%HEADER% +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = Arm9ArmLibPrePi + FILE_GUID = e9b6011f-ee15-4e59-ab8f-a819a081fa54 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = ArmLib + +[Sources.common] + ../Common/ArmLibSupport.S | GCC + ../Common/ArmLibSupport.asm | RVCT + ../Common/ArmLib.c + + Arm9Support.S | GCC + Arm9Support.asm | RVCT + + Arm9Lib.c + Arm9CacheInformation.c + +[Packages] + ArmPkg/ArmPkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + PrePiLib + +[Protocols] + gEfiCpuArchProtocolGuid + +[FixedPcd] + gArmTokenSpaceGuid.PcdArmCacheOperationThreshold diff --git a/ArmPkg/Library/ArmLib/Arm9/Arm9CacheInformation.c b/ArmPkg/Library/ArmLib/Arm9/Arm9CacheInformation.c new file mode 100644 index 0000000000..a8207b905f --- /dev/null +++ b/ArmPkg/Library/ArmLib/Arm9/Arm9CacheInformation.c @@ -0,0 +1,164 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include "ArmLibPrivate.h" + +ARM_CACHE_TYPE +EFIAPI +ArmCacheType ( + VOID + ) +{ + switch (CACHE_TYPE(Cp15CacheInfo())) + { + case CACHE_TYPE_WRITE_BACK: return ARM_CACHE_TYPE_WRITE_BACK; + default: return ARM_CACHE_TYPE_UNKNOWN; + } +} + +ARM_CACHE_ARCHITECTURE +EFIAPI +ArmCacheArchitecture ( + VOID + ) +{ + switch (CACHE_ARCHITECTURE(Cp15CacheInfo())) + { + case CACHE_ARCHITECTURE_UNIFIED: return ARM_CACHE_ARCHITECTURE_UNIFIED; + case CACHE_ARCHITECTURE_SEPARATE: return ARM_CACHE_ARCHITECTURE_SEPARATE; + default: return ARM_CACHE_ARCHITECTURE_UNKNOWN; + } +} + +BOOLEAN +EFIAPI +ArmDataCachePresent ( + VOID + ) +{ + switch (DATA_CACHE_PRESENT(Cp15CacheInfo())) + { + case CACHE_PRESENT: return TRUE; + case CACHE_NOT_PRESENT: return FALSE; + default: return FALSE; + } +} + +UINTN +EFIAPI +ArmDataCacheSize ( + VOID + ) +{ + switch (DATA_CACHE_SIZE(Cp15CacheInfo())) + { + case CACHE_SIZE_4_KB: return 4 * 1024; + case CACHE_SIZE_8_KB: return 8 * 1024; + case CACHE_SIZE_16_KB: return 16 * 1024; + case CACHE_SIZE_32_KB: return 32 * 1024; + case CACHE_SIZE_64_KB: return 64 * 1024; + case CACHE_SIZE_128_KB: return 128 * 1024; + default: return 0; + } +} + +UINTN +EFIAPI +ArmDataCacheAssociativity ( + VOID + ) +{ + switch (DATA_CACHE_ASSOCIATIVITY(Cp15CacheInfo())) + { + case CACHE_ASSOCIATIVITY_4_WAY: return 4; + case CACHE_ASSOCIATIVITY_DIRECT: return 1; + default: return 0; + } +} + +UINTN +EFIAPI +ArmDataCacheLineLength ( + VOID + ) +{ + switch (DATA_CACHE_LINE_LENGTH(Cp15CacheInfo())) + { + case CACHE_LINE_LENGTH_32_BYTES: return 32; + default: return 0; + } +} + +BOOLEAN +EFIAPI +ArmInstructionCachePresent ( + VOID + ) +{ + switch (INSTRUCTION_CACHE_PRESENT(Cp15CacheInfo())) + { + case CACHE_PRESENT: return TRUE; + case CACHE_NOT_PRESENT: return FALSE; + default: return FALSE; + } +} + +UINTN +EFIAPI +ArmInstructionCacheSize ( + VOID + ) +{ + switch (INSTRUCTION_CACHE_SIZE(Cp15CacheInfo())) + { + case CACHE_SIZE_4_KB: return 4 * 1024; + case CACHE_SIZE_8_KB: return 8 * 1024; + case CACHE_SIZE_16_KB: return 16 * 1024; + case CACHE_SIZE_32_KB: return 32 * 1024; + case CACHE_SIZE_64_KB: return 64 * 1024; + case CACHE_SIZE_128_KB: return 128 * 1024; + default: return 0; + } +} + +UINTN +EFIAPI +ArmInstructionCacheAssociativity ( + VOID + ) +{ + switch (INSTRUCTION_CACHE_ASSOCIATIVITY(Cp15CacheInfo())) + { + case CACHE_ASSOCIATIVITY_8_WAY: return 8; + case CACHE_ASSOCIATIVITY_4_WAY: return 4; + case CACHE_ASSOCIATIVITY_DIRECT: return 1; + default: return 0; + } +} + +UINTN +EFIAPI +ArmInstructionCacheLineLength ( + VOID + ) +{ + switch (INSTRUCTION_CACHE_LINE_LENGTH(Cp15CacheInfo())) + { + case CACHE_LINE_LENGTH_32_BYTES: return 32; + default: return 0; + } +} + + diff --git a/ArmPkg/Library/ArmLib/Arm9/Arm9Lib.c b/ArmPkg/Library/ArmLib/Arm9/Arm9Lib.c new file mode 100644 index 0000000000..0ba2237d29 --- /dev/null +++ b/ArmPkg/Library/ArmLib/Arm9/Arm9Lib.c @@ -0,0 +1,118 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include + +VOID +FillTranslationTable ( + IN UINT32 *TranslationTable, + IN ARM_MEMORY_REGION_DESCRIPTOR *MemoryRegion + ) +{ + UINT32 *Entry; + UINTN Sections; + UINTN Index; + UINT32 Attributes; + UINT32 PhysicalBase = MemoryRegion->PhysicalBase; + + switch (MemoryRegion->Attributes) { + case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK: + Attributes = TT_DESCRIPTOR_SECTION_WRITE_BACK; + break; + case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_THROUGH: + Attributes = TT_DESCRIPTOR_SECTION_WRITE_THROUGH; + break; + case ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED: + default: + Attributes = TT_DESCRIPTOR_SECTION_UNCACHED_UNBUFFERED; + break; + } + + Entry = TRANSLATION_TABLE_ENTRY_FOR_VIRTUAL_ADDRESS(TranslationTable, MemoryRegion->VirtualBase); + Sections = MemoryRegion->Length / TT_DESCRIPTOR_SECTION_SIZE; + + for (Index = 0; Index < Sections; Index++) + { + *Entry++ = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(PhysicalBase) | Attributes; + PhysicalBase += TT_DESCRIPTOR_SECTION_SIZE; + } +} + +VOID +EFIAPI +ArmConfigureMmu ( + IN ARM_MEMORY_REGION_DESCRIPTOR *MemoryTable, + OUT VOID **TranslationTableBase OPTIONAL, + OUT UINTN *TranslationTableSize OPTIONAL + ) +{ + VOID *TranslationTable; + + // Allocate pages for translation table. + TranslationTable = AllocatePages(EFI_SIZE_TO_PAGES(TRANSLATION_TABLE_SIZE + TRANSLATION_TABLE_ALIGNMENT)); + TranslationTable = (VOID *)(((UINTN)TranslationTable + TRANSLATION_TABLE_ALIGNMENT_MASK) & ~TRANSLATION_TABLE_ALIGNMENT_MASK); + + if (TranslationTableBase != NULL) { + *TranslationTableBase = TranslationTable; + } + + if (TranslationTableBase != NULL) { + *TranslationTableSize = TRANSLATION_TABLE_SIZE; + } + + ZeroMem(TranslationTable, TRANSLATION_TABLE_SIZE); + + ArmCleanInvalidateDataCache(); + ArmInvalidateInstructionCache(); + ArmInvalidateTlb(); + + ArmDisableDataCache(); + ArmDisableInstructionCache(); + ArmDisableMmu(); + + // Make sure nothing sneaked into the cache + ArmCleanInvalidateDataCache(); + ArmInvalidateInstructionCache(); + + while (MemoryTable->Length != 0) { + FillTranslationTable(TranslationTable, MemoryTable); + MemoryTable++; + } + + ArmSetTranslationTableBaseAddress(TranslationTable); + + ArmSetDomainAccessControl(DOMAIN_ACCESS_CONTROL_NONE(15) | + DOMAIN_ACCESS_CONTROL_NONE(14) | + DOMAIN_ACCESS_CONTROL_NONE(13) | + DOMAIN_ACCESS_CONTROL_NONE(12) | + DOMAIN_ACCESS_CONTROL_NONE(11) | + DOMAIN_ACCESS_CONTROL_NONE(10) | + DOMAIN_ACCESS_CONTROL_NONE( 9) | + DOMAIN_ACCESS_CONTROL_NONE( 8) | + DOMAIN_ACCESS_CONTROL_NONE( 7) | + DOMAIN_ACCESS_CONTROL_NONE( 6) | + DOMAIN_ACCESS_CONTROL_NONE( 5) | + DOMAIN_ACCESS_CONTROL_NONE( 4) | + DOMAIN_ACCESS_CONTROL_NONE( 3) | + DOMAIN_ACCESS_CONTROL_NONE( 2) | + DOMAIN_ACCESS_CONTROL_NONE( 1) | + DOMAIN_ACCESS_CONTROL_MANAGER(0)); + + ArmEnableInstructionCache(); + ArmEnableDataCache(); + ArmEnableMmu(); +} diff --git a/ArmPkg/Library/ArmLib/Arm9/Arm9Support.S b/ArmPkg/Library/ArmLib/Arm9/Arm9Support.S new file mode 100644 index 0000000000..5c9afe9347 --- /dev/null +++ b/ArmPkg/Library/ArmLib/Arm9/Arm9Support.S @@ -0,0 +1,128 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2008-2009 Apple Inc. All rights reserved. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + +.text +.align 2 +.globl ASM_PFX(ArmCleanInvalidateDataCache) +.globl ASM_PFX(ArmCleanDataCache) +.globl ASM_PFX(ArmInvalidateDataCache) +.globl ASM_PFX(ArmInvalidateInstructionCache) +.globl ASM_PFX(ArmInvalidateDataCacheEntryByMVA) +.globl ASM_PFX(ArmCleanDataCacheEntryByMVA) +.globl ASM_PFX(ArmCleanInvalidateDataCacheEntryByMVA) +.globl ASM_PFX(ArmEnableMmu) +.globl ASM_PFX(ArmDisableMmu) +.globl ASM_PFX(ArmEnableDataCache) +.globl ASM_PFX(ArmDisableDataCache) +.globl ASM_PFX(ArmEnableInstructionCache) +.globl ASM_PFX(ArmDisableInstructionCache) +.globl ASM_PFX(ArmEnableBranchPrediction) +.globl ASM_PFX(ArmDisableBranchPrediction) + +.set DC_ON, (1<<2) +.set IC_ON, (1<<12) + +#------------------------------------------------------------------------------ + +ASM_PFX(ArmInvalidateDataCacheEntryByMVA): + mcr p15, 0, r0, c7, c6, 1 @ invalidate single data cache line + bx lr + +ASM_PFX(ArmCleanDataCacheEntryByMVA): + mcr p15, 0, r0, c7, c10, 1 @ clean single data cache line + bx lr + +ASM_PFX(ArmCleanInvalidateDataCacheEntryByMVA): + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate single data cache line + bx lr + +ASM_PFX(ArmEnableInstructionCache): + ldr r1,=IC_ON + mrc p15,0,r0,c1,c0,0 @Read control register configuration data + orr r0,r0,r1 @Set I bit + mcr p15,0,r0,c1,c0,0 @Write control register configuration data + bx LR + +ASM_PFX(ArmDisableInstructionCache): + ldr r1,=IC_ON + mrc p15,0,r0,c1,c0,0 @Read control register configuration data + bic r0,r0,r1 @Clear I bit. + mcr p15,0,r0,c1,c0,0 @Write control register configuration data + bx LR + +ASM_PFX(ArmInvalidateInstructionCache): + mov r0,#0 + mcr p15,0,r0,c7,c5,0 @Invalidate entire Instruction cache. + @Also flushes the branch target cache. + mov r0,#0 + mcr p15,0,r0,c7,c10,4 @Data write buffer + bx LR + +ASM_PFX(ArmEnableMmu): + mrc p15,0,R0,c1,c0,0 + orr R0,R0,#1 + mcr p15,0,R0,c1,c0,0 + bx LR + +ASM_PFX(ArmDisableMmu): + mrc p15,0,R0,c1,c0,0 + bic R0,R0,#1 + mcr p15,0,R0,c1,c0,0 + mov R0,#0 + mcr p15,0,R0,c7,c10,4 @Drain write buffer + bx LR + +ASM_PFX(ArmEnableDataCache): + ldr R1,=DC_ON + mrc p15,0,R0,c1,c0,0 @Read control register configuration data + orr R0,R0,R1 @Set C bit + mcr p15,0,r0,c1,c0,0 @Write control register configuration data + bx LR + +ASM_PFX(ArmDisableDataCache): + ldr R1,=DC_ON + mrc p15,0,R0,c1,c0,0 @Read control register configuration data + bic R0,R0,R1 @Clear C bit + mcr p15,0,r0,c1,c0,0 @Write control register configuration data + bx LR + +ASM_PFX(ArmCleanDataCache): + mrc p15,0,r15,c7,c10,3 + bne ASM_PFX(ArmCleanDataCache) + mov R0,#0 + mcr p15,0,R0,c7,c10,4 @Drain write buffer + bx LR + +ASM_PFX(ArmInvalidateDataCache): + mov R0,#0 + mcr p15,0,R0,c7,c6,0 @Invalidate entire data cache + mov R0,#0 + mcr p15,0,R0,c7,c10,4 @Drain write buffer + bx LR + +ASM_PFX(ArmCleanInvalidateDataCache): + mrc p15,0,r15,c7,c14,3 + bne ASM_PFX(ArmCleanInvalidateDataCache) + mov R0,#0 + mcr p15,0,R0,c7,c10,4 @Drain write buffer + bx LR + +ASM_PFX(ArmEnableBranchPrediction): + bx LR @Branch prediction is not supported. + +ASM_PFX(ArmDisableBranchPrediction): + bx LR @Branch prediction is not supported. + +ASM_FUNCTION_REMOVE_IF_UNREFERENCED + diff --git a/ArmPkg/Library/ArmLib/Arm9/Arm9Support.asm b/ArmPkg/Library/ArmLib/Arm9/Arm9Support.asm new file mode 100644 index 0000000000..3204d6607f --- /dev/null +++ b/ArmPkg/Library/ArmLib/Arm9/Arm9Support.asm @@ -0,0 +1,129 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2008-2009 Apple Inc. All rights reserved. +// +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +//------------------------------------------------------------------------------ + + EXPORT ArmCleanInvalidateDataCache + EXPORT ArmCleanDataCache + EXPORT ArmInvalidateDataCache + EXPORT ArmInvalidateInstructionCache + EXPORT ArmInvalidateDataCacheEntryByMVA + EXPORT ArmCleanDataCacheEntryByMVA + EXPORT ArmCleanInvalidateDataCacheEntryByMVA + EXPORT ArmEnableMmu + EXPORT ArmDisableMmu + EXPORT ArmEnableDataCache + EXPORT ArmDisableDataCache + EXPORT ArmEnableInstructionCache + EXPORT ArmDisableInstructionCache + EXPORT ArmEnableBranchPrediction + EXPORT ArmDisableBranchPrediction + + +DC_ON EQU ( 0x1:SHL:2 ) +IC_ON EQU ( 0x1:SHL:12 ) + + AREA ArmCacheLib, CODE, READONLY + PRESERVE8 + + +ArmInvalidateDataCacheEntryByMVA + MCR p15, 0, r0, c7, c6, 1 ; invalidate single data cache line + BX lr + + +ArmCleanDataCacheEntryByMVA + MCR p15, 0, r0, c7, c10, 1 ; clean single data cache line + BX lr + + +ArmCleanInvalidateDataCacheEntryByMVA + MCR p15, 0, r0, c7, c14, 1 ; clean and invalidate single data cache line + BX lr + +ArmEnableInstructionCache + LDR R1,=IC_ON + MRC p15,0,R0,c1,c0,0 ;Read control register configuration data + ORR R0,R0,R1 ;Set I bit + MCR p15,0,r0,c1,c0,0 ;Write control register configuration data + BX LR + +ArmDisableInstructionCache + LDR R1,=IC_ON + MRC p15,0,R0,c1,c0,0 ;Read control register configuration data + BIC R0,R0,R1 ;Clear I bit. + MCR p15,0,r0,c1,c0,0 ;Write control register configuration data + BX LR + +ArmInvalidateInstructionCache + MOV R0,#0 + MCR p15,0,R0,c7,c5,0 ;Invalidate entire instruction cache + MOV R0,#0 + MCR p15,0,R0,c7,c10,4 ;Drain write buffer + BX LR + +ArmEnableMmu + mrc p15,0,R0,c1,c0,0 + orr R0,R0,#1 + mcr p15,0,R0,c1,c0,0 + bx LR + +ArmDisableMmu + mrc p15,0,R0,c1,c0,0 + bic R0,R0,#1 + mcr p15,0,R0,c1,c0,0 + mov R0,#0 + mcr p15,0,R0,c7,c10,4 ;Drain write buffer + bx LR + +ArmEnableDataCache + LDR R1,=DC_ON + MRC p15,0,R0,c1,c0,0 ;Read control register configuration data + ORR R0,R0,R1 ;Set C bit + MCR p15,0,r0,c1,c0,0 ;Write control register configuration data + BX LR + +ArmDisableDataCache + LDR R1,=DC_ON + MRC p15,0,R0,c1,c0,0 ;Read control register configuration data + BIC R0,R0,R1 ;Clear C bit + MCR p15,0,r0,c1,c0,0 ;Write control register configuration data + BX LR + +ArmCleanDataCache + MRC p15,0,r15,c7,c10,3 + BNE ArmCleanDataCache + MOV R0,#0 + MCR p15,0,R0,c7,c10,4 ;Drain write buffer + BX LR + +ArmInvalidateDataCache + MOV R0,#0 + MCR p15,0,R0,c7,c6,0 ;Invalidate entire data cache + MOV R0,#0 + MCR p15,0,R0,c7,c10,4 ;Drain write buffer + BX LR + +ArmCleanInvalidateDataCache + MRC p15,0,r15,c7,c14,3 + BNE ArmCleanInvalidateDataCache + MOV R0,#0 + MCR p15,0,R0,c7,c10,4 ;Drain write buffer + BX LR + +ArmEnableBranchPrediction + bx LR ;Branch prediction is not supported. + +ArmDisableBranchPrediction + bx LR ;Branch prediction is not supported. + + END diff --git a/ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexALib.c b/ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexALib.c new file mode 100644 index 0000000000..4dfa18db58 --- /dev/null +++ b/ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexALib.c @@ -0,0 +1,288 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include +#include "ArmCortexALib.h" + +VOID +FillTranslationTable ( + IN UINT32 *TranslationTable, + IN ARM_MEMORY_REGION_DESCRIPTOR *MemoryRegion + ) +{ + UINT32 *Entry; + UINTN Sections; + UINTN Index; + UINT32 Attributes; + UINT32 PhysicalBase = MemoryRegion->PhysicalBase; + + switch (MemoryRegion->Attributes) { + case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK: + Attributes = TT_DESCRIPTOR_SECTION_WRITE_BACK; + break; + case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_THROUGH: + Attributes = TT_DESCRIPTOR_SECTION_WRITE_THROUGH; + break; + case ARM_MEMORY_REGION_ATTRIBUTE_DEVICE: + Attributes = TT_DESCRIPTOR_SECTION_DEVICE; + break; + case ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED: + default: + Attributes = TT_DESCRIPTOR_SECTION_UNCACHED; + break; + } + + Entry = TRANSLATION_TABLE_ENTRY_FOR_VIRTUAL_ADDRESS(TranslationTable, MemoryRegion->VirtualBase); + Sections = MemoryRegion->Length / TT_DESCRIPTOR_SECTION_SIZE; + + for (Index = 0; Index < Sections; Index++) + { + *Entry++ = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(PhysicalBase) | Attributes; + PhysicalBase += TT_DESCRIPTOR_SECTION_SIZE; + } +} + +VOID +EFIAPI +ArmConfigureMmu ( + IN ARM_MEMORY_REGION_DESCRIPTOR *MemoryTable, + OUT VOID **TranslationTableBase OPTIONAL, + OUT UINTN *TranslationTableSize OPTIONAL + ) +{ + VOID *TranslationTable; + + // Allocate pages for translation table. + TranslationTable = AllocatePages(EFI_SIZE_TO_PAGES(TRANSLATION_TABLE_SIZE + TRANSLATION_TABLE_ALIGNMENT)); + TranslationTable = (VOID *)(((UINTN)TranslationTable + TRANSLATION_TABLE_ALIGNMENT_MASK) & ~TRANSLATION_TABLE_ALIGNMENT_MASK); + + if (TranslationTableBase != NULL) { + *TranslationTableBase = TranslationTable; + } + + if (TranslationTableBase != NULL) { + *TranslationTableSize = TRANSLATION_TABLE_SIZE; + } + + ZeroMem(TranslationTable, TRANSLATION_TABLE_SIZE); + + ArmCleanInvalidateDataCache(); + ArmInvalidateInstructionCache(); + ArmInvalidateTlb(); + + ArmDisableDataCache(); + ArmDisableInstructionCache(); + ArmDisableMmu(); + + // Make sure nothing sneaked into the cache + ArmCleanInvalidateDataCache(); + ArmInvalidateInstructionCache(); + + while (MemoryTable->Length != 0) { + FillTranslationTable(TranslationTable, MemoryTable); + MemoryTable++; + } + + ArmSetTranslationTableBaseAddress(TranslationTable); + + ArmSetDomainAccessControl(DOMAIN_ACCESS_CONTROL_NONE(15) | + DOMAIN_ACCESS_CONTROL_NONE(14) | + DOMAIN_ACCESS_CONTROL_NONE(13) | + DOMAIN_ACCESS_CONTROL_NONE(12) | + DOMAIN_ACCESS_CONTROL_NONE(11) | + DOMAIN_ACCESS_CONTROL_NONE(10) | + DOMAIN_ACCESS_CONTROL_NONE( 9) | + DOMAIN_ACCESS_CONTROL_NONE( 8) | + DOMAIN_ACCESS_CONTROL_NONE( 7) | + DOMAIN_ACCESS_CONTROL_NONE( 6) | + DOMAIN_ACCESS_CONTROL_NONE( 5) | + DOMAIN_ACCESS_CONTROL_NONE( 4) | + DOMAIN_ACCESS_CONTROL_NONE( 3) | + DOMAIN_ACCESS_CONTROL_NONE( 2) | + DOMAIN_ACCESS_CONTROL_NONE( 1) | + DOMAIN_ACCESS_CONTROL_MANAGER(0)); + + ArmEnableInstructionCache(); + ArmEnableDataCache(); + ArmEnableMmu(); +} + +ARM_CACHE_TYPE +EFIAPI +ArmCacheType ( + VOID + ) +{ + return ARM_CACHE_TYPE_WRITE_BACK; +} + +ARM_CACHE_ARCHITECTURE +EFIAPI +ArmCacheArchitecture ( + VOID + ) +{ + return ARM_CACHE_ARCHITECTURE_SEPARATE; +} + +BOOLEAN +EFIAPI +ArmDataCachePresent ( + VOID + ) +{ + return TRUE; +} + +UINTN +EFIAPI +ArmDataCacheSize ( + VOID + ) +{ + return 16 * 1024; +} + +UINTN +EFIAPI +ArmDataCacheAssociativity ( + VOID + ) +{ + return 4; +} + +UINTN +ArmDataCacheSets ( + VOID + ) +{ + return 64; +} + +UINTN +EFIAPI +ArmDataCacheLineLength ( + VOID + ) +{ + return 64; +} + +BOOLEAN +EFIAPI +ArmInstructionCachePresent ( + VOID + ) +{ + return TRUE; +} + +UINTN +EFIAPI +ArmInstructionCacheSize ( + VOID + ) +{ + return 16 * 1024; +} + +UINTN +EFIAPI +ArmInstructionCacheAssociativity ( + VOID + ) +{ + return 4; +} + +UINTN +EFIAPI +ArmInstructionCacheLineLength ( + VOID + ) +{ + return 64; +} + +VOID +ArmCortexADataCacheOperation ( + IN ARM_CORTEX_A_CACHE_OPERATION DataCacheOperation + ) +{ + UINTN Set; + UINTN SetCount; + UINTN SetShift; + UINTN Way; + UINTN WayCount; + UINTN WayShift; + UINT32 SetWayFormat; + UINTN SavedInterruptState; + + SetCount = ArmDataCacheSets(); + WayCount = ArmDataCacheAssociativity(); + + // Cortex-A8 Manual, System Control Coprocessor chapter + SetShift = 6; + WayShift = 32 - LowBitSet32 ((UINT32)WayCount); + + SavedInterruptState = ArmDisableInterrupts(); + + for (Way = 0; Way < WayCount; Way++) { + for (Set = 0; Set < SetCount; Set++) { + // Build the format that the CP15 instruction can understand + SetWayFormat = (Way << WayShift) | (Set << SetShift); + + // Pass it through + (*DataCacheOperation)(SetWayFormat); + } + } + + ArmDrainWriteBuffer(); + + if (SavedInterruptState) { + ArmEnableInterrupts(); + } +} + +VOID +EFIAPI +ArmInvalidateDataCache ( + VOID + ) +{ + ArmCortexADataCacheOperation(ArmInvalidateDataCacheEntryBySetWay); +} + +VOID +EFIAPI +ArmCleanInvalidateDataCache ( + VOID + ) +{ + ArmCortexADataCacheOperation(ArmCleanInvalidateDataCacheEntryBySetWay); +} + +VOID +EFIAPI +ArmCleanDataCache ( + VOID + ) +{ + ArmCortexADataCacheOperation(ArmCleanDataCacheEntryBySetWay); +} diff --git a/ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexALib.h b/ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexALib.h new file mode 100644 index 0000000000..afe98bdfa2 --- /dev/null +++ b/ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexALib.h @@ -0,0 +1,45 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __ARMCORTEXALIB_H__ +#define __ARMCORTEXALIB_H__ + +typedef VOID (*ARM_CORTEX_A_CACHE_OPERATION)(UINT32); + +VOID +EFIAPI +ArmDrainWriteBuffer ( + VOID + ); + +VOID +EFIAPI +ArmInvalidateDataCacheEntryBySetWay ( + IN UINT32 SetWayFormat + ); + +VOID +EFIAPI +ArmCleanDataCacheEntryBySetWay ( + IN UINT32 SetWayFormat + ); + +VOID +EFIAPI +ArmCleanInvalidateDataCacheEntryBySetWay ( + IN UINT32 SetWayFormat + ); + +#endif // __ARMCORTEXALIB_H__ + diff --git a/ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexASupport.S b/ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexASupport.S new file mode 100644 index 0000000000..0e24f6341c --- /dev/null +++ b/ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexASupport.S @@ -0,0 +1,140 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2008-2009 Apple Inc. All rights reserved. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + +.text +.align 2 +.globl ASM_PFX(ArmInvalidateInstructionCache) +.globl ASM_PFX(ArmInvalidateDataCacheEntryByMVA) +.globl ASM_PFX(ArmCleanDataCacheEntryByMVA) +.globl ASM_PFX(ArmCleanInvalidateDataCacheEntryByMVA) +.globl ASM_PFX(ArmInvalidateDataCacheEntryBySetWay) +.globl ASM_PFX(ArmCleanDataCacheEntryBySetWay) +.globl ASM_PFX(ArmCleanInvalidateDataCacheEntryBySetWay) +.globl ASM_PFX(ArmDrainWriteBuffer) +.globl ASM_PFX(ArmEnableMmu) +.globl ASM_PFX(ArmDisableMmu) +.globl ASM_PFX(ArmEnableDataCache) +.globl ASM_PFX(ArmDisableDataCache) +.globl ASM_PFX(ArmEnableInstructionCache) +.globl ASM_PFX(ArmDisableInstructionCache) +.globl ASM_PFX(ArmEnableExtendPTConfig) +.globl ASM_PFX(ArmDisableExtendPTConfig) +.globl ASM_PFX(ArmEnableBranchPrediction) +.globl ASM_PFX(ArmDisableBranchPrediction) + +.set DC_ON, (0x1<<2) +.set IC_ON, (0x1<<12) +.set XP_ON, (0x1<<23) + +ASM_PFX(ArmInvalidateDataCacheEntryByMVA): + mcr p15, 0, r0, c7, c6, 1 @invalidate single data cache line + bx lr + + +ASM_PFX(ArmCleanDataCacheEntryByMVA): + mcr p15, 0, r0, c7, c10, 1 @clean single data cache line + bx lr + + +ASM_PFX(ArmCleanInvalidateDataCacheEntryByMVA): + mcr p15, 0, r0, c7, c14, 1 @clean and invalidate single data cache line + bx lr + + +ASM_PFX(ArmInvalidateDataCacheEntryBySetWay): + mcr p15, 0, r0, c7, c6, 2 @ Invalidate this line + bx lr + + +ASM_PFX(ArmCleanInvalidateDataCacheEntryBySetWay): + mcr p15, 0, r0, c7, c14, 2 @ Clean and Invalidate this line + bx lr + + +ASM_PFX(ArmCleanDataCacheEntryBySetWay): + mcr p15, 0, r0, c7, c10, 2 @ Clean this line + bx lr + + +ASM_PFX(ArmDrainWriteBuffer): + mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer for sync + bx lr + + +ASM_PFX(ArmInvalidateInstructionCache): + mov R0,#0 + mcr p15,0,R0,c7,c5,0 @Invalidate entire instruction cache + mov R0,#0 + mcr p15,0,R0,c7,c5,4 @Instruction synchronization barrier + bx LR + +ASM_PFX(ArmEnableMmu): + mrc p15,0,R0,c1,c0,0 + orr R0,R0,#1 + mcr p15,0,R0,c1,c0,0 + bx LR + +ASM_PFX(ArmDisableMmu): + mov R0,#0 + mcr p15,0,R0,c13,c0,0 @FCSE PID register must be cleared before disabling MMU + mrc p15,0,R0,c1,c0,0 + bic R0,R0,#1 + mcr p15,0,R0,c1,c0,0 @Disable MMU + mov R0,#0 + mcr p15,0,R0,c7,c10,4 @Data synchronization barrier + mov R0,#0 + mcr p15,0,R0,c7,c5,4 @Instruction synchronization barrier + bx LR + +ASM_PFX(ArmEnableDataCache): + ldr R1,=DC_ON + mrc p15,0,R0,c1,c0,0 @Read control register configuration data + orr R0,R0,R1 @Set C bit + mcr p15,0,r0,c1,c0,0 @Write control register configuration data + bx LR + +ASM_PFX(ArmDisableDataCache): + ldr R1,=DC_ON + mrc p15,0,R0,c1,c0,0 @Read control register configuration data + bic R0,R0,R1 @Clear C bit + mcr p15,0,r0,c1,c0,0 @Write control register configuration data + bx LR + +ASM_PFX(ArmEnableInstructionCache): + ldr R1,=IC_ON + mrc p15,0,R0,c1,c0,0 @Read control register configuration data + orr R0,R0,R1 @Set I bit + mcr p15,0,r0,c1,c0,0 @Write control register configuration data + bx LR + +ASM_PFX(ArmDisableInstructionCache): + ldr R1,=IC_ON + mrc p15,0,R0,c1,c0,0 @Read control register configuration data + bic R0,R0,R1 @Clear I bit. + mcr p15,0,r0,c1,c0,0 @Write control register configuration data + bx LR + +ASM_PFX(ArmEnableBranchPrediction): + mrc p15, 0, r0, c1, c0, 0 + orr r0, r0, #0x00000800 + mcr p15, 0, r0, c1, c0, 0 + bx LR + +ASM_PFX(ArmDisableBranchPrediction): + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #0x00000800 + mcr p15, 0, r0, c1, c0, 0 + bx LR + +ASM_FUNCTION_REMOVE_IF_UNREFERENCED diff --git a/ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexASupport.asm b/ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexASupport.asm new file mode 100644 index 0000000000..dbd8bd246a --- /dev/null +++ b/ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexASupport.asm @@ -0,0 +1,141 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2008-2009 Apple Inc. All rights reserved. +// +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +//------------------------------------------------------------------------------ + + EXPORT ArmInvalidateInstructionCache + EXPORT ArmInvalidateDataCacheEntryByMVA + EXPORT ArmCleanDataCacheEntryByMVA + EXPORT ArmCleanInvalidateDataCacheEntryByMVA + EXPORT ArmInvalidateDataCacheEntryBySetWay + EXPORT ArmCleanDataCacheEntryBySetWay + EXPORT ArmCleanInvalidateDataCacheEntryBySetWay + EXPORT ArmDrainWriteBuffer + EXPORT ArmEnableMmu + EXPORT ArmDisableMmu + EXPORT ArmEnableDataCache + EXPORT ArmDisableDataCache + EXPORT ArmEnableInstructionCache + EXPORT ArmDisableInstructionCache + EXPORT ArmEnableBranchPrediction + EXPORT ArmDisableBranchPrediction + +DC_ON EQU ( 0x1:SHL:2 ) +IC_ON EQU ( 0x1:SHL:12 ) +XP_ON EQU ( 0x1:SHL:23 ) + + + AREA ArmCacheLib, CODE, READONLY + PRESERVE8 + + +ArmInvalidateDataCacheEntryByMVA + MCR p15, 0, r0, c7, c6, 1 ; invalidate single data cache line + BX lr + + +ArmCleanDataCacheEntryByMVA + MCR p15, 0, r0, c7, c10, 1 ; clean single data cache line + BX lr + + +ArmCleanInvalidateDataCacheEntryByMVA + MCR p15, 0, r0, c7, c14, 1 ; clean and invalidate single data cache line + BX lr + + +ArmInvalidateDataCacheEntryBySetWay + mcr p15, 0, r0, c7, c6, 2 ; Invalidate this line + bx lr + + +ArmCleanInvalidateDataCacheEntryBySetWay + mcr p15, 0, r0, c7, c14, 2 ; Clean and Invalidate this line + bx lr + + +ArmCleanDataCacheEntryBySetWay + mcr p15, 0, r0, c7, c10, 2 ; Clean this line + bx lr + + +ArmDrainWriteBuffer + mcr p15, 0, r0, c7, c10, 4 ; Drain write buffer for sync + bx lr + + +ArmInvalidateInstructionCache + MOV R0,#0 + MCR p15,0,R0,c7,c5,0 ;Invalidate entire instruction cache + MOV R0,#0 + MCR p15,0,R0,c7,c5,4 ;Instruction synchronization barrier + BX LR + +ArmEnableMmu + mrc p15,0,R0,c1,c0,0 + orr R0,R0,#1 + mcr p15,0,R0,c1,c0,0 + bx LR + +ArmDisableMmu + mov R0,#0 + mcr p15,0,R0,c13,c0,0 ;FCSE PID register must be cleared before disabling MMU + mrc p15,0,R0,c1,c0,0 + bic R0,R0,#1 + mcr p15,0,R0,c1,c0,0 ;Disable MMU + mov R0,#0 + mcr p15,0,R0,c7,c10,4 ;Data synchronization barrier + mov R0,#0 + mcr p15,0,R0,c7,c5,4 ;Instruction synchronization barrier + bx LR + +ArmEnableDataCache + LDR R1,=DC_ON + MRC p15,0,R0,c1,c0,0 ;Read control register configuration data + ORR R0,R0,R1 ;Set C bit + MCR p15,0,r0,c1,c0,0 ;Write control register configuration data + BX LR + +ArmDisableDataCache + LDR R1,=DC_ON + MRC p15,0,R0,c1,c0,0 ;Read control register configuration data + BIC R0,R0,R1 ;Clear C bit + MCR p15,0,r0,c1,c0,0 ;Write control register configuration data + BX LR + +ArmEnableInstructionCache + LDR R1,=IC_ON + MRC p15,0,R0,c1,c0,0 ;Read control register configuration data + ORR R0,R0,R1 ;Set I bit + MCR p15,0,r0,c1,c0,0 ;Write control register configuration data + BX LR + +ArmDisableInstructionCache + LDR R1,=IC_ON + MRC p15,0,R0,c1,c0,0 ;Read control register configuration data + BIC R0,R0,R1 ;Clear I bit. + MCR p15,0,r0,c1,c0,0 ;Write control register configuration data + BX LR + +ArmEnableBranchPrediction + mrc p15, 0, r0, c1, c0, 0 + orr r0, r0, #0x00000800 + mcr p15, 0, r0, c1, c0, 0 + bx LR + +ArmDisableBranchPrediction + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #0x00000800 + mcr p15, 0, r0, c1, c0, 0 + bx LR + + END diff --git a/ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexArmLib.inf b/ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexArmLib.inf new file mode 100644 index 0000000000..54b77e31b4 --- /dev/null +++ b/ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexArmLib.inf @@ -0,0 +1,31 @@ +#%HEADER% +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ArmCortexArmLib + FILE_GUID = 411cdfd8-f964-4b9d-a3e3-1719a9c15559 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = ArmLib + +[Sources.common] + ../Common/ArmLibSupport.S | GCC + ../Common/ArmLibSupport.asm | RVCT + ../Common/ArmLib.c + + ArmCortexASupport.S | GCC + ArmCortexASupport.asm | RVCT + + ArmCortexALib.c + +[Packages] + ArmPkg/ArmPkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + MemoryAllocationLib + +[Protocols] + gEfiCpuArchProtocolGuid + +[FixedPcd] + gArmTokenSpaceGuid.PcdArmCacheOperationThreshold diff --git a/ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexArmLibPrePi.inf b/ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexArmLibPrePi.inf new file mode 100644 index 0000000000..450dfe5936 --- /dev/null +++ b/ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexArmLibPrePi.inf @@ -0,0 +1,31 @@ +#%HEADER% +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ArmCortexArmLibPrePi + FILE_GUID = A150FA0C-F4E8-4207-9BEB-CD6DFB430D73 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = ArmLib + +[Sources.common] + ../Common/ArmLibSupport.S | GCC + ../Common/ArmLibSupport.asm | RVCT + ../Common/ArmLib.c + + ArmCortexASupport.S | GCC + ArmCortexASupport.asm | RVCT + + ArmCortexALib.c + +[Packages] + ArmPkg/ArmPkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + PrePiLib + +[Protocols] + gEfiCpuArchProtocolGuid + +[FixedPcd] + gArmTokenSpaceGuid.PcdArmCacheOperationThreshold diff --git a/ArmPkg/Library/ArmLib/Common/ArmLib.c b/ArmPkg/Library/ArmLib/Common/ArmLib.c new file mode 100644 index 0000000000..b015dc4aa1 --- /dev/null +++ b/ArmPkg/Library/ArmLib/Common/ArmLib.c @@ -0,0 +1,60 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include + +#include "ArmLibPrivate.h" + +VOID +EFIAPI +ArmCacheInformation ( + OUT ARM_CACHE_INFO *CacheInfo + ) +{ + if (CacheInfo != NULL) { + CacheInfo->Type = ArmCacheType(); + CacheInfo->Architecture = ArmCacheArchitecture(); + CacheInfo->DataCachePresent = ArmDataCachePresent(); + CacheInfo->DataCacheSize = ArmDataCacheSize(); + CacheInfo->DataCacheAssociativity = ArmDataCacheAssociativity(); + CacheInfo->DataCacheLineLength = ArmDataCacheLineLength(); + CacheInfo->InstructionCachePresent = ArmInstructionCachePresent(); + CacheInfo->InstructionCacheSize = ArmInstructionCacheSize(); + CacheInfo->InstructionCacheAssociativity = ArmInstructionCacheAssociativity(); + CacheInfo->InstructionCacheLineLength = ArmInstructionCacheLineLength(); + } +} + +VOID +EFIAPI +ArmSwitchProcessorMode ( + IN ARM_PROCESSOR_MODE Mode + ) +{ + CPSRMaskInsert(ARM_PROCESSOR_MODE_MASK, Mode); +} + + +ARM_PROCESSOR_MODE +EFIAPI +ArmProcessorMode ( + VOID + ) +{ + return (ARM_PROCESSOR_MODE)(CPSRRead() & (UINT32)ARM_PROCESSOR_MODE_MASK); +} diff --git a/ArmPkg/Library/ArmLib/Common/ArmLibPrivate.h b/ArmPkg/Library/ArmLib/Common/ArmLibPrivate.h new file mode 100644 index 0000000000..d1d2523947 --- /dev/null +++ b/ArmPkg/Library/ArmLib/Common/ArmLibPrivate.h @@ -0,0 +1,70 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __ARM_LIB_PRIVATE_H__ +#define __ARM_LIB_PRIVATE_H__ + +#define CACHE_SIZE_4_KB (3UL) +#define CACHE_SIZE_8_KB (4UL) +#define CACHE_SIZE_16_KB (5UL) +#define CACHE_SIZE_32_KB (6UL) +#define CACHE_SIZE_64_KB (7UL) +#define CACHE_SIZE_128_KB (8UL) + +#define CACHE_ASSOCIATIVITY_DIRECT (0UL) +#define CACHE_ASSOCIATIVITY_4_WAY (2UL) +#define CACHE_ASSOCIATIVITY_8_WAY (3UL) + +#define CACHE_PRESENT (0UL) +#define CACHE_NOT_PRESENT (1UL) + +#define CACHE_LINE_LENGTH_32_BYTES (2UL) + +#define SIZE_FIELD_TO_CACHE_SIZE(x) (((x) >> 6) & 0x0F) +#define SIZE_FIELD_TO_CACHE_ASSOCIATIVITY(x) (((x) >> 3) & 0x07) +#define SIZE_FIELD_TO_CACHE_PRESENCE(x) (((x) >> 2) & 0x01) +#define SIZE_FIELD_TO_CACHE_LINE_LENGTH(x) (((x) >> 0) & 0x03) + +#define DATA_CACHE_SIZE_FIELD(x) (((x) >> 12) & 0x0FFF) +#define INSTRUCTION_CACHE_SIZE_FIELD(x) (((x) >> 0) & 0x0FFF) + +#define DATA_CACHE_SIZE(x) (SIZE_FIELD_TO_CACHE_SIZE(DATA_CACHE_SIZE_FIELD(x))) +#define DATA_CACHE_ASSOCIATIVITY(x) (SIZE_FIELD_TO_CACHE_ASSOCIATIVITY(DATA_CACHE_SIZE_FIELD(x))) +#define DATA_CACHE_PRESENT(x) (SIZE_FIELD_TO_CACHE_PRESENCE(DATA_CACHE_SIZE_FIELD(x))) +#define DATA_CACHE_LINE_LENGTH(x) (SIZE_FIELD_TO_CACHE_LINE_LENGTH(DATA_CACHE_SIZE_FIELD(x))) + +#define INSTRUCTION_CACHE_SIZE(x) (SIZE_FIELD_TO_CACHE_SIZE(INSTRUCTION_CACHE_SIZE_FIELD(x))) +#define INSTRUCTION_CACHE_ASSOCIATIVITY(x) (SIZE_FIELD_TO_CACHE_ASSOCIATIVITY(INSTRUCTION_CACHE_SIZE_FIELD(x))) +#define INSTRUCTION_CACHE_PRESENT(x) (SIZE_FIELD_TO_CACHE_PRESENCE(INSTRUCTION_CACHE_SIZE_FIELD(x))) +#define INSTRUCTION_CACHE_LINE_LENGTH(x) (SIZE_FIELD_TO_CACHE_LINE_LENGTH(INSTRUCTION_CACHE_SIZE_FIELD(x))) + +#define CACHE_TYPE(x) (((x) >> 25) & 0x0F) +#define CACHE_TYPE_WRITE_BACK (0x0EUL) + +#define CACHE_ARCHITECTURE(x) (((x) >> 24) & 0x01) +#define CACHE_ARCHITECTURE_UNIFIED (0UL) +#define CACHE_ARCHITECTURE_SEPARATE (1UL) + +VOID +CPSRMaskInsert ( + IN UINT32 Mask, + IN UINT32 Value + ); + +UINT32 +CPSRRead ( + VOID + ); + +#endif // __ARM_LIB_PRIVATE_H__ diff --git a/ArmPkg/Library/ArmLib/Common/ArmLibSupport.S b/ArmPkg/Library/ArmLib/Common/ArmLibSupport.S new file mode 100644 index 0000000000..d80100c788 --- /dev/null +++ b/ArmPkg/Library/ArmLib/Common/ArmLibSupport.S @@ -0,0 +1,89 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2008-2009 Apple Inc. All rights reserved. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + +.text +.align 2 +.globl ASM_PFX(Cp15IdCode) +.globl ASM_PFX(Cp15CacheInfo) +.globl ASM_PFX(ArmEnableInterrupts) +.globl ASM_PFX(ArmDisableInterrupts) +.globl ASM_PFX(ArmGetInterruptState) +.globl ASM_PFX(ArmInvalidateTlb) +.globl ASM_PFX(ArmSetTranslationTableBaseAddress) +.globl ASM_PFX(ArmSetDomainAccessControl) +.globl ASM_PFX(CPSRMaskInsert) +.globl ASM_PFX(CPSRRead) + +#------------------------------------------------------------------------------ + +ASM_PFX(Cp15IdCode): + mrc p15,0,R0,c0,c0,0 + bx LR + +ASM_PFX(Cp15CacheInfo): + mrc p15,0,R0,c0,c0,1 + bx LR + +ASM_PFX(ArmEnableInterrupts): + mrs R0,CPSR + bic R0,R0,#0x80 @Enable IRQ interrupts + msr CPSR_c,R0 + bx LR + +ASM_PFX(ArmDisableInterrupts): + mrs R0,CPSR + orr R1,R0,#0x80 @Disable IRQ interrupts + msr CPSR_c,R1 + tst R0,#0x80 + moveq R0,#1 + movne R0,#0 + bx LR + +ASM_PFX(ArmGetInterruptState): + mrs R0,CPSR + tst R0,#0x80 @Check if IRQ is enabled. + moveq R0,#1 + movne R0,#0 + bx LR + +ASM_PFX(ArmInvalidateTlb): + mov r0,#0 + mcr p15,0,r0,c8,c7,0 + bx lr + +ASM_PFX(ArmSetTranslationTableBaseAddress): + mcr p15,0,r0,c2,c0,0 + bx lr + +ASM_PFX(ArmSetDomainAccessControl): + mcr p15,0,r0,c3,c0,0 + bx lr + +ASM_PFX(CPSRMaskInsert): @ on entry, r0 is the mask and r1 is the field to insert + stmfd sp!, {r4-r12, lr} @ save all the banked registers + mov r3, sp @ copy the stack pointer into a non-banked register + mrs r2, cpsr @ read the cpsr + bic r2, r2, r0 @ clear mask in the cpsr + and r1, r1, r0 @ clear bits outside the mask in the input + orr r2, r2, r1 @ set field + msr cpsr_cxsf, r2 @ write back cpsr (may have caused a mode switch) + mov sp, r3 @ restore stack pointer + ldmfd sp!, {r4-r12, lr} @ restore registers + bx lr @ return (hopefully thumb-safe!) + +ASM_PFX(CPSRRead): + mrs r0, cpsr + bx lr + +ASM_FUNCTION_REMOVE_IF_UNREFERENCED diff --git a/ArmPkg/Library/ArmLib/Common/ArmLibSupport.asm b/ArmPkg/Library/ArmLib/Common/ArmLibSupport.asm new file mode 100644 index 0000000000..ec7db638af --- /dev/null +++ b/ArmPkg/Library/ArmLib/Common/ArmLibSupport.asm @@ -0,0 +1,90 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2008-2009 Apple Inc. All rights reserved. +// +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +//------------------------------------------------------------------------------ + + + EXPORT Cp15IdCode + EXPORT Cp15CacheInfo + EXPORT ArmEnableInterrupts + EXPORT ArmDisableInterrupts + EXPORT ArmGetInterruptState + EXPORT ArmInvalidateTlb + EXPORT ArmSetTranslationTableBaseAddress + EXPORT ArmSetDomainAccessControl + EXPORT CPSRMaskInsert + EXPORT CPSRRead + + AREA ArmLibSupport, CODE, READONLY + +Cp15IdCode + mrc p15,0,R0,c0,c0,0 + bx LR + +Cp15CacheInfo + mrc p15,0,R0,c0,c0,1 + bx LR + +ArmEnableInterrupts + mrs R0,CPSR + bic R0,R0,#0x80 ;Enable IRQ interrupts + msr CPSR_c,R0 + bx LR + +ArmDisableInterrupts + mrs R0,CPSR + orr R1,R0,#0x80 ;Disable IRQ interrupts + msr CPSR_c,R1 + tst R0,#0x80 + moveq R0,#1 + movne R0,#0 + bx LR + +ArmGetInterruptState + mrs R0,CPSR + tst R0,#0x80 ;Check if IRQ is enabled. + moveq R0,#1 + movne R0,#0 + bx LR + +ArmInvalidateTlb + mov r0,#0 + mcr p15,0,r0,c8,c7,0 + bx lr + +ArmSetTranslationTableBaseAddress + mcr p15,0,r0,c2,c0,0 + bx lr + +ArmSetDomainAccessControl + mcr p15,0,r0,c3,c0,0 + bx lr + +CPSRMaskInsert ; on entry, r0 is the mask and r1 is the field to insert + stmfd sp!, {r4-r12, lr} ; save all the banked registers + mov r3, sp ; copy the stack pointer into a non-banked register + mrs r2, cpsr ; read the cpsr + bic r2, r2, r0 ; clear mask in the cpsr + and r1, r1, r0 ; clear bits outside the mask in the input + orr r2, r2, r1 ; set field + msr cpsr_cxsf, r2 ; write back cpsr (may have caused a mode switch) + mov sp, r3 ; restore stack pointer + ldmfd sp!, {r4-r12, lr} ; restore registers + bx lr ; return (hopefully thumb-safe!) + +CPSRRead + mrs r0, cpsr + bx lr + + END + + diff --git a/ArmPkg/Library/ArmLib/Null/NullArmCacheInformation.c b/ArmPkg/Library/ArmLib/Null/NullArmCacheInformation.c new file mode 100644 index 0000000000..08a1ad0c5f --- /dev/null +++ b/ArmPkg/Library/ArmLib/Null/NullArmCacheInformation.c @@ -0,0 +1,106 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include "ArmLibPrivate.h" + +ARM_CACHE_TYPE +EFIAPI +ArmCacheType ( + VOID + ) +{ + return ARM_CACHE_TYPE_UNKNOWN; +} + +ARM_CACHE_ARCHITECTURE +EFIAPI +ArmCacheArchitecture ( + VOID + ) +{ + return ARM_CACHE_ARCHITECTURE_UNKNOWN; +} + +BOOLEAN +EFIAPI +ArmDataCachePresent ( + VOID + ) +{ + return FALSE; +} + +UINTN +EFIAPI +ArmDataCacheSize ( + VOID + ) +{ + return 0; +} + +UINTN +EFIAPI +ArmDataCacheAssociativity ( + VOID + ) +{ + return 0; +} + +UINTN +EFIAPI +ArmDataCacheLineLength ( + VOID + ) +{ + return 0; +} + +BOOLEAN +EFIAPI +ArmInstructionCachePresent ( + VOID + ) +{ + return FALSE; +} + +UINTN +EFIAPI +ArmInstructionCacheSize ( + VOID + ) +{ + return 0; +} + +UINTN +EFIAPI +ArmInstructionCacheAssociativity ( + VOID + ) +{ + return 0; +} + +UINTN +EFIAPI +ArmInstructionCacheLineLength ( + VOID + ) +{ + return 0; +} diff --git a/ArmPkg/Library/ArmLib/Null/NullArmLib.c b/ArmPkg/Library/ArmLib/Null/NullArmLib.c new file mode 100644 index 0000000000..6e95cba706 --- /dev/null +++ b/ArmPkg/Library/ArmLib/Null/NullArmLib.c @@ -0,0 +1,117 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include + +VOID +EFIAPI +ArmCleanInvalidateDataCache ( + VOID + ) +{ + // Do not run code using the Null cache library. + ASSERT(FALSE); +} + +VOID +EFIAPI +ArmCleanDataCache ( + VOID + ) +{ + // Do not run code using the Null cache library. + ASSERT(FALSE); +} + +VOID +EFIAPI +ArmInvalidateInstructionCache ( + VOID + ) +{ + // Do not run code using the Null cache library. + ASSERT(FALSE); +} + +VOID +EFIAPI +ArmInvalidateDataCacheEntryByMVA ( + IN UINTN Address + ) +{ + // Do not run code using the Null cache library. + ASSERT(FALSE); +} + +VOID +EFIAPI +ArmCleanDataCacheEntryByMVA ( + IN UINTN Address + ) +{ + // Do not run code using the Null cache library. + ASSERT(FALSE); +} + +VOID +EFIAPI +ArmCleanInvalidateDataCacheEntryByMVA ( + IN UINTN Address + ) +{ + // Do not run code using the Null cache library. + ASSERT(FALSE); +} + +VOID +EFIAPI +ArmEnableDataCache ( + VOID + ) +{ + // Do not run code using the Null cache library. + ASSERT(FALSE); +} + +VOID +EFIAPI +ArmDisableDataCache ( + VOID + ) +{ + // Do not run code using the Null cache library. + ASSERT(FALSE); +} + +VOID +EFIAPI +ArmEnableInstructionCache ( + VOID + ) +{ + // Do not run code using the Null cache library. + ASSERT(FALSE); +} + +VOID +EFIAPI +ArmDisableInstructionCache ( + VOID + ) +{ + // Do not run code using the Null cache library. + ASSERT(FALSE); +} diff --git a/ArmPkg/Library/ArmLib/Null/NullArmLib.inf b/ArmPkg/Library/ArmLib/Null/NullArmLib.inf new file mode 100644 index 0000000000..ff31b9cecb --- /dev/null +++ b/ArmPkg/Library/ArmLib/Null/NullArmLib.inf @@ -0,0 +1,26 @@ +#%HEADER% +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = NullArmLib + FILE_GUID = 00586300-0E06-4790-AC44-86C56ACBB942 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = ArmLib + +[Sources.common] + ../Common/ArmLibSupport.S | GCC + ../Common/ArmLibSupport.asm | RVCT + ../Common/ArmLib.c + + NullArmLib.c + NullArmCacheInformation.c + +[Packages] + ArmPkg/ArmPkg.dec + MdePkg/MdePkg.dec + +[Protocols] + gEfiCpuArchProtocolGuid + +[FixedPcd] + gArmTokenSpaceGuid.PcdArmCacheOperationThreshold diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/Llvm_int_lib.h b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/Llvm_int_lib.h new file mode 100644 index 0000000000..e2c00a2033 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/Llvm_int_lib.h @@ -0,0 +1,83 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +/** + University of Illinois/NCSA + Open Source License + + Copyright (c) 2003-2008 University of Illinois at Urbana-Champaign. + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. +**/ + +#include +#include + +#define CHAR_BIT 8 + +typedef union { + INT64 all; + struct { + UINT32 low; + INT32 high; + }; +} dwords; + +typedef union { + UINT64 all; + struct { + UINT32 low; + UINT32 high; + }; +} udwords; + +#if __GNUC__ + #define COUNT_LEADING_ZEROS(_a) __builtin_clz((_a)) + #define COUNT_TRAILING_ZEROS(_a) __builtin_ctz((_a)) +#else +#error COUNT_LEADING_ZEROS() and COUNT_TRAILING_ZEROS() macros not ported to your compiler +#endif diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashldi3.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashldi3.S new file mode 100644 index 0000000000..ac2bdbafd0 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashldi3.S @@ -0,0 +1,38 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2008-2009 Apple Inc. All rights reserved. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + + .text + .align 2 + .globl ___ashldi3 +___ashldi3: + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 0, uses_anonymous_args = 0 + @ link register save eliminated. + cmp r2, #31 + @ lr needed for prologue + bls L2 + cmp r2, #63 + subls r2, r2, #32 + movls r2, r0, asl r2 + movhi r2, #0 + mov r1, r2 + mov r0, #0 + bx lr +L2: + cmp r2, #0 + rsbne r3, r2, #32 + movne r3, r0, lsr r3 + movne r0, r0, asl r2 + orrne r1, r3, r1, asl r2 + bx lr diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashldi3.c b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashldi3.c new file mode 100644 index 0000000000..f708737035 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashldi3.c @@ -0,0 +1,83 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +/** + University of Illinois/NCSA + Open Source License + + Copyright (c) 2003-2008 University of Illinois at Urbana-Champaign. + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. +**/ + +#include "Llvm_int_lib.h" + +// Returns: a << b + +// Precondition: 0 <= b < bits_in_dword + +INT64 +__ashldi3(INT64 a, INT32 b) +{ + const int bits_in_word = (int)(sizeof(INT32) * CHAR_BIT); + dwords input; + dwords result; + input.all = a; + if (b & bits_in_word) // bits_in_word <= b < bits_in_dword + { + result.low = 0; + result.high = input.low << (b - bits_in_word); + } + else // 0 <= b < bits_in_word + { + if (b == 0) + return a; + result.low = input.low << b; + result.high = (input.high << b) | (input.low >> (bits_in_word - b)); + } + return result.all; +} diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashrdi3.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashrdi3.S new file mode 100644 index 0000000000..fb87c88a09 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashrdi3.S @@ -0,0 +1,39 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2008-2009 Apple Inc. All rights reserved. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + + .text + .align 2 + .globl ___ashrdi3 +___ashrdi3: + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 0, uses_anonymous_args = 0 + @ link register save eliminated. + cmp r2, #31 + @ lr needed for prologue + bls L2 + cmp r2, #63 + subls r2, r2, #32 + mov ip, r1, asr #31 + movls r2, r1, asr r2 + movhi r2, ip + mov r0, r2 + mov r1, ip + bx lr +L2: + cmp r2, #0 + rsbne r3, r2, #32 + movne r3, r1, asl r3 + movne r1, r1, asr r2 + orrne r0, r3, r0, lsr r2 + bx lr diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashrdi3.c b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashrdi3.c new file mode 100644 index 0000000000..ce5134eb64 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashrdi3.c @@ -0,0 +1,84 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +/** + University of Illinois/NCSA + Open Source License + + Copyright (c) 2003-2008 University of Illinois at Urbana-Champaign. + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. +**/ + +#include "Llvm_int_lib.h" + +// Returns: arithmetic a >> b + +// Precondition: 0 <= b < bits_in_dword + +INT64 +__ashrdi3(INT64 a, INT32 b) +{ + const int bits_in_word = (int)(sizeof(INT32) * CHAR_BIT); + dwords input; + dwords result; + input.all = a; + if (b & bits_in_word) // bits_in_word <= b < bits_in_dword + { + // result.high = input.high < 0 ? -1 : 0 + result.high = input.high >> (bits_in_word - 1); + result.low = input.high >> (b - bits_in_word); + } + else // 0 <= b < bits_in_word + { + if (b == 0) + return a; + result.high = input.high >> b; + result.low = (input.high << (bits_in_word - b)) | (input.low >> b); + } + return result.all; +} diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/clzsi2.c b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/clzsi2.c new file mode 100644 index 0000000000..c7b4607ca4 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/clzsi2.c @@ -0,0 +1,96 @@ +/** @file + Compiler intrinsic to return the number of leading zeros, ported from LLVM code. + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +/** + University of Illinois/NCSA + Open Source License + + Copyright (c) 2003-2008 University of Illinois at Urbana-Champaign. + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. +**/ + + +#include "Llvm_int_lib.h" + +// Returns: the number of leading 0-bits + +// Precondition: a != 0 + +INT32 +__clzsi2(INT32 a) +{ + UINT32 x = (UINT32)a; + INT32 t = ((x & 0xFFFF0000) == 0) << 4; // if (x is small) t = 16 else 0 + x >>= 16 - t; // x = [0 - 0xFFFF] + UINT32 r = t; // r = [0, 16] + // return r + clz(x) + t = ((x & 0xFF00) == 0) << 3; + x >>= 8 - t; // x = [0 - 0xFF] + r += t; // r = [0, 8, 16, 24] + // return r + clz(x) + t = ((x & 0xF0) == 0) << 2; + x >>= 4 - t; // x = [0 - 0xF] + r += t; // r = [0, 4, 8, 12, 16, 20, 24, 28] + // return r + clz(x) + t = ((x & 0xC) == 0) << 1; + x >>= 2 - t; // x = [0 - 3] + r += t; // r = [0 - 30] and is even + // return r + clz(x) +// switch (x) +// { +// case 0: +// return r + 2; +// case 1: +// return r + 1; +// case 2: +// case 3: +// return r; +// } + return r + ((2 - x) & -((x & 2) == 0)); +} diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ctzsi2.c b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ctzsi2.c new file mode 100644 index 0000000000..c0e18977ec --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ctzsi2.c @@ -0,0 +1,111 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +/** @file + Compiler intrinsic to return the number of trailing zeros, ported from LLVM code. + + Copyright (c) 2008, Apple, Inc. + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +/** + University of Illinois/NCSA + Open Source License + + Copyright (c) 2003-2008 University of Illinois at Urbana-Champaign. + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. +**/ + + +#include "Llvm_int_lib.h" + +// Returns: the number of trailing 0-bits + +// Precondition: a != 0 + +INT32 +__ctzsi2(INT32 a) +{ + UINT32 x = (UINT32)a; + INT32 t = ((x & 0x0000FFFF) == 0) << 4; // if (x has no small bits) t = 16 else 0 + x >>= t; // x = [0 - 0xFFFF] + higher garbage bits + UINT32 r = t; // r = [0, 16] + // return r + ctz(x) + t = ((x & 0x00FF) == 0) << 3; + x >>= t; // x = [0 - 0xFF] + higher garbage bits + r += t; // r = [0, 8, 16, 24] + // return r + ctz(x) + t = ((x & 0x0F) == 0) << 2; + x >>= t; // x = [0 - 0xF] + higher garbage bits + r += t; // r = [0, 4, 8, 12, 16, 20, 24, 28] + // return r + ctz(x) + t = ((x & 0x3) == 0) << 1; + x >>= t; + x &= 3; // x = [0 - 3] + r += t; // r = [0 - 30] and is even + // return r + ctz(x) +// The branch-less return statement below is equivalent +// to the following switch statement: +// switch (x) +// { +// case 0: +// return r + 2; +// case 2: +// return r + 1; +// case 1: +// case 3: +// return r; +// } + return r + ((2 - (x >> 1)) & -((x & 1) == 0)); +} diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/div.asm b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/div.asm new file mode 100644 index 0000000000..f6f9bc2d56 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/div.asm @@ -0,0 +1,155 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2008-2009 Apple Inc. All rights reserved. +// +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +//------------------------------------------------------------------------------ + + + EXPORT __aeabi_uidiv + EXPORT __aeabi_uidivmod + EXPORT __aeabi_idiv + EXPORT __aeabi_idivmod + + AREA Math, CODE, READONLY + +; +;UINT32 +;EFIAPI +;__aeabi_uidivmode ( +; IN UINT32 Dividen +; IN UINT32 Divisor +; ); +; + +__aeabi_uidiv +__aeabi_uidivmod + RSBS r12, r1, r0, LSR #4 + MOV r2, #0 + BCC __arm_div4 + RSBS r12, r1, r0, LSR #8 + BCC __arm_div8 + MOV r3, #0 + B __arm_div_large + +; +;INT32 +;EFIAPI +;__aeabi_idivmode ( +; IN INT32 Dividen +; IN INT32 Divisor +; ); +; +__aeabi_idiv +__aeabi_idivmod + ORRS r12, r0, r1 + BMI __arm_div_negative + RSBS r12, r1, r0, LSR #1 + MOV r2, #0 + BCC __arm_div1 + RSBS r12, r1, r0, LSR #4 + BCC __arm_div4 + RSBS r12, r1, r0, LSR #8 + BCC __arm_div8 + MOV r3, #0 + B __arm_div_large +__arm_div8 + RSBS r12, r1, r0, LSR #7 + SUBCS r0, r0, r1, LSL #7 + ADC r2, r2, r2 + RSBS r12, r1, r0,LSR #6 + SUBCS r0, r0, r1, LSL #6 + ADC r2, r2, r2 + RSBS r12, r1, r0, LSR #5 + SUBCS r0, r0, r1, LSL #5 + ADC r2, r2, r2 + RSBS r12, r1, r0, LSR #4 + SUBCS r0, r0, r1, LSL #4 + ADC r2, r2, r2 +__arm_div4 + RSBS r12, r1, r0, LSR #3 + SUBCS r0, r0, r1, LSL #3 + ADC r2, r2, r2 + RSBS r12, r1, r0, LSR #2 + SUBCS r0, r0, r1, LSL #2 + ADCS r2, r2, r2 + RSBS r12, r1, r0, LSR #1 + SUBCS r0, r0, r1, LSL #1 + ADC r2, r2, r2 +__arm_div1 + SUBS r1, r0, r1 + MOVCC r1, r0 + ADC r0, r2, r2 + BX r14 +__arm_div_negative + ANDS r2, r1, #0x80000000 + RSBMI r1, r1, #0 + EORS r3, r2, r0, ASR #32 + RSBCS r0, r0, #0 + RSBS r12, r1, r0, LSR #4 + BCC label1 + RSBS r12, r1, r0, LSR #8 + BCC label2 +__arm_div_large + LSL r1, r1, #6 + RSBS r12, r1, r0, LSR #8 + ORR r2, r2, #0xfc000000 + BCC label2 + LSL r1, r1, #6 + RSBS r12, r1, r0, LSR #8 + ORR r2, r2, #0x3f00000 + BCC label2 + LSL r1, r1, #6 + RSBS r12, r1, r0, LSR #8 + ORR r2, r2, #0xfc000 + ORRCS r2, r2, #0x3f00 + LSLCS r1, r1, #6 + RSBS r12, r1, #0 + BCS __aeabi_idiv0 +label3 + LSRCS r1, r1, #6 +label2 + RSBS r12, r1, r0, LSR #7 + SUBCS r0, r0, r1, LSL #7 + ADC r2, r2, r2 + RSBS r12, r1, r0, LSR #6 + SUBCS r0, r0, r1, LSL #6 + ADC r2, r2, r2 + RSBS r12, r1, r0, LSR #5 + SUBCS r0, r0, r1, LSL #5 + ADC r2, r2, r2 + RSBS r12, r1, r0, LSR #4 + SUBCS r0, r0, r1, LSL #4 + ADC r2, r2, r2 +label1 + RSBS r12, r1, r0, LSR #3 + SUBCS r0, r0, r1, LSL #3 + ADC r2, r2, r2 + RSBS r12, r1, r0, LSR #2 + SUBCS r0, r0, r1, LSL #2 + ADCS r2, r2, r2 + BCS label3 + RSBS r12, r1, r0, LSR #1 + SUBCS r0, r0, r1, LSL #1 + ADC r2, r2, r2 + SUBS r1, r0, r1 + MOVCC r1, r0 + ADC r0, r2, r2 + ASRS r3, r3, #31 + RSBMI r0, r0, #0 + RSBCS r1, r1, #0 + BX r14 + + ; What to do about division by zero? For now, just return. +__aeabi_idiv0 + BX r14 + + END + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/divdi3.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/divdi3.S new file mode 100644 index 0000000000..b7d946ecc7 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/divdi3.S @@ -0,0 +1,48 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2008-2009 Apple Inc. All rights reserved. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + + .text + .align 2 + .globl ___divdi3 +___divdi3: + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 1, uses_anonymous_args = 0 + stmfd sp!, {r4, r5, r7, lr} + mov r4, r3, asr #31 + add r7, sp, #8 + stmfd sp!, {r10, r11} + mov r10, r1, asr #31 + sub sp, sp, #8 + mov r11, r10 + mov r5, r4 + eor r0, r0, r10 + eor r1, r1, r10 + eor r2, r2, r4 + eor r3, r3, r4 + subs r2, r2, r4 + sbc r3, r3, r5 + mov ip, #0 + subs r0, r0, r10 + sbc r1, r1, r11 + str ip, [sp, #0] + bl ___udivmoddi4 + eor r2, r10, r4 + eor r3, r10, r4 + eor r0, r0, r2 + eor r1, r1, r3 + subs r0, r0, r2 + sbc r1, r1, r3 + sub sp, r7, #16 + ldmfd sp!, {r10, r11} + ldmfd sp!, {r4, r5, r7, pc} diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/divdi3.c b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/divdi3.c new file mode 100644 index 0000000000..286a504b49 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/divdi3.c @@ -0,0 +1,77 @@ +/** @file + Compiler intrinsic for 64-bit compare, ported from LLVM code. + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +/** + University of Illinois/NCSA + Open Source License + + Copyright (c) 2003-2008 University of Illinois at Urbana-Champaign. + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. +**/ + + +#include "Llvm_int_lib.h" + +UINT64 __udivmoddi4(UINT64 a, UINT64 b, UINT64* rem); + +// Returns: a / b + +INT64 +__divdi3(INT64 a, INT64 b) +{ + const int bits_in_dword_m1 = (int)(sizeof(INT64) * CHAR_BIT) - 1; + INT64 s_a = a >> bits_in_dword_m1; // s_a = a < 0 ? -1 : 0 + INT64 s_b = b >> bits_in_dword_m1; // s_b = b < 0 ? -1 : 0 + a = (a ^ s_a) - s_a; // negate if s_a == -1 + b = (b ^ s_b) - s_b; // negate if s_b == -1 + s_a ^= s_b; // sign of quotient + return (__udivmoddi4(a, b, (UINT64*)0) ^ s_a) - s_a; // negate if s_a == -1 +} + + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/divsi3.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/divsi3.S new file mode 100644 index 0000000000..2651572222 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/divsi3.S @@ -0,0 +1,33 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2008-2009 Apple Inc. All rights reserved. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + + .text + .align 2 + .globl ___divsi3 +___divsi3: + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 1, uses_anonymous_args = 0 + eor r3, r0, r0, asr #31 + eor r2, r1, r1, asr #31 + stmfd sp!, {r4, r5, r7, lr} + mov r5, r0, asr #31 + add r7, sp, #8 + mov r4, r1, asr #31 + sub r0, r3, r0, asr #31 + sub r1, r2, r1, asr #31 + bl ___udivsi3 + eor r1, r5, r4 + eor r0, r0, r1 + rsb r0, r1, r0 + ldmfd sp!, {r4, r5, r7, pc} diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/divsi3.c b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/divsi3.c new file mode 100644 index 0000000000..56d731ca8e --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/divsi3.c @@ -0,0 +1,78 @@ +/** @file + Compiler intrinsic for 32--bit unsigned division, ported from LLVM code. + + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +/** + University of Illinois/NCSA + Open Source License + + Copyright (c) 2003-2008 University of Illinois at Urbana-Champaign. + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. +**/ + + +#include "Llvm_int_lib.h" + +UINT32 __udivsi3(UINT32 n, UINT32 d); + +// Returns: a / b + +INT32 +__divsi3(INT32 a, INT32 b) +{ + const int bits_in_word_m1 = (int)(sizeof(INT32) * CHAR_BIT) - 1; + INT32 s_a = a >> bits_in_word_m1; // s_a = a < 0 ? -1 : 0 + INT32 s_b = b >> bits_in_word_m1; // s_b = b < 0 ? -1 : 0 + a = (a ^ s_a) - s_a; // negate if s_a == -1 + b = (b ^ s_b) - s_b; // negate if s_b == -1 + s_a ^= s_b; // sign of quotient + return (__udivsi3(a, b) ^ s_a) - s_a; // negate if s_a == -1 +} + + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/lasr.asm b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/lasr.asm new file mode 100644 index 0000000000..9956d064c2 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/lasr.asm @@ -0,0 +1,41 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2008-2009 Apple Inc. All rights reserved. +// +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +//------------------------------------------------------------------------------ + + + EXPORT __aeabi_lasr + + AREA Math, CODE, READONLY + +; +;UINT32 +;EFIAPI +;__aeabi_lasr ( +; IN UINT32 Dividen +; IN UINT32 Divisor +; ); +; +__aeabi_lasr + SUBS r3,r2,#0x20 + BPL {pc} + 0x18 ; 0x1c + RSB r3,r2,#0x20 + LSR r0,r0,r2 + ORR r0,r0,r1,LSL r3 + ASR r1,r1,r2 + BX lr + ASR r0,r1,r3 + ASR r1,r1,#31 + BX lr + + END + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ldivmod.asm b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ldivmod.asm new file mode 100644 index 0000000000..cb81608b01 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ldivmod.asm @@ -0,0 +1,54 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2008-2009 Apple Inc. All rights reserved. +// +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +//------------------------------------------------------------------------------ + + + EXPORT __aeabi_ldivmod + EXTERN __aeabi_uldivmod + + AREA Math, CODE, READONLY + +; +;UINT32 +;EFIAPI +;__aeabi_uidivmode ( +; IN UINT32 Dividen +; IN UINT32 Divisor +; ); +; + +__aeabi_ldivmod + PUSH {r4,lr} + ASRS r4,r1,#1 + EOR r4,r4,r3,LSR #1 + BPL {pc} + 0xc ; 0x18 + RSBS r0,r0,#0 + RSC r1,r1,#0 + TST r3,r3 + BPL {pc} + 0xc ; 0x28 + RSBS r2,r2,#0 + RSC r3,r3,#0 + BL __aeabi_uldivmod ; + TST r4,#0x40000000 + BEQ {pc} + 0xc ; 0x3c + RSBS r0,r0,#0 + RSC r1,r1,#0 + TST r4,#0x80000000 + BEQ {pc} + 0xc ; 0x4c + RSBS r2,r2,#0 + RSC r3,r3,#0 + POP {r4,pc} + + END + + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/llsl.asm b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/llsl.asm new file mode 100644 index 0000000000..745b984085 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/llsl.asm @@ -0,0 +1,43 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2008-2009 Apple Inc. All rights reserved. +// +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +//------------------------------------------------------------------------------ + + + EXPORT __aeabi_llsl + + AREA Math, CODE, READONLY + +; +;VOID +;EFIAPI +;__aeabi_llsl ( +; IN VOID *Destination, +; IN VOID *Source, +; IN UINT32 Size +; ); +; + +__aeabi_llsl + SUBS r3,r2,#0x20 + BPL {pc} + 0x18 ; 0x1c + RSB r3,r2,#0x20 + LSL r1,r1,r2 + ORR r1,r1,r0,LSR r3 + LSL r0,r0,r2 + BX lr + LSL r1,r0,r3 + MOV r0,#0 + BX lr + + END + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/llsr.asm b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/llsr.asm new file mode 100644 index 0000000000..630b542c70 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/llsr.asm @@ -0,0 +1,44 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2008-2009 Apple Inc. All rights reserved. +// +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +//------------------------------------------------------------------------------ + + + EXPORT __aeabi_llsr + + AREA Math, CODE, READONLY + +; +;VOID +;EFIAPI +;__aeabi_llsr ( +; IN VOID *Destination, +; IN VOID *Source, +; IN UINT32 Size +; ); +; +__aeabi_llsr + SUBS r3,r2,#0x20 + BPL {pc} + 0x18 ; 0x1c + RSB r3,r2,#0x20 + LSR r0,r0,r2 + ORR r0,r0,r1,LSL r3 + LSR r1,r1,r2 + BX lr + LSR r0,r1,r3 + MOV r1,#0 + BX lr + + END + + + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/lshrdi3.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/lshrdi3.S new file mode 100644 index 0000000000..2257deef97 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/lshrdi3.S @@ -0,0 +1,38 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2008-2009 Apple Inc. All rights reserved. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + + .text + .align 2 + .globl ___lshrdi3 +___lshrdi3: + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 0, uses_anonymous_args = 0 + @ link register save eliminated. + cmp r2, #31 + @ lr needed for prologue + bls L2 + cmp r2, #63 + subls r2, r2, #32 + movls r2, r1, lsr r2 + movhi r2, #0 + mov r0, r2 + mov r1, #0 + bx lr +L2: + cmp r2, #0 + rsbne r3, r2, #32 + movne r3, r1, asl r3 + movne r1, r1, lsr r2 + orrne r0, r3, r0, lsr r2 + bx lr diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/lshrdi3.c b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/lshrdi3.c new file mode 100644 index 0000000000..14b3c8f00a --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/lshrdi3.c @@ -0,0 +1,83 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +/** + University of Illinois/NCSA + Open Source License + + Copyright (c) 2003-2008 University of Illinois at Urbana-Champaign. + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. +**/ + +#include "Llvm_int_lib.h" + +// Returns: logical a >> b + +// Precondition: 0 <= b < bits_in_dword + +INT64 +__lshrdi3(INT64 a, INT32 b) +{ + const int bits_in_word = (int)(sizeof(INT32) * CHAR_BIT); + udwords input; + udwords result; + input.all = a; + if (b & bits_in_word) // bits_in_word <= b < bits_in_dword + { + result.high = 0; + result.low = input.high >> (b - bits_in_word); + } + else // 0 <= b < bits_in_word + { + if (b == 0) + return a; + result.high = input.high >> b; + result.low = (input.high << (bits_in_word - b)) | (input.low >> b); + } + return result.all; +} diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/memcpy.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/memcpy.S new file mode 100644 index 0000000000..2582a81f90 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/memcpy.S @@ -0,0 +1,35 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2008-2009 Apple Inc. All rights reserved. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + + .text + .align 2 + .globl _memcpy +_memcpy: + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 1, uses_anonymous_args = 0 + stmfd sp!, {r7, lr} + mov ip, #0 + add r7, sp, #0 + mov lr, r0 + b L4 +L5: + ldrb r3, [r1], #1 @ zero_extendqisi2 + add ip, ip, #1 + and r3, r3, #255 + strb r3, [lr], #1 +L4: + cmp ip, r2 + bne L5 + ldmfd sp!, {r7, pc} + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/memcpy.asm b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/memcpy.asm new file mode 100644 index 0000000000..60dbcf2ab5 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/memcpy.asm @@ -0,0 +1,40 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2008-2009 Apple Inc. All rights reserved. +// +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +//------------------------------------------------------------------------------ + + + EXPORT __aeabi_memcpy + + AREA Memcpy, CODE, READONLY + +; +;VOID +;EFIAPI +;__aeabi_memcpy ( +; IN VOID *Destination, +; IN VOID *Source, +; IN UINT32 Size +; ); +; +__aeabi_memcpy + CMP r2, #0 + BXEQ r14 +loop + LDRB r3, [r1], #1 + STRB r3, [r0], #1 + SUBS r2, r2, #1 + BXEQ r14 + B loop + + END + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/memcpy4.asm b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/memcpy4.asm new file mode 100644 index 0000000000..fb251c1eaa --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/memcpy4.asm @@ -0,0 +1,61 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2008-2009 Apple Inc. All rights reserved. +// +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +//------------------------------------------------------------------------------ + + + EXPORT __aeabi_memcpy4 + + AREA Memcpy4, CODE, READONLY + +; +;VOID +;EFIAPI +;__aeabi_memcpy ( +; IN VOID *Destination, +; IN VOID *Source, +; IN UINT32 Size +; ); +; +__aeabi_memcpy4 + stmdb sp!, {r4, lr} + subs r2, r2, #32 ; 0x20 + bcc memcpy4_label2 +memcpy4_label1 + ldmcsia r1!, {r3, r4, ip, lr} + stmcsia r0!, {r3, r4, ip, lr} + ldmcsia r1!, {r3, r4, ip, lr} + stmcsia r0!, {r3, r4, ip, lr} + subcss r2, r2, #32 ; 0x20 + bcs memcpy4_label1 +memcpy4_label2 + movs ip, r2, lsl #28 + ldmcsia r1!, {r3, r4, ip, lr} + stmcsia r0!, {r3, r4, ip, lr} + ldmmiia r1!, {r3, r4} + stmmiia r0!, {r3, r4} + ldmia sp!, {r4, lr} + movs ip, r2, lsl #30 + ldrcs r3, [r1], #4 + strcs r3, [r0], #4 + bxeq lr + +_memcpy4_lastbytes_aligned + movs r2, r2, lsl #31 + ldrcsh r3, [r1], #2 + ldrmib r2, [r1], #1 + strcsh r3, [r0], #2 + strmib r2, [r0], #1 + bx lr + + END + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/memset.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/memset.S new file mode 100644 index 0000000000..f88464483b --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/memset.S @@ -0,0 +1,35 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2008-2009 Apple Inc. All rights reserved. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + + + .text + .align 2 + .globl _memset +_memset: + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 1, uses_anonymous_args = 0 + stmfd sp!, {r7, lr} + mov ip, #0 + add r7, sp, #0 + mov lr, r0 + b L9 +L10: + and r3, r1, #255 + add ip, ip, #1 + strb r3, [lr], #1 +L9: + cmp ip, r2 + bne L10 + ldmfd sp!, {r7, pc} + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/moddi3.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/moddi3.S new file mode 100644 index 0000000000..7af8d21683 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/moddi3.S @@ -0,0 +1,47 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2008-2009 Apple Inc. All rights reserved. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + + .text + .align 2 + .globl ___moddi3 +___moddi3: + @ args = 0, pretend = 0, frame = 8 + @ frame_needed = 1, uses_anonymous_args = 0 + stmfd sp!, {r4, r5, r7, lr} + mov r4, r1, asr #31 + add r7, sp, #8 + stmfd sp!, {r10, r11} + mov r10, r3, asr #31 + sub sp, sp, #16 + mov r5, r4 + mov r11, r10 + eor r0, r0, r4 + eor r1, r1, r4 + eor r2, r2, r10 + eor r3, r3, r10 + add ip, sp, #8 + subs r0, r0, r4 + sbc r1, r1, r5 + subs r2, r2, r10 + sbc r3, r3, r11 + str ip, [sp, #0] + bl ___udivmoddi4 + ldrd r0, [sp, #8] + eor r0, r0, r4 + eor r1, r1, r4 + subs r0, r0, r4 + sbc r1, r1, r5 + sub sp, r7, #16 + ldmfd sp!, {r10, r11} + ldmfd sp!, {r4, r5, r7, pc} diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/moddi3.c b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/moddi3.c new file mode 100644 index 0000000000..796b179dd3 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/moddi3.c @@ -0,0 +1,77 @@ +/** @file + Compiler intrinsic for 64-bit mod, ported from LLVM code. + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +/** + University of Illinois/NCSA + Open Source License + + Copyright (c) 2003-2008 University of Illinois at Urbana-Champaign. + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. +**/ + + +#include "Llvm_int_lib.h" + +UINT64 __udivmoddi4(UINT64 a, UINT64 b, UINT64* rem); + +// Returns: a % b + +INT64 +__moddi3(INT64 a, INT64 b) +{ + const int bits_in_dword_m1 = (int)(sizeof(INT64) * CHAR_BIT) - 1; + INT64 s = b >> bits_in_dword_m1; // s = b < 0 ? -1 : 0 + b = (b ^ s) - s; // negate if s == -1 + s = a >> bits_in_dword_m1; // s = a < 0 ? -1 : 0 + a = (a ^ s) - s; // negate if s == -1 + INT64 r; + __udivmoddi4(a, b, (UINT64*)&r); + return (r ^ s) - s; // negate if s == -1 +} + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/modsi3.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/modsi3.S new file mode 100644 index 0000000000..14d8542198 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/modsi3.S @@ -0,0 +1,28 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2008-2009 Apple Inc. All rights reserved. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + + .text + .align 2 + .globl ___modsi3 +___modsi3: + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 1, uses_anonymous_args = 0 + stmfd sp!, {r4, r5, r7, lr} + add r7, sp, #8 + mov r5, r0 + mov r4, r1 + bl ___divsi3 + mul r0, r4, r0 + rsb r0, r0, r5 + ldmfd sp!, {r4, r5, r7, pc} diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/modsi3.c b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/modsi3.c new file mode 100644 index 0000000000..45e0afd0d1 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/modsi3.c @@ -0,0 +1,70 @@ +/** @file + Compiler intrinsic for 32-bit mod, ported from LLVM code. + + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +/** + University of Illinois/NCSA + Open Source License + + Copyright (c) 2003-2008 University of Illinois at Urbana-Champaign. + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. +**/ + + +#include "Llvm_int_lib.h" + +// Returns: a % b + +INT32 +__modsi3(INT32 a, INT32 b) +{ + return a - (a / b) * b; +} + + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/muldi3.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/muldi3.S new file mode 100644 index 0000000000..a36dbff8c3 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/muldi3.S @@ -0,0 +1,59 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2008-2009 Apple Inc. All rights reserved. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + + .text + .align 2 + .globl ___muldi3 +___muldi3: + @ args = 0, pretend = 0, frame = 8 + @ frame_needed = 1, uses_anonymous_args = 0 + stmfd sp!, {r4, r5, r6, r7, lr} + add r7, sp, #12 + stmfd sp!, {r8, r10, r11} + ldr r11, L4 + mov r4, r0, lsr #16 + and r8, r0, r11 + and ip, r2, r11 + mul lr, ip, r8 + mul ip, r4, ip + sub sp, sp, #8 + add r10, ip, lr, lsr #16 + and ip, r10, r11 + and lr, lr, r11 + mov r6, r2, lsr #16 + str r4, [sp, #4] + add r4, lr, ip, asl #16 + mul ip, r8, r6 + mov r5, r10, lsr #16 + add r10, ip, r4, lsr #16 + and ip, r10, r11 + and lr, r4, r11 + add r4, lr, ip, asl #16 + mul r0, r3, r0 + add ip, r5, r10, lsr #16 + ldr r5, [sp, #4] + mla r0, r2, r1, r0 + mla r5, r6, r5, ip + mov r10, r4 + add r11, r0, r5 + mov r1, r11 + mov r0, r4 + sub sp, r7, #24 + ldmfd sp!, {r8, r10, r11} + ldmfd sp!, {r4, r5, r6, r7, pc} + .p2align 2 +L5: + .align 2 +L4: + .long 65535 diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/muldi3.c b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/muldi3.c new file mode 100644 index 0000000000..88c88cec2d --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/muldi3.c @@ -0,0 +1,98 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +/** + University of Illinois/NCSA + Open Source License + + Copyright (c) 2003-2008 University of Illinois at Urbana-Champaign. + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. +**/ + +#include +#include "Llvm_int_lib.h" + + +// Returns: a * b + +static +INT64 +__muldsi3(UINT32 a, UINT32 b) +{ + dwords r; + const int bits_in_word_2 = (int)(sizeof(INT32) * CHAR_BIT) / 2; + const UINT32 lower_mask = (UINT32)~0 >> bits_in_word_2; + r.low = (a & lower_mask) * (b & lower_mask); + UINT32 t = r.low >> bits_in_word_2; + r.low &= lower_mask; + t += (a >> bits_in_word_2) * (b & lower_mask); + r.low += (t & lower_mask) << bits_in_word_2; + r.high = t >> bits_in_word_2; + t = r.low >> bits_in_word_2; + r.low &= lower_mask; + t += (b >> bits_in_word_2) * (a & lower_mask); + r.low += (t & lower_mask) << bits_in_word_2; + r.high += t >> bits_in_word_2; + r.high += (a >> bits_in_word_2) * (b >> bits_in_word_2); + return r.all; +} + +// Returns: a * b + +INT64 +__muldi3(INT64 a, INT64 b) +{ + dwords x; + x.all = a; + dwords y; + y.all = b; + dwords r; + r.all = __muldsi3(x.low, y.low); + r.high += x.high * y.low + x.low * y.high; + return r.all; +} diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/mullu.asm b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/mullu.asm new file mode 100644 index 0000000000..baf7caa006 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/mullu.asm @@ -0,0 +1,49 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2008-2009 Apple Inc. All rights reserved. +// +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +//------------------------------------------------------------------------------ + + + EXPORT __ARM_ll_mullu + EXPORT __aeabi_lmul + + AREA Math, CODE, READONLY + +; +;INT64 +;EFIAPI +;__aeabi_lmul ( +; IN INT64 Multiplicand +; IN INT32 Multiplier +; ); +; +__ARM_ll_mullu + mov r3, #0 +// Make upper part of INT64 Multiplier 0 and use __aeabi_lmul + +; +;INT64 +;EFIAPI +;__aeabi_lmul ( +; IN INT64 Multiplicand +; IN INT64 Multiplier +; ); +; +__aeabi_lmul + stmdb sp!, {lr} + mov lr, r0 + umull r0, ip, r2, lr + mla r1, r2, r1, ip + mla r1, r3, lr, r1 + ldmia sp!, {pc} + + END diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch.asm b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch.asm new file mode 100644 index 0000000000..2e26160363 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch.asm @@ -0,0 +1,29 @@ +///------------------------------------------------------------------------------ +// +// Copyright (c) 2008-2009 Apple Inc. All rights reserved. +// +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +//------------------------------------------------------------------------------ + + + + EXPORT __ARM_switch8 + + AREA ArmSwitch, CODE, READONLY + +__ARM_switch8 + LDRB r12,[lr,#-1] + CMP r3,r12 + LDRBCC r3,[lr,r3] + LDRBCS r3,[lr,r12] + ADD r12,lr,r3,LSL #1 + BX r12 + + END diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch16.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch16.S new file mode 100644 index 0000000000..48e2ab74df --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch16.S @@ -0,0 +1,46 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2008-2009 Apple Inc. All rights reserved. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + +#/** @file +# Compiler intrinsic for ARM compiler +# +# Copyright (c) 2008, Apple, Inc. +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http)://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.; +# +#**/ +# + +.text +.p2align 2 + +.globl ASM_PFX(__switch16) + + +ASM_PFX(__switch16): + ldrh ip, [lr, #-1] + cmp r0, ip + add r0, lr, r0, lsl #1 + ldrccsh r0, [r0, #1] + add ip, lr, ip, lsl #1 + ldrcssh r0, [ip, #1] + add ip, lr, r0, lsl #1 + bx ip + + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch32.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch32.S new file mode 100644 index 0000000000..5ecffa6fee --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch32.S @@ -0,0 +1,45 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2008-2009 Apple Inc. All rights reserved. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + +#/** @file +# Compiler intrinsic for ARM compiler +# +# Copyright (c) 2008, Apple, Inc. +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http)://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.; +# +#**/ +# + +.text +.p2align 2 + +.globl ASM_PFX(__switch32) + + +ASM_PFX(__switch32): + ldr ip, [lr, #-1] + cmp r0, ip + add r0, lr, r0, lsl #2 + ldrcc r0, [r0, #3] + add ip, lr, ip, lsl #2 + ldrcs r0, [ip, #3] + add ip, lr, r0 + bx ip + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch8.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch8.S new file mode 100644 index 0000000000..947156ee57 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch8.S @@ -0,0 +1,43 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2008-2009 Apple Inc. All rights reserved. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + +#/** @file +# Compiler intrinsic for ARM compiler +# +# Copyright (c) 2008, Apple, Inc. +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http)://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.; +# +#**/ +# + +.text +.p2align 2 + +.globl ASM_PFX(__switch8) + + +ASM_PFX(__switch8): + ldrb ip, [lr, #-1] + cmp r0, ip + ldrccsb r0, [lr, r0] + ldrcssb r0, [lr, ip] + add ip, lr, r0, lsl #1 + bx ip + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switchu8.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switchu8.S new file mode 100644 index 0000000000..e49204fdd4 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switchu8.S @@ -0,0 +1,43 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2008-2009 Apple Inc. All rights reserved. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + +#/** @file +# Compiler intrinsic for ARM compiler +# +# Copyright (c) 2008, Apple, Inc. +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http)://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.; +# +#**/ +# + +.text +.p2align 2 + +.globl ASM_PFX(__switchu8) + + +ASM_PFX(__switchu8): + ldrb ip,[lr,#-1] + cmp r3,ip + ldrccb r3,[lr,r3] + ldrcsb r3,[lr,ip] + add ip,lr,r3,LSL #1 + bx ip + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ucmpdi2.c b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ucmpdi2.c new file mode 100644 index 0000000000..0cf1404b32 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ucmpdi2.c @@ -0,0 +1,82 @@ +/** @file + Compiler intrinsic for 64-bit compare, ported from LLVM code. + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +/** + University of Illinois/NCSA + Open Source License + + Copyright (c) 2003-2008 University of Illinois at Urbana-Champaign. + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. +**/ + + +#include "Llvm_int_lib.h" + + +// Returns: if (a < b) returns 0 +// if (a == b) returns 1 +// if (a > b) returns 2 + +UINT32 +__ucmpdi2(UINT64 a, UINT64 b) +{ + udwords x; + x.all = a; + udwords y; + y.all = b; + if (x.high < y.high) + return 0; + if (x.high > y.high) + return 2; + if (x.low < y.low) + return 0; + if (x.low > y.low) + return 2; + return 1; +} diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivdi3.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivdi3.S new file mode 100644 index 0000000000..fd7715da66 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivdi3.S @@ -0,0 +1,28 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2008-2009 Apple Inc. All rights reserved. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + + .text + .align 2 + .globl ___udivdi3 +___udivdi3: + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 1, uses_anonymous_args = 0 + stmfd sp!, {r7, lr} + add r7, sp, #0 + sub sp, sp, #8 + mov ip, #0 + str ip, [sp, #0] + bl ___udivmoddi4 + sub sp, r7, #0 + ldmfd sp!, {r7, pc} diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivdi3.c b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivdi3.c new file mode 100644 index 0000000000..1a04ea7dd1 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivdi3.c @@ -0,0 +1,71 @@ +/** @file + Compiler intrinsic for 64-bit unisigned div, ported from LLVM code. + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +/** + University of Illinois/NCSA + Open Source License + + Copyright (c) 2003-2008 University of Illinois at Urbana-Champaign. + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. +**/ + + +#include "Llvm_int_lib.h" + +UINT64 __udivmoddi4 (UINT64 a, UINT64 b, UINT64 *rem); + +// Returns: a / b + +UINT64 +__udivdi3(UINT64 a, UINT64 b) +{ + return __udivmoddi4(a, b, 0); +} + + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivmoddi4.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivmoddi4.S new file mode 100644 index 0000000000..1e54baec24 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivmoddi4.S @@ -0,0 +1,243 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2008-2009 Apple Inc. All rights reserved. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + + .text + .align 2 + .globl ___udivmoddi4 +___udivmoddi4: + @ args = 8, pretend = 0, frame = 16 + @ frame_needed = 1, uses_anonymous_args = 0 + stmfd sp!, {r4, r5, r6, r7, lr} + add r7, sp, #12 + stmfd sp!, {r10, r11} + sub sp, sp, #20 + stmia sp, {r2-r3} + ldr r6, [sp, #48] + orrs r2, r2, r3 + mov r10, r0 + mov r11, r1 + beq L2 + subs ip, r1, #0 + bne L4 + cmp r3, #0 + bne L6 + cmp r6, #0 + beq L8 + mov r1, r2 + bl ___umodsi3 + mov r1, #0 + stmia r6, {r0-r1} +L8: + ldr r1, [sp, #0] + mov r0, r10 + b L45 +L6: + cmp r6, #0 + movne r1, #0 + stmneia r6, {r0-r1} + b L2 +L4: + ldr r1, [sp, #0] + cmp r1, #0 + bne L12 + ldr r2, [sp, #4] + cmp r2, #0 + bne L14 + cmp r6, #0 + beq L16 + mov r1, r2 + mov r0, r11 + bl ___umodsi3 + mov r1, #0 + stmia r6, {r0-r1} +L16: + ldr r1, [sp, #4] + mov r0, r11 +L45: + bl ___udivsi3 +L46: + mov r10, r0 + mov r11, #0 + b L10 +L14: + subs r1, r0, #0 + bne L18 + cmp r6, #0 + beq L16 + ldr r1, [sp, #4] + mov r0, r11 + bl ___umodsi3 + mov r4, r10 + mov r5, r0 + stmia r6, {r4-r5} + b L16 +L18: + sub r3, r2, #1 + tst r2, r3 + bne L22 + cmp r6, #0 + movne r4, r0 + andne r5, ip, r3 + stmneia r6, {r4-r5} +L24: + rsb r3, r2, #0 + and r3, r2, r3 + clz r3, r3 + rsb r3, r3, #31 + mov r0, ip, lsr r3 + b L46 +L22: + clz r2, r2 + clz r3, ip + rsb r3, r3, r2 + cmp r3, #30 + bhi L48 + rsb r2, r3, #31 + add lr, r3, #1 + mov r3, r1, asl r2 + str r3, [sp, #12] + mov r3, r1, lsr lr + ldr r0, [sp, #0] + mov r5, ip, lsr lr + orr r4, r3, ip, asl r2 + str r0, [sp, #8] + b L29 +L12: + ldr r3, [sp, #4] + cmp r3, #0 + bne L30 + sub r3, r1, #1 + tst r1, r3 + bne L32 + cmp r6, #0 + andne r3, r3, r0 + movne r2, r3 + movne r3, #0 + stmneia r6, {r2-r3} +L34: + cmp r1, #1 + beq L10 + rsb r3, r1, #0 + and r3, r1, r3 + clz r3, r3 + rsb r0, r3, #31 + mov r1, ip, lsr r0 + rsb r3, r0, #32 + mov r0, r10, lsr r0 + orr ip, r0, ip, asl r3 + str r1, [sp, #12] + str ip, [sp, #8] + ldrd r10, [sp, #8] + b L10 +L32: + clz r2, r1 + clz r3, ip + rsb r3, r3, r2 + rsb r4, r3, #31 + mov r2, r0, asl r4 + mvn r1, r3 + and r2, r2, r1, asr #31 + add lr, r3, #33 + str r2, [sp, #8] + add r2, r3, #1 + mov r3, r3, asr #31 + and r0, r3, r0, asl r1 + mov r3, r10, lsr r2 + orr r3, r3, ip, asl r4 + and r3, r3, r1, asr #31 + orr r0, r0, r3 + mov r3, ip, lsr lr + str r0, [sp, #12] + mov r0, r10, lsr lr + and r5, r3, r2, asr #31 + rsb r3, lr, #31 + mov r3, r3, asr #31 + orr r0, r0, ip, asl r1 + and r3, r3, ip, lsr r2 + and r0, r0, r2, asr #31 + orr r4, r3, r0 + b L29 +L30: + clz r2, r3 + clz r3, ip + rsb r3, r3, r2 + cmp r3, #31 + bls L37 +L48: + cmp r6, #0 + stmneia r6, {r10-r11} + b L2 +L37: + rsb r1, r3, #31 + mov r0, r0, asl r1 + add lr, r3, #1 + mov r2, #0 + str r0, [sp, #12] + mov r0, r10, lsr lr + str r2, [sp, #8] + sub r2, r3, #31 + and r0, r0, r2, asr #31 + mov r3, ip, lsr lr + orr r4, r0, ip, asl r1 + and r5, r3, r2, asr #31 +L29: + mov ip, #0 + mov r10, ip + b L40 +L41: + ldr r1, [sp, #12] + ldr r2, [sp, #8] + mov r3, r4, lsr #31 + orr r5, r3, r5, asl #1 + mov r3, r1, lsr #31 + orr r4, r3, r4, asl #1 + mov r3, r2, lsr #31 + orr r0, r3, r1, asl #1 + orr r1, ip, r2, asl #1 + ldmia sp, {r2-r3} + str r0, [sp, #12] + subs r2, r2, r4 + sbc r3, r3, r5 + str r1, [sp, #8] + subs r0, r2, #1 + sbc r1, r3, #0 + mov r2, r1, asr #31 + ldmia sp, {r0-r1} + mov r3, r2 + and ip, r2, #1 + and r3, r3, r1 + and r2, r2, r0 + subs r4, r4, r2 + sbc r5, r5, r3 + add r10, r10, #1 +L40: + cmp r10, lr + bne L41 + ldrd r0, [sp, #8] + adds r0, r0, r0 + adc r1, r1, r1 + cmp r6, #0 + orr r10, r0, ip + mov r11, r1 + stmneia r6, {r4-r5} + b L10 +L2: + mov r10, #0 + mov r11, #0 +L10: + mov r0, r10 + mov r1, r11 + sub sp, r7, #20 + ldmfd sp!, {r10, r11} + ldmfd sp!, {r4, r5, r6, r7, pc} diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivmoddi4.c b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivmoddi4.c new file mode 100644 index 0000000000..58f7554cc3 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivmoddi4.c @@ -0,0 +1,287 @@ +/** @file + Compiler intrinsic for 64-bit compare, ported from LLVM code. + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +/** + University of Illinois/NCSA + Open Source License + + Copyright (c) 2003-2008 University of Illinois at Urbana-Champaign. + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. +**/ + + +#include "Llvm_int_lib.h" + +// Effects: if rem != 0, *rem = a % b +// Returns: a / b + +// Translated from Figure 3-40 of The PowerPC Compiler Writer's Guide + +UINT64 +__udivmoddi4 (UINT64 a, UINT64 b, UINT64* rem) +{ + const unsigned n_uword_bits = sizeof(UINT32) * CHAR_BIT; + const unsigned n_udword_bits = sizeof(UINT64) * CHAR_BIT; + udwords n; + n.all = a; + udwords d; + d.all = b; + udwords q; + udwords r; + unsigned sr; + + if (b == 0) { +// ASSERT (FALSE); + return 0; + } + + // special cases, X is unknown, K != 0 + if (n.high == 0) + { + if (d.high == 0) + { + // 0 X + // --- + // 0 X + if (rem) + *rem = n.low % d.low; + return n.low / d.low; + } + // 0 X + // --- + // K X + if (rem) + *rem = n.low; + return 0; + } + // n.high != 0 + if (d.low == 0) + { + if (d.high == 0) + { + // K X + // --- + // 0 0 + if (rem) + *rem = n.high % d.low; + return n.high / d.low; + } + // d.high != 0 + if (n.low == 0) + { + // K 0 + // --- + // K 0 + if (rem) + { + r.high = n.high % d.high; + r.low = 0; + *rem = r.all; + } + return n.high / d.high; + } + // K K + // --- + // K 0 + if ((d.high & (d.high - 1)) == 0) // if d is a power of 2 + { + if (rem) + { + r.low = n.low; + r.high = n.high & (d.high - 1); + *rem = r.all; + } + return n.high >> COUNT_TRAILING_ZEROS(d.high); + } + // K K + // --- + // K 0 + sr = COUNT_LEADING_ZEROS(d.high) - COUNT_LEADING_ZEROS(n.high); + // 0 <= sr <= n_uword_bits - 2 or sr large + if (sr > n_uword_bits - 2) + { + if (rem) + *rem = n.all; + return 0; + } + ++sr; + // 1 <= sr <= n_uword_bits - 1 + // q.all = n.all << (n_udword_bits - sr); + q.low = 0; + q.high = n.low << (n_uword_bits - sr); + // r.all = n.all >> sr; + r.high = n.high >> sr; + r.low = (n.high << (n_uword_bits - sr)) | (n.low >> sr); + } + else // d.low != 0 + { + if (d.high == 0) + { + // K X + // --- + // 0 K + if ((d.low & (d.low - 1)) == 0) // if d is a power of 2 + { + if (rem) + *rem = n.low & (d.low - 1); + if (d.low == 1) + return n.all; + unsigned sr = COUNT_TRAILING_ZEROS(d.low); + q.high = n.high >> sr; + q.low = (n.high << (n_uword_bits - sr)) | (n.low >> sr); + return q.all; + } + // K X + // --- + // 0 K + sr = 1 + n_uword_bits + COUNT_LEADING_ZEROS(d.low) - COUNT_LEADING_ZEROS(n.high); + // 2 <= sr <= n_udword_bits - 1 + // q.all = n.all << (n_udword_bits - sr); + // r.all = n.all >> sr; + // if (sr == n_uword_bits) + // { + // q.low = 0; + // q.high = n.low; + // r.high = 0; + // r.low = n.high; + // } + // else if (sr < n_uword_bits) // 2 <= sr <= n_uword_bits - 1 + // { + // q.low = 0; + // q.high = n.low << (n_uword_bits - sr); + // r.high = n.high >> sr; + // r.low = (n.high << (n_uword_bits - sr)) | (n.low >> sr); + // } + // else // n_uword_bits + 1 <= sr <= n_udword_bits - 1 + // { + // q.low = n.low << (n_udword_bits - sr); + // q.high = (n.high << (n_udword_bits - sr)) | + // (n.low >> (sr - n_uword_bits)); + // r.high = 0; + // r.low = n.high >> (sr - n_uword_bits); + // } + q.low = (n.low << (n_udword_bits - sr)) & + ((INT32)(n_uword_bits - sr) >> (n_uword_bits-1)); + q.high = ((n.low << ( n_uword_bits - sr)) & + ((INT32)(sr - n_uword_bits - 1) >> (n_uword_bits-1))) | + (((n.high << (n_udword_bits - sr)) | + (n.low >> (sr - n_uword_bits))) & + ((INT32)(n_uword_bits - sr) >> (n_uword_bits-1))); + r.high = (n.high >> sr) & + ((INT32)(sr - n_uword_bits) >> (n_uword_bits-1)); + r.low = ((n.high >> (sr - n_uword_bits)) & + ((INT32)(n_uword_bits - sr - 1) >> (n_uword_bits-1))) | + (((n.high << (n_uword_bits - sr)) | + (n.low >> sr)) & + ((INT32)(sr - n_uword_bits) >> (n_uword_bits-1))); + } + else + { + // K X + // --- + // K K + sr = COUNT_LEADING_ZEROS(d.high) - COUNT_LEADING_ZEROS(n.high); + // 0 <= sr <= n_uword_bits - 1 or sr large + if (sr > n_uword_bits - 1) + { + if (rem) + *rem = n.all; + return 0; + } + ++sr; + // 1 <= sr <= n_uword_bits + // q.all = n.all << (n_udword_bits - sr); + q.low = 0; + q.high = n.low << (n_uword_bits - sr); + // r.all = n.all >> sr; + // if (sr < n_uword_bits) + // { + // r.high = n.high >> sr; + // r.low = (n.high << (n_uword_bits - sr)) | (n.low >> sr); + // } + // else + // { + // r.high = 0; + // r.low = n.high; + // } + r.high = (n.high >> sr) & + ((INT32)(sr - n_uword_bits) >> (n_uword_bits-1)); + r.low = (n.high << (n_uword_bits - sr)) | + ((n.low >> sr) & + ((INT32)(sr - n_uword_bits) >> (n_uword_bits-1))); + } + } + // Not a special case + // q and r are initialized with: + // q.all = n.all << (n_udword_bits - sr); + // r.all = n.all >> sr; + // 1 <= sr <= n_udword_bits - 1 + UINT32 carry = 0; + for (; sr > 0; --sr) + { + // r:q = ((r:q) << 1) | carry + r.high = (r.high << 1) | (r.low >> (n_uword_bits - 1)); + r.low = (r.low << 1) | (q.high >> (n_uword_bits - 1)); + q.high = (q.high << 1) | (q.low >> (n_uword_bits - 1)); + q.low = (q.low << 1) | carry; + // carry = 0; + // if (r.all >= d.all) + // { + // r.all -= d.all; + // carry = 1; + // } + const INT64 s = (INT64)(d.all - r.all - 1) >> (n_udword_bits - 1); + carry = s & 1; + r.all -= d.all & s; + } + q.all = (q.all << 1) | carry; + if (rem) + *rem = r.all; + return q.all; +} diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivsi3.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivsi3.S new file mode 100644 index 0000000000..e5a0afa053 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivsi3.S @@ -0,0 +1,57 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2008-2009 Apple Inc. All rights reserved. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + + .text + .align 2 + .globl ___udivsi3 +___udivsi3: + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 1, uses_anonymous_args = 0 + cmp r1, #0 + cmpne r0, #0 + stmfd sp!, {r4, r5, r7, lr} + add r7, sp, #8 + beq L2 + clz r2, r1 + clz r3, r0 + rsb r3, r3, r2 + cmp r3, #31 + bhi L2 + ldmeqfd sp!, {r4, r5, r7, pc} + add r5, r3, #1 + rsb r3, r3, #31 + mov lr, #0 + mov r2, r0, asl r3 + mov ip, r0, lsr r5 + mov r4, lr + b L8 +L9: + mov r0, r2, lsr #31 + orr ip, r0, ip, asl #1 + orr r2, r3, lr + rsb r3, ip, r1 + sub r3, r3, #1 + and r0, r1, r3, asr #31 + mov lr, r3, lsr #31 + rsb ip, r0, ip + add r4, r4, #1 +L8: + cmp r4, r5 + mov r3, r2, asl #1 + bne L9 + orr r0, r3, lr + ldmfd sp!, {r4, r5, r7, pc} +L2: + mov r0, #0 + ldmfd sp!, {r4, r5, r7, pc} diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivsi3.c b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivsi3.c new file mode 100644 index 0000000000..59d5b23643 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivsi3.c @@ -0,0 +1,111 @@ +/** @file + Compiler intrinsic for 32-bit unsigned div, ported from LLVM code. + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +/** + University of Illinois/NCSA + Open Source License + + Copyright (c) 2003-2008 University of Illinois at Urbana-Champaign. + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. +**/ + + +#include "Llvm_int_lib.h" + + +// Returns: n / d + +// Translated from Figure 3-40 of The PowerPC Compiler Writer's Guide + +UINT32 +__udivsi3(UINT32 n, UINT32 d) +{ + const unsigned n_uword_bits = sizeof(UINT32) * CHAR_BIT; + UINT32 q; + UINT32 r; + unsigned sr; + + // special cases + if (d == 0) { +// ASSERT (FALSE); + return 0; // ?! + } + if (n == 0) + return 0; + + sr = COUNT_LEADING_ZEROS(d) - COUNT_LEADING_ZEROS(n); + // 0 <= sr <= n_uword_bits - 1 or sr large + if (sr > n_uword_bits - 1) // d > r + return 0; + if (sr == n_uword_bits - 1) // d == 1 + return n; + ++sr; + // 1 <= sr <= n_uword_bits - 1 + // Not a special case + q = n << (n_uword_bits - sr); + r = n >> sr; + UINT32 carry = 0; + for (; sr > 0; --sr) + { + // r:q = ((r:q) << 1) | carry + r = (r << 1) | (q >> (n_uword_bits - 1)); + q = (q << 1) | carry; + // carry = 0; + // if (r.all >= d.all) + // { + // r.all -= d.all; + // carry = 1; + // } + const INT32 s = (INT32)(d - r - 1) >> (n_uword_bits - 1); + carry = s & 1; + r -= d & s; + } + q = (q << 1) | carry; + return q; +} diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/uldiv.asm b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/uldiv.asm new file mode 100644 index 0000000000..a26ac762a4 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/uldiv.asm @@ -0,0 +1,268 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2008-2009 Apple Inc. All rights reserved. +// +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +//------------------------------------------------------------------------------ + + + + EXPORT __aeabi_uldivmod + + AREA Uldivmod, CODE, READONLY + +; +;UINT64 +;EFIAPI +;__aeabi_uldivmod ( +; IN UINT64 Dividend +; IN UINT64 Divisor +; ) +; +__aeabi_uldivmod + stmdb sp!, {r4, r5, r6, lr} + mov r4, r1 + mov r5, r0 + mov r6, #0 ; 0x0 + orrs ip, r3, r2, lsr #31 + bne __aeabi_uldivmod_label1 + tst r2, r2 + beq _ll_div0 + movs ip, r2, lsr #15 + addeq r6, r6, #16 ; 0x10 + mov ip, r2, lsl r6 + movs lr, ip, lsr #23 + moveq ip, ip, lsl #8 + addeq r6, r6, #8 ; 0x8 + movs lr, ip, lsr #27 + moveq ip, ip, lsl #4 + addeq r6, r6, #4 ; 0x4 + movs lr, ip, lsr #29 + moveq ip, ip, lsl #2 + addeq r6, r6, #2 ; 0x2 + movs lr, ip, lsr #30 + moveq ip, ip, lsl #1 + addeq r6, r6, #1 ; 0x1 + b _ll_udiv_small +__aeabi_uldivmod_label1 + tst r3, #-2147483648 ; 0x80000000 + bne __aeabi_uldivmod_label2 + movs ip, r3, lsr #15 + addeq r6, r6, #16 ; 0x10 + mov ip, r3, lsl r6 + movs lr, ip, lsr #23 + moveq ip, ip, lsl #8 + addeq r6, r6, #8 ; 0x8 + movs lr, ip, lsr #27 + moveq ip, ip, lsl #4 + addeq r6, r6, #4 ; 0x4 + movs lr, ip, lsr #29 + moveq ip, ip, lsl #2 + addeq r6, r6, #2 ; 0x2 + movs lr, ip, lsr #30 + addeq r6, r6, #1 ; 0x1 + rsb r3, r6, #32 ; 0x20 + moveq ip, ip, lsl #1 + orr ip, ip, r2, lsr r3 + mov lr, r2, lsl r6 + b _ll_udiv_big +__aeabi_uldivmod_label2 + mov ip, r3 + mov lr, r2 + b _ll_udiv_ginormous + +_ll_udiv_small + cmp r4, ip, lsl #1 + mov r3, #0 ; 0x0 + subcs r4, r4, ip, lsl #1 + addcs r3, r3, #2 ; 0x2 + cmp r4, ip + subcs r4, r4, ip + adcs r3, r3, #0 ; 0x0 + add r2, r6, #32 ; 0x20 + cmp r2, #32 ; 0x20 + rsb ip, ip, #0 ; 0x0 + bcc _ll_udiv_small_label1 + orrs r0, r4, r5, lsr #30 + moveq r4, r5 + moveq r5, #0 ; 0x0 + subeq r2, r2, #32 ; 0x20 +_ll_udiv_small_label1 + mov r1, #0 ; 0x0 + cmp r2, #16 ; 0x10 + bcc _ll_udiv_small_label2 + movs r0, r4, lsr #14 + moveq r4, r4, lsl #16 + addeq r1, r1, #16 ; 0x10 +_ll_udiv_small_label2 + sub lr, r2, r1 + cmp lr, #8 ; 0x8 + bcc _ll_udiv_small_label3 + movs r0, r4, lsr #22 + moveq r4, r4, lsl #8 + addeq r1, r1, #8 ; 0x8 +_ll_udiv_small_label3 + rsb r0, r1, #32 ; 0x20 + sub r2, r2, r1 + orr r4, r4, r5, lsr r0 + mov r5, r5, lsl r1 + cmp r2, #1 ; 0x1 + bcc _ll_udiv_small_label5 + sub r2, r2, #1 ; 0x1 + and r0, r2, #7 ; 0x7 + eor r0, r0, #7 ; 0x7 + adds r0, r0, r0, lsl #1 + add pc, pc, r0, lsl #2 + nop ; (mov r0,r0) +_ll_udiv_small_label4 + adcs r5, r5, r5 + adcs r4, ip, r4, lsl #1 + rsbcc r4, ip, r4 + adcs r5, r5, r5 + adcs r4, ip, r4, lsl #1 + rsbcc r4, ip, r4 + adcs r5, r5, r5 + adcs r4, ip, r4, lsl #1 + rsbcc r4, ip, r4 + adcs r5, r5, r5 + adcs r4, ip, r4, lsl #1 + rsbcc r4, ip, r4 + adcs r5, r5, r5 + adcs r4, ip, r4, lsl #1 + rsbcc r4, ip, r4 + adcs r5, r5, r5 + adcs r4, ip, r4, lsl #1 + rsbcc r4, ip, r4 + adcs r5, r5, r5 + adcs r4, ip, r4, lsl #1 + rsbcc r4, ip, r4 + adcs r5, r5, r5 + adcs r4, ip, r4, lsl #1 + sub r2, r2, #8 ; 0x8 + tst r2, r2 + rsbcc r4, ip, r4 + bpl _ll_udiv_small_label4 +_ll_udiv_small_label5 + mov r2, r4, lsr r6 + bic r4, r4, r2, lsl r6 + adcs r0, r5, r5 + adc r1, r4, r4 + add r1, r1, r3, lsl r6 + mov r3, #0 ; 0x0 + ldmia sp!, {r4, r5, r6, pc} + +_ll_udiv_big + subs r0, r5, lr + mov r3, #0 ; 0x0 + sbcs r1, r4, ip + movcs r5, r0 + movcs r4, r1 + adcs r3, r3, #0 ; 0x0 + subs r0, r5, lr + sbcs r1, r4, ip + movcs r5, r0 + movcs r4, r1 + adcs r3, r3, #0 ; 0x0 + subs r0, r5, lr + sbcs r1, r4, ip + movcs r5, r0 + movcs r4, r1 + adcs r3, r3, #0 ; 0x0 + mov r1, #0 ; 0x0 + rsbs lr, lr, #0 ; 0x0 + rsc ip, ip, #0 ; 0x0 + cmp r6, #16 ; 0x10 + bcc _ll_udiv_big_label1 + movs r0, r4, lsr #14 + moveq r4, r4, lsl #16 + addeq r1, r1, #16 ; 0x10 +_ll_udiv_big_label1 + sub r2, r6, r1 + cmp r2, #8 ; 0x8 + bcc _ll_udiv_big_label2 + movs r0, r4, lsr #22 + moveq r4, r4, lsl #8 + addeq r1, r1, #8 ; 0x8 +_ll_udiv_big_label2 + rsb r0, r1, #32 ; 0x20 + sub r2, r6, r1 + orr r4, r4, r5, lsr r0 + mov r5, r5, lsl r1 + cmp r2, #1 ; 0x1 + bcc _ll_udiv_big_label4 + sub r2, r2, #1 ; 0x1 + and r0, r2, #3 ; 0x3 + rsb r0, r0, #3 ; 0x3 + adds r0, r0, r0, lsl #1 + add pc, pc, r0, lsl #3 + nop ; (mov r0,r0) +_ll_udiv_big_label3 + adcs r5, r5, r5 + adcs r4, r4, r4 + adcs r0, lr, r5 + adcs r1, ip, r4 + movcs r5, r0 + movcs r4, r1 + adcs r5, r5, r5 + adcs r4, r4, r4 + adcs r0, lr, r5 + adcs r1, ip, r4 + movcs r5, r0 + movcs r4, r1 + adcs r5, r5, r5 + adcs r4, r4, r4 + adcs r0, lr, r5 + adcs r1, ip, r4 + movcs r5, r0 + movcs r4, r1 + sub r2, r2, #4 ; 0x4 + adcs r5, r5, r5 + adcs r4, r4, r4 + adcs r0, lr, r5 + adcs r1, ip, r4 + tst r2, r2 + movcs r5, r0 + movcs r4, r1 + bpl _ll_udiv_big_label3 +_ll_udiv_big_label4 + mov r1, #0 ; 0x0 + mov r2, r5, lsr r6 + bic r5, r5, r2, lsl r6 + adcs r0, r5, r5 + adc r1, r1, #0 ; 0x0 + movs lr, r3, lsl r6 + mov r3, r4, lsr r6 + bic r4, r4, r3, lsl r6 + adc r1, r1, #0 ; 0x0 + adds r0, r0, lr + orr r2, r2, r4, ror r6 + adc r1, r1, #0 ; 0x0 + ldmia sp!, {r4, r5, r6, pc} + +_ll_udiv_ginormous + subs r2, r5, lr + mov r1, #0 ; 0x0 + sbcs r3, r4, ip + adc r0, r1, r1 + movcc r2, r5 + movcc r3, r4 + ldmia sp!, {r4, r5, r6, pc} + +_ll_div0 + ldmia sp!, {r4, r5, r6, lr} + mov r0, #0 ; 0x0 + mov r1, #0 ; 0x0 + b __aeabi_ldiv0 + +__aeabi_ldiv0 + BX r14 + + END + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/umoddi3.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/umoddi3.S new file mode 100644 index 0000000000..6396036c04 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/umoddi3.S @@ -0,0 +1,30 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2008-2009 Apple Inc. All rights reserved. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + + .text + .align 2 + .globl ___umoddi3 +___umoddi3: + @ args = 0, pretend = 0, frame = 8 + @ frame_needed = 1, uses_anonymous_args = 0 + stmfd sp!, {r7, lr} + add r7, sp, #0 + sub sp, sp, #16 + add ip, sp, #8 + str ip, [sp, #0] + bl ___udivmoddi4 + ldrd r0, [sp, #8] + sub sp, r7, #0 + ldmfd sp!, {r7, pc} + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/umoddi3.c b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/umoddi3.c new file mode 100644 index 0000000000..73d796e499 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/umoddi3.c @@ -0,0 +1,72 @@ +/** @file + Compiler intrinsic for 64-bit unsigned mod, ported from LLVM code. + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +/** + University of Illinois/NCSA + Open Source License + + Copyright (c) 2003-2008 University of Illinois at Urbana-Champaign. + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. +**/ + + +#include "Llvm_int_lib.h" + +UINT64 __udivmoddi4(UINT64 a, UINT64 b, UINT64* rem); + +// Returns: a % b + +UINT64 +__umoddi3(UINT64 a, UINT64 b) +{ + UINT64 r; + __udivmoddi4(a, b, &r); + return r; +} + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/umodsi3.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/umodsi3.S new file mode 100644 index 0000000000..4cde76beb5 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/umodsi3.S @@ -0,0 +1,40 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2008-2009 Apple Inc. All rights reserved. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + + .text + .align 2 + .globl ___umodsi3 +___umodsi3: + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 1, uses_anonymous_args = 0 + stmfd sp!, {r4, r5, r7, lr} + add r7, sp, #8 + mov r5, r0 + mov r4, r1 + bl L___udivsi3$stub + mul r0, r4, r0 + rsb r0, r0, r5 + ldmfd sp!, {r4, r5, r7, pc} + .section __TEXT,__symbol_stub4,symbol_stubs,none,12 + .align 2 +L___udivsi3$stub: + .indirect_symbol ___udivsi3 + ldr ip, L___udivsi3$slp + ldr pc, [ip, #0] +L___udivsi3$slp: + .long L___udivsi3$lazy_ptr + .lazy_symbol_pointer +L___udivsi3$lazy_ptr: + .indirect_symbol ___udivsi3 + .long dyld_stub_binding_helper diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/umodsi3.c b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/umodsi3.c new file mode 100644 index 0000000000..09d4008e78 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/umodsi3.c @@ -0,0 +1,68 @@ +/** @file + Compiler intrinsic for 32-bit unsigned mod, ported from LLVM code. + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +/** + University of Illinois/NCSA + Open Source License + + Copyright (c) 2003-2008 University of Illinois at Urbana-Champaign. + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. +**/ + + +#include "Llvm_int_lib.h" + + +// Returns: a % b + +UINT32 +__umodsi3(UINT32 a, UINT32 b) +{ + return a - (a / b) * b; +} diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/uread.asm b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/uread.asm new file mode 100644 index 0000000000..1d3d192821 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/uread.asm @@ -0,0 +1,38 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2008-2009 Apple Inc. All rights reserved. +// +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +//------------------------------------------------------------------------------ + + + + EXPORT __aeabi_uread4 + + AREA Uread4, CODE, READONLY + +; +;UINT32 +;EFIAPI +;__aeabi_uread4 ( +; IN VOID *Pointer +; ); +; +__aeabi_uread4 + ldrb r2, [r0, #1] + ldrb r1, [r0] + ldrb r3, [r0, #2] + ldrb r0, [r0, #3] + orr r1, r1, r2, lsl #8 + orr r1, r1, r3, lsl #16 + orr r0, r1, r0, lsl #24 + bx lr + + END diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/uwrite.asm b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/uwrite.asm new file mode 100644 index 0000000000..d6a1e2fb00 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/uwrite.asm @@ -0,0 +1,40 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2008-2009 Apple Inc. All rights reserved. +// +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +//------------------------------------------------------------------------------ + + + EXPORT __aeabi_uwrite4 + + AREA Uwrite4, CODE, READONLY + +; +;UINT32 +;EFIAPI +;__aeabi_uwrite4 ( +; IN UINT32 Data, +; IN VOID *Pointer +; ); +; +; +__aeabi_uwrite4 + mov r2, r0, lsr #8 + strb r0, [r1] + strb r2, [r1, #1] + mov r2, r0, lsr #16 + strb r2, [r1, #2] + mov r2, r0, lsr #24 + strb r2, [r1, #3] + bx lr + + END + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf b/ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf new file mode 100644 index 0000000000..b1429737c7 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf @@ -0,0 +1,92 @@ +#%HEADER% +#/** @file +# Base Library implementation. +# +# Copyright (c) 2009, Apple, Inc. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = CompilerIntrinsicsLib + FILE_GUID = 855274FA-3575-4C20-9709-C031DC5589FA + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = CompilerIntrinsicsLib + + +[Sources.common] + + +[Sources.ARM] + Arm/mullu.asm | RVCT + Arm/switch.asm | RVCT + Arm/llsr.asm | RVCT + Arm/memcpy.asm | RVCT + Arm/memcpy4.asm | RVCT + Arm/uread.asm | RVCT + Arm/uwrite.asm | RVCT + Arm/lasr.asm | RVCT + Arm/llsl.asm | RVCT + Arm/div.asm | RVCT + Arm/uldiv.asm | RVCT + Arm/ldivmod.asm | RVCT + + +# +# Move .c to .s to work around LLVM issues +# +# Arm/ashrdi3.c | GCC +# Arm/ashldi3.c | GCC +# Arm/divdi3.c | GCC +# Arm/divsi3.c | GCC +# Arm/lshrdi3.c | GCC + Arm/ashrdi3.S | GCC + Arm/ashldi3.S | GCC + Arm/divdi3.S | GCC + Arm/divsi3.S | GCC + Arm/lshrdi3.S | GCC + + Arm/memcpy.S | GCC + Arm/memset.S | GCC + +# Arm/modsi3.c | GCC +# Arm/moddi3.c | GCC +# Arm/muldi3.c | GCC + Arm/modsi3.S | GCC + Arm/moddi3.S | GCC + Arm/muldi3.S | GCC + +# Arm/udivsi3.c | GCC +# Arm/umodsi3.c | GCC +# Arm/udivdi3.c | GCC +# Arm/umoddi3.c | GCC +# Arm/udivmoddi4.c | GCC + Arm/udivsi3.S | GCC + Arm/umodsi3.S | GCC + Arm/udivdi3.S | GCC + Arm/umoddi3.S | GCC + Arm/udivmoddi4.S | GCC + +# Arm/clzsi2.c | GCC +# Arm/ctzsi2.c | GCC +# Arm/ucmpdi2.c | GCC + Arm/switch8.S | GCC + Arm/switchu8.S | GCC + Arm/switch16.S | GCC + Arm/switch32.S | GCC + + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + diff --git a/ArmPkg/Library/SemiHostingDebugLib/DebugLib.c b/ArmPkg/Library/SemiHostingDebugLib/DebugLib.c new file mode 100644 index 0000000000..61e3aac3c2 --- /dev/null +++ b/ArmPkg/Library/SemiHostingDebugLib/DebugLib.c @@ -0,0 +1,258 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +/** @file + UEFI Debug Library that uses PrintLib to send messages to STDERR. + + Copyright (c) 2006 - 2007, Intel Corporation
+ All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include +#include +#include +#include +#include +#include +#include + +// +// Define the maximum debug and assert message length that this library supports +// +#define MAX_DEBUG_MESSAGE_LENGTH 0x100 + +/** + + Prints a debug message to the debug output device if the specified error level is enabled. + + If any bit in ErrorLevel is also set in PcdDebugPrintErrorLevel, then print + the message specified by Format and the associated variable argument list to + the debug output device. + + If Format is NULL, then ASSERT(). + + @param ErrorLevel The error level of the debug message. + @param Format Format string for the debug message to print. + +**/ +VOID +EFIAPI +DebugPrint ( + IN UINTN ErrorLevel, + IN CONST CHAR8 *Format, + ... + ) +{ + CHAR8 AsciiBuffer[MAX_DEBUG_MESSAGE_LENGTH]; + VA_LIST Marker; + + // + // If Format is NULL, then ASSERT(). + // + ASSERT (Format != NULL); + + // + // Check driver debug mask value and global mask + // + if ((ErrorLevel & PcdGet32(PcdDebugPrintErrorLevel)) == 0) { + return; + } + + // + // Convert the DEBUG() message to a Unicode String + // + VA_START (Marker, Format); + AsciiVSPrint (AsciiBuffer, sizeof (AsciiBuffer), Format, Marker); + VA_END (Marker); + + SemihostWriteString (AsciiBuffer); +} + + +/** + + Prints an assert message containing a filename, line number, and description. + This may be followed by a breakpoint or a dead loop. + + Print a message of the form "ASSERT (): \n" + to the debug output device. If DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED bit of + PcdDebugProperyMask is set then CpuBreakpoint() is called. Otherwise, if + DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED bit of PcdDebugProperyMask is set then + CpuDeadLoop() is called. If neither of these bits are set, then this function + returns immediately after the message is printed to the debug output device. + DebugAssert() must actively prevent recusrsion. If DebugAssert() is called while + processing another DebugAssert(), then DebugAssert() must return immediately. + + If FileName is NULL, then a string of "(NULL) Filename" is printed. + + If Description is NULL, then a string of "(NULL) Description" is printed. + + @param FileName Pointer to the name of the source file that generated the assert condition. + @param LineNumber The line number in the source file that generated the assert condition + @param Description Pointer to the description of the assert condition. + +**/ +VOID +EFIAPI +DebugAssert ( + IN CONST CHAR8 *FileName, + IN UINTN LineNumber, + IN CONST CHAR8 *Description + ) +{ + CHAR8 AsciiBuffer[MAX_DEBUG_MESSAGE_LENGTH]; + + // + // Generate the ASSERT() message in Unicode format + // + AsciiSPrint (AsciiBuffer, sizeof (AsciiBuffer), "ASSERT %a(%d): %a\n", FileName, LineNumber, Description); + + SemihostWriteString (AsciiBuffer); + + // + // Generate a Breakpoint, DeadLoop, or NOP based on PCD settings + // + if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED) != 0) { + CpuBreakpoint (); + } else if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED) != 0) { + CpuDeadLoop (); + } +} + + +/** + + Fills a target buffer with PcdDebugClearMemoryValue, and returns the target buffer. + + This function fills Length bytes of Buffer with the value specified by + PcdDebugClearMemoryValue, and returns Buffer. + + If Buffer is NULL, then ASSERT(). + + If Length is greater than (MAX_ADDRESS ? Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to fill with PcdDebugClearMemoryValue. + @param Length Number of bytes in Buffer to fill with zeros PcdDebugClearMemoryValue. + + @return Buffer + +**/ +VOID * +EFIAPI +DebugClearMemory ( + OUT VOID *Buffer, + IN UINTN Length + ) +{ + // + // If Buffer is NULL, then ASSERT(). + // + ASSERT (Buffer != NULL); + + // + // SetMem() checks for the the ASSERT() condition on Length and returns Buffer + // + return SetMem (Buffer, Length, PcdGet8(PcdDebugClearMemoryValue)); +} + + +/** + + Returns TRUE if ASSERT() macros are enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugAssertEnabled ( + VOID + ) +{ + return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED) != 0); +} + + +/** + + Returns TRUE if DEBUG()macros are enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugPrintEnabled ( + VOID + ) +{ + return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_PRINT_ENABLED) != 0); +} + + +/** + + Returns TRUE if DEBUG_CODE()macros are enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugCodeEnabled ( + VOID + ) +{ + return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_CODE_ENABLED) != 0); +} + + +/** + + Returns TRUE if DEBUG_CLEAR_MEMORY()macro is enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_CLEAR_MEMORY_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugClearMemoryEnabled ( + VOID + ) +{ + return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED) != 0); +} diff --git a/ArmPkg/Library/SemiHostingDebugLib/SemiHostingDebugLib.inf b/ArmPkg/Library/SemiHostingDebugLib/SemiHostingDebugLib.inf new file mode 100644 index 0000000000..683f03f2f3 --- /dev/null +++ b/ArmPkg/Library/SemiHostingDebugLib/SemiHostingDebugLib.inf @@ -0,0 +1,46 @@ +#%HEADER% +#/** @file +# Debug Library for UEFI drivers +# +# Library to abstract Framework extensions that conflict with UEFI 2.0 Specification +# Copyright (c) 2007, Intel Corporation. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SemiHostingDebugLib + FILE_GUID = 2A8D3FC4-8DB1-4D27-A3F3-780AF03CF848 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = DebugLib|BASE SEC DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER + + +[Sources.common] + DebugLib.c + + +[Packages] + MdePkg/MdePkg.dec + ArmPkg/ArmPkg.dec + +[LibraryClasses] + BaseMemoryLib + BaseLib + PcdLib + PrintLib + SemihostLib + +[Pcd.common] + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel + gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask + diff --git a/ArmPkg/Library/SemiHostingSerialPortLib/SemiHostingSerialPortLib.inf b/ArmPkg/Library/SemiHostingSerialPortLib/SemiHostingSerialPortLib.inf new file mode 100644 index 0000000000..c0a540342a --- /dev/null +++ b/ArmPkg/Library/SemiHostingSerialPortLib/SemiHostingSerialPortLib.inf @@ -0,0 +1,35 @@ +#%HEADER% +#/** @file +# Semihosting serail port lib +# +# Copyright (c) 2008, Apple Inc. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SemiHostingSerialPortLib + FILE_GUID = E9FB2D1E-05D9-421C-8C35-6100BB0093B7 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = SerialPortLib + + +[Sources.common] + SerialPortLib.c + + +[Packages] + MdePkg/MdePkg.dec + ArmPkg/ArmPkg.dec + +[LibraryClasses] + SemihostLib diff --git a/ArmPkg/Library/SemiHostingSerialPortLib/SerialPortLib.c b/ArmPkg/Library/SemiHostingSerialPortLib/SerialPortLib.c new file mode 100644 index 0000000000..df43f31413 --- /dev/null +++ b/ArmPkg/Library/SemiHostingSerialPortLib/SerialPortLib.c @@ -0,0 +1,144 @@ +/** @file + Serial I/O Port library functions with no library constructor/destructor + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include + + +/* + + Programmed hardware of Serial port. + + @return Always return EFI_UNSUPPORTED. + +**/ +RETURN_STATUS +EFIAPI +SerialPortInitialize ( + VOID + ) +{ + if (SemihostConnectionSupported ()) { + return RETURN_SUCCESS; + } else { + return RETURN_UNSUPPORTED; + } +} + +/** + Write data to serial device. + + @param Buffer Point of data buffer which need to be writed. + @param NumberOfBytes Number of output bytes which are cached in Buffer. + + @retval 0 Write data failed. + @retval !0 Actual number of bytes writed to serial device. + +**/ + +#define PRINT_BUFFER_SIZE 512 +#define PRINT_BUFFER_THRESHOLD (PRINT_BUFFER_SIZE - 4) + +UINTN +EFIAPI +SerialPortWrite ( + IN UINT8 *Buffer, + IN UINTN NumberOfBytes +) +{ + UINT8 PrintBuffer[PRINT_BUFFER_SIZE]; + UINTN SourceIndex = 0; + UINTN DestinationIndex = 0; + UINT8 CurrentCharacter; + + while (SourceIndex < NumberOfBytes) + { + CurrentCharacter = Buffer[SourceIndex++]; + + switch (CurrentCharacter) + { + case '\r': + continue; + + case '\n': + PrintBuffer[DestinationIndex++] = ' '; + // fall through + + default: + PrintBuffer[DestinationIndex++] = CurrentCharacter; + break; + } + + if (DestinationIndex > PRINT_BUFFER_THRESHOLD) + { + PrintBuffer[DestinationIndex] = '\0'; + SemihostWriteString ((CHAR8 *) PrintBuffer); + + DestinationIndex = 0; + } + } + + if (DestinationIndex > 0) + { + PrintBuffer[DestinationIndex] = '\0'; + SemihostWriteString ((CHAR8 *) PrintBuffer); + } + + return 0; +} + + +/** + Read data from serial device and save the datas in buffer. + + @param Buffer Point of data buffer which need to be writed. + @param NumberOfBytes Number of output bytes which are cached in Buffer. + + @retval 0 Read data failed. + @retval !0 Aactual number of bytes read from serial device. + +**/ +UINTN +EFIAPI +SerialPortRead ( + OUT UINT8 *Buffer, + IN UINTN NumberOfBytes +) +{ + *Buffer = SemihostReadCharacter (); + return 1; +} + + + +/** + Check to see if any data is avaiable to be read from the debug device. + + @retval TRUE At least one byte of data is avaiable to be read + @retval FALS No data is avaiable to be read + +**/ +BOOLEAN +EFIAPI +SerialPortPoll ( + VOID + ) +{ + // Since SemiHosting read character is blocking always say we have a char ready? + return SemihostConnectionSupported (); +} + diff --git a/ArmPkg/Library/SemihostLib/Arm/SemihostLib.c b/ArmPkg/Library/SemihostLib/Arm/SemihostLib.c new file mode 100644 index 0000000000..e1a515ef21 --- /dev/null +++ b/ArmPkg/Library/SemihostLib/Arm/SemihostLib.c @@ -0,0 +1,221 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +#include + +#include +#include + +#include "SemihostPrivate.h" + +BOOLEAN +SemihostConnectionSupported ( + VOID + ) +{ + return SEMIHOST_SUPPORTED; +} + +EFI_STATUS +SemihostFileOpen ( + IN CHAR8 *FileName, + IN UINT32 Mode, + OUT UINT32 *FileHandle + ) +{ + SEMIHOST_FILE_OPEN_BLOCK OpenBlock; + INT32 Result; + + if (FileHandle == NULL) + return EFI_INVALID_PARAMETER; + + OpenBlock.FileName = FileName; + OpenBlock.Mode = Mode; + OpenBlock.NameLength = AsciiStrLen(FileName); + + Result = Semihost_SYS_OPEN(&OpenBlock); + + if (Result == -1) + { + return EFI_NOT_FOUND; + } + else + { + *FileHandle = Result; + return EFI_SUCCESS; + } +} + +EFI_STATUS +SemihostFileSeek ( + IN UINT32 FileHandle, + IN UINT32 Offset + ) +{ + SEMIHOST_FILE_SEEK_BLOCK SeekBlock; + INT32 Result; + + SeekBlock.Handle = FileHandle; + SeekBlock.Location = Offset; + + Result = Semihost_SYS_SEEK(&SeekBlock); + + if (Result == 0) + return EFI_SUCCESS; + else + return EFI_ABORTED; +} + +EFI_STATUS +SemihostFileRead ( + IN UINT32 FileHandle, + IN OUT UINT32 *Length, + OUT VOID *Buffer + ) +{ + SEMIHOST_FILE_READ_WRITE_BLOCK ReadBlock; + UINT32 Result; + + if ((Length == NULL) || (Buffer == NULL)) + return EFI_INVALID_PARAMETER; + + ReadBlock.Handle = FileHandle; + ReadBlock.Buffer = Buffer; + ReadBlock.Length = *Length; + + Result = Semihost_SYS_READ(&ReadBlock); + + if (Result == *Length) + { + return EFI_ABORTED; + } + else + { + *Length -= Result; + return EFI_SUCCESS; + } +} + +EFI_STATUS +SemihostFileWrite ( + IN UINT32 FileHandle, + IN OUT UINT32 *Length, + IN VOID *Buffer + ) +{ + SEMIHOST_FILE_READ_WRITE_BLOCK WriteBlock; + + if ((Length == NULL) || (Buffer == NULL)) + return EFI_INVALID_PARAMETER; + + WriteBlock.Handle = FileHandle; + WriteBlock.Buffer = Buffer; + WriteBlock.Length = *Length; + + *Length = Semihost_SYS_WRITE(&WriteBlock); + + return EFI_SUCCESS; +} + +EFI_STATUS +SemihostFileClose ( + IN UINT32 FileHandle + ) +{ + INT32 Result = Semihost_SYS_CLOSE(&FileHandle); + + if (Result == -1) + return EFI_INVALID_PARAMETER; + else + return EFI_SUCCESS; +} + +EFI_STATUS +SemihostFileLength ( + IN UINT32 FileHandle, + OUT UINT32 *Length + ) +{ + INT32 Result; + + if (Length == NULL) + return EFI_INVALID_PARAMETER; + + Result = Semihost_SYS_FLEN(&FileHandle); + + if (Result == -1) + { + return EFI_ABORTED; + } + else + { + *Length = Result; + return EFI_SUCCESS; + } +} + +EFI_STATUS +SemihostFileRemove ( + IN CHAR8 *FileName + ) +{ + SEMIHOST_FILE_REMOVE_BLOCK RemoveBlock; + UINT32 Result; + + RemoveBlock.FileName = FileName; + RemoveBlock.NameLength = AsciiStrLen(FileName); + + Result = Semihost_SYS_REMOVE(&RemoveBlock); + + if (Result == 0) + return EFI_SUCCESS; + else + return EFI_ABORTED; +} + +CHAR8 +SemihostReadCharacter ( + VOID + ) +{ + return Semihost_SYS_READC(); +} + +VOID +SemihostWriteCharacter ( + IN CHAR8 Character + ) +{ + Semihost_SYS_WRITEC(&Character); +} + +VOID +SemihostWriteString ( + IN CHAR8 *String + ) +{ + Semihost_SYS_WRITE0(String); +} + +UINT32 +SemihostSystem ( + IN CHAR8 *CommandLine + ) +{ + SEMIHOST_SYSTEM_BLOCK SystemBlock; + + SystemBlock.CommandLine = CommandLine; + SystemBlock.CommandLength = AsciiStrLen(CommandLine); + + return Semihost_SYS_SYSTEM(&SystemBlock); +} diff --git a/ArmPkg/Library/SemihostLib/Arm/SemihostPrivate.h b/ArmPkg/Library/SemihostLib/Arm/SemihostPrivate.h new file mode 100644 index 0000000000..e82111430a --- /dev/null +++ b/ArmPkg/Library/SemihostLib/Arm/SemihostPrivate.h @@ -0,0 +1,162 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __SEMIHOST_PRIVATE_H__ +#define __SEMIHOST_PRIVATE_H__ + +typedef struct { + CHAR8 *FileName; + UINT32 Mode; + UINT32 NameLength; +} SEMIHOST_FILE_OPEN_BLOCK; + +typedef struct { + UINT32 Handle; + VOID *Buffer; + UINT32 Length; +} SEMIHOST_FILE_READ_WRITE_BLOCK; + +typedef struct { + UINT32 Handle; + UINT32 Location; +} SEMIHOST_FILE_SEEK_BLOCK; + +typedef struct { + CHAR8 *FileName; + UINT32 NameLength; +} SEMIHOST_FILE_REMOVE_BLOCK; + +typedef struct { + CHAR8 *CommandLine; + UINT32 CommandLength; +} SEMIHOST_SYSTEM_BLOCK; + +#ifdef __CC_ARM + +#if defined(__thumb__) +#define SWI 0xAB +#else +#define SWI 0x123456 +#endif + +#define SEMIHOST_SUPPORTED TRUE + +__swi(SWI) +INT32 +_Semihost_SYS_OPEN( + IN UINTN SWI_0x01, + IN SEMIHOST_FILE_OPEN_BLOCK *OpenBlock + ); + +__swi(SWI) +INT32 +_Semihost_SYS_CLOSE( + IN UINTN SWI_0x02, + IN UINT32 *Handle + ); + +__swi(SWI) +VOID +_Semihost_SYS_WRITEC( + IN UINTN SWI_0x03, + IN CHAR8 *Character + ); + +__swi(SWI) +VOID +_Semihost_SYS_WRITE0( + IN UINTN SWI_0x04, + IN CHAR8 *String + ); + +__swi(SWI) +UINT32 +_Semihost_SYS_WRITE( + IN UINTN SWI_0x05, + IN OUT SEMIHOST_FILE_READ_WRITE_BLOCK *WriteBlock + ); + +__swi(SWI) +UINT32 +_Semihost_SYS_READ( + IN UINTN SWI_0x06, + IN OUT SEMIHOST_FILE_READ_WRITE_BLOCK *ReadBlock + ); + +__swi(SWI) +CHAR8 +_Semihost_SYS_READC( + IN UINTN SWI_0x07, + IN UINTN Zero + ); + +__swi(SWI) +INT32 +_Semihost_SYS_SEEK( + IN UINTN SWI_0x0A, + IN SEMIHOST_FILE_SEEK_BLOCK *SeekBlock + ); + +__swi(SWI) +INT32 +_Semihost_SYS_FLEN( + IN UINTN SWI_0x0C, + IN UINT32 *Handle + ); + +__swi(SWI) +UINT32 +_Semihost_SYS_REMOVE( + IN UINTN SWI_0x0E, + IN SEMIHOST_FILE_REMOVE_BLOCK *RemoveBlock + ); + +__swi(SWI) +UINT32 +_Semihost_SYS_SYSTEM( + IN UINTN SWI_0x12, + IN SEMIHOST_SYSTEM_BLOCK *SystemBlock + ); + +#define Semihost_SYS_OPEN(OpenBlock) _Semihost_SYS_OPEN(0x01, OpenBlock) +#define Semihost_SYS_CLOSE(Handle) _Semihost_SYS_CLOSE(0x02, Handle) +#define Semihost_SYS_WRITE0(String) _Semihost_SYS_WRITE0(0x04, String) +#define Semihost_SYS_WRITEC(Character) _Semihost_SYS_WRITEC(0x03, Character) +#define Semihost_SYS_WRITE(WriteBlock) _Semihost_SYS_WRITE(0x05, WriteBlock) +#define Semihost_SYS_READ(ReadBlock) _Semihost_SYS_READ(0x06, ReadBlock) +#define Semihost_SYS_READC() _Semihost_SYS_READC(0x07, 0) +#define Semihost_SYS_SEEK(SeekBlock) _Semihost_SYS_SEEK(0x0A, SeekBlock) +#define Semihost_SYS_FLEN(Handle) _Semihost_SYS_FLEN(0x0C, Handle) +#define Semihost_SYS_REMOVE(RemoveBlock) _Semihost_SYS_REMOVE(0x0E, RemoveBlock) +#define Semihost_SYS_SYSTEM(SystemBlock) _Semihost_SYS_SYSTEM(0x12, SystemBlock) + +#else // __CC_ARM + +#define SEMIHOST_SUPPORTED FALSE + +#define Semihost_SYS_OPEN(OpenBlock) (-1) +#define Semihost_SYS_CLOSE(Handle) (-1) +#define Semihost_SYS_WRITE0(String) +#define Semihost_SYS_WRITEC(Character) +#define Semihost_SYS_WRITE(WriteBlock) (0) +#define Semihost_SYS_READ(ReadBlock) ((ReadBlock)->Length) +#define Semihost_SYS_READC() ('x') +#define Semihost_SYS_SEEK(SeekBlock) (-1) +#define Semihost_SYS_FLEN(Handle) (-1) +#define Semihost_SYS_REMOVE(RemoveBlock) (-1) +#define Semihost_SYS_SYSTEM(SystemBlock) (-1) + +#endif // __CC_ARM + +#endif //__SEMIHOST_PRIVATE_H__ diff --git a/ArmPkg/Library/SemihostLib/SemihostLib.inf b/ArmPkg/Library/SemihostLib/SemihostLib.inf new file mode 100644 index 0000000000..cb278083c0 --- /dev/null +++ b/ArmPkg/Library/SemihostLib/SemihostLib.inf @@ -0,0 +1,32 @@ +#%HEADER% +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SemihostLib + FILE_GUID = C40D08BA-DB7B-4F07-905A-C5FE4B5AF987 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = SemihostLib + + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = ARM +# +[Sources.ARM] + Arm/SemihostLib.c + + +[Packages] + MdePkg/MdePkg.dec + ArmPkg/ArmPkg.dec + +[LibraryClasses] + BaseLib + +[Protocols] + +[Guids] + +[Pcd] + \ No newline at end of file diff --git a/ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.c b/ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.c new file mode 100644 index 0000000000..060ba6bf98 --- /dev/null +++ b/ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.c @@ -0,0 +1,626 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include +#include +#include + +EFI_PHYSICAL_ADDRESS +ConvertToPhysicalAddress ( + IN VOID *VirtualAddress + ) +{ + UINTN UncachedMemoryMask = (UINTN)PcdGet64(PcdArmUncachedMemoryMask); + UINTN PhysicalAddress; + + PhysicalAddress = (UINTN)VirtualAddress & ~UncachedMemoryMask; + + return (EFI_PHYSICAL_ADDRESS)PhysicalAddress; +} + +VOID * +ConvertToCachedAddress ( + IN VOID *Address + ) +{ + return (VOID *)(UINTN)ConvertToPhysicalAddress(Address); +} + +VOID * +ConvertToUncachedAddress ( + IN VOID *Address + ) +{ + UINTN UncachedMemoryMask = (UINTN)PcdGet64(PcdArmUncachedMemoryMask); + UINTN UncachedAddress; + + UncachedAddress = (UINTN)Address | UncachedMemoryMask; + + return (VOID *)UncachedAddress; +} + +VOID +FlushCache ( + IN EFI_PHYSICAL_ADDRESS Address, + IN UINTN Size + ) +{ + EFI_CPU_ARCH_PROTOCOL *Cpu; + EFI_STATUS Status; + + Status = gBS->LocateProtocol(&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu); + ASSERT_EFI_ERROR(Status); + + Status = Cpu->FlushDataCache(Cpu, Address, Size, EfiCpuFlushTypeWriteBackInvalidate); + ASSERT_EFI_ERROR(Status); +} + +VOID * +UncachedInternalAllocatePages ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS Memory; + + if (Pages == 0) { + return NULL; + } + + Status = gBS->AllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory); + if (EFI_ERROR (Status)) { + Memory = 0; + } + + if (Memory != 0) { + FlushCache(Memory, EFI_PAGES_TO_SIZE(Pages)); + Memory = (EFI_PHYSICAL_ADDRESS)(UINTN)ConvertToUncachedAddress((VOID *)(UINTN)Memory); + } + + return (VOID *) (UINTN) Memory; +} + +VOID * +EFIAPI +UncachedAllocatePages ( + IN UINTN Pages + ) +{ + return UncachedInternalAllocatePages (EfiBootServicesData, Pages); +} + +VOID * +EFIAPI +UncachedAllocateRuntimePages ( + IN UINTN Pages + ) +{ + return UncachedInternalAllocatePages (EfiRuntimeServicesData, Pages); +} + +VOID * +EFIAPI +UncachedAllocateReservedPages ( + IN UINTN Pages + ) +{ + return UncachedInternalAllocatePages (EfiReservedMemoryType, Pages); +} + +VOID +EFIAPI +UncachedFreePages ( + IN VOID *Buffer, + IN UINTN Pages + ) +{ + EFI_STATUS Status; + + ASSERT (Pages != 0); + + Buffer = ConvertToCachedAddress(Buffer); + + Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages); + ASSERT_EFI_ERROR (Status); +} + +VOID * +UncachedInternalAllocateAlignedPages ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN UINTN Alignment + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS Memory; + UINTN AlignedMemory; + UINTN AlignmentMask; + UINTN UnalignedPages; + UINTN RealPages; + + // + // Alignment must be a power of two or zero. + // + ASSERT ((Alignment & (Alignment - 1)) == 0); + + if (Pages == 0) { + return NULL; + } + if (Alignment > EFI_PAGE_SIZE) { + // + // Caculate the total number of pages since alignment is larger than page size. + // + AlignmentMask = Alignment - 1; + RealPages = Pages + EFI_SIZE_TO_PAGES (Alignment); + // + // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow. + // + ASSERT (RealPages > Pages); + + Status = gBS->AllocatePages (AllocateAnyPages, MemoryType, RealPages, &Memory); + if (EFI_ERROR (Status)) { + return NULL; + } + AlignedMemory = ((UINTN) Memory + AlignmentMask) & ~AlignmentMask; + UnalignedPages = EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN) Memory); + if (UnalignedPages > 0) { + // + // Free first unaligned page(s). + // + Status = gBS->FreePages (Memory, UnalignedPages); + ASSERT_EFI_ERROR (Status); + } + Memory = (EFI_PHYSICAL_ADDRESS) (AlignedMemory + EFI_PAGES_TO_SIZE (Pages)); + UnalignedPages = RealPages - Pages - UnalignedPages; + if (UnalignedPages > 0) { + // + // Free last unaligned page(s). + // + Status = gBS->FreePages (Memory, UnalignedPages); + ASSERT_EFI_ERROR (Status); + } + } else { + // + // Do not over-allocate pages in this case. + // + Status = gBS->AllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory); + if (EFI_ERROR (Status)) { + return NULL; + } + AlignedMemory = (UINTN) Memory; + } + + if (AlignedMemory != 0) { + FlushCache(AlignedMemory, EFI_PAGES_TO_SIZE(Pages)); + AlignedMemory = (UINTN)ConvertToUncachedAddress((VOID *)AlignedMemory); + } + + return (VOID *) AlignedMemory; +} + +VOID * +EFIAPI +UncachedAllocateAlignedPages ( + IN UINTN Pages, + IN UINTN Alignment + ) +{ + return UncachedInternalAllocateAlignedPages (EfiBootServicesData, Pages, Alignment); +} + +VOID * +EFIAPI +UncachedAllocateAlignedRuntimePages ( + IN UINTN Pages, + IN UINTN Alignment + ) +{ + return UncachedInternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment); +} + +VOID * +EFIAPI +UncachedAllocateAlignedReservedPages ( + IN UINTN Pages, + IN UINTN Alignment + ) +{ + return UncachedInternalAllocateAlignedPages (EfiReservedMemoryType, Pages, Alignment); +} + +VOID +EFIAPI +UncachedFreeAlignedPages ( + IN VOID *Buffer, + IN UINTN Pages + ) +{ + EFI_STATUS Status; + + ASSERT (Pages != 0); + + Buffer = ConvertToCachedAddress(Buffer); + + Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages); + ASSERT_EFI_ERROR (Status); +} + +VOID * +UncachedInternalAllocateAlignedPool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN AllocationSize, + IN UINTN Alignment + ) +{ + VOID *RawAddress; + UINTN AlignedAddress; + UINTN AlignmentMask; + UINTN OverAllocationSize; + UINTN RealAllocationSize; + VOID **FreePointer; + UINTN DataCacheLineLength; + EFI_STATUS Status; + + // + // Alignment must be a power of two or zero. + // + ASSERT ((Alignment & (Alignment - 1)) == 0); + + DataCacheLineLength = ArmDataCacheLineLength(); + + // Alignment must be at least cache-line aligned + if (Alignment < DataCacheLineLength) { + Alignment = DataCacheLineLength; + } + + if (Alignment == 0) { + AlignmentMask = Alignment; + } else { + AlignmentMask = Alignment - 1; + } + + // + // Calculate the extra memory size, over-allocate memory pool and get the aligned memory address. + // + OverAllocationSize = sizeof (RawAddress) + AlignmentMask; + RealAllocationSize = AllocationSize + OverAllocationSize; + // + // Make sure that AllocationSize plus OverAllocationSize does not overflow. + // + ASSERT (RealAllocationSize > AllocationSize); + + Status = gBS->AllocatePool (PoolType, RealAllocationSize, &RawAddress); + if (EFI_ERROR (Status)) { + return NULL; + } + + AlignedAddress = ((UINTN) RawAddress + OverAllocationSize) & ~AlignmentMask; + // + // Save the original memory address just before the aligned address. + // + FreePointer = (VOID **)(AlignedAddress - sizeof (RawAddress)); + *FreePointer = RawAddress; + + if (AlignedAddress != 0) { + FlushCache(AlignedAddress, AllocationSize); + AlignedAddress = (UINTN)ConvertToUncachedAddress((VOID *)AlignedAddress); + } + + return (VOID *) AlignedAddress; +} + +VOID * +EFIAPI +UncachedAllocateAlignedPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ) +{ + return UncachedInternalAllocateAlignedPool (EfiBootServicesData, AllocationSize, Alignment); +} + +VOID * +EFIAPI +UncachedAllocateAlignedRuntimePool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ) +{ + return UncachedInternalAllocateAlignedPool (EfiRuntimeServicesData, AllocationSize, Alignment); +} + +VOID * +EFIAPI +UncachedAllocateAlignedReservedPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ) +{ + return UncachedInternalAllocateAlignedPool (EfiReservedMemoryType, AllocationSize, Alignment); +} + +VOID * +UncachedInternalAllocateAlignedZeroPool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN AllocationSize, + IN UINTN Alignment + ) +{ + VOID *Memory; + Memory = UncachedInternalAllocateAlignedPool (PoolType, AllocationSize, Alignment); + if (Memory != NULL) { + Memory = ZeroMem (Memory, AllocationSize); + } + return Memory; +} + +VOID * +EFIAPI +UncachedAllocateAlignedZeroPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ) +{ + return UncachedInternalAllocateAlignedZeroPool (EfiBootServicesData, AllocationSize, Alignment); +} + +VOID * +EFIAPI +UncachedAllocateAlignedRuntimeZeroPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ) +{ + return UncachedInternalAllocateAlignedZeroPool (EfiRuntimeServicesData, AllocationSize, Alignment); +} + +VOID * +EFIAPI +UncachedAllocateAlignedReservedZeroPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ) +{ + return UncachedInternalAllocateAlignedZeroPool (EfiReservedMemoryType, AllocationSize, Alignment); +} + +VOID * +UncachedInternalAllocateAlignedCopyPool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN AllocationSize, + IN CONST VOID *Buffer, + IN UINTN Alignment + ) +{ + VOID *Memory; + + ASSERT (Buffer != NULL); + ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN) Buffer + 1)); + + Memory = UncachedInternalAllocateAlignedPool (PoolType, AllocationSize, Alignment); + if (Memory != NULL) { + Memory = CopyMem (Memory, Buffer, AllocationSize); + } + return Memory; +} + +VOID * +EFIAPI +UncachedAllocateAlignedCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer, + IN UINTN Alignment + ) +{ + return UncachedInternalAllocateAlignedCopyPool (EfiBootServicesData, AllocationSize, Buffer, Alignment); +} + +VOID * +EFIAPI +UncachedAllocateAlignedRuntimeCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer, + IN UINTN Alignment + ) +{ + return UncachedInternalAllocateAlignedCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer, Alignment); +} + +VOID * +EFIAPI +UncachedAllocateAlignedReservedCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer, + IN UINTN Alignment + ) +{ + return UncachedInternalAllocateAlignedCopyPool (EfiReservedMemoryType, AllocationSize, Buffer, Alignment); +} + +VOID +EFIAPI +UncachedFreeAlignedPool ( + IN VOID *Buffer + ) +{ + VOID *RawAddress; + VOID **FreePointer; + EFI_STATUS Status; + + Buffer = ConvertToCachedAddress(Buffer); + + // + // Get the pre-saved original address in the over-allocate pool. + // + FreePointer = (VOID **)((UINTN) Buffer - sizeof (RawAddress)); + RawAddress = *FreePointer; + + Status = gBS->FreePool (RawAddress); + ASSERT_EFI_ERROR (Status); +} + +VOID * +UncachedInternalAllocatePool ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN AllocationSize + ) +{ + UINTN CacheLineLength = ArmDataCacheLineLength(); + return UncachedInternalAllocateAlignedPool(MemoryType, AllocationSize, CacheLineLength); +} + +VOID * +EFIAPI +UncachedAllocatePool ( + IN UINTN AllocationSize + ) +{ + return UncachedInternalAllocatePool (EfiBootServicesData, AllocationSize); +} + +VOID * +EFIAPI +UncachedAllocateRuntimePool ( + IN UINTN AllocationSize + ) +{ + return UncachedInternalAllocatePool (EfiRuntimeServicesData, AllocationSize); +} + +VOID * +EFIAPI +UncachedAllocateReservedPool ( + IN UINTN AllocationSize + ) +{ + return UncachedInternalAllocatePool (EfiReservedMemoryType, AllocationSize); +} + +VOID * +UncachedInternalAllocateZeroPool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN AllocationSize + ) +{ + VOID *Memory; + + Memory = UncachedInternalAllocatePool (PoolType, AllocationSize); + if (Memory != NULL) { + Memory = ZeroMem (Memory, AllocationSize); + } + return Memory; +} + +VOID * +EFIAPI +UncachedAllocateZeroPool ( + IN UINTN AllocationSize + ) +{ + return UncachedInternalAllocateZeroPool (EfiBootServicesData, AllocationSize); +} + +VOID * +EFIAPI +UncachedAllocateRuntimeZeroPool ( + IN UINTN AllocationSize + ) +{ + return UncachedInternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize); +} + +VOID * +EFIAPI +UncachedAllocateReservedZeroPool ( + IN UINTN AllocationSize + ) +{ + return UncachedInternalAllocateZeroPool (EfiReservedMemoryType, AllocationSize); +} + +VOID * +UncachedInternalAllocateCopyPool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + VOID *Memory; + + ASSERT (Buffer != NULL); + ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN) Buffer + 1)); + + Memory = UncachedInternalAllocatePool (PoolType, AllocationSize); + if (Memory != NULL) { + Memory = CopyMem (Memory, Buffer, AllocationSize); + } + return Memory; +} + +VOID * +EFIAPI +UncachedAllocateCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + return UncachedInternalAllocateCopyPool (EfiBootServicesData, AllocationSize, Buffer); +} + +VOID * +EFIAPI +UncachedAllocateRuntimeCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + return UncachedInternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer); +} + +VOID * +EFIAPI +UncachedAllocateReservedCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + return UncachedInternalAllocateCopyPool (EfiReservedMemoryType, AllocationSize, Buffer); +} + +VOID +EFIAPI +UncachedFreePool ( + IN VOID *Buffer + ) +{ + UncachedFreeAlignedPool(Buffer); +} + +VOID +EFIAPI +UncachedSafeFreePool ( + IN VOID *Buffer + ) +{ + if (Buffer != NULL) { + UncachedFreePool (Buffer); + Buffer = NULL; + } +} + diff --git a/ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.inf b/ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.inf new file mode 100644 index 0000000000..1a62eb4231 --- /dev/null +++ b/ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.inf @@ -0,0 +1,25 @@ +#%HEADER% +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = UncachedMemoryAllocationLib + FILE_GUID = DC101A1A-7525-429B-84AF-EEAA630E576C + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = UncachedMemoryAllocationLib + +[Sources.common] + UncachedMemoryAllocationLib.c + +[Packages] + ArmPkg/ArmPkg.dec + MdePkg/MdePkg.dec + +[Protocols] + gEfiCpuArchProtocolGuid + +[LibraryClasses] + ArmLib + +[FixedPcd] + gArmTokenSpaceGuid.PcdArmUncachedMemoryMask + \ No newline at end of file diff --git a/BeagleBoardPkg/AppleBeagleBoardPkg.dsc b/BeagleBoardPkg/AppleBeagleBoardPkg.dsc new file mode 100644 index 0000000000..251e8d563e --- /dev/null +++ b/BeagleBoardPkg/AppleBeagleBoardPkg.dsc @@ -0,0 +1,366 @@ +#/** @file +# Beagle board package. +# +# Copyright (c) 2009, Apple Inc. All rights reserved. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/ + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + PLATFORM_NAME = AppleBeagleBoardPkg + PLATFORM_GUID = 1C1D4FD7-703A-4DD5-A97B-FB794921859E + PLATFORM_VERSION = 0.1 + DSC_SPECIFICATION = 0x00010005 + OUTPUT_DIRECTORY = Build/AppleBeagleBoard + SUPPORTED_ARCHITECTURES = ARM + BUILD_TARGETS = DEBUG|RELEASE + SKUID_IDENTIFIER = DEFAULT + FLASH_DEFINITION = BeagleBoardPkg/AppleBeagleBoardPkg.fdf + + +[LibraryClasses.common] + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf + + + ArmLib|ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexArmLib.inf + + BaseLib|MdePkg/Library/BaseLib/BaseLib.inf + BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf + + BeagleBoardSystemLib|BeagleBoardPkg/Library/BeagleBoardSystemLib/BeagleBoardSystemLib.inf + EfiResetSystemLib|BeagleBoardPkg/Library/ResetSystemLib/ResetSystemLib.inf + + PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf + PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf + + EblCmdLib|BeagleBoardPkg/Library/EblCmdLib/EblCmdLib.inf + + EfiFileLib|EmbeddedPkg/Library/EfiFileLib/EfiFileLib.inf + + + PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf + PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf + PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf + CacheMaintenanceLib|ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.inf + PrePiLib|EmbeddedPkg/Library/PrePiLib/PrePiLib.inf + + SerialPortLib|BeagleBoardPkg/Library/SerialPortLib/SerialPortLib.inf + SemihostLib|ArmPkg/Library/SemihostLib/SemihostLib.inf + + RealTimeClockLib|EmbeddedPkg/Library/TemplateRealTimeClockLib/TemplateRealTimeClockLib.inf + + IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf + + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + UefiLib|MdePkg/Library/UefiLib/UefiLib.inf + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf + UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf + + DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf + UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf + UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf + +# +# Assume everything is fixed at build +# + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + + UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf + + UsbLib|AppleCommonPkg/Library/AppleUsbLib/AppleUsbDxeLib.inf + EblAddExternalCommandLib|EmbeddedPkg/Library/EblAddExternalCommandLib/EblAddExternalCommandLib.inf + + UncachedMemoryAllocationLib|ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.inf + + TimerLib|BeagleBoardPkg/Library/BeagleBoardTimerLib/BeagleBoardTimerLib.inf + OmapLib|BeagleBoardPkg/Library/OmapLib/OmapLib.inf + EblNetworkLib|EmbeddedPkg/Library/EblNetworkLib/EblNetworkLib.inf + + GdbSerialLib|BeagleBoardPkg/Library/GdbSerialLib/GdbSerialLib.inf + SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf + +[LibraryClasses.common.SEC] + ArmLib|ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexArmLibPrePi.inf + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf + UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf + ExtractGuidedSectionLib|EmbeddedPkg/Library/PrePiExtractGuidedSectionLib/PrePiExtractGuidedSectionLib.inf + LzmaDecompressLib|IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf + +[LibraryClasses.common.PEI_CORE] + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf + +[LibraryClasses.common.DXE_CORE] + HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf + MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf + DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf + ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf + UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf + DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf + +[LibraryClasses.common.DXE_DRIVER] + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf + DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf + + +[LibraryClasses.common.UEFI_APPLICATION] + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf + UefiDecompressLib|IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf + +[LibraryClasses.common.UEFI_DRIVER] + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf + UefiDecompressLib|IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf + ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf + +[LibraryClasses.common.DXE_RUNTIME_DRIVER] + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf + CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf + +[BuildOptions] + XCODE:*_*_ARM_ARCHCC_FLAGS == -arch armv6 -march=armv6 + XCODE:*_*_ARM_ARCHASM_FLAGS == -arch armv6 + XCODE:*_*_ARM_ARCHDLINK_FLAGS == -arch armv6 + + RVCT:*_*_ARM_ARCHCC_FLAGS == --cpu Cortex-A8 + RVCT:*_*_ARM_ARCHASM_FLAGS == --cpu Cortex-A8 + + +################################################################################ +# +# Pcd Section - list of all EDK II PCD Entries defined by this Platform +# +################################################################################ + +[PcdsFeatureFlag.common] + gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable|TRUE + gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnosticsDisable|TRUE + gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable|TRUE + gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable|TRUE + + # + # Control what commands are supported from the UI + # Turn these on and off to add features or save size + # + gEmbeddedTokenSpaceGuid.PcdEmbeddedMacBoot|TRUE + gEmbeddedTokenSpaceGuid.PcdEmbeddedDirCmd|TRUE + gEmbeddedTokenSpaceGuid.PcdEmbeddedHobCmd|TRUE + gEmbeddedTokenSpaceGuid.PcdEmbeddedHwDebugCmd|TRUE + gEmbeddedTokenSpaceGuid.PcdEmbeddedPciDebugCmd|TRUE + gEmbeddedTokenSpaceGuid.PcdEmbeddedIoEnable|FALSE + gEmbeddedTokenSpaceGuid.PcdEmbeddedScriptCmd|FALSE + + gEmbeddedTokenSpaceGuid.PcdCacheEnable|TRUE + + gEmbeddedTokenSpaceGuid.PcdPrePiProduceMemoryTypeInformationHob|TRUE + gArmTokenSpaceGuid.PcdCpuDxeProduceDebugSupport|FALSE + + # + # Beagle board Specific PCDs + # + +[PcdsFixedAtBuild.common] + gEmbeddedTokenSpaceGuid.PcdEmbeddedPrompt|"AppleEFI" + gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize|32 + gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize|0 + gEfiMdePkgTokenSpaceGuid.PcdMaximumUnicodeStringLength|1000000 + gEfiMdePkgTokenSpaceGuid.PcdMaximumAsciiStringLength|1000000 + gEfiMdePkgTokenSpaceGuid.PcdMaximumLinkedListLength|1000000 + gEfiMdePkgTokenSpaceGuid.PcdSpinLockTimeout|10000000 + gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue|0xAF + gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask|0 + gEfiMdePkgTokenSpaceGuid.PcdPostCodePropertyMask|0 + gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|320 + + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2f + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000004 + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x07 + + gEmbeddedTokenSpaceGuid.PcdEmbeddedAutomaticBootCommand|"" + gEmbeddedTokenSpaceGuid.PcdEmbeddedDefaultTextColor|0x07 + gEmbeddedTokenSpaceGuid.PcdEmbeddedMemVariableStoreSize|0x10000 + + gEmbeddedTokenSpaceGuid.PcdPrePiTempMemorySize|0 + gEmbeddedTokenSpaceGuid.PcdPrePiBfvBaseAddress|0 + gEmbeddedTokenSpaceGuid.PcdPrePiBfvSize|0 + gEmbeddedTokenSpaceGuid.PcdFlashFvMainBase|0 + gEmbeddedTokenSpaceGuid.PcdFlashFvMainSize|0 + +# +# Optional feature to help prevent EFI memory map fragments +# Turned on and off via: PcdPrePiProduceMemoryTypeInformationHob +# Values are in EFI Pages (4K). DXE Core will make sure that +# at least this much of each type of memory can be allocated +# from a single memory range. This way you only end up with +# maximum of two fragements for each type in the memory map +# (the memory used, and the free memory that was prereserved +# but not used). +# + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIReclaimMemory|0 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIMemoryNVS|0 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType|0 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData|80 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode|40 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesCode|400 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesData|3000 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderCode|10 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderData|0 + + +# +# Beagle board Specific PCDs +# + gEmbeddedTokenSpaceGuid.PcdPrePiHobBase|0x80001000 + gEmbeddedTokenSpaceGuid.PcdPrePiStackBase|0x87FE0000 # stack at top of memory + gEmbeddedTokenSpaceGuid.PcdPrePiStackSize|0x20000 # 128K stack + gBeagleBoardTokenSpaceGuid.PcdBeagleBoardIRAMFullSize|0x00000000 + gArmTokenSpaceGuid.PcdCpuVectorBaseAddress|0x80000000 + gArmTokenSpaceGuid.PcdCpuResetAddress|0x80008000 + + gBeagleBoardTokenSpaceGuid.PcdBeagleGpmcOffset|0x6E000000 + gBeagleBoardTokenSpaceGuid.PcdBeagleMMCHS1Base|0x4809C000 + + # Console + gBeagleBoardTokenSpaceGuid.PcdBeagleConsoleUart|3 + + # Timers +# gBeagleBoardTokenSpaceGuid.PcdBeagleArchTimer|OMAP3530_GPTIMER3 + gBeagleBoardTokenSpaceGuid.PcdBeagleArchTimer|3 +# gBeagleBoardTokenSpaceGuid.PcdBeagleFreeTimer|OMAP3530_GPTIMER4 + gBeagleBoardTokenSpaceGuid.PcdBeagleFreeTimer|4 + gEmbeddedTokenSpaceGuid.PcdTimerPeriod|100000 + gEmbeddedTokenSpaceGuid.PcdEmbeddedFdPerformanceCounterPeriodInNanoseconds|77 + gEmbeddedTokenSpaceGuid.PcdEmbeddedFdPerformanceCounterFrequencyInHz|13000000 + + # + # ARM Pcds + # + gArmTokenSpaceGuid.PcdArmUncachedMemoryMask|0x0000000040000000 + +################################################################################ +# +# Components Section - list of all EDK II Modules needed by this Platform +# +################################################################################ +[Components.common] + +# +# SEC +# + BeagleBoardPkg/Sec/Sec.inf + +# +# DXE +# + MdeModulePkg/Core/Dxe/DxeMain.inf { + + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + NULL|MdeModulePkg/Library/DxeCrc32GuidedSectionExtractLib/DxeCrc32GuidedSectionExtractLib.inf + NULL|IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf + } + + ArmPkg/Drivers/CpuDxe/CpuDxe.inf + + MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf + MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf + MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf + MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf + MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf + EmbeddedPkg/EmbeddedMonotonicCounter/EmbeddedMonotonicCounter.inf + EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOutSerial.inf + + EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf + EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf + EmbeddedPkg/TemplateMetronomeDxe/TemplateMetronomeDxe.inf + + # + # Semi-hosting filesystem + # + ArmPkg/Filesystem/SemihostFs/SemihostFs.inf + + # + # FAT filesystem + GPT/MBR partitioning + # + MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf + MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf + EnhancedFat/FatDxe/FatDxe.inf + MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf + + # + # USB + # + BeagleBoardPkg/PciEmulation/PciEmulation.inf + AppleCommonPkg/Bus/Pci/EhciDxe/Ehci.inf + AppleCommonPkg/Bus/Usb/UsbBotDxe/UsbBot.inf + AppleCommonPkg/Bus/Usb/UsbCbiDxe/Cbi0/UsbCbi0.inf + AppleCommonPkg/Bus/Usb/UsbCbiDxe/Cbi1/UsbCbi1.inf + AppleCommonPkg/Bus/Usb/UsbBusDxe/UsbBus.inf + AppleCommonPkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorage.inf + + #NOTE: Open source EHCI stack doesn't work on Beagleboard. + #NOTE: UsbBus and UsbMassStorage don't work using iPhond SDK tool chain. + #MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf + #MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf + #MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf + + # + # Nand Flash + # + BeagleBoardPkg/Flash/Flash.inf + + # + # MMC/SD + # + BeagleBoardPkg/MMCHSDxe/MMCHS.inf + + # + # I2C + # + BeagleBoardPkg/SmbusDxe/Smbus.inf + + # + # SoC Drivers + # + BeagleBoardPkg/Gpio/Gpio.inf + BeagleBoardPkg/InterruptDxe/InterruptDxe.inf + BeagleBoardPkg/TimerDxe/TimerDxe.inf + + # + # Power IC + # + BeagleBoardPkg/TPS65950Dxe/TPS65950.inf + + # + # Application + # + EmbeddedPkg/Ebl/Ebl.inf + + # + # Bds + # + BeagleBoardPkg/Bds/Bds.inf + + # + # Gdb Stub + # + EmbeddedPkg/GdbStub/GdbStub.inf + ArmPkg/Drivers/DebugSupportDxe/DebugSupportDxe.inf + diff --git a/BeagleBoardPkg/AppleBeagleBoardPkg.fdf b/BeagleBoardPkg/AppleBeagleBoardPkg.fdf new file mode 100644 index 0000000000..9852dfdd3f --- /dev/null +++ b/BeagleBoardPkg/AppleBeagleBoardPkg.fdf @@ -0,0 +1,303 @@ +# FLASH layout file for Beagle board. +# +# Copyright (c) 2009, Apple Inc. All rights reserved. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# + +################################################################################ +# +# FD Section +# The [FD] Section is made up of the definition statements and a +# description of what goes into the Flash Device Image. Each FD section +# defines one flash "device" image. A flash device image may be one of +# the following: Removable media bootable image (like a boot floppy +# image,) an Option ROM image (that would be "flashed" into an add-in +# card,) a System "Flash" image (that would be burned into a system's +# flash) or an Update ("Capsule") image that will be used to update and +# existing system flash. +# +################################################################################ + + +[FD.BeagleBoard_EFI] +BaseAddress = 0x80008000|gEmbeddedTokenSpaceGuid.PcdEmbeddedFdBaseAddress #The base address of the FLASH Device. +Size = 0x00080000|gEmbeddedTokenSpaceGuid.PcdEmbeddedFdSize #The size in bytes of the FLASH Device +ErasePolarity = 1 +BlockSize = 0x40 +NumBlocks = 0x2000 + +################################################################################ +# +# Following are lists of FD Region layout which correspond to the locations of different +# images within the flash device. +# +# Regions must be defined in ascending order and may not overlap. +# +# A Layout Region start with a eight digit hex offset (leading "0x" required) followed by +# the pipe "|" character, followed by the size of the region, also in hex with the leading +# "0x" characters. Like: +# Offset|Size +# PcdOffsetCName|PcdSizeCName +# RegionType +# +################################################################################ + +# 512 bytes of configuration header & 8 bytes of image header +0x00000000|0x00000208 + +0x00000208|0x0007FDF8 +gEmbeddedTokenSpaceGuid.PcdFlashFvMainBase|gEmbeddedTokenSpaceGuid.PcdFlashFvMainSize +FV = FVMAIN_COMPACT + +################################################################################ +# +# FV Section +# +# [FV] section is used to define what components or modules are placed within a flash +# device file. This section also defines order the components and modules are positioned +# within the image. The [FV] section consists of define statements, set statements and +# module statements. +# +################################################################################ + +[FV.FvMain] +BlockSize = 0x40 +NumBlocks = 0x9000 +FvAlignment = 8 #FV alignment and FV attributes setting. +ERASE_POLARITY = 1 +MEMORY_MAPPED = TRUE +STICKY_WRITE = TRUE +LOCK_CAP = TRUE +LOCK_STATUS = TRUE +WRITE_DISABLED_CAP = TRUE +WRITE_ENABLED_CAP = TRUE +WRITE_STATUS = TRUE +WRITE_LOCK_CAP = TRUE +WRITE_LOCK_STATUS = TRUE +READ_DISABLED_CAP = TRUE +READ_ENABLED_CAP = TRUE +READ_STATUS = TRUE +READ_LOCK_CAP = TRUE +READ_LOCK_STATUS = TRUE + + # + # PI DXE Drivers producing Architectural Protocols (EFI Services) + # + INF ArmPkg/Drivers/CpuDxe/CpuDxe.inf + + INF MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf + INF MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf + INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf + INF MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf + INF MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf + INF EmbeddedPkg/EmbeddedMonotonicCounter/EmbeddedMonotonicCounter.inf + + INF EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOutSerial.inf + + INF EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf + INF EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf + INF EmbeddedPkg/TemplateMetronomeDxe/TemplateMetronomeDxe.inf + + # + # Semi-hosting filesystem + # + INF ArmPkg/Filesystem/SemihostFs/SemihostFs.inf + + # + # Nand Flash + # + INF BeagleBoardPkg/Flash/Flash.inf + + # + # MMC/SD + # + INF BeagleBoardPkg/MMCHSDxe/MMCHS.inf + + # + # I2C + # + INF BeagleBoardPkg/SmbusDxe/Smbus.inf + + # + # SoC Drivers + # + INF BeagleBoardPkg/Gpio/Gpio.inf + INF BeagleBoardPkg/InterruptDxe/InterruptDxe.inf + INF BeagleBoardPkg/TimerDxe/TimerDxe.inf + + # + # Power IC + # + INF BeagleBoardPkg/TPS65950Dxe/TPS65950.inf + + # + # FAT filesystem + GPT/MBR partitioning + # + INF MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf + INF MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf + INF EnhancedFat/FatDxe/FatDxe.inf + INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf + + # + # USB Support + # + + INF BeagleBoardPkg/PciEmulation/PciEmulation.inf + INF AppleCommonPkg/Bus/Pci/EhciDxe/Ehci.inf + INF AppleCommonPkg/Bus/Usb/UsbBotDxe/UsbBot.inf + INF AppleCommonPkg/Bus/Usb/UsbCbiDxe/Cbi0/UsbCbi0.inf + INF AppleCommonPkg/Bus/Usb/UsbCbiDxe/Cbi1/UsbCbi1.inf + INF AppleCommonPkg/Bus/Usb/UsbBusDxe/UsbBus.inf + INF AppleCommonPkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorage.inf + + + #NOTE: Open source EHCI stack doesn't work on Beagleboard. + #NOTE: UsbBus and UsbMassStorage don't work using iPhond SDK tool chain. + #INF MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf + #INF MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf + #INF MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf + + # + # UEFI application (Shell Embedded Boot Loader) + # + INF EmbeddedPkg/Ebl/Ebl.inf + + + # + # Bds + # + INF BeagleBoardPkg/Bds/Bds.inf + + # + # Gdb Stub + # + #INF ArmPkg/Drivers/DebugSupportDxe/DebugSupportDxe.inf + #INF ApplePkg/Universal/GdbStub/GdbStub.inf + + +[FV.FVMAIN_COMPACT] +FvAlignment = 8 +ERASE_POLARITY = 1 +MEMORY_MAPPED = TRUE +STICKY_WRITE = TRUE +LOCK_CAP = TRUE +LOCK_STATUS = TRUE +WRITE_DISABLED_CAP = TRUE +WRITE_ENABLED_CAP = TRUE +WRITE_STATUS = TRUE +WRITE_LOCK_CAP = TRUE +WRITE_LOCK_STATUS = TRUE +READ_DISABLED_CAP = TRUE +READ_ENABLED_CAP = TRUE +READ_STATUS = TRUE +READ_LOCK_CAP = TRUE +READ_LOCK_STATUS = TRUE + + INF BeagleBoardPkg/Sec/Sec.inf + INF MdeModulePkg/Core/Dxe/DxeMain.inf + + FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 { + SECTION GUIDED EE4E5898-3914-4259-9D6E-DC7BD79403CF PROCESSING_REQUIRED = TRUE { + SECTION FV_IMAGE = FVMAIN + } + } + + +################################################################################ +# +# Rules are use with the [FV] section's module INF type to define +# how an FFS file is created for a given INF file. The following Rule are the default +# rules for the different module type. User can add the customized rules to define the +# content of the FFS file. +# +################################################################################ + + +############################################################################ +# Example of a DXE_DRIVER FFS file with a Checksum encapsulation section # +############################################################################ +# +#[Rule.Common.DXE_DRIVER] +# FILE DRIVER = $(NAMED_GUID) { +# DXE_DEPEX DXE_DEPEX Optional |.depex +# COMPRESS PI_STD { +# GUIDED { +# PE32 PE32 |.efi +# UI STRING="$(MODULE_NAME)" Optional +# VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) +# } +# } +# } +# +############################################################################ + +[Rule.Common.SEC] + FILE SEC = $(NAMED_GUID) RELOCS_STRIPPED { + TE TE Align = 8 |.efi + } + +[Rule.Common.PEI_CORE] + FILE PEI_CORE = $(NAMED_GUID) { + TE TE |.efi + UI STRING ="$(MODULE_NAME)" Optional + } + +[Rule.Common.PEIM] + FILE PEIM = $(NAMED_GUID) { + PEI_DEPEX PEI_DEPEX Optional |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + } + +[Rule.Common.PEIM.TIANOCOMPRESSED] + FILE PEIM = $(NAMED_GUID) DEBUG_MYTOOLS_IA32 { + PEI_DEPEX PEI_DEPEX Optional |.depex + GUIDED A31280AD-481E-41B6-95E8-127F4C984779 PROCESSING_REQUIRED = TRUE { + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + } + } + +[Rule.Common.DXE_CORE] + FILE DXE_CORE = $(NAMED_GUID) { + GUIDED EE4E5898-3914-4259-9D6E-DC7BD79403CF PROCESSING_REQUIRED = TRUE { + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + } + } + + +[Rule.Common.UEFI_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + } + +[Rule.Common.DXE_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + } + +[Rule.Common.DXE_RUNTIME_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + } + + +[Rule.Common.UEFI_APPLICATION] + FILE APPLICATION = $(NAMED_GUID) { + UI STRING ="$(MODULE_NAME)" Optional + PE32 PE32 |.efi + } diff --git a/BeagleBoardPkg/Bds/Bds.inf b/BeagleBoardPkg/Bds/Bds.inf new file mode 100644 index 0000000000..18e019147b --- /dev/null +++ b/BeagleBoardPkg/Bds/Bds.inf @@ -0,0 +1,70 @@ +#%HEADER% +#/** @file +# +# Component discription file for Bds module +# +# Copyright (c) 2009 Apple, Inc. All rights reserved. +# +# This document is the property of Apple, Inc. +# It is considered confidential and proprietary. +# +# This document may not be reproduced or transmitted in any form, +# in whole or in part, without the express written permission of +# Apple, Inc. +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BeagleBoardBds + FILE_GUID = 934431fe-5745-402e-913d-17b4434eb0f3 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = BdsInitialize + +[Sources.common] + BdsEntry.c + FirmwareVolume.c + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + +[LibraryClasses] + DevicePathLib + BaseLib + HobLib + UefiRuntimeServicesTableLib + ReportStatusCodeLib + PerformanceLib + DxeServicesTableLib + MemoryAllocationLib + UefiLib + UefiBootServicesTableLib + BaseMemoryLib + DebugLib + PrintLib + UefiDriverEntryPoint + +[Guids] + + +[Protocols] + gEfiBdsArchProtocolGuid + gEfiSimpleTextInProtocolGuid + gEfiSimpleTextOutProtocolGuid + gEfiSerialIoProtocolGuid + gEfiDevicePathProtocolGuid + gEfiSimpleFileSystemProtocolGuid + gEfiUsbIoProtocolGuid + gEfiFirmwareVolume2ProtocolGuid + + +[FeaturePcd] + +[FixedPcd] + gEmbeddedTokenSpaceGuid.PcdPrePiStackSize + +[Depex] + TRUE diff --git a/BeagleBoardPkg/Bds/BdsEntry.c b/BeagleBoardPkg/Bds/BdsEntry.c new file mode 100644 index 0000000000..05afd190dd --- /dev/null +++ b/BeagleBoardPkg/Bds/BdsEntry.c @@ -0,0 +1,240 @@ +/** @file + The entry of the embedded BDS. This BDS does not follow the Boot Manager requirements + of the UEFI specification as it is designed to implement an embedded systmes + propriatary boot scheme. + + This template assume a DXE driver produces a SerialIo protocol not using the EFI + driver module and it will attempt to connect a console on top of this. + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "BdsEntry.h" + + +BOOLEAN gConsolePresent = FALSE; + + +EFI_HANDLE mBdsImageHandle = NULL; +EFI_BDS_ARCH_PROTOCOL gBdsProtocol = { + BdsEntry, +}; + + + + +/** + This function uses policy data from the platform to determine what operating + system or system utility should be loaded and invoked. This function call + also optionally make the use of user input to determine the operating system + or system utility to be loaded and invoked. When the DXE Core has dispatched + all the drivers on the dispatch queue, this function is called. This + function will attempt to connect the boot devices required to load and invoke + the selected operating system or system utility. During this process, + additional firmware volumes may be discovered that may contain addition DXE + drivers that can be dispatched by the DXE Core. If a boot device cannot be + fully connected, this function calls the DXE Service Dispatch() to allow the + DXE drivers from any newly discovered firmware volumes to be dispatched. + Then the boot device connection can be attempted again. If the same boot + device connection operation fails twice in a row, then that boot device has + failed, and should be skipped. This function should never return. + + @param This The EFI_BDS_ARCH_PROTOCOL instance. + + @return None. + +**/ +VOID +EFIAPI +BdsEntry ( + IN EFI_BDS_ARCH_PROTOCOL *This + ) +{ + EFI_STATUS Status; + UINTN NoHandles; + EFI_HANDLE *Buffer; + EFI_HANDLE FvHandle; + EFI_HANDLE ImageHandle; + EFI_HANDLE UsbDeviceHandle; + EFI_GUID NameGuid; + UINTN Size; + UINTN HandleCount; + UINTN OldHandleCount; + EFI_HANDLE *HandleBuffer; + UINTN Index; + EFI_DEVICE_PATH_PROTOCOL *LoadImageDevicePath; + EFI_DEVICE_PATH_PROTOCOL *FileSystemDevicePath; + + // + // Now do the EFI stuff + // + Size = 0x100; + gST->FirmwareVendor = AllocateRuntimePool (Size); + ASSERT (gST->FirmwareVendor != NULL); + + UnicodeSPrint (gST->FirmwareVendor, Size, L"BeagleBoard EFI %a %a", __DATE__, __TIME__); + + // + // Now we need to setup the EFI System Table with information about the console devices. + // This code is normally in the console spliter driver on platforms that support multiple + // consoles at the same time + // + Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiSimpleTextOutProtocolGuid, NULL, &NoHandles, &Buffer); + if (!EFI_ERROR (Status)) { + // Use the first SimpleTextOut we find and update the EFI System Table + gST->ConsoleOutHandle = Buffer[0]; + gST->StandardErrorHandle = Buffer[0]; + Status = gBS->HandleProtocol (Buffer[0], &gEfiSimpleTextOutProtocolGuid, (VOID **)&gST->ConOut); + ASSERT_EFI_ERROR (Status); + + gST->StdErr = gST->ConOut; + + gST->ConOut->OutputString (gST->ConOut, L"BDS: Console Started!!!!\n\r"); + FreePool (Buffer); + + gConsolePresent = TRUE; + } + + + Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiSimpleTextInProtocolGuid, NULL, &NoHandles, &Buffer); + if (!EFI_ERROR (Status)) { + // Use the first SimpleTextIn we find and update the EFI System Table + gST->ConsoleInHandle = Buffer[0]; + Status = gBS->HandleProtocol (Buffer[0], &gEfiSimpleTextInProtocolGuid, (VOID **)&gST->ConIn); + ASSERT_EFI_ERROR (Status); + + FreePool (Buffer); + } + + // + // We now have EFI Consoles up and running. Print () will work now. DEBUG () and ASSERT () worked + // prior to this point as they were configured to use a more primative output scheme. + // + + // + //Perform Connect + // + HandleCount = 0; + while (1) { + OldHandleCount = HandleCount; + Status = gBS->LocateHandleBuffer ( + AllHandles, + NULL, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + break; + } + + if (HandleCount == OldHandleCount) { + break; + } + + for (Index = 0; Index < HandleCount; Index++) { + gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE); + } + } + + //Locate handles for SimpleFileSystem protocol + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiSimpleFileSystemProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (!EFI_ERROR(Status)) { + for (Index = 0; Index < HandleCount; Index++) { + //Get the device path + FileSystemDevicePath = DevicePathFromHandle(HandleBuffer[Index]); + if (FileSystemDevicePath == NULL) { + continue; + } + + //Check if UsbIo is on any handles in the device path. + Status = gBS->LocateDevicePath(&gEfiUsbIoProtocolGuid, &FileSystemDevicePath, &UsbDeviceHandle); + if (EFI_ERROR(Status)) { + continue; + } + + //Check if Usb stick has a magic EBL file. + LoadImageDevicePath = FileDevicePath(HandleBuffer[Index], L"Ebl.efi"); + Status = gBS->LoadImage (TRUE, gImageHandle, LoadImageDevicePath, NULL, 0, &ImageHandle); + if (EFI_ERROR(Status)) { + continue; + } + + //Boot to Shell on USB stick. + Status = gBS->StartImage (ImageHandle, NULL, NULL); + if (EFI_ERROR(Status)) { + continue; + } + } + } + + // + // Normal UEFI behavior is to process Globally Defined Variables as defined in Chapter 3 + // (Boot Manager) of the UEFI specification. For this embedded system we don't do this. + // + + // + // Search all the FVs for an application with a UI Section of Ebl. A .FDF file can be used + // to control the names of UI sections in an FV. + // + Status = FindApplicationMatchingUiSection (L"Ebl", &FvHandle, &NameGuid); + if (!EFI_ERROR (Status)) { + + //Boot to Shell. + Status = LoadPeCoffSectionFromFv (FvHandle, &NameGuid); + + if (EFI_ERROR(Status)) { + DEBUG((EFI_D_ERROR, "Boot from Shell failed. Status: %r\n", Status)); + } + } + + // + // EFI does not define the behaviour if all boot attemps fail and the last one returns. + // So we make a policy choice to reset the system since this BDS does not have a UI. + // + gRT->ResetSystem (EfiResetShutdown, Status, 0, NULL); + + return ; +} + + +EFI_STATUS +EFIAPI +BdsInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + mBdsImageHandle = ImageHandle; + + // + // Install protocol interface + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &mBdsImageHandle, + &gEfiBdsArchProtocolGuid, &gBdsProtocol, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + + diff --git a/BeagleBoardPkg/Bds/BdsEntry.h b/BeagleBoardPkg/Bds/BdsEntry.h new file mode 100644 index 0000000000..21e49498cf --- /dev/null +++ b/BeagleBoardPkg/Bds/BdsEntry.h @@ -0,0 +1,65 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __BDS_ENTRY_H__ +#define __BDS_ENTRY_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +EFI_STATUS +LoadPeCoffSectionFromFv ( + IN EFI_HANDLE FvHandle, + IN EFI_GUID *NameGuid + ); + +EFI_STATUS +FindApplicationMatchingUiSection ( + IN CHAR16 *UiString, + OUT EFI_HANDLE *FvHandle, + OUT EFI_GUID *NameGuid + ); + +VOID +EFIAPI +BdsEntry ( + IN EFI_BDS_ARCH_PROTOCOL *This + ); + +#endif + diff --git a/BeagleBoardPkg/Bds/FirmwareVolume.c b/BeagleBoardPkg/Bds/FirmwareVolume.c new file mode 100644 index 0000000000..f08de5767a --- /dev/null +++ b/BeagleBoardPkg/Bds/FirmwareVolume.c @@ -0,0 +1,150 @@ +/** @file + The entry of the embedded BDS. This BDS does not follow the Boot Manager requirements + of the UEFI specification as it is designed to implement an embedded systmes + propriatary boot scheme. + + This template assume a DXE driver produces a SerialIo protocol not using the EFI + driver module and it will attempt to connect a console on top of this. + + + Copyright (c) 2009 Apple, Inc. All rights reserved. + Portions copyright (c) 2008-2009, Apple Inc. All rights reserved. + + + This document is the property of Apple, Inc. + It is considered confidential and proprietary. + + This document may not be reproduced or transmitted in any form, + in whole or in part, without the express written permission of + Apple, Inc. + +**/ + +#include "BdsEntry.h" + + +EFI_STATUS +FindApplicationMatchingUiSection ( + IN CHAR16 *UiString, + OUT EFI_HANDLE *FvHandle, + OUT EFI_GUID *NameGuid + ) +{ + EFI_STATUS Status; + EFI_STATUS NextStatus; + UINTN NoHandles; + EFI_HANDLE *Buffer; + UINTN Index; + EFI_FV_FILETYPE FileType; + EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; + VOID *Key; + EFI_FV_FILE_ATTRIBUTES Attributes; + UINTN Size; + UINTN UiStringLen; + CHAR16 *UiSection; + UINT32 Authentication; + + + UiStringLen = 0; + if (UiString != NULL) { + DEBUG ((DEBUG_ERROR, "UiString %s\n", UiString)); + UiStringLen = StrLen (UiString); + } + + Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiFirmwareVolume2ProtocolGuid, NULL, &NoHandles, &Buffer); + if (!EFI_ERROR (Status)) { + for (Index = 0; Index < NoHandles; Index++) { + Status = gBS->HandleProtocol (Buffer[Index], &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&Fv); + if (!EFI_ERROR (Status)) { + Key = AllocatePool (Fv->KeySize); + ASSERT (Key != NULL); + ZeroMem (Key, Fv->KeySize); + + FileType = EFI_FV_FILETYPE_APPLICATION; + + do { + NextStatus = Fv->GetNextFile (Fv, Key, &FileType, NameGuid, &Attributes, &Size); + if (!EFI_ERROR (NextStatus)) { + if (UiString == NULL) { + // + // If UiString is NULL match first application we find. + // + *FvHandle = Buffer[Index]; + FreePool (Key); + return Status; + } + + UiSection = NULL; + Status = Fv->ReadSection ( + Fv, + NameGuid, + EFI_SECTION_USER_INTERFACE, + 0, + (VOID **)&UiSection, + &Size, + &Authentication + ); + if (!EFI_ERROR (Status)) { + if (StrnCmp (UiString, UiSection, UiStringLen) == 0) { + // + // We found a UiString match. + // + *FvHandle = Buffer[Index]; + FreePool (Key); + FreePool (UiSection); + return Status; + } + FreePool (UiSection); + } + } + } while (!EFI_ERROR (NextStatus)); + + FreePool (Key); + } + } + + FreePool (Buffer); + } + + return EFI_NOT_FOUND; +} + + +EFI_DEVICE_PATH * +FvFileDevicePath ( + IN EFI_HANDLE FvHandle, + IN EFI_GUID *NameGuid + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH NewNode; + + DevicePath = DevicePathFromHandle (FvHandle); + + EfiInitializeFwVolDevicepathNode (&NewNode, NameGuid); + + return AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&NewNode); +} + + + +EFI_STATUS +LoadPeCoffSectionFromFv ( + IN EFI_HANDLE FvHandle, + IN EFI_GUID *NameGuid + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_HANDLE ImageHandle; + + DevicePath = FvFileDevicePath (FvHandle, NameGuid); + + Status = gBS->LoadImage (TRUE, gImageHandle, DevicePath, NULL, 0, &ImageHandle); + if (!EFI_ERROR (Status)) { + Status = gBS->StartImage (ImageHandle, NULL, NULL); + } + + return Status; +} + diff --git a/BeagleBoardPkg/BeagleBoardPkg.dec b/BeagleBoardPkg/BeagleBoardPkg.dec new file mode 100644 index 0000000000..7a92f94a21 --- /dev/null +++ b/BeagleBoardPkg/BeagleBoardPkg.dec @@ -0,0 +1,65 @@ +#%HEADER% +#/** @file +# Beagle board package. +# +# Copyright (c) 2009, Apple Inc. +# +# All rights reserved. +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License which accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/ + +[Defines] + DEC_SPECIFICATION = 0x00010005 + PACKAGE_NAME = BeagleBoardPkg + PACKAGE_GUID = 6eba6648-d853-4eb3-9761-528b82d5ab04 + PACKAGE_VERSION = 0.1 + +################################################################################ +# +# Include Section - list of Include Paths that are provided by this package. +# Comments are used for Keywords and Module Types. +# +# Supported Module Types: +# BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION +# +################################################################################ +[Includes.common] + Include # Root include for the package + +[Guids.common] + gBeagleBoardTokenSpaceGuid = { 0x6834fe45, 0x4aee, 0x4fc6, { 0xbc, 0xb5, 0xff, 0x45, 0xb7, 0xa8, 0x71, 0xe2 } } + +#[PcdsEnumerations.common] +# OMAP3530_GPTIMER: +# OMAP3530_GPTIMER1|1 +# OMAP3530_GPTIMER2|2 +# OMAP3530_GPTIMER3|3 +# OMAP3530_GPTIMER4|4 +# OMAP3530_GPTIMER5|5 +# OMAP3530_GPTIMER6|6 +# OMAP3530_GPTIMER7|7 +# OMAP3530_GPTIMER8|8 +# OMAP3530_GPTIMER9|9 +# OMAP3530_GPTIMER10|10 +# OMAP3530_GPTIMER11|11 +# OMAP3530_GPTIMER12|12 + +[PcdsFeatureFlag.common] + +[PcdsFixedAtBuild.common] + gBeagleBoardTokenSpaceGuid.PcdBeagleBoardIRAMFullSize|0x00000000|UINT32|0x00000201 + gBeagleBoardTokenSpaceGuid.PcdBeagleConsoleUart|3|UINT32|0x00000202 + gBeagleBoardTokenSpaceGuid.PcdBeagleGpmcOffset|0x00000000|UINT32|0x00000203 + gBeagleBoardTokenSpaceGuid.PcdBeagleMMCHS1Base|0x00000000|UINT32|0x00000204 +# gBeagleBoardTokenSpaceGuid.PcdBeagleArchTimer|OMAP3530_GPTIMER3|OMAP3530_GPTIMER|0x00000205 + gBeagleBoardTokenSpaceGuid.PcdBeagleArchTimer|3|UINT32|0x00000205 +# gBeagleBoardTokenSpaceGuid.PcdBeagleFreeTimer|OMAP3530_GPTIMER4|OMAP3530_GPTIMER|0x00000206 + gBeagleBoardTokenSpaceGuid.PcdBeagleFreeTimer|4|UINT32|0x00000206 + diff --git a/BeagleBoardPkg/BeagleBoardPkg.dsc b/BeagleBoardPkg/BeagleBoardPkg.dsc new file mode 100644 index 0000000000..a0d7a77172 --- /dev/null +++ b/BeagleBoardPkg/BeagleBoardPkg.dsc @@ -0,0 +1,415 @@ +#/** @file +# Beagle board package. +# +# Copyright (c) 2009, Apple Inc. All rights reserved. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/ + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + PLATFORM_NAME = BeagleBoardPkg + PLATFORM_GUID = 91fa6c28-33df-46ac-aee6-292d6811ea31 + PLATFORM_VERSION = 0.1 + DSC_SPECIFICATION = 0x00010005 + OUTPUT_DIRECTORY = Build/BeagleBoard + SUPPORTED_ARCHITECTURES = ARM + BUILD_TARGETS = DEBUG|RELEASE + SKUID_IDENTIFIER = DEFAULT + FLASH_DEFINITION = BeagleBoardPkg/BeagleBoardPkg.fdf + DEFINE TARGET_HACK = DEBUG + + +[LibraryClasses.common] +!if TARGET_HACK == DEBUG + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf +!else + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf +!endif + + + ArmLib|ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexArmLib.inf + + BaseLib|MdePkg/Library/BaseLib/BaseLib.inf + BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf + + BeagleBoardSystemLib|BeagleBoardPkg/Library/BeagleBoardSystemLib/BeagleBoardSystemLib.inf + EfiResetSystemLib|BeagleBoardPkg/Library/ResetSystemLib/ResetSystemLib.inf + + PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf + PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf + + EblCmdLib|BeagleBoardPkg/Library/EblCmdLib/EblCmdLib.inf + + EfiFileLib|EmbeddedPkg/Library/EfiFileLib/EfiFileLib.inf + + + PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf + PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf + PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf + CacheMaintenanceLib|ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.inf + PrePiLib|EmbeddedPkg/Library/PrePiLib/PrePiLib.inf + + SerialPortLib|BeagleBoardPkg/Library/SerialPortLib/SerialPortLib.inf + SemihostLib|ArmPkg/Library/SemihostLib/SemihostLib.inf + + RealTimeClockLib|EmbeddedPkg/Library/TemplateRealTimeClockLib/TemplateRealTimeClockLib.inf + + IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf + + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + UefiLib|MdePkg/Library/UefiLib/UefiLib.inf + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf + UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf + + DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf + UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf + UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf + +# +# Assume everything is fixed at build +# + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + + UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf + + UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf + EblAddExternalCommandLib|EmbeddedPkg/Library/EblAddExternalCommandLib/EblAddExternalCommandLib.inf + + UncachedMemoryAllocationLib|ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.inf + + TimerLib|BeagleBoardPkg/Library/BeagleBoardTimerLib/BeagleBoardTimerLib.inf + OmapLib|BeagleBoardPkg/Library/OmapLib/OmapLib.inf + EblNetworkLib|EmbeddedPkg/Library/EblNetworkLib/EblNetworkLib.inf + + GdbSerialLib|BeagleBoardPkg/Library/GdbSerialLib/GdbSerialLib.inf + + +[LibraryClasses.common.SEC] + ArmLib|ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexArmLibPrePi.inf + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf + UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf + ExtractGuidedSectionLib|EmbeddedPkg/Library/PrePiExtractGuidedSectionLib/PrePiExtractGuidedSectionLib.inf + LzmaDecompressLib|IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf + +[LibraryClasses.common.PEI_CORE] + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf + +[LibraryClasses.common.DXE_CORE] + HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf + MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf + DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf + ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf + UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf + DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf + +[LibraryClasses.common.DXE_DRIVER] + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf + DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf + SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf + + +[LibraryClasses.common.UEFI_APPLICATION] + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf + UefiDecompressLib|IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf + +[LibraryClasses.common.UEFI_DRIVER] + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf + UefiDecompressLib|IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf + ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf + +[LibraryClasses.common.DXE_RUNTIME_DRIVER] + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf + CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf + +[BuildOptions] + XCODE:*_*_ARM_ARCHCC_FLAGS == -arch armv6 -march=armv6 + XCODE:*_*_ARM_ARCHASM_FLAGS == -arch armv6 + XCODE:*_*_ARM_ARCHDLINK_FLAGS == -arch armv6 + + RVCT:*_*_ARM_ARCHCC_FLAGS == --cpu Cortex-A8 + RVCT:*_*_ARM_ARCHASM_FLAGS == --cpu Cortex-A8 + + +################################################################################ +# +# Pcd Section - list of all EDK II PCD Entries defined by this Platform +# +################################################################################ + +[PcdsFeatureFlag.common] + gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable|TRUE + gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnosticsDisable|TRUE + gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable|TRUE + gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable|TRUE + + # + # Control what commands are supported from the UI + # Turn these on and off to add features or save size + # + gEmbeddedTokenSpaceGuid.PcdEmbeddedMacBoot|TRUE + gEmbeddedTokenSpaceGuid.PcdEmbeddedDirCmd|TRUE + gEmbeddedTokenSpaceGuid.PcdEmbeddedHobCmd|TRUE + gEmbeddedTokenSpaceGuid.PcdEmbeddedHwDebugCmd|TRUE + gEmbeddedTokenSpaceGuid.PcdEmbeddedPciDebugCmd|TRUE + gEmbeddedTokenSpaceGuid.PcdEmbeddedIoEnable|FALSE + gEmbeddedTokenSpaceGuid.PcdEmbeddedScriptCmd|FALSE + + gEmbeddedTokenSpaceGuid.PcdCacheEnable|TRUE + + gEmbeddedTokenSpaceGuid.PcdPrePiProduceMemoryTypeInformationHob|TRUE + gArmTokenSpaceGuid.PcdCpuDxeProduceDebugSupport|FALSE + + # + # Beagle board Specific PCDs + # + +[PcdsFixedAtBuild.common] + gEmbeddedTokenSpaceGuid.PcdEmbeddedPrompt|"BeagleEdk2" + gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize|32 + gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize|0 + gEfiMdePkgTokenSpaceGuid.PcdMaximumUnicodeStringLength|1000000 + gEfiMdePkgTokenSpaceGuid.PcdMaximumAsciiStringLength|1000000 + gEfiMdePkgTokenSpaceGuid.PcdMaximumLinkedListLength|1000000 + gEfiMdePkgTokenSpaceGuid.PcdSpinLockTimeout|10000000 + gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue|0xAF + gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask|0 + gEfiMdePkgTokenSpaceGuid.PcdPostCodePropertyMask|0 + gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|320 + +# DEBUG_ASSERT_ENABLED 0x01 + +# DEBUG_PRINT_ENABLED 0x02 + +# DEBUG_CODE_ENABLED 0x04 + +# CLEAR_MEMORY_ENABLED 0x08 + +# ASSERT_BREAKPOINT_ENABLED 0x10 + +# ASSERT_DEADLOOP_ENABLED 0x20 + + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2f + +# DEBUG_INIT 0x00000001 // Initialization + +# DEBUG_WARN 0x00000002 // Warnings + +# DEBUG_LOAD 0x00000004 // Load events + +# DEBUG_FS 0x00000008 // EFI File system + +# DEBUG_POOL 0x00000010 // Alloc & Free's + +# DEBUG_PAGE 0x00000020 // Alloc & Free's + +# DEBUG_INFO 0x00000040 // Verbose + +# DEBUG_DISPATCH 0x00000080 // PEI/DXE Dispatchers + +# DEBUG_VARIABLE 0x00000100 // Variable + +# DEBUG_BM 0x00000400 // Boot Manager + +# DEBUG_BLKIO 0x00001000 // BlkIo Driver + +# DEBUG_NET 0x00004000 // SNI Driver + +# DEBUG_UNDI 0x00010000 // UNDI Driver + +# DEBUG_LOADFILE 0x00020000 // UNDI Driver + +# DEBUG_EVENT 0x00080000 // Event messages + +# DEBUG_ERROR 0x80000000 // Error + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000004 + + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x07 + + gEmbeddedTokenSpaceGuid.PcdEmbeddedAutomaticBootCommand|"" + gEmbeddedTokenSpaceGuid.PcdEmbeddedDefaultTextColor|0x07 + gEmbeddedTokenSpaceGuid.PcdEmbeddedMemVariableStoreSize|0x10000 + + gEmbeddedTokenSpaceGuid.PcdPrePiTempMemorySize|0 + gEmbeddedTokenSpaceGuid.PcdPrePiBfvBaseAddress|0 + gEmbeddedTokenSpaceGuid.PcdPrePiBfvSize|0 + gEmbeddedTokenSpaceGuid.PcdFlashFvMainBase|0 + gEmbeddedTokenSpaceGuid.PcdFlashFvMainSize|0 + +# +# Optional feature to help prevent EFI memory map fragments +# Turned on and off via: PcdPrePiProduceMemoryTypeInformationHob +# Values are in EFI Pages (4K). DXE Core will make sure that +# at least this much of each type of memory can be allocated +# from a single memory range. This way you only end up with +# maximum of two fragements for each type in the memory map +# (the memory used, and the free memory that was prereserved +# but not used). +# + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIReclaimMemory|0 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIMemoryNVS|0 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType|0 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData|80 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode|40 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesCode|400 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesData|3000 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderCode|10 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderData|0 + + +# +# Beagle board Specific PCDs +# + gEmbeddedTokenSpaceGuid.PcdPrePiHobBase|0x80001000 + gEmbeddedTokenSpaceGuid.PcdPrePiStackBase|0x87FE0000 # stack at top of memory + gEmbeddedTokenSpaceGuid.PcdPrePiStackSize|0x20000 # 128K stack + gBeagleBoardTokenSpaceGuid.PcdBeagleBoardIRAMFullSize|0x00000000 + gArmTokenSpaceGuid.PcdCpuVectorBaseAddress|0x80000000 + gArmTokenSpaceGuid.PcdCpuResetAddress|0x80008000 + + gBeagleBoardTokenSpaceGuid.PcdBeagleGpmcOffset|0x6E000000 + gBeagleBoardTokenSpaceGuid.PcdBeagleMMCHS1Base|0x4809C000 + + # Console + gBeagleBoardTokenSpaceGuid.PcdBeagleConsoleUart|3 + + # Timers +# gBeagleBoardTokenSpaceGuid.PcdBeagleArchTimer|OMAP3530_GPTIMER3 + gBeagleBoardTokenSpaceGuid.PcdBeagleArchTimer|3 +# gBeagleBoardTokenSpaceGuid.PcdBeagleFreeTimer|OMAP3530_GPTIMER4 + gBeagleBoardTokenSpaceGuid.PcdBeagleFreeTimer|4 + gEmbeddedTokenSpaceGuid.PcdTimerPeriod|100000 + gEmbeddedTokenSpaceGuid.PcdEmbeddedFdPerformanceCounterPeriodInNanoseconds|77 + gEmbeddedTokenSpaceGuid.PcdEmbeddedFdPerformanceCounterFrequencyInHz|13000000 + + # + # ARM Pcds + # + gArmTokenSpaceGuid.PcdArmUncachedMemoryMask|0x0000000040000000 + +################################################################################ +# +# Components Section - list of all EDK II Modules needed by this Platform +# +################################################################################ +[Components.common] + +# +# SEC +# + BeagleBoardPkg/Sec/Sec.inf + +# +# DXE +# + MdeModulePkg/Core/Dxe/DxeMain.inf { + + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + NULL|MdeModulePkg/Library/DxeCrc32GuidedSectionExtractLib/DxeCrc32GuidedSectionExtractLib.inf + NULL|IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf + } + + ArmPkg/Drivers/CpuDxe/CpuDxe.inf + + MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf + MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf + MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf + MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf + MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf + EmbeddedPkg/EmbeddedMonotonicCounter/EmbeddedMonotonicCounter.inf + EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOutSerial.inf + + EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf + EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf + EmbeddedPkg/TemplateMetronomeDxe/TemplateMetronomeDxe.inf + + # + # Semi-hosting filesystem + # + ArmPkg/Filesystem/SemihostFs/SemihostFs.inf + + # + # FAT filesystem + GPT/MBR partitioning + # + MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf + MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf + FatPkg/EnhancedFatDxe/Fat.inf + MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf + + # + # USB + # + BeagleBoardPkg/PciEmulation/PciEmulation.inf + + #NOTE: Open source EHCI stack doesn't work on Beagleboard. + #NOTE: UsbBus and UsbMassStorage don't work using iPhone SDK tool chain. + MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf { + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x800fffff + } + MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf + MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf + + # + # Nand Flash + # + BeagleBoardPkg/Flash/Flash.inf + + # + # MMC/SD + # + BeagleBoardPkg/MMCHSDxe/MMCHS.inf + + # + # I2C + # + BeagleBoardPkg/SmbusDxe/Smbus.inf + + # + # SoC Drivers + # + BeagleBoardPkg/Gpio/Gpio.inf + BeagleBoardPkg/InterruptDxe/InterruptDxe.inf + BeagleBoardPkg/TimerDxe/TimerDxe.inf + + # + # Power IC + # + BeagleBoardPkg/TPS65950Dxe/TPS65950.inf + + # + # Application + # + EmbeddedPkg/Ebl/Ebl.inf + + # + # Bds + # + BeagleBoardPkg/Bds/Bds.inf + + # + # Gdb Stub + # + EmbeddedPkg/GdbStub/GdbStub.inf + ArmPkg/Drivers/DebugSupportDxe/DebugSupportDxe.inf + diff --git a/BeagleBoardPkg/BeagleBoardPkg.fdf b/BeagleBoardPkg/BeagleBoardPkg.fdf new file mode 100644 index 0000000000..d29650497e --- /dev/null +++ b/BeagleBoardPkg/BeagleBoardPkg.fdf @@ -0,0 +1,296 @@ +# FLASH layout file for Beagle board. +# +# Copyright (c) 2009, Apple Inc. All rights reserved. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# + +################################################################################ +# +# FD Section +# The [FD] Section is made up of the definition statements and a +# description of what goes into the Flash Device Image. Each FD section +# defines one flash "device" image. A flash device image may be one of +# the following: Removable media bootable image (like a boot floppy +# image,) an Option ROM image (that would be "flashed" into an add-in +# card,) a System "Flash" image (that would be burned into a system's +# flash) or an Update ("Capsule") image that will be used to update and +# existing system flash. +# +################################################################################ + + +[FD.BeagleBoard_EFI] +BaseAddress = 0x80008000|gEmbeddedTokenSpaceGuid.PcdEmbeddedFdBaseAddress #The base address of the FLASH Device. +Size = 0x00080000|gEmbeddedTokenSpaceGuid.PcdEmbeddedFdSize #The size in bytes of the FLASH Device +ErasePolarity = 1 +BlockSize = 0x40 +NumBlocks = 0x2000 + +################################################################################ +# +# Following are lists of FD Region layout which correspond to the locations of different +# images within the flash device. +# +# Regions must be defined in ascending order and may not overlap. +# +# A Layout Region start with a eight digit hex offset (leading "0x" required) followed by +# the pipe "|" character, followed by the size of the region, also in hex with the leading +# "0x" characters. Like: +# Offset|Size +# PcdOffsetCName|PcdSizeCName +# RegionType +# +################################################################################ + +# 512 bytes of configuration header & 8 bytes of image header +0x00000000|0x00000208 + +0x00000208|0x0007FDF8 +gEmbeddedTokenSpaceGuid.PcdFlashFvMainBase|gEmbeddedTokenSpaceGuid.PcdFlashFvMainSize +FV = FVMAIN_COMPACT + +################################################################################ +# +# FV Section +# +# [FV] section is used to define what components or modules are placed within a flash +# device file. This section also defines order the components and modules are positioned +# within the image. The [FV] section consists of define statements, set statements and +# module statements. +# +################################################################################ + +[FV.FvMain] +BlockSize = 0x40 +NumBlocks = 0x9000 +FvAlignment = 8 #FV alignment and FV attributes setting. +ERASE_POLARITY = 1 +MEMORY_MAPPED = TRUE +STICKY_WRITE = TRUE +LOCK_CAP = TRUE +LOCK_STATUS = TRUE +WRITE_DISABLED_CAP = TRUE +WRITE_ENABLED_CAP = TRUE +WRITE_STATUS = TRUE +WRITE_LOCK_CAP = TRUE +WRITE_LOCK_STATUS = TRUE +READ_DISABLED_CAP = TRUE +READ_ENABLED_CAP = TRUE +READ_STATUS = TRUE +READ_LOCK_CAP = TRUE +READ_LOCK_STATUS = TRUE + + # + # PI DXE Drivers producing Architectural Protocols (EFI Services) + # + INF ArmPkg/Drivers/CpuDxe/CpuDxe.inf + + INF MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf + INF MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf + INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf + INF MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf + INF MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf + INF EmbeddedPkg/EmbeddedMonotonicCounter/EmbeddedMonotonicCounter.inf + + INF EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOutSerial.inf + + INF EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf + INF EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf + INF EmbeddedPkg/TemplateMetronomeDxe/TemplateMetronomeDxe.inf + + # + # Semi-hosting filesystem + # + INF ArmPkg/Filesystem/SemihostFs/SemihostFs.inf + + # + # Nand Flash + # + INF BeagleBoardPkg/Flash/Flash.inf + + # + # MMC/SD + # + INF BeagleBoardPkg/MMCHSDxe/MMCHS.inf + + # + # I2C + # + INF BeagleBoardPkg/SmbusDxe/Smbus.inf + + # + # SoC Drivers + # + INF BeagleBoardPkg/Gpio/Gpio.inf + INF BeagleBoardPkg/InterruptDxe/InterruptDxe.inf + INF BeagleBoardPkg/TimerDxe/TimerDxe.inf + + # + # Power IC + # + INF BeagleBoardPkg/TPS65950Dxe/TPS65950.inf + + # + # FAT filesystem + GPT/MBR partitioning + # + INF MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf + INF MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf + INF FatPkg/EnhancedFatDxe/Fat.inf + INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf + + # + # USB Support + # + + INF BeagleBoardPkg/PciEmulation/PciEmulation.inf + + #NOTE: Open source EHCI stack doesn't work on Beagleboard. + #NOTE: UsbBus and UsbMassStorage don't work using iPhond SDK tool chain. + INF MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf + INF MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf + INF MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf + + # + # UEFI application (Shell Embedded Boot Loader) + # + INF EmbeddedPkg/Ebl/Ebl.inf + + + # + # Bds + # + INF BeagleBoardPkg/Bds/Bds.inf + + # + # Gdb Stub + # + #INF ArmPkg/Drivers/DebugSupportDxe/DebugSupportDxe.inf + #INF ApplePkg/Universal/GdbStub/GdbStub.inf + + +[FV.FVMAIN_COMPACT] +FvAlignment = 8 +ERASE_POLARITY = 1 +MEMORY_MAPPED = TRUE +STICKY_WRITE = TRUE +LOCK_CAP = TRUE +LOCK_STATUS = TRUE +WRITE_DISABLED_CAP = TRUE +WRITE_ENABLED_CAP = TRUE +WRITE_STATUS = TRUE +WRITE_LOCK_CAP = TRUE +WRITE_LOCK_STATUS = TRUE +READ_DISABLED_CAP = TRUE +READ_ENABLED_CAP = TRUE +READ_STATUS = TRUE +READ_LOCK_CAP = TRUE +READ_LOCK_STATUS = TRUE + + INF BeagleBoardPkg/Sec/Sec.inf + INF MdeModulePkg/Core/Dxe/DxeMain.inf + + FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 { + SECTION GUIDED EE4E5898-3914-4259-9D6E-DC7BD79403CF PROCESSING_REQUIRED = TRUE { + SECTION FV_IMAGE = FVMAIN + } + } + + +################################################################################ +# +# Rules are use with the [FV] section's module INF type to define +# how an FFS file is created for a given INF file. The following Rule are the default +# rules for the different module type. User can add the customized rules to define the +# content of the FFS file. +# +################################################################################ + + +############################################################################ +# Example of a DXE_DRIVER FFS file with a Checksum encapsulation section # +############################################################################ +# +#[Rule.Common.DXE_DRIVER] +# FILE DRIVER = $(NAMED_GUID) { +# DXE_DEPEX DXE_DEPEX Optional |.depex +# COMPRESS PI_STD { +# GUIDED { +# PE32 PE32 |.efi +# UI STRING="$(MODULE_NAME)" Optional +# VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) +# } +# } +# } +# +############################################################################ + +[Rule.Common.SEC] + FILE SEC = $(NAMED_GUID) RELOCS_STRIPPED { + TE TE Align = 8 |.efi + } + +[Rule.Common.PEI_CORE] + FILE PEI_CORE = $(NAMED_GUID) { + TE TE |.efi + UI STRING ="$(MODULE_NAME)" Optional + } + +[Rule.Common.PEIM] + FILE PEIM = $(NAMED_GUID) { + PEI_DEPEX PEI_DEPEX Optional |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + } + +[Rule.Common.PEIM.TIANOCOMPRESSED] + FILE PEIM = $(NAMED_GUID) DEBUG_MYTOOLS_IA32 { + PEI_DEPEX PEI_DEPEX Optional |.depex + GUIDED A31280AD-481E-41B6-95E8-127F4C984779 PROCESSING_REQUIRED = TRUE { + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + } + } + +[Rule.Common.DXE_CORE] + FILE DXE_CORE = $(NAMED_GUID) { + GUIDED EE4E5898-3914-4259-9D6E-DC7BD79403CF PROCESSING_REQUIRED = TRUE { + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + } + } + + +[Rule.Common.UEFI_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + } + +[Rule.Common.DXE_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + } + +[Rule.Common.DXE_RUNTIME_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + } + + +[Rule.Common.UEFI_APPLICATION] + FILE APPLICATION = $(NAMED_GUID) { + UI STRING ="$(MODULE_NAME)" Optional + PE32 PE32 |.efi + } diff --git a/BeagleBoardPkg/ConfigurationHeader.dat b/BeagleBoardPkg/ConfigurationHeader.dat new file mode 100644 index 0000000000..5f6897e306 --- /dev/null +++ b/BeagleBoardPkg/ConfigurationHeader.dat @@ -0,0 +1,41 @@ +PRM_CLKSRC_CTRL=0x00000080 +PRM_CLKSEL=0x00000003 +CM_CLKSEL1_EMU=0x03020A50 +CM_CLKSEL_CORE=0x0000030A +CM_CLKSEL_WKUP=0x00000015 +CM_CLKEN_PLL_DPLL3=0x00370037 +CM_AUTOIDLE_PLL_DPLL3=0x00000000 +CM_CLKSEL1_PLL=0x094C0C00 +CM_CLKEN_PLL_DPLL4=0x00370037 +CM_AUTOIDLE_PLL_DPLL4=0x00000000 +CM_CLKSEL2_PLL=0x0001B00C +CM_CLKSEL3_PLL=0x00000009 +CM_CLKEN_PLL_MPU=0x00000037 +CM_AUTOIDLE_PLL_MPU=0x00000000 +CM_CLKSEL1_PLL_MPU=0x0011F40C +CM_CLKSEL2_PLL_MPU=0x00000001 +CM_CLKSTCTRL_MPU=0x00000000 +SDRC_SYSCONFIG_LSB=0x0000 +SDRC_CS_CFG_LSB=0x0001 +SDRC_SHARING_LSB=0x0100 +SDRC_ERR_TYPE_LSB=0x0000 +SDRC_DLLA_CTRL=0x0000000A +SDRC_POWER=0x00000081 +MEMORY_TYPE_CS0=0x0003 +SDRC_MCFG_0=0x02D04011 +SDRC_MR_0_LSB=0x0032 +SDRC_EMR1_0_LSB=0x0000 +SDRC_EMR2_0_LSB=0x0000 +SDRC_EMR3_0_LSB=0x0000 +SDRC_ACTIM_CTRLA_0=0xBA9DC4C6 +SDRC_ACTIM_CTRLB_0=0x00012522 +SDRC_RFRCTRL_0=0x0004E201 +MEMORY_TYPE_CS1=0x0003 +SDRC_MCFG_1=0x02D04011 +SDRC_MR_1_LSB=0x0032 +SDRC_EMR1_1_LSB=0x0000 +SDRC_EMR2_1_LSB=0x0000 +SDRC_EMR3_1_LSB=0x0000 +SDRC_ACTIM_CTRLA_1=0xBA9DC4C6 +SDRC_ACTIM_CTRLB_1=0x00012522 +SDRC_RFRCTRL_1=0x0004E201 diff --git a/BeagleBoardPkg/Debugger_scripts/rvi_boot_from_ram.inc b/BeagleBoardPkg/Debugger_scripts/rvi_boot_from_ram.inc new file mode 100644 index 0000000000..72c0fd75dd --- /dev/null +++ b/BeagleBoardPkg/Debugger_scripts/rvi_boot_from_ram.inc @@ -0,0 +1,21 @@ +// +// Copyright (c) 2008-2009, Apple Inc. All rights reserved. +// +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +error = continue +unload +error = abort + +setreg @CP15_CONTROL = 0x0005107E +setreg @pc=0x80008208 +setreg @cpsr=0x000000D3 +dis/D +readfile,raw,nowarn "ZZZZZZ/FV/BEAGLEBOARD_EFI.fd"=0x80008000 + diff --git a/BeagleBoardPkg/Debugger_scripts/rvi_convert_symbols.sh b/BeagleBoardPkg/Debugger_scripts/rvi_convert_symbols.sh new file mode 100755 index 0000000000..72947cc1c1 --- /dev/null +++ b/BeagleBoardPkg/Debugger_scripts/rvi_convert_symbols.sh @@ -0,0 +1,23 @@ +#!/bin/sh +# +# Copyright (c) 2008-2009, Apple Inc. All rights reserved. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http:#opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# + + +IN=`/usr/bin/cygpath -u $1` +OUT=`/usr/bin/cygpath -u $2` + +/usr/bin/sed -e "s/\/cygdrive\/\(.\)/load\/a\/ni\/np \"\1:/g" \ + -e 's:\\:/:g' \ + -e "s/^/load\/a\/ni\/np \"/g" \ + -e "s/dll /dll\" \&/g" \ + $IN | /usr/bin/sort.exe --key=3 --output=$OUT + diff --git a/BeagleBoardPkg/Debugger_scripts/rvi_dummy.axf b/BeagleBoardPkg/Debugger_scripts/rvi_dummy.axf new file mode 100755 index 0000000000000000000000000000000000000000..17fabaa6cc649d520848f087954c0729043bf001 GIT binary patch literal 7984 zcmbVRZERcDd44ZRnY3iPwCQ$+=LU4Zwq6p;vganAF|?8`#nvjvj3mcis+FS1D~S!i za7o%$YS@%3eDNK>lfYWA*T&CZW3b-hrU^ zUZwWhDv{UmNKd6My?CN{#w+z;czE%od}Z7JG@CD;?VhjoU@See1M48;>$%$S_PkQ1 z{HT|vEA@w(J8I}_TSV@9W&7I~&HnoGKJ*^|zF_v(m;bZbyt@W|YQ5XvCjSY{YrWT( z>Ay&|&bc+gtBp<2`ONMOKc~I>So}w^;-D=9KTTUc@CG4!x7ob24s!-{`Kpx~b<-aC zs5=C#LEnZCSL%V_Ttj585u(i?)`Br@P&fUavE{sSec2a&wXwDbwyI~VUinN-!n2J| zkr&tX{6$sU{PJP~G=Fe*(ckm!xx>ugAd4rW%kMvc2uoEo9M%eV#To>`e{_Ssn z0(Q7g)4yn?_DK!C!awP~)bK?w!M{o^AeS0z(f>8#rT9GgO3gctN3I}VRt(HOSgB)u zW=y19sSR-rn3KzxE0-IJrUlE3zTgWD($pNs0ePXtL%ha;gBU+xOWASt%tc2K@d#IH zt9p>bTbCB^X;}Z+>&vaYag7c+Gd{?t6yJsJ{n}H-zQhi+;e>YyoeL~ zP(b&f+t;(*T7NI&KD+3RE+EgZBL02V4vE%K%a72ffV|r1kaG1e8T;}1+AAVmzTm5n zy@Kayw~NqokvXpW7A`gd3vV_y zs{FiseOc>$Yf0p2y#q22%V_;$G8*#bE1K_eMf(WOjV|oXG0fwb*evo^<6()`$0Qp1 z7#`H7rj4KX;5_Q|%V-Vp_in;i!0$KvqllMm4g;^2{tZ6JXd++Mdf!;8V&8Vk5ya+C zy|4k9N_}-0`GwD#ys_kyOV;`?!*BWbhBp5aaJ1fuHFi`gP%~QpL9@A;ap_uLsr@-) z0$J8Pb;0f(E&LO#Z5Z`l_Q>q4zeA4Ie${O5l`v{#>+FAg6FzJ~p1H@oa%q{l{2*j` z_RtpU8g?q7EvQKW--kfkh`f-`7lwa06Ugg>4{L%~8i6qL9j$Mas~y3fD`uSiu#MXF z3UqAy-)6HPwIz1#ExGD$8Q84-d)Ao*+o*fF%X1DfzQeur!(TV=T6-s2|NCDzHh(Jku!`^zNjbVaH$y1O@^meh$4B$ z1h&=L(+M3sqqW|-#kH(A#9rh!YC0N1JU1gqceLoaMbrprM?m{gi$>Wz{HMME^fGpW z^UaHS#x4Ng=s$8{om;`Od3G{3e8yq8w~Q+aeG| zj)yus`@68|sAn3_QrQ~!y{yf7LZ=5hZ$M99ml<=)$t-e!F6y*n8->8B(a`A|$~N;v znO?|HcZ;n*bP8+m^mg{&2uT;bRf83O(`At$WT=C(*P!D*dieE%=c4z5?|et-bA9Jl z&G|#eXF@Z5oj2b2&UfDoo$l)j9p}0z^V-=5)?%)g{(KGdjLSiL?O}{Lf5V<%@pHv5 z>LkxC@c7W%q7t#^Z)1KO<7q1{=R61BFvF0x8C4E#9r{4s0(yyu*E&WDm`3anjX`9Z#G;A37Pk6mPLMWB_2 z^vEBy;5$vOPs(aSGuIn%V4VH3$AQV;>%wUVCjUtXCjTiHo^#=w4ovxfb70CZxiHTH zt6BbXk2*2;nG=@0jd)ij*`$c+P&&OKu_%Rknw6SH0w zru;PrraWuaYL@=5IWXz0SttEX2PU0$tLVh6QzvF!Ix%a|iCKdR)4zxVQy**5YIgix zn0r~#@lqwXU6^;O)jaYcHAL@|cbbFfSuX+fUi`W|j9xX;M-@O%{8{4i3O{~>wVKj5 zSH_u(S?ascqORCu{c+Eb{-rkbCD6I&Nx#;H&U)m0JGz_y>n{2C!vE~z|5xC2*}9`> z&rN6ixF3R=%?>P{!!aK&fVg}(sI`+JY=&tJLdUkC05{V|*V z9S1##dj2C12zCp4-f2EXT( z16Jof@jn93l`a2>zXd!G%=aVWe*wM$%z7by3-~6mqE~^JfO%e%-T+p=9f*GgtbP{| zcY3Y!^1jW#30S?qll};>Ivn?RVl|0IU5?9E9Q5?fZN^@Md83?o0Y3Himk67OFV^>hBz|dJm?)F9EClN&L6KYJU;`1F+gZlwSbmeu=2{0jv5a{b#_c z-iiMUSe<{=#~0RHkY^+Pp^laJiy-K`fYtj2*MGpq$w(wF zktF_g8+tsQj2Gjg?;X?AMk+Cu)Q{`wu~a^nESwk{cye&;z~InYqwy)=p~1-6M6 zp3JARDUwe{Ci7`LgbyqN_Tu?GO->Y)T6!5zr*nxF*Hcs3c-jpWza6YZyjau?7(=iM z7I?tabUd3(>jvYqb*l|x&!=QxDV0w46^lk{qEyrikx1Y0q1fO^-|^j%Ly_n}q;K!g zu3eF1dxv)JjErD3I504$?;en_3M54n3BYPqPeftKF?~+)oRM2BcZ{oRFVp>l;mI(oAtIW;>tG#gmwH zpqNpltaBz?N~c{@&+A6cjB_l;mBfvyp_r~RFELv)Y7`kjOR#=&g6;7n!0tg1Cv13*YSe~u8Unu5`_>^utoJ+*h9GfvR zOAdfRo6?Ksq!o-rE|Wp=K&#Pm!7!Jail?2nhL6UEQW-OxrZZScAs3oW=o?bW#w}NpmH|QXv*kCJjpq*KUT+(5F&4gw}~-Qzh(C%t3f$@WAlsp@Bn+ zqm`;cYRZvx#fJ4{Q6jNeQlE^M(nylI>0-%L0qH@l6pJ$_jKs9iE4vD?sgdPGE;|X8 z`I4cd7GlXHTTf~DfYSfT<4Ge}V+^6X$FVsYU7#nElv z+vs|cA#_&5I6Rcf;xK$HJp9c5(Le0&34hw$(&5KHzVpvIWiXq^C*u7`A!@#`7dM`H z=;rX5WBAaH(dklVBD{ac{zo4rPdNN>i~(Bc9QvyD*a}#wXAh z4YSYYikM~jV(plowh2(hSGV2NS+<^~Rk+*y!fz5~#`^s>>fr-%Qx|nomugBEzPsD+ z>DC>)35LcM6MDtRuTGBFN+I7@716;T#+a{Xs@=r5#4sLQ(SlbjQy+gME literal 0 HcmV?d00001 diff --git a/BeagleBoardPkg/Debugger_scripts/rvi_hw_setup.inc b/BeagleBoardPkg/Debugger_scripts/rvi_hw_setup.inc new file mode 100644 index 0000000000..eb5ce57aa3 --- /dev/null +++ b/BeagleBoardPkg/Debugger_scripts/rvi_hw_setup.inc @@ -0,0 +1,67 @@ +// +// Copyright (c) 2008-2009, Apple Inc. All rights reserved. +// +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// + +error = continue +unload +error = abort + +setreg @CP15_CONTROL = 0x0005107E +setreg @cpsr=0x000000D3 + +; General clock settings. +setmem /32 0x48307270=0x00000080 +setmem /32 0x48306D40=0x00000003 +setmem /32 0x48005140=0x03020A50 + +;Clock configuration +setmem /32 0x48004A40=0x0000030A +setmem /32 0x48004C40=0x00000015 + +;DPLL3 (Core) settings +setmem /32 0x48004D00=0x00370037 +setmem /32 0x48004D30=0x00000000 +setmem /32 0x48004D40=0x094C0C00 + +;DPLL4 (Peripheral) settings +setmem /32 0x48004D00=0x00370037 +setmem /32 0x48004D30=0x00000000 +setmem /32 0x48004D44=0x0001B00C +setmem /32 0x48004D48=0x00000009 + +;DPLL1 (MPU) settings +setmem /32 0x48004904=0x00000037 +setmem /32 0x48004934=0x00000000 +setmem /32 0x48004940=0x0011F40C +setmem /32 0x48004944=0x00000001 +setmem /32 0x48004948=0x00000000 + +;RAM setup. +setmem /16 0x6D000010=0x0000 +setmem /16 0x6D000040=0x0001 +setmem /16 0x6D000044=0x0100 +setmem /16 0x6D000048=0x0000 +setmem /32 0x6D000060=0x0000000A +setmem /32 0x6D000070=0x00000081 +setmem /16 0x6D000040=0x0003 +setmem /32 0x6D000080=0x02D04011 +setmem /16 0x6D000084=0x0032 +setmem /16 0x6D00008C=0x0000 +setmem /32 0x6D00009C=0xBA9DC4C6 +setmem /32 0x6D0000A0=0x00012522 +setmem /32 0x6D0000A4=0x0004E201 +setmem /16 0x6D000040=0x0003 +setmem /32 0x6D0000B0=0x02D04011 +setmem /16 0x6D0000B4=0x0032 +setmem /16 0x6D0000BC=0x0000 +setmem /32 0x6D0000C4=0xBA9DC4C6 +setmem /32 0x6D0000C8=0x00012522 +setmem /32 0x6D0000D4=0x0004E201 \ No newline at end of file diff --git a/BeagleBoardPkg/Debugger_scripts/rvi_load_symbols.inc b/BeagleBoardPkg/Debugger_scripts/rvi_load_symbols.inc new file mode 100644 index 0000000000..27d4007d1c --- /dev/null +++ b/BeagleBoardPkg/Debugger_scripts/rvi_load_symbols.inc @@ -0,0 +1,23 @@ +// +// Copyright (c) 2008-2009, Apple Inc. All rights reserved. +// +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// + +include 'ZZZZZZ/rvi_symbols_macros.inc' + +macro write_symbols_file("ZZZZZZ/rvi_symbols.tmp", 0x00000000, 0x10000000) + +host "bash -o igncr ZZZZZZ/rvi_convert_symbols.sh ZZZZZZ/rvi_symbols.tmp ZZZZZZ/rvi_symbols.inc" +include 'ZZZZZZ/rvi_symbols.inc' +load /NI /NP 'ZZZZZZ/rvi_dummy.axf' ;.constdata +unload rvi_dummy.axf +delfile rvi_dummy.axf + + diff --git a/BeagleBoardPkg/Debugger_scripts/rvi_symbols_macros.inc b/BeagleBoardPkg/Debugger_scripts/rvi_symbols_macros.inc new file mode 100755 index 0000000000..ccd1ea068f --- /dev/null +++ b/BeagleBoardPkg/Debugger_scripts/rvi_symbols_macros.inc @@ -0,0 +1,194 @@ +// +// Copyright (c) 2008-2009, Apple Inc. All rights reserved. +// +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// + +define /R int compare_guid(guid1, guid2) + unsigned char *guid1; + unsigned char *guid2; +{ + return strncmp(guid1, guid2, 16); +} +. + +define /R unsigned char * find_system_table(mem_start, mem_size) + unsigned char *mem_start; + unsigned long mem_size; +{ + unsigned char *mem_ptr; + + mem_ptr = mem_start + mem_size; + + do + { + mem_ptr -= 0x400000; // 4 MB + + if (strncmp(mem_ptr, "IBI SYST", 8) == 0) + { + return *(unsigned long *)(mem_ptr + 8); // EfiSystemTableBase + } + + } while (mem_ptr > mem_start); + + return 0; +} +. + +define /R unsigned char * find_debug_info_table_header(system_table) + unsigned char *system_table; +{ + unsigned long configuration_table_entries; + unsigned char *configuration_table; + unsigned long index; + unsigned char debug_table_guid[16]; + + // Fill in the debug table's guid + debug_table_guid[ 0] = 0x77; + debug_table_guid[ 1] = 0x2E; + debug_table_guid[ 2] = 0x15; + debug_table_guid[ 3] = 0x49; + debug_table_guid[ 4] = 0xDA; + debug_table_guid[ 5] = 0x1A; + debug_table_guid[ 6] = 0x64; + debug_table_guid[ 7] = 0x47; + debug_table_guid[ 8] = 0xB7; + debug_table_guid[ 9] = 0xA2; + debug_table_guid[10] = 0x7A; + debug_table_guid[11] = 0xFE; + debug_table_guid[12] = 0xFE; + debug_table_guid[13] = 0xD9; + debug_table_guid[14] = 0x5E; + debug_table_guid[15] = 0x8B; + + configuration_table_entries = *(unsigned long *)(system_table + 64); + configuration_table = *(unsigned long *)(system_table + 68); + + for (index = 0; index < configuration_table_entries; index++) + { + if (compare_guid(configuration_table, debug_table_guid) == 0) + { + return *(unsigned long *)(configuration_table + 16); + } + + configuration_table += 20; + } + + return 0; +} +. + +define /R int valid_pe_header(header) + unsigned char *header; +{ + if ((header[0x00] == 'M') && + (header[0x01] == 'Z') && + (header[0x80] == 'P') && + (header[0x81] == 'E')) + { + return 1; + } + + return 0; +} +. + +define /R unsigned long pe_headersize(header) + unsigned char *header; +{ + unsigned long *size; + + size = header + 0x00AC; + + return *size; +} +. + +define /R unsigned char *pe_filename(header) + unsigned char *header; +{ + unsigned long *debugOffset; + unsigned char *stringOffset; + + if (valid_pe_header(header)) + { + debugOffset = header + 0x0128; + stringOffset = header + *debugOffset + 0x002C; + + return stringOffset; + } + + return 0; +} +. + +define /R int char_is_valid(c) + unsigned char c; +{ + if (c >= 32 && c < 127) + return 1; + + return 0; +} +. + +define /R write_symbols_file(filename, mem_start, mem_size) + unsigned char *filename; + unsigned char *mem_start; + unsigned long mem_size; +{ + unsigned char *system_table; + unsigned char *debug_info_table_header; + unsigned char *debug_info_table; + unsigned long debug_info_table_size; + unsigned long index; + unsigned char *debug_image_info; + unsigned char *loaded_image_protocol; + unsigned char *image_base; + unsigned char *debug_filename; + unsigned long header_size; + int status; + + system_table = find_system_table(mem_start, mem_size); + if (system_table == 0) + { + return; + } + + status = fopen(88, filename, "w"); + + debug_info_table_header = find_debug_info_table_header(system_table); + + debug_info_table = *(unsigned long *)(debug_info_table_header + 8); + debug_info_table_size = *(unsigned long *)(debug_info_table_header + 4); + + for (index = 0; index < (debug_info_table_size * 4); index += 4) + { + debug_image_info = *(unsigned long *)(debug_info_table + index); + + if (debug_image_info == 0) + { + break; + } + + loaded_image_protocol = *(unsigned long *)(debug_image_info + 4); + + image_base = *(unsigned long *)(loaded_image_protocol + 32); + + debug_filename = pe_filename(image_base); + header_size = pe_headersize(image_base); + + $fprintf 88, "%s 0x%08x\n", debug_filename, image_base + header_size$; + } + + + fclose(88); +} +. + diff --git a/BeagleBoardPkg/Debugger_scripts/rvi_unload_symbols.inc b/BeagleBoardPkg/Debugger_scripts/rvi_unload_symbols.inc new file mode 100755 index 0000000000..9d28582fcb --- /dev/null +++ b/BeagleBoardPkg/Debugger_scripts/rvi_unload_symbols.inc @@ -0,0 +1,118 @@ +// +// Copyright (c) 2008-2009, Apple Inc. All rights reserved. +// +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// + +error = continue + +unload + +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 + +error = abort diff --git a/BeagleBoardPkg/Debugger_scripts/trace32_load_symbols.cmm b/BeagleBoardPkg/Debugger_scripts/trace32_load_symbols.cmm new file mode 100644 index 0000000000..0dffaa461a --- /dev/null +++ b/BeagleBoardPkg/Debugger_scripts/trace32_load_symbols.cmm @@ -0,0 +1,211 @@ +// +// Copyright (c) 2008-2009, Apple Inc. All rights reserved. +// +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// + + ENTRY &ram_start &ram_size + + ;If system is running then stop the execution so we can load symbols. + break + + ;Reset all windows + WINPAGE.RESET + + ;Create AREA to display the symbols we are loading. + AREA.Reset + AREA.Create SYMBOL 300. 100. + AREA.View SYMBOL + AREA.Select SYMBOL + SYS.Option BE OFF + + ;Added based on suggestion from Lauterbach support. + MMU.TABLEWALK ON + MMU.ON + + ;Load symbols. + GOSUB load_symbols &ram_start &ram_size + + ;Open some windows and enable semihosting. + TOOLBAR ON + STATUSBAR ON + WINPAGE.RESET + + WINCLEAR + WINPOS 0.0 17.0 72. 13. 0. 0. W000 + SYStem + + WINPOS 0.0 0.0 110. 55. 13. 1. W001 + WINTABS 10. 10. 25. 62. + Data.List + + WINPAGE.SELECT P000 + + //Enable semihosting + System.Option.BigEndian OFF + + tronchip.set swi on // ARM9/10/11 variant + + // configure and open semihosting channel + winpos 50% 50% 50% 50% + term.heapinfo 0 0x20000 0x30000 0x20000 + term.method armswi + term.mode string + term.gate + + WINPOS 115.0 0. 70. 35. 0. 1. W002 + Var.Local %HEX + + WINPOS 115.10 45. 48. 9. 0. 0. W003 + Register + + END + +find_system_table: + ENTRY &mem_start &mem_size + &mem_ptr=&mem_start+&mem_size + RPT + ( + &mem_ptr=&mem_ptr-0x400000 // 4 MB + &word1=Data.LONG(D:&mem_ptr) + &word2=Data.LONG(D:&mem_ptr+0x04) + IF &word1==0x20494249 + ( + IF &word2==0x54535953 + ( + &result=Data.LONG(D:&mem_ptr+0x08) + RETURN &result + ) + ) + ) + WHILE &mem_ptr>&mem_start + &result=0 + RETURN &result + +compare_guid: + ENTRY &guid + IF Data.LONG(D:&guid)==0x49152E77 + ( + IF Data.LONG(D:&guid+0x04)==0x47641ADA + ( + IF Data.LONG(D:&guid+0x08)==0xFE7AA2B7 + ( + IF Data.LONG(D:&guid+0x0C)==0x8B5ED9FE + ( + RETURN 0 + ) + ) + ) + ) + RETURN 1 + +find_debug_info_table_header: + ENTRY &system_table + &config_table_entries=Data.LONG(D:&system_table+0x40) + &config_table_pointer=Data.LONG(D:&system_table+0x44) + RPT &config_table_entries + ( + GOSUB compare_guid &config_table_pointer + ENTRY &result + IF &result==0 + ( + &result=Data.LONG(D:&config_table_pointer+0x10) + RETURN &result + ) + &config_table_pointer=&config_table_pointer+0x14 + ) + RETURN 0; + +valid_pe_header: + ENTRY &header + IF Data.BYTE(D:&header+0x00)==0x4D + ( + IF Data.BYTE(D:&header+0x01)==0x5A + ( + IF Data.BYTE(D:&header+0x80)==0x50 + ( + IF Data.BYTE(D:&header+0x81)==0x45 + ( + RETURN 1 + ) + ) + ) + ) + RETURN 0 + +get_file_string: + ENTRY &stringOffset + + local &string + + &more_string=data.string(d:&stringOffset) + + if (string.len("&more_string")>=128.) + ( + &string="&string"+"&more_string" + &stringOffset=&stringOffset+string.len("&more_string") + + //Get remaining file string + GOSUB get_file_string &stringOffset + ENTRY &more_string + &string="&string"+"&more_string" + ) + else + ( + &string="&string"+"&more_string" + &more_string="" + ) + RETURN &string + +load_symbol_file: + ENTRY &header &load_address + GOSUB valid_pe_header &header + ENTRY &result + + IF &result==1 + ( + &debugOffset=Data.LONG(D:&header+0x0128) + &stringOffset=&header+&debugOffset+0x002C + + GOSUB get_file_string &stringOffset + ENTRY &filestring + + PRINT "&filestring 0x" &load_address + TDIAG Data.load.elf &filestring &load_address /nocode /noclear + ) + RETURN + +pe_headersize: + ENTRY &header; + RETURN Data.LONG(D:&header+0x00AC) + +load_symbols: + ENTRY &mem_start &mem_size + GOSUB find_system_table &mem_start &mem_size + ENTRY &system_table + GOSUB find_debug_info_table_header &system_table + ENTRY &debug_info_table_header + &debug_info_table=Data.LONG(D:&debug_info_table_header+0x08) + &debug_info_table_size=Data.LONG(D:&debug_info_table_header+0x04) + &index=0 + RPT &debug_info_table_size + ( + &debug_image_info=Data.LONG(D:&debug_info_table+&index) + IF &debug_image_info==0 + RETURN + &loaded_image_protocol=Data.LONG(D:&debug_image_info+0x04); + &image_base=Data.LONG(D:&loaded_image_protocol+0x20); + GOSUB pe_headersize &image_base + ENTRY &header_size + &image_load_address=&image_base+&header_size + GOSUB load_symbol_file &image_base &image_load_address + &index=&index+0x4 + ) + + RETURN diff --git a/BeagleBoardPkg/Debugger_scripts/trace32_load_symbols_cygwin.cmm b/BeagleBoardPkg/Debugger_scripts/trace32_load_symbols_cygwin.cmm new file mode 100644 index 0000000000..011df5254d --- /dev/null +++ b/BeagleBoardPkg/Debugger_scripts/trace32_load_symbols_cygwin.cmm @@ -0,0 +1,188 @@ +// +// Copyright (c) 2008-2009, Apple Inc. All rights reserved. +// +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// + + ENTRY &ram_start &ram_size + + ;If system is running then stop the execution so we can load symbols. + break + + ;Reset all windows + WINPAGE.RESET + + AREA.Reset + AREA.Create SYMBOL 300. 100. + AREA.View SYMBOL + AREA.Select SYMBOL + SYS.Option BE OFF + + ; Added based on suggestion from Lauterbach support. + MMU.TABLEWALK ON + MMU.ON + + GOSUB load_symbols &ram_start &ram_size + + ;Open some windows. + WINPOS 83.125 29.063 48. 9. 0. 0. W003 + Register + + WINPOS 83.25 10. 48. 9. 0. 1. W002 + Var.Local + + END + +find_system_table: + ENTRY &mem_start &mem_size + &mem_ptr=&mem_start+&mem_size + RPT + ( + &mem_ptr=&mem_ptr-0x400000 // 4 MB + &word1=Data.LONG(D:&mem_ptr) + &word2=Data.LONG(D:&mem_ptr+0x04) + IF &word1==0x20494249 + ( + IF &word2==0x54535953 + ( + &result=Data.LONG(D:&mem_ptr+0x08) + RETURN &result + ) + ) + ) + WHILE &mem_ptr>&mem_start + &result=0 + RETURN &result + +compare_guid: + ENTRY &guid + IF Data.LONG(D:&guid)==0x49152E77 + ( + IF Data.LONG(D:&guid+0x04)==0x47641ADA + ( + IF Data.LONG(D:&guid+0x08)==0xFE7AA2B7 + ( + IF Data.LONG(D:&guid+0x0C)==0x8B5ED9FE + ( + RETURN 0 + ) + ) + ) + ) + RETURN 1 + +find_debug_info_table_header: + ENTRY &system_table + &config_table_entries=Data.LONG(D:&system_table+0x40) + &config_table_pointer=Data.LONG(D:&system_table+0x44) + RPT &config_table_entries + ( + GOSUB compare_guid &config_table_pointer + ENTRY &result + IF &result==0 + ( + &result=Data.LONG(D:&config_table_pointer+0x10) + RETURN &result + ) + &config_table_pointer=&config_table_pointer+0x14 + ) + RETURN 0; + +valid_pe_header: + ENTRY &header + IF Data.BYTE(D:&header+0x00)==0x4D + ( + IF Data.BYTE(D:&header+0x01)==0x5A + ( + IF Data.BYTE(D:&header+0x80)==0x50 + ( + IF Data.BYTE(D:&header+0x81)==0x45 + ( + RETURN 1 + ) + ) + ) + ) + RETURN 0 + +get_file_string: + ENTRY &stringOffset + + local &string + + &more_string=data.string(d:&stringOffset) + + if (string.len("&more_string")>=128.) + ( + &string="&string"+"&more_string" + &stringOffset=&stringOffset+string.len("&more_string") + + //Get remaining file string + GOSUB get_file_string &stringOffset + ENTRY &more_string + &string="&string"+"&more_string" + ) + else + ( + &string="&string"+"&more_string" + &more_string="" + ) + RETURN &string + +load_symbol_file: + ENTRY &header &load_address + GOSUB valid_pe_header &header + ENTRY &result + + IF &result==1 + ( + &debugOffset=Data.LONG(D:&header+0x0128) + &stringOffset=&header+&debugOffset+0x002C + + &stringOffset=&stringOffset+11. + + GOSUB get_file_string &stringOffset + ENTRY &filestring + + &filestring="c:"+"&filestring" + + PRINT "&filestring 0x" &load_address + Data.load.elf &filestring &load_address /nocode /noclear + ) + RETURN + +pe_headersize: + ENTRY &header; + RETURN Data.LONG(D:&header+0x00AC) + +load_symbols: + ENTRY &mem_start &mem_size + GOSUB find_system_table &mem_start &mem_size + ENTRY &system_table + GOSUB find_debug_info_table_header &system_table + ENTRY &debug_info_table_header + &debug_info_table=Data.LONG(D:&debug_info_table_header+0x08) + &debug_info_table_size=Data.LONG(D:&debug_info_table_header+0x04) + &index=0 + RPT &debug_info_table_size + ( + &debug_image_info=Data.LONG(D:&debug_info_table+&index) + IF &debug_image_info==0 + RETURN + &loaded_image_protocol=Data.LONG(D:&debug_image_info+0x04); + &image_base=Data.LONG(D:&loaded_image_protocol+0x20); + GOSUB pe_headersize &image_base + ENTRY &header_size + &image_load_address=&image_base+&header_size + GOSUB load_symbol_file &image_base &image_load_address + &index=&index+0x4 + ) + + RETURN + \ No newline at end of file diff --git a/BeagleBoardPkg/Flash/Flash.c b/BeagleBoardPkg/Flash/Flash.c new file mode 100644 index 0000000000..26a381aa2a --- /dev/null +++ b/BeagleBoardPkg/Flash/Flash.c @@ -0,0 +1,748 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "Flash.h" + +NAND_PART_INFO_TABLE gNandPartInfoTable[1] = { + { 0x2C, 0xBA, 17, 11 } +}; + +NAND_FLASH_INFO *gNandFlashInfo = NULL; +UINT8 *gEccCode; +UINTN gNum512BytesChunks = 0; + +// +// Device path for SemiHosting. It contains our autogened Caller ID GUID. +// +typedef struct { + VENDOR_DEVICE_PATH Guid; + EFI_DEVICE_PATH_PROTOCOL End; +} FLASH_DEVICE_PATH; + +FLASH_DEVICE_PATH gDevicePath = { + { + { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, sizeof (VENDOR_DEVICE_PATH), 0 }, + EFI_CALLER_ID_GUID + }, + { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, sizeof (EFI_DEVICE_PATH_PROTOCOL), 0} +}; + + +//Actual page address = Column address + Page address + Block address. +UINTN +GetActualPageAddressInBytes ( + UINTN BlockIndex, + UINTN PageIndex +) +{ + //BlockAddressStart = Start of the Block address in actual NAND + //PageAddressStart = Start of the Page address in actual NAND + return ((BlockIndex << gNandFlashInfo->BlockAddressStart) + (PageIndex << gNandFlashInfo->PageAddressStart)); +} + +VOID +NandSendCommand ( + UINT8 Command +) +{ + MmioWrite16(GPMC_NAND_COMMAND_0, Command); +} + +VOID +NandSendAddress ( + UINT8 Address +) +{ + MmioWrite16(GPMC_NAND_ADDRESS_0, Address); +} + +UINT16 +NandReadStatus ( + VOID + ) +{ + //Send READ STATUS command + NandSendCommand(READ_STATUS_CMD); + + //Read status. + return MmioRead16(GPMC_NAND_DATA_0); +} + +VOID +NandSendAddressCycles ( + UINTN Address +) +{ + //Column address + NandSendAddress(Address & 0xff); + Address >>= 8; + + //Column address + NandSendAddress(Address & 0x07); + Address >>= 3; + + //Page and Block address + NandSendAddress(Address & 0xff); + Address >>= 8; + + //Block address + NandSendAddress(Address & 0xff); + Address >>= 8; + + //Block address + NandSendAddress(Address & 0x01); +} + +VOID +GpmcInit ( + VOID + ) +{ + //Enable Smart-idle mode. + MmioWrite32(GPMC_SYSCONFIG, SMARTIDLEMODE); + + //Set IRQSTATUS and IRQENABLE to the reset value + MmioWrite32(GPMC_IRQSTATUS, 0x0); + MmioWrite32(GPMC_IRQENABLE, 0x0); + + //Disable GPMC timeout control. + MmioWrite32(GPMC_TIMEOUT_CONTROL, TIMEOUTDISABLE); + + //Set WRITEPROTECT bit to enable write access. + MmioWrite32(GPMC_CONFIG, WRITEPROTECT_HIGH); + + //NOTE: Following GPMC_CONFIGi_0 register settings are taken from u-boot memory dump. + MmioWrite32(GPMC_CONFIG1_0, DEVICETYPE_NAND | DEVICESIZE_X16); + MmioWrite32(GPMC_CONFIG2_0, CSRDOFFTIME | CSWROFFTIME); + MmioWrite32(GPMC_CONFIG3_0, ADVRDOFFTIME | ADVWROFFTIME); + MmioWrite32(GPMC_CONFIG4_0, OEONTIME | OEOFFTIME | WEONTIME | WEOFFTIME); + MmioWrite32(GPMC_CONFIG5_0, RDCYCLETIME | WRCYCLETIME | RDACCESSTIME | PAGEBURSTACCESSTIME); + MmioWrite32(GPMC_CONFIG6_0, WRACCESSTIME | WRDATAONADMUXBUS | CYCLE2CYCLEDELAY | CYCLE2CYCLESAMECSEN); + MmioWrite32(GPMC_CONFIG7_0, MASKADDRESS_128MB | CSVALID | BASEADDRESS); +} + +EFI_STATUS +NandDetectPart ( + VOID +) +{ + UINT8 NandInfo = 0; + UINT8 PartInfo[5]; + UINTN Index; + BOOLEAN Found = FALSE; + + //Send READ ID command + NandSendCommand(READ_ID_CMD); + + //Send one address cycle. + NandSendAddress(0); + + //Read 5-bytes to idenfity code programmed into the NAND flash devices. + //BYTE 0 = Manufacture ID + //Byte 1 = Device ID + //Byte 2, 3, 4 = Nand part specific information (Page size, Block size etc) + for (Index = 0; Index < sizeof(PartInfo); Index++) { + PartInfo[Index] = MmioRead16(GPMC_NAND_DATA_0); + } + + //Check if the ManufactureId and DeviceId are part of the currently supported nand parts. + for (Index = 0; Index < sizeof(gNandPartInfoTable)/sizeof(NAND_PART_INFO_TABLE); Index++) { + if (gNandPartInfoTable[Index].ManufactureId == PartInfo[0] && gNandPartInfoTable[Index].DeviceId == PartInfo[1]) { + gNandFlashInfo->BlockAddressStart = gNandPartInfoTable[Index].BlockAddressStart; + gNandFlashInfo->PageAddressStart = gNandPartInfoTable[Index].PageAddressStart; + Found = TRUE; + break; + } + } + + if (Found == FALSE) { + DEBUG ((EFI_D_ERROR, "Nand part is not currently supported. Manufacture id: %x, Device id: %x\n", PartInfo[0], PartInfo[1])); + return EFI_NOT_FOUND; + } + + //Populate NAND_FLASH_INFO based on the result of READ ID command. + gNandFlashInfo->ManufactureId = PartInfo[0]; + gNandFlashInfo->DeviceId = PartInfo[1]; + NandInfo = PartInfo[3]; + + if (PAGE_SIZE(NandInfo) == PAGE_SIZE_2K_VAL) { + gNandFlashInfo->PageSize = PAGE_SIZE_2K; + } else { + DEBUG ((EFI_D_ERROR, "Unknown Page size.\n")); + return EFI_DEVICE_ERROR; + } + + if (SPARE_AREA_SIZE(NandInfo) == SPARE_AREA_SIZE_64B_VAL) { + gNandFlashInfo->SparePageSize = SPARE_AREA_SIZE_64B; + } else { + DEBUG ((EFI_D_ERROR, "Unknown Spare area size.\n")); + return EFI_DEVICE_ERROR; + } + + if (BLOCK_SIZE(NandInfo) == BLOCK_SIZE_128K_VAL) { + gNandFlashInfo->BlockSize = BLOCK_SIZE_128K; + } else { + DEBUG ((EFI_D_ERROR, "Unknown Block size.\n")); + return EFI_DEVICE_ERROR; + } + + if (ORGANIZATION(NandInfo) == ORGANIZATION_X8) { + gNandFlashInfo->Organization = 0; + } else if (ORGANIZATION(NandInfo) == ORGANIZATION_X16) { + gNandFlashInfo->Organization = 1; + } + + //Calculate total number of blocks. + gNandFlashInfo->NumPagesPerBlock = DivU64x32(gNandFlashInfo->BlockSize, gNandFlashInfo->PageSize); + + return EFI_SUCCESS; +} + +VOID +NandConfigureEcc ( + VOID + ) +{ + //Define ECC size 0 and size 1 to 512 bytes + MmioWrite32(GPMC_ECC_SIZE_CONFIG, (ECCSIZE0_512BYTES | ECCSIZE1_512BYTES)); +} + +VOID +NandEnableEcc ( + VOID + ) +{ + //Clear all the ECC result registers and select ECC result register 1 + MmioWrite32(GPMC_ECC_CONTROL, (ECCCLEAR | ECCPOINTER_REG1)); + + //Enable ECC engine on CS0 + MmioWrite32(GPMC_ECC_CONFIG, (ECCENABLE | ECCCS_0 | ECC16B)); +} + +VOID +NandDisableEcc ( + VOID + ) +{ + //Turn off ECC engine. + MmioWrite32(GPMC_ECC_CONFIG, ECCDISABLE); +} + +VOID +NandCalculateEcc ( + VOID + ) +{ + UINTN Index; + UINTN EccResultRegister; + UINTN EccResult; + + //Capture 32-bit ECC result for each 512-bytes chunk. + //In our case PageSize is 2K so read ECC1-ECC4 result registers and + //generate total of 12-bytes of ECC code for the particular page. + + EccResultRegister = GPMC_ECC1_RESULT; + + for (Index = 0; Index < gNum512BytesChunks; Index++) { + + EccResult = MmioRead32(EccResultRegister); + + //Calculate ECC code from 32-bit ECC result value. + //NOTE: Following calculation is not part of TRM. We got this information + //from Beagleboard mailing list. + gEccCode[Index * 3] = EccResult & 0xFF; + gEccCode[(Index * 3) + 1] = (EccResult >> 16) & 0xFF; + gEccCode[(Index * 3) + 2] = (((EccResult >> 20) & 0xF0) | ((EccResult >> 8) & 0x0F)); + + //Point to next ECC result register. + EccResultRegister += 4; + } +} + +EFI_STATUS +NandReadPage ( + IN UINTN BlockIndex, + IN UINTN PageIndex, + OUT VOID *Buffer, + OUT UINT8 *SpareBuffer +) +{ + UINTN Address; + UINTN Index; + UINTN NumMainAreaWords = (gNandFlashInfo->PageSize/2); + UINTN NumSpareAreaWords = (gNandFlashInfo->SparePageSize/2); + UINT16 *MainAreaWordBuffer = Buffer; + UINT16 *SpareAreaWordBuffer = (UINT16 *)SpareBuffer; + UINTN Timeout = MAX_RETRY_COUNT; + + //Generate device address in bytes to access specific block and page index + Address = GetActualPageAddressInBytes(BlockIndex, PageIndex); + + //Send READ command + NandSendCommand(PAGE_READ_CMD); + + //Send 5 Address cycles to access specific device address + NandSendAddressCycles(Address); + + //Send READ CONFIRM command + NandSendCommand(PAGE_READ_CONFIRM_CMD); + + //Poll till device is busy. + while (Timeout) { + if ((NandReadStatus() & NAND_READY) == NAND_READY) { + break; + } + Timeout--; + } + + if (Timeout == 0) { + DEBUG ((EFI_D_ERROR, "Read page timed out.\n")); + return EFI_TIMEOUT; + } + + //Reissue READ command + NandSendCommand(PAGE_READ_CMD); + + //Enable ECC engine. + NandEnableEcc(); + + //Read data into the buffer. + for (Index = 0; Index < NumMainAreaWords; Index++) { + *MainAreaWordBuffer++ = MmioRead16(GPMC_NAND_DATA_0); + } + + //Read spare area into the buffer. + for (Index = 0; Index < NumSpareAreaWords; Index++) { + *SpareAreaWordBuffer++ = MmioRead16(GPMC_NAND_DATA_0); + } + + //Calculate ECC. + NandCalculateEcc(); + + //Turn off ECC engine. + NandDisableEcc(); + + //Perform ECC correction. + //Need to implement.. + + return EFI_SUCCESS; +} + +EFI_STATUS +NandWritePage ( + IN UINTN BlockIndex, + IN UINTN PageIndex, + OUT VOID *Buffer, + IN UINT8 *SpareBuffer +) +{ + UINTN Address; + UINT16 *MainAreaWordBuffer = Buffer; + UINT16 *SpareAreaWordBuffer = (UINT16 *)SpareBuffer; + UINTN Index; + UINTN NandStatus; + UINTN Timeout = MAX_RETRY_COUNT; + + //Generate device address in bytes to access specific block and page index + Address = GetActualPageAddressInBytes(BlockIndex, PageIndex); + + //Send SERIAL DATA INPUT command + NandSendCommand(PROGRAM_PAGE_CMD); + + //Send 5 Address cycles to access specific device address + NandSendAddressCycles(Address); + + //Enable ECC engine. + NandEnableEcc(); + + //Data input from Buffer + for (Index = 0; Index < (gNandFlashInfo->PageSize/2); Index++) { + MmioWrite16(GPMC_NAND_DATA_0, *MainAreaWordBuffer++); + + //After each write access, device has to wait to accept data. + //Currently we may not be programming proper timing parameters to + //the GPMC_CONFIGi_0 registers and we would need to figure that out. + //Without following delay, page programming fails. + gBS->Stall(1); + } + + //Calculate ECC. + NandCalculateEcc(); + + //Turn off ECC engine. + NandDisableEcc(); + + //Prepare Spare area buffer with ECC codes. + SetMem(SpareBuffer, gNandFlashInfo->SparePageSize, 0xFF); + CopyMem(&SpareBuffer[ECC_POSITION], gEccCode, gNum512BytesChunks * 3); + + //Program spare area with calculated ECC. + for (Index = 0; Index < (gNandFlashInfo->SparePageSize/2); Index++) { + MmioWrite16(GPMC_NAND_DATA_0, *SpareAreaWordBuffer++); + } + + //Send PROGRAM command + NandSendCommand(PROGRAM_PAGE_CONFIRM_CMD); + + //Poll till device is busy. + while (Timeout) { + NandStatus = NandReadStatus(); + if ((NandStatus & NAND_READY) == NAND_READY) { + break; + } + Timeout--; + } + + if (Timeout == 0) { + DEBUG ((EFI_D_ERROR, "Program page timed out.\n")); + return EFI_TIMEOUT; + } + + //Bit0 indicates Pass/Fail status + if (NandStatus & NAND_FAILURE) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +NandEraseBlock ( + IN UINTN BlockIndex +) +{ + UINTN Address; + UINTN NandStatus; + UINTN Timeout = MAX_RETRY_COUNT; + + //Generate device address in bytes to access specific block and page index + Address = GetActualPageAddressInBytes(BlockIndex, 0); + + //Send ERASE SETUP command + NandSendCommand(BLOCK_ERASE_CMD); + + //Send 3 address cycles to device to access Page address and Block address + Address >>= 11; //Ignore column addresses + + NandSendAddress(Address & 0xff); + Address >>= 8; + + NandSendAddress(Address & 0xff); + Address >>= 8; + + NandSendAddress(Address & 0xff); + + //Send ERASE CONFIRM command + NandSendCommand(BLOCK_ERASE_CONFIRM_CMD); + + //Poll till device is busy. + while (Timeout) { + NandStatus = NandReadStatus(); + if ((NandStatus & NAND_READY) == NAND_READY) { + break; + } + Timeout--; + gBS->Stall(1); + } + + if (Timeout == 0) { + DEBUG ((EFI_D_ERROR, "Erase block timed out for Block: %d.\n", BlockIndex)); + return EFI_TIMEOUT; + } + + //Bit0 indicates Pass/Fail status + if (NandStatus & NAND_FAILURE) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +NandReadBlock ( + IN UINTN StartBlockIndex, + IN UINTN EndBlockIndex, + OUT VOID *Buffer, + OUT VOID *SpareBuffer +) +{ + UINTN BlockIndex; + UINTN PageIndex; + EFI_STATUS Status = EFI_SUCCESS; + + for (BlockIndex = StartBlockIndex; BlockIndex <= EndBlockIndex; BlockIndex++) { + //For each block read number of pages + for (PageIndex = 0; PageIndex < gNandFlashInfo->NumPagesPerBlock; PageIndex++) { + Status = NandReadPage(BlockIndex, PageIndex, Buffer, SpareBuffer); + if (EFI_ERROR(Status)) { + return Status; + } + Buffer = ((UINT8 *)Buffer + gNandFlashInfo->PageSize); + } + } + + return Status; +} + +EFI_STATUS +NandWriteBlock ( + IN UINTN StartBlockIndex, + IN UINTN EndBlockIndex, + OUT VOID *Buffer, + OUT VOID *SpareBuffer + ) +{ + UINTN BlockIndex; + UINTN PageIndex; + EFI_STATUS Status = EFI_SUCCESS; + + for (BlockIndex = StartBlockIndex; BlockIndex <= EndBlockIndex; BlockIndex++) { + //Page programming. + for (PageIndex = 0; PageIndex < gNandFlashInfo->NumPagesPerBlock; PageIndex++) { + Status = NandWritePage(BlockIndex, PageIndex, Buffer, SpareBuffer); + if (EFI_ERROR(Status)) { + return Status; + } + Buffer = ((UINT8 *)Buffer + gNandFlashInfo->PageSize); + } + } + + return Status; +} + +EFI_STATUS +EFIAPI +NandFlashReset ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + UINTN BusyStall = 50; // microSeconds + UINTN ResetBusyTimeout = (1000000 / BusyStall); // 1 Second + + //Send RESET command to device. + NandSendCommand(RESET_CMD); + + //Wait for 1ms before we check status register. + gBS->Stall(1000); + + //Check BIT#5 & BIT#6 in Status register to make sure RESET is done. + while ((NandReadStatus() & NAND_RESET_STATUS) != NAND_RESET_STATUS) { + + //In case of extended verification, wait for extended amount of time + //to make sure device is reset. + if (ExtendedVerification) { + if (ResetBusyTimeout == 0) { + return EFI_DEVICE_ERROR; + } + + gBS->Stall(BusyStall); + ResetBusyTimeout--; + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +NandFlashReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + UINTN NumBlocks; + UINTN EndBlockIndex; + EFI_STATUS Status; + UINT8 *SpareBuffer = NULL; + + if (Buffer == NULL) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + + if (Lba > LAST_BLOCK) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + + if ((BufferSize % gNandFlashInfo->BlockSize) != 0) { + Status = EFI_BAD_BUFFER_SIZE; + goto exit; + } + + NumBlocks = DivU64x32(BufferSize, gNandFlashInfo->BlockSize); + EndBlockIndex = ((UINTN)Lba + NumBlocks) - 1; + + SpareBuffer = (UINT8 *)AllocatePool(gNandFlashInfo->SparePageSize); + if (SpareBuffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto exit; + } + + //Read block + Status = NandReadBlock((UINTN)Lba, EndBlockIndex, Buffer, SpareBuffer); + if (EFI_ERROR(Status)) { + DEBUG((EFI_D_ERROR, "Read block fails: %x\n", Status)); + goto exit; + } + +exit: + if (SpareBuffer != NULL) { + FreePool (SpareBuffer); + } + + return Status; +} + +EFI_STATUS +EFIAPI +NandFlashWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + IN VOID *Buffer + ) +{ + UINTN BlockIndex; + UINTN NumBlocks; + UINTN EndBlockIndex; + EFI_STATUS Status; + UINT8 *SpareBuffer = NULL; + + if (Buffer == NULL) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + + if (Lba > LAST_BLOCK) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + + if ((BufferSize % gNandFlashInfo->BlockSize) != 0) { + Status = EFI_BAD_BUFFER_SIZE; + goto exit; + } + + NumBlocks = DivU64x32(BufferSize, gNandFlashInfo->BlockSize); + EndBlockIndex = ((UINTN)Lba + NumBlocks) - 1; + + SpareBuffer = (UINT8 *)AllocatePool(gNandFlashInfo->SparePageSize); + if (SpareBuffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto exit; + } + + // Erase block + for (BlockIndex = (UINTN)Lba; BlockIndex <= EndBlockIndex; BlockIndex++) { + Status = NandEraseBlock(BlockIndex); + if (EFI_ERROR(Status)) { + DEBUG((EFI_D_ERROR, "Erase block failed. Status: %x\n", Status)); + goto exit; + } + } + + // Program data + Status = NandWriteBlock((UINTN)Lba, EndBlockIndex, Buffer, SpareBuffer); + if (EFI_ERROR(Status)) { + DEBUG((EFI_D_ERROR, "Block write fails: %x\n", Status)); + goto exit; + } + +exit: + if (SpareBuffer != NULL) { + FreePool (SpareBuffer); + } + + return Status; +} + +EFI_STATUS +EFIAPI +NandFlashFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ) +{ + return EFI_SUCCESS; +} + +EFI_BLOCK_IO_PROTOCOL BlockIo = +{ + EFI_BLOCK_IO_INTERFACE_REVISION, // Revision + &NandFlashMedia, // *Media + NandFlashReset, // Reset + NandFlashReadBlocks, // ReadBlocks + NandFlashWriteBlocks, // WriteBlocks + NandFlashFlushBlocks // FlushBlocks +}; + +EFI_STATUS +NandFlashInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + gNandFlashInfo = (NAND_FLASH_INFO *)AllocateZeroPool(sizeof(NAND_FLASH_INFO)); + + //Initialize GPMC module. + GpmcInit(); + + //Reset NAND part + NandFlashReset(&BlockIo, FALSE); + + //Detect NAND part and populate gNandFlashInfo structure + Status = NandDetectPart(); + if (EFI_ERROR(Status)) { + DEBUG((EFI_D_ERROR, "Nand part id detection failure: Status: %x\n", Status)); + return Status; + } + + //Count total number of 512Bytes chunk based on the page size. + if (gNandFlashInfo->PageSize == PAGE_SIZE_512B) { + gNum512BytesChunks = 1; + } else if (gNandFlashInfo->PageSize == PAGE_SIZE_2K) { + gNum512BytesChunks = 4; + } else if (gNandFlashInfo->PageSize == PAGE_SIZE_4K) { + gNum512BytesChunks = 8; + } + + gEccCode = (UINT8 *)AllocatePool(gNum512BytesChunks * 3); + if (gEccCode == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + //Configure ECC + NandConfigureEcc(); + + //Patch EFI_BLOCK_IO_MEDIA structure. + NandFlashMedia.BlockSize = gNandFlashInfo->BlockSize; + NandFlashMedia.LastBlock = LAST_BLOCK; + + //Publish BlockIO. + Status = gBS->InstallMultipleProtocolInterfaces ( + &ImageHandle, + &gEfiBlockIoProtocolGuid, &BlockIo, + &gEfiDevicePathProtocolGuid, &gDevicePath, + NULL + ); + return Status; +} + diff --git a/BeagleBoardPkg/Flash/Flash.h b/BeagleBoardPkg/Flash/Flash.h new file mode 100644 index 0000000000..533e416c7e --- /dev/null +++ b/BeagleBoardPkg/Flash/Flash.h @@ -0,0 +1,118 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef FLASH_H +#define FLASH_H + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define PAGE_SIZE(x) ((x) & 0x01) +#define PAGE_SIZE_2K_VAL (0x01UL) + +#define SPARE_AREA_SIZE(x) (((x) >> 2) & 0x01) +#define SPARE_AREA_SIZE_64B_VAL (0x1UL) + +#define BLOCK_SIZE(x) (((x) >> 4) & 0x01) +#define BLOCK_SIZE_128K_VAL (0x01UL) + +#define ORGANIZATION(x) (((x) >> 6) & 0x01) +#define ORGANIZATION_X8 (0x0UL) +#define ORGANIZATION_X16 (0x1UL) + +#define PAGE_SIZE_512B (512) +#define PAGE_SIZE_2K (2048) +#define PAGE_SIZE_4K (4096) +#define SPARE_AREA_SIZE_16B (16) +#define SPARE_AREA_SIZE_64B (64) + +#define BLOCK_SIZE_16K (16*1024) +#define BLOCK_SIZE_128K (128*1024) + +#define BLOCK_COUNT (2048) +#define LAST_BLOCK (BLOCK_COUNT - 1) + +#define ECC_POSITION 2 + +//List of commands. +#define RESET_CMD 0xFF +#define READ_ID_CMD 0x90 + +#define READ_STATUS_CMD 0x70 + +#define PAGE_READ_CMD 0x00 +#define PAGE_READ_CONFIRM_CMD 0x30 + +#define BLOCK_ERASE_CMD 0x60 +#define BLOCK_ERASE_CONFIRM_CMD 0xD0 + +#define PROGRAM_PAGE_CMD 0x80 +#define PROGRAM_PAGE_CONFIRM_CMD 0x10 + +//Nand status register bit definition +#define NAND_SUCCESS (0x0UL << 0) +#define NAND_FAILURE (0x1UL << 0) + +#define NAND_BUSY (0x0UL << 6) +#define NAND_READY (0x1UL << 6) + +#define NAND_RESET_STATUS (0x60UL << 0) + +#define MAX_RETRY_COUNT 1500 + +EFI_BLOCK_IO_MEDIA NandFlashMedia = { + SIGNATURE_32('n','a','n','d'), // MediaId + FALSE, // RemovableMedia + TRUE, // MediaPresent + TRUE, // LogicalPartition + FALSE, // ReadOnly + FALSE, // WriteCaching + 0, // BlockSize + 2, // IoAlign + 0, // Pad + 0 // LastBlock +}; + +typedef struct { + UINT8 ManufactureId; + UINT8 DeviceId; + UINT8 BlockAddressStart; //Start of the Block address in actual NAND + UINT8 PageAddressStart; //Start of the Page address in actual NAND +} NAND_PART_INFO_TABLE; + +typedef struct { + UINT8 ManufactureId; + UINT8 DeviceId; + UINT8 Organization; //x8 or x16 + UINT32 PageSize; + UINT32 SparePageSize; + UINT32 BlockSize; + UINT32 NumPagesPerBlock; + UINT8 BlockAddressStart; //Start of the Block address in actual NAND + UINT8 PageAddressStart; //Start of the Page address in actual NAND +} NAND_FLASH_INFO; + +#endif //FLASH_H diff --git a/BeagleBoardPkg/Flash/Flash.inf b/BeagleBoardPkg/Flash/Flash.inf new file mode 100644 index 0000000000..bb089850e1 --- /dev/null +++ b/BeagleBoardPkg/Flash/Flash.inf @@ -0,0 +1,36 @@ +#%HEADER% +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = NandFlash + FILE_GUID = 4d00ef14-c4e0-426b-81b7-30a00a14aad6 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = NandFlashInitialize + + +[Sources.common] + Flash.c + +[Packages] + MdePkg/MdePkg.dec + BeagleBoardPkg/BeagleBoardPkg.dec + +[LibraryClasses] + PcdLib + UefiLib + UefiDriverEntryPoint + MemoryAllocationLib + IoLib + +[Guids] + +[Protocols] + gEfiBlockIoProtocolGuid + gEfiCpuArchProtocolGuid + +[Pcd] + gBeagleBoardTokenSpaceGuid.PcdBeagleGpmcOffset + +[depex] + TRUE \ No newline at end of file diff --git a/BeagleBoardPkg/Gpio/Gpio.c b/BeagleBoardPkg/Gpio/Gpio.c new file mode 100644 index 0000000000..7bc5478933 --- /dev/null +++ b/BeagleBoardPkg/Gpio/Gpio.c @@ -0,0 +1,135 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include + +#include + +#include + +EFI_STATUS +Get ( + IN EMBEDDED_GPIO *This, + IN EMBEDDED_GPIO_PIN Gpio, + OUT UINTN *Value + ) +{ + UINTN Port; + UINTN Pin; + UINT32 DataInRegister; + + if (Value == NULL) + { + return EFI_UNSUPPORTED; + } + + Port = GPIO_PORT(Gpio); + Pin = GPIO_PIN(Gpio); + + DataInRegister = GpioBase(Port) + GPIO_DATAIN; + + if (MmioRead32(DataInRegister) & GPIO_DATAIN_MASK(Pin)) { + *Value = 1; + } else { + *Value = 0; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +Set ( + IN EMBEDDED_GPIO *This, + IN EMBEDDED_GPIO_PIN Gpio, + IN EMBEDDED_GPIO_MODE Mode + ) +{ + UINTN Port; + UINTN Pin; + UINT32 OutputEnableRegister; + UINT32 SetDataOutRegister; + UINT32 ClearDataOutRegister; + + Port = GPIO_PORT(Gpio); + Pin = GPIO_PIN(Gpio); + + OutputEnableRegister = GpioBase(Port) + GPIO_OE; + SetDataOutRegister = GpioBase(Port) + GPIO_SETDATAOUT; + ClearDataOutRegister = GpioBase(Port) + GPIO_CLEARDATAOUT; + + switch (Mode) + { + case GPIO_MODE_INPUT: + MmioAndThenOr32(OutputEnableRegister, ~GPIO_OE_MASK(Pin), GPIO_OE_INPUT(Pin)); + break; + + case GPIO_MODE_OUTPUT_0: + MmioWrite32(ClearDataOutRegister, GPIO_CLEARDATAOUT_BIT(Pin)); + MmioAndThenOr32(OutputEnableRegister, ~GPIO_OE_MASK(Pin), GPIO_OE_OUTPUT(Pin)); + break; + + case GPIO_MODE_OUTPUT_1: + MmioWrite32(SetDataOutRegister, GPIO_SETDATAOUT_BIT(Pin)); + MmioAndThenOr32(OutputEnableRegister, ~GPIO_OE_MASK(Pin), GPIO_OE_OUTPUT(Pin)); + break; + + default: + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +GetMode ( + IN EMBEDDED_GPIO *This, + IN EMBEDDED_GPIO_PIN Gpio, + OUT EMBEDDED_GPIO_MODE *Mode + ) +{ + return EFI_UNSUPPORTED; +} + +EFI_STATUS +SetPull ( + IN EMBEDDED_GPIO *This, + IN EMBEDDED_GPIO_PIN Gpio, + IN EMBEDDED_GPIO_PULL Direction + ) +{ + return EFI_UNSUPPORTED; +} + +EMBEDDED_GPIO Gpio = { + Get, + Set, + GetMode, + SetPull +}; + +EFI_STATUS +GpioInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = gBS->InstallMultipleProtocolInterfaces(&ImageHandle, &gEmbeddedGpioProtocolGuid, &Gpio, NULL); + return Status; +} diff --git a/BeagleBoardPkg/Gpio/Gpio.inf b/BeagleBoardPkg/Gpio/Gpio.inf new file mode 100644 index 0000000000..c903ed9052 --- /dev/null +++ b/BeagleBoardPkg/Gpio/Gpio.inf @@ -0,0 +1,33 @@ +#%HEADER% +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = Gpio + FILE_GUID = E7D9CAE1-6930-46E3-BDF9-0027446E7DF2 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = GpioInitialize + + +[Sources.common] + Gpio.c + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + BeagleBoardPkg/BeagleBoardPkg.dec + +[LibraryClasses] + IoLib + UefiDriverEntryPoint + OmapLib + +[Guids] + +[Protocols] + gEmbeddedGpioProtocolGuid + +[Pcd] + +[depex] + TRUE \ No newline at end of file diff --git a/BeagleBoardPkg/Include/Library/BeagleBoardSystemLib.h b/BeagleBoardPkg/Include/Library/BeagleBoardSystemLib.h new file mode 100644 index 0000000000..93a6113262 --- /dev/null +++ b/BeagleBoardPkg/Include/Library/BeagleBoardSystemLib.h @@ -0,0 +1,36 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __BEAGLEBOARD_YSTEMLIB_H__ +#define __BEAGLEBOARD_YSTEMLIB_H__ + +VOID +EFIAPI +GoLittleEndian ( + UINTN ImageAddress + ); + +VOID +EFIAPI +ResetSystem ( + IN EFI_RESET_TYPE ResetType + ); + +VOID +EFIAPI +ShutdownEfi ( + VOID + ); + +#endif // __BEAGLEBOARD_YSTEMLIB_H__ diff --git a/BeagleBoardPkg/Include/Library/OmapLib.h b/BeagleBoardPkg/Include/Library/OmapLib.h new file mode 100644 index 0000000000..e2845ca7df --- /dev/null +++ b/BeagleBoardPkg/Include/Library/OmapLib.h @@ -0,0 +1,39 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __OMAPLIB_H__ +#define __OMAPLIB_H__ + +UINT32 +GpioBase ( + IN UINTN Port + ); + +UINT32 +TimerBase ( + IN UINTN Timer + ); + +UINTN +InterruptVectorForTimer ( + IN UINTN TImer + ); + +UINT32 +UartBase ( + IN UINTN Uart + ); + +#endif // __OMAPLIB_H__ + diff --git a/BeagleBoardPkg/Include/Omap3530/Omap3530.h b/BeagleBoardPkg/Include/Omap3530/Omap3530.h new file mode 100644 index 0000000000..7d3b011327 --- /dev/null +++ b/BeagleBoardPkg/Include/Omap3530/Omap3530.h @@ -0,0 +1,38 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __OMAP3530_H__ +#define __OMAP3530_H__ + +#include "Omap3530Gpio.h" +#include "Omap3530Interrupt.h" +#include "Omap3530Prcm.h" +#include "Omap3530Timer.h" +#include "Omap3530Uart.h" +#include "Omap3530Usb.h" +#include "Omap3530MMCHS.h" +#include "Omap3530I2c.h" +#include "Omap3530PadConfiguration.h" +#include "Omap3530Gpmc.h" + +//CONTROL_PBIAS_LITE +#define CONTROL_PBIAS_LITE 0x48002520 +#define PBIASLITEVMODE0 (0x1UL << 0) +#define PBIASLITEPWRDNZ0 (0x1UL << 1) +#define PBIASSPEEDCTRL0 (0x1UL << 2) +#define PBIASLITEVMODE1 (0x1UL << 8) +#define PBIASLITEWRDNZ1 (0x1UL << 9) + +#endif // __OMAP3530_H__ + diff --git a/BeagleBoardPkg/Include/Omap3530/Omap3530Gpio.h b/BeagleBoardPkg/Include/Omap3530/Omap3530Gpio.h new file mode 100644 index 0000000000..6e825a725c --- /dev/null +++ b/BeagleBoardPkg/Include/Omap3530/Omap3530Gpio.h @@ -0,0 +1,131 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __OMAP3530GPIO_H__ +#define __OMAP3530GPIO_H__ + +#define GPIO1_BASE (0x48310000) +#define GPIO2_BASE (0x49050000) +#define GPIO3_BASE (0x49052000) +#define GPIO4_BASE (0x49054000) +#define GPIO5_BASE (0x49056000) +#define GPIO6_BASE (0x49058000) + +#define GPIO_SYSCONFIG (0x0010) +#define GPIO_SYSSTATUS (0x0014) +#define GPIO_IRQSTATUS1 (0x0018) +#define GPIO_IRQENABLE1 (0x001C) +#define GPIO_WAKEUPENABLE (0x0020) +#define GPIO_IRQSTATUS2 (0x0028) +#define GPIO_IRQENABLE2 (0x002C) +#define GPIO_CTRL (0x0030) +#define GPIO_OE (0x0034) +#define GPIO_DATAIN (0x0038) +#define GPIO_DATAOUT (0x003C) +#define GPIO_LEVELDETECT0 (0x0040) +#define GPIO_LEVELDETECT1 (0x0044) +#define GPIO_RISINGDETECT (0x0048) +#define GPIO_FALLINGDETECT (0x004C) +#define GPIO_DEBOUNCENABLE (0x0050) +#define GPIO_DEBOUNCINGTIME (0x0054) +#define GPIO_CLEARIRQENABLE1 (0x0060) +#define GPIO_SETIRQENABLE1 (0x0064) +#define GPIO_CLEARIRQENABLE2 (0x0070) +#define GPIO_SETIRQENABLE2 (0x0074) +#define GPIO_CLEARWKUENA (0x0080) +#define GPIO_SETWKUENA (0x0084) +#define GPIO_CLEARDATAOUT (0x0090) +#define GPIO_SETDATAOUT (0x0094) + +#define GPIO_SYSCONFIG_IDLEMODE_MASK (3UL << 3) +#define GPIO_SYSCONFIG_IDLEMODE_FORCE (0UL << 3) +#define GPIO_SYSCONFIG_IDLEMODE_NONE (1UL << 3) +#define GPIO_SYSCONFIG_IDLEMODE_SMART (2UL << 3) +#define GPIO_SYSCONFIG_ENAWAKEUP_MASK (1UL << 2) +#define GPIO_SYSCONFIG_ENAWAKEUP_DISABLE (0UL << 2) +#define GPIO_SYSCONFIG_ENAWAKEUP_ENABLE (1UL << 2) +#define GPIO_SYSCONFIG_SOFTRESET_MASK (1UL << 1) +#define GPIO_SYSCONFIG_SOFTRESET_NORMAL (0UL << 1) +#define GPIO_SYSCONFIG_SOFTRESET_RESET (1UL << 1) +#define GPIO_SYSCONFIG_AUTOIDLE_MASK (1UL << 0) +#define GPIO_SYSCONFIG_AUTOIDLE_FREE_RUN (0UL << 0) +#define GPIO_SYSCONFIG_AUTOIDLE_ON (1UL << 0) + +#define GPIO_SYSSTATUS_RESETDONE_MASK (1UL << 0) +#define GPIO_SYSSTATUS_RESETDONE_ONGOING (0UL << 0) +#define GPIO_SYSSTATUS_RESETDONE_COMPLETE (1UL << 0) + +#define GPIO_IRQSTATUS_MASK(x) (1UL << (x)) +#define GPIO_IRQSTATUS_NOT_TRIGGERED(x) (0UL << (x)) +#define GPIO_IRQSTATUS_TRIGGERED(x) (1UL << (x)) +#define GPIO_IRQSTATUS_CLEAR(x) (1UL << (x)) + +#define GPIO_IRQENABLE_MASK(x) (1UL << (x)) +#define GPIO_IRQENABLE_DISABLE(x) (0UL << (x)) +#define GPIO_IRQENABLE_ENABLE(x) (1UL << (x)) + +#define GPIO_WAKEUPENABLE_MASK(x) (1UL << (x)) +#define GPIO_WAKEUPENABLE_DISABLE(x) (0UL << (x)) +#define GPIO_WAKEUPENABLE_ENABLE(x) (1UL << (x)) + +#define GPIO_CTRL_GATINGRATIO_MASK (3UL << 1) +#define GPIO_CTRL_GATINGRATIO_DIV_1 (0UL << 1) +#define GPIO_CTRL_GATINGRATIO_DIV_2 (1UL << 1) +#define GPIO_CTRL_GATINGRATIO_DIV_4 (2UL << 1) +#define GPIO_CTRL_GATINGRATIO_DIV_8 (3UL << 1) +#define GPIO_CTRL_DISABLEMODULE_MASK (1UL << 0) +#define GPIO_CTRL_DISABLEMODULE_ENABLE (0UL << 0) +#define GPIO_CTRL_DISABLEMODULE_DISABLE (1UL << 0) + +#define GPIO_OE_MASK(x) (1UL << (x)) +#define GPIO_OE_OUTPUT(x) (0UL << (x)) +#define GPIO_OE_INPUT(x) (1UL << (x)) + +#define GPIO_DATAIN_MASK(x) (1UL << (x)) + +#define GPIO_DATAOUT_MASK(x) (1UL << (x)) + +#define GPIO_LEVELDETECT_MASK(x) (1UL << (x)) +#define GPIO_LEVELDETECT_DISABLE(x) (0UL << (x)) +#define GPIO_LEVELDETECT_ENABLE(x) (1UL << (x)) + +#define GPIO_RISINGDETECT_MASK(x) (1UL << (x)) +#define GPIO_RISINGDETECT_DISABLE(x) (0UL << (x)) +#define GPIO_RISINGDETECT_ENABLE(x) (1UL << (x)) + +#define GPIO_FALLINGDETECT_MASK(x) (1UL << (x)) +#define GPIO_FALLINGDETECT_DISABLE(x) (0UL << (x)) +#define GPIO_FALLINGDETECT_ENABLE(x) (1UL << (x)) + +#define GPIO_DEBOUNCENABLE_MASK(x) (1UL << (x)) +#define GPIO_DEBOUNCENABLE_DISABLE(x) (0UL << (x)) +#define GPIO_DEBOUNCENABLE_ENABLE(x) (1UL << (x)) + +#define GPIO_DEBOUNCINGTIME_MASK (0xFF) +#define GPIO_DEBOUNCINGTIME_US(x) ((((x) / 31) - 1) & GPIO_DEBOUNCINGTIME_MASK) + +#define GPIO_CLEARIRQENABLE_BIT(x) (1UL << (x)) + +#define GPIO_SETIRQENABLE_BIT(x) (1UL << (x)) + +#define GPIO_CLEARWKUENA_BIT(x) (1UL << (x)) + +#define GPIO_SETWKUENA_BIT(x) (1UL << (x)) + +#define GPIO_CLEARDATAOUT_BIT(x) (1UL << (x)) + +#define GPIO_SETDATAOUT_BIT(x) (1UL << (x)) + +#endif // __OMAP3530GPIO_H__ + diff --git a/BeagleBoardPkg/Include/Omap3530/Omap3530Gpmc.h b/BeagleBoardPkg/Include/Omap3530/Omap3530Gpmc.h new file mode 100644 index 0000000000..907806c378 --- /dev/null +++ b/BeagleBoardPkg/Include/Omap3530/Omap3530Gpmc.h @@ -0,0 +1,107 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __OMAP3530GPMC_H__ +#define __OMAP3530GPMC_H__ + +#define GPMC_BASE (0x6E000000) + +//GPMC NAND definitions. +#define GPMC_SYSCONFIG (GPMC_BASE + 0x10) +#define SMARTIDLEMODE (0x2UL << 3) + +#define GPMC_SYSSTATUS (GPMC_BASE + 0x14) +#define GPMC_IRQSTATUS (GPMC_BASE + 0x18) +#define GPMC_IRQENABLE (GPMC_BASE + 0x1C) + +#define GPMC_TIMEOUT_CONTROL (GPMC_BASE + 0x40) +#define TIMEOUTENABLE (0x1UL << 0) +#define TIMEOUTDISABLE (0x0UL << 0) + +#define GPMC_ERR_ADDRESS (GPMC_BASE + 0x44) +#define GPMC_ERR_TYPE (GPMC_BASE + 0x48) + +#define GPMC_CONFIG (GPMC_BASE + 0x50) +#define WRITEPROTECT_HIGH (0x1UL << 4) +#define WRITEPROTECT_LOW (0x0UL << 4) + +#define GPMC_STATUS (GPMC_BASE + 0x54) + +#define GPMC_CONFIG1_0 (GPMC_BASE + 0x60) +#define DEVICETYPE_NOR (0x0UL << 10) +#define DEVICETYPE_NAND (0x2UL << 10) +#define DEVICESIZE_X8 (0x0UL << 12) +#define DEVICESIZE_X16 (0x1UL << 12) + +#define GPMC_CONFIG2_0 (GPMC_BASE + 0x64) +#define CSONTIME (0x0UL << 0) +#define CSRDOFFTIME (0x14UL << 8) +#define CSWROFFTIME (0x14UL << 16) + +#define GPMC_CONFIG3_0 (GPMC_BASE + 0x68) +#define ADVRDOFFTIME (0x14UL << 8) +#define ADVWROFFTIME (0x14UL << 16) + +#define GPMC_CONFIG4_0 (GPMC_BASE + 0x6C) +#define OEONTIME (0x1UL << 0) +#define OEOFFTIME (0xFUL << 8) +#define WEONTIME (0x1UL << 16) +#define WEOFFTIME (0xFUL << 24) + +#define GPMC_CONFIG5_0 (GPMC_BASE + 0x70) +#define RDCYCLETIME (0x14UL << 0) +#define WRCYCLETIME (0x14UL << 8) +#define RDACCESSTIME (0xCUL << 16) +#define PAGEBURSTACCESSTIME (0x1UL << 24) + +#define GPMC_CONFIG6_0 (GPMC_BASE + 0x74) +#define CYCLE2CYCLESAMECSEN (0x1UL << 7) +#define CYCLE2CYCLEDELAY (0xAUL << 8) +#define WRDATAONADMUXBUS (0xFUL << 16) +#define WRACCESSTIME (0x1FUL << 24) + +#define GPMC_CONFIG7_0 (GPMC_BASE + 0x78) +#define BASEADDRESS (0x30UL << 0) +#define CSVALID (0x1UL << 6) +#define MASKADDRESS_128MB (0x8UL << 8) + +#define GPMC_NAND_COMMAND_0 (GPMC_BASE + 0x7C) +#define GPMC_NAND_ADDRESS_0 (GPMC_BASE + 0x80) +#define GPMC_NAND_DATA_0 (GPMC_BASE + 0x84) + +#define GPMC_ECC_CONFIG (GPMC_BASE + 0x1F4) +#define ECCENABLE (0x1UL << 0) +#define ECCDISABLE (0x0UL << 0) +#define ECCCS_0 (0x0UL << 1) +#define ECC16B (0x1UL << 7) + +#define GPMC_ECC_CONTROL (GPMC_BASE + 0x1F8) +#define ECCPOINTER_REG1 (0x1UL << 0) +#define ECCCLEAR (0x1UL << 8) + +#define GPMC_ECC_SIZE_CONFIG (GPMC_BASE + 0x1FC) +#define ECCSIZE0_512BYTES (0xFFUL << 12) +#define ECCSIZE1_512BYTES (0xFFUL << 22) + +#define GPMC_ECC1_RESULT (GPMC_BASE + 0x200) +#define GPMC_ECC2_RESULT (GPMC_BASE + 0x204) +#define GPMC_ECC3_RESULT (GPMC_BASE + 0x208) +#define GPMC_ECC4_RESULT (GPMC_BASE + 0x20C) +#define GPMC_ECC5_RESULT (GPMC_BASE + 0x210) +#define GPMC_ECC6_RESULT (GPMC_BASE + 0x214) +#define GPMC_ECC7_RESULT (GPMC_BASE + 0x218) +#define GPMC_ECC8_RESULT (GPMC_BASE + 0x21C) +#define GPMC_ECC9_RESULT (GPMC_BASE + 0x220) + +#endif //__OMAP3530GPMC_H__ diff --git a/BeagleBoardPkg/Include/Omap3530/Omap3530I2c.h b/BeagleBoardPkg/Include/Omap3530/Omap3530I2c.h new file mode 100644 index 0000000000..5477b61645 --- /dev/null +++ b/BeagleBoardPkg/Include/Omap3530/Omap3530I2c.h @@ -0,0 +1,62 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __OMAP3530I2C_H__ +#define __OMAP3530I2C_H__ + +//I2C register definitions. +#define I2C1BASE 0x48070000 + +#define I2C_IE (I2C1BASE + 0x4) +#define XRDY_IE (0x1UL << 4) +#define RRDY_IE (0x1UL << 3) +#define ARDY_IE (0x1UL << 2) +#define NACK_IE (0x1UL << 1) + +#define I2C_STAT (I2C1BASE + 0x8) +#define BB (0x1UL << 12) +#define XRDY (0x1UL << 4) +#define RRDY (0x1UL << 3) +#define ARDY (0x1UL << 2) +#define NACK (0x1UL << 1) + +#define I2C_WE (I2C1BASE + 0xC) +#define I2C_SYSS (I2C1BASE + 0x10) +#define I2C_BUF (I2C1BASE + 0x14) +#define I2C_CNT (I2C1BASE + 0x18) +#define I2C_DATA (I2C1BASE + 0x1C) +#define I2C_SYSC (I2C1BASE + 0x20) + +#define I2C_CON (I2C1BASE + 0x24) +#define STT (0x1UL << 0) +#define STP (0x1UL << 1) +#define XSA (0x1UL << 8) +#define TRX (0x1UL << 9) +#define MST (0x1UL << 10) +#define I2C_EN (0x1UL << 15) + +#define I2C_OA0 (I2C1BASE + 0x28) +#define I2C_SA (I2C1BASE + 0x2C) +#define I2C_PSC (I2C1BASE + 0x30) +#define I2C_SCLL (I2C1BASE + 0x34) +#define I2C_SCLH (I2C1BASE + 0x38) +#define I2C_SYSTEST (I2C1BASE + 0x3C) +#define I2C_BUFSTAT (I2C1BASE + 0x40) +#define I2C_OA1 (I2C1BASE + 0x44) +#define I2C_OA2 (I2C1BASE + 0x48) +#define I2C_OA3 (I2C1BASE + 0x4C) +#define I2C_ACTOA (I2C1BASE + 0x50) +#define I2C_SBLOCK (I2C1BASE + 0x54) + +#endif //__OMAP3530I2C_H__ diff --git a/BeagleBoardPkg/Include/Omap3530/Omap3530Interrupt.h b/BeagleBoardPkg/Include/Omap3530/Omap3530Interrupt.h new file mode 100644 index 0000000000..129d8c0469 --- /dev/null +++ b/BeagleBoardPkg/Include/Omap3530/Omap3530Interrupt.h @@ -0,0 +1,46 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __OMAP3530INTERRUPT_H__ +#define __OMAP3530INTERRUPT_H__ + +#define INTERRUPT_BASE (0x48200000) + +#define INT_NROF_VECTORS (96) +#define MAX_VECTOR (INT_NROF_VECTORS - 1) +#define INTCPS_SYSCONFIG (INTERRUPT_BASE + 0x0010) +#define INTCPS_SYSSTATUS (INTERRUPT_BASE + 0x0014) +#define INTCPS_SIR_IRQ (INTERRUPT_BASE + 0x0040) +#define INTCPS_SIR_IFQ (INTERRUPT_BASE + 0x0044) +#define INTCPS_CONTROL (INTERRUPT_BASE + 0x0048) +#define INTCPS_PROTECTION (INTERRUPT_BASE + 0x004C) +#define INTCPS_IDLE (INTERRUPT_BASE + 0x0050) +#define INTCPS_IRQ_PRIORITY (INTERRUPT_BASE + 0x0060) +#define INTCPS_FIQ_PRIORITY (INTERRUPT_BASE + 0x0064) +#define INTCPS_THRESHOLD (INTERRUPT_BASE + 0x0068) +#define INTCPS_ITR(n) (INTERRUPT_BASE + 0x0080 + (0x20 * (n))) +#define INTCPS_MIR(n) (INTERRUPT_BASE + 0x0084 + (0x20 * (n))) +#define INTCPS_MIR_CLEAR(n) (INTERRUPT_BASE + 0x0088 + (0x20 * (n))) +#define INTCPS_MIR_SET(n) (INTERRUPT_BASE + 0x008C + (0x20 * (n))) +#define INTCPS_ISR_SET(n) (INTERRUPT_BASE + 0x0090 + (0x20 * (n))) +#define INTCPS_ISR_CLEAR(n) (INTERRUPT_BASE + 0x0094 + (0x20 * (n))) +#define INTCPS_PENDING_IRQ(n) (INTERRUPT_BASE + 0x0098 + (0x20 * (n))) +#define INTCPS_PENDING_FIQ(n) (INTERRUPT_BASE + 0x009C + (0x20 * (n))) +#define INTCPS_ILR(m) (INTERRUPT_BASE + 0x0100 + (0x04 * (m))) + +#define INTCPS_SIR_IRQ_MASK (0x7F) +#define INTCPS_CONTROL_NEWIRQAGR (1UL << 0) + +#endif // __OMAP3530INTERRUPT_H__ + diff --git a/BeagleBoardPkg/Include/Omap3530/Omap3530MMCHS.h b/BeagleBoardPkg/Include/Omap3530/Omap3530MMCHS.h new file mode 100755 index 0000000000..5ade843801 --- /dev/null +++ b/BeagleBoardPkg/Include/Omap3530/Omap3530MMCHS.h @@ -0,0 +1,208 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __OMAP3530SDIO_H__ +#define __OMAP3530SDIO_H__ + +//MMC/SD/SDIO1 register definitions. +#define MMCHS1BASE 0x4809C000 +#define MMC_REFERENCE_CLK (96000000) + +#define MMCHS_SYSCONFIG (MMCHS1BASE + 0x10) +#define SOFTRESET (0x1UL << 1) +#define ENAWAKEUP (0x1UL << 2) + +#define MMCHS_SYSSTATUS (MMCHS1BASE + 0x14) +#define RESETDONE_MASK (0x1UL << 0) +#define RESETDONE (0x1UL << 0) + +#define MMCHS_CSRE (MMCHS1BASE + 0x24) +#define MMCHS_SYSTEST (MMCHS1BASE + 0x28) + +#define MMCHS_CON (MMCHS1BASE + 0x2C) +#define OD (0x1UL << 0) +#define NOINIT (0x0UL << 1) +#define INIT (0x1UL << 1) +#define HR (0x1UL << 2) +#define STR (0x1UL << 3) +#define MODE (0x1UL << 4) +#define DW8_1_4_BIT (0x0UL << 5) +#define DW8_8_BIT (0x1UL << 5) +#define MIT (0x1UL << 6) +#define CDP (0x1UL << 7) +#define WPP (0x1UL << 8) +#define CTPL (0x1UL << 11) +#define CEATA_OFF (0x0UL << 12) +#define CEATA_ON (0x1UL << 12) + +#define MMCHS_PWCNT (MMCHS1BASE + 0x30) + +#define MMCHS_BLK (MMCHS1BASE + 0x104) +#define BLEN_512BYTES (0x200UL << 0) + +#define MMCHS_ARG (MMCHS1BASE + 0x108) + +#define MMCHS_CMD (MMCHS1BASE + 0x10C) +#define DE_ENABLE (0x1UL << 0) +#define BCE_ENABLE (0x1UL << 1) +#define ACEN_ENABLE (0x1UL << 2) +#define DDIR_READ (0x1UL << 4) +#define DDIR_WRITE (0x0UL << 4) +#define MSBS_SGLEBLK (0x0UL << 5) +#define MSBS_MULTBLK (0x1UL << 5) +#define RSP_TYPE_MASK (0x3UL << 16) +#define RSP_TYPE_136BITS (0x1UL << 16) +#define RSP_TYPE_48BITS (0x2UL << 16) +#define CCCE_ENABLE (0x1UL << 19) +#define CICE_ENABLE (0x1UL << 20) +#define DP_ENABLE (0x1UL << 21) +#define INDX(CMD_INDX) ((CMD_INDX & 0x3F) << 24) + +#define MMCHS_RSP10 (MMCHS1BASE + 0x110) +#define MMCHS_RSP32 (MMCHS1BASE + 0x114) +#define MMCHS_RSP54 (MMCHS1BASE + 0x118) +#define MMCHS_RSP76 (MMCHS1BASE + 0x11C) +#define MMCHS_DATA (MMCHS1BASE + 0x120) + +#define MMCHS_PSTATE (MMCHS1BASE + 0x124) +#define CMDI_MASK (0x1UL << 0) +#define CMDI_ALLOWED (0x0UL << 0) +#define CMDI_NOT_ALLOWED (0x1UL << 0) +#define DATI_MASK (0x1UL << 1) +#define DATI_ALLOWED (0x0UL << 1) +#define DATI_NOT_ALLOWED (0x1UL << 1) + +#define MMCHS_HCTL (MMCHS1BASE + 0x128) +#define DTW_1_BIT (0x0UL << 1) +#define DTW_4_BIT (0x1UL << 1) +#define SDBP_MASK (0x1UL << 8) +#define SDBP_OFF (0x0UL << 8) +#define SDBP_ON (0x1UL << 8) +#define SDVS_1_8_V (0x5UL << 9) +#define SDVS_3_0_V (0x6UL << 9) +#define IWE (0x1UL << 24) + +#define MMCHS_SYSCTL (MMCHS1BASE + 0x12C) +#define ICE (0x1UL << 0) +#define ICS_MASK (0x1UL << 1) +#define ICS (0x1UL << 1) +#define CEN (0x1UL << 2) +#define CLKD_MASK (0x3FFUL << 6) +#define CLKD_80KHZ (0x258UL) //(96*1000/80)/2 +#define CLKD_400KHZ (0xF0UL) +#define DTO_MASK (0xFUL << 16) +#define DTO_VAL (0xEUL << 16) +#define SRA (0x1UL << 24) +#define SRC_MASK (0x1UL << 25) +#define SRC (0x1UL << 25) +#define SRD (0x1UL << 26) + +#define MMCHS_STAT (MMCHS1BASE + 0x130) +#define CC (0x1UL << 0) +#define TC (0x1UL << 1) +#define BWR (0x1UL << 4) +#define BRR (0x1UL << 5) +#define ERRI (0x1UL << 15) +#define CTO (0x1UL << 16) +#define DTO (0x1UL << 20) +#define DCRC (0x1UL << 21) +#define DEB (0x1UL << 22) + +#define MMCHS_IE (MMCHS1BASE + 0x134) +#define CC_EN (0x1UL << 0) +#define TC_EN (0x1UL << 1) +#define BWR_EN (0x1UL << 4) +#define BRR_EN (0x1UL << 5) +#define CTO_EN (0x1UL << 16) +#define CCRC_EN (0x1UL << 17) +#define CEB_EN (0x1UL << 18) +#define CIE_EN (0x1UL << 19) +#define DTO_EN (0x1UL << 20) +#define DCRC_EN (0x1UL << 21) +#define DEB_EN (0x1UL << 22) +#define CERR_EN (0x1UL << 28) +#define BADA_EN (0x1UL << 29) + +#define MMCHS_ISE (MMCHS1BASE + 0x138) +#define CC_SIGEN (0x1UL << 0) +#define TC_SIGEN (0x1UL << 1) +#define BWR_SIGEN (0x1UL << 4) +#define BRR_SIGEN (0x1UL << 5) +#define CTO_SIGEN (0x1UL << 16) +#define CCRC_SIGEN (0x1UL << 17) +#define CEB_SIGEN (0x1UL << 18) +#define CIE_SIGEN (0x1UL << 19) +#define DTO_SIGEN (0x1UL << 20) +#define DCRC_SIGEN (0x1UL << 21) +#define DEB_SIGEN (0x1UL << 22) +#define CERR_SIGEN (0x1UL << 28) +#define BADA_SIGEN (0x1UL << 29) + +#define MMCHS_AC12 (MMCHS1BASE + 0x13C) + +#define MMCHS_CAPA (MMCHS1BASE + 0x140) +#define VS30 (0x1UL << 25) +#define VS18 (0x1UL << 26) + +#define MMCHS_CUR_CAPA (MMCHS1BASE + 0x148) +#define MMCHS_REV (MMCHS1BASE + 0x1FC) + +#define CMD0 INDX(0) +#define CMD0_INT_EN (CC_EN | CEB_EN) + +#define CMD1 (INDX(1) | RSP_TYPE_48BITS) +#define CMD1_INT_EN (CC_EN | CEB_EN | CTO_EN) + +#define CMD2 (INDX(2) | CCCE_ENABLE | RSP_TYPE_136BITS) +#define CMD2_INT_EN (CERR_EN | CIE_EN | CCRC_EN | CC_EN | CEB_EN | CTO_EN) + +#define CMD3 (INDX(3) | CICE_ENABLE | CCCE_ENABLE | RSP_TYPE_48BITS) +#define CMD3_INT_EN (CERR_EN | CIE_EN | CCRC_EN | CC_EN | CEB_EN | CTO_EN) + +#define CMD5 (INDX(5) | RSP_TYPE_48BITS) +#define CMD5_INT_EN (CC_EN | CEB_EN | CTO_EN) + +#define CMD7 (INDX(7) | CICE_ENABLE | CCCE_ENABLE | RSP_TYPE_48BITS) +#define CMD7_INT_EN (CERR_EN | CIE_EN | CCRC_EN | CC_EN | CEB_EN | CTO_EN) + +#define CMD8 (INDX(8) | CICE_ENABLE | CCCE_ENABLE | RSP_TYPE_48BITS) +#define CMD8_INT_EN (CERR_EN | CIE_EN | CCRC_EN | CC_EN | CEB_EN | CTO_EN) +//Reserved(0)[12:31], Supply voltage(1)[11:8], check pattern(0xCE)[7:0] = 0x1CE +#define CMD8_ARG (0x0UL << 12 | 0x1UL << 8 | 0xCEUL << 0) + +#define CMD9 (INDX(9) | CCCE_ENABLE | RSP_TYPE_136BITS) +#define CMD9_INT_EN (CCRC_EN | CC_EN | CEB_EN | CTO_EN) + +#define CMD16 (INDX(16) | CICE_ENABLE | CCCE_ENABLE | RSP_TYPE_48BITS) +#define CMD16_INT_EN (CERR_EN | CIE_EN | CCRC_EN | CC_EN | CEB_EN | CTO_EN) + +#define CMD17 (INDX(17) | DP_ENABLE | CICE_ENABLE | CCCE_ENABLE | RSP_TYPE_48BITS | DDIR_READ) +#define CMD17_INT_EN (CERR_EN | CIE_EN | CCRC_EN | CC_EN | TC_EN | BRR_EN | CTO_EN | DTO_EN | DCRC_EN | DEB_EN | CEB_EN) + +#define CMD18 (INDX(18) | DP_ENABLE | CICE_ENABLE | CCCE_ENABLE | RSP_TYPE_48BITS | MSBS_MULTBLK | DDIR_READ | BCE_ENABLE | DE_ENABLE) +#define CMD18_INT_EN (CERR_EN | CIE_EN | CCRC_EN | CC_EN | TC_EN | BRR_EN | CTO_EN | DTO_EN | DCRC_EN | DEB_EN | CEB_EN) + +#define CMD23 (INDX(23) | CICE_ENABLE | CCCE_ENABLE | RSP_TYPE_48BITS) +#define CMD23_INT_EN (CERR_EN | CIE_EN | CCRC_EN | CC_EN | CEB_EN | CTO_EN) + +#define CMD24 (INDX(24) | DP_ENABLE | CICE_ENABLE | CCCE_ENABLE | RSP_TYPE_48BITS | DDIR_WRITE) +#define CMD24_INT_EN (CERR_EN | CIE_EN | CCRC_EN | CC_EN | TC_EN | BWR_EN | CTO_EN | DTO_EN | DCRC_EN | DEB_EN | CEB_EN) + +#define CMD55 (INDX(55) | CICE_ENABLE | CCCE_ENABLE | RSP_TYPE_48BITS) +#define CMD55_INT_EN (CERR_EN | CIE_EN | CCRC_EN | CC_EN | CEB_EN | CTO_EN) + +#define ACMD41 (INDX(41) | RSP_TYPE_48BITS) +#define ACMD41_INT_EN (CERR_EN | CIE_EN | CCRC_EN | CC_EN | CEB_EN | CTO_EN) + +#endif //__OMAP3530SDIO_H__ diff --git a/BeagleBoardPkg/Include/Omap3530/Omap3530PadConfiguration.h b/BeagleBoardPkg/Include/Omap3530/Omap3530PadConfiguration.h new file mode 100644 index 0000000000..baae8c68c8 --- /dev/null +++ b/BeagleBoardPkg/Include/Omap3530/Omap3530PadConfiguration.h @@ -0,0 +1,298 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __OMAP3530_PAD_CONFIGURATION_H__ +#define __OMAP3530_PAD_CONFIGURATION_H__ + +#define SYSTEM_CONTROL_MODULE_BASE 0x48002000 + +//Pin definition +#define SDRC_D0 (SYSTEM_CONTROL_MODULE_BASE + 0x030) +#define SDRC_D1 (SYSTEM_CONTROL_MODULE_BASE + 0x032) +#define SDRC_D2 (SYSTEM_CONTROL_MODULE_BASE + 0x034) +#define SDRC_D3 (SYSTEM_CONTROL_MODULE_BASE + 0x036) +#define SDRC_D4 (SYSTEM_CONTROL_MODULE_BASE + 0x038) +#define SDRC_D5 (SYSTEM_CONTROL_MODULE_BASE + 0x03A) +#define SDRC_D6 (SYSTEM_CONTROL_MODULE_BASE + 0x03C) +#define SDRC_D7 (SYSTEM_CONTROL_MODULE_BASE + 0x03E) +#define SDRC_D8 (SYSTEM_CONTROL_MODULE_BASE + 0x040) +#define SDRC_D9 (SYSTEM_CONTROL_MODULE_BASE + 0x042) +#define SDRC_D10 (SYSTEM_CONTROL_MODULE_BASE + 0x044) +#define SDRC_D11 (SYSTEM_CONTROL_MODULE_BASE + 0x046) +#define SDRC_D12 (SYSTEM_CONTROL_MODULE_BASE + 0x048) +#define SDRC_D13 (SYSTEM_CONTROL_MODULE_BASE + 0x04A) +#define SDRC_D14 (SYSTEM_CONTROL_MODULE_BASE + 0x04C) +#define SDRC_D15 (SYSTEM_CONTROL_MODULE_BASE + 0x04E) +#define SDRC_D16 (SYSTEM_CONTROL_MODULE_BASE + 0x050) +#define SDRC_D17 (SYSTEM_CONTROL_MODULE_BASE + 0x052) +#define SDRC_D18 (SYSTEM_CONTROL_MODULE_BASE + 0x054) +#define SDRC_D19 (SYSTEM_CONTROL_MODULE_BASE + 0x056) +#define SDRC_D20 (SYSTEM_CONTROL_MODULE_BASE + 0x058) +#define SDRC_D21 (SYSTEM_CONTROL_MODULE_BASE + 0x05A) +#define SDRC_D22 (SYSTEM_CONTROL_MODULE_BASE + 0x05C) +#define SDRC_D23 (SYSTEM_CONTROL_MODULE_BASE + 0x05E) +#define SDRC_D24 (SYSTEM_CONTROL_MODULE_BASE + 0x060) +#define SDRC_D25 (SYSTEM_CONTROL_MODULE_BASE + 0x062) +#define SDRC_D26 (SYSTEM_CONTROL_MODULE_BASE + 0x064) +#define SDRC_D27 (SYSTEM_CONTROL_MODULE_BASE + 0x066) +#define SDRC_D28 (SYSTEM_CONTROL_MODULE_BASE + 0x068) +#define SDRC_D29 (SYSTEM_CONTROL_MODULE_BASE + 0x06A) +#define SDRC_D30 (SYSTEM_CONTROL_MODULE_BASE + 0x06C) +#define SDRC_D31 (SYSTEM_CONTROL_MODULE_BASE + 0x06E) +#define SDRC_CLK (SYSTEM_CONTROL_MODULE_BASE + 0x070) +#define SDRC_DQS0 (SYSTEM_CONTROL_MODULE_BASE + 0x072) +#define SDRC_CKE0 (SYSTEM_CONTROL_MODULE_BASE + 0x262) +#define SDRC_CKE1 (SYSTEM_CONTROL_MODULE_BASE + 0x264) +#define SDRC_DQS1 (SYSTEM_CONTROL_MODULE_BASE + 0x074) +#define SDRC_DQS2 (SYSTEM_CONTROL_MODULE_BASE + 0x076) +#define SDRC_DQS3 (SYSTEM_CONTROL_MODULE_BASE + 0x078) +#define GPMC_A1 (SYSTEM_CONTROL_MODULE_BASE + 0x07A) +#define GPMC_A2 (SYSTEM_CONTROL_MODULE_BASE + 0x07C) +#define GPMC_A3 (SYSTEM_CONTROL_MODULE_BASE + 0x07E) +#define GPMC_A4 (SYSTEM_CONTROL_MODULE_BASE + 0x080) +#define GPMC_A5 (SYSTEM_CONTROL_MODULE_BASE + 0x082) +#define GPMC_A6 (SYSTEM_CONTROL_MODULE_BASE + 0x084) +#define GPMC_A7 (SYSTEM_CONTROL_MODULE_BASE + 0x086) +#define GPMC_A8 (SYSTEM_CONTROL_MODULE_BASE + 0x088) +#define GPMC_A9 (SYSTEM_CONTROL_MODULE_BASE + 0x08A) +#define GPMC_A10 (SYSTEM_CONTROL_MODULE_BASE + 0x08C) +#define GPMC_D0 (SYSTEM_CONTROL_MODULE_BASE + 0x08E) +#define GPMC_D1 (SYSTEM_CONTROL_MODULE_BASE + 0x090) +#define GPMC_D2 (SYSTEM_CONTROL_MODULE_BASE + 0x092) +#define GPMC_D3 (SYSTEM_CONTROL_MODULE_BASE + 0x094) +#define GPMC_D4 (SYSTEM_CONTROL_MODULE_BASE + 0x096) +#define GPMC_D5 (SYSTEM_CONTROL_MODULE_BASE + 0x098) +#define GPMC_D6 (SYSTEM_CONTROL_MODULE_BASE + 0x09A) +#define GPMC_D7 (SYSTEM_CONTROL_MODULE_BASE + 0x09C) +#define GPMC_D8 (SYSTEM_CONTROL_MODULE_BASE + 0x09E) +#define GPMC_D9 (SYSTEM_CONTROL_MODULE_BASE + 0x0A0) +#define GPMC_D10 (SYSTEM_CONTROL_MODULE_BASE + 0x0A2) +#define GPMC_D11 (SYSTEM_CONTROL_MODULE_BASE + 0x0A4) +#define GPMC_D12 (SYSTEM_CONTROL_MODULE_BASE + 0x0A6) +#define GPMC_D13 (SYSTEM_CONTROL_MODULE_BASE + 0x0A8) +#define GPMC_D14 (SYSTEM_CONTROL_MODULE_BASE + 0x0AA) +#define GPMC_D15 (SYSTEM_CONTROL_MODULE_BASE + 0x0AC) +#define GPMC_NCS0 (SYSTEM_CONTROL_MODULE_BASE + 0x0AE) +#define GPMC_NCS1 (SYSTEM_CONTROL_MODULE_BASE + 0x0B0) +#define GPMC_NCS2 (SYSTEM_CONTROL_MODULE_BASE + 0x0B2) +#define GPMC_NCS3 (SYSTEM_CONTROL_MODULE_BASE + 0x0B4) +#define GPMC_NCS4 (SYSTEM_CONTROL_MODULE_BASE + 0x0B6) +#define GPMC_NCS5 (SYSTEM_CONTROL_MODULE_BASE + 0x0B8) +#define GPMC_NCS6 (SYSTEM_CONTROL_MODULE_BASE + 0x0BA) +#define GPMC_NCS7 (SYSTEM_CONTROL_MODULE_BASE + 0x0BC) +#define GPMC_CLK (SYSTEM_CONTROL_MODULE_BASE + 0x0BE) +#define GPMC_NADV_ALE (SYSTEM_CONTROL_MODULE_BASE + 0x0C0) +#define GPMC_NOE (SYSTEM_CONTROL_MODULE_BASE + 0x0C2) +#define GPMC_NWE (SYSTEM_CONTROL_MODULE_BASE + 0x0C4) +#define GPMC_NBE0_CLE (SYSTEM_CONTROL_MODULE_BASE + 0x0C6) +#define GPMC_NBE1 (SYSTEM_CONTROL_MODULE_BASE + 0x0C8) +#define GPMC_NWP (SYSTEM_CONTROL_MODULE_BASE + 0x0CA) +#define GPMC_WAIT0 (SYSTEM_CONTROL_MODULE_BASE + 0x0CC) +#define GPMC_WAIT1 (SYSTEM_CONTROL_MODULE_BASE + 0x0CE) +#define GPMC_WAIT2 (SYSTEM_CONTROL_MODULE_BASE + 0x0D0) +#define GPMC_WAIT3 (SYSTEM_CONTROL_MODULE_BASE + 0x0D2) +#define DSS_PCLK (SYSTEM_CONTROL_MODULE_BASE + 0x0D4) +#define DSS_HSYNC (SYSTEM_CONTROL_MODULE_BASE + 0x0D6) +#define DSS_PSYNC (SYSTEM_CONTROL_MODULE_BASE + 0x0D8) +#define DSS_ACBIAS (SYSTEM_CONTROL_MODULE_BASE + 0x0DA) +#define DSS_DATA0 (SYSTEM_CONTROL_MODULE_BASE + 0x0DC) +#define DSS_DATA1 (SYSTEM_CONTROL_MODULE_BASE + 0x0DE) +#define DSS_DATA2 (SYSTEM_CONTROL_MODULE_BASE + 0x0E0) +#define DSS_DATA3 (SYSTEM_CONTROL_MODULE_BASE + 0x0E2) +#define DSS_DATA4 (SYSTEM_CONTROL_MODULE_BASE + 0x0E4) +#define DSS_DATA5 (SYSTEM_CONTROL_MODULE_BASE + 0x0E6) +#define DSS_DATA6 (SYSTEM_CONTROL_MODULE_BASE + 0x0E8) +#define DSS_DATA7 (SYSTEM_CONTROL_MODULE_BASE + 0x0EA) +#define DSS_DATA8 (SYSTEM_CONTROL_MODULE_BASE + 0x0EC) +#define DSS_DATA9 (SYSTEM_CONTROL_MODULE_BASE + 0x0EE) +#define DSS_DATA10 (SYSTEM_CONTROL_MODULE_BASE + 0x0F0) +#define DSS_DATA11 (SYSTEM_CONTROL_MODULE_BASE + 0x0F2) +#define DSS_DATA12 (SYSTEM_CONTROL_MODULE_BASE + 0x0F4) +#define DSS_DATA13 (SYSTEM_CONTROL_MODULE_BASE + 0x0F6) +#define DSS_DATA14 (SYSTEM_CONTROL_MODULE_BASE + 0x0F8) +#define DSS_DATA15 (SYSTEM_CONTROL_MODULE_BASE + 0x0FA) +#define DSS_DATA16 (SYSTEM_CONTROL_MODULE_BASE + 0x0FC) +#define DSS_DATA17 (SYSTEM_CONTROL_MODULE_BASE + 0x0FE) +#define DSS_DATA18 (SYSTEM_CONTROL_MODULE_BASE + 0x100) +#define DSS_DATA19 (SYSTEM_CONTROL_MODULE_BASE + 0x102) +#define DSS_DATA20 (SYSTEM_CONTROL_MODULE_BASE + 0x104) +#define DSS_DATA21 (SYSTEM_CONTROL_MODULE_BASE + 0x106) +#define DSS_DATA22 (SYSTEM_CONTROL_MODULE_BASE + 0x108) +#define DSS_DATA23 (SYSTEM_CONTROL_MODULE_BASE + 0x10A) +#define CAM_HS (SYSTEM_CONTROL_MODULE_BASE + 0x10C) +#define CAM_VS (SYSTEM_CONTROL_MODULE_BASE + 0x10E) +#define CAM_XCLKA (SYSTEM_CONTROL_MODULE_BASE + 0x110) +#define CAM_PCLK (SYSTEM_CONTROL_MODULE_BASE + 0x112) +#define CAM_FLD (SYSTEM_CONTROL_MODULE_BASE + 0x114) +#define CAM_D0 (SYSTEM_CONTROL_MODULE_BASE + 0x116) +#define CAM_D1 (SYSTEM_CONTROL_MODULE_BASE + 0x118) +#define CAM_D2 (SYSTEM_CONTROL_MODULE_BASE + 0x11A) +#define CAM_D3 (SYSTEM_CONTROL_MODULE_BASE + 0x11C) +#define CAM_D4 (SYSTEM_CONTROL_MODULE_BASE + 0x11E) +#define CAM_D5 (SYSTEM_CONTROL_MODULE_BASE + 0x120) +#define CAM_D6 (SYSTEM_CONTROL_MODULE_BASE + 0x122) +#define CAM_D7 (SYSTEM_CONTROL_MODULE_BASE + 0x124) +#define CAM_D8 (SYSTEM_CONTROL_MODULE_BASE + 0x126) +#define CAM_D9 (SYSTEM_CONTROL_MODULE_BASE + 0x128) +#define CAM_D10 (SYSTEM_CONTROL_MODULE_BASE + 0x12A) +#define CAM_D11 (SYSTEM_CONTROL_MODULE_BASE + 0x12C) +#define CAM_XCLKB (SYSTEM_CONTROL_MODULE_BASE + 0x12E) +#define CAM_WEN (SYSTEM_CONTROL_MODULE_BASE + 0x130) +#define CAM_STROBE (SYSTEM_CONTROL_MODULE_BASE + 0x132) +#define CSI2_DX0 (SYSTEM_CONTROL_MODULE_BASE + 0x134) +#define CSI2_DY0 (SYSTEM_CONTROL_MODULE_BASE + 0x136) +#define CSI2_DX1 (SYSTEM_CONTROL_MODULE_BASE + 0x138) +#define CSI2_DY1 (SYSTEM_CONTROL_MODULE_BASE + 0x13A) +#define MCBSP2_FSX (SYSTEM_CONTROL_MODULE_BASE + 0x13C) +#define MCBSP2_CLKX (SYSTEM_CONTROL_MODULE_BASE + 0x13E) +#define MCBSP2_DR (SYSTEM_CONTROL_MODULE_BASE + 0x140) +#define MCBSP2_DX (SYSTEM_CONTROL_MODULE_BASE + 0x142) +#define MMC1_CLK (SYSTEM_CONTROL_MODULE_BASE + 0x144) +#define MMC1_CMD (SYSTEM_CONTROL_MODULE_BASE + 0x146) +#define MMC1_DAT0 (SYSTEM_CONTROL_MODULE_BASE + 0x148) +#define MMC1_DAT1 (SYSTEM_CONTROL_MODULE_BASE + 0x14A) +#define MMC1_DAT2 (SYSTEM_CONTROL_MODULE_BASE + 0x14C) +#define MMC1_DAT3 (SYSTEM_CONTROL_MODULE_BASE + 0x14E) +#define MMC1_DAT4 (SYSTEM_CONTROL_MODULE_BASE + 0x150) +#define MMC1_DAT5 (SYSTEM_CONTROL_MODULE_BASE + 0x152) +#define MMC1_DAT6 (SYSTEM_CONTROL_MODULE_BASE + 0x154) +#define MMC1_DAT7 (SYSTEM_CONTROL_MODULE_BASE + 0x156) +#define MMC2_CLK (SYSTEM_CONTROL_MODULE_BASE + 0x158) +#define MMC2_CMD (SYSTEM_CONTROL_MODULE_BASE + 0x15A) +#define MMC2_DAT0 (SYSTEM_CONTROL_MODULE_BASE + 0x15C) +#define MMC2_DAT1 (SYSTEM_CONTROL_MODULE_BASE + 0x15E) +#define MMC2_DAT2 (SYSTEM_CONTROL_MODULE_BASE + 0x160) +#define MMC2_DAT3 (SYSTEM_CONTROL_MODULE_BASE + 0x162) +#define MMC2_DAT4 (SYSTEM_CONTROL_MODULE_BASE + 0x164) +#define MMC2_DAT5 (SYSTEM_CONTROL_MODULE_BASE + 0x166) +#define MMC2_DAT6 (SYSTEM_CONTROL_MODULE_BASE + 0x168) +#define MMC2_DAT7 (SYSTEM_CONTROL_MODULE_BASE + 0x16A) +#define MCBSP3_DX (SYSTEM_CONTROL_MODULE_BASE + 0x16C) +#define MCBSP3_DR (SYSTEM_CONTROL_MODULE_BASE + 0x16E) +#define MCBSP3_CLKX (SYSTEM_CONTROL_MODULE_BASE + 0x170) +#define MCBSP3_FSX (SYSTEM_CONTROL_MODULE_BASE + 0x172) +#define UART2_CTS (SYSTEM_CONTROL_MODULE_BASE + 0x174) +#define UART2_RTS (SYSTEM_CONTROL_MODULE_BASE + 0x176) +#define UART2_TX (SYSTEM_CONTROL_MODULE_BASE + 0x178) +#define UART2_RX (SYSTEM_CONTROL_MODULE_BASE + 0x17A) +#define UART1_TX (SYSTEM_CONTROL_MODULE_BASE + 0x17C) +#define UART1_RTS (SYSTEM_CONTROL_MODULE_BASE + 0x17E) +#define UART1_CTS (SYSTEM_CONTROL_MODULE_BASE + 0x180) +#define UART1_RX (SYSTEM_CONTROL_MODULE_BASE + 0x182) +#define MCBSP4_CLKX (SYSTEM_CONTROL_MODULE_BASE + 0x184) +#define MCBSP4_DR (SYSTEM_CONTROL_MODULE_BASE + 0x186) +#define MCBSP4_DX (SYSTEM_CONTROL_MODULE_BASE + 0x188) +#define MCBSP4_FSX (SYSTEM_CONTROL_MODULE_BASE + 0x18A) +#define MCBSP1_CLKR (SYSTEM_CONTROL_MODULE_BASE + 0x18C) +#define MCBSP1_FSR (SYSTEM_CONTROL_MODULE_BASE + 0x18E) +#define MCBSP1_DX (SYSTEM_CONTROL_MODULE_BASE + 0x190) +#define MCBSP1_DR (SYSTEM_CONTROL_MODULE_BASE + 0x192) +#define MCBSP1_CLKS (SYSTEM_CONTROL_MODULE_BASE + 0x194) +#define MCBSP1_FSX (SYSTEM_CONTROL_MODULE_BASE + 0x196) +#define MCBSP1_CLKX (SYSTEM_CONTROL_MODULE_BASE + 0x198) +#define UART3_CTS_RCTX (SYSTEM_CONTROL_MODULE_BASE + 0x19A) +#define UART3_RTS_SD (SYSTEM_CONTROL_MODULE_BASE + 0x19C) +#define UART3_RX_IRRX (SYSTEM_CONTROL_MODULE_BASE + 0x19E) +#define UART3_TX_IRTX (SYSTEM_CONTROL_MODULE_BASE + 0x1A0) +#define HSUSB0_CLK (SYSTEM_CONTROL_MODULE_BASE + 0x1A2) +#define HSUSB0_STP (SYSTEM_CONTROL_MODULE_BASE + 0x1A4) +#define HSUSB0_DIR (SYSTEM_CONTROL_MODULE_BASE + 0x1A6) +#define HSUSB0_NXT (SYSTEM_CONTROL_MODULE_BASE + 0x1A8) +#define HSUSB0_DATA0 (SYSTEM_CONTROL_MODULE_BASE + 0x1AA) +#define HSUSB0_DATA1 (SYSTEM_CONTROL_MODULE_BASE + 0x1AC) +#define HSUSB0_DATA2 (SYSTEM_CONTROL_MODULE_BASE + 0x1AE) +#define HSUSB0_DATA3 (SYSTEM_CONTROL_MODULE_BASE + 0x1B0) +#define HSUSB0_DATA4 (SYSTEM_CONTROL_MODULE_BASE + 0x1B2) +#define HSUSB0_DATA5 (SYSTEM_CONTROL_MODULE_BASE + 0x1B4) +#define HSUSB0_DATA6 (SYSTEM_CONTROL_MODULE_BASE + 0x1B6) +#define HSUSB0_DATA7 (SYSTEM_CONTROL_MODULE_BASE + 0x1B8) +#define I2C1_SCL (SYSTEM_CONTROL_MODULE_BASE + 0x1BA) +#define I2C1_SDA (SYSTEM_CONTROL_MODULE_BASE + 0x1BC) +#define I2C2_SCL (SYSTEM_CONTROL_MODULE_BASE + 0x1BE) +#define I2C2_SDA (SYSTEM_CONTROL_MODULE_BASE + 0x1C0) +#define I2C3_SCL (SYSTEM_CONTROL_MODULE_BASE + 0x1C2) +#define I2C3_SDA (SYSTEM_CONTROL_MODULE_BASE + 0x1C4) +#define HDQ_SIO (SYSTEM_CONTROL_MODULE_BASE + 0x1C6) +#define MCSPI1_CLK (SYSTEM_CONTROL_MODULE_BASE + 0x1C8) +#define MCSPI1_SIMO (SYSTEM_CONTROL_MODULE_BASE + 0x1CA) +#define MCSPI1_SOMI (SYSTEM_CONTROL_MODULE_BASE + 0x1CC) +#define MCSPI1_CS0 (SYSTEM_CONTROL_MODULE_BASE + 0x1CE) +#define MCSPI1_CS1 (SYSTEM_CONTROL_MODULE_BASE + 0x1D0) +#define MCSPI1_CS2 (SYSTEM_CONTROL_MODULE_BASE + 0x1D2) +#define MCSPI1_CS3 (SYSTEM_CONTROL_MODULE_BASE + 0x1D4) +#define MCSPI2_CLK (SYSTEM_CONTROL_MODULE_BASE + 0x1D6) +#define MCSPI2_SIMO (SYSTEM_CONTROL_MODULE_BASE + 0x1D8) +#define MCSPI2_SOMI (SYSTEM_CONTROL_MODULE_BASE + 0x1DA) +#define MCSPI2_CS0 (SYSTEM_CONTROL_MODULE_BASE + 0x1DC) +#define MCSPI2_CS1 (SYSTEM_CONTROL_MODULE_BASE + 0x1DE) +#define SYS_NIRQ (SYSTEM_CONTROL_MODULE_BASE + 0x1E0) +#define SYS_CLKOUT2 (SYSTEM_CONTROL_MODULE_BASE + 0x1E2) +#define ETK_CLK (SYSTEM_CONTROL_MODULE_BASE + 0x5D8) +#define ETK_CTL (SYSTEM_CONTROL_MODULE_BASE + 0x5DA) +#define ETK_D0 (SYSTEM_CONTROL_MODULE_BASE + 0x5DC) +#define ETK_D1 (SYSTEM_CONTROL_MODULE_BASE + 0x5DE) +#define ETK_D2 (SYSTEM_CONTROL_MODULE_BASE + 0x5E0) +#define ETK_D3 (SYSTEM_CONTROL_MODULE_BASE + 0x5E2) +#define ETK_D4 (SYSTEM_CONTROL_MODULE_BASE + 0x5E4) +#define ETK_D5 (SYSTEM_CONTROL_MODULE_BASE + 0x5E6) +#define ETK_D6 (SYSTEM_CONTROL_MODULE_BASE + 0x5E8) +#define ETK_D7 (SYSTEM_CONTROL_MODULE_BASE + 0x5EA) +#define ETK_D8 (SYSTEM_CONTROL_MODULE_BASE + 0x5EC) +#define ETK_D9 (SYSTEM_CONTROL_MODULE_BASE + 0x5EE) +#define ETK_D10 (SYSTEM_CONTROL_MODULE_BASE + 0x5F0) +#define ETK_D11 (SYSTEM_CONTROL_MODULE_BASE + 0x5F2) +#define ETK_D12 (SYSTEM_CONTROL_MODULE_BASE + 0x5F4) +#define ETK_D13 (SYSTEM_CONTROL_MODULE_BASE + 0x5F6) +#define ETK_D14 (SYSTEM_CONTROL_MODULE_BASE + 0x5F8) +#define ETK_D15 (SYSTEM_CONTROL_MODULE_BASE + 0x5FA) + +//Mux modes +#define MUXMODE0 (0x0UL) +#define MUXMODE1 (0x1UL) +#define MUXMODE2 (0x2UL) +#define MUXMODE3 (0x3UL) +#define MUXMODE4 (0x4UL) +#define MUXMODE5 (0x5UL) +#define MUXMODE6 (0x6UL) +#define MUXMODE7 (0x7UL) + +//Pad configuration register. +#define PAD_CONFIG_MASK (0xFFFFUL) +#define MUXMODE_OFFSET 0 +#define MUXMODE_MASK (0x7UL << MUXMODE_OFFSET) +#define PULL_CONFIG_OFFSET 3 +#define PULL_CONFIG_MASK (0x3UL << PULL_CONFIG_OFFSET) +#define INPUTENABLE_OFFSET 8 +#define INPUTENABLE_MASK (0x1UL << INPUTENABLE_OFFSET) +#define OFFMODE_VALUE_OFFSET 9 +#define OFFMODE_VALUE_MASK (0x1FUL << OFFMODE_VALUE_OFFSET) +#define WAKEUP_OFFSET 14 +#define WAKEUP_MASK (0x2UL << WAKEUP_OFFSET) + +#define PULLUDDISABLE (0x0UL << 0) +#define PULLUDENABLE (0x1UL << 0) +#define PULLTYPENOSELECT (0x0UL << 1) +#define PULLTYPESELECT (0x1UL << 1) + +#define OUTPUT (0x0UL) //Pin is configured in output only mode. +#define INPUT (0x1UL) //Pin is configured in bi-directional mode. + +typedef struct { + UINTN Pin; + UINTN MuxMode; + UINTN PullConfig; + UINTN InputEnable; +} PAD_CONFIGURATION; + +#endif //__OMAP3530_PAD_CONFIGURATION_H__ diff --git a/BeagleBoardPkg/Include/Omap3530/Omap3530Prcm.h b/BeagleBoardPkg/Include/Omap3530/Omap3530Prcm.h new file mode 100644 index 0000000000..036f8bcece --- /dev/null +++ b/BeagleBoardPkg/Include/Omap3530/Omap3530Prcm.h @@ -0,0 +1,164 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __OMAP3530PRCM_H__ +#define __OMAP3530PRCM_H__ + +#define CM_FCLKEN1_CORE (0x48004A00) +#define CM_FCLKEN3_CORE (0x48004A08) +#define CM_ICLKEN1_CORE (0x48004A10) +#define CM_ICLKEN3_CORE (0x48004A18) +#define CM_CLKEN2_PLL (0x48004D04) +#define CM_CLKSEL4_PLL (0x48004D4C) +#define CM_CLKSEL5_PLL (0x48004D50) +#define CM_FCLKEN_USBHOST (0x48005400) +#define CM_ICLKEN_USBHOST (0x48005410) + +//Wakeup clock defintion +#define CM_FCLKEN_WKUP (0x48004C00) +#define CM_ICLKEN_WKUP (0x48004C10) + +//Peripheral clock definition +#define CM_FCLKEN_PER (0x48005000) +#define CM_ICLKEN_PER (0x48005010) +#define CM_CLKSEL_PER (0x48005040) + +//Reset management definition +#define PRM_RSTCTRL (0x48307250) +#define PRM_RSTST (0x48307258) + +//CORE clock +#define CM_FCLKEN1_CORE_EN_I2C1_MASK (1UL << 15) +#define CM_FCLKEN1_CORE_EN_I2C1_DISABLE (0UL << 15) +#define CM_FCLKEN1_CORE_EN_I2C1_ENABLE (1UL << 15) + +#define CM_ICLKEN1_CORE_EN_I2C1_MASK (1UL << 15) +#define CM_ICLKEN1_CORE_EN_I2C1_DISABLE (0UL << 15) +#define CM_ICLKEN1_CORE_EN_I2C1_ENABLE (1UL << 15) + +#define CM_FCLKEN1_CORE_EN_MMC1_MASK (1UL << 24) +#define CM_FCLKEN1_CORE_EN_MMC1_DISABLE (0UL << 24) +#define CM_FCLKEN1_CORE_EN_MMC1_ENABLE (1UL << 24) + +#define CM_FCLKEN3_CORE_EN_USBTLL_MASK (1UL << 2) +#define CM_FCLKEN3_CORE_EN_USBTLL_DISABLE (0UL << 2) +#define CM_FCLKEN3_CORE_EN_USBTLL_ENABLE (1UL << 2) + +#define CM_ICLKEN1_CORE_EN_MMC1_MASK (1UL << 24) +#define CM_ICLKEN1_CORE_EN_MMC1_DISABLE (0UL << 24) +#define CM_ICLKEN1_CORE_EN_MMC1_ENABLE (1UL << 24) + +#define CM_ICLKEN3_CORE_EN_USBTLL_MASK (1UL << 2) +#define CM_ICLKEN3_CORE_EN_USBTLL_DISABLE (0UL << 2) +#define CM_ICLKEN3_CORE_EN_USBTLL_ENABLE (1UL << 2) + +#define CM_CLKEN_FREQSEL_075_100 (0x03UL << 4) +#define CM_CLKEN_ENABLE (7UL << 0) + +#define CM_CLKSEL_PLL_MULT(x) (((x) & 0x07FF) << 8) +#define CM_CLKSEL_PLL_DIV(x) ((((x) - 1) & 0x7F) << 0) + +#define CM_CLKSEL_DIV_120M(x) (((x) & 0x1F) << 0) + +#define CM_FCLKEN_USBHOST_EN_USBHOST2_MASK (1UL << 1) +#define CM_FCLKEN_USBHOST_EN_USBHOST2_DISABLE (0UL << 1) +#define CM_FCLKEN_USBHOST_EN_USBHOST2_ENABLE (1UL << 1) + +#define CM_FCLKEN_USBHOST_EN_USBHOST1_MASK (1UL << 0) +#define CM_FCLKEN_USBHOST_EN_USBHOST1_DISABLE (0UL << 0) +#define CM_FCLKEN_USBHOST_EN_USBHOST1_ENABLE (1UL << 0) + +#define CM_ICLKEN_USBHOST_EN_USBHOST_MASK (1UL << 0) +#define CM_ICLKEN_USBHOST_EN_USBHOST_DISABLE (0UL << 0) +#define CM_ICLKEN_USBHOST_EN_USBHOST_ENABLE (1UL << 0) + +//Wakeup functional clock +#define CM_FCLKEN_WKUP_EN_GPIO1_DISABLE (0UL << 3) +#define CM_FCLKEN_WKUP_EN_GPIO1_ENABLE (1UL << 3) + +#define CM_FCLKEN_WKUP_EN_WDT2_DISABLE (0UL << 5) +#define CM_FCLKEN_WKUP_EN_WDT2_ENABLE (1UL << 5) + +//Wakeup interface clock +#define CM_ICLKEN_WKUP_EN_GPIO1_DISABLE (0UL << 3) +#define CM_ICLKEN_WKUP_EN_GPIO1_ENABLE (1UL << 3) + +#define CM_ICLKEN_WKUP_EN_WDT2_DISABLE (0UL << 5) +#define CM_ICLKEN_WKUP_EN_WDT2_ENABLE (1UL << 5) + +//Peripheral functional clock +#define CM_FCLKEN_PER_EN_GPT3_DISABLE (0UL << 4) +#define CM_FCLKEN_PER_EN_GPT3_ENABLE (1UL << 4) + +#define CM_FCLKEN_PER_EN_GPT4_DISABLE (0UL << 5) +#define CM_FCLKEN_PER_EN_GPT4_ENABLE (1UL << 5) + +#define CM_FCLKEN_PER_EN_UART3_DISABLE (0UL << 11) +#define CM_FCLKEN_PER_EN_UART3_ENABLE (1UL << 11) + +#define CM_FCLKEN_PER_EN_GPIO2_DISABLE (0UL << 13) +#define CM_FCLKEN_PER_EN_GPIO2_ENABLE (1UL << 13) + +#define CM_FCLKEN_PER_EN_GPIO3_DISABLE (0UL << 14) +#define CM_FCLKEN_PER_EN_GPIO3_ENABLE (1UL << 14) + +#define CM_FCLKEN_PER_EN_GPIO4_DISABLE (0UL << 15) +#define CM_FCLKEN_PER_EN_GPIO4_ENABLE (1UL << 15) + +#define CM_FCLKEN_PER_EN_GPIO5_DISABLE (0UL << 16) +#define CM_FCLKEN_PER_EN_GPIO5_ENABLE (1UL << 16) + +#define CM_FCLKEN_PER_EN_GPIO6_DISABLE (0UL << 17) +#define CM_FCLKEN_PER_EN_GPIO6_ENABLE (1UL << 17) + +//Peripheral interface clock +#define CM_ICLKEN_PER_EN_GPT3_DISABLE (0UL << 4) +#define CM_ICLKEN_PER_EN_GPT3_ENABLE (1UL << 4) + +#define CM_ICLKEN_PER_EN_GPT4_DISABLE (0UL << 5) +#define CM_ICLKEN_PER_EN_GPT4_ENABLE (1UL << 5) + +#define CM_ICLKEN_PER_EN_UART3_DISABLE (0UL << 11) +#define CM_ICLKEN_PER_EN_UART3_ENABLE (1UL << 11) + +#define CM_ICLKEN_PER_EN_GPIO2_DISABLE (0UL << 13) +#define CM_ICLKEN_PER_EN_GPIO2_ENABLE (1UL << 13) + +#define CM_ICLKEN_PER_EN_GPIO3_DISABLE (0UL << 14) +#define CM_ICLKEN_PER_EN_GPIO3_ENABLE (1UL << 14) + +#define CM_ICLKEN_PER_EN_GPIO4_DISABLE (0UL << 15) +#define CM_ICLKEN_PER_EN_GPIO4_ENABLE (1UL << 15) + +#define CM_ICLKEN_PER_EN_GPIO5_DISABLE (0UL << 16) +#define CM_ICLKEN_PER_EN_GPIO5_ENABLE (1UL << 16) + +#define CM_ICLKEN_PER_EN_GPIO6_DISABLE (0UL << 17) +#define CM_ICLKEN_PER_EN_GPIO6_ENABLE (1UL << 17) + +//Timer source clock selection +#define CM_CLKSEL_PER_CLKSEL_GPT3_32K (0UL << 1) +#define CM_CLKSEL_PER_CLKSEL_GPT3_SYS (1UL << 1) + +#define CM_CLKSEL_PER_CLKSEL_GPT4_32K (0UL << 2) +#define CM_CLKSEL_PER_CLKSEL_GPT4_SYS (1UL << 2) + +//Reset management (Global and Cold reset) +#define RST_GS (0x1UL << 1) +#define RST_DPLL3 (0x1UL << 2) +#define GLOBAL_SW_RST (0x1UL << 1) +#define GLOBAL_COLD_RST (0x0UL << 0) + +#endif // __OMAP3530PRCM_H__ + diff --git a/BeagleBoardPkg/Include/Omap3530/Omap3530Timer.h b/BeagleBoardPkg/Include/Omap3530/Omap3530Timer.h new file mode 100644 index 0000000000..1c43b3ee32 --- /dev/null +++ b/BeagleBoardPkg/Include/Omap3530/Omap3530Timer.h @@ -0,0 +1,82 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __OMAP3530TIMER_H__ +#define __OMAP3530TIMER_H__ + +#define GPTIMER1_BASE (0x48313000) +#define GPTIMER2_BASE (0x49032000) +#define GPTIMER3_BASE (0x49034000) +#define GPTIMER4_BASE (0x49036000) +#define GPTIMER5_BASE (0x49038000) +#define GPTIMER6_BASE (0x4903A000) +#define GPTIMER7_BASE (0x4903C000) +#define GPTIMER8_BASE (0x4903E000) +#define GPTIMER9_BASE (0x49040000) +#define GPTIMER10_BASE (0x48086000) +#define GPTIMER11_BASE (0x48088000) +#define GPTIMER12_BASE (0x48304000) +#define WDTIMER2_BASE (0x48314000) + +#define GPTIMER_TIOCP_CFG (0x0010) +#define GPTIMER_TISTAT (0x0014) +#define GPTIMER_TISR (0x0018) +#define GPTIMER_TIER (0x001C) +#define GPTIMER_TWER (0x0020) +#define GPTIMER_TCLR (0x0024) +#define GPTIMER_TCRR (0x0028) +#define GPTIMER_TLDR (0x002C) +#define GPTIMER_TTGR (0x0030) +#define GPTIMER_TWPS (0x0034) +#define GPTIMER_TMAR (0x0038) +#define GPTIMER_TCAR1 (0x003C) +#define GPTIMER_TSICR (0x0040) +#define GPTIMER_TCAR2 (0x0044) +#define GPTIMER_TPIR (0x0048) +#define GPTIMER_TNIR (0x004C) +#define GPTIMER_TCVR (0x0050) +#define GPTIMER_TOCR (0x0054) +#define GPTIMER_TOWR (0x0058) + +#define WSPR (0x048) + +#define TISR_TCAR_IT_FLAG_MASK (1UL << 2) +#define TISR_OVF_IT_FLAG_MASK (1UL << 1) +#define TISR_MAT_IT_FLAG_MASK (1UL << 0) +#define TISR_ALL_INTERRUPT_MASK (TISR_TCAR_IT_FLAG_MASK | TISR_OVF_IT_FLAG_MASK | TISR_MAT_IT_FLAG_MASK) + +#define TISR_TCAR_IT_FLAG_NOT_PENDING (0UL << 2) +#define TISR_OVF_IT_FLAG_NOT_PENDING (0UL << 1) +#define TISR_MAT_IT_FLAG_NOT_PENDING (0UL << 0) +#define TISR_NO_INTERRUPTS_PENDING (TISR_TCAR_IT_FLAG_NOT_PENDING | TISR_OVF_IT_FLAG_NOT_PENDING | TISR_MAT_IT_FLAG_NOT_PENDING) + +#define TISR_TCAR_IT_FLAG_CLEAR (1UL << 2) +#define TISR_OVF_IT_FLAG_CLEAR (1UL << 1) +#define TISR_MAT_IT_FLAG_CLEAR (1UL << 0) +#define TISR_CLEAR_ALL (TISR_TCAR_IT_FLAG_CLEAR | TISR_OVF_IT_FLAG_CLEAR | TISR_MAT_IT_FLAG_CLEAR) + +#define TCLR_AR_AUTORELOAD (1UL << 1) +#define TCLR_AR_ONESHOT (0UL << 1) +#define TCLR_ST_ON (1UL << 0) +#define TCLR_ST_OFF (0UL << 0) + +#define TIER_TCAR_IT_ENABLE (1UL << 2) +#define TIER_TCAR_IT_DISABLE (0UL << 2) +#define TIER_OVF_IT_ENABLE (1UL << 1) +#define TIER_OVF_IT_DISABLE (0UL << 1) +#define TIER_MAT_IT_ENABLE (1UL << 0) +#define TIER_MAT_IT_DISABLE (0UL << 0) + +#endif // __OMAP3530TIMER_H__ + diff --git a/BeagleBoardPkg/Include/Omap3530/Omap3530Uart.h b/BeagleBoardPkg/Include/Omap3530/Omap3530Uart.h new file mode 100644 index 0000000000..aef1c4bab9 --- /dev/null +++ b/BeagleBoardPkg/Include/Omap3530/Omap3530Uart.h @@ -0,0 +1,53 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __OMAP3530UART_H__ +#define __OMAP3530UART_H__ + +#define UART1_BASE (0x4806A000) +#define UART2_BASE (0x4806C000) +#define UART3_BASE (0x49020000) + +#define UART_DLL_REG (0x0000) +#define UART_RBR_REG (0x0000) +#define UART_THR_REG (0x0000) +#define UART_DLH_REG (0x0004) +#define UART_FCR_REG (0x0008) +#define UART_LCR_REG (0x000C) +#define UART_MCR_REG (0x0010) +#define UART_LSR_REG (0x0014) +#define UART_MDR1_REG (0x0020) + +#define UART_FCR_TX_FIFO_CLEAR (1UL << 3) +#define UART_FCR_RX_FIFO_CLEAR (1UL << 3) +#define UART_FCR_FIFO_ENABLE (1UL << 3) + +#define UART_LCR_DIV_EN_ENABLE (1UL << 7) +#define UART_LCR_DIV_EN_DISABLE (0UL << 7) +#define UART_LCR_CHAR_LENGTH_8 (3UL << 0) + +#define UART_MCR_RTS_FORCE_ACTIVE (1UL << 1) +#define UART_MCR_DTR_FORCE_ACTIVE (1UL << 0) + +#define UART_LSR_TX_FIFO_E_MASK (1UL << 5) +#define UART_LSR_TX_FIFO_E_NOT_EMPTY (0UL << 5) +#define UART_LSR_TX_FIFO_E_EMPTY (1UL << 5) +#define UART_LSR_RX_FIFO_E_MASK (1UL << 0) +#define UART_LSR_RX_FIFO_E_NOT_EMPTY (1UL << 0) +#define UART_LSR_RX_FIFO_E_EMPTY (0UL << 0) + +#define UART_MDR1_MODE_SELECT_DISABLE (7UL << 0) +#define UART_MDR1_MODE_SELECT_UART_16X (0UL << 0) + +#endif // __OMAP3530UART_H__ diff --git a/BeagleBoardPkg/Include/Omap3530/Omap3530Usb.h b/BeagleBoardPkg/Include/Omap3530/Omap3530Usb.h new file mode 100644 index 0000000000..5ffaa9d8e4 --- /dev/null +++ b/BeagleBoardPkg/Include/Omap3530/Omap3530Usb.h @@ -0,0 +1,42 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __OMAP3530USB_H__ +#define __OMAP3530USB_H__ + +#define USB_BASE (0x48060000) + +#define UHH_SYSCONFIG (USB_BASE + 0x4010) +#define UHH_HOSTCONFIG (USB_BASE + 0x4040) + +#define USB_EHCI_HCCAPBASE (USB_BASE + 0x4800) + +#define UHH_SYSCONFIG_MIDLEMODE_NO_STANDBY (1UL << 12) +#define UHH_SYSCONFIG_CLOCKACTIVITY_ON (1UL << 8) +#define UHH_SYSCONFIG_SIDLEMODE_NO_STANDBY (1UL << 3) +#define UHH_SYSCONFIG_ENAWAKEUP_ENABLE (1UL << 2) +#define UHH_SYSCONFIG_AUTOIDLE_ALWAYS_RUN (0UL << 0) + +#define UHH_HOSTCONFIG_P3_CONNECT_STATUS_DISCONNECT (0UL << 10) +#define UHH_HOSTCONFIG_P2_CONNECT_STATUS_DISCONNECT (0UL << 9) +#define UHH_HOSTCONFIG_P1_CONNECT_STATUS_DISCONNECT (0UL << 8) +#define UHH_HOSTCONFIG_ENA_INCR_ALIGN_DISABLE (0UL << 5) +#define UHH_HOSTCONFIG_ENA_INCR16_ENABLE (1UL << 4) +#define UHH_HOSTCONFIG_ENA_INCR8_ENABLE (1UL << 3) +#define UHH_HOSTCONFIG_ENA_INCR4_ENABLE (1UL << 2) +#define UHH_HOSTCONFIG_AUTOPPD_ON_OVERCUR_EN_ON (0UL << 1) +#define UHH_HOSTCONFIG_P1_ULPI_BYPASS_ULPI_MODE (0UL << 0) + +#endif // __OMAP3530USB_H__ + diff --git a/BeagleBoardPkg/Include/TPS65950.h b/BeagleBoardPkg/Include/TPS65950.h new file mode 100644 index 0000000000..4b69099219 --- /dev/null +++ b/BeagleBoardPkg/Include/TPS65950.h @@ -0,0 +1,46 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __TPS65950_H__ +#define __TPS65950_H__ + +#define EXTERNAL_DEVICE_REGISTER_TO_SLAVE_ADDRESS(x) (((x) >> 8) & 0xFF) +#define EXTERNAL_DEVICE_REGISTER_TO_REGISTER(x) ((x) & 0xFF) +#define EXTERNAL_DEVICE_REGISTER(SlaveAddress, Register) (((SlaveAddress) & 0xFF) << 8 | ((Register) & 0xFF)) + +//I2C Address group +#define I2C_ADDR_GRP_ID1 0x48 +#define I2C_ADDR_GRP_ID2 0x49 +#define I2C_ADDR_GRP_ID3 0x4A +#define I2C_ADDR_GRP_ID4 0x4B +#define I2C_ADDR_GRP_ID5 0x12 + +//MMC definitions. +#define VMMC1_DEV_GRP 0x82 +#define DEV_GRP_P1 (0x01UL << 5) + +#define VMMC1_DEDICATED_REG 0x85 +#define VSEL_1_85V 0x0 +#define VSEL_2_85V 0x1 +#define VSEL_3_00V 0x2 +#define VSEL_3_15V 0x3 + +//LEDEN register +#define LEDEN 0xEE +#define LEDAON (0x1UL << 0) +#define LEDBON (0x1UL << 1) +#define LEDAPWM (0x1UL << 4) +#define LEDBPWM (0x1UL << 5) + +#endif //__TPS65950_H__ diff --git a/BeagleBoardPkg/InterruptDxe/HardwareInterrupt.c b/BeagleBoardPkg/InterruptDxe/HardwareInterrupt.c new file mode 100644 index 0000000000..97361ffbc1 --- /dev/null +++ b/BeagleBoardPkg/InterruptDxe/HardwareInterrupt.c @@ -0,0 +1,339 @@ +/** @file + Template for Metronome Architecture Protocol driver of the ARM flavor + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +// +// Notifications +// +VOID *CpuProtocolNotificationToken = NULL; +EFI_EVENT CpuProtocolNotificationEvent = (EFI_EVENT)NULL; +EFI_EVENT EfiExitBootServicesEvent = (EFI_EVENT)NULL; + + +HARDWARE_INTERRUPT_HANDLER gRegisteredInterruptHandlers[INT_NROF_VECTORS]; + +/** + Shutdown our hardware + + DXE Core will disable interrupts and turn off the timer and disable interrupts + after all the event handlers have run. + + @param[in] Event The Event that is being processed + @param[in] Context Event Context +**/ +VOID +EFIAPI +ExitBootServicesEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + // Disable all interrupts + MmioWrite32(INTCPS_MIR(0), 0xFFFFFFFF); + MmioWrite32(INTCPS_MIR(1), 0xFFFFFFFF); + MmioWrite32(INTCPS_MIR(2), 0xFFFFFFFF); + MmioWrite32(INTCPS_CONTROL, INTCPS_CONTROL_NEWIRQAGR); +} + +/** + Register Handler for the specified interrupt source. + + @param This Instance pointer for this protocol + @param Source Hardware source of the interrupt + @param Handler Callback for interrupt. NULL to unregister + + @retval EFI_SUCCESS Source was updated to support Handler. + @retval EFI_DEVICE_ERROR Hardware could not be programmed. + +**/ +EFI_STATUS +EFIAPI +RegisterInterruptSource ( + IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This, + IN HARDWARE_INTERRUPT_SOURCE Source, + IN HARDWARE_INTERRUPT_HANDLER Handler + ) +{ + if (Source > MAX_VECTOR) { + ASSERT(FALSE); + return EFI_UNSUPPORTED; + } + + if ((Handler == NULL) && (gRegisteredInterruptHandlers[Source] == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if ((Handler != NULL) && (gRegisteredInterruptHandlers[Source] != NULL)) { + return EFI_ALREADY_STARTED; + } + + gRegisteredInterruptHandlers[Source] = Handler; + + return This->EnableInterruptSource(This, Source); +} + + +/** + Enable interrupt source Source. + + @param This Instance pointer for this protocol + @param Source Hardware source of the interrupt + + @retval EFI_SUCCESS Source interrupt enabled. + @retval EFI_DEVICE_ERROR Hardware could not be programmed. + +**/ +EFI_STATUS +EFIAPI +EnableInterruptSource ( + IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This, + IN HARDWARE_INTERRUPT_SOURCE Source + ) +{ + UINTN Bank; + UINTN Bit; + + if (Source > MAX_VECTOR) { + ASSERT(FALSE); + return EFI_UNSUPPORTED; + } + + Bank = Source / 32; + Bit = 1UL << (Source % 32); + + MmioWrite32(INTCPS_MIR_CLEAR(Bank), Bit); + + return EFI_SUCCESS; +} + + +/** + Disable interrupt source Source. + + @param This Instance pointer for this protocol + @param Source Hardware source of the interrupt + + @retval EFI_SUCCESS Source interrupt disabled. + @retval EFI_DEVICE_ERROR Hardware could not be programmed. + +**/ +EFI_STATUS +EFIAPI +DisableInterruptSource( + IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This, + IN HARDWARE_INTERRUPT_SOURCE Source + ) +{ + UINTN Bank; + UINTN Bit; + + if (Source > MAX_VECTOR) { + ASSERT(FALSE); + return EFI_UNSUPPORTED; + } + + Bank = Source / 32; + Bit = 1UL << (Source % 32); + + MmioWrite32(INTCPS_MIR_SET(Bank), Bit); + + return EFI_SUCCESS; +} + + + +/** + Return current state of interrupt source Source. + + @param This Instance pointer for this protocol + @param Source Hardware source of the interrupt + @param InterruptState TRUE: source enabled, FALSE: source disabled. + + @retval EFI_SUCCESS InterruptState is valid + @retval EFI_DEVICE_ERROR InterruptState is not valid + +**/ +EFI_STATUS +EFIAPI +GetInterruptSourceState ( + IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This, + IN HARDWARE_INTERRUPT_SOURCE Source, + IN BOOLEAN *InterruptState + ) +{ + UINTN Bank; + UINTN Bit; + + if (InterruptState == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Source > MAX_VECTOR) { + ASSERT(FALSE); + return EFI_UNSUPPORTED; + } + + Bank = Source / 32; + Bit = 1UL << (Source % 32); + + if ((MmioRead32(INTCPS_MIR(Bank)) & Bit) == Bit) { + *InterruptState = FALSE; + } else { + *InterruptState = TRUE; + } + + return EFI_SUCCESS; +} + + + +/** + EFI_CPU_INTERRUPT_HANDLER that is called when a processor interrupt occurs. + + @param InterruptType Defines the type of interrupt or exception that + occurred on the processor.This parameter is processor architecture specific. + @param SystemContext A pointer to the processor context when + the interrupt occurred on the processor. + + @return None + +**/ +VOID +EFIAPI +IrqInterruptHandler ( + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + UINT32 Vector; + HARDWARE_INTERRUPT_HANDLER InterruptHandler; + + Vector = MmioRead32(INTCPS_SIR_IRQ) & INTCPS_SIR_IRQ_MASK; + + InterruptHandler = gRegisteredInterruptHandlers[Vector]; + if (InterruptHandler != NULL) { + // Call the registered interrupt handler. + InterruptHandler(Vector, SystemContext); + } + + MmioWrite32(INTCPS_CONTROL, INTCPS_CONTROL_NEWIRQAGR); +} + +// +// Making this global saves a few bytes in image size +// +EFI_HANDLE gHardwareInterruptHandle = NULL; + +// +// The protocol instance produced by this driver +// +EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptProtocol = { + RegisterInterruptSource, + EnableInterruptSource, + DisableInterruptSource, + GetInterruptSourceState +}; + +// +// Notification routines +// +VOID +CpuProtocolInstalledNotification ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + EFI_CPU_ARCH_PROTOCOL *Cpu; + + // + // Get the cpu protocol that this driver requires. + // + Status = gBS->LocateProtocol(&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu); + ASSERT_EFI_ERROR(Status); + + // + // Unregister the default exception handler. + // + Status = Cpu->RegisterInterruptHandler(Cpu, EXCEPT_ARM_IRQ, NULL); + ASSERT_EFI_ERROR(Status); + + // + // Register to receive interrupts + // + Status = Cpu->RegisterInterruptHandler(Cpu, EXCEPT_ARM_IRQ, IrqInterruptHandler); + ASSERT_EFI_ERROR(Status); +} + +/** + Initialize the state information for the CPU Architectural Protocol + + @param ImageHandle of the loaded driver + @param SystemTable Pointer to the System Table + + @retval EFI_SUCCESS Protocol registered + @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure + @retval EFI_DEVICE_ERROR Hardware problems + +**/ +EFI_STATUS +InterruptDxeInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // Make sure the Interrupt Controller Protocol is not already installed in the system. + ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gHardwareInterruptProtocolGuid); + + // Make sure all interrupts are disabled by default. + MmioWrite32(INTCPS_MIR(0), 0xFFFFFFFF); + MmioWrite32(INTCPS_MIR(1), 0xFFFFFFFF); + MmioWrite32(INTCPS_MIR(2), 0xFFFFFFFF); + MmioWrite32(INTCPS_CONTROL, INTCPS_CONTROL_NEWIRQAGR); + + Status = gBS->InstallMultipleProtocolInterfaces(&gHardwareInterruptHandle, + &gHardwareInterruptProtocolGuid, &gHardwareInterruptProtocol, + NULL); + ASSERT_EFI_ERROR(Status); + + // Set up to be notified when the Cpu protocol is installed. + Status = gBS->CreateEvent(EVT_NOTIFY_SIGNAL, TPL_CALLBACK, CpuProtocolInstalledNotification, NULL, &CpuProtocolNotificationEvent); + ASSERT_EFI_ERROR(Status); + + Status = gBS->RegisterProtocolNotify(&gEfiCpuArchProtocolGuid, CpuProtocolNotificationEvent, (VOID *)&CpuProtocolNotificationToken); + ASSERT_EFI_ERROR(Status); + + // Register for an ExitBootServicesEvent + Status = gBS->CreateEvent(EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_NOTIFY, ExitBootServicesEvent, NULL, &EfiExitBootServicesEvent); + ASSERT_EFI_ERROR(Status); + + return Status; +} + diff --git a/BeagleBoardPkg/InterruptDxe/InterruptDxe.inf b/BeagleBoardPkg/InterruptDxe/InterruptDxe.inf new file mode 100644 index 0000000000..92b8f780bf --- /dev/null +++ b/BeagleBoardPkg/InterruptDxe/InterruptDxe.inf @@ -0,0 +1,56 @@ +#%HEADER% +#/** @file +# +# Interrupt DXE driver +# +# Copyright (c) 2009, Apple, Inc
+# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BeagleBoardInterruptDxe + FILE_GUID = 23eed05d-1b93-4a1a-8e1b-931d69e37952 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = InterruptDxeInitialize + + +[Sources.common] + HardwareInterrupt.c + + +[Packages] + BeagleBoardPkg/BeagleBoardPkg.dec + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + +[LibraryClasses] + BaseLib + UefiLib + UefiBootServicesTableLib + DebugLib + PrintLib + UefiDriverEntryPoint + IoLib + +[Guids] + + +[Protocols] + gHardwareInterruptProtocolGuid + gEfiCpuArchProtocolGuid + +[FixedPcd.common] + gEmbeddedTokenSpaceGuid.PcdInterruptBaseAddress + +[depex] + TRUE diff --git a/BeagleBoardPkg/Library/BeagleBoardSystemLib/BeagleBoardSystemLib.c b/BeagleBoardPkg/Library/BeagleBoardSystemLib/BeagleBoardSystemLib.c new file mode 100644 index 0000000000..a03ef575fb --- /dev/null +++ b/BeagleBoardPkg/Library/BeagleBoardSystemLib/BeagleBoardSystemLib.c @@ -0,0 +1,110 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +VOID +ResetSystem ( + IN EFI_RESET_TYPE ResetType + ) +{ + switch (ResetType) { + case EfiResetWarm: + //Perform warm reset of the system. + GoLittleEndian(PcdGet32(PcdFlashFvMainBase)); + break; + case EfiResetCold: + case EfiResetShutdown: + default: + //Perform cold reset of the system. + MmioOr32(PRM_RSTCTRL, RST_DPLL3); + while ((MmioRead32(PRM_RSTST) & GLOBAL_COLD_RST) != 0x1); + break; + } + + //Should never come here. + ASSERT(FALSE); +} + +VOID +ShutdownEfi ( + VOID + ) +{ + EFI_STATUS Status; + UINTN MemoryMapSize; + EFI_MEMORY_DESCRIPTOR *MemoryMap; + UINTN MapKey; + UINTN DescriptorSize; + UINTN DescriptorVersion; + UINTN Pages; + + MemoryMap = NULL; + MemoryMapSize = 0; + do { + Status = gBS->GetMemoryMap ( + &MemoryMapSize, + MemoryMap, + &MapKey, + &DescriptorSize, + &DescriptorVersion + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + + Pages = EFI_SIZE_TO_PAGES (MemoryMapSize) + 1; + MemoryMap = AllocatePages (Pages); + + // + // Get System MemoryMap + // + Status = gBS->GetMemoryMap ( + &MemoryMapSize, + MemoryMap, + &MapKey, + &DescriptorSize, + &DescriptorVersion + ); + // Don't do anything between the GetMemoryMap() and ExitBootServices() + if (!EFI_ERROR (Status)) { + Status = gBS->ExitBootServices (gImageHandle, MapKey); + if (EFI_ERROR (Status)) { + FreePages (MemoryMap, Pages); + MemoryMap = NULL; + MemoryMapSize = 0; + } + } + } + } while (EFI_ERROR (Status)); + + //Clean and invalidate caches. + WriteBackInvalidateDataCache(); + InvalidateInstructionCache(); + + //Turning off Caches and MMU + ArmDisableDataCache(); + ArmDisableInstructionCache(); + ArmDisableMmu(); +} + diff --git a/BeagleBoardPkg/Library/BeagleBoardSystemLib/BeagleBoardSystemLib.inf b/BeagleBoardPkg/Library/BeagleBoardSystemLib/BeagleBoardSystemLib.inf new file mode 100644 index 0000000000..2c23ad00e7 --- /dev/null +++ b/BeagleBoardPkg/Library/BeagleBoardSystemLib/BeagleBoardSystemLib.inf @@ -0,0 +1,45 @@ +#%HEADER% +#/** @file +# Support for Airport libraries. +# +# Copyright (c) 2009, Apple Inc. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BeagleBoardSystemLib + FILE_GUID = b15a2640-fef2-447c-98e1-9ce22cfa529c + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = BeagleBoardSystemLib + +[Sources.ARM] + BeagleBoardSystemLib.c + GoLittleEndian.asm | RVCT + GoLittleEndian.S | GCC + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + ArmPkg/ArmPkg.dec + BeagleBoardPkg/BeagleBoardPkg.dec + +[LibraryClasses] + ArmLib + CacheMaintenanceLib + MemoryAllocationLib + UefiRuntimeServicesTableLib + TimerLib + UefiLib + +[Pcd] + gEmbeddedTokenSpaceGuid.PcdFlashFvMainBase diff --git a/BeagleBoardPkg/Library/BeagleBoardSystemLib/GoLittleEndian.S b/BeagleBoardPkg/Library/BeagleBoardSystemLib/GoLittleEndian.S new file mode 100644 index 0000000000..a37ae7c883 --- /dev/null +++ b/BeagleBoardPkg/Library/BeagleBoardSystemLib/GoLittleEndian.S @@ -0,0 +1,27 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2008-2009 Apple Inc. All rights reserved. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + +.text +.align 3 +.globl ASM_PFX(GoLittleEndian) + +// r0 is target address +ASM_PFX(GoLittleEndian): + + // Switch to SVC Mode + mov r2,#0xD3 // SVC mode + msr CPSR_c,r2 // Switch modes + + bx r0 + diff --git a/BeagleBoardPkg/Library/BeagleBoardSystemLib/GoLittleEndian.asm b/BeagleBoardPkg/Library/BeagleBoardSystemLib/GoLittleEndian.asm new file mode 100755 index 0000000000..8daced6b8f --- /dev/null +++ b/BeagleBoardPkg/Library/BeagleBoardSystemLib/GoLittleEndian.asm @@ -0,0 +1,27 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2008-2009 Apple Inc. All rights reserved. +// +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +//------------------------------------------------------------------------------ + + EXPORT GoLittleEndian + PRESERVE8 + AREA Ebl, CODE, READONLY + +// r0 is target address +GoLittleEndian + // Switch to SVC Mode + mov r2,#0xD3 // SVC mode + msr CPSR_c,r2 // Switch modes + + bx r0 + + END diff --git a/BeagleBoardPkg/Library/BeagleBoardTimerLib/BeagleBoardTimerLib.inf b/BeagleBoardPkg/Library/BeagleBoardTimerLib/BeagleBoardTimerLib.inf new file mode 100644 index 0000000000..5b59014585 --- /dev/null +++ b/BeagleBoardPkg/Library/BeagleBoardTimerLib/BeagleBoardTimerLib.inf @@ -0,0 +1,46 @@ +#%HEADER% +#/** @file +# Timer library implementation +# +# A non-functional instance of the Timer Library that can be used as a template +# for the implementation of a functional timer library instance. This library instance can +# also be used to test build DXE, Runtime, DXE SAL, and DXE SMM modules that require timer +# services as well as EBC modules that require timer services +# Copyright (c) 2007, Intel Corporation. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BeagleBoardTimerLib + FILE_GUID = fe1d7183-9abb-42ce-9a3b-36d7c6a8959f + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = TimerLib + +[Sources.common] + TimerLib.c + +[Packages] + BeagleBoardPkg/BeagleBoardPkg.dec + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + +[LibraryClasses] + DebugLib + OmapLib + IoLib + +[Pcd] + gEmbeddedTokenSpaceGuid.PcdEmbeddedPerformanceCounterFreqencyInHz + gEmbeddedTokenSpaceGuid.PcdEmbeddedFdPerformanceCounterPeriodInNanoseconds + gBeagleBoardTokenSpaceGuid.PcdBeagleFreeTimer + diff --git a/BeagleBoardPkg/Library/BeagleBoardTimerLib/TimerLib.c b/BeagleBoardPkg/Library/BeagleBoardTimerLib/TimerLib.c new file mode 100755 index 0000000000..1b9a5bac4f --- /dev/null +++ b/BeagleBoardPkg/Library/BeagleBoardTimerLib/TimerLib.c @@ -0,0 +1,102 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include +#include +#include +#include + +#include + +UINTN +EFIAPI +MicroSecondDelay ( + IN UINTN MicroSeconds + ) +{ + UINT64 NanoSeconds; + + NanoSeconds = MultU64x32(MicroSeconds, 1000); + + while (NanoSeconds > (UINTN)-1) { + NanoSecondDelay((UINTN)-1); + NanoSeconds -= (UINTN)-1; + } + + NanoSecondDelay(NanoSeconds); + + return MicroSeconds; +} + +UINTN +EFIAPI +NanoSecondDelay ( + IN UINTN NanoSeconds + ) +{ + UINT32 Delay; + UINT32 StartTime; + UINT32 CurrentTime; + UINT32 ElapsedTime; + UINT32 TimerCountRegister; + + Delay = (NanoSeconds / PcdGet32(PcdEmbeddedFdPerformanceCounterPeriodInNanoseconds)) + 1; + + TimerCountRegister = TimerBase(PcdGet32(PcdBeagleFreeTimer)) + GPTIMER_TCRR; + + StartTime = MmioRead32(TimerCountRegister); + + do + { + CurrentTime = MmioRead32(TimerCountRegister); + ElapsedTime = CurrentTime - StartTime; + } while (ElapsedTime < Delay); + + NanoSeconds = ElapsedTime * PcdGet32(PcdEmbeddedFdPerformanceCounterPeriodInNanoseconds); + + return NanoSeconds; +} + +UINT64 +EFIAPI +GetPerformanceCounter ( + VOID + ) +{ + return (UINT64)MmioRead32(TimerBase(PcdGet32(PcdBeagleFreeTimer)) + GPTIMER_TCRR); +} + +UINT64 +EFIAPI +GetPerformanceCounterProperties ( + OUT UINT64 *StartValue, OPTIONAL + OUT UINT64 *EndValue OPTIONAL + ) +{ + if (StartValue != NULL) { + // Timer starts with the reload value + *StartValue = (UINT64)MmioRead32(TimerBase(PcdGet32(PcdBeagleFreeTimer)) + GPTIMER_TLDR); + } + + if (EndValue != NULL) { + // Timer counts up to 0xFFFFFFFF + *EndValue = 0xFFFFFFFF; + } + + return PcdGet64(PcdEmbeddedPerformanceCounterFreqencyInHz); +} diff --git a/BeagleBoardPkg/Library/EblCmdLib/EblCmdLib.c b/BeagleBoardPkg/Library/EblCmdLib/EblCmdLib.c new file mode 100644 index 0000000000..93164d68df --- /dev/null +++ b/BeagleBoardPkg/Library/EblCmdLib/EblCmdLib.c @@ -0,0 +1,42 @@ +/** @file + Add custom commands for BeagleBoard development. + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mLibCmdTemplate[] = +{ +}; + + +VOID +EblInitializeExternalCmd ( + VOID + ) +{ + EblAddCommands (mLibCmdTemplate, sizeof (mLibCmdTemplate)/sizeof (EBL_COMMAND_TABLE)); + return; +} diff --git a/BeagleBoardPkg/Library/EblCmdLib/EblCmdLib.inf b/BeagleBoardPkg/Library/EblCmdLib/EblCmdLib.inf new file mode 100644 index 0000000000..aa8482b79d --- /dev/null +++ b/BeagleBoardPkg/Library/EblCmdLib/EblCmdLib.inf @@ -0,0 +1,49 @@ +#%HEADER% +#/** @file +# Component description file for the entry point to a EFIDXE Drivers +# +# Library to abstract Framework extensions that conflict with UEFI 2.0 Specification +# Copyright (c) 2007 - 2007, Intel Corporation +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BeagleBoardEblCmdLib + FILE_GUID = ea62bdc3-1063-425f-8851-98cb47f213a8 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = EblCmdLib|DXE_DRIVER UEFI_APPLICATION UEFI_DRIVER + + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources.common] + EblCmdLib.c + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + ArmPkg/ArmPkg.dec + +[LibraryClasses] + BaseLib + DebugLib + +[Protocols] + +[Guids] + +[Pcd] diff --git a/BeagleBoardPkg/Library/GdbSerialLib/GdbSerialLib.c b/BeagleBoardPkg/Library/GdbSerialLib/GdbSerialLib.c new file mode 100644 index 0000000000..9d5f429e2d --- /dev/null +++ b/BeagleBoardPkg/Library/GdbSerialLib/GdbSerialLib.c @@ -0,0 +1,103 @@ +/** @file + Basic serial IO abstaction for GDB + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include +#include +#include + +RETURN_STATUS +EFIAPI +GdbSerialLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return RETURN_SUCCESS; +} + +RETURN_STATUS +EFIAPI +GdbSerialInit ( + IN UINT64 BaudRate, + IN UINT8 Parity, + IN UINT8 DataBits, + IN UINT8 StopBits + ) +{ + return RETURN_SUCCESS; +} + +BOOLEAN +EFIAPI +GdbIsCharAvailable ( + VOID + ) +{ + UINT32 LSR = UartBase(PcdGet32(PcdBeagleConsoleUart)) + UART_LSR_REG; + + if ((MmioRead8(LSR) & UART_LSR_RX_FIFO_E_MASK) == UART_LSR_RX_FIFO_E_NOT_EMPTY) { + return TRUE; + } else { + return FALSE; + } +} + +CHAR8 +EFIAPI +GdbGetChar ( + VOID + ) +{ + UINT32 LSR = UartBase(PcdGet32(PcdBeagleConsoleUart)) + UART_LSR_REG; + UINT32 RBR = UartBase(PcdGet32(PcdBeagleConsoleUart)) + UART_RBR_REG; + CHAR8 Char; + + while ((MmioRead8(LSR) & UART_LSR_RX_FIFO_E_MASK) == UART_LSR_RX_FIFO_E_EMPTY); + Char = MmioRead8(RBR); + + return Char; +} + +VOID +EFIAPI +GdbPutChar ( + IN CHAR8 Char + ) +{ + UINT32 LSR = UartBase(PcdGet32(PcdBeagleConsoleUart)) + UART_LSR_REG; + UINT32 THR = UartBase(PcdGet32(PcdBeagleConsoleUart)) + UART_THR_REG; + + while ((MmioRead8(LSR) & UART_LSR_TX_FIFO_E_MASK) == UART_LSR_TX_FIFO_E_NOT_EMPTY); + MmioWrite8(THR, Char); +} + +VOID +GdbPutString ( + IN CHAR8 *String + ) +{ + while (*String != '\0') { + GdbPutChar (*String); + String++; + } +} + + + + diff --git a/BeagleBoardPkg/Library/GdbSerialLib/GdbSerialLib.inf b/BeagleBoardPkg/Library/GdbSerialLib/GdbSerialLib.inf new file mode 100644 index 0000000000..c8e6859023 --- /dev/null +++ b/BeagleBoardPkg/Library/GdbSerialLib/GdbSerialLib.inf @@ -0,0 +1,29 @@ +#%HEADER% +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = GdbSerialLib + FILE_GUID = E2423349-EF5D-439B-95F5-8B8D8E3B443F + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = GdbSerialLib + + CONSTRUCTOR = GdbSerialLibConstructor + + +[Sources.common] + GdbSerialLib.c + + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + BeagleBoardPkg/BeagleBoardPkg.dec + +[LibraryClasses] + DebugLib + IoLib + OmapLib + +[FixedPcd] + gBeagleBoardTokenSpaceGuid.PcdBeagleConsoleUart + diff --git a/BeagleBoardPkg/Library/OmapLib/OmapLib.c b/BeagleBoardPkg/Library/OmapLib/OmapLib.c new file mode 100644 index 0000000000..7464b2e74a --- /dev/null +++ b/BeagleBoardPkg/Library/OmapLib/OmapLib.c @@ -0,0 +1,83 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include + +UINT32 +GpioBase ( + IN UINTN Port + ) +{ + switch (Port) { + case 1: return GPIO1_BASE; + case 2: return GPIO2_BASE; + case 3: return GPIO3_BASE; + case 4: return GPIO4_BASE; + case 5: return GPIO5_BASE; + case 6: return GPIO6_BASE; + default: ASSERT(FALSE); return 0; + } +} + +UINT32 +TimerBase ( + IN UINTN Timer + ) +{ + switch (Timer) { + case 1: return GPTIMER1_BASE; + case 2: return GPTIMER2_BASE; + case 3: return GPTIMER3_BASE; + case 4: return GPTIMER4_BASE; + case 5: return GPTIMER5_BASE; + case 6: return GPTIMER6_BASE; + case 7: return GPTIMER7_BASE; + case 8: return GPTIMER8_BASE; + case 9: return GPTIMER9_BASE; + case 10: return GPTIMER10_BASE; + case 11: return GPTIMER11_BASE; + case 12: return GPTIMER12_BASE; + default: return 0; + } +} + +UINTN +InterruptVectorForTimer ( + IN UINTN Timer + ) +{ + if ((Timer < 1) || (Timer > 12)) { + ASSERT(FALSE); + return 0xFFFFFFFF; + } + + return 36 + Timer; +} + +UINT32 +UartBase ( + IN UINTN Uart + ) +{ + switch (Uart) { + case 1: return UART1_BASE; + case 2: return UART2_BASE; + case 3: return UART3_BASE; + default: ASSERT(FALSE); return 0; + } +} + diff --git a/BeagleBoardPkg/Library/OmapLib/OmapLib.inf b/BeagleBoardPkg/Library/OmapLib/OmapLib.inf new file mode 100644 index 0000000000..8fe030cff1 --- /dev/null +++ b/BeagleBoardPkg/Library/OmapLib/OmapLib.inf @@ -0,0 +1,25 @@ +#%HEADER% +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = OmapLib + FILE_GUID = d035f5c2-1b92-4746-9f6c-5ff6202970df + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = OmapLib + +[Sources.common] + OmapLib.c + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + BeagleBoardPkg/BeagleBoardPkg.dec + +[LibraryClasses] + DebugLib + +[Protocols] + +[Guids] + +[Pcd] diff --git a/BeagleBoardPkg/Library/ResetSystemLib/ResetSystemLib.c b/BeagleBoardPkg/Library/ResetSystemLib/ResetSystemLib.c new file mode 100644 index 0000000000..9c427e5c65 --- /dev/null +++ b/BeagleBoardPkg/Library/ResetSystemLib/ResetSystemLib.c @@ -0,0 +1,84 @@ +/** @file + Template library implementation to support ResetSystem Runtime call. + + Fill in the templates with what ever makes you system reset. + + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include + +#include +#include +#include +#include +#include + +#include + +/** + Resets the entire platform. + + @param ResetType The type of reset to perform. + @param ResetStatus The status code for the reset. + @param DataSize The size, in bytes, of WatchdogData. + @param ResetData For a ResetType of EfiResetCold, EfiResetWarm, or + EfiResetShutdown the data buffer starts with a Null-terminated + Unicode string, optionally followed by additional binary data. + +**/ +EFI_STATUS +EFIAPI +LibResetSystem ( + IN EFI_RESET_TYPE ResetType, + IN EFI_STATUS ResetStatus, + IN UINTN DataSize, + IN CHAR16 *ResetData OPTIONAL + ) +{ + if (ResetData != NULL) { + DEBUG((EFI_D_ERROR, "%s", ResetData)); + } + + //Shutdown EFI services. + ShutdownEfi(); + + //Reset the sytem. + ResetSystem(ResetType); + + // If the reset didn't work, return an error. + return EFI_DEVICE_ERROR; +} + + + +/** + Initialize any infrastructure required for LibResetSystem () to function. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +LibInitializeResetSystem ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EFI_SUCCESS; +} + diff --git a/BeagleBoardPkg/Library/ResetSystemLib/ResetSystemLib.inf b/BeagleBoardPkg/Library/ResetSystemLib/ResetSystemLib.inf new file mode 100644 index 0000000000..e62d94b5b4 --- /dev/null +++ b/BeagleBoardPkg/Library/ResetSystemLib/ResetSystemLib.inf @@ -0,0 +1,41 @@ +#%HEADER% +#/** @file +# Reset System lib to make it easy to port new platforms +# +# Copyright (c) 2008, Apple Inc. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BeagleBoardResetSystemLib + FILE_GUID = 781371a2-3fdd-41d4-96a1-7b34cbc9e895 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = EfiResetSystemLib + + +[Sources.common] + ResetSystemLib.c + +[Packages] + BeagleBoardPkg/BeagleBoardPkg.dec + ArmPkg/ArmPkg.dec + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + +[Pcd.common] + gArmTokenSpaceGuid.PcdCpuResetAddress + gEmbeddedTokenSpaceGuid.PcdEmbeddedFdBaseAddress + +[LibraryClasses] + DebugLib + BeagleBoardSystemLib diff --git a/BeagleBoardPkg/Library/SerialPortLib/SerialPortLib.c b/BeagleBoardPkg/Library/SerialPortLib/SerialPortLib.c new file mode 100644 index 0000000000..0509deb8ab --- /dev/null +++ b/BeagleBoardPkg/Library/SerialPortLib/SerialPortLib.c @@ -0,0 +1,124 @@ +/** @file + Serial I/O Port library functions with no library constructor/destructor + + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include +#include +#include + +/* + + Programmed hardware of Serial port. + + @return Always return EFI_UNSUPPORTED. + +**/ +RETURN_STATUS +EFIAPI +SerialPortInitialize ( + VOID + ) +{ + // assume assembly code at reset vector has setup UART + return RETURN_SUCCESS; +} + +/** + Write data to serial device. + + @param Buffer Point of data buffer which need to be writed. + @param NumberOfBytes Number of output bytes which are cached in Buffer. + + @retval 0 Write data failed. + @retval !0 Actual number of bytes writed to serial device. + +**/ +UINTN +EFIAPI +SerialPortWrite ( + IN UINT8 *Buffer, + IN UINTN NumberOfBytes +) +{ + UINT32 LSR = UartBase(PcdGet32(PcdBeagleConsoleUart)) + UART_LSR_REG; + UINT32 THR = UartBase(PcdGet32(PcdBeagleConsoleUart)) + UART_THR_REG; + UINTN Count; + + for (Count = 0; Count < NumberOfBytes; Count++, Buffer++) { + while ((MmioRead8(LSR) & UART_LSR_TX_FIFO_E_MASK) == UART_LSR_TX_FIFO_E_NOT_EMPTY); + MmioWrite8(THR, *Buffer); + } + + return NumberOfBytes; +} + + +/** + Read data from serial device and save the datas in buffer. + + @param Buffer Point of data buffer which need to be writed. + @param NumberOfBytes Number of output bytes which are cached in Buffer. + + @retval 0 Read data failed. + @retval !0 Aactual number of bytes read from serial device. + +**/ +UINTN +EFIAPI +SerialPortRead ( + OUT UINT8 *Buffer, + IN UINTN NumberOfBytes +) +{ + UINT32 LSR = UartBase(PcdGet32(PcdBeagleConsoleUart)) + UART_LSR_REG; + UINT32 RBR = UartBase(PcdGet32(PcdBeagleConsoleUart)) + UART_RBR_REG; + UINTN Count; + + for (Count = 0; Count < NumberOfBytes; Count++, Buffer++) { + while ((MmioRead8(LSR) & UART_LSR_RX_FIFO_E_MASK) == UART_LSR_RX_FIFO_E_EMPTY); + *Buffer = MmioRead8(RBR); + } + + return NumberOfBytes; +} + + +/** + Check to see if any data is avaiable to be read from the debug device. + + @retval EFI_SUCCESS At least one byte of data is avaiable to be read + @retval EFI_NOT_READY No data is avaiable to be read + @retval EFI_DEVICE_ERROR The serial device is not functioning properly + +**/ +BOOLEAN +EFIAPI +SerialPortPoll ( + VOID + ) +{ + UINT32 LSR = UartBase(PcdGet32(PcdBeagleConsoleUart)) + UART_LSR_REG; + + if ((MmioRead8(LSR) & UART_LSR_RX_FIFO_E_MASK) == UART_LSR_RX_FIFO_E_NOT_EMPTY) { + return TRUE; + } else { + return FALSE; + } +} + diff --git a/BeagleBoardPkg/Library/SerialPortLib/SerialPortLib.inf b/BeagleBoardPkg/Library/SerialPortLib/SerialPortLib.inf new file mode 100644 index 0000000000..b81bbca657 --- /dev/null +++ b/BeagleBoardPkg/Library/SerialPortLib/SerialPortLib.inf @@ -0,0 +1,44 @@ +#%HEADER% +#/** @file +# EDK Serial port lib +# +# Copyright (c) 2009, Apple Inc. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BeagleBoardSerialPortLib + FILE_GUID = 97546cbd-c0ff-4c48-ab0b-e4f58862acd3 + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + LIBRARY_CLASS = SerialPortLib + + +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources.common] + SerialPortLib.c + +[LibraryClasses] + DebugLib + IoLib + OmapLib + +[Packages] + MdePkg/MdePkg.dec + BeagleBoardPkg/BeagleBoardPkg.dec + +[FixedPcd] + gBeagleBoardTokenSpaceGuid.PcdBeagleConsoleUart + diff --git a/BeagleBoardPkg/MMCHSDxe/MMCHS.c b/BeagleBoardPkg/MMCHSDxe/MMCHS.c new file mode 100644 index 0000000000..77c5fbdbfa --- /dev/null +++ b/BeagleBoardPkg/MMCHSDxe/MMCHS.c @@ -0,0 +1,1018 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include "MMCHS.h" + +EFI_BLOCK_IO_MEDIA MMCHSMedia = { + SIGNATURE_32('s','d','i','o'), // MediaId + FALSE, // RemovableMedia + TRUE, // MediaPresent + TRUE, // LogicalPartition + FALSE, // ReadOnly + FALSE, // WriteCaching + 512, // BlockSize + 4, // IoAlign + 0, // Pad + 0 // LastBlock +}; + +typedef struct { + VENDOR_DEVICE_PATH Mmc; + EFI_DEVICE_PATH End; +} MMCHS_DEVICE_PATH; + +MMCHS_DEVICE_PATH gMmcHsDevicePath = +{ + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + (UINT8)(sizeof(VENDOR_DEVICE_PATH)), + (UINT8)((sizeof(VENDOR_DEVICE_PATH)) >> 8), + 0xb615f1f5, 0x5088, 0x43cd, 0x80, 0x9c, 0xa1, 0x6e, 0x52, 0x48, 0x7d, 0x00 + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + sizeof (EFI_DEVICE_PATH_PROTOCOL), + 0 + } +}; + +CARD_INFO *gCardInfo; +EMBEDDED_EXTERNAL_DEVICE *gTPS65950; + +// +// Internal Functions +// + +STATIC +VOID +ParseCardCIDData ( + UINT32 Response0, + UINT32 Response1, + UINT32 Response2, + UINT32 Response3 + ) +{ + gCardInfo->CIDData.MDT = ((Response0 >> 8) & 0xFFF); + gCardInfo->CIDData.PSN = (((Response0 >> 24) & 0xFF) | ((Response1 & 0xFFFFFF) << 8)); + gCardInfo->CIDData.PRV = ((Response1 >> 24) & 0xFF); + gCardInfo->CIDData.PNM[4] = ((Response2) & 0xFF); + gCardInfo->CIDData.PNM[3] = ((Response2 >> 8) & 0xFF); + gCardInfo->CIDData.PNM[2] = ((Response2 >> 16) & 0xFF); + gCardInfo->CIDData.PNM[1] = ((Response2 >> 24) & 0xFF); + gCardInfo->CIDData.PNM[0] = ((Response3) & 0xFF); + gCardInfo->CIDData.OID = ((Response3 >> 8) & 0xFFFF); + gCardInfo->CIDData.MID = ((Response3 >> 24) & 0xFF); +} + +STATIC +VOID +UpdateMMCHSClkFrequency ( + UINTN NewCLKD + ) +{ + //Set Clock enable to 0x0 to not provide the clock to the card + MmioAnd32(MMCHS_SYSCTL, ~CEN); + + //Set new clock frequency. + MmioAndThenOr32(MMCHS_SYSCTL, ~CLKD_MASK, NewCLKD << 6); + + //Poll till Internal Clock Stable + while ((MmioRead32(MMCHS_SYSCTL) & ICS_MASK) != ICS); + + //Set Clock enable to 0x1 to provide the clock to the card + MmioOr32(MMCHS_SYSCTL, CEN); +} + +STATIC +EFI_STATUS +SendCmd ( + UINTN Cmd, + UINTN CmdInterruptEnableVal, + UINTN CmdArgument + ) +{ + UINTN MmcStatus; + UINTN RetryCount = 0; + + //Check if command line is in use or not. Poll till command line is available. + while ((MmioRead32(MMCHS_PSTATE) & DATI_MASK) == DATI_NOT_ALLOWED); + + //Provide the block size. + MmioWrite32(MMCHS_BLK, BLEN_512BYTES); + + //Setting Data timeout counter value to max value. + MmioAndThenOr32(MMCHS_SYSCTL, ~DTO_MASK, DTO_VAL); + + //Clear Status register. + MmioWrite32(MMCHS_STAT, 0xFFFFFFFF); + + //Set command argument register + MmioWrite32(MMCHS_ARG, CmdArgument); + + //Enable interrupt enable events to occur + MmioWrite32(MMCHS_IE, CmdInterruptEnableVal); + + //Send a command + MmioWrite32(MMCHS_CMD, Cmd); + + //Check for the command status. + while (RetryCount < MAX_RETRY_COUNT) { + do { + MmcStatus = MmioRead32(MMCHS_STAT); + } while (MmcStatus == 0); + + //Read status of command response + if ((MmcStatus & ERRI) != 0) { + + //Perform soft-reset for mmci_cmd line. + MmioOr32(MMCHS_SYSCTL, SRC); + while ((MmioRead32(MMCHS_SYSCTL) & SRC)); + + DEBUG ((EFI_D_INFO, "MmcStatus: %x\n", MmcStatus)); + return EFI_DEVICE_ERROR; + } + + //Check if command is completed. + if ((MmcStatus & CC) == CC) { + MmioWrite32(MMCHS_STAT, CC); + break; + } + + RetryCount++; + } + + if (RetryCount == MAX_RETRY_COUNT) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +STATIC +VOID +GetBlockInformation ( + UINTN *BlockSize, + UINTN *NumBlocks + ) +{ + CSD_SDV2 *CsdSDV2Data; + UINTN CardSize; + + if (gCardInfo->CardType == SD_CARD_2_HIGH) { + CsdSDV2Data = (CSD_SDV2 *)&gCardInfo->CSDData; + + //Populate BlockSize. + *BlockSize = (0x1UL << CsdSDV2Data->READ_BL_LEN); + + //Calculate Total number of blocks. + CardSize = CsdSDV2Data->C_SIZELow16 | (CsdSDV2Data->C_SIZEHigh6 << 2); + *NumBlocks = ((CardSize + 1) * 1024); + } else { + //Populate BlockSize. + *BlockSize = (0x1UL << gCardInfo->CSDData.READ_BL_LEN); + + //Calculate Total number of blocks. + CardSize = gCardInfo->CSDData.C_SIZELow2 | (gCardInfo->CSDData.C_SIZEHigh10 << 2); + *NumBlocks = (CardSize + 1) * (1 << (gCardInfo->CSDData.C_SIZE_MULT + 2)); + } + + //For >=2G card, BlockSize may be 1K, but the transfer size is 512 bytes. + if (*BlockSize > 512) { + *NumBlocks = MultU64x32(*NumBlocks, *BlockSize/2); + *BlockSize = 512; + } + + DEBUG ((EFI_D_INFO, "Card type: %x, BlockSize: %x, NumBlocks: %x\n", gCardInfo->CardType, *BlockSize, *NumBlocks)); +} + +STATIC +VOID +CalculateCardCLKD ( + UINTN *ClockFrequencySelect + ) +{ + UINT8 MaxDataTransferRate; + UINTN TransferRateValue = 0; + UINTN TimeValue = 0 ; + UINTN Frequency = 0; + + MaxDataTransferRate = gCardInfo->CSDData.TRAN_SPEED; + + //Calculate Transfer rate unit (Bits 2:0 of TRAN_SPEED) + switch (MaxDataTransferRate & 0x7) { + case 0: + TransferRateValue = 100 * 1000; + break; + + case 1: + TransferRateValue = 1 * 1000 * 1000; + break; + + case 2: + TransferRateValue = 10 * 1000 * 1000; + break; + + case 3: + TransferRateValue = 100 * 1000 * 1000; + break; + + default: + DEBUG((EFI_D_ERROR, "Invalid parameter.\n")); + ASSERT(FALSE); + } + + //Calculate Time value (Bits 6:3 of TRAN_SPEED) + switch ((MaxDataTransferRate >> 3) & 0xF) { + case 1: + TimeValue = 10; + break; + + case 2: + TimeValue = 12; + break; + + case 3: + TimeValue = 13; + break; + + case 4: + TimeValue = 15; + break; + + case 5: + TimeValue = 20; + break; + + case 6: + TimeValue = 25; + break; + + case 7: + TimeValue = 30; + break; + + case 8: + TimeValue = 35; + break; + + case 9: + TimeValue = 40; + break; + + case 10: + TimeValue = 45; + break; + + case 11: + TimeValue = 50; + break; + + case 12: + TimeValue = 55; + break; + + case 13: + TimeValue = 60; + break; + + case 14: + TimeValue = 70; + break; + + case 15: + TimeValue = 80; + break; + + default: + DEBUG((EFI_D_ERROR, "Invalid parameter.\n")); + ASSERT(FALSE); + } + + Frequency = TransferRateValue * TimeValue/10; + + //Calculate Clock divider value to program in MMCHS_SYSCTL[CLKD] field. + *ClockFrequencySelect = ((MMC_REFERENCE_CLK/Frequency) + 1); + + DEBUG ((EFI_D_INFO, "MaxDataTransferRate: 0x%x, Frequency: %d KHz, ClockFrequencySelect: %x\n", MaxDataTransferRate, Frequency/1000, *ClockFrequencySelect)); +} + +STATIC +VOID +GetCardConfigurationData ( + VOID + ) +{ + UINTN BlockSize; + UINTN NumBlocks; + UINTN ClockFrequencySelect; + + //Calculate BlockSize and Total number of blocks in the detected card. + GetBlockInformation(&BlockSize, &NumBlocks); + gCardInfo->BlockSize = BlockSize; + gCardInfo->NumBlocks = NumBlocks; + + //Calculate Card clock divider value. + CalculateCardCLKD(&ClockFrequencySelect); + gCardInfo->ClockFrequencySelect = ClockFrequencySelect; +} + +STATIC +EFI_STATUS +InitializeMMCHS ( + VOID + ) +{ + UINT8 Data = 0; + EFI_STATUS Status; + + //Select Device group to belong to P1 device group in Power IC. + Data = DEV_GRP_P1; + Status = gTPS65950->Write(gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, VMMC1_DEV_GRP), 1, &Data); + ASSERT_EFI_ERROR(Status); + + //Configure voltage regulator for MMC1 in Power IC to output 3.0 voltage. + Data = VSEL_3_00V; + Status = gTPS65950->Write(gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, VMMC1_DEDICATED_REG), 1, &Data); + ASSERT_EFI_ERROR(Status); + + //After ramping up voltage, set VDDS stable bit to indicate that voltage level is stable. + MmioOr32(CONTROL_PBIAS_LITE, (PBIASLITEVMODE0 | PBIASLITEPWRDNZ0 | PBIASSPEEDCTRL0 | PBIASLITEVMODE1 | PBIASLITEWRDNZ1)); + + //Software reset of the MMCHS host controller. + MmioWrite32(MMCHS_SYSCONFIG, SOFTRESET); + gBS->Stall(1000); + while ((MmioRead32(MMCHS_SYSSTATUS) & RESETDONE_MASK) != RESETDONE); + + //Soft reset for all. + MmioWrite32(MMCHS_SYSCTL, SRA); + gBS->Stall(1000); + while ((MmioRead32(MMCHS_SYSCTL) & SRA) != 0x0); + + //Voltage capabilities initialization. Activate VS18 and VS30. + MmioOr32(MMCHS_CAPA, (VS30 | VS18)); + + //Wakeup configuration + MmioOr32(MMCHS_SYSCONFIG, ENAWAKEUP); + MmioOr32(MMCHS_HCTL, IWE); + + //MMCHS Controller default initialization + MmioOr32(MMCHS_CON, (OD | DW8_1_4_BIT | CEATA_OFF)); + + MmioWrite32(MMCHS_HCTL, (SDVS_3_0_V | DTW_1_BIT | SDBP_OFF)); + + //Enable internal clock + MmioOr32(MMCHS_SYSCTL, ICE); + + //Set the clock frequency to 80KHz. + UpdateMMCHSClkFrequency(CLKD_80KHZ); + + //Enable SD bus power. + MmioOr32(MMCHS_HCTL, (SDBP_ON)); + + //Poll till SD bus power bit is set. + while ((MmioRead32(MMCHS_HCTL) & SDBP_MASK) != SDBP_ON); + + return Status; +} + +STATIC +EFI_STATUS +PerformCardIdenfication ( + VOID + ) +{ + EFI_STATUS Status; + UINTN CmdArgument = 0; + UINTN Response = 0; + UINTN RetryCount = 0; + BOOLEAN SDCmd8Supported = FALSE; + + //Enable interrupts. + MmioWrite32(MMCHS_IE, (BADA_EN | CERR_EN | DEB_EN | DCRC_EN | DTO_EN | CIE_EN | + CEB_EN | CCRC_EN | CTO_EN | BRR_EN | BWR_EN | TC_EN | CC_EN)); + + //Controller INIT procedure start. + MmioOr32(MMCHS_CON, INIT); + MmioWrite32(MMCHS_CMD, 0x00000000); + while (!(MmioRead32(MMCHS_STAT) & CC)); + + //Wait for 1 ms + gBS->Stall(1000); + + //Set CC bit to 0x1 to clear the flag + MmioOr32(MMCHS_STAT, CC); + + //Retry INIT procedure. + MmioWrite32(MMCHS_CMD, 0x00000000); + while (!(MmioRead32(MMCHS_STAT) & CC)); + + //End initialization sequence + MmioAnd32(MMCHS_CON, ~INIT); + + MmioOr32(MMCHS_HCTL, (SDVS_3_0_V | DTW_1_BIT | SDBP_ON)); + + //Change clock frequency to 400KHz to fit protocol + UpdateMMCHSClkFrequency(CLKD_400KHZ); + + MmioOr32(MMCHS_CON, OD); + + //Send CMD0 command. + Status = SendCmd(CMD0, CMD0_INT_EN, CmdArgument); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_ERROR, "Cmd0 fails.\n")); + return Status; + } + + DEBUG ((EFI_D_INFO, "CMD0 response: %x\n", MmioRead32(MMCHS_RSP10))); + + //Send CMD5 command. + Status = SendCmd(CMD5, CMD5_INT_EN, CmdArgument); + if (Status == EFI_SUCCESS) { + DEBUG ((EFI_D_ERROR, "CMD5 Success. SDIO card. Follow SDIO card specification.\n")); + DEBUG ((EFI_D_INFO, "CMD5 response: %x\n", MmioRead32(MMCHS_RSP10))); + //NOTE: Returning unsupported error for now. Need to implement SDIO specification. + return EFI_UNSUPPORTED; + } else { + DEBUG ((EFI_D_INFO, "CMD5 fails. Not an SDIO card.\n")); + } + + MmioOr32(MMCHS_SYSCTL, SRC); + gBS->Stall(1000); + while ((MmioRead32(MMCHS_SYSCTL) & SRC)); + + //Send CMD8 command. (New v2.00 command for Voltage check) + //Only 2.7V - 3.6V is supported for SD2.0, only SD 2.0 card can pass. + //MMC & SD1.1 card will fail this command. + CmdArgument = CMD8_ARG; + Status = SendCmd(CMD8, CMD8_INT_EN, CmdArgument); + if (Status == EFI_SUCCESS) { + Response = MmioRead32(MMCHS_RSP10); + DEBUG ((EFI_D_INFO, "CMD8 success. CMD8 response: %x\n", Response)); + if (Response != CmdArgument) { + return EFI_DEVICE_ERROR; + } + DEBUG ((EFI_D_INFO, "Card is SD2.0\n")); + SDCmd8Supported = TRUE; //Supports high capacity. + } else { + DEBUG ((EFI_D_INFO, "CMD8 fails. Not an SD2.0 card.\n")); + } + + MmioOr32(MMCHS_SYSCTL, SRC); + gBS->Stall(1000); + while ((MmioRead32(MMCHS_SYSCTL) & SRC)); + + //Poll till card is busy + while (RetryCount < MAX_RETRY_COUNT) { + //Send CMD55 command. + CmdArgument = 0; + Status = SendCmd(CMD55, CMD55_INT_EN, CmdArgument); + if (Status == EFI_SUCCESS) { + DEBUG ((EFI_D_INFO, "CMD55 success. CMD55 response: %x\n", MmioRead32(MMCHS_RSP10))); + gCardInfo->CardType = SD_CARD; + } else { + DEBUG ((EFI_D_INFO, "CMD55 fails.\n")); + gCardInfo->CardType = MMC_CARD; + } + + //Send appropriate command for the card type which got detected. + if (gCardInfo->CardType == SD_CARD) { + CmdArgument = ((UINTN *) &(gCardInfo->OCRData))[0]; + + //Set HCS bit. + if (SDCmd8Supported) { + CmdArgument |= HCS; + } + + Status = SendCmd(ACMD41, ACMD41_INT_EN, CmdArgument); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_INFO, "ACMD41 fails.\n")); + return Status; + } + ((UINT32 *) &(gCardInfo->OCRData))[0] = MmioRead32(MMCHS_RSP10); + DEBUG ((EFI_D_INFO, "SD card detected. ACMD41 OCR: %x\n", ((UINT32 *) &(gCardInfo->OCRData))[0])); + } else if (gCardInfo->CardType == MMC_CARD) { + CmdArgument = 0; + Status = SendCmd(CMD1, CMD1_INT_EN, CmdArgument); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_INFO, "CMD1 fails.\n")); + return Status; + } + Response = MmioRead32(MMCHS_RSP10); + DEBUG ((EFI_D_INFO, "MMC card detected.. CMD1 response: %x\n", Response)); + + //NOTE: For now, I am skipping this since I only have an SD card. + //Compare card OCR and host OCR (Section 22.6.1.3.2.4) + return EFI_UNSUPPORTED; //For now, MMC is not supported. + } + + //Poll the card until it is out of its power-up sequence. + if (gCardInfo->OCRData.Busy == 1) { + + if (SDCmd8Supported) { + gCardInfo->CardType = SD_CARD_2; + } + + //Card is ready. Check CCS (Card capacity status) bit (bit#30). + //SD 2.0 standard card will response with CCS 0, SD high capacity card will respond with CCS 1. + if (gCardInfo->OCRData.AccessMode & BIT1) { + gCardInfo->CardType = SD_CARD_2_HIGH; + DEBUG ((EFI_D_INFO, "High capacity card.\n")); + } else { + DEBUG ((EFI_D_INFO, "Standard capacity card.\n")); + } + + break; + } + + gBS->Stall(1000); + RetryCount++; + } + + if (RetryCount == MAX_RETRY_COUNT) { + DEBUG ((EFI_D_ERROR, "Timeout error. RetryCount: %d\n", RetryCount)); + return EFI_TIMEOUT; + } + + //Read CID data. + CmdArgument = 0; + Status = SendCmd(CMD2, CMD2_INT_EN, CmdArgument); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_ERROR, "CMD2 fails. Status: %x\n", Status)); + return Status; + } + + DEBUG ((EFI_D_INFO, "CMD2 response: %x %x %x %x\n", MmioRead32(MMCHS_RSP10), MmioRead32(MMCHS_RSP32), MmioRead32(MMCHS_RSP54), MmioRead32(MMCHS_RSP76))); + + //Parse CID register data. + ParseCardCIDData(MmioRead32(MMCHS_RSP10), MmioRead32(MMCHS_RSP32), MmioRead32(MMCHS_RSP54), MmioRead32(MMCHS_RSP76)); + + //Read RCA + CmdArgument = 0; + Status = SendCmd(CMD3, CMD3_INT_EN, CmdArgument); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_ERROR, "CMD3 fails. Status: %x\n", Status)); + return Status; + } + + //Set RCA for the detected card. RCA is CMD3 response. + gCardInfo->RCA = (MmioRead32(MMCHS_RSP10) >> 16); + DEBUG ((EFI_D_INFO, "CMD3 response: RCA %x\n", gCardInfo->RCA)); + + //MMC Bus setting change after card identification. + MmioAnd32(MMCHS_CON, ~OD); + MmioOr32(MMCHS_HCTL, SDVS_3_0_V); + UpdateMMCHSClkFrequency(CLKD_400KHZ); //Set the clock frequency to 400KHz. + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +GetCardSpecificData ( + VOID + ) +{ + EFI_STATUS Status; + UINTN CmdArgument; + + //Send CMD9 to retrieve CSD. + CmdArgument = gCardInfo->RCA << 16; + Status = SendCmd(CMD9, CMD9_INT_EN, CmdArgument); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_ERROR, "CMD9 fails. Status: %x\n", Status)); + return Status; + } + + //Populate 128-bit CSD register data. + ((UINT32 *)&(gCardInfo->CSDData))[0] = MmioRead32(MMCHS_RSP10); + ((UINT32 *)&(gCardInfo->CSDData))[1] = MmioRead32(MMCHS_RSP32); + ((UINT32 *)&(gCardInfo->CSDData))[2] = MmioRead32(MMCHS_RSP54); + ((UINT32 *)&(gCardInfo->CSDData))[3] = MmioRead32(MMCHS_RSP76); + + DEBUG ((EFI_D_INFO, "CMD9 response: %x %x %x %x\n", MmioRead32(MMCHS_RSP10), MmioRead32(MMCHS_RSP32), MmioRead32(MMCHS_RSP54), MmioRead32(MMCHS_RSP76))); + + //Calculate total number of blocks and max. data transfer rate supported by the detected card. + GetCardConfigurationData(); + + //Change MMCHS clock frequency to what detected card can support. + UpdateMMCHSClkFrequency(gCardInfo->ClockFrequencySelect); + + return Status; +} + +STATIC +EFI_STATUS +PerformCardConfiguration ( + VOID + ) +{ + UINTN CmdArgument = 0; + EFI_STATUS Status; + + //Send CMD7 + CmdArgument = gCardInfo->RCA << 16; + Status = SendCmd(CMD7, CMD7_INT_EN, CmdArgument); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_ERROR, "CMD7 fails. Status: %x\n", Status)); + return Status; + } + + //Send CMD16 to set the block length + CmdArgument = gCardInfo->BlockSize; + Status = SendCmd(CMD16, CMD16_INT_EN, CmdArgument); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_ERROR, "CMD16 fails. Status: %x\n", Status)); + return Status; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +ReadBlockData( + IN EFI_BLOCK_IO_PROTOCOL *This, + OUT VOID *Buffer + ) +{ + UINTN MmcStatus; + UINTN *DataBuffer = Buffer; + UINTN DataSize = This->Media->BlockSize/4; + UINTN Count; + UINTN RetryCount = 0; + + //Check controller status to make sure there is no error. + while (RetryCount < MAX_RETRY_COUNT) { + do { + //Read Status. + MmcStatus = MmioRead32(MMCHS_STAT); + } while(MmcStatus == 0); + + //Check if Buffer read ready (BRR) bit is set? + if (MmcStatus & BRR) { + + //Clear BRR bit + MmioOr32(MMCHS_STAT, BRR); + + //Read block worth of data. + for (Count = 0; Count < DataSize; Count++) { + *DataBuffer++ = MmioRead32(MMCHS_DATA); + } + break; + } + RetryCount++; + } + + if (RetryCount == MAX_RETRY_COUNT) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +WriteBlockData( + IN EFI_BLOCK_IO_PROTOCOL *This, + OUT VOID *Buffer + ) +{ + UINTN MmcStatus; + UINTN *DataBuffer = Buffer; + UINTN DataSize = This->Media->BlockSize/4; + UINTN Count; + UINTN RetryCount = 0; + + //Check controller status to make sure there is no error. + while (RetryCount < MAX_RETRY_COUNT) { + do { + //Read Status. + MmcStatus = MmioRead32(MMCHS_STAT); + } while(MmcStatus == 0); + + //Check if Buffer write ready (BWR) bit is set? + if (MmcStatus & BWR) { + + //Clear BWR bit + MmioOr32(MMCHS_STAT, BWR); + + //Write block worth of data. + for (Count = 0; Count < DataSize; Count++) { + MmioWrite32(MMCHS_DATA, *DataBuffer++); + } + + break; + } + RetryCount++; + } + + if (RetryCount == MAX_RETRY_COUNT) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +TransferBlockData( + IN EFI_BLOCK_IO_PROTOCOL *This, + OUT VOID *Buffer, + IN OPERATION_TYPE OperationType + ) +{ + EFI_STATUS Status; + UINTN MmcStatus; + UINTN RetryCount = 0; + + //Read or Write data. + if (OperationType == READ) { + Status = ReadBlockData(This, Buffer); + if (EFI_ERROR(Status)) { + DEBUG((EFI_D_ERROR, "ReadBlockData fails.\n")); + return Status; + } + } else if (OperationType == WRITE) { + Status = WriteBlockData(This, Buffer); + if (EFI_ERROR(Status)) { + DEBUG((EFI_D_ERROR, "WriteBlockData fails.\n")); + return Status; + } + } + + //Check for the Transfer completion. + while (RetryCount < MAX_RETRY_COUNT) { + //Read Status + do { + MmcStatus = MmioRead32(MMCHS_STAT); + } while (MmcStatus == 0); + + //Check if Transfer complete (TC) bit is set? + if (MmcStatus & TC) { + break; + } else { + DEBUG ((EFI_D_ERROR, "MmcStatus for TC: %x\n", MmcStatus)); + //Check if DEB, DCRC or DTO interrupt occured. + if ((MmcStatus & DEB) | (MmcStatus & DCRC) | (MmcStatus & DTO)) { + //There was an error during the data transfer. + + //Set SRD bit to 1 and wait until it return to 0x0. + MmioOr32(MMCHS_SYSCTL, SRD); + while((MmioRead32(MMCHS_SYSCTL) & SRD) != 0x0); + + return EFI_DEVICE_ERROR; + } + } + RetryCount++; + } + + if (RetryCount == MAX_RETRY_COUNT) { + DEBUG ((EFI_D_ERROR, "TransferBlockData timed out.\n")); + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +SdReadWrite ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINTN Lba, + OUT VOID *Buffer, + IN UINTN BufferSize, + IN OPERATION_TYPE OperationType + ) +{ + EFI_STATUS Status; + UINTN RetryCount = 0; + UINTN NumBlocks; + UINTN Cmd = 0; + UINTN CmdInterruptEnable = 0; + UINTN CmdArgument = 0; + + //Check if the data lines are not in use. + while ((RetryCount++ < MAX_RETRY_COUNT) && ((MmioRead32(MMCHS_PSTATE) & DATI_MASK) != DATI_ALLOWED)); + if (RetryCount == MAX_RETRY_COUNT) { + return EFI_TIMEOUT; + } + + //Populate the command information based on the operation type. + if (OperationType == READ) { + Cmd = CMD17; //Single block read + CmdInterruptEnable = CMD17_INT_EN; + } else if (OperationType == WRITE) { + Cmd = CMD24; //Single block write + CmdInterruptEnable = CMD24_INT_EN; + } + + //Calculate total number of blocks its going to read. + NumBlocks = (BufferSize + (This->Media->BlockSize - 1))/This->Media->BlockSize; + + //Set command argument based on the card access mode (Byte mode or Block mode) + if (gCardInfo->OCRData.AccessMode & BIT1) { + CmdArgument = (UINTN)Lba; + } else { + CmdArgument = (UINTN)Lba * This->Media->BlockSize; + } + + while(NumBlocks) { + //Send Command. + Status = SendCmd(Cmd, CmdInterruptEnable, CmdArgument); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_ERROR, "CMD fails. Status: %x\n", Status)); + return Status; + } + + //Transfer a block worth of data. + Status = TransferBlockData(This, Buffer, OperationType); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_ERROR, "TransferBlockData fails. %x\n", Status)); + return Status; + } + + //Adjust command argument. + if (gCardInfo->OCRData.AccessMode & BIT1) { + CmdArgument++; //Increase BlockIndex by one. + } else { + CmdArgument += This->Media->BlockSize; //Increase BlockIndex by BlockSize + } + + //Adjust Buffer. + Buffer = (UINT8 *)Buffer + This->Media->BlockSize; + NumBlocks--; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +MMCHSReset ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +MMCHSReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + + if (Buffer == NULL) + { + return EFI_INVALID_PARAMETER; + } + + if (Lba > This->Media->LastBlock) + { + return EFI_INVALID_PARAMETER; + } + + if ((BufferSize % This->Media->BlockSize) != 0) + { + return EFI_BAD_BUFFER_SIZE; + } + + //Perform Read operation. + Status = SdReadWrite(This, (UINTN)Lba, Buffer, BufferSize, READ); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_ERROR, "Read operation fails.\n")); + } + + return Status; +} + +EFI_STATUS +EFIAPI +MMCHSWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Lba > This->Media->LastBlock) { + return EFI_INVALID_PARAMETER; + } + + if ((BufferSize % This->Media->BlockSize) != 0) { + return EFI_BAD_BUFFER_SIZE; + } + + if (This->Media->ReadOnly) { + return EFI_WRITE_PROTECTED; + } + + //Perform write operation. + Status = SdReadWrite(This, (UINTN)Lba, Buffer, BufferSize, WRITE); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_ERROR, "Write operation fails.\n")); + } + + return Status; +} + +EFI_STATUS +EFIAPI +MMCHSFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ) +{ + return EFI_SUCCESS; +} + +EFI_BLOCK_IO_PROTOCOL BlockIo = +{ + EFI_BLOCK_IO_INTERFACE_REVISION, // Revision + &MMCHSMedia, // *Media + MMCHSReset, // Reset + MMCHSReadBlocks, // ReadBlocks + MMCHSWriteBlocks, // WriteBlocks + MMCHSFlushBlocks // FlushBlocks +}; + +EFI_STATUS +MMCHSInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol(&gEmbeddedExternalDeviceProtocolGuid, NULL, (VOID **)&gTPS65950); + ASSERT_EFI_ERROR(Status); + + gCardInfo = (CARD_INFO *)AllocateZeroPool(sizeof(CARD_INFO)); + if (gCardInfo == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + //Initialize MMC host controller. + Status = InitializeMMCHS(); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_ERROR, "Initialize MMC host controller fails. Status: %x\n", Status)); + return Status; + } + + //Card idenfication + Status = PerformCardIdenfication(); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_ERROR, "No MMC/SD card detected.\n")); + return EFI_SUCCESS; //NOTE: Check if this is correct.. + } + + //Get CSD (Card specific data) for the detected card. + Status = GetCardSpecificData(); + if (EFI_ERROR(Status)) { + return Status; + } + + //Configure the card in data transfer mode. + Status = PerformCardConfiguration(); + if (EFI_ERROR(Status)) { + return Status; + } + + //Patch the Media structure. + MMCHSMedia.LastBlock = (gCardInfo->NumBlocks - 1); + MMCHSMedia.BlockSize = gCardInfo->BlockSize; + + //Publish BlockIO. + Status = gBS->InstallMultipleProtocolInterfaces(&ImageHandle, + &gEfiBlockIoProtocolGuid, &BlockIo, + &gEfiDevicePathProtocolGuid, &gMmcHsDevicePath, + NULL); + return Status; +} diff --git a/BeagleBoardPkg/MMCHSDxe/MMCHS.h b/BeagleBoardPkg/MMCHSDxe/MMCHS.h new file mode 100755 index 0000000000..9baac74931 --- /dev/null +++ b/BeagleBoardPkg/MMCHSDxe/MMCHS.h @@ -0,0 +1,158 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _MMCHS_H_ +#define _MMCHS_H_ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#define MAX_RETRY_COUNT 100 + +#define HCS (0x1UL << 30) //Host capacity support/1 = Supporting high capacity +#define CCS (0x1UL << 30) //Card capacity status/1 = High capacity card +typedef struct { + UINT32 Reserved0: 7; // 0 + UINT32 V170_V195: 1; // 1.70V - 1.95V + UINT32 V200_V260: 7; // 2.00V - 2.60V + UINT32 V270_V360: 9; // 2.70V - 3.60V + UINT32 RESERVED_1: 5; // Reserved + UINT32 AccessMode: 2; // 00b (byte mode), 10b (sector mode) + UINT32 Busy: 1; // This bit is set to LOW if the card has not finished the power up routine +}OCR; + +typedef struct { + UINT32 NOT_USED; // 1 [0:0] + UINT32 CRC; // CRC7 checksum [7:1] + UINT32 MDT; // Manufacturing date [19:8] + UINT32 RESERVED_1; // Reserved [23:20] + UINT32 PSN; // Product serial number [55:24] + UINT8 PRV; // Product revision [63:56] + UINT8 PNM[5]; // Product name [64:103] + UINT16 OID; // OEM/Application ID [119:104] + UINT8 MID; // Manufacturer ID [127:120] +}CID; + +typedef struct { + UINT8 NOT_USED: 1; // Not used, always 1 [0:0] + UINT8 CRC: 7; // CRC [7:1] + UINT8 RESERVED_1: 2; // Reserved [9:8] + UINT8 FILE_FORMAT: 2; // File format [11:10] + UINT8 TMP_WRITE_PROTECT: 1; // Temporary write protection [12:12] + UINT8 PERM_WRITE_PROTECT: 1; // Permanent write protection [13:13] + UINT8 COPY: 1; // Copy flag (OTP) [14:14] + UINT8 FILE_FORMAT_GRP: 1; // File format group [15:15] + UINT16 RESERVED_2: 5; // Reserved [20:16] + UINT16 WRITE_BL_PARTIAL: 1; // Partial blocks for write allowed [21:21] + UINT16 WRITE_BL_LEN: 4; // Max. write data block length [25:22] + UINT16 R2W_FACTOR: 3; // Write speed factor [28:26] + UINT16 RESERVED_3: 2; // Reserved [30:29] + UINT16 WP_GRP_ENABLE: 1; // Write protect group enable [31:31] + UINT32 WP_GRP_SIZE: 7; // Write protect group size [38:32] + UINT32 SECTOR_SIZE: 7; // Erase sector size [45:39] + UINT32 ERASE_BLK_EN: 1; // Erase single block enable [46:46] + UINT32 C_SIZE_MULT: 3; // Device size multiplier [49:47] + UINT32 VDD_W_CURR_MAX: 3; // Max. write current @ VDD max [52:50] + UINT32 VDD_W_CURR_MIN: 3; // Max. write current @ VDD min [55:53] + UINT32 VDD_R_CURR_MAX: 3; // Max. read current @ VDD max [58:56] + UINT32 VDD_R_CURR_MIN: 3; // Max. read current @ VDD min [61:59] + UINT32 C_SIZELow2: 2; // Device size [73:62] + UINT32 C_SIZEHigh10: 10;// Device size [73:62] + UINT32 RESERVED_4: 2; // Reserved [75:74] + UINT32 DSR_IMP: 1; // DSR implemented [76:76] + UINT32 READ_BLK_MISALIGN: 1; // Read block misalignment [77:77] + UINT32 WRITE_BLK_MISALIGN: 1; // Write block misalignment [78:78] + UINT32 READ_BL_PARTIAL: 1; // Partial blocks for read allowed [79:79] + UINT32 READ_BL_LEN: 4; // Max. read data block length [83:80] + UINT32 CCC: 12;// Card command classes [95:84] + UINT8 TRAN_SPEED ; // Max. bus clock frequency [103:96] + UINT8 NSAC ; // Data read access-time 2 in CLK cycles (NSAC*100) [111:104] + UINT8 TAAC ; // Data read access-time 1 [119:112] + UINT8 RESERVED_5: 6; // Reserved [125:120] + UINT8 CSD_STRUCTURE: 2; // CSD structure [127:126] +}CSD; + +typedef struct { + UINT8 NOT_USED: 1; // Not used, always 1 [0:0] + UINT8 CRC: 7; // CRC [7:1] + UINT8 RESERVED_1: 2; // Reserved [9:8] + UINT8 FILE_FORMAT: 2; // File format [11:10] + UINT8 TMP_WRITE_PROTECT: 1; // Temporary write protection [12:12] + UINT8 PERM_WRITE_PROTECT: 1; // Permanent write protection [13:13] + UINT8 COPY: 1; // Copy flag (OTP) [14:14] + UINT8 FILE_FORMAT_GRP: 1; // File format group [15:15] + UINT16 RESERVED_2: 5; // Reserved [20:16] + UINT16 WRITE_BL_PARTIAL: 1; // Partial blocks for write allowed [21:21] + UINT16 WRITE_BL_LEN: 4; // Max. write data block length [25:22] + UINT16 R2W_FACTOR: 3; // Write speed factor [28:26] + UINT16 RESERVED_3: 2; // Reserved [30:29] + UINT16 WP_GRP_ENABLE: 1; // Write protect group enable [31:31] + UINT16 WP_GRP_SIZE: 7; // Write protect group size [38:32] + UINT16 SECTOR_SIZE: 7; // Erase sector size [45:39] + UINT16 ERASE_BLK_EN: 1; // Erase single block enable [46:46] + UINT16 RESERVED_4: 1; // Reserved [47:47] + UINT32 C_SIZELow16: 16;// Device size [69:48] + UINT32 C_SIZEHigh6: 6; // Device size [69:48] + UINT32 RESERVED_5: 6; // Reserved [75:70] + UINT32 DSR_IMP: 1; // DSR implemented [76:76] + UINT32 READ_BLK_MISALIGN: 1; // Read block misalignment [77:77] + UINT32 WRITE_BLK_MISALIGN: 1; // Write block misalignment [78:78] + UINT32 READ_BL_PARTIAL: 1; // Partial blocks for read allowed [79:79] + UINT16 READ_BL_LEN: 4; // Max. read data block length [83:80] + UINT16 CCC: 12;// Card command classes [95:84] + UINT8 TRAN_SPEED ; // Max. bus clock frequency [103:96] + UINT8 NSAC ; // Data read access-time 2 in CLK cycles (NSAC*100) [111:104] + UINT8 TAAC ; // Data read access-time 1 [119:112] + UINT8 RESERVED_6: 6; // 0 [125:120] + UINT8 CSD_STRUCTURE: 2; // CSD structure [127:126] +}CSD_SDV2; + +typedef enum { + UNKNOWN_CARD, + MMC_CARD, //MMC card + SD_CARD, //SD 1.1 card + SD_CARD_2, //SD 2.0 or above standard card + SD_CARD_2_HIGH //SD 2.0 or above high capacity card +} CARD_TYPE; + +typedef enum { + READ, + WRITE +} OPERATION_TYPE; + +typedef struct +{ + UINT16 RCA; + UINTN BlockSize; + UINTN NumBlocks; + UINTN ClockFrequencySelect; + CARD_TYPE CardType; + OCR OCRData; + CID CIDData; + CSD CSDData; +} CARD_INFO; + +#endif diff --git a/BeagleBoardPkg/MMCHSDxe/MMCHS.inf b/BeagleBoardPkg/MMCHSDxe/MMCHS.inf new file mode 100644 index 0000000000..3636f35583 --- /dev/null +++ b/BeagleBoardPkg/MMCHSDxe/MMCHS.inf @@ -0,0 +1,39 @@ +#%HEADER% +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = MMCHS + FILE_GUID = 100c2cfa-b586-4198-9b4c-1683d195b1da + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = MMCHSInitialize + + +[Sources.common] + MMCHS.c + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + BeagleBoardPkg/BeagleBoardPkg.dec + +[LibraryClasses] + PcdLib + UefiLib + UefiDriverEntryPoint + MemoryAllocationLib + IoLib + +[Guids] + +[Protocols] + gEfiBlockIoProtocolGuid + gEfiCpuArchProtocolGuid + gEfiDevicePathProtocolGuid + gEmbeddedExternalDeviceProtocolGuid + +[Pcd] + gBeagleBoardTokenSpaceGuid.PcdBeagleMMCHS1Base + +[depex] + gEmbeddedExternalDeviceProtocolGuid diff --git a/BeagleBoardPkg/PciEmulation/PciEmulation.c b/BeagleBoardPkg/PciEmulation/PciEmulation.c new file mode 100644 index 0000000000..dee0541971 --- /dev/null +++ b/BeagleBoardPkg/PciEmulation/PciEmulation.c @@ -0,0 +1,584 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "PciEmulation.h" +#include + +EFI_CPU_ARCH_PROTOCOL *gCpu; +EMBEDDED_EXTERNAL_DEVICE *gTPS65950; + +#define HOST_CONTROLLER_OPERATION_REG_SIZE 0x44 + +typedef struct { + ACPI_HID_DEVICE_PATH AcpiDevicePath; + PCI_DEVICE_PATH PciDevicePath; + EFI_DEVICE_PATH_PROTOCOL EndDevicePath; +} EFI_PCI_IO_DEVICE_PATH; + +typedef struct { + UINT32 Signature; + EFI_PCI_IO_DEVICE_PATH DevicePath; + EFI_PCI_IO_PROTOCOL PciIoProtocol; + PCI_TYPE00 *ConfigSpace; + PCI_ROOT_BRIDGE RootBridge; + UINTN Segment; +} EFI_PCI_IO_PRIVATE_DATA; + +#define EFI_PCI_IO_PRIVATE_DATA_SIGNATURE SIGNATURE_32('p', 'c', 'i', 'o') +#define EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(a) CR(a, EFI_PCI_IO_PRIVATE_DATA, PciIoProtocol, EFI_PCI_IO_PRIVATE_DATA_SIGNATURE) + +EFI_PCI_IO_DEVICE_PATH PciIoDevicePathTemplate = +{ + { + { ACPI_DEVICE_PATH, ACPI_DP, sizeof (ACPI_HID_DEVICE_PATH), 0}, + EISA_PNP_ID(0x0A03), // HID + 0 // UID + }, + { + { HARDWARE_DEVICE_PATH, HW_PCI_DP, sizeof (PCI_DEVICE_PATH), 0}, + 0, + 0 + }, + { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, sizeof (EFI_DEVICE_PATH_PROTOCOL), 0} +}; + +STATIC +VOID +ConfigureUSBHost ( + VOID + ) +{ + EFI_STATUS Status; + UINT8 Data = 0; + + // Take USB host out of force-standby mode + MmioWrite32(UHH_SYSCONFIG, UHH_SYSCONFIG_MIDLEMODE_NO_STANDBY + | UHH_SYSCONFIG_CLOCKACTIVITY_ON + | UHH_SYSCONFIG_SIDLEMODE_NO_STANDBY + | UHH_SYSCONFIG_ENAWAKEUP_ENABLE + | UHH_SYSCONFIG_AUTOIDLE_ALWAYS_RUN); + MmioWrite32(UHH_HOSTCONFIG, UHH_HOSTCONFIG_P3_CONNECT_STATUS_DISCONNECT + | UHH_HOSTCONFIG_P2_CONNECT_STATUS_DISCONNECT + | UHH_HOSTCONFIG_P1_CONNECT_STATUS_DISCONNECT + | UHH_HOSTCONFIG_ENA_INCR_ALIGN_DISABLE + | UHH_HOSTCONFIG_ENA_INCR16_ENABLE + | UHH_HOSTCONFIG_ENA_INCR8_ENABLE + | UHH_HOSTCONFIG_ENA_INCR4_ENABLE + | UHH_HOSTCONFIG_AUTOPPD_ON_OVERCUR_EN_ON + | UHH_HOSTCONFIG_P1_ULPI_BYPASS_ULPI_MODE); + + // USB reset (GPIO 147 - Port 5 pin 19) output high + MmioAnd32(GPIO5_BASE + GPIO_OE, ~BIT19); + MmioWrite32(GPIO5_BASE + GPIO_SETDATAOUT, BIT19); + + // Get the Power IC protocol. + Status = gBS->LocateProtocol(&gEmbeddedExternalDeviceProtocolGuid, NULL, (VOID **)&gTPS65950); + ASSERT_EFI_ERROR(Status); + + //Enable power to the USB host. + Status = gTPS65950->Read(gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID3, LEDEN), 1, &Data); + ASSERT_EFI_ERROR(Status); + + //LEDAON & LEDAPWM control the power to the USB host so enable those bits. + Data |= (LEDAON | LEDAPWM); + + Status = gTPS65950->Write(gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID3, LEDEN), 1, &Data); + ASSERT_EFI_ERROR(Status); +} + +EFI_STATUS +PciIoPollMem ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINT64 Mask, + IN UINT64 Value, + IN UINT64 Delay, + OUT UINT64 *Result + ) +{ + ASSERT (FALSE); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +PciIoPollIo ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINT64 Mask, + IN UINT64 Value, + IN UINT64 Delay, + OUT UINT64 *Result + ) +{ + ASSERT (FALSE); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +PciIoMemRead ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This); + + return PciRootBridgeIoMemRead (&Private->RootBridge.Io, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, + Private->ConfigSpace->Device.Bar[BarIndex] + Offset, + Count, + Buffer + ); +} + +EFI_STATUS +PciIoMemWrite ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This); + + return PciRootBridgeIoMemWrite (&Private->RootBridge.Io, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, + Private->ConfigSpace->Device.Bar[BarIndex] + Offset, + Count, + Buffer + ); +} + +EFI_STATUS +PciIoIoRead ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + ASSERT (FALSE); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +PciIoIoWrite ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + ASSERT (FALSE); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +PciIoPciRead ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This); + + return PciRootBridgeIoMemRW ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)Width, + Count, + TRUE, + (PTR)(UINTN)Buffer, + TRUE, + (PTR)(UINTN)(((UINT8 *)Private->ConfigSpace) + Offset) + ); +} + +EFI_STATUS +PciIoPciWrite ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This); + + return PciRootBridgeIoMemRW ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, + Count, + TRUE, + (PTR)(UINTN)(((UINT8 *)Private->ConfigSpace) + Offset), + TRUE, + (PTR)(UINTN)Buffer + ); +} + +EFI_STATUS +PciIoCopyMem ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 DestBarIndex, + IN UINT64 DestOffset, + IN UINT8 SrcBarIndex, + IN UINT64 SrcOffset, + IN UINTN Count + ) +{ + ASSERT (FALSE); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +PciIoMap ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_OPERATION Operation, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +{ + MAP_INFO_INSTANCE *Map; + EFI_STATUS Status; + + if ( HostAddress == NULL || NumberOfBytes == NULL || + DeviceAddress == NULL || Mapping == NULL ) { + + return EFI_INVALID_PARAMETER; + } + + + if (Operation >= EfiPciOperationMaximum) { + return EFI_INVALID_PARAMETER; + } + + *DeviceAddress = ConvertToPhysicalAddress (HostAddress); + + // Data cache flush (HostAddress, NumberOfBytes); + + // Remember range so we can flush on the other side + Status = gBS->AllocatePool (EfiBootServicesData, sizeof (PCI_DMA_MAP), (VOID **) &Map); + if (EFI_ERROR(Status)) { + return EFI_OUT_OF_RESOURCES; + } + + *Mapping = Map; + + Map->HostAddress = (UINTN)HostAddress; + Map->DeviceAddress = *DeviceAddress; + Map->NumberOfBytes = *NumberOfBytes; + Map->Operation = Operation; + + // EfiCpuFlushTypeWriteBack, EfiCpuFlushTypeInvalidate + gCpu->FlushDataCache (gCpu, (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress, *NumberOfBytes, EfiCpuFlushTypeWriteBackInvalidate); + + return EFI_SUCCESS; +} + +EFI_STATUS +PciIoUnmap ( + IN EFI_PCI_IO_PROTOCOL *This, + IN VOID *Mapping + ) +{ + PCI_DMA_MAP *Map; + + if (Mapping == NULL) { + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + Map = (PCI_DMA_MAP *)Mapping; + if (Map->Operation == EfiPciOperationBusMasterWrite) { + // + // Make sure we read buffer from uncached memory and not the cache + // + gCpu->FlushDataCache (gCpu, Map->HostAddress, Map->NumberOfBytes, EfiCpuFlushTypeInvalidate); + } else if (Map->Operation == EfiPciOperationBusMasterCommonBuffer) { + // + // CPU was using uncached address, so anything in the cached range is bogus + // + gCpu->FlushDataCache (gCpu, Map->DeviceAddress, Map->NumberOfBytes, EfiCpuFlushTypeInvalidate); + } + + FreePool (Map); + + return EFI_SUCCESS; +} + +EFI_STATUS +PciIoAllocateBuffer ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT VOID **HostAddress, + IN UINT64 Attributes + ) +{ + if (Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) { + return EFI_UNSUPPORTED; + } + + if (HostAddress == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData + // + // We used uncached memory to keep coherency + // + if (MemoryType == EfiBootServicesData) { + *HostAddress = UncachedAllocatePages (Pages); + } else if (MemoryType != EfiRuntimeServicesData) { + *HostAddress = UncachedAllocateRuntimePages (Pages); + } else { + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +PciIoFreeBuffer ( + IN EFI_PCI_IO_PROTOCOL *This, + IN UINTN Pages, + IN VOID *HostAddress + ) +{ + if (HostAddress == NULL) { + return EFI_INVALID_PARAMETER; + } + + UncachedFreePages (HostAddress, Pages); + return EFI_SUCCESS; +} + + +EFI_STATUS +PciIoFlush ( + IN EFI_PCI_IO_PROTOCOL *This + ) +{ + return EFI_SUCCESS; +} + +EFI_STATUS +PciIoGetLocation ( + IN EFI_PCI_IO_PROTOCOL *This, + OUT UINTN *SegmentNumber, + OUT UINTN *BusNumber, + OUT UINTN *DeviceNumber, + OUT UINTN *FunctionNumber + ) +{ + EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This); + + if (SegmentNumber != NULL) { + *SegmentNumber = Private->Segment; + } + + if (BusNumber != NULL) { + *BusNumber = 0xff; + } + + if (DeviceNumber != NULL) { + *DeviceNumber = 0; + } + + if (FunctionNumber != NULL) { + *FunctionNumber = 0; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +PciIoAttributes ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation, + IN UINT64 Attributes, + OUT UINT64 *Result OPTIONAL + ) +{ + switch (Operation) { + case EfiPciIoAttributeOperationGet: + case EfiPciIoAttributeOperationSupported: + if (Result == NULL) { + return EFI_INVALID_PARAMETER; + } + // We are not a real PCI device so just say things we kind of do + *Result = EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER | EFI_PCI_DEVICE_ENABLE; + break; + + case EfiPciIoAttributeOperationSet: + case EfiPciIoAttributeOperationEnable: + case EfiPciIoAttributeOperationDisable: + // Since we are not a real PCI device no enable/set or disable operations exist. + return EFI_SUCCESS; + break; + + default: + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + }; + return EFI_SUCCESS; +} + +EFI_STATUS +PciIoGetBarAttributes ( + IN EFI_PCI_IO_PROTOCOL *This, + IN UINT8 BarIndex, + OUT UINT64 *Supports, OPTIONAL + OUT VOID **Resources OPTIONAL + ) +{ + ASSERT (FALSE); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +PciIoSetBarAttributes ( + IN EFI_PCI_IO_PROTOCOL *This, + IN UINT64 Attributes, + IN UINT8 BarIndex, + IN OUT UINT64 *Offset, + IN OUT UINT64 *Length + ) +{ + ASSERT (FALSE); + return EFI_UNSUPPORTED; +} + +EFI_PCI_IO_PROTOCOL PciIoTemplate = +{ + PciIoPollMem, + PciIoPollIo, + PciIoMemRead, + PciIoMemWrite, + PciIoIoRead, + PciIoIoWrite, + PciIoPciRead, + PciIoPciWrite, + PciIoCopyMem, + PciIoMap, + PciIoUnmap, + PciIoAllocateBuffer, + PciIoFreeBuffer, + PciIoFlush, + PciIoGetLocation, + PciIoAttributes, + PciIoGetBarAttributes, + PciIoSetBarAttributes, + 0, + 0 +}; + +EFI_STATUS +EFIAPI +PciEmulationEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + EFI_PCI_IO_PRIVATE_DATA *Private; + UINT8 CapabilityLength; + UINT8 PhysicalPorts; + UINTN Count; + + // Get the Cpu protocol for later use + Status = gBS->LocateProtocol(&gEfiCpuArchProtocolGuid, NULL, (VOID **)&gCpu); + ASSERT_EFI_ERROR(Status); + + //Configure USB host for OMAP3530. + ConfigureUSBHost(); + + // Create a private structure + Private = AllocatePool(sizeof(EFI_PCI_IO_PRIVATE_DATA)); + if (Private == NULL) { + Status = EFI_OUT_OF_RESOURCES; + return Status; + } + + Private->Signature = EFI_PCI_IO_PRIVATE_DATA_SIGNATURE; // Fill in signature + Private->RootBridge.Signature = PCI_ROOT_BRIDGE_SIGNATURE; // Fake Root Bridge structure needs a signature too + Private->RootBridge.MemoryStart = USB_EHCI_HCCAPBASE; // Get the USB capability register base + Private->Segment = 0; // Default to segment zero + + // Find out the capability register length and number of physical ports. + CapabilityLength = MmioRead8(Private->RootBridge.MemoryStart); + PhysicalPorts = (MmioRead32(Private->RootBridge.MemoryStart + 0x4)) & 0x0000000F; + + // Calculate the total size of the USB registers. + Private->RootBridge.MemorySize = CapabilityLength + (HOST_CONTROLLER_OPERATION_REG_SIZE + ((4 * PhysicalPorts) - 1)); + + // Enable Port Power bit in Port status and control registers in EHCI register space. + // Port Power Control (PPC) bit in the HCSPARAMS register is already set which indicates + // host controller implementation includes port power control. + for (Count = 0; Count < PhysicalPorts; Count++) { + MmioOr32((Private->RootBridge.MemoryStart + CapabilityLength + HOST_CONTROLLER_OPERATION_REG_SIZE + 4*Count), 0x00001000); + } + + // Create fake PCI config space. + Private->ConfigSpace = AllocateZeroPool(sizeof(PCI_TYPE00)); + if (Private->ConfigSpace == NULL) { + Status = EFI_OUT_OF_RESOURCES; + FreePool(Private); + return Status; + } + + // Configure PCI config space + Private->ConfigSpace->Hdr.VendorId = 0x3530; + Private->ConfigSpace->Hdr.DeviceId = 0x3530; + Private->ConfigSpace->Hdr.ClassCode[0] = 0x20; + Private->ConfigSpace->Hdr.ClassCode[1] = 0x03; + Private->ConfigSpace->Hdr.ClassCode[2] = 0x0C; + Private->ConfigSpace->Device.Bar[0] = Private->RootBridge.MemoryStart; + + Handle = NULL; + + // Unique device path. + CopyMem(&Private->DevicePath, &PciIoDevicePathTemplate, sizeof(PciIoDevicePathTemplate)); + Private->DevicePath.AcpiDevicePath.UID = 0; + + // Copy protocol structure + CopyMem(&Private->PciIoProtocol, &PciIoTemplate, sizeof(PciIoTemplate)); + + Status = gBS->InstallMultipleProtocolInterfaces(&Handle, + &gEfiPciIoProtocolGuid, &Private->PciIoProtocol, + &gEfiDevicePathProtocolGuid, &Private->DevicePath, + NULL); + if (EFI_ERROR(Status)) { + DEBUG((EFI_D_ERROR, "PciEmulationEntryPoint InstallMultipleProtocolInterfaces() failed.\n")); + } + + return Status; +} + diff --git a/BeagleBoardPkg/PciEmulation/PciEmulation.h b/BeagleBoardPkg/PciEmulation/PciEmulation.h new file mode 100644 index 0000000000..c19cd8c551 --- /dev/null +++ b/BeagleBoardPkg/PciEmulation/PciEmulation.h @@ -0,0 +1,305 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _PCI_ROOT_BRIDGE_H_ +#define _PCI_ROOT_BRIDGE_H_ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +extern EFI_CPU_ARCH_PROTOCOL *gCpu; + +#define EFI_RESOURCE_NONEXISTENT 0xFFFFFFFFFFFFFFFFULL +#define EFI_RESOURCE_LESS 0xFFFFFFFFFFFFFFFEULL +#define EFI_RESOURCE_SATISFIED 0x0000000000000000ULL + + +typedef struct { + ACPI_HID_DEVICE_PATH AcpiDevicePath; + EFI_DEVICE_PATH_PROTOCOL EndDevicePath; +} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH; + + +#define ACPI_CONFIG_IO 0 +#define ACPI_CONFIG_MMIO 1 +#define ACPI_CONFIG_BUS 2 + +typedef struct { + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR Desc[3]; + EFI_ACPI_END_TAG_DESCRIPTOR EndDesc; +} ACPI_CONFIG_INFO; + + +#define PCI_ROOT_BRIDGE_SIGNATURE SIGNATURE_32 ('P', 'c', 'i', 'F') + +typedef struct { + UINT32 Signature; + EFI_HANDLE Handle; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL Io; + EFI_PCI_ROOT_BRIDGE_DEVICE_PATH DevicePath; + + UINT8 StartBus; + UINT8 EndBus; + UINT16 Type; + UINT32 MemoryStart; + UINT32 MemorySize; + UINTN IoOffset; + UINT32 IoStart; + UINT32 IoSize; + UINT64 PciAttributes; + + ACPI_CONFIG_INFO *Config; + +} PCI_ROOT_BRIDGE; + + +#define INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(a) CR (a, PCI_ROOT_BRIDGE, Io, PCI_ROOT_BRIDGE_SIGNATURE) + + +typedef union { + UINT8 volatile *buf; + UINT8 volatile *ui8; + UINT16 volatile *ui16; + UINT32 volatile *ui32; + UINT64 volatile *ui64; + UINTN volatile ui; +} PTR; + + +typedef struct { + EFI_PHYSICAL_ADDRESS HostAddress; + EFI_PHYSICAL_ADDRESS DeviceAddress; + UINTN NumberOfBytes; + EFI_PCI_IO_PROTOCOL_OPERATION Operation; + +} MAP_INFO_INSTANCE; + + +typedef struct { + EFI_PHYSICAL_ADDRESS HostAddress; + EFI_PHYSICAL_ADDRESS DeviceAddress; + UINTN NumberOfBytes; + EFI_PCI_IO_PROTOCOL_OPERATION Operation; +} PCI_DMA_MAP; + +EFI_STATUS +EFIAPI +PciRootBridgeIoPollMem ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINT64 Mask, + IN UINT64 Value, + IN UINT64 Delay, + OUT UINT64 *Result + ); + +EFI_STATUS +EFIAPI +PciRootBridgeIoPollIo ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINT64 Mask, + IN UINT64 Value, + IN UINT64 Delay, + OUT UINT64 *Result + ); + +EFI_STATUS +EFIAPI +PciRootBridgeIoMemRead ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +EFI_STATUS +EFIAPI +PciRootBridgeIoMemWrite ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +EFI_STATUS +EFIAPI +PciRootBridgeIoIoRead ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 UserAddress, + IN UINTN Count, + IN OUT VOID *UserBuffer + ); + +EFI_STATUS +EFIAPI +PciRootBridgeIoIoWrite ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 UserAddress, + IN UINTN Count, + IN OUT VOID *UserBuffer + ); + +EFI_STATUS +EFIAPI +PciRootBridgeIoCopyMem ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 DestAddress, + IN UINT64 SrcAddress, + IN UINTN Count + ); + +EFI_STATUS +EFIAPI +PciRootBridgeIoPciRead ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +EFI_STATUS +EFIAPI +PciRootBridgeIoPciWrite ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +EFI_STATUS +EFIAPI +PciRootBridgeIoMap ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ); + +EFI_STATUS +EFIAPI +PciRootBridgeIoUnmap ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN VOID *Mapping + ); + +EFI_STATUS +EFIAPI +PciRootBridgeIoAllocateBuffer ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT VOID **HostAddress, + IN UINT64 Attributes + ); + +EFI_STATUS +EFIAPI +PciRootBridgeIoFreeBuffer ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN UINTN Pages, + OUT VOID *HostAddress + ); + +EFI_STATUS +EFIAPI +PciRootBridgeIoFlush ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This + ); + +EFI_STATUS +EFIAPI +PciRootBridgeIoGetAttributes ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + OUT UINT64 *Supported, + OUT UINT64 *Attributes + ); + +EFI_STATUS +EFIAPI +PciRootBridgeIoSetAttributes ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN UINT64 Attributes, + IN OUT UINT64 *ResourceBase, + IN OUT UINT64 *ResourceLength + ); + +EFI_STATUS +EFIAPI +PciRootBridgeIoConfiguration ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + OUT VOID **Resources + ); + +// +// Private Function Prototypes +// +EFI_STATUS +EFIAPI +PciRootBridgeIoMemRW ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINTN Count, + IN BOOLEAN InStrideFlag, + IN PTR In, + IN BOOLEAN OutStrideFlag, + OUT PTR Out + ); + +BOOLEAN +PciIoMemAddressValid ( + IN EFI_PCI_IO_PROTOCOL *This, + IN UINT64 Address + ); + +EFI_STATUS +EmulatePciIoForEhci ( + INTN MvPciIfMaxIf + ); + +#endif + diff --git a/BeagleBoardPkg/PciEmulation/PciEmulation.inf b/BeagleBoardPkg/PciEmulation/PciEmulation.inf new file mode 100644 index 0000000000..a6958b197b --- /dev/null +++ b/BeagleBoardPkg/PciEmulation/PciEmulation.inf @@ -0,0 +1,58 @@ +#%HEADER% +/** @file + + Copyright (c) 2009 Apple, Inc. All rights reserved. + + This document is the property of Apple, Inc. + It is considered confidential and proprietary. + + This document may not be reproduced or transmitted in any form, + in whole or in part, without the express written permission of + Apple, Inc. + +**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BeagleBoardPciEmulation + FILE_GUID = feaa2e2b-53ac-4d5e-ae10-1efd5da4a2ba + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = PciEmulationEntryPoint + +[Sources.common] + PciRootBridgeIo.c + PciEmulation.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + ArmPkg/ArmPkg.dec + EmbeddedPkg/EmbeddedPkg.dec + BeagleBoardPkg/BeagleBoardPkg.dec + +[LibraryClasses] + BaseLib + DxeServicesTableLib + UefiLib + UefiBootServicesTableLib + UefiDriverEntryPoint + UefiRuntimeServicesTableLib + UncachedMemoryAllocationLib + IoLib + +[Protocols] + gEfiPciRootBridgeIoProtocolGuid + gEfiDevicePathProtocolGuid + gEfiPciHostBridgeResourceAllocationProtocolGuid + gEfiCpuArchProtocolGuid + gEfiPciIoProtocolGuid + gEmbeddedExternalDeviceProtocolGuid + +[Depex] + gEfiMetronomeArchProtocolGuid AND + gEfiCpuArchProtocolGuid AND + gEmbeddedExternalDeviceProtocolGuid + \ No newline at end of file diff --git a/BeagleBoardPkg/PciEmulation/PciRootBridgeIo.c b/BeagleBoardPkg/PciEmulation/PciRootBridgeIo.c new file mode 100644 index 0000000000..d06a56ce57 --- /dev/null +++ b/BeagleBoardPkg/PciEmulation/PciRootBridgeIo.c @@ -0,0 +1,306 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "PciEmulation.h" + +BOOLEAN +PciRootBridgeMemAddressValid ( + IN PCI_ROOT_BRIDGE *Private, + IN UINT64 Address + ) +{ + if ((Address >= Private->MemoryStart) && (Address < (Private->MemoryStart + Private->MemorySize))) { + return TRUE; + } + + return FALSE; +} + + +EFI_STATUS +PciRootBridgeIoMemRW ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINTN Count, + IN BOOLEAN InStrideFlag, + IN PTR In, + IN BOOLEAN OutStrideFlag, + OUT PTR Out + ) +{ + UINTN Stride; + UINTN InStride; + UINTN OutStride; + + + Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03); + Stride = (UINTN)1 << Width; + InStride = InStrideFlag ? Stride : 0; + OutStride = OutStrideFlag ? Stride : 0; + + // + // Loop for each iteration and move the data + // + switch (Width) { + case EfiPciWidthUint8: + for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) { + *In.ui8 = *Out.ui8; + } + break; + case EfiPciWidthUint16: + for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) { + *In.ui16 = *Out.ui16; + } + break; + case EfiPciWidthUint32: + for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) { + *In.ui32 = *Out.ui32; + } + break; + default: + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +PciRootBridgeIoPciRW ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN BOOLEAN Write, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 UserAddress, + IN UINTN Count, + IN OUT VOID *UserBuffer + ) +{ + return EFI_SUCCESS; +} + +/** + Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space. + + @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param Width Signifies the width of the memory operations. + @param Address The base address of the memory operations. + @param Count The number of memory operations to perform. + @param Buffer For read operations, the destination buffer to store the results. For write + operations, the source buffer to write data from. + + @retval EFI_SUCCESS The data was read from or written to the PCI root bridge. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + +**/ +EFI_STATUS +EFIAPI +PciRootBridgeIoMemRead ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + PCI_ROOT_BRIDGE *Private; + UINTN AlignMask; + PTR In; + PTR Out; + + if ( Buffer == NULL ) { + return EFI_INVALID_PARAMETER; + } + + Private = INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This); + + if (!PciRootBridgeMemAddressValid (Private, Address)) { + return EFI_INVALID_PARAMETER; + } + + AlignMask = (1 << (Width & 0x03)) - 1; + if (Address & AlignMask) { + return EFI_INVALID_PARAMETER; + } + + In.buf = Buffer; + Out.buf = (VOID *)(UINTN) Address; + + switch (Width) { + case EfiPciWidthUint8: + case EfiPciWidthUint16: + case EfiPciWidthUint32: + case EfiPciWidthUint64: + return PciRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out); + + case EfiPciWidthFifoUint8: + case EfiPciWidthFifoUint16: + case EfiPciWidthFifoUint32: + case EfiPciWidthFifoUint64: + return PciRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out); + + case EfiPciWidthFillUint8: + case EfiPciWidthFillUint16: + case EfiPciWidthFillUint32: + case EfiPciWidthFillUint64: + return PciRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out); + + default: + break; + } + + return EFI_INVALID_PARAMETER; +} + + + +/** + Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space. + + @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param Width Signifies the width of the memory operations. + @param Address The base address of the memory operations. + @param Count The number of memory operations to perform. + @param Buffer For read operations, the destination buffer to store the results. For write + operations, the source buffer to write data from. + + @retval EFI_SUCCESS The data was read from or written to the PCI root bridge. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + +**/ +EFI_STATUS +EFIAPI +PciRootBridgeIoMemWrite ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + PCI_ROOT_BRIDGE *Private; + UINTN AlignMask; + PTR In; + PTR Out; + + if ( Buffer == NULL ) { + return EFI_INVALID_PARAMETER; + } + + Private = INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This); + + if (!PciRootBridgeMemAddressValid (Private, Address)) { + return EFI_INVALID_PARAMETER; + } + + AlignMask = (1 << (Width & 0x03)) - 1; + if (Address & AlignMask) { + return EFI_INVALID_PARAMETER; + } + + In.buf = (VOID *)(UINTN) Address; + Out.buf = Buffer; + + switch (Width) { + case EfiPciWidthUint8: + case EfiPciWidthUint16: + case EfiPciWidthUint32: + case EfiPciWidthUint64: + return PciRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out); + + case EfiPciWidthFifoUint8: + case EfiPciWidthFifoUint16: + case EfiPciWidthFifoUint32: + case EfiPciWidthFifoUint64: + return PciRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out); + + case EfiPciWidthFillUint8: + case EfiPciWidthFillUint16: + case EfiPciWidthFillUint32: + case EfiPciWidthFillUint64: + return PciRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out); + + default: + break; + } + + return EFI_INVALID_PARAMETER; +} + +/** + Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space. + + @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param Width Signifies the width of the memory operations. + @param Address The base address of the memory operations. + @param Count The number of memory operations to perform. + @param Buffer For read operations, the destination buffer to store the results. For write + operations, the source buffer to write data from. + + @retval EFI_SUCCESS The data was read from or written to the PCI root bridge. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + +**/ +EFI_STATUS +EFIAPI +PciRootBridgeIoPciRead ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + return PciRootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer); +} + + + +/** + Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space. + + @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param Width Signifies the width of the memory operations. + @param Address The base address of the memory operations. + @param Count The number of memory operations to perform. + @param Buffer For read operations, the destination buffer to store the results. For write + operations, the source buffer to write data from. + + @retval EFI_SUCCESS The data was read from or written to the PCI root bridge. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + +**/ +EFI_STATUS +EFIAPI +PciRootBridgeIoPciWrite ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + return PciRootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer); +} + + diff --git a/BeagleBoardPkg/Sec/Arm/Macro.inc b/BeagleBoardPkg/Sec/Arm/Macro.inc new file mode 100755 index 0000000000..cacfef976a --- /dev/null +++ b/BeagleBoardPkg/Sec/Arm/Macro.inc @@ -0,0 +1,67 @@ +//%HEADER% + MACRO + MmioWrite32Macro $Address, $Data + ldr r1, = ($Address) + ldr r0, = ($Data) + str r0, [r1] + MEND + + MACRO + MmioOr32Macro $Address, $OrData + ldr r1, =($Address) + ldr r2, =($OrData) + ldr r0, [r1] + orr r0, r0, r2 + str r0, [r1] + MEND + + MACRO + MmioAnd32Macro $Address, $AndData + ldr r1, =($Address) + ldr r2, =($AndData) + ldr r0, [r1] + and r0, r0, r2 + str r0, [r1] + MEND + + MACRO + MmioAndThenOr32Macro $Address, $AndData, $OrData + ldr r1, =($Address) + ldr r0, [r1] + ldr r2, =($AndData) + and r0, r0, r2 + ldr r2, =($OrData) + orr r0, r0, r2 + str r0, [r1] + MEND + + MACRO + MmioWriteFromReg32Macro $Address, $Reg + ldr r1, =($Address) + str $Reg, [r1] + MEND + + MACRO + MmioRead32Macro $Address + ldr r1, =($Address) + ldr r0, [r1] + MEND + + MACRO + MmioReadToReg32Macro $Address, $Reg + ldr r1, =($Address) + ldr $Reg, [r1] + MEND + + MACRO + LoadConstantMacro $Data + ldr r0, =($Data) + MEND + + MACRO + LoadConstantToRegMacro $Data, $Reg + ldr $Reg, =($Data) + MEND + + END + \ No newline at end of file diff --git a/BeagleBoardPkg/Sec/Arm/ModuleEntryPoint.S b/BeagleBoardPkg/Sec/Arm/ModuleEntryPoint.S new file mode 100755 index 0000000000..0ae8da6a24 --- /dev/null +++ b/BeagleBoardPkg/Sec/Arm/ModuleEntryPoint.S @@ -0,0 +1,93 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2008-2009 Apple Inc. All rights reserved. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + +#include +#include + +.text +.align 3 + +.globl ASM_PFX(CEntryPoint) +.globl ASM_PFX(_ModuleEntryPoint) + +ASM_PFX(_ModuleEntryPoint): + + //Disable L2 cache + mrc p15, 0, r0, c1, c0, 1 // read Auxiliary Control Register + bic r0, r0, #0x00000002 // disable L2 cache + mcr p15, 0, r0, c1, c0, 1 // store Auxiliary Control Register + + //Enable Strict alignment checking & Instruction cache + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */ + bic r0, r0, #0x00000005 /* clear bits 0, 2 (---- -C-M) */ + orr r0, r0, #0x00000002 /* set bit 1 (A) Align */ + orr r0, r0, #0x00001000 /* set bit 12 (I) enable I-Cache */ + mcr p15, 0, r0, c1, c0, 0 + + // Set CPU vectors to start of DRAM + mov r0, #0x80000000 + mcr p15, 0, r0, c12, c0, 0 + + /* before we call C code, lets setup the stack pointer */ +stack_pointer_setup: + + // + // Set stack based on PCD values. Need to do it this way to make C code work + // when it runs from FLASH. + // + LoadConstantToReg (FixedPcdGet32(PcdPrePiStackBase) ,r2) /* stack base arg2 */ + LoadConstantToReg (FixedPcdGet32(PcdPrePiStackSize) ,r3) /* stack size arg3 */ + add r4, r2, r3 + + //Enter IRQ mode and set up IRQ stack pointer + mov r0,#0x12|0x80|0x40 + msr CPSR_c,r0 + mov r13,r4 + + //Enter Abort mode and set up Abort stack pointer + mov r0,#0x17|0x80|0x40 + msr CPSR_c,r0 + sub r4, r4, #0x400 + mov r13,r4 + + //Enter Undefined mode and set up Undefined stack pointer + mov r0,#0x1b|0x80|0x40 + msr CPSR_c,r0 + sub r4, r4, #0x400 + mov r13,r4 + + //Enter SVC mode and set up SVC stack pointer + mov r0,#0x13|0x80|0x40 + msr CPSR_c,r0 + sub r4, r4, #0x400 + mov r13,r4 + + //Enter System mode and set up System stack pointer + mov r0,#0x1f|0x80|0x40 + msr CPSR_c,r0 + sub r4, r4, #0x400 + mov r13,r4 + + // Call C entry point + mov r0, #0x80000000 /* memory base arg0 */ + mov r1, #0x10000000 /* memory size arg1 */ + + bl ASM_PFX(CEntryPoint) /* Assume C code is ARM */ + +ShouldNeverGetHere: + /* _CEntryPoint should never return */ + b ShouldNeverGetHere + + diff --git a/BeagleBoardPkg/Sec/Arm/ModuleEntryPoint.asm b/BeagleBoardPkg/Sec/Arm/ModuleEntryPoint.asm new file mode 100755 index 0000000000..fb30e4dd59 --- /dev/null +++ b/BeagleBoardPkg/Sec/Arm/ModuleEntryPoint.asm @@ -0,0 +1,95 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2008-2009 Apple Inc. All rights reserved. +// +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +//------------------------------------------------------------------------------ + +#include +#include +#include + INCLUDE AsmMacroIoLib.inc + + IMPORT CEntryPoint + EXPORT _ModuleEntryPoint + + PRESERVE8 + AREA ModuleEntryPoint, CODE, READONLY + + +_ModuleEntryPoint + + //Disable L2 cache + mrc p15, 0, r0, c1, c0, 1 // read Auxiliary Control Register + bic r0, r0, #0x00000002 // disable L2 cache + mcr p15, 0, r0, c1, c0, 1 // store Auxiliary Control Register + + //Enable Strict alignment checking & Instruction cache + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */ + bic r0, r0, #0x00000005 /* clear bits 0, 2 (---- -C-M) */ + orr r0, r0, #0x00000002 /* set bit 1 (A) Align */ + orr r0, r0, #0x00001000 /* set bit 12 (I) enable I-Cache */ + mcr p15, 0, r0, c1, c0, 0 + + // Set CPU vectors to start of DRAM + mov r0, #0x80000000 + mcr p15, 0, r0, c12, c0, 0 + /* before we call C code, lets setup the stack pointer in internal RAM*/ +stack_pointer_setup + + // + // Set stack based on PCD values. Need to do it this way to make C code work + // when it runs from FLASH. + // + LoadConstantToReg (FixedPcdGet32(PcdPrePiStackBase) ,r2) /* stack base arg2 */ + LoadConstantToReg (FixedPcdGet32(PcdPrePiStackSize) ,r3) /* stack size arg3 */ + add r4, r2, r3 + + //Enter IRQ mode and set up IRQ stack pointer + mov r0,#0x12|0x80|0x40 + msr CPSR_c,r0 + mov r13,r4 + + //Enter Abort mode and set up Abort stack pointer + mov r0,#0x17|0x80|0x40 + msr CPSR_c,r0 + sub r4, r4, #0x400 + mov r13,r4 + + //Enter Undefined mode and set up Undefined stack pointer + mov r0,#0x1b|0x80|0x40 + msr CPSR_c,r0 + sub r4, r4, #0x400 + mov r13,r4 + + //Enter SVC mode and set up SVC stack pointer + mov r0,#0x13|0x80|0x40 + msr CPSR_c,r0 + sub r4, r4, #0x400 + mov r13,r4 + + //Enter System mode and set up System stack pointer + mov r0,#0x1f|0x80|0x40 + msr CPSR_c,r0 + sub r4, r4, #0x400 + mov r13,r4 + + // Call C entry point + mov r0, #0x80000000 /* memory base arg0 */ + mov r1, #0x08000000 /* memory size arg1 */ + blx CEntryPoint /* Assume C code is thumb */ + +ShouldNeverGetHere + /* _CEntryPoint should never return */ + b ShouldNeverGetHere + + END + diff --git a/BeagleBoardPkg/Sec/Cache.c b/BeagleBoardPkg/Sec/Cache.c new file mode 100755 index 0000000000..12bf990812 --- /dev/null +++ b/BeagleBoardPkg/Sec/Cache.c @@ -0,0 +1,88 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include + +// DDR attributes +#define DDR_ATTRIBUTES_CACHED ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK +#define DDR_ATTRIBUTES_UNCACHED ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED + +// SoC registers. L3 interconnects +#define SOC_REGISTERS_L3_PHYSICAL_BASE 0x68000000 +#define SOC_REGISTERS_L3_PHYSICAL_LENGTH 0x08000000 +#define SOC_REGISTERS_L3_ATTRIBUTES ARM_MEMORY_REGION_ATTRIBUTE_DEVICE + +// SoC registers. L4 interconnects +#define SOC_REGISTERS_L4_PHYSICAL_BASE 0x48000000 +#define SOC_REGISTERS_L4_PHYSICAL_LENGTH 0x08000000 +#define SOC_REGISTERS_L4_ATTRIBUTES ARM_MEMORY_REGION_ATTRIBUTE_DEVICE + +VOID +InitCache ( + IN UINT32 MemoryBase, + IN UINT32 MemoryLength + ) +{ + UINTN UncachedMemoryMask; + UINT32 CacheAttributes; + ARM_MEMORY_REGION_DESCRIPTOR MemoryTable[5]; + VOID *TranslationTableBase; + UINTN TranslationTableSize; + + UncachedMemoryMask = PcdGet64(PcdArmUncachedMemoryMask); + + if (FeaturePcdGet(PcdCacheEnable) == TRUE) { + CacheAttributes = DDR_ATTRIBUTES_CACHED; + } else { + CacheAttributes = DDR_ATTRIBUTES_UNCACHED; + } + + // DDR + MemoryTable[0].PhysicalBase = MemoryBase; + MemoryTable[0].VirtualBase = MemoryBase; + MemoryTable[0].Length = MemoryLength; + MemoryTable[0].Attributes = (ARM_MEMORY_REGION_ATTRIBUTES)CacheAttributes; + + // Uncached DDR Mirror + MemoryTable[1].PhysicalBase = MemoryBase; + MemoryTable[1].VirtualBase = MemoryBase | UncachedMemoryMask; + MemoryTable[1].Length = MemoryLength; + MemoryTable[1].Attributes = DDR_ATTRIBUTES_UNCACHED; + + // SOC Registers. L3 interconnects + MemoryTable[2].PhysicalBase = SOC_REGISTERS_L3_PHYSICAL_BASE; + MemoryTable[2].VirtualBase = SOC_REGISTERS_L3_PHYSICAL_BASE; + MemoryTable[2].Length = SOC_REGISTERS_L3_PHYSICAL_LENGTH; + MemoryTable[2].Attributes = SOC_REGISTERS_L3_ATTRIBUTES; + + // SOC Registers. L4 interconnects + MemoryTable[3].PhysicalBase = SOC_REGISTERS_L4_PHYSICAL_BASE; + MemoryTable[3].VirtualBase = SOC_REGISTERS_L4_PHYSICAL_BASE; + MemoryTable[3].Length = SOC_REGISTERS_L4_PHYSICAL_LENGTH; + MemoryTable[3].Attributes = SOC_REGISTERS_L4_ATTRIBUTES; + + // End of Table + MemoryTable[4].PhysicalBase = 0; + MemoryTable[4].VirtualBase = 0; + MemoryTable[4].Length = 0; + MemoryTable[4].Attributes = (ARM_MEMORY_REGION_ATTRIBUTES)0; + + ArmConfigureMmu(MemoryTable, &TranslationTableBase, &TranslationTableSize); + + BuildMemoryAllocationHob((EFI_PHYSICAL_ADDRESS)(UINTN)TranslationTableBase, TranslationTableSize, EfiBootServicesData); +} diff --git a/BeagleBoardPkg/Sec/Clock.c b/BeagleBoardPkg/Sec/Clock.c new file mode 100644 index 0000000000..2d814e49e9 --- /dev/null +++ b/BeagleBoardPkg/Sec/Clock.c @@ -0,0 +1,70 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include + +#include + +VOID +ClockInit ( + VOID + ) +{ + //DPLL1 - DPLL4 are configured part of Configuration header which OMAP3 ROM parses. + + // Enable PLL5 and set to 120 MHz as a reference clock. + MmioWrite32(CM_CLKSEL4_PLL, CM_CLKSEL_PLL_MULT(120) | CM_CLKSEL_PLL_DIV(13)); + MmioWrite32(CM_CLKSEL5_PLL, CM_CLKSEL_DIV_120M(1)); + MmioWrite32(CM_CLKEN2_PLL, CM_CLKEN_FREQSEL_075_100 | CM_CLKEN_ENABLE); + + // Turn on functional & interface clocks to the USBHOST power domain + MmioOr32(CM_FCLKEN_USBHOST, CM_FCLKEN_USBHOST_EN_USBHOST2_ENABLE + | CM_FCLKEN_USBHOST_EN_USBHOST1_ENABLE); + MmioOr32(CM_ICLKEN_USBHOST, CM_ICLKEN_USBHOST_EN_USBHOST_ENABLE); + + // Turn on functional & interface clocks to the USBTLL block. + MmioOr32(CM_FCLKEN3_CORE, CM_FCLKEN3_CORE_EN_USBTLL_ENABLE); + MmioOr32(CM_ICLKEN3_CORE, CM_ICLKEN3_CORE_EN_USBTLL_ENABLE); + + // Turn on functional & interface clocks to MMC1 and I2C1 modules. + MmioOr32(CM_FCLKEN1_CORE, CM_FCLKEN1_CORE_EN_MMC1_ENABLE + | CM_FCLKEN1_CORE_EN_I2C1_ENABLE); + MmioOr32(CM_ICLKEN1_CORE, CM_ICLKEN1_CORE_EN_MMC1_ENABLE + | CM_ICLKEN1_CORE_EN_I2C1_ENABLE); + + // Turn on functional & interface clocks to various Peripherals. + MmioOr32(CM_FCLKEN_PER, CM_FCLKEN_PER_EN_UART3_ENABLE + | CM_FCLKEN_PER_EN_GPT3_ENABLE + | CM_FCLKEN_PER_EN_GPT4_ENABLE + | CM_FCLKEN_PER_EN_GPIO2_ENABLE + | CM_FCLKEN_PER_EN_GPIO3_ENABLE + | CM_FCLKEN_PER_EN_GPIO4_ENABLE + | CM_FCLKEN_PER_EN_GPIO5_ENABLE + | CM_FCLKEN_PER_EN_GPIO6_ENABLE); + MmioOr32(CM_ICLKEN_PER, CM_ICLKEN_PER_EN_UART3_ENABLE + | CM_ICLKEN_PER_EN_GPT3_ENABLE + | CM_ICLKEN_PER_EN_GPT4_ENABLE + | CM_ICLKEN_PER_EN_GPIO2_ENABLE + | CM_ICLKEN_PER_EN_GPIO3_ENABLE + | CM_ICLKEN_PER_EN_GPIO4_ENABLE + | CM_ICLKEN_PER_EN_GPIO5_ENABLE + | CM_ICLKEN_PER_EN_GPIO6_ENABLE); + + // Turn on functional & inteface clocks to various wakeup modules. + MmioOr32(CM_FCLKEN_WKUP, CM_FCLKEN_WKUP_EN_GPIO1_ENABLE + | CM_FCLKEN_WKUP_EN_WDT2_ENABLE); + MmioOr32(CM_ICLKEN_WKUP, CM_ICLKEN_WKUP_EN_GPIO1_ENABLE + | CM_ICLKEN_WKUP_EN_WDT2_ENABLE); +} diff --git a/BeagleBoardPkg/Sec/PadConfiguration.c b/BeagleBoardPkg/Sec/PadConfiguration.c new file mode 100644 index 0000000000..b478cdfd92 --- /dev/null +++ b/BeagleBoardPkg/Sec/PadConfiguration.c @@ -0,0 +1,282 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include + +#define NUM_PINS 238 + +PAD_CONFIGURATION PadConfigurationTable[NUM_PINS] = { + //Pin, MuxMode, PullConfig, InputEnable + { SDRC_D0, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { SDRC_D1, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { SDRC_D2, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { SDRC_D3, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { SDRC_D4, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { SDRC_D5, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { SDRC_D6, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { SDRC_D7, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { SDRC_D8, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { SDRC_D9, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { SDRC_D10, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { SDRC_D11, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { SDRC_D12, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { SDRC_D13, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { SDRC_D14, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { SDRC_D15, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { SDRC_D16, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { SDRC_D17, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { SDRC_D18, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { SDRC_D19, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { SDRC_D20, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { SDRC_D21, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { SDRC_D22, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { SDRC_D23, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { SDRC_D24, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { SDRC_D25, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { SDRC_D26, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { SDRC_D27, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { SDRC_D28, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { SDRC_D29, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { SDRC_D30, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { SDRC_D31, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { SDRC_CLK, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { SDRC_DQS0, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { SDRC_CKE0, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { SDRC_CKE1, MUXMODE7, PULLTYPENOSELECT, INPUT }, + { SDRC_DQS1, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { SDRC_DQS2, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { SDRC_DQS3, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { GPMC_A1, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { GPMC_A2, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { GPMC_A3, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { GPMC_A4, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { GPMC_A5, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { GPMC_A6, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { GPMC_A7, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { GPMC_A8, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { GPMC_A9, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { GPMC_A10, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { GPMC_D0, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { GPMC_D1, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { GPMC_D2, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { GPMC_D3, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { GPMC_D4, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { GPMC_D5, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { GPMC_D6, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { GPMC_D7, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { GPMC_D8, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { GPMC_D9, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { GPMC_D10, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { GPMC_D11, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { GPMC_D12, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { GPMC_D13, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { GPMC_D14, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { GPMC_D15, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { GPMC_NCS0, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { GPMC_NCS1, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), OUTPUT }, + { GPMC_NCS2, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), OUTPUT }, + { GPMC_NCS3, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), OUTPUT }, + { GPMC_NCS4, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), OUTPUT }, + { GPMC_NCS5, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { GPMC_NCS6, MUXMODE1, PULLTYPENOSELECT, INPUT }, + { GPMC_NCS7, MUXMODE1, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { GPMC_CLK, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { GPMC_NADV_ALE, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { GPMC_NOE, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { GPMC_NWE, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { GPMC_NBE0_CLE, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { GPMC_NBE1, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { GPMC_NWP, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { GPMC_WAIT0, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { GPMC_WAIT1, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { GPMC_WAIT2, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { GPMC_WAIT3, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { DSS_PCLK, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { DSS_HSYNC, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { DSS_PSYNC, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { DSS_ACBIAS, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { DSS_DATA0, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { DSS_DATA1, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { DSS_DATA2, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { DSS_DATA3, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { DSS_DATA4, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { DSS_DATA5, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { DSS_DATA6, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { DSS_DATA7, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { DSS_DATA8, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { DSS_DATA9, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { DSS_DATA10, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { DSS_DATA11, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { DSS_DATA12, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { DSS_DATA13, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { DSS_DATA14, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { DSS_DATA15, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { DSS_DATA16, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { DSS_DATA17, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { DSS_DATA18, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { DSS_DATA19, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { DSS_DATA20, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { DSS_DATA21, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { DSS_DATA22, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { DSS_DATA23, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { CAM_HS, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { CAM_VS, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { CAM_XCLKA, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { CAM_PCLK, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { CAM_FLD, MUXMODE4, PULLTYPENOSELECT, OUTPUT }, + { CAM_D0, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { CAM_D1, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { CAM_D2, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { CAM_D3, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { CAM_D4, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { CAM_D5, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { CAM_D6, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { CAM_D7, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { CAM_D8, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { CAM_D9, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { CAM_D10, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { CAM_D11, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { CAM_XCLKB, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { CAM_WEN, MUXMODE4, PULLTYPENOSELECT, INPUT }, + { CAM_STROBE, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { CSI2_DX0, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { CSI2_DY0, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { CSI2_DX1, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { CSI2_DY1, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { MCBSP2_FSX, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { MCBSP2_CLKX, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { MCBSP2_DR, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { MCBSP2_DX, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { MMC1_CLK, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), OUTPUT }, + { MMC1_CMD, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { MMC1_DAT0, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { MMC1_DAT1, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { MMC1_DAT2, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { MMC1_DAT3, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { MMC1_DAT4, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { MMC1_DAT5, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { MMC1_DAT6, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { MMC1_DAT7, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { MMC2_CLK, MUXMODE4, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { MMC2_CMD, MUXMODE4, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { MMC2_DAT0, MUXMODE4, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { MMC2_DAT1, MUXMODE4, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { MMC2_DAT2, MUXMODE4, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { MMC2_DAT3, MUXMODE4, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { MMC2_DAT4, MUXMODE4, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { MMC2_DAT5, MUXMODE4, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { MMC2_DAT6, MUXMODE4, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { MMC2_DAT7, MUXMODE4, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { MCBSP3_DX, MUXMODE4, PULLTYPENOSELECT, OUTPUT }, + { MCBSP3_DR, MUXMODE4, PULLTYPENOSELECT, OUTPUT }, + { MCBSP3_CLKX, MUXMODE4, PULLTYPENOSELECT, OUTPUT }, + { MCBSP3_FSX, MUXMODE4, PULLTYPENOSELECT, OUTPUT }, + { UART2_CTS, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { UART2_RTS, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { UART2_TX, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { UART2_RX, MUXMODE4, PULLTYPENOSELECT, OUTPUT }, + { UART1_TX, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { UART1_RTS, MUXMODE4, PULLTYPENOSELECT, OUTPUT }, + { UART1_CTS, MUXMODE4, PULLTYPENOSELECT, OUTPUT }, + { UART1_RX, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { MCBSP4_CLKX, MUXMODE1, PULLTYPENOSELECT, INPUT }, + { MCBSP4_DR, MUXMODE1, PULLTYPENOSELECT, INPUT }, + { MCBSP4_DX, MUXMODE1, PULLTYPENOSELECT, INPUT }, + { MCBSP4_FSX, MUXMODE1, PULLTYPENOSELECT, INPUT }, + { MCBSP1_CLKR, MUXMODE4, PULLTYPENOSELECT, OUTPUT }, + { MCBSP1_FSR, MUXMODE4, (PULLTYPESELECT | PULLUDENABLE), OUTPUT }, + { MCBSP1_DX, MUXMODE4, PULLTYPENOSELECT, OUTPUT }, + { MCBSP1_DR, MUXMODE4, PULLTYPENOSELECT, OUTPUT }, + { MCBSP1_CLKS, MUXMODE0, PULLTYPESELECT, INPUT }, + { MCBSP1_FSX, MUXMODE4, PULLTYPENOSELECT, OUTPUT }, + { MCBSP1_CLKX, MUXMODE4, PULLTYPENOSELECT, OUTPUT }, + { UART3_CTS_RCTX,MUXMODE0, PULLUDENABLE, INPUT }, + { UART3_RTS_SD, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { UART3_RX_IRRX, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { UART3_TX_IRTX, MUXMODE0, PULLTYPENOSELECT, OUTPUT }, + { HSUSB0_CLK, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { HSUSB0_STP, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), OUTPUT }, + { HSUSB0_DIR, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { HSUSB0_NXT, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { HSUSB0_DATA0, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { HSUSB0_DATA1, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { HSUSB0_DATA2, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { HSUSB0_DATA3, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { HSUSB0_DATA4, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { HSUSB0_DATA5, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { HSUSB0_DATA6, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { HSUSB0_DATA7, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { I2C1_SCL, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { I2C1_SDA, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { I2C2_SCL, MUXMODE4, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { I2C2_SDA, MUXMODE4, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { I2C3_SCL, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { I2C3_SDA, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { HDQ_SIO, MUXMODE4, (PULLTYPESELECT | PULLUDENABLE), OUTPUT }, + { MCSPI1_CLK, MUXMODE4, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { MCSPI1_SIMO, MUXMODE4, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { MCSPI1_SOMI, MUXMODE0, PULLTYPENOSELECT, INPUT }, + { MCSPI1_CS0, MUXMODE0, PULLUDENABLE, INPUT }, + { MCSPI1_CS1, MUXMODE0, PULLUDENABLE, OUTPUT }, + { MCSPI1_CS2, MUXMODE4, PULLTYPENOSELECT, OUTPUT }, + { MCSPI1_CS3, MUXMODE3, PULLTYPESELECT, INPUT }, + { MCSPI2_CLK, MUXMODE3, PULLTYPESELECT, INPUT }, + { MCSPI2_SIMO, MUXMODE3, PULLTYPESELECT, INPUT }, + { MCSPI2_SOMI, MUXMODE3, PULLTYPESELECT, INPUT }, + { MCSPI2_CS0, MUXMODE3, PULLTYPESELECT, INPUT }, + { MCSPI2_CS1, MUXMODE3, PULLTYPESELECT, INPUT }, + { SYS_NIRQ, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { SYS_CLKOUT2, MUXMODE4, (PULLTYPESELECT | PULLUDENABLE), INPUT }, + { ETK_CLK, MUXMODE3, (PULLTYPESELECT | PULLUDENABLE), OUTPUT }, + { ETK_CTL, MUXMODE3, PULLTYPESELECT, OUTPUT }, + { ETK_D0, MUXMODE3, PULLTYPESELECT, INPUT }, + { ETK_D1, MUXMODE3, PULLTYPESELECT, INPUT }, + { ETK_D2, MUXMODE3, PULLTYPESELECT, INPUT }, + { ETK_D3, MUXMODE3, PULLTYPESELECT, INPUT }, + { ETK_D4, MUXMODE3, PULLTYPESELECT, INPUT }, + { ETK_D5, MUXMODE3, PULLTYPESELECT, INPUT }, + { ETK_D6, MUXMODE3, PULLTYPESELECT, INPUT }, + { ETK_D7, MUXMODE3, PULLTYPESELECT, INPUT }, + { ETK_D8, MUXMODE3, PULLTYPESELECT, INPUT }, + { ETK_D9, MUXMODE3, PULLTYPESELECT, INPUT }, + { ETK_D10, MUXMODE3, PULLTYPESELECT, OUTPUT }, + { ETK_D11, MUXMODE3, PULLTYPESELECT, OUTPUT }, + { ETK_D12, MUXMODE3, PULLTYPESELECT, INPUT }, + { ETK_D13, MUXMODE3, PULLTYPESELECT, INPUT }, + { ETK_D14, MUXMODE3, PULLTYPESELECT, INPUT }, + { ETK_D15, MUXMODE3, PULLTYPESELECT, INPUT } +}; + +VOID +PadConfiguration ( + VOID + ) +{ + UINTN Index; + UINT16 PadConfiguration; + UINTN NumPinsToConfigure = sizeof(PadConfigurationTable)/sizeof(PAD_CONFIGURATION); + + for (Index = 0; Index < NumPinsToConfigure; Index++) { + //Set up Pad configuration for particular pin. + PadConfiguration = (PadConfigurationTable[Index].MuxMode << MUXMODE_OFFSET); + PadConfiguration |= (PadConfigurationTable[Index].PullConfig << PULL_CONFIG_OFFSET); + PadConfiguration |= (PadConfigurationTable[Index].InputEnable << INPUTENABLE_OFFSET); + + //Configure the pin with specific Pad configuration. + MmioWrite16(PadConfigurationTable[Index].Pin, PadConfiguration); + } +} diff --git a/BeagleBoardPkg/Sec/Sec.c b/BeagleBoardPkg/Sec/Sec.c new file mode 100755 index 0000000000..321b35940c --- /dev/null +++ b/BeagleBoardPkg/Sec/Sec.c @@ -0,0 +1,165 @@ +/** @file + C Entry point for the SEC. First C code after the reset vector. + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include + +VOID +PadConfiguration ( + VOID + ); + +VOID +ClockInit ( + VOID + ); + +VOID +TimerInit ( + VOID + ) +{ + UINTN Timer = FixedPcdGet32(PcdBeagleFreeTimer); + UINT32 TimerBaseAddress = TimerBase(Timer); + + // Set source clock for GPT3 & GPT4 to SYS_CLK + MmioOr32(CM_CLKSEL_PER, CM_CLKSEL_PER_CLKSEL_GPT3_SYS + | CM_CLKSEL_PER_CLKSEL_GPT4_SYS); + + // Set count & reload registers + MmioWrite32(TimerBaseAddress + GPTIMER_TCRR, 0x00000000); + MmioWrite32(TimerBaseAddress + GPTIMER_TLDR, 0x00000000); + + // Disable interrupts + MmioWrite32(TimerBaseAddress + GPTIMER_TIER, TIER_TCAR_IT_DISABLE | TIER_OVF_IT_DISABLE | TIER_MAT_IT_DISABLE); + + // Start Timer + MmioWrite32(TimerBaseAddress + GPTIMER_TCLR, TCLR_AR_AUTORELOAD | TCLR_ST_ON); + + //Disable OMAP Watchdog timer (WDT2) + MmioWrite32(WDTIMER2_BASE + WSPR, 0xAAAA); + DEBUG ((EFI_D_ERROR, "Magic delay to disable watchdog timers properly.\n")); + MmioWrite32(WDTIMER2_BASE + WSPR, 0x5555); +} + +VOID +UartInit ( + VOID + ) +{ + UINTN Uart = FixedPcdGet32(PcdBeagleConsoleUart); + UINT32 UartBaseAddress = UartBase(Uart); + + // Set MODE_SELECT=DISABLE before trying to initialize or modify DLL, DLH registers. + MmioWrite32(UartBaseAddress + UART_MDR1_REG, UART_MDR1_MODE_SELECT_DISABLE); + + // Put device in configuration mode. + MmioWrite32(UartBaseAddress + UART_LCR_REG, UART_LCR_DIV_EN_ENABLE); + + // Programmable divisor N = 48Mhz/16/115200 = 26 + MmioWrite32(UartBaseAddress + UART_DLL_REG, 26); // low divisor + MmioWrite32(UartBaseAddress + UART_DLH_REG, 0); // high divisor + + // Enter into UART operational mode. + MmioWrite32(UartBaseAddress + UART_LCR_REG, UART_LCR_DIV_EN_DISABLE | UART_LCR_CHAR_LENGTH_8); + + // Force DTR and RTS output to active + MmioWrite32(UartBaseAddress + UART_MCR_REG, UART_MCR_RTS_FORCE_ACTIVE | UART_MCR_DTR_FORCE_ACTIVE); + + // Clear & enable fifos + MmioWrite32(UartBaseAddress + UART_FCR_REG, UART_FCR_TX_FIFO_CLEAR | UART_FCR_RX_FIFO_CLEAR | UART_FCR_FIFO_ENABLE); + + // Restore MODE_SELECT + MmioWrite32(UartBaseAddress + UART_MDR1_REG, UART_MDR1_MODE_SELECT_UART_16X); +} + +VOID +InitCache ( + IN UINT32 MemoryBase, + IN UINT32 MemoryLength + ); + +EFI_STATUS +EFIAPI +ExtractGuidedSectionLibConstructor ( + VOID + ); + +EFI_STATUS +EFIAPI +LzmaDecompressLibConstructor ( + VOID + ); + +VOID +CEntryPoint ( + IN VOID *MemoryBase, + IN UINTN MemorySize, + IN VOID *StackBase, + IN UINTN StackSize + ) +{ + VOID *HobBase; + + //Set up Pin muxing. + PadConfiguration(); + + // Set up system clocking + ClockInit(); + + // Build a basic HOB list + HobBase = (VOID *)(UINTN)(FixedPcdGet32(PcdEmbeddedFdBaseAddress) + FixedPcdGet32(PcdEmbeddedFdSize)); + CreateHobList(MemoryBase, MemorySize, HobBase, StackBase); + + // Enable program flow prediction, if supported. + ArmEnableBranchPrediction(); + + // Initialize CPU cache + InitCache((UINT32)MemoryBase, (UINT32)MemorySize); + + // Add memory allocation hob for relocated FD + BuildMemoryAllocationHob(FixedPcdGet32(PcdEmbeddedFdBaseAddress), FixedPcdGet32(PcdEmbeddedFdSize), EfiBootServicesData); + + // Add the FVs to the hob list + BuildFvHob(PcdGet32(PcdFlashFvMainBase), PcdGet32(PcdFlashFvMainSize)); + + // Start talking + UartInit(); + DEBUG((EFI_D_ERROR, "UART Test Line\n")); + + // Start up a free running time so that the timer lib will work + TimerInit(); + + // SEC phase needs to run library constructors by hand. + ExtractGuidedSectionLibConstructor(); + LzmaDecompressLibConstructor(); + + // Load the DXE Core and transfer control to it + LoadDxeCoreFromFv(NULL, 0); + + // DXE Core should always load and never return + ASSERT(FALSE); +} + diff --git a/BeagleBoardPkg/Sec/Sec.inf b/BeagleBoardPkg/Sec/Sec.inf new file mode 100755 index 0000000000..834519cf76 --- /dev/null +++ b/BeagleBoardPkg/Sec/Sec.inf @@ -0,0 +1,66 @@ +#%HEADER% +#/** @file +# SEC - Reset vector code that jumps to C and loads DXE core +# +# Copyright (c) 2008, Apple Inc.
+# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BeagleBoardSec + FILE_GUID = d959e387-7b91-452c-90e0-a1dbac90ddb8 + MODULE_TYPE = SEC + VERSION_STRING = 1.0 + + +[Sources.ARM] + Arm/ModuleEntryPoint.S | GCC + Arm/ModuleEntryPoint.asm | RVCT + +[Sources.ARM] + Sec.c + Cache.c + PadConfiguration.c + Clock.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + ArmPkg/ArmPkg.dec + BeagleBoardPkg/BeagleBoardPkg.dec + +[LibraryClasses] + BaseLib + DebugLib + ArmLib + IoLib + ExtractGuidedSectionLib + LzmaDecompressLib + OmapLib + +[FeaturePcd] + gEmbeddedTokenSpaceGuid.PcdCacheEnable + +[FixedPcd] + gArmTokenSpaceGuid.PcdArmUncachedMemoryMask + + gEmbeddedTokenSpaceGuid.PcdEmbeddedFdBaseAddress + gEmbeddedTokenSpaceGuid.PcdEmbeddedFdSize + gEmbeddedTokenSpaceGuid.PcdFlashFvMainBase + gEmbeddedTokenSpaceGuid.PcdFlashFvMainSize + gEmbeddedTokenSpaceGuid.PcdPrePiStackSize + gEmbeddedTokenSpaceGuid.PcdPrePiStackBase + + gBeagleBoardTokenSpaceGuid.PcdBeagleConsoleUart + gBeagleBoardTokenSpaceGuid.PcdBeagleFreeTimer + gBeagleBoardTokenSpaceGuid.PcdBeagleBoardIRAMFullSize + diff --git a/BeagleBoardPkg/SmbusDxe/Smbus.c b/BeagleBoardPkg/SmbusDxe/Smbus.c new file mode 100644 index 0000000000..35b17eb1fb --- /dev/null +++ b/BeagleBoardPkg/SmbusDxe/Smbus.c @@ -0,0 +1,325 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include + +#include +#include +#include + +#include + +#define MAX_RETRY 1000 + +// +// Internal Functions +// +STATIC +EFI_STATUS +WaitForBusBusy ( + VOID + ) +{ + UINTN Retry = 0; + + while (++Retry < MAX_RETRY && (MmioRead16(I2C_STAT) & BB) == 0x1); + + if (Retry == MAX_RETRY) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +PollForStatus( + UINT16 StatusBit + ) +{ + UINTN Retry = 0; + + while(Retry < MAX_RETRY) { + if (MmioRead16(I2C_STAT) & StatusBit) { + //Clear particular status bit from Status register. + MmioOr16(I2C_STAT, StatusBit); + break; + } + Retry++; + } + + if (Retry == MAX_RETRY) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +ConfigureI2c ( + VOID + ) +{ + //Program prescaler to obtain 12-MHz clock + MmioWrite16(I2C_PSC, 0x0000); + + //Program SCLL and SCLH + //NOTE: Following values are the register dump after U-Boot code executed. + //We need to figure out how its calculated based on the I2C functional clock and I2C_PSC. + MmioWrite16(I2C_SCLL, 0x0035); + MmioWrite16(I2C_SCLH, 0x0035); + + //Take the I2C controller out of reset. + MmioOr16(I2C_CON, I2C_EN); + + //Initialize the I2C controller. + + //Set I2C controller in Master mode. + MmioOr16(I2C_CON, MST); + + //Enable interrupts for receive/transmit mode. + MmioOr16(I2C_IE, (XRDY_IE | RRDY_IE | ARDY_IE | NACK_IE)); + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +I2CReadOneByte ( + UINT8 *Data + ) +{ + EFI_STATUS Status; + + //I2C bus status checking + Status = WaitForBusBusy(); + if (EFI_ERROR(Status)) { + return Status; + } + + //Poll till Receive ready bit is set. + Status = PollForStatus(RRDY); + if (EFI_ERROR(Status)) { + return Status; + } + + *Data = MmioRead8(I2C_DATA); + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +I2CWriteOneByte ( + UINT8 Data + ) +{ + EFI_STATUS Status; + + //I2C bus status checking + Status = WaitForBusBusy(); + if (EFI_ERROR(Status)) { + return Status; + } + + //Data transfer + //Poll till Transmit ready bit is set + Status = PollForStatus(XRDY); + if (EFI_ERROR(Status)) { + return Status; + } + + MmioWrite8(I2C_DATA, Data); + + //Wait and check if the NACK is not set. + gBS->Stall(1000); + if (MmioRead16(I2C_STAT) & NACK) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +SmbusBlockRead ( + OUT UINT8 *Buffer, + IN UINTN Length + ) +{ + UINTN Index = 0; + EFI_STATUS Status = EFI_SUCCESS; + + //Transfer configuration for receiving data. + MmioWrite16(I2C_CNT, Length); + //Need stop bit before sending data. + MmioWrite16(I2C_CON, (I2C_EN | MST | STP | STT)); + + while (Index < Length) { + //Read a byte + Status = I2CReadOneByte(&Buffer[Index++]); + if (EFI_ERROR(Status)) { + return Status; + } + } + + //Transfer completion + Status = PollForStatus(ARDY); + if (EFI_ERROR(Status)) { + return Status; + } + + return Status; +} + +STATIC +EFI_STATUS +SmbusBlockWrite ( + IN UINT8 *Buffer, + IN UINTN Length + ) +{ + UINTN Index = 0; + EFI_STATUS Status = EFI_SUCCESS; + + //Transfer configuration for transmitting data + MmioWrite16(I2C_CNT, Length); + MmioWrite16(I2C_CON, (I2C_EN | TRX | MST | STT | STP)); + + while (Index < Length) { + //Send a byte + Status = I2CWriteOneByte(Buffer[Index++]); + if (EFI_ERROR(Status)) { + return Status; + } + } + + //Transfer completion + Status = PollForStatus(ARDY); + if (EFI_ERROR(Status)) { + return Status; + } + + return Status; +} + +// +// Public Functions. +// +EFI_STATUS +EFIAPI +SmbusExecute ( + IN CONST EFI_SMBUS_HC_PROTOCOL *This, + IN CONST EFI_SMBUS_DEVICE_ADDRESS SlaveAddress, + IN CONST EFI_SMBUS_DEVICE_COMMAND Command, + IN CONST EFI_SMBUS_OPERATION Operation, + IN CONST BOOLEAN PecCheck, + IN OUT UINTN *Length, + IN OUT VOID *Buffer + ) +{ + UINT8 *ByteBuffer = Buffer; + EFI_STATUS Status = EFI_SUCCESS; + UINT8 SlaveAddr = (UINT8)(SlaveAddress.SmbusDeviceAddress); + + if (PecCheck) { + return EFI_UNSUPPORTED; + } + + if ((Operation != EfiSmbusWriteBlock) && (Operation != EfiSmbusReadBlock)) { + return EFI_UNSUPPORTED; + } + + //Set the Slave address. + MmioWrite16(I2C_SA, SlaveAddr); + + if (Operation == EfiSmbusReadBlock) { + Status = SmbusBlockRead(ByteBuffer, *Length); + } else if (Operation == EfiSmbusWriteBlock) { + Status = SmbusBlockWrite(ByteBuffer, *Length); + } + + return Status; +} + +EFI_STATUS +EFIAPI +SmbusArpDevice ( + IN CONST EFI_SMBUS_HC_PROTOCOL *This, + IN CONST BOOLEAN ArpAll, + IN CONST EFI_SMBUS_UDID *SmbusUdid OPTIONAL, + IN OUT EFI_SMBUS_DEVICE_ADDRESS *SlaveAddress OPTIONAL + ) +{ + return EFI_UNSUPPORTED; +} + + +EFI_STATUS +EFIAPI +SmbusGetArpMap ( + IN CONST EFI_SMBUS_HC_PROTOCOL *This, + IN OUT UINTN *Length, + IN OUT EFI_SMBUS_DEVICE_MAP **SmbusDeviceMap + ) +{ + return EFI_UNSUPPORTED; +} + + +EFI_STATUS +EFIAPI +SmbusNotify ( + IN CONST EFI_SMBUS_HC_PROTOCOL *This, + IN CONST EFI_SMBUS_DEVICE_ADDRESS SlaveAddress, + IN CONST UINTN Data, + IN CONST EFI_SMBUS_NOTIFY_FUNCTION NotifyFunction + ) +{ + return EFI_UNSUPPORTED; +} + +EFI_SMBUS_HC_PROTOCOL SmbusProtocol = +{ + SmbusExecute, + SmbusArpDevice, + SmbusGetArpMap, + SmbusNotify +}; + +EFI_STATUS +InitializeSmbus ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_HANDLE Handle = NULL; + EFI_STATUS Status; + + //Configure I2C controller. + Status = ConfigureI2c(); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_ERROR, "InitializeI2c fails.\n")); + return Status; + } + + // Install the SMBUS interface + Status = gBS->InstallMultipleProtocolInterfaces(&Handle, &gEfiSmbusHcProtocolGuid, &SmbusProtocol, NULL); + ASSERT_EFI_ERROR(Status); + + return Status; +} + diff --git a/BeagleBoardPkg/SmbusDxe/Smbus.inf b/BeagleBoardPkg/SmbusDxe/Smbus.inf new file mode 100644 index 0000000000..b13072054a --- /dev/null +++ b/BeagleBoardPkg/SmbusDxe/Smbus.inf @@ -0,0 +1,33 @@ +#%HEADER% +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = Smbus + FILE_GUID = d5125e0f-1226-444f-a218-0085996ed5da + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = InitializeSmbus + +[Sources.common] + Smbus.c + +[Packages] + MdePkg/MdePkg.dec + BeagleBoardPkg/BeagleBoardPkg.dec + +[LibraryClasses] + PcdLib + UefiLib + UefiDriverEntryPoint + MemoryAllocationLib + IoLib + +[Guids] + +[Protocols] + gEfiSmbusHcProtocolGuid + +[Pcd] + +[depex] + TRUE \ No newline at end of file diff --git a/BeagleBoardPkg/TPS65950Dxe/TPS65950.c b/BeagleBoardPkg/TPS65950Dxe/TPS65950.c new file mode 100644 index 0000000000..f47f795a1d --- /dev/null +++ b/BeagleBoardPkg/TPS65950Dxe/TPS65950.c @@ -0,0 +1,116 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include + +#include +#include +#include +#include + +#include +#include + +EFI_SMBUS_HC_PROTOCOL *Smbus; + +EFI_STATUS +Read ( + IN EMBEDDED_EXTERNAL_DEVICE *This, + IN UINTN Register, + IN UINTN Length, + OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + EFI_SMBUS_DEVICE_ADDRESS SlaveAddress; + UINT8 DeviceRegister; + UINTN DeviceRegisterLength = 1; + + SlaveAddress.SmbusDeviceAddress = EXTERNAL_DEVICE_REGISTER_TO_SLAVE_ADDRESS(Register); + DeviceRegister = (UINT8)EXTERNAL_DEVICE_REGISTER_TO_REGISTER(Register); + + //Write DeviceRegister. + Status = Smbus->Execute(Smbus, SlaveAddress, 0, EfiSmbusWriteBlock, FALSE, &DeviceRegisterLength, &DeviceRegister); + if (EFI_ERROR(Status)) { + return Status; + } + + //Read Data + Status = Smbus->Execute(Smbus, SlaveAddress, 0, EfiSmbusReadBlock, FALSE, &Length, Buffer); + return Status; +} + +EFI_STATUS +Write ( + IN EMBEDDED_EXTERNAL_DEVICE *This, + IN UINTN Register, + IN UINTN Length, + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + EFI_SMBUS_DEVICE_ADDRESS SlaveAddress; + UINT8 DeviceRegister; + UINTN DeviceBufferLength = Length + 1; + UINT8 *DeviceBuffer; + + SlaveAddress.SmbusDeviceAddress = EXTERNAL_DEVICE_REGISTER_TO_SLAVE_ADDRESS(Register); + DeviceRegister = (UINT8)EXTERNAL_DEVICE_REGISTER_TO_REGISTER(Register); + + //Prepare buffer for writing + DeviceBuffer = (UINT8 *)AllocatePool(DeviceBufferLength); + if (DeviceBuffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto exit; + } + + //Set Device register followed by data to write. + DeviceBuffer[0] = DeviceRegister; + CopyMem(&DeviceBuffer[1], Buffer, Length); + + //Write Data + Status = Smbus->Execute(Smbus, SlaveAddress, 0, EfiSmbusWriteBlock, FALSE, &DeviceBufferLength, DeviceBuffer); + if (EFI_ERROR(Status)) { + goto exit; + } + +exit: + if (DeviceBuffer) { + FreePool(DeviceBuffer); + } + + return Status; +} + +EMBEDDED_EXTERNAL_DEVICE ExternalDevice = { + Read, + Write +}; + +EFI_STATUS +TPS65950Initialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol(&gEfiSmbusHcProtocolGuid, NULL, (VOID **)&Smbus); + ASSERT_EFI_ERROR(Status); + + Status = gBS->InstallMultipleProtocolInterfaces(&ImageHandle, &gEmbeddedExternalDeviceProtocolGuid, &ExternalDevice, NULL); + return Status; +} diff --git a/BeagleBoardPkg/TPS65950Dxe/TPS65950.inf b/BeagleBoardPkg/TPS65950Dxe/TPS65950.inf new file mode 100644 index 0000000000..cc3be3d60a --- /dev/null +++ b/BeagleBoardPkg/TPS65950Dxe/TPS65950.inf @@ -0,0 +1,36 @@ +#%HEADER% +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TPS65950 + FILE_GUID = 71fe861a-5450-48b6-bfb0-b93522616f99 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = TPS65950Initialize + + +[Sources.common] + TPS65950.c + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + BeagleBoardPkg/BeagleBoardPkg.dec + +[LibraryClasses] + BaseMemoryLib + PcdLib + UefiLib + UefiDriverEntryPoint + MemoryAllocationLib + +[Guids] + +[Protocols] + gEfiSmbusHcProtocolGuid + gEmbeddedExternalDeviceProtocolGuid + +[Pcd] + +[depex] + gEfiSmbusHcProtocolGuid diff --git a/BeagleBoardPkg/TimerDxe/Timer.c b/BeagleBoardPkg/TimerDxe/Timer.c new file mode 100644 index 0000000000..32ba09c1eb --- /dev/null +++ b/BeagleBoardPkg/TimerDxe/Timer.c @@ -0,0 +1,239 @@ +/** @file + Template for Timer Architecture Protocol driver of the ARM flavor + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + + +// The notification function to call on every timer interrupt. +volatile EFI_TIMER_NOTIFY mTimerNotifyFunction = (EFI_TIMER_NOTIFY)NULL; +volatile EFI_PERIODIC_CALLBACK mTimerPeriodicCallback = (EFI_PERIODIC_CALLBACK)NULL; + + +// The current period of the timer interrupt +volatile UINT64 mTimerPeriod = 0; + +// Cached copy of the Hardware Interrupt protocol instance +EFI_HARDWARE_INTERRUPT_PROTOCOL *gInterrupt = NULL; + +// Cached registers +volatile UINT32 TISR; +volatile UINT32 TCLR; +volatile UINT32 TLDR; +volatile UINT32 TCRR; +volatile UINT32 TIER; + +// Cached interrupt vector +volatile UINTN gVector; + +VOID +EFIAPI +TimerInterruptHandler ( + IN HARDWARE_INTERRUPT_SOURCE Source, + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + if (mTimerPeriodicCallback) { + mTimerPeriodicCallback(SystemContext); + } + + if (mTimerNotifyFunction) { + mTimerNotifyFunction(mTimerPeriod); + } + + // Clear all timer interrupts + MmioWrite32(TISR, TISR_CLEAR_ALL); + + // Poll interrupt status bits to ensure clearing + while ((MmioRead32(TISR) & TISR_ALL_INTERRUPT_MASK) != TISR_NO_INTERRUPTS_PENDING); +} + +EFI_STATUS +EFIAPI +TimerDriverRegisterHandler ( + IN EFI_TIMER_ARCH_PROTOCOL *This, + IN EFI_TIMER_NOTIFY NotifyFunction + ) +{ + if ((NotifyFunction == NULL) && (mTimerNotifyFunction == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if ((NotifyFunction != NULL) && (mTimerNotifyFunction != NULL)) { + return EFI_ALREADY_STARTED; + } + + mTimerNotifyFunction = NotifyFunction; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +TimerDriverSetTimerPeriod ( + IN EFI_TIMER_ARCH_PROTOCOL *This, + IN UINT64 TimerPeriod + ) +{ + EFI_STATUS Status; + UINT64 TimerCount; + INT32 LoadValue; + + if (TimerPeriod == 0) { + // Turn off GPTIMER3 + MmioWrite32(TCLR, TCLR_ST_OFF); + + Status = gInterrupt->DisableInterruptSource(gInterrupt, gVector); + } else { + // Calculate required timer count + TimerCount = DivU64x32(TimerPeriod * 100, PcdGet32(PcdEmbeddedFdPerformanceCounterPeriodInNanoseconds)); + + // Set GPTIMER3 Load register + LoadValue = (INT32) -TimerCount; + MmioWrite32(TLDR, LoadValue); + MmioWrite32(TCRR, LoadValue); + + // Enable Overflow interrupt + MmioWrite32(TIER, TIER_TCAR_IT_DISABLE | TIER_OVF_IT_ENABLE | TIER_MAT_IT_DISABLE); + + // Turn on GPTIMER3, it will reload at overflow + MmioWrite32(TCLR, TCLR_AR_AUTORELOAD | TCLR_ST_ON); + + Status = gInterrupt->EnableInterruptSource(gInterrupt, gVector); + } + + // + // Save the new timer period + // + mTimerPeriod = TimerPeriod; + return Status; +} + +EFI_STATUS +EFIAPI +TimerDriverGetTimerPeriod ( + IN EFI_TIMER_ARCH_PROTOCOL *This, + OUT UINT64 *TimerPeriod + ) +{ + if (TimerPeriod == NULL) { + return EFI_INVALID_PARAMETER; + } + + *TimerPeriod = mTimerPeriod; + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +TimerDriverGenerateSoftInterrupt ( + IN EFI_TIMER_ARCH_PROTOCOL *This + ) +{ + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +TimerDriverRegisterPeriodicCallback ( + IN TIMER_DEBUG_SUPPORT_PROTOCOL *This, + IN EFI_PERIODIC_CALLBACK PeriodicCallback + ) +{ + if ((PeriodicCallback == NULL) && (mTimerPeriodicCallback == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if ((PeriodicCallback != NULL) && (mTimerPeriodicCallback != NULL)) { + return EFI_ALREADY_STARTED; + } + + mTimerPeriodicCallback = PeriodicCallback; + + return EFI_SUCCESS; +} + +EFI_TIMER_ARCH_PROTOCOL gTimer = { + TimerDriverRegisterHandler, + TimerDriverSetTimerPeriod, + TimerDriverGetTimerPeriod, + TimerDriverGenerateSoftInterrupt +}; + +TIMER_DEBUG_SUPPORT_PROTOCOL gTimerDebugSupport = { + TimerDriverRegisterPeriodicCallback +}; + +EFI_STATUS +EFIAPI +TimerInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_HANDLE Handle = NULL; + EFI_STATUS Status; + UINT32 TimerBaseAddress; + + // Find the interrupt controller protocol. ASSERT if not found. + Status = gBS->LocateProtocol(&gHardwareInterruptProtocolGuid, NULL, (VOID **)&gInterrupt); + ASSERT_EFI_ERROR (Status); + + // Set up the timer registers + TimerBaseAddress = TimerBase(FixedPcdGet32(PcdBeagleArchTimer)); + TISR = TimerBaseAddress + GPTIMER_TISR; + TCLR = TimerBaseAddress + GPTIMER_TCLR; + TLDR = TimerBaseAddress + GPTIMER_TLDR; + TCRR = TimerBaseAddress + GPTIMER_TCRR; + TIER = TimerBaseAddress + GPTIMER_TIER; + + // Disable the timer + Status = TimerDriverSetTimerPeriod(&gTimer, 0); + ASSERT_EFI_ERROR (Status); + + // Install interrupt handler + gVector = InterruptVectorForTimer(FixedPcdGet32(PcdBeagleArchTimer)); + Status = gInterrupt->RegisterInterruptSource(gInterrupt, gVector, TimerInterruptHandler); + ASSERT_EFI_ERROR (Status); + + // Set up default timer + Status = TimerDriverSetTimerPeriod(&gTimer, FixedPcdGet32(PcdTimerPeriod)); + ASSERT_EFI_ERROR (Status); + + // Install the Timer Architectural Protocol onto a new handle + Status = gBS->InstallMultipleProtocolInterfaces(&Handle, + &gEfiTimerArchProtocolGuid, &gTimer, + &gTimerDebugSupportProtocolGuid, &gTimerDebugSupport, + NULL); + ASSERT_EFI_ERROR(Status); + + return Status; +} + diff --git a/BeagleBoardPkg/TimerDxe/TimerDxe.inf b/BeagleBoardPkg/TimerDxe/TimerDxe.inf new file mode 100644 index 0000000000..b755aa79b4 --- /dev/null +++ b/BeagleBoardPkg/TimerDxe/TimerDxe.inf @@ -0,0 +1,60 @@ +#%HEADER% +#/** @file +# +# Component discription file for Timer module +# +# Copyright (c) 2009, Apple Inc.
+# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BeagleBoardTimerDxe + FILE_GUID = 6ddbf08b-cfc9-43cc-9e81-0784ba312ca0 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = TimerInitialize + +[Sources.common] + Timer.c + +[Packages] + BeagleBoardPkg/BeagleBoardPkg.dec + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + ArmPkg/ArmPkg.dec + +[LibraryClasses] + BaseLib + UefiRuntimeServicesTableLib + PerformanceLib + UefiLib + UefiBootServicesTableLib + BaseMemoryLib + DebugLib + UefiDriverEntryPoint + IoLib + OmapLib + +[Guids] + +[Protocols] + gEfiTimerArchProtocolGuid + gHardwareInterruptProtocolGuid + gTimerDebugSupportProtocolGuid + +[Pcd.common] + gEmbeddedTokenSpaceGuid.PcdTimerPeriod + gEmbeddedTokenSpaceGuid.PcdEmbeddedFdPerformanceCounterPeriodInNanoseconds + gBeagleBoardTokenSpaceGuid.PcdBeagleArchTimer + +[Depex] + gHardwareInterruptProtocolGuid \ No newline at end of file diff --git a/BeagleBoardPkg/Tools/GNUmakefile b/BeagleBoardPkg/Tools/GNUmakefile new file mode 100644 index 0000000000..2e4e67825e --- /dev/null +++ b/BeagleBoardPkg/Tools/GNUmakefile @@ -0,0 +1,20 @@ +# +# Copyright (c) 2008-2009, Apple Inc. All rights reserved. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# + +CC = gcc +CFLAGS = -g + +generate_image: generate_image.c + $(CC) $(CCFLAGS) $(LDFLAGS) -o generate_image generate_image.c + +clean: + rm -f generate_image generate_image.exe diff --git a/BeagleBoardPkg/Tools/generate_image.c b/BeagleBoardPkg/Tools/generate_image.c new file mode 100644 index 0000000000..9bcd67a187 --- /dev/null +++ b/BeagleBoardPkg/Tools/generate_image.c @@ -0,0 +1,410 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include +#include +#include + +//TOC structure as defined by OMAP35XX TRM. +typedef struct { + unsigned int Start; + unsigned int Size; + unsigned int Reserved1; + unsigned int Reserved2; + unsigned int Reserved3; + unsigned char Filename[12]; +} TOC_DATA; + +//NOTE: OMAP3430 TRM has CHSETTINGS and CHRAM structures. +typedef struct { + unsigned int SectionKey; + unsigned char Valid; + unsigned char Version; + unsigned short Reserved; + unsigned int Flags; + unsigned int PRM_CLKSRC_CTRL; + unsigned int PRM_CLKSEL; + unsigned int CM_CLKSEL1_EMU; + unsigned int CM_CLKSEL_CORE; + unsigned int CM_CLKSEL_WKUP; + unsigned int CM_CLKEN_PLL_DPLL3; + unsigned int CM_AUTOIDLE_PLL_DPLL3; + unsigned int CM_CLKSEL1_PLL; + unsigned int CM_CLKEN_PLL_DPLL4; + unsigned int CM_AUTOIDLE_PLL_DPLL4; + unsigned int CM_CLKSEL2_PLL; + unsigned int CM_CLKSEL3_PLL; + unsigned int CM_CLKEN_PLL_MPU; + unsigned int CM_AUTOIDLE_PLL_MPU; + unsigned int CM_CLKSEL1_PLL_MPU; + unsigned int CM_CLKSEL2_PLL_MPU; + unsigned int CM_CLKSTCTRL_MPU; +} CHSETTINGS_DATA; + +typedef struct { + unsigned int SectionKey; + unsigned char Valid; + unsigned char Reserved1; + unsigned char Reserved2; + unsigned char Reserved3; + unsigned short SDRC_SYSCONFIG_LSB; + unsigned short SDRC_CS_CFG_LSB; + unsigned short SDRC_SHARING_LSB; + unsigned short SDRC_ERR_TYPE_LSB; + unsigned int SDRC_DLLA_CTRL; + unsigned short Reserved4; + unsigned short Reserved5; + unsigned int SDRC_POWER; + unsigned short MEMORY_TYPE_CS0; + unsigned short Reserved6; + unsigned int SDRC_MCFG_0; + unsigned short SDRC_MR_0_LSB; + unsigned short SDRC_EMR1_0_LSB; + unsigned short SDRC_EMR2_0_LSB; + unsigned short SDRC_EMR3_0_LSB; + unsigned int SDRC_ACTIM_CTRLA_0; + unsigned int SDRC_ACTIM_CTRLB_0; + unsigned int SDRC_RFRCTRL_0; + unsigned short MEMORY_TYPE_CS1; + unsigned short Reserved7; + unsigned int SDRC_MCFG_1; + unsigned short SDRC_MR_1_LSB; + unsigned short SDRC_EMR1_1_LSB; + unsigned short SDRC_EMR2_1_LSB; + unsigned short SDRC_EMR3_1_LSB; + unsigned int SDRC_ACTIM_CTRLA_1; + unsigned int SDRC_ACTIM_CTRLB_1; + unsigned int SDRC_RFRCTRL_1; + unsigned int Reserved8; + unsigned short Flags; + unsigned short Reserved9; +} CHRAM_DATA; + +#define CHSETTINGS_START 0xA0 +#define CHSETTINGS_SIZE 0x50 +#define CHRAM_START 0xF0 +#define CHRAM_SIZE 0x5C +#define CLOSING_TOC_ITEM_SIZE 4 + +unsigned char gConfigurationHeader[512]; +unsigned int gImageExecutionAddress; +char *gInputImageFile = NULL; +char *gOutputImageFile = NULL; +char *gDataFile = NULL; + +static +void +PrintUsage ( + void + ) +{ + printf("Usage..\n"); +} + +static +void +PopulateCHSETTINGSData ( + FILE *DataFile, + CHSETTINGS_DATA *CHSETTINGSData + ) +{ + unsigned int Value; + + CHSETTINGSData->SectionKey = 0xC0C0C0C1; + CHSETTINGSData->Valid = 0x1; + CHSETTINGSData->Version = 0x1; + CHSETTINGSData->Reserved = 0x00; + CHSETTINGSData->Flags = 0x050001FD; + + //General clock settings. + fscanf(DataFile, "PRM_CLKSRC_CTRL=0x%08x\n", &Value); + CHSETTINGSData->PRM_CLKSRC_CTRL = Value; + fscanf(DataFile, "PRM_CLKSEL=0x%08x\n", &Value); + CHSETTINGSData->PRM_CLKSEL = Value; + fscanf(DataFile, "CM_CLKSEL1_EMU=0x%08x\n", &Value); + CHSETTINGSData->CM_CLKSEL1_EMU = Value; + + //Clock configuration + fscanf(DataFile, "CM_CLKSEL_CORE=0x%08x\n", &Value); + CHSETTINGSData->CM_CLKSEL_CORE = Value; + fscanf(DataFile, "CM_CLKSEL_WKUP=0x%08x\n", &Value); + CHSETTINGSData->CM_CLKSEL_WKUP = Value; + + //DPLL3 (Core) settings + fscanf(DataFile, "CM_CLKEN_PLL_DPLL3=0x%08x\n", &Value); + CHSETTINGSData->CM_CLKEN_PLL_DPLL3 = Value; + fscanf(DataFile, "CM_AUTOIDLE_PLL_DPLL3=0x%08x\n", &Value); + CHSETTINGSData->CM_AUTOIDLE_PLL_DPLL3 = Value; + fscanf(DataFile, "CM_CLKSEL1_PLL=0x%08x\n", &Value); + CHSETTINGSData->CM_CLKSEL1_PLL = Value; + + //DPLL4 (Peripheral) settings + fscanf(DataFile, "CM_CLKEN_PLL_DPLL4=0x%08x\n", &Value); + CHSETTINGSData->CM_CLKEN_PLL_DPLL4 = Value; + fscanf(DataFile, "CM_AUTOIDLE_PLL_DPLL4=0x%08x\n", &Value); + CHSETTINGSData->CM_AUTOIDLE_PLL_DPLL4 = Value; + fscanf(DataFile, "CM_CLKSEL2_PLL=0x%08x\n", &Value); + CHSETTINGSData->CM_CLKSEL2_PLL = Value; + fscanf(DataFile, "CM_CLKSEL3_PLL=0x%08x\n", &Value); + CHSETTINGSData->CM_CLKSEL3_PLL = Value; + + //DPLL1 (MPU) settings + fscanf(DataFile, "CM_CLKEN_PLL_MPU=0x%08x\n", &Value); + CHSETTINGSData->CM_CLKEN_PLL_MPU = Value; + fscanf(DataFile, "CM_AUTOIDLE_PLL_MPU=0x%08x\n", &Value); + CHSETTINGSData->CM_AUTOIDLE_PLL_MPU = Value; + fscanf(DataFile, "CM_CLKSEL1_PLL_MPU=0x%08x\n", &Value); + CHSETTINGSData->CM_CLKSEL1_PLL_MPU = Value; + fscanf(DataFile, "CM_CLKSEL2_PLL_MPU=0x%08x\n", &Value); + CHSETTINGSData->CM_CLKSEL2_PLL_MPU = Value; + fscanf(DataFile, "CM_CLKSTCTRL_MPU=0x%08x\n", &Value); + CHSETTINGSData->CM_CLKSTCTRL_MPU = Value; +} + +static +void +PopulateCHRAMData ( + FILE *DataFile, + CHRAM_DATA *CHRAMData + ) +{ + unsigned int Value; + + CHRAMData->SectionKey = 0xC0C0C0C2; + CHRAMData->Valid = 0x1; + + fscanf(DataFile, "SDRC_SYSCONFIG_LSB=0x%04x\n", &Value); + CHRAMData->SDRC_SYSCONFIG_LSB = Value; + fscanf(DataFile, "SDRC_CS_CFG_LSB=0x%04x\n", &Value); + CHRAMData->SDRC_CS_CFG_LSB = Value; + fscanf(DataFile, "SDRC_SHARING_LSB=0x%04x\n", &Value); + CHRAMData->SDRC_SHARING_LSB = Value; + fscanf(DataFile, "SDRC_ERR_TYPE_LSB=0x%04x\n", &Value); + CHRAMData->SDRC_ERR_TYPE_LSB = Value; + fscanf(DataFile, "SDRC_DLLA_CTRL=0x%08x\n", &Value); + CHRAMData->SDRC_DLLA_CTRL = Value; + fscanf(DataFile, "SDRC_POWER=0x%08x\n", &Value); + CHRAMData->SDRC_POWER = Value; + fscanf(DataFile, "MEMORY_TYPE_CS0=0x%04x\n", &Value); + CHRAMData->MEMORY_TYPE_CS0 = Value; + fscanf(DataFile, "SDRC_MCFG_0=0x%08x\n", &Value); + CHRAMData->SDRC_MCFG_0 = Value; + fscanf(DataFile, "SDRC_MR_0_LSB=0x%04x\n", &Value); + CHRAMData->SDRC_MR_0_LSB = Value; + fscanf(DataFile, "SDRC_EMR1_0_LSB=0x%04x\n", &Value); + CHRAMData->SDRC_EMR1_0_LSB = Value; + fscanf(DataFile, "SDRC_EMR2_0_LSB=0x%04x\n", &Value); + CHRAMData->SDRC_EMR2_0_LSB = Value; + fscanf(DataFile, "SDRC_EMR3_0_LSB=0x%04x\n", &Value); + CHRAMData->SDRC_EMR3_0_LSB = Value; + fscanf(DataFile, "SDRC_ACTIM_CTRLA_0=0x%08x\n", &Value); + CHRAMData->SDRC_ACTIM_CTRLA_0 = Value; + fscanf(DataFile, "SDRC_ACTIM_CTRLB_0=0x%08x\n", &Value); + CHRAMData->SDRC_ACTIM_CTRLB_0 = Value; + fscanf(DataFile, "SDRC_RFRCTRL_0=0x%08x\n", &Value); + CHRAMData->SDRC_RFRCTRL_0 = Value; + fscanf(DataFile, "MEMORY_TYPE_CS1=0x%04x\n", &Value); + CHRAMData->MEMORY_TYPE_CS1 = Value; + fscanf(DataFile, "SDRC_MCFG_1=0x%08x\n", &Value); + CHRAMData->SDRC_MCFG_1 = Value; + fscanf(DataFile, "SDRC_MR_1_LSB=0x%04x\n", &Value); + CHRAMData->SDRC_MR_1_LSB = Value; + fscanf(DataFile, "SDRC_EMR1_1_LSB=0x%04x\n", &Value); + CHRAMData->SDRC_EMR1_1_LSB = Value; + fscanf(DataFile, "SDRC_EMR2_1_LSB=0x%04x\n", &Value); + CHRAMData->SDRC_EMR2_1_LSB = Value; + fscanf(DataFile, "SDRC_EMR3_1_LSB=0x%04x\n", &Value); + CHRAMData->SDRC_EMR3_1_LSB = Value; + fscanf(DataFile, "SDRC_ACTIM_CTRLA_1=0x%08x\n", &Value); + CHRAMData->SDRC_ACTIM_CTRLA_1 = Value; + fscanf(DataFile, "SDRC_ACTIM_CTRLB_1=0x%08x\n", &Value); + CHRAMData->SDRC_ACTIM_CTRLB_1 = Value; + fscanf(DataFile, "SDRC_RFRCTRL_1=0x%08x\n", &Value); + CHRAMData->SDRC_RFRCTRL_1 = Value; + + CHRAMData->Flags = 0x0003; +} + +static +void +PrepareConfigurationHeader ( + void + ) +{ + TOC_DATA Toc; + CHSETTINGS_DATA CHSETTINGSData; + CHRAM_DATA CHRAMData; + unsigned int ConfigurationHdrOffset = 0; + FILE *DataFile; + + // Open data file + DataFile = fopen(gDataFile, "rb"); + if (DataFile == NULL) { + fprintf(stderr, "Can't open data file %s.\n", gOutputImageFile); + exit(1); + } + + //Initialize configuration header. + memset(gConfigurationHeader, 0x00, sizeof(gConfigurationHeader)); + + //CHSETTINGS TOC + memset(&Toc, 0x00, sizeof(TOC_DATA)); + Toc.Start = CHSETTINGS_START; + Toc.Size = CHSETTINGS_SIZE; + strcpy((char *)Toc.Filename, (const char *)"CHSETTINGS"); + memcpy(gConfigurationHeader + ConfigurationHdrOffset, &Toc, sizeof(TOC_DATA)); + + //Populate CHSETTINGS Data + memset(&CHSETTINGSData, 0x00, sizeof(CHSETTINGS_DATA)); + PopulateCHSETTINGSData(DataFile, &CHSETTINGSData); + memcpy(gConfigurationHeader + Toc.Start, &CHSETTINGSData, Toc.Size); + + //Adjust ConfigurationHdrOffset to point to next TOC + ConfigurationHdrOffset += sizeof(TOC_DATA); + + //CHRAM TOC + memset(&Toc, 0x00, sizeof(TOC_DATA)); + Toc.Start = CHRAM_START; + Toc.Size = CHRAM_SIZE; + strcpy((char *)Toc.Filename, (const char *)"CHRAM"); + memcpy(gConfigurationHeader + ConfigurationHdrOffset, &Toc, sizeof(TOC_DATA)); + + //Populate CHRAM Data + memset(&CHRAMData, 0x00, sizeof(CHRAM_DATA)); + PopulateCHRAMData(DataFile, &CHRAMData); + memcpy(gConfigurationHeader + Toc.Start, &CHRAMData, Toc.Size); + + //Adjust ConfigurationHdrOffset to point to next TOC + ConfigurationHdrOffset += sizeof(TOC_DATA); + + //Closing TOC item + memset(gConfigurationHeader + ConfigurationHdrOffset, 0xFF, CLOSING_TOC_ITEM_SIZE); + ConfigurationHdrOffset += CLOSING_TOC_ITEM_SIZE; + + // Close data file + fclose(DataFile); +} + +static +void +ConstructImage ( + void + ) +{ + FILE *InputFile; + FILE *OutputFile; + unsigned int InputImageFileSize; + unsigned int NewImageFileSize; + struct stat FileStat; + char Ch; + unsigned int i; + + InputFile = fopen(gInputImageFile, "rb"); + if (InputFile == NULL) { + fprintf(stderr, "Can't open input file.\n"); + exit(0); + } + + //Get the size of the input image. + fstat(fileno(InputFile), &FileStat); + InputImageFileSize = FileStat.st_size; + + //Calculate new file size + NewImageFileSize = InputImageFileSize - 520; + + OutputFile = fopen(gOutputImageFile, "wb"); + if (OutputFile == NULL) { + fprintf(stderr, "Can't open output file %s.\n", gOutputImageFile); + exit(0); + } + + //Write Configuration header + fwrite(gConfigurationHeader, 1, sizeof(gConfigurationHeader), OutputFile); + + //Write image header (Input image size, execution address) + fwrite(&NewImageFileSize, 1, 4, OutputFile); + fwrite(&gImageExecutionAddress, 1, 4, OutputFile); + + //Skip first 0x207 bytes + fseek(InputFile, 520, SEEK_SET); + + //Copy input image to the output file. + for (i = 0; i < NewImageFileSize; i++) { + fread(&Ch, 1, 1, InputFile); + fwrite(&Ch, 1, 1, OutputFile); + } + + fclose(InputFile); + fclose(OutputFile); +} + +int +main ( + int argc, + char** argv + ) +{ + char Ch; + unsigned char *ptr; + + if (argc == 1) { + PrintUsage (); + exit(1); + } + + while ((Ch = getopt(argc, argv, "D:E:I:O:")) != -1) { + switch (Ch) { + case 'E': /* Image execution address */ + gImageExecutionAddress = strtoul (optarg, (char **)&ptr, 16); + break; + + case 'I': /* Input image file */ + gInputImageFile = optarg; + break; + + case 'O': /* Output image file */ + gOutputImageFile = optarg; + break; + + case 'D': /* Data file */ + gDataFile = optarg; + break; + + case '?': + if ((optopt == 'E') || (optopt == 'I') || (optopt == 'O')) { + fprintf (stderr, "Option -%c requires an argument.\n", optopt); + } else if (isprint (optopt)) { + fprintf (stderr, "Unknown option `-%c'.\n", optopt); + } else { + fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt); + } + return 1; + + default: + abort (); + } + } + + //Prepare configuration header + PrepareConfigurationHeader (); + + //Build image with configuration header + image header + image + ConstructImage (); + + return 0; +} diff --git a/BeagleBoardPkg/build.sh b/BeagleBoardPkg/build.sh new file mode 100755 index 0000000000..94cabbe623 --- /dev/null +++ b/BeagleBoardPkg/build.sh @@ -0,0 +1,127 @@ +#!/bin/bash +# Copyright (c) 2008 - 2009, Apple, Inc. All rights reserved. +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# + +set -e +shopt -s nocasematch + +function process_debug_scripts { + if [[ -d $1 ]]; then + for filename in `ls $1` + do + sed -e "s@ZZZZZZ@$BUILD_ROOT@g" -e "s@WWWWWW@$WORKSPACE@g" \ + "$1/$filename" \ + > "$BUILD_ROOT/$filename" + + #For ARMCYGWIN, we have to change /cygdrive/c to c: + if [[ $TARGET_TOOLS == RVCT31CYGWIN ]] + then + mv "$BUILD_ROOT/$filename" "$BUILD_ROOT/$filename"_temp + sed -e "s@/cygdrive/\(.\)@\1:@g" \ + "$BUILD_ROOT/$filename"_temp \ + > "$BUILD_ROOT/$filename" + rm -f "$BUILD_ROOT/$filename"_temp + fi + done + fi +} + + +# +# Setup workspace if it is not set +# +if [ -z "$WORKSPACE" ] +then + echo Initializing workspace + cd .. + export EDK_TOOLS_PATH=`pwd`/BaseTools + source edksetup.sh BaseTools +else + echo Building from: $WORKSPACE +fi + +# +# Pick a default tool type for a given OS +# +case `uname` in + CYGWIN*) + TARGET_TOOLS=RVCT31CYGWIN + ;; + Linux*) + # Not tested + TARGET_TOOLS=ELFGCC + ;; + Darwin*) + Major=$(uname -r | cut -f 1 -d '.') + if [[ $Major == 9 ]] + then + # Not supported by this open source project + TARGET_TOOLS=XCODE31 + else + TARGET_TOOLS=XCODE32 + fi + ;; +esac + +BUILD_ROOT=$WORKSPACE/Build/BeagleBoard/DEBUG_"$TARGET_TOOLS" +GENERATE_IMAGE=$WORKSPACE/BeagleBoardPkg/Tools/generate_image +FLASH_BOOT=$BUILD_ROOT/FV/BeagleBoard_EFI_flashboot.fd + +if [[ ! -f `which build` || ! -f `which GenFv` ]]; +then + # build the tools if they don't yet exist + echo Building tools + make -C $WORKSPACE/BaseTools +else + echo using prebuilt tools +fi + +# +# Build the edk2 BeagleBoard code +# +build -p $WORKSPACE/BeagleBoardPkg/BeagleBoardPkg.dsc -a ARM -t $TARGET_TOOLS $1 $2 $3 $4 $5 $6 $7 $8 + +for arg in "$@" +do + if [[ $arg == clean ]]; then + # no need to post process if we are doing a clean + exit + elif [[ $arg == cleanall ]]; then + make -C BaseTools/ clean + make -C $WORKSPACE/BeagleBoardPkg/Tools clean + exit + + fi +done + + +# +# Build the tool used to patch the FLASH image to work with the Beagle board ROM +# +if [[ ! -e $GENERATE_IMAGE ]]; +then + make -C $WORKSPACE/BeagleBoardPkg/Tools +fi + +echo Patching FD to work with BeagleBoard ROM +rm -f $FLASH_BOOT + +# +# Ram starts at 0x80000000 +# OMAP 3530 TRM defines 0x80008208 as the entry point +# The reset vector is caught by the mask ROM in the OMAP 3530 so that is why this entry +# point looks so strange. +# OMAP 3430 TRM section 26.4.8 has Image header information. (missing in OMAP 3530 TRM) +# +$GENERATE_IMAGE -D $WORKSPACE/BeagleBoardPkg/ConfigurationHeader.dat -E 0x80008208 -I $BUILD_ROOT/FV/BEAGLEBOARD_EFI.fd -O $FLASH_BOOT + +echo Creating debugger scripts +process_debug_scripts $WORKSPACE/BeagleBoardPkg/Debugger_scripts + diff --git a/BeagleBoardPkg/readme.txt b/BeagleBoardPkg/readme.txt new file mode 100644 index 0000000000..8234fead73 --- /dev/null +++ b/BeagleBoardPkg/readme.txt @@ -0,0 +1,11 @@ +Build: +====== +Build requires a bash script. +./build.sh. + +FAQ: +==== +If you get a build error 000E: File/directory not found FatPkg/EnhancedFat/FatDxe/FatDxe.inf + +cd $WORKSPACE +svn checkout https://fat-driver2.tianocore.org/svn/fat-driver2/trunk/FatPkg FatPkg --username username \ No newline at end of file diff --git a/EmbeddedPkg/DebugSupportDxe/DebugSupport.c b/EmbeddedPkg/DebugSupportDxe/DebugSupport.c new file mode 100644 index 0000000000..26f4c387dc --- /dev/null +++ b/EmbeddedPkg/DebugSupportDxe/DebugSupport.c @@ -0,0 +1,119 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include + +#include +#include +#include + +EFI_STATUS +EFIAPI +DebugSupportGetMaximumProcessorIndex ( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + OUT UINTN *MaxProcessorIndex + ) +{ + if (MaxProcessorIndex == NULL) { + return EFI_INVALID_PARAMETER; + } + + *MaxProcessorIndex = 0; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +DebugSupportRegisterPeriodicCallback ( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + IN UINTN ProcessorIndex, + IN EFI_PERIODIC_CALLBACK PeriodicCallback + ) +{ + TIMER_DEBUG_SUPPORT_PROTOCOL *Timer; + EFI_STATUS Status; + + Status = gBS->LocateProtocol(&gTimerDebugSupportProtocolGuid, NULL, (VOID **)&Timer); + if (EFI_ERROR(Status)) { + return Status; + } + + Status = Timer->RegisterPeriodicCallback(Timer, PeriodicCallback); + + return Status; +} + +EFI_STATUS +EFIAPI +DebugSupportRegisterExceptionCallback ( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + IN UINTN ProcessorIndex, + IN EFI_EXCEPTION_CALLBACK ExceptionCallback, + IN EFI_EXCEPTION_TYPE ExceptionType + ) +{ + EFI_CPU_ARCH_PROTOCOL *Cpu; + EFI_STATUS Status; + + Status = gBS->LocateProtocol(&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu); + if (EFI_ERROR(Status)) { + return Status; + } + + Status = Cpu->RegisterInterruptHandler(Cpu, ExceptionType, (EFI_CPU_INTERRUPT_HANDLER)ExceptionCallback); + + return Status; +} + +EFI_STATUS +EFIAPI +DebugSupportInvalidateInstructionCache ( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + IN UINTN ProcessorIndex, + IN VOID *Start, + IN UINT64 Length + ) +{ + InvalidateInstructionCacheRange(Start, Length); + return EFI_SUCCESS; +} + +EFI_DEBUG_SUPPORT_PROTOCOL mDebugSupport = { + IsaArm, + DebugSupportGetMaximumProcessorIndex, + DebugSupportRegisterPeriodicCallback, + DebugSupportRegisterExceptionCallback, + DebugSupportInvalidateInstructionCache +}; + +EFI_STATUS +DebugSupportDxeInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle = NULL; + + ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiDebugSupportProtocolGuid); + Status = gBS->InstallMultipleProtocolInterfaces(&Handle, &gEfiDebugSupportProtocolGuid, &mDebugSupport, NULL); + + return Status; +} + diff --git a/EmbeddedPkg/DebugSupportDxe/DebugSupportDxe.inf b/EmbeddedPkg/DebugSupportDxe/DebugSupportDxe.inf new file mode 100644 index 0000000000..d3dab66ab7 --- /dev/null +++ b/EmbeddedPkg/DebugSupportDxe/DebugSupportDxe.inf @@ -0,0 +1,28 @@ +#%HEADER% +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ArmDebugSupportDxe + FILE_GUID = 2e7c151b-cbd8-4df6-a0e3-cde660067c6a + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = DebugSupportDxeInitialize + +[Sources.common] + DebugSupport.c + +[Packages] + MdePkg/MdePkg.dec + EmbeddedePkg/EmbeddedePkg.dec + +[LibraryClasses] + BaseMemoryLib + CacheMaintenanceLib + UefiDriverEntryPoint + ArmLib + +[Protocols] + gEfiCpuArchProtocolGuid + gEfiDebugSupportProtocolGuid + gTimerDebugSupportProtocolGuid + diff --git a/EmbeddedPkg/Ebl/CmdTemplate.c b/EmbeddedPkg/Ebl/CmdTemplate.c new file mode 100644 index 0000000000..456c4afe72 --- /dev/null +++ b/EmbeddedPkg/Ebl/CmdTemplate.c @@ -0,0 +1,65 @@ +/** @file + %CommandName% for EBL (Embedded Boot Loader) + + Copyright (c) 2007, Intel Corporation
+ All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + Module Name: CmdTemplate.c + + Search/Replace %CommandName% with the name of your new command + +**/ + +#include "Ebl.h" + + +/** + Fill Me In + + Argv[0] - "%CommandName%" + + @param Argc Number of command arguments in Argv + @param Argv Array of strings that represent the parsed command line. + Argv[0] is the comamnd name + + @return EFI_SUCCESS + +**/ +EFI_STATUS +Ebl%CommandName%Cmd ( + IN UINTN Argc, + IN CHAR8 **Argv + ) +{ + return EFI_SUCCESS; +} + + +GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmd%CommandName%Template[] = +{ + { + "%CommandName%", + " [show args] ; explain args and command", + NULL, + Ebl%CommandName%Cmd + } +}; + + +/** + Initialize the commands in this in this file +**/ +VOID +EblInitialize%CommandName%Cmd ( + VOID + ) +{ + EblAddCommands (mCmd%CommandName%Template, sizeof (mCmd%CommandName%Template)/sizeof (EBL_COMMAND_TABLE)); +} + diff --git a/EmbeddedPkg/Ebl/Command.c b/EmbeddedPkg/Ebl/Command.c new file mode 100644 index 0000000000..7899a0f442 --- /dev/null +++ b/EmbeddedPkg/Ebl/Command.c @@ -0,0 +1,978 @@ +/** @file + Basic commands and command processing infrastructure for EBL + + Copyright (c) 2007, Intel Corporation
+ Portions copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "Ebl.h" +#include +#include + +UINTN mCmdTableMaxIndex = EBL_MAX_COMMAND_COUNT; +UINTN mCmdTableNextFreeIndex = 0; +EBL_COMMAND_TABLE *mCmdTable[EBL_MAX_COMMAND_COUNT]; + +/** + Converts a lowercase Ascii character to upper one + + If Chr is lowercase Ascii character, then converts it to upper one. + + If Value >= 0xA0, then ASSERT(). + If (Value & 0x0F) >= 0x0A, then ASSERT(). + + @param chr one Ascii character + + @return The uppercase value of Ascii character + +**/ +STATIC +CHAR8 +AsciiToUpper ( + IN CHAR8 Chr + ) +{ + return (UINT8) ((Chr >= 'a' && Chr <= 'z') ? Chr - ('a' - 'A') : Chr); +} + + +/** + Case insensitve comparison of two Null-terminated Unicode strings with maximum + lengths, and returns the difference between the first mismatched Unicode + characters. + This function compares the Null-terminated Unicode string FirstString to the + Null-terminated Unicode string SecondString. At most, Length Unicode + characters will be compared. If Length is 0, then 0 is returned. If + FirstString is identical to SecondString, then 0 is returned. Otherwise, the + value returned is the first mismatched Unicode character in SecondString + subtracted from the first mismatched Unicode character in FirstString. + + @param FirstString Pointer to a Null-terminated ASCII string. + @param SecondString Pointer to a Null-terminated ASCII string. + @param Length Max length to compare. + + @retval 0 FirstString is identical to SecondString using case insensitive + comparisons. + @retval !=0 FirstString is not identical to SecondString using case + insensitive comparisons. + +**/ +INTN +EFIAPI +AsciiStrniCmp ( + IN CONST CHAR8 *FirstString, + IN CONST CHAR8 *SecondString, + IN UINTN Length + ) +{ + if (Length == 0) { + return 0; + } + + while ((AsciiToUpper (*FirstString) != '\0') && + (AsciiToUpper (*FirstString) == AsciiToUpper (*SecondString)) && + (Length > 1)) { + FirstString++; + SecondString++; + Length--; + } + + return AsciiToUpper (*FirstString) - AsciiToUpper (*SecondString); +} + + + +/** + Add a command to the mCmdTable. If there is no free space in the command + table ASSERT. The mCmdTable is maintained in alphabetical order and the + new entry is inserted into its sorted possition. + + @param Entry Commnad Entry to add to the CmdTable + +**/ +VOID +EFIAPI +EblAddCommand ( + IN const EBL_COMMAND_TABLE *Entry + ) +{ + UINTN Count; + + if (mCmdTableNextFreeIndex == EBL_MAX_COMMAND_COUNT) { + // + // Ran out of space to store commands. Increase EBL_MAX_COMMAND_COUNT + // + ASSERT (FALSE); + return; + } + + // + // Add command and Insertion sort array in the process + // + mCmdTable[mCmdTableNextFreeIndex] = (EBL_COMMAND_TABLE *)Entry; + if (mCmdTableNextFreeIndex != 0) { + for (Count = mCmdTableNextFreeIndex; Count > 0; Count--) { + if (AsciiStriCmp (mCmdTable[Count - 1]->Name, Entry->Name) <= 0) { + break; + } + + mCmdTable[Count] = mCmdTable[Count - 1]; + } + mCmdTable[Count] = (EBL_COMMAND_TABLE *)Entry; + } + + mCmdTableNextFreeIndex++; +} + + +/** + Add an set of commands to the command table. Most commonly used on static + array of commands. + + @param EntryArray Pointer to array of command entries + @param ArrayCount Number of commnad entries to add + +**/ +VOID +EFIAPI +EblAddCommands ( + IN const EBL_COMMAND_TABLE *EntryArray, + IN UINTN ArrayCount + ) +{ + UINTN Index; + + for (Index = 0; Index < ArrayCount; Index++) { + EblAddCommand (&EntryArray[Index]); + } +} + + +EBL_ADD_COMMAND_PROTOCOL gEblAddCommand = { + EblAddCommand, + EblAddCommands, + EblGetCharKey, + EblAnyKeyToContinueQtoQuit +}; + + + +/** + Return the best matching command for the passed in command name. The match + does not have to be exact, it just needs to be unqiue. This enables commands + to be shortend to the smallest set of starting characters that is unique. + + @param CommandName Name of command to search for + + @return NULL CommandName did not match or was not unique + Other Pointer to EBL_COMMAND_TABLE entry for CommandName + +**/ +EBL_COMMAND_TABLE * +EblGetCommand ( + IN CHAR8 *CommandName + ) +{ + UINTN Index; + UINTN BestMatchCount; + UINTN Length; + EBL_COMMAND_TABLE *Match; + + Length = AsciiStrLen (CommandName); + for (Index = 0, BestMatchCount = 0, Match = NULL; Index < mCmdTableNextFreeIndex; Index++) { + if (AsciiStriCmp (mCmdTable[Index]->Name, CommandName) == 0) { + // match a command exactly + return mCmdTable[Index]; + } + + if (AsciiStrniCmp (CommandName, mCmdTable[Index]->Name, Length) == 0) { + // partial match, so keep looking to make sure there is only one partial match + BestMatchCount++; + Match = mCmdTable[Index]; + } + } + + if (BestMatchCount == 1) { + return Match; + } + + // + // We had no matches or too many matches + // + return NULL; +} + + + +/** + List out help information on all the commands or print extended information + about a specific passed in command. + + Argv[0] - "help" + Argv[1] - Command to display help about + + @param Argc Number of command arguments in Argv + @param Argv Array of strings that represent the parsed command line. + Argv[0] is the comamnd name + + @return EFI_SUCCESS + +**/ +EFI_STATUS +EblHelpCmd ( + IN UINTN Argc, + IN CHAR8 **Argv + ) +{ + UINTN Index; + CHAR8 *Ptr; + UINTN CurrentRow; + + if (Argc == 1) { + // Print all the commands + AsciiPrint ("Embedded Boot Loader (EBL) commands (help command for more info):\n"); + for (Index = 0; Index < mCmdTableNextFreeIndex; Index++) { + EblSetTextColor (EFI_YELLOW); + AsciiPrint (" %a", mCmdTable[Index]->Name); + EblSetTextColor (0); + AsciiPrint ("%a\n", mCmdTable[Index]->HelpSummary); + } + } else if (Argv[1] != NULL) { + // Print specific help + for (Index = 0, CurrentRow = 0; Index < mCmdTableNextFreeIndex; Index++) { + if (AsciiStriCmp (Argv[1], mCmdTable[Index]->Name) == 0) { + Ptr = (mCmdTable[Index]->Help == NULL) ? mCmdTable[Index]->HelpSummary : mCmdTable[Index]->Help; + AsciiPrint ("%a%a\n", Argv[1], Ptr); + if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) { + break; + } + } + } + } + + return EFI_SUCCESS; +} + + +/** + Exit the EBL. If the commnad processor sees EFI_ABORTED return status it will + exit the EBL. + + Argv[0] - "exit" + + @param Argc Number of command arguments in Argv + @param Argv Array of strings that represent the parsed command line. + Argv[0] is the comamnd name + + @return EFI_ABORTED + +**/ +EFI_STATUS +EblExitCmd ( + IN UINTN Argc, + IN CHAR8 **Argv + ) +{ + EFI_STATUS Status; + UINTN MemoryMapSize; + EFI_MEMORY_DESCRIPTOR *MemoryMap; + UINTN MapKey; + UINTN DescriptorSize; + UINTN DescriptorVersion; + UINTN Pages; + + if (Argc > 1) { + if (AsciiStriCmp (Argv[1], "efi") != 0) { + return EFI_ABORTED; + } + } else if (Argc == 1) { + return EFI_ABORTED; + } + + MemoryMap = NULL; + MemoryMapSize = 0; + do { + Status = gBS->GetMemoryMap ( + &MemoryMapSize, + MemoryMap, + &MapKey, + &DescriptorSize, + &DescriptorVersion + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + + Pages = EFI_SIZE_TO_PAGES (MemoryMapSize) + 1; + MemoryMap = AllocatePages (Pages); + + // + // Get System MemoryMap + // + Status = gBS->GetMemoryMap ( + &MemoryMapSize, + MemoryMap, + &MapKey, + &DescriptorSize, + &DescriptorVersion + ); + // Don't do anything between the GetMemoryMap() and ExitBootServices() + if (!EFI_ERROR (Status)) { + Status = gBS->ExitBootServices (gImageHandle, MapKey); + if (EFI_ERROR (Status)) { + FreePages (MemoryMap, Pages); + MemoryMap = NULL; + MemoryMapSize = 0; + } + } + } + } while (EFI_ERROR (Status)); + + // + // At this point it is very dangerous to do things EFI as most of EFI is now gone. + // This command is useful if you are working with a debugger as it will shutdown + // DMA and other things that could break a soft resets. + // + CpuDeadLoop (); + + // Should never get here, but makes the compiler happy + return EFI_ABORTED; +} + + +/** + Update the screen by decrementing the timeout value. + This AsciiPrint has to match the AsciiPrint in + EblPauseCmd. + + @param ElaspedTime Current timout value remaining + +**/ +VOID +EFIAPI +EblPauseCallback ( + IN UINTN ElapsedTime + ) +{ + AsciiPrint ("\b\b\b\b\b\b\b\b\b\b\b\b \b\b%3d seconds", ElapsedTime); +} + +/** + Pause until a key is pressed and abort the remaining commands on the command + line. If no key is pressed continue processing the command line. This command + allows the user to stop an operation from happening and return control to the + command prompt. + + Argv[0] - "pause" + Argv[1] - timeout value is decimal seconds + + @param Argc Number of command arguments in Argv + @param Argv Array of strings that represent the parsed command line. + Argv[0] is the comamnd name + + @return EFI_SUCCESS Timeout expired with no input + @return EFI_TIMEOUT Stop procesing other commands on the same command line + +**/ +EFI_STATUS +EblPauseCmd ( + IN UINTN Argc, + IN CHAR8 **Argv + ) +{ + EFI_STATUS Status; + UINTN Delay; + EFI_INPUT_KEY Key; + + Delay = (Argc == 1)? 10 : AsciiStrDecimalToUintn (Argv[1]); + + AsciiPrint ("Hit any key to break. You have %3d seconds", Delay); + Status = EblGetCharKey (&Key, Delay, EblPauseCallback); + AsciiPrint ("\n"); + + // If we timeout then the pause succeded thus return success + // If we get a key return timout to stop other commnad on this cmd line + return (Status == EFI_SUCCESS) ? EFI_TIMEOUT : EFI_SUCCESS;; +} + + +/** + On a debug build issue a software breakpoint to enter the debugger + + Argv[0] - "break" + + @param Argc Number of command arguments in Argv + @param Argv Array of strings that represent the parsed command line. + Argv[0] is the comamnd name + + @return EFI_SUCCESS + +**/ +EFI_STATUS +EblBreakPointCmd ( + IN UINTN Argc, + IN CHAR8 **Argv + ) +{ + CpuBreakpoint (); + return EFI_SUCCESS; +} + + +/** + Reset the system. If no Argument do a Cold reset. If argument use that reset type + (W)arm = Warm Reset + (S)hutdown = Shutdown Reset + + Argv[0] - "reset" + Argv[1] - warm or shutdown reset type + + @param Argc Number of command arguments in Argv + @param Argv Array of strings that represent the parsed command line. + Argv[0] is the comamnd name + + @return EFI_SUCCESS + +**/ +EFI_STATUS +EblResetCmd ( + IN UINTN Argc, + IN CHAR8 **Argv + ) +{ + EFI_RESET_TYPE ResetType; + + ResetType = EfiResetCold; + if (Argc > 1) { + switch (*Argv[1]) { + case 'W': + case 'w': + ResetType = EfiResetWarm; + break; + case 'S': + case 's': + ResetType = EfiResetShutdown; + } + } + + gRT->ResetSystem (ResetType, EFI_SUCCESS, 0, NULL); + return EFI_SUCCESS; +} + + +/** + Toggle page break global. This turns on and off prompting to Quit or hit any + key to continue when a command is about to scroll the screen with its output + + Argv[0] - "page" + Argv[1] - on or off + + @param Argc Number of command arguments in Argv + @param Argv Array of strings that represent the parsed command line. + Argv[0] is the comamnd name + + @return EFI_SUCCESS + +**/ +EFI_STATUS +EblPageCmd ( + IN UINTN Argc, + IN CHAR8 **Argv + ) +{ + if (Argc <= 1) { + // toggle setting + gPageBreak = (gPageBreak) ? FALSE : TRUE; + } else { + // use argv to set the value + if ((Argv[1][0] == 'o') || (Argv[1][0] == 'O')) { + if ((Argv[1][1] == 'n') || (Argv[1][1] == 'N')) { + gPageBreak = TRUE; + } else if ((Argv[1][1] == 'f') || (Argv[1][1] == 'F')) { + gPageBreak = FALSE; + } else { + return EFI_INVALID_PARAMETER; + } + } + } + return EFI_SUCCESS; +} + +EFI_STATUS +EblSleepCmd ( + IN UINTN Argc, + IN CHAR8 **Argv + ) +{ + UINTN Delay; + + Delay = (Argc == 1)? 10 : AsciiStrDecimalToUintn (Argv[1]); + + gBS->Stall (Delay * 1000000); + + return EFI_SUCCESS; +} + +CHAR8 +ConvertToTextLine ( + IN CHAR8 Character + ) +{ + if (Character < ' ' || Character > '~') + { + return '.'; + } + else + { + return Character; + } +} + +UINTN +GetBytes ( + IN UINT8 *Address, + IN UINTN Bytes + ) +{ + UINTN Result = 0; + + if (Bytes >= 1) + Result = *Address++; + + if (Bytes >= 2) + Result = (Result << 8) + *Address++; + + if (Bytes >= 3) + Result = (Result << 8) + *Address++; + + return Result; +} + +CHAR8 mBlanks[] = " "; + +EFI_STATUS +OutputData ( + IN UINT8 *Address, + IN UINTN Length, + IN UINTN Width, + IN UINTN Offset + ) +{ + UINT8 *EndAddress; + UINTN Line; + CHAR8 TextLine[0x11]; + UINTN CurrentRow = 0; + UINTN Bytes; + UINTN Spaces = 0; + CHAR8 Blanks[80]; + + AsciiStrCpy (Blanks, mBlanks); + for (EndAddress = Address + Length; Address < EndAddress; Offset += Line) + { + AsciiPrint ("%08x: ", Offset); + for (Line = 0; (Line < 0x10) && (Address < EndAddress);) + { + Bytes = EndAddress - Address; + + switch (Width) + { + case 4: + if (Bytes >= 4) + { + AsciiPrint ("%08x ", *((UINT32 *)Address)); + TextLine[Line++] = ConvertToTextLine(*Address++); + TextLine[Line++] = ConvertToTextLine(*Address++); + TextLine[Line++] = ConvertToTextLine(*Address++); + TextLine[Line++] = ConvertToTextLine(*Address++); + } + else + { + AsciiPrint ("%08x ", GetBytes(Address, Bytes)); + Address += Bytes; + Line += Bytes; + } + break; + + case 2: + if (Bytes >= 2) + { + AsciiPrint ("%04x ", *((UINT16 *)Address)); + TextLine[Line++] = ConvertToTextLine(*Address++); + TextLine[Line++] = ConvertToTextLine(*Address++); + } + else + { + AsciiPrint ("%04x ", GetBytes(Address, Bytes)); + Address += Bytes; + Line += Bytes; + } + break; + + case 1: + AsciiPrint ("%02x ", *((UINT8 *)Address)); + TextLine[Line++] = ConvertToTextLine(*Address++); + break; + + default: + AsciiPrint ("Width must be 1, 2, or 4!\n"); + return EFI_INVALID_PARAMETER; + } + } + + // Pad spaces + if (Line < 0x10) + { + switch (Width) + { + case 4: + Spaces = 9 * ((0x10 - Line)/4); + break; + case 2: + Spaces = 5 * ((0x10 - Line)/2); + break; + case 1: + Spaces = 3 * (0x10 - Line); + break; + } + + Blanks[Spaces] = '\0'; + + AsciiPrint(Blanks); + + Blanks[Spaces] = ' '; + } + + TextLine[Line] = 0; + AsciiPrint ("|%a|\n", TextLine); + + if (EblAnyKeyToContinueQtoQuit(&CurrentRow, FALSE)) + { + return EFI_END_OF_FILE; + } + } + + if (Length % Width != 0) + { + AsciiPrint ("%08x\n", Offset); + } + + return EFI_SUCCESS; +} + +#define HEXDUMP_CHUNK 1024 + +EFI_STATUS +EblHexdumpCmd ( + IN UINTN Argc, + IN CHAR8 **Argv + ) +{ + EFI_OPEN_FILE *File; + VOID *Location; + UINTN Size; + UINTN Width = 1; + UINTN Offset = 0; + EFI_STATUS Status; + UINTN Chunk = HEXDUMP_CHUNK; + + if ((Argc < 2) || (Argc > 3)) + { + return EFI_INVALID_PARAMETER; + } + + if (Argc == 3) + { + Width = AsciiStrDecimalToUintn(Argv[2]); + } + + if ((Width != 1) && (Width != 2) && (Width != 4)) + { + return EFI_INVALID_PARAMETER; + } + + File = EfiOpen(Argv[1], EFI_FILE_MODE_READ, 0); + if (File == NULL) + { + return EFI_NOT_FOUND; + } + + Location = AllocatePool(Chunk); + Size = EfiTell(File, NULL); + + for (Offset = 0; Offset + HEXDUMP_CHUNK <= Size; Offset += Chunk) + { + Chunk = HEXDUMP_CHUNK; + + Status = EfiRead(File, Location, &Chunk); + if (EFI_ERROR(Status)) + { + AsciiPrint ("Error reading file content\n"); + goto Exit; + } + + Status = OutputData(Location, Chunk, Width, File->BaseOffset + Offset); + if (EFI_ERROR(Status)) + { + if (Status == EFI_END_OF_FILE) { + Status = EFI_SUCCESS; + } + goto Exit; + } + } + + // Any left over? + if (Offset < Size) + { + Chunk = Size - Offset; + Status = EfiRead(File, Location, &Chunk); + if (EFI_ERROR(Status)) + { + AsciiPrint ("Error reading file content\n"); + goto Exit; + } + + Status = OutputData(Location, Chunk, Width, File->BaseOffset + Offset); + if (EFI_ERROR(Status)) + { + if (Status == EFI_END_OF_FILE) { + Status = EFI_SUCCESS; + } + goto Exit; + } + } + +Exit: + EfiClose(File); + + FreePool(Location); + + return EFI_SUCCESS; +} + +#define USE_DISKIO 1 + +EFI_STATUS +EblDiskIoCmd ( + IN UINTN Argc, + IN CHAR8 **Argv + ) +{ + EFI_STATUS Status; + UINTN Offset; + UINT8 *EndOffset; + UINTN Length; + UINTN Line; + UINT8 *Buffer; + UINT8 *BufferOffset; + CHAR8 TextLine[0x11]; +#if USE_DISKIO + EFI_DISK_IO_PROTOCOL *DiskIo; +#else + EFI_BLOCK_IO_PROTOCOL *BlockIo; + UINTN Lba; +#endif + + if (AsciiStrCmp(Argv[1], "r") == 0) + { + Offset = AsciiStrHexToUintn(Argv[2]); + Length = AsciiStrHexToUintn(Argv[3]); + +#if USE_DISKIO + Status = gBS->LocateProtocol(&gEfiDiskIoProtocolGuid, NULL, (VOID **)&DiskIo); + if (EFI_ERROR(Status)) + { + AsciiPrint("Did not locate DiskIO\n"); + return Status; + } + + Buffer = AllocatePool(Length); + BufferOffset = Buffer; + + Status = DiskIo->ReadDisk(DiskIo, SIGNATURE_32('f','l','s','h'), Offset, Length, Buffer); + if (EFI_ERROR(Status)) + { + AsciiPrint("DiskIO read failed\n"); + gBS->FreePool(Buffer); + return Status; + } +#else + Status = gBS->LocateProtocol(&gEfiBlockIoProtocolGuid, NULL, (VOID **)&BlockIo); + if (EFI_ERROR(Status)) + { + AsciiPrint("Did not locate BlockIo\n"); + return Status; + } + + Length = BlockIo->Media->BlockSize; + Buffer = AllocatePool(Length); + BufferOffset = Buffer; + Lba = Offset/BlockIo->Media->BlockSize; + + Status = BlockIo->ReadBlocks(BlockIo, BlockIo->Media->MediaId, Lba, Length, Buffer); + if (EFI_ERROR(Status)) + { + AsciiPrint("BlockIo read failed\n"); + gBS->FreePool(Buffer); + return Status; + } + + // Whack offset to what we actually read from + Offset = Lba * BlockIo->Media->BlockSize; + + Length = 0x100; +#endif + + for (EndOffset = BufferOffset + Length; BufferOffset < EndOffset; Offset += 0x10) + { + AsciiPrint ("%08x: ", Offset); + + for (Line = 0; Line < 0x10; Line++) + { + AsciiPrint ("%02x ", *BufferOffset); + + if (*BufferOffset < ' ' || *BufferOffset > '~') + TextLine[Line] = '.'; + else + TextLine[Line] = *BufferOffset; + + BufferOffset++; + } + + TextLine[Line] = '\0'; + AsciiPrint ("|%a|\n", TextLine); + } + + gBS->FreePool(Buffer); + + return EFI_SUCCESS; + } + else if (AsciiStrCmp(Argv[1], "w") == 0) + { + Offset = AsciiStrHexToUintn(Argv[2]); + Length = AsciiStrHexToUintn(Argv[3]); + Buffer = (UINT8 *)AsciiStrHexToUintn(Argv[4]); + +#if USE_DISKIO + Status = gBS->LocateProtocol(&gEfiDiskIoProtocolGuid, NULL, (VOID **)&DiskIo); + if (EFI_ERROR(Status)) + { + AsciiPrint("Did not locate DiskIO\n"); + return Status; + } + + Status = DiskIo->WriteDisk(DiskIo, SIGNATURE_32('f','l','s','h'), Offset, Length, Buffer); + if (EFI_ERROR(Status)) + { + AsciiPrint("DiskIO write failed\n"); + return Status; + } + +#else +#endif + + return EFI_SUCCESS; + } + else + { + return EFI_INVALID_PARAMETER; + } +} + +GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdTemplate[] = +{ + { + "reset", + " [type]; Reset system. type = [warm] [shutdown] default is cold reset", + NULL, + EblResetCmd + }, + { + "exit", + "; Exit EBL", + NULL, + EblExitCmd + }, + { + "help", + " [cmd]; Help on cmd or a list of all commands if cmd is ommited", + NULL, + EblHelpCmd + }, + { + "break", + "; Generate debugging breakpoint", + NULL, + EblBreakPointCmd + }, + { + "page", + " [on|off]]; toggle promting on command output larger than screen", + NULL, + EblPageCmd + }, + { + "pause", + " [sec]; Pause for sec[10] seconds. ", + NULL, + EblPauseCmd + }, + { + "sleep", + " [sec]; Sleep for sec[10] seconds. ", + NULL, + EblSleepCmd + }, + { + "hexdump", + " filename ; dump a file as hex bytes", + NULL, + EblHexdumpCmd + }, + { + "diskio", + " [r|w] offset [length [dataptr]]; do a DiskIO read or write ", + NULL, + EblDiskIoCmd + } +}; + + +EFI_HANDLE gExternalCmdHandle = NULL; + +/** + Initialize the commands in this in this file +**/ +VOID +EblInitializeCmdTable ( + VOID + ) +{ + + EblAddCommands (mCmdTemplate, sizeof (mCmdTemplate)/sizeof (EBL_COMMAND_TABLE)); + + gBS->InstallProtocolInterface ( + &gExternalCmdHandle, + &gEfiEblAddCommandProtocolGuid, + EFI_NATIVE_INTERFACE, + &gEblAddCommand + ); + +} + + +VOID +EblShutdownExternalCmdTable ( + VOID + ) +{ + gBS->UninstallProtocolInterface (gExternalCmdHandle, &gEfiEblAddCommandProtocolGuid, &gEblAddCommand); +} + + diff --git a/EmbeddedPkg/Ebl/Dir.c b/EmbeddedPkg/Ebl/Dir.c new file mode 100644 index 0000000000..4e9f7b98b2 --- /dev/null +++ b/EmbeddedPkg/Ebl/Dir.c @@ -0,0 +1,305 @@ +/** @file + Dir for EBL (Embedded Boot Loader) + + Copyright (c) 2007, Intel Corporation
+ Portions copyright (c) 2008-2009, Apple Inc. All rights reserved. + + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + Module Name: CmdTemplate.c + + Search/Replace Dir with the name of your new command + +**/ + +#include "Ebl.h" + + +GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 *gFvFileType[] = { + "All", + "Raw", + "Freeform", + "SEC", + "PeiCore", + "DxeCore", + "PEIM", + "Driver", + "Combo Driver", + "Application", + "NULL", + "FV" +}; + + +/** + Perform a dir on a device. The device must support Simple File System Protocol + or the FV protocol. + + Argv[0] - "dir" + Argv[1] - Device Name:path. Path is optional + Argv[2] - Optional filename to match on. A leading * means match substring + Argv[3] - Optional FV file type + + dir fs1:\efi ; perform a dir on fs1: device in the efi directory + dir fs1:\efi *.efi; perform a dir on fs1: device in the efi directory but + only print out files that contain the string *.efi + dir fv1:\ ; perform a dir on fv1: device in the efi directory + NOTE: fv devices do not contian subdirs + dir fv1:\ * PEIM ; will match all files of type SEC + + @param Argc Number of command arguments in Argv + @param Argv Array of strings that represent the parsed command line. + Argv[0] is the comamnd name + + @return EFI_SUCCESS + +**/ +EFI_STATUS +EblDirCmd ( + IN UINTN Argc, + IN CHAR8 **Argv + ) +{ + EFI_STATUS Status; + EFI_OPEN_FILE *File; + EFI_FILE_INFO *DirInfo; + UINTN ReadSize; + UINTN CurrentRow; + CHAR16 *MatchSubString; + EFI_STATUS GetNextFileStatus; + UINTN Key; + EFI_FV_FILETYPE SearchType; + EFI_FV_FILETYPE Type; + EFI_FV_FILE_ATTRIBUTES Attributes; + UINTN Size; + EFI_GUID NameGuid; + EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; + UINT32 AuthenticationStatus; + VOID *Section; + UINTN SectionSize; + EFI_FV_FILETYPE Index; + UINTN Length; + UINTN BestMatchCount; + CHAR16 UnicodeFileName[MAX_CMD_LINE]; + + + if (Argc <= 1) { + // CWD not currently supported + return EFI_SUCCESS; + } + + File = EfiOpen (Argv[1], EFI_FILE_MODE_READ, 0); + if (File == NULL) { + return EFI_SUCCESS; + } + + if (File->Type == EfiOpenFirmwareVolume) { + // FV Dir + + SearchType = EFI_FV_FILETYPE_ALL; + UnicodeFileName[0] = '\0'; + MatchSubString = &UnicodeFileName[0]; + if (Argc > 2) { + AsciiStrToUnicodeStr (Argv[2], UnicodeFileName); + if (UnicodeFileName[0] == '*') { + // Handle *Name substring matching + MatchSubString = &UnicodeFileName[1]; + } + + // Handle file type matchs + if (Argc > 3) { + // match a specific file type, always last argument + Length = AsciiStrLen (Argv[3]); + for (Index = 1, BestMatchCount = 0; Index < sizeof (gFvFileType)/sizeof (CHAR8 *); Index++) { + if (AsciiStriCmp (gFvFileType[Index], Argv[3]) == 0) { + // exact match + SearchType = Index; + break; + } + + if (AsciiStrniCmp (Argv[3], gFvFileType[Index], Length) == 0) { + // partial match, so keep looking to make sure there is only one partial match + BestMatchCount++; + SearchType = Index; + } + } + + if (BestMatchCount > 1) { + SearchType = EFI_FV_FILETYPE_ALL; + } + } + } + + Fv = File->Fv; + Key = 0; + CurrentRow = 0; + do { + Type = SearchType; + GetNextFileStatus = Fv->GetNextFile ( + Fv, + &Key, + &Type, + &NameGuid, + &Attributes, + &Size + ); + if (!EFI_ERROR (GetNextFileStatus)) { + // Calculate size of entire file + Section = NULL; + Size = 0; + Status = Fv->ReadFile ( + Fv, + &NameGuid, + Section, + &Size, + &Type, + &Attributes, + &AuthenticationStatus + ); + if (!((Status == EFI_BUFFER_TOO_SMALL) || !EFI_ERROR (Status))) { + // EFI_SUCCESS or EFI_BUFFER_TOO_SMALL mean size is valid + Size = 0; + } + + // read the UI seciton to do a name match. + Section = NULL; + Status = Fv->ReadSection ( + Fv, + &NameGuid, + EFI_SECTION_USER_INTERFACE, + 0, + &Section, + &SectionSize, + &AuthenticationStatus + ); + if (!EFI_ERROR (Status)) { + if (StrStr (Section, MatchSubString) != NULL) { + AsciiPrint (" %g %s %a %,d\n", &NameGuid, Section, gFvFileType[Type], Size); + if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) { + break; + } + } + FreePool (Section); + } else { + if (*MatchSubString == '\0') { + AsciiPrint (" %g %a %,d\n", &NameGuid, gFvFileType[Type], Size); + if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) { + break; + } + } + } + } + } while (!EFI_ERROR (GetNextFileStatus)); + + } else if ((File->Type == EfiOpenFileSystem) || (File->Type == EfiOpenBlockIo)) { + // Simple File System DIR + + if (File->FsFileInfo == NULL) { + return EFI_SUCCESS; + } + + if (!(File->FsFileInfo->Attribute & EFI_FILE_DIRECTORY)) { + return EFI_SUCCESS; + } + + // Handle *Name substring matching + MatchSubString = NULL; + UnicodeFileName[0] = '\0'; + if (Argc > 2) { + AsciiStrToUnicodeStr (Argv[2], UnicodeFileName); + if (UnicodeFileName[0] == '*') { + MatchSubString = &UnicodeFileName[1]; + } + } + + File->FsFileHandle->SetPosition (File->FsFileHandle, 0); + for (CurrentRow = 0;;) { + // First read gets the size + DirInfo = NULL; + ReadSize = 0; + Status = File->FsFileHandle->Read (File->FsFileHandle, &ReadSize, DirInfo); + if (Status == EFI_BUFFER_TOO_SMALL) { + // Allocate the buffer for the real read + DirInfo = AllocatePool (ReadSize); + if (DirInfo == NULL) { + goto Done; + } + + // Read the data + Status = File->FsFileHandle->Read (File->FsFileHandle, &ReadSize, DirInfo); + if ((EFI_ERROR (Status)) || (ReadSize == 0)) { + break; + } + } else { + break; + } + + if (MatchSubString != NULL) { + if (StrStr (&DirInfo->FileName[0], MatchSubString) == NULL) { + // does not match *name argument, so skip + continue; + } + } else if (UnicodeFileName[0] != '\0') { + // is not an exact match for name argument, so skip + if (StrCmp (&DirInfo->FileName[0], UnicodeFileName) != 0) { + continue; + } + } + + if (DirInfo->Attribute & EFI_FILE_DIRECTORY) { + AsciiPrint (" %s\n", &DirInfo->FileName[0]); + } else { + AsciiPrint ("%,14ld %s\n", DirInfo->FileSize, &DirInfo->FileName[0]); + } + + if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) { + break; + } + + FreePool (DirInfo); + } + +Done: + if (DirInfo != NULL) { + FreePool (DirInfo); + } + } + + EfiClose (File); + + return EFI_SUCCESS; +} + + + +GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdDirTemplate[] = +{ + { + "dir", + " dirdev [*match]; directory listing of dirdev. opt match a substring", + NULL, + EblDirCmd + } +}; + + +/** + Initialize the commands in this in this file +**/ +VOID +EblInitializeDirCmd ( + VOID + ) +{ + if (FeaturePcdGet (PcdEmbeddedDirCmd)) { + EblAddCommands (mCmdDirTemplate, sizeof (mCmdDirTemplate)/sizeof (EBL_COMMAND_TABLE)); + } +} + diff --git a/EmbeddedPkg/Ebl/Ebl.h b/EmbeddedPkg/Ebl/Ebl.h new file mode 100644 index 0000000000..705511a0e4 --- /dev/null +++ b/EmbeddedPkg/Ebl/Ebl.h @@ -0,0 +1,194 @@ +/** @file + Include flie for basic command line parser for EBL (Embedded Boot Loader) + + Copyright (c) 2007, Intel Corporation
+ Portions copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EBL_H__ +#define __EBL_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +// +// Prompt for the command line +// +#define CMD_SEPERATOR ';' +#define EBL_MAX_COMMAND_COUNT 0x100 +#define MAX_CMD_HISTORY 16 +#define MAX_CMD_LINE 256 +#define MAX_ARGS 32 + +#define EBL_CR 0x0a +#define EBL_LF 0x0d + +#define EFI_SET_TIMER_TO_SECOND 10000000 + + + +EBL_COMMAND_TABLE * +EblGetCommand ( + IN CHAR8 *CommandName + ); + + +EFI_STATUS +EblPathToDevice ( + IN CHAR8 *Path, + OUT EFI_HANDLE *DeviceHandle, + OUT EFI_DEVICE_PATH_PROTOCOL **PathDevicePath, + OUT VOID **Buffer, + OUT UINTN *BufferSize + ); + +BOOLEAN +EblAnyKeyToContinueQtoQuit ( + IN UINTN *CurrentRow, + IN BOOLEAN PrefixNewline + ); + +VOID +EblUpdateDeviceLists ( + VOID + ); + +VOID +EblInitializeCmdTable ( + VOID + ); + +VOID +EblShutdownExternalCmdTable ( + VOID + ); + +VOID +EblSetTextColor ( + UINTN Attribute + ); + + +EFI_STATUS +EblGetCharKey ( + IN OUT EFI_INPUT_KEY *Key, + IN UINTN TimoutInSec, + IN EBL_GET_CHAR_CALL_BACK CallBack OPTIONAL + ); + +// BugBug: Move me to a library +INTN +EFIAPI +AsciiStrniCmp ( + IN CONST CHAR8 *FirstString, + IN CONST CHAR8 *SecondString, + IN UINTN Length + ); + + +VOID +EblInitializeDeviceCmd ( + VOID + ); + +VOID +EblInitializemdHwDebugCmds ( + VOID + ); + +VOID +EblInitializeDirCmd ( + VOID + ); + +VOID +EblInitializeHobCmd ( + VOID + ); + +VOID +EblInitializemdHwIoDebugCmds ( + VOID + ); + +VOID +EblInitializeScriptCmd ( + VOID + ); + +VOID +EblInitializeNetworkCmd ( + VOID + ); + +CHAR8 * +ParseArguments ( + IN CHAR8 *CmdLine, + OUT UINTN *Argc, + OUT CHAR8 **Argv + ); + +EFI_STATUS +ProcessCmdLine ( + IN CHAR8 *CmdLine, + IN UINTN MaxCmdLineSize + ); + +EFI_STATUS +OutputData ( + IN UINT8 *Address, + IN UINTN Length, + IN UINTN Width, + IN UINTN Offset + ); + +extern UINTN gScreenColumns; +extern UINTN gScreenRows; +extern BOOLEAN gPageBreak; +extern CHAR8 *gMemMapType[]; + +#endif + diff --git a/EmbeddedPkg/Ebl/Ebl.inf b/EmbeddedPkg/Ebl/Ebl.inf new file mode 100644 index 0000000000..f3413546be --- /dev/null +++ b/EmbeddedPkg/Ebl/Ebl.inf @@ -0,0 +1,110 @@ +#%HEADER% +#/** @file +# EBL Applicaiton +# +# This is a shell application that will display Hello World. +# Copyright (c) 2007, Intel Corporation. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = Ebl + FILE_GUID = 3CEF354A-3B7A-4519-AD70-72A134698311 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = EdkBootLoaderEntry + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# +[Sources.common] + Main.c + Command.c + EfiDevice.c + HwDebug.c + HwIoDebug.c + Dir.c + Hob.c + Script.c + Ebl.h + Network.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + +[LibraryClasses] + DebugLib + UefiLib + UefiApplicationEntryPoint + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + BaseMemoryLib + MemoryAllocationLib + DevicePathLib + IoLib + PrintLib + PcdLib + EfiFileLib + HobLib + BaseLib + EblCmdLib + EblNetworkLib + +[LibraryClasses.ARM] + SemihostLib + +[Protocols.common] + gEfiFirmwareVolume2ProtocolGuid + gEfiFirmwareVolumeBlockProtocolGuid + gEfiBlockIoProtocolGuid + gEfiSimpleFileSystemProtocolGuid + gEfiLoadFileProtocolGuid + gEfiLoadedImageProtocolGuid + gEfiPxeBaseCodeProtocolGuid + gEfiEblAddCommandProtocolGuid + gEfiDiskIoProtocolGuid + gEfiPciIoProtocolGuid + gEfiSimpleNetworkProtocolGuid + +[Guids.common] + gEfiDxeServicesTableGuid + gEfiFileInfoGuid + gEfiHobMemoryAllocModuleGuid + gEfiMemoryTypeInformationGuid + +[FeaturePcd.common] + gEmbeddedTokenSpaceGuid.PcdEmbeddedMacBoot + gEmbeddedTokenSpaceGuid.PcdEmbeddedDirCmd + gEmbeddedTokenSpaceGuid.PcdEmbeddedHobCmd + gEmbeddedTokenSpaceGuid.PcdEmbeddedHwDebugCmd + gEmbeddedTokenSpaceGuid.PcdEmbeddedIoEnable + gEmbeddedTokenSpaceGuid.PcdEmbeddedScriptCmd + gEmbeddedTokenSpaceGuid.PcdEmbeddedPciDebugCmd + +[FixedPcd.common] + gEmbeddedTokenSpaceGuid.PcdEmbeddedAutomaticBootCommand + gEmbeddedTokenSpaceGuid.PcdEmbeddedDefaultTextColor + gEmbeddedTokenSpaceGuid.PcdEmbeddedMemVariableStoreSize + gEmbeddedTokenSpaceGuid.PcdEmbeddedShellCharacterEcho + gEmbeddedTokenSpaceGuid.PcdEmbeddedPrompt + diff --git a/EmbeddedPkg/Ebl/EfiDevice.c b/EmbeddedPkg/Ebl/EfiDevice.c new file mode 100644 index 0000000000..7633d66934 --- /dev/null +++ b/EmbeddedPkg/Ebl/EfiDevice.c @@ -0,0 +1,969 @@ +/** @file + EBL commands for EFI and PI Devices + + Copyright (c) 2007, Intel Corporation
+ Portions copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "Ebl.h" + + +EFI_DXE_SERVICES *gDS = NULL; + + +/** + Print information about the File System device. + + @param File Open File for the device + +**/ +VOID +EblPrintFsInfo ( + IN EFI_OPEN_FILE *File + ) +{ + if (File == NULL) { + return; + } + + AsciiPrint (" %a: ", File->DeviceName); + if (File->FsInfo != NULL) { + AsciiPrint ("%s: ", File->FsInfo->VolumeLabel); + if (File->FsInfo->ReadOnly) { + AsciiPrint ("ReadOnly"); + } + } + + AsciiPrint ("\n"); + EfiClose (File); +} + + +/** + Print information about the FV devices. + + @param File Open File for the device + +**/ +VOID +EblPrintFvbInfo ( + IN EFI_OPEN_FILE *File + ) +{ + if (File == NULL) { + return; + } + + AsciiPrint (" %a: 0x%08lx - 0x%08lx : 0x%08x\n", File->DeviceName, File->FvStart, File->FvStart + File->FvSize - 1, File->FvSize); + EfiClose (File); +} + + +/** + Print information about the Blk IO devices. + If the device supports PXE dump out extra information + + @param File Open File for the device + +**/ +VOID +EblPrintBlkIoInfo ( + IN EFI_OPEN_FILE *File + ) +{ + UINT64 DeviceSize; + + + if (File == NULL) { + return; + } + + AsciiPrint (" %a: ", File->DeviceName); + if (File->FsBlockIoMedia.RemovableMedia) { + AsciiPrint ("Removable "); + } + if (!File->FsBlockIoMedia.MediaPresent) { + AsciiPrint ("No Media "); + } + if (File->FsBlockIoMedia.LogicalPartition) { + AsciiPrint ("Partition "); + } + DeviceSize = MultU64x32 (File->FsBlockIoMedia.LastBlock + 1, File->FsBlockIoMedia.BlockSize); + AsciiPrint ("Size = 0x%lX\n", DeviceSize); + + EfiClose (File); +} + + + /** + Print information about the Load File devices. + If the device supports PXE dump out extra information + + @param File Open File for the device + +**/ +VOID +EblPrintLoadFileInfo ( + IN EFI_OPEN_FILE *File + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePathNode; + MAC_ADDR_DEVICE_PATH *MacAddr; + UINTN HwAddressSize; + UINTN Index; + + if (File == NULL) { + return; + } + + AsciiPrint (" %a: %a ", File->DeviceName, EblLoadFileBootTypeString (File->EfiHandle)); + + if (File->DevicePath != NULL) { + // Try to print out the MAC address + for (DevicePathNode = File->DevicePath; + !IsDevicePathEnd (DevicePathNode); + DevicePathNode = NextDevicePathNode (DevicePathNode)) { + + if ((DevicePathType (DevicePathNode) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (DevicePathNode) == MSG_MAC_ADDR_DP)) { + MacAddr = (MAC_ADDR_DEVICE_PATH *)DevicePathNode; + + HwAddressSize = sizeof (EFI_MAC_ADDRESS); + if (MacAddr->IfType == 0x01 || MacAddr->IfType == 0x00) { + HwAddressSize = 6; + } + + AsciiPrint ("MAC "); + for (Index = 0; Index < HwAddressSize; Index++) { + AsciiPrint ("%02x", MacAddr->MacAddress.Addr[Index] & 0xff); + } + } + } + } + + AsciiPrint ("\n"); + EfiClose (File); + return; +} + + + +/** + Dump information about devices in the system. + + fv: PI Firmware Volume + fs: EFI Simple File System + blk: EFI Block IO + LoadFile: EFI Load File Protocol (commonly PXE network boot) + + Argv[0] - "device" + + @param Argc Number of command arguments in Argv + @param Argv Array of strings that represent the parsed command line. + Argv[0] is the comamnd name + + @return EFI_SUCCESS + +**/ +EFI_STATUS +EblDeviceCmd ( + IN UINTN Argc, + IN CHAR8 **Argv + ) +{ + UINTN Index; + UINTN CurrentRow; + UINTN Max; + + CurrentRow = 0; + + // Need to call here to make sure Device Counts are valid + EblUpdateDeviceLists (); + + Max = EfiGetDeviceCounts (EfiOpenFirmwareVolume); + if (Max != 0) { + AsciiPrint ("Firmware Volume Devices:\n"); + for (Index = 0; Index < Max; Index++) { + EblPrintFvbInfo (EfiDeviceOpenByType (EfiOpenFirmwareVolume, Index)); + if (EblAnyKeyToContinueQtoQuit (&CurrentRow, TRUE)) { + break; + } + } + } + + Max = EfiGetDeviceCounts (EfiOpenFileSystem); + if (Max != 0) { + AsciiPrint ("File System Devices:\n"); + for (Index = 0; Index < Max; Index++) { + EblPrintFsInfo (EfiDeviceOpenByType (EfiOpenFileSystem, Index)); + if (EblAnyKeyToContinueQtoQuit (&CurrentRow, TRUE)) { + break; + } + } + } + + Max = EfiGetDeviceCounts (EfiOpenBlockIo); + if (Max != 0) { + AsciiPrint ("Block IO Devices:\n"); + for (Index = 0; Index < Max; Index++) { + EblPrintBlkIoInfo (EfiDeviceOpenByType (EfiOpenBlockIo, Index)); + if (EblAnyKeyToContinueQtoQuit (&CurrentRow, TRUE)) { + break; + } + } + } + + Max = EfiGetDeviceCounts (EfiOpenLoadFile); + if (Max != 0) { + AsciiPrint ("LoadFile Devices: (usually network)\n"); + for (Index = 0; Index < Max; Index++) { + EblPrintLoadFileInfo (EfiDeviceOpenByType (EfiOpenLoadFile, Index)); + if (EblAnyKeyToContinueQtoQuit (&CurrentRow, TRUE)) { + break; + } + } + } + + return EFI_SUCCESS; +} + + +/** + Start an EFI image (PE32+ with EFI defined entry point). + + Argv[0] - "start" + Argv[1] - device name and path + Argv[2] - "" string to pass into image being started + + start fs1:\Temp\Fv.Fv "arg to pass" ; load an FV from the disk and pass the + ; ascii string arg to pass to the image + start fv0:\FV ; load an FV from an FV (not common) + start LoadFile0: ; load an FV via a PXE boot + + @param Argc Number of command arguments in Argv + @param Argv Array of strings that represent the parsed command line. + Argv[0] is the comamnd name + + @return EFI_SUCCESS + +**/ +EFI_STATUS +EblStartCmd ( + IN UINTN Argc, + IN CHAR8 **Argv + ) +{ + EFI_STATUS Status; + EFI_OPEN_FILE *File; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_HANDLE ImageHandle; + UINTN ExitDataSize; + CHAR16 *ExitData; + VOID *Buffer; + UINTN BufferSize; + EFI_LOADED_IMAGE_PROTOCOL *ImageInfo; + + ImageHandle = NULL; + + if (Argc < 2) { + return EFI_INVALID_PARAMETER; + } + + File = EfiOpen (Argv[1], EFI_FILE_MODE_READ, 0); + if (File == NULL) { + return EFI_INVALID_PARAMETER; + } + + DevicePath = File->DevicePath; + if (DevicePath != NULL) { + // check for device path form: blk, fv, fs, and loadfile + Status = gBS->LoadImage (FALSE, gImageHandle, DevicePath, NULL, 0, &ImageHandle); + } else { + // Check for buffer form: A0x12345678:0x1234 syntax. + // Means load using buffer starting at 0x12345678 of size 0x1234. + + Status = EfiReadAllocatePool (File, &Buffer, &BufferSize); + if (EFI_ERROR (Status)) { + EfiClose (File); + return Status; + } + Status = gBS->LoadImage (FALSE, gImageHandle, DevicePath, Buffer, BufferSize, &ImageHandle); + + FreePool (Buffer); + } + + EfiClose (File); + + if (!EFI_ERROR (Status)) { + if (Argc >= 3) { + // Argv[2] is a "" string that we pass directly to the EFI application without the "" + // We don't pass Argv[0] to the EFI Application (it's name) just the args + Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&ImageInfo); + ASSERT_EFI_ERROR (Status); + + ImageInfo->LoadOptionsSize = (UINT32)AsciiStrSize (Argv[2]); + ImageInfo->LoadOptions = AllocatePool (ImageInfo->LoadOptionsSize); + AsciiStrCpy (ImageInfo->LoadOptions, Argv[2]); + } + + // Transfer control to the EFI image we loaded with LoadImage() + Status = gBS->StartImage (ImageHandle, &ExitDataSize, &ExitData); + } + + return Status; +} + + +/** + Load a Firmware Volume (FV) into memory from a device. This causes drivers in + the FV to be dispatched if the dependancies of the drivers are met. + + Argv[0] - "loadfv" + Argv[1] - device name and path + + loadfv fs1:\Temp\Fv.Fv ; load an FV from the disk + loadfv fv0:\FV ; load an FV from an FV (not common) + loadfv LoadFile0: ; load an FV via a PXE boot + + @param Argc Number of command arguments in Argv + @param Argv Array of strings that represent the parsed command line. + Argv[0] is the comamnd name + + @return EFI_SUCCESS + +**/ +EFI_STATUS +EblLoadFvCmd ( + IN UINTN Argc, + IN CHAR8 **Argv + ) +{ + EFI_STATUS Status; + EFI_OPEN_FILE *File; + VOID *FvStart; + UINTN FvSize; + EFI_HANDLE FvHandle; + + + if (Argc < 2) { + return EFI_INVALID_PARAMETER; + } + + File = EfiOpen (Argv[1], EFI_FILE_MODE_READ, 0); + if (File == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (File->Type == EfiOpenMemoryBuffer) { + // If it is a address just use it. + Status = gDS->ProcessFirmwareVolume (File->Buffer, File->Size, &FvHandle); + } else { + // If it is a file read it into memory and use it + Status = EfiReadAllocatePool (File, &FvStart, &FvSize); + EfiClose (File); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gDS->ProcessFirmwareVolume (FvStart, FvSize, &FvHandle); + FreePool (FvStart); + } + return Status; +} + + +/** + Perform an EFI connect to connect devices that follow the EFI driver model. + If it is a PI system also call the dispatcher in case a new FV was made + availible by one of the connect EFI drivers (this is not a common case). + + Argv[0] - "connect" + + @param Argc Number of command arguments in Argv + @param Argv Array of strings that represent the parsed command line. + Argv[0] is the comamnd name + + @return EFI_SUCCESS + +**/ +EFI_STATUS +EblConnectCmd ( + IN UINTN Argc, + IN CHAR8 **Argv + ) +{ + EFI_STATUS Status; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN Index; + BOOLEAN Dispatch; + EFI_OPEN_FILE *File; + + + if (Argc > 1) { + if ((*Argv[1] == 'd') || (*Argv[1] == 'D')) { + Status = gBS->LocateHandleBuffer ( + AllHandles, + NULL, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + for (Index = 0; Index < HandleCount; Index++) { + gBS->DisconnectController (HandleBuffer[Index], NULL, NULL); + } + + // + // Given we disconnect our console we should go and do a connect now + // + } else { + File = EfiOpen (Argv[1], EFI_FILE_MODE_READ, 0); + if (File != NULL) { + AsciiPrint ("Connecting %a\n", Argv[1]); + gBS->ConnectController (File->EfiHandle, NULL, NULL, TRUE); + EfiClose (File); + return EFI_SUCCESS; + } + } + } + + Dispatch = FALSE; + do { + Status = gBS->LocateHandleBuffer ( + AllHandles, + NULL, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + for (Index = 0; Index < HandleCount; Index++) { + gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE); + } + + FreePool (HandleBuffer); + + // + // Check to see if it's possible to dispatch an more DXE drivers. + // The BdsLibConnectAllEfi () may have made new DXE drivers show up. + // If anything is Dispatched Status == EFI_SUCCESS and we will try + // the connect again. + // + if (gDS == NULL) { + Status = EFI_NOT_FOUND; + } else { + Status = gDS->Dispatch (); + if (!EFI_ERROR (Status)) { + Dispatch = TRUE; + } + } + + } while (!EFI_ERROR (Status)); + + if (Dispatch) { + AsciiPrint ("Connected and dispatched\n"); + } else { + AsciiPrint ("Connect\n"); + } + + return EFI_SUCCESS; +} + + + +CHAR8 *gMemMapType[] = { + "reserved ", + "LoaderCode", + "LoaderData", + "BS_code ", + "BS_data ", + "RT_code ", + "RT_data ", + "available ", + "Unusable ", + "ACPI_recl ", + "ACPI_NVS ", + "MemMapIO ", + "MemPortIO ", + "PAL_code " +}; + + +/** + Dump out the EFI memory map + + Argv[0] - "memmap" + + @param Argc Number of command arguments in Argv + @param Argv Array of strings that represent the parsed command line. + Argv[0] is the comamnd name + + @return EFI_SUCCESS + +**/ +EFI_STATUS +EblMemMapCmd ( + IN UINTN Argc, + IN CHAR8 **Argv + ) +{ + EFI_STATUS Status; + EFI_MEMORY_DESCRIPTOR *MemMap; + EFI_MEMORY_DESCRIPTOR *OrigMemMap; + UINTN MemMapSize; + UINTN MapKey; + UINTN DescriptorSize; + UINT32 DescriptorVersion; + UINT64 PageCount[EfiMaxMemoryType]; + UINTN Index; + UINT64 EntrySize; + UINTN CurrentRow; + UINT64 TotalMemory; + + ZeroMem (PageCount, sizeof (PageCount)); + + AsciiPrint ("EFI Memory Map\n"); + + // First call is to figure out how big the buffer needs to be + MemMapSize = 0; + MemMap = NULL; + Status = gBS->GetMemoryMap (&MemMapSize, MemMap, &MapKey, &DescriptorSize, &DescriptorVersion); + if (Status == EFI_BUFFER_TOO_SMALL) { + // In case the AllocatPool changes the memory map we added in some extra descriptors + MemMapSize += (DescriptorSize * 0x100); + OrigMemMap = MemMap = AllocatePool (MemMapSize); + if (OrigMemMap != NULL) { + // 2nd time we get the data + Status = gBS->GetMemoryMap (&MemMapSize, MemMap, &MapKey, &DescriptorSize, &DescriptorVersion); + if (!EFI_ERROR (Status)) { + for (Index = 0, CurrentRow = 0; Index < MemMapSize/DescriptorSize; Index++) { + EntrySize = LShiftU64 (MemMap->NumberOfPages, 12); + AsciiPrint ("\n%a %016lx - %016lx: # %08lx %016lx", gMemMapType[MemMap->Type % EfiMaxMemoryType], MemMap->PhysicalStart, MemMap->PhysicalStart + EntrySize -1, MemMap->NumberOfPages, MemMap->Attribute); + if (EblAnyKeyToContinueQtoQuit (&CurrentRow, TRUE)) { + break; + } + + PageCount[MemMap->Type % EfiMaxMemoryType] += MemMap->NumberOfPages; + MemMap = NEXT_MEMORY_DESCRIPTOR (MemMap, DescriptorSize); + } + } + + for (Index = 0, TotalMemory = 0; Index < EfiMaxMemoryType; Index++) { + if (PageCount[Index] != 0) { + AsciiPrint ("\n %a %,7ld Pages (%,14ld)", gMemMapType[Index], PageCount[Index], LShiftU64 (PageCount[Index], 12)); + if (Index == EfiLoaderCode || + Index == EfiLoaderData || + Index == EfiBootServicesCode || + Index == EfiBootServicesData || + Index == EfiRuntimeServicesCode || + Index == EfiRuntimeServicesData || + Index == EfiConventionalMemory || + Index == EfiACPIReclaimMemory || + Index == EfiACPIMemoryNVS || + Index == EfiPalCode + ) { + // Count total memory + TotalMemory += PageCount[Index]; + } + } + } + + AsciiPrint ("\nTotal Memory: %,ld MB (%,ld bytes)\n", RShiftU64 (TotalMemory, 8), LShiftU64 (TotalMemory, 12)); + + FreePool (OrigMemMap); + + } + } + + return EFI_SUCCESS; +} + + + + +/** + Load a file into memory and optionally jump to it. A load addres can be + specified or automatically allocated. A quoted command line can optionally + be passed into the image. + + Argv[0] - "go" + Argv[1] - Device Name:path for the file to load + Argv[2] - Address to load to or '*' if the load address will be allocated + Argv[3] - Optional Entry point to the image. Image will be called if present + Argv[4] - "" string that will be passed as Argc & Argv to EntryPoint. Needs + to include the command name + + go fv1:\EblCmdX 0x10000 0x10010 "EblCmdX Arg2 Arg3 Arg4"; - load EblCmdX + from FV1 to location 0x10000 and call the entry point at 0x10010 passing + in "EblCmdX Arg2 Arg3 Arg4" as the arguments. + + go fv0:\EblCmdX * 0x10 "EblCmdX Arg2 Arg3 Arg4"; - load EblCmdX from FS0 + to location allocated by this comamnd and call the entry point at offset 0x10 + passing in "EblCmdX Arg2 Arg3 Arg4" as the arguments. + + go fv1:\EblCmdX 0x10000; Load EblCmdX to address 0x10000 and return + + @param Argc Number of command arguments in Argv + @param Argv Array of strings that represent the parsed command line. + Argv[0] is the comamnd name + + @return EFI_SUCCESS + +**/ +EFI_STATUS +EblGoCmd ( + IN UINTN Argc, + IN CHAR8 **Argv + ) +{ + EFI_STATUS Status; + EFI_OPEN_FILE *File; + VOID *Address; + UINTN Size; + EBL_COMMMAND EntryPoint; + UINTN EntryPointArgc; + CHAR8 *EntryPointArgv[MAX_ARGS]; + + + if (Argc <= 2) { + // device name and laod address are required + return EFI_SUCCESS; + } + + File = EfiOpen (Argv[1], EFI_FILE_MODE_READ, 0); + if (File == NULL) { + AsciiPrint (" %a is not a valid path\n", Argv[1]); + return EFI_SUCCESS; + } + + EntryPoint = (EBL_COMMMAND)((Argc > 3) ? (UINTN)AsciiStrHexToUintn (Argv[3]) : (UINTN)NULL); + if (Argv[2][0] == '*') { + // * Means allocate the buffer + Status = EfiReadAllocatePool (File, &Address, &Size); + + // EntryPoint is relatvie to the start of the image + EntryPoint = (EBL_COMMMAND)((UINTN)EntryPoint + (UINTN)Address); + + } else { + Address = (VOID *)AsciiStrHexToUintn (Argv[2]); + Size = File->Size; + + // File->Size for LoadFile is lazy so we need to use the tell to figure it out + EfiTell (File, NULL); + Status = EfiRead (File, Address, &Size); + } + + if (!EFI_ERROR (Status)) { + AsciiPrint ("Loaded %,d bytes to 0x%08x\n", Size, Address); + + if (Argc > 3) { + if (Argc > 4) { + ParseArguments (Argv[4], &EntryPointArgc, EntryPointArgv); + } else { + EntryPointArgc = 1; + EntryPointArgv[0] = File->FileName; + } + + Status = EntryPoint (EntryPointArgc, EntryPointArgv); + } + } + + EfiClose (File); + return Status; +} + +#define FILE_COPY_CHUNK 0x20000 + +EFI_STATUS +EblFileCopyCmd ( + IN UINTN Argc, + IN CHAR8 **Argv + ) +{ + EFI_OPEN_FILE *Source = NULL; + EFI_OPEN_FILE *Destination = NULL; + EFI_STATUS Status = EFI_SUCCESS; + VOID *Buffer = NULL; + UINTN Size; + UINTN Offset; + UINTN Chunk = FILE_COPY_CHUNK; + + if (Argc < 3) { + return EFI_INVALID_PARAMETER; + } + + Source = EfiOpen(Argv[1], EFI_FILE_MODE_READ, 0); + if (Source == NULL) { + AsciiPrint("Source file open error.\n"); + return EFI_NOT_FOUND; + } + + Destination = EfiOpen(Argv[2], EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, 0); + if (Destination == NULL) { + AsciiPrint("Destination file open error.\n"); + return EFI_NOT_FOUND; + } + + Buffer = AllocatePool(FILE_COPY_CHUNK); + if (Buffer == NULL) { + goto Exit; + } + + Size = EfiTell(Source, NULL); + + for (Offset = 0; Offset + FILE_COPY_CHUNK <= Size; Offset += Chunk) { + Chunk = FILE_COPY_CHUNK; + + Status = EfiRead(Source, Buffer, &Chunk); + if (EFI_ERROR(Status)) { + AsciiPrint("Read file error\n"); + goto Exit; + } + + Status = EfiWrite(Destination, Buffer, &Chunk); + if (EFI_ERROR(Status)) { + AsciiPrint("Write file error\n"); + goto Exit; + } + } + + // Any left over? + if (Offset < Size) { + Chunk = Size - Offset; + + Status = EfiRead(Source, Buffer, &Chunk); + if (EFI_ERROR(Status)) { + AsciiPrint("Read file error\n"); + goto Exit; + } + + Status = EfiWrite(Destination, Buffer, &Chunk); + if (EFI_ERROR(Status)) { + AsciiPrint("Write file error\n"); + goto Exit; + } + } + +Exit: + if (Source != NULL) { + Status = EfiClose(Source); + if (EFI_ERROR(Status)) { + AsciiPrint("Source close error %r\n", Status); + } + } + + if (Destination != NULL) { + Status = EfiClose(Destination); + if (EFI_ERROR(Status)) { + AsciiPrint("Destination close error %r\n", Status); + } + } + + if (Buffer != NULL) { + FreePool(Buffer); + } + + return Status; +} + +EFI_STATUS +EblFileDiffCmd ( + IN UINTN Argc, + IN CHAR8 **Argv + ) +{ + EFI_OPEN_FILE *File1 = NULL; + EFI_OPEN_FILE *File2 = NULL; + EFI_STATUS Status = EFI_SUCCESS; + VOID *Buffer1 = NULL; + VOID *Buffer2 = NULL; + UINTN Size1; + UINTN Size2; + UINTN Offset; + UINTN Chunk = FILE_COPY_CHUNK; + + if (Argc != 3) { + return EFI_INVALID_PARAMETER; + } + + File1 = EfiOpen(Argv[1], EFI_FILE_MODE_READ, 0); + if (File1 == NULL) { + AsciiPrint("File 1 open error.\n"); + return EFI_NOT_FOUND; + } + + File2 = EfiOpen(Argv[2], EFI_FILE_MODE_READ, 0); + if (File2 == NULL) { + AsciiPrint("File 2 open error.\n"); + return EFI_NOT_FOUND; + } + + Size1 = EfiTell(File1, NULL); + Size2 = EfiTell(File2, NULL); + + if (Size1 != Size2) { + AsciiPrint("Files differ.\n"); + goto Exit; + } + + Buffer1 = AllocatePool(FILE_COPY_CHUNK); + if (Buffer1 == NULL) { + goto Exit; + } + + Buffer2 = AllocatePool(FILE_COPY_CHUNK); + if (Buffer2 == NULL) { + goto Exit; + } + + for (Offset = 0; Offset + FILE_COPY_CHUNK <= Size1; Offset += Chunk) { + Chunk = FILE_COPY_CHUNK; + + Status = EfiRead(File1, Buffer1, &Chunk); + if (EFI_ERROR(Status)) { + AsciiPrint("File 1 read error\n"); + goto Exit; + } + + Status = EfiRead(File2, Buffer2, &Chunk); + if (EFI_ERROR(Status)) { + AsciiPrint("File 2 read error\n"); + goto Exit; + } + + if (CompareMem(Buffer1, Buffer2, Chunk) != 0) { + AsciiPrint("Files differ.\n"); + goto Exit; + }; + } + + // Any left over? + if (Offset < Size1) { + Chunk = Size1 - Offset; + + Status = EfiRead(File1, Buffer1, &Chunk); + if (EFI_ERROR(Status)) { + AsciiPrint("File 1 read error\n"); + goto Exit; + } + + Status = EfiRead(File2, Buffer2, &Chunk); + if (EFI_ERROR(Status)) { + AsciiPrint("File 2 read error\n"); + goto Exit; + } + } + + if (CompareMem(Buffer1, Buffer2, Chunk) != 0) { + AsciiPrint("Files differ.\n"); + } else { + AsciiPrint("Files are identical.\n"); + } + +Exit: + if (File1 != NULL) { + Status = EfiClose(File1); + if (EFI_ERROR(Status)) { + AsciiPrint("File 1 close error %r\n", Status); + } + } + + if (File2 != NULL) { + Status = EfiClose(File2); + if (EFI_ERROR(Status)) { + AsciiPrint("File 2 close error %r\n", Status); + } + } + + if (Buffer1 != NULL) { + FreePool(Buffer1); + } + + if (Buffer2 != NULL) { + FreePool(Buffer2); + } + + return Status; +} + +GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdDeviceTemplate[] = +{ + { + "connect", + "[d]; Connect all EFI devices. d means disconnect", + NULL, + EblConnectCmd + }, + { + "device", + "; Show information about boot devices", + NULL, + EblDeviceCmd + }, + { + "go", + " dev:path loadaddress entrypoint args; load to given address and jump in", + NULL, + EblGoCmd + }, + { + "loadfv", + " devname; Load PI FV from device", + NULL, + EblLoadFvCmd + }, + { + "start", + " path; EFI Boot Device:filepath. fs1:\\EFI\\BOOT.EFI", + NULL, + EblStartCmd + }, + { + "memmap", + "; dump EFI memory map", + NULL, + EblMemMapCmd + }, + { + "cp", + " file1 file2; copy file", + NULL, + EblFileCopyCmd + }, + { + "diff", + " file1 file2; compare files", + NULL, + EblFileDiffCmd + } +}; + + +/** + Initialize the commands in this in this file +**/ + +VOID +EblInitializeDeviceCmd ( + VOID + ) +{ + EfiGetSystemConfigurationTable (&gEfiDxeServicesTableGuid, (VOID **) &gDS); + EblAddCommands (mCmdDeviceTemplate, sizeof (mCmdDeviceTemplate)/sizeof (EBL_COMMAND_TABLE)); +} + diff --git a/EmbeddedPkg/Ebl/Hob.c b/EmbeddedPkg/Ebl/Hob.c new file mode 100644 index 0000000000..c541f66968 --- /dev/null +++ b/EmbeddedPkg/Ebl/Hob.c @@ -0,0 +1,232 @@ +/** @file + Hob command for EBL (Embedded Boot Loader) + + Copyright (c) 2007, Intel Corporation
+ Portions copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + Module Name: Hob.c + + Search/Replace Dir with the name of your new command + + Boot Mode: + ========== + BOOT_WITH_FULL_CONFIGURATION 0x00 + BOOT_WITH_MINIMAL_CONFIGURATION 0x01 + BOOT_ASSUMING_NO_CONFIGURATION_CHANGES 0x02 + BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS 0x03 + BOOT_WITH_DEFAULT_SETTINGS 0x04 + BOOT_ON_S4_RESUME 0x05 + BOOT_ON_S5_RESUME 0x06 + BOOT_ON_S2_RESUME 0x10 + BOOT_ON_S3_RESUME 0x11 + BOOT_ON_FLASH_UPDATE 0x12 + BOOT_IN_RECOVERY_MODE 0x20 + BOOT_IN_RECOVERY_MODE_MASK 0x40 + BOOT_SPECIAL_MASK 0x80 + + Mem Alloc HOB Type: + =================== + typedef enum { + EfiReservedMemoryType = 0x00 + EfiLoaderCode = 0x01 + EfiLoaderData = 0x02 + EfiBootServicesCode = 0x03 + EfiBootServicesData = 0x04 + EfiRuntimeServicesCode = 0x05 + EfiRuntimeServicesData = 0x06 + EfiConventionalMemory = 0x07 + EfiUnusableMemory = 0x08 + EfiACPIReclaimMemory = 0x09 + EfiACPIMemoryNVS = 0x0a + EfiMemoryMappedIO = 0x0b + EfiMemoryMappedIOPortSpace = 0x0c + EfiPalCode = 0x0d + EfiMaxMemoryType = 0x0e + } EFI_MEMORY_TYPE; + + Resource Hob Tye: + ================= + EFI_RESOURCE_SYSTEM_MEMORY 0 + EFI_RESOURCE_MEMORY_MAPPED_IO 1 + EFI_RESOURCE_IO 2 + EFI_RESOURCE_FIRMWARE_DEVICE 3 + EFI_RESOURCE_MEMORY_MAPPED_IO_PORT 4 + EFI_RESOURCE_MEMORY_RESERVED 5 + EFI_RESOURCE_IO_RESERVED 6 + EFI_RESOURCE_MAX_MEMORY_TYPE 7 + + Resource Hob Attribute (last thing printed): + ============================================ + EFI_RESOURCE_ATTRIBUTE_PRESENT 0x00000001 + EFI_RESOURCE_ATTRIBUTE_INITIALIZED 0x00000002 + EFI_RESOURCE_ATTRIBUTE_TESTED 0x00000004 + EFI_RESOURCE_ATTRIBUTE_SINGLE_BIT_ECC 0x00000008 + EFI_RESOURCE_ATTRIBUTE_MULTIPLE_BIT_ECC 0x00000010 + EFI_RESOURCE_ATTRIBUTE_ECC_RESERVED_1 0x00000020 + EFI_RESOURCE_ATTRIBUTE_ECC_RESERVED_2 0x00000040 + EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED 0x00000080 + EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED 0x00000100 + EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED 0x00000200 + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE 0x00000400 + EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE 0x00000800 + EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE 0x00001000 + EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE 0x00002000 + EFI_RESOURCE_ATTRIBUTE_16_BIT_IO 0x00004000 + EFI_RESOURCE_ATTRIBUTE_32_BIT_IO 0x00008000 + EFI_RESOURCE_ATTRIBUTE_64_BIT_IO 0x00010000 + EFI_RESOURCE_ATTRIBUTE_UNCACHED_EXPORTED 0x00020000 + +**/ + +#include "Ebl.h" +// BugBug: Autogen does not allow this to be included currently +//#include + +GLOBAL_REMOVE_IF_UNREFERENCED char *mHobResourceType[] = { + "Memory ", + "MMIO ", + "IO ", + "Firmware ", + "MMIO Port ", + "Reserved ", + "IO Reserved", + "Illegal " +}; + + +/** + Dump out the HOBs in the system. HOBs are defined in the PI specificaiton + and they are used to hand off information from PEI to DXE. + + Argv[0] - "hob" + + @param Argc Number of command arguments in Argv + @param Argv Array of strings that represent the parsed command line. + Argv[0] is the comamnd name + + @return EFI_SUCCESS + +**/ +EFI_STATUS +EblHobCmd ( + IN UINTN Argc, + IN CHAR8 **Argv + ) +{ + UINTN CurrentRow; + EFI_PEI_HOB_POINTERS Hob; + EFI_MEMORY_TYPE_INFORMATION *EfiMemoryTypeInformation; + UINTN Index; + + CurrentRow = 0; + for (Hob.Raw = GetHobList (); !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) { + if (Hob.Header->HobType == EFI_HOB_TYPE_HANDOFF) { + AsciiPrint ("PHIT HOB Ver %x Boot Mode %02x Top %lx Bottom %lx\n", + Hob.HandoffInformationTable->Version, + Hob.HandoffInformationTable->BootMode, + Hob.HandoffInformationTable->EfiMemoryTop, + Hob.HandoffInformationTable->EfiMemoryBottom + ); + + if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) { + return EFI_SUCCESS; + } + + AsciiPrint (" Free Top %lx Free Bottom %lx End Of HOB %lx\n", + Hob.HandoffInformationTable->EfiFreeMemoryTop, + Hob.HandoffInformationTable->EfiFreeMemoryBottom, + Hob.HandoffInformationTable->EfiEndOfHobList + ); + + } else if (Hob.Header->HobType == EFI_HOB_TYPE_MEMORY_ALLOCATION) { + // mod(%) on array index is just to prevent buffer overrun + AsciiPrint ("Mem Alloc HOB %a %g %08lx:%lx\n", + (Hob.MemoryAllocation->AllocDescriptor.MemoryType < EfiMaxMemoryType) ? gMemMapType[Hob.MemoryAllocation->AllocDescriptor.MemoryType] : "ILLEGAL TYPE", + &Hob.MemoryAllocation->AllocDescriptor.Name, + Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress, + Hob.MemoryAllocation->AllocDescriptor.MemoryLength + ); + if (CompareGuid (&gEfiHobMemoryAllocModuleGuid, &Hob.MemoryAllocation->AllocDescriptor.Name)) { + if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) { + return EFI_SUCCESS; + } + AsciiPrint (" Module Name %g EntryPoint %lx\n", &Hob.MemoryAllocationModule->ModuleName, Hob.MemoryAllocationModule->EntryPoint); + } + } else if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { + AsciiPrint ("Resource HOB %a %g %08lx:%lx\n Attributes: %08x\n", + (Hob.ResourceDescriptor->ResourceType < EFI_RESOURCE_MAX_MEMORY_TYPE) ? mHobResourceType[Hob.ResourceDescriptor->ResourceType] : mHobResourceType[EFI_RESOURCE_MAX_MEMORY_TYPE], + &Hob.ResourceDescriptor->Owner, + Hob.ResourceDescriptor->PhysicalStart, + Hob.ResourceDescriptor->ResourceLength, + Hob.ResourceDescriptor->ResourceAttribute + ); + if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) { + return EFI_SUCCESS; + } + } else if (Hob.Header->HobType == EFI_HOB_TYPE_GUID_EXTENSION) { + AsciiPrint ("GUID HOB %g\n", &Hob.Guid->Name); + if (CompareGuid (&gEfiMemoryTypeInformationGuid, &Hob.Guid->Name)) { + EfiMemoryTypeInformation = GET_GUID_HOB_DATA (Hob.Guid); + for (Index = 0; Index < (GET_GUID_HOB_DATA_SIZE (Hob.Guid)/sizeof (EFI_MEMORY_TYPE_INFORMATION)); Index++, EfiMemoryTypeInformation++) { + if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) { + return EFI_SUCCESS; + } + AsciiPrint (" %a 0x%08x\n", + (EfiMemoryTypeInformation->Type < EfiMaxMemoryType) ? gMemMapType[EfiMemoryTypeInformation->Type] : "END ", + EfiMemoryTypeInformation->NumberOfPages + ); + } + } + } else if (Hob.Header->HobType == EFI_HOB_TYPE_FV) { + AsciiPrint ("FV HOB %08lx:%08lx\n", Hob.FirmwareVolume->BaseAddress, Hob.FirmwareVolume->Length); + } else if (Hob.Header->HobType == EFI_HOB_TYPE_CPU) { + AsciiPrint ("CPU HOB: Mem %x IO %x\n", Hob.Cpu->SizeOfMemorySpace, Hob.Cpu->SizeOfIoSpace); + } else if (Hob.Header->HobType == EFI_HOB_TYPE_MEMORY_POOL) { + AsciiPrint ("Mem Pool HOB:\n"); +/* Not in PI + } else if (Hob.Header->HobType == EFI_HOB_TYPE_CV) { + AsciiPrint ("CV HOB: %08lx:%08lx\n", Hob.CapsuleVolume->BaseAddress, Hob.CapsuleVolume->Length); + */ + } + + if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) { + break; + } + } + + return EFI_SUCCESS; +} + + +GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdHobTemplate[] = +{ + { + "hob", + "; dump HOBs", + NULL, + EblHobCmd + } +}; + + +/** + Initialize the commands in this in this file +**/ +VOID +EblInitializeHobCmd ( + VOID + ) +{ + if (FeaturePcdGet (PcdEmbeddedHobCmd)) { + EblAddCommands (mCmdHobTemplate, sizeof (mCmdHobTemplate)/sizeof (EBL_COMMAND_TABLE)); + } +} + diff --git a/EmbeddedPkg/Ebl/HwDebug.c b/EmbeddedPkg/Ebl/HwDebug.c new file mode 100644 index 0000000000..6ffbaf1170 --- /dev/null +++ b/EmbeddedPkg/Ebl/HwDebug.c @@ -0,0 +1,342 @@ +/** @file + Basic command line parser for EBL (Embedded Boot Loader) + + Copyright (c) 2007, Intel Corporation
+ Portions copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + Module Name: HwDebug.c + + Commands useful for debugging hardware. + +**/ + +#include "Ebl.h" + + +/** + Dump memory + + Argv[0] - "md" + Argv[1] - Hex Address to dump + Argv[2] - Number of hex bytes to dump (0x20 is default) + Argv[3] - [1|2|4|8] byte width of the dump + + md 0x123445678 50 4 ; Dump 0x50 4 byte quantities starting at 0x123445678 + md 0x123445678 40 ; Dump 0x40 1 byte quantities starting at 0x123445678 + md 0x123445678 ; Dump 0x20 1 byte quantities starting at 0x123445678 + + @param Argc Number of command arguments in Argv + @param Argv Array of strings that represent the parsed command line. + Argv[0] is the comamnd name + + @return EFI_SUCCESS + +**/ +EFI_STATUS +EblMdCmd ( + IN UINTN Argc, + IN CHAR8 **Argv + ) +{ + STATIC UINT8 *Address = NULL; + STATIC UINTN Length = 0x20; + STATIC UINTN Width = 1; + + switch (Argc) + { + case 4: + Width = AsciiStrHexToUintn(Argv[3]); + case 3: + Length = AsciiStrHexToUintn(Argv[2]); + case 2: + Address = (UINT8 *)AsciiStrHexToUintn(Argv[1]); + default: + break; + } + + OutputData(Address, Length, Width, (UINTN)Address); + + Address += Length; + + return EFI_SUCCESS; +} + + +/** + Fill Memory with data + + Argv[0] - "mfill" + Argv[1] - Hex Address to fill + Argv[2] - Data to write (0x00 is default) + Argv[3] - Number of units to dump. + Argv[4] - [1|2|4|8] byte width of the dump + + mf 0x123445678 aa 1 100 ; Start at 0x123445678 and write aa (1 byte) to the next 100 bytes + mf 0x123445678 aa 4 100 ; Start at 0x123445678 and write aa (4 byte) to the next 400 bytes + mf 0x123445678 aa ; Start at 0x123445678 and write aa (4 byte) to the next 1 byte + mf 0x123445678 ; Start at 0x123445678 and write 00 (4 byte) to the next 1 byte + + @param Argc Number of command arguments in Argv + @param Argv Array of strings that represent the parsed command line. + Argv[0] is the comamnd name + + @return EFI_SUCCESS + +**/ +EFI_STATUS +EblMfillCmd ( + IN UINTN Argc, + IN CHAR8 **Argv + ) +{ + UINTN Address; + UINTN EndAddress; + UINT32 Data; + UINTN Length; + UINTN Width; + + if (Argc < 2) { + return EFI_INVALID_PARAMETER; + } + + Address = AsciiStrHexToUintn (Argv[1]); + Data = (Argc > 2) ? (UINT32)AsciiStrHexToUintn (Argv[2]) : 0; + Width = (Argc > 3) ? AsciiStrHexToUintn (Argv[3]) : 4; + Length = (Argc > 4) ? AsciiStrHexToUintn (Argv[4]) : 1; + + for (EndAddress = Address + (Length * Width); Address < EndAddress; Address += Width) { + if (Width == 4) { + MmioWrite32 (Address, Data); + } else if (Width == 2) { + MmioWrite32 (Address, (UINT16)Data); + } else { + MmioWrite32 (Address, (UINT8)Data); + } + } + + return EFI_SUCCESS; +} + + +// +// Strings for PCI Class code [2] +// +CHAR8 *gPciDevClass[] = { + "Old Device ", + "Mass storage ", + "Network ", + "Display ", + "Multimedia ", + "Memory controller ", + "Bridge device ", + "simple communications ", + "base system peripherals", + "Input devices ", + "Docking stations ", + "Processors ", + "serial bus ", +}; + + +CHAR8 *gPciSerialClassCodes[] = { + "Mass storage ", + "Firewire ", + "ACCESS bus ", + "SSA ", + "USB " +}; + + +/** + PCI Dump + + Argv[0] - "pci" + Argv[1] - bus + Argv[2] - dev + Argv[3] - func + + @param Argc Number of command arguments in Argv + @param Argv Array of strings that represent the parsed command line. + Argv[0] is the comamnd name + + @return EFI_SUCCESS + +**/ +EFI_STATUS +EblPciCmd ( + IN UINTN Argc, + IN CHAR8 **Argv + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *Pci; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN Seg; + UINTN Bus; + UINTN Dev; + UINTN Func; + UINTN BusArg; + UINTN DevArg; + UINTN FuncArg; + UINTN Index; + UINTN Count; + PCI_TYPE_GENERIC PciHeader; + PCI_TYPE_GENERIC *Header; + PCI_BRIDGE_CONTROL_REGISTER *Bridge; + PCI_DEVICE_HEADER_TYPE_REGION *Device; + PCI_DEVICE_INDEPENDENT_REGION *Hdr; + CHAR8 *Str; + UINTN ThisBus; + + + BusArg = (Argc > 1) ? AsciiStrDecimalToUintn (Argv[1]) : 0; + DevArg = (Argc > 2) ? AsciiStrDecimalToUintn (Argv[2]) : 0; + FuncArg = (Argc > 3) ? AsciiStrDecimalToUintn (Argv[3]) : 0; + + Header = &PciHeader; + + Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiPciIoProtocolGuid, NULL, &HandleCount, &HandleBuffer); + if (EFI_ERROR (Status)) { + AsciiPrint ("No PCI devices found in the system\n"); + return EFI_SUCCESS; + } + + if (Argc == 1) { + // Dump all PCI devices + AsciiPrint ("BusDevFun VendorId DeviceId Device Class Sub-Class\n"); + AsciiPrint ("_____________________________________________________________"); + for (ThisBus = 0; ThisBus <= PCI_MAX_BUS; ThisBus++) { + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID **)&Pci); + if (!EFI_ERROR (Status)) { + Pci->GetLocation (Pci, &Seg, &Bus, &Dev, &Func); + if (ThisBus != Bus) { + continue; + } + AsciiPrint ("\n%03d.%02d.%02d", Bus, Dev, Func); + Status = Pci->Pci.Read (Pci, EfiPciIoWidthUint32, 0, sizeof (PciHeader)/sizeof (UINT32), &PciHeader); + if (!EFI_ERROR (Status)) { + Hdr = &PciHeader.Bridge.Hdr; + + if (Hdr->ClassCode[2] < sizeof (gPciDevClass)/sizeof (VOID *)) { + Str = gPciDevClass[Hdr->ClassCode[2]]; + if (Hdr->ClassCode[2] == PCI_CLASS_SERIAL) { + if (Hdr->ClassCode[1] < sizeof (gPciSerialClassCodes)/sizeof (VOID *)) { + // print out Firewire or USB inplace of Serial Bus controllers + Str = gPciSerialClassCodes[Hdr->ClassCode[1]]; + } + } + } else { + Str = "Unknown device "; + } + AsciiPrint (" 0x%04x 0x%04x %a 0x%02x", Hdr->VendorId, Hdr->DeviceId, Str, Hdr->ClassCode[1]); + } + if (Seg != 0) { + // Only print Segment if it is non zero. If you only have one PCI segment it is + // redundent to print it out + AsciiPrint (" Seg:%d", Seg); + } + } + } + } + AsciiPrint ("\n"); + } else { + // Dump specific PCI device + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID **)&Pci); + if (!EFI_ERROR (Status)) { + Pci->GetLocation (Pci, &Seg, &Bus, &Dev, &Func); + if ((Bus == BusArg) && (Dev == DevArg) && (Func == FuncArg)) { + // Only print Segment if it is non zero. If you only have one PCI segment it is + // redundent to print it out + if (Seg != 0) { + AsciiPrint ("Seg:%d ", Seg); + } + AsciiPrint ("Bus:%d Dev:%d Func:%d ", Bus, Dev, Func); + + Status = Pci->Pci.Read (Pci, EfiPciIoWidthUint32, 0, sizeof (PciHeader)/sizeof (UINT32), Header); + if (!EFI_ERROR (Status)) { + Hdr = &PciHeader.Bridge.Hdr; + if (IS_PCI_BRIDGE (&PciHeader.Bridge)) { + Bridge = &PciHeader.Bridge.Bridge; + AsciiPrint ( + "PCI Bridge. Bus Primary %d Secondary %d Subordinate %d\n", + Bridge->PrimaryBus, Bridge->SecondaryBus, Bridge->SubordinateBus + ); + AsciiPrint (" Bar 0: 0x%08x Bar 1: 0x%08x\n", Bridge->Bar[0], Bridge->Bar[1]); + } else { + Device = &PciHeader.Device.Device; + AsciiPrint ( + "VendorId: 0x%04x DeviceId: 0x%04x SubSusVendorId: 0x%04x SubSysDeviceId: 0x%04x\n", + Hdr->VendorId, Hdr->DeviceId, Device->SubsystemVendorID, Device->SubsystemID + ); + AsciiPrint (" Class Code: 0x%02x 0x%02x 0x%02x\n", Hdr->ClassCode[2], Hdr->ClassCode[1], Hdr->ClassCode[0]); + for (Count = 0; Count < 6; Count++) { + AsciiPrint (" Bar %d: 0x%08x\n", Count, Device->Bar[Count]); + } + } + } + + AsciiPrint ("\n"); + break; + } + } + } + } + + FreePool (HandleBuffer); + return EFI_SUCCESS; +} + + +GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdPciDebugTemplate[] = { + "pci", + " [bus] [dev] [func]; Dump PCI", + NULL, + EblPciCmd +}; + + +GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdHwDebugTemplate[] = +{ + { + "md", + " [Addr] [Len] [1|2|4]; Memory Dump from Addr Len bytes", + NULL, + EblMdCmd + }, + { + "mfill", + " Addr Len [data] [1|2|4]; Memory Fill Addr Len*(1|2|4) bytes of data(0)", + NULL, + EblMfillCmd + }, +}; + + + +/** + Initialize the commands in this in this file +**/ +VOID +EblInitializemdHwDebugCmds ( + VOID + ) +{ + if (FeaturePcdGet (PcdEmbeddedHwDebugCmd)) { + EblAddCommands (mCmdHwDebugTemplate, sizeof (mCmdHwDebugTemplate)/sizeof (EBL_COMMAND_TABLE)); + } + if (FeaturePcdGet (PcdEmbeddedPciDebugCmd)) { + EblAddCommands (mCmdPciDebugTemplate, sizeof (mCmdPciDebugTemplate)/sizeof (EBL_COMMAND_TABLE)); + } +} + diff --git a/EmbeddedPkg/Ebl/HwIoDebug.c b/EmbeddedPkg/Ebl/HwIoDebug.c new file mode 100644 index 0000000000..2d23e7c936 --- /dev/null +++ b/EmbeddedPkg/Ebl/HwIoDebug.c @@ -0,0 +1,153 @@ +/** @file + Hardware IO based debug commands + + Copyright (c) 2007, Intel Corporation
+ Portions copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + Commands useful for debugging hardware. IO commands seperated out as not all + processor architectures support the IO command. + +**/ + +#include "Ebl.h" + + + +/** + Read from IO space + + Argv[0] - "ioread" + Argv[1] - Hex IO address + Argv[2] - IO Width [1|2|4] with a default of 1 + + ior 0x3f8 4 ;Do a 32-bit IO Read from 0x3f8 + ior 0x3f8 1 ;Do a 8-bit IO Read from 0x3f8 + + @param Argc Number of command arguments in Argv + @param Argv Array of strings that represent the parsed command line. + Argv[0] is the comamnd name + + @return EFI_SUCCESS + +**/ +EFI_STATUS +EblIoReadCmd ( + IN UINTN Argc, + IN CHAR8 **Argv + ) +{ + UINTN Width; + UINTN Port; + UINTN Data; + + if (Argc < 2) { + return EFI_INVALID_PARAMETER; + } + + Port = AsciiStrHexToUintn (Argv[1]); + Width = (Argc > 2) ? AsciiStrHexToUintn (Argv[2]) : 1; + + if (Width == 1) { + Data = IoRead8 (Port); + } else if (Width == 2) { + Data = IoRead16 (Port); + } else if (Width == 4) { + Data = IoRead32 (Port); + } else { + return EFI_INVALID_PARAMETER; + } + + AsciiPrint ("0x%04x = 0x%x", Port, Data); + + return EFI_SUCCESS; +} + + +/** + Write to IO space + + Argv[0] - "iowrite" + Argv[1] - Hex IO address + Argv[2] - Hex data to write + Argv[3] - IO Width [1|2|4] with a default of 1 + + iow 0x3f8 af 4 ;Do a 32-bit IO write of af to 0x3f8 + iow 0x3f8 af ;Do an 8-bit IO write of af to 0x3f8 + + @param Argc Number of command arguments in Argv + @param Argv Array of strings that represent the parsed command line. + Argv[0] is the comamnd name + + @return EFI_SUCCESS + +**/ +EFI_STATUS +EblIoWriteCmd ( + IN UINTN Argc, + IN CHAR8 **Argv + ) +{ + UINTN Width; + UINTN Port; + UINTN Data; + + if (Argc < 3) { + return EFI_INVALID_PARAMETER; + } + + Port = AsciiStrHexToUintn (Argv[1]); + Data = AsciiStrHexToUintn (Argv[2]); + Width = (Argc > 3) ? AsciiStrHexToUintn (Argv[3]) : 1; + + if (Width == 1) { + IoWrite8 (Port, (UINT8)Data); + } else if (Width == 2) { + IoWrite16 (Port, (UINT16)Data); + } else if (Width == 4) { + IoWrite32 (Port, (UINT32)Data); + } else { + return EFI_INVALID_PARAMETER; + } + return EFI_SUCCESS; +} + + +GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdHwIoDebugTemplate[] = +{ + { + "ioread", + " Port [1|2|4]; IO read of width[1] byte(s) from Port", + NULL, + EblIoReadCmd + }, + { + "iowrite", + " Port Data [1|2|4]; IO write Data of width[1] byte(s) to Port", + NULL, + EblIoWriteCmd + } +}; + + + +/** + Initialize the commands in this in this file +**/ +VOID +EblInitializemdHwIoDebugCmds ( + VOID + ) +{ + if (FeaturePcdGet (PcdEmbeddedIoEnable)) { + EblAddCommands (mCmdHwIoDebugTemplate, sizeof (mCmdHwIoDebugTemplate)/sizeof (EBL_COMMAND_TABLE)); + } +} + diff --git a/EmbeddedPkg/Ebl/Main.c b/EmbeddedPkg/Ebl/Main.c new file mode 100644 index 0000000000..5d1a37916f --- /dev/null +++ b/EmbeddedPkg/Ebl/Main.c @@ -0,0 +1,616 @@ +/** @file + Basic command line parser for EBL (Embedded Boot Loader) + + Copyright (c) 2007, Intel Corporation
+ Portions copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#include "Ebl.h" + +// Globals for command history processing +INTN mCmdHistoryEnd = -1; +INTN mCmdHistoryStart = -1; +INTN mCmdHistoryCurrent = -1; +CHAR8 mCmdHistory[MAX_CMD_HISTORY][MAX_CMD_LINE]; +CHAR8 *mCmdBlank = ""; + +// Globals to remember current screen geometry +UINTN gScreenColumns; +UINTN gScreenRows; + +// Global to turn on/off breaking commands with prompts before they scroll the screen +BOOLEAN gPageBreak = TRUE; + +VOID +RingBufferIncrement ( + IN INTN *Value + ) +{ + *Value = *Value + 1; + + if (*Value >= MAX_CMD_HISTORY) { + *Value = 0; + } +} + +VOID +RingBufferDecrement ( + IN INTN *Value + ) +{ + *Value = *Value - 1; + + if (*Value < 0) { + *Value = MAX_CMD_HISTORY - 1; + } +} + +/** + Save this command in the circular history buffer. Older commands are + overwritten with newer commands. + + @param Cmd Command line to archive the history of. + + @return None + +**/ +VOID +SetCmdHistory ( + IN CHAR8 *Cmd + ) +{ + // Don't bother adding empty commands to the list + if (AsciiStrLen(Cmd) != 0) { + + // First entry + if (mCmdHistoryStart == -1) { + mCmdHistoryStart = 0; + mCmdHistoryEnd = 0; + } else { + // Record the new command at the next index + RingBufferIncrement(&mCmdHistoryStart); + + // If the next index runs into the end index, shuffle end back by one + if (mCmdHistoryStart == mCmdHistoryEnd) { + RingBufferIncrement(&mCmdHistoryEnd); + } + } + + // Copy the new command line into the ring buffer + AsciiStrnCpy(&mCmdHistory[mCmdHistoryStart][0], Cmd, MAX_CMD_LINE); + } + + // Reset the command history for the next up arrow press + mCmdHistoryCurrent = mCmdHistoryStart; +} + + +/** + Retreave data from the Command History buffer. Direction maps into up arrow + an down arrow on the command line + + @param Direction Command forward or back + + @return The Command history based on the Direction + +**/ +CHAR8 * +GetCmdHistory ( + IN UINT16 Direction + ) +{ + CHAR8 *HistoricalCommand = NULL; + + // No history yet? + if (mCmdHistoryCurrent == -1) { + HistoricalCommand = mCmdBlank; + goto Exit; + } + + if (Direction == SCAN_UP) { + HistoricalCommand = &mCmdHistory[mCmdHistoryCurrent][0]; + + // if we just echoed the last command, hang out there, don't wrap around + if (mCmdHistoryCurrent == mCmdHistoryEnd) { + goto Exit; + } + + // otherwise, back up by one + RingBufferDecrement(&mCmdHistoryCurrent); + + } else if (Direction == SCAN_DOWN) { + + // if we last echoed the start command, put a blank prompt out + if (mCmdHistoryCurrent == mCmdHistoryStart) { + HistoricalCommand = mCmdBlank; + goto Exit; + } + + // otherwise increment the current pointer and return that command + RingBufferIncrement(&mCmdHistoryCurrent); + RingBufferIncrement(&mCmdHistoryCurrent); + + HistoricalCommand = &mCmdHistory[mCmdHistoryCurrent][0]; + RingBufferDecrement(&mCmdHistoryCurrent); + } + +Exit: + return HistoricalCommand; +} + + +/** + Parse the CmdLine and break it up into Argc (arg count) and Argv (array of + pointers to each argument). The Cmd buffer is altered and seperators are + converted to string terminators. This allows Argv to point into CmdLine. + A CmdLine can support multiple commands. The next command in the command line + is returned if it exists. + + @param CmdLine String to parse for a set of commands + @param Argc Returns the number of arguments in the CmdLine current command + @param Argv Argc pointers to each string in CmdLine + + @return Next Command in the command line or NULL if non exists +**/ +CHAR8 * +ParseArguments ( + IN CHAR8 *CmdLine, + OUT UINTN *Argc, + OUT CHAR8 **Argv + ) +{ + UINTN Arg; + CHAR8 *Char; + BOOLEAN LookingForArg; + BOOLEAN InQuote; + + *Argc = 0; + if (AsciiStrLen (CmdLine) == 0) { + return NULL; + } + + // Walk a single command line. A CMD_SEPERATOR allows mult commands on a single line + InQuote = FALSE; + LookingForArg = TRUE; + for (Char = CmdLine, Arg = 0; *Char != '\0'; Char++) { + if (!InQuote && *Char == CMD_SEPERATOR) { + break; + } + + // Perform any text coversion here + if (*Char == '\t') { + // TAB to space + *Char = ' '; + } + + if (LookingForArg) { + // Look for the beging of an Argv[] entry + if (*Char == '"') { + Argv[Arg++] = ++Char; + LookingForArg = FALSE; + InQuote = TRUE; + } else if (*Char != ' ') { + Argv[Arg++] = Char; + LookingForArg = FALSE; + } + } else { + // Looking for the terminator of an Argv[] entry + if ((InQuote && (*Char == '"')) || (!InQuote && (*Char == ' '))) { + *Char = '\0'; + LookingForArg = TRUE; + } + } + } + + *Argc = Arg; + + if (*Char == CMD_SEPERATOR) { + // Replace the command delimeter with null and return pointer to next command line + *Char = '\0'; + return ++Char; + } + + return NULL; +} + + +/** + Return a keypress or optionally timeout if a timeout value was passed in. + An optional callback funciton is called evey second when waiting for a + timeout. + + @param Key EFI Key information returned + @param TimeoutInSec Number of seconds to wait to timeout + @param CallBack Callback called every second during the timeout wait + + @return EFI_SUCCESS Key was returned + @return EFI_TIMEOUT If the TimoutInSec expired + +**/ +EFI_STATUS +EblGetCharKey ( + IN OUT EFI_INPUT_KEY *Key, + IN UINTN TimeoutInSec, + IN EBL_GET_CHAR_CALL_BACK CallBack OPTIONAL + ) +{ + EFI_STATUS Status; + UINTN WaitCount; + UINTN WaitIndex; + EFI_EVENT WaitList[2]; + + WaitCount = 1; + WaitList[0] = gST->ConIn->WaitForKey; + if (TimeoutInSec != 0) { + // Create a time event for 1 sec duration if we have a timeout + gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &WaitList[1]); + gBS->SetTimer (WaitList[1], TimerPeriodic, EFI_SET_TIMER_TO_SECOND); + WaitCount++; + } + + for (;;) { + Status = gBS->WaitForEvent (WaitCount, WaitList, &WaitIndex); + ASSERT_EFI_ERROR (Status); + + switch (WaitIndex) { + case 0: + // Key event signaled + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, Key); + if (!EFI_ERROR (Status)) { + if (WaitCount == 2) { + gBS->CloseEvent (WaitList[1]); + } + return EFI_SUCCESS; + } + break; + + case 1: + // Periodic 1 sec timer signaled + TimeoutInSec--; + if (CallBack != NULL) { + // Call the users callback function if registered + CallBack (TimeoutInSec); + } + if (TimeoutInSec == 0) { + gBS->CloseEvent (WaitList[1]); + return EFI_TIMEOUT; + } + break; + default: + ASSERT (FALSE); + } + } +} + + +/** + This routine is used prevent command output data from scrolling off the end + of the screen. The global gPageBreak is used to turn on or off this feature. + If the CurrentRow is near the end of the screen pause and print out a prompt + If the use hits Q to quit return TRUE else for any other key return FALSE. + PrefixNewline is used to figure out if a newline is needed before the prompt + string. This depends on the last print done before calling this function. + CurrentRow is updated by one on a call or set back to zero if a prompt is + needed. + + @param CurrentRow Used to figure out if its the end of the page and updated + @param PrefixNewline Did previous print issue a newline + + @return TRUE if Q was hit to quit, FALSE in all other cases. + +**/ +BOOLEAN +EblAnyKeyToContinueQtoQuit ( + IN UINTN *CurrentRow, + IN BOOLEAN PrefixNewline + ) +{ + EFI_INPUT_KEY InputKey; + + if (!gPageBreak) { + // global disable for this feature + return FALSE; + } + + if (*CurrentRow >= (gScreenRows - 2)) { + if (PrefixNewline) { + AsciiPrint ("\n"); + } + AsciiPrint ("Any key to continue (Q to quit): "); + EblGetCharKey (&InputKey, 0, NULL); + AsciiPrint ("\n"); + + // Time to promt to stop the screen. We have to leave space for the prompt string + *CurrentRow = 0; + if (InputKey.UnicodeChar == 'Q' || InputKey.UnicodeChar == 'q') { + return TRUE; + } + } else { + *CurrentRow += 1; + } + + return FALSE; +} + + +/** + Set the text color of the EFI Console. If a zero is passed in reset to + default text/background color. + + @param Attribute For text and background color + +**/ +VOID +EblSetTextColor ( + UINTN Attribute + ) +{ + if (Attribute == 0) { + // Set the text color back to default + Attribute = (UINTN)PcdGet32 (PcdEmbeddedDefaultTextColor); + } + + gST->ConOut->SetAttribute (gST->ConOut, Attribute); +} + + +/** + Collect the keyboard input for a cmd line. Carage Return, New Line, or ESC + terminates the command line. You can edit the command line via left arrow, + delete and backspace and they all back up and erase the command line. + No edit of commnad line is possible without deletion at this time! + The up arrow and down arrow fill Cmd with information from the history + buffer. + + @param Cmd Command line to return + @param CmdMaxSize Maximum size of Cmd + + @return The Status of EblGetCharKey() + +**/ +EFI_STATUS +GetCmd ( + IN OUT CHAR8 *Cmd, + IN UINTN CmdMaxSize + ) +{ + EFI_STATUS Status; + UINTN Index; + UINTN Index2; + CHAR8 Char; + CHAR8 *History; + EFI_INPUT_KEY Key; + + for (Index = 0; Index < CmdMaxSize - 1;) { + Status = EblGetCharKey (&Key, 0, NULL); + if (EFI_ERROR (Status)) { + Cmd[Index] = '\0'; + AsciiPrint ("\n"); + return Status; + } + + Char = (CHAR8)Key.UnicodeChar; + if ((Char == '\n') || (Char == '\r') || (Char == 0x7f)) { + Cmd[Index] = '\0'; + if (FixedPcdGetBool(PcdEmbeddedShellCharacterEcho) == TRUE) { + AsciiPrint ("\n\r"); + } + return EFI_SUCCESS; + } else if ((Char == '\b') || (Key.ScanCode == SCAN_LEFT) || (Key.ScanCode == SCAN_DELETE)){ + if (Index != 0) { + Index--; + // + // Update the display + // + AsciiPrint ("\b \b"); + } + } else if ((Key.ScanCode == SCAN_UP) || Key.ScanCode == SCAN_DOWN) { + History = GetCmdHistory (Key.ScanCode); + // + // Clear display line + // + for (Index2 = 0; Index2 < Index; Index2++) { + AsciiPrint ("\b \b"); + } + AsciiPrint (History); + Index = AsciiStrLen (History); + AsciiStrnCpy (Cmd, History, CmdMaxSize); + } else { + Cmd[Index++] = Char; + if (FixedPcdGetBool(PcdEmbeddedShellCharacterEcho) == TRUE) { + AsciiPrint ("%c", Char); + } + } + } + + return EFI_SUCCESS; +} + + +/** + Print the boot up banner for the EBL. +**/ +VOID +EblPrintStartupBanner ( + VOID + ) +{ + AsciiPrint ("Embedded Boot Loader ("); + EblSetTextColor (EFI_YELLOW); + AsciiPrint ("EBL"); + EblSetTextColor (0); + AsciiPrint (") prototype. Built at %a on %a\n",__TIME__, __DATE__); + AsciiPrint ("THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN 'AS IS' BASIS,\nWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\n"); + AsciiPrint ("Please send feedback to dev@edk2.tianocore.org\n"); +} + + +/** + Print the prompt for the EBL. +**/ +VOID +EblPrompt ( + VOID + ) +{ + EblSetTextColor (EFI_YELLOW); + AsciiPrint ((CHAR8 *)PcdGetPtr (PcdEmbeddedPrompt)); + EblSetTextColor (0); + AsciiPrint ("%a", ">"); +} + + + +/** + Parse a command line and execute the commands. The ; seperator allows + multiple commands for each command line. Stop processing if one of the + commands returns an error. + + @param CmdLine Command Line to process. + @param MaxCmdLineSize MaxSize of the Command line + + @return EFI status of the Command + +**/ +EFI_STATUS +ProcessCmdLine ( + IN CHAR8 *CmdLine, + IN UINTN MaxCmdLineSize + ) +{ + EFI_STATUS Status; + EBL_COMMAND_TABLE *Cmd; + CHAR8 *Ptr; + UINTN Argc; + CHAR8 *Argv[MAX_ARGS]; + + // Parse the command line. The loop processes commands seperated by ; + for (Ptr = CmdLine, Status = EFI_SUCCESS; Ptr != NULL;) { + Ptr = ParseArguments (Ptr, &Argc, Argv); + if (Argc != 0) { + Cmd = EblGetCommand (Argv[0]); + if (Cmd != NULL) { + // Execute the Command! + Status = Cmd->Command (Argc, Argv); + if (Status == EFI_ABORTED) { + // exit command so lets exit + break; + } else if (Status == EFI_TIMEOUT) { + // pause command got imput so don't process any more cmd on this cmd line + break; + } else if (EFI_ERROR (Status)) { + AsciiPrint ("%a returned %r error\n", Cmd->Name, Status); + // if any command fails stop processing CmdLine + break; + } + } + } + } + + return Status; +} + + + +/** + Embedded Boot Loader (EBL) - A simple EFI command line application for embedded + devices. PcdEmbeddedAutomaticBootCommand is a complied in commnad line that + gets executed automatically. The ; seperator allows multiple commands + for each command line. + + @param ImageHandle EFI ImageHandle for this application. + @param SystemTable EFI system table + + @return EFI status of the applicaiton + +**/ +EFI_STATUS +EFIAPI +EdkBootLoaderEntry ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + CHAR8 CmdLine[MAX_CMD_LINE]; + CHAR16 *CommandLineVariable = NULL; + CHAR16 *CommandLineVariableName = L"default-cmdline"; + UINTN CommandLineVariableSize = 0; + EFI_GUID VendorGuid; + + // Initialize tables of commnads + EblInitializeCmdTable (); + EblInitializeDeviceCmd (); + EblInitializemdHwDebugCmds (); + EblInitializemdHwIoDebugCmds (); + EblInitializeDirCmd (); + EblInitializeHobCmd (); + EblInitializeScriptCmd (); + EblInitializeExternalCmd (); + EblInitializeNetworkCmd(); + + if (FeaturePcdGet (PcdEmbeddedMacBoot)) { + // A MAC will boot in graphics mode, so turn it back to text here + // This protocol was removed from edk2. It is only an edk thing. We need to make our own copy. + // DisableQuietBoot (); + + // Enable the biggest output screen size possible + gST->ConOut->SetMode (gST->ConOut, (UINTN)gST->ConOut->Mode->MaxMode - 1); + + // Disable the 5 minute EFI watchdog time so we don't get automatically reset + gBS->SetWatchdogTimer (0, 0, 0, NULL); + } + + // Save current screen mode + gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &gScreenColumns, &gScreenRows); + + EblPrintStartupBanner (); + + // Parse command line and handle commands seperated by ; + // The loop prints the prompt gets user input and saves history + + // Look for a variable with a default command line, otherwise use the Pcd + ZeroMem(&VendorGuid, sizeof(EFI_GUID)); + + Status = gRT->GetVariable(CommandLineVariableName, &VendorGuid, NULL, &CommandLineVariableSize, CommandLineVariable); + if (Status == EFI_BUFFER_TOO_SMALL) { + CommandLineVariable = AllocatePool(CommandLineVariableSize); + + Status = gRT->GetVariable(CommandLineVariableName, &VendorGuid, NULL, &CommandLineVariableSize, CommandLineVariable); + if (!EFI_ERROR(Status)) { + UnicodeStrToAsciiStr(CommandLineVariable, CmdLine); + } + + FreePool(CommandLineVariable); + } + + if (EFI_ERROR(Status)) { + AsciiStrCpy (CmdLine, (CHAR8 *)PcdGetPtr (PcdEmbeddedAutomaticBootCommand)); + } + + for (;;) { + Status = ProcessCmdLine (CmdLine, MAX_CMD_LINE); + if (Status == EFI_ABORTED) { + // if a command returns EFI_ABORTED then exit the EBL + EblShutdownExternalCmdTable (); + return EFI_SUCCESS; + } + + // get the command line from the user + EblPrompt (); + GetCmd (CmdLine, MAX_CMD_LINE); + SetCmdHistory (CmdLine); + } +} + + diff --git a/EmbeddedPkg/Ebl/Network.c b/EmbeddedPkg/Ebl/Network.c new file mode 100644 index 0000000000..c566dda49a --- /dev/null +++ b/EmbeddedPkg/Ebl/Network.c @@ -0,0 +1,104 @@ +/** @file + EBL commands for Network Devices + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "Ebl.h" + +EFI_STATUS +ParseIp ( + IN CHAR8 *String, + OUT EFI_IP_ADDRESS *Address + ) +{ + Address->v4.Addr[0] = AsciiStrDecimalToUintn(String); + String = AsciiStrStr(String, ".") + 1; + Address->v4.Addr[1] = AsciiStrDecimalToUintn(String); + String = AsciiStrStr(String, ".") + 1; + Address->v4.Addr[2] = AsciiStrDecimalToUintn(String); + String = AsciiStrStr(String, ".") + 1; + Address->v4.Addr[3] = AsciiStrDecimalToUintn(String); + + return EFI_SUCCESS; +} + +EFI_STATUS +EblIpCmd ( + IN UINTN Argc, + IN CHAR8 **Argv + ) +{ + EFI_STATUS Status = EFI_INVALID_PARAMETER; + EFI_MAC_ADDRESS Mac; + EFI_IP_ADDRESS Ip; + + if (Argc == 1) { + // Get current IP/MAC + + // Get current MAC address + Status = EblGetCurrentMacAddress (&Mac); + if (EFI_ERROR (Status)) { + goto Exit; + } + + AsciiPrint ("MAC Address: %02x:%02x:%02x:%02x:%02x:%02x\n", Mac.Addr[0], Mac.Addr[1], Mac.Addr[2], Mac.Addr[3], Mac.Addr[4], Mac.Addr[5]); + + // Get current IP address + Status = EblGetCurrentIpAddress (&Ip); + if (EFI_ERROR(Status)) { + AsciiPrint("IP Address is not configured.\n"); + Status = EFI_SUCCESS; + goto Exit; + } + + AsciiPrint("IP Address: %d.%d.%d.%d\n", Ip.v4.Addr[0], Ip.v4.Addr[1],Ip.v4.Addr[2], Ip.v4.Addr[3]); + + } else if ((Argv[1][0] == 'r') && (Argc == 2)) { + // Get new address via dhcp + Status = EblPerformDHCP (TRUE); + } else if ((Argv[1][0] == 's') && (Argc == 3)) { + // Set static IP + Status = ParseIp (Argv[2], &Ip); + if (EFI_ERROR (Status)) { + goto Exit; + } + + Status = EblSetStationIp (&Ip, NULL); + } + +Exit: + return Status; +} + +GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdNetworkTemplate[] = +{ + { + "ip", + " ; print current ip address\n\r [r]; request DHCP address\n\r [s] ipaddr; set static IP address", + NULL, + EblIpCmd + } +}; + + +/** + Initialize the commands in this in this file +**/ +VOID +EblInitializeNetworkCmd ( + VOID + ) +{ + EblAddCommands (mCmdNetworkTemplate, sizeof (mCmdNetworkTemplate)/sizeof (EBL_COMMAND_TABLE)); +} + diff --git a/EmbeddedPkg/Ebl/Script.c b/EmbeddedPkg/Ebl/Script.c new file mode 100644 index 0000000000..2229005d1c --- /dev/null +++ b/EmbeddedPkg/Ebl/Script.c @@ -0,0 +1,126 @@ +/** @file + Script command allows the execution of commands from a text file + + Copyright (c) 2007, Intel Corporation
+ Portions copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + Module Name: EfiDevice.c + +**/ + +#include "Ebl.h" + + +/** + Execute the passed in file like a series of commands. The ; can be used on + a single line to indicate multiple commands per line. The Ascii text file + can contain any number of lines. The following line termination forms are + supported: + LF : Unix, Mac OS X*, BeOS + CR+LF: MS-DOS*, Microsoft Windows* + CR : Commodore, Apple II, and realy Mac OS + LF+CR: for simplicity and completeness + + Argv[0] - "script" + Argv[1] - Device Name:path for the file to load + + script fv1:\script.txt + + @param Argc Number of command arguments in Argv + @param Argv Array of strings that represent the parsed command line. + Argv[0] is the comamnd name + + @return EFI_SUCCESS + +**/ +EFI_STATUS +EblScriptCmd ( + IN UINTN Argc, + IN CHAR8 **Argv + ) +{ + EFI_STATUS Status; + EFI_OPEN_FILE *File; + VOID *Address; + UINTN Size; + CHAR8 *Ptr; + CHAR8 *ScanPtr; + UINTN CmdLineSize; + + + + if (Argc < 2) { + // file name required + return EFI_SUCCESS; + } + + File = EfiOpen (Argv[1], EFI_FILE_MODE_READ, 0); + if (File == NULL) { + AsciiPrint (" %a is not a valid path\n", Argv[1]); + return EFI_SUCCESS; + } + + Status = EfiReadAllocatePool (File, &Address, &Size); + if (!EFI_ERROR (Status)) { + // Loop through each line in the text file + for (Ptr = (CHAR8 *)Address; (Ptr < (((CHAR8 *)Address) + Size)) && !EFI_ERROR (Status); Ptr += CmdLineSize) { + for (CmdLineSize = 0, ScanPtr = Ptr; ; CmdLineSize++, ScanPtr++) { + // look for the end of the line + if ((*ScanPtr == EBL_CR) || (*ScanPtr == EBL_LF)) { + // convert to NULL as this is what input routine would do + *ScanPtr = 0; + if ((*(ScanPtr + 1) == EBL_CR) || (*(ScanPtr + 1) == EBL_LF)) { + // if its a set get the 2nd EOL char + CmdLineSize++; + *(ScanPtr + 1) = 0; + } + CmdLineSize++; + break; + } + + } + + Status = ProcessCmdLine (Ptr, CmdLineSize); + } + + FreePool (Address); + } + + EfiClose (File); + return Status; +} + + + +GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mScriptTemplate[] = { + { + "script", + " device:path; load an ascii file and execute it like commands", + NULL, + EblScriptCmd + } +}; + + +/** + Initialize the commands in this in this file +**/ + +VOID +EblInitializeScriptCmd ( + VOID + ) +{ + if (FeaturePcdGet (PcdEmbeddedScriptCmd)) { + EblAddCommands (mScriptTemplate, sizeof (mScriptTemplate)/sizeof (EBL_COMMAND_TABLE)); + } +} + diff --git a/EmbeddedPkg/EblExternCmd/EntryPointGlue.c b/EmbeddedPkg/EblExternCmd/EntryPointGlue.c new file mode 100644 index 0000000000..1e26fb5159 --- /dev/null +++ b/EmbeddedPkg/EblExternCmd/EntryPointGlue.c @@ -0,0 +1,152 @@ +/** @file + Glue code that contains the EFI entry point and converts it to an EBL + ASCII Argc, Argv sytle entry point + + + Copyright (c) 2007, Intel Corporation
+ Portions copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#define CMD_SEPERATOR ';' +#define MAX_ARGS 32 + +EFI_STATUS +EblMain ( + IN UINTN Argc, + IN CHAR8 **Argv + ); + + +/// +/// EdkExternCmdEntry() & ParseArguments() convert the standard EFI entry point +/// into Argc, Argv form that calls EblMain(). +/// + + +/** + Parse the CmdLine and break it up into Argc (arg count) and Argv (array of + pointers to each argument). The Cmd buffer is altered and seperators are + converted to string terminators. This allows Argv to point into CmdLine. + A CmdLine can support multiple commands. The next command in the command line + is returned if it exists. + + @param CmdLine String to parse for a set of commands + @param CmdLineSize Size of CmdLine in bytes + @param Argc Returns the number of arguments in the CmdLine current command + @param Argv Argc pointers to each string in CmdLine + + @return Next Command in the command line or NULL if non exists +**/ +VOID +ParseArguments ( + IN CHAR8 *CmdLine, + IN UINTN CmdLineSize, + OUT UINTN *Argc, + OUT CHAR8 **Argv + ) +{ + UINTN Arg; + CHAR8 *Char; + BOOLEAN LookingForArg; + BOOLEAN InQuote; + UINTN Index; + + *Argc = 0; + if ((CmdLineSize == 0) || (AsciiStrLen (CmdLine) == 0)) { + // basic error checking failed on the arguments + return; + } + + // Walk a single command line. A CMD_SEPERATOR allows mult commands on a single line + InQuote = FALSE; + LookingForArg = TRUE; + for (Char = CmdLine, Arg = 0, Index = 0; *Char != '\0' && *Char != CMD_SEPERATOR; Char++, Index++) { + // Perform any text coversion here + if (*Char == '\t') { + // TAB to space + *Char = ' '; + } + + if (LookingForArg) { + // Look for the beging of an Argv[] entry + if (*Char == '"') { + Argv[Arg++] = ++Char; + LookingForArg = FALSE; + InQuote = TRUE; + } else if (*Char != ' ') { + Argv[Arg++] = Char; + LookingForArg = FALSE; + } + } else { + // Looking for the terminator of an Argv[] entry + if ((InQuote && (*Char == '"')) || (!InQuote && (*Char == ' '))) { + *Char = '\0'; + LookingForArg = TRUE; + } + } + + if ((Arg >= MAX_ARGS) || (Index > CmdLineSize)) { + // Error check buffer and exit since it does not look valid + break; + } + } + + *Argc = Arg; + + if (*Char == CMD_SEPERATOR) { + // Replace the command delimeter with null + *Char = '\0'; + } + + return; +} + + + + +/** + Embedded Boot Loader (EBL) - A simple EFI command line application for embedded + devices. PcdEmbeddedAutomaticBootCommand is a complied in commnad line that + gets executed automatically. The ; seperator allows multiple commands + for each command line. + + @param ImageHandle EFI ImageHandle for this application. + @param SystemTable EFI system table + + @return EFI status of the applicaiton + +**/ +EFI_STATUS +EFIAPI +EdkExternCmdEntry ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_LOADED_IMAGE_PROTOCOL *ImageInfo; + UINTN Argc; + CHAR8 *Argv[MAX_ARGS]; + + Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&ImageInfo); + if (EFI_ERROR (Status)) { + Argc = 0; + } else { + // Looks like valid commands were passed in. + ParseArguments (ImageInfo->LoadOptions, ImageInfo->LoadOptionsSize, &Argc, Argv); + } + + return EblMain (Argc, Argv); +} + + diff --git a/EmbeddedPkg/EblExternCmd/Main.c b/EmbeddedPkg/EblExternCmd/Main.c new file mode 100644 index 0000000000..04f1eab600 --- /dev/null +++ b/EmbeddedPkg/EblExternCmd/Main.c @@ -0,0 +1,52 @@ +/** @file + Example of an external EBL command. It's loaded via EBL start command. + Argc and Argv are passed in via "" of the EBL command line. + + Start fs0:\EdkExternCmd.efi "Argv[0] Argv[1] 2" + + will launch this command with + Argv[0] = "Argv[0]" + Argv[1] = "Argv[2]" + Argv[2] = "3" + + Copyright (c) 2007, Intel Corporation
+ Portions copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + + +/** + Entry point with Argc, Argv. Put your code here. + + @param Argc Number of command arguments in Argv + @param Argv Array of strings that represent the parsed command line. + Argv[0] is the comamnd name + + @return EFI_SUCCESS + +**/ +EFI_STATUS +EblMain ( + IN UINTN Argc, + IN CHAR8 **Argv + ) +{ + UINTN Index; + + AsciiPrint ("Hello World\n"); + for (Index = 0; Index < Argc; Index++) { + AsciiPrint ("Argv[%d] = %a\n", Index, Argv[Index]); + } + + return EFI_SUCCESS; +} + diff --git a/EmbeddedPkg/EmbeddedMonotonicCounter/EmbeddedMonotonicCounter.c b/EmbeddedPkg/EmbeddedMonotonicCounter/EmbeddedMonotonicCounter.c new file mode 100644 index 0000000000..66ebe67a92 --- /dev/null +++ b/EmbeddedPkg/EmbeddedMonotonicCounter/EmbeddedMonotonicCounter.c @@ -0,0 +1,82 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include +#include + +#include + +UINT64 gCurrentMonotonicCount = 0; + +EFI_STATUS +EFIAPI +GetNextMonotonicCount ( + OUT UINT64 *Count + ) +{ + if (Count == NULL) { + return EFI_INVALID_PARAMETER; + } + + *Count = gCurrentMonotonicCount++; + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +GetNextHighMonotonicCount ( + OUT UINT32 *HighCount + ) +{ + if (HighCount == NULL) { + return EFI_INVALID_PARAMETER; + } + + gCurrentMonotonicCount += 0x0000000100000000ULL; + + *HighCount = RShiftU64 (gCurrentMonotonicCount, 32) & 0xFFFFFFFF; + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +MonotonicCounterDriverInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle = NULL; + + // Make sure the Monotonic Counter Architectural Protocol is not already installed in the system + ASSERT_PROTOCOL_ALREADY_INSTALLED(NULL, &gEfiMonotonicCounterArchProtocolGuid); + + // Fill in the EFI Boot Services and EFI Runtime Services Monotonic Counter Fields + gBS->GetNextMonotonicCount = GetNextMonotonicCount; + gRT->GetNextHighMonotonicCount = GetNextHighMonotonicCount; + + // Install the Monotonic Counter Architctural Protocol onto a new handle + Status = gBS->InstallMultipleProtocolInterfaces ( + &Handle, + &gEfiMonotonicCounterArchProtocolGuid, NULL, + NULL + ); + return Status; +} diff --git a/EmbeddedPkg/EmbeddedMonotonicCounter/EmbeddedMonotonicCounter.inf b/EmbeddedPkg/EmbeddedMonotonicCounter/EmbeddedMonotonicCounter.inf new file mode 100644 index 0000000000..8508ac53a3 --- /dev/null +++ b/EmbeddedPkg/EmbeddedMonotonicCounter/EmbeddedMonotonicCounter.inf @@ -0,0 +1,29 @@ +#%HEADER% +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = EmbeddedMonotonicCounter + FILE_GUID = FCABE6A7-7953-4A84-B7EC-D29E89B62E87 + MODULE_TYPE = DXE_RUNTIME_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = MonotonicCounterDriverInitialize + +[Sources.common] + EmbeddedMonotonicCounter.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + DebugLib + UefiBootServicesTableLib + UefiDriverEntryPoint + UefiRuntimeServicesTableLib + +[Protocols] + gEfiMonotonicCounterArchProtocolGuid + +[Depex] + TRUE + diff --git a/EmbeddedPkg/EmbeddedPkg.dec b/EmbeddedPkg/EmbeddedPkg.dec new file mode 100644 index 0000000000..22ee365e7b --- /dev/null +++ b/EmbeddedPkg/EmbeddedPkg.dec @@ -0,0 +1,126 @@ +#%HEADER% +#/** @file +# Framework Module Development Environment Industry Standards +# +# This Package provides headers and libraries that conform to EFI/PI Industry standards. +# Copyright (c) 2007, Intel Corporation. +# +# All rights reserved. +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License which accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/ + +[Defines] + DEC_SPECIFICATION = 0x00010005 + PACKAGE_NAME = EmbeddedPkg + PACKAGE_GUID = dea8e498-7e1b-47c1-b6fa-4bc04092587e + PACKAGE_VERSION = 0.1 + + +################################################################################ +# +# Include Section - list of Include Paths that are provided by this package. +# Comments are used for Keywords and Module Types. +# +# Supported Module Types: +# BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION +# +################################################################################ +[Includes.common] + Include # Root include for the package + +[LibraryClasses.common] + EfiFileLib|Include/Library/EfiFileLib.h + PrePiLib|Include/Library/PrePiLib.h + RealTimeClockLib|Include/Library/RealTimeClockLib.h + EfiResetSystemLib|Include/Library/EfiResetSystemLib.h + EblCmdLib|Include/Library/EblCmdLib.h + EblAddExternalCommandLib|Library/EblAddExternalCommandLib.h + EblNetworkLib|Library/EblNetworkLib.h + GdbSerialLib|Include/Library/GdbSerialLib.h + + +[Guids.common] + gEmbeddedTokenSpaceGuid = { 0xe0d8ca17, 0x4276, 0x4386, { 0xbb, 0x79, 0x48, 0xcb, 0x81, 0x3d, 0x3c, 0x4f }} + +[Protocols.common] + gHardwareInterruptProtocolGuid = { 0x2890B3EA, 0x053D, 0x1643, { 0xAD, 0x0C, 0xD6, 0x48, 0x08, 0xDA, 0x3F, 0xF1 } } + gEfiDebugSupportPeriodicCallbackProtocolGuid = { 0x9546e07c, 0x2cbb, 0x4c88, { 0x98, 0x6c, 0xcd, 0x34, 0x10, 0x86, 0xf0, 0x44 } } + gEfiEblAddCommandProtocolGuid = { 0xaeda2428, 0x9a22, 0x4637, { 0x9b, 0x21, 0x54, 0x5e, 0x28, 0xfb, 0xb8, 0x29 } } + gEmbeddedDeviceGuid = { 0xbf4b9d10, 0x13ec, 0x43dd, { 0x88, 0x80, 0xe9, 0xb, 0x71, 0x8f, 0x27, 0xde } } + gEmbeddedExternalDeviceProtocolGuid = { 0x735F8C64, 0xD696, 0x44D0, { 0xBD, 0xF2, 0x44, 0x7F, 0xD0, 0x5A, 0x54, 0x06 }} + gEmbeddedGpioProtocolGuid = { 0x17a0a3d7, 0xc0a5, 0x4635, { 0xbb, 0xd5, 0x07, 0x21, 0x87, 0xdf, 0xe2, 0xee }} + +[PcdsFeatureFlag.common] + gEmbeddedTokenSpaceGuid.PcdEmbeddedMacBoot|FALSE|BOOLEAN|0x00000001 + gEmbeddedTokenSpaceGuid.PcdEmbeddedDirCmd|TRUE|BOOLEAN|0x00000002 + gEmbeddedTokenSpaceGuid.PcdEmbeddedHobCmd|TRUE|BOOLEAN|0x00000003 + gEmbeddedTokenSpaceGuid.PcdEmbeddedHwDebugCmd|TRUE|BOOLEAN|0x00000004 + gEmbeddedTokenSpaceGuid.PcdEmbeddedIoEnable|FALSE|BOOLEAN|0x00000005 + gEmbeddedTokenSpaceGuid.PcdEmbeddedScriptCmd|FALSE|BOOLEAN|0x00000006 + gEmbeddedTokenSpaceGuid.PcdEmbeddedPciDebugCmd|FALSE|BOOLEAN|0x00000041 + gEmbeddedTokenSpaceGuid.PcdPrePiProduceMemoryTypeInformationHob|FALSE|BOOLEAN|0x0000001b + gEmbeddedTokenSpaceGuid.PcdCacheEnable|FALSE|BOOLEAN|0x00000042 + gEmbeddedTokenSpaceGuid.PcdGdbSerial|FALSE|BOOLEAN|0x0000004d + + +[PcdsFixedAtBuild.common] + gEmbeddedTokenSpaceGuid.PcdEmbeddedAutomaticBootCommand|L""|VOID*|0x00000007 + gEmbeddedTokenSpaceGuid.PcdEmbeddedDefaultTextColor|0x07|UINT32|0x00000008 + gEmbeddedTokenSpaceGuid.PcdEmbeddedMemVariableStoreSize|0x10000|UINT32|0x00000009 + gEmbeddedTokenSpaceGuid.PcdEmbeddedPrompt|"Ebl"|VOID*|0x00000034 + + gEmbeddedTokenSpaceGuid.PcdPrePiHobBase|131072|UINT32|0x00000040 + gEmbeddedTokenSpaceGuid.PcdPrePiStackBase|0|UINT32|0x0000000b + gEmbeddedTokenSpaceGuid.PcdPrePiStackSize|131072|UINT32|0x0000000c + gEmbeddedTokenSpaceGuid.PcdPrePiTempMemorySize|0|UINT32|0x000000d + gEmbeddedTokenSpaceGuid.PcdPrePiBfvBaseAddress|0|UINT32|0x000000e + gEmbeddedTokenSpaceGuid.PcdPrePiBfvSize|0|UINT32|0x0000000f + gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize|32|UINT8|0x00000010 + gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize|0|UINT8|0x00000011 + + gEmbeddedTokenSpaceGuid.PcdFlashFvMainBase|0x0|UINT32|0x00000043 + gEmbeddedTokenSpaceGuid.PcdFlashFvMainOffset|0x0|UINT32|0x00000044 + gEmbeddedTokenSpaceGuid.PcdFlashFvMainSize|0x0|UINT32|0x000000045 + + +# Used to help reduce fragmentation in the EFI memory map +# EFI Pages (4K) are the units used + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIReclaimMemory|0|UINT32|0x00000012 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIMemoryNVS|0|UINT32|0x00000013 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType|0|UINT32|0x00000014 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData|0|UINT32|0x00000015 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode|0|UINT32|0x00000016 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesCode|0|UINT32|0x00000017 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesData|0|UINT32|0x00000018 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderCode|0|UINT32|0x00000019 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderData|0|UINT32|0x0000001a + + gEmbeddedTokenSpaceGuid.PcdTimerBaseAddress|0x3c700000|UINT32|0x0000001c + gEmbeddedTokenSpaceGuid.PcdTimerVector|7|UINT32|0x0000001d + gEmbeddedTokenSpaceGuid.PcdTimerPeriod|100000|UINT32|0x0000001e + gEmbeddedTokenSpaceGuid.PcdInterruptBaseAddress|0x38e00000|UINT32|0x0000001f + + gEmbeddedTokenSpaceGuid.PcdEmbeddedFdBaseAddress|0xffff0000|UINT32|0x00000030 + gEmbeddedTokenSpaceGuid.PcdEmbeddedFdSize|0x0000000|UINT32|0x00000031 + gEmbeddedTokenSpaceGuid.PcdEmbeddedPerformanceCounterFreqencyInHz|0x0000000|UINT64|0x00000032 + gEmbeddedTokenSpaceGuid.PcdEmbeddedFdPerformanceCounterPeriodInNanoseconds|0x0000000|UINT32|0x00000033 + +# Shell characteristics + gEmbeddedTokenSpaceGuid.PcdEmbeddedShellCharacterEcho|TRUE|BOOLEAN|0x00000046 + + gEmbeddedTokenSpaceGuid.PcdGdbBaudRate|115200|UINT64|0x00000047 + gEmbeddedTokenSpaceGuid.PcdGdbDataBits|8|UINT8|0x00000048 + gEmbeddedTokenSpaceGuid.PcdGdbParity|1|UINT8|0x00000049 + gEmbeddedTokenSpaceGuid.PcdGdbStopBits|1|UINT8|0x0000004a + gEmbeddedTokenSpaceGuid.PcdGdbUartPort|0x3f8|UINT32|0x0000004b + gEmbeddedTokenSpaceGuid.PcdGdbMaxPacketRetryCount|10000000|UINT32|0x0000004c + + + diff --git a/EmbeddedPkg/EmbeddedPkg.dsc b/EmbeddedPkg/EmbeddedPkg.dsc new file mode 100644 index 0000000000..d1a4ed8da3 --- /dev/null +++ b/EmbeddedPkg/EmbeddedPkg.dsc @@ -0,0 +1,266 @@ +#%HEADER% +#/** @file +# Embedded Package +# +# +# Copyright (c) 2007, Intel Corporation +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/ + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + PLATFORM_NAME = Embedded + PLATFORM_GUID = 8DBB580B-CF89-4D57-95C6-DFE96C44686E + PLATFORM_VERSION = 0.1 + DSC_SPECIFICATION = 0x00010005 + OUTPUT_DIRECTORY = Build/Embedded + SUPPORTED_ARCHITECTURES = IA32|X64|IPF|ARM + BUILD_TARGETS = DEBUG|RELEASE + SKUID_IDENTIFIER = DEFAULT + FLASH_DEFINITION = EmbeddedPkg/EmbeddedPkg.fdf + + +################################################################################ +# +# SKU Identification section - list of all SKU IDs supported by this +# Platform. +# +################################################################################ +[SkuIds] + 0|DEFAULT # The entry: 0|DEFAULT is reserved and always required. + +################################################################################ +# +# Library Class section - list of all Library Classes needed by this Platform. +# +################################################################################ +[LibraryClasses.common] +# DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + + + BaseLib|MdePkg/Library/BaseLib/BaseLib.inf + BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf + PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf + PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf + UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf + EfiFileLib|EmbeddedPkg/Library/EfiFileLib/EfiFileLib.inf + + TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf + + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf + + PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf + PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf + PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf + CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf + PrePiLib|EmbeddedPkg/Library/PrePiLib/PrePiLib.inf + + SerialPortLib|EmbeddedPkg/Library/TemplateSerialPortLib/TemplateSerialPortLib.inf + RealTimeClockLib|EmbeddedPkg/Library/TemplateRealTimeClockLib/TemplateRealTimeClockLib.inf + EfiResetSystemLib|EmbeddedPkg/Library/TemplateResetSystemLib/TemplateResetSystemLib.inf + GdbSerialLib|EmbeddedPkg/Library/GdbSerialLib/GdbSerialLib.inf + + + # + # Need to change this for IPF + # + IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf + + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + UefiLib|MdePkg/Library/UefiLib/UefiLib.inf + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf + UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf + ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf + + DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf + UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf + UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf + + + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + EblCmdLib|EmbeddedPkg/Library/EblCmdLibNull/EblCmdLibNull.inf + + EblNetworkLib|EmbeddedPkg/Library/EblNetworkLib/EblNetworkLib.inf + + +[LibraryClasses.common.DXE_DRIVER] + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf + + +[LibraryClasses.common.UEFI_APPLICATION] + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf + +[LibraryClasses.common.UEFI_DRIVER] + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf + +[LibraryClasses.common.SEC] + ExtractGuidedSectionLib|EmbeddedPkg/Library/PrePiExtractGuidedSectionLib/PrePiExtractGuidedSectionLib.inf + +[LibraryClasses.ARM] + SemihostLib|ArmPkg/Library/SemihostLib/SemihostLib.inf + +################################################################################ +# +# Pcd Section - list of all PCD Entries defined by this Platform +# +################################################################################ + +[PcdsFeatureFlag.common] + gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable|FALSE + gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnosticsDisable|FALSE + gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable|FALSE + gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable|FALSE + + # + # Control what commands are supported from the UI + # Turn these on and off to add features or save size + # + gEmbeddedTokenSpaceGuid.PcdEmbeddedMacBoot|TRUE + gEmbeddedTokenSpaceGuid.PcdEmbeddedDirCmd|TRUE + gEmbeddedTokenSpaceGuid.PcdEmbeddedHobCmd|TRUE + gEmbeddedTokenSpaceGuid.PcdEmbeddedHwDebugCmd|TRUE + gEmbeddedTokenSpaceGuid.PcdEmbeddedIoEnable|FALSE + gEmbeddedTokenSpaceGuid.PcdEmbeddedScriptCmd|FALSE + gEmbeddedTokenSpaceGuid.PcdEmbeddedPciDebugCmd|TRUE + + gEmbeddedTokenSpaceGuid.PcdPrePiProduceMemoryTypeInformationHob|FALSE + + +[PcdsFixedAtBuild.common] + gEfiMdePkgTokenSpaceGuid.PcdMaximumUnicodeStringLength|1000000 + gEfiMdePkgTokenSpaceGuid.PcdMaximumAsciiStringLength|1000000 + gEfiMdePkgTokenSpaceGuid.PcdMaximumLinkedListLength|1000000 + gEfiMdePkgTokenSpaceGuid.PcdSpinLockTimeout|10000000 + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x0f + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000000 + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x06 + gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue|0xAF + gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask|0 + gEfiMdePkgTokenSpaceGuid.PcdPostCodePropertyMask|0 + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|0xE0000000 + gEfiMdePkgTokenSpaceGuid.PcdFSBClock|200000000 + gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|320 + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000000 + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|0xE0000000 + gEfiMdePkgTokenSpaceGuid.PcdFSBClock|200000000 + gEmbeddedTokenSpaceGuid.PcdEmbeddedAutomaticBootCommand|L""|VOID*|2 + gEmbeddedTokenSpaceGuid.PcdEmbeddedDefaultTextColor|0x07 + gEmbeddedTokenSpaceGuid.PcdEmbeddedMemVariableStoreSize|0x10000 + + gEmbeddedTokenSpaceGuid.PcdPrePiHobBase|0 + gEmbeddedTokenSpaceGuid.PcdPrePiStackBase|0 + gEmbeddedTokenSpaceGuid.PcdPrePiStackSize|0 + gEmbeddedTokenSpaceGuid.PcdPrePiTempMemorySize|0 + gEmbeddedTokenSpaceGuid.PcdPrePiBfvBaseAddress|0 + gEmbeddedTokenSpaceGuid.PcdPrePiBfvSize|0 + +# +# Optinal feature to help prevent EFI memory map fragments +# Turned on and off via: PcdPrePiProduceMemoryTypeInformationHob +# Values are in EFI Pages (4K). DXE Core will make sure that +# at least this much of each type of memory can be allocated +# from a single memory range. This way you only end up with +# maximum of two fragements for each type in the memory map +# (the memory used, and the free memory that was prereserved +# but not used). +# + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIReclaimMemory|0 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIMemoryNVS|0 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType|0 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData|0 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode|0 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesCode|0 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesData|0 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderCode|0 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderData|0 + +# +# Timer config for this platform +# + gEmbeddedTokenSpaceGuid.PcdTimerBaseAddress|0x3c700000 + gEmbeddedTokenSpaceGuid.PcdTimerVector|7 + gEmbeddedTokenSpaceGuid.PcdTimerPeriod|100000 + + +[PcdsFixedAtBuild.ARM] + gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize|32 + gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize|0 + +[PcdsFixedAtBuild.IA32] + gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize|36 + gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize|16 + +[PcdsFixedAtBuild.X64] + gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize|52 + gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize|16 + + + +[PcdsFixedAtBuild.IPF] + gEfiMdePkgTokenSpaceGuid.PcdIoBlockBaseAddressForIpf|0x0ffffc000000 + +# +# This makes it so you can source level debug with NT32. VC++ debugger limitiation! +# +#[BuildOptions] +# DEBUG_*_IA32_DLINK_FLAGS = /EXPORT:InitializeDriver=$(IMAGE_ENTRY_POINT) /ALIGN:4096 /SUBSYSTEM:CONSOLE +# RELEASE_*_IA32_DLINK_FLAGS = /ALIGN:4096 +# *_*_IA32_CC_FLAGS = /D EFI_SPECIFICATION_VERSION=0x0002000A /D TIANO_RELEASE_VERSION=0x00080006 + + +################################################################################ +# +# Components Section - list of all Modules needed by this Platform +# +################################################################################ +[Components.common] + EmbeddedPkg/Library/EblAddExternalCommandLib/EblAddExternalCommandLib.inf + EmbeddedPkg/Library/EblCmdLibNull/EblCmdLibNull.inf + EmbeddedPkg/Library/EfiFileLib/EfiFileLib.inf + EmbeddedPkg/Library/GdbSerialDebugPortLib/GdbSerialDebugPortLib.inf # ApplePkg + EmbeddedPkg/Library/GdbSerialLib/GdbSerialLib.inf # ApplePkg + EmbeddedPkg/Library/PrePiExtractGuidedSectionLib/PrePiExtractGuidedSectionLib.inf + EmbeddedPkg/Library/PrePiLib/PrePiLib.inf + EmbeddedPkg/Library/TemplateSerialPortLib/TemplateSerialPortLib.inf + EmbeddedPkg/Library/TemplateResetSystemLib/TemplateResetSystemLib.inf + EmbeddedPkg/Library/TemplateRealTimeClockLib/TemplateRealTimeClockLib.inf + +####ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.inf ??? + + + EmbeddedPkg/Ebl/Ebl.inf +#### EmbeddedPkg/EblExternCmd/EblExternCmd.inf + EmbeddedPkg/EmbeddedMonotonicCounter/EmbeddedMonotonicCounter.inf + EmbeddedPkg/GdbStub/GdbStub.inf + EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf + EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf + EmbeddedPkg/SerialDxe/SerialDxe.inf + EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOutSerial.inf + EmbeddedPkg/TemplateBds/TemplateBds.inf + EmbeddedPkg/TemplateCpuDxe/TemplateCpuDxe.inf + EmbeddedPkg/TemplateMetronomeDxe/TemplateMetronomeDxe.inf + EmbeddedPkg/TemplateSec/TemplateSec.inf + EmbeddedPkg/TemplateTimerDxe/TemplateTimerDxe.inf + + + + diff --git a/EmbeddedPkg/EmbeddedPkg.fdf b/EmbeddedPkg/EmbeddedPkg.fdf new file mode 100644 index 0000000000..67e329e89d --- /dev/null +++ b/EmbeddedPkg/EmbeddedPkg.fdf @@ -0,0 +1,141 @@ +# This is Ebl FDF file +# +# Copyright (c) 2008, Intel Corporation +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# + +################################################################################ +# +# FV Section +# +# [FV] section is used to define what components or modules are placed within a flash +# device file. This section also defines order the components and modules are positioned +# within the image. The [FV] section consists of define statements, set statements and +# module statements. +# +################################################################################ +[FV.FvLoad] +FvAlignment = 16 #FV alignment and FV attributes setting. +ERASE_POLARITY = 1 +MEMORY_MAPPED = TRUE +STICKY_WRITE = TRUE +LOCK_CAP = TRUE +LOCK_STATUS = TRUE +WRITE_DISABLED_CAP = TRUE +WRITE_ENABLED_CAP = TRUE +WRITE_STATUS = TRUE +WRITE_LOCK_CAP = TRUE +WRITE_LOCK_STATUS = TRUE +READ_DISABLED_CAP = TRUE +READ_ENABLED_CAP = TRUE +READ_STATUS = TRUE +READ_LOCK_CAP = TRUE +READ_LOCK_STATUS = TRUE + +################################################################################ +# +# The INF statements point to module INF files, which will be placed into this FV image. +# Parsing tools will scan the INF file to determine the type of component or module. +# The component or module type is used to reference the standard rules +# defined elsewhere in the FDF file. +# +# The format for INF statements is: +# INF $(PathAndInfFileName) +# +################################################################################ +INF EmbeddedPkg/Ebl/Ebl.inf + +################################################################################ +# +# Rules are use with the [FV] section's module INF type to define +# how an FFS file is created for a given INF file. The following Rule are the default +# rules for the different module type. User can add the customized rules to define the +# content of the FFS file. +# +################################################################################ + + +############################################################################ +# Example of a DXE_DRIVER FFS file with a Checksum encapsulation section # +############################################################################ +# +#[Rule.Common.DXE_DRIVER] +# FILE DRIVER = $(NAMED_GUID) { +# DXE_DEPEX DXE_DEPEX Optional |.depex +# COMPRESS PI_STD { +# GUIDED { +# PE32 PE32 |.efi +# UI STRING="$(MODULE_NAME)" Optional +# VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) +# } +# } +# } +# +############################################################################ + +[Rule.Common.SEC] + FILE SEC = $(NAMED_GUID) { + PE32 PE32 |.efi + } + +[Rule.Common.PEI_CORE] + FILE PEI_CORE = $(NAMED_GUID) { + PE32 PE32 |.efi + UI STRING ="$(MODULE_NAME)" Optional + } + +[Rule.Common.PEIM] + FILE PEIM = $(NAMED_GUID) { + PEI_DEPEX PEI_DEPEX Optional |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + } + +[Rule.Common.PEIM.TIANOCOMPRESSED] + FILE PEIM = $(NAMED_GUID) DEBUG_MYTOOLS_IA32 { + PEI_DEPEX PEI_DEPEX Optional |.depex + GUIDED A31280AD-481E-41B6-95E8-127F4C984779 PROCESSING_REQUIRED = TRUE { + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + } + } + +[Rule.Common.DXE_CORE] + FILE DXE_CORE = $(NAMED_GUID) { + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + } + +[Rule.Common.UEFI_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + } + +[Rule.Common.DXE_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + } + +[Rule.Common.DXE_RUNTIME_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + } + +[Rule.Common.UEFI_APPLICATION] + FILE APPLICATION = $(NAMED_GUID) { + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + } diff --git a/EmbeddedPkg/GdbStub/Arm/Processor.c b/EmbeddedPkg/GdbStub/Arm/Processor.c new file mode 100644 index 0000000000..e620d344e6 --- /dev/null +++ b/EmbeddedPkg/GdbStub/Arm/Processor.c @@ -0,0 +1,717 @@ +/** @file + Processor specific parts of the GDB stub + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +/** @file + + Copyright (c) 2008, Apple, Inc + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include + +// +// Array of exception types that need to be hooked by the debugger +// (efi, gdb) //efi number +// +EFI_EXCEPTION_TYPE_ENTRY gExceptionType[] = { + { EXCEPT_ARM_SOFTWARE_INTERRUPT, GDB_SIGTRAP } +// { EXCEPT_ARM_UNDEFINED_INSTRUCTION, GDB_SIGTRAP }, +// { EXCEPT_ARM_PREFETCH_ABORT, GDB_SIGTRAP }, +// { EXCEPT_ARM_DATA_ABORT, GDB_SIGEMT }, +// { EXCEPT_ARM_RESERVED, GDB_SIGILL } +}; + +// Shut up some annoying RVCT warnings +#ifdef __CC_ARM +#pragma diag_suppress 1296 +#endif + +UINTN gRegisterOffsets[] = { + OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R0), + OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R1), + OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R2), + OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R3), + OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R4), + OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R5), + OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R6), + OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R7), + OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R8), + OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R9), + OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R10), + OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R11), + OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R12), + OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, SP), + OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, LR), + OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, PC), + 0x00000F01, // f0 + 0x00000F02, + 0x00000F03, + 0x00000F11, // f1 + 0x00000F12, + 0x00000F13, + 0x00000F21, // f2 + 0x00000F22, + 0x00000F23, + 0x00000F31, // f3 + 0x00000F32, + 0x00000F33, + 0x00000F41, // f4 + 0x00000F42, + 0x00000F43, + 0x00000F51, // f5 + 0x00000F52, + 0x00000F53, + 0x00000F61, // f6 + 0x00000F62, + 0x00000F63, + 0x00000F71, // f7 + 0x00000F72, + 0x00000F73, + 0x00000FFF, // fps + 0x00000FFF, + 0x00000FFF, + OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, CPSR) +}; + +// restore warnings for RVCT +#ifdef __CC_ARM +#pragma diag_default 1296 +#endif + +/** + Return the number of entries in the gExceptionType[] + + @retval UINTN, the number of entries in the gExceptionType[] array. + **/ +UINTN +MaxEfiException ( + VOID + ) +{ + return sizeof (gExceptionType)/sizeof (EFI_EXCEPTION_TYPE_ENTRY); +} + + +/** + Return the number of entries in the gRegisters[] + + @retval UINTN, the number of entries (registers) in the gRegisters[] array. + **/ +UINTN +MaxRegisterCount ( + VOID + ) +{ + return sizeof (gRegisterOffsets)/sizeof (UINTN); +} + + +/** + Check to see if the ISA is supported. + ISA = Instruction Set Architecture + + @retval TRUE if Isa is supported + +**/ +BOOLEAN +CheckIsa ( + IN EFI_INSTRUCTION_SET_ARCHITECTURE Isa + ) +{ + if (Isa == IsaArm) { + return TRUE; + } else { + return FALSE; + } +} + + +/** + This takes in the register number and the System Context, and returns a pointer to the RegNumber-th register in gdb ordering + It is, by default, set to find the register pointer of the ARM member + @param SystemContext Register content at time of the exception + @param RegNumber The register to which we want to find a pointer + @retval the pointer to the RegNumber-th pointer + **/ +UINTN * +FindPointerToRegister( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN RegNumber + ) +{ + UINT8 *TempPtr; + ASSERT(gRegisterOffsets[RegNumber] < 0xF00); + TempPtr = ((UINT8 *)SystemContext.SystemContextArm) + gRegisterOffsets[RegNumber]; + return (UINT32 *)TempPtr; +} + + +/** + Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr + @param SystemContext Register content at time of the exception + @param RegNumber the number of the register that we want to read + @param OutBufPtr pointer to the output buffer's end. the new data will be added from this point on. + @retval the pointer to the next character of the output buffer that is available to be written on. + **/ +CHAR8 * +BasicReadRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN RegNumber, + IN CHAR8 *OutBufPtr + ) +{ + UINTN RegSize; + CHAR8 Char; + + if (gRegisterOffsets[RegNumber] > 0xF00) { + AsciiSPrint(OutBufPtr, 9, "00000000"); + OutBufPtr += 8; + return OutBufPtr; + } + + RegSize = 0; + while (RegSize < 32) { + Char = mHexToStr[(UINT8)((*FindPointerToRegister(SystemContext, RegNumber) >> (RegSize+4)) & 0xf)]; + if ((Char >= 'A') && (Char <= 'F')) { + Char = Char - 'A' + 'a'; + } + *OutBufPtr++ = Char; + + Char = mHexToStr[(UINT8)((*FindPointerToRegister(SystemContext, RegNumber) >> RegSize) & 0xf)]; + if ((Char >= 'A') && (Char <= 'F')) { + Char = Char - 'A' + 'a'; + } + *OutBufPtr++ = Char; + + RegSize = RegSize + 8; + } + return OutBufPtr; +} + + +/** ‘p n’ + Reads the n-th register's value into an output buffer and sends it as a packet + @param SystemContext Register content at time of the exception + @param InBuffer Pointer to the input buffer received from gdb server + **/ +VOID +ReadNthRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *InBuffer + ) +{ + UINTN RegNumber; + CHAR8 OutBuffer[9]; // 1 reg=8 hex chars, and the end '\0' (escape seq) + CHAR8 *OutBufPtr; // pointer to the output buffer + + RegNumber = AsciiStrHexToUintn (&InBuffer[1]); + + if (RegNumber >= MaxRegisterCount()) { + SendError (GDB_EINVALIDREGNUM); + return; + } + + OutBufPtr = OutBuffer; + OutBufPtr = BasicReadRegister (SystemContext, RegNumber, OutBufPtr); + + *OutBufPtr = '\0'; // the end of the buffer + SendPacket(OutBuffer); +} + + +/** ‘g’ + Reads the general registers into an output buffer and sends it as a packet + @param SystemContext Register content at time of the exception + **/ +VOID +EFIAPI +ReadGeneralRegisters ( + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + UINTN Index; + CHAR8 *OutBuffer; + CHAR8 *OutBufPtr; + UINTN RegisterCount = MaxRegisterCount(); + + // It is not safe to allocate pool here.... + OutBuffer = AllocatePool((RegisterCount * 8) + 1); // 8 bytes per register in string format plus a null to terminate + OutBufPtr = OutBuffer; + for (Index = 0; Index < RegisterCount; Index++) { + OutBufPtr = BasicReadRegister (SystemContext, Index, OutBufPtr); + } + + *OutBufPtr = '\0'; + SendPacket(OutBuffer); + FreePool(OutBuffer); +} + + +/** + Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr + @param SystemContext Register content at time of the exception + @param RegNumber the number of the register that we want to write + @param InBufPtr pointer to the output buffer. the new data will be extracted from the input buffer from this point on. + @retval the pointer to the next character of the input buffer that can be used + **/ +CHAR8 +*BasicWriteRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN RegNumber, + IN CHAR8 *InBufPtr + ) +{ + UINTN RegSize; + UINTN TempValue; // the value transferred from a hex char + UINT32 NewValue; // the new value of the RegNumber-th Register + + if (gRegisterOffsets[RegNumber] > 0xF00) { + return InBufPtr + 8; + } + + NewValue = 0; + RegSize = 0; + while (RegSize < 32) { + TempValue = HexCharToInt(*InBufPtr++); + + if ((INTN)TempValue < 0) { + SendError (GDB_EBADMEMDATA); + return NULL; + } + + NewValue += (TempValue << (RegSize+4)); + TempValue = HexCharToInt(*InBufPtr++); + + if ((INTN)TempValue < 0) { + SendError (GDB_EBADMEMDATA); + return NULL; + } + + NewValue += (TempValue << RegSize); + RegSize = RegSize + 8; + } + *(FindPointerToRegister(SystemContext, RegNumber)) = NewValue; + return InBufPtr; +} + + +/** ‘P n...=r...’ + Writes the new value of n-th register received into the input buffer to the n-th register + @param SystemContext Register content at time of the exception + @param InBuffer Ponter to the input buffer received from gdb server + **/ +VOID +WriteNthRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *InBuffer + ) +{ + UINTN RegNumber; + CHAR8 RegNumBuffer[MAX_REG_NUM_BUF_SIZE]; // put the 'n..' part of the message into this array + CHAR8 *RegNumBufPtr; + CHAR8 *InBufPtr; // pointer to the input buffer + + // find the register number to write + InBufPtr = &InBuffer[1]; + RegNumBufPtr = RegNumBuffer; + while (*InBufPtr != '=') { + *RegNumBufPtr++ = *InBufPtr++; + } + *RegNumBufPtr = '\0'; + RegNumber = AsciiStrHexToUintn (RegNumBuffer); + + // check if this is a valid Register Number + if (RegNumber >= MaxRegisterCount()) { + SendError (GDB_EINVALIDREGNUM); + return; + } + InBufPtr++; // skips the '=' character + BasicWriteRegister (SystemContext, RegNumber, InBufPtr); + SendSuccess(); +} + + +/** ‘G XX...’ + Writes the new values received into the input buffer to the general registers + @param SystemContext Register content at time of the exception + @param InBuffer Pointer to the input buffer received from gdb server + **/ + +VOID +EFIAPI +WriteGeneralRegisters ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *InBuffer + ) +{ + UINTN i; + CHAR8 *InBufPtr; /// pointer to the input buffer + UINTN MinLength; + UINTN RegisterCount = MaxRegisterCount(); + + MinLength = (RegisterCount * 8) + 1; // 'G' plus the registers in ASCII format + + if (AsciiStrLen(InBuffer) < MinLength) { + //Bad message. Message is not the right length + SendError (GDB_EBADBUFSIZE); + return; + } + + InBufPtr = &InBuffer[1]; + + // Read the new values for the registers from the input buffer to an array, NewValueArray. + // The values in the array are in the gdb ordering + for(i = 0; i < RegisterCount; i++) { + InBufPtr = BasicWriteRegister (SystemContext, i, InBufPtr); + } + + SendSuccess (); +} + +// What about Thumb? +// Use SWI 0xdbdbdb as the debug instruction +#define GDB_ARM_BKPT 0xefdbdbdb + +BOOLEAN mSingleStepActive = FALSE; +UINT32 mSingleStepPC; +UINT32 mSingleStepData; +UINTN mSingleStepDataSize; + +typedef struct { + LIST_ENTRY Link; + UINT64 Signature; + UINT32 Address; + UINT32 Instruction; +} ARM_SOFTWARE_BREAKPOINT; + +#define ARM_SOFTWARE_BREAKPOINT_SIGNATURE SIGNATURE_64('A', 'R', 'M', 'B', 'R', 'K', 'P', 'T') +#define ARM_SOFTWARE_BREAKPOINT_FROM_LINK(a) CR(a, ARM_SOFTWARE_BREAKPOINT, Link, ARM_SOFTWARE_BREAKPOINT_SIGNATURE) + +LIST_ENTRY BreakpointList; + +/** + Insert Single Step in the SystemContext + + @param SystemContext Register content at time of the exception + **/ +VOID +AddSingleStep ( + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + if (mSingleStepActive) { + // Currently don't support nesting + return; + } + mSingleStepActive = TRUE; + + mSingleStepPC = SystemContext.SystemContextArm->PC; + + mSingleStepDataSize = sizeof (UINT32); + mSingleStepData = (*(UINT32 *)mSingleStepPC); + *(UINT32 *)mSingleStepPC = GDB_ARM_BKPT; + if (*(UINT32 *)mSingleStepPC != GDB_ARM_BKPT) { + // For some reason our breakpoint did not take + mSingleStepActive = FALSE; + } + + InvalidateInstructionCacheRange((VOID *)mSingleStepPC, mSingleStepDataSize); + //DEBUG((EFI_D_ERROR, "AddSingleStep at 0x%08x (was: 0x%08x is:0x%08x)\n", SystemContext.SystemContextArm->PC, mSingleStepData, *(UINT32 *)mSingleStepPC)); +} + + +/** + Remove Single Step in the SystemContext + + @param SystemContext Register content at time of the exception + **/ +VOID +RemoveSingleStep ( + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + if (!mSingleStepActive) { + return; + } + + if (mSingleStepDataSize == sizeof (UINT16)) { + *(UINT16 *)mSingleStepPC = (UINT16)mSingleStepData; + } else { + //DEBUG((EFI_D_ERROR, "RemoveSingleStep at 0x%08x (was: 0x%08x is:0x%08x)\n", SystemContext.SystemContextArm->PC, *(UINT32 *)mSingleStepPC, mSingleStepData)); + *(UINT32 *)mSingleStepPC = mSingleStepData; + } + InvalidateInstructionCacheRange((VOID *)mSingleStepPC, mSingleStepDataSize); + mSingleStepActive = FALSE; +} + + + +/** ‘c [addr ]’ + Continue. addr is Address to resume. If addr is omitted, resume at current + Address. + + @param SystemContext Register content at time of the exception + **/ +VOID +EFIAPI +ContinueAtAddress ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *PacketData + ) +{ + if (PacketData[1] != '\0') { + SystemContext.SystemContextArm->PC = AsciiStrHexToUintn(&PacketData[1]); + } +} + + +/** ‘s [addr ]’ + Single step. addr is the Address at which to resume. If addr is omitted, resume + at same Address. + + @param SystemContext Register content at time of the exception + **/ +VOID +EFIAPI +SingleStep ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *PacketData + ) +{ + SendNotSupported(); +} + +UINTN +GetBreakpointDataAddress ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN BreakpointNumber + ) +{ + return 0; +} + +UINTN +GetBreakpointDetected ( + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + return 0; +} + +BREAK_TYPE +GetBreakpointType ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN BreakpointNumber + ) +{ + return NotSupported; +} + +ARM_SOFTWARE_BREAKPOINT * +SearchBreakpointList ( + IN UINT32 Address + ) +{ + LIST_ENTRY *Current; + ARM_SOFTWARE_BREAKPOINT *Breakpoint; + + Current = GetFirstNode(&BreakpointList); + while (!IsNull(&BreakpointList, Current)) { + Breakpoint = ARM_SOFTWARE_BREAKPOINT_FROM_LINK(Current); + + if (Address == Breakpoint->Address) { + return Breakpoint; + } + + Current = GetNextNode(&BreakpointList, Current); + } + + return NULL; +} + +VOID +SetBreakpoint ( + IN UINT32 Address + ) +{ + ARM_SOFTWARE_BREAKPOINT *Breakpoint; + + Breakpoint = SearchBreakpointList(Address); + + if (Breakpoint != NULL) { + return; + } + + // create and fill breakpoint structure + Breakpoint = AllocatePool(sizeof(ARM_SOFTWARE_BREAKPOINT)); + + Breakpoint->Signature = ARM_SOFTWARE_BREAKPOINT_SIGNATURE; + Breakpoint->Address = Address; + Breakpoint->Instruction = *(UINT32 *)Address; + + // Add it to the list + InsertTailList(&BreakpointList, &Breakpoint->Link); + + // Insert the software breakpoint + *(UINT32 *)Address = GDB_ARM_BKPT; + InvalidateInstructionCacheRange((VOID *)Address, 4); + + //DEBUG((EFI_D_ERROR, "SetBreakpoint at 0x%08x (was: 0x%08x is:0x%08x)\n", Address, Breakpoint->Instruction, *(UINT32 *)Address)); +} + +VOID +ClearBreakpoint ( + IN UINT32 Address + ) +{ + ARM_SOFTWARE_BREAKPOINT *Breakpoint; + + Breakpoint = SearchBreakpointList(Address); + + if (Breakpoint == NULL) { + return; + } + + // Add it to the list + RemoveEntryList(&Breakpoint->Link); + + // Restore the original instruction + *(UINT32 *)Address = Breakpoint->Instruction; + InvalidateInstructionCacheRange((VOID *)Address, 4); + + //DEBUG((EFI_D_ERROR, "ClearBreakpoint at 0x%08x (was: 0x%08x is:0x%08x)\n", Address, GDB_ARM_BKPT, *(UINT32 *)Address)); + + FreePool(Breakpoint); +} + +VOID +EFIAPI +InsertBreakPoint ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *PacketData + ) +{ + UINTN Type; + UINTN Address; + UINTN Length; + UINTN ErrorCode; + + ErrorCode = ParseBreakpointPacket(PacketData, &Type, &Address, &Length); + if (ErrorCode > 0) { + SendError ((UINT8)ErrorCode); + return; + } + + switch (Type) { + case 0: //Software breakpoint + break; + + default : + DEBUG((EFI_D_ERROR, "Insert breakpoint default: %x\n", Type)); + SendError (GDB_EINVALIDBRKPOINTTYPE); + return; + } + + SetBreakpoint(Address); + + SendSuccess (); +} + +VOID +EFIAPI +RemoveBreakPoint ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *PacketData + ) +{ + UINTN Type; + UINTN Address; + UINTN Length; + UINTN ErrorCode; + + //Parse breakpoint packet data + ErrorCode = ParseBreakpointPacket (PacketData, &Type, &Address, &Length); + if (ErrorCode > 0) { + SendError ((UINT8)ErrorCode); + return; + } + + switch (Type) { + case 0: //Software breakpoint + break; + + default: + SendError (GDB_EINVALIDBRKPOINTTYPE); + return; + } + + ClearBreakpoint(Address); + + SendSuccess (); +} + +VOID +InitializeProcessor ( + VOID + ) +{ + // Initialize breakpoint list + InitializeListHead(&BreakpointList); +} + +BOOLEAN +ValidateAddress ( + IN VOID *Address + ) +{ + if ((UINT32)Address < 0x80000000) { + return FALSE; + } else { + return TRUE; + } +} + +BOOLEAN +ValidateException ( + IN EFI_EXCEPTION_TYPE ExceptionType, + IN OUT EFI_SYSTEM_CONTEXT SystemContext + ) +{ + UINT32 ExceptionAddress; + UINT32 Instruction; + + // Is it a debugger SWI? + ExceptionAddress = SystemContext.SystemContextArm->PC -= 4; + Instruction = *(UINT32 *)ExceptionAddress; + if (Instruction != GDB_ARM_BKPT) { + return FALSE; + } + + // Special for SWI-based exception handling. SWI sets up the context + // to return to the instruction following the SWI instruction - NOT what we want + // for a debugger! + SystemContext.SystemContextArm->PC = ExceptionAddress; + + return TRUE; +} + diff --git a/EmbeddedPkg/GdbStub/GdbStub.c b/EmbeddedPkg/GdbStub/GdbStub.c new file mode 100644 index 0000000000..b121e413f3 --- /dev/null +++ b/EmbeddedPkg/GdbStub/GdbStub.c @@ -0,0 +1,1264 @@ +/** @file + UEFI driver that implements a GDB stub + + Note: Any code in the path of the Serial IO output can not call DEBUG as will + will blow out the stack. Serial IO calls DEBUG, debug calls Serail IO, ... + + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include + + +UINTN gMaxProcessorIndex = 0; + +// +// Buffers for basic gdb communication +// +CHAR8 gInBuffer[MAX_BUF_SIZE]; +CHAR8 gOutBuffer[MAX_BUF_SIZE]; + +// Assume gdb does a "qXfer:libraries:read::offset,length" when it connects so we can default +// this value to FALSE. Since gdb can reconnect its self a global default is not good enough +BOOLEAN gSymbolTableUpdate = FALSE; +EFI_EVENT gEvent; +VOID *gGdbSymbolEventHandlerRegistration = NULL; + +// +// Globals for returning XML from qXfer:libraries:read packet +// +UINTN gPacketqXferLibraryOffset = 0; +UINTN gEfiDebugImageTableEntry = 0; +EFI_DEBUG_IMAGE_INFO_TABLE_HEADER *gDebugImageTableHeader = NULL; +EFI_DEBUG_IMAGE_INFO *gDebugTable = NULL; +CHAR8 gXferLibraryBuffer[2000]; + +GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mHexToStr[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; + + +VOID +EFIAPI +GdbSymbolEventHandler ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ +} + + +/** + The user Entry Point for Application. The user code starts with this function + as the real entry point for the image goes into a library that calls this + function. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +GdbStubEntry ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) + +{ + EFI_STATUS Status; + EFI_DEBUG_SUPPORT_PROTOCOL *DebugSupport; + UINTN HandleCount; + EFI_HANDLE *Handles; + UINTN Index; + UINTN Processor; + BOOLEAN IsaSupported; + + + Status = EfiGetSystemConfigurationTable (&gEfiDebugImageInfoTableGuid, (VOID **)&gDebugImageTableHeader); + if (EFI_ERROR (Status)) { + gDebugImageTableHeader = NULL; + } + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiDebugSupportProtocolGuid, + NULL, + &HandleCount, + &Handles + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Debug Support Protocol not found\n")); + + return Status; + } + + DebugSupport = NULL; + IsaSupported = FALSE; + do { + HandleCount--; + Status = gBS->HandleProtocol ( + Handles[HandleCount], + &gEfiDebugSupportProtocolGuid, + (VOID **) &DebugSupport + ); + if (!EFI_ERROR (Status)) { + if (CheckIsa (DebugSupport->Isa)) { + // We found what we are looking for so break out of the loop + IsaSupported = TRUE; + break; + } + } + } while (HandleCount > 0); + FreePool (Handles); + + if (!IsaSupported) { + DEBUG ((EFI_D_ERROR, "Debug Support Protocol does not support our ISA\n")); + + return EFI_NOT_FOUND; + } + + Status = DebugSupport->GetMaximumProcessorIndex (DebugSupport, &gMaxProcessorIndex); + ASSERT_EFI_ERROR (Status); + + // Make this an EFI_D_INFO after we get everything debugged. + DEBUG ((EFI_D_ERROR, "Debug Support Protocol ISA %x\n", DebugSupport->Isa)); + DEBUG ((EFI_D_ERROR, "Debug Support Protocol Processor Index %d\n", gMaxProcessorIndex)); + + // Call processor-specific init routine + InitializeProcessor(); + + for (Processor = 0; Processor <= gMaxProcessorIndex; Processor++) { + + for (Index = 0; Index < MaxEfiException (); Index++) { + Status = DebugSupport->RegisterExceptionCallback (DebugSupport, Processor, GdbExceptionHandler, gExceptionType[Index].Exception); + ASSERT_EFI_ERROR (Status); + } + // + // Current edk2 DebugPort is not interrupt context safe so we can not use it + // + Status = DebugSupport->RegisterPeriodicCallback (DebugSupport, Processor, GdbPeriodicCallBack); + ASSERT_EFI_ERROR (Status); + } + + // + // This even fires every time an image is added. This allows the stub to know when gdb needs + // to update the symbol table. + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + GdbSymbolEventHandler, + NULL, + &gEvent + ); + ASSERT_EFI_ERROR (Status); + + // + // Register for protocol notifactions on this event + // + Status = gBS->RegisterProtocolNotify ( + &gEfiLoadedImageProtocolGuid, + gEvent, + &gGdbSymbolEventHandlerRegistration + ); + ASSERT_EFI_ERROR (Status); + + + if (PcdGetBool (PcdGdbSerial)) { + GdbInitializeSerialConsole (); + } + + return EFI_SUCCESS; +} + + + +/** + Transfer length bytes of input buffer, starting at Address, to memory. + + @param length the number of the bytes to be transferred/written + @param *address the start address of the transferring/writing the memory + @param *new_data the new data to be written to memory + **/ + +VOID +TransferFromInBufToMem ( + IN UINTN Length, + IN unsigned char *Address, + IN CHAR8 *NewData + ) +{ + CHAR8 c1; + CHAR8 c2; + + while (Length-- > 0) { + c1 = (CHAR8)HexCharToInt (*NewData++); + c2 = (CHAR8)HexCharToInt (*NewData++); + + if ((c1 < 0) || (c2 < 0)) { + Print ((CHAR16 *)L"Bad message from write to memory..\n"); + SendError (GDB_EBADMEMDATA); + return; + } + *Address++ = (UINT8)((c1 << 4) + c2); + } + + SendSuccess(); +} + + +/** + Transfer Length bytes of memory starting at Address to an output buffer, OutBuffer. This function will finally send the buffer + as a packet. + + @param Length the number of the bytes to be transferred/read + @param *address pointer to the start address of the transferring/reading the memory + **/ + +VOID +TransferFromMemToOutBufAndSend ( + IN UINTN Length, + IN unsigned char *Address + ) +{ + // there are Length bytes and every byte is represented as 2 hex chars + CHAR8 OutBuffer[MAX_BUF_SIZE]; + CHAR8 *OutBufPtr; // pointer to the output buffer + CHAR8 Char; + + if (ValidateAddress(Address) == FALSE) { + SendError(14); + return; + } + + OutBufPtr = OutBuffer; + while (Length > 0) { + + Char = mHexToStr[*Address >> 4]; + if ((Char >= 'A') && (Char <= 'F')) { + Char = Char - 'A' + 'a'; + } + *OutBufPtr++ = Char; + + Char = mHexToStr[*Address & 0x0f]; + if ((Char >= 'A') && (Char <= 'F')) { + Char = Char - 'A' + 'a'; + } + *OutBufPtr++ = Char; + + Address++; + Length--; + } + + *OutBufPtr = '\0' ; // the end of the buffer + SendPacket (OutBuffer); +} + + + +/** + Send a GDB Remote Serial Protocol Packet + + $PacketData#checksum PacketData is passed in and this function adds the packet prefix '$', + the packet teminating character '#' and the two digit checksum. + + If an ack '+' is not sent resend the packet, but timeout eventually so we don't end up + in an infinit loop. This is so if you unplug the debugger code just keeps running + + @param PacketData Payload data for the packet + + + @retval Number of bytes of packet data sent. + +**/ +UINTN +SendPacket ( + IN CHAR8 *PacketData + ) +{ + UINT8 CheckSum; + UINTN Timeout; + CHAR8 *Ptr; + CHAR8 TestChar; + UINTN Count; + + Timeout = PcdGet32 (PcdGdbMaxPacketRetryCount); + + Count = 0; + do { + + Ptr = PacketData; + + if (Timeout-- == 0) { + // Only try a finite number of times so we don't get stuck in the loop + return Count; + } + + // Packet prefix + GdbPutChar ('$'); + + for (CheckSum = 0, Count =0 ; *Ptr != '\0'; Ptr++, Count++) { + GdbPutChar (*Ptr); + CheckSum = CheckSum + *Ptr; + } + + // Packet terminating character and checksum + GdbPutChar ('#'); + GdbPutChar (mHexToStr[CheckSum >> 4]); + GdbPutChar (mHexToStr[CheckSum & 0x0F]); + + TestChar = GdbGetChar (); + } while (TestChar != '+'); + + return Count; +} + +/** + Receive a GDB Remote Serial Protocol Packet + + $PacketData#checksum PacketData is passed in and this function adds the packet prefix '$', + the packet teminating character '#' and the two digit checksum. + + If host re-starts sending a packet without ending the previous packet, only the last valid packet is proccessed. + (In other words, if received packet is '$12345$12345$123456#checksum', only '$123456#checksum' will be processed.) + + If an ack '+' is not sent resend the packet + + @param PacketData Payload data for the packet + + @retval Number of bytes of packet data received. + +**/ +UINTN +ReceivePacket ( + OUT CHAR8 *PacketData, + IN UINTN PacketDataSize + ) +{ + UINT8 CheckSum; + UINTN Index; + CHAR8 Char; + CHAR8 SumString[3]; + CHAR8 TestChar; + + ZeroMem (PacketData, PacketDataSize); + + for (;;) { + // wait for the start of a packet + TestChar = GdbGetChar (); + while (TestChar != '$') { + TestChar = GdbGetChar (); + }; + + retry: + for (Index = 0, CheckSum = 0; Index < (PacketDataSize - 1); Index++) { + Char = GdbGetChar (); + if (Char == '$') { + goto retry; + } + if (Char == '#') { + break; + } + + PacketData[Index] = Char; + CheckSum = CheckSum + Char; + } + PacketData[Index] = '\0'; + + if (Index == PacketDataSize) { + continue; + } + + SumString[0] = GdbGetChar (); + SumString[1] = GdbGetChar (); + SumString[2] = '\0'; + + if (AsciiStrHexToUintn (SumString) == CheckSum) { + // Ack: Success + GdbPutChar ('+'); + + // Null terminate the callers string + PacketData[Index] = '\0'; + return Index; + } else { + // Ack: Failure + GdbPutChar ('-'); + } + } + + //return 0; +} + + +/** + Empties the given buffer + @param Buf pointer to the first element in buffer to be emptied + **/ +VOID +EmptyBuffer ( + IN CHAR8 *Buf + ) +{ + *Buf = '\0'; +} + + +/** + Converts an 8-bit Hex Char into a INTN. + + @param Char the hex character to be converted into UINTN + @retval a INTN, from 0 to 15, that corressponds to Char + -1 if Char is not a hex character + **/ +INTN +HexCharToInt ( + IN CHAR8 Char + ) +{ + if ((Char >= 'A') && (Char <= 'F')) { + return Char - 'A' + 10; + } else if ((Char >= 'a') && (Char <= 'f')) { + return Char - 'a' + 10; + } else if ((Char >= '0') && (Char <= '9')) { + return Char - '0'; + } else { // if not a hex value, return a negative value + return -1; + } +} + + // 'E' + the biggest error number is 255, so its 2 hex digits + buffer end +CHAR8 *gError = "E__"; + +/** 'E NN' + Send an error with the given error number after converting to hex. + The error number is put into the buffer in hex. '255' is the biggest errno we can send. + ex: 162 will be sent as A2. + + @param errno the error number that will be sent + **/ +VOID +EFIAPI +SendError ( + IN UINT8 ErrorNum + ) +{ + // + // Replace _, or old data, with current errno + // + gError[1] = mHexToStr [ErrorNum >> 4]; + gError[2] = mHexToStr [ErrorNum & 0x0f]; + + SendPacket (gError); // send buffer +} + + + +/** + Send 'OK' when the function is done executing successfully. + **/ +VOID +EFIAPI +SendSuccess ( + VOID + ) +{ + SendPacket ("OK"); // send buffer +} + + +/** + Send empty packet to specify that particular command/functionality is not supported. + **/ +VOID +EFIAPI +SendNotSupported ( + VOID + ) +{ + SendPacket (""); +} + + + +/** + Send the T signal with the given exception type (in gdb order) and possibly with n:r pairs related to the watchpoints + + @param SystemContext Register content at time of the exception + @param GdbExceptionType GDB exception type + **/ +VOID +GdbSendTSignal ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINT8 GdbExceptionType + ) +{ + CHAR8 TSignalBuffer[128]; + CHAR8 *TSignalPtr; + UINTN BreakpointDetected; + BREAK_TYPE BreakType; + UINTN DataAddress; + CHAR8 *WatchStrPtr = NULL; + UINTN RegSize; + + TSignalPtr = &TSignalBuffer[0]; + + //Construct TSignal packet + *TSignalPtr++ = 'T'; + + // + // replace _, or previous value, with Exception type + // + *TSignalPtr++ = mHexToStr [GdbExceptionType >> 4]; + *TSignalPtr++ = mHexToStr [GdbExceptionType & 0x0f]; + + if (GdbExceptionType == GDB_SIGTRAP) { + if (gSymbolTableUpdate) { + // + // We can only send back on reason code. So if the flag is set it means the breakpoint is from our event handler + // + WatchStrPtr = "library:;"; + while (*WatchStrPtr != '\0') { + *TSignalPtr++ = *WatchStrPtr++; + } + gSymbolTableUpdate = FALSE; + } else { + + + // + // possible n:r pairs + // + + //Retrieve the breakpoint number + BreakpointDetected = GetBreakpointDetected (SystemContext); + + //Figure out if the exception is happend due to watch, rwatch or awatch. + BreakType = GetBreakpointType (SystemContext, BreakpointDetected); + + //INFO: rwatch is not supported due to the way IA32 debug registers work + if ((BreakType == DataWrite) || (BreakType == DataRead) || (BreakType == DataReadWrite)) { + + //Construct n:r pair + DataAddress = GetBreakpointDataAddress (SystemContext, BreakpointDetected); + + //Assign appropriate buffer to print particular watchpoint type + if (BreakType == DataWrite) { + WatchStrPtr = "watch"; + } else if (BreakType == DataRead) { + WatchStrPtr = "rwatch"; + } else if (BreakType == DataReadWrite) { + WatchStrPtr = "awatch"; + } + + while (*WatchStrPtr != '\0') { + *TSignalPtr++ = *WatchStrPtr++; + } + + *TSignalPtr++ = ':'; + + //Set up series of bytes in big-endian byte order. "awatch" won't work with little-endian byte order. + RegSize = REG_SIZE; + while (RegSize > 0) { + RegSize = RegSize-4; + *TSignalPtr++ = mHexToStr[(UINT8)(DataAddress >> RegSize) & 0xf]; + } + + //Always end n:r pair with ';' + *TSignalPtr++ = ';'; + } + } + } + + *TSignalPtr = '\0'; + + SendPacket (TSignalBuffer); +} + + +/** + Translates the EFI mapping to GDB mapping + + @param EFIExceptionType EFI Exception that is being processed + @retval UINTN that corresponds to EFIExceptionType's GDB exception type number + **/ +UINT8 +ConvertEFItoGDBtype ( + IN EFI_EXCEPTION_TYPE EFIExceptionType + ) +{ + UINTN i; + + for (i=0; i < MaxEfiException() ; i++) { + if (gExceptionType[i].Exception == EFIExceptionType) { + return gExceptionType[i].SignalNo; + } + } + return GDB_SIGTRAP; // this is a GDB trap +} + + +/** "m addr,length" + Find the Length of the area to read and the start addres. Finally, pass them to + another function, TransferFromMemToOutBufAndSend, that will read from that memory space and + send it as a packet. + **/ + +VOID +EFIAPI +ReadFromMemory ( + CHAR8 *PacketData + ) +{ + UINTN Address; + UINTN Length; + CHAR8 AddressBuffer[MAX_ADDR_SIZE]; // the buffer that will hold the address in hex chars + CHAR8 *AddrBufPtr; // pointer to the address buffer + CHAR8 *InBufPtr; /// pointer to the input buffer + + AddrBufPtr = AddressBuffer; + InBufPtr = &PacketData[1]; + while (*InBufPtr != ',') { + *AddrBufPtr++ = *InBufPtr++; + } + *AddrBufPtr = '\0'; + + InBufPtr++; // this skips ',' in the buffer + + /* Error checking */ + if (AsciiStrLen(AddressBuffer) >= MAX_ADDR_SIZE) { + Print((CHAR16 *)L"Address is too long\n"); + SendError (GDB_EBADMEMADDRBUFSIZE); + return; + } + + // 2 = 'm' + ',' + if (AsciiStrLen(PacketData) - AsciiStrLen(AddressBuffer) - 2 >= MAX_LENGTH_SIZE) { + Print((CHAR16 *)L"Length is too long\n"); + SendError (GDB_EBADMEMLENGTH); + return; + } + + Address = AsciiStrHexToUintn (AddressBuffer); + Length = AsciiStrHexToUintn (InBufPtr); + + TransferFromMemToOutBufAndSend (Length, (unsigned char *)Address); +} + + +/** "M addr,length :XX..." + Find the Length of the area in bytes to write and the start addres. Finally, pass them to + another function, TransferFromInBufToMem, that will write to that memory space the info in + the input buffer. + **/ +VOID +EFIAPI +WriteToMemory ( + IN CHAR8 *PacketData + ) +{ + UINTN Address; + UINTN Length; + UINTN MessageLength; + CHAR8 AddressBuffer[MAX_ADDR_SIZE]; // the buffer that will hold the Address in hex chars + CHAR8 LengthBuffer[MAX_LENGTH_SIZE]; // the buffer that will hold the Length in hex chars + CHAR8 *AddrBufPtr; // pointer to the Address buffer + CHAR8 *LengthBufPtr; // pointer to the Length buffer + CHAR8 *InBufPtr; /// pointer to the input buffer + + AddrBufPtr = AddressBuffer; + LengthBufPtr = LengthBuffer; + InBufPtr = &PacketData[1]; + + while (*InBufPtr != ',') { + *AddrBufPtr++ = *InBufPtr++; + } + *AddrBufPtr = '\0'; + + InBufPtr++; // this skips ',' in the buffer + + while (*InBufPtr != ':') { + *LengthBufPtr++ = *InBufPtr++; + } + *LengthBufPtr = '\0'; + + InBufPtr++; // this skips ':' in the buffer + + Address = AsciiStrHexToUintn (AddressBuffer); + Length = AsciiStrHexToUintn (LengthBuffer); + + /* Error checking */ + + //Check if Address is not too long. + if (AsciiStrLen(AddressBuffer) >= MAX_ADDR_SIZE) { + Print ((CHAR16 *)L"Address too long..\n"); + SendError (GDB_EBADMEMADDRBUFSIZE); + return; + } + + //Check if message length is not too long + if (AsciiStrLen(LengthBuffer) >= MAX_LENGTH_SIZE) { + Print ((CHAR16 *)L"Length too long..\n"); + SendError (GDB_EBADMEMLENGBUFSIZE); + return; + } + + // Check if Message is not too long/short. + // 3 = 'M' + ',' + ':' + MessageLength = (AsciiStrLen(PacketData) - AsciiStrLen(AddressBuffer) - AsciiStrLen(LengthBuffer) - 3); + if (MessageLength != (2*Length)) { + //Message too long/short. New data is not the right size. + SendError (GDB_EBADMEMDATASIZE); + return; + } + TransferFromInBufToMem (Length, (unsigned char *)Address, InBufPtr); +} + +/** + Parses breakpoint packet data and captures Breakpoint type, Address and length. + In case of an error, function returns particular error code. Returning 0 meaning + no error. + + @param PacketData Pointer to the payload data for the packet. + @param Type Breakpoint type + @param Address Breakpoint address + @param Length Breakpoint length in Bytes (1 byte, 2 byte, 4 byte) + + @retval 1 Success + @retval {other} Particular error code + +**/ +UINTN +ParseBreakpointPacket ( + IN CHAR8 *PacketData, + OUT UINTN *Type, + OUT UINTN *Address, + OUT UINTN *Length + ) +{ + CHAR8 AddressBuffer[MAX_ADDR_SIZE]; + CHAR8 *AddressBufferPtr; + CHAR8 *PacketDataPtr; + + PacketDataPtr = &PacketData[1]; + AddressBufferPtr = AddressBuffer; + + *Type = AsciiStrHexToUintn (PacketDataPtr); + + //Breakpoint/watchpoint type should be between 0 to 4 + if (*Type > 4) { + Print ((CHAR16 *)L"Type is invalid\n"); + return 22; //EINVAL: Invalid argument. + } + + //Skip ',' in the buffer. + while (*PacketDataPtr++ != ','); + + //Parse Address information + while (*PacketDataPtr != ',') { + *AddressBufferPtr++ = *PacketDataPtr++; + } + *AddressBufferPtr = '\0'; + + //Check if Address is not too long. + if (AsciiStrLen(AddressBuffer) >= MAX_ADDR_SIZE) { + Print ((CHAR16 *)L"Address too long..\n"); + return 40; //EMSGSIZE: Message size too long. + } + + *Address = AsciiStrHexToUintn (AddressBuffer); + + PacketDataPtr++; //This skips , in the buffer + + //Parse Length information + *Length = AsciiStrHexToUintn (PacketDataPtr); + + //Length should be 1, 2 or 4 bytes + if (*Length > 4) { + Print ((CHAR16 *)L"Length is invalid\n"); + return 22; //EINVAL: Invalid argument + } + + return 0; //0 = No error +} + +UINTN +gXferObjectReadResponse ( + IN CHAR8 Type, + IN CHAR8 *Str + ) +{ + CHAR8 *OutBufPtr; // pointer to the output buffer + CHAR8 Char; + UINTN Count; + + // responce starts with 'm' or 'l' if it is the end + OutBufPtr = gOutBuffer; + *OutBufPtr++ = Type; + Count = 1; + + // Binary data encoding + OutBufPtr = gOutBuffer; + while (*Str != '\0') { + Char = *Str++; + if ((Char == 0x7d) || (Char == 0x23) || (Char == 0x24) || (Char == 0x2a)) { + // escape character + *OutBufPtr++ = 0x7d; + + Char ^= 0x20; + } + *OutBufPtr++ = Char; + Count++; + } + + *OutBufPtr = '\0' ; // the end of the buffer + SendPacket (gOutBuffer); + + return Count; +} + + +/** + Note: This should be a library function. In the Apple case you have to add + the size of the PE/COFF header into the starting address to make things work + right as there is no way to pad the Mach-O for the size of the PE/COFF header. + + + Returns a pointer to the PDB file name for a PE/COFF image that has been + loaded into system memory with the PE/COFF Loader Library functions. + + Returns the PDB file name for the PE/COFF image specified by Pe32Data. If + the PE/COFF image specified by Pe32Data is not a valid, then NULL is + returned. If the PE/COFF image specified by Pe32Data does not contain a + debug directory entry, then NULL is returned. If the debug directory entry + in the PE/COFF image specified by Pe32Data does not contain a PDB file name, + then NULL is returned. + If Pe32Data is NULL, then ASSERT(). + + @param Pe32Data Pointer to the PE/COFF image that is loaded in system + memory. + @param DebugBase Address that the debugger would use as the base of the image + + @return The PDB file name for the PE/COFF image specified by Pe32Data or NULL + if it cannot be retrieved. DebugBase is only valid if PDB file name is + valid. + +**/ +VOID * +EFIAPI +PeCoffLoaderGetDebuggerInfo ( + IN VOID *Pe32Data, + OUT VOID **DebugBase + ) +{ + EFI_IMAGE_DOS_HEADER *DosHdr; + EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; + EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry; + EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry; + UINTN DirCount; + VOID *CodeViewEntryPointer; + INTN TEImageAdjust; + UINT32 NumberOfRvaAndSizes; + UINT16 Magic; + UINTN SizeOfHeaders; + + ASSERT (Pe32Data != NULL); + + TEImageAdjust = 0; + DirectoryEntry = NULL; + DebugEntry = NULL; + NumberOfRvaAndSizes = 0; + SizeOfHeaders = 0; + + DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data; + if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) { + // + // DOS image header is present, so read the PE header after the DOS image header. + // + Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff)); + } else { + // + // DOS image header is not present, so PE header is at the image base. + // + Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data; + } + + if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) { + if (Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) { + DirectoryEntry = &Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG]; + TEImageAdjust = sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize; + DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN) Hdr.Te + + Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress + + TEImageAdjust); + } + SizeOfHeaders = sizeof (EFI_TE_IMAGE_HEADER) + (UINTN)Hdr.Te->BaseOfCode - (UINTN)Hdr.Te->StrippedSize; + + // __APPLE__ check this math... + *DebugBase = ((CHAR8 *)Pe32Data) - TEImageAdjust; + } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) { + + *DebugBase = Pe32Data; + + + // + // NOTE: We use Machine field to identify PE32/PE32+, instead of Magic. + // It is due to backward-compatibility, for some system might + // generate PE32+ image with PE32 Magic. + // + switch (Hdr.Pe32->FileHeader.Machine) { + case EFI_IMAGE_MACHINE_IA32: + // + // Assume PE32 image with IA32 Machine field. + // + Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC; + break; + case EFI_IMAGE_MACHINE_X64: + case EFI_IMAGE_MACHINE_IA64: + // + // Assume PE32+ image with X64 or IPF Machine field + // + Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC; + break; + default: + // + // For unknow Machine field, use Magic in optional Header + // + Magic = Hdr.Pe32->OptionalHeader.Magic; + } + + if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + // + // Use PE32 offset get Debug Directory Entry + // + SizeOfHeaders = Hdr.Pe32->OptionalHeader.SizeOfHeaders; + NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes; + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]); + DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) Pe32Data + DirectoryEntry->VirtualAddress); + } else if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + // + // Use PE32+ offset get Debug Directory Entry + // + SizeOfHeaders = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders; + NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes; + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]); + DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) Pe32Data + DirectoryEntry->VirtualAddress); + } + + if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) { + DirectoryEntry = NULL; + DebugEntry = NULL; + } + } else { + return NULL; + } + + if (DebugEntry == NULL || DirectoryEntry == NULL) { + return NULL; + } + + for (DirCount = 0; DirCount < DirectoryEntry->Size; DirCount += sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY), DebugEntry++) { + if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) { + if (DebugEntry->SizeOfData > 0) { + CodeViewEntryPointer = (VOID *) ((UINTN) DebugEntry->RVA + ((UINTN)Pe32Data) + (UINTN)TEImageAdjust); + switch (* (UINT32 *) CodeViewEntryPointer) { + case CODEVIEW_SIGNATURE_NB10: + return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY)); + case CODEVIEW_SIGNATURE_RSDS: + return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY)); + case CODEVIEW_SIGNATURE_MTOC: + *DebugBase = (VOID *)(UINTN)((UINTN)DebugBase + SizeOfHeaders); + return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY)); + default: + break; + } + } + } + } + + (void)SizeOfHeaders; + return NULL; +} + + + +/** + Process "qXfer:object:read:annex:offset,length" request. + + Returns an XML document that contains loaded libraries. In our case it is + infomration in the EFI Debug Inmage Table converted into an XML document. + + GDB will call with an arbitrary length (it can't know the real length and + will reply with chunks of XML that are easy for us to deal with. Gdb will + keep calling until we say we are done. XML doc looks like: + + + + + + + + Since we can not allocate memory in interupt context this module has + assumptions about how it will get called: + 1) Length will generally be max remote packet size (big enough) + 2) First Offset of an XML document read needs to be 0 + 3) This code will return back small chunks of the XML document on every read. + Each subseqent call will ask for the next availble part of the document. + + Note: The only variable size element in the XML is: + " \n" and it is + based on the file path and name of the symbol file. If the symbol file name + is bigger than the max gdb remote packet size we could update this code + to respond back in chunks. + + @param Offset offset into special data area + @param Length number of bytes to read starting at Offset + + **/ +VOID +QxferLibrary ( + IN UINTN Offset, + IN UINTN Length + ) +{ + VOID *LoadAddress; + CHAR8 *Pdb; + UINTN Size; + + if (Offset != gPacketqXferLibraryOffset) { + SendError (GDB_EINVALIDARG); + Print (L"\nqXferLibrary (%d, %d) != %d\n", Offset, Length, gPacketqXferLibraryOffset); + + // Force a retry from the beginning + gPacketqXferLibraryOffset = 0; + return; + } + + if (Offset == 0) { + gPacketqXferLibraryOffset += gXferObjectReadResponse ('m', "\n"); + + // The owner of the table may have had to ralloc it so grab a fresh copy every time + // we assume qXferLibrary will get called over and over again until the entire XML table is + // returned in a tight loop. Since we are in the debugger the table should not get updated + gDebugTable = gDebugImageTableHeader->EfiDebugImageInfoTable; + gEfiDebugImageTableEntry = 0; + return; + } + + if (gDebugTable != NULL) { + for (; gEfiDebugImageTableEntry < gDebugImageTableHeader->TableSize; gEfiDebugImageTableEntry++, gDebugTable++) { + if (gDebugTable->NormalImage != NULL) { + if ((gDebugTable->NormalImage->ImageInfoType == EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL) && + (gDebugTable->NormalImage->LoadedImageProtocolInstance != NULL)) { + Pdb = PeCoffLoaderGetDebuggerInfo ( + gDebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase, + &LoadAddress + ); + if (Pdb != NULL) { + Size = AsciiSPrint ( + gXferLibraryBuffer, + sizeof (gXferLibraryBuffer), + " \n", + Pdb, + LoadAddress + ); + if ((Size != 0) && (Size != (sizeof (gXferLibraryBuffer) - 1))) { + gPacketqXferLibraryOffset += gXferObjectReadResponse ('m', gXferLibraryBuffer); + + // Update loop variables so we are in the right place when we get back + gEfiDebugImageTableEntry++; + gDebugTable++; + return; + } else { + // We could handle entires larger than sizeof (gXferLibraryBuffer) here if + // needed by breaking up into N packets + // " (fixed size) + // + // But right now we just skip any entry that is too big + } + } + } + } + } + } + + + gXferObjectReadResponse ('l', "\n"); + gPacketqXferLibraryOffset = 0; + return; +} + + +/** + Exception Hanldler for GDB. It will be called for all exceptions + registered via the gExceptionType[] array. + + @param ExceptionType Exception that is being processed + @param SystemContext Register content at time of the exception + **/ +VOID +EFIAPI +GdbExceptionHandler ( + IN EFI_EXCEPTION_TYPE ExceptionType, + IN OUT EFI_SYSTEM_CONTEXT SystemContext + ) +{ + UINT8 GdbExceptionType; + CHAR8 *Ptr; + + + if (ValidateException(ExceptionType, SystemContext) == FALSE) { + return; + } + + RemoveSingleStep (SystemContext); + + GdbExceptionType = ConvertEFItoGDBtype (ExceptionType); + GdbSendTSignal (SystemContext, GdbExceptionType); + + for( ; ; ) { + ReceivePacket (gInBuffer, MAX_BUF_SIZE); + + switch (gInBuffer[0]) { + case '?': + GdbSendTSignal (SystemContext, GdbExceptionType); + break; + + case 'c': + ContinueAtAddress (SystemContext, gInBuffer); + return; + + case 'g': + ReadGeneralRegisters (SystemContext); + break; + + case 'G': + WriteGeneralRegisters (SystemContext, gInBuffer); + break; + + case 'H': + //Return "OK" packet since we don't have more than one thread. + SendSuccess (); + break; + + case 'm': + ReadFromMemory (gInBuffer); + break; + + case 'M': + WriteToMemory (gInBuffer); + break; + + case 'P': + WriteNthRegister (SystemContext, gInBuffer); + break; + + // + // Still debugging this code. Not used in Darwin + // + case 'q': + // General Query Packets + if (AsciiStrnCmp (gInBuffer, "qSupported", 10) == 0) { + // return what we currently support, we don't parse what gdb suports + AsciiSPrint (gOutBuffer, MAX_BUF_SIZE, "qXfer:libraries:read+;PacketSize=%d", MAX_BUF_SIZE); + SendPacket (gOutBuffer); + } else if (AsciiStrnCmp (gInBuffer, "qXfer:libraries:read::", 22) == 0) { + // ‘qXfer:libraries:read::offset,length + // gInBuffer[22] is offset string, ++Ptr is length string’ + for (Ptr = &gInBuffer[22]; *Ptr != ','; Ptr++); + + // Not sure if multi-radix support is required. Currently only support decimal + QxferLibrary (AsciiStrHexToUintn (&gInBuffer[22]), AsciiStrHexToUintn (++Ptr)); + } if (AsciiStrnCmp (gInBuffer, "qOffsets", 10) == 0) { + AsciiSPrint (gOutBuffer, MAX_BUF_SIZE, "Text=1000;Data=f000;Bss=f000"); + SendPacket (gOutBuffer); + } else { + //Send empty packet + SendNotSupported (); + } + break; + + case 's': + SingleStep (SystemContext, gInBuffer); + return; + + case 'z': + RemoveBreakPoint (SystemContext, gInBuffer); + break; + + case 'Z': + InsertBreakPoint (SystemContext, gInBuffer); + break; + + default: + //Send empty packet + SendNotSupported (); + break; + } + } +} + + +/** + Periodic callback for GDB. This function is used to catch a ctrl-c or other + break in type command from GDB. + + @param SystemContext Register content at time of the call + **/ +VOID +EFIAPI +GdbPeriodicCallBack ( + IN OUT EFI_SYSTEM_CONTEXT SystemContext + ) +{ + // + // gCtrlCBreakFlag may have been set from a previous F response package + // and we set the global as we need to process it at a point where we + // can update the system context. If we are in the middle of processing + // a F Packet it is not safe to read the GDB serial stream so we need + // to skip it on this check + // + if (!gCtrlCBreakFlag && !gProcessingFPacket) { + // + // Ctrl-C was not pending so grab any pending characters and see if they + // are a Ctrl-c (0x03). If so set the Ctrl-C global. + // + while (TRUE) { + if (!GdbIsCharAvailable ()) { + // + // No characters are pending so exit the loop + // + break; + } + + if (GdbGetChar () == 0x03) { + gCtrlCBreakFlag = TRUE; + // + // We have a ctrl-c so exit the loop + // + break; + } + } + } + + if (gCtrlCBreakFlag) { + // + // Update the context to force a single step trap when we exit the GDB + // stub. This will trasfer control to GdbExceptionHandler () and let + // us break into the program. We don't want to break into the GDB stub. + // + AddSingleStep (SystemContext); + gCtrlCBreakFlag = FALSE; + } +} diff --git a/EmbeddedPkg/GdbStub/GdbStub.inf b/EmbeddedPkg/GdbStub/GdbStub.inf new file mode 100644 index 0000000000..2b54f0abef --- /dev/null +++ b/EmbeddedPkg/GdbStub/GdbStub.inf @@ -0,0 +1,78 @@ +#%HEADER% +#/** @file +# UEFI GDB stub +# +# This is a shell application that will display Hello World. +# Copyright (c) 2008, Apple, Inc. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = GdbStub + FILE_GUID = 1F2CCB4F-D817-404E-98E7-80E4851FB33E + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = GdbStubEntry + +[Sources.common] + GdbStub.c + SerialIo.c + +[Sources.ARM] + Arm/Processor.c + +[Sources.IA32] + Ia32/Processor.c + +[Sources.X64] + X64/Processor.c + + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + +[LibraryClasses] + BaseLib + DebugLib + UefiLib + UefiDriverEntryPoint + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + BaseMemoryLib + MemoryAllocationLib + DevicePathLib + PcdLib + GdbSerialLib + PrintLib + CacheMaintenanceLib + + +[Protocols] + gEfiDebugSupportProtocolGuid + gEfiDebugPortProtocolGuid + gEfiSerialIoProtocolGuid + +[Guids] + gEfiDebugImageInfoTableGuid + +[FeaturePcd.common] + gEmbeddedTokenSpaceGuid.PcdGdbSerial + +[FixedPcd.common] + gEmbeddedTokenSpaceGuid.PcdGdbMaxPacketRetryCount diff --git a/EmbeddedPkg/GdbStub/GdbStubInternal.h b/EmbeddedPkg/GdbStub/GdbStubInternal.h new file mode 100644 index 0000000000..20231cff82 --- /dev/null +++ b/EmbeddedPkg/GdbStub/GdbStubInternal.h @@ -0,0 +1,746 @@ +/** @file + Private include file for GDB stub + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __GDB_STUB_INTERNAL__ +#define __GDB_STUB_INTERNAL__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +extern CONST CHAR8 mHexToStr[]; + +// maximum size of input and output buffers +// This value came from the show remote command of the gdb we tested against +#define MAX_BUF_SIZE 2000 + +// maximum size of address buffer +#define MAX_ADDR_SIZE 32 + +// maximum size of register number buffer +#define MAX_REG_NUM_BUF_SIZE 32 + +// maximum size of length buffer +#define MAX_LENGTH_SIZE 32 + +// maximum size of T signal members +#define MAX_T_SIGNAL_SIZE 64 + +// the mask used to clear all the cache +#define TF_BIT 0x00000100 + + +// +// GDB Signal definitions - generic names for interrupts +// +#define GDB_SIGILL 4 // Illegal instruction +#define GDB_SIGTRAP 5 // Trace Trap (Breakpoint and SingleStep) +#define GDB_SIGEMT 7 // Emulator Trap +#define GDB_SIGFPE 8 // Floating point exception +#define GDB_SIGSEGV 11 // Setgment violation, page fault + + +// +// GDB File I/O Error values, zero means no error +// Includes all general GDB Unix like error values +// +#define GDB_EBADMEMADDRBUFSIZE 11 // the buffer that stores memory Address to be read from/written to is not the right size +#define GDB_EBADMEMLENGBUFSIZE 12 // the buffer that stores Length is not the right size +#define GDB_EBADMEMLENGTH 13 // Length, the given number of bytes to read or write, is not the right size +#define GDB_EBADMEMDATA 14 // one of the bytes or nibbles of the memory is leess than 0 +#define GDB_EBADMEMDATASIZE 15 // the memory data, 'XX..', is too short or too long +#define GDB_EBADBUFSIZE 21 // the buffer created is not the correct size +#define GDB_EINVALIDARG 31 // argument is invalid +#define GDB_ENOSPACE 41 // +#define GDB_EINVALIDBRKPOINTTYPE 51 // the breakpoint type is not recognized +#define GDB_EINVALIDREGNUM 61 // given register number is not valid: either <0 or >=Number of Registers +#define GDB_EUNKNOWN 255 // unknown + + +// +// These devices are open by GDB so we can just read and write to them +// +#define GDB_STDIN 0x00 +#define GDB_STDOUT 0x01 +#define GDB_STDERR 0x02 + +// +//Define Register size for different architectures +// +#if defined (MDE_CPU_IA32) +#define REG_SIZE 32 +#elif defined (MDE_CPU_X64) +#define REG_SIZE 64 +#elif defined (MDE_CPU_ARM) +#define REG_SIZE 32 +#endif + +#define GDB_SERIAL_DEV_SIGNATURE SIGNATURE_32 ('g', 'd', 'b', 's') + +typedef struct { + VENDOR_DEVICE_PATH VendorDevice; + UINT32 Index; // Suport more than one + EFI_DEVICE_PATH_PROTOCOL End; +} GDB_SERIAL_DEVICE_PATH; + +// +// Name: SERIAL_DEV +// Purpose: To provide device specific information +// Fields: +// Signature UINTN: The identity of the serial device +// SerialIo SERIAL_IO_PROTOCOL: Serial I/O protocol interface +// SerialMode SERIAL_IO_MODE: +// DevicePath EFI_DEVICE_PATH_PROTOCOL *: Device path of the serial device +// +typedef struct { + UINTN Signature; + EFI_HANDLE Handle; + EFI_SERIAL_IO_PROTOCOL SerialIo; + EFI_SERIAL_IO_MODE SerialMode; + GDB_SERIAL_DEVICE_PATH DevicePath; + INTN InFileDescriptor; + INTN OutFileDescriptor; +} GDB_SERIAL_DEV; + + +#define GDB_SERIAL_DEV_FROM_THIS(a) CR (a, GDB_SERIAL_DEV, SerialIo, GDB_SERIAL_DEV_SIGNATURE) + + +typedef struct { + EFI_EXCEPTION_TYPE Exception; + UINT8 SignalNo; +} EFI_EXCEPTION_TYPE_ENTRY; + + +#if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64) + +// +// Byte packed structure for DR6 +// 32-bits on IA-32 +// 64-bits on X64. The upper 32-bits on X64 are reserved +// +typedef union { + struct { + UINT32 B0:1; // Breakpoint condition detected + UINT32 B1:1; // Breakpoint condition detected + UINT32 B2:1; // Breakpoint condition detected + UINT32 B3:1; // Breakpoint condition detected + UINT32 Reserved_1:9; // Reserved + UINT32 BD:1; // Debug register access detected + UINT32 BS:1; // Single step + UINT32 BT:1; // Task switch + UINT32 Reserved_2:16; // Reserved + } Bits; + UINTN UintN; +} IA32_DR6; + +// +// Byte packed structure for DR7 +// 32-bits on IA-32 +// 64-bits on X64. The upper 32-bits on X64 are reserved +// +typedef union { + struct { + UINT32 L0:1; // Local breakpoint enable + UINT32 G0:1; // Global breakpoint enable + UINT32 L1:1; // Local breakpoint enable + UINT32 G1:1; // Global breakpoint enable + UINT32 L2:1; // Local breakpoint enable + UINT32 G2:1; // Global breakpoint enable + UINT32 L3:1; // Local breakpoint enable + UINT32 G3:1; // Global breakpoint enable + UINT32 LE:1; // Local exact breakpoint enable + UINT32 GE:1; // Global exact breakpoint enable + UINT32 Reserved_1:3; // Reserved + UINT32 GD:1; // Global detect enable + UINT32 Reserved_2:2; // Reserved + UINT32 RW0:2; // Read/Write field + UINT32 LEN0:2; // Length field + UINT32 RW1:2; // Read/Write field + UINT32 LEN1:2; // Length field + UINT32 RW2:2; // Read/Write field + UINT32 LEN2:2; // Length field + UINT32 RW3:2; // Read/Write field + UINT32 LEN3:2; // Length field + } Bits; + UINTN UintN; +} IA32_DR7; + +#endif /* if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64) */ + +typedef enum { + InstructionExecution, //Hardware breakpoint + DataWrite, //watch + DataRead, //rwatch + DataReadWrite, //awatch + SoftwareBreakpoint, //Software breakpoint + NotSupported +} BREAK_TYPE; + +// +// Array of exception types that need to be hooked by the debugger +// +extern EFI_EXCEPTION_TYPE_ENTRY gExceptionType[]; + +// +// Set TRUE if F Reply package signals a ctrl-c. We can not process the Ctrl-c +// here we need to wait for the periodic callback to do this. +// +extern BOOLEAN gCtrlCBreakFlag; + +// +// If the periodic callback is called while we are processing an F packet we need +// to let the callback know to not read from the serail stream as it could steal +// characters from the F reponse packet +// +extern BOOLEAN gProcessingFPacket; + + +// The offsets of registers SystemContext. +// The fields in the array are in the gdb ordering. +// +extern UINTN gRegisterOffsets[]; + +/** + Return the number of entries in the gExceptionType[] + + @retval UINTN, the number of entries in the gExceptionType[] array. + **/ +UINTN +MaxEfiException ( + VOID + ); + + +/** + Return the number of entries in the gRegisters[] + + @retval UINTN, the number of entries (registers) in the gRegisters[] array. + **/ +UINTN +MaxRegisterCount ( + VOID + ); + + +/** + Check to see if the ISA is supported. + ISA = Instruction Set Architecture + + @retval TRUE if Isa is supported, + FALSE otherwise. + **/ +BOOLEAN +CheckIsa ( + IN EFI_INSTRUCTION_SET_ARCHITECTURE Isa + ); + + +/** + Send the T signal with the given exception type (in gdb order) and possibly with n:r pairs related to the watchpoints + + @param SystemContext Register content at time of the exception + @param GdbExceptionType GDB exception type + **/ + +VOID +GdbSendTSignal ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINT8 GdbExceptionType + ); + + +/** + Translates the EFI mapping to GDB mapping + + @param EFIExceptionType EFI Exception that is being processed + @retval UINTN that corresponds to EFIExceptionType's GDB exception type number + **/ +UINT8 +ConvertEFItoGDBtype ( + IN EFI_EXCEPTION_TYPE EFIExceptionType + ); + + +/** + Empties the given buffer + @param *Buf pointer to the first element in buffer to be emptied + **/ +VOID +EmptyBuffer ( + IN CHAR8 *Buf + ); + + +/** + Converts an 8-bit Hex Char into a INTN. + + @param Char - the hex character to be converted into UINTN + @retval a INTN, from 0 to 15, that corressponds to Char + -1 if Char is not a hex character + **/ +INTN +HexCharToInt ( + IN CHAR8 Char + ); + + +/** 'E NN' + Send an error with the given error number after converting to hex. + The error number is put into the buffer in hex. '255' is the biggest errno we can send. + ex: 162 will be sent as A2. + + @param errno the error number that will be sent + **/ +VOID +EFIAPI +SendError ( + IN UINT8 ErrorNum + ); + + +/** + Send 'OK' when the function is done executing successfully. + **/ +VOID +SendSuccess ( + VOID + ); + + +/** + Send empty packet to specify that particular command/functionality is not supported. + **/ +VOID +SendNotSupported ( + VOID + ); + +/** ‘p n’ + Reads the n-th register's value into an output buffer and sends it as a packet + @param SystemContext Register content at time of the exception + @param InBuffer This is the input buffer received from gdb server + **/ +VOID +ReadNthRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *InBuffer + ); + + +/** ‘g’ + Reads the general registers into an output buffer and sends it as a packet + @param SystemContext Register content at time of the exception + **/ +VOID +ReadGeneralRegisters ( + IN EFI_SYSTEM_CONTEXT SystemContext + ); + + +/** ‘P n...=r...’ + Writes the new value of n-th register received into the input buffer to the n-th register + @param SystemContext Register content at time of the exception + @param InBuffer This is the input buffer received from gdb server + **/ +VOID +WriteNthRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *InBuffer + ); + + +/** ‘G XX...’ + Writes the new values received into the input buffer to the general registers + @param SystemContext Register content at time of the exception + @param InBuffer Pointer to the input buffer received from gdb server + **/ + +VOID +WriteGeneralRegisters ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *InBuffer + ); + + +/** ‘m addr,length ’ + Find the Length of the area to read and the start addres. Finally, pass them to + another function, TransferFromMemToOutBufAndSend, that will read from that memory space and + send it as a packet. + + @param *PacketData Pointer to Payload data for the packet + **/ +VOID +ReadFromMemory ( + IN CHAR8 *PacketData + ); + + +/** ‘M addr,length :XX...’ + Find the Length of the area in bytes to write and the start addres. Finally, pass them to + another function, TransferFromInBufToMem, that will write to that memory space the info in + the input buffer. + + @param PacketData Pointer to Payload data for the packet + **/ +VOID +WriteToMemory ( + IN CHAR8 *PacketData + ); + + +/** ‘c [addr ]’ + Continue. addr is Address to resume. If addr is omitted, resume at current + Address. + + @param SystemContext Register content at time of the exception + @param *PacketData Pointer to PacketData + **/ + +VOID +ContinueAtAddress ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *PacketData + ); + + +/** ‘s [addr ]’ + Single step. addr is the Address at which to resume. If addr is omitted, resume + at same Address. + + @param SystemContext Register content at time of the exception + @param PacketData Pointer to Payload data for the packet + **/ +VOID +SingleStep ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *PacketData + ); + +/** + Insert Single Step in the SystemContext + + @param SystemContext Register content at time of the exception + **/ +VOID +AddSingleStep ( + IN EFI_SYSTEM_CONTEXT SystemContext + ); + +/** + Remove Single Step in the SystemContext + + @param SystemContext Register content at time of the exception + **/ +VOID +RemoveSingleStep ( + IN EFI_SYSTEM_CONTEXT SystemContext + ); + + +/** + ‘Z1, [addr], [length]’ + ‘Z2, [addr], [length]’ + ‘Z3, [addr], [length]’ + ‘Z4, [addr], [length]’ + + Insert hardware breakpoint/watchpoint at address addr of size length + + @param SystemContext Register content at time of the exception + @param *PacketData Pointer to the Payload data for the packet + +**/ +VOID +EFIAPI +InsertBreakPoint( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *PacketData + ); + + +/** + ‘z1, [addr], [length]’ + ‘z2, [addr], [length]’ + ‘z3, [addr], [length]’ + ‘z4, [addr], [length]’ + + Remove hardware breakpoint/watchpoint at address addr of size length + + @param SystemContext Register content at time of the exception + @param *PacketData Pointer to the Payload data for the packet + +**/ +VOID +EFIAPI +RemoveBreakPoint( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *PacketData + ); + + +/** + Exception Hanldler for GDB. It will be called for all exceptions + registered via the gExceptionType[] array. + + @param ExceptionType Exception that is being processed + @param SystemContext Register content at time of the exception + + **/ +VOID +EFIAPI +GdbExceptionHandler ( + IN EFI_EXCEPTION_TYPE ExceptionType, + IN OUT EFI_SYSTEM_CONTEXT SystemContext + ); + + +/** + Periodic callback for GDB. This function is used to catch a ctrl-c or other + break in type command from GDB. + + @param SystemContext Register content at time of the call + + **/ +VOID +EFIAPI +GdbPeriodicCallBack ( + IN OUT EFI_SYSTEM_CONTEXT SystemContext + ); + + +/** + Make two serail consoles: 1) StdIn and StdOut via GDB. 2) StdErr via GDB. + + These console show up on the remote system running GDB + +**/ + +VOID +GdbInitializeSerialConsole ( + VOID + ); + + +/** + Send a GDB Remote Serial Protocol Packet + + $PacketData#checksum PacketData is passed in and this function adds the packet prefix '$', + the packet teminating character '#' and the two digit checksum. + + If an ack '+' is not sent resend the packet, but timeout eventually so we don't end up + in an infinit loop. This is so if you unplug the debugger code just keeps running + + @param PacketData Payload data for the packet + + @retval Number of bytes of packet data sent. + +**/ +UINTN +SendPacket ( + IN CHAR8 *PacketData + ); + + +/** + Receive a GDB Remote Serial Protocol Packet + + $PacketData#checksum PacketData is passed in and this function adds the packet prefix '$', + the packet teminating character '#' and the two digit checksum. + + If host re-starts sending a packet without ending the previous packet, only the last valid packet is proccessed. + (In other words, if received packet is '$12345$12345$123456#checksum', only '$123456#checksum' will be processed.) + + If an ack '+' is not sent resend the packet + + @param PacketData Payload data for the packet + + @retval Number of bytes of packet data received. + + **/ +UINTN +ReceivePacket ( + OUT CHAR8 *PacketData, + IN UINTN PacketDataSize + ); + + +/** + Read data from a FileDescriptor. On success number of bytes read is returned. Zero indicates + the end of a file. On error -1 is returned. If count is zero, GdbRead returns zero. + + @param FileDescriptor Device to talk to. + @param Buffer Buffer to hold Count bytes that were read + @param Count Number of bytes to transfer. + + @retval -1 Error + @retval {other} Number of bytes read. + +**/ +INTN +GdbRead ( + IN INTN FileDescriptor, + OUT VOID *Buffer, + IN UINTN Count + ); + + +/** + Write data to a FileDescriptor. On success number of bytes written is returned. Zero indicates + nothing was written. On error -1 is returned. + + @param FileDescriptor Device to talk to. + @param Buffer Buffer to hold Count bytes that are to be written + @param Count Number of bytes to transfer. + + @retval -1 Error + @retval {other} Number of bytes written. + +**/ +INTN +GdbWrite ( + IN INTN FileDescriptor, + OUT CONST VOID *Buffer, + IN UINTN Count + ); + +UINTN * +FindPointerToRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN RegNumber + ); + +CHAR8 * +BasicReadRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN RegNumber, + IN CHAR8 *OutBufPtr + ); + +VOID +TransferFromInBufToMem ( + IN UINTN Length, + IN UINT8 *Address, + IN CHAR8 *NewData + ); + +VOID +TransferFromMemToOutBufAndSend ( + IN UINTN Length, + IN UINT8 *Address + ); + +CHAR8 * +BasicWriteRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN RegNumber, + IN CHAR8 *InBufPtr + ); + +VOID +PrintReg ( + EFI_SYSTEM_CONTEXT SystemContext + ); + +UINTN +ParseBreakpointPacket ( + IN CHAR8 *PacketData, + OUT UINTN *Type, + OUT UINTN *Address, + OUT UINTN *Length + ); + +UINTN +GetBreakpointDataAddress ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN BreakpointNumber + ); + +UINTN +GetBreakpointDetected ( + IN EFI_SYSTEM_CONTEXT SystemContext + ); + +BREAK_TYPE +GetBreakpointType ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN BreakpointNumber + ); + +UINTN +ConvertLengthData ( + IN UINTN Length + ); + +EFI_STATUS +FindNextFreeDebugRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + OUT UINTN *Register + ); + +EFI_STATUS +EnableDebugRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN Register, + IN UINTN Address, + IN UINTN Length, + IN UINTN Type + ); + +EFI_STATUS +FindMatchingDebugRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN Address, + IN UINTN Length, + IN UINTN Type, + OUT UINTN *Register + ); + +EFI_STATUS +DisableDebugRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN Register + ); + +VOID +InitializeProcessor ( + VOID + ); + +BOOLEAN +ValidateAddress ( + IN VOID *Address + ); + +BOOLEAN +ValidateException ( + IN EFI_EXCEPTION_TYPE ExceptionType, + IN OUT EFI_SYSTEM_CONTEXT SystemContext + ); + +#endif diff --git a/EmbeddedPkg/GdbStub/Ia32/Processor.c b/EmbeddedPkg/GdbStub/Ia32/Processor.c new file mode 100644 index 0000000000..90a2224edf --- /dev/null +++ b/EmbeddedPkg/GdbStub/Ia32/Processor.c @@ -0,0 +1,993 @@ +/** @file + Processor specific parts of the GDB stub + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +// +// Array of exception types that need to be hooked by the debugger +// {EFI mapping, GDB mapping} +// +EFI_EXCEPTION_TYPE_ENTRY gExceptionType[] = { + { EXCEPT_IA32_DIVIDE_ERROR, GDB_SIGFPE }, + { EXCEPT_IA32_DEBUG, GDB_SIGTRAP }, + { EXCEPT_IA32_NMI, GDB_SIGEMT }, + { EXCEPT_IA32_BREAKPOINT, GDB_SIGTRAP }, + { EXCEPT_IA32_OVERFLOW, GDB_SIGSEGV }, + { EXCEPT_IA32_BOUND, GDB_SIGSEGV }, + { EXCEPT_IA32_INVALID_OPCODE, GDB_SIGILL }, + { EXCEPT_IA32_DOUBLE_FAULT, GDB_SIGEMT }, + { EXCEPT_IA32_STACK_FAULT, GDB_SIGSEGV }, + { EXCEPT_IA32_GP_FAULT, GDB_SIGSEGV }, + { EXCEPT_IA32_PAGE_FAULT, GDB_SIGSEGV }, + { EXCEPT_IA32_FP_ERROR, GDB_SIGEMT }, + { EXCEPT_IA32_ALIGNMENT_CHECK, GDB_SIGEMT }, + { EXCEPT_IA32_MACHINE_CHECK, GDB_SIGEMT } +}; + + +// The offsets of registers SystemContext. +// The fields in the array are in the gdb ordering. +// +//16 regs +UINTN gRegisterOffsets[] = { + OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Eax), + OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Ecx), + OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Edx), + OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Ebx), + OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Esp), + OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Ebp), + OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Esi), + OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Edi), + OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Eip), + OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Eflags), + OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Cs), + OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Ss), + OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Ds), + OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Es), + OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Fs), + OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Gs) +}; + + +//Debug only.. +VOID +PrintReg ( + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + Print ((CHAR16 *)L"EAX: %x ", SystemContext.SystemContextIa32->Eax); + Print ((CHAR16 *)L"ECX: %x ", SystemContext.SystemContextIa32->Ecx); + Print ((CHAR16 *)L"EDX: %x ", SystemContext.SystemContextIa32->Edx); + Print ((CHAR16 *)L"EBX: %x ", SystemContext.SystemContextIa32->Ebx); + Print ((CHAR16 *)L"ESP: %x ", SystemContext.SystemContextIa32->Esp); + Print ((CHAR16 *)L"EBP: %x ", SystemContext.SystemContextIa32->Ebp); + Print ((CHAR16 *)L"ESI: %x ", SystemContext.SystemContextIa32->Esi); + Print ((CHAR16 *)L"EDI: %x ", SystemContext.SystemContextIa32->Edi); + Print ((CHAR16 *)L"EIP: %x\n", SystemContext.SystemContextIa32->Eip); + Print ((CHAR16 *)L"EFlags: %x\n", SystemContext.SystemContextIa32->Eflags); +} + +//Debug only.. +VOID +PrintDRreg ( + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + Print ((CHAR16 *)L"DR0: %x ", SystemContext.SystemContextIa32->Dr0); + Print ((CHAR16 *)L"DR1: %x ", SystemContext.SystemContextIa32->Dr1); + Print ((CHAR16 *)L"DR2: %x ", SystemContext.SystemContextIa32->Dr2); + Print ((CHAR16 *)L"DR3: %x ", SystemContext.SystemContextIa32->Dr3); + Print ((CHAR16 *)L"DR6: %x ", SystemContext.SystemContextIa32->Dr6); + Print ((CHAR16 *)L"DR7: %x\n", SystemContext.SystemContextIa32->Dr7); +} + + +/** + Return the number of entries in the gExceptionType[] + + @retval UINTN, the number of entries in the gExceptionType[] array. + **/ +UINTN +MaxEfiException ( + VOID + ) +{ + return sizeof (gExceptionType)/sizeof (EFI_EXCEPTION_TYPE_ENTRY); +} + + +/** + Return the number of entries in the gRegisters[] + + @retval UINTN, the number of entries (registers) in the gRegisters[] array. + **/ +UINTN +MaxRegisterCount ( + VOID + ) +{ + return sizeof (gRegisterOffsets)/sizeof (UINTN); +} + + +/** + Check to see if the ISA is supported. + ISA = Instruction Set Architecture + + @retval TRUE if Isa is supported, + FALSE otherwise. +**/ +BOOLEAN +CheckIsa ( + IN EFI_INSTRUCTION_SET_ARCHITECTURE Isa + ) +{ + return (BOOLEAN)(Isa == IsaIa32); +} + + +/** + This takes in the register number and the System Context, and returns a pointer to the RegNumber-th register in gdb ordering + It is, by default, set to find the register pointer of the IA32 member + + @param SystemContext Register content at time of the exception + @param RegNumber The register to which we want to find a pointer + @retval the pointer to the RegNumber-th pointer + **/ +UINTN * +FindPointerToRegister( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN RegNumber + ) +{ + UINT8 *TempPtr; + TempPtr = ((UINT8 *)SystemContext.SystemContextIa32) + gRegisterOffsets[RegNumber]; + return (UINTN *)TempPtr; +} + + +/** + Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr + + @param SystemContext Register content at time of the exception + @param RegNumber the number of the register that we want to read + @param OutBufPtr pointer to the output buffer's end. the new data will be added from this point on. + @retval the pointer to the next character of the output buffer that is available to be written on. + **/ +CHAR8 * +BasicReadRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN RegNumber, + IN CHAR8 *OutBufPtr + ) +{ + UINTN RegSize; + + RegSize = 0; + while (RegSize < REG_SIZE) { + *OutBufPtr++ = mHexToStr[((*FindPointerToRegister(SystemContext, RegNumber) >> (RegSize+4)) & 0xf)]; + *OutBufPtr++ = mHexToStr[((*FindPointerToRegister(SystemContext, RegNumber) >> RegSize) & 0xf)]; + RegSize = RegSize + 8; + } + return OutBufPtr; +} + + +/** ‘p n’ + Reads the n-th register's value into an output buffer and sends it as a packet + + @param SystemContext Register content at time of the exception + @param InBuffer Pointer to the input buffer received from gdb server + **/ +VOID +EFIAPI +ReadNthRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *InBuffer + ) +{ + UINTN RegNumber; + CHAR8 OutBuffer[9]; // 1 reg=8 hex chars, and the end '\0' (escape seq) + CHAR8 *OutBufPtr; // pointer to the output buffer + + RegNumber = AsciiStrHexToUintn (&InBuffer[1]); + + if ((RegNumber < 0) || (RegNumber >= MaxRegisterCount())) { + SendError (GDB_EINVALIDREGNUM); + return; + } + + OutBufPtr = OutBuffer; + OutBufPtr = BasicReadRegister(SystemContext, RegNumber, OutBufPtr); + + *OutBufPtr = '\0'; // the end of the buffer + SendPacket(OutBuffer); +} + + +/** ‘g’ + Reads the general registers into an output buffer and sends it as a packet + + @param SystemContext Register content at time of the exception + **/ +VOID +EFIAPI +ReadGeneralRegisters ( + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + UINTN i; + CHAR8 OutBuffer[129]; // 16 regs, 8 hex chars each, and the end '\0' (escape seq) + CHAR8 *OutBufPtr; // pointer to the output buffer + + OutBufPtr = OutBuffer; + for(i = 0 ; i < MaxRegisterCount() ; i++) { // there are only 16 registers to read + OutBufPtr = BasicReadRegister(SystemContext, i, OutBufPtr); + } + + *OutBufPtr = '\0'; // the end of the buffer + SendPacket(OutBuffer); +} + + +/** + Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr + + @param SystemContext Register content at time of the exception + @param RegNumber the number of the register that we want to write + @param InBufPtr pointer to the output buffer. the new data will be extracted from the input buffer from this point on. + @retval the pointer to the next character of the input buffer that can be used + **/ +CHAR8 * +BasicWriteRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN RegNumber, + IN CHAR8 *InBufPtr + ) +{ + UINTN RegSize; + UINTN TempValue; // the value transferred from a hex char + UINT32 NewValue; // the new value of the RegNumber-th Register + + NewValue = 0; + RegSize = 0; + while (RegSize < REG_SIZE) { + TempValue = HexCharToInt(*InBufPtr++); + + if (TempValue < 0) { + SendError (GDB_EBADMEMDATA); + return NULL; + } + + NewValue += (TempValue << (RegSize+4)); + TempValue = HexCharToInt(*InBufPtr++); + + if (TempValue < 0) { + SendError (GDB_EBADMEMDATA); + return NULL; + } + + NewValue += (TempValue << RegSize); + RegSize = RegSize + 8; + } + *(FindPointerToRegister(SystemContext, RegNumber)) = NewValue; + return InBufPtr; +} + + +/** ‘P n...=r...’ + Writes the new value of n-th register received into the input buffer to the n-th register + + @param SystemContext Register content at time of the exception + @param InBuffer Ponter to the input buffer received from gdb server + **/ +VOID +EFIAPI +WriteNthRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *InBuffer + ) +{ + UINTN RegNumber; + CHAR8 RegNumBuffer[MAX_REG_NUM_BUF_SIZE]; // put the 'n..' part of the message into this array + CHAR8 *RegNumBufPtr; + CHAR8 *InBufPtr; // pointer to the input buffer + + // find the register number to write + InBufPtr = &InBuffer[1]; + RegNumBufPtr = RegNumBuffer; + while (*InBufPtr != '=') { + *RegNumBufPtr++ = *InBufPtr++; + } + *RegNumBufPtr = '\0'; + RegNumber = AsciiStrHexToUintn (RegNumBuffer); + + // check if this is a valid Register Number + if ((RegNumber < 0) || (RegNumber >= MaxRegisterCount())) { + SendError (GDB_EINVALIDREGNUM); + return; + } + InBufPtr++; // skips the '=' character + BasicWriteRegister (SystemContext, RegNumber, InBufPtr); + SendSuccess(); +} + + +/** ‘G XX...’ + Writes the new values received into the input buffer to the general registers + + @param SystemContext Register content at time of the exception + @param InBuffer Pointer to the input buffer received from gdb server + **/ +VOID +EFIAPI +WriteGeneralRegisters ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *InBuffer + ) +{ + UINTN i; + CHAR8 *InBufPtr; /// pointer to the input buffer + + // check to see if the buffer is the right size which is + // 1 (for 'G') + 16 (for 16 registers) * 8 ( for 8 hex chars each) = 129 + if (AsciiStrLen(InBuffer) != 129) { // 16 regs, 8 hex chars each, and the end '\0' (escape seq) + //Bad message. Message is not the right length + SendError (GDB_EBADBUFSIZE); + return; + } + + InBufPtr = &InBuffer[1]; + + // Read the new values for the registers from the input buffer to an array, NewValueArray. + // The values in the array are in the gdb ordering + for(i=0; i < MaxRegisterCount(); i++) { // there are only 16 registers to write + InBufPtr = BasicWriteRegister(SystemContext, i, InBufPtr); + } + + SendSuccess(); +} + + +/** + Insert Single Step in the SystemContext + + @param SystemContext Register content at time of the exception + **/ +VOID +AddSingleStep ( + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + SystemContext.SystemContextIa32->Eflags |= TF_BIT; //Setting the TF bit. +} + + +/** + Remove Single Step in the SystemContext + + @param SystemContext Register content at time of the exception + **/ +VOID +RemoveSingleStep ( + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + SystemContext.SystemContextIa32->Eflags &= ~TF_BIT; // clearing the TF bit. +} + + + +/** ‘c [addr ]’ + Continue. addr is Address to resume. If addr is omitted, resume at current + Address. + + @param SystemContext Register content at time of the exception + **/ +VOID +EFIAPI +ContinueAtAddress ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *PacketData + ) +{ + if (PacketData[1] != '\0') { + SystemContext.SystemContextIa32->Eip = AsciiStrHexToUintn (&PacketData[1]); + } +} + + +/** ‘s [addr ]’ + Single step. addr is the Address at which to resume. If addr is omitted, resume + at same Address. + + @param SystemContext Register content at time of the exception + **/ +VOID +EFIAPI +SingleStep ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *PacketData + ) +{ + if (PacketData[1] != '\0') { + SystemContext.SystemContextIa32->Eip = AsciiStrHexToUintn (&PacketData[1]); + } + + AddSingleStep (SystemContext); +} + + +/** + Returns breakpoint data address from DR0-DR3 based on the input breakpoint number + + @param SystemContext Register content at time of the exception + @param BreakpointNumber Breakpoint number + + @retval Address Data address from DR0-DR3 based on the breakpoint number. + +**/ +UINTN +GetBreakpointDataAddress ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN BreakpointNumber + ) +{ + UINTN Address; + + if (BreakpointNumber == 1) { + Address = SystemContext.SystemContextIa32->Dr0; + } else if (BreakpointNumber == 2) { + Address = SystemContext.SystemContextIa32->Dr1; + } else if (BreakpointNumber == 3) { + Address = SystemContext.SystemContextIa32->Dr2; + } else if (BreakpointNumber == 4) { + Address = SystemContext.SystemContextIa32->Dr3; + } else { + Address = 0; + } + + return Address; +} + + +/** + Returns currently detected breakpoint value based on the register DR6 B0-B3 field. + If no breakpoint is detected then it returns 0. + + @param SystemContext Register content at time of the exception + + @retval {1-4} Currently detected breakpoint value + @retval 0 No breakpoint detected. + +**/ +UINTN +GetBreakpointDetected ( + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + IA32_DR6 Dr6; + UINTN BreakpointNumber; + + Dr6.UintN = SystemContext.SystemContextIa32->Dr6; + + if (Dr6.Bits.B0 == 1) { + BreakpointNumber = 1; + } else if (Dr6.Bits.B1 == 1) { + BreakpointNumber = 2; + } else if (Dr6.Bits.B2 == 1) { + BreakpointNumber = 3; + } else if (Dr6.Bits.B3 == 1) { + BreakpointNumber = 4; + } else { + BreakpointNumber = 0; //No breakpoint detected + } + + return BreakpointNumber; +} + + +/** + Returns Breakpoint type (InstructionExecution, DataWrite, DataRead or DataReadWrite) + based on the Breakpoint number + + @param SystemContext Register content at time of the exception + @param BreakpointNumber Breakpoint number + + @retval BREAK_TYPE Breakpoint type value read from register DR7 RWn field + For unknown value, it returns NotSupported. + +**/ +BREAK_TYPE +GetBreakpointType ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN BreakpointNumber + ) +{ + IA32_DR7 Dr7; + BREAK_TYPE Type = NotSupported; //Default is NotSupported type + + Dr7.UintN = SystemContext.SystemContextIa32->Dr7; + + if (BreakpointNumber == 1) { + Type = (BREAK_TYPE) Dr7.Bits.RW0; + } else if (BreakpointNumber == 2) { + Type = (BREAK_TYPE) Dr7.Bits.RW1; + } else if (BreakpointNumber == 3) { + Type = (BREAK_TYPE) Dr7.Bits.RW2; + } else if (BreakpointNumber == 4) { + Type = (BREAK_TYPE) Dr7.Bits.RW3; + } + + return Type; +} + + +/** + Parses Length and returns the length which DR7 LENn field accepts. + For example: If we receive 1-Byte length then we should return 0. + Zero gets written to DR7 LENn field. + + @param Length Breakpoint length in Bytes (1 byte, 2 byte, 4 byte) + + @retval Length Appropriate converted values which DR7 LENn field accepts. + +**/ +UINTN +ConvertLengthData ( + IN UINTN Length + ) +{ + if (Length == 1) { //1-Byte length + return 0; + } else if (Length == 2) { //2-Byte length + return 1; + } else if (Length == 4) { //4-Byte length + return 3; + } else { //Undefined or 8-byte length + return 2; + } +} + + +/** + Finds the next free debug register. If all the registers are occupied then + EFI_OUT_OF_RESOURCES is returned. + + @param SystemContext Register content at time of the exception + @param Register Register value (0 - 3 for the first free debug register) + + @retval EFI_STATUS Appropriate status value. + +**/ +EFI_STATUS +FindNextFreeDebugRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + OUT UINTN *Register + ) +{ + IA32_DR7 Dr7; + + Dr7.UintN = SystemContext.SystemContextIa32->Dr7; + + if (Dr7.Bits.G0 == 0) { + *Register = 0; + } else if (Dr7.Bits.G1 == 0) { + *Register = 1; + } else if (Dr7.Bits.G2 == 0) { + *Register = 2; + } else if (Dr7.Bits.G3 == 0) { + *Register = 3; + } else { + return EFI_OUT_OF_RESOURCES; + } + + return EFI_SUCCESS; +} + + +/** + Enables the debug register. Writes Address value to appropriate DR0-3 register. + Sets LENn, Gn, RWn bits in DR7 register. + + @param SystemContext Register content at time of the exception + @param Register Register value (0 - 3) + @param Address Breakpoint address value + @param Type Breakpoint type (Instruction, Data write, Data read + or write etc.) + + @retval EFI_STATUS Appropriate status value. + +**/ +EFI_STATUS +EnableDebugRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN Register, + IN UINTN Address, + IN UINTN Length, + IN UINTN Type + ) +{ + IA32_DR7 Dr7; + + //Convert length data + Length = ConvertLengthData (Length); + + //For Instruction execution, length should be 0 + //(Ref. Intel reference manual 18.2.4) + if ((Type == 0) && (Length != 0)) { + return EFI_INVALID_PARAMETER; + } + + //Hardware doesn't support ReadWatch (z3 packet) type. GDB can handle + //software breakpoint. We should send empty packet in both these cases. + if ((Type == (BREAK_TYPE)DataRead) || + (Type == (BREAK_TYPE)SoftwareBreakpoint)) { + return EFI_UNSUPPORTED; + } + + //Read DR7 so appropriate Gn, RWn and LENn bits can be modified. + Dr7.UintN = SystemContext.SystemContextIa32->Dr7; + + if (Register == 0) { + SystemContext.SystemContextIa32->Dr0 = Address; + Dr7.Bits.G0 = 1; + Dr7.Bits.RW0 = Type; + Dr7.Bits.LEN0 = Length; + } else if (Register == 1) { + SystemContext.SystemContextIa32->Dr1 = Address; + Dr7.Bits.G1 = 1; + Dr7.Bits.RW1 = Type; + Dr7.Bits.LEN1 = Length; + } else if (Register == 2) { + SystemContext.SystemContextIa32->Dr2 = Address; + Dr7.Bits.G2 = 1; + Dr7.Bits.RW2 = Type; + Dr7.Bits.LEN2 = Length; + } else if (Register == 3) { + SystemContext.SystemContextIa32->Dr3 = Address; + Dr7.Bits.G3 = 1; + Dr7.Bits.RW3 = Type; + Dr7.Bits.LEN3 = Length; + } else { + return EFI_INVALID_PARAMETER; + } + + //Update Dr7 with appropriate Gn, RWn and LENn bits + SystemContext.SystemContextIa32->Dr7 = Dr7.UintN; + + return EFI_SUCCESS; +} + + +/** + Returns register number 0 - 3 for the maching debug register. + This function compares incoming Address, Type, Length and + if there is a match then it returns the appropriate register number. + In case of mismatch, function returns EFI_NOT_FOUND message. + + @param SystemContext Register content at time of the exception + @param Address Breakpoint address value + @param Length Breakpoint length value + @param Type Breakpoint type (Instruction, Data write, + Data read or write etc.) + @param Register Register value to be returned + + @retval EFI_STATUS Appropriate status value. + +**/ +EFI_STATUS +FindMatchingDebugRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN Address, + IN UINTN Length, + IN UINTN Type, + OUT UINTN *Register + ) +{ + IA32_DR7 Dr7; + + //Hardware doesn't support ReadWatch (z3 packet) type. GDB can handle + //software breakpoint. We should send empty packet in both these cases. + if ((Type == (BREAK_TYPE)DataRead) || + (Type == (BREAK_TYPE)SoftwareBreakpoint)) { + return EFI_UNSUPPORTED; + } + + //Convert length data + Length = ConvertLengthData(Length); + + Dr7.UintN = SystemContext.SystemContextIa32->Dr7; + + if ((Dr7.Bits.G0 == 1) && + (Dr7.Bits.LEN0 == Length) && + (Dr7.Bits.RW0 == Type) && + (Address == SystemContext.SystemContextIa32->Dr0)) { + *Register = 0; + } else if ((Dr7.Bits.G1 == 1) && + (Dr7.Bits.LEN1 == Length) && + (Dr7.Bits.RW1 == Type) && + (Address == SystemContext.SystemContextIa32->Dr1)) { + *Register = 1; + } else if ((Dr7.Bits.G2 == 1) && + (Dr7.Bits.LEN2 == Length) && + (Dr7.Bits.RW2 == Type) && + (Address == SystemContext.SystemContextIa32->Dr2)) { + *Register = 2; + } else if ((Dr7.Bits.G3 == 1) && + (Dr7.Bits.LEN3 == Length) && + (Dr7.Bits.RW3 == Type) && + (Address == SystemContext.SystemContextIa32->Dr3)) { + *Register = 3; + } else { + Print ((CHAR16 *)L"No match found..\n"); + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + + +/** + Disables the particular debug register. + + @param SystemContext Register content at time of the exception + @param Register Register to be disabled + + @retval EFI_STATUS Appropriate status value. + +**/ +EFI_STATUS +DisableDebugRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN Register + ) +{ + IA32_DR7 Dr7; + UINTN Address = 0; + + //Read DR7 register so appropriate Gn, RWn and LENn bits can be turned off. + Dr7.UintN = SystemContext.SystemContextIa32->Dr7; + + if (Register == 0) { + SystemContext.SystemContextIa32->Dr0 = Address; + Dr7.Bits.G0 = 0; + Dr7.Bits.RW0 = 0; + Dr7.Bits.LEN0 = 0; + } else if (Register == 1) { + SystemContext.SystemContextIa32->Dr1 = Address; + Dr7.Bits.G1 = 0; + Dr7.Bits.RW1 = 0; + Dr7.Bits.LEN1 = 0; + } else if (Register == 2) { + SystemContext.SystemContextIa32->Dr2 = Address; + Dr7.Bits.G2 = 0; + Dr7.Bits.RW2 = 0; + Dr7.Bits.LEN2 = 0; + } else if (Register == 3) { + SystemContext.SystemContextIa32->Dr3 = Address; + Dr7.Bits.G3 = 0; + Dr7.Bits.RW3 = 0; + Dr7.Bits.LEN3 = 0; + } else { + return EFI_INVALID_PARAMETER; + } + + //Update DR7 register so appropriate Gn, RWn and LENn bits can be turned off. + SystemContext.SystemContextIa32->Dr7 = Dr7.UintN; + + return EFI_SUCCESS; +} + + +/** + ‘Z1, [addr], [length]’ + ‘Z2, [addr], [length]’ + ‘Z3, [addr], [length]’ + ‘Z4, [addr], [length]’ + + Insert hardware breakpoint/watchpoint at address addr of size length + + @param SystemContext Register content at time of the exception + @param *PacketData Pointer to the Payload data for the packet + +**/ +VOID +EFIAPI +InsertBreakPoint ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *PacketData + ) +{ + UINTN Type; + UINTN Address; + UINTN Length; + UINTN Register; + EFI_STATUS Status; + BREAK_TYPE BreakType = NotSupported; + UINTN ErrorCode; + + ErrorCode = ParseBreakpointPacket (PacketData, &Type, &Address, &Length); + if (ErrorCode > 0) { + SendError ((UINT8)ErrorCode); + return; + } + + switch (Type) { + + case 0: //Software breakpoint + BreakType = SoftwareBreakpoint; + break; + + case 1: //Hardware breakpoint + BreakType = InstructionExecution; + break; + + case 2: //Write watchpoint + BreakType = DataWrite; + break; + + case 3: //Read watchpoint + BreakType = DataRead; + break; + + case 4: //Access watchpoint + BreakType = DataReadWrite; + break; + + default : + Print ((CHAR16 *)L"Insert breakpoint default: %x\n", Type); + SendError (GDB_EINVALIDBRKPOINTTYPE); + return; + } + + // Find next free debug register + Status = FindNextFreeDebugRegister (SystemContext, &Register); + if (EFI_ERROR(Status)) { + Print ((CHAR16 *)L"No space left on device\n"); + SendError (GDB_ENOSPACE); + return; + } + + // Write Address, length data at particular DR register + Status = EnableDebugRegister (SystemContext, Register, Address, Length, (UINTN)BreakType); + if (EFI_ERROR(Status)) { + + if (Status == EFI_UNSUPPORTED) { + Print ((CHAR16 *)L"Not supported\n"); + SendNotSupported(); + return; + } + + Print ((CHAR16 *)L"Invalid argument\n"); + SendError (GDB_EINVALIDARG); + return; + } + + SendSuccess (); +} + + +/** + ‘z1, [addr], [length]’ + ‘z2, [addr], [length]’ + ‘z3, [addr], [length]’ + ‘z4, [addr], [length]’ + + Remove hardware breakpoint/watchpoint at address addr of size length + + @param *PacketData Pointer to the Payload data for the packet + +**/ +VOID +EFIAPI +RemoveBreakPoint ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *PacketData + ) +{ + UINTN Type; + UINTN Address; + UINTN Length; + UINTN Register; + BREAK_TYPE BreakType = NotSupported; + EFI_STATUS Status; + UINTN ErrorCode; + + //Parse breakpoint packet data + ErrorCode = ParseBreakpointPacket (PacketData, &Type, &Address, &Length); + if (ErrorCode > 0) { + SendError ((UINT8)ErrorCode); + return; + } + + switch (Type) { + + case 0: //Software breakpoint + BreakType = SoftwareBreakpoint; + break; + + case 1: //Hardware breakpoint + BreakType = InstructionExecution; + break; + + case 2: //Write watchpoint + BreakType = DataWrite; + break; + + case 3: //Read watchpoint + BreakType = DataRead; + break; + + case 4: //Access watchpoint + BreakType = DataReadWrite; + break; + + default : + SendError (GDB_EINVALIDBRKPOINTTYPE); + return; + } + + //Find matching debug register + Status = FindMatchingDebugRegister (SystemContext, Address, Length, (UINTN)BreakType, &Register); + if (EFI_ERROR(Status)) { + + if (Status == EFI_UNSUPPORTED) { + Print ((CHAR16 *)L"Not supported.\n"); + SendNotSupported(); + return; + } + + Print ((CHAR16 *)L"No matching register found.\n"); + SendError (GDB_ENOSPACE); + return; + } + + //Remove breakpoint + Status = DisableDebugRegister(SystemContext, Register); + if (EFI_ERROR(Status)) { + Print ((CHAR16 *)L"Invalid argument.\n"); + SendError (GDB_EINVALIDARG); + return; + } + + SendSuccess (); +} + + +VOID +InitializeProcessor ( + VOID + ) +{ +} + +BOOLEAN +ValidateAddress ( + IN VOID *Address + ) +{ + return TRUE; +} + +BOOLEAN +ValidateException ( + IN EFI_EXCEPTION_TYPE ExceptionType, + IN OUT EFI_SYSTEM_CONTEXT SystemContext + ) +{ + return TRUE; +} + diff --git a/EmbeddedPkg/GdbStub/SerialIo.c b/EmbeddedPkg/GdbStub/SerialIo.c new file mode 100644 index 0000000000..5afaed06b9 --- /dev/null +++ b/EmbeddedPkg/GdbStub/SerialIo.c @@ -0,0 +1,551 @@ +/** @file + Serial IO Abstraction for GDB stub. This allows an EFI consoles that shows up on the system + running GDB. One consle for error information and another console for user input/output. + + Basic packet format is $packet-data#checksum. So every comand has 4 bytes of overhead: $, + #, 0, 0. The 0 and 0 are the ascii characters for the checksum. + + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +// +// Set TRUE if F Reply package signals a ctrl-c. We can not process the Ctrl-c +// here we need to wait for the periodic callback to do this. +// +BOOLEAN gCtrlCBreakFlag = FALSE; + +// +// If the periodic callback is called while we are processing an F packet we need +// to let the callback know to not read from the serail stream as it could steal +// characters from the F reponse packet +// +BOOLEAN gProcessingFPacket = FALSE; + +/** + Process a control-C break message. + + Currently a place holder, remove the ASSERT when it gets implemented. + + @param ErrNo Error infomration from the F reply packet or other source + +**/ + +VOID +GdbCtrlCBreakMessage ( + IN UINTN ErrNo + ) +{ + // See D.10.5 of gdb.pdf + // This should look like a break message. Should look like SIGINT + + /* TODO: Make sure if we should do anything with ErrNo */ + //Turn on the global Ctrl-C flag. + gCtrlCBreakFlag = TRUE; +} + + +/** + Parse the F reply packet and extract the return value and an ErrNo if it exists. + + @param Packet Packet to parse like an F reply packet + @param ErrNo Buffer to hold Count bytes that were read + + @retval -1 Error, not a valid F reply packet + @retval other Return the return code from the F reply packet + +**/ +INTN +GdbParseFReplyPacket ( + IN CHAR8 *Packet, + OUT UINTN *ErrNo + ) +{ + INTN RetCode; + + if (Packet[0] != 'F') { + // A valid responce would be an F packet + return -1; + } + + RetCode = AsciiStrHexToUintn (&Packet[1]); + + // Find 1st comma + for (;*Packet != '\0' && *Packet != ','; Packet++); + if (*Packet == '\0') { + *ErrNo = 0; + return RetCode; + } + + *ErrNo = AsciiStrHexToUintn (++Packet); + + // Find 2nd comma + for (;*Packet != '\0' && *Packet != ','; Packet++); + if (*Packet == '\0') { + return RetCode; + } + + if (*(++Packet) == 'C') { + GdbCtrlCBreakMessage (*ErrNo); + } + + return RetCode; +} + + +/** + Read data from a FileDescriptor. On success number of bytes read is returned. Zero indicates + the end of a file. On error -1 is returned. If count is zero, GdbRead returns zero. + + @param FileDescriptor Device to talk to. + @param Buffer Buffer to hold Count bytes that were read + @param Count Number of bytes to transfer. + + @retval -1 Error + @retval {other} Number of bytes read. + +**/ +INTN +GdbRead ( + IN INTN FileDescriptor, + OUT VOID *Buffer, + IN UINTN Count + ) +{ + CHAR8 Packet[128]; + UINTN Size; + INTN RetCode; + UINTN ErrNo; + BOOLEAN ReceiveDone = FALSE; + + // Send: + // "Fread,XX,YYYYYYYY,XX + // + // XX - FileDescriptor in ASCII + // YYYYYYYY - Buffer address in ASCII + // XX - Count in ASCII + // SS - check sum + // + Size = AsciiSPrint (Packet, sizeof (Packet), "Fread,%x,%x,%x", FileDescriptor, Buffer, Count); + // Packet array is too small if you got this ASSERT + ASSERT (Size < sizeof (Packet)); + + gProcessingFPacket = TRUE; + SendPacket (Packet); + Print ((CHAR16 *)L"Packet sent..\n"); + + do { + // Reply: + ReceivePacket (Packet, sizeof (Packet)); + Print ((CHAR16 *)L"Command received..%c\n", Packet[0]); + + // Process GDB commands + switch (Packet[0]) { + //Write memory command. + //M addr,length:XX... + case 'M': + WriteToMemory (Packet); + break; + + //Fretcode, errno, Ctrl-C flag + //retcode - Count read + case 'F': + //Once target receives F reply packet that means the previous + //transactions are finished. + ReceiveDone = TRUE; + break; + + //Send empty buffer + default : + SendNotSupported(); + break; + } + } while (ReceiveDone == FALSE); + + RetCode = GdbParseFReplyPacket (Packet, &ErrNo); + Print ((CHAR16 *)L"RetCode: %x..ErrNo: %x..\n", RetCode, ErrNo); + + if (ErrNo > 0) { + //Send error to the host if there is any. + SendError ((UINT8)ErrNo); + } + + gProcessingFPacket = FALSE; + + return RetCode; +} + + +/** + Write data to a FileDescriptor. On success number of bytes written is returned. Zero indicates + nothing was written. On error -1 is returned. + + @param FileDescriptor Device to talk to. + @param Buffer Buffer to hold Count bytes that are to be written + @param Count Number of bytes to transfer. + + @retval -1 Error + @retval {other} Number of bytes written. + +**/ +INTN +GdbWrite ( + IN INTN FileDescriptor, + OUT CONST VOID *Buffer, + IN UINTN Count + ) +{ + CHAR8 Packet[128]; + UINTN Size; + INTN RetCode; + UINTN ErrNo; + BOOLEAN ReceiveDone = FALSE; + + // Send: + // #Fwrite,XX,YYYYYYYY,XX$SS + // + // XX - FileDescriptor in ASCII + // YYYYYYYY - Buffer address in ASCII + // XX - Count in ASCII + // SS - check sum + // + Size = AsciiSPrint (Packet, sizeof (Packet), "Fwrite,%x,%x,%x", FileDescriptor, Buffer, Count); + // Packet array is too small if you got this ASSERT + ASSERT (Size < sizeof (Packet)); + + SendPacket (Packet); + Print ((CHAR16 *)L"Packet sent..\n"); + + do { + // Reply: + ReceivePacket (Packet, sizeof (Packet)); + Print ((CHAR16 *)L"Command received..%c\n", Packet[0]); + + // Process GDB commands + switch (Packet[0]) { + //Read memory command. + //m addr,length. + case 'm': + ReadFromMemory (Packet); + break; + + //Fretcode, errno, Ctrl-C flag + //retcode - Count read + case 'F': + //Once target receives F reply packet that means the previous + //transactions are finished. + ReceiveDone = TRUE; + break; + + //Send empty buffer + default : + SendNotSupported(); + break; + } + } while (ReceiveDone == FALSE); + + RetCode = GdbParseFReplyPacket (Packet, &ErrNo); + Print ((CHAR16 *)L"RetCode: %x..ErrNo: %x..\n", RetCode, ErrNo); + + //Send error to the host if there is any. + if (ErrNo > 0) { + SendError((UINT8)ErrNo); + } + + return RetCode; +} + + +/** + Reset the serial device. + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS The device was reset. + @retval EFI_DEVICE_ERROR The serial device could not be reset. + +**/ +EFI_STATUS +EFIAPI +GdbSerialReset ( + IN EFI_SERIAL_IO_PROTOCOL *This + ) +{ + return EFI_SUCCESS; +} + + +/** + Sets the baud rate, receive FIFO depth, transmit/receice time out, parity, + data buts, and stop bits on a serial device. + + @param This Protocol instance pointer. + @param BaudRate The requested baud rate. A BaudRate value of 0 will use the the + device's default interface speed. + @param ReveiveFifoDepth The requested depth of the FIFO on the receive side of the + serial interface. A ReceiveFifoDepth value of 0 will use + the device's dfault FIFO depth. + @param Timeout The requested time out for a single character in microseconds. + This timeout applies to both the transmit and receive side of the + interface. A Timeout value of 0 will use the device's default time + out value. + @param Parity The type of parity to use on this serial device. A Parity value of + DefaultParity will use the device's default parity value. + @param DataBits The number of data bits to use on the serial device. A DataBits + vaule of 0 will use the device's default data bit setting. + @param StopBits The number of stop bits to use on this serial device. A StopBits + value of DefaultStopBits will use the device's default number of + stop bits. + + @retval EFI_SUCCESS The device was reset. + @retval EFI_DEVICE_ERROR The serial device could not be reset. + +**/ +EFI_STATUS +EFIAPI +GdbSerialSetAttributes ( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN UINT64 BaudRate, + IN UINT32 ReceiveFifoDepth, + IN UINT32 Timeout, + IN EFI_PARITY_TYPE Parity, + IN UINT8 DataBits, + IN EFI_STOP_BITS_TYPE StopBits + ) +{ + return EFI_UNSUPPORTED; +} + + +/** + Set the control bits on a serial device + + @param This Protocol instance pointer. + @param Control Set the bits of Control that are settable. + + @retval EFI_SUCCESS The new control bits were set on the serial device. + @retval EFI_UNSUPPORTED The serial device does not support this operation. + @retval EFI_DEVICE_ERROR The serial device is not functioning correctly. + +**/ +EFI_STATUS +EFIAPI +GdbSerialSetControl ( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN UINT32 Control + ) +{ + return EFI_UNSUPPORTED; +} + + +/** + Retrieves the status of thecontrol bits on a serial device + + @param This Protocol instance pointer. + @param Control A pointer to return the current Control signals from the serial device. + + @retval EFI_SUCCESS The control bits were read from the serial device. + @retval EFI_DEVICE_ERROR The serial device is not functioning correctly. + +**/ +EFI_STATUS +EFIAPI +GdbSerialGetControl ( + IN EFI_SERIAL_IO_PROTOCOL *This, + OUT UINT32 *Control + ) +{ + return EFI_UNSUPPORTED; +} + + +/** + Writes data to a serial device. + + @param This Protocol instance pointer. + @param BufferSize On input, the size of the Buffer. On output, the amount of + data actually written. + @param Buffer The buffer of data to write + + @retval EFI_SUCCESS The data was written. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_TIMEOUT The data write was stopped due to a timeout. + +**/ +EFI_STATUS +EFIAPI +GdbSerialWrite ( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +{ + GDB_SERIAL_DEV *SerialDev; + UINTN Return; + + SerialDev = GDB_SERIAL_DEV_FROM_THIS (This); + + Return = GdbWrite (SerialDev->OutFileDescriptor, Buffer, *BufferSize); + if (Return == (UINTN)-1) { + return EFI_DEVICE_ERROR; + } + + if (Return != *BufferSize) { + *BufferSize = Return; + } + + return EFI_SUCCESS; +} + +/** + Writes data to a serial device. + + @param This Protocol instance pointer. + @param BufferSize On input, the size of the Buffer. On output, the amount of + data returned in Buffer. + @param Buffer The buffer to return the data into. + + @retval EFI_SUCCESS The data was read. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_TIMEOUT The data write was stopped due to a timeout. + +**/ + +EFI_STATUS +EFIAPI +GdbSerialRead ( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + GDB_SERIAL_DEV *SerialDev; + UINTN Return; + + SerialDev = GDB_SERIAL_DEV_FROM_THIS (This); + + Return = GdbRead (SerialDev->InFileDescriptor, Buffer, *BufferSize); + if (Return == (UINTN)-1) { + return EFI_DEVICE_ERROR; + } + + if (Return != *BufferSize) { + *BufferSize = Return; + } + + return EFI_SUCCESS; +} + + +// +// Template used to initailize the GDB Serial IO protocols +// +GDB_SERIAL_DEV gdbSerialDevTemplate = { + GDB_SERIAL_DEV_SIGNATURE, + NULL, + + { // SerialIo + SERIAL_IO_INTERFACE_REVISION, + GdbSerialReset, + GdbSerialSetAttributes, + GdbSerialSetControl, + GdbSerialGetControl, + GdbSerialWrite, + GdbSerialRead, + NULL + }, + { // SerialMode + 0, // ControlMask + 0, // Timeout + 0, // BaudRate + 1, // RceiveFifoDepth + 0, // DataBits + 0, // Parity + 0 // StopBits + }, + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH) + sizeof (UINT32)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH) + sizeof (UINT32)) >> 8) + }, + EFI_SERIAL_IO_PROTOCOL_GUID, + }, + 0, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8) (sizeof (EFI_DEVICE_PATH_PROTOCOL)), + (UINT8) (sizeof (EFI_DEVICE_PATH_PROTOCOL) >> 8) + } + }, + }, + GDB_STDIN, + GDB_STDOUT +}; + + +/** + Make two serial consoles: 1) StdIn and StdOut via GDB. 2) StdErr via GDB. + + These console show up on the remote system running GDB + +**/ +VOID +GdbInitializeSerialConsole ( + VOID + ) +{ + EFI_STATUS Status; + GDB_SERIAL_DEV *StdOutSerialDev; + GDB_SERIAL_DEV *StdErrSerialDev; + + // Use the template to make a copy of the Serial Console private data structure. + StdOutSerialDev = AllocateCopyPool (sizeof (GDB_SERIAL_DEV), &gdbSerialDevTemplate); + ASSERT (StdOutSerialDev != NULL); + + // Fixup pointer after the copy + StdOutSerialDev->SerialIo.Mode = &StdOutSerialDev->SerialMode; + + StdErrSerialDev = AllocateCopyPool (sizeof (GDB_SERIAL_DEV), &gdbSerialDevTemplate); + ASSERT (StdErrSerialDev != NULL); + + // Fixup pointer and modify stuff that is different for StdError + StdErrSerialDev->SerialIo.Mode = &StdErrSerialDev->SerialMode; + StdErrSerialDev->DevicePath.Index = 1; + StdErrSerialDev->OutFileDescriptor = GDB_STDERR; + + // Make a new handle with Serial IO protocol and its device path on it. + Status = gBS->InstallMultipleProtocolInterfaces ( + &StdOutSerialDev->Handle, + &gEfiSerialIoProtocolGuid, &StdOutSerialDev->SerialIo, + &gEfiDevicePathProtocolGuid, &StdOutSerialDev->DevicePath, + NULL + ); + ASSERT_EFI_ERROR (Status); + + // Make a new handle with Serial IO protocol and its device path on it. + Status = gBS->InstallMultipleProtocolInterfaces ( + &StdErrSerialDev->Handle, + &gEfiSerialIoProtocolGuid, &StdErrSerialDev->SerialIo, + &gEfiDevicePathProtocolGuid, &StdErrSerialDev->DevicePath, + NULL + ); + ASSERT_EFI_ERROR (Status); +} + diff --git a/EmbeddedPkg/GdbStub/X64/Processor.c b/EmbeddedPkg/GdbStub/X64/Processor.c new file mode 100644 index 0000000000..0758bc4a84 --- /dev/null +++ b/EmbeddedPkg/GdbStub/X64/Processor.c @@ -0,0 +1,963 @@ +/** @file + Processor specific parts of the GDB stub + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +// +// Array of exception types that need to be hooked by the debugger +// +EFI_EXCEPTION_TYPE_ENTRY gExceptionType[] = { + { EXCEPT_X64_DIVIDE_ERROR, GDB_SIGFPE }, + { EXCEPT_X64_DEBUG, GDB_SIGTRAP }, + { EXCEPT_X64_NMI, GDB_SIGEMT }, + { EXCEPT_X64_BREAKPOINT, GDB_SIGTRAP }, + { EXCEPT_X64_OVERFLOW, GDB_SIGSEGV }, + { EXCEPT_X64_BOUND, GDB_SIGSEGV }, + { EXCEPT_X64_INVALID_OPCODE, GDB_SIGILL }, + { EXCEPT_X64_DOUBLE_FAULT, GDB_SIGEMT }, + { EXCEPT_X64_STACK_FAULT, GDB_SIGSEGV }, + { EXCEPT_X64_GP_FAULT, GDB_SIGSEGV }, + { EXCEPT_X64_PAGE_FAULT, GDB_SIGSEGV }, + { EXCEPT_X64_FP_ERROR, GDB_SIGEMT }, + { EXCEPT_X64_ALIGNMENT_CHECK, GDB_SIGEMT }, + { EXCEPT_X64_MACHINE_CHECK, GDB_SIGEMT } +}; + + +// The offsets of registers SystemContextX64. +// The fields in the array are in the gdb ordering. +// HAVE TO DOUBLE-CHECK THE ORDER of the 24 regs +// +UINTN gRegisterOffsets[] = { + OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rax), + OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rcx), + OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rdx), + OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rbx), + OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rsp), + OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rbp), + OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rsi), + OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rdi), + OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rip), + OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rflags), + OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Cs), + OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Ss), + OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Ds), + OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Es), + OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Fs), + OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Gs), + OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R8), + OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R9), + OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R10), + OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R11), + OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R12), + OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R13), + OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R14), + OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R15) +}; + + +/** + Return the number of entries in the gExceptionType[] + + @retval UINTN, the number of entries in the gExceptionType[] array. + **/ +UINTN +MaxEfiException ( + VOID + ) +{ + return sizeof (gExceptionType)/sizeof (EFI_EXCEPTION_TYPE_ENTRY); +} + + +/** + Return the number of entries in the gRegisters[] + + @retval UINTN, the number of entries (registers) in the gRegisters[] array. + **/ +UINTN +MaxRegisterCount ( + VOID + ) +{ + return sizeof (gRegisterOffsets)/sizeof (UINTN); +} + + +/** + Check to see if the ISA is supported. + ISA = Instruction Set Architecture + + @retval TRUE if Isa is supported +**/ +BOOLEAN +CheckIsa ( + IN EFI_INSTRUCTION_SET_ARCHITECTURE Isa + ) +{ + return (BOOLEAN)(Isa == IsaX64); +} + + +/** + This takes in the register number and the System Context, and returns a pointer to the RegNumber-th register in gdb ordering + It is, by default, set to find the register pointer of the X64 member + @param SystemContext Register content at time of the exception + @param RegNumber The register to which we want to find a pointer + @retval the pointer to the RegNumber-th pointer + **/ +UINTN * +FindPointerToRegister( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN RegNumber + ) +{ + UINT8 *TempPtr; + TempPtr = ((UINT8 *)SystemContext.SystemContextX64) + gRegisterOffsets[RegNumber]; + return (UINTN *)TempPtr; +} + + +/** + Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr + @param SystemContext Register content at time of the exception + @param RegNumber the number of the register that we want to read + @param OutBufPtr pointer to the output buffer's end. the new data will be added from this point on. + @retval the pointer to the next character of the output buffer that is available to be written on. + **/ +CHAR8 * +BasicReadRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN RegNumber, + IN CHAR8 *OutBufPtr + ) +{ + UINTN RegSize; + + RegSize = 0; + while (RegSize < 64) { + *OutBufPtr++ = mHexToStr[((*FindPointerToRegister(SystemContext, RegNumber) >> (RegSize+4)) & 0xf)]; + *OutBufPtr++ = mHexToStr[((*FindPointerToRegister(SystemContext, RegNumber) >> RegSize) & 0xf)]; + RegSize = RegSize + 8; + } + return OutBufPtr; +} + + +/** ‘p n’ + Reads the n-th register's value into an output buffer and sends it as a packet + @param SystemContext Register content at time of the exception + @param InBuffer Pointer to the input buffer received from gdb server + **/ +VOID +ReadNthRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *InBuffer + ) +{ + UINTN RegNumber; + CHAR8 OutBuffer[17]; // 1 reg=16 hex chars, and the end '\0' (escape seq) + CHAR8 *OutBufPtr; // pointer to the output buffer + + RegNumber = AsciiStrHexToUintn (&InBuffer[1]); + + if ((RegNumber < 0) || (RegNumber >= MaxRegisterCount())) { + SendError (GDB_EINVALIDREGNUM); + return; + } + + OutBufPtr = OutBuffer; + OutBufPtr = BasicReadRegister(SystemContext, RegNumber, OutBufPtr); + + *OutBufPtr = '\0'; // the end of the buffer + SendPacket (OutBuffer); +} + + +/** ‘g’ + Reads the general registers into an output buffer and sends it as a packet + + @param SystemContext Register content at time of the exception + **/ +VOID +EFIAPI +ReadGeneralRegisters ( + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + UINTN i; + CHAR8 OutBuffer[385]; // 24 regs, 16 hex chars each, and the end '\0' (escape seq) + CHAR8 *OutBufPtr; // pointer to the output buffer + + OutBufPtr = OutBuffer; + for(i = 0 ; i < MaxRegisterCount() ; i++) { // there are only 24 registers to read + OutBufPtr = BasicReadRegister(SystemContext, i, OutBufPtr); + } + + *OutBufPtr = '\0'; // the end of the buffer + SendPacket (OutBuffer); +} + + +/** + Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr + + @param SystemContext Register content at time of the exception + @param RegNumber the number of the register that we want to write + @param InBufPtr pointer to the output buffer. the new data will be extracted from the input buffer from this point on. + @retval the pointer to the next character of the input buffer that can be used + **/ +CHAR8 * +BasicWriteRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN RegNumber, + IN CHAR8 *InBufPtr + ) +{ + UINTN RegSize; + UINTN TempValue; // the value transferred from a hex char + UINT64 NewValue; // the new value of the RegNumber-th Register + + NewValue = 0; + RegSize = 0; + while (RegSize < 64) { + TempValue = HexCharToInt(*InBufPtr++); + + if (TempValue < 0) { + SendError (GDB_EBADMEMDATA); + return NULL; + } + + NewValue += (TempValue << (RegSize+4)); + TempValue = HexCharToInt(*InBufPtr++); + + if (TempValue < 0) { + SendError (GDB_EBADMEMDATA); + return NULL; + } + + NewValue += (TempValue << RegSize); + RegSize = RegSize + 8; + } + *(FindPointerToRegister(SystemContext, RegNumber)) = NewValue; + return InBufPtr; +} + + +/** ‘P n...=r...’ + Writes the new value of n-th register received into the input buffer to the n-th register + + @param SystemContext Register content at time of the exception + @param InBuffer Ponter to the input buffer received from gdb server + **/ +VOID +EFIAPI +WriteNthRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *InBuffer + ) +{ + UINTN RegNumber; + CHAR8 RegNumBuffer[MAX_REG_NUM_BUF_SIZE]; // put the 'n..' part of the message into this array + CHAR8 *RegNumBufPtr; + CHAR8 *InBufPtr; // pointer to the input buffer + + // find the register number to write + InBufPtr = &InBuffer[1]; + RegNumBufPtr = RegNumBuffer; + while (*InBufPtr != '=') { + *RegNumBufPtr++ = *InBufPtr++; + } + *RegNumBufPtr = '\0'; + RegNumber = AsciiStrHexToUintn (RegNumBuffer); + + // check if this is a valid Register Number + if ((RegNumber < 0) || (RegNumber >= MaxRegisterCount())) { + SendError (GDB_EINVALIDREGNUM); + return; + } + InBufPtr++; // skips the '=' character + BasicWriteRegister (SystemContext, RegNumber, InBufPtr); + SendSuccess(); +} + + +/** ‘G XX...’ + Writes the new values received into the input buffer to the general registers + + @param SystemContext Register content at time of the exception + @param InBuffer Pointer to the input buffer received from gdb server + **/ +VOID +EFIAPI +WriteGeneralRegisters ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *InBuffer + ) +{ + UINTN i; + CHAR8 *InBufPtr; /// pointer to the input buffer + + // check to see if the buffer is the right size which is + // 1 (for 'G') + 16 (for 16 registers) * 8 ( for 8 hex chars each) = 385 + if (AsciiStrLen(InBuffer) != 385) { // 24 regs, 16 hex chars each, and the end '\0' (escape seq) + //Bad message. Message is not the right length + SendError (GDB_EBADBUFSIZE); + return; + } + + InBufPtr = &InBuffer[1]; + + // Read the new values for the registers from the input buffer to an array, NewValueArray. + // The values in the array are in the gdb ordering + for(i=0; i < MaxRegisterCount(); i++) { // there are only 16 registers to write + InBufPtr = BasicWriteRegister(SystemContext, i, InBufPtr); + } + + SendSuccess(); +} + + + /** + Insert Single Step in the SystemContext + + @param SystemContext Register content at time of the exception + **/ +VOID +AddSingleStep ( + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + SystemContext.SystemContextX64->Rflags |= TF_BIT; //Setting the TF bit. +} + + + +/** + Remove Single Step in the SystemContext + + @param SystemContext Register content at time of the exception + **/ +VOID +RemoveSingleStep ( + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + SystemContext.SystemContextX64->Rflags &= ~TF_BIT; // clearing the TF bit. +} + + + +/** ‘c [addr ]’ + Continue. addr is Address to resume. If addr is omitted, resume at current + Address. + + @param SystemContext Register content at time of the exception + **/ +VOID +EFIAPI +ContinueAtAddress ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *PacketData + ) +{ + if (PacketData[1] != '\0') { + SystemContext.SystemContextX64->Rip = AsciiStrHexToUintn(&PacketData[1]); + } +} + + +/** ‘s [addr ]’ + Single step. addr is the Address at which to resume. If addr is omitted, resume + at same Address. + + @param SystemContext Register content at time of the exception + **/ +VOID +EFIAPI +SingleStep ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *PacketData + ) +{ + if (PacketData[1] != '\0') { + SystemContext.SystemContextX64->Rip = AsciiStrHexToUintn (&PacketData[1]); + } + + AddSingleStep (SystemContext); +} + + +/** + Returns breakpoint data address from DR0-DR3 based on the input breakpoint + number + + @param SystemContext Register content at time of the exception + @param BreakpointNumber Breakpoint number + + @retval Address Data address from DR0-DR3 based on the + breakpoint number. + +**/ +UINTN +GetBreakpointDataAddress ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN BreakpointNumber + ) +{ + UINTN Address; + + if (BreakpointNumber == 1) { + Address = SystemContext.SystemContextIa32->Dr0; + } else if (BreakpointNumber == 2) { + Address = SystemContext.SystemContextIa32->Dr1; + } else if (BreakpointNumber == 3) { + Address = SystemContext.SystemContextIa32->Dr2; + } else if (BreakpointNumber == 4) { + Address = SystemContext.SystemContextIa32->Dr3; + } else { + Address = 0; + } + + return Address; +} + +/** + Returns currently detected breakpoint value based on the register + DR6 B0-B3 field. + If no breakpoint is detected then it returns 0. + + @param SystemContext Register content at time of the exception + + @retval {1-4} Currently detected breakpoint value + @retval 0 No breakpoint detected. + +**/ +UINTN +GetBreakpointDetected ( + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + IA32_DR6 Dr6; + UINTN BreakpointNumber; + + Dr6.UintN = SystemContext.SystemContextIa32->Dr6; + + if (Dr6.Bits.B0 == 1) { + BreakpointNumber = 1; + } else if (Dr6.Bits.B1 == 1) { + BreakpointNumber = 2; + } else if (Dr6.Bits.B2 == 1) { + BreakpointNumber = 3; + } else if (Dr6.Bits.B3 == 1) { + BreakpointNumber = 4; + } else { + BreakpointNumber = 0; //No breakpoint detected + } + + return BreakpointNumber; +} + +/** + Returns Breakpoint type (InstructionExecution, DataWrite, DataRead + or DataReadWrite) based on the Breakpoint number + + @param SystemContext Register content at time of the exception + @param BreakpointNumber Breakpoint number + + @retval BREAK_TYPE Breakpoint type value read from register DR7 RWn + field. For unknown value, it returns NotSupported. + +**/ +BREAK_TYPE +GetBreakpointType ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN BreakpointNumber + ) +{ + IA32_DR7 Dr7; + BREAK_TYPE Type = NotSupported; //Default is NotSupported type + + Dr7.UintN = SystemContext.SystemContextIa32->Dr7; + + if (BreakpointNumber == 1) { + Type = (BREAK_TYPE) Dr7.Bits.RW0; + } else if (BreakpointNumber == 2) { + Type = (BREAK_TYPE) Dr7.Bits.RW1; + } else if (BreakpointNumber == 3) { + Type = (BREAK_TYPE) Dr7.Bits.RW2; + } else if (BreakpointNumber == 4) { + Type = (BREAK_TYPE) Dr7.Bits.RW3; + } + + return Type; +} + + +/** + Parses Length and returns the length which DR7 LENn field accepts. + For example: If we receive 1-Byte length then we should return 0. + Zero gets written to DR7 LENn field. + + @param Length Breakpoint length in Bytes (1 byte, 2 byte, 4 byte) + + @retval Length Appropriate converted values which DR7 LENn field accepts. + +**/ +UINTN +ConvertLengthData ( + IN UINTN Length + ) +{ + if (Length == 1) { //1-Byte length + return 0; + } else if (Length == 2) { //2-Byte length + return 1; + } else if (Length == 4) { //4-Byte length + return 3; + } else { //Undefined or 8-byte length + return 2; + } +} + + +/** + Finds the next free debug register. If all the registers are occupied then + EFI_OUT_OF_RESOURCES is returned. + + @param SystemContext Register content at time of the exception + @param Register Register value (0 - 3 for the first free debug register) + + @retval EFI_STATUS Appropriate status value. + +**/ +EFI_STATUS +FindNextFreeDebugRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + OUT UINTN *Register + ) +{ + IA32_DR7 Dr7; + + Dr7.UintN = SystemContext.SystemContextIa32->Dr7; + + if (Dr7.Bits.G0 == 0) { + *Register = 0; + } else if (Dr7.Bits.G1 == 0) { + *Register = 1; + } else if (Dr7.Bits.G2 == 0) { + *Register = 2; + } else if (Dr7.Bits.G3 == 0) { + *Register = 3; + } else { + return EFI_OUT_OF_RESOURCES; + } + + return EFI_SUCCESS; +} + + +/** + Enables the debug register. Writes Address value to appropriate DR0-3 register. + Sets LENn, Gn, RWn bits in DR7 register. + + @param SystemContext Register content at time of the exception + @param Register Register value (0 - 3) + @param Address Breakpoint address value + @param Type Breakpoint type (Instruction, Data write, + Data read or write etc.) + + @retval EFI_STATUS Appropriate status value. + +**/ +EFI_STATUS +EnableDebugRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN Register, + IN UINTN Address, + IN UINTN Length, + IN UINTN Type + ) +{ + IA32_DR7 Dr7; + + //Convert length data + Length = ConvertLengthData (Length); + + //For Instruction execution, length should be 0 + //(Ref. Intel reference manual 18.2.4) + if ((Type == 0) && (Length != 0)) { + return EFI_INVALID_PARAMETER; + } + + //Hardware doesn't support ReadWatch (z3 packet) type. GDB can handle + //software breakpoint. We should send empty packet in both these cases. + if ((Type == (BREAK_TYPE)DataRead) || + (Type == (BREAK_TYPE)SoftwareBreakpoint)) { + return EFI_UNSUPPORTED; + } + + //Read DR7 so appropriate Gn, RWn and LENn bits can be modified. + Dr7.UintN = SystemContext.SystemContextIa32->Dr7; + + if (Register == 0) { + SystemContext.SystemContextIa32->Dr0 = Address; + Dr7.Bits.G0 = 1; + Dr7.Bits.RW0 = Type; + Dr7.Bits.LEN0 = Length; + } else if (Register == 1) { + SystemContext.SystemContextIa32->Dr1 = Address; + Dr7.Bits.G1 = 1; + Dr7.Bits.RW1 = Type; + Dr7.Bits.LEN1 = Length; + } else if (Register == 2) { + SystemContext.SystemContextIa32->Dr2 = Address; + Dr7.Bits.G2 = 1; + Dr7.Bits.RW2 = Type; + Dr7.Bits.LEN2 = Length; + } else if (Register == 3) { + SystemContext.SystemContextIa32->Dr3 = Address; + Dr7.Bits.G3 = 1; + Dr7.Bits.RW3 = Type; + Dr7.Bits.LEN3 = Length; + } else { + return EFI_INVALID_PARAMETER; + } + + //Update Dr7 with appropriate Gn, RWn and LENn bits + SystemContext.SystemContextIa32->Dr7 = Dr7.UintN; + + return EFI_SUCCESS; +} + + +/** + Returns register number 0 - 3 for the maching debug register. + This function compares incoming Address, Type, Length and + if there is a match then it returns the appropriate register number. + In case of mismatch, function returns EFI_NOT_FOUND message. + + @param SystemContext Register content at time of the exception + @param Address Breakpoint address value + @param Length Breakpoint length value + @param Type Breakpoint type (Instruction, Data write, Data read + or write etc.) + @param Register Register value to be returned + + @retval EFI_STATUS Appropriate status value. + +**/ +EFI_STATUS +FindMatchingDebugRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN Address, + IN UINTN Length, + IN UINTN Type, + OUT UINTN *Register + ) +{ + IA32_DR7 Dr7; + + //Hardware doesn't support ReadWatch (z3 packet) type. GDB can handle + //software breakpoint. We should send empty packet in both these cases. + if ((Type == (BREAK_TYPE)DataRead) || + (Type == (BREAK_TYPE)SoftwareBreakpoint)) { + return EFI_UNSUPPORTED; + } + + //Convert length data + Length = ConvertLengthData(Length); + + Dr7.UintN = SystemContext.SystemContextIa32->Dr7; + + if ((Dr7.Bits.G0 == 1) && + (Dr7.Bits.LEN0 == Length) && + (Dr7.Bits.RW0 == Type) && + (Address == SystemContext.SystemContextIa32->Dr0)) { + *Register = 0; + } else if ((Dr7.Bits.G1 == 1) && + (Dr7.Bits.LEN1 == Length) && + (Dr7.Bits.RW1 == Type) && + (Address == SystemContext.SystemContextIa32->Dr1)) { + *Register = 1; + } else if ((Dr7.Bits.G2 == 1) && + (Dr7.Bits.LEN2 == Length) && + (Dr7.Bits.RW2 == Type) && + (Address == SystemContext.SystemContextIa32->Dr2)) { + *Register = 2; + } else if ((Dr7.Bits.G3 == 1) && + (Dr7.Bits.LEN3 == Length) && + (Dr7.Bits.RW3 == Type) && + (Address == SystemContext.SystemContextIa32->Dr3)) { + *Register = 3; + } else { + Print ((CHAR16 *)L"No match found..\n"); + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + + +/** + Disables the particular debug register. + + @param SystemContext Register content at time of the exception + @param Register Register to be disabled + + @retval EFI_STATUS Appropriate status value. + +**/ +EFI_STATUS +DisableDebugRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN Register + ) +{ + IA32_DR7 Dr7; + UINTN Address = 0; + + //Read DR7 register so appropriate Gn, RWn and LENn bits can be turned off. + Dr7.UintN = SystemContext.SystemContextIa32->Dr7; + + if (Register == 0) { + SystemContext.SystemContextIa32->Dr0 = Address; + Dr7.Bits.G0 = 0; + Dr7.Bits.RW0 = 0; + Dr7.Bits.LEN0 = 0; + } else if (Register == 1) { + SystemContext.SystemContextIa32->Dr1 = Address; + Dr7.Bits.G1 = 0; + Dr7.Bits.RW1 = 0; + Dr7.Bits.LEN1 = 0; + } else if (Register == 2) { + SystemContext.SystemContextIa32->Dr2 = Address; + Dr7.Bits.G2 = 0; + Dr7.Bits.RW2 = 0; + Dr7.Bits.LEN2 = 0; + } else if (Register == 3) { + SystemContext.SystemContextIa32->Dr3 = Address; + Dr7.Bits.G3 = 0; + Dr7.Bits.RW3 = 0; + Dr7.Bits.LEN3 = 0; + } else { + return EFI_INVALID_PARAMETER; + } + + //Update DR7 register so appropriate Gn, RWn and LENn bits can be turned off. + SystemContext.SystemContextIa32->Dr7 = Dr7.UintN; + + return EFI_SUCCESS; +} + +/** + ‘Z1, [addr], [length]’ + ‘Z2, [addr], [length]’ + ‘Z3, [addr], [length]’ + ‘Z4, [addr], [length]’ + + Insert hardware breakpoint/watchpoint at address addr of size length + + @param SystemContext Register content at time of the exception + @param *PacketData Pointer to the Payload data for the packet + +**/ +VOID +EFIAPI +InsertBreakPoint ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *PacketData + ) +{ + UINTN Type; + UINTN Address; + UINTN Length; + UINTN Register; + EFI_STATUS Status; + BREAK_TYPE BreakType = NotSupported; + UINTN ErrorCode; + + ErrorCode = ParseBreakpointPacket (PacketData, &Type, &Address, &Length); + if (ErrorCode > 0) { + SendError ((UINT8)ErrorCode); + return; + } + + switch (Type) { + + case 0: //Software breakpoint + BreakType = SoftwareBreakpoint; + break; + + case 1: //Hardware breakpoint + BreakType = InstructionExecution; + break; + + case 2: //Write watchpoint + BreakType = DataWrite; + break; + + case 3: //Read watchpoint + BreakType = DataRead; + break; + + case 4: //Access watchpoint + BreakType = DataReadWrite; + break; + + default : + Print ((CHAR16 *)L"Insert breakpoint default: %x\n", Type); + SendError (GDB_EINVALIDBRKPOINTTYPE); + return; + } + + // Find next free debug register + Status = FindNextFreeDebugRegister (SystemContext, &Register); + if (EFI_ERROR(Status)) { + Print ((CHAR16 *)L"No space left on device\n"); + SendError (GDB_ENOSPACE); + return; + } + + // Write Address, length data at particular DR register + Status = EnableDebugRegister (SystemContext, Register, Address, Length, (UINTN)BreakType); + if (EFI_ERROR(Status)) { + + if (Status == EFI_UNSUPPORTED) { + Print ((CHAR16 *)L"Not supported\n"); + SendNotSupported(); + return; + } + + Print ((CHAR16 *)L"Invalid argument\n"); + SendError (GDB_EINVALIDARG); + return; + } + + SendSuccess (); +} + + +/** + ‘z1, [addr], [length]’ + ‘z2, [addr], [length]’ + ‘z3, [addr], [length]’ + ‘z4, [addr], [length]’ + + Remove hardware breakpoint/watchpoint at address addr of size length + + @param *PacketData Pointer to the Payload data for the packet + +**/ +VOID +EFIAPI +RemoveBreakPoint ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *PacketData + ) +{ + UINTN Type; + UINTN Address; + UINTN Length; + UINTN Register; + BREAK_TYPE BreakType = NotSupported; + EFI_STATUS Status; + UINTN ErrorCode; + + //Parse breakpoint packet data + ErrorCode = ParseBreakpointPacket (PacketData, &Type, &Address, &Length); + if (ErrorCode > 0) { + SendError ((UINT8)ErrorCode); + return; + } + + switch (Type) { + + case 0: //Software breakpoint + BreakType = SoftwareBreakpoint; + break; + + case 1: //Hardware breakpoint + BreakType = InstructionExecution; + break; + + case 2: //Write watchpoint + BreakType = DataWrite; + break; + + case 3: //Read watchpoint + BreakType = DataRead; + break; + + case 4: //Access watchpoint + BreakType = DataReadWrite; + break; + + default : + SendError (GDB_EINVALIDBRKPOINTTYPE); + return; + } + + //Find matching debug register + Status = FindMatchingDebugRegister (SystemContext, Address, Length, (UINTN)BreakType, &Register); + if (EFI_ERROR(Status)) { + + if (Status == EFI_UNSUPPORTED) { + Print ((CHAR16 *)L"Not supported.\n"); + SendNotSupported(); + return; + } + + Print ((CHAR16 *)L"No matching register found.\n"); + SendError (GDB_ENOSPACE); + return; + } + + //Remove breakpoint + Status = DisableDebugRegister(SystemContext, Register); + if (EFI_ERROR(Status)) { + Print ((CHAR16 *)L"Invalid argument.\n"); + SendError (GDB_EINVALIDARG); + return; + } + + SendSuccess (); +} + + +VOID +InitializeProcessor ( + VOID + ) +{ +} + +BOOLEAN +ValidateAddress ( + IN VOID *Address + ) +{ + return TRUE; +} + +BOOLEAN +ValidateException ( + IN EFI_EXCEPTION_TYPE ExceptionType, + IN OUT EFI_SYSTEM_CONTEXT SystemContext + ) +{ + return TRUE; +} + diff --git a/EmbeddedPkg/Include/Library/EblAddExternalCommandLib.h b/EmbeddedPkg/Include/Library/EblAddExternalCommandLib.h new file mode 100644 index 0000000000..c3f1678180 --- /dev/null +++ b/EmbeddedPkg/Include/Library/EblAddExternalCommandLib.h @@ -0,0 +1,122 @@ +/** @file + Include flie for basic command line parser for EBL (Embedded Boot Loader) + + Copyright (c) 2007, Intel Corporation
+ Portions copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EBL_ADD_EXTERNAL_COMMAND_LIB_H__ +#define __EBL_ADD_EXTERNAL_COMMAND_LIB_H__ + +#include +#include + + +EFI_STATUS +EFIAPI +EblAddExternalCommands ( + IN const EBL_COMMAND_TABLE *EntryArray, + IN UINTN ArrayCount + ); + +/** + + Return a keypress or optionally timeout if a timeout value was passed in. + + An optional callback funciton is called evey second when waiting for a + + timeout. + + + + @param Key EFI Key information returned + + @param TimeoutInSec Number of seconds to wait to timeout + + @param CallBack Callback called every second during the timeout wait + + + + @return EFI_SUCCESS Key was returned + + @return EFI_TIMEOUT If the TimoutInSec expired + + + +**/ + +EFI_STATUS + +EFIAPI + +EblGetCharKey ( + + IN OUT EFI_INPUT_KEY *Key, + + IN UINTN TimeoutInSec, + + IN EBL_GET_CHAR_CALL_BACK CallBack OPTIONAL + + ); + + + + + +/** + + This routine is used prevent command output data from scrolling off the end + + of the screen. The global gPageBreak is used to turn on or off this feature. + + If the CurrentRow is near the end of the screen pause and print out a prompt + + If the use hits Q to quit return TRUE else for any other key return FALSE. + + PrefixNewline is used to figure out if a newline is needed before the prompt + + string. This depends on the last print done before calling this function. + + CurrentRow is updated by one on a call or set back to zero if a prompt is + + needed. + + + + @param CurrentRow Used to figure out if its the end of the page and updated + + @param PrefixNewline Did previous print issue a newline + + + + @return TRUE if Q was hit to quit, FALSE in all other cases. + + + +**/ + +BOOLEAN + +EFIAPI + +EblAnyKeyToContinueQtoQuit ( + + IN UINTN *CurrentRow, + + IN BOOLEAN PrefixNewline + + ); + + + +#endif + diff --git a/EmbeddedPkg/Include/Library/EblCmdLib.h b/EmbeddedPkg/Include/Library/EblCmdLib.h new file mode 100644 index 0000000000..70ed3c8c71 --- /dev/null +++ b/EmbeddedPkg/Include/Library/EblCmdLib.h @@ -0,0 +1,48 @@ +/** @file + Include flie for basic command line parser for EBL (Embedded Boot Loader) + + Copyright (c) 2007, Intel Corporation
+ Portions copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EBL_LIB_H__ +#define __EBL_LIB_H__ + +#include +#include + + +VOID +EblAddCommand ( + IN const EBL_COMMAND_TABLE *Entry + ); + +VOID +EblAddCommands ( + IN const EBL_COMMAND_TABLE *EntryArray, + IN UINTN ArrayCount + ); + + +// +// LIbrary constructor called directly from Ebl Code. +// This module calls EblAddCommand () or EblAddCommands () to register new commands +// +VOID +EblInitializeExternalCmd ( + VOID + ); + + + +#endif + diff --git a/EmbeddedPkg/Include/Library/EblNetworkLib.h b/EmbeddedPkg/Include/Library/EblNetworkLib.h new file mode 100644 index 0000000000..5c9ec03cfc --- /dev/null +++ b/EmbeddedPkg/Include/Library/EblNetworkLib.h @@ -0,0 +1,68 @@ +/** @file + Abstractions for Ebl network accesses. + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EBL_NETWORK_LIB_H__ +#define __EBL_NETWORK_LIB_H__ + +#include + + +EFI_STATUS +EFIAPI +EblGetCurrentIpAddress ( + IN OUT EFI_IP_ADDRESS *Ip + ); + +EFI_STATUS +EFIAPI +EblGetCurrentMacAddress ( + IN OUT EFI_MAC_ADDRESS *Mac + ); + +CHAR8 * +EFIAPI +EblLoadFileBootTypeString ( + IN EFI_HANDLE Handle + ); + +EFI_STATUS +EFIAPI +EblPerformDHCP ( + IN BOOLEAN SortOffers + ); + +EFI_STATUS +EFIAPI +EblSetStationIp ( + IN EFI_IP_ADDRESS *NewStationIp, OPTIONAL + IN EFI_IP_ADDRESS *NewSubnetMask OPTIONAL + ); + +EFI_STATUS +EFIAPI +EblMtftp ( + IN EFI_PXE_BASE_CODE_TFTP_OPCODE Operation, + IN OUT VOID *BufferPtr OPTIONAL, + IN BOOLEAN Overwrite, + IN OUT UINT64 *BufferSize, + IN UINTN *BlockSize OPTIONAL, + IN EFI_IP_ADDRESS *ServerIp, + IN UINT8 *Filename OPTIONAL, + IN EFI_PXE_BASE_CODE_MTFTP_INFO *Info OPTIONAL, + IN BOOLEAN DontUseBuffer + ); + +#endif + diff --git a/EmbeddedPkg/Include/Library/EfiFileLib.h b/EmbeddedPkg/Include/Library/EfiFileLib.h new file mode 100644 index 0000000000..992d326997 --- /dev/null +++ b/EmbeddedPkg/Include/Library/EfiFileLib.h @@ -0,0 +1,315 @@ +/** @file + Library functions that perform file IO. Memory buffer, file system, and + fimrware volume operations are supproted. + + Copyright (c) 2007, Intel Corporation
+ Portions copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + Basic support for opening files on different device types. The device string + is in the form of DevType:Path. Current DevType is required as there is no + current mounted device concept of current working directory concept implement + by this library. + + Device names are case insensative and only check the leading characters for + unique matches. Thus the following are all the same: + LoadFile0: + l0: + L0: + Lo0: + + Supported Device Names: + A0x1234:0x12 - A memory buffer starting at address 0x1234 for 0x12 bytes + l1: - EFI LoadFile device one. + B0: - EFI BlockIo zero. + fs3: - EFI Simple File System device 3 + Fv2: - EFI Firmware VOlume device 2 + 1.2.3.4:name - TFTP IP and file name + +**/ + +#ifndef __EFI_FILE_LIB_H__ +#define __EFI_FILE_LIB_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_PATHNAME 0x200 + +/// Type of the file that has been opened +typedef enum { + EfiOpenLoadFile, + EfiOpenMemoryBuffer, + EfiOpenFirmwareVolume, + EfiOpenFileSystem, + EfiOpenBlockIo, + EfiOpenTftp, + EfiOpenMaxValue +} EFI_OPEN_FILE_TYPE; + + +/// Public information about the open file +typedef struct { + UINTN Version; // Common information + EFI_OPEN_FILE_TYPE Type; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_STATUS LastError; + EFI_HANDLE EfiHandle; + CHAR8 *DeviceName; + CHAR8 *FileName; + + UINT64 CurrentPosition; // Information for Seek + UINT64 MaxPosition; + + UINTN BaseOffset; // Base offset for hexdump command + + UINTN Size; // Valid for all types other than l#: + UINT8 *Buffer; // Information valid for A#: + + EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; // Information valid for Fv#: + EFI_GUID FvNameGuid; + EFI_SECTION_TYPE FvSectionType; + EFI_FV_FILETYPE FvType; + EFI_FV_FILE_ATTRIBUTES FvAttributes; + + EFI_PHYSICAL_ADDRESS FvStart; + UINTN FvSize; + + EFI_FILE *FsFileHandle; // Information valid for Fs#: + EFI_FILE_SYSTEM_INFO *FsInfo; + EFI_FILE_INFO *FsFileInfo; + EFI_BLOCK_IO_MEDIA FsBlockIoMedia; // Information valid for Fs#: or B#: + + UINTN DiskOffset; // Information valid for B#: + + EFI_LOAD_FILE_PROTOCOL *LoadFile; // Information valid for l#: + + EFI_IP_ADDRESS ServerIp; // Information valid for t: + BOOLEAN IsDirty; + BOOLEAN IsBufferValid; + +} EFI_OPEN_FILE; + + +/// Type of Seek to perform +typedef enum { + EfiSeekStart, + EfiSeekCurrent, + EfiSeekEnd, + EfiSeekMax +} EFI_SEEK_TYPE; + + +/** + Open a device named by PathName. The PathName includes a device name and + path seperated by a :. See file header for more details on the PathName + syntax. There is no checking to prevent a file from being opened more than + one type. + + SectionType is only used to open an FV. Each file in an FV contains multiple + secitons and only the SectionType section is opened. + + For any file that is opened with EfiOpen() must be closed with EfiClose(). + + @param PathName Path to parse to open + @param OpenMode Same as EFI_FILE.Open() + @param SectionType Section in FV to open. + + @return NULL Open failed + @return Valid EFI_OPEN_FILE handle + +**/ +EFI_OPEN_FILE * +EfiOpen ( + IN CHAR8 *PathName, + IN CONST UINT64 OpenMode, + IN CONST EFI_SECTION_TYPE SectionType + ); + +EFI_STATUS +EfiCopyFile ( + IN CHAR8 *DestinationFile, + IN CHAR8 *SourceFile + ); + +/** + Use DeviceType and Index to form a valid PathName and try and open it. + + @param DeviceType Device type to open + @param Index Device Index to use. Zero relative. + + @return NULL Open failed + @return Valid EFI_OPEN_FILE handle + +**/ +EFI_OPEN_FILE * +EfiDeviceOpenByType ( + IN EFI_OPEN_FILE_TYPE DeviceType, + IN UINTN Index + ); + + +/** + Close a file handle opened by EfiOpen() and free all resources allocated by + EfiOpen(). + + @param Stream Open File Handle + + @return EFI_INVALID_PARAMETER Stream is not an Open File + @return EFI_SUCCESS Steam closed + +**/ +EFI_STATUS +EfiClose ( + IN EFI_OPEN_FILE *Stream + ); + + +/** + Return the size of the file represented by Stream. Also return the current + Seek position. Opening a file will enable a valid file size to be returned. + LoadFile is an exception as a load file size is set to zero. + + @param Stream Open File Handle + + @return 0 Stream is not an Open File or a valid LoadFile handle + +**/ +UINTN +EfiTell ( + IN EFI_OPEN_FILE *Stream, + OUT UINT64 *CurrentPosition OPTIONAL + ); + + +/** + Seek to the Offset locaiton in the file. LoadFile and FV device types do + not support EfiSeek(). It is not possible to grow the file size using + EfiSeek(). + + SeekType defines how use Offset to calculate the new file position: + EfiSeekStart : Position = Offset + EfiSeekCurrent: Position is Offset bytes from the current position + EfiSeekEnd : Only supported if Offset is zero to seek to end of file. + + @param Stream Open File Handle + @param Offset Offset to seek too. + @param SeekType Type of seek to perform + + + @return EFI_INVALID_PARAMETER Stream is not an Open File + @return EFI_UNSUPPORTED LoadFile and FV doe not support Seek + @return EFI_NOT_FOUND Seek past the end of the file. + @return EFI_SUCCESS Steam closed + +**/ +EFI_STATUS +EfiSeek ( + IN EFI_OPEN_FILE *Stream, + IN EFI_LBA Offset, + IN EFI_SEEK_TYPE SeekType + ); + + +/** + Read BufferSize bytes from the current locaiton in the file. For load file + and FV case you must read the entire file. + + @param Stream Open File Handle + @param Buffer Caller allocated buffer. + @param BufferSize Size of buffer in bytes. + + + @return EFI_SUCCESS Stream is not an Open File + @return EFI_END_OF_FILE Tried to read past the end of the file + @return EFI_INVALID_PARAMETER Stream is not an open file handle + @return EFI_BUFFER_TOO_SMALL Buffer is not big enough to do the read + @return "other" Error returned from device read + +**/ +EFI_STATUS +EfiRead ( + IN EFI_OPEN_FILE *Stream, + OUT VOID *Buffer, + OUT UINTN *BufferSize + ); + + +/** + Read the entire file into a buffer. This routine allocates the buffer and + returns it to the user full of the read data. + + This is very useful for load flie where it's hard to know how big the buffer + must be. + + @param Stream Open File Handle + @param Buffer Pointer to buffer to return. + @param BufferSize Pointer to Size of buffer return.. + + + @return EFI_SUCCESS Stream is not an Open File + @return EFI_END_OF_FILE Tried to read past the end of the file + @return EFI_INVALID_PARAMETER Stream is not an open file handle + @return EFI_BUFFER_TOO_SMALL Buffer is not big enough to do the read + @return "other" Error returned from device read + +**/ +EFI_STATUS +EfiReadAllocatePool ( + IN EFI_OPEN_FILE *Stream, + OUT VOID **Buffer, + OUT UINTN *BufferSize + ); + + +/** + Write data back to the file. + + @param Stream Open File Handle + @param Buffer Pointer to buffer to return. + @param BufferSize Pointer to Size of buffer return.. + + + @return EFI_SUCCESS Stream is not an Open File + @return EFI_END_OF_FILE Tried to read past the end of the file + @return EFI_INVALID_PARAMETER Stream is not an open file handle + @return EFI_BUFFER_TOO_SMALL Buffer is not big enough to do the read + @return "other" Error returned from device write + +**/ +EFI_STATUS +EfiWrite ( + IN EFI_OPEN_FILE *Stream, + OUT VOID *Buffer, + OUT UINTN *BufferSize + ); + + +/** + Return the number of devices of the current type active in the system + + @param Type Device type to check + + @return 0 Invalid type + +**/ +UINTN +EfiGetDeviceCounts ( + IN EFI_OPEN_FILE_TYPE Type + ); + +#endif diff --git a/EmbeddedPkg/Include/Library/EfiResetSystemLib.h b/EmbeddedPkg/Include/Library/EfiResetSystemLib.h new file mode 100644 index 0000000000..162857660f --- /dev/null +++ b/EmbeddedPkg/Include/Library/EfiResetSystemLib.h @@ -0,0 +1,58 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#ifndef __EFI_RESET_SYSTEM_LIB_H___ +#define __EFI_RESET_SYSTEM_LIB_H___ + + +/** + Resets the entire platform. + + @param ResetType The type of reset to perform. + @param ResetStatus The status code for the reset. + @param DataSize The size, in bytes, of WatchdogData. + @param ResetData For a ResetType of EfiResetCold, EfiResetWarm, or + EfiResetShutdown the data buffer starts with a Null-terminated + Unicode string, optionally followed by additional binary data. + +**/ +EFI_STATUS +EFIAPI +LibResetSystem ( + IN EFI_RESET_TYPE ResetType, + IN EFI_STATUS ResetStatus, + IN UINTN DataSize, + IN CHAR16 *ResetData OPTIONAL + ); + + + +/** + Initialize any infrastructure required for LibResetSystem () to function. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +LibInitializeResetSystem ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +#endif diff --git a/EmbeddedPkg/Include/Library/GdbSerialLib.h b/EmbeddedPkg/Include/Library/GdbSerialLib.h new file mode 100644 index 0000000000..3d72005c91 --- /dev/null +++ b/EmbeddedPkg/Include/Library/GdbSerialLib.h @@ -0,0 +1,107 @@ +/** @file + Basic serial IO abstaction for GDB + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __GDB_SERIAL_LIB_H__ +#define __GDB_SERIAL_LIB_H__ + + + +/** + Sets the baud rate, receive FIFO depth, transmit/receice time out, parity, + data buts, and stop bits on a serial device. This call is optional as the serial + port will be set up with defaults base on PCD values. + + @param BaudRate The requested baud rate. A BaudRate value of 0 will use the the + device's default interface speed. + @param Parity The type of parity to use on this serial device. A Parity value of + DefaultParity will use the device's default parity value. + @param DataBits The number of data bits to use on the serial device. A DataBits + vaule of 0 will use the device's default data bit setting. + @param StopBits The number of stop bits to use on this serial device. A StopBits + value of DefaultStopBits will use the device's default number of + stop bits. + + @retval EFI_SUCCESS The device was configured. + @retval EFI_DEVICE_ERROR The serial device could not be coonfigured. + +**/ +RETURN_STATUS +EFIAPI +GdbSerialInit ( + IN UINT64 BaudRate, + IN UINT8 Parity, + IN UINT8 DataBits, + IN UINT8 StopBits + ); + + +/** + Check to see if a character is available from GDB. Do not read the character as that is + done via GdbGetChar(). + + @return TRUE - Character availible + @return FALSE - Character not availible + +**/ +BOOLEAN +EFIAPI +GdbIsCharAvailable ( + VOID + ); + +/** + Get a character from GDB. This function must be able to run in interrupt context. + + @return A character from GDB + +**/ +CHAR8 +EFIAPI +GdbGetChar ( + VOID + ); + + +/** + Send a character to GDB. This function must be able to run in interrupt context. + + + @param Char Send a character to GDB + +**/ + +VOID +EFIAPI +GdbPutChar ( + IN CHAR8 Char + ); + + +/** + Send an ASCII string to GDB. This function must be able to run in interrupt context. + + + @param String Send a string to GDB + +**/ + +VOID +GdbPutString ( + IN CHAR8 *String + ); + + +#endif + diff --git a/EmbeddedPkg/Include/Library/HalRuntimeServicesLib.h b/EmbeddedPkg/Include/Library/HalRuntimeServicesLib.h new file mode 100644 index 0000000000..d77edfa437 --- /dev/null +++ b/EmbeddedPkg/Include/Library/HalRuntimeServicesLib.h @@ -0,0 +1,165 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#ifndef __RUNTIME_SERVICES_LIB_H__ +#define __RUNTIME_SERVICES_LIB_H__ + +VOID +LibMtcInitialize (VOID); + +VOID +LibMtcVirtualAddressChangeEvent (VOID); + +EFI_STATUS +EFIAPI +LibMtcGetNextHighMonotonicCount ( + OUT UINT32 *HighCount + ); + +EFI_STATUS +LibMtcGetNextMonotonicCount ( + OUT UINT64 *Count + ); + + + +VOID +LibVariableInitialize (VOID); + +VOID +LibVariableVirtualAddressChangeEvent (VOID); + +EFI_STATUS +LibGetVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + OUT UINT32 *Attributes OPTIONAL, + IN OUT UINTN *DataSize, + OUT VOID *Data + ); + +EFI_STATUS +LibGetNextVariableName ( + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, + IN OUT EFI_GUID *VendorGuid + ); + +EFI_STATUS +LibSetVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + IN UINTN DataSize, + IN VOID *Data + ); + +EFI_STATUS +LibQueryVariableInfo ( + IN UINT32 Attributes, + OUT UINT64 *MaximumVariableStorageSize, + OUT UINT64 *RemainingVariableStorageSize, + OUT UINT64 *MaximumVariableSize + ); + + + +VOID +LibResetInitializeReset (VOID); + +VOID +LibResetVirtualAddressChangeEvent (VOID); + +VOID +LibResetSystem ( + IN EFI_RESET_TYPE ResetType, + IN EFI_STATUS ResetStatus, + IN UINTN DataSize, + IN CHAR16 *ResetData OPTIONAL + ); + + +VOID +LibCapsuleInitialize (VOID); + +VOID +LibCapsuleVirtualAddressChangeEvent (VOID); + +EFI_STATUS +LibUpdateCapsule ( + IN UEFI_CAPSULE_HEADER **CapsuleHeaderArray, + IN UINTN CapsuleCount, + IN EFI_PHYSICAL_ADDRESS ScatterGatherList OPTIONAL + ); + +EFI_STATUS +QueryCapsuleCapabilities ( + IN UEFI_CAPSULE_HEADER **CapsuleHeaderArray, + IN UINTN CapsuleCount, + OUT UINT64 *MaxiumCapsuleSize, + OUT EFI_RESET_TYPE *ResetType + ); + + + +VOID +LibRtcInitialize (VOID); + +VOID +LibRtcVirtualAddressChangeEvent (VOID); + +EFI_STATUS +LibGetTime ( + OUT EFI_TIME *Time, + OUT EFI_TIME_CAPABILITIES *Capabilities + ); + +EFI_STATUS +LibSetTime ( + IN EFI_TIME *Time + ); + +EFI_STATUS +LibGetWakeupTime ( + OUT BOOLEAN *Enabled, + OUT BOOLEAN *Pending, + OUT EFI_TIME *Time + ); + +EFI_STATUS +LibSetWakeupTime ( + IN BOOLEAN Enabled, + OUT EFI_TIME *Time + ); + + +VOID +LibReportStatusCodeInitialize (VOID); + +VOID +LibReportStatusCodeVirtualAddressChangeEvent (VOID); + +EFI_STATUS +LibReportStatusCode ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID *CallerId, + IN EFI_STATUS_CODE_DATA *Data OPTIONAL + ); + + +#endif + diff --git a/EmbeddedPkg/Include/Library/PrePiLib.h b/EmbeddedPkg/Include/Library/PrePiLib.h new file mode 100644 index 0000000000..61c7e4d7ac --- /dev/null +++ b/EmbeddedPkg/Include/Library/PrePiLib.h @@ -0,0 +1,766 @@ +/** @file + Library that helps implement monolithic PEI. (SEC goes to DXE) + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PRE_PI_LIB_H__ +#define __PRE_PI_LIB_H__ + +/** + This service enables discovery of additional firmware volumes. + + @param Instance This instance of the firmware volume to find. The value 0 is the + Boot Firmware Volume (BFV). + @param FwVolHeader Pointer to the firmware volume header of the volume to return. + + @retval EFI_SUCCESS The volume was found. + @retval EFI_NOT_FOUND The volume was not found. + @retval EFI_INVALID_PARAMETER FwVolHeader is NULL. + +**/ +EFI_STATUS +EFIAPI +FfsFindNextVolume ( + IN UINTN Instance, + IN OUT EFI_PEI_FV_HANDLE *VolumeHandle + ); + + +/** + This service enables discovery of additional firmware files. + + @param SearchType A filter to find files only of this type. + @param FwVolHeader Pointer to the firmware volume header of the volume to search. + This parameter must point to a valid FFS volume. + @param FileHeader Pointer to the current file from which to begin searching. + + @retval EFI_SUCCESS The file was found. + @retval EFI_NOT_FOUND The file was not found. + @retval EFI_NOT_FOUND The header checksum was not zero. + +**/ +EFI_STATUS +EFIAPI +FfsFindNextFile ( + IN EFI_FV_FILETYPE SearchType, + IN EFI_PEI_FV_HANDLE VolumeHandle, + IN OUT EFI_PEI_FILE_HANDLE *FileHandle + ); + + +/** + This service enables discovery sections of a given type within a valid FFS file. + + @param SearchType The value of the section type to find. + @param FfsFileHeader A pointer to the file header that contains the set of sections to + be searched. + @param SectionData A pointer to the discovered section, if successful. + + @retval EFI_SUCCESS The section was found. + @retval EFI_NOT_FOUND The section was not found. + +**/ +EFI_STATUS +EFIAPI +FfsFindSectionData ( + IN EFI_SECTION_TYPE SectionType, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT VOID **SectionData + ); + + +/** + Find a file in the volume by name + + @param FileName A pointer to the name of the file to + find within the firmware volume. + + @param VolumeHandle The firmware volume to search FileHandle + Upon exit, points to the found file's + handle or NULL if it could not be found. + + @retval EFI_SUCCESS File was found. + + @retval EFI_NOT_FOUND File was not found. + + @retval EFI_INVALID_PARAMETER VolumeHandle or FileHandle or + FileName was NULL. + +**/ +EFI_STATUS +EFIAPI +FfsFindByName ( + IN CONST EFI_GUID *FileName, + IN CONST EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_PEI_FILE_HANDLE *FileHandle + ); + + +/** + Get information about the file by name. + + @param FileHandle Handle of the file. + + @param FileInfo Upon exit, points to the file's + information. + + @retval EFI_SUCCESS File information returned. + + @retval EFI_INVALID_PARAMETER If FileHandle does not + represent a valid file. + + @retval EFI_INVALID_PARAMETER If FileInfo is NULL. + +**/ +EFI_STATUS +EFIAPI +FfsGetFileInfo ( + IN CONST EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_FV_FILE_INFO *FileInfo + ); + + +/** + Get Information about the volume by name + + @param VolumeHandle Handle of the volume. + + @param VolumeInfo Upon exit, points to the volume's + information. + + @retval EFI_SUCCESS File information returned. + + @retval EFI_INVALID_PARAMETER If FileHandle does not + represent a valid file. + + @retval EFI_INVALID_PARAMETER If FileInfo is NULL. + +**/ +EFI_STATUS +EFIAPI +FfsGetVolumeInfo ( + IN EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_FV_INFO *VolumeInfo + ); + + + +/** + Get Fv image from the FV type file, then add FV & FV2 Hob. + + @param FileHandle File handle of a Fv type file. + + + @retval EFI_NOT_FOUND FV image can't be found. + @retval EFI_SUCCESS Successfully to process it. + +**/ +EFI_STATUS +EFIAPI +FfsProcessFvFile ( + IN EFI_PEI_FILE_HANDLE FvFileHandle + ); + + +/** + Search through every FV until you find a file of type FileType + + @param FileType File handle of a Fv type file. + @param Volumehandle On succes Volume Handle of the match + @param FileHandle On success File Handle of the match + + @retval EFI_NOT_FOUND FV image can't be found. + @retval EFI_SUCCESS Successfully found FileType + +**/ +EFI_STATUS +EFIAPI +FfsAnyFvFindFirstFile ( + IN EFI_FV_FILETYPE FileType, + OUT EFI_PEI_FV_HANDLE *VolumeHandle, + OUT EFI_PEI_FILE_HANDLE *FileHandle + ); + + +/** + Get Fv image from the FV type file, then add FV & FV2 Hob. + + @param FileHandle File handle of a Fv type file. + + + @retval EFI_NOT_FOUND FV image can't be found. + @retval EFI_SUCCESS Successfully to process it. + +**/ +EFI_STATUS +EFIAPI +FfsProcessFvFile ( + IN EFI_PEI_FILE_HANDLE FvFileHandle + ); + + +/** + This service enables PEIMs to ascertain the present value of the boot mode. + + + @retval BootMode + +**/ +EFI_BOOT_MODE +EFIAPI +GetBootMode ( + VOID + ); + + +/** + This service enables PEIMs to update the boot mode variable. + + @param BootMode The value of the boot mode to set. + + @retval EFI_SUCCESS The value was successfully updated + +**/ +EFI_STATUS +EFIAPI +SetBootMode ( + IN EFI_BOOT_MODE BootMode + ); + +/** + This service enables a PEIM to ascertain the address of the list of HOBs in memory. + + @param HobList A pointer to the list of HOBs that the PEI Foundation will initialize. + + @retval EFI_SUCCESS The list was successfully returned. + @retval EFI_NOT_AVAILABLE_YET The HOB list is not yet published. + +**/ +VOID * +EFIAPI +GetHobList ( + VOID + ); + + +/** + Updates the pointer to the HOB list. + + @param HobList Hob list pointer to store + +**/ +EFI_STATUS +EFIAPI +SetHobList ( + IN VOID *HobList + ); + + +/** + Retrieves the magic value from the PE/COFF header. + + @param Hdr The buffer in which to return the PE32, PE32+, or TE header. + + @return EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC - Image is PE32 + @return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC - Image is PE32+ + +**/ +VOID +CreateHobList ( + IN VOID *MemoryBegin, + IN UINTN MemoryLength, + IN VOID *HobBase, + IN VOID *StackBase + ); + + +/** + This service enables PEIMs to create various types of HOBs. + + @param Type The type of HOB to be installed. + @param Length The length of the HOB to be added. + + @retval !NULL The HOB was successfully created. + @retval NULL There is no additional space for HOB creation. + +**/ +VOID * +CreateHob ( + IN UINT16 HobType, + IN UINT16 HobLenght + ); + + +/** + Returns the next instance of a HOB type from the starting HOB. + + This function searches the first instance of a HOB type from the starting HOB pointer. + If there does not exist such HOB type from the starting HOB pointer, it will return NULL. + In contrast with macro GET_NEXT_HOB(), this function does not skip the starting HOB pointer + unconditionally: it returns HobStart back if HobStart itself meets the requirement; + caller is required to use GET_NEXT_HOB() if it wishes to skip current HobStart. + If HobStart is NULL, then ASSERT(). + + @param Type The HOB type to return. + @param HobStart The starting HOB pointer to search from. + + @return The next instance of a HOB type from the starting HOB. + +**/ +VOID * +EFIAPI +GetNextHob ( + IN UINT16 Type, + IN CONST VOID *HobStart + ); + +/** + Returns the first instance of a HOB type among the whole HOB list. + + This function searches the first instance of a HOB type among the whole HOB list. + If there does not exist such HOB type in the HOB list, it will return NULL. + + @param Type The HOB type to return. + + @return The next instance of a HOB type from the starting HOB. + +**/ +VOID * +EFIAPI +GetFirstHob ( + IN UINT16 Type + ); + +/** + This function searches the first instance of a HOB from the starting HOB pointer. + Such HOB should satisfy two conditions: + its HOB type is EFI_HOB_TYPE_GUID_EXTENSION and its GUID Name equals to the input Guid. + If there does not exist such HOB from the starting HOB pointer, it will return NULL. + Caller is required to apply GET_GUID_HOB_DATA () and GET_GUID_HOB_DATA_SIZE () + to extract the data section and its size info respectively. + In contrast with macro GET_NEXT_HOB(), this function does not skip the starting HOB pointer + unconditionally: it returns HobStart back if HobStart itself meets the requirement; + caller is required to use GET_NEXT_HOB() if it wishes to skip current HobStart. + If Guid is NULL, then ASSERT(). + If HobStart is NULL, then ASSERT(). + + @param Guid The GUID to match with in the HOB list. + @param HobStart A pointer to a Guid. + + @return The next instance of the matched GUID HOB from the starting HOB. + +**/ +VOID * +EFIAPI +GetNextGuidHob ( + IN CONST EFI_GUID *Guid, + IN CONST VOID *HobStart + ); + +/** + This function searches the first instance of a HOB among the whole HOB list. + Such HOB should satisfy two conditions: + its HOB type is EFI_HOB_TYPE_GUID_EXTENSION and its GUID Name equals to the input Guid. + If there does not exist such HOB from the starting HOB pointer, it will return NULL. + Caller is required to apply GET_GUID_HOB_DATA () and GET_GUID_HOB_DATA_SIZE () + to extract the data section and its size info respectively. + If Guid is NULL, then ASSERT(). + + @param Guid The GUID to match with in the HOB list. + + @return The first instance of the matched GUID HOB among the whole HOB list. + +**/ +VOID * +EFIAPI +GetFirstGuidHob ( + IN CONST EFI_GUID *Guid + ); + + +/** + Builds a HOB for a loaded PE32 module. + + This function builds a HOB for a loaded PE32 module. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If ModuleName is NULL, then ASSERT(). + If there is no additional space for HOB creation, then ASSERT(). + + @param ModuleName The GUID File Name of the module. + @param MemoryAllocationModule The 64 bit physical address of the module. + @param ModuleLength The length of the module in bytes. + @param EntryPoint The 64 bit physical address of the module entry point. + +**/ +VOID +EFIAPI +BuildModuleHob ( + IN CONST EFI_GUID *ModuleName, + IN EFI_PHYSICAL_ADDRESS MemoryAllocationModule, + IN UINT64 ModuleLength, + IN EFI_PHYSICAL_ADDRESS EntryPoint + ); + +/** + Builds a HOB that describes a chunk of system memory. + + This function builds a HOB that describes a chunk of system memory. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If there is no additional space for HOB creation, then ASSERT(). + + @param ResourceType The type of resource described by this HOB. + @param ResourceAttribute The resource attributes of the memory described by this HOB. + @param PhysicalStart The 64 bit physical address of memory described by this HOB. + @param NumberOfBytes The length of the memory described by this HOB in bytes. + +**/ +VOID +EFIAPI +BuildResourceDescriptorHob ( + IN EFI_RESOURCE_TYPE ResourceType, + IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute, + IN EFI_PHYSICAL_ADDRESS PhysicalStart, + IN UINT64 NumberOfBytes + ); + +/** + Builds a GUID HOB with a certain data length. + + This function builds a customized HOB tagged with a GUID for identification + and returns the start address of GUID HOB data so that caller can fill the customized data. + The HOB Header and Name field is already stripped. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If Guid is NULL, then ASSERT(). + If there is no additional space for HOB creation, then ASSERT(). + If DataLength >= (0x10000 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT(). + + @param Guid The GUID to tag the customized HOB. + @param DataLength The size of the data payload for the GUID HOB. + + @return The start address of GUID HOB data. + +**/ +VOID * +EFIAPI +BuildGuidHob ( + IN CONST EFI_GUID *Guid, + IN UINTN DataLength + ); + +/** + Copies a data buffer to a newly-built HOB. + + This function builds a customized HOB tagged with a GUID for identification, + copies the input data to the HOB data field and returns the start address of the GUID HOB data. + The HOB Header and Name field is already stripped. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If Guid is NULL, then ASSERT(). + If Data is NULL and DataLength > 0, then ASSERT(). + If there is no additional space for HOB creation, then ASSERT(). + If DataLength >= (0x10000 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT(). + + @param Guid The GUID to tag the customized HOB. + @param Data The data to be copied into the data field of the GUID HOB. + @param DataLength The size of the data payload for the GUID HOB. + + @return The start address of GUID HOB data. + +**/ +VOID * +EFIAPI +BuildGuidDataHob ( + IN CONST EFI_GUID *Guid, + IN VOID *Data, + IN UINTN DataLength + ); + +/** + Builds a Firmware Volume HOB. + + This function builds a Firmware Volume HOB. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The base address of the Firmware Volume. + @param Length The size of the Firmware Volume in bytes. + +**/ +VOID +EFIAPI +BuildFvHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ); + +/** + Builds a Firmware Volume HOB and a resrouce descriptor hob + + This function builds a Firmware Volume HOB. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The base address of the Firmware Volume. + @param Length The size of the Firmware Volume in bytes. + +**/ +VOID +EFIAPI +BuildFvHobs ( + IN EFI_PHYSICAL_ADDRESS PhysicalStart, + IN UINT64 NumberOfBytes, + IN EFI_RESOURCE_ATTRIBUTE_TYPE *ResourceAttribute OPTIONAL + ); + + +/** + Builds a EFI_HOB_TYPE_FV2 HOB. + + This function builds a EFI_HOB_TYPE_FV2 HOB. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The base address of the Firmware Volume. + @param Length The size of the Firmware Volume in bytes. + @param FvName The name of the Firmware Volume. + @param FileName The name of the file. + +**/ +VOID +EFIAPI +BuildFv2Hob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN CONST EFI_GUID *FvName, + IN CONST EFI_GUID *FileName + ); + +/** + Builds a Capsule Volume HOB. + + This function builds a Capsule Volume HOB. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The base address of the Capsule Volume. + @param Length The size of the Capsule Volume in bytes. + +**/ +VOID +EFIAPI +BuildCvHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ); + +/** + Builds a HOB for the CPU. + + This function builds a HOB for the CPU. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If there is no additional space for HOB creation, then ASSERT(). + + @param SizeOfMemorySpace The maximum physical memory addressability of the processor. + @param SizeOfIoSpace The maximum physical I/O addressability of the processor. + +**/ +VOID +EFIAPI +BuildCpuHob ( + IN UINT8 SizeOfMemorySpace, + IN UINT8 SizeOfIoSpace + ); + +/** + Builds a HOB for the Stack. + + This function builds a HOB for the stack. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The 64 bit physical address of the Stack. + @param Length The length of the stack in bytes. + +**/ +VOID +EFIAPI +BuildStackHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ); + +/** + Update the Stack Hob if the stack has been moved + + @param BaseAddress The 64 bit physical address of the Stack. + @param Length The length of the stack in bytes. + +**/ +VOID +UpdateStackHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ); + + +/** + Builds a HOB for the BSP store. + + This function builds a HOB for BSP store. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The 64 bit physical address of the BSP. + @param Length The length of the BSP store in bytes. + @param MemoryType Type of memory allocated by this HOB. + +**/ +VOID +EFIAPI +BuildBspStoreHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_MEMORY_TYPE MemoryType + ); + +/** + Builds a HOB for the memory allocation. + + This function builds a HOB for the memory allocation. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The 64 bit physical address of the memory. + @param Length The length of the memory allocation in bytes. + @param MemoryType Type of memory allocated by this HOB. + +**/ +VOID +EFIAPI +BuildMemoryAllocationHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_MEMORY_TYPE MemoryType + ); + + +/** + Allocates one or more 4KB pages of type EfiBootServicesData. + + Allocates the number of 4KB pages of MemoryType and returns a pointer to the + allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL + is returned. If there is not enough memory remaining to satisfy the request, then NULL is + returned. + + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocatePages ( + IN UINTN Pages + ); + +/** + Allocates a buffer of type EfiBootServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiBootServicesData and returns a + pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is + returned. If there is not enough memory remaining to satisfy the request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocatePool ( + IN UINTN AllocationSize + ); + + +/** + Allocates one or more 4KB pages of type EfiBootServicesData at a specified alignment. + + Allocates the number of 4KB pages specified by Pages of type EfiBootServicesData with an + alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is + returned. If there is not enough memory at the specified alignment remaining to satisfy the + request, then NULL is returned. + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateAlignedPages ( + IN UINTN Pages, + IN UINTN Alignment + ); + + +EFI_STATUS +EFIAPI +LoadPeCoffImage ( + IN VOID *PeCoffImage, + OUT EFI_PHYSICAL_ADDRESS *ImageAddress, + OUT UINT64 *ImageSize, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint + ); + +EFI_STATUS +EFIAPI +LoadDxeCoreFromFfsFile ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN UINTN StackSize + ); + +EFI_STATUS +EFIAPI +LoadDxeCoreFromFv ( + IN UINTN *FvInstance, OPTIONAL + IN UINTN StackSize + ); + +EFI_STATUS +EFIAPI +DecompressFirstFv ( + VOID + ); + +VOID +EFIAPI +AddDxeCoreReportStatusCodeCallback ( + VOID + ); + + +#endif diff --git a/EmbeddedPkg/Include/Library/RealTimeClockLib.h b/EmbeddedPkg/Include/Library/RealTimeClockLib.h new file mode 100644 index 0000000000..6fdc34d8b9 --- /dev/null +++ b/EmbeddedPkg/Include/Library/RealTimeClockLib.h @@ -0,0 +1,138 @@ +/** @file + Implement EFI RealTimeClock runtime services via Lib. + + Currently this driver does not support runtime virtual calling. + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __REAL_TIME_CLOCK_LIB__ +#define __REAL_TIME_CLOCK_LIB__ + + +/** + Returns the current time and date information, and the time-keeping capabilities + of the hardware platform. + + @param Time A pointer to storage to receive a snapshot of the current time. + @param Capabilities An optional pointer to a buffer to receive the real time clock + device's capabilities. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER Time is NULL. + @retval EFI_DEVICE_ERROR The time could not be retrieved due to hardware error. + +**/ +EFI_STATUS +EFIAPI +LibGetTime ( + OUT EFI_TIME *Time, + OUT EFI_TIME_CAPABILITIES *Capabilities + ); + + +/** + Sets the current local time and date information. + + @param Time A pointer to the current time. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER A time field is out of range. + @retval EFI_DEVICE_ERROR The time could not be set due due to hardware error. + +**/ +EFI_STATUS +EFIAPI +LibSetTime ( + IN EFI_TIME *Time + ); + + +/** + Returns the current wakeup alarm clock setting. + + @param Enabled Indicates if the alarm is currently enabled or disabled. + @param Pending Indicates if the alarm signal is pending and requires acknowledgement. + @param Time The current alarm setting. + + @retval EFI_SUCCESS The alarm settings were returned. + @retval EFI_INVALID_PARAMETER Any parameter is NULL. + @retval EFI_DEVICE_ERROR The wakeup time could not be retrieved due to a hardware error. + +**/ +EFI_STATUS +EFIAPI +LibGetWakeupTime ( + OUT BOOLEAN *Enabled, + OUT BOOLEAN *Pending, + OUT EFI_TIME *Time + ); + + +/** + Sets the system wakeup alarm clock time. + + @param Enabled Enable or disable the wakeup alarm. + @param Time If Enable is TRUE, the time to set the wakeup alarm for. + + @retval EFI_SUCCESS If Enable is TRUE, then the wakeup alarm was enabled. If + Enable is FALSE, then the wakeup alarm was disabled. + @retval EFI_INVALID_PARAMETER A time field is out of range. + @retval EFI_DEVICE_ERROR The wakeup time could not be set due to a hardware error. + @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform. + +**/ +EFI_STATUS +EFIAPI +LibSetWakeupTime ( + IN BOOLEAN Enabled, + OUT EFI_TIME *Time + ); + + + +/** + This is the declaration of an EFI image entry point. This can be the entry point to an application + written to this specification, an EFI boot service driver, or an EFI runtime driver. + + @param ImageHandle Handle that identifies the loaded image. + @param SystemTable System Table for this image. + + @retval EFI_SUCCESS The operation completed successfully. + +**/ +EFI_STATUS +EFIAPI +LibRtcInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + + +/** + Fixup internal data so that EFI can be call in virtual mode. + Call the passed in Child Notify event and convert any pointers in + lib to virtual mode. + + @param[in] Event The Event that is being processed + @param[in] Context Event Context +**/ +VOID +EFIAPI +LibRtcVirtualNotifyEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ); + + +#endif + diff --git a/EmbeddedPkg/Include/Protocol/DebugSupportPeriodicCallback.h b/EmbeddedPkg/Include/Protocol/DebugSupportPeriodicCallback.h new file mode 100644 index 0000000000..d780cbd4cb --- /dev/null +++ b/EmbeddedPkg/Include/Protocol/DebugSupportPeriodicCallback.h @@ -0,0 +1,42 @@ +/** @file + Protocol is used to help implement DebugSupport.RegisterPeriodicCallback() functionality. + This enables the DXE timer driver to support the periodic callback function so the + DebugSupport driver does not need to contain platform specific information about how a timer + works. + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#ifndef __DEBUG_SUPPORT_PERIODIC_CALLBACK_H__ +#define __DEBUG_SUPPORT_PERIODIC_CALLBACK_H__ + +#include + +typedef struct _EFI_DEBUG_SUPPORT_PERIODIC_CALLBACK_PROTOCOL EFI_DEBUG_SUPPORT_PERIODIC_CALLBACK_PROTOCOL; + + +// {9546E07C-2CBB-4c88-986C-CD341086F044} +#define EFI_DEBUG_SUPPORT_PERIODIC_CALLBACK_PROTOCOL_GUID \ + { 0x9546e07c, 0x2cbb, 0x4c88, { 0x98, 0x6c, 0xcd, 0x34, 0x10, 0x86, 0xf0, 0x44 } } + + +// +// DebugSupport protocol definition +// +struct _EFI_DEBUG_SUPPORT_PERIODIC_CALLBACK_PROTOCOL { + EFI_PERIODIC_CALLBACK PeriodicCallback; +}; + +extern EFI_GUID gEfiDebugSupportPeriodicCallbackProtocolGuid; + +#endif diff --git a/EmbeddedPkg/Include/Protocol/EblAddCommand.h b/EmbeddedPkg/Include/Protocol/EblAddCommand.h new file mode 100644 index 0000000000..2c11e7fe58 --- /dev/null +++ b/EmbeddedPkg/Include/Protocol/EblAddCommand.h @@ -0,0 +1,156 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +/** @file + Abstraction for hardware based interrupt routine + + Copyright (c) 2009 Apple Inc. + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#ifndef __EBL_ADD_COMMAND_H__ +#define __EBL_ADD_COMMAND_H__ + + + +// +// Protocol GUID +// +// AEDA2428-9A22-4637-9B21-545E28FBB829 + +#define EBL_ADD_COMMAND_PROTOCOL_GUID \ + { 0xaeda2428, 0x9a22, 0x4637, { 0x9b, 0x21, 0x54, 0x5e, 0x28, 0xfb, 0xb8, 0x29 } } + + +typedef struct _EBL_ADD_COMMAND_PROTOCOL EBL_ADD_COMMAND_PROTOCOL; + +typedef +EFI_STATUS +(EFIAPI *EBL_COMMMAND) ( + IN UINTN Argc, + IN CHAR8 **Argv + ); + +typedef struct { + CHAR8 *Name; + CHAR8 *HelpSummary; + CHAR8 *Help; + EBL_COMMMAND Command; +} EBL_COMMAND_TABLE; + + +/** + Add a single command table entry. + + @param EntryArray Pointer EBL_COMMAND_TABLE of the command that is being added + +**/ +typedef +VOID +(EFIAPI *EBL_ADD_COMMAND) ( + IN const EBL_COMMAND_TABLE *Entry + ); + + +/** + Add a multiple command table entry. + + @param EntryArray Pointer EBL_COMMAND_TABLE of the commands that are being added + + @param ArrayCount Nuber of commands in the EntryArray. + +**/ +typedef +VOID +(EFIAPI *EBL_ADD_COMMANDS) ( + IN const EBL_COMMAND_TABLE *EntryArray, + IN UINTN ArrayCount + ); + + +typedef +VOID +(EFIAPI *EBL_GET_CHAR_CALL_BACK) ( + IN UINTN ElapsedTime + ); + +/** + Return a keypress or optionally timeout if a timeout value was passed in. + An optional callback funciton is called evey second when waiting for a + timeout. + + @param Key EFI Key information returned + @param TimeoutInSec Number of seconds to wait to timeout + @param CallBack Callback called every second during the timeout wait + + @return EFI_SUCCESS Key was returned + @return EFI_TIMEOUT If the TimoutInSec expired + +**/ +typedef +EFI_STATUS +(EFIAPI *EBL_GET_CHAR_KEY) ( + IN OUT EFI_INPUT_KEY *Key, + IN UINTN TimeoutInSec, + IN EBL_GET_CHAR_CALL_BACK CallBack OPTIONAL + ); + + +/** + This routine is used prevent command output data from scrolling off the end + of the screen. The global gPageBreak is used to turn on or off this feature. + If the CurrentRow is near the end of the screen pause and print out a prompt + If the use hits Q to quit return TRUE else for any other key return FALSE. + PrefixNewline is used to figure out if a newline is needed before the prompt + string. This depends on the last print done before calling this function. + CurrentRow is updated by one on a call or set back to zero if a prompt is + needed. + + @param CurrentRow Used to figure out if its the end of the page and updated + @param PrefixNewline Did previous print issue a newline + + @return TRUE if Q was hit to quit, FALSE in all other cases. + +**/ +typedef +BOOLEAN +(EFIAPI *EBL_ANY_KEY_CONTINUE_Q_QUIT) ( + IN UINTN *CurrentRow, + IN BOOLEAN PrefixNewline + ); + + + +struct _EBL_ADD_COMMAND_PROTOCOL { + EBL_ADD_COMMAND AddCommand; + EBL_ADD_COMMANDS AddCommands; + + // Commands to reuse EBL infrastructure + EBL_GET_CHAR_KEY EblGetCharKey; + EBL_ANY_KEY_CONTINUE_Q_QUIT EblAnyKeyToContinueQtoQuit; +}; + +extern EFI_GUID gEfiEblAddCommandProtocolGuid; + +#endif + + diff --git a/EmbeddedPkg/Include/Protocol/EmbeddedDevice.h b/EmbeddedPkg/Include/Protocol/EmbeddedDevice.h new file mode 100644 index 0000000000..4be6c11a28 --- /dev/null +++ b/EmbeddedPkg/Include/Protocol/EmbeddedDevice.h @@ -0,0 +1,58 @@ +/** @file + Deal with devices that just exist in memory space. + + To follow the EFI driver model you need a root handle to start with. An + EFI driver will have a driver binding protocol (Supported, Start, Stop) + that is used to layer on top of a handle via a gBS->ConnectController. + The first handle has to just be in the system to make that work. For + PCI it is a PCI Root Bridge IO protocol that provides the root. + + On an embedded system with MMIO device we need a handle to just + show up. That handle will have this protocol and a device path + protocol on it. + + For an ethernet device the device path must contain a MAC address device path + node. + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EMBEDDED_DEVICE_PROTOCOL_H__ +#define __EMBEDDED_DEVICE_PROTOCOL_H__ + + +// +// Protocol GUID +// +// BF4B9D10-13EC-43dd-8880-E90B718F27DE + +#define EMBEDDED_DEVICE_PROTOCOL_GUID \ + { 0xbf4b9d10, 0x13ec, 0x43dd, { 0x88, 0x80, 0xe9, 0xb, 0x71, 0x8f, 0x27, 0xde } } + + + +typedef struct { + UINT16 VendorId; + UINT16 DeviceId; + UINT16 RevisionId; + UINT16 SubsystemId; + UINT16 SubsystemVendorId; + UINT8 ClassCode[3]; + UINT8 HeaderSize; + UINTN BaseAddress; +} EMBEDDED_DEVICE_PROTOCOL; + +extern EFI_GUID gEmbeddedDeviceGuid; + +#endif + + diff --git a/EmbeddedPkg/Include/Protocol/EmbeddedExternalDevice.h b/EmbeddedPkg/Include/Protocol/EmbeddedExternalDevice.h new file mode 100644 index 0000000000..1131399a60 --- /dev/null +++ b/EmbeddedPkg/Include/Protocol/EmbeddedExternalDevice.h @@ -0,0 +1,94 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EMBEDDED_EXTERNAL_DEVICE_H__ +#define __EMBEDDED_EXTERNAL_DEVICE_H__ + +// +// Protocol GUID +// +#define EMBEDDED_EXTERNAL_DEVICE_PROTOCOL_GUID { 0x735F8C64, 0xD696, 0x44D0, { 0xBD, 0xF2, 0x44, 0x7F, 0xD0, 0x5A, 0x54, 0x06 }} + +// +// Protocol interface structure +// +typedef struct _EMBEDDED_EXTERNAL_DEVICE EMBEDDED_EXTERNAL_DEVICE; + +// +// Function Prototypes +// +typedef +EFI_STATUS +(EFIAPI *EMBEDDED_EXTERNAL_DEVICE_READ) ( + IN EMBEDDED_EXTERNAL_DEVICE *This, + IN UINTN Register, + IN UINTN Length, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Read a set of contiguous external device registers. + +Arguments: + + This - pointer to protocol + Offset - starting register number + Length - number of bytes to read + Buffer - destination buffer + +Returns: + + EFI_SUCCESS - registers read successfully + +--*/ +; + +typedef +EFI_STATUS +(EFIAPI *EMBEDDED_EXTERNAL_DEVICE_WRITE) ( + IN EMBEDDED_EXTERNAL_DEVICE *This, + IN UINTN Register, + IN UINTN Length, + IN VOID *Buffer + ) +/*++ + +Routine Description: + + Write to a set of contiguous external device registers. + +Arguments: + + This - pointer to protocol + Offset - starting register number + Length - number of bytes to write + Buffer - source buffer + +Returns: + + EFI_SUCCESS - registers written successfully + +--*/ +; + +struct _EMBEDDED_EXTERNAL_DEVICE { + EMBEDDED_EXTERNAL_DEVICE_READ Read; + EMBEDDED_EXTERNAL_DEVICE_WRITE Write; +}; + +extern EFI_GUID gEmbeddedExternalDeviceProtocolGuid; + +#endif // __EMBEDDED_EXTERNAL_DEVICE_H__ diff --git a/EmbeddedPkg/Include/Protocol/EmbeddedGpio.h b/EmbeddedPkg/Include/Protocol/EmbeddedGpio.h new file mode 100644 index 0000000000..fd3d3bd9bc --- /dev/null +++ b/EmbeddedPkg/Include/Protocol/EmbeddedGpio.h @@ -0,0 +1,167 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EMBEDDED_GPIO_H__ +#define __EMBEDDED_GPIO_H__ + +// +// Protocol interface structure +// +typedef struct _EMBEDDED_GPIO EMBEDDED_GPIO; + +// +// Data Types +// +typedef UINTN EMBEDDED_GPIO_PIN; + +#define GPIO(Port, Pin) ((EMBEDDED_GPIO_PIN)(((Port) << (16)) | (Pin))) +#define GPIO_PIN(x) ((EMBEDDED_GPIO_PIN)(x) & (0xFFFF)) +#define GPIO_PORT(x) ((EMBEDDED_GPIO_PIN)(x) >> (16)) + +typedef enum { + GPIO_MODE_INPUT = 0x00, + GPIO_MODE_OUTPUT_0 = 0x0E, + GPIO_MODE_OUTPUT_1 = 0x0F, + GPIO_MODE_SPECIAL_FUNCTION_2 = 0x02, + GPIO_MODE_SPECIAL_FUNCTION_3 = 0x03, + GPIO_MODE_SPECIAL_FUNCTION_4 = 0x04, + GPIO_MODE_SPECIAL_FUNCTION_5 = 0x05, + GPIO_MODE_SPECIAL_FUNCTION_6 = 0x06, + GPIO_MODE_SPECIAL_FUNCTION_7 = 0x07 +} EMBEDDED_GPIO_MODE; + +typedef enum { + GPIO_PULL_NONE, + GPIO_PULL_UP, + GPIO_PULL_DOWN +} EMBEDDED_GPIO_PULL; + +// +// Function Prototypes +// +typedef +EFI_STATUS +(EFIAPI *EMBEDDED_GPIO_GET) ( + IN EMBEDDED_GPIO *This, + IN EMBEDDED_GPIO_PIN Gpio, + OUT UINTN *Value + ); +/*++ + +Routine Description: + + Gets the state of a GPIO pin + +Arguments: + + This - pointer to protocol + Gpio - which pin to read + Value - state of the pin + +Returns: + + EFI_SUCCESS - GPIO state returned in Value + +--*/ + + +typedef +EFI_STATUS +(EFIAPI *EMBEDDED_GPIO_SET) ( + IN EMBEDDED_GPIO *This, + IN EMBEDDED_GPIO_PIN Gpio, + IN EMBEDDED_GPIO_MODE Mode + ); +/*++ + +Routine Description: + + Sets the state of a GPIO pin + +Arguments: + + This - pointer to protocol + Gpio - which pin to modify + Mode - mode to set + +Returns: + + EFI_SUCCESS - GPIO set as requested + +--*/ + + +typedef +EFI_STATUS +(EFIAPI *EMBEDDED_GPIO_GET_MODE) ( + IN EMBEDDED_GPIO *This, + IN EMBEDDED_GPIO_PIN Gpio, + OUT EMBEDDED_GPIO_MODE *Mode + ); +/*++ + +Routine Description: + + Gets the mode (function) of a GPIO pin + +Arguments: + + This - pointer to protocol + Gpio - which pin + Mode - pointer to output mode value + +Returns: + + EFI_SUCCESS - mode value retrieved + +--*/ + + +typedef +EFI_STATUS +(EFIAPI *EMBEDDED_GPIO_SET_PULL) ( + IN EMBEDDED_GPIO *This, + IN EMBEDDED_GPIO_PIN Gpio, + IN EMBEDDED_GPIO_PULL Direction + ); +/*++ + +Routine Description: + + Sets the pull-up / pull-down resistor of a GPIO pin + +Arguments: + + This - pointer to protocol + Gpio - which pin + Direction - pull-up, pull-down, or none + +Returns: + + EFI_SUCCESS - pin was set + +--*/ + + + +struct _EMBEDDED_GPIO { + EMBEDDED_GPIO_GET Get; + EMBEDDED_GPIO_SET Set; + EMBEDDED_GPIO_GET_MODE GetMode; + EMBEDDED_GPIO_SET_PULL SetPull; +}; + +extern EFI_GUID gEmbeddedGpioProtocolGuid; + +#endif diff --git a/EmbeddedPkg/Include/Protocol/HardwareInterrupt.h b/EmbeddedPkg/Include/Protocol/HardwareInterrupt.h new file mode 100644 index 0000000000..a4825832c4 --- /dev/null +++ b/EmbeddedPkg/Include/Protocol/HardwareInterrupt.h @@ -0,0 +1,151 @@ +/** @file + Abstraction for hardware based interrupt routine + + On non IA-32 systems it is common to have a single hardware interrupt vector + and a 2nd layer of software that routes the interrupt handlers based on the + interrupt source. This protocol enables this routing. The driver implementing + this protocol is responsible for clearing the pending interrupt in the + interrupt routing hardware. The HARDWARE_INTERRUPT_HANDLER is responsible + for clearing interrupt sources from individual devices. + + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __HARDWARE_INTERRUPT_H__ +#define __HARDWARE_INTERRUPT_H__ + +#include + + +// +// Protocol GUID +// +// EAB39028-3D05-4316-AD0C-D64808DA3FF1 + +#define EFI_HARDWARE_INTERRUPT_PROTOCOL_GGUID \ + { 0x2890B3EA, 0x053D, 0x1643, { 0xAD, 0x0C, 0xD6, 0x48, 0x08, 0xDA, 0x3F, 0xF1 } } + + +typedef struct _EFI_HARDWARE_INTERRUPT_PROTOCOL EFI_HARDWARE_INTERRUPT_PROTOCOL; + + +typedef UINTN HARDWARE_INTERRUPT_SOURCE; + + +/** + C Interrupt Handler calledin the interrupt context when Source interrupt is active. + + @param Source Source of the interrupt. Hardware routing off a specific platform defines + what source means. + @param SystemContext Pointer to system register context. Mostly used by debuggers and will + update the system context after the return from the interrupt if + modified. Don't change these values unless you know what you are doing + +**/ +typedef +VOID +(EFIAPI *HARDWARE_INTERRUPT_HANDLER) ( + IN HARDWARE_INTERRUPT_SOURCE Source, + IN EFI_SYSTEM_CONTEXT SystemContext + ); + + +/** + Register Handler for the specified interrupt source. + + @param This Instance pointer for this protocol + @param Source Hardware source of the interrupt + @param Handler Callback for interrupt. NULL to unregister + + @retval EFI_SUCCESS Source was updated to support Handler. + @retval EFI_DEVICE_ERROR Hardware could not be programmed. + +**/ +typedef +EFI_STATUS +(EFIAPI *HARDWARE_INTERRUPT_REGISTER) ( + IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This, + IN HARDWARE_INTERRUPT_SOURCE Source, + IN HARDWARE_INTERRUPT_HANDLER Handler + ); + + +/** + Enable interrupt source Source. + + @param This Instance pointer for this protocol + @param Source Hardware source of the interrupt + + @retval EFI_SUCCESS Source interrupt enabled. + @retval EFI_DEVICE_ERROR Hardware could not be programmed. + +**/ +typedef +EFI_STATUS +(EFIAPI *HARDWARE_INTERRUPT_ENABLE) ( + IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This, + IN HARDWARE_INTERRUPT_SOURCE Source + ); + + + +/** + Disable interrupt source Source. + + @param This Instance pointer for this protocol + @param Source Hardware source of the interrupt + + @retval EFI_SUCCESS Source interrupt disabled. + @retval EFI_DEVICE_ERROR Hardware could not be programmed. + +**/ +typedef +EFI_STATUS +(EFIAPI *HARDWARE_INTERRUPT_DISABLE) ( + IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This, + IN HARDWARE_INTERRUPT_SOURCE Source + ); + + +/** + Return current state of interrupt source Source. + + @param This Instance pointer for this protocol + @param Source Hardware source of the interrupt + @param InterruptState TRUE: source enabled, FALSE: source disabled. + + @retval EFI_SUCCESS InterruptState is valid + @retval EFI_DEVICE_ERROR InterruptState is not valid + +**/ +typedef +EFI_STATUS +(EFIAPI *HARDWARE_INTERRUPT_INTERRUPT_STATE) ( + IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This, + IN HARDWARE_INTERRUPT_SOURCE Source, + IN BOOLEAN *InterruptState + ); + + +struct _EFI_HARDWARE_INTERRUPT_PROTOCOL { + HARDWARE_INTERRUPT_REGISTER RegisterInterruptSource; + HARDWARE_INTERRUPT_ENABLE EnableInterruptSource; + HARDWARE_INTERRUPT_DISABLE DisableInterruptSource; + HARDWARE_INTERRUPT_INTERRUPT_STATE GetInterruptSourceState; +}; + +extern EFI_GUID gHardwareInterruptProtocolGuid; + +#endif + + diff --git a/EmbeddedPkg/Library/EblAddExternalCommandLib/EblAddExternalCommandLib.c b/EmbeddedPkg/Library/EblAddExternalCommandLib/EblAddExternalCommandLib.c new file mode 100644 index 0000000000..fcb533c8b7 --- /dev/null +++ b/EmbeddedPkg/Library/EblAddExternalCommandLib/EblAddExternalCommandLib.c @@ -0,0 +1,156 @@ +/** @file + Add external EblCmd Lib + + Copyright (c) 2007, Intel Corporation
+ Portions copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#include +#include +#include +#include +#include + + +STATIC BOOLEAN gInstalledCommand = FALSE; +STATIC EFI_EVENT mEblCommandRegistration = NULL; + +STATIC const EBL_COMMAND_TABLE *mAddExternalCmdLibTemplate = NULL; +STATIC UINTN mAddExternalCmdLibTemplateSize = 0; +EBL_ADD_COMMAND_PROTOCOL *gEblExternalCommand = NULL; + + +/** + Return a keypress or optionally timeout if a timeout value was passed in. + An optional callback funciton is called evey second when waiting for a + timeout. + + @param Key EFI Key information returned + @param TimeoutInSec Number of seconds to wait to timeout + @param CallBack Callback called every second during the timeout wait + + @return EFI_SUCCESS Key was returned + @return EFI_TIMEOUT If the TimoutInSec expired + +**/ +EFI_STATUS +EFIAPI +EblGetCharKey ( + IN OUT EFI_INPUT_KEY *Key, + IN UINTN TimeoutInSec, + IN EBL_GET_CHAR_CALL_BACK CallBack OPTIONAL + ) +{ + if (gEblExternalCommand != NULL) { + return gEblExternalCommand->EblGetCharKey (Key, TimeoutInSec, CallBack); + } + return EFI_TIMEOUT; +} + + +/** + This routine is used prevent command output data from scrolling off the end + of the screen. The global gPageBreak is used to turn on or off this feature. + If the CurrentRow is near the end of the screen pause and print out a prompt + If the use hits Q to quit return TRUE else for any other key return FALSE. + PrefixNewline is used to figure out if a newline is needed before the prompt + string. This depends on the last print done before calling this function. + CurrentRow is updated by one on a call or set back to zero if a prompt is + needed. + + @param CurrentRow Used to figure out if its the end of the page and updated + @param PrefixNewline Did previous print issue a newline + + @return TRUE if Q was hit to quit, FALSE in all other cases. + +**/ +BOOLEAN +EFIAPI +EblAnyKeyToContinueQtoQuit ( + IN UINTN *CurrentRow, + IN BOOLEAN PrefixNewline + ) +{ + if (gEblExternalCommand != NULL) { + return gEblExternalCommand->EblAnyKeyToContinueQtoQuit (CurrentRow, PrefixNewline); + } + return FALSE; +} + + + +/** + Update mFvbEntry. Add new entry, or update existing entry if Fvb protocol is + reinstalled. + + @param Event The Event that is being processed + @param Context Event Context + +**/ +VOID +EFIAPI +EblAddCommandNotificationEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + + if (!gInstalledCommand) { + Status = gBS->LocateProtocol (&gEfiEblAddCommandProtocolGuid, NULL, (VOID **)&gEblExternalCommand); + if (!EFI_ERROR (Status)) { + gEblExternalCommand->AddCommands (mAddExternalCmdLibTemplate, mAddExternalCmdLibTemplateSize); + gInstalledCommand = TRUE; + } + } +} + + + +/** + The user Entry Point for the driver. The user code starts with this function + as the real entry point for the image goes into a library that calls this + function. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +EblAddExternalCommands ( + IN const EBL_COMMAND_TABLE *EntryArray, + IN UINTN ArrayCount + ) +{ + if (mAddExternalCmdLibTemplate != NULL) { + return EFI_ALREADY_STARTED; + } + + mAddExternalCmdLibTemplate = EntryArray; + mAddExternalCmdLibTemplateSize = ArrayCount; + + EfiCreateProtocolNotifyEvent ( + &gEfiEblAddCommandProtocolGuid, + TPL_CALLBACK, + EblAddCommandNotificationEvent, + NULL, + &mEblCommandRegistration + ); + + return EFI_SUCCESS; +} + diff --git a/EmbeddedPkg/Library/EblAddExternalCommandLib/EblAddExternalCommandLib.inf b/EmbeddedPkg/Library/EblAddExternalCommandLib/EblAddExternalCommandLib.inf new file mode 100644 index 0000000000..5b0af6e75a --- /dev/null +++ b/EmbeddedPkg/Library/EblAddExternalCommandLib/EblAddExternalCommandLib.inf @@ -0,0 +1,47 @@ +#%HEADER% +#/** @file +# Component description file for the entry point to a EFIDXE Drivers +# +# Library to abstract Framework extensions that conflict with UEFI 2.0 Specification +# Copyright (c) 2007 - 2007, Intel Corporation +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = EblAddExternalCommandLib + FILE_GUID = 9195D970-C6F7-484E-8013-5B03C89C3B81 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = EblAddExternalCommandLib|DXE_DRIVER UEFI_APPLICATION UEFI_DRIVER + + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources.common] + EblAddExternalCommandLib.c + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + +[LibraryClasses] + UefiBootServicesTableLib + UefiLib + +[Protocols] + +[Guids] + \ No newline at end of file diff --git a/EmbeddedPkg/Library/EblCmdLibNull/EblCmdLibNull.c b/EmbeddedPkg/Library/EblCmdLibNull/EblCmdLibNull.c new file mode 100644 index 0000000000..5cbdfdb15a --- /dev/null +++ b/EmbeddedPkg/Library/EblCmdLibNull/EblCmdLibNull.c @@ -0,0 +1,28 @@ +/** @file + Null EblCmdLib + + Copyright (c) 2007, Intel Corporation
+ Portions copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#include +#include + + +VOID +EblInitializeExternalCmd ( + VOID + ) +{ + return; +} diff --git a/EmbeddedPkg/Library/EblCmdLibNull/EblCmdLibNull.inf b/EmbeddedPkg/Library/EblCmdLibNull/EblCmdLibNull.inf new file mode 100644 index 0000000000..b40935b838 --- /dev/null +++ b/EmbeddedPkg/Library/EblCmdLibNull/EblCmdLibNull.inf @@ -0,0 +1,45 @@ +#%HEADER% +#/** @file +# Component description file for the entry point to a EFIDXE Drivers +# +# Library to abstract Framework extensions that conflict with UEFI 2.0 Specification +# Copyright (c) 2007 - 2007, Intel Corporation +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = EblCmdLibNull + FILE_GUID = 3513C4E2-06D6-4921-9C2B-E938777BA79E + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = EfiCmdLib|DXE_DRIVER UEFI_APPLICATION UEFI_DRIVER + + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources.common] + EblCmdLibNull.c + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + +[LibraryClasses] + +[Protocols] + +[Guids] + \ No newline at end of file diff --git a/EmbeddedPkg/Library/EblNetworkLib/EblNetworkLib.c b/EmbeddedPkg/Library/EblNetworkLib/EblNetworkLib.c new file mode 100644 index 0000000000..13766c88b2 --- /dev/null +++ b/EmbeddedPkg/Library/EblNetworkLib/EblNetworkLib.c @@ -0,0 +1,173 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include + +#include +#include + + +BOOLEAN gUseIpv6 = FALSE; + +EFI_STATUS +EFIAPI +EblGetCurrentIpAddress ( + IN OUT EFI_IP_ADDRESS *Ip + ) +{ + EFI_STATUS Status; + EFI_PXE_BASE_CODE_PROTOCOL *Pxe; + + Status = gBS->LocateProtocol (&gEfiPxeBaseCodeProtocolGuid, NULL, (VOID **)&Pxe); + if (EFI_ERROR(Status)) { + return Status; + } + + Status = Pxe->Start (Pxe, gUseIpv6); + if (EFI_ERROR(Status) && (Status != EFI_ALREADY_STARTED)) { + return Status; + } + + CopyMem (Ip, &Pxe->Mode->StationIp, sizeof (EFI_IP_ADDRESS)); + + return Status; +} + + +EFI_STATUS +EFIAPI +EblGetCurrentMacAddress ( + IN OUT EFI_MAC_ADDRESS *Mac + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNet; + + Status = gBS->LocateProtocol (&gEfiSimpleNetworkProtocolGuid, NULL, (VOID **)&SimpleNet); + if (EFI_ERROR(Status)) { + return Status; + } + + CopyMem (SimpleNet->Mode->CurrentAddress.Addr, Mac, sizeof (EFI_MAC_ADDRESS)); + return Status; +} + + +CHAR8 * +EFIAPI +EblLoadFileBootTypeString ( + IN EFI_HANDLE Handle + ) +{ + EFI_STATUS Status; + VOID *NullPtr; + + Status = gBS->HandleProtocol (Handle, &gEfiPxeBaseCodeProtocolGuid, &NullPtr); + if (!EFI_ERROR (Status)) { + return "EFI PXE Network Boot"; + } + + return ""; +} + +EFI_STATUS +EFIAPI +EblPerformDHCP ( + IN BOOLEAN SortOffers + ) +{ + EFI_STATUS Status; + EFI_PXE_BASE_CODE_PROTOCOL *Pxe; + + Status = gBS->LocateProtocol (&gEfiPxeBaseCodeProtocolGuid, NULL, (VOID **)&Pxe); + if (EFI_ERROR(Status)) { + return Status; + } + + Status = Pxe->Start (Pxe, gUseIpv6); + if (EFI_ERROR(Status) && (Status != EFI_ALREADY_STARTED)) { + return Status; + } + + Status = Pxe->Dhcp(Pxe, TRUE); + return Status; +} + + +EFI_STATUS +EFIAPI +EblSetStationIp ( + IN EFI_IP_ADDRESS *NewStationIp, OPTIONAL + IN EFI_IP_ADDRESS *NewSubnetMask OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_PXE_BASE_CODE_PROTOCOL *Pxe; + + Status = gBS->LocateProtocol (&gEfiPxeBaseCodeProtocolGuid, NULL, (VOID **)&Pxe); + if (EFI_ERROR(Status)) { + return Status; + } + + Status = Pxe->Start (Pxe, gUseIpv6); + if (EFI_ERROR(Status) && (Status != EFI_ALREADY_STARTED)) { + return Status; + } + + Status = Pxe->SetStationIp (Pxe, NewStationIp, NewSubnetMask); + return Status; +} + + +EFI_STATUS +EFIAPI +EblMtftp ( + IN EFI_PXE_BASE_CODE_TFTP_OPCODE Operation, + IN OUT VOID *BufferPtr OPTIONAL, + IN BOOLEAN Overwrite, + IN OUT UINT64 *BufferSize, + IN UINTN *BlockSize OPTIONAL, + IN EFI_IP_ADDRESS *ServerIp, + IN UINT8 *Filename OPTIONAL, + IN EFI_PXE_BASE_CODE_MTFTP_INFO *Info OPTIONAL, + IN BOOLEAN DontUseBuffer + ) +{ + EFI_STATUS Status; + EFI_PXE_BASE_CODE_PROTOCOL *Pxe; + + Status = gBS->LocateProtocol (&gEfiPxeBaseCodeProtocolGuid, NULL, (VOID **)&Pxe); + if (EFI_ERROR(Status)) { + return Status; + } + + Status = Pxe->Mtftp ( + Pxe, + Operation, + BufferPtr, + Overwrite, + BufferSize, + BlockSize, + ServerIp, + Filename, + Info, + DontUseBuffer + ); + return Status; +} + diff --git a/EmbeddedPkg/Library/EblNetworkLib/EblNetworkLib.inf b/EmbeddedPkg/Library/EblNetworkLib/EblNetworkLib.inf new file mode 100644 index 0000000000..f46242fc62 --- /dev/null +++ b/EmbeddedPkg/Library/EblNetworkLib/EblNetworkLib.inf @@ -0,0 +1,28 @@ +#%HEADER% +# +# Copyright (c) 2005 - 2009 Apple Computer, Inc. All rights reserved. +# +# +# + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = EblNetworkLib + FILE_GUID = D885869A-7869-47DB-9429-DE03C318BCFD + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = EblNetworkLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER + +[sources.common] + EblNetworkLib.c + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + +[Protocols] + gEfiSimpleNetworkProtocolGuid + gEfiPxeBaseCodeProtocolGuid + +[Depex] + TRUE \ No newline at end of file diff --git a/EmbeddedPkg/Library/EfiFileLib/EfiFileLib.c b/EmbeddedPkg/Library/EfiFileLib/EfiFileLib.c new file mode 100644 index 0000000000..e98651b14d --- /dev/null +++ b/EmbeddedPkg/Library/EfiFileLib/EfiFileLib.c @@ -0,0 +1,1483 @@ +/** @file + File IO routines inspired by Streams with an EFI flavor + + Copyright (c) 2007, Intel Corporation
+ Portions copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + Basic support for opening files on different device types. The device string + is in the form of DevType:Path. Current DevType is required as there is no + current mounted device concept of current working directory concept implement + by this library. + + Device names are case insensative and only check the leading characters for + unique matches. Thus the following are all the same: + LoadFile0: + l0: + L0: + Lo0: + + Supported Device Names: + A0x1234:0x12 - A memory buffer starting at address 0x1234 for 0x12 bytes + l1: - EFI LoadFile device one. + B0: - EFI BlockIo zero. + fs3: - EFI Simple File System device 3 + Fv2: - EFI Firmware VOlume device 2 + 10.0.1.102: - TFTP service IP followed by the file name +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define EFI_OPEN_FILE_GUARD_HEADER 0x4B4D4641 +#define EFI_OPEN_FILE_GUARD_FOOTER 0x444D5A56 + +// Need to defend against this overflowing +#define MAX_CMD_LINE 0x200 + +typedef struct { + UINT32 Header; + EFI_OPEN_FILE File; + UINT32 Footer; +} EFI_OPEN_FILE_GUARD; + + +// globals to store current open device info +EFI_HANDLE *mBlkIo = NULL; +UINTN mBlkIoCount = 0; + +EFI_HANDLE *mFs = NULL; +UINTN mFsCount = 0; +// mFsInfo[] array entries must match mFs[] handles +EFI_FILE_SYSTEM_INFO **mFsInfo = NULL; + +EFI_HANDLE *mFv = NULL; +UINTN mFvCount = 0; +EFI_HANDLE *mLoadFile = NULL; +UINTN mLoadFileCount = 0; + + + +/** + Internal worker function to validate a File handle. + + @param File Open File Handle + + @return TRUE File is valid + @return FALSE File is not valid + + +**/ +BOOLEAN +FileHandleValid ( + IN EFI_OPEN_FILE *File + ) +{ + EFI_OPEN_FILE_GUARD *GuardFile; + + // Look right before and after file structure for the correct signatures + GuardFile = BASE_CR (File, EFI_OPEN_FILE_GUARD, File); + if ((GuardFile->Header != EFI_OPEN_FILE_GUARD_HEADER) || + (GuardFile->Footer != EFI_OPEN_FILE_GUARD_FOOTER) ) { + return FALSE; + } + + return TRUE; +} + +/** + Internal worker function. If Buffer is not NULL free it. + + @param Buffer Buffer to FreePool() + +**/ +VOID +EblFreePool ( + IN VOID *Buffer + ) +{ + if (Buffer != NULL) { + FreePool (Buffer); + } +} + +/** + Update Device List Global Variables + +**/ +VOID +EblUpdateDeviceLists ( + VOID + ) +{ + EFI_STATUS Status; + UINTN Size; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs; + EFI_FILE_HANDLE Root; + UINTN Index; + + if (mBlkIo != NULL) { + FreePool (mBlkIo); + } + gBS->LocateHandleBuffer (ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &mBlkIoCount, &mBlkIo); + + if (mFv != NULL) { + FreePool (mFv); + } + gBS->LocateHandleBuffer (ByProtocol, &gEfiFirmwareVolume2ProtocolGuid, NULL, &mFvCount, &mFv); + + if (mLoadFile != NULL) { + FreePool (mLoadFile); + } + gBS->LocateHandleBuffer (ByProtocol, &gEfiLoadFileProtocolGuid, NULL, &mLoadFileCount, &mLoadFile); + + if (mFs != NULL) { + FreePool (mFs); + } + + if (&mFsInfo[0] != NULL) { + // Need to Free the mFsInfo prior to reclaculating mFsCount so don't move this code + for (Index = 0; Index < mFsCount; Index++) { + if (mFsInfo[Index] != NULL) { + FreePool (mFsInfo[Index]); + } + } + FreePool (mFsInfo); + } + + gBS->LocateHandleBuffer (ByProtocol, &gEfiSimpleFileSystemProtocolGuid, NULL, &mFsCount, &mFs); + + + mFsInfo = AllocateZeroPool (mFsCount * sizeof (EFI_FILE_SYSTEM_INFO *)); + if (mFsInfo == NULL) { + // If we can't do this then we can't support file system entries + mFsCount = 0; + } else { + // Loop through all the file system structures and cache the file system info data + for (Index =0; Index < mFsCount; Index++) { + Status = gBS->HandleProtocol (mFs[Index], &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Fs); + if (!EFI_ERROR (Status)) { + Status = Fs->OpenVolume (Fs, &Root); + if (!EFI_ERROR (Status)) { + // Get information about the volume + Size = 0; + Status = Root->GetInfo (Root, &gEfiFileSystemInfoGuid, &Size, mFsInfo[Index]); + if (Status == EFI_BUFFER_TOO_SMALL) { + mFsInfo[Index] = AllocatePool (Size); + Status = Root->GetInfo (Root, &gEfiFileSystemInfoGuid, &Size, mFsInfo[Index]); + } + + Root->Close (Root); + } + } + } + } +} + + +/** + PathName is in the form : for example fs1:\ or ROOT:\. + Return TRUE if the prefix of PathName matches a file system + Volume Name. MatchIndex is the array index in mFsInfo[] of the match, + and it can be used with mFs[] to find the handle that needs to be opened + + @param PathName PathName to check + @param FileStart Index of the first character of the + @param MatchIndex Index in mFsInfo[] that matches + + @return TRUE PathName matches a Volume Label and MatchIndex is valid + @return FALSE PathName does not match a Volume Label MatchIndex undefined + +**/ +BOOLEAN +EblMatchVolumeName ( + IN CHAR8 *PathName, + IN UINTN FileStart, + OUT UINTN *MatchIndex + ) +{ + UINTN Index; + UINTN Compare; + UINTN VolStrLen; + BOOLEAN Match; + + for (Index =0; Index < mFsCount; Index++) { + if (mFsInfo[Index] == NULL) { + // FsInfo is not valid so skip it + continue; + } + VolStrLen = StrLen (mFsInfo[Index]->VolumeLabel); + for (Compare = 0, Match = TRUE; Compare < (FileStart - 1); Compare++) { + if (Compare > VolStrLen) { + Match = FALSE; + break; + } + if (PathName[Compare] != (CHAR8)mFsInfo[Index]->VolumeLabel[Compare]) { + // If the VolumeLabel has a space allow a _ to match with it in addition to ' ' + if (!((PathName[Compare] == '_') && (mFsInfo[Index]->VolumeLabel[Compare] == L' '))) { + Match = FALSE; + break; + } + } + } + if (Match) { + *MatchIndex = Index; + return TRUE; + } + } + + return FALSE; +} + + +/** + Return the number of devices of the current type active in the system + + @param Type Device type to check + + @return 0 Invalid type + +**/ +UINTN +EfiGetDeviceCounts ( + IN EFI_OPEN_FILE_TYPE DeviceType + ) +{ + switch (DeviceType) { + case EfiOpenLoadFile: + return mLoadFileCount; + case EfiOpenFirmwareVolume: + return mFvCount; + case EfiOpenFileSystem: + return mFsCount; + case EfiOpenBlockIo: + return mBlkIoCount; + default: + return 0; + } +} + +EFI_STATUS +ConvertIpStringToEfiIp ( + IN CHAR8 *PathName, + OUT EFI_IP_ADDRESS *ServerIp + ) +{ + CHAR8 *Str; + + Str = PathName; + ServerIp->v4.Addr[0] = (UINT8)AsciiStrDecimalToUintn (Str); + + Str = AsciiStrStr (Str, "."); + if (Str == NULL) { + return EFI_DEVICE_ERROR; + } + + ServerIp->v4.Addr[1] = (UINT8)AsciiStrDecimalToUintn (++Str); + + Str = AsciiStrStr (Str, "."); + if (Str == NULL) { + return EFI_DEVICE_ERROR; + } + + ServerIp->v4.Addr[2] = (UINT8)AsciiStrDecimalToUintn (++Str); + + Str = AsciiStrStr (Str, "."); + if (Str == NULL) { + return EFI_DEVICE_ERROR; + } + + ServerIp->v4.Addr[3] = (UINT8)AsciiStrDecimalToUintn (++Str); + + return EFI_SUCCESS; +} + + +/** + Internal work function to extract a device number from a string skipping + text. Easy way to extract numbers from strings like blk7:. + + @param Str String to extract device number form + + @return -1 Device string is not valid + @return Device # + +**/ +UINTN +EblConvertDevStringToNumber ( + IN CHAR8 *Str + ) +{ + UINTN Max; + UINTN Index; + + + // Find the first digit + Max = AsciiStrLen (Str); + for (Index = 0; !((*Str >= '0') && (*Str <= '9')) && (Index < Max); Index++) { + Str++; + } + if (Index == Max) { + return (UINTN)-1; + } + + return AsciiStrDecimalToUintn (Str); +} + + +/** + Internal work function to fill in EFI_OPEN_FILE information for the Fs and BlkIo + + @param File Open file handle + @param FileName Name of file after device stripped off + + +**/ +EFI_STATUS +EblFileDevicePath ( + IN OUT EFI_OPEN_FILE *File, + IN CHAR8 *FileName, + IN CONST UINT64 OpenMode + ) +{ + EFI_STATUS Status; + UINTN Size; + FILEPATH_DEVICE_PATH *FilePath; + EFI_DEVICE_PATH_PROTOCOL *FileDevicePath; + CHAR16 UnicodeFileName[MAX_PATHNAME]; + EFI_BLOCK_IO_PROTOCOL *BlkIo; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs; + EFI_FILE_HANDLE Root; + + + if ( *FileName != 0 ) { + AsciiStrToUnicodeStr (FileName, UnicodeFileName); + } else { + AsciiStrToUnicodeStr ("\\", UnicodeFileName); + } + + Size = StrSize (UnicodeFileName); + FileDevicePath = AllocatePool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + sizeof (EFI_DEVICE_PATH_PROTOCOL)); + if (FileDevicePath != NULL) { + FilePath = (FILEPATH_DEVICE_PATH *) FileDevicePath; + FilePath->Header.Type = MEDIA_DEVICE_PATH; + FilePath->Header.SubType = MEDIA_FILEPATH_DP; + CopyMem (&FilePath->PathName, UnicodeFileName, Size); + SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH); + SetDevicePathEndNode (NextDevicePathNode (&FilePath->Header)); + + if (File->EfiHandle != NULL) { + File->DevicePath = DevicePathFromHandle (File->EfiHandle); + } + + File->DevicePath = AppendDevicePath (File->DevicePath, FileDevicePath); + FreePool (FileDevicePath); + } + + Status = gBS->HandleProtocol (File->EfiHandle, &gEfiBlockIoProtocolGuid, (VOID **)&BlkIo); + if (!EFI_ERROR (Status)) { + CopyMem (&File->FsBlockIoMedia, BlkIo->Media, sizeof (EFI_BLOCK_IO_MEDIA)); + + // If we are not opening the device this will get over written with file info + File->MaxPosition = MultU64x32 (BlkIo->Media->LastBlock + 1, BlkIo->Media->BlockSize); + } + + if (File->Type == EfiOpenFileSystem) { + Status = gBS->HandleProtocol (File->EfiHandle, &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Fs); + if (!EFI_ERROR (Status)) { + Status = Fs->OpenVolume (Fs, &Root); + if (!EFI_ERROR (Status)) { + // Get information about the volume + Size = 0; + Status = Root->GetInfo (Root, &gEfiFileSystemInfoGuid, &Size, File->FsInfo); + if (Status == EFI_BUFFER_TOO_SMALL) { + File->FsInfo = AllocatePool (Size); + Status = Root->GetInfo (Root, &gEfiFileSystemInfoGuid, &Size, File->FsInfo); + } + + // Get information about the file + Status = Root->Open (Root, &File->FsFileHandle, UnicodeFileName, OpenMode, 0); + if (!EFI_ERROR (Status)) { + Size = 0; + Status = File->FsFileHandle->GetInfo (File->FsFileHandle, &gEfiFileInfoGuid, &Size, NULL); + if (Status == EFI_BUFFER_TOO_SMALL) { + File->FsFileInfo = AllocatePool (Size); + Status = File->FsFileHandle->GetInfo (File->FsFileHandle, &gEfiFileInfoGuid, &Size, File->FsFileInfo); + if (!EFI_ERROR (Status)) { + File->Size = (UINTN)File->FsFileInfo->FileSize; + File->MaxPosition = (UINT64)File->Size; + } + } + } + + Root->Close (Root); + } + } + } else if (File->Type == EfiOpenBlockIo) { + File->Size = (UINTN)File->MaxPosition; + } + + return Status; +} + +#define ToUpper(a) ((((a) >= 'a') && ((a) <= 'z')) ? ((a) - 'a' + 'A') : (a)) + +EFI_STATUS +CompareGuidToString ( + IN EFI_GUID *Guid, + IN CHAR8 *String + ) +{ + CHAR8 AsciiGuid[64]; + CHAR8 *StringPtr; + CHAR8 *GuidPtr; + + AsciiSPrint (AsciiGuid, sizeof(AsciiGuid), "%g", Guid); + + StringPtr = String; + GuidPtr = AsciiGuid; + + while ((*StringPtr != '\0') && (*GuidPtr != '\0')) { + // Skip dashes + if (*StringPtr == '-') { + StringPtr++; + continue; + } + + if (*GuidPtr == '-') { + GuidPtr++; + continue; + } + + if (ToUpper(*StringPtr) != ToUpper(*GuidPtr)) { + return EFI_NOT_FOUND; + } + + StringPtr++; + GuidPtr++; + } + + return EFI_SUCCESS; +} + + +/** + Internal work function to fill in EFI_OPEN_FILE information for the FV + + @param File Open file handle + @param FileName Name of file after device stripped off + + +**/ +EFI_STATUS +EblFvFileDevicePath ( + IN OUT EFI_OPEN_FILE *File, + IN CHAR8 *FileName, + IN CONST UINT64 OpenMode + ) +{ + EFI_STATUS Status; + EFI_STATUS GetNextFileStatus; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH DevicePathNode; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UINTN Key; + UINT32 AuthenticationStatus; + CHAR8 AsciiSection[MAX_PATHNAME]; + VOID *Section; + UINTN SectionSize; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; + EFI_LBA Lba; + UINTN BlockSize; + UINTN NumberOfBlocks; + + + Status = gBS->HandleProtocol (File->EfiHandle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&File->Fv); + if (EFI_ERROR (Status)) { + return Status; + } + + DevicePath = DevicePathFromHandle (File->EfiHandle); + + if (*FileName == '\0') { + File->DevicePath = DuplicateDevicePath (DevicePath); + } else { + Key = 0; + do { + File->FvType = EFI_FV_FILETYPE_ALL; + GetNextFileStatus = File->Fv->GetNextFile ( + File->Fv, + &Key, + &File->FvType, + &File->FvNameGuid, + &File->FvAttributes, + &File->Size + ); + if (!EFI_ERROR (GetNextFileStatus)) { + Section = NULL; + + // Compare GUID first + Status = CompareGuidToString (&File->FvNameGuid, FileName); + if (!EFI_ERROR(Status)) { + break; + } + + Status = File->Fv->ReadSection ( + File->Fv, + &File->FvNameGuid, + EFI_SECTION_USER_INTERFACE, + 0, + &Section, + &SectionSize, + &AuthenticationStatus + ); + if (!EFI_ERROR (Status)) { + UnicodeStrToAsciiStr (Section, AsciiSection); + if (AsciiStriCmp (FileName, AsciiSection) == 0) { + FreePool (Section); + break; + } + FreePool (Section); + } + } + } while (!EFI_ERROR (GetNextFileStatus)); + + if (EFI_ERROR (GetNextFileStatus)) { + return GetNextFileStatus; + } + + File->MaxPosition = File->Size; + EfiInitializeFwVolDevicepathNode (&DevicePathNode, &File->FvNameGuid); + File->DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&DevicePathNode); + } + + + // Get FVB Info about the handle + Status = gBS->HandleProtocol (File->EfiHandle, &gEfiFirmwareVolumeBlockProtocolGuid, (VOID **)&Fvb); + if (!EFI_ERROR (Status)) { + Status = Fvb->GetPhysicalAddress (Fvb, &File->FvStart); + if (!EFI_ERROR (Status)) { + for (Lba = 0, File->FvSize = 0; ; File->FvSize += (BlockSize * NumberOfBlocks), Lba += NumberOfBlocks) { + Status = Fvb->GetBlockSize (Fvb, Lba, &BlockSize, &NumberOfBlocks); + if (EFI_ERROR (Status)) { + break; + } + } + } + } + + // FVB not required if FV was soft loaded... + return EFI_SUCCESS; +} + + + + +/** + Open a device named by PathName. The PathName includes a device name and + path seperated by a :. See file header for more details on the PathName + syntax. There is no checking to prevent a file from being opened more than + one type. + + SectionType is only used to open an FV. Each file in an FV contains multiple + secitons and only the SectionType section is opened. + + For any file that is opened with EfiOpen() must be closed with EfiClose(). + + @param PathName Path to parse to open + @param OpenMode Same as EFI_FILE.Open() + @param SectionType Section in FV to open. + + @return NULL Open failed + @return Valid EFI_OPEN_FILE handle + +**/ +EFI_OPEN_FILE * +EfiOpen ( + IN CHAR8 *PathName, + IN CONST UINT64 OpenMode, + IN CONST EFI_SECTION_TYPE SectionType + ) +{ + EFI_STATUS Status; + EFI_OPEN_FILE *File; + EFI_OPEN_FILE FileData; + UINTN StrLen; + UINTN FileStart; + UINTN DevNumber = 0; + EFI_OPEN_FILE_GUARD *GuardFile; + BOOLEAN VolumeNameMatch; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UINTN Size; + EFI_IP_ADDRESS Ip; + + EblUpdateDeviceLists (); + + File = &FileData; + ZeroMem (File, sizeof (EFI_OPEN_FILE)); + File->FvSectionType = SectionType; + + StrLen = AsciiStrSize (PathName); + if (StrLen <= 2) { + // Smallest valid path is 1 char and a null + return NULL; + } + + for (FileStart = 0; FileStart < StrLen; FileStart++) { + if (PathName[FileStart] == ':') { + FileStart++; + break; + } + } + + if (FileStart == 0) { + // We could add a current working diretory concept + return NULL; + } + + // + // Matching volume name has precedence over handle based names + // + VolumeNameMatch = EblMatchVolumeName (PathName, FileStart, &DevNumber); + if (!VolumeNameMatch) { + DevNumber = EblConvertDevStringToNumber ((CHAR8 *)PathName); + } + + File->DeviceName = AllocatePool (StrLen); + AsciiStrCpy (File->DeviceName, PathName); + File->DeviceName[FileStart - 1] = '\0'; + File->FileName = &File->DeviceName[FileStart]; + + // + // Use best match algorithm on the dev names so we only need to look at the + // first few charters to match the full device name. Short name forms are + // legal from the caller. + // + Status = EFI_SUCCESS; + if (*PathName == 'f' || *PathName == 'F' || VolumeNameMatch) { + if (PathName[1] == 's' || PathName[1] == 'S' || VolumeNameMatch) { + if (DevNumber >= mFsCount) { + goto ErrorExit; + } + File->Type = EfiOpenFileSystem; + File->EfiHandle = mFs[DevNumber]; + Status = EblFileDevicePath (File, &PathName[FileStart], OpenMode); + + } else if (PathName[1] == 'v' || PathName[1] == 'V') { + if (DevNumber >= mFvCount) { + goto ErrorExit; + } + File->Type = EfiOpenFirmwareVolume; + File->EfiHandle = mFv[DevNumber]; + + if ((PathName[FileStart] == '/') || (PathName[FileStart] == '\\')) { + // Skip leading / as its not really needed for the FV since no directories are supported + FileStart++; + } + Status = EblFvFileDevicePath (File, &PathName[FileStart], OpenMode); + } + } else if ((*PathName == 'A') || (*PathName == 'a')) { + // Handle a:0x10000000:0x1234 address form a:ADDRESS:SIZE + File->Type = EfiOpenMemoryBuffer; + // 1st colon is at PathName[FileStart - 1] + File->Buffer = (VOID *)AsciiStrHexToUintn (&PathName[FileStart]); + + // Find 2nd colon + while ((PathName[FileStart] != ':') && (PathName[FileStart] != '\0')) { + FileStart++; + } + + // If we ran out of string, there's no extra data + if (PathName[FileStart] == '\0') { + File->Size = 0; + } else { + File->Size = AsciiStrHexToUintn (&PathName[FileStart + 1]); + } + + // if there's no number after the second colon, default + // the end of memory + if (File->Size == 0) { + File->Size = (UINTN)(0 - (UINTN)File->Buffer); + } + + File->MaxPosition = File->Size; + File->BaseOffset = (UINTN)File->Buffer; + + } else if (*PathName== 'l' || *PathName == 'L') { + if (DevNumber >= mLoadFileCount) { + goto ErrorExit; + } + File->Type = EfiOpenLoadFile; + File->EfiHandle = mLoadFile[DevNumber]; + + Status = gBS->HandleProtocol (File->EfiHandle, &gEfiLoadFileProtocolGuid, (VOID **)&File->LoadFile); + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + Status = gBS->HandleProtocol (File->EfiHandle, &gEfiDevicePathProtocolGuid, (VOID **)&DevicePath); + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + File->DevicePath = DuplicateDevicePath (DevicePath); + + } else if (*PathName == 'b' || *PathName == 'B') { + // Handle b#:0x10000000:0x1234 address form b#:ADDRESS:SIZE + if (DevNumber >= mBlkIoCount) { + goto ErrorExit; + } + File->Type = EfiOpenBlockIo; + File->EfiHandle = mBlkIo[DevNumber]; + EblFileDevicePath (File, "", OpenMode); + + // 1st colon is at PathName[FileStart - 1] + File->DiskOffset = AsciiStrHexToUintn (&PathName[FileStart]); + + // Find 2nd colon + while ((PathName[FileStart] != ':') && (PathName[FileStart] != '\0')) { + FileStart++; + } + + // If we ran out of string, there's no extra data + if (PathName[FileStart] == '\0') { + Size = 0; + } else { + Size = AsciiStrHexToUintn (&PathName[FileStart + 1]); + } + + // if a zero size is passed in (or the size is left out entirely), + // go to the end of the device. + if (Size == 0) { + File->Size = File->Size - File->DiskOffset; + } else { + File->Size = Size; + } + + File->MaxPosition = File->Size; + File->BaseOffset = File->DiskOffset; + } else if ((*PathName) >= '0' && (*PathName <= '9')) { + + // Get current IP address + Status = EblGetCurrentIpAddress (&Ip); + if (EFI_ERROR(Status)) { + AsciiPrint("Device IP Address is not configured.\n"); + goto ErrorExit; + } + + + // Parse X.X.X.X:Filename, only support IPv4 TFTP for now... + File->Type = EfiOpenTftp; + File->IsDirty = FALSE; + File->IsBufferValid = FALSE; + + Status = ConvertIpStringToEfiIp (PathName, &File->ServerIp); + } + + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + GuardFile = (EFI_OPEN_FILE_GUARD *)AllocateZeroPool (sizeof (EFI_OPEN_FILE_GUARD)); + if (GuardFile == NULL) { + goto ErrorExit; + } + + GuardFile->Header = EFI_OPEN_FILE_GUARD_HEADER; + CopyMem (&(GuardFile->File), &FileData, sizeof (EFI_OPEN_FILE)); + GuardFile->Footer = EFI_OPEN_FILE_GUARD_FOOTER; + + return &(GuardFile->File); + +ErrorExit: + FreePool (File->DeviceName); + return NULL; +} + +#define FILE_COPY_CHUNK 0x01000000 + +EFI_STATUS +EfiCopyFile ( + IN CHAR8 *DestinationFile, + IN CHAR8 *SourceFile + ) +{ + EFI_OPEN_FILE *Source = NULL; + EFI_OPEN_FILE *Destination = NULL; + EFI_STATUS Status = EFI_SUCCESS; + VOID *Buffer = NULL; + UINTN Size; + UINTN Offset; + UINTN Chunk = FILE_COPY_CHUNK; + + Source = EfiOpen(SourceFile, EFI_FILE_MODE_READ, 0); + if (Source == NULL) { + AsciiPrint("Source file open error.\n"); + Status = EFI_NOT_FOUND; + goto Exit; + } + + Destination = EfiOpen(DestinationFile, EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, 0); + if (Destination == NULL) { + AsciiPrint("Destination file open error.\n"); + Status = EFI_NOT_FOUND; + goto Exit; + } + + Buffer = AllocatePool(FILE_COPY_CHUNK); + if (Buffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + + Size = EfiTell(Source, NULL); + + for (Offset = 0; Offset + FILE_COPY_CHUNK <= Size; Offset += Chunk) { + Chunk = FILE_COPY_CHUNK; + + Status = EfiRead(Source, Buffer, &Chunk); + if (EFI_ERROR(Status)) { + AsciiPrint("Read file error\n"); + goto Exit; + } + + Status = EfiWrite(Destination, Buffer, &Chunk); + if (EFI_ERROR(Status)) { + AsciiPrint("Write file error\n"); + goto Exit; + } + } + + // Any left over? + if (Offset < Size) { + Chunk = Size - Offset; + + Status = EfiRead(Source, Buffer, &Chunk); + if (EFI_ERROR(Status)) { + AsciiPrint("Read file error\n"); + goto Exit; + } + + Status = EfiWrite(Destination, Buffer, &Chunk); + if (EFI_ERROR(Status)) { + AsciiPrint("Write file error\n"); + goto Exit; + } + } + +Exit: + if (Source != NULL) { + Status = EfiClose(Source); + if (EFI_ERROR(Status)) { + AsciiPrint("Source close error"); + } + } + + if (Destination != NULL) { + Status = EfiClose(Destination); + if (EFI_ERROR(Status)) { + AsciiPrint("Destination close error"); + } + } + + if (Buffer != NULL) { + FreePool(Buffer); + } + + return Status; +} + +/** + Use DeviceType and Index to form a valid PathName and try and open it. + + @param DeviceType Device type to open + @param Index Device Index to use. Zero relative. + + @return NULL Open failed + @return Valid EFI_OPEN_FILE handle + +**/ +EFI_OPEN_FILE * +EfiDeviceOpenByType ( + IN EFI_OPEN_FILE_TYPE DeviceType, + IN UINTN Index + ) +{ + CHAR8 *DevStr; + CHAR8 Path[MAX_CMD_LINE]; + + switch (DeviceType) { + case EfiOpenLoadFile: + DevStr = "loadfile%d:"; + break; + case EfiOpenFirmwareVolume: + DevStr = "fv%d:"; + break; + case EfiOpenFileSystem: + DevStr = "fs%d:"; + break; + case EfiOpenBlockIo: + DevStr = "blk%d:"; + break; + case EfiOpenMemoryBuffer: + DevStr = "a%d:"; + break; + default: + return NULL; + } + + AsciiSPrint (Path, MAX_PATHNAME, DevStr, Index); + + return EfiOpen (Path, EFI_FILE_MODE_READ, 0); +} + + +/** + Close a file handle opened by EfiOpen() and free all resources allocated by + EfiOpen(). + + @param Stream Open File Handle + + @return EFI_INVALID_PARAMETER Stream is not an Open File + @return EFI_SUCCESS Steam closed + +**/ +EFI_STATUS +EfiClose ( + IN EFI_OPEN_FILE *File + ) +{ + EFI_STATUS Status; + UINT64 TftpBufferSize; + + if (!FileHandleValid (File)) { + return EFI_INVALID_PARAMETER; + } + + //Write the buffer contents to TFTP file. + if ((File->Type == EfiOpenTftp) && (File->IsDirty)) { + + TftpBufferSize = File->Size; + Status = EblMtftp ( + EFI_PXE_BASE_CODE_TFTP_WRITE_FILE, + File->Buffer, + TRUE, + &TftpBufferSize, + NULL, + &File->ServerIp, + (UINT8 *)File->FileName, + NULL, + FALSE + ); + if (EFI_ERROR(Status)) { + AsciiPrint("TFTP error during APPLE_NSP_TFTP_WRITE_FILE: %r\n", Status); + return Status; + } + } + + if ((File->Type == EfiOpenLoadFile) || + ((File->Type == EfiOpenTftp) && (File->IsBufferValid == TRUE))) { + EblFreePool(File->Buffer); + } + + EblFreePool (File->DevicePath); + EblFreePool (File->DeviceName); + EblFreePool (File->FsFileInfo); + EblFreePool (File->FsInfo); + + if (File->FsFileHandle != NULL) { + File->FsFileHandle->Close (File->FsFileHandle); + } + + // Need to free File and it's Guard structures + EblFreePool (BASE_CR (File, EFI_OPEN_FILE_GUARD, File)); + return EFI_SUCCESS; +} + + +/** + Return the size of the file represented by Stream. Also return the current + Seek position. Opening a file will enable a valid file size to be returned. + LoadFile is an exception as a load file size is set to zero. + + @param Stream Open File Handle + + @return 0 Stream is not an Open File or a valid LoadFile handle + +**/ +UINTN +EfiTell ( + IN EFI_OPEN_FILE *File, + OUT EFI_LBA *CurrentPosition OPTIONAL + ) +{ + EFI_STATUS Status; + UINT64 BufferSize = 0; + + if (!FileHandleValid (File)) { + return 0; + } + + if (CurrentPosition != NULL) { + *CurrentPosition = File->CurrentPosition; + } + + if (File->Type == EfiOpenLoadFile) { + // Figure out the File->Size + File->Buffer = NULL; + File->Size = 0; + Status = File->LoadFile->LoadFile (File->LoadFile, File->DevicePath, FALSE, &File->Size, File->Buffer); + if (Status != EFI_BUFFER_TOO_SMALL) { + return 0; + } + + File->MaxPosition = (UINT64)File->Size; + } else if (File->Type == EfiOpenTftp) { + + Status = EblMtftp ( + EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE, + NULL, + FALSE, + &BufferSize, + NULL, + &File->ServerIp, + (UINT8 *)File->FileName, + NULL, + TRUE + ); + if (EFI_ERROR(Status)) { + AsciiPrint("TFTP error during APPLE_NSP_TFTP_GET_FILE_SIZE: %r\n", Status); + return 0; + } + + File->Size = BufferSize; + File->MaxPosition = File->Size; + } + + return File->Size; +} + + +/** + Seek to the Offset locaiton in the file. LoadFile and FV device types do + not support EfiSeek(). It is not possible to grow the file size using + EfiSeek(). + + SeekType defines how use Offset to calculate the new file position: + EfiSeekStart : Position = Offset + EfiSeekCurrent: Position is Offset bytes from the current position + EfiSeekEnd : Only supported if Offset is zero to seek to end of file. + + @param Stream Open File Handle + @param Offset Offset to seek too. + @param SeekType Type of seek to perform + + + @return EFI_INVALID_PARAMETER Stream is not an Open File + @return EFI_UNSUPPORTED LoadFile and FV doe not support Seek + @return EFI_NOT_FOUND Seek past the end of the file. + @return EFI_SUCCESS Steam closed + +**/ +EFI_STATUS +EfiSeek ( + IN EFI_OPEN_FILE *File, + IN EFI_LBA Offset, + IN EFI_SEEK_TYPE SeekType + ) +{ + EFI_STATUS Status; + UINT64 CurrentPosition; + + if (!FileHandleValid (File)) { + return EFI_INVALID_PARAMETER; + } + + if (File->Type == EfiOpenLoadFile || File->Type == EfiOpenFirmwareVolume) { + // LoadFile and FV do not support Seek + return EFI_UNSUPPORTED; + } + + CurrentPosition = File->CurrentPosition; + switch (SeekType) { + case EfiSeekStart: + if (Offset > File->MaxPosition) { + return EFI_NOT_FOUND; + } + CurrentPosition = Offset; + break; + + case EfiSeekCurrent: + if ((File->CurrentPosition + Offset) > File->MaxPosition) { + return EFI_NOT_FOUND; + } + CurrentPosition += Offset; + break; + + case EfiSeekEnd: + if (Offset != 0) { + // We don't support growing file size via seeking past end of file + return EFI_UNSUPPORTED; + } + CurrentPosition = File->MaxPosition; + break; + + default: + return EFI_NOT_FOUND; + } + + Status = EFI_SUCCESS; + if (File->FsFileHandle != NULL) { + Status = File->FsFileHandle->SetPosition (File->FsFileHandle, CurrentPosition); + } + + if (!EFI_ERROR (Status)) { + File->CurrentPosition = CurrentPosition; + } + + return Status; +} + +EFI_STATUS +CacheTftpFile ( + IN OUT EFI_OPEN_FILE *File + ) +{ + EFI_STATUS Status; + UINT64 TftpBufferSize; + + if (File->IsBufferValid) { + return EFI_SUCCESS; + } + + // Make sure the file size is set. + EfiTell (File, NULL); + + //Allocate a buffer to hold the whole file. + File->Buffer = AllocatePool(File->Size); + if (File->Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + TftpBufferSize = File->Size; + + Status = EblMtftp ( + EFI_PXE_BASE_CODE_TFTP_READ_FILE, + File->Buffer, + FALSE, + &TftpBufferSize, + NULL, + &File->ServerIp, + (UINT8 *)File->FileName, + NULL, + FALSE); + if (EFI_ERROR(Status)) { + AsciiPrint("TFTP error during APPLE_NSP_TFTP_READ_FILE: %r\n", Status); + FreePool(File->Buffer); + return Status; + } + + // Set the buffer valid flag. + File->IsBufferValid = TRUE; + + return Status; +} + +/** + Read BufferSize bytes from the current locaiton in the file. For load file, + FV, and TFTP case you must read the entire file. + + @param Stream Open File Handle + @param Buffer Caller allocated buffer. + @param BufferSize Size of buffer in bytes. + + + @return EFI_SUCCESS Stream is not an Open File + @return EFI_END_OF_FILE Tried to read past the end of the file + @return EFI_INVALID_PARAMETER Stream is not an open file handle + @return EFI_BUFFER_TOO_SMALL Buffer is not big enough to do the read + @return "other" Error returned from device read + +**/ +EFI_STATUS +EfiRead ( + IN EFI_OPEN_FILE *File, + OUT VOID *Buffer, + OUT UINTN *BufferSize + ) +{ + EFI_STATUS Status; + UINT32 AuthenticationStatus; + EFI_DISK_IO_PROTOCOL *DiskIo; + + if (!FileHandleValid (File)) { + return EFI_INVALID_PARAMETER; + } + + // Don't read past the end of the file. + if ((File->CurrentPosition + *BufferSize) > File->MaxPosition) { + return EFI_END_OF_FILE; + } + + switch (File->Type) { + case EfiOpenMemoryBuffer: + CopyMem (Buffer, File->Buffer + File->CurrentPosition, *BufferSize); + File->CurrentPosition += *BufferSize; + Status = EFI_SUCCESS; + break; + + case EfiOpenLoadFile: + // Figure out the File->Size + EfiTell (File, NULL); + + Status = File->LoadFile->LoadFile (File->LoadFile, File->DevicePath, FALSE, BufferSize, Buffer); + break; + + case EfiOpenFirmwareVolume: + if (File->FvSectionType == EFI_SECTION_ALL) { + Status = File->Fv->ReadFile ( + File->Fv, + &File->FvNameGuid, + &Buffer, + BufferSize, + &File->FvType, + &File->FvAttributes, + &AuthenticationStatus + ); + } else { + Status = File->Fv->ReadSection ( + File->Fv, + &File->FvNameGuid, + File->FvSectionType, + 0, + &Buffer, + BufferSize, + &AuthenticationStatus + ); + } + break; + + case EfiOpenFileSystem: + Status = File->FsFileHandle->Read (File->FsFileHandle, BufferSize, Buffer); + File->CurrentPosition += *BufferSize; + break; + + case EfiOpenBlockIo: + Status = gBS->HandleProtocol(File->EfiHandle, &gEfiDiskIoProtocolGuid, (VOID **)&DiskIo); + if (!EFI_ERROR(Status)) { + Status = DiskIo->ReadDisk(DiskIo, File->FsBlockIoMedia.MediaId, File->DiskOffset + File->CurrentPosition, *BufferSize, Buffer); + } + File->CurrentPosition += *BufferSize; + break; + + case EfiOpenTftp: + // Cache the file if it hasn't been cached yet. + if (File->IsBufferValid == FALSE) { + Status = CacheTftpFile (File); + if (EFI_ERROR (Status)) { + return Status; + } + } + + // Copy out the requested data + CopyMem (Buffer, File->Buffer + File->CurrentPosition, *BufferSize); + File->CurrentPosition += *BufferSize; + + Status = EFI_SUCCESS; + break; + + default: + return EFI_INVALID_PARAMETER; + }; + + return Status; +} + + +/** + Read the entire file into a buffer. This routine allocates the buffer and + returns it to the user full of the read data. + + This is very useful for load flie where it's hard to know how big the buffer + must be. + + @param Stream Open File Handle + @param Buffer Pointer to buffer to return. + @param BufferSize Pointer to Size of buffer return.. + + + @return EFI_SUCCESS Stream is not an Open File + @return EFI_END_OF_FILE Tried to read past the end of the file + @return EFI_INVALID_PARAMETER Stream is not an open file handle + @return EFI_BUFFER_TOO_SMALL Buffer is not big enough to do the read + @return "other" Error returned from device read + +**/ +EFI_STATUS +EfiReadAllocatePool ( + IN EFI_OPEN_FILE *File, + OUT VOID **Buffer, + OUT UINTN *BufferSize + ) +{ + if (!FileHandleValid (File)) { + return EFI_INVALID_PARAMETER; + } + + // Loadfile defers file size determination on Open so use tell to find it + EfiTell (File, NULL); + + *BufferSize = File->Size; + *Buffer = AllocatePool (*BufferSize); + if (*Buffer == NULL) { + return EFI_NOT_FOUND; + } + + return EfiRead (File, *Buffer, BufferSize); +} + + +/** + Write data back to the file. For TFTP case you must write the entire file. + + @param Stream Open File Handle + @param Buffer Pointer to buffer to return. + @param BufferSize Pointer to Size of buffer return.. + + + @return EFI_SUCCESS Stream is not an Open File + @return EFI_END_OF_FILE Tried to read past the end of the file + @return EFI_INVALID_PARAMETER Stream is not an open file handle + @return EFI_BUFFER_TOO_SMALL Buffer is not big enough to do the read + @return "other" Error returned from device write + +**/ +EFI_STATUS +EfiWrite ( + IN EFI_OPEN_FILE *File, + OUT VOID *Buffer, + OUT UINTN *BufferSize + ) +{ + EFI_STATUS Status; + EFI_FV_WRITE_FILE_DATA FileData; + EFI_DISK_IO_PROTOCOL *DiskIo; + + if (!FileHandleValid (File)) { + return EFI_INVALID_PARAMETER; + } + + switch (File->Type) { + case EfiOpenMemoryBuffer: + if ((File->CurrentPosition + *BufferSize) > File->MaxPosition) { + return EFI_END_OF_FILE; + } + + CopyMem (File->Buffer + File->CurrentPosition, Buffer, *BufferSize); + File->CurrentPosition += *BufferSize; + Status = EFI_SUCCESS; + + case EfiOpenLoadFile: + // LoadFile device is read only be definition + Status = EFI_UNSUPPORTED; + + case EfiOpenFirmwareVolume: + if (File->FvSectionType != EFI_SECTION_ALL) { + // Writes not support to a specific section. You have to update entire file + return EFI_UNSUPPORTED; + } + + FileData.NameGuid = &(File->FvNameGuid); + FileData.Type = File->FvType; + FileData.FileAttributes = File->FvAttributes; + FileData.Buffer = Buffer; + FileData.BufferSize = (UINT32)*BufferSize; + Status = File->Fv->WriteFile (File->Fv, 1, EFI_FV_UNRELIABLE_WRITE, &FileData); + break; + + case EfiOpenFileSystem: + Status = File->FsFileHandle->Write (File->FsFileHandle, BufferSize, Buffer); + File->CurrentPosition += *BufferSize; + break; + + case EfiOpenBlockIo: + if ((File->CurrentPosition + *BufferSize) > File->MaxPosition) { + return EFI_END_OF_FILE; + } + + Status = gBS->HandleProtocol (File->EfiHandle, &gEfiDiskIoProtocolGuid, (VOID **)&DiskIo); + if (!EFI_ERROR(Status)) { + Status = DiskIo->WriteDisk (DiskIo, File->FsBlockIoMedia.MediaId, File->DiskOffset + File->CurrentPosition, *BufferSize, Buffer); + } + File->CurrentPosition += *BufferSize; + break; + + case EfiOpenTftp: + // Cache the file if it hasn't been cached yet. + if (File->IsBufferValid == FALSE) { + Status = CacheTftpFile(File); + if (EFI_ERROR(Status)) { + return Status; + } + } + + // Don't overwrite the buffer + if ((File->CurrentPosition + *BufferSize) > File->MaxPosition) { + UINT8 *TempBuffer; + + TempBuffer = File->Buffer; + + File->Buffer = AllocatePool (File->CurrentPosition + *BufferSize); + if (File->Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + CopyMem (File->Buffer, TempBuffer, File->Size); + + FreePool (TempBuffer); + + File->Size = File->CurrentPosition + *BufferSize; + File->MaxPosition = File->Size; + } + + // Copy in the requested data + CopyMem (File->Buffer + File->CurrentPosition, Buffer, *BufferSize); + File->CurrentPosition += *BufferSize; + + // Mark the file dirty + File->IsDirty = TRUE; + + Status = EFI_SUCCESS; + break; + + default: + Status = EFI_INVALID_PARAMETER; + }; + + return Status; +} + diff --git a/EmbeddedPkg/Library/EfiFileLib/EfiFileLib.inf b/EmbeddedPkg/Library/EfiFileLib/EfiFileLib.inf new file mode 100644 index 0000000000..a69fb0c423 --- /dev/null +++ b/EmbeddedPkg/Library/EfiFileLib/EfiFileLib.inf @@ -0,0 +1,64 @@ +#%HEADER% +#/** @file +# Component description file for the entry point to a EFIDXE Drivers +# +# Library to abstract Framework extensions that conflict with UEFI 2.0 Specification +# Copyright (c) 2007 - 2007, Intel Corporation +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = EfiFileLib + FILE_GUID = d8c640db-73ba-48f5-a7ed-8e93c6012491 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = EfiFileLib|DXE_DRIVER UEFI_APPLICATION UEFI_DRIVER + + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources.common] + EfiFileLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + EmbeddedPkg/EmbeddedPkg.dec + +[LibraryClasses] + BaseLib + MemoryAllocationLib + DevicePathLib + PrintLib + BaseMemoryLib + UefiLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + DebugLib + EblNetworkLib + +[Protocols] + gEfiBlockIoProtocolGuid # PROTOCOL SOMETIMES_CONSUMED + gEfiDiskIoProtocolGuid # PROTOCOL SOMETIMES_CONSUMED + gEfiSimpleFileSystemProtocolGuid # PROTOCOL SOMETIMES_CONSUMED + gEfiFirmwareVolume2ProtocolGuid # PROTOCOL SOMETIMES_CONSUMED + gEfiLoadFileProtocolGuid # PROTOCOL SOMETIMES_CONSUMED + gEfiFirmwareVolumeBlockProtocolGuid # PROTOCOL SOMETIMES_CONSUMED + +[Guids] + gEfiFileInfoGuid + gEfiFileSystemInfoGuid diff --git a/EmbeddedPkg/Library/GdbSerialDebugPortLib/GdbSerialDebugPortLib.c b/EmbeddedPkg/Library/GdbSerialDebugPortLib/GdbSerialDebugPortLib.c new file mode 100644 index 0000000000..ef5a2f2a7f --- /dev/null +++ b/EmbeddedPkg/Library/GdbSerialDebugPortLib/GdbSerialDebugPortLib.c @@ -0,0 +1,187 @@ +/** @file + Basic serial IO abstaction for GDB + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include +#include + +#include + + +EFI_DEBUGPORT_PROTOCOL *gDebugPort = NULL; +UINTN gTimeOut = 0; + +/** + The constructor function initializes the UART. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS. + +**/ +RETURN_STATUS +EFIAPI +GdbSerialLibDebugPortConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol (&gEfiDebugPortProtocolGuid, NULL, (VOID **)&gDebugPort); + if (!EFI_ERROR (Status)) { + gTimeOut = PcdGet32 (PcdGdbMaxPacketRetryCount); + gDebugPort->Reset (gDebugPort); + } + + return Status; +} + + + +/** + Sets the baud rate, receive FIFO depth, transmit/receice time out, parity, + data buts, and stop bits on a serial device. This call is optional as the serial + port will be set up with defaults base on PCD values. + + @param BaudRate The requested baud rate. A BaudRate value of 0 will use the the + device's default interface speed. + @param Parity The type of parity to use on this serial device. A Parity value of + DefaultParity will use the device's default parity value. + @param DataBits The number of data bits to use on the serial device. A DataBits + vaule of 0 will use the device's default data bit setting. + @param StopBits The number of stop bits to use on this serial device. A StopBits + value of DefaultStopBits will use the device's default number of + stop bits. + + @retval EFI_SUCCESS The device was configured. + @retval EFI_DEVICE_ERROR The serial device could not be coonfigured. + +**/ +RETURN_STATUS +EFIAPI +GdbSerialInit ( + IN UINT64 BaudRate, + IN UINT8 Parity, + IN UINT8 DataBits, + IN UINT8 StopBits + ) +{ + EFI_STATUS Status; + + Status = gDebugPort->Reset (gDebugPort); + return Status; +} + + +/** + Check to see if a character is available from GDB. Do not read the character as that is + done via GdbGetChar(). + + @return TRUE - Character availible + @return FALSE - Character not availible + +**/ +BOOLEAN +EFIAPI +GdbIsCharAvailable ( + VOID + ) +{ + EFI_STATUS Status; + + Status = gDebugPort->Poll (gDebugPort); + + return (Status == EFI_SUCCESS ? TRUE : FALSE); +} + + +/** + Get a character from GDB. This function must be able to run in interrupt context. + + @return A character from GDB + +**/ +CHAR8 +EFIAPI +GdbGetChar ( + VOID + ) +{ + EFI_STATUS Status; + CHAR8 Char; + UINTN BufferSize; + + do { + BufferSize = sizeof (Char); + Status = gDebugPort->Read (gDebugPort, gTimeOut, &BufferSize, &Char); + } while (EFI_ERROR (Status) || BufferSize != sizeof (Char)); + + return Char; +} + + +/** + Send a character to GDB. This function must be able to run in interrupt context. + + + @param Char Send a character to GDB + +**/ + +VOID +EFIAPI +GdbPutChar ( + IN CHAR8 Char + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + + do { + BufferSize = sizeof (Char); + Status = gDebugPort->Write (gDebugPort, gTimeOut, &BufferSize, &Char); + } while (EFI_ERROR (Status) || BufferSize != sizeof (Char)); + + return; +} + +/** + Send an ASCII string to GDB. This function must be able to run in interrupt context. + + + @param String Send a string to GDB + +**/ + +VOID +GdbPutString ( + IN CHAR8 *String + ) +{ + // We could performance enhance this function by calling gDebugPort->Write () + while (*String != '\0') { + GdbPutChar (*String); + String++; + } +} + + + + diff --git a/EmbeddedPkg/Library/GdbSerialDebugPortLib/GdbSerialDebugPortLib.inf b/EmbeddedPkg/Library/GdbSerialDebugPortLib/GdbSerialDebugPortLib.inf new file mode 100644 index 0000000000..42a7caaa91 --- /dev/null +++ b/EmbeddedPkg/Library/GdbSerialDebugPortLib/GdbSerialDebugPortLib.inf @@ -0,0 +1,50 @@ +#%HEADER% +#/** @file +# Component description file for Base PCI Cf8 Library. +# +# PCI CF8 Library that uses I/O ports 0xCF8 and 0xCFC to perform PCI Configuration cycles. +# Layers on top of an I/O Library instance. +# Copyright (c) 2007, Intel Corporation. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = GdbSerialDebugPortLib + FILE_GUID = 42ABB10A-660A-4BEC-AEFA-CC94AB4D993D + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = GdbSerialLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER + + CONSTRUCTOR = GdbSerialLibDebugPortConstructor + + +[Sources.common] + GdbSerialDebugPortLib.c + + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + +[LibraryClasses] + DebugLib + IoLib + +[Protocols.common] + gEfiDebugPortProtocolGuid + +[FixedPcd.common] + gEmbeddedTokenSpaceGuid.PcdGdbBaudRate|115200 + gEmbeddedTokenSpaceGuid.PcdGdbDataBits|8 + gEmbeddedTokenSpaceGuid.PcdGdbParity|1 + gEmbeddedTokenSpaceGuid.PcdGdbStopBits|1 + gEmbeddedTokenSpaceGuid.PcdGdbMaxPacketRetryCount diff --git a/EmbeddedPkg/Library/GdbSerialLib/GdbSerialLib.c b/EmbeddedPkg/Library/GdbSerialLib/GdbSerialLib.c new file mode 100644 index 0000000000..62d8636456 --- /dev/null +++ b/EmbeddedPkg/Library/GdbSerialLib/GdbSerialLib.c @@ -0,0 +1,262 @@ +/** @file + Basic serial IO abstaction for GDB + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include + + +//--------------------------------------------- +// UART Register Offsets +//--------------------------------------------- +#define BAUD_LOW_OFFSET 0x00 +#define BAUD_HIGH_OFFSET 0x01 +#define IER_OFFSET 0x01 +#define LCR_SHADOW_OFFSET 0x01 +#define FCR_SHADOW_OFFSET 0x02 +#define IR_CONTROL_OFFSET 0x02 +#define FCR_OFFSET 0x02 +#define EIR_OFFSET 0x02 +#define BSR_OFFSET 0x03 +#define LCR_OFFSET 0x03 +#define MCR_OFFSET 0x04 +#define LSR_OFFSET 0x05 +#define MSR_OFFSET 0x06 + +//--------------------------------------------- +// UART Register Bit Defines +//--------------------------------------------- +#define LSR_TXRDY 0x20 +#define LSR_RXDA 0x01 +#define DLAB 0x01 +#define ENABLE_FIFO 0x01 +#define CLEAR_FIFOS 0x06 + + + +// IO Port Base for the UART +UINTN gPort; + + +/** + The constructor function initializes the UART. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS. + +**/ +RETURN_STATUS +EFIAPI +GdbSerialLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + UINT64 BaudRate; + UINT8 DataBits; + UINT8 Parity; + UINT8 StopBits; + + gPort = (UINTN)PcdGet32 (PcdGdbUartPort); + + BaudRate = PcdGet64 (PcdGdbBaudRate); + Parity = PcdGet8 (PcdGdbParity); + DataBits = PcdGet8 (PcdGdbDataBits); + StopBits = PcdGet8 (PcdGdbStopBits); + + return GdbSerialInit (BaudRate, Parity, DataBits, StopBits); +} + + + +/** + Sets the baud rate, receive FIFO depth, transmit/receice time out, parity, + data buts, and stop bits on a serial device. This call is optional as the serial + port will be set up with defaults base on PCD values. + + @param BaudRate The requested baud rate. A BaudRate value of 0 will use the the + device's default interface speed. + @param Parity The type of parity to use on this serial device. A Parity value of + DefaultParity will use the device's default parity value. + @param DataBits The number of data bits to use on the serial device. A DataBits + vaule of 0 will use the device's default data bit setting. + @param StopBits The number of stop bits to use on this serial device. A StopBits + value of DefaultStopBits will use the device's default number of + stop bits. + + @retval EFI_SUCCESS The device was configured. + @retval EFI_DEVICE_ERROR The serial device could not be coonfigured. + +**/ +RETURN_STATUS +EFIAPI +GdbSerialInit ( + IN UINT64 BaudRate, + IN UINT8 Parity, + IN UINT8 DataBits, + IN UINT8 StopBits + ) +{ + UINTN Divisor; + UINT8 OutputData; + UINT8 Data; + UINT8 BreakSet = 0; + + // + // We assume the UART has been turned on to decode gPort address range + // + + // + // Map 5..8 to 0..3 + // + Data = (UINT8) (DataBits - (UINT8)5); + + // + // Calculate divisor for baud generator + // + Divisor = 115200/(UINTN)BaudRate; + + // + // Set communications format + // + OutputData = (UINT8)((DLAB << 7) | ((BreakSet << 6) | ((Parity << 3) | ((StopBits << 2) | Data)))); + IoWrite8 (gPort + LCR_OFFSET, OutputData); + + // + // Configure baud rate + // + IoWrite8 (gPort + BAUD_HIGH_OFFSET, (UINT8)(Divisor >> 8)); + IoWrite8 (gPort + BAUD_LOW_OFFSET, (UINT8)(Divisor & 0xff)); + + + // + // Switch back to bank 0 + // + OutputData = (UINT8)((~DLAB<<7)|((BreakSet<<6)|((Parity<<3)|((StopBits<<2)| Data)))); + IoWrite8 (gPort + LCR_OFFSET, OutputData); + + // Not sure this is the right place to enable the FIFOs.... + // We probably need the FIFO enabled to not drop input + IoWrite8 (gPort + FCR_SHADOW_OFFSET, ENABLE_FIFO); + + + // Configure the UART hardware here + return RETURN_SUCCESS; +} + + +/** + Check to see if a character is available from GDB. Do not read the character as that is + done via GdbGetChar(). + + @return TRUE - Character availible + @return FALSE - Character not availible + +**/ +BOOLEAN +EFIAPI +GdbIsCharAvailable ( + VOID + ) +{ + UINT8 Data; + + Data = IoRead8 (gPort + LSR_OFFSET); + + return ((Data & LSR_RXDA) == LSR_RXDA); +} + + +/** + Get a character from GDB. This function must be able to run in interrupt context. + + @return A character from GDB + +**/ +CHAR8 +EFIAPI +GdbGetChar ( + VOID + ) +{ + UINT8 Data; + CHAR8 Char; + + // Wait for the serial port to be ready + do { + Data = IoRead8 (gPort + LSR_OFFSET); + } while ((Data & LSR_RXDA) == 0); + + Char = IoRead8 (gPort); + + // Make this an EFI_D_INFO after we get everything debugged. + DEBUG ((EFI_D_ERROR, "<%c<", Char)); + return Char; +} + + +/** + Send a character to GDB. This function must be able to run in interrupt context. + + + @param Char Send a character to GDB + +**/ + +VOID +EFIAPI +GdbPutChar ( + IN CHAR8 Char + ) +{ + UINT8 Data; + + // Make this an EFI_D_INFO after we get everything debugged. + DEBUG ((EFI_D_ERROR, ">%c>", Char)); + + // Wait for the serial port to be ready + do { + Data = IoRead8 (gPort + LSR_OFFSET); + } while ((Data & LSR_TXRDY) == 0); + + IoWrite8 (gPort, Char); +} + +/** + Send an ASCII string to GDB. This function must be able to run in interrupt context. + + + @param String Send a string to GDB + +**/ + +VOID +GdbPutString ( + IN CHAR8 *String + ) +{ + while (*String != '\0') { + GdbPutChar (*String); + String++; + } +} + + + + diff --git a/EmbeddedPkg/Library/GdbSerialLib/GdbSerialLib.inf b/EmbeddedPkg/Library/GdbSerialLib/GdbSerialLib.inf new file mode 100644 index 0000000000..0c8d0e6a69 --- /dev/null +++ b/EmbeddedPkg/Library/GdbSerialLib/GdbSerialLib.inf @@ -0,0 +1,47 @@ +#%HEADER% +#/** @file +# Component description file for Base PCI Cf8 Library. +# +# PCI CF8 Library that uses I/O ports 0xCF8 and 0xCFC to perform PCI Configuration cycles. +# Layers on top of an I/O Library instance. +# Copyright (c) 2007, Intel Corporation. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = GdbSerialLib + FILE_GUID = 9999B4EE-081F-4501-AEDC-137A534BAF69 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = GdbSerialLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER + + CONSTRUCTOR = GdbSerialLibConstructor + + +[Sources.common] + GdbSerialLib.c + + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + +[LibraryClasses] + DebugLib + IoLib + +[FixedPcd.common] + gEmbeddedTokenSpaceGuid.PcdGdbBaudRate|115200 + gEmbeddedTokenSpaceGuid.PcdGdbDataBits|8 + gEmbeddedTokenSpaceGuid.PcdGdbParity|1 + gEmbeddedTokenSpaceGuid.PcdGdbStopBits|1 + gEmbeddedTokenSpaceGuid.PcdGdbUartPort diff --git a/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Capsule.c b/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Capsule.c new file mode 100644 index 0000000000..cbc48b2b0c --- /dev/null +++ b/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Capsule.c @@ -0,0 +1,288 @@ +/** @file + Generic Capsule services + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + + +// +//Max size capsule services support are platform policy,to populate capsules we just need +//memory to maintain them across reset,it is not a problem. And to special capsules ,for +//example,update flash,it is mostly decided by the platform. Here is a sample size for +//different type capsules. +// +#define MAX_SIZE_POPULATE (0) +#define MAX_SIZE_NON_POPULATE (0) +#define MAX_SUPPORT_CAPSULE_NUM 0x10 + + +BOOLEAN +EFIAPI +SupportUpdateCapsuleRest ( + VOID + ) +{ + // + //If the platform has a way to guarantee the memory integrity across a system reset, return + //TRUE, else FALSE. + // + return FALSE; +} + + + +VOID +EFIAPI +SupportCapsuleSize ( + IN OUT UINT32 *MaxSizePopulate, + IN OUT UINT32 *MaxSizeNonPopulate + ) +{ + // + //Here is a sample size, different platforms have different sizes. + // + *MaxSizePopulate = MAX_SIZE_POPULATE; + *MaxSizeNonPopulate = MAX_SIZE_NON_POPULATE; + return; +} + + + + +EFI_STATUS +LibUpdateCapsule ( + IN UEFI_CAPSULE_HEADER **CapsuleHeaderArray, + IN UINTN CapsuleCount, + IN EFI_PHYSICAL_ADDRESS ScatterGatherList OPTIONAL + ) +/*++ + +Routine Description: + + This code finds if the capsule needs reset to update, if no, update immediately. + +Arguments: + + CapsuleHeaderArray A array of pointers to capsule headers passed in + CapsuleCount The number of capsule + ScatterGatherList Physical address of datablock list points to capsule + +Returns: + + EFI STATUS + EFI_SUCCESS Valid capsule was passed.If CAPSULE_FLAG_PERSIT_ACROSS_RESET is + not set, the capsule has been successfully processed by the firmware. + If it set, the ScattlerGatherList is successfully to be set. + EFI_INVALID_PARAMETER CapsuleCount is less than 1,CapsuleGuid is not supported. + EFI_DEVICE_ERROR Failed to SetVariable or AllocatePool or ProcessFirmwareVolume. + +--*/ +{ + UINTN CapsuleSize; + UINTN ArrayNumber; + VOID *BufferPtr; + EFI_STATUS Status; + EFI_HANDLE FvHandle; + UEFI_CAPSULE_HEADER *CapsuleHeader; + + if ((CapsuleCount < 1) || (CapsuleCount > MAX_SUPPORT_CAPSULE_NUM)){ + return EFI_INVALID_PARAMETER; + } + + BufferPtr = NULL; + CapsuleHeader = NULL; + + // + //Compare GUIDs with EFI_CAPSULE_GUID, if capsule header contains CAPSULE_FLAGS_PERSIST_ACROSS_RESET + //and CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flags,whatever the GUID is ,the service supports. + // + for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) { + CapsuleHeader = CapsuleHeaderArray[ArrayNumber]; + if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)) == CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) { + return EFI_INVALID_PARAMETER; + } + if (!CompareGuid (&CapsuleHeader->CapsuleGuid, &gEfiCapsuleGuid)) { + if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0) { + return EFI_UNSUPPORTED; + } + } + } + + // + //Assume that capsules have the same flags on reseting or not. + // + CapsuleHeader = CapsuleHeaderArray[0]; + + if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) { + // + //Check if the platform supports update capsule across a system reset + // + if (!SupportUpdateCapsuleRest()) { + return EFI_UNSUPPORTED; + } + + if (ScatterGatherList == 0) { + return EFI_INVALID_PARAMETER; + } else { + Status = EfiSetVariable ( + EFI_CAPSULE_VARIABLE_NAME, + &gEfiCapsuleVendorGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof (UINTN), + (VOID *) &ScatterGatherList + ); + if (Status != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + } + return EFI_SUCCESS; + } + + // + //The rest occurs in the condition of non-reset mode + // + if (EfiAtRuntime ()) { + return EFI_INVALID_PARAMETER; + } + + // + //Here should be in the boot-time + // + for (ArrayNumber = 0; ArrayNumber < CapsuleCount ; ArrayNumber++) { + CapsuleHeader = CapsuleHeaderArray[ArrayNumber]; + CapsuleSize = CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize; + Status = gBS->AllocatePool (EfiBootServicesData, CapsuleSize, &BufferPtr); + if (Status != EFI_SUCCESS) { + goto Done; + } + gBS->CopyMem (BufferPtr, (UINT8*)CapsuleHeader+ CapsuleHeader->HeaderSize, CapsuleSize); + + // + //Call DXE service ProcessFirmwareVolume to process immediatelly + // + Status = gDS->ProcessFirmwareVolume (BufferPtr, CapsuleSize, &FvHandle); + if (Status != EFI_SUCCESS) { + gBS->FreePool (BufferPtr); + return EFI_DEVICE_ERROR; + } + gDS->Dispatch (); + gBS->FreePool (BufferPtr); + } + return EFI_SUCCESS; + +Done: + if (BufferPtr != NULL) { + gBS->FreePool (BufferPtr); + } + return EFI_DEVICE_ERROR; +} + + +EFI_STATUS +QueryCapsuleCapabilities ( + IN UEFI_CAPSULE_HEADER **CapsuleHeaderArray, + IN UINTN CapsuleCount, + OUT UINT64 *MaxiumCapsuleSize, + OUT EFI_RESET_TYPE *ResetType + ) +/*++ + +Routine Description: + + This code is query about capsule capability. + +Arguments: + + CapsuleHeaderArray A array of pointers to capsule headers passed in + CapsuleCount The number of capsule + MaxiumCapsuleSize Max capsule size is supported + ResetType Reset type the capsule indicates, if reset is not needed,return EfiResetCold. + If reset is needed, return EfiResetWarm. + +Returns: + + EFI STATUS + EFI_SUCCESS Valid answer returned + EFI_INVALID_PARAMETER MaxiumCapsuleSize is NULL,ResetType is NULL.CapsuleCount is less than 1,CapsuleGuid is not supported. + EFI_UNSUPPORTED The capsule type is not supported. + +--*/ +{ + UINTN ArrayNumber; + UEFI_CAPSULE_HEADER *CapsuleHeader; + UINT32 MaxSizePopulate; + UINT32 MaxSizeNonPopulate; + + + if ((CapsuleCount < 1) || (CapsuleCount > MAX_SUPPORT_CAPSULE_NUM)){ + return EFI_INVALID_PARAMETER; + } + + if ((MaxiumCapsuleSize == NULL) ||(ResetType == NULL)) { + return EFI_INVALID_PARAMETER; + } + + CapsuleHeader = NULL; + + // + //Compare GUIDs with EFI_CAPSULE_GUID, if capsule header contains CAPSULE_FLAGS_PERSIST_ACROSS_RESET + //and CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flags,whatever the GUID is ,the service supports. + // + for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) { + CapsuleHeader = CapsuleHeaderArray[ArrayNumber]; + if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)) == CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) { + return EFI_INVALID_PARAMETER; + } + if (!CompareGuid (&CapsuleHeader->CapsuleGuid, &gEfiCapsuleGuid)) { + if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0) { + return EFI_UNSUPPORTED; + } + } + } + + SupportCapsuleSize(&MaxSizePopulate,&MaxSizeNonPopulate); + // + //Assume that capsules have the same flags on reseting or not. + // + CapsuleHeader = CapsuleHeaderArray[0]; + if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) { + // + //Check if the platform supports update capsule across a system reset + // + if (!SupportUpdateCapsuleRest()) { + return EFI_UNSUPPORTED; + } + *ResetType = EfiResetWarm; + *MaxiumCapsuleSize = MaxSizePopulate; + } else { + *ResetType = EfiResetCold; + *MaxiumCapsuleSize = MaxSizeNonPopulate; + } + return EFI_SUCCESS; +} + + +VOID +LibCapsuleVirtualAddressChangeEvent ( + VOID + ) +{ +} + +VOID +LibCapsuleInitialize ( + VOID + ) +{ +} diff --git a/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Mtc.c b/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Mtc.c new file mode 100644 index 0000000000..8e8f2dbf24 --- /dev/null +++ b/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Mtc.c @@ -0,0 +1,226 @@ +/** @file + Generic Monotonic Counter services + + Copyright (c) 2007, Intel Corporation
+ Portions copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + + +// +// The current Monotonic count value +// +UINT64 mEfiMtc = 0; + + +// +// Event to use to update the Mtc's high part when wrapping +// +EFI_EVENT mEfiMtcEvent; + +// +// EfiMtcName - Variable name of the MTC value +// +CHAR16 *mEfiMtcName = L"MTC"; + +// +// EfiMtcGuid - Guid of the MTC value +// +EFI_GUID mEfiMtcGuid = { 0xeb704011, 0x1402, 0x11d3, { 0x8e, 0x77, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } }; + + + +// +// Worker functions +// + + +VOID +EFIAPI +EfiMtcEventHandler ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + + Monotonic count event handler. This handler updates the high monotonic count. + +Arguments: + + Event The event to handle + Context The event context + +Returns: + + EFI_SUCCESS The event has been handled properly + EFI_NOT_FOUND An error occurred updating the variable. + +--*/ +{ + UINT32 HighCount; + + EfiGetNextHighMonotonicCount (&HighCount); + return; +} + + + +VOID +LibMtcVirtualAddressChangeEvent (VOID) +{ +} + + +EFI_STATUS +EFIAPI +LibMtcGetNextHighMonotonicCount ( + OUT UINT32 *HighCount + ) +{ + EFI_STATUS Status; + EFI_TPL OldTpl; + + // + // Check input parameters + // + if (HighCount == NULL) { + return EFI_INVALID_PARAMETER; + } + + + if (!EfiAtRuntime ()) { + // Use a lock if called before ExitBootServices() + OldTpl = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL); + } + + *HighCount = (UINT32) RShiftU64 (mEfiMtc, 32) + 1; + mEfiMtc = LShiftU64 (*HighCount, 32); + + if (!EfiAtRuntime ()) { + gBS->RestoreTPL (OldTpl); + } + + // + // Update the NvRam store to match the new high part + // + Status = EfiSetVariable ( + mEfiMtcName, + &mEfiMtcGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof (UINT32), + HighCount + ); + + return Status; +} + + +EFI_STATUS +LibMtcGetNextMonotonicCount ( + OUT UINT64 *Count + ) +{ + EFI_STATUS Status; + EFI_TPL OldTpl; + UINT32 HighCount; + UINTN BufferSize; + + // + // Can not be called after ExitBootServices() + // + if (EfiAtRuntime ()) { + return EFI_UNSUPPORTED; + } + + // + // Check input parameters + // + if (Count == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (mEfiMtc == 0) { + // + // If the MTC has not been initialized read the variable + // + + // + // Read the last high part + // + BufferSize = sizeof (UINT32); + Status = EfiGetVariable ( + mEfiMtcName, + &mEfiMtcGuid, + NULL, + &BufferSize, + &HighCount + ); + if (EFI_ERROR (Status)) { + HighCount = 0; + } + + // + // Set the current value + // + mEfiMtc = LShiftU64 (HighCount, 32); + // + // Increment the upper 32 bits for this boot + // Continue even if it fails. It will only fail if the variable services are + // not functional. + // + Status = EfiGetNextHighMonotonicCount (&HighCount); + } + + + // + // Update the monotonic counter with a lock + // + OldTpl = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL); + *Count = mEfiMtc; + mEfiMtc++; + gBS->RestoreTPL (OldTpl); + + // + // If the MSB bit of the low part toggled, then signal that the high + // part needs updated now + // + if ((((UINT32) mEfiMtc) ^ ((UINT32) *Count)) & 0x80000000) { + gBS->SignalEvent (mEfiMtcEvent); + } + + return EFI_SUCCESS; +} + + + +VOID +LibMtcInitialize ( + VOID + ) +{ + EFI_STATUS Status; + + // + // Initialize event to handle overflows + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + EFI_TPL_CALLBACK, + EfiMtcEventHandler, + NULL, + &mEfiMtcEvent + ); + ASSERT_EFI_ERROR (Status); +} + diff --git a/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/ReportStatusCode.c b/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/ReportStatusCode.c new file mode 100644 index 0000000000..f1953a89d8 --- /dev/null +++ b/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/ReportStatusCode.c @@ -0,0 +1,198 @@ +/** @file + Report status code lib on top of either SerialLib and/or EFI Serial Protocol. + Based on PcdStatusCodeUseEfiSerial & PcdStatusCodeUseHardSerial settings + + There is just a single runtime memory buffer that contans all the data. + + Copyright (c) 2007, Intel Corporation
+ Portions copyright (c) 2008-2009, Apple Inc. All rights reserved. + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +//////////#include "DxeStatusCode.h" + + +EFI_SERIAL_IO_PROTOCOL *mSerialIoProtocol = NULL; + + +EFI_STATUS +LibReportStatusCode ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID *CallerId, + IN EFI_STATUS_CODE_DATA *Data OPTIONAL + ) +{ + CHAR8 *Filename; + CHAR8 *Description; + CHAR8 *Format; + CHAR8 Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE]; + UINT32 ErrorLevel; + UINT32 LineNumber; + UINTN CharCount; + VA_LIST Marker; + EFI_DEBUG_INFO *DebugInfo; + EFI_TPL CurrentTpl; + + + if (FeaturePcdGet (PcdStatusCodeUseEfiSerial)) { + if (EfiAtRuntime ()) { + return EFI_DEVICE_ERROR; + } + CurrentTpl = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL); + gBS->RestoreTPL (CurrentTpl); + + if (CurrentTpl > EFI_TPL_CALLBACK ) { + return EFI_DEVICE_ERROR; + } + } + + Buffer[0] = '\0'; + + if (Data != NULL && + ReportStatusCodeExtractAssertInfo (CodeType, Value, Data, &Filename, &Description, &LineNumber)) { + // + // Print ASSERT() information into output buffer. + // + CharCount = AsciiSPrint ( + Buffer, + EFI_STATUS_CODE_DATA_MAX_SIZE, + "\n\rDXE_ASSERT!: %a (%d): %a\n\r", + Filename, + LineNumber, + Description + ); + } else if (Data != NULL && + ReportStatusCodeExtractDebugInfo (Data, &ErrorLevel, &Marker, &Format)) { + // + // Print DEBUG() information into output buffer. + // + CharCount = AsciiVSPrint ( + Buffer, + EFI_STATUS_CODE_DATA_MAX_SIZE, + Format, + Marker + ); + } else if (Data != NULL && + CompareGuid (&Data->Type, &gEfiStatusCodeSpecificDataGuid) && + (CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE) { + // + // Print specific data into output buffer. + // + DebugInfo = (EFI_DEBUG_INFO *) (Data + 1); + Marker = (VA_LIST) (DebugInfo + 1); + Format = (CHAR8 *) (((UINT64 *) (DebugInfo + 1)) + 12); + + CharCount = AsciiVSPrint (Buffer, EFI_STATUS_CODE_DATA_MAX_SIZE, Format, Marker); + } else if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) { + // + // Print ERROR information into output buffer. + // + CharCount = AsciiSPrint ( + Buffer, + EFI_STATUS_CODE_DATA_MAX_SIZE, + "ERROR: C%x:V%x I%x", + CodeType, + Value, + Instance + ); + + // + // Make sure we don't try to print values that weren't + // intended to be printed, especially NULL GUID pointers. + // + + if (CallerId != NULL) { + CharCount += AsciiSPrint ( + &Buffer[CharCount - 1], + (EFI_STATUS_CODE_DATA_MAX_SIZE - (sizeof (Buffer[0]) * CharCount)), + " %g", + CallerId + ); + } + + if (Data != NULL) { + CharCount += AsciiSPrint ( + &Buffer[CharCount - 1], + (EFI_STATUS_CODE_DATA_MAX_SIZE - (sizeof (Buffer[0]) * CharCount)), + " %x", + Data + ); + } + + CharCount += AsciiSPrint ( + &Buffer[CharCount - 1], + (EFI_STATUS_CODE_DATA_MAX_SIZE - (sizeof (Buffer[0]) * CharCount)), + "\n\r" + ); + } else if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) { + CharCount = AsciiSPrint ( + Buffer, + EFI_STATUS_CODE_DATA_MAX_SIZE, + "PROGRESS CODE: V%x I%x\n\r", + Value, + Instance + ); + } else { + CharCount = AsciiSPrint ( + Buffer, + EFI_STATUS_CODE_DATA_MAX_SIZE, + "Undefined: C%x:V%x I%x\n\r", + CodeType, + Value, + Instance + ); + } + + + if (FeaturePcdGet (PcdStatusCodeUseHardSerial)) { + // + // Callout to SerialPort Lib function to do print. + // + SerialPortWrite ((UINT8 *) Buffer, CharCount); + } + if (FeaturePcdGet (PcdStatusCodeUseEfiSerial)) { + if (mSerialIoProtocol == NULL) { + gBS->LocateProtocol (&gEfiSerialIoProtocolGuid, NULL, (VOID **) &mSerialIoProtocol); + } + + if (mSerialIoProtocol == NULL) { + mSerialIoProtocol->Write ( + mSerialIoProtocol, + &CharCount, + Buffer + ); + } + } + + return EFI_SUCCESS; +} + + +VOID +LibReportStatusCodeVirtualAddressChangeEvent ( + VOID + ) +{ + return; +} + +VOID +LibReportStatusCodeInitialize ( + VOID + ) +{ + return; +} + + + diff --git a/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Reset.c b/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Reset.c new file mode 100644 index 0000000000..8671971a22 --- /dev/null +++ b/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Reset.c @@ -0,0 +1,63 @@ +/** @file + Simple PC Port 0x92 reset driver + + Copyright (c) 2007, Intel Corporation
+ Portions copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + + + +VOID +LibResetInitializeReset ( + VOID + ) +{ +} + +VOID +LibResetVirtualAddressChangeEvent ( + VOID + ) +{ +} + + +VOID +LibResetSystem ( + IN EFI_RESET_TYPE ResetType, + IN EFI_STATUS ResetStatus, + IN UINTN DataSize, + IN CHAR16 *ResetData OPTIONAL + ) +{ + UINT8 Data; + + switch (ResetType) { + case EfiResetWarm: + case EfiResetCold: + case EfiResetShutdown: + Data = IoRead8 (0x92); + Data |= 1; + IoWrite8 (0x92, Data); + break; + + default: + return ; + } + + // + // Given we should have reset getting here would be bad + // + ASSERT (FALSE); +} + diff --git a/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Rtc.c b/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Rtc.c new file mode 100644 index 0000000000..bb87ba82be --- /dev/null +++ b/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Rtc.c @@ -0,0 +1,861 @@ +/** @file + Simple PC RTC + + Copyright (c) 2007, Intel Corporation
+ Portions copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + + + +typedef struct { + EFI_LOCK RtcLock; + UINT16 SavedTimeZone; + UINT8 Daylight; +} PC_RTC_GLOBALS; + +#define PCAT_RTC_ADDRESS_REGISTER 0x70 +#define PCAT_RTC_DATA_REGISTER 0x71 + +// +// Dallas DS12C887 Real Time Clock +// +#define RTC_ADDRESS_SECONDS 0 // R/W Range 0..59 +#define RTC_ADDRESS_SECONDS_ALARM 1 // R/W Range 0..59 +#define RTC_ADDRESS_MINUTES 2 // R/W Range 0..59 +#define RTC_ADDRESS_MINUTES_ALARM 3 // R/W Range 0..59 +#define RTC_ADDRESS_HOURS 4 // R/W Range 1..12 or 0..23 Bit 7 is AM/PM +#define RTC_ADDRESS_HOURS_ALARM 5 // R/W Range 1..12 or 0..23 Bit 7 is AM/PM +#define RTC_ADDRESS_DAY_OF_THE_WEEK 6 // R/W Range 1..7 +#define RTC_ADDRESS_DAY_OF_THE_MONTH 7 // R/W Range 1..31 +#define RTC_ADDRESS_MONTH 8 // R/W Range 1..12 +#define RTC_ADDRESS_YEAR 9 // R/W Range 0..99 +#define RTC_ADDRESS_REGISTER_A 10 // R/W[0..6] R0[7] +#define RTC_ADDRESS_REGISTER_B 11 // R/W +#define RTC_ADDRESS_REGISTER_C 12 // RO +#define RTC_ADDRESS_REGISTER_D 13 // RO +#define RTC_ADDRESS_CENTURY 50 // R/W Range 19..20 Bit 8 is R/W +// +// Date and time initial values. +// They are used if the RTC values are invalid during driver initialization +// +#define RTC_INIT_SECOND 0 +#define RTC_INIT_MINUTE 0 +#define RTC_INIT_HOUR 0 +#define RTC_INIT_DAY 1 +#define RTC_INIT_MONTH 1 +#define RTC_INIT_YEAR 2001 + +// +// Register initial values +// +#define RTC_INIT_REGISTER_A 0x26 +#define RTC_INIT_REGISTER_B 0x02 +#define RTC_INIT_REGISTER_D 0x0 + +#pragma pack(1) +// +// Register A +// +typedef struct { + UINT8 RS : 4; // Rate Selection Bits + UINT8 DV : 3; // Divisor + UINT8 UIP : 1; // Update in progress +} RTC_REGISTER_A_BITS; + +typedef union { + RTC_REGISTER_A_BITS Bits; + UINT8 Data; +} RTC_REGISTER_A; + +// +// Register B +// +typedef struct { + UINT8 DSE : 1; // 0 - Daylight saving disabled 1 - Daylight savings enabled + UINT8 MIL : 1; // 0 - 12 hour mode 1 - 24 hour mode + UINT8 DM : 1; // 0 - BCD Format 1 - Binary Format + UINT8 SQWE : 1; // 0 - Disable SQWE output 1 - Enable SQWE output + UINT8 UIE : 1; // 0 - Update INT disabled 1 - Update INT enabled + UINT8 AIE : 1; // 0 - Alarm INT disabled 1 - Alarm INT Enabled + UINT8 PIE : 1; // 0 - Periodic INT disabled 1 - Periodic INT Enabled + UINT8 SET : 1; // 0 - Normal operation. 1 - Updates inhibited +} RTC_REGISTER_B_BITS; + +typedef union { + RTC_REGISTER_B_BITS Bits; + UINT8 Data; +} RTC_REGISTER_B; + +// +// Register C +// +typedef struct { + UINT8 Reserved : 4; // Read as zero. Can not be written. + UINT8 UF : 1; // Update End Interrupt Flag + UINT8 AF : 1; // Alarm Interrupt Flag + UINT8 PF : 1; // Periodic Interrupt Flag + UINT8 IRQF : 1; // Iterrupt Request Flag = PF & PIE | AF & AIE | UF & UIE +} RTC_REGISTER_C_BITS; + +typedef union { + RTC_REGISTER_C_BITS Bits; + UINT8 Data; +} RTC_REGISTER_C; + +// +// Register D +// +typedef struct { + UINT8 Reserved : 7; // Read as zero. Can not be written. + UINT8 VRT : 1; // Valid RAM and Time +} RTC_REGISTER_D_BITS; + +typedef union { + RTC_REGISTER_D_BITS Bits; + UINT8 Data; +} RTC_REGISTER_D; + +#pragma pack() + +PC_RTC_GLOBALS mRtc; + +BOOLEAN +IsLeapYear ( + IN EFI_TIME *Time + ) +{ + if (Time->Year % 4 == 0) { + if (Time->Year % 100 == 0) { + if (Time->Year % 400 == 0) { + return TRUE; + } else { + return FALSE; + } + } else { + return TRUE; + } + } else { + return FALSE; + } +} + + +const INTN mDayOfMonth[12] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + +BOOLEAN +DayValid ( + IN EFI_TIME *Time + ) +{ + if (Time->Day < 1 || + Time->Day > mDayOfMonth[Time->Month - 1] || + (Time->Month == 2 && (!IsLeapYear (Time) && Time->Day > 28)) + ) { + return FALSE; + } + + return TRUE; +} + + +UINT8 +DecimaltoBcd ( + IN UINT8 DecValue + ) +{ + UINTN High; + UINTN Low; + + High = DecValue / 10; + Low = DecValue - (High * 10); + + return (UINT8) (Low + (High << 4)); +} + +UINT8 +BcdToDecimal ( + IN UINT8 BcdValue + ) +{ + UINTN High; + UINTN Low; + + High = BcdValue >> 4; + Low = BcdValue - (High << 4); + + return (UINT8) (Low + (High * 10)); +} + + + + +VOID +ConvertEfiTimeToRtcTime ( + IN EFI_TIME *Time, + IN RTC_REGISTER_B RegisterB, + IN UINT8 *Century + ) +{ + BOOLEAN PM; + + PM = TRUE; + // + // Adjust hour field if RTC in in 12 hour mode + // + if (RegisterB.Bits.MIL == 0) { + if (Time->Hour < 12) { + PM = FALSE; + } + + if (Time->Hour >= 13) { + Time->Hour = (UINT8) (Time->Hour - 12); + } else if (Time->Hour == 0) { + Time->Hour = 12; + } + } + // + // Set the Time/Date/Daylight Savings values. + // + *Century = DecimaltoBcd ((UINT8) (Time->Year / 100)); + + Time->Year = (UINT16) (Time->Year % 100); + + if (RegisterB.Bits.DM == 0) { + Time->Year = DecimaltoBcd ((UINT8) Time->Year); + Time->Month = DecimaltoBcd (Time->Month); + Time->Day = DecimaltoBcd (Time->Day); + Time->Hour = DecimaltoBcd (Time->Hour); + Time->Minute = DecimaltoBcd (Time->Minute); + Time->Second = DecimaltoBcd (Time->Second); + } + // + // If we are in 12 hour mode and PM is set, then set bit 7 of the Hour field. + // + if (RegisterB.Bits.MIL == 0 && PM) { + Time->Hour = (UINT8) (Time->Hour | 0x80); + } +} + +EFI_STATUS +RtcTimeFieldsValid ( + IN EFI_TIME *Time + ) +/*++ + +Routine Description: + + Arguments: + + Returns: +--*/ +// TODO: Time - add argument and description to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + if (Time->Year < 1998 || + Time->Year > 2099 || + Time->Month < 1 || + Time->Month > 12 || + (!DayValid (Time)) || + Time->Hour > 23 || + Time->Minute > 59 || + Time->Second > 59 || + Time->Nanosecond > 999999999 || + (!(Time->TimeZone == EFI_UNSPECIFIED_TIMEZONE || (Time->TimeZone >= -1440 && Time->TimeZone <= 1440))) || + (Time->Daylight & (~(EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT))) + ) { + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} + +UINT8 +RtcRead ( + IN UINT8 Address + ) +{ + IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, (UINT8) (Address | (UINT8) (IoRead8 (PCAT_RTC_ADDRESS_REGISTER) & 0x80))); + return IoRead8 (PCAT_RTC_DATA_REGISTER); +} + +VOID +RtcWrite ( + IN UINT8 Address, + IN UINT8 Data + ) +{ + IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, (UINT8) (Address | (UINT8) (IoRead8 (PCAT_RTC_ADDRESS_REGISTER) & 0x80))); + IoWrite8 (PCAT_RTC_DATA_REGISTER, Data); +} + + +EFI_STATUS +RtcTestCenturyRegister ( + VOID + ) +{ + UINT8 Century; + UINT8 Temp; + + Century = RtcRead (RTC_ADDRESS_CENTURY); + // + // RtcWrite (RTC_ADDRESS_CENTURY, 0x00); + // + Temp = (UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f); + RtcWrite (RTC_ADDRESS_CENTURY, Century); + if (Temp == 0x19 || Temp == 0x20) { + return EFI_SUCCESS; + } + + return EFI_DEVICE_ERROR; +} + +VOID +ConvertRtcTimeToEfiTime ( + IN EFI_TIME *Time, + IN RTC_REGISTER_B RegisterB + ) +{ + BOOLEAN PM; + + if ((Time->Hour) & 0x80) { + PM = TRUE; + } else { + PM = FALSE; + } + + Time->Hour = (UINT8) (Time->Hour & 0x7f); + + if (RegisterB.Bits.DM == 0) { + Time->Year = BcdToDecimal ((UINT8) Time->Year); + Time->Month = BcdToDecimal (Time->Month); + Time->Day = BcdToDecimal (Time->Day); + Time->Hour = BcdToDecimal (Time->Hour); + Time->Minute = BcdToDecimal (Time->Minute); + Time->Second = BcdToDecimal (Time->Second); + } + // + // If time is in 12 hour format, convert it to 24 hour format + // + if (RegisterB.Bits.MIL == 0) { + if (PM && Time->Hour < 12) { + Time->Hour = (UINT8) (Time->Hour + 12); + } + + if (!PM && Time->Hour == 12) { + Time->Hour = 0; + } + } + + Time->Nanosecond = 0; + Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE; + Time->Daylight = 0; +} + +EFI_STATUS +RtcWaitToUpdate ( + UINTN Timeout + ) +{ + RTC_REGISTER_A RegisterA; + RTC_REGISTER_D RegisterD; + + // + // See if the RTC is functioning correctly + // + RegisterD.Data = RtcRead (RTC_ADDRESS_REGISTER_D); + + if (RegisterD.Bits.VRT == 0) { + return EFI_DEVICE_ERROR; + } + // + // Wait for up to 0.1 seconds for the RTC to be ready. + // + Timeout = (Timeout / 10) + 1; + RegisterA.Data = RtcRead (RTC_ADDRESS_REGISTER_A); + while (RegisterA.Bits.UIP == 1 && Timeout > 0) { + MicroSecondDelay (10); + RegisterA.Data = RtcRead (RTC_ADDRESS_REGISTER_A); + Timeout--; + } + + RegisterD.Data = RtcRead (RTC_ADDRESS_REGISTER_D); + if (Timeout == 0 || RegisterD.Bits.VRT == 0) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +LibGetTime ( + OUT EFI_TIME *Time, + OUT EFI_TIME_CAPABILITIES *Capabilities + ) +{ + EFI_STATUS Status; + RTC_REGISTER_B RegisterB; + UINT8 Century; + UINTN BufferSize; + + // + // Check parameters for null pointer + // + if (Time == NULL) { + return EFI_INVALID_PARAMETER; + + } + // + // Acquire RTC Lock to make access to RTC atomic + // + EfiAcquireLock (&mRtc.RtcLock); + + // + // Wait for up to 0.1 seconds for the RTC to be updated + // + Status = RtcWaitToUpdate (100000); + if (EFI_ERROR (Status)) { + EfiReleaseLock (&mRtc.RtcLock); + return Status; + } + // + // Read Register B + // + RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B); + + // + // Get the Time/Date/Daylight Savings values. + // + Time->Second = RtcRead (RTC_ADDRESS_SECONDS); + Time->Minute = RtcRead (RTC_ADDRESS_MINUTES); + Time->Hour = RtcRead (RTC_ADDRESS_HOURS); + Time->Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH); + Time->Month = RtcRead (RTC_ADDRESS_MONTH); + Time->Year = RtcRead (RTC_ADDRESS_YEAR); + + ConvertRtcTimeToEfiTime (Time, RegisterB); + + if (RtcTestCenturyRegister () == EFI_SUCCESS) { + Century = BcdToDecimal ((UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f)); + } else { + Century = BcdToDecimal (RtcRead (RTC_ADDRESS_CENTURY)); + } + + Time->Year = (UINT16) (Century * 100 + Time->Year); + + // + // Release RTC Lock. + // + EfiReleaseLock (&mRtc.RtcLock); + + // + // Get the variable that containts the TimeZone and Daylight fields + // + Time->TimeZone = mRtc.SavedTimeZone; + Time->Daylight = mRtc.Daylight; + + BufferSize = sizeof (INT16) + sizeof (UINT8); + + // + // Make sure all field values are in correct range + // + Status = RtcTimeFieldsValid (Time); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + // + // Fill in Capabilities if it was passed in + // + if (Capabilities) { + Capabilities->Resolution = 1; + // + // 1 hertz + // + Capabilities->Accuracy = 50000000; + // + // 50 ppm + // + Capabilities->SetsToZero = FALSE; + } + + return EFI_SUCCESS; +} + + + +EFI_STATUS +LibSetTime ( + IN EFI_TIME *Time + ) +{ + EFI_STATUS Status; + EFI_TIME RtcTime; + RTC_REGISTER_B RegisterB; + UINT8 Century; + + if (Time == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Make sure that the time fields are valid + // + Status = RtcTimeFieldsValid (Time); + if (EFI_ERROR (Status)) { + return Status; + } + + CopyMem (&RtcTime, Time, sizeof (EFI_TIME)); + + // + // Acquire RTC Lock to make access to RTC atomic + // + EfiAcquireLock (&mRtc.RtcLock); + + // + // Wait for up to 0.1 seconds for the RTC to be updated + // + Status = RtcWaitToUpdate (100000); + if (EFI_ERROR (Status)) { + EfiReleaseLock (&mRtc.RtcLock); + return Status; + } + // + // Read Register B, and inhibit updates of the RTC + // + RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B); + RegisterB.Bits.SET = 1; + RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data); + + ConvertEfiTimeToRtcTime (&RtcTime, RegisterB, &Century); + + RtcWrite (RTC_ADDRESS_SECONDS, RtcTime.Second); + RtcWrite (RTC_ADDRESS_MINUTES, RtcTime.Minute); + RtcWrite (RTC_ADDRESS_HOURS, RtcTime.Hour); + RtcWrite (RTC_ADDRESS_DAY_OF_THE_MONTH, RtcTime.Day); + RtcWrite (RTC_ADDRESS_MONTH, RtcTime.Month); + RtcWrite (RTC_ADDRESS_YEAR, (UINT8) RtcTime.Year); + if (RtcTestCenturyRegister () == EFI_SUCCESS) { + Century = (UINT8) ((Century & 0x7f) | (RtcRead (RTC_ADDRESS_CENTURY) & 0x80)); + } + + RtcWrite (RTC_ADDRESS_CENTURY, Century); + + // + // Allow updates of the RTC registers + // + RegisterB.Bits.SET = 0; + RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data); + + // + // Release RTC Lock. + // + EfiReleaseLock (&mRtc.RtcLock); + + // + // Set the variable that containts the TimeZone and Daylight fields + // + mRtc.SavedTimeZone = Time->TimeZone; + mRtc.Daylight = Time->Daylight; + return Status; +} + +EFI_STATUS +libGetWakeupTime ( + OUT BOOLEAN *Enabled, + OUT BOOLEAN *Pending, + OUT EFI_TIME *Time + ) +{ + EFI_STATUS Status; + RTC_REGISTER_B RegisterB; + RTC_REGISTER_C RegisterC; + UINT8 Century; + + // + // Check paramters for null pointers + // + if ((Enabled == NULL) || (Pending == NULL) || (Time == NULL)) { + return EFI_INVALID_PARAMETER; + + } + // + // Acquire RTC Lock to make access to RTC atomic + // + EfiAcquireLock (&mRtc.RtcLock); + + // + // Wait for up to 0.1 seconds for the RTC to be updated + // + Status = RtcWaitToUpdate (100000); + if (EFI_ERROR (Status)) { + EfiReleaseLock (&mRtc.RtcLock); + return EFI_DEVICE_ERROR; + } + // + // Read Register B and Register C + // + RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B); + RegisterC.Data = RtcRead (RTC_ADDRESS_REGISTER_C); + + // + // Get the Time/Date/Daylight Savings values. + // + *Enabled = RegisterB.Bits.AIE; + if (*Enabled) { + Time->Second = RtcRead (RTC_ADDRESS_SECONDS_ALARM); + Time->Minute = RtcRead (RTC_ADDRESS_MINUTES_ALARM); + Time->Hour = RtcRead (RTC_ADDRESS_HOURS_ALARM); + Time->Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH); + Time->Month = RtcRead (RTC_ADDRESS_MONTH); + Time->Year = RtcRead (RTC_ADDRESS_YEAR); + } else { + Time->Second = 0; + Time->Minute = 0; + Time->Hour = 0; + Time->Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH); + Time->Month = RtcRead (RTC_ADDRESS_MONTH); + Time->Year = RtcRead (RTC_ADDRESS_YEAR); + } + + ConvertRtcTimeToEfiTime (Time, RegisterB); + + if (RtcTestCenturyRegister () == EFI_SUCCESS) { + Century = BcdToDecimal ((UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f)); + } else { + Century = BcdToDecimal (RtcRead (RTC_ADDRESS_CENTURY)); + } + + Time->Year = (UINT16) (Century * 100 + Time->Year); + + // + // Release RTC Lock. + // + EfiReleaseLock (&mRtc.RtcLock); + + // + // Make sure all field values are in correct range + // + Status = RtcTimeFieldsValid (Time); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + *Pending = RegisterC.Bits.AF; + + return EFI_SUCCESS; +} + +EFI_STATUS +LibSetWakeupTime ( + IN BOOLEAN Enabled, + OUT EFI_TIME *Time + ) +{ + EFI_STATUS Status; + EFI_TIME RtcTime; + RTC_REGISTER_B RegisterB; + UINT8 Century; + EFI_TIME_CAPABILITIES Capabilities; + + if (Enabled) { + + if (Time == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Make sure that the time fields are valid + // + Status = RtcTimeFieldsValid (Time); + if (EFI_ERROR (Status)) { + return EFI_INVALID_PARAMETER; + } + // + // Just support set alarm time within 24 hours + // + LibGetTime (&RtcTime, &Capabilities); + if (Time->Year != RtcTime.Year || + Time->Month != RtcTime.Month || + (Time->Day != RtcTime.Day && Time->Day != (RtcTime.Day + 1)) + ) { + return EFI_UNSUPPORTED; + } + // + // Make a local copy of the time and date + // + CopyMem (&RtcTime, Time, sizeof (EFI_TIME)); + + } + // + // Acquire RTC Lock to make access to RTC atomic + // + EfiAcquireLock (&mRtc.RtcLock); + + // + // Wait for up to 0.1 seconds for the RTC to be updated + // + Status = RtcWaitToUpdate (100000); + if (EFI_ERROR (Status)) { + EfiReleaseLock (&mRtc.RtcLock); + return EFI_DEVICE_ERROR; + } + // + // Read Register B, and inhibit updates of the RTC + // + RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B); + + RegisterB.Bits.SET = 1; + RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data); + + if (Enabled) { + ConvertEfiTimeToRtcTime (&RtcTime, RegisterB, &Century); + + // + // Set RTC alarm time + // + RtcWrite (RTC_ADDRESS_SECONDS_ALARM, RtcTime.Second); + RtcWrite (RTC_ADDRESS_MINUTES_ALARM, RtcTime.Minute); + RtcWrite (RTC_ADDRESS_HOURS_ALARM, RtcTime.Hour); + + RegisterB.Bits.AIE = 1; + + } else { + RegisterB.Bits.AIE = 0; + } + // + // Allow updates of the RTC registers + // + RegisterB.Bits.SET = 0; + RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data); + + // + // Release RTC Lock. + // + EfiReleaseLock (&mRtc.RtcLock); + + return EFI_SUCCESS; +} + + + +VOID +LibRtcVirtualAddressChangeEvent ( + VOID + ) +{ +} + + +VOID +LibRtcInitialize ( + VOID + ) +{ + EFI_STATUS Status; + RTC_REGISTER_A RegisterA; + RTC_REGISTER_B RegisterB; + RTC_REGISTER_C RegisterC; + RTC_REGISTER_D RegisterD; + UINT8 Century; + EFI_TIME Time; + + // + // Acquire RTC Lock to make access to RTC atomic + // + EfiAcquireLock (&mRtc.RtcLock); + + // + // Initialize RTC Register + // + // Make sure Division Chain is properly configured, + // or RTC clock won't "tick" -- time won't increment + // + RegisterA.Data = RTC_INIT_REGISTER_A; + RtcWrite (RTC_ADDRESS_REGISTER_A, RegisterA.Data); + + // + // Read Register B + // + RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B); + + // + // Clear RTC flag register + // + RegisterC.Data = RtcRead (RTC_ADDRESS_REGISTER_C); + + // + // Clear RTC register D + // + RegisterD.Data = RTC_INIT_REGISTER_D; + RtcWrite (RTC_ADDRESS_REGISTER_D, RegisterD.Data); + + // + // Wait for up to 0.1 seconds for the RTC to be updated + // + Status = RtcWaitToUpdate (100000); + if (EFI_ERROR (Status)) { + EfiReleaseLock (&mRtc.RtcLock); + return; + } + + // + // Get the Time/Date/Daylight Savings values. + // + Time.Second = RtcRead (RTC_ADDRESS_SECONDS); + Time.Minute = RtcRead (RTC_ADDRESS_MINUTES); + Time.Hour = RtcRead (RTC_ADDRESS_HOURS); + Time.Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH); + Time.Month = RtcRead (RTC_ADDRESS_MONTH); + Time.Year = RtcRead (RTC_ADDRESS_YEAR); + + ConvertRtcTimeToEfiTime (&Time, RegisterB); + + if (RtcTestCenturyRegister () == EFI_SUCCESS) { + Century = BcdToDecimal ((UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f)); + } else { + Century = BcdToDecimal (RtcRead (RTC_ADDRESS_CENTURY)); + } + + Time.Year = (UINT16) (Century * 100 + Time.Year); + + // + // Set RTC configuration after get original time + // + RtcWrite (RTC_ADDRESS_REGISTER_B, RTC_INIT_REGISTER_B); + + // + // Release RTC Lock. + // + EfiReleaseLock (&mRtc.RtcLock); + + // + // Validate time fields + // + Status = RtcTimeFieldsValid (&Time); + if (EFI_ERROR (Status)) { + Time.Second = RTC_INIT_SECOND; + Time.Minute = RTC_INIT_MINUTE; + Time.Hour = RTC_INIT_HOUR; + Time.Day = RTC_INIT_DAY; + Time.Month = RTC_INIT_MONTH; + Time.Year = RTC_INIT_YEAR; + } + // + // Reset time value according to new RTC configuration + // + LibSetTime (&Time); + + return; +} + + diff --git a/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Variable.c b/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Variable.c new file mode 100644 index 0000000000..d96a44304a --- /dev/null +++ b/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Variable.c @@ -0,0 +1,306 @@ +/** @file + Variable services implemented from system memory + + There is just a single runtime memory buffer that contans all the data. + + Copyright (c) 2007, Intel Corporation
+ Portions copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + + +UINT64 mMaximumVariableStorageSize; +UINT64 mRemainingVariableStorageSize; +UINT64 mMaximumVariableSize; + +typedef struct { + EFI_GUID VendorGuid; + UINT32 Attribute; + UINTN DataSize; +} VARIABLE_ARRAY_ENTRY; +// CHAR16 VariableName[] +// UINT8 Data[] + +VARIABLE_ARRAY_ENTRY *mVariableArray = NULL; +VARIABLE_ARRAY_ENTRY *mVariableArrayNextFree = NULL; +VARIABLE_ARRAY_ENTRY *mVariableArrayEnd = NULL; + + +VARIABLE_ARRAY_ENTRY * +AddEntry ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + IN UINTN DataSize, + IN VOID *Data + ) +{ + UINTN Size; + UINTN SizeOfString; + VARIABLE_ARRAY_ENTRY *Entry; + EFI_TPL CurrentTpl; + + + SizeOfString = StrSize (VariableName); + Size = SizeOfString + sizeof (VARIABLE_ARRAY_ENTRY) + DataSize; + if ((VARIABLE_ARRAY_ENTRY *)(((UINT8 *)mVariableArrayNextFree) + Size) > mVariableArrayEnd) { + // ran out of space + return NULL; + } + + if (!EfiAtRuntime ()) { + // Enter critical section + CurrentTpl = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL); + } + + Entry = mVariableArrayNextFree; + CopyGuid (&Entry->VendorGuid, VendorGuid); + Entry->Attribute = Attributes; + Entry->DataSize = DataSize; + StrCpy ((CHAR16 *)++mVariableArrayNextFree, VariableName); + mVariableArrayNextFree = (VARIABLE_ARRAY_ENTRY *)(((UINT8 *)mVariableArrayNextFree) + SizeOfString); + CopyMem (mVariableArrayNextFree, Data, DataSize); + mVariableArrayNextFree = (VARIABLE_ARRAY_ENTRY *)(((UINT8 *)mVariableArrayNextFree) + DataSize); + + if (!EfiAtRuntime ()) { + // Exit Critical section + gBS->RestoreTPL (CurrentTpl); + } + + return Entry; +} + +VOID +DeleteEntry ( + IN VARIABLE_ARRAY_ENTRY *Entry + ) +{ + UINTN Size; + UINT8 *Data; + EFI_TPL CurrentTpl; + + Size = StrSize ((CHAR16 *)(Entry + 1)) + sizeof (VARIABLE_ARRAY_ENTRY) + Entry->DataSize; + Data = ((UINT8 *)Entry) + Size; + + CopyMem (Entry, Data, (UINTN)mVariableArrayNextFree - (UINTN)Data); + + if (!EfiAtRuntime ()) { + // Enter critical section + CurrentTpl = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL); + } + + mVariableArrayNextFree = (VARIABLE_ARRAY_ENTRY *)(((UINT8 *)mVariableArrayNextFree) - Size); + + if (!EfiAtRuntime ()) { + // Exit Critical section + gBS->RestoreTPL (CurrentTpl); + } +} + + +VARIABLE_ARRAY_ENTRY * +GetVariableArrayEntry ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + OUT VOID **Data OPTIONAL + ) +{ + VARIABLE_ARRAY_ENTRY *Entry; + UINTN Size; + + if (*VariableName == L'\0') { + // by definition first entry is null-terminated string + if (mVariableArray == mVariableArrayNextFree) { + return NULL; + } + return mVariableArray; + } + + for (Entry = mVariableArray; Entry < mVariableArrayEnd;) { + if (CompareGuid (VendorGuid, &Entry->VendorGuid)) { + if (StrCmp (VariableName, (CHAR16 *)(Entry + 1))) { + Size = StrSize ((CHAR16 *)(Entry + 1)); + if (Data != NULL) { + *Data = (VOID *)(((UINT8 *)Entry) + (Size + sizeof (VARIABLE_ARRAY_ENTRY))); + } + return Entry; + } + } + + Size = StrSize ((CHAR16 *)(Entry + 1)) + sizeof (VARIABLE_ARRAY_ENTRY) + Entry->DataSize; + Entry = (VARIABLE_ARRAY_ENTRY *)(((UINT8 *)Entry) + Size); + } + + return NULL; +} + + +EFI_STATUS +LibGetVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + OUT UINT32 *Attributes OPTIONAL, + IN OUT UINTN *DataSize, + OUT VOID *Data + ) +{ + VARIABLE_ARRAY_ENTRY *Entry; + VOID *InternalData; + + if (EfiAtRuntime () && (Attributes != NULL)) { + if ((*Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0) { + return EFI_NOT_FOUND; + } + } + + Entry = GetVariableArrayEntry (VariableName, VendorGuid, &InternalData); + if (Entry == NULL) { + return EFI_NOT_FOUND; + } + + if (*DataSize < Entry->DataSize) { + *DataSize = Entry->DataSize; + return EFI_BUFFER_TOO_SMALL; + } + + *DataSize = Entry->DataSize; + if (Attributes != NULL) { + *Attributes = Entry->Attribute; + } + + CopyMem (Data, InternalData, *DataSize); + return EFI_SUCCESS; +} + + +EFI_STATUS +LibGetNextVariableName ( + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, + IN OUT EFI_GUID *VendorGuid + ) +{ + VARIABLE_ARRAY_ENTRY *Entry; + VOID *InternalData; + UINTN StringSize; + BOOLEAN Done; + + for (Done = FALSE; !Done; ) { + Entry = GetVariableArrayEntry (VariableName, VendorGuid, &InternalData); + if (Entry == NULL) { + return EFI_NOT_FOUND; + } + + // If we are at runtime skip variables that do not have the Runitme attribute set. + Done = (EfiAtRuntime () && ((Entry->Attribute & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) ? FALSE : TRUE; + } + + StringSize = StrSize ((CHAR16 *)(Entry + 1)); + Entry = (VARIABLE_ARRAY_ENTRY *)(((UINT8 *)Entry) + (StringSize + sizeof (VARIABLE_ARRAY_ENTRY) + Entry->DataSize)); + if (Entry >= mVariableArrayEnd) { + return EFI_NOT_FOUND; + } + + if (*VariableNameSize < StringSize) { + *VariableNameSize = StringSize; + return EFI_BUFFER_TOO_SMALL; + } + + *VariableNameSize = StringSize; + CopyMem (VariableName, (CHAR16 *)(Entry + 1), StringSize); + CopyMem (VendorGuid, &Entry->VendorGuid, sizeof (EFI_GUID)); + return EFI_SUCCESS; +} + + + +EFI_STATUS +LibSetVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + IN UINTN DataSize, + IN VOID *Data + ) +{ + VARIABLE_ARRAY_ENTRY *Entry; + VOID *InternalData; + + if (EfiAtRuntime () && ((Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) { + return EFI_NOT_FOUND; + } + + Entry = GetVariableArrayEntry (VariableName, VendorGuid, &InternalData); + if (Entry == NULL) { + if (DataSize == 0) { + return EFI_NOT_FOUND; + } + Entry = AddEntry (VariableName, VendorGuid, Attributes, DataSize, Data); + return (Entry == NULL) ? EFI_OUT_OF_RESOURCES : EFI_SUCCESS; + + } else if (DataSize == 0) { + // DataSize is zero so delete + DeleteEntry (Entry); + } else if (DataSize == Entry->DataSize) { + // No change is size so just update the store + Entry->Attribute |= Attributes; + CopyMem (InternalData, Data, DataSize); + } else { + // Grow the entry by deleting and adding back. Don't lose previous Attributes + Attributes |= Entry->Attribute; + DeleteEntry (Entry); + Entry = AddEntry (VariableName, VendorGuid, Attributes, DataSize, Data); + return (Entry == NULL) ? EFI_OUT_OF_RESOURCES : EFI_SUCCESS; + } +} + + +EFI_STATUS +LibQueryVariableInfo ( + IN UINT32 Attributes, + OUT UINT64 *MaximumVariableStorageSize, + OUT UINT64 *RemainingVariableStorageSize, + OUT UINT64 *MaximumVariableSize + ) +{ + *MaximumVariableStorageSize = mMaximumVariableStorageSize; + *RemainingVariableStorageSize = mRemainingVariableStorageSize; + *MaximumVariableStorageSize = mRemainingVariableStorageSize; + return EFI_SUCCESS; +} + + +VOID +LibVariableVirtualAddressChangeEvent (VOID) +{ + EfiConvertPointer (0, (VOID **)&mVariableArray); + EfiConvertPointer (0, (VOID **)&mVariableArrayNextFree); + EfiConvertPointer (0, (VOID **)&mVariableArrayEnd); +} + + +VOID +LibVariableInitialize (VOID) +{ + UINTN Size; + + Size = PcdGet32 (PcdEmbeddedMemVariableStoreSize); + mVariableArray = mVariableArrayNextFree = (VARIABLE_ARRAY_ENTRY *)AllocateRuntimePool (Size); + ASSERT (mVariableArray != NULL); + + mVariableArrayEnd = (VARIABLE_ARRAY_ENTRY *)(((UINT8 *)mVariableArray) + Size); + + mMaximumVariableStorageSize = Size - sizeof (VARIABLE_ARRAY_ENTRY); + mRemainingVariableStorageSize = mMaximumVariableStorageSize; + mMaximumVariableSize = mMaximumVariableStorageSize; +} + diff --git a/EmbeddedPkg/Library/PrePiExtractGuidedSectionLib/PrePiExtractGuidedSectionLib.c b/EmbeddedPkg/Library/PrePiExtractGuidedSectionLib/PrePiExtractGuidedSectionLib.c new file mode 100644 index 0000000000..b635fa0d9e --- /dev/null +++ b/EmbeddedPkg/Library/PrePiExtractGuidedSectionLib/PrePiExtractGuidedSectionLib.c @@ -0,0 +1,247 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include +#include + +#define PRE_PI_EXTRACT_GUIDED_SECTION_DATA_GUID { 0x385A982C, 0x2F49, 0x4043, { 0xA5, 0x1E, 0x49, 0x01, 0x02, 0x5C, 0x8B, 0x6B }} + +typedef struct { + UINT32 NumberOfExtractHandler; + GUID *ExtractHandlerGuidTable; + EXTRACT_GUIDED_SECTION_DECODE_HANDLER *ExtractDecodeHandlerTable; + EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER *ExtractGetInfoHandlerTable; +} PRE_PI_EXTRACT_GUIDED_SECTION_DATA; + +PRE_PI_EXTRACT_GUIDED_SECTION_DATA * +GetSavedData ( + VOID + ) +{ + EFI_HOB_GUID_TYPE *GuidHob; + GUID SavedDataGuid = PRE_PI_EXTRACT_GUIDED_SECTION_DATA_GUID; + + GuidHob = GetFirstGuidHob(&SavedDataGuid); + GuidHob++; + + return (PRE_PI_EXTRACT_GUIDED_SECTION_DATA *)GuidHob; +} + +RETURN_STATUS +EFIAPI +ExtractGuidedSectionRegisterHandlers ( + IN CONST GUID *SectionGuid, + IN EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER GetInfoHandler, + IN EXTRACT_GUIDED_SECTION_DECODE_HANDLER DecodeHandler + ) +{ + PRE_PI_EXTRACT_GUIDED_SECTION_DATA *SavedData; + UINT32 Index; + // + // Check input paramter. + // + if (SectionGuid == NULL) { + return RETURN_INVALID_PARAMETER; + } + + SavedData = GetSavedData(); + + // + // Search the match registered GetInfo handler for the input guided section. + // + for (Index = 0; Index < SavedData->NumberOfExtractHandler; Index ++) { + if (CompareGuid (&SavedData->ExtractHandlerGuidTable[Index], SectionGuid)) { + break; + } + } + + // + // If the guided handler has been registered before, only update its handler. + // + if (Index < SavedData->NumberOfExtractHandler) { + SavedData->ExtractDecodeHandlerTable [Index] = DecodeHandler; + SavedData->ExtractGetInfoHandlerTable [Index] = GetInfoHandler; + return RETURN_SUCCESS; + } + + // + // Check the global table is enough to contain new Handler. + // + if (SavedData->NumberOfExtractHandler >= PcdGet32 (PcdMaximumGuidedExtractHandler)) { + return RETURN_OUT_OF_RESOURCES; + } + + // + // Register new Handler and guid value. + // + CopyGuid (&SavedData->ExtractHandlerGuidTable [SavedData->NumberOfExtractHandler], SectionGuid); + SavedData->ExtractDecodeHandlerTable [SavedData->NumberOfExtractHandler] = DecodeHandler; + SavedData->ExtractGetInfoHandlerTable [SavedData->NumberOfExtractHandler++] = GetInfoHandler; + + return RETURN_SUCCESS; +} + +UINTN +EFIAPI +ExtractGuidedSectionGetGuidList ( + IN OUT GUID **ExtractHandlerGuidTable + ) +{ + PRE_PI_EXTRACT_GUIDED_SECTION_DATA *SavedData; + + ASSERT(ExtractHandlerGuidTable != NULL); + + SavedData = GetSavedData(); + + *ExtractHandlerGuidTable = SavedData->ExtractHandlerGuidTable; + return SavedData->NumberOfExtractHandler; +} + +RETURN_STATUS +EFIAPI +ExtractGuidedSectionGetInfo ( + IN CONST VOID *InputSection, + OUT UINT32 *OutputBufferSize, + OUT UINT32 *ScratchBufferSize, + OUT UINT16 *SectionAttribute + ) +{ + PRE_PI_EXTRACT_GUIDED_SECTION_DATA *SavedData; + UINT32 Index; + + if (InputSection == NULL) { + return RETURN_INVALID_PARAMETER; + } + + ASSERT (OutputBufferSize != NULL); + ASSERT (ScratchBufferSize != NULL); + ASSERT (SectionAttribute != NULL); + + SavedData = GetSavedData(); + + // + // Search the match registered GetInfo handler for the input guided section. + // + for (Index = 0; Index < SavedData->NumberOfExtractHandler; Index ++) { + if (CompareGuid (&SavedData->ExtractHandlerGuidTable[Index], &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid))) { + break; + } + } + + // + // Not found, the input guided section is not supported. + // + if (Index == SavedData->NumberOfExtractHandler) { + return RETURN_INVALID_PARAMETER; + } + + // + // Call the match handler to getinfo for the input section data. + // + return SavedData->ExtractGetInfoHandlerTable [Index] ( + InputSection, + OutputBufferSize, + ScratchBufferSize, + SectionAttribute + ); +} + +RETURN_STATUS +EFIAPI +ExtractGuidedSectionDecode ( + IN CONST VOID *InputSection, + OUT VOID **OutputBuffer, + OUT VOID *ScratchBuffer, OPTIONAL + OUT UINT32 *AuthenticationStatus + ) +{ + PRE_PI_EXTRACT_GUIDED_SECTION_DATA *SavedData; + UINT32 Index; + + if (InputSection == NULL) { + return RETURN_INVALID_PARAMETER; + } + + ASSERT (OutputBuffer != NULL); + ASSERT (AuthenticationStatus != NULL); + + SavedData = GetSavedData(); + + // + // Search the match registered GetInfo handler for the input guided section. + // + for (Index = 0; Index < SavedData->NumberOfExtractHandler; Index ++) { + if (CompareGuid (&SavedData->ExtractHandlerGuidTable[Index], &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid))) { + break; + } + } + + // + // Not found, the input guided section is not supported. + // + if (Index == SavedData->NumberOfExtractHandler) { + return RETURN_INVALID_PARAMETER; + } + + // + // Call the match handler to getinfo for the input section data. + // + return SavedData->ExtractDecodeHandlerTable [Index] ( + InputSection, + OutputBuffer, + ScratchBuffer, + AuthenticationStatus + ); +} + +RETURN_STATUS +EFIAPI +ExtractGuidedSectionLibConstructor ( + VOID + ) +{ + PRE_PI_EXTRACT_GUIDED_SECTION_DATA SavedData; + GUID HobGuid = PRE_PI_EXTRACT_GUIDED_SECTION_DATA_GUID; + + // + // Allocate global pool space to store the registered handler and its guid value. + // + SavedData.ExtractHandlerGuidTable = (GUID *)AllocatePool(PcdGet32(PcdMaximumGuidedExtractHandler) * sizeof(GUID)); + if (SavedData.ExtractHandlerGuidTable == NULL) { + return RETURN_OUT_OF_RESOURCES; + } + + SavedData.ExtractDecodeHandlerTable = (EXTRACT_GUIDED_SECTION_DECODE_HANDLER *)AllocatePool(PcdGet32(PcdMaximumGuidedExtractHandler) * sizeof(EXTRACT_GUIDED_SECTION_DECODE_HANDLER)); + if (SavedData.ExtractDecodeHandlerTable == NULL) { + return RETURN_OUT_OF_RESOURCES; + } + + SavedData.ExtractGetInfoHandlerTable = (EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER *)AllocatePool(PcdGet32(PcdMaximumGuidedExtractHandler) * sizeof(EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER)); + if (SavedData.ExtractGetInfoHandlerTable == NULL) { + return RETURN_OUT_OF_RESOURCES; + } + + // + // the initialized number is Zero. + // + SavedData.NumberOfExtractHandler = 0; + + BuildGuidDataHob(&HobGuid, &SavedData, sizeof(SavedData)); + + return RETURN_SUCCESS; +} diff --git a/EmbeddedPkg/Library/PrePiExtractGuidedSectionLib/PrePiExtractGuidedSectionLib.inf b/EmbeddedPkg/Library/PrePiExtractGuidedSectionLib/PrePiExtractGuidedSectionLib.inf new file mode 100644 index 0000000000..bffe5b250a --- /dev/null +++ b/EmbeddedPkg/Library/PrePiExtractGuidedSectionLib/PrePiExtractGuidedSectionLib.inf @@ -0,0 +1,24 @@ +#%HEADER% +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PrePiExtractGuidedSectionLib + FILE_GUID = 36F6E94E-6E8E-488E-89A4-7AD911C5AFB1 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = ExtractGuidedSectionLib + + CONSTRUCTOR = ExtractGuidedSectionLibConstructor + +[Sources.common] + PrePiExtractGuidedSectionLib.c + +[Packages] + EmbeddedPkg/EmbeddedPkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseMemoryLib + DebugLib + +[FixedPcd.common] + gEfiMdePkgTokenSpaceGuid.PcdMaximumGuidedExtractHandler diff --git a/EmbeddedPkg/Library/PrePiLib/FwVol.c b/EmbeddedPkg/Library/PrePiLib/FwVol.c new file mode 100644 index 0000000000..4a9e24683f --- /dev/null +++ b/EmbeddedPkg/Library/PrePiLib/FwVol.c @@ -0,0 +1,841 @@ +/** @file + Implementation of the 6 PEI Ffs (FV) APIs in library form. + + This code only knows about a FV if it has a EFI_HOB_TYPE_FV entry in the HOB list + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include + + +#define GET_OCCUPIED_SIZE(ActualSize, Alignment) \ + (ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1)) + + +/** + Returns the highest bit set of the State field + + @param ErasePolarity Erase Polarity as defined by EFI_FVB2_ERASE_POLARITY + in the Attributes field. + @param FfsHeader Pointer to FFS File Header + + + @retval the highest bit in the State field + +**/ +STATIC +EFI_FFS_FILE_STATE +GetFileState( + IN UINT8 ErasePolarity, + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +{ + EFI_FFS_FILE_STATE FileState; + EFI_FFS_FILE_STATE HighestBit; + + FileState = FfsHeader->State; + + if (ErasePolarity != 0) { + FileState = (EFI_FFS_FILE_STATE)~FileState; + } + + HighestBit = 0x80; + while (HighestBit != 0 && (HighestBit & FileState) == 0) { + HighestBit >>= 1; + } + + return HighestBit; +} + + +/** + Calculates the checksum of the header of a file. + The header is a zero byte checksum, so zero means header is good + + @param FfsHeader Pointer to FFS File Header + + @retval Checksum of the header + +**/ +STATIC +UINT8 +CalculateHeaderChecksum ( + IN EFI_FFS_FILE_HEADER *FileHeader + ) +{ + UINT8 *Ptr; + UINTN Index; + UINT8 Sum; + + Sum = 0; + Ptr = (UINT8 *)FileHeader; + + for (Index = 0; Index < sizeof(EFI_FFS_FILE_HEADER) - 3; Index += 4) { + Sum = (UINT8)(Sum + Ptr[Index]); + Sum = (UINT8)(Sum + Ptr[Index+1]); + Sum = (UINT8)(Sum + Ptr[Index+2]); + Sum = (UINT8)(Sum + Ptr[Index+3]); + } + + for (; Index < sizeof(EFI_FFS_FILE_HEADER); Index++) { + Sum = (UINT8)(Sum + Ptr[Index]); + } + + // + // State field (since this indicates the different state of file). + // + Sum = (UINT8)(Sum - FileHeader->State); + // + // Checksum field of the file is not part of the header checksum. + // + Sum = (UINT8)(Sum - FileHeader->IntegrityCheck.Checksum.File); + + return Sum; +} + + +/** + Given a FileHandle return the VolumeHandle + + @param FileHandle File handle to look up + @param VolumeHandle Match for FileHandle + + @retval TRUE VolumeHandle is valid + +**/ +STATIC +BOOLEAN +EFIAPI +FileHandleToVolume ( + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_PEI_FV_HANDLE *VolumeHandle + ) +{ + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + EFI_PEI_HOB_POINTERS Hob; + + Hob.Raw = GetHobList (); + if (Hob.Raw == NULL) { + return FALSE; + } + + do { + Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV, Hob.Raw); + if (Hob.Raw != NULL) { + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(Hob.FirmwareVolume->BaseAddress); + if (((UINT64) (UINTN) FileHandle > (UINT64) (UINTN) FwVolHeader ) && \ + ((UINT64) (UINTN) FileHandle <= ((UINT64) (UINTN) FwVolHeader + FwVolHeader->FvLength - 1))) { + *VolumeHandle = (EFI_PEI_FV_HANDLE)FwVolHeader; + return TRUE; + } + + Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV, GET_NEXT_HOB (Hob)); + } + } while (Hob.Raw != NULL); + + return FALSE; +} + + + +/** + Given the input file pointer, search for the next matching file in the + FFS volume as defined by SearchType. The search starts from FileHeader inside + the Firmware Volume defined by FwVolHeader. + + @param FileHandle File handle to look up + @param VolumeHandle Match for FileHandle + + +**/ +EFI_STATUS +FindFileEx ( + IN CONST EFI_PEI_FV_HANDLE FvHandle, + IN CONST EFI_GUID *FileName, OPTIONAL + IN EFI_FV_FILETYPE SearchType, + IN OUT EFI_PEI_FILE_HANDLE *FileHandle + ) +{ + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + EFI_FFS_FILE_HEADER **FileHeader; + EFI_FFS_FILE_HEADER *FfsFileHeader; + EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExHeaderInfo; + UINT32 FileLength; + UINT32 FileOccupiedSize; + UINT32 FileOffset; + UINT64 FvLength; + UINT8 ErasePolarity; + UINT8 FileState; + + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)FvHandle; + FileHeader = (EFI_FFS_FILE_HEADER **)FileHandle; + + FvLength = FwVolHeader->FvLength; + if (FwVolHeader->Attributes & EFI_FVB2_ERASE_POLARITY) { + ErasePolarity = 1; + } else { + ErasePolarity = 0; + } + + // + // If FileHeader is not specified (NULL) or FileName is not NULL, + // start with the first file in the firmware volume. Otherwise, + // start from the FileHeader. + // + if ((*FileHeader == NULL) || (FileName != NULL)) { + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FwVolHeader + FwVolHeader->HeaderLength); + if (FwVolHeader->ExtHeaderOffset != 0) { + FwVolExHeaderInfo = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)(((UINT8 *)FwVolHeader) + FwVolHeader->ExtHeaderOffset); + FfsFileHeader = (EFI_FFS_FILE_HEADER *)(((UINT8 *)FwVolExHeaderInfo) + FwVolExHeaderInfo->ExtHeaderSize); + } + } else { + // + // Length is 24 bits wide so mask upper 8 bits + // FileLength is adjusted to FileOccupiedSize as it is 8 byte aligned. + // + FileLength = *(UINT32 *)(*FileHeader)->Size & 0x00FFFFFF; + FileOccupiedSize = GET_OCCUPIED_SIZE (FileLength, 8); + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)*FileHeader + FileOccupiedSize); + } + + FileOffset = (UINT32) ((UINT8 *)FfsFileHeader - (UINT8 *)FwVolHeader); + ASSERT (FileOffset <= 0xFFFFFFFF); + + while (FileOffset < (FvLength - sizeof (EFI_FFS_FILE_HEADER))) { + // + // Get FileState which is the highest bit of the State + // + FileState = GetFileState (ErasePolarity, FfsFileHeader); + + switch (FileState) { + + case EFI_FILE_HEADER_INVALID: + FileOffset += sizeof(EFI_FFS_FILE_HEADER); + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + sizeof(EFI_FFS_FILE_HEADER)); + break; + + case EFI_FILE_DATA_VALID: + case EFI_FILE_MARKED_FOR_UPDATE: + if (CalculateHeaderChecksum (FfsFileHeader) != 0) { + ASSERT (FALSE); + *FileHeader = NULL; + return EFI_NOT_FOUND; + } + + FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF; + FileOccupiedSize = GET_OCCUPIED_SIZE(FileLength, 8); + + if (FileName != NULL) { + if (CompareGuid (&FfsFileHeader->Name, (EFI_GUID*)FileName)) { + *FileHeader = FfsFileHeader; + return EFI_SUCCESS; + } + } else if (((SearchType == FfsFileHeader->Type) || (SearchType == EFI_FV_FILETYPE_ALL)) && + (FfsFileHeader->Type != EFI_FV_FILETYPE_FFS_PAD)) { + *FileHeader = FfsFileHeader; + return EFI_SUCCESS; + } + + FileOffset += FileOccupiedSize; + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize); + break; + + case EFI_FILE_DELETED: + FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF; + FileOccupiedSize = GET_OCCUPIED_SIZE(FileLength, 8); + FileOffset += FileOccupiedSize; + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize); + break; + + default: + *FileHeader = NULL; + return EFI_NOT_FOUND; + } + } + + + *FileHeader = NULL; + return EFI_NOT_FOUND; +} + + +/** + Go through the file to search SectionType section, + when meeting an encapsuled section. + + @param SectionType - Filter to find only section of this type. + @param Section - From where to search. + @param SectionSize - The file size to search. + @param OutputBuffer - Pointer to the section to search. + + @retval EFI_SUCCESS +**/ +EFI_STATUS +FfsProcessSection ( + IN EFI_SECTION_TYPE SectionType, + IN EFI_COMMON_SECTION_HEADER *Section, + IN UINTN SectionSize, + OUT VOID **OutputBuffer + ) +{ + EFI_STATUS Status; + UINT32 SectionLength; + UINT32 ParsedLength; + EFI_COMPRESSION_SECTION *CompressionSection; + UINTN DstBufferSize; + VOID *ScratchBuffer; + UINT32 ScratchBufferSize; + VOID *DstBuffer; + UINT16 SectionAttribute; + UINT32 AuthenticationStatus; + + + *OutputBuffer = NULL; + ParsedLength = 0; + Status = EFI_NOT_FOUND; + while (ParsedLength < SectionSize) { + if (Section->Type == SectionType) { + *OutputBuffer = (VOID *)(Section + 1); + + return EFI_SUCCESS; + } else if ((Section->Type == EFI_SECTION_COMPRESSION) || (Section->Type == EFI_SECTION_GUID_DEFINED)) { + + if (Section->Type == EFI_SECTION_COMPRESSION) { + CompressionSection = (EFI_COMPRESSION_SECTION *) Section; + SectionLength = *(UINT32 *)Section->Size & 0x00FFFFFF; + + if (CompressionSection->CompressionType != EFI_STANDARD_COMPRESSION) { + return EFI_UNSUPPORTED; + } + + Status = UefiDecompressGetInfo ( + (UINT8 *) ((EFI_COMPRESSION_SECTION *) Section + 1), + (UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION), + (UINT32 *) &DstBufferSize, + &ScratchBufferSize + ); + } else if (Section->Type == EFI_SECTION_GUID_DEFINED) { + Status = ExtractGuidedSectionGetInfo ( + Section, + (UINT32 *) &DstBufferSize, + &ScratchBufferSize, + &SectionAttribute + ); + } + + if (EFI_ERROR (Status)) { + // + // GetInfo failed + // + DEBUG ((EFI_D_ERROR, "Decompress GetInfo Failed - %r\n", Status)); + return EFI_NOT_FOUND; + } + // + // Allocate scratch buffer + // + ScratchBuffer = (VOID *)(UINTN)AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize)); + if (ScratchBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // Allocate destination buffer, extra one page for adjustment + // + DstBuffer = (VOID *)(UINTN)AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1); + if (DstBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // DstBuffer still is one section. Adjust DstBuffer offset, skip EFI section header + // to make section data at page alignment. + // + DstBuffer = (UINT8 *)DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER); + // + // Call decompress function + // + if (Section->Type == EFI_SECTION_COMPRESSION) { + Status = UefiDecompress ( + (CHAR8 *) ((EFI_COMPRESSION_SECTION *) Section + 1), + DstBuffer, + ScratchBuffer + ); + } else if (Section->Type == EFI_SECTION_GUID_DEFINED) { + Status = ExtractGuidedSectionDecode ( + Section, + &DstBuffer, + ScratchBuffer, + &AuthenticationStatus + ); + } + + if (EFI_ERROR (Status)) { + // + // Decompress failed + // + DEBUG ((EFI_D_ERROR, "Decompress Failed - %r\n", Status)); + return EFI_NOT_FOUND; + } else { + return FfsProcessSection ( + SectionType, + DstBuffer, + DstBufferSize, + OutputBuffer + ); + } + } + + // + // Size is 24 bits wide so mask upper 8 bits. + // SectionLength is adjusted it is 4 byte aligned. + // Go to the next section + // + SectionLength = *(UINT32 *)Section->Size & 0x00FFFFFF; + SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4); + ASSERT (SectionLength != 0); + ParsedLength += SectionLength; + Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength); + } + + return EFI_NOT_FOUND; +} + + + +/** + This service enables discovery sections of a given type within a valid FFS file. + + @param SearchType The value of the section type to find. + @param FfsFileHeader A pointer to the file header that contains the set of sections to + be searched. + @param SectionData A pointer to the discovered section, if successful. + + @retval EFI_SUCCESS The section was found. + @retval EFI_NOT_FOUND The section was not found. + +**/ +EFI_STATUS +EFIAPI +FfsFindSectionData ( + IN EFI_SECTION_TYPE SectionType, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT VOID **SectionData + ) +{ + EFI_FFS_FILE_HEADER *FfsFileHeader; + UINT32 FileSize; + EFI_COMMON_SECTION_HEADER *Section; + + FfsFileHeader = (EFI_FFS_FILE_HEADER *)(FileHandle); + + // + // Size is 24 bits wide so mask upper 8 bits. + // Does not include FfsFileHeader header size + // FileSize is adjusted to FileOccupiedSize as it is 8 byte aligned. + // + Section = (EFI_COMMON_SECTION_HEADER *)(FfsFileHeader + 1); + FileSize = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF; + FileSize -= sizeof (EFI_FFS_FILE_HEADER); + + return FfsProcessSection ( + SectionType, + Section, + FileSize, + SectionData + ); +} + + + + + + +/** + This service enables discovery of additional firmware files. + + @param SearchType A filter to find files only of this type. + @param FwVolHeader Pointer to the firmware volume header of the volume to search. + This parameter must point to a valid FFS volume. + @param FileHeader Pointer to the current file from which to begin searching. + + @retval EFI_SUCCESS The file was found. + @retval EFI_NOT_FOUND The file was not found. + @retval EFI_NOT_FOUND The header checksum was not zero. + +**/ +EFI_STATUS +EFIAPI +FfsFindNextFile ( + IN UINT8 SearchType, + IN EFI_PEI_FV_HANDLE VolumeHandle, + IN OUT EFI_PEI_FILE_HANDLE *FileHandle + ) +{ + return FindFileEx (VolumeHandle, NULL, SearchType, FileHandle); +} + + +/** + This service enables discovery of additional firmware volumes. + + @param Instance This instance of the firmware volume to find. The value 0 is the + Boot Firmware Volume (BFV). + @param FwVolHeader Pointer to the firmware volume header of the volume to return. + + @retval EFI_SUCCESS The volume was found. + @retval EFI_NOT_FOUND The volume was not found. + +**/ +EFI_STATUS +EFIAPI +FfsFindNextVolume ( + IN UINTN Instance, + IN OUT EFI_PEI_FV_HANDLE *VolumeHandle + ) +{ + EFI_PEI_HOB_POINTERS Hob; + + + Hob.Raw = GetHobList (); + if (Hob.Raw == NULL) { + return EFI_NOT_FOUND; + } + + do { + Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV, Hob.Raw); + if (Hob.Raw != NULL) { + if (Instance-- == 0) { + *VolumeHandle = (EFI_PEI_FV_HANDLE)(UINTN)(Hob.FirmwareVolume->BaseAddress); + return EFI_SUCCESS; + } + + Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV, GET_NEXT_HOB (Hob)); + } + } while (Hob.Raw != NULL); + + return EFI_NOT_FOUND; + +} + + +/** + Find a file in the volume by name + + @param FileName A pointer to the name of the file to + find within the firmware volume. + + @param VolumeHandle The firmware volume to search FileHandle + Upon exit, points to the found file's + handle or NULL if it could not be found. + + @retval EFI_SUCCESS File was found. + + @retval EFI_NOT_FOUND File was not found. + + @retval EFI_INVALID_PARAMETER VolumeHandle or FileHandle or + FileName was NULL. + +**/ +EFI_STATUS +EFIAPI +FfsFindFileByName ( + IN CONST EFI_GUID *FileName, + IN EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_PEI_FILE_HANDLE *FileHandle + ) +{ + EFI_STATUS Status; + if ((VolumeHandle == NULL) || (FileName == NULL) || (FileHandle == NULL)) { + return EFI_INVALID_PARAMETER; + } + Status = FindFileEx (VolumeHandle, FileName, 0, FileHandle); + if (Status == EFI_NOT_FOUND) { + *FileHandle = NULL; + } + return Status; +} + + + + +/** + Get information about the file by name. + + @param FileHandle Handle of the file. + + @param FileInfo Upon exit, points to the file's + information. + + @retval EFI_SUCCESS File information returned. + + @retval EFI_INVALID_PARAMETER If FileHandle does not + represent a valid file. + + @retval EFI_INVALID_PARAMETER If FileInfo is NULL. + +**/ +EFI_STATUS +EFIAPI +FfsGetFileInfo ( + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_FV_FILE_INFO *FileInfo + ) +{ + UINT8 FileState; + UINT8 ErasePolarity; + EFI_FFS_FILE_HEADER *FileHeader; + EFI_PEI_FV_HANDLE VolumeHandle; + + if ((FileHandle == NULL) || (FileInfo == NULL)) { + return EFI_INVALID_PARAMETER; + } + + VolumeHandle = 0; + // + // Retrieve the FirmwareVolume which the file resides in. + // + if (!FileHandleToVolume(FileHandle, &VolumeHandle)) { + return EFI_INVALID_PARAMETER; + } + + if (((EFI_FIRMWARE_VOLUME_HEADER*)VolumeHandle)->Attributes & EFI_FVB2_ERASE_POLARITY) { + ErasePolarity = 1; + } else { + ErasePolarity = 0; + } + + // + // Get FileState which is the highest bit of the State + // + FileState = GetFileState (ErasePolarity, (EFI_FFS_FILE_HEADER*)FileHandle); + + switch (FileState) { + case EFI_FILE_DATA_VALID: + case EFI_FILE_MARKED_FOR_UPDATE: + break; + default: + return EFI_INVALID_PARAMETER; + } + + FileHeader = (EFI_FFS_FILE_HEADER *)FileHandle; + CopyMem (&FileInfo->FileName, &FileHeader->Name, sizeof(EFI_GUID)); + FileInfo->FileType = FileHeader->Type; + FileInfo->FileAttributes = FileHeader->Attributes; + FileInfo->BufferSize = ((*(UINT32 *)FileHeader->Size) & 0x00FFFFFF) - sizeof (EFI_FFS_FILE_HEADER); + FileInfo->Buffer = (FileHeader + 1); + return EFI_SUCCESS; +} + + +/** + Get Information about the volume by name + + @param VolumeHandle Handle of the volume. + + @param VolumeInfo Upon exit, points to the volume's + information. + + @retval EFI_SUCCESS File information returned. + + @retval EFI_INVALID_PARAMETER If FileHandle does not + represent a valid file. + + @retval EFI_INVALID_PARAMETER If FileInfo is NULL. + +**/ +EFI_STATUS +EFIAPI +FfsGetVolumeInfo ( + IN EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_FV_INFO *VolumeInfo + ) +{ + EFI_FIRMWARE_VOLUME_HEADER FwVolHeader; + EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExHeaderInfo; + + if (VolumeInfo == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // VolumeHandle may not align at 8 byte, + // but FvLength is UINT64 type, which requires FvHeader align at least 8 byte. + // So, Copy FvHeader into the local FvHeader structure. + // + CopyMem (&FwVolHeader, VolumeHandle, sizeof (EFI_FIRMWARE_VOLUME_HEADER)); + // + // Check Fv Image Signature + // + if (FwVolHeader.Signature != EFI_FVH_SIGNATURE) { + return EFI_INVALID_PARAMETER; + } + VolumeInfo->FvAttributes = FwVolHeader.Attributes; + VolumeInfo->FvStart = (VOID *) VolumeHandle; + VolumeInfo->FvSize = FwVolHeader.FvLength; + CopyMem (&VolumeInfo->FvFormat, &FwVolHeader.FileSystemGuid, sizeof(EFI_GUID)); + + if (FwVolHeader.ExtHeaderOffset != 0) { + FwVolExHeaderInfo = (EFI_FIRMWARE_VOLUME_EXT_HEADER*)(((UINT8 *)VolumeHandle) + FwVolHeader.ExtHeaderOffset); + CopyMem (&VolumeInfo->FvName, &FwVolExHeaderInfo->FvName, sizeof(EFI_GUID)); + } + return EFI_SUCCESS; +} + + + +/** + Search through every FV until you find a file of type FileType + + @param FileType File handle of a Fv type file. + @param Volumehandle On succes Volume Handle of the match + @param FileHandle On success File Handle of the match + + @retval EFI_NOT_FOUND FV image can't be found. + @retval EFI_SUCCESS Successfully found FileType + +**/ +EFI_STATUS +EFIAPI +FfsAnyFvFindFirstFile ( + IN EFI_FV_FILETYPE FileType, + OUT EFI_PEI_FV_HANDLE *VolumeHandle, + OUT EFI_PEI_FILE_HANDLE *FileHandle + ) +{ + EFI_STATUS Status; + UINTN Instance; + + // + // Search every FV for the DXE Core + // + Instance = 0; + *FileHandle = NULL; + + while (1) + { + Status = FfsFindNextVolume (Instance++, VolumeHandle); + if (EFI_ERROR (Status)) + { + break; + } + + Status = FfsFindNextFile (FileType, *VolumeHandle, FileHandle); + if (!EFI_ERROR (Status)) + { + break; + } + } + + return Status; +} + + + +/** + Get Fv image from the FV type file, then add FV & FV2 Hob. + + @param FileHandle File handle of a Fv type file. + + + @retval EFI_NOT_FOUND FV image can't be found. + @retval EFI_SUCCESS Successfully to process it. + +**/ +EFI_STATUS +EFIAPI +FfsProcessFvFile ( + IN EFI_PEI_FILE_HANDLE FvFileHandle + ) +{ + EFI_STATUS Status; + EFI_PEI_FV_HANDLE FvImageHandle; + EFI_FV_INFO FvImageInfo; + UINT32 FvAlignment; + VOID *FvBuffer; + EFI_PEI_HOB_POINTERS HobFv2; + + FvBuffer = NULL; + + + // + // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has already + // been extracted. + // + HobFv2.Raw = GetHobList (); + while ((HobFv2.Raw = GetNextHob (EFI_HOB_TYPE_FV2, HobFv2.Raw)) != NULL) { + if (CompareGuid (&(((EFI_FFS_FILE_HEADER *)FvFileHandle)->Name), &HobFv2.FirmwareVolume2->FileName)) { + // + // this FILE has been dispatched, it will not be dispatched again. + // + return EFI_SUCCESS; + } + HobFv2.Raw = GET_NEXT_HOB (HobFv2); + } + + // + // Find FvImage in FvFile + // + Status = FfsFindSectionData (EFI_SECTION_FIRMWARE_VOLUME_IMAGE, FvFileHandle, (VOID **)&FvImageHandle); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Collect FvImage Info. + // + Status = FfsGetVolumeInfo (FvImageHandle, &FvImageInfo); + ASSERT_EFI_ERROR (Status); + + // + // FvAlignment must be more than 8 bytes required by FvHeader structure. + // + FvAlignment = 1 << ((FvImageInfo.FvAttributes & EFI_FVB2_ALIGNMENT) >> 16); + if (FvAlignment < 8) { + FvAlignment = 8; + } + + // + // Check FvImage + // + if ((UINTN) FvImageInfo.FvStart % FvAlignment != 0) { + FvBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINT32) FvImageInfo.FvSize), FvAlignment); + if (FvBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + CopyMem (FvBuffer, FvImageInfo.FvStart, (UINTN) FvImageInfo.FvSize); + // + // Update FvImageInfo after reload FvImage to new aligned memory + // + FfsGetVolumeInfo ((EFI_PEI_FV_HANDLE) FvBuffer, &FvImageInfo); + } + + + // + // Inform HOB consumer phase, i.e. DXE core, the existance of this FV + // + BuildFvHob ((EFI_PHYSICAL_ADDRESS) (UINTN) FvImageInfo.FvStart, FvImageInfo.FvSize); + + // + // Makes the encapsulated volume show up in DXE phase to skip processing of + // encapsulated file again. + // + BuildFv2Hob ( + (EFI_PHYSICAL_ADDRESS) (UINTN) FvImageInfo.FvStart, + FvImageInfo.FvSize, + &FvImageInfo.FvName, + &(((EFI_FFS_FILE_HEADER *)FvFileHandle)->Name) + ); + + return EFI_SUCCESS; +} + + diff --git a/EmbeddedPkg/Library/PrePiLib/Hob.c b/EmbeddedPkg/Library/PrePiLib/Hob.c new file mode 100644 index 0000000000..3c6574282c --- /dev/null +++ b/EmbeddedPkg/Library/PrePiLib/Hob.c @@ -0,0 +1,808 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include + +// +// Have to use build system to set the original value in case we are running +// from FLASH and globals don't work. So if you do a GetHobList() and gHobList +// and gHobList is NULL the PCD default values are used. +// +VOID *gHobList = NULL; + + + + +// May want to put this into a library so you only need the PCD setings if you are using the feature? +VOID +BuildMemoryTypeInformationHob ( + VOID + ) +{ + EFI_MEMORY_TYPE_INFORMATION Info[10]; + + Info[0].Type = EfiACPIReclaimMemory; + Info[0].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiACPIReclaimMemory); + Info[1].Type = EfiACPIMemoryNVS; + Info[1].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiACPIMemoryNVS); + Info[2].Type = EfiReservedMemoryType; + Info[2].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiReservedMemoryType); + Info[3].Type = EfiRuntimeServicesData; + Info[3].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiRuntimeServicesData); + Info[4].Type = EfiRuntimeServicesCode; + Info[4].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiRuntimeServicesCode); + Info[5].Type = EfiBootServicesCode; + Info[5].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiBootServicesCode); + Info[6].Type = EfiBootServicesData; + Info[6].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiBootServicesData); + Info[7].Type = EfiLoaderCode; + Info[7].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiLoaderCode); + Info[8].Type = EfiLoaderData; + Info[8].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiLoaderData); + + // Terminator for the list + Info[9].Type = EfiMaxMemoryType; + Info[9].NumberOfPages = 0; + + + BuildGuidDataHob (&gEfiMemoryTypeInformationGuid, &Info, sizeof (Info)); +} + +/** + + +**/ +VOID +CreateHobList ( + IN VOID *MemoryBegin, + IN UINTN MemoryLength, + IN VOID *HobBase, + IN VOID *StackBase + ) +{ + EFI_HOB_HANDOFF_INFO_TABLE *Hob; + EFI_HOB_GENERIC_HEADER *HobEnd; + EFI_RESOURCE_ATTRIBUTE_TYPE Attributes; + + + Hob = HobBase; + HobEnd = (EFI_HOB_GENERIC_HEADER *)(Hob+1); + + Hob->Header.HobType = EFI_HOB_TYPE_HANDOFF; + Hob->Header.HobLength = sizeof(EFI_HOB_HANDOFF_INFO_TABLE); + Hob->Header.Reserved = 0; + + HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST; + HobEnd->HobLength = sizeof(EFI_HOB_GENERIC_HEADER); + HobEnd->Reserved = 0; + + Hob->Version = EFI_HOB_HANDOFF_TABLE_VERSION; + Hob->BootMode = BOOT_WITH_FULL_CONFIGURATION; + + Hob->EfiMemoryTop = (UINTN)MemoryBegin + MemoryLength; + Hob->EfiMemoryBottom = (UINTN)MemoryBegin; + Hob->EfiFreeMemoryTop = (UINTN)StackBase; + Hob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS)(UINTN)(HobEnd+1); + Hob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS)(UINTN)HobEnd; + + SetHobList (Hob); + + BuildCpuHob (PcdGet8 (PcdPrePiCpuMemorySize), PcdGet8 (PcdPrePiCpuIoSize)); + + Attributes =( + EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_TESTED | + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE + ); + + BuildResourceDescriptorHob (EFI_RESOURCE_SYSTEM_MEMORY, Attributes, (UINTN)MemoryBegin, MemoryLength); + + + BuildStackHob ((UINTN)StackBase, Hob->EfiMemoryTop - (UINTN)StackBase); + + if (FeaturePcdGet (PcdPrePiProduceMemoryTypeInformationHob)) { + // Optional feature that helps prevent EFI memory map fragmentation. + BuildMemoryTypeInformationHob (); + } + +} + + +VOID +EFIAPI +BuildFvHobs ( + IN EFI_PHYSICAL_ADDRESS PhysicalStart, + IN UINT64 NumberOfBytes, + IN EFI_RESOURCE_ATTRIBUTE_TYPE *ResourceAttribute + ) +{ + + EFI_RESOURCE_ATTRIBUTE_TYPE Resource; + + BuildFvHob (PhysicalStart, NumberOfBytes); + + if (ResourceAttribute == NULL) { + Resource = (EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_TESTED | + EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE); + } else { + Resource = *ResourceAttribute; + } + + BuildResourceDescriptorHob (EFI_RESOURCE_FIRMWARE_DEVICE, Resource, PhysicalStart, NumberOfBytes); +} + + + + + +/** + Returns the pointer to the HOB list. + + This function returns the pointer to first HOB in the list. + + @return The pointer to the HOB list. + +**/ +VOID * +EFIAPI +GetHobList ( + VOID + ) +{ + if (gHobList == NULL) { + return (VOID *)(UINTN)PcdGet32 (PcdPrePiHobBase); + } else { + return gHobList; + } +} + + + +/** + Updates the pointer to the HOB list. + + @param HobList Hob list pointer to store + +**/ +EFI_STATUS +EFIAPI +SetHobList ( + IN VOID *HobList + ) +{ + gHobList = HobList; + + // + // If this code is running from ROM this could fail + // + return (gHobList == HobList) ? EFI_SUCCESS: EFI_UNSUPPORTED; +} + + + +VOID * +CreateHob ( + IN UINT16 HobType, + IN UINT16 HobLength + ) +{ + EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob; + EFI_HOB_GENERIC_HEADER *HobEnd; + EFI_PHYSICAL_ADDRESS FreeMemory; + VOID *Hob; + + HandOffHob = GetHobList (); + + HobLength = (UINT16)((HobLength + 0x7) & (~0x7)); + + FreeMemory = HandOffHob->EfiFreeMemoryTop - HandOffHob->EfiFreeMemoryBottom; + + if (FreeMemory < HobLength) { + return NULL; + } + + Hob = (VOID*) (UINTN) HandOffHob->EfiEndOfHobList; + ((EFI_HOB_GENERIC_HEADER*) Hob)->HobType = HobType; + ((EFI_HOB_GENERIC_HEADER*) Hob)->HobLength = HobLength; + ((EFI_HOB_GENERIC_HEADER*) Hob)->Reserved = 0; + + HobEnd = (EFI_HOB_GENERIC_HEADER*) ((UINTN)Hob + HobLength); + HandOffHob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd; + + HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST; + HobEnd->HobLength = sizeof(EFI_HOB_GENERIC_HEADER); + HobEnd->Reserved = 0; + HobEnd++; + HandOffHob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd; + + return Hob; +} + + +/** + Returns the next instance of a HOB type from the starting HOB. + + This function searches the first instance of a HOB type from the starting HOB pointer. + If there does not exist such HOB type from the starting HOB pointer, it will return NULL. + In contrast with macro GET_NEXT_HOB(), this function does not skip the starting HOB pointer + unconditionally: it returns HobStart back if HobStart itself meets the requirement; + caller is required to use GET_NEXT_HOB() if it wishes to skip current HobStart. + If HobStart is NULL, then ASSERT(). + + @param Type The HOB type to return. + @param HobStart The starting HOB pointer to search from. + + @return The next instance of a HOB type from the starting HOB. + +**/ +VOID * +EFIAPI +GetNextHob ( + IN UINT16 Type, + IN CONST VOID *HobStart + ) +{ + EFI_PEI_HOB_POINTERS Hob; + + ASSERT (HobStart != NULL); + + Hob.Raw = (UINT8 *) HobStart; + // + // Parse the HOB list until end of list or matching type is found. + // + while (!END_OF_HOB_LIST (Hob)) { + if (Hob.Header->HobType == Type) { + return Hob.Raw; + } + Hob.Raw = GET_NEXT_HOB (Hob); + } + return NULL; +} + + + +/** + Returns the first instance of a HOB type among the whole HOB list. + + This function searches the first instance of a HOB type among the whole HOB list. + If there does not exist such HOB type in the HOB list, it will return NULL. + + @param Type The HOB type to return. + + @return The next instance of a HOB type from the starting HOB. + +**/ +VOID * +EFIAPI +GetFirstHob ( + IN UINT16 Type + ) +{ + VOID *HobList; + + HobList = GetHobList (); + return GetNextHob (Type, HobList); +} + + +/** + This function searches the first instance of a HOB from the starting HOB pointer. + Such HOB should satisfy two conditions: + its HOB type is EFI_HOB_TYPE_GUID_EXTENSION and its GUID Name equals to the input Guid. + If there does not exist such HOB from the starting HOB pointer, it will return NULL. + Caller is required to apply GET_GUID_HOB_DATA () and GET_GUID_HOB_DATA_SIZE () + to extract the data section and its size info respectively. + In contrast with macro GET_NEXT_HOB(), this function does not skip the starting HOB pointer + unconditionally: it returns HobStart back if HobStart itself meets the requirement; + caller is required to use GET_NEXT_HOB() if it wishes to skip current HobStart. + If Guid is NULL, then ASSERT(). + If HobStart is NULL, then ASSERT(). + + @param Guid The GUID to match with in the HOB list. + @param HobStart A pointer to a Guid. + + @return The next instance of the matched GUID HOB from the starting HOB. + +**/ +VOID * +EFIAPI +GetNextGuidHob ( + IN CONST EFI_GUID *Guid, + IN CONST VOID *HobStart + ){ + EFI_PEI_HOB_POINTERS GuidHob; + + GuidHob.Raw = (UINT8 *) HobStart; + while ((GuidHob.Raw = GetNextHob (EFI_HOB_TYPE_GUID_EXTENSION, GuidHob.Raw)) != NULL) { + if (CompareGuid (Guid, &GuidHob.Guid->Name)) { + break; + } + GuidHob.Raw = GET_NEXT_HOB (GuidHob); + } + return GuidHob.Raw; +} + + +/** + This function searches the first instance of a HOB among the whole HOB list. + Such HOB should satisfy two conditions: + its HOB type is EFI_HOB_TYPE_GUID_EXTENSION and its GUID Name equals to the input Guid. + If there does not exist such HOB from the starting HOB pointer, it will return NULL. + Caller is required to apply GET_GUID_HOB_DATA () and GET_GUID_HOB_DATA_SIZE () + to extract the data section and its size info respectively. + If Guid is NULL, then ASSERT(). + + @param Guid The GUID to match with in the HOB list. + + @return The first instance of the matched GUID HOB among the whole HOB list. + +**/ +VOID * +EFIAPI +GetFirstGuidHob ( + IN CONST EFI_GUID *Guid + ) +{ + VOID *HobList; + + HobList = GetHobList (); + return GetNextGuidHob (Guid, HobList); +} + + +/** + Get the Boot Mode from the HOB list. + + This function returns the system boot mode information from the + PHIT HOB in HOB list. + + @param VOID + + @return The Boot Mode. + +**/ +EFI_BOOT_MODE +EFIAPI +GetBootMode ( + VOID + ) +{ + EFI_PEI_HOB_POINTERS Hob; + + Hob.Raw = GetHobList (); + return Hob.HandoffInformationTable->BootMode; +} + + +/** + Get the Boot Mode from the HOB list. + + This function returns the system boot mode information from the + PHIT HOB in HOB list. + + @param VOID + + @return The Boot Mode. + +**/ +EFI_STATUS +EFIAPI +SetBootMode ( + IN EFI_BOOT_MODE BootMode + ) +{ + EFI_PEI_HOB_POINTERS Hob; + + Hob.Raw = GetHobList (); + Hob.HandoffInformationTable->BootMode = BootMode; + return BootMode; +} + +/** + Builds a HOB for a loaded PE32 module. + + This function builds a HOB for a loaded PE32 module. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If ModuleName is NULL, then ASSERT(). + If there is no additional space for HOB creation, then ASSERT(). + + @param ModuleName The GUID File Name of the module. + @param MemoryAllocationModule The 64 bit physical address of the module. + @param ModuleLength The length of the module in bytes. + @param EntryPoint The 64 bit physical address of the module entry point. + +**/ +VOID +EFIAPI +BuildModuleHob ( + IN CONST EFI_GUID *ModuleName, + IN EFI_PHYSICAL_ADDRESS MemoryAllocationModule, + IN UINT64 ModuleLength, + IN EFI_PHYSICAL_ADDRESS EntryPoint + ) +{ + EFI_HOB_MEMORY_ALLOCATION_MODULE *Hob; + + ASSERT (((MemoryAllocationModule & (EFI_PAGE_SIZE - 1)) == 0) && + ((ModuleLength & (EFI_PAGE_SIZE - 1)) == 0)); + + Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION_MODULE)); + + CopyGuid (&(Hob->MemoryAllocationHeader.Name), &gEfiHobMemoryAllocModuleGuid); + Hob->MemoryAllocationHeader.MemoryBaseAddress = MemoryAllocationModule; + Hob->MemoryAllocationHeader.MemoryLength = ModuleLength; + Hob->MemoryAllocationHeader.MemoryType = EfiBootServicesCode; + + // + // Zero the reserved space to match HOB spec + // + ZeroMem (Hob->MemoryAllocationHeader.Reserved, sizeof (Hob->MemoryAllocationHeader.Reserved)); + + CopyGuid (&Hob->ModuleName, ModuleName); + Hob->EntryPoint = EntryPoint; +} + + +/** + Builds a HOB that describes a chunk of system memory. + + This function builds a HOB that describes a chunk of system memory. + If there is no additional space for HOB creation, then ASSERT(). + + @param ResourceType The type of resource described by this HOB. + @param ResourceAttribute The resource attributes of the memory described by this HOB. + @param PhysicalStart The 64 bit physical address of memory described by this HOB. + @param NumberOfBytes The length of the memory described by this HOB in bytes. + +**/ +VOID +EFIAPI +BuildResourceDescriptorHob ( + IN EFI_RESOURCE_TYPE ResourceType, + IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute, + IN EFI_PHYSICAL_ADDRESS PhysicalStart, + IN UINT64 NumberOfBytes + ) +{ + EFI_HOB_RESOURCE_DESCRIPTOR *Hob; + + Hob = CreateHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, sizeof (EFI_HOB_RESOURCE_DESCRIPTOR)); + + Hob->ResourceType = ResourceType; + Hob->ResourceAttribute = ResourceAttribute; + Hob->PhysicalStart = PhysicalStart; + Hob->ResourceLength = NumberOfBytes; +} + + +/** + Builds a GUID HOB with a certain data length. + + This function builds a customized HOB tagged with a GUID for identification + and returns the start address of GUID HOB data so that caller can fill the customized data. + The HOB Header and Name field is already stripped. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If Guid is NULL, then ASSERT(). + If there is no additional space for HOB creation, then ASSERT(). + If DataLength >= (0x10000 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT(). + + @param Guid The GUID to tag the customized HOB. + @param DataLength The size of the data payload for the GUID HOB. + + @return The start address of GUID HOB data. + +**/ +VOID * +EFIAPI +BuildGuidHob ( + IN CONST EFI_GUID *Guid, + IN UINTN DataLength + ) +{ + EFI_HOB_GUID_TYPE *Hob; + + // + // Make sure that data length is not too long. + // + ASSERT (DataLength <= (0xffff - sizeof (EFI_HOB_GUID_TYPE))); + + Hob = CreateHob (EFI_HOB_TYPE_GUID_EXTENSION, (UINT16) (sizeof (EFI_HOB_GUID_TYPE) + DataLength)); + CopyGuid (&Hob->Name, Guid); + return Hob + 1; +} + + +/** + Copies a data buffer to a newly-built HOB. + + This function builds a customized HOB tagged with a GUID for identification, + copies the input data to the HOB data field and returns the start address of the GUID HOB data. + The HOB Header and Name field is already stripped. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If Guid is NULL, then ASSERT(). + If Data is NULL and DataLength > 0, then ASSERT(). + If there is no additional space for HOB creation, then ASSERT(). + If DataLength >= (0x10000 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT(). + + @param Guid The GUID to tag the customized HOB. + @param Data The data to be copied into the data field of the GUID HOB. + @param DataLength The size of the data payload for the GUID HOB. + + @return The start address of GUID HOB data. + +**/ +VOID * +EFIAPI +BuildGuidDataHob ( + IN CONST EFI_GUID *Guid, + IN VOID *Data, + IN UINTN DataLength + ) +{ + VOID *HobData; + + ASSERT (Data != NULL || DataLength == 0); + + HobData = BuildGuidHob (Guid, DataLength); + + return CopyMem (HobData, Data, DataLength); +} + + +/** + Builds a Firmware Volume HOB. + + This function builds a Firmware Volume HOB. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The base address of the Firmware Volume. + @param Length The size of the Firmware Volume in bytes. + +**/ +VOID +EFIAPI +BuildFvHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + EFI_HOB_FIRMWARE_VOLUME *Hob; + + Hob = CreateHob (EFI_HOB_TYPE_FV, sizeof (EFI_HOB_FIRMWARE_VOLUME)); + + Hob->BaseAddress = BaseAddress; + Hob->Length = Length; +} + + +/** + Builds a EFI_HOB_TYPE_FV2 HOB. + + This function builds a EFI_HOB_TYPE_FV2 HOB. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The base address of the Firmware Volume. + @param Length The size of the Firmware Volume in bytes. + @param FvName The name of the Firmware Volume. + @param FileName The name of the file. + +**/ +VOID +EFIAPI +BuildFv2Hob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN CONST EFI_GUID *FvName, + IN CONST EFI_GUID *FileName + ) +{ + EFI_HOB_FIRMWARE_VOLUME2 *Hob; + + Hob = CreateHob (EFI_HOB_TYPE_FV2, sizeof (EFI_HOB_FIRMWARE_VOLUME2)); + + Hob->BaseAddress = BaseAddress; + Hob->Length = Length; + CopyGuid (&Hob->FvName, FvName); + CopyGuid (&Hob->FileName, FileName); +} + + + +/** + Builds a Capsule Volume HOB. + + This function builds a Capsule Volume HOB. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The base address of the Capsule Volume. + @param Length The size of the Capsule Volume in bytes. + +**/ +VOID +EFIAPI +BuildCvHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + ASSERT (FALSE); +} + + +/** + Builds a HOB for the CPU. + + This function builds a HOB for the CPU. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If there is no additional space for HOB creation, then ASSERT(). + + @param SizeOfMemorySpace The maximum physical memory addressability of the processor. + @param SizeOfIoSpace The maximum physical I/O addressability of the processor. + +**/ +VOID +EFIAPI +BuildCpuHob ( + IN UINT8 SizeOfMemorySpace, + IN UINT8 SizeOfIoSpace + ) +{ + EFI_HOB_CPU *Hob; + + Hob = CreateHob (EFI_HOB_TYPE_CPU, sizeof (EFI_HOB_CPU)); + + Hob->SizeOfMemorySpace = SizeOfMemorySpace; + Hob->SizeOfIoSpace = SizeOfIoSpace; + + // + // Zero the reserved space to match HOB spec + // + ZeroMem (Hob->Reserved, sizeof (Hob->Reserved)); +} + + +/** + Builds a HOB for the Stack. + + This function builds a HOB for the stack. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The 64 bit physical address of the Stack. + @param Length The length of the stack in bytes. + +**/ +VOID +EFIAPI +BuildStackHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + EFI_HOB_MEMORY_ALLOCATION_STACK *Hob; + + ASSERT (((BaseAddress & (EFI_PAGE_SIZE - 1)) == 0) && + ((Length & (EFI_PAGE_SIZE - 1)) == 0)); + + Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION_STACK)); + + CopyGuid (&(Hob->AllocDescriptor.Name), &gEfiHobMemoryAllocStackGuid); + Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress; + Hob->AllocDescriptor.MemoryLength = Length; + Hob->AllocDescriptor.MemoryType = EfiBootServicesData; + + // + // Zero the reserved space to match HOB spec + // + ZeroMem (Hob->AllocDescriptor.Reserved, sizeof (Hob->AllocDescriptor.Reserved)); +} + + +/** + Update the Stack Hob if the stack has been moved + + @param BaseAddress The 64 bit physical address of the Stack. + @param Length The length of the stack in bytes. + +**/ +VOID +UpdateStackHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + EFI_PEI_HOB_POINTERS Hob; + + Hob.Raw = GetHobList (); + while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw)) != NULL) { + if (CompareGuid (&gEfiHobMemoryAllocStackGuid, &(Hob.MemoryAllocationStack->AllocDescriptor.Name))) { + // + // Build a new memory allocation HOB with old stack info with EfiConventionalMemory type + // to be reclaimed by DXE core. + // + BuildMemoryAllocationHob ( + Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress, + Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength, + EfiConventionalMemory + ); + // + // Update the BSP Stack Hob to reflect the new stack info. + // + Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress = BaseAddress; + Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength = Length; + break; + } + Hob.Raw = GET_NEXT_HOB (Hob); + } +} + + + +/** + Builds a HOB for the memory allocation. + + This function builds a HOB for the memory allocation. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The 64 bit physical address of the memory. + @param Length The length of the memory allocation in bytes. + @param MemoryType Type of memory allocated by this HOB. + +**/ +VOID +EFIAPI +BuildMemoryAllocationHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_MEMORY_TYPE MemoryType + ) +{ + EFI_HOB_MEMORY_ALLOCATION *Hob; + + ASSERT (((BaseAddress & (EFI_PAGE_SIZE - 1)) == 0) && + ((Length & (EFI_PAGE_SIZE - 1)) == 0)); + + Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION)); + + ZeroMem (&(Hob->AllocDescriptor.Name), sizeof (EFI_GUID)); + Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress; + Hob->AllocDescriptor.MemoryLength = Length; + Hob->AllocDescriptor.MemoryType = MemoryType; + // + // Zero the reserved space to match HOB spec + // + ZeroMem (Hob->AllocDescriptor.Reserved, sizeof (Hob->AllocDescriptor.Reserved)); +} + + diff --git a/EmbeddedPkg/Library/PrePiLib/Memory.c b/EmbeddedPkg/Library/PrePiLib/Memory.c new file mode 100644 index 0000000000..209c71b42f --- /dev/null +++ b/EmbeddedPkg/Library/PrePiLib/Memory.c @@ -0,0 +1,160 @@ +/** @file + Implementation of the 6 PEI Ffs (FV) APIs in library form. + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + + + +/** + Allocates one or more 4KB pages of type EfiBootServicesData. + + Allocates the number of 4KB pages of MemoryType and returns a pointer to the + allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL + is returned. If there is not enough memory remaining to satisfy the request, then NULL is + returned. + + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocatePages ( + IN UINTN Pages + ) +{ + EFI_PEI_HOB_POINTERS Hob; + EFI_PHYSICAL_ADDRESS Offset; + + Hob.Raw = GetHobList (); + + // Check to see if on 4k boundary + Offset = Hob.HandoffInformationTable->EfiFreeMemoryTop & 0xFFF; + if (Offset != 0) { + // If not aligned, make the allocation aligned. + Hob.HandoffInformationTable->EfiFreeMemoryTop -= Offset; + } + + // + // Verify that there is sufficient memory to satisfy the allocation + // + if (Hob.HandoffInformationTable->EfiFreeMemoryTop - ((Pages * EFI_PAGE_SIZE) + sizeof (EFI_HOB_MEMORY_ALLOCATION)) < Hob.HandoffInformationTable->EfiFreeMemoryBottom) { + return 0; + } else { + // + // Update the PHIT to reflect the memory usage + // + Hob.HandoffInformationTable->EfiFreeMemoryTop -= Pages * EFI_PAGE_SIZE; + + // This routine used to create a memory allocation HOB a la PEI, but that's not + // necessary for us. + + return (VOID *)(UINTN)Hob.HandoffInformationTable->EfiFreeMemoryTop; + } +} + + +/** + Allocates one or more 4KB pages of type EfiBootServicesData at a specified alignment. + + Allocates the number of 4KB pages specified by Pages of type EfiBootServicesData with an + alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is + returned. If there is not enough memory at the specified alignment remaining to satisfy the + request, then NULL is returned. + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateAlignedPages ( + IN UINTN Pages, + IN UINTN Alignment + ) +{ + VOID *Memory; + UINTN AlignmentMask; + + // + // Alignment must be a power of two or zero. + // + ASSERT ((Alignment & (Alignment - 1)) == 0); + + if (Pages == 0) { + return NULL; + } + // + // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow. + // + ASSERT (Pages <= (MAX_ADDRESS - EFI_SIZE_TO_PAGES (Alignment))); + // + // We would rather waste some memory to save PEI code size. + // + Memory = (VOID *)(UINTN)AllocatePages (Pages + EFI_SIZE_TO_PAGES (Alignment)); + if (Alignment == 0) { + AlignmentMask = Alignment; + } else { + AlignmentMask = Alignment - 1; + } + return (VOID *) (UINTN) (((UINTN) Memory + AlignmentMask) & ~AlignmentMask); +} + + + + +/** + Allocates a buffer of type EfiBootServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiBootServicesData and returns a + pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is + returned. If there is not enough memory remaining to satisfy the request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocatePool ( + IN UINTN AllocationSize + ) +{ + EFI_HOB_MEMORY_POOL *Hob; + + Hob = GetHobList (); + + + // + // Verify that there is sufficient memory to satisfy the allocation + // + if (AllocationSize > 0x10000) { + // Please call AllcoatePages for big allocations + return 0; + } else { + + Hob = (EFI_HOB_MEMORY_POOL *)CreateHob (EFI_HOB_TYPE_MEMORY_POOL, (UINT16)(sizeof (EFI_HOB_TYPE_MEMORY_POOL) + AllocationSize)); + return (VOID *)(Hob + 1); + } +} + + + diff --git a/EmbeddedPkg/Library/PrePiLib/PrePi.h b/EmbeddedPkg/Library/PrePiLib/PrePi.h new file mode 100644 index 0000000000..dc3ef48614 --- /dev/null +++ b/EmbeddedPkg/Library/PrePiLib/PrePi.h @@ -0,0 +1,44 @@ +/** @file + Library that helps implement monolithic PEI (i.e. PEI part of SEC) + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _PI_PEI_H_ +#define _PI_PEI_H_ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +#define GET_HOB_TYPE(Hob) ((Hob).Header->HobType) +#define GET_HOB_LENGTH(Hob) ((Hob).Header->HobLength) +#define GET_NEXT_HOB(Hob) ((Hob).Raw + GET_HOB_LENGTH (Hob)) +#define END_OF_HOB_LIST(Hob) (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_END_OF_HOB_LIST) + +// +// Get the data and data size field of GUID +// +#define GET_GUID_HOB_DATA(GuidHob) ((VOID *) (((UINT8 *) &((GuidHob)->Name)) + sizeof (EFI_GUID))) +#define GET_GUID_HOB_DATA_SIZE(GuidHob) (((GuidHob)->Header).HobLength - sizeof (EFI_HOB_GUID_TYPE)) + +#endif diff --git a/EmbeddedPkg/Library/PrePiLib/PrePiLib.c b/EmbeddedPkg/Library/PrePiLib/PrePiLib.c new file mode 100644 index 0000000000..f92be0fea3 --- /dev/null +++ b/EmbeddedPkg/Library/PrePiLib/PrePiLib.c @@ -0,0 +1,231 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +// +// Hack to work in NT32 +// +EFI_STATUS + +EFIAPI + +SecWinNtPeiLoadFile ( + + IN VOID *Pe32Data, + + IN EFI_PHYSICAL_ADDRESS *ImageAddress, + + IN UINT64 *ImageSize, + + IN EFI_PHYSICAL_ADDRESS *EntryPoint + + ); + + +EFI_STATUS +EFIAPI +LoadPeCoffImage ( + IN VOID *PeCoffImage, + OUT EFI_PHYSICAL_ADDRESS *ImageAddress, + OUT UINT64 *ImageSize, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint + ) +{ + RETURN_STATUS Status; + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + VOID *Buffer; + + ZeroMem (&ImageContext, sizeof (ImageContext)); + + ImageContext.Handle = PeCoffImage; + ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory; + + Status = PeCoffLoaderGetImageInfo (&ImageContext); + ASSERT_EFI_ERROR (Status); + + + // + // Allocate Memory for the image + // + Buffer = AllocatePages (EFI_SIZE_TO_PAGES((UINT32)ImageContext.ImageSize)); + ASSERT (Buffer != 0); + + + ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer; + + // + // Load the image to our new buffer + // + Status = PeCoffLoaderLoadImage (&ImageContext); + ASSERT_EFI_ERROR (Status); + + // + // Relocate the image in our new buffer + // + Status = PeCoffLoaderRelocateImage (&ImageContext); + ASSERT_EFI_ERROR (Status); + + + *ImageAddress = ImageContext.ImageAddress; + *ImageSize = ImageContext.ImageSize; + *EntryPoint = ImageContext.EntryPoint; + + // + // Flush not needed for all architectures. We could have a processor specific + // function in this library that does the no-op if needed. + // + InvalidateInstructionCacheRange ((VOID *)(UINTN)*ImageAddress, (UINTN)*ImageSize); + + return Status; +} + + + +typedef +VOID +(EFIAPI *DXE_CORE_ENTRY_POINT) ( + IN VOID *HobStart + ); + +EFI_STATUS +EFIAPI +LoadDxeCoreFromFfsFile ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN UINTN StackSize + ) +{ + EFI_STATUS Status; + VOID *PeCoffImage; + EFI_PHYSICAL_ADDRESS ImageAddress; + UINT64 ImageSize; + EFI_PHYSICAL_ADDRESS EntryPoint; + VOID *BaseOfStack; + VOID *TopOfStack; + VOID *Hob; + EFI_FV_FILE_INFO FvFileInfo; + + + Status = FfsFindSectionData (EFI_SECTION_PE32, FileHandle, &PeCoffImage); + if (EFI_ERROR (Status)) { + return Status; + } + + + Status = LoadPeCoffImage (PeCoffImage, &ImageAddress, &ImageSize, &EntryPoint); +// For NT32 Debug Status = SecWinNtPeiLoadFile (PeCoffImage, &ImageAddress, &ImageSize, &EntryPoint); + ASSERT_EFI_ERROR (Status); + + // + // Extract the DxeCore GUID file name. + // + Status = FfsGetFileInfo (FileHandle, &FvFileInfo); + ASSERT_EFI_ERROR (Status); + + BuildModuleHob (&FvFileInfo.FileName, (EFI_PHYSICAL_ADDRESS)(UINTN)ImageAddress, EFI_SIZE_TO_PAGES ((UINT32) ImageSize) * EFI_PAGE_SIZE, EntryPoint); + + DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading DxeCore at 0x%10p EntryPoint=0x%10p\n", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)EntryPoint)); + + Hob = GetHobList (); + if (StackSize == 0) { + // User the current stack + ((DXE_CORE_ENTRY_POINT)(UINTN)EntryPoint) (Hob); + } else { + + // + // Allocate 128KB for the Stack + // + BaseOfStack = AllocatePages (EFI_SIZE_TO_PAGES (StackSize)); + ASSERT (BaseOfStack != NULL); + + // + // Compute the top of the stack we were allocated. Pre-allocate a UINTN + // for safety. + // + TopOfStack = (VOID *) ((UINTN) BaseOfStack + EFI_SIZE_TO_PAGES (StackSize) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT); + TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT); + + // + // Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore. + // + UpdateStackHob ((EFI_PHYSICAL_ADDRESS)(UINTN) BaseOfStack, StackSize); + + SwitchStack ( + (SWITCH_STACK_ENTRY_POINT)(UINTN)EntryPoint, + Hob, + NULL, + TopOfStack + ); + + } + + // Should never get here as DXE Core does not return + DEBUG ((EFI_D_ERROR, "DxeCore returned\n")); + ASSERT (FALSE); + + return EFI_DEVICE_ERROR; +} + + + +EFI_STATUS +EFIAPI +LoadDxeCoreFromFv ( + IN UINTN *FvInstance, OPTIONAL + IN UINTN StackSize + ) +{ + EFI_STATUS Status; + EFI_PEI_FV_HANDLE VolumeHandle; + EFI_PEI_FILE_HANDLE FileHandle = NULL; + + if (FvInstance != NULL) { + // + // Caller passed in a specific FV to try, so only try that one + // + Status = FfsFindNextVolume (*FvInstance, &VolumeHandle); + if (!EFI_ERROR (Status)) { + Status = FfsFindNextFile (EFI_FV_FILETYPE_DXE_CORE, VolumeHandle, &FileHandle); + } + } else { + Status = FfsAnyFvFindFirstFile (EFI_FV_FILETYPE_DXE_CORE, &VolumeHandle, &FileHandle); + } + + if (!EFI_ERROR (Status)) { + return LoadDxeCoreFromFfsFile (FileHandle, StackSize); + } + + return Status; +} + + +EFI_STATUS +EFIAPI +DecompressFirstFv ( + VOID + ) +{ + EFI_STATUS Status; + EFI_PEI_FV_HANDLE VolumeHandle; + EFI_PEI_FILE_HANDLE FileHandle; + + Status = FfsAnyFvFindFirstFile (EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, &VolumeHandle, &FileHandle); + if (!EFI_ERROR (Status)) { + Status = FfsProcessFvFile (FileHandle); + } + + return Status; +} + + diff --git a/EmbeddedPkg/Library/PrePiLib/PrePiLib.inf b/EmbeddedPkg/Library/PrePiLib/PrePiLib.inf new file mode 100644 index 0000000000..278ee44722 --- /dev/null +++ b/EmbeddedPkg/Library/PrePiLib/PrePiLib.inf @@ -0,0 +1,90 @@ +#%HEADER% +#/** @file +# Component description file for Apple Pre PI Library +# +# LIbrary helps you build a platform that skips PEI and loads DXE Core +# directly. Helps building HOBs, reading data from the FV, and doing +# decompression. +# +# Copyright (c) 2008, Apple, Inc. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PrePiLib + FILE_GUID = 1F3A3278-82EB-4C0D-86F1-5BCDA5846CB2 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = PrePiLib + + +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources.common] + FwVol.c + Hob.c + Memory.c + PrePiLib.c + ReportStatusCode.c + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec # needed to support StatusCodes + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec # needed to support StatusCodes + + +[LibraryClasses] + BaseLib + DebugLib + BaseMemoryLib + UefiDecompressLib + PeCoffLib + CacheMaintenanceLib + PrintLib + SerialPortLib + ExtractGuidedSectionLib + +[Guids] + gEfiHobMemoryAllocModuleGuid + gEfiHobMemoryAllocStackGuid + gEfiStatusCodeSpecificDataGuid + gEfiMemoryTypeInformationGuid + gEfiStatusCodeDataTypeDebugGuid + +[Protocols] + gEfiStatusCodeRuntimeProtocolGuid + + +[FixedPcd.common] + gEmbeddedTokenSpaceGuid.PcdPrePiHobBase + gEmbeddedTokenSpaceGuid.PcdPrePiTempMemorySize + gEmbeddedTokenSpaceGuid.PcdPrePiBfvBaseAddress + gEmbeddedTokenSpaceGuid.PcdPrePiBfvSize + gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize + gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize + + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIReclaimMemory + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIMemoryNVS + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesCode + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesData + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderCode + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderData + +[FeaturePcd] + gEmbeddedTokenSpaceGuid.PcdPrePiProduceMemoryTypeInformationHob diff --git a/EmbeddedPkg/Library/PrePiLib/ReportStatusCode.c b/EmbeddedPkg/Library/PrePiLib/ReportStatusCode.c new file mode 100644 index 0000000000..8833567fe5 --- /dev/null +++ b/EmbeddedPkg/Library/PrePiLib/ReportStatusCode.c @@ -0,0 +1,327 @@ +/** @file + Library that helps implement monolithic PEI + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#define EFI_STATUS_CODE_DATA_MAX_SIZE 200 + +EFI_STATUS +EFIAPI +SerialReportStatusCode ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN CONST EFI_GUID *CallerId, + IN CONST EFI_STATUS_CODE_DATA *Data OPTIONAL + ); + + +EFI_STATUS_CODE_PROTOCOL gStatusCode = { + (EFI_REPORT_STATUS_CODE)SerialReportStatusCode +}; + +/** + Extracts ASSERT() information from a status code structure. + + Converts the status code specified by CodeType, Value, and Data to the ASSERT() + arguments specified by Filename, Description, and LineNumber. If CodeType is + an EFI_ERROR_CODE, and CodeType has a severity of EFI_ERROR_UNRECOVERED, and + Value has an operation mask of EFI_SW_EC_ILLEGAL_SOFTWARE_STATE, extract + Filename, Description, and LineNumber from the optional data area of the + status code buffer specified by Data. The optional data area of Data contains + a Null-terminated ASCII string for the FileName, followed by a Null-terminated + ASCII string for the Description, followed by a 32-bit LineNumber. If the + ASSERT() information could be extracted from Data, then return TRUE. + Otherwise, FALSE is returned. + + If Data is NULL, then ASSERT(). + If Filename is NULL, then ASSERT(). + If Description is NULL, then ASSERT(). + If LineNumber is NULL, then ASSERT(). + + @param CodeType The type of status code being converted. + @param Value The status code value being converted. + @param Data Pointer to status code data buffer. + @param Filename Pointer to the source file name that generated the ASSERT(). + @param Description Pointer to the description of the ASSERT(). + @param LineNumber Pointer to source line number that generated the ASSERT(). + + @retval TRUE The status code specified by CodeType, Value, and Data was + converted ASSERT() arguments specified by Filename, Description, + and LineNumber. + @retval FALSE The status code specified by CodeType, Value, and Data could + not be converted to ASSERT() arguments. + +**/ +BOOLEAN +EFIAPI +ReportStatusCodeExtractAssertInfo ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN CONST EFI_STATUS_CODE_DATA *Data, + OUT CHAR8 **Filename, + OUT CHAR8 **Description, + OUT UINT32 *LineNumber + ) +{ + EFI_DEBUG_ASSERT_DATA *AssertData; + + ASSERT (Data != NULL); + ASSERT (Filename != NULL); + ASSERT (Description != NULL); + ASSERT (LineNumber != NULL); + + if (((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) && + ((CodeType & EFI_STATUS_CODE_SEVERITY_MASK) == EFI_ERROR_UNRECOVERED) && + ((Value & EFI_STATUS_CODE_OPERATION_MASK) == EFI_SW_EC_ILLEGAL_SOFTWARE_STATE)) { + AssertData = (EFI_DEBUG_ASSERT_DATA *)(Data + 1); + *Filename = (CHAR8 *)(AssertData + 1); + *Description = *Filename + AsciiStrLen (*Filename) + 1; + *LineNumber = AssertData->LineNumber; + return TRUE; + } + return FALSE; +} + + +/** + Extracts DEBUG() information from a status code structure. + + Converts the status code specified by Data to the DEBUG() arguments specified + by ErrorLevel, Marker, and Format. If type GUID in Data is + EFI_STATUS_CODE_DATA_TYPE_DEBUG_GUID, then extract ErrorLevel, Marker, and + Format from the optional data area of the status code buffer specified by Data. + The optional data area of Data contains a 32-bit ErrorLevel followed by Marker + which is 12 UINTN parameters, followed by a Null-terminated ASCII string for + the Format. If the DEBUG() information could be extracted from Data, then + return TRUE. Otherwise, FALSE is returned. + + If Data is NULL, then ASSERT(). + If ErrorLevel is NULL, then ASSERT(). + If Marker is NULL, then ASSERT(). + If Format is NULL, then ASSERT(). + + @param Data Pointer to status code data buffer. + @param ErrorLevel Pointer to error level mask for a debug message. + @param Marker Pointer to the variable argument list associated with Format. + @param Format Pointer to a Null-terminated ASCII format string of a + debug message. + + @retval TRUE The status code specified by Data was converted DEBUG() arguments + specified by ErrorLevel, Marker, and Format. + @retval FALSE The status code specified by Data could not be converted to + DEBUG() arguments. + +**/ +BOOLEAN +EFIAPI +ReportStatusCodeExtractDebugInfo ( + IN CONST EFI_STATUS_CODE_DATA *Data, + OUT UINT32 *ErrorLevel, + OUT BASE_LIST *Marker, + OUT CHAR8 **Format + ) +{ + EFI_DEBUG_INFO *DebugInfo; + + ASSERT (Data != NULL); + ASSERT (ErrorLevel != NULL); + ASSERT (Marker != NULL); + ASSERT (Format != NULL); + + // + // If the GUID type is not EFI_STATUS_CODE_DATA_TYPE_DEBUG_GUID then return FALSE + // + if (!CompareGuid (&Data->Type, &gEfiStatusCodeDataTypeDebugGuid)) { + return FALSE; + } + + // + // Retrieve the debug information from the status code record + // + DebugInfo = (EFI_DEBUG_INFO *)(Data + 1); + + *ErrorLevel = DebugInfo->ErrorLevel; + + // + // The first 12 * UINTN bytes of the string are really an + // argument stack to support varargs on the Format string. + // + *Marker = (BASE_LIST) (DebugInfo + 1); + *Format = (CHAR8 *)(((UINT64 *)*Marker) + 12); + + return TRUE; +} + + + + +EFI_STATUS +EFIAPI +SerialReportStatusCode ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN CONST EFI_GUID *CallerId, + IN CONST EFI_STATUS_CODE_DATA *Data OPTIONAL + ) +{ + CHAR8 *Filename; + CHAR8 *Description; + CHAR8 *Format; + CHAR8 Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE]; + UINT32 ErrorLevel; + UINT32 LineNumber; + UINTN CharCount; + BASE_LIST Marker; + EFI_DEBUG_INFO *DebugInfo; + + Buffer[0] = '\0'; + + + if (Data != NULL && + ReportStatusCodeExtractAssertInfo (CodeType, Value, Data, &Filename, &Description, &LineNumber)) { + + // + // Print ASSERT() information into output buffer. + // + CharCount = AsciiSPrint ( + Buffer, + EFI_STATUS_CODE_DATA_MAX_SIZE, + "\n\rASSERT!: %a (%d): %a\n\r", + Filename, + LineNumber, + Description + ); + + + // + // Callout to standard output. + // + SerialPortWrite ((UINT8 *)Buffer, CharCount); + return EFI_SUCCESS; + + } else if (Data != NULL && + ReportStatusCodeExtractDebugInfo (Data, &ErrorLevel, &Marker, &Format)) { + + // + // Print DEBUG() information into output buffer. + // + CharCount = AsciiBSPrint ( + Buffer, + EFI_STATUS_CODE_DATA_MAX_SIZE, + Format, + Marker + ); + + } else if (Data != NULL && + CompareGuid (&Data->Type, &gEfiStatusCodeSpecificDataGuid) && + (CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE) { + + // + // Print specific data into output buffer. + // + DebugInfo = (EFI_DEBUG_INFO *) (Data + 1); + Marker = (BASE_LIST) (DebugInfo + 1); + Format = (CHAR8 *) (((UINT64 *) (DebugInfo + 1)) + 12); + + CharCount = AsciiBSPrint (Buffer, EFI_STATUS_CODE_DATA_MAX_SIZE, Format, Marker); + + } else if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) { + // + // Print ERROR information into output buffer. + // + + CharCount = AsciiSPrint ( + Buffer, + EFI_STATUS_CODE_DATA_MAX_SIZE, + "ERROR: C%x:V%x I%x", + CodeType, + Value, + Instance + ); + + // + // Make sure we don't try to print values that weren't intended to be printed, especially NULL GUID pointers. + // + if (CallerId != NULL) { + CharCount += AsciiSPrint ( + &Buffer[CharCount - 1], + (EFI_STATUS_CODE_DATA_MAX_SIZE - (sizeof (Buffer[0]) * CharCount)), + " %g", + CallerId + ); + } + + if (Data != NULL) { + CharCount += AsciiSPrint ( + &Buffer[CharCount - 1], + (EFI_STATUS_CODE_DATA_MAX_SIZE - (sizeof (Buffer[0]) * CharCount)), + " %x", + Data + ); + + } + + + CharCount += AsciiSPrint ( + &Buffer[CharCount - 1], + (EFI_STATUS_CODE_DATA_MAX_SIZE - (sizeof (Buffer[0]) * CharCount)), + "\n\r" + ); + + } else if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) { + CharCount = AsciiSPrint ( + Buffer, + EFI_STATUS_CODE_DATA_MAX_SIZE, + "PROGRESS CODE: V%x I%x\n\r", + Value, + Instance + ); + } else { + CharCount = AsciiSPrint ( + Buffer, + EFI_STATUS_CODE_DATA_MAX_SIZE, + "Undefined: C%x:V%x I%x\n\r", + CodeType, + Value, + Instance + ); + + } + + SerialPortWrite ((UINT8 *)Buffer, CharCount); + return EFI_SUCCESS; + +} + + +VOID +EFIAPI +AddDxeCoreReportStatusCodeCallback ( + VOID + ) +{ + BuildGuidDataHob (&gEfiStatusCodeRuntimeProtocolGuid, &gStatusCode, sizeof(VOID *)); +} + diff --git a/EmbeddedPkg/Library/SemiHostingDebugLib/DebugLib.c b/EmbeddedPkg/Library/SemiHostingDebugLib/DebugLib.c new file mode 100644 index 0000000000..61e3aac3c2 --- /dev/null +++ b/EmbeddedPkg/Library/SemiHostingDebugLib/DebugLib.c @@ -0,0 +1,258 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +/** @file + UEFI Debug Library that uses PrintLib to send messages to STDERR. + + Copyright (c) 2006 - 2007, Intel Corporation
+ All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include +#include +#include +#include +#include +#include +#include + +// +// Define the maximum debug and assert message length that this library supports +// +#define MAX_DEBUG_MESSAGE_LENGTH 0x100 + +/** + + Prints a debug message to the debug output device if the specified error level is enabled. + + If any bit in ErrorLevel is also set in PcdDebugPrintErrorLevel, then print + the message specified by Format and the associated variable argument list to + the debug output device. + + If Format is NULL, then ASSERT(). + + @param ErrorLevel The error level of the debug message. + @param Format Format string for the debug message to print. + +**/ +VOID +EFIAPI +DebugPrint ( + IN UINTN ErrorLevel, + IN CONST CHAR8 *Format, + ... + ) +{ + CHAR8 AsciiBuffer[MAX_DEBUG_MESSAGE_LENGTH]; + VA_LIST Marker; + + // + // If Format is NULL, then ASSERT(). + // + ASSERT (Format != NULL); + + // + // Check driver debug mask value and global mask + // + if ((ErrorLevel & PcdGet32(PcdDebugPrintErrorLevel)) == 0) { + return; + } + + // + // Convert the DEBUG() message to a Unicode String + // + VA_START (Marker, Format); + AsciiVSPrint (AsciiBuffer, sizeof (AsciiBuffer), Format, Marker); + VA_END (Marker); + + SemihostWriteString (AsciiBuffer); +} + + +/** + + Prints an assert message containing a filename, line number, and description. + This may be followed by a breakpoint or a dead loop. + + Print a message of the form "ASSERT (): \n" + to the debug output device. If DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED bit of + PcdDebugProperyMask is set then CpuBreakpoint() is called. Otherwise, if + DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED bit of PcdDebugProperyMask is set then + CpuDeadLoop() is called. If neither of these bits are set, then this function + returns immediately after the message is printed to the debug output device. + DebugAssert() must actively prevent recusrsion. If DebugAssert() is called while + processing another DebugAssert(), then DebugAssert() must return immediately. + + If FileName is NULL, then a string of "(NULL) Filename" is printed. + + If Description is NULL, then a string of "(NULL) Description" is printed. + + @param FileName Pointer to the name of the source file that generated the assert condition. + @param LineNumber The line number in the source file that generated the assert condition + @param Description Pointer to the description of the assert condition. + +**/ +VOID +EFIAPI +DebugAssert ( + IN CONST CHAR8 *FileName, + IN UINTN LineNumber, + IN CONST CHAR8 *Description + ) +{ + CHAR8 AsciiBuffer[MAX_DEBUG_MESSAGE_LENGTH]; + + // + // Generate the ASSERT() message in Unicode format + // + AsciiSPrint (AsciiBuffer, sizeof (AsciiBuffer), "ASSERT %a(%d): %a\n", FileName, LineNumber, Description); + + SemihostWriteString (AsciiBuffer); + + // + // Generate a Breakpoint, DeadLoop, or NOP based on PCD settings + // + if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED) != 0) { + CpuBreakpoint (); + } else if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED) != 0) { + CpuDeadLoop (); + } +} + + +/** + + Fills a target buffer with PcdDebugClearMemoryValue, and returns the target buffer. + + This function fills Length bytes of Buffer with the value specified by + PcdDebugClearMemoryValue, and returns Buffer. + + If Buffer is NULL, then ASSERT(). + + If Length is greater than (MAX_ADDRESS ? Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to fill with PcdDebugClearMemoryValue. + @param Length Number of bytes in Buffer to fill with zeros PcdDebugClearMemoryValue. + + @return Buffer + +**/ +VOID * +EFIAPI +DebugClearMemory ( + OUT VOID *Buffer, + IN UINTN Length + ) +{ + // + // If Buffer is NULL, then ASSERT(). + // + ASSERT (Buffer != NULL); + + // + // SetMem() checks for the the ASSERT() condition on Length and returns Buffer + // + return SetMem (Buffer, Length, PcdGet8(PcdDebugClearMemoryValue)); +} + + +/** + + Returns TRUE if ASSERT() macros are enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugAssertEnabled ( + VOID + ) +{ + return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED) != 0); +} + + +/** + + Returns TRUE if DEBUG()macros are enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugPrintEnabled ( + VOID + ) +{ + return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_PRINT_ENABLED) != 0); +} + + +/** + + Returns TRUE if DEBUG_CODE()macros are enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugCodeEnabled ( + VOID + ) +{ + return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_CODE_ENABLED) != 0); +} + + +/** + + Returns TRUE if DEBUG_CLEAR_MEMORY()macro is enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_CLEAR_MEMORY_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugClearMemoryEnabled ( + VOID + ) +{ + return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED) != 0); +} diff --git a/EmbeddedPkg/Library/SemiHostingDebugLib/SemiHostingDebugLib.inf b/EmbeddedPkg/Library/SemiHostingDebugLib/SemiHostingDebugLib.inf new file mode 100644 index 0000000000..683f03f2f3 --- /dev/null +++ b/EmbeddedPkg/Library/SemiHostingDebugLib/SemiHostingDebugLib.inf @@ -0,0 +1,46 @@ +#%HEADER% +#/** @file +# Debug Library for UEFI drivers +# +# Library to abstract Framework extensions that conflict with UEFI 2.0 Specification +# Copyright (c) 2007, Intel Corporation. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SemiHostingDebugLib + FILE_GUID = 2A8D3FC4-8DB1-4D27-A3F3-780AF03CF848 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = DebugLib|BASE SEC DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER + + +[Sources.common] + DebugLib.c + + +[Packages] + MdePkg/MdePkg.dec + ArmPkg/ArmPkg.dec + +[LibraryClasses] + BaseMemoryLib + BaseLib + PcdLib + PrintLib + SemihostLib + +[Pcd.common] + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel + gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask + diff --git a/EmbeddedPkg/Library/SemiHostingSerialPortLib/SemiHostingSerialPortLib.inf b/EmbeddedPkg/Library/SemiHostingSerialPortLib/SemiHostingSerialPortLib.inf new file mode 100644 index 0000000000..c0a540342a --- /dev/null +++ b/EmbeddedPkg/Library/SemiHostingSerialPortLib/SemiHostingSerialPortLib.inf @@ -0,0 +1,35 @@ +#%HEADER% +#/** @file +# Semihosting serail port lib +# +# Copyright (c) 2008, Apple Inc. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SemiHostingSerialPortLib + FILE_GUID = E9FB2D1E-05D9-421C-8C35-6100BB0093B7 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = SerialPortLib + + +[Sources.common] + SerialPortLib.c + + +[Packages] + MdePkg/MdePkg.dec + ArmPkg/ArmPkg.dec + +[LibraryClasses] + SemihostLib diff --git a/EmbeddedPkg/Library/SemiHostingSerialPortLib/SerialPortLib.c b/EmbeddedPkg/Library/SemiHostingSerialPortLib/SerialPortLib.c new file mode 100644 index 0000000000..cadeb73731 --- /dev/null +++ b/EmbeddedPkg/Library/SemiHostingSerialPortLib/SerialPortLib.c @@ -0,0 +1,145 @@ +/** @file + Serial I/O Port library functions with no library constructor/destructor + + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include + + +/* + + Programmed hardware of Serial port. + + @return Always return EFI_UNSUPPORTED. + +**/ +RETURN_STATUS +EFIAPI +SerialPortInitialize ( + VOID + ) +{ + if (SemihostConnectionSupported ()) { + return RETURN_SUCCESS; + } else { + return RETURN_UNSUPPORTED; + } +} + +/** + Write data to serial device. + + @param Buffer Point of data buffer which need to be writed. + @param NumberOfBytes Number of output bytes which are cached in Buffer. + + @retval 0 Write data failed. + @retval !0 Actual number of bytes writed to serial device. + +**/ + +#define PRINT_BUFFER_SIZE 512 +#define PRINT_BUFFER_THRESHOLD (PRINT_BUFFER_SIZE - 4) + +UINTN +EFIAPI +SerialPortWrite ( + IN UINT8 *Buffer, + IN UINTN NumberOfBytes +) +{ + UINT8 PrintBuffer[PRINT_BUFFER_SIZE]; + UINTN SourceIndex = 0; + UINTN DestinationIndex = 0; + UINT8 CurrentCharacter; + + while (SourceIndex < NumberOfBytes) + { + CurrentCharacter = Buffer[SourceIndex++]; + + switch (CurrentCharacter) + { + case '\r': + continue; + + case '\n': + PrintBuffer[DestinationIndex++] = ' '; + // fall through + + default: + PrintBuffer[DestinationIndex++] = CurrentCharacter; + break; + } + + if (DestinationIndex > PRINT_BUFFER_THRESHOLD) + { + PrintBuffer[DestinationIndex] = '\0'; + SemihostWriteString ((CHAR8 *) PrintBuffer); + + DestinationIndex = 0; + } + } + + if (DestinationIndex > 0) + { + PrintBuffer[DestinationIndex] = '\0'; + SemihostWriteString ((CHAR8 *) PrintBuffer); + } + + return 0; +} + + +/** + Read data from serial device and save the datas in buffer. + + @param Buffer Point of data buffer which need to be writed. + @param NumberOfBytes Number of output bytes which are cached in Buffer. + + @retval 0 Read data failed. + @retval !0 Aactual number of bytes read from serial device. + +**/ +UINTN +EFIAPI +SerialPortRead ( + OUT UINT8 *Buffer, + IN UINTN NumberOfBytes +) +{ + *Buffer = SemihostReadCharacter (); + return 1; +} + + + +/** + Check to see if any data is avaiable to be read from the debug device. + + @retval TRUE At least one byte of data is avaiable to be read + @retval FALS No data is avaiable to be read + +**/ +BOOLEAN +EFIAPI +SerialPortPoll ( + VOID + ) +{ + // Since SemiHosting read character is blocking always say we have a char ready? + return SemihostConnectionSupported (); +} + diff --git a/EmbeddedPkg/Library/TemplateRealTimeClockLib/RealTimeClockLib.c b/EmbeddedPkg/Library/TemplateRealTimeClockLib/RealTimeClockLib.c new file mode 100644 index 0000000000..6a5acad376 --- /dev/null +++ b/EmbeddedPkg/Library/TemplateRealTimeClockLib/RealTimeClockLib.c @@ -0,0 +1,175 @@ +/** @file + Implement EFI RealTimeClock runtime services via RTC Lib. + + Currently this driver does not support runtime virtual calling. + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include + + +/** + Returns the current time and date information, and the time-keeping capabilities + of the hardware platform. + + @param Time A pointer to storage to receive a snapshot of the current time. + @param Capabilities An optional pointer to a buffer to receive the real time clock + device's capabilities. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER Time is NULL. + @retval EFI_DEVICE_ERROR The time could not be retrieved due to hardware error. + +**/ +EFI_STATUS +EFIAPI +LibGetTime ( + OUT EFI_TIME *Time, + OUT EFI_TIME_CAPABILITIES *Capabilities + ) +{ + // + // Fill in Time and Capabilities via data from you RTC + // + return EFI_DEVICE_ERROR; +} + + +/** + Sets the current local time and date information. + + @param Time A pointer to the current time. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER A time field is out of range. + @retval EFI_DEVICE_ERROR The time could not be set due due to hardware error. + +**/ +EFI_STATUS +EFIAPI +LibSetTime ( + IN EFI_TIME *Time + ) +{ + // + // Use Time, to set the time in your RTC hardware + // + return EFI_DEVICE_ERROR; +} + + +/** + Returns the current wakeup alarm clock setting. + + @param Enabled Indicates if the alarm is currently enabled or disabled. + @param Pending Indicates if the alarm signal is pending and requires acknowledgement. + @param Time The current alarm setting. + + @retval EFI_SUCCESS The alarm settings were returned. + @retval EFI_INVALID_PARAMETER Any parameter is NULL. + @retval EFI_DEVICE_ERROR The wakeup time could not be retrieved due to a hardware error. + +**/ +EFI_STATUS +EFIAPI +LibGetWakeupTime ( + OUT BOOLEAN *Enabled, + OUT BOOLEAN *Pending, + OUT EFI_TIME *Time + ) +{ + // Not a required feature + return EFI_UNSUPPORTED; +} + + +/** + Sets the system wakeup alarm clock time. + + @param Enabled Enable or disable the wakeup alarm. + @param Time If Enable is TRUE, the time to set the wakeup alarm for. + + @retval EFI_SUCCESS If Enable is TRUE, then the wakeup alarm was enabled. If + Enable is FALSE, then the wakeup alarm was disabled. + @retval EFI_INVALID_PARAMETER A time field is out of range. + @retval EFI_DEVICE_ERROR The wakeup time could not be set due to a hardware error. + @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform. + +**/ +EFI_STATUS +EFIAPI +LibSetWakeupTime ( + IN BOOLEAN Enabled, + OUT EFI_TIME *Time + ) +{ + // Not a required feature + return EFI_UNSUPPORTED; +} + + + +/** + This is the declaration of an EFI image entry point. This can be the entry point to an application + written to this specification, an EFI boot service driver, or an EFI runtime driver. + + @param ImageHandle Handle that identifies the loaded image. + @param SystemTable System Table for this image. + + @retval EFI_SUCCESS The operation completed successfully. + +**/ +EFI_STATUS +EFIAPI +LibRtcInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + // + // Do some initialization if reqruied to turn on the RTC + // + return EFI_SUCCESS; +} + + +/** + Fixup internal data so that EFI can be call in virtual mode. + Call the passed in Child Notify event and convert any pointers in + lib to virtual mode. + + @param[in] Event The Event that is being processed + @param[in] Context Event Context +**/ +VOID +EFIAPI +LibRtcVirtualNotifyEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + // + // Only needed if you are going to support the OS calling RTC functions in virtual mode. + // You will need to call EfiConvertPointer (). To convert any stored physical addresses + // to virtual address. After the OS transistions to calling in virtual mode, all future + // runtime calls will be made in virtual mode. + // + return; +} + + + diff --git a/EmbeddedPkg/Library/TemplateRealTimeClockLib/TemplateRealTimeClockLib.inf b/EmbeddedPkg/Library/TemplateRealTimeClockLib/TemplateRealTimeClockLib.inf new file mode 100644 index 0000000000..b9f39dd380 --- /dev/null +++ b/EmbeddedPkg/Library/TemplateRealTimeClockLib/TemplateRealTimeClockLib.inf @@ -0,0 +1,38 @@ +#%HEADER% +#/** @file +# Memory Status Code Library for UEFI drivers +# +# Lib to provide memory journal status code reporting Routines +# Copyright (c) 2006, Intel Corporation. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TemplateRealTimeClockLib + FILE_GUID = B661E02D-A90B-42AB-A5F9-CF841AAA43D9 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = RealTimeClockLib + + +[Sources.common] + RealTimeClockLib.c + + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + +[LibraryClasses] + IoLib + DebugLib + \ No newline at end of file diff --git a/EmbeddedPkg/Library/TemplateResetSystemLib/ResetSystemLib.c b/EmbeddedPkg/Library/TemplateResetSystemLib/ResetSystemLib.c new file mode 100644 index 0000000000..fe02f9863f --- /dev/null +++ b/EmbeddedPkg/Library/TemplateResetSystemLib/ResetSystemLib.c @@ -0,0 +1,103 @@ +/** @file + Template library implementation to support ResetSystem Runtime call. + + Fill in the templates with what ever makes you system reset. + + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include + +#include +#include +#include + + +/** + Resets the entire platform. + + @param ResetType The type of reset to perform. + @param ResetStatus The status code for the reset. + @param DataSize The size, in bytes, of WatchdogData. + @param ResetData For a ResetType of EfiResetCold, EfiResetWarm, or + EfiResetShutdown the data buffer starts with a Null-terminated + Unicode string, optionally followed by additional binary data. + +**/ +EFI_STATUS +EFIAPI +LibResetSystem ( + IN EFI_RESET_TYPE ResetType, + IN EFI_STATUS ResetStatus, + IN UINTN DataSize, + IN CHAR16 *ResetData OPTIONAL + ) +{ + UINTN Address; + UINT8 Data; + + + switch (ResetType) { + case EfiResetCold: + // system power cycle + + // Example using IoLib functions to do IO. + Address = 0x12345678; + Data = MmioRead8 (Address); + MmioWrite8 (Address, Data | 0x01); + + // Note this is a bad example asa MmioOr8 (Address, 0x01) does the same thing + break; + + case EfiResetWarm: + // not a full power cycle, maybe memory stays around. + // if not support do the same thing as EfiResetCold. + break; + + case EfiResetShutdown: + // turn off the system. + // if not support do the same thing as EfiResetCold. + break; + + default: + return EFI_INVALID_PARAMETER; + } + + // + // If we reset, we would not have returned... + // + return EFI_DEVICE_ERROR; +} + + + +/** + Initialize any infrastructure required for LibResetSystem () to function. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +LibInitializeResetSystem ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EFI_SUCCESS; +} + diff --git a/EmbeddedPkg/Library/TemplateResetSystemLib/TemplateResetSystemLib.inf b/EmbeddedPkg/Library/TemplateResetSystemLib/TemplateResetSystemLib.inf new file mode 100644 index 0000000000..4b6fa5bb1a --- /dev/null +++ b/EmbeddedPkg/Library/TemplateResetSystemLib/TemplateResetSystemLib.inf @@ -0,0 +1,36 @@ +#%HEADER% +#/** @file +# Memory Status Code Library for UEFI drivers +# +# Lib to provide memory journal status code reporting Routines +# Copyright (c) 2006, Intel Corporation. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TemplateResetSystemLib + FILE_GUID = 40BAFDE5-4CC8-4FBE-A8BA-071890076E50 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = EfiResetSystemLib + + +[Sources.common] + ResetSystemLib.c + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + +[LibraryClasses] + IoLib + DebugLib \ No newline at end of file diff --git a/EmbeddedPkg/Library/TemplateSerialPortLib/TemplateSerialPortLib.c b/EmbeddedPkg/Library/TemplateSerialPortLib/TemplateSerialPortLib.c new file mode 100644 index 0000000000..98087f9dc0 --- /dev/null +++ b/EmbeddedPkg/Library/TemplateSerialPortLib/TemplateSerialPortLib.c @@ -0,0 +1,99 @@ +/** @file + Serial I/O Port library functions with no library constructor/destructor + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + + +#include + +/* + + Programmed hardware of Serial port. + + @return Always return EFI_UNSUPPORTED. + +**/ +RETURN_STATUS +EFIAPI +SerialPortInitialize ( + VOID + ) +{ + return RETURN_UNSUPPORTED; +} + +/** + Write data to serial device. + + @param Buffer Point of data buffer which need to be writed. + @param NumberOfBytes Number of output bytes which are cached in Buffer. + + @retval 0 Write data failed. + @retval !0 Actual number of bytes writed to serial device. + +**/ +UINTN +EFIAPI +SerialPortWrite ( + IN UINT8 *Buffer, + IN UINTN NumberOfBytes +) +{ + return 0; +} + + +/** + Read data from serial device and save the datas in buffer. + + @param Buffer Point of data buffer which need to be writed. + @param NumberOfBytes Number of output bytes which are cached in Buffer. + + @retval 0 Read data failed. + @retval !0 Aactual number of bytes read from serial device. + +**/ +UINTN +EFIAPI +SerialPortRead ( + OUT UINT8 *Buffer, + IN UINTN NumberOfBytes +) +{ + return 0; +} + + + +/** + Poll the serial device to see if there is any data waiting. + + If there is data waiting to be read from the serial port, then return + TRUE. If there is no data waiting to be read from the serial port, then + return FALSE. + + @retval TRUE Data is waiting to be read. + @retval FALSE There is no data waiting to be read. + +**/ +BOOLEAN +EFIAPI +SerialPortPoll ( + VOID + ) +{ + return 0; +} + diff --git a/EmbeddedPkg/Library/TemplateSerialPortLib/TemplateSerialPortLib.inf b/EmbeddedPkg/Library/TemplateSerialPortLib/TemplateSerialPortLib.inf new file mode 100644 index 0000000000..e2a994b63e --- /dev/null +++ b/EmbeddedPkg/Library/TemplateSerialPortLib/TemplateSerialPortLib.inf @@ -0,0 +1,37 @@ +#%HEADER% +#/** @file +# Memory Status Code Library for UEFI drivers +# +# Lib to provide memory journal status code reporting Routines +# Copyright (c) 2006, Intel Corporation. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TemplateSerialPortLib + FILE_GUID = A9133571-AD4B-4457-94A8-A9CC2CE7574F + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + LIBRARY_CLASS = SerialPortLib + + +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources.common] + TemplateSerialPortLib.c + + +[Packages] + MdePkg/MdePkg.dec + diff --git a/EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClock.c b/EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClock.c new file mode 100644 index 0000000000..b93626a6fb --- /dev/null +++ b/EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClock.c @@ -0,0 +1,158 @@ +/** @file + Implement EFI RealTimeClock runtime services via RTC Lib. + + Currently this driver does not support runtime virtual calling. + + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include + +EFI_HANDLE mHandle = NULL; + + + +/** + Returns the current time and date information, and the time-keeping capabilities + of the hardware platform. + + @param Time A pointer to storage to receive a snapshot of the current time. + @param Capabilities An optional pointer to a buffer to receive the real time clock + device's capabilities. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER Time is NULL. + @retval EFI_DEVICE_ERROR The time could not be retrieved due to hardware error. + +**/ +EFI_STATUS +EFIAPI +GetTime ( + OUT EFI_TIME *Time, + OUT EFI_TIME_CAPABILITIES *Capabilities + ) +{ + return LibGetTime (Time, Capabilities); +} + + + +/** + Sets the current local time and date information. + + @param Time A pointer to the current time. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER A time field is out of range. + @retval EFI_DEVICE_ERROR The time could not be set due due to hardware error. + +**/ +EFI_STATUS +EFIAPI +SetTime ( + IN EFI_TIME *Time + ) +{ + return LibSetTime (Time); +} + + +/** + Returns the current wakeup alarm clock setting. + + @param Enabled Indicates if the alarm is currently enabled or disabled. + @param Pending Indicates if the alarm signal is pending and requires acknowledgement. + @param Time The current alarm setting. + + @retval EFI_SUCCESS The alarm settings were returned. + @retval EFI_INVALID_PARAMETER Any parameter is NULL. + @retval EFI_DEVICE_ERROR The wakeup time could not be retrieved due to a hardware error. + +**/ +EFI_STATUS +EFIAPI +GetWakeupTime ( + OUT BOOLEAN *Enabled, + OUT BOOLEAN *Pending, + OUT EFI_TIME *Time + ) +{ + return LibGetWakeupTime (Enabled, Pending, Time); +} + + +/** + Sets the system wakeup alarm clock time. + + @param Enabled Enable or disable the wakeup alarm. + @param Time If Enable is TRUE, the time to set the wakeup alarm for. + + @retval EFI_SUCCESS If Enable is TRUE, then the wakeup alarm was enabled. If + Enable is FALSE, then the wakeup alarm was disabled. + @retval EFI_INVALID_PARAMETER A time field is out of range. + @retval EFI_DEVICE_ERROR The wakeup time could not be set due to a hardware error. + @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform. + +**/ +EFI_STATUS +EFIAPI +SetWakeupTime ( + IN BOOLEAN Enabled, + OUT EFI_TIME *Time + ) +{ + return LibSetWakeupTime (Enabled, Time); +} + + + +/** + This is the declaration of an EFI image entry point. This can be the entry point to an application + written to this specification, an EFI boot service driver, or an EFI runtime driver. + + @param ImageHandle Handle that identifies the loaded image. + @param SystemTable System Table for this image. + + @retval EFI_SUCCESS The operation completed successfully. + +**/ +EFI_STATUS +EFIAPI +InitializeRealTimeClock ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + LibRtcInitialize (ImageHandle, SystemTable); + + SystemTable->RuntimeServices->GetTime = GetTime; + SystemTable->RuntimeServices->SetTime = SetTime; + SystemTable->RuntimeServices->GetWakeupTime = GetWakeupTime; + SystemTable->RuntimeServices->SetWakeupTime = SetWakeupTime; + + Status = gBS->InstallMultipleProtocolInterfaces ( + &mHandle, + &gEfiRealTimeClockArchProtocolGuid, + NULL, + NULL + ); + + return Status; +} + diff --git a/EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf b/EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf new file mode 100644 index 0000000000..f0afceeb65 --- /dev/null +++ b/EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf @@ -0,0 +1,45 @@ +#%HEADER% +#/** @file +# NT Emulation Reset Architectural Protocol Driver as defined in TIANO +# +# This Reset module simulates system reset by process exit on NT. +# Copyright (c) 2006 - 2007, Intel Corporation +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = RealTimeClock + FILE_GUID = B336F62D-4135-4A55-AE4E-4971BBF0885D + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = InitializeRealTimeClock + +[Sources.common] + RealTimeClock.c + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + +[LibraryClasses] + UefiBootServicesTableLib + UefiDriverEntryPoint + DebugLib + RealTimeClockLib + +[Protocols] + gEfiRealTimeClockArchProtocolGuid + +[Depex] + TRUE + diff --git a/EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf b/EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf new file mode 100644 index 0000000000..956aab709a --- /dev/null +++ b/EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf @@ -0,0 +1,51 @@ +#%HEADER% +#/** @file +# NT Emulation Reset Architectural Protocol Driver as defined in TIANO +# +# This Reset module simulates system reset by process exit on NT. +# Copyright (c) 2006 - 2007, Intel Corporation +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = Reset + FILE_GUID = 16036A73-E8EF-46D0-953C-9B8E96527D13 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = InitializeReset + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 +# + +[Sources.common] + reset.c + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + +[LibraryClasses] + UefiBootServicesTableLib + UefiDriverEntryPoint + DebugLib + EfiResetSystemLib + +[Protocols] + gEfiResetArchProtocolGuid # PROTOCOL ALWAYS_PRODUCED + +[Depex] + TRUE + diff --git a/EmbeddedPkg/ResetRuntimeDxe/reset.c b/EmbeddedPkg/ResetRuntimeDxe/reset.c new file mode 100644 index 0000000000..3327b8d1ec --- /dev/null +++ b/EmbeddedPkg/ResetRuntimeDxe/reset.c @@ -0,0 +1,74 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include +#include + + +/** + Resets the entire platform. + + @param ResetType The type of reset to perform. + @param ResetStatus The status code for the reset. + @param DataSize The size, in bytes, of WatchdogData. + @param ResetData For a ResetType of EfiResetCold, EfiResetWarm, or + EfiResetShutdown the data buffer starts with a Null-terminated + Unicode string, optionally followed by additional binary data. + +**/ +VOID +EFIAPI +ResetSystemViaLib ( + IN EFI_RESET_TYPE ResetType, + IN EFI_STATUS ResetStatus, + IN UINTN DataSize, + IN VOID *ResetData OPTIONAL + ) +{ + LibResetSystem (ResetType, ResetStatus, DataSize, ResetData); + return; +} + + + +EFI_STATUS +EFIAPI +InitializeReset ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + + LibInitializeResetSystem (ImageHandle, SystemTable); + + SystemTable->RuntimeServices->ResetSystem = ResetSystemViaLib; + + Handle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &Handle, + &gEfiResetArchProtocolGuid, + NULL, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + diff --git a/EmbeddedPkg/SerialDxe/SerialDxe.inf b/EmbeddedPkg/SerialDxe/SerialDxe.inf new file mode 100644 index 0000000000..29c0aa8c2a --- /dev/null +++ b/EmbeddedPkg/SerialDxe/SerialDxe.inf @@ -0,0 +1,54 @@ +#%HEADER% +#/** @file +# +# Component discription file for Bds module +# +# Copyright (c) 2008, Intel Corporation.
+# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SerialDxe + FILE_GUID = D3987D4B-971A-435F-8CAF-4967EB627241 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = SerialDxeInitialize + + +[Sources.common] + SerialIo.c + + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + ReportStatusCodeLib + MemoryAllocationLib + UefiLib + UefiBootServicesTableLib + BaseMemoryLib + DebugLib + UefiDriverEntryPoint + SerialPortLib + +[Guids] + + +[Protocols] + gEfiSerialIoProtocolGuid + gEfiDevicePathProtocolGuid + + +[Depex] + TRUE diff --git a/EmbeddedPkg/SerialDxe/SerialIo.c b/EmbeddedPkg/SerialDxe/SerialIo.c new file mode 100644 index 0000000000..aa9653bcf3 --- /dev/null +++ b/EmbeddedPkg/SerialDxe/SerialIo.c @@ -0,0 +1,258 @@ +/** @file + Serial IO Abstraction for GDB stub. This allows an EFI consoles that shows up on the system + running GDB. One consle for error information and another console for user input/output. + + Basic packet format is $packet-data#checksum. So every comand has 4 bytes of overhead: $, + #, 0, 0. The 0 and 0 are the ascii characters for the checksum. + + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include + +#include + +/** + Reset the serial device. + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS The device was reset. + @retval EFI_DEVICE_ERROR The serial device could not be reset. + +**/ +EFI_STATUS +EFIAPI +SerialReset ( + IN EFI_SERIAL_IO_PROTOCOL *This + ) +{ + SerialPortInitialize (); + return EFI_SUCCESS; +} + + +/** + Sets the baud rate, receive FIFO depth, transmit/receice time out, parity, + data buts, and stop bits on a serial device. + + @param This Protocol instance pointer. + @param BaudRate The requested baud rate. A BaudRate value of 0 will use the the + device's default interface speed. + @param ReveiveFifoDepth The requested depth of the FIFO on the receive side of the + serial interface. A ReceiveFifoDepth value of 0 will use + the device's dfault FIFO depth. + @param Timeout The requested time out for a single character in microseconds. + This timeout applies to both the transmit and receive side of the + interface. A Timeout value of 0 will use the device's default time + out value. + @param Parity The type of parity to use on this serial device. A Parity value of + DefaultParity will use the device's default parity value. + @param DataBits The number of data bits to use on the serial device. A DataBits + vaule of 0 will use the device's default data bit setting. + @param StopBits The number of stop bits to use on this serial device. A StopBits + value of DefaultStopBits will use the device's default number of + stop bits. + + @retval EFI_SUCCESS The device was reset. + @retval EFI_DEVICE_ERROR The serial device could not be reset. + +**/ +EFI_STATUS +EFIAPI +SerialSetAttributes ( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN UINT64 BaudRate, + IN UINT32 ReceiveFifoDepth, + IN UINT32 Timeout, + IN EFI_PARITY_TYPE Parity, + IN UINT8 DataBits, + IN EFI_STOP_BITS_TYPE StopBits + ) +{ + return EFI_UNSUPPORTED; +} + + +/** + Set the control bits on a serial device + + @param This Protocol instance pointer. + @param Control Set the bits of Control that are settable. + + @retval EFI_SUCCESS The new control bits were set on the serial device. + @retval EFI_UNSUPPORTED The serial device does not support this operation. + @retval EFI_DEVICE_ERROR The serial device is not functioning correctly. + +**/ +EFI_STATUS +EFIAPI +SerialSetControl ( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN UINT32 Control + ) +{ + return EFI_UNSUPPORTED; +} + + +/** + Retrieves the status of thecontrol bits on a serial device + + @param This Protocol instance pointer. + @param Control A pointer to return the current Control signals from the serial device. + + @retval EFI_SUCCESS The control bits were read from the serial device. + @retval EFI_DEVICE_ERROR The serial device is not functioning correctly. + +**/ +EFI_STATUS +EFIAPI +SerialGetControl ( + IN EFI_SERIAL_IO_PROTOCOL *This, + OUT UINT32 *Control + ) +{ + if (SerialPortPoll ()) { + // If a character is pending don't set EFI_SERIAL_INPUT_BUFFER_EMPTY + *Control = EFI_SERIAL_OUTPUT_BUFFER_EMPTY; + } else { + *Control = EFI_SERIAL_INPUT_BUFFER_EMPTY | EFI_SERIAL_OUTPUT_BUFFER_EMPTY; + } + return EFI_SUCCESS; +} + + +/** + Writes data to a serial device. + + @param This Protocol instance pointer. + @param BufferSize On input, the size of the Buffer. On output, the amount of + data actually written. + @param Buffer The buffer of data to write + + @retval EFI_SUCCESS The data was written. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_TIMEOUT The data write was stopped due to a timeout. + +**/ +EFI_STATUS +EFIAPI +SerialWrite ( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +{ + UINTN Count; + + Count = SerialPortWrite (Buffer, *BufferSize); + *BufferSize = Count; + return (Count == 0) ? EFI_DEVICE_ERROR : EFI_SUCCESS; +} + +/** + Writes data to a serial device. + + @param This Protocol instance pointer. + @param BufferSize On input, the size of the Buffer. On output, the amount of + data returned in Buffer. + @param Buffer The buffer to return the data into. + + @retval EFI_SUCCESS The data was read. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_TIMEOUT The data write was stopped due to a timeout. + +**/ + +EFI_STATUS +EFIAPI +SerialRead ( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + UINTN Count; + + Count = SerialPortWrite (Buffer, *BufferSize); + *BufferSize = Count; + return (Count == 0) ? EFI_DEVICE_ERROR : EFI_SUCCESS; +} + + +EFI_HANDLE gHandle = NULL; + +// +// Template used to initailize the GDB Serial IO protocols +// +EFI_SERIAL_IO_MODE gSerialIoMode = { + 0, // ControlMask + 0, // Timeout + 0, // BaudRate + 1, // RceiveFifoDepth + 0, // DataBits + 0, // Parity + 0 // StopBits +}; + + +EFI_SERIAL_IO_PROTOCOL gSerialIoTemplate = { + SERIAL_IO_INTERFACE_REVISION, + SerialReset, + SerialSetAttributes, + SerialSetControl, + SerialGetControl, + SerialWrite, + SerialRead, + &gSerialIoMode +}; + + +/** + Initialize the state information for the Serial Io Protocol + + @param ImageHandle of the loaded driver + @param SystemTable Pointer to the System Table + + @retval EFI_SUCCESS Protocol registered + @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure + @retval EFI_DEVICE_ERROR Hardware problems + +**/ +EFI_STATUS +EFIAPI +SerialDxeInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + + // Make a new handle with Serial IO protocol and its device path on it. + Status = gBS->InstallMultipleProtocolInterfaces ( + &gHandle, + &gEfiSerialIoProtocolGuid, &gSerialIoTemplate, + &gEfiDevicePathProtocolGuid, NULL, // BugBug: Need a device path + NULL + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + diff --git a/EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOut.c b/EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOut.c new file mode 100644 index 0000000000..f491de6e95 --- /dev/null +++ b/EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOut.c @@ -0,0 +1,671 @@ +/** @file + Simple Console that sits on a SerialLib. + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +/* + Symbols used in table below +=========================== + ESC = 0x1B + CSI = 0x9B + DEL = 0x7f + ^ = CTRL + ++=========+======+===========+==========+==========+ +| | EFI | UEFI 2.0 | | | +| | Scan | | VT100+ | | +| KEY | Code | PC ANSI | VTUTF8 | VT100 | ++=========+======+===========+==========+==========+ +| NULL | 0x00 | | | | +| UP | 0x01 | ESC [ A | ESC [ A | ESC [ A | +| DOWN | 0x02 | ESC [ B | ESC [ B | ESC [ B | +| RIGHT | 0x03 | ESC [ C | ESC [ C | ESC [ C | +| LEFT | 0x04 | ESC [ D | ESC [ D | ESC [ D | +| HOME | 0x05 | ESC [ H | ESC h | ESC [ H | +| END | 0x06 | ESC [ F | ESC k | ESC [ K | +| INSERT | 0x07 | ESC [ @ | ESC + | ESC [ @ | +| | | ESC [ L | | ESC [ L | +| DELETE | 0x08 | ESC [ X | ESC - | ESC [ P | +| PG UP | 0x09 | ESC [ I | ESC ? | ESC [ V | +| | | | | ESC [ ? | +| PG DOWN | 0x0A | ESC [ G | ESC / | ESC [ U | +| | | | | ESC [ / | +| F1 | 0x0B | ESC [ M | ESC 1 | ESC O P | +| F2 | 0x0C | ESC [ N | ESC 2 | ESC O Q | +| F3 | 0x0D | ESC [ O | ESC 3 | ESC O w | +| F4 | 0x0E | ESC [ P | ESC 4 | ESC O x | +| F5 | 0x0F | ESC [ Q | ESC 5 | ESC O t | +| F6 | 0x10 | ESC [ R | ESC 6 | ESC O u | +| F7 | 0x11 | ESC [ S | ESC 7 | ESC O q | +| F8 | 0x12 | ESC [ T | ESC 8 | ESC O r | +| F9 | 0x13 | ESC [ U | ESC 9 | ESC O p | +| F10 | 0x14 | ESC [ V | ESC 0 | ESC O M | +| Escape | 0x17 | ESC | ESC | ESC | +| F11 | 0x15 | | ESC ! | | +| F12 | 0x16 | | ESC @ | | ++=========+======+===========+==========+==========+ + +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +#define MODE0_COLUMN_COUNT 80 +#define MODE0_ROW_COUNT 25 + + +EFI_STATUS +EFIAPI +TextInReset( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + + +EFI_STATUS +EFIAPI +ReadKeyStroke( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + OUT EFI_INPUT_KEY *Key + ); + + +EFI_STATUS +EFIAPI +TextOutReset( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +CHAR8 * +EFIAPI +SafeUnicodeStrToAsciiStr ( + IN CONST CHAR16 *Source, + OUT CHAR8 *Destination + ); + +EFI_STATUS +EFIAPI +OutputString ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *String + ); + + +EFI_STATUS +EFIAPI +TestString ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *String + ); + + +EFI_STATUS +EFIAPI +QueryMode ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNumber, + OUT UINTN *Columns, + OUT UINTN *Rows + ); + + +EFI_STATUS +EFIAPI +SetMode( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNumber + ); + + +EFI_STATUS +EFIAPI +SetAttribute( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Attribute + ); + + +EFI_STATUS +EFIAPI +ClearScreen ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This + ); + + +EFI_STATUS +EFIAPI +SetCursorPosition ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Column, + IN UINTN Row + ); + + +EFI_STATUS +EFIAPI +EnableCursor ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN Enable + ); + + + EFI_SIMPLE_TEXT_INPUT_PROTOCOL mSimpleTextIn = { + TextInReset, + ReadKeyStroke, + NULL +}; + + EFI_SIMPLE_TEXT_OUTPUT_MODE mSimpleTextOutMode = { + 1, + 0, + EFI_TEXT_ATTR( EFI_LIGHTGRAY, EFI_BLACK ), + 0, + 0, + TRUE +}; + +EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL mSimpleTextOut = { + TextOutReset, + OutputString, + TestString, + QueryMode, + SetMode, + SetAttribute, + ClearScreen, + SetCursorPosition, + EnableCursor, + &mSimpleTextOutMode +}; + + EFI_HANDLE mInstallHandle = NULL; + + + +BOOLEAN +TextOutIsValidAscii ( + IN CHAR16 Ascii + ) +{ + // + // valid ASCII code lies in the extent of 0x20 - 0x7F + // + if ((Ascii >= 0x20) && (Ascii <= 0x7F)) { + return TRUE; + } + + return FALSE; +} + + +BOOLEAN +TextOutIsValidEfiCntlChar ( + IN CHAR16 Char + ) +{ + // + // only support four control characters. + // + if (Char == CHAR_NULL || + Char == CHAR_BACKSPACE || + Char == CHAR_LINEFEED || + Char == CHAR_CARRIAGE_RETURN || + Char == CHAR_TAB ) { + return TRUE; + } + + return FALSE; +} + + +VOID +EFIAPI +WaitForKeyEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + if (SerialPortPoll ()) { + gBS->SignalEvent (Event); + } +} + + +EFI_STATUS +EFIAPI +TextInReset ( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +ReadKeyStroke ( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + OUT EFI_INPUT_KEY *Key + ) +{ + CHAR8 Char; + + SerialPortRead ((UINT8 *)&Char, 1); + + // + // Check for ESC sequence. This code is not techincally correct VT100 code. + // An illegal ESC sequence represents an ESC and the characters that follow. + // This code will eat one or two chars after an escape. This is done to + // prevent some complex FIFOing of the data. It is good enough to get + // the arrow and delete keys working + // + Key->UnicodeChar = 0; + Key->ScanCode = SCAN_NULL; + if (Char == 0x1b) { + SerialPortRead ((UINT8 *)&Char, 1); + if (Char == '[') { + SerialPortRead ((UINT8 *)&Char, 1); + switch (Char) { + case 'A': + Key->ScanCode = SCAN_UP; + break; + case 'B': + Key->ScanCode = SCAN_DOWN; + break; + case 'C': + Key->ScanCode = SCAN_RIGHT; + break; + case 'D': + Key->ScanCode = SCAN_LEFT; + break; + case 'H': + Key->ScanCode = SCAN_HOME; + break; + case 'K': + case 'F': // PC ANSI + Key->ScanCode = SCAN_END; + break; + case '@': + case 'L': + Key->ScanCode = SCAN_INSERT; + break; + case 'P': + case 'X': // PC ANSI + Key->ScanCode = SCAN_DELETE; + break; + case 'U': + case '/': + case 'G': // PC ANSI + Key->ScanCode = SCAN_PAGE_DOWN; + break; + case 'V': + case '?': + case 'I': // PC ANSI + Key->ScanCode = SCAN_PAGE_UP; + break; + + // PCANSI that does not conflict with VT100 + case 'M': + Key->ScanCode = SCAN_F1; + break; + case 'N': + Key->ScanCode = SCAN_F2; + break; + case 'O': + Key->ScanCode = SCAN_F3; + break; + case 'Q': + Key->ScanCode = SCAN_F5; + break; + case 'R': + Key->ScanCode = SCAN_F6; + break; + case 'S': + Key->ScanCode = SCAN_F7; + break; + case 'T': + Key->ScanCode = SCAN_F8; + break; + + default: + Key->UnicodeChar = Char; + break; + } + } else if (Char == '0') { + SerialPortRead ((UINT8 *)&Char, 1); + switch (Char) { + case 'P': + Key->ScanCode = SCAN_F1; + break; + case 'Q': + Key->ScanCode = SCAN_F2; + break; + case 'w': + Key->ScanCode = SCAN_F3; + break; + case 'x': + Key->ScanCode = SCAN_F4; + break; + case 't': + Key->ScanCode = SCAN_F5; + break; + case 'u': + Key->ScanCode = SCAN_F6; + break; + case 'q': + Key->ScanCode = SCAN_F7; + break; + case 'r': + Key->ScanCode = SCAN_F8; + break; + case 'p': + Key->ScanCode = SCAN_F9; + break; + case 'm': + Key->ScanCode = SCAN_F10; + break; + default : + break; + } + } + } else if (Char < ' ') { + if ((Char == CHAR_BACKSPACE) || + (Char == CHAR_TAB) || + (Char == CHAR_LINEFEED) || + (Char == CHAR_CARRIAGE_RETURN)) { + // Only let through EFI required control characters + Key->UnicodeChar = (CHAR16)Char; + } + } else if (Char == 0x7f) { + Key->ScanCode = SCAN_DELETE; + } else { + Key->UnicodeChar = (CHAR16)Char; + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +TextOutReset ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + EFI_STATUS Status; + + This->SetAttribute( + This, + EFI_TEXT_ATTR(This->Mode->Attribute & 0x0F, EFI_BACKGROUND_BLACK) + ); + + Status = This->SetMode (This, 0); + + return Status; +} + +CHAR8 * +EFIAPI +SafeUnicodeStrToAsciiStr ( + IN CONST CHAR16 *Source, + OUT CHAR8 *Destination + ) +{ + CHAR8 *ReturnValue; + + ASSERT (Destination != NULL); + + // + // ASSERT if Source is long than PcdMaximumUnicodeStringLength. + // Length tests are performed inside StrLen(). + // + ASSERT (StrSize (Source) != 0); + + // + // Source and Destination should not overlap + // + ASSERT ((UINTN) ((CHAR16 *) Destination - Source) > StrLen (Source)); + ASSERT ((UINTN) ((CHAR8 *) Source - Destination) > StrLen (Source)); + + + ReturnValue = Destination; + while (*Source != '\0') { + // + // If any non-ascii characters in Source then replace it with '?'. + // + if (*Source < 0x80) { + *Destination = (CHAR8) *Source; + } else { + *Destination = '?'; + + //Surrogate pair check. + if ((*Source >= 0xD800) && (*Source <= 0xDFFF)) { + Source++; + } + } + + Destination++; + Source++; + } + + *Destination = '\0'; + + // + // ASSERT Original Destination is less long than PcdMaximumAsciiStringLength. + // Length tests are performed inside AsciiStrLen(). + // + ASSERT (AsciiStrSize (ReturnValue) != 0); + + return ReturnValue; +} + +EFI_STATUS +EFIAPI +OutputString ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *String + ) +{ + UINTN Size = StrLen(String) + 1; + CHAR8 *OutputString = AllocatePool(Size); + + //If there is any non-ascii characters in String buffer then replace it with '?' + //Eventually, UnicodeStrToAsciiStr API should be fixed. + SafeUnicodeStrToAsciiStr(String, OutputString); + SerialPortWrite ((UINT8 *)OutputString, Size - 1); + + FreePool(OutputString); + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +TestString ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *String + ) +{ + CHAR8 Character; + + for ( ; *String != CHAR_NULL; String++) { + Character = (CHAR8)*String; + if (!(TextOutIsValidAscii (Character) || TextOutIsValidEfiCntlChar (Character))) { + return EFI_UNSUPPORTED; + } + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +QueryMode ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNumber, + OUT UINTN *Columns, + OUT UINTN *Rows + ) +{ + if (This->Mode->MaxMode > 1) { + return EFI_DEVICE_ERROR; + } + + if (ModeNumber == 0) { + *Columns = MODE0_COLUMN_COUNT; + *Rows = MODE0_ROW_COUNT; + return EFI_SUCCESS; + } + + return EFI_UNSUPPORTED; +} + + +EFI_STATUS +EFIAPI +SetMode ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNumber + ) +{ + if (ModeNumber != 0) { + return EFI_UNSUPPORTED; + } + + This->Mode->Mode = 0; + This->ClearScreen (This); + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +SetAttribute( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Attribute + ) +{ + This->Mode->Attribute = (INT32)Attribute; + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +ClearScreen ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This + ) +{ + EFI_STATUS Status; + + Status = This->SetCursorPosition (This, 0, 0); + return Status; +} + + +EFI_STATUS +EFIAPI +SetCursorPosition ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Column, + IN UINTN Row + ) +{ + EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode; + EFI_STATUS Status; + UINTN MaxColumn; + UINTN MaxRow; + + Mode = This->Mode; + + Status = This->QueryMode( + This, + Mode->Mode, + &MaxColumn, + &MaxRow + ); + if (EFI_ERROR(Status)) { + return EFI_UNSUPPORTED; + } + + if ((Column >= MaxColumn) || (Row >= MaxRow)) { + return EFI_UNSUPPORTED; + } + + Mode->CursorColumn = (INT32)Column; + Mode->CursorRow = (INT32)Row; + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +EnableCursor ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN Enable + ) +{ + if (!Enable) { + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +SimpleTextInOutEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = gBS->CreateEvent ( + EVT_NOTIFY_WAIT, + TPL_NOTIFY, + WaitForKeyEvent, + NULL, + &mSimpleTextIn.WaitForKey + ); + ASSERT_EFI_ERROR (Status); + + Status = gBS->InstallMultipleProtocolInterfaces( + &mInstallHandle, + &gEfiSimpleTextInProtocolGuid, &mSimpleTextIn, + &gEfiSimpleTextOutProtocolGuid, &mSimpleTextOut, + NULL + ); + if (!EFI_ERROR (Status)) { + gST->ConOut = &mSimpleTextOut; + gST->ConIn = &mSimpleTextIn; + } + + return Status; +} diff --git a/EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOutSerial.inf b/EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOutSerial.inf new file mode 100644 index 0000000000..17821d62f7 --- /dev/null +++ b/EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOutSerial.inf @@ -0,0 +1,56 @@ +#%HEADER% +#/** @file +# +# Component discription file for Bds module +# +# Copyright (c) 2008, Intel Corporation.
+# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SimpleTextInOutSerial + FILE_GUID = 6696936D-3637-467C-87CB-14EA8248948C + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = SimpleTextInOutEntryPoint + + +[Sources.common] + SimpleTextInOut.c + + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + +[LibraryClasses] + BaseLib + ReportStatusCodeLib + MemoryAllocationLib + UefiLib + UefiBootServicesTableLib + BaseMemoryLib + DebugLib + UefiDriverEntryPoint + SerialPortLib + +[Guids] + + +[Protocols] + gEfiSimpleTextInProtocolGuid + gEfiSimpleTextOutProtocolGuid + gEfiSerialIoProtocolGuid + gEfiDevicePathProtocolGuid + +[depex] + TRUE diff --git a/EmbeddedPkg/TemplateBds/BdsEntry.c b/EmbeddedPkg/TemplateBds/BdsEntry.c new file mode 100644 index 0000000000..dcdf499d20 --- /dev/null +++ b/EmbeddedPkg/TemplateBds/BdsEntry.c @@ -0,0 +1,183 @@ +/** @file + The entry of the embedded BDS. This BDS does not follow the Boot Manager requirements + of the UEFI specification as it is designed to implement an embedded systmes + propriatary boot scheme. + + This template assume a DXE driver produces a SerialIo protocol not using the EFI + driver module and it will attempt to connect a console on top of this. + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "BdsEntry.h" + + +BOOLEAN gConsolePresent = FALSE; + + +EFI_HANDLE mBdsImageHandle = NULL; +EFI_BDS_ARCH_PROTOCOL gBdsProtocol = { + BdsEntry, +}; + + + + +/** + This function uses policy data from the platform to determine what operating + system or system utility should be loaded and invoked. This function call + also optionally make the use of user input to determine the operating system + or system utility to be loaded and invoked. When the DXE Core has dispatched + all the drivers on the dispatch queue, this function is called. This + function will attempt to connect the boot devices required to load and invoke + the selected operating system or system utility. During this process, + additional firmware volumes may be discovered that may contain addition DXE + drivers that can be dispatched by the DXE Core. If a boot device cannot be + fully connected, this function calls the DXE Service Dispatch() to allow the + DXE drivers from any newly discovered firmware volumes to be dispatched. + Then the boot device connection can be attempted again. If the same boot + device connection operation fails twice in a row, then that boot device has + failed, and should be skipped. This function should never return. + + @param This The EFI_BDS_ARCH_PROTOCOL instance. + + @return None. + +**/ +VOID +EFIAPI +BdsEntry ( + IN EFI_BDS_ARCH_PROTOCOL *This + ) +{ + EFI_STATUS Status; + UINTN NoHandles; + EFI_HANDLE *Buffer; + UINTN Index; + EFI_HANDLE FvHandle; + EFI_GUID *NameGuid; + + // + // This code assumes that a DXE driver produces a SerialIo protocol not following the EFI + // driver model. At a minimum we need to connect an EFI driver model terminal driver on top + // of the serial driver. + // + Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiSerialIoProtocolGuid, NULL, &NoHandles, &Buffer); + if (!EFI_ERROR (Status)) { + for (Index = 0; Index < NoHandles; Index++) { + // For every Serial IO protocol in the system connect EFI drivers to it. + // This should cause the terminal driver to bind to the Serial IO protocol and produce a + // child handle that produces SimpleTextOut & SImpleTextIn protocols + gBS->ConnectController (Buffer[Index], NULL, NULL, TRUE); + } + + FreePool (Buffer); + } + + // + // Now we need to setup the EFI System Table with information about the console devices. + // This code is normally in the console spliter driver on platforms that support multiple + // consoles at the same time + // + Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiSimpleTextOutProtocolGuid, NULL, &NoHandles, &Buffer); + if (!EFI_ERROR (Status)) { + // Use the first SimpleTextOut we find and update the EFI System Table + gST->ConsoleOutHandle = Buffer[0]; + gST->StandardErrorHandle = Buffer[0]; + Status = gBS->HandleProtocol (Buffer[0], &gEfiSimpleTextOutProtocolGuid, (VOID **)&gST->ConOut); + ASSERT_EFI_ERROR (Status); + + gST->StdErr = gST->ConOut; + + FreePool (Buffer); + + gConsolePresent = TRUE; + } + + Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiSimpleTextInProtocolGuid, NULL, &NoHandles, &Buffer); + if (!EFI_ERROR (Status)) { + // Use the first SimpleTextIn we find and update the EFI System Table + gST->ConsoleInHandle = Buffer[0]; + Status = gBS->HandleProtocol (Buffer[0], &gEfiSimpleTextInProtocolGuid, (VOID **)&gST->ConIn); + ASSERT_EFI_ERROR (Status); + + FreePool (Buffer); + } + + // + // We now have EFI Consoles up and running. Print () will work now. DEBUG () and ASSERT () worked + // prior to this point as they were configured to use a more primative output scheme. + // + + + // + // Platform specific stuff goes here + // + + + // + // Normal UEFI behavior is to process Globally Defined Variables as defined in Chapter 3 + // (Boot Manager) of the UEFI specification. For this embedded system we don't do this. + // + + // + // Search all the FVs for an application with a UI Section of Ebl. A .FDF file can be used + // to control the names of UI sections in an FV. + // + Status = FindApplicationMatchingUiSection (L"Ebl", &FvHandle, &NameGuid); + if (EFI_ERROR (Status)) { + // + // Just load the first application we find reguardless of name. + // This is the fallback path. + // + Status = FindApplicationMatchingUiSection (NULL, &FvHandle, &NameGuid); + // Nothing to boot + ASSERT_EFI_ERROR (Status); + } + + Status = LoadPeCoffSectionFromFv (FvHandle, NameGuid); + + // + // EFI does not define the bavior if all boot attemps fail and the last one returns. + // So we make a policy choice to reset the system since this BDS does not have a UI. + // + gRT->ResetSystem (EfiResetCold, Status, 0, NULL); + + return ; +} + + +EFI_STATUS +EFIAPI +BdsInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + mBdsImageHandle = ImageHandle; + + // + // Install protocol interface + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &mBdsImageHandle, + &gEfiBdsArchProtocolGuid, &gBdsProtocol, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + + diff --git a/EmbeddedPkg/TemplateBds/BdsEntry.h b/EmbeddedPkg/TemplateBds/BdsEntry.h new file mode 100644 index 0000000000..31eb6d7d4e --- /dev/null +++ b/EmbeddedPkg/TemplateBds/BdsEntry.h @@ -0,0 +1,62 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#ifndef __BDS_ENTRY_H__ +#define __BDS_ENTRY_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + + + +EFI_STATUS +LoadPeCoffSectionFromFv ( + IN EFI_HANDLE FvHandle, + IN EFI_GUID *NameGuid + ); + +EFI_STATUS +FindApplicationMatchingUiSection ( + IN CHAR16 *UiString, + OUT EFI_HANDLE *FvHandle, + OUT EFI_GUID **NameGuid + ); + +VOID +EFIAPI +BdsEntry ( + IN EFI_BDS_ARCH_PROTOCOL *This + ); + +#endif + diff --git a/EmbeddedPkg/TemplateBds/FirmwareVolume.c b/EmbeddedPkg/TemplateBds/FirmwareVolume.c new file mode 100644 index 0000000000..b6a2206a86 --- /dev/null +++ b/EmbeddedPkg/TemplateBds/FirmwareVolume.c @@ -0,0 +1,160 @@ +/** @file + The entry of the embedded BDS. This BDS does not follow the Boot Manager requirements + of the UEFI specification as it is designed to implement an embedded systmes + propriatary boot scheme. + + This template assume a DXE driver produces a SerialIo protocol not using the EFI + driver module and it will attempt to connect a console on top of this. + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "BdsEntry.h" + + +EFI_STATUS +FindApplicationMatchingUiSection ( + IN CHAR16 *UiString, + OUT EFI_HANDLE *FvHandle, + OUT EFI_GUID **NameGuid + ) +{ + EFI_STATUS Status; + EFI_STATUS NextStatus; + UINTN NoHandles; + EFI_HANDLE *Buffer; + UINTN Index; + EFI_FV_FILETYPE FileType; + EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; + VOID *Key; + EFI_FV_FILE_ATTRIBUTES Attributes; + UINTN Size; + UINTN UiStringLen; + CHAR16 *UiSection; + UINT32 Authentication; + + + UiStringLen = 0; + if (UiString != NULL) { + UiStringLen = StrLen (UiString); + } + + Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiFirmwareVolume2ProtocolGuid, NULL, &NoHandles, &Buffer); + if (!EFI_ERROR (Status)) { + for (Index = 0; Index < NoHandles; Index++) { + Status = gBS->HandleProtocol (Buffer[Index], &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&Fv); + if (!EFI_ERROR (Status)) { + Key = AllocatePool (Fv->KeySize); + FileType = EFI_FV_FILETYPE_APPLICATION; + + do { + NextStatus = Fv->GetNextFile (Fv, Key, &FileType, *NameGuid, &Attributes, &Size); + if (!EFI_ERROR (NextStatus)) { + if (UiString == NULL) { + // + // If UiString is NULL match first application we find. + // + *FvHandle = Buffer[Index]; + FreePool (Key); + return Status; + } + + UiSection = NULL; + Status = Fv->ReadSection ( + Fv, + *NameGuid, + EFI_SECTION_USER_INTERFACE, + 0, + (VOID **)&UiSection, + &Size, + &Authentication + ); + if (!EFI_ERROR (Status)) { + if (StrnCmp (UiString, UiSection, UiStringLen)) { + // + // We found a UiString match. + // + *FvHandle = Buffer[Index]; + FreePool (Key); + FreePool (UiSection); + return Status; + } + FreePool (UiSection); + } + } + } while (!EFI_ERROR (NextStatus)); + + FreePool (Key); + } + } + + FreePool (Buffer); + } + + return EFI_NOT_FOUND; +} + + +EFI_DEVICE_PATH * +FvFileDevicePath ( + IN EFI_HANDLE FvHandle, + IN EFI_GUID *NameGuid + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH NewNode; + + DevicePath = DevicePathFromHandle (FvHandle); + + EfiInitializeFwVolDevicepathNode (&NewNode, NameGuid); + + return AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&NewNode); +} + + + +EFI_STATUS +LoadPeCoffSectionFromFv ( + IN EFI_HANDLE FvHandle, + IN EFI_GUID *NameGuid + ) +{ + EFI_STATUS Status; + EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; + VOID *Buffer; + UINTN BufferSize; + UINT32 Authentication; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_HANDLE ImageHandle; + + Status = gBS->HandleProtocol (FvHandle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&Fv); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = Fv->ReadSection (Fv, NameGuid, EFI_SECTION_PE32, 0, &Buffer, &BufferSize, &Authentication); + if (!EFI_ERROR (Status)) { + DevicePath = FvFileDevicePath (FvHandle, NameGuid); + Status = gBS->LoadImage (TRUE, gImageHandle, DevicePath, Buffer, BufferSize, &ImageHandle); + if (!EFI_ERROR (Status)) { + // ExitData is NULL so we need to pass in a size of zero + BufferSize = 0; + Status = gBS->StartImage (ImageHandle, &BufferSize, NULL); + } + + FreePool (Buffer); + } + + + return Status; +} + diff --git a/EmbeddedPkg/TemplateBds/TemplateBds.inf b/EmbeddedPkg/TemplateBds/TemplateBds.inf new file mode 100644 index 0000000000..5a3c1b9801 --- /dev/null +++ b/EmbeddedPkg/TemplateBds/TemplateBds.inf @@ -0,0 +1,68 @@ +#%HEADER% +#/** @file +# +# Component discription file for Bds module +# +# Copyright (c) 2008, Intel Corporation.
+# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TemplateBds + FILE_GUID = 3C85595C-70FD-447D-B0CB-7F6BBA9C9BEB + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = BdsInitialize + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources.common] + BdsEntry.c + FirmwareVolume.c + + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + DevicePathLib + BaseLib + HobLib + UefiRuntimeServicesTableLib + ReportStatusCodeLib + PerformanceLib + DxeServicesTableLib + MemoryAllocationLib + UefiLib + UefiBootServicesTableLib + BaseMemoryLib + DebugLib + PrintLib + UefiDriverEntryPoint + +[Guids] + + +[Protocols] + gEfiBdsArchProtocolGuid + gEfiSimpleTextInProtocolGuid + gEfiSimpleTextOutProtocolGuid + gEfiSerialIoProtocolGuid + gEfiDevicePathProtocolGuid + gEfiFirmwareVolume2ProtocolGuid + +[depex] + TRUE diff --git a/EmbeddedPkg/TemplateCpuDxe/Arm/Exception.c b/EmbeddedPkg/TemplateCpuDxe/Arm/Exception.c new file mode 100644 index 0000000000..e32d47e123 --- /dev/null +++ b/EmbeddedPkg/TemplateCpuDxe/Arm/Exception.c @@ -0,0 +1,250 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include + +VOID +ExceptionHandlersStart ( + VOID + ); + +VOID +ExceptionHandlersEnd ( + VOID + ); + +VOID +CommonExceptionEntry ( + VOID + ); + +VOID +AsmCommonExceptionEntry ( + VOID + ); + + +EFI_EXCEPTION_CALLBACK gExceptionHandlers[MAX_ARM_EXCEPTION + 1]; + + +/** + This function registers and enables the handler specified by InterruptHandler for a processor + interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the + handler for the processor interrupt or exception type specified by InterruptType is uninstalled. + The installed handler is called once for each processor interrupt or exception. + + @param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts + are enabled and FALSE if interrupts are disabled. + @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called + when a processor interrupt occurs. If this parameter is NULL, then the handler + will be uninstalled. + + @retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled. + @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was + previously installed. + @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not + previously installed. + @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported. + +**/ +EFI_STATUS +RegisterInterruptHandler ( + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler + ) +{ + if (InterruptType > MAX_ARM_EXCEPTION) { + return EFI_UNSUPPORTED; + } + + if ((InterruptHandler == NULL) && (gExceptionHandlers[InterruptType] == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if ((InterruptHandler != NULL) && (gExceptionHandlers[InterruptType] != NULL)) { + return EFI_ALREADY_STARTED; + } + + gExceptionHandlers[InterruptType] = InterruptHandler; + + return EFI_SUCCESS; +} + + + + +VOID +EFIAPI +DefaultSWIExceptionHandler( + IN EFI_EXCEPTION_TYPE ExceptionType, + IN OUT EFI_SYSTEM_CONTEXT SystemContext + ) +{ + return; +} + + +VOID +EFIAPI +DefaultExceptionHandler( + IN EFI_EXCEPTION_TYPE ExceptionType, + IN OUT EFI_SYSTEM_CONTEXT SystemContext + ) +{ + DEBUG ((EFI_D_ERROR, "Exception %d from %x\n", ExceptionType, SystemContext.SystemContextArm->PC)); + ASSERT (FALSE); + + return; +} + + + +EFI_STATUS +InitializeExceptions ( + IN EFI_CPU_ARCH_PROTOCOL *Cpu + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + UINTN Offset; + UINTN Length; + UINTN Index; + BOOLEAN Enabled; + + // + // Disable interrupts + // + Cpu->GetInterruptState (Cpu, &Enabled); + Cpu->DisableInterrupt (Cpu); + + // + // Initialize the C entry points for interrupts + // + for (Index = 0; Index <= MAX_ARM_EXCEPTION; Index++) { + if (Index == EXCEPT_ARM_SOFTWARE_INTERRUPT) { + Status = Cpu->RegisterInterruptHandler (Cpu, Index, DefaultSWIExceptionHandler); + } else { + Status = Cpu->RegisterInterruptHandler (Cpu, Index, DefaultExceptionHandler); + } + ASSERT_EFI_ERROR (Status); + } + + // + // Copy an implementation of the ARM exception vectors to 0x0. + // + Length = (UINTN)ExceptionHandlersEnd - (UINTN)ExceptionHandlersStart; + + CopyMem ((VOID *)(UINTN)PcdGet32 (PcdCpuVectorBaseAddress), (VOID *)ExceptionHandlersStart, Length); + + // + // Patch in the common Assembly exception handler + // + Offset = (UINTN)CommonExceptionEntry - (UINTN)ExceptionHandlersStart; + *(UINTN *) ((UINT8 *)(UINTN)PcdGet32 (PcdCpuVectorBaseAddress) + Offset) = (UINTN)AsmCommonExceptionEntry; + + // + // Flush Caches since we updated executable stuff + // + InvalidateInstructionCache (); + + if (Enabled) { + // + // Restore interrupt state + // + Status = Cpu->EnableInterrupt (Cpu); + } + + return Status; +} + + + +/** + This function reads the processor timer specified by TimerIndex and returns it in TimerValue. + + @param TimerIndex Specifies which processor timer is to be returned in TimerValue. This parameter + must be between 0 and NumberOfTimers-1. + @param TimerValue Pointer to the returned timer value. + @param TimerPeriod A pointer to the amount of time that passes in femtoseconds for each increment + of TimerValue. + + @retval EFI_SUCCESS The processor timer value specified by TimerIndex was returned in TimerValue. + @retval EFI_DEVICE_ERROR An error occurred attempting to read one of the processor's timers. + @retval EFI_INVALID_PARAMETER TimerValue is NULL or TimerIndex is not valid. + @retval EFI_UNSUPPORTED The processor does not have any readable timers. + +**/ +EFI_STATUS +EFIAPI +GetTimerValue ( + IN UINT32 TimerIndex, + OUT UINT64 *TimerValue, + OUT UINT64 *TimerPeriod OPTIONAL + ) +{ + return EFI_UNSUPPORTED; +} + + +/** + This function flushes the range of addresses from Start to Start+Length + from the processor's data cache. If Start is not aligned to a cache line + boundary, then the bytes before Start to the preceding cache line boundary + are also flushed. If Start+Length is not aligned to a cache line boundary, + then the bytes past Start+Length to the end of the next cache line boundary + are also flushed. The FlushType of EfiCpuFlushTypeWriteBackInvalidate must be + supported. If the data cache is fully coherent with all DMA operations, then + this function can just return EFI_SUCCESS. If the processor does not support + flushing a range of the data cache, then the entire data cache can be flushed. + + @param Start The beginning physical address to flush from the processor's data + cache. + @param Length The number of bytes to flush from the processor's data cache. This + function may flush more bytes than Length specifies depending upon + the granularity of the flush operation that the processor supports. + @param FlushType Specifies the type of flush operation to perform. + + @retval EFI_SUCCESS The address range from Start to Start+Length was flushed from + the processor's data cache. + @retval EFI_UNSUPPORTED The processor does not support the cache flush type specified + by FlushType. + @retval EFI_DEVICE_ERROR The address range from Start to Start+Length could not be flushed + from the processor's data cache. + +**/ +EFI_STATUS +EFIAPI +FlushCpuDataCache ( + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length, + IN EFI_CPU_FLUSH_TYPE FlushType + ) +{ + if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) { + WriteBackInvalidateDataCacheRange((VOID *)(UINTN)Start, (UINTN)Length); + return EFI_SUCCESS; + } else if (FlushType == EfiCpuFlushTypeInvalidate) { + InvalidateDataCacheRange((VOID *)(UINTN)Start, (UINTN)Length); + return EFI_SUCCESS; + } else if (FlushType == EfiCpuFlushTypeWriteBack) { + WriteBackDataCacheRange((VOID *)(UINTN)Start, (UINTN)Length); + return EFI_SUCCESS; + } else { + return EFI_UNSUPPORTED; + } +} + + + + diff --git a/EmbeddedPkg/TemplateCpuDxe/Arm/Exceptions.S b/EmbeddedPkg/TemplateCpuDxe/Arm/Exceptions.S new file mode 100755 index 0000000000..d864759afd --- /dev/null +++ b/EmbeddedPkg/TemplateCpuDxe/Arm/Exceptions.S @@ -0,0 +1,158 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2008-2009 Apple Inc. All rights reserved. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + +.text +.align 2 + +.globl _ExceptionHandlersStart +.globl _ExceptionHandlersEnd +.globl _CommonExceptionEntry +.globl _AsmCommonExceptionEntry +.globl _gExceptionHandlers + +_ExceptionHandlersStart: + +_Reset: + b _ResetEntry + +_UndefinedInstruction: + b _UndefinedInstructionEntry + +_SoftwareInterrupt: + b _SoftwareInterruptEntry + +_PrefetchAbort: + b _PrefetchAbortEntry + +_DataAbort: + b _DataAbortEntry + +_ReservedException: + b _ReservedExceptionEntry + +_Irq: + b _IrqEntry + +_Fiq: + b _FiqEntry + +_ResetEntry: + stmfd sp!,{r0-r1} + mov r0,#0 + ldr r1,_CommonExceptionEntry + bx r1 + +_UndefinedInstructionEntry: + stmfd sp!,{r0-r1} + mov r0,#1 + ldr r1,_CommonExceptionEntry + bx r1 + +_SoftwareInterruptEntry: + stmfd sp!,{r0-r1} + mov r0,#2 + ldr r1,_CommonExceptionEntry + bx r1 + +_PrefetchAbortEntry: + stmfd sp!,{r0-r1} + mov r0,#3 + sub lr,lr,#4 + ldr r1,_CommonExceptionEntry + bx r1 + +_DataAbortEntry: + stmfd sp!,{r0-r1} + mov r0,#4 + sub lr,lr,#8 + ldr r1,_CommonExceptionEntry + bx r1 + +_ReservedExceptionEntry: + stmfd sp!,{r0-r1} + mov r0,#5 + ldr r1,_CommonExceptionEntry + bx r1 + +_IrqEntry: + stmfd sp!,{r0-r1} + mov r0,#6 + sub lr,lr,#4 + ldr r1,_CommonExceptionEntry + bx r1 + +_FiqEntry: + stmfd sp!,{r0-r1} + mov r0,#7 + sub lr,lr,#4 + ldr r1,_CommonExceptionEntry + bx r1 + +_CommonExceptionEntry: + .byte 0x12 + .byte 0x34 + .byte 0x56 + .byte 0x78 + +_ExceptionHandlersEnd: + +LIndirectgExceptionHandlers: + .long _gExceptionHandlers + +_AsmCommonExceptionEntry: + mrc p15, 0, r1, c6, c0, 2 @ Read IFAR + stmfd sp!,{r1} @ Store the IFAR + + mrc p15, 0, r1, c5, c0, 1 @ Read IFSR + stmfd sp!,{r1} @ Store the IFSR + + mrc p15, 0, r1, c6, c0, 0 @ Read DFAR + stmfd sp!,{r1} @ Store the DFAR + + mrc p15, 0, r1, c5, c0, 0 @ Read DFSR + stmfd sp!,{r1} @ Store the DFSR + + mrs r1,spsr @ Read SPSR (which is the pre-exception CPSR) + stmfd sp!,{r1} @ Store the SPSR + + stmfd sp!,{lr} @ Store the link register (which is the pre-exception PC) + stmfd sp,{sp,lr}^ @ Store user/system mode stack pointer and link register + nop @ Required by ARM architecture + sub sp,sp,#0x08 @ Adjust stack pointer + stmfd sp!,{r2-r12} @ Store general purpose registers + + ldr r3,[sp,#0x40] @ Read saved R1 from the stack (it was saved by the exception entry routine) + ldr r2,[sp,#0x3C] @ Read saved R0 from the stack (it was saved by the exception entry routine) + stmfd sp!,{r2-r3} @ Store general purpose registers R0 and R1 + + mov r1,sp @ Prepare System Context pointer as an argument for the exception handler + + ldr r2,LIndirectgExceptionHandlers @ Offset to 32-bit address of exception handler + ldr r2,[r2] @ Load exception handler table + ldr r3,[r2,r0,lsl #2] @ Index to find the handler for this exception + +// blx r3 @ Call exception handler + bx r3 @ Call exception handler + + ldr r2,[sp,#0x40] @ Load CPSR from context, in case it has changed + msr SPSR_cxsf,r2 @ Store it back to the SPSR to be restored when exiting this handler + + ldmfd sp!,{r0-r12} @ Restore general purpose registers + ldmia sp,{sp,lr}^ @ Restore user/system mode stack pointer and link register + nop @ Required by ARM architecture + add sp,sp,#0x08 @ Adjust stack pointer + ldmfd sp!,{lr} @ Restore the link register (which is the pre-exception PC) + add sp,sp,#0x1C @ Clear out the remaining stack space + movs pc,lr @ Return from exception + diff --git a/EmbeddedPkg/TemplateCpuDxe/Arm/Exceptions.asm b/EmbeddedPkg/TemplateCpuDxe/Arm/Exceptions.asm new file mode 100755 index 0000000000..b91639d149 --- /dev/null +++ b/EmbeddedPkg/TemplateCpuDxe/Arm/Exceptions.asm @@ -0,0 +1,152 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2008-2009 Apple Inc. All rights reserved. +// +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +//------------------------------------------------------------------------------ + + EXPORT ExceptionHandlersStart + EXPORT ExceptionHandlersEnd + EXPORT CommonExceptionEntry + EXPORT AsmCommonExceptionEntry + IMPORT gExceptionHandlers + + AREA DxeExceptionHandlers, CODE, READONLY + +ExceptionHandlersStart + +Reset + B ResetEntry + +UndefinedInstruction + B UndefinedInstructionEntry + +SoftwareInterrupt + B SoftwareInterruptEntry + +PrefetchAbort + B PrefetchAbortEntry + +DataAbort + B DataAbortEntry + +ReservedException + B ReservedExceptionEntry + +Irq + B IrqEntry + +Fiq + B FiqEntry + +ResetEntry + STMFD SP!,{R0-R1} + MOV R0,#0 + LDR R1,CommonExceptionEntry + BX R1 + +UndefinedInstructionEntry + STMFD SP!,{R0-R1} + MOV R0,#1 + LDR R1,CommonExceptionEntry + BX R1 + +SoftwareInterruptEntry + STMFD SP!,{R0-R1} + MOV R0,#2 + LDR R1,CommonExceptionEntry + BX R1 + +PrefetchAbortEntry + STMFD SP!,{R0-R1} + MOV R0,#3 + SUB LR,LR,#4 + LDR R1,CommonExceptionEntry + BX R1 + +DataAbortEntry + STMFD SP!,{R0-R1} + MOV R0,#4 + SUB LR,LR,#8 + LDR R1,CommonExceptionEntry + BX R1 + +ReservedExceptionEntry + STMFD SP!,{R0-R1} + MOV R0,#5 + LDR R1,CommonExceptionEntry + BX R1 + +IrqEntry + STMFD SP!,{R0-R1} + MOV R0,#6 + SUB LR,LR,#4 + LDR R1,CommonExceptionEntry + BX R1 + +FiqEntry + STMFD SP!,{R0-R1} + MOV R0,#7 + SUB LR,LR,#4 + LDR R1,CommonExceptionEntry + BX R1 + +CommonExceptionEntry + DCD 0x12345678 + +ExceptionHandlersEnd + +AsmCommonExceptionEntry + MRC p15, 0, r1, c6, c0, 2 ; Read IFAR + STMFD SP!,{R1} ; Store the IFAR + + MRC p15, 0, r1, c5, c0, 1 ; Read IFSR + STMFD SP!,{R1} ; Store the IFSR + + MRC p15, 0, r1, c6, c0, 0 ; Read DFAR + STMFD SP!,{R1} ; Store the DFAR + + MRC p15, 0, r1, c5, c0, 0 ; Read DFSR + STMFD SP!,{R1} ; Store the DFSR + + MRS R1,SPSR ; Read SPSR (which is the pre-exception CPSR) + STMFD SP!,{R1} ; Store the SPSR + + STMFD SP!,{LR} ; Store the link register (which is the pre-exception PC) + STMFD SP,{SP,LR}^ ; Store user/system mode stack pointer and link register + NOP ; Required by ARM architecture + SUB SP,SP,#0x08 ; Adjust stack pointer + STMFD SP!,{R2-R12} ; Store general purpose registers + + LDR R3,[SP,#0x40] ; Read saved R1 from the stack (it was saved by the exception entry routine) + LDR R2,[SP,#0x3C] ; Read saved R0 from the stack (it was saved by the exception entry routine) + STMFD SP!,{R2-R3} ; Store general purpose registers R0 and R1 + + MOV R1,SP ; Prepare System Context pointer as an argument for the exception handler + + LDR R2,=gExceptionHandlers ; Load exception handler table + LDR R3,[R2,R0,LSL #2] ; Index to find the handler for this exception + + BLX R3 ; Call exception handler + + LDR R2,[SP,#0x40] ; Load CPSR from context, in case it has changed + MSR SPSR_cxsf,R2 ; Store it back to the SPSR to be restored when exiting this handler + + LDMFD SP!,{R0-R12} ; Restore general purpose registers + LDM SP,{SP,LR}^ ; Restore user/system mode stack pointer and link register + NOP ; Required by ARM architecture + ADD SP,SP,#0x08 ; Adjust stack pointer + LDMFD SP!,{LR} ; Restore the link register (which is the pre-exception PC) + ADD SP,SP,#0x1C ; Clear out the remaining stack space + MOVS PC,LR ; Return from exception + + END + + diff --git a/EmbeddedPkg/TemplateCpuDxe/CpuDxe.c b/EmbeddedPkg/TemplateCpuDxe/CpuDxe.c new file mode 100644 index 0000000000..90bf8a9af8 --- /dev/null +++ b/EmbeddedPkg/TemplateCpuDxe/CpuDxe.c @@ -0,0 +1,323 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "CpuDxe.h" + + + +/** + This function flushes the range of addresses from Start to Start+Length + from the processor's data cache. If Start is not aligned to a cache line + boundary, then the bytes before Start to the preceding cache line boundary + are also flushed. If Start+Length is not aligned to a cache line boundary, + then the bytes past Start+Length to the end of the next cache line boundary + are also flushed. The FlushType of EfiCpuFlushTypeWriteBackInvalidate must be + supported. If the data cache is fully coherent with all DMA operations, then + this function can just return EFI_SUCCESS. If the processor does not support + flushing a range of the data cache, then the entire data cache can be flushed. + + @param This The EFI_CPU_ARCH_PROTOCOL instance. + @param Start The beginning physical address to flush from the processor's data + cache. + @param Length The number of bytes to flush from the processor's data cache. This + function may flush more bytes than Length specifies depending upon + the granularity of the flush operation that the processor supports. + @param FlushType Specifies the type of flush operation to perform. + + @retval EFI_SUCCESS The address range from Start to Start+Length was flushed from + the processor's data cache. + @retval EFI_UNSUPPORTED The processor does not support the cache flush type specified + by FlushType. + @retval EFI_DEVICE_ERROR The address range from Start to Start+Length could not be flushed + from the processor's data cache. + +**/ +EFI_STATUS +EFIAPI +CpuFlushCpuDataCache ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length, + IN EFI_CPU_FLUSH_TYPE FlushType + ) +{ + return FlushCpuDataCache (Start, Length, FlushType); +} + + +/** + This function enables interrupt processing by the processor. + + @param This The EFI_CPU_ARCH_PROTOCOL instance. + + @retval EFI_SUCCESS Interrupts are enabled on the processor. + @retval EFI_DEVICE_ERROR Interrupts could not be enabled on the processor. + +**/ +EFI_STATUS +EFIAPI +CpuEnableInterrupt ( + IN EFI_CPU_ARCH_PROTOCOL *This + ) +{ + EnableInterrupts (); + return EFI_SUCCESS; +} + + +/** + This function disables interrupt processing by the processor. + + @param This The EFI_CPU_ARCH_PROTOCOL instance. + + @retval EFI_SUCCESS Interrupts are disabled on the processor. + @retval EFI_DEVICE_ERROR Interrupts could not be disabled on the processor. + +**/ +EFI_STATUS +EFIAPI +CpuDisableInterrupt ( + IN EFI_CPU_ARCH_PROTOCOL *This + ) +/*++ + +Routine Description: + Disables CPU interrupts. + +Arguments: + This - Protocol instance structure + +Returns: + EFI_SUCCESS - If interrupts were disabled in the CPU. + EFI_DEVICE_ERROR - If interrupts could not be disabled on the CPU. + +--*/ +{ + DisableInterrupts (); + return EFI_SUCCESS; +} + + +/** + This function retrieves the processor's current interrupt state a returns it in + State. If interrupts are currently enabled, then TRUE is returned. If interrupts + are currently disabled, then FALSE is returned. + + @param This The EFI_CPU_ARCH_PROTOCOL instance. + @param State A pointer to the processor's current interrupt state. Set to TRUE if + interrupts are enabled and FALSE if interrupts are disabled. + + @retval EFI_SUCCESS The processor's current interrupt state was returned in State. + @retval EFI_INVALID_PARAMETER State is NULL. + +**/ +EFI_STATUS +EFIAPI +CpuGetInterruptState ( + IN EFI_CPU_ARCH_PROTOCOL *This, + OUT BOOLEAN *State + ) +{ + if (State == NULL) { + return EFI_INVALID_PARAMETER; + } + + *State = GetInterruptState (); + return EFI_SUCCESS; +} + + +/** + This function generates an INIT on the processor. If this function succeeds, then the + processor will be reset, and control will not be returned to the caller. If InitType is + not supported by this processor, or the processor cannot programmatically generate an + INIT without help from external hardware, then EFI_UNSUPPORTED is returned. If an error + occurs attempting to generate an INIT, then EFI_DEVICE_ERROR is returned. + + @param This The EFI_CPU_ARCH_PROTOCOL instance. + @param InitType The type of processor INIT to perform. + + @retval EFI_SUCCESS The processor INIT was performed. This return code should never be seen. + @retval EFI_UNSUPPORTED The processor INIT operation specified by InitType is not supported + by this processor. + @retval EFI_DEVICE_ERROR The processor INIT failed. + +**/ +EFI_STATUS +EFIAPI +CpuInit ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_CPU_INIT_TYPE InitType + ) +{ + return EFI_UNSUPPORTED; +} + + +/** + This function registers and enables the handler specified by InterruptHandler for a processor + interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the + handler for the processor interrupt or exception type specified by InterruptType is uninstalled. + The installed handler is called once for each processor interrupt or exception. + + @param This The EFI_CPU_ARCH_PROTOCOL instance. + @param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts + are enabled and FALSE if interrupts are disabled. + @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called + when a processor interrupt occurs. If this parameter is NULL, then the handler + will be uninstalled. + + @retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled. + @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was + previously installed. + @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not + previously installed. + @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported. + +**/ +EFI_STATUS +EFIAPI +CpuRegisterInterruptHandler ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler + ) +{ + return RegisterInterruptHandler (InterruptType, InterruptHandler); +} + + +/** + This function reads the processor timer specified by TimerIndex and returns it in TimerValue. + + @param This The EFI_CPU_ARCH_PROTOCOL instance. + @param TimerIndex Specifies which processor timer is to be returned in TimerValue. This parameter + must be between 0 and NumberOfTimers-1. + @param TimerValue Pointer to the returned timer value. + @param TimerPeriod A pointer to the amount of time that passes in femtoseconds for each increment + of TimerValue. + + @retval EFI_SUCCESS The processor timer value specified by TimerIndex was returned in TimerValue. + @retval EFI_DEVICE_ERROR An error occurred attempting to read one of the processor's timers. + @retval EFI_INVALID_PARAMETER TimerValue is NULL or TimerIndex is not valid. + @retval EFI_UNSUPPORTED The processor does not have any readable timers. + +**/ +EFI_STATUS +EFIAPI +CpuGetTimerValue ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN UINT32 TimerIndex, + OUT UINT64 *TimerValue, + OUT UINT64 *TimerPeriod OPTIONAL + ) +{ + return GetTimerValue (TimerIndex, TimerValue, TimerPeriod); +} + + +/** + This function modifies the attributes for the memory region specified by BaseAddress and + Length from their current attributes to the attributes specified by Attributes. + + @param This The EFI_CPU_ARCH_PROTOCOL instance. + @param BaseAddress The physical address that is the start address of a memory region. + @param Length The size in bytes of the memory region. + @param Attributes The bit mask of attributes to set for the memory region. + + @retval EFI_SUCCESS The attributes were set for the memory region. + @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by + BaseAddress and Length cannot be modified. + @retval EFI_INVALID_PARAMETER Length is zero. + @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of + the memory resource range. + @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory + resource range specified by BaseAddress and Length. + The bit mask of attributes is not support for the memory resource + range specified by BaseAddress and Length. + +**/ +EFI_STATUS +EFIAPI +CpuSetMemoryAttributes ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes + ) +{ + // + // This is used to set cachability via the MMU on ARM + // + // This more about optimization and we can usually run fine if the default + // settings for cachability are good. + // + return EFI_UNSUPPORTED; +} + + + + +// +// Globals used to initialize the protocol +// +EFI_HANDLE mCpuHandle = NULL; +EFI_CPU_ARCH_PROTOCOL mCpu = { + CpuFlushCpuDataCache, + CpuEnableInterrupt, + CpuDisableInterrupt, + CpuGetInterruptState, + CpuInit, + CpuRegisterInterruptHandler, + CpuGetTimerValue, + CpuSetMemoryAttributes, + 0, // NumberOfTimers + 4, // DmaBufferAlignment +}; + + +/** + Initialize the state information for the CPU Architectural Protocol + + @param ImageHandle of the loaded driver + @param SystemTable Pointer to the System Table + + @retval EFI_SUCCESS Protocol registered + @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure + @retval EFI_DEVICE_ERROR Hardware problems + +**/ +EFI_STATUS +CpuDxeInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + InitializeExceptions (&mCpu); + + // + // Install CPU Architectural Protocol and the thunk protocol + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &mCpuHandle, + &gEfiCpuArchProtocolGuid, &mCpu, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + diff --git a/EmbeddedPkg/TemplateCpuDxe/CpuDxe.h b/EmbeddedPkg/TemplateCpuDxe/CpuDxe.h new file mode 100644 index 0000000000..c81d8012f8 --- /dev/null +++ b/EmbeddedPkg/TemplateCpuDxe/CpuDxe.h @@ -0,0 +1,124 @@ +/** @file + + Copyright (c) 2006 - 2008, Intel Corporation
+ Portions copyright (c) 2008-2009 Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + + +/** + This function registers and enables the handler specified by InterruptHandler for a processor + interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the + handler for the processor interrupt or exception type specified by InterruptType is uninstalled. + The installed handler is called once for each processor interrupt or exception. + + @param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts + are enabled and FALSE if interrupts are disabled. + @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called + when a processor interrupt occurs. If this parameter is NULL, then the handler + will be uninstalled. + + @retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled. + @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was + previously installed. + @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not + previously installed. + @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported. + +**/ +EFI_STATUS +RegisterInterruptHandler ( + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler + ); + + +EFI_STATUS +InitializeExceptions ( + IN EFI_CPU_ARCH_PROTOCOL *Cpu + ); + + +/** + This function reads the processor timer specified by TimerIndex and returns it in TimerValue. + + @param TimerIndex Specifies which processor timer is to be returned in TimerValue. This parameter + must be between 0 and NumberOfTimers-1. + @param TimerValue Pointer to the returned timer value. + @param TimerPeriod A pointer to the amount of time that passes in femtoseconds for each increment + of TimerValue. + + @retval EFI_SUCCESS The processor timer value specified by TimerIndex was returned in TimerValue. + @retval EFI_DEVICE_ERROR An error occurred attempting to read one of the processor's timers. + @retval EFI_INVALID_PARAMETER TimerValue is NULL or TimerIndex is not valid. + @retval EFI_UNSUPPORTED The processor does not have any readable timers. + +**/ +EFI_STATUS +GetTimerValue ( + IN UINT32 TimerIndex, + OUT UINT64 *TimerValue, + OUT UINT64 *TimerPeriod OPTIONAL + ); + + +/** + This function flushes the range of addresses from Start to Start+Length + from the processor's data cache. If Start is not aligned to a cache line + boundary, then the bytes before Start to the preceding cache line boundary + are also flushed. If Start+Length is not aligned to a cache line boundary, + then the bytes past Start+Length to the end of the next cache line boundary + are also flushed. The FlushType of EfiCpuFlushTypeWriteBackInvalidate must be + supported. If the data cache is fully coherent with all DMA operations, then + this function can just return EFI_SUCCESS. If the processor does not support + flushing a range of the data cache, then the entire data cache can be flushed. + + @param Start The beginning physical address to flush from the processor's data + cache. + @param Length The number of bytes to flush from the processor's data cache. This + function may flush more bytes than Length specifies depending upon + the granularity of the flush operation that the processor supports. + @param FlushType Specifies the type of flush operation to perform. + + @retval EFI_SUCCESS The address range from Start to Start+Length was flushed from + the processor's data cache. + @retval EFI_UNSUPPORTED The processor does not support the cache flush type specified + by FlushType. + @retval EFI_DEVICE_ERROR The address range from Start to Start+Length could not be flushed + from the processor's data cache. + +**/ +EFI_STATUS +EFIAPI +FlushCpuDataCache ( + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length, + IN EFI_CPU_FLUSH_TYPE FlushType + ); + + diff --git a/EmbeddedPkg/TemplateCpuDxe/IA32/Exception.c b/EmbeddedPkg/TemplateCpuDxe/IA32/Exception.c new file mode 100644 index 0000000000..5ba38e1623 --- /dev/null +++ b/EmbeddedPkg/TemplateCpuDxe/IA32/Exception.c @@ -0,0 +1,183 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + + +EFI_EXCEPTION_CALLBACK gExceptionHandlers[0x100]; + + +/** + This function registers and enables the handler specified by InterruptHandler for a processor + interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the + handler for the processor interrupt or exception type specified by InterruptType is uninstalled. + The installed handler is called once for each processor interrupt or exception. + + @param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts + are enabled and FALSE if interrupts are disabled. + @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called + when a processor interrupt occurs. If this parameter is NULL, then the handler + will be uninstalled. + + @retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled. + @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was + previously installed. + @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not + previously installed. + @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported. + +**/ +EFI_STATUS +RegisterInterruptHandler ( + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler + ) +{ + if (InterruptType > 0xFF) { + return EFI_UNSUPPORTED; + } + + if ((InterruptHandler == NULL) && (gExceptionHandlers[InterruptType] == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if ((InterruptHandler != NULL) && (gExceptionHandlers[InterruptType] != NULL)) { + return EFI_ALREADY_STARTED; + } + + gExceptionHandlers[InterruptType] = InterruptHandler; + + return EFI_SUCCESS; +} + + + + +VOID +EFIAPI +DefaultExceptionHandler ( + IN EFI_EXCEPTION_TYPE ExceptionType, + IN OUT EFI_SYSTEM_CONTEXT SystemContext + ) +{ + DEBUG ((EFI_D_ERROR, "Exception %d from %x\n", ExceptionType, SystemContext.SystemContextIa32->Eip)); + ASSERT (FALSE); + + return; +} + + + +EFI_STATUS +InitializeExceptions ( + IN EFI_CPU_ARCH_PROTOCOL *Cpu + ) +{ + // You need to initialize gExceptionHandlers[] to point to DefaultExceptionHandler() + // and write all the assembly to handle the interrupts. + ASSERT (FALSE); + return EFI_UNSUPPORTED; +} + + + +/** + This function reads the processor timer specified by TimerIndex and returns it in TimerValue. + + @param TimerIndex Specifies which processor timer is to be returned in TimerValue. This parameter + must be between 0 and NumberOfTimers-1. + @param TimerValue Pointer to the returned timer value. + @param TimerPeriod A pointer to the amount of time that passes in femtoseconds for each increment + of TimerValue. + + @retval EFI_SUCCESS The processor timer value specified by TimerIndex was returned in TimerValue. + @retval EFI_DEVICE_ERROR An error occurred attempting to read one of the processor's timers. + @retval EFI_INVALID_PARAMETER TimerValue is NULL or TimerIndex is not valid. + @retval EFI_UNSUPPORTED The processor does not have any readable timers. + +**/ +EFI_STATUS +EFIAPI +GetTimerValue ( + IN UINT32 TimerIndex, + OUT UINT64 *TimerValue, + OUT UINT64 *TimerPeriod OPTIONAL + ) +{ + if (TimerValue == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (TimerIndex == 0) { + *TimerValue = AsmReadTsc (); + if (TimerPeriod != NULL) { + // + // BugBug: Hard coded. Don't know how to do this generically + // + *TimerPeriod = 1000000000; + } + return EFI_SUCCESS; + } + return EFI_INVALID_PARAMETER; +} + + +/** + This function flushes the range of addresses from Start to Start+Length + from the processor's data cache. If Start is not aligned to a cache line + boundary, then the bytes before Start to the preceding cache line boundary + are also flushed. If Start+Length is not aligned to a cache line boundary, + then the bytes past Start+Length to the end of the next cache line boundary + are also flushed. The FlushType of EfiCpuFlushTypeWriteBackInvalidate must be + supported. If the data cache is fully coherent with all DMA operations, then + this function can just return EFI_SUCCESS. If the processor does not support + flushing a range of the data cache, then the entire data cache can be flushed. + + @param Start The beginning physical address to flush from the processor's data + cache. + @param Length The number of bytes to flush from the processor's data cache. This + function may flush more bytes than Length specifies depending upon + the granularity of the flush operation that the processor supports. + @param FlushType Specifies the type of flush operation to perform. + + @retval EFI_SUCCESS The address range from Start to Start+Length was flushed from + the processor's data cache. + @retval EFI_UNSUPPORTED The processor does not support the cache flush type specified + by FlushType. + @retval EFI_DEVICE_ERROR The address range from Start to Start+Length could not be flushed + from the processor's data cache. + +**/ +EFI_STATUS +EFIAPI +FlushCpuDataCache ( + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length, + IN EFI_CPU_FLUSH_TYPE FlushType + ) +{ + if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) { + AsmWbinvd (); + return EFI_SUCCESS; + } else if (FlushType == EfiCpuFlushTypeInvalidate) { + AsmInvd (); + return EFI_SUCCESS; + } else { + return EFI_UNSUPPORTED; + } +} + + + + diff --git a/EmbeddedPkg/TemplateCpuDxe/TemplateCpuDxe.inf b/EmbeddedPkg/TemplateCpuDxe/TemplateCpuDxe.inf new file mode 100644 index 0000000000..67d3edc7c4 --- /dev/null +++ b/EmbeddedPkg/TemplateCpuDxe/TemplateCpuDxe.inf @@ -0,0 +1,71 @@ +#%HEADER% +#/** @file +# +# Component discription file for Bds module +# +# Copyright (c) 2008, Intel Corporation.
+# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TemplateCpuDxe + FILE_GUID = CB6DC1E4-5B27-41E8-BC27-9AA50B62081E + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = CpuDxeInitialize + + +[Sources.common] + CpuDxe.c + +[Sources.ARM] + Arm/Exception.c + Arm/Exceptions.asm + Arm/Exceptions.S + +[Sources.IA32] + IA32/Exception.c + +[Sources.X64] + X64/Exception.c + + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + +[Packages.ARM] + ArmPkg/ArmPkg.dec + +[LibraryClasses] + BaseLib + UefiRuntimeServicesTableLib + ReportStatusCodeLib + PerformanceLib + DxeServicesTableLib + MemoryAllocationLib + UefiLib + UefiBootServicesTableLib + BaseMemoryLib + DebugLib + UefiDriverEntryPoint + CacheMaintenanceLib + +[Protocols] + gEfiCpuArchProtocolGuid + +[Pcd.ARM] + gArmTokenSpaceGuid.PcdCpuVectorBaseAddress + + +[depex] + TRUE diff --git a/EmbeddedPkg/TemplateCpuDxe/X64/Exception.c b/EmbeddedPkg/TemplateCpuDxe/X64/Exception.c new file mode 100644 index 0000000000..f86eda077a --- /dev/null +++ b/EmbeddedPkg/TemplateCpuDxe/X64/Exception.c @@ -0,0 +1,183 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + + +EFI_EXCEPTION_CALLBACK gExceptionHandlers[0x100]; + + +/** + This function registers and enables the handler specified by InterruptHandler for a processor + interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the + handler for the processor interrupt or exception type specified by InterruptType is uninstalled. + The installed handler is called once for each processor interrupt or exception. + + @param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts + are enabled and FALSE if interrupts are disabled. + @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called + when a processor interrupt occurs. If this parameter is NULL, then the handler + will be uninstalled. + + @retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled. + @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was + previously installed. + @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not + previously installed. + @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported. + +**/ +EFI_STATUS +RegisterInterruptHandler ( + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler + ) +{ + if (InterruptType > 0xFF) { + return EFI_UNSUPPORTED; + } + + if ((InterruptHandler == NULL) && (gExceptionHandlers[InterruptType] == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if ((InterruptHandler != NULL) && (gExceptionHandlers[InterruptType] != NULL)) { + return EFI_ALREADY_STARTED; + } + + gExceptionHandlers[InterruptType] = InterruptHandler; + + return EFI_SUCCESS; +} + + + + +VOID +EFIAPI +DefaultExceptionHandler ( + IN EFI_EXCEPTION_TYPE ExceptionType, + IN OUT EFI_SYSTEM_CONTEXT SystemContext + ) +{ + DEBUG ((EFI_D_ERROR, "Exception %d from %x\n", ExceptionType, SystemContext.SystemContextX64->Rip)); + ASSERT (FALSE); + + return; +} + + + +EFI_STATUS +InitializeExceptions ( + IN EFI_CPU_ARCH_PROTOCOL *Cpu + ) +{ + // You need to initialize gExceptionHandlers[] to point to DefaultExceptionHandler() + // and write all the assembly to handle the interrupts. + ASSERT (FALSE); + return EFI_UNSUPPORTED; +} + + + +/** + This function reads the processor timer specified by TimerIndex and returns it in TimerValue. + + @param TimerIndex Specifies which processor timer is to be returned in TimerValue. This parameter + must be between 0 and NumberOfTimers-1. + @param TimerValue Pointer to the returned timer value. + @param TimerPeriod A pointer to the amount of time that passes in femtoseconds for each increment + of TimerValue. + + @retval EFI_SUCCESS The processor timer value specified by TimerIndex was returned in TimerValue. + @retval EFI_DEVICE_ERROR An error occurred attempting to read one of the processor's timers. + @retval EFI_INVALID_PARAMETER TimerValue is NULL or TimerIndex is not valid. + @retval EFI_UNSUPPORTED The processor does not have any readable timers. + +**/ +EFI_STATUS +EFIAPI +GetTimerValue ( + IN UINT32 TimerIndex, + OUT UINT64 *TimerValue, + OUT UINT64 *TimerPeriod OPTIONAL + ) +{ + if (TimerValue == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (TimerIndex == 0) { + *TimerValue = AsmReadTsc (); + if (TimerPeriod != NULL) { + // + // BugBug: Hard coded. Don't know how to do this generically + // + *TimerPeriod = 1000000000; + } + return EFI_SUCCESS; + } + return EFI_INVALID_PARAMETER; +} + + +/** + This function flushes the range of addresses from Start to Start+Length + from the processor's data cache. If Start is not aligned to a cache line + boundary, then the bytes before Start to the preceding cache line boundary + are also flushed. If Start+Length is not aligned to a cache line boundary, + then the bytes past Start+Length to the end of the next cache line boundary + are also flushed. The FlushType of EfiCpuFlushTypeWriteBackInvalidate must be + supported. If the data cache is fully coherent with all DMA operations, then + this function can just return EFI_SUCCESS. If the processor does not support + flushing a range of the data cache, then the entire data cache can be flushed. + + @param Start The beginning physical address to flush from the processor's data + cache. + @param Length The number of bytes to flush from the processor's data cache. This + function may flush more bytes than Length specifies depending upon + the granularity of the flush operation that the processor supports. + @param FlushType Specifies the type of flush operation to perform. + + @retval EFI_SUCCESS The address range from Start to Start+Length was flushed from + the processor's data cache. + @retval EFI_UNSUPPORTED The processor does not support the cache flush type specified + by FlushType. + @retval EFI_DEVICE_ERROR The address range from Start to Start+Length could not be flushed + from the processor's data cache. + +**/ +EFI_STATUS +EFIAPI +FlushCpuDataCache ( + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length, + IN EFI_CPU_FLUSH_TYPE FlushType + ) +{ + if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) { + AsmWbinvd (); + return EFI_SUCCESS; + } else if (FlushType == EfiCpuFlushTypeInvalidate) { + AsmInvd (); + return EFI_SUCCESS; + } else { + return EFI_UNSUPPORTED; + } +} + + + + diff --git a/EmbeddedPkg/TemplateMetronomeDxe/Metronome.c b/EmbeddedPkg/TemplateMetronomeDxe/Metronome.c new file mode 100644 index 0000000000..861bf249cd --- /dev/null +++ b/EmbeddedPkg/TemplateMetronomeDxe/Metronome.c @@ -0,0 +1,132 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + + + +/** + The WaitForTick() function waits for the number of ticks specified by + TickNumber from a known time source in the platform. If TickNumber of + ticks are detected, then EFI_SUCCESS is returned. The actual time passed + between entry of this function and the first tick is between 0 and + TickPeriod 100 nS units. If you want to guarantee that at least TickPeriod + time has elapsed, wait for two ticks. This function waits for a hardware + event to determine when a tick occurs. It is possible for interrupt + processing, or exception processing to interrupt the execution of the + WaitForTick() function. Depending on the hardware source for the ticks, it + is possible for a tick to be missed. This function cannot guarantee that + ticks will not be missed. If a timeout occurs waiting for the specified + number of ticks, then EFI_TIMEOUT is returned. + + @param This The EFI_METRONOME_ARCH_PROTOCOL instance. + @param TickNumber Number of ticks to wait. + + @retval EFI_SUCCESS The wait for the number of ticks specified by TickNumber + succeeded. + @retval EFI_TIMEOUT A timeout occurred waiting for the specified number of ticks. + +**/ +EFI_STATUS +EFIAPI +WaitForTick ( + IN EFI_METRONOME_ARCH_PROTOCOL *This, + IN UINT32 TickNumber + ) +{ + // + // Fill me in + // + MicroSecondDelay (10 * TickNumber); + return EFI_UNSUPPORTED; +} + + + +/** + Interface stucture for the Metronome Architectural Protocol. + + @par Protocol Description: + This protocol provides access to a known time source in the platform to the + core. The core uses this known time source to produce core services that + require calibrated delays. + + @param WaitForTick + Waits for a specified number of ticks from a known time source + in the platform. The actual time passed between entry of this + function and the first tick is between 0 and TickPeriod 100 nS + units. If you want to guarantee that at least TickPeriod time + has elapsed, wait for two ticks. + + @param TickPeriod + The period of platform's known time source in 100 nS units. + This value on any platform must be at least 10 uS, and must not + exceed 200 uS. The value in this field is a constant that must + not be modified after the Metronome architectural protocol is + installed. All consumers must treat this as a read-only field. + +**/ +EFI_METRONOME_ARCH_PROTOCOL gMetronome = { + WaitForTick, + 100 +}; + + +EFI_HANDLE gMetronomeHandle = NULL; + + + +/** + Initialize the state information for the CPU Architectural Protocol + + @param ImageHandle of the loaded driver + @param SystemTable Pointer to the System Table + + @retval EFI_SUCCESS Protocol registered + @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure + @retval EFI_DEVICE_ERROR Hardware problems + +**/ +EFI_STATUS +MetronomeInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Do any hardware init required to make WaitForTick () to work here. + // + + Status = gBS->InstallMultipleProtocolInterfaces ( + &gMetronomeHandle, + &gEfiMetronomeArchProtocolGuid, &gMetronome, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + diff --git a/EmbeddedPkg/TemplateMetronomeDxe/TemplateMetronomeDxe.inf b/EmbeddedPkg/TemplateMetronomeDxe/TemplateMetronomeDxe.inf new file mode 100644 index 0000000000..9a4e53a703 --- /dev/null +++ b/EmbeddedPkg/TemplateMetronomeDxe/TemplateMetronomeDxe.inf @@ -0,0 +1,50 @@ +#%HEADER% +#/** @file +# +# Component discription file for Bds module +# +# Copyright (c) 2008, Apple, Inc
+# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TemplateMetronomeDxe + FILE_GUID = 4C6E0267-C77D-410D-8100-1495911A989D + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = MetronomeInitialize + + +[Sources.common] + Metronome.c + + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + UefiLib + UefiBootServicesTableLib + DebugLib + PrintLib + UefiDriverEntryPoint + TimerLib + +[Guids] + + +[Protocols] + gEfiMetronomeArchProtocolGuid + +[depex] + TRUE diff --git a/EmbeddedPkg/TemplateSec/TemplateSec.c b/EmbeddedPkg/TemplateSec/TemplateSec.c new file mode 100644 index 0000000000..dbbf3cb815 --- /dev/null +++ b/EmbeddedPkg/TemplateSec/TemplateSec.c @@ -0,0 +1,76 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include + +#include + +VOID +_ModuleEntryPoint ( + VOID + ) +{ +} + +VOID +CEntryPoint ( + VOID *MemoryBase, + UINTN MemorySize, + VOID *StackBase, + UINTN StackSize + ) +{ + EFI_PHYSICAL_ADDRESS MemoryBegin; + UINT64 MemoryLength; + VOID *HobBase; + + // + // Boot strap the C environment so the other library services will work properly. + // + MemoryBegin = (EFI_PHYSICAL_ADDRESS)(UINTN)MemoryBase; + MemoryLength = (UINT64)MemorySize; + HobBase = (VOID *)(UINTN)(FixedPcdGet32(PcdEmbeddedFdBaseAddress) + FixedPcdGet32(PcdEmbeddedFdSize)); + CreateHobList (MemoryBase, MemorySize, HobBase, StackBase); + + MemoryBegin = (EFI_PHYSICAL_ADDRESS)(UINTN)StackBase; + MemoryLength = (UINT64)StackSize; + UpdateStackHob (MemoryBegin, MemoryLength); + + DEBUG ((DEBUG_ERROR, "CEntryPoint (%x,%x,%x,%x)\n", MemoryBase, MemorySize, StackBase, StackSize)); + + // + // Add your C code stuff here.... + // + + + // + // Load the DXE Core and transfer control to it + // + + // Give the DXE Core access to our DEBUG and ASSERT infrastructure so this will work prior + // to the DXE version being loaded. Thus we close the debugging gap between phases. + AddDxeCoreReportStatusCodeCallback (); + + //BuildFvHobs (PcdBfvBase, PcdBfvSize, NULL); + + LoadDxeCoreFromFv (NULL, 0); + + // DXE Core should always load and never return + ASSERT (FALSE); +} + diff --git a/EmbeddedPkg/TemplateSec/TemplateSec.inf b/EmbeddedPkg/TemplateSec/TemplateSec.inf new file mode 100644 index 0000000000..5c62b7520e --- /dev/null +++ b/EmbeddedPkg/TemplateSec/TemplateSec.inf @@ -0,0 +1,66 @@ +#%HEADER% +#/** @file +# +# Component description file for DxeIpl module +# +# The responsibility of this module is to load the DXE Core from a Firmware Volume. This implementation i used to load a 32-bit DXE Core. +# +# Copyright (c) 2006 - 2008, Intel Corporation.
+# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TemplateSec + FILE_GUID = 1D6F730F-5A55-4078-869B-E0A18324BDC8 + MODULE_TYPE = SEC + VERSION_STRING = 1.0 + + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 ARM +# + +[Sources.common] + TemplateSec.c + +[Sources.Ia32] +# Ia32/ResetVector.asm | MSFT +# Ia32/ResetVector.S | GCC + +[Sources.X64] +# X64/ResetVector.asm | MSFT +# X64/ResetVector.S | GCC + +[Sources.ARM] +# Arm/ResetVector.asm | RVCT +# Arm/ResetVector.S | GCC + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + + +[LibraryClasses] + BaseLib + DebugLib + BaseMemoryLib + UefiDecompressLib + PeCoffLib + CacheMaintenanceLib + PrePiLib + +[Pcd] + gEmbeddedTokenSpaceGuid.PcdEmbeddedFdBaseAddress + gEmbeddedTokenSpaceGuid.PcdEmbeddedFdSize + diff --git a/EmbeddedPkg/TemplateTimerDxe/TemplateTimerDxe.inf b/EmbeddedPkg/TemplateTimerDxe/TemplateTimerDxe.inf new file mode 100644 index 0000000000..d7c1f05674 --- /dev/null +++ b/EmbeddedPkg/TemplateTimerDxe/TemplateTimerDxe.inf @@ -0,0 +1,56 @@ +#%HEADER% +#/** @file +# +# Component discription file for Bds module +# +# Copyright (c) 2008, Apple Inc.
+# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TemplateTimerDxe + FILE_GUID = E697928E-7C98-4501-8406-21F5509549CC + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = TimerInitialize + +[Sources.common] + Timer.c + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + +[LibraryClasses] + BaseLib + UefiRuntimeServicesTableLib + PerformanceLib + UefiLib + UefiBootServicesTableLib + BaseMemoryLib + DebugLib + UefiDriverEntryPoint + IoLib + +[Guids] + +[Protocols] + gEfiTimerArchProtocolGuid + gHardwareInterruptProtocolGuid + +[Pcd.common] + gEmbeddedTokenSpaceGuid.PcdTimerBaseAddress + gEmbeddedTokenSpaceGuid.PcdTimerVector + gEmbeddedTokenSpaceGuid.PcdTimerPeriod + +[Depex] + gHardwareInterruptProtocolGuid \ No newline at end of file diff --git a/EmbeddedPkg/TemplateTimerDxe/Timer.c b/EmbeddedPkg/TemplateTimerDxe/Timer.c new file mode 100644 index 0000000000..4bfa3e8622 --- /dev/null +++ b/EmbeddedPkg/TemplateTimerDxe/Timer.c @@ -0,0 +1,373 @@ +/** @file + Template for Timer Architecture Protocol driver of the ARM flavor + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +// +// Get Base Address of timer block from platform .DSC file +// +#define TIMER_BASE ((UINTN)FixedPcdGet32 (PcdTimerBaseAddress) + 0x00c0) + + +#define TIMER_CMD ((UINTN)FixedPcdGet32 (PcdTimerBaseAddress) + 0x00000004) +#define TIMER_DATA ((UINTN)FixedPcdGet32 (PcdTimerBaseAddress) + 0x00000008) + +// +// The notification function to call on every timer interrupt. +// A bug in the compiler prevents us from initializing this here. +// +volatile EFI_TIMER_NOTIFY mTimerNotifyFunction; + +// +// The current period of the timer interrupt +// +volatile UINT64 mTimerPeriod = 0; + +// +// Cached copy of the Hardware Interrupt protocol instance +// +EFI_HARDWARE_INTERRUPT_PROTOCOL *gInterrupt = NULL; + + +/** + C Interrupt Handler calledin the interrupt context when Source interrupt is active. + + @param Source Source of the interrupt. Hardware routing off a specific platform defines + what source means. + @param SystemContext Pointer to system register context. Mostly used by debuggers and will + update the system context after the return from the interrupt if + modified. Don't change these values unless you know what you are doing + +**/ +VOID +EFIAPI +TimerInterruptHandler ( + IN HARDWARE_INTERRUPT_SOURCE Source, + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + EFI_TPL OriginalTPL; + + // Mask all interrupts + OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL); + + MmioWrite32 (TIMER_CMD, 0); + + if (mTimerNotifyFunction) { + mTimerNotifyFunction (mTimerPeriod); + } + + // restore state + gBS->RestoreTPL (OriginalTPL); +} + + + +/** + This function registers the handler NotifyFunction so it is called every time + the timer interrupt fires. It also passes the amount of time since the last + handler call to the NotifyFunction. If NotifyFunction is NULL, then the + handler is unregistered. If the handler is registered, then EFI_SUCCESS is + returned. If the CPU does not support registering a timer interrupt handler, + then EFI_UNSUPPORTED is returned. If an attempt is made to register a handler + when a handler is already registered, then EFI_ALREADY_STARTED is returned. + If an attempt is made to unregister a handler when a handler is not registered, + then EFI_INVALID_PARAMETER is returned. If an error occurs attempting to + register the NotifyFunction with the timer interrupt, then EFI_DEVICE_ERROR + is returned. + + @param This The EFI_TIMER_ARCH_PROTOCOL instance. + @param NotifyFunction The function to call when a timer interrupt fires. This + function executes at TPL_HIGH_LEVEL. The DXE Core will + register a handler for the timer interrupt, so it can know + how much time has passed. This information is used to + signal timer based events. NULL will unregister the handler. + + @retval EFI_SUCCESS The timer handler was registered. + @retval EFI_UNSUPPORTED The platform does not support timer interrupts. + @retval EFI_ALREADY_STARTED NotifyFunction is not NULL, and a handler is already + registered. + @retval EFI_INVALID_PARAMETER NotifyFunction is NULL, and a handler was not + previously registered. + @retval EFI_DEVICE_ERROR The timer handler could not be registered. + +**/ +EFI_STATUS +EFIAPI +TimerDriverRegisterHandler ( + IN EFI_TIMER_ARCH_PROTOCOL *This, + IN EFI_TIMER_NOTIFY NotifyFunction + ) +{ + // + // Check for invalid parameters + // + if (NotifyFunction == NULL && mTimerNotifyFunction == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (NotifyFunction != NULL && mTimerNotifyFunction != NULL) { + return EFI_ALREADY_STARTED; + } + + mTimerNotifyFunction = NotifyFunction; + + return EFI_SUCCESS; +} + + + +/** + This function adjusts the period of timer interrupts to the value specified + by TimerPeriod. If the timer period is updated, then the selected timer + period is stored in EFI_TIMER.TimerPeriod, and EFI_SUCCESS is returned. If + the timer hardware is not programmable, then EFI_UNSUPPORTED is returned. + If an error occurs while attempting to update the timer period, then the + timer hardware will be put back in its state prior to this call, and + EFI_DEVICE_ERROR is returned. If TimerPeriod is 0, then the timer interrupt + is disabled. This is not the same as disabling the CPU's interrupts. + Instead, it must either turn off the timer hardware, or it must adjust the + interrupt controller so that a CPU interrupt is not generated when the timer + interrupt fires. + + @param This The EFI_TIMER_ARCH_PROTOCOL instance. + @param TimerPeriod The rate to program the timer interrupt in 100 nS units. If + the timer hardware is not programmable, then EFI_UNSUPPORTED is + returned. If the timer is programmable, then the timer period + will be rounded up to the nearest timer period that is supported + by the timer hardware. If TimerPeriod is set to 0, then the + timer interrupts will be disabled. + + @retval EFI_SUCCESS The timer period was changed. + @retval EFI_UNSUPPORTED The platform cannot change the period of the timer interrupt. + @retval EFI_DEVICE_ERROR The timer period could not be changed due to a device error. + +**/ +EFI_STATUS +EFIAPI +TimerDriverSetTimerPeriod ( + IN EFI_TIMER_ARCH_PROTOCOL *This, + IN UINT64 TimerPeriod + ) +{ + EFI_STATUS Status; + UINT64 TimerCount; + + if (TimerPeriod == 0) { + // + // Disable interrupt 0 and timer + // + MmioAnd32 (TIMER_DATA, 0); + + Status = gInterrupt->DisableInterruptSource (gInterrupt, FixedPcdGet32 (PcdTimerVector)); + } else { + // + // Convert TimerPeriod into Timer F counts + // + TimerCount = DivU64x32 (TimerPeriod + 5, 10); + + // + // Program Timer F with the new count value + // + MmioWrite32 (TIMER_DATA, (UINT32)TimerCount); + + // + // Enable interrupt and initialize and enable timer. + // + MmioOr32 (TIMER_CMD, 0x11); + + Status = gInterrupt->EnableInterruptSource (gInterrupt, FixedPcdGet32 (PcdTimerVector)); + } + + // + // Save the new timer period + // + mTimerPeriod = TimerPeriod; + return Status; +} + + +/** + This function retrieves the period of timer interrupts in 100 ns units, + returns that value in TimerPeriod, and returns EFI_SUCCESS. If TimerPeriod + is NULL, then EFI_INVALID_PARAMETER is returned. If a TimerPeriod of 0 is + returned, then the timer is currently disabled. + + @param This The EFI_TIMER_ARCH_PROTOCOL instance. + @param TimerPeriod A pointer to the timer period to retrieve in 100 ns units. If + 0 is returned, then the timer is currently disabled. + + @retval EFI_SUCCESS The timer period was returned in TimerPeriod. + @retval EFI_INVALID_PARAMETER TimerPeriod is NULL. + +**/ +EFI_STATUS +EFIAPI +TimerDriverGetTimerPeriod ( + IN EFI_TIMER_ARCH_PROTOCOL *This, + OUT UINT64 *TimerPeriod + ) +{ + if (TimerPeriod == NULL) { + return EFI_INVALID_PARAMETER; + } + + *TimerPeriod = mTimerPeriod; + return EFI_SUCCESS; +} + + + +/** + This function generates a soft timer interrupt. If the platform does not support soft + timer interrupts, then EFI_UNSUPPORTED is returned. Otherwise, EFI_SUCCESS is returned. + If a handler has been registered through the EFI_TIMER_ARCH_PROTOCOL.RegisterHandler() + service, then a soft timer interrupt will be generated. If the timer interrupt is + enabled when this service is called, then the registered handler will be invoked. The + registered handler should not be able to distinguish a hardware-generated timer + interrupt from a software-generated timer interrupt. + + @param This The EFI_TIMER_ARCH_PROTOCOL instance. + + @retval EFI_SUCCESS The soft timer interrupt was generated. + @retval EFI_UNSUPPORTED The platform does not support the generation of soft timer interrupts. + +**/ +EFI_STATUS +EFIAPI +TimerDriverGenerateSoftInterrupt ( + IN EFI_TIMER_ARCH_PROTOCOL *This + ) +{ + return EFI_UNSUPPORTED; +} + + +/** + Interface stucture for the Timer Architectural Protocol. + + @par Protocol Description: + This protocol provides the services to initialize a periodic timer + interrupt, and to register a handler that is called each time the timer + interrupt fires. It may also provide a service to adjust the rate of the + periodic timer interrupt. When a timer interrupt occurs, the handler is + passed the amount of time that has passed since the previous timer + interrupt. + + @param RegisterHandler + Registers a handler that will be called each time the + timer interrupt fires. TimerPeriod defines the minimum + time between timer interrupts, so TimerPeriod will also + be the minimum time between calls to the registered + handler. + + @param SetTimerPeriod + Sets the period of the timer interrupt in 100 nS units. + This function is optional, and may return EFI_UNSUPPORTED. + If this function is supported, then the timer period will + be rounded up to the nearest supported timer period. + + @param GetTimerPeriod + Retrieves the period of the timer interrupt in 100 nS units. + + @param GenerateSoftInterrupt + Generates a soft timer interrupt that simulates the firing of + the timer interrupt. This service can be used to invoke the + registered handler if the timer interrupt has been masked for + a period of time. + +**/ +EFI_TIMER_ARCH_PROTOCOL gTimer = { + TimerDriverRegisterHandler, + TimerDriverSetTimerPeriod, + TimerDriverGetTimerPeriod, + TimerDriverGenerateSoftInterrupt +}; + +EFI_HANDLE gTimerHandle = NULL; + + +/** + Initialize the state information for the Timer Architectural Protocol + + @param ImageHandle of the loaded driver + @param SystemTable Pointer to the System Table + + @retval EFI_SUCCESS Protocol registered + @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure + @retval EFI_DEVICE_ERROR Hardware problems + +**/ +EFI_STATUS +EFIAPI +TimerInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Find the interrupt controller protocol. ASSERT if not found. + // + Status = gBS->LocateProtocol (&gHardwareInterruptProtocolGuid, NULL, ( VOID ** )&gInterrupt); + ASSERT_EFI_ERROR (Status); + + MmioWrite32 (TIMER_CMD, 0x01); + + // + // Force the timer to be disabled + // + Status = TimerDriverSetTimerPeriod (&gTimer, 0); + ASSERT_EFI_ERROR (Status); + + // + // Install interrupt handler + // + Status = gInterrupt->RegisterInterruptSource (gInterrupt, FixedPcdGet32 (PcdTimerVector), TimerInterruptHandler); + ASSERT_EFI_ERROR (Status); + + // + // Force the timer to be enabled at its default period + // + Status = TimerDriverSetTimerPeriod (&gTimer, FixedPcdGet32 (PcdTimerPeriod)); + ASSERT_EFI_ERROR (Status); + + + // + // Install the Timer Architectural Protocol onto a new handle + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &gTimerHandle, + &gEfiTimerArchProtocolGuid, &gTimer, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + -- 2.39.2