Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>\r
Portions copyright (c) 2013-2014, ARM Ltd. All rights reserved.<BR>\r
\r
-This program and the accompanying materials are licensed and made available\r
-under the terms and conditions of the BSD License which accompanies this\r
-distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
} else if (mEhdr->e_machine == EM_AARCH64) {\r
\r
switch (ELF_R_TYPE(Rel->r_info)) {\r
+ INT64 Offset;\r
+\r
+ case R_AARCH64_LD64_GOT_LO12_NC:\r
+ //\r
+ // Convert into an ADD instruction - see R_AARCH64_ADR_GOT_PAGE below.\r
+ //\r
+ *(UINT32 *)Targ &= 0x3ff;\r
+ *(UINT32 *)Targ |= 0x91000000 | ((Sym->st_value & 0xfff) << 10);\r
+ break;\r
+\r
+ case R_AARCH64_ADR_GOT_PAGE:\r
+ //\r
+ // This relocation points to the GOT entry that contains the absolute\r
+ // address of the symbol we are referring to. Since EDK2 only uses\r
+ // fully linked binaries, we can avoid the indirection, and simply\r
+ // refer to the symbol directly. This implies having to patch the\r
+ // subsequent LDR instruction (covered by a R_AARCH64_LD64_GOT_LO12_NC\r
+ // relocation) into an ADD instruction - this is handled above.\r
+ //\r
+ Offset = (Sym->st_value - (Rel->r_offset & ~0xfff)) >> 12;\r
+\r
+ *(UINT32 *)Targ &= 0x9000001f;\r
+ *(UINT32 *)Targ |= ((Offset & 0x1ffffc) << (5 - 2)) | ((Offset & 0x3) << 29);\r
+\r
+ /* fall through */\r
\r
case R_AARCH64_ADR_PREL_PG_HI21:\r
+ //\r
+ // In order to handle Cortex-A53 erratum #843419, the LD linker may\r
+ // convert ADRP instructions into ADR instructions, but without\r
+ // updating the static relocation type, and so we may end up here\r
+ // while the instruction in question is actually ADR. So let's\r
+ // just disregard it: the section offset check we apply below to\r
+ // ADR instructions will trigger for its R_AARCH64_xxx_ABS_LO12_NC\r
+ // companion instruction as well, so it is safe to omit it here.\r
+ //\r
+ if ((*(UINT32 *)Targ & BIT31) == 0) {\r
+ break;\r
+ }\r
+\r
//\r
// AArch64 PG_H21 relocations are typically paired with ABS_LO12\r
// relocations, where a PC-relative reference with +/- 4 GB range is\r
// Attempt to convert the ADRP into an ADR instruction.\r
// This is only possible if the symbol is within +/- 1 MB.\r
//\r
- INT64 Offset;\r
\r
// Decode the ADRP instruction\r
Offset = (INT32)((*(UINT32 *)Targ & 0xffffe0) << 8);\r
case R_AARCH64_LDST32_ABS_LO12_NC:\r
case R_AARCH64_LDST64_ABS_LO12_NC:\r
case R_AARCH64_LDST128_ABS_LO12_NC:\r
+ case R_AARCH64_ADR_GOT_PAGE:\r
+ case R_AARCH64_LD64_GOT_LO12_NC:\r
//\r
// No fixups are required for relative relocations, provided that\r
// the relative offsets between sections have been preserved in\r