#include "FvLib.h"\r
#include "PeCoffLib.h"\r
\r
-#define ARMT_UNCONDITIONAL_JUMP_INSTRUCTION 0xEB000000\r
#define ARM64_UNCONDITIONAL_JUMP_INSTRUCTION 0x14000000\r
\r
+/*\r
+ * Arm instruction to jump to Fv entry instruction in Arm or Thumb mode.\r
+ * From ARM Arch Ref Manual versions b/c/d, section A8.8.25 BL, BLX (immediate)\r
+ * BLX (encoding A2) branches to offset in Thumb instruction set mode.\r
+ * BL (encoding A1) branches to offset in Arm instruction set mode.\r
+ */\r
+#define ARM_JUMP_OFFSET_MAX 0xffffff\r
+#define ARM_JUMP_TO_ARM(Offset) (0xeb000000 | ((Offset - 8) >> 2))\r
+\r
+#define _ARM_JUMP_TO_THUMB(Imm32) (0xfa000000 | \\r
+ (((Imm32) & (1 << 1)) << (24 - 1)) | \\r
+ (((Imm32) >> 2) & 0x7fffff))\r
+#define ARM_JUMP_TO_THUMB(Offset) _ARM_JUMP_TO_THUMB((Offset) - 8)\r
+\r
+/*\r
+ * Arm instruction to return from exception (MOVS PC, LR)\r
+ */\r
+#define ARM_RETURN_FROM_EXCEPTION 0xE1B0F07E\r
+\r
BOOLEAN mArm = FALSE;\r
BOOLEAN mRiscV = FALSE;\r
STATIC UINT32 MaxFfsAlignment = 0;\r
// if we found an SEC core entry point then generate a branch instruction\r
// to it and populate a debugger SWI entry as well\r
if (UpdateVectorSec) {\r
+ UINT32 EntryOffset;\r
\r
VerboseMsg("UpdateArmResetVectorIfNeeded updating ARM SEC vector");\r
\r
- // B SecEntryPoint - signed_immed_24 part +/-32MB offset\r
- // on ARM, the PC is always 8 ahead, so we're not really jumping from the base address, but from base address + 8\r
- ResetVector[0] = (INT32)(SecCoreEntryAddress - FvInfo->BaseAddress - 8) >> 2;\r
+ EntryOffset = (INT32)(SecCoreEntryAddress - FvInfo->BaseAddress);\r
\r
- if (ResetVector[0] > 0x00FFFFFF) {\r
- Error(NULL, 0, 3000, "Invalid", "SEC Entry point must be within 32MB of the start of the FV");\r
+ if (EntryOffset > ARM_JUMP_OFFSET_MAX) {\r
+ Error(NULL, 0, 3000, "Invalid", "SEC Entry point offset above 1MB of the start of the FV");\r
return EFI_ABORTED;\r
}\r
\r
- // Add opcode for an unconditional branch with no link. i.e.: " B SecEntryPoint"\r
- ResetVector[0] |= ARMT_UNCONDITIONAL_JUMP_INSTRUCTION;\r
+ if ((SecCoreEntryAddress & 1) != 0) {\r
+ ResetVector[0] = ARM_JUMP_TO_THUMB(EntryOffset);\r
+ } else {\r
+ ResetVector[0] = ARM_JUMP_TO_ARM(EntryOffset);\r
+ }\r
\r
// SWI handler movs pc,lr. Just in case a debugger uses SWI\r
- ResetVector[2] = 0xE1B0F07E;\r
+ ResetVector[2] = ARM_RETURN_FROM_EXCEPTION;\r
\r
// Place holder to support a common interrupt handler from ROM.\r
// Currently not supported. For this to be used the reset vector would not be in this FV\r