EDK2 doxygen online documents - Firmware Encoding Index 1
EDK2 doxygen online documents - Firmware Encoding Index

ArmPkg/Library/BasePeCoffLib/Arm/PeCoffLoaderEx.c

Go to the documentation of this file.
00001 
00016 #include "BasePeCoffLibInternals.h"
00017 
00018 
00019 //
00020 // The PE/COFF specification needs to get update for ARMv7 MOVW/MOVT
00021 // When it gets updated we can move these defines to PeImage.h
00022 //
00023 #define EFI_IMAGE_REL_BASED_ARM_THUMB_MOVW  11
00024 #define EFI_IMAGE_REL_BASED_ARM_THUMB_MOVT  12
00025 
00026 
00036 UINT16
00037 ThumbMovtImmediateAddress (
00038   IN UINT16 *Instruction
00039   )
00040 {
00041   UINT32  Movt;
00042   UINT16  Address;
00043   
00044   // Thumb2 is two 16-bit instructions working together. Not a single 32-bit instruction
00045   // Example MOVT R0, #0 is 0x0000f2c0 or 0xf2c0 0x0000
00046   Movt = (*Instruction << 16) | (*(Instruction + 1)); 
00047 
00048   // imm16 = imm4:i:imm3:imm8
00049   //         imm4 -> Bit19:Bit16
00050   //         i    -> Bit26
00051   //         imm3 -> Bit14:Bit12
00052   //         imm8 -> Bit7:Bit0
00053   Address  = (UINT16)(Movt & 0x000000ff);         // imm8
00054   Address |= (UINT16)((Movt >> 4) &  0x0000f700); // imm4 imm3
00055   Address |= (Movt & BIT26 ? BIT11 : 0);          // i
00056   return Address;
00057 }
00058 
00059 
00066 VOID
00067 ThumbMovtImmediatePatch (
00068   IN OUT UINT16 *Instruction,
00069   IN     UINT16 Address
00070   )
00071 {
00072   UINT16  Patch;
00073 
00074   // First 16-bit chunk of instruciton
00075   Patch  = ((Address >> 12) & 0x000f);            // imm4 
00076   Patch |= (((Address & BIT11) != 0) ? BIT10 : 0); // i
00077   // Mask out instruction bits and or in address
00078   *(Instruction) = (*Instruction & ~0x040f) | Patch;
00079 
00080   // Second 16-bit chunk of instruction
00081   Patch  =  Address & 0x000000ff;          // imm8
00082   Patch |=  ((Address << 4) & 0x00007000); // imm3
00083   // Mask out instruction bits and or in address
00084   Instruction++;
00085   *Instruction = (*Instruction & ~0x70ff) | Patch;
00086 }
00087 
00088 
00101 RETURN_STATUS
00102 PeCoffLoaderRelocateImageEx (
00103   IN UINT16      **Reloc,
00104   IN OUT CHAR8   *Fixup,
00105   IN OUT CHAR8   **FixupData,
00106   IN UINT64      Adjust
00107   )
00108 {
00109   UINT16      *Fixup16;
00110   UINT16      FixupVal;
00111   UINT16      *Addend;
00112 
00113   Fixup16   = (UINT16 *) Fixup;
00114 
00115   switch ((**Reloc) >> 12) {
00116   case EFI_IMAGE_REL_BASED_ARM_THUMB_MOVW:
00117     FixupVal = ThumbMovtImmediateAddress (Fixup16) + (UINT16)Adjust;
00118     ThumbMovtImmediatePatch (Fixup16, FixupVal);
00119 
00120     if (*FixupData != NULL) {
00121       *FixupData             = ALIGN_POINTER (*FixupData, sizeof (UINT16));
00122       *(UINT16 *)*FixupData  = *Fixup16;
00123       *FixupData             = *FixupData + sizeof (UINT16);
00124     }
00125     break;
00126 
00127   case EFI_IMAGE_REL_BASED_ARM_THUMB_MOVT:
00128     // For MOVT you need to know the lower 16-bits do do the math
00129     // So this relocation entry is really two entries.
00130     *Reloc = *Reloc + 1;
00131     Addend = *Reloc; 
00132     FixupVal = (UINT16)(((ThumbMovtImmediateAddress (Fixup16) << 16) + Adjust + *Addend) >> 16);
00133     ThumbMovtImmediatePatch (Fixup16, FixupVal);
00134 
00135     if (*FixupData != NULL) {
00136       *FixupData             = ALIGN_POINTER (*FixupData, sizeof (UINT16));
00137       *(UINT16 *)*FixupData  = *Fixup16;
00138       *FixupData             = *FixupData + sizeof (UINT16);
00139     }
00140     break;
00141   
00142   default:
00143     return RETURN_UNSUPPORTED;
00144   }
00145 
00146   return RETURN_SUCCESS;
00147 }
00148 
00162 BOOLEAN
00163 PeCoffLoaderImageFormatSupported (
00164   IN  UINT16  Machine
00165   )
00166 {
00167   if ((Machine == IMAGE_FILE_MACHINE_ARMTHUMB_MIXED) || (Machine ==  IMAGE_FILE_MACHINE_EBC)) {
00168     return TRUE; 
00169   }
00170 
00171   return FALSE;
00172 }
00173 
00187 RETURN_STATUS
00188 PeHotRelocateImageEx (
00189   IN UINT16      **Reloc,
00190   IN OUT CHAR8   *Fixup,
00191   IN OUT CHAR8   **FixupData,
00192   IN UINT64      Adjust
00193   )
00194 {
00195   UINT16  *Fixup16;
00196   UINT16  FixupVal;
00197   UINT16  *Addend;
00198 
00199   Fixup16 = (UINT16 *)Fixup;
00200 
00201   switch ((**Reloc) >> 12) {
00202   case EFI_IMAGE_REL_BASED_ARM_THUMB_MOVW:
00203     *FixupData  = ALIGN_POINTER (*FixupData, sizeof (UINT16));
00204     if (*(UINT16 *) (*FixupData) == *Fixup16) {
00205       FixupVal = ThumbMovtImmediateAddress (Fixup16) + (UINT16)Adjust;
00206       ThumbMovtImmediatePatch (Fixup16, FixupVal);
00207     }
00208     break;
00209 
00210   case EFI_IMAGE_REL_BASED_ARM_THUMB_MOVT:
00211     *FixupData  = ALIGN_POINTER (*FixupData, sizeof (UINT16));
00212     if (*(UINT16 *) (*FixupData) == *Fixup16) {
00213       // For MOVT you need to know the lower 16-bits do do the math
00214       // So this relocation entry is really two entries.
00215       *Reloc = *Reloc + 1;
00216       Addend = *Reloc; 
00217       FixupVal = (UINT16)(((ThumbMovtImmediateAddress (Fixup16) << 16) + Adjust + *Addend) >> 16);
00218       ThumbMovtImmediatePatch (Fixup16, FixupVal);
00219     }
00220     break;
00221 
00222   default:
00223     DEBUG ((EFI_D_ERROR, "PeHotRelocateEx:unknown fixed type\n"));
00224     return RETURN_UNSUPPORTED;
00225   }
00226 
00227   return RETURN_SUCCESS;
00228 }
00229 
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Defines