Date   

Re: Ingebrigtsen: The End of Gmane?

Laszlo Ersek
 

On 07/31/16 04:25, Bruce Cran wrote:
On 7/28/2016 1:19 PM, Andrew Fish wrote:

Seems he will send you the disks. What could go wrong?
I'm actually tempted to take him up on that offer.
Just today I went looking for information about UefiDebugLib to see if
it was possible for a driver to print debug information to the serial
port (or other sort of debug device) instead of the console, and came
across the thread at
http://comments.gmane.org/gmane.comp.bios.tianocore.devel/3024 where
thanks to Google's cache I learned that:

"The EDK used some Tiano and implementation defined protocols to support
DEBUG and ASSERT macros. So DEBUG
and ASSERT from the EDK can only be reliably used if you compile all the
EDK firmware together. As Liming
points out it is much safer to use a UEFI console based debug message
for developing generic drivers and
applications."

It's a shame to lose information like that.
I think the Internet Archive intends to pick up the DB + WebUI:

https://lars.ingebrigtsen.no/2016/07/28/the-end-of-gmane/comment-page-1/#comment-13501

Also, from Lars Ingebrigtsen (speaking to a yet to be determined entity):

"I hand over the gmane.org domain to you [...] All previous
permalink.gmane.org (etc.) links continue to work as before, but they’ll
look new and spiffy in your new and spiffy web interface."

https://lars.ingebrigtsen.no/2016/07/28/the-end-of-gmane/comment-page-1/#comment-13502

(Actually, I'm a huge fan of the current (oldie but goldie) WebUI, so
"new and spiffy" is a minus for me, but at least the links should
continue to work.)

Going forward I'll have to constrain myself to the builtin mailman2
links at <https://lists.01.org/pipermail/edk2-devel/>. (Thanks again
Bruce and Mike for enabling those.)

Thanks
Laszlo


Re: bugzilla whining

Laszlo Ersek
 

On 07/29/16 18:10, Kinney, Michael D wrote:
Laszlo,

I have changed the global email setting for 'whinedays' to 0 to disable
that built-in Whine Event.

This means the only whine messages that should occur are Whine Events
added by individual users or administrators.
Thanks!

FYI...I had enabled that feature to make sure the cron jobs were
running correctly. Thanks for verifying :)
Haha, my pleasure :)

Cheers!
Laszlo


Re: [PATCH] ArmPkg/Library: Add ArmReadSctlr for aarch64

Ard Biesheuvel
 

On 30 July 2016 at 01:06, Supreeth Venkatesh <supreeth.venkatesh@arm.com> wrote:
One of the UEFI Self Certification tests (UEFI-SCT) need to read the
current exception level SCTLR Register.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: John Powell <john.powell@arm.com>
Signed-off-by: Supreeth Venkatesh <supreeth.venkatesh@arm.com>
---
Thanks for the patch. I don't think mentioning the UEFI-SCT here makes
any sense, since the function is defined in ArmLIb.h, and simply
missing from the AARCH64 implementation.

I fixed this up when applying (07783fdd67e4)

Thanks,
Ard.




ArmPkg/Library/ArmLib/Common/AArch64/ArmLibSupport.S | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/ArmPkg/Library/ArmLib/Common/AArch64/ArmLibSupport.S b/ArmPkg/Library/ArmLib/Common/AArch64/ArmLibSupport.S
index a6fd5e3..c9f3bd1 100644
--- a/ArmPkg/Library/ArmLib/Common/AArch64/ArmLibSupport.S
+++ b/ArmPkg/Library/ArmLib/Common/AArch64/ArmLibSupport.S
@@ -1,7 +1,7 @@
#------------------------------------------------------------------------------
#
# Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
-# Copyright (c) 2011 - 2014, ARM Limited. All rights reserved.
+# Copyright (c) 2011 - 2016, ARM Limited. All rights reserved.
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
@@ -39,6 +39,7 @@ GCC_ASM_EXPORT (ArmCallWFE)
GCC_ASM_EXPORT (ArmCallSEV)
GCC_ASM_EXPORT (ArmReadCpuActlr)
GCC_ASM_EXPORT (ArmWriteCpuActlr)
+GCC_ASM_EXPORT (ArmReadSctlr)

#------------------------------------------------------------------------------

@@ -205,4 +206,13 @@ ASM_PFX(ArmWriteCpuActlr):
isb
ret

+ASM_PFX(ArmReadSctlr):
+ EL1_OR_EL2_OR_EL3(x1)
+1:mrs x0, sctlr_el1
+ ret
+2:mrs x0, sctlr_el2
+ ret
+3:mrs x0, sctlr_el3
+4:ret
+
ASM_FUNCTION_REMOVE_IF_UNREFERENCED
--
2.8.0


Re: [PATCH 1/2] BaseTools/GenFw AARCH64: convert ADRP to ADR if binary size allows it

Ard Biesheuvel
 

On 27 July 2016 at 13:26, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
The ADRP instruction in the AArch64 ISA requires the link time and load
time offsets of a binary to be equal modulo 4 KB. The reason is that this
instruction always produces a multiple of 4 KB, and relies on a subsequent
ADD or LDR instruction to set the offset into the page. The resulting
symbol reference only produces the correct value if the symbol in question
resides at that exact offset into the page, and so loading the binary at
arbitrary offsets is not possible.

Due to the various levels of padding when packing FVs into FVs into FDs,
this alignment is very costly for XIP code, and so we would like to relax
this alignment requirement if possible.

Given that symbols that are sufficiently close (within 1 MB) of the
reference can also be reached using an ADR instruction which does not
suffer from this alignment issue, let's replace ADRP instructions with ADR
after linking if the offset can be encoded in this instruction's immediate
field. Note that this only makes sense if the section alignment is < 4 KB.
Otherwise, replacing the ADRP has no benefit, considering that the
subsequent ADD or LDR instruction is retained, and that micro-architectures
are more likely to be optimized for ADRP/ADD pairs (i.e., via micro op
fusing) than for ADR/ADD pairs, which are non-typical.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
@Liming, @Leif:

are there any objections to these patches? I know it is unfortunate
that we need to modify instructions as part of the ELF to PE/COFF
conversion, but it is very effective

ArmVirtQemu-AARCH64 built with CLANG35:

Before:

FVMAIN_COMPACT [41%Full] 2093056 total, 868416 used, 1224640 free
FVMAIN [99%Full] 4848064 total, 4848008 used, 56 free

After:

FVMAIN_COMPACT [36%Full] 2093056 total, 768064 used, 1324992 free
FVMAIN [99%Full] 4848064 total, 4848008 used, 56 free

For comparision, GCC49

FVMAIN_COMPACT [35%Full] 2093056 total, 749960 used, 1343096 free
FVMAIN [99%Full] 3929088 total, 3929032 used, 56 free

and GCC5 (with LTO)

FVMAIN_COMPACT [34%Full] 2093056 total, 732400 used, 1360656 free
FVMAIN [99%Full] 3730240 total, 3730216 used, 24 free

In other words, it turns CLANG35 from a pathetic outlier into
something usable :-)

Regards,
Ard.


[PATCH] IntelFsp2Pkg: Locate FSP Info Header dynamically

Satya Yarlagadda <satya.p.yarlagadda@...>
 

we need to locate the FSP Info Header by calculating offset dynamically to
handle the scenario of FSP component is being rebased to different location.

Cc: Maurice Ma <maurice.ma@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Giri P Mudusuru <giri.p.mudusuru@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Satya Yarlagadda <satya.p.yarlagadda@intel.com>
---
IntelFsp2Pkg/FspSecCore/Ia32/FspHelper.nasm | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/IntelFsp2Pkg/FspSecCore/Ia32/FspHelper.nasm b/IntelFsp2Pkg/FspSecCore/Ia32/FspHelper.nasm
index 00e953b..7d5fa5e 100644
--- a/IntelFsp2Pkg/FspSecCore/Ia32/FspHelper.nasm
+++ b/IntelFsp2Pkg/FspSecCore/Ia32/FspHelper.nasm
@@ -14,22 +14,22 @@
SECTION .text

global ASM_PFX(FspInfoHeaderRelativeOff)
-ASM_PFX(FspInfoHeaderRelativeOff):
- ;
- ; This value will be pached by the build script
- ;
- DD 0x12345678

global ASM_PFX(AsmGetFspBaseAddress)
ASM_PFX(AsmGetFspBaseAddress):
- mov eax, ASM_PFX(AsmGetFspInfoHeader)
- sub eax, dword [ASM_PFX(FspInfoHeaderRelativeOff)]
+ call ASM_PFX(AsmGetFspInfoHeader)
add eax, 0x1C
mov eax, dword [eax]
ret

global ASM_PFX(AsmGetFspInfoHeader)
ASM_PFX(AsmGetFspInfoHeader):
- mov eax, ASM_PFX(AsmGetFspInfoHeader)
- sub eax, dword [ASM_PFX(FspInfoHeaderRelativeOff)]
+ call ASM_PFX(NextInstruction)
+ASM_PFX(NextInstruction):
+ pop eax
+ sub eax, ASM_PFX(NextInstruction)
+ add eax, ASM_PFX(AsmGetFspInfoHeader)
+ ;sub eax, 012345678h
+ DB 02Dh
+ASM_PFX(FspInfoHeaderRelativeOff): DD 0x12345678
ret
--
2.9.2.windows.1


[patch 2/2] BaseTools/VfrCompile: Add two new option for VfrCompile

Dandan Bi
 

1.--autodefault option
VfrCompile will generate default opcodes for questions if some
default are missing.
2 --checkdefault option
VfrCompile will check whether every question has no default or
has all default. If not, will generate an error to let user know
the question misses default.

Cc: Liming Gao <liming.gao@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Dandan Bi <dandan.bi@intel.com>
Reviewed-by: Eric Dong <eric.dong@intel.com>
---
BaseTools/Source/C/VfrCompile/VfrCompiler.cpp | 56 +-
BaseTools/Source/C/VfrCompile/VfrCompiler.h | 3 +-
BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp | 788 ++++++++++++++++++++++--
BaseTools/Source/C/VfrCompile/VfrFormPkg.h | 33 +-
BaseTools/Source/C/VfrCompile/VfrSyntax.g | 118 ++--
BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp | 68 +-
BaseTools/Source/C/VfrCompile/VfrUtilityLib.h | 18 +-
7 files changed, 918 insertions(+), 166 deletions(-)

diff --git a/BaseTools/Source/C/VfrCompile/VfrCompiler.cpp b/BaseTools/Source/C/VfrCompile/VfrCompiler.cpp
index 695ce6c..59f4bf3 100644
--- a/BaseTools/Source/C/VfrCompile/VfrCompiler.cpp
+++ b/BaseTools/Source/C/VfrCompile/VfrCompiler.cpp
@@ -81,10 +81,12 @@ CVfrCompiler::OptionInitialization (
mOptions.SkipCPreprocessor = TRUE;
mOptions.CPreprocessorOptions = NULL;
mOptions.CompatibleMode = FALSE;
mOptions.HasOverrideClassGuid = FALSE;
mOptions.WarningAsError = FALSE;
+ mOptions.AutoDefault = FALSE;
+ mOptions.CheckDefault = FALSE;
memset (&mOptions.OverrideClassGuid, 0, sizeof (EFI_GUID));

if (Argc == 1) {
Usage ();
SET_RUN_STATUS (STATUS_DEAD);
@@ -158,10 +160,14 @@ CVfrCompiler::OptionInitialization (
goto Fail;
}
mOptions.HasOverrideClassGuid = TRUE;
} else if (stricmp(Argv[Index], "-w") == 0 || stricmp(Argv[Index], "--warning-as-error") == 0) {
mOptions.WarningAsError = TRUE;
+ } else if (stricmp(Argv[Index], "-a") == 0 ||stricmp(Argv[Index], "--autodefault") == 0) {
+ mOptions.AutoDefault = TRUE;
+ } else if (stricmp(Argv[Index], "-d") == 0 ||stricmp(Argv[Index], "--checkdefault") == 0) {
+ mOptions.CheckDefault = TRUE;
} else {
DebugError (NULL, 0, 1000, "Unknown option", "unrecognized option %s", Argv[Index]);
goto Fail;
}
}
@@ -435,10 +441,12 @@ CVfrCompiler::Usage (
" -g, --guid",
" override class guid input",
" format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
" -w --warning-as-error",
" treat warning as an error",
+ " -a --autodefaut generate default value for question opcode if some default is missing",
+ " -d --checkdefault check the default information in a question opcode",
NULL
};
for (Index = 0; Help[Index] != NULL; Index++) {
fprintf (stdout, "%s\n", Help[Index]);
}
@@ -580,57 +588,33 @@ Fail:
fclose (pInFile);
}
}

VOID
-CVfrCompiler::UpdateInfoForDynamicOpcode (
+CVfrCompiler::AdjustBin (
VOID
)
{
- SIfrRecord *pRecord;
+ EFI_VFR_RETURN_CODE Status;

- if (!gNeedAdjustOpcode) {
+ if (!IS_RUN_STATUS(STATUS_COMPILEED)) {
return;
}
-
- //
- // Base on the original offset info to update the record list.
- //
- if (!gCIfrRecordInfoDB.IfrAdjustDynamicOpcodeInRecords()) {
- DebugError (NULL, 0, 1001, "Error parsing vfr file", "Can find the offset in the record.");
- }

- //
- // Base on the opcode binary length to recalculate the offset for each opcode.
- //
- gCIfrRecordInfoDB.IfrAdjustOffsetForRecord();
+ if (gNeedAdjustOpcode) {
+ //
+ // When parsing the Vfr, has created some opcodes, now need to update the record info.
+ //
+ gCIfrRecordInfoDB.IfrUpdateRecordInfoForDynamicOpcode (FALSE);
+ }

//
- // Base on the offset to find the binary address.
+ // Check whether need to check default info for question or auto add default for question.
//
- pRecord = gCIfrRecordInfoDB.GetRecordInfoFromOffset(gAdjustOpcodeOffset);
- while (pRecord != NULL) {
- pRecord->mIfrBinBuf = gCFormPkg.GetBufAddrBaseOnOffset(pRecord->mOffset);
- if (pRecord->mIfrBinBuf == NULL) {
- DebugError (NULL, 0, 0001, "Error parsing vfr file", " 0x%X. offset not allocated.", pRecord->mOffset);
- }
- pRecord = pRecord->mNext;
+ if (mOptions.AutoDefault || mOptions.CheckDefault) {
+ gCIfrRecordInfoDB.IfrCheckAddDefaultRecord (mOptions.AutoDefault, mOptions.CheckDefault);
}
-}
-
-VOID
-CVfrCompiler::AdjustBin (
- VOID
- )
-{
- EFI_VFR_RETURN_CODE Status;
-
- if (!IS_RUN_STATUS(STATUS_COMPILEED)) {
- return;
- }
-
- UpdateInfoForDynamicOpcode ();

//
// Check Binary Code consistent between Form and IfrRecord
//

diff --git a/BaseTools/Source/C/VfrCompile/VfrCompiler.h b/BaseTools/Source/C/VfrCompile/VfrCompiler.h
index f2d9814..7dd9dd0 100644
--- a/BaseTools/Source/C/VfrCompile/VfrCompiler.h
+++ b/BaseTools/Source/C/VfrCompile/VfrCompiler.h
@@ -55,10 +55,12 @@ typedef struct {
CHAR8 *CPreprocessorOptions;
BOOLEAN CompatibleMode;
BOOLEAN HasOverrideClassGuid;
EFI_GUID OverrideClassGuid;
BOOLEAN WarningAsError;
+ BOOLEAN AutoDefault;
+ BOOLEAN CheckDefault;
} OPTIONS;

typedef enum {
STATUS_STARTED = 0,
STATUS_INITIALIZED,
@@ -86,11 +88,10 @@ private:
INT8 SetPreprocessorOutputFileName (VOID);
INT8 SetRecordListFileName (VOID);

VOID SET_RUN_STATUS (IN COMPILER_RUN_STATUS);
BOOLEAN IS_RUN_STATUS (IN COMPILER_RUN_STATUS);
- VOID UpdateInfoForDynamicOpcode (VOID);

public:
COMPILER_RUN_STATUS RunStatus (VOID) {
return mRunStatus;
}
diff --git a/BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp b/BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp
index 892b7b8..db1e4bd 100644
--- a/BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp
+++ b/BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp
@@ -650,71 +650,72 @@ CFormPkg::GetBufAddrBaseOnOffset (
return NULL;
}

EFI_VFR_RETURN_CODE
CFormPkg::AdjustDynamicInsertOpcode (
- IN CHAR8 *LastFormEndAddr,
- IN CHAR8 *InsertOpcodeAddr
+ IN CHAR8 *InserPositionAddr,
+ IN CHAR8 *InsertOpcodeAddr,
+ IN BOOLEAN CreateOpcodeAfterParsingVfr
)
{
- SBufferNode *LastFormEndNode;
+ SBufferNode *InserPositionNode;
SBufferNode *InsertOpcodeNode;
SBufferNode *NewRestoreNodeBegin;
SBufferNode *NewRestoreNodeEnd;
SBufferNode *NewLastEndNode;
SBufferNode *TmpNode;
UINT32 NeedRestoreCodeLen;

NewRestoreNodeEnd = NULL;

- LastFormEndNode = GetBinBufferNodeForAddr(LastFormEndAddr);
+ InserPositionNode = GetBinBufferNodeForAddr(InserPositionAddr);
InsertOpcodeNode = GetBinBufferNodeForAddr(InsertOpcodeAddr);

- if (LastFormEndNode == InsertOpcodeNode) {
+ if (InserPositionNode == InsertOpcodeNode) {
//
// Create New Node to save the restore opcode.
//
- NeedRestoreCodeLen = InsertOpcodeAddr - LastFormEndAddr;
+ NeedRestoreCodeLen = InsertOpcodeAddr - InserPositionAddr;
gAdjustOpcodeLen = NeedRestoreCodeLen;
NewRestoreNodeBegin = CreateNewNode ();
if (NewRestoreNodeBegin == NULL) {
return VFR_RETURN_OUT_FOR_RESOURCES;
}
- memcpy (NewRestoreNodeBegin->mBufferFree, LastFormEndAddr, NeedRestoreCodeLen);
+ memcpy (NewRestoreNodeBegin->mBufferFree, InserPositionAddr, NeedRestoreCodeLen);
NewRestoreNodeBegin->mBufferFree += NeedRestoreCodeLen;

//
// Override the restore buffer data.
//
- memmove (LastFormEndAddr, InsertOpcodeAddr, InsertOpcodeNode->mBufferFree - InsertOpcodeAddr);
+ memmove (InserPositionAddr, InsertOpcodeAddr, InsertOpcodeNode->mBufferFree - InsertOpcodeAddr);
InsertOpcodeNode->mBufferFree -= NeedRestoreCodeLen;
memset (InsertOpcodeNode->mBufferFree, 0, NeedRestoreCodeLen);
} else {
//
// Create New Node to save the restore opcode.
//
- NeedRestoreCodeLen = LastFormEndNode->mBufferFree - LastFormEndAddr;
+ NeedRestoreCodeLen = InserPositionNode->mBufferFree - InserPositionAddr;
gAdjustOpcodeLen = NeedRestoreCodeLen;
NewRestoreNodeBegin = CreateNewNode ();
if (NewRestoreNodeBegin == NULL) {
return VFR_RETURN_OUT_FOR_RESOURCES;
}
- memcpy (NewRestoreNodeBegin->mBufferFree, LastFormEndAddr, NeedRestoreCodeLen);
+ memcpy (NewRestoreNodeBegin->mBufferFree, InserPositionAddr, NeedRestoreCodeLen);
NewRestoreNodeBegin->mBufferFree += NeedRestoreCodeLen;
//
// Override the restore buffer data.
//
- LastFormEndNode->mBufferFree -= NeedRestoreCodeLen;
+ InserPositionNode->mBufferFree -= NeedRestoreCodeLen;
//
// Link the restore data to new node.
//
- NewRestoreNodeBegin->mNext = LastFormEndNode->mNext;
+ NewRestoreNodeBegin->mNext = InserPositionNode->mNext;

//
// Count the Adjust opcode len.
//
- TmpNode = LastFormEndNode->mNext;
+ TmpNode = InserPositionNode->mNext;
while (TmpNode != InsertOpcodeNode) {
gAdjustOpcodeLen += TmpNode->mBufferFree - TmpNode->mBufferStart;
TmpNode = TmpNode->mNext;
}

@@ -738,54 +739,68 @@ CFormPkg::AdjustDynamicInsertOpcode (

//
// Insert the last restore data node.
//
TmpNode = GetNodeBefore (InsertOpcodeNode);
- if (TmpNode == LastFormEndNode) {
+ if (TmpNode == InserPositionNode) {
NewRestoreNodeBegin->mNext = NewRestoreNodeEnd;
} else {
TmpNode->mNext = NewRestoreNodeEnd;
}
//
- // Connect the dynamic opcode node to the node before last form end node.
+ // Connect the dynamic opcode node to the node after InserPositionNode.
//
- LastFormEndNode->mNext = InsertOpcodeNode;
+ InserPositionNode->mNext = InsertOpcodeNode;
}
}

- if (mBufferNodeQueueTail->mBufferFree - mBufferNodeQueueTail->mBufferStart > 2) {
+ if (CreateOpcodeAfterParsingVfr) {
//
- // End form set opcode all in the mBufferNodeQueueTail node.
+ // Th new opcodes were created after Parsing Vfr file,
+ // so the content in mBufferNodeQueueTail must be the new created opcodes.
+ // So connet the NewRestoreNodeBegin to the tail and update the tail node.
//
- NewLastEndNode = CreateNewNode ();
- if (NewLastEndNode == NULL) {
- return VFR_RETURN_OUT_FOR_RESOURCES;
- }
- NewLastEndNode->mBufferStart[0] = 0x29;
- NewLastEndNode->mBufferStart[1] = 0x02;
- NewLastEndNode->mBufferFree += 2;
-
- mBufferNodeQueueTail->mBufferFree -= 2;
-
mBufferNodeQueueTail->mNext = NewRestoreNodeBegin;
if (NewRestoreNodeEnd != NULL) {
- NewRestoreNodeEnd->mNext = NewLastEndNode;
+ mBufferNodeQueueTail = NewRestoreNodeEnd;
} else {
- NewRestoreNodeBegin->mNext = NewLastEndNode;
+ mBufferNodeQueueTail = NewRestoreNodeBegin;
}
+ } else {
+ if (mBufferNodeQueueTail->mBufferFree - mBufferNodeQueueTail->mBufferStart > 2) {
+ //
+ // End form set opcode all in the mBufferNodeQueueTail node.
+ //
+ NewLastEndNode = CreateNewNode ();
+ if (NewLastEndNode == NULL) {
+ return VFR_RETURN_OUT_FOR_RESOURCES;
+ }
+ NewLastEndNode->mBufferStart[0] = 0x29;
+ NewLastEndNode->mBufferStart[1] = 0x02;
+ NewLastEndNode->mBufferFree += 2;

- mBufferNodeQueueTail = NewLastEndNode;
- } else if (mBufferNodeQueueTail->mBufferFree - mBufferNodeQueueTail->mBufferStart == 2) {
- TmpNode = GetNodeBefore(mBufferNodeQueueTail);
- TmpNode->mNext = NewRestoreNodeBegin;
- if (NewRestoreNodeEnd != NULL) {
- NewRestoreNodeEnd->mNext = mBufferNodeQueueTail;
- } else {
- NewRestoreNodeBegin->mNext = mBufferNodeQueueTail;
+ mBufferNodeQueueTail->mBufferFree -= 2;
+
+ mBufferNodeQueueTail->mNext = NewRestoreNodeBegin;
+ if (NewRestoreNodeEnd != NULL) {
+ NewRestoreNodeEnd->mNext = NewLastEndNode;
+ } else {
+ NewRestoreNodeBegin->mNext = NewLastEndNode;
+ }
+
+ mBufferNodeQueueTail = NewLastEndNode;
+ } else if (mBufferNodeQueueTail->mBufferFree - mBufferNodeQueueTail->mBufferStart == 2) {
+ TmpNode = GetNodeBefore(mBufferNodeQueueTail);
+ TmpNode->mNext = NewRestoreNodeBegin;
+ if (NewRestoreNodeEnd != NULL) {
+ NewRestoreNodeEnd->mNext = mBufferNodeQueueTail;
+ } else {
+ NewRestoreNodeBegin->mNext = mBufferNodeQueueTail;
+ }
}
}
-
+ mCurrBufferNode = mBufferNodeQueueTail;
return VFR_RETURN_SUCCESS;
}

EFI_VFR_RETURN_CODE
CFormPkg::DeclarePendingQuestion (
@@ -981,10 +996,14 @@ CIfrRecordInfoDB::CIfrRecordInfoDB (
{
mSwitch = TRUE;
mRecordCount = EFI_IFR_RECORDINFO_IDX_START;
mIfrRecordListHead = NULL;
mIfrRecordListTail = NULL;
+ mAllDefaultTypeCount = 0;
+ for (UINT8 i = 0; i < EFI_HII_MAX_SUPPORT_DEFAULT_TYPE; i++) {
+ mAllDefaultIdArray[i] = 0xffff;
+ }
}

CIfrRecordInfoDB::~CIfrRecordInfoDB (
VOID
)
@@ -1231,67 +1250,135 @@ CIfrRecordInfoDB::GetRecordInfoFromOffset (
}

return pNode;
}

-/*
+/**
Add just the op code position.

+ Case1 (CreateOpcodeAfterParsingVfr == FALSE): The dynamic opcodes were created before the formset opcode,
+ so pDynamicOpcodeNodes is before mIfrRecordListTail.
+
From
-
- | form end opcode + end of if opcode for form ... + Dynamic opcode + form set end opcode |
-
+
+ |mIfrRecordListHead + ...+ pAdjustNode + pDynamicOpcodeNodes + mIfrRecordListTail|
+
To
-
- | Dynamic opcode + form end opcode + end of if opcode for form ... + form set end opcode |

-*/
+ |mIfrRecordListHead + ...+ pDynamicOpcodeNodes + pAdjustNode + mIfrRecordListTail|
+
+ Case2 (CreateOpcodeAfterParsingVfr == TRUE): The dynamic opcodes were created after paring the vfr file,
+ so new records are appennded to the end of OriginalIfrRecordListTail.
+
+ From
+
+ |mIfrRecordListHead + ...+ pAdjustNode + ... + OriginalIfrRecordListTail + pDynamicOpcodeNodes|
+
+ To
+
+ |mIfrRecordListHead + ...+ pDynamicOpcodeNodes + pAdjustNode + ... + OriginalIfrRecordListTail|
+
+
+ @param CreateOpcodeAfterParsingVfr Whether create the dynamic opcode after parsing the VFR file.
+
+**/
BOOLEAN
CIfrRecordInfoDB::IfrAdjustDynamicOpcodeInRecords (
- VOID
+ IN BOOLEAN CreateOpcodeAfterParsingVfr
)
{
UINT32 OpcodeOffset;
SIfrRecord *pNode, *pPreNode;
- SIfrRecord *pStartNode, *pNodeBeforeStart;
- SIfrRecord *pEndNode;
-
- pStartNode = NULL;
- pEndNode = NULL;
- OpcodeOffset = 0;
+ SIfrRecord *pAdjustNode, *pNodeBeforeAdjust;
+ SIfrRecord *pNodeBeforeDynamic;
+
+ pAdjustNode = NULL;
+ pNodeBeforeDynamic = NULL;
+ OpcodeOffset = 0;

//
- // Base on the offset info to get the node.
+ // Base on the gAdjustOpcodeOffset and gAdjustOpcodeLen to find the pAdjustNod, the node before pAdjustNode,
+ // and the node before pDynamicOpcodeNode.
//
- for (pNode = mIfrRecordListHead; pNode->mNext != NULL; pPreNode = pNode,pNode = pNode->mNext) {
+ for (pNode = mIfrRecordListHead; pNode!= NULL; pNode = pNode->mNext) {
if (OpcodeOffset == gAdjustOpcodeOffset) {
- pStartNode = pNode;
- pNodeBeforeStart = pPreNode;
+ pAdjustNode = pNode;
+ pNodeBeforeAdjust = pPreNode;
} else if (OpcodeOffset == gAdjustOpcodeOffset + gAdjustOpcodeLen) {
- pEndNode = pPreNode;
+ pNodeBeforeDynamic = pPreNode;
+ }
+ if (pNode->mNext != NULL) {
+ pPreNode = pNode;
}
-
OpcodeOffset += pNode->mBinBufLen;
}

//
- // Check the value.
+ // Check the nodes whether exist.
//
- if (pEndNode == NULL || pStartNode == NULL) {
+ if (pNodeBeforeDynamic == NULL || pAdjustNode == NULL) {
return FALSE;
}

//
// Adjust the node. pPreNode save the Node before mIfrRecordListTail
//
- pNodeBeforeStart->mNext = pEndNode->mNext;
- pPreNode->mNext = pStartNode;
- pEndNode->mNext = mIfrRecordListTail;
+ pNodeBeforeAdjust->mNext = pNodeBeforeDynamic->mNext;
+ if (CreateOpcodeAfterParsingVfr) {
+ //
+ // mIfrRecordListTail is the end of pDynamicNode (Case2).
+ //
+ mIfrRecordListTail->mNext = pAdjustNode;
+ mIfrRecordListTail = pNodeBeforeDynamic;
+ mIfrRecordListTail->mNext = NULL;
+ } else {
+ //
+ //pPreNode is the end of pDynamicNode(Case1).
+ //
+ pPreNode->mNext = pAdjustNode;
+ pNodeBeforeDynamic->mNext = mIfrRecordListTail;
+ }

return TRUE;
}

+/**
+ Update the record info(the position in the record list, offset and mIfrBinBuf) for new created record.
+
+ @param CreateOpcodeAfterParsingVfr Whether create the dynamic opcode after parsing the VFR file.
+
+**/
+VOID
+CIfrRecordInfoDB::IfrUpdateRecordInfoForDynamicOpcode (
+ IN BOOLEAN CreateOpcodeAfterParsingVfr
+ )
+{
+ SIfrRecord *pRecord;
+
+ //
+ // Base on the original offset info to update the record list.
+ //
+ if (!IfrAdjustDynamicOpcodeInRecords(CreateOpcodeAfterParsingVfr)) {
+ gCVfrErrorHandle.PrintMsg (0, "Error", "Can not find the adjust offset in the record.");
+ }
+
+ //
+ // Base on the opcode binary length to recalculate the offset for each opcode.
+ //
+ IfrAdjustOffsetForRecord();
+
+ //
+ // Base on the offset to find the binary address.
+ //
+ pRecord = GetRecordInfoFromOffset(gAdjustOpcodeOffset);
+ while (pRecord != NULL) {
+ pRecord->mIfrBinBuf = gCFormPkg.GetBufAddrBaseOnOffset(pRecord->mOffset);
+ pRecord = pRecord->mNext;
+ }
+}
+
+
VOID
CIfrRecordInfoDB::IfrAdjustOffsetForRecord (
VOID
)
{
@@ -1520,10 +1607,583 @@ CIfrRecordInfoDB::IfrRecordAdjust (
IfrAdjustOffsetForRecord ();
}
return Status;
}

+/**
+ When the Varstore of the question is EFI_VFR_VARSTORE_BUFFER and the default value is not
+ given by expression, should save the default info for the Buffer VarStore.
+
+ @param DefaultId The default id.
+ @param pQuestionNode Point to the question opcode node.
+ @param Value The default value.
+**/
+VOID
+CIfrRecordInfoDB::IfrAddDefaultToBufferConfig (
+ IN UINT16 DefaultId,
+ IN SIfrRecord *pQuestionNode,
+ IN EFI_IFR_TYPE_VALUE Value
+ )
+{
+ CHAR8 *VarStoreName = NULL;
+ EFI_VFR_VARSTORE_TYPE VarStoreType = EFI_VFR_VARSTORE_INVALID;
+ EFI_GUID *VarGuid = NULL;
+ EFI_VARSTORE_INFO VarInfo;
+ EFI_IFR_QUESTION_HEADER *QuestionHead;
+ EFI_IFR_OP_HEADER *pQuestionOpHead;
+
+ pQuestionOpHead = (EFI_IFR_OP_HEADER *) pQuestionNode->mIfrBinBuf;
+ QuestionHead = (EFI_IFR_QUESTION_HEADER *) (pQuestionOpHead + 1);
+
+ //
+ // Get the Var Store name and type.
+ //
+ gCVfrDataStorage.GetVarStoreName (QuestionHead->VarStoreId, &VarStoreName);
+ VarGuid= gCVfrDataStorage.GetVarStoreGuid (QuestionHead->VarStoreId);
+ VarStoreType = gCVfrDataStorage.GetVarStoreType (QuestionHead->VarStoreId);
+
+ //
+ // Only for Buffer storage need to save the default info in the storage.
+ // Other type storage, just return.
+ //
+ if (VarStoreType != EFI_VFR_VARSTORE_BUFFER) {
+ return;
+ } else {
+ VarInfo.mInfo.mVarOffset = QuestionHead->VarStoreInfo.VarOffset;
+ VarInfo.mVarStoreId = QuestionHead->VarStoreId;
+ }
+
+ //
+ // Get the buffer storage info about this question.
+ //
+ gCVfrDataStorage.GetBufferVarStoreFieldInfo (&VarInfo);
+
+ //
+ // Add action.
+ //
+ gCVfrDefaultStore.BufferVarStoreAltConfigAdd (
+ DefaultId,
+ VarInfo,
+ VarStoreName,
+ VarGuid,
+ VarInfo.mVarType,
+ Value
+ );
+}
+
+/**
+ Record the number and default id of all defaultstore opcode.
+
+**/
+VOID
+CIfrRecordInfoDB::IfrGetDefaultStoreInfo (
+ VOID
+ )
+{
+ SIfrRecord *pNode;
+ EFI_IFR_OP_HEADER *pOpHead;
+ EFI_IFR_DEFAULTSTORE *DefaultStore;
+
+ pNode = mIfrRecordListHead;
+ mAllDefaultTypeCount = 0;
+
+ while (pNode != NULL) {
+ pOpHead = (EFI_IFR_OP_HEADER *) pNode->mIfrBinBuf;
+
+ if (pOpHead->OpCode == EFI_IFR_DEFAULTSTORE_OP){
+ DefaultStore = (EFI_IFR_DEFAULTSTORE *) pNode->mIfrBinBuf;
+ mAllDefaultIdArray[mAllDefaultTypeCount++] = DefaultStore->DefaultId;
+ }
+ pNode = pNode->mNext;
+ }
+}
+
+/**
+ Create new default opcode record.
+
+ @param Size The new default opcode size.
+ @param DefaultId The new default id.
+ @param Type The new default type.
+ @param LineNo The line number of the new record.
+ @param Value The new default value.
+
+**/
+VOID
+CIfrRecordInfoDB::IfrCreateDefaultRecord(
+ IN UINT8 Size,
+ IN UINT16 DefaultId,
+ IN UINT8 Type,
+ IN UINT32 LineNo,
+ IN EFI_IFR_TYPE_VALUE Value
+ )
+{
+ CIfrDefault *DObj;
+ CIfrDefault2 *DObj2;
+
+ DObj = NULL;
+ DObj2 = NULL;
+
+ if (Type == EFI_IFR_TYPE_OTHER) {
+ DObj2 = new CIfrDefault2 (Size);
+ DObj2->SetDefaultId(DefaultId);
+ DObj2->SetType(Type);
+ DObj2->SetLineNo(LineNo);
+ DObj2->SetScope (1);
+ delete DObj2;
+ } else {
+ DObj = new CIfrDefault (Size);
+ DObj->SetDefaultId(DefaultId);
+ DObj->SetType(Type);
+ DObj->SetLineNo(LineNo);
+ DObj->SetValue (Value);
+ delete DObj;
+ }
+}
+
+/**
+ Create new default opcode for question base on the QuestionDefaultInfo.
+
+ @param pQuestionNode Point to the question opcode Node.
+ @param QuestionDefaultInfo Point to the QuestionDefaultInfo for current question.
+
+**/
+VOID
+CIfrRecordInfoDB::IfrCreateDefaultForQuestion (
+ IN SIfrRecord *pQuestionNode,
+ IN QuestionDefaultRecord *QuestionDefaultInfo
+ )
+{
+ EFI_IFR_OP_HEADER *pOpHead;
+ EFI_IFR_DEFAULT *Default;
+ SIfrRecord *pSNode;
+ SIfrRecord *pENode;
+ SIfrRecord *pDefaultNode;
+ CIfrObj *Obj;
+ CHAR8 *ObjBinBuf;
+ UINT8 ScopeCount;
+ UINT8 OpcodeNumber;
+ UINT8 OpcodeCount;
+ UINT8 DefaultSize;
+ EFI_IFR_ONE_OF_OPTION *DefaultOptionOpcode;
+ EFI_IFR_TYPE_VALUE CheckBoxDefaultValue;
+
+ CheckBoxDefaultValue.b = 1;
+ pOpHead = (EFI_IFR_OP_HEADER *) pQuestionNode->mIfrBinBuf;
+ ScopeCount = 0;
+ OpcodeCount = 0;
+ Obj = NULL;
+
+ //
+ // Record the offset of node which need to be adjust, will move the new created default opcode to this offset.
+ //
+ gAdjustOpcodeOffset = pQuestionNode->mNext->mOffset;
+ //
+ // Case 1:
+ // For oneof, the default with smallest default id is given by the option flag.
+ // So create the missing defaults base on the oneof option value(mDefaultValueRecord).
+ //
+ if (pOpHead->OpCode == EFI_IFR_ONE_OF_OP && !QuestionDefaultInfo->mIsDefaultOpcode) {
+ DefaultOptionOpcode = (EFI_IFR_ONE_OF_OPTION *)QuestionDefaultInfo->mDefaultValueRecord->mIfrBinBuf;
+ DefaultSize = QuestionDefaultInfo->mDefaultValueRecord->mBinBufLen - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value);
+ DefaultSize += OFFSET_OF (EFI_IFR_DEFAULT, Value);
+ for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {
+ if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {
+ IfrCreateDefaultRecord (DefaultSize, mAllDefaultIdArray[i], DefaultOptionOpcode->Type, pQuestionNode->mLineNo, DefaultOptionOpcode->Value);
+ //
+ // Save the new created default in the buffer storage.
+ //
+ IfrAddDefaultToBufferConfig (mAllDefaultIdArray[i], pQuestionNode, DefaultOptionOpcode->Value);
+ }
+ }
+ return;
+ }
+
+ //
+ // Case2:
+ // For checkbox, the default with smallest default id is given by the question flag.
+ // And create the missing defaults with true value.
+ //
+ if (pOpHead-> OpCode == EFI_IFR_CHECKBOX_OP && !QuestionDefaultInfo->mIsDefaultOpcode) {
+ DefaultSize = OFFSET_OF (EFI_IFR_DEFAULT, Value) + sizeof (BOOLEAN);
+ for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {
+ if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {
+ IfrCreateDefaultRecord (DefaultSize, mAllDefaultIdArray[i], EFI_IFR_TYPE_BOOLEAN, pQuestionNode->mLineNo, CheckBoxDefaultValue);
+ //
+ // Save the new created default.
+ //
+ IfrAddDefaultToBufferConfig (mAllDefaultIdArray[i], pQuestionNode, CheckBoxDefaultValue);
+ }
+ }
+ return;
+ }
+
+ //
+ // Case3:
+ // The default with smallest default id is given by the default opcode.
+ // So create the missing defaults base on the value in the default opcode.
+ //
+
+ //
+ // pDefaultNode point to the mDefaultValueRecord in QuestionDefaultInfo.
+ //
+ pDefaultNode = QuestionDefaultInfo->mDefaultValueRecord;
+ Default = (EFI_IFR_DEFAULT *)pDefaultNode->mIfrBinBuf;
+ //
+ // Record the offset of node which need to be adjust, will move the new created default opcode to this offset.
+ //
+ gAdjustOpcodeOffset = pDefaultNode->mNext->mOffset;
+
+ if (Default->Type == EFI_IFR_TYPE_OTHER) {
+ //
+ // EFI_IFR_DEFAULT_2 opcode.
+ //
+ // Point to the first expression opcode.
+ //
+ pSNode = pDefaultNode->mNext;
+ ScopeCount++;
+ //
+ // Get opcode number behind the EFI_IFR_DEFAULT_2 until reach its END opcode (including the END opcode of EFI_IFR_DEFAULT_2)
+ //
+ while (pSNode != NULL && pSNode->mNext != NULL && ScopeCount != 0) {
+ pOpHead = (EFI_IFR_OP_HEADER *) pSNode->mIfrBinBuf;
+ if (pOpHead->Scope == 1) {
+ ScopeCount++;
+ }
+ if (pOpHead->OpCode == EFI_IFR_END_OP) {
+ ScopeCount--;
+ }
+ pENode = pSNode;
+ pSNode = pSNode->mNext;
+ OpcodeCount++;
+ }
+ //
+ // Record the offset of node which need to be adjust, will move the new created default opcode to this offset.
+ //
+ gAdjustOpcodeOffset = pSNode->mOffset;
+ //
+ // Create new default opcode node for missing default.
+ //
+ for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {
+ OpcodeNumber = OpcodeCount;
+ if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {
+ IfrCreateDefaultRecord (Default->Header.Length, mAllDefaultIdArray[i], Default->Type, pENode->mLineNo, Default->Value);
+ //
+ // Point to the first expression opcode node.
+ //
+ pSNode = pDefaultNode->mNext;
+ //
+ // Create the expression opcode and end opcode for the new created EFI_IFR_DEFAULT_2 opcode.
+ //
+ while (pSNode != NULL && pSNode->mNext != NULL && OpcodeNumber-- != 0) {
+ pOpHead = (EFI_IFR_OP_HEADER *) pSNode->mIfrBinBuf;
+ Obj = new CIfrObj (pOpHead->OpCode, NULL, pSNode->mBinBufLen, FALSE);
+ Obj->SetLineNo (pSNode->mLineNo);
+ ObjBinBuf = Obj->GetObjBinAddr();
+ memcpy (ObjBinBuf, pSNode->mIfrBinBuf, (UINTN)pSNode->mBinBufLen);
+ delete Obj;
+ pSNode = pSNode->mNext;
+ }
+ }
+ }
+ } else {
+ //
+ // EFI_IFR_DEFAULT opcode.
+ //
+ // Create new default opcode node for missing default.
+ //
+ for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {
+ if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {
+ IfrCreateDefaultRecord (Default->Header.Length, mAllDefaultIdArray[i], Default->Type, pDefaultNode->mLineNo, Default->Value);
+ //
+ // Save the new created default in the buffer storage..
+ //
+ IfrAddDefaultToBufferConfig (mAllDefaultIdArray[i], pQuestionNode, Default->Value);
+ }
+ }
+ }
+}
+
+/**
+ Parse the default information in a question, get the QuestionDefaultInfo.
+
+ @param pQuestionNode Point to the question record Node.
+ @param QuestionDefaultInfo On return, point to the QuestionDefaultInfo.
+**/
+VOID
+CIfrRecordInfoDB::IfrParseDefaulInfoInQuestion(
+ IN SIfrRecord *pQuestionNode,
+ OUT QuestionDefaultRecord *QuestionDefaultInfo
+ )
+{
+ SIfrRecord *pSNode;
+ EFI_IFR_ONE_OF_OPTION *OneofOptionOpcode;
+ EFI_IFR_OP_HEADER *pSOpHead;
+ EFI_IFR_CHECKBOX *CheckBoxOpcode;
+ EFI_IFR_DEFAULT *DefaultOpcode;
+ BOOLEAN IsOneOfOpcode;
+ UINT16 SmallestDefaultId;
+ UINT8 ScopeCount;
+
+ SmallestDefaultId = 0xffff;
+ IsOneOfOpcode = FALSE;
+ ScopeCount = 0;
+ pSNode = pQuestionNode;
+
+ //
+ // Parse all the opcodes in the Question.
+ //
+ while (pSNode != NULL) {
+ pSOpHead = (EFI_IFR_OP_HEADER *) pSNode->mIfrBinBuf;
+ //
+ // For a question, its scope bit must be set, the scope exists until it reaches a corresponding EFI_IFR_END_OP.
+ // Scopes may be nested within other scopes.
+ // When finishing parsing a question, the scope count must be zero.
+ //
+ if (pSOpHead->Scope == 1) {
+ ScopeCount++;
+ }
+ if (pSOpHead->OpCode == EFI_IFR_END_OP) {
+ ScopeCount--;
+ }
+ //
+ // Check whether finishing parsing a question.
+ //
+ if (ScopeCount == 0) {
+ break;
+ }
+
+ //
+ // Record the default information in the question.
+ //
+ switch (pSOpHead->OpCode) {
+ case EFI_IFR_ONE_OF_OP:
+ IsOneOfOpcode = TRUE;
+ break;
+ case EFI_IFR_CHECKBOX_OP:
+ //
+ // The default info of check box may be given by flag.
+ // So need to check the flag of check box.
+ //
+ CheckBoxOpcode = (EFI_IFR_CHECKBOX *)pSNode->mIfrBinBuf;
+ if ((CheckBoxOpcode->Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0) {
+ //
+ // Check whether need to update the smallest default id.
+ //
+ if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_STANDARD) {
+ SmallestDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
+ }
+ //
+ // Update the QuestionDefaultInfo.
+ //
+ for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {
+ if (mAllDefaultIdArray[i] == EFI_HII_DEFAULT_CLASS_STANDARD) {
+ if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {
+ QuestionDefaultInfo->mDefaultNumber ++;
+ QuestionDefaultInfo->mIsDefaultIdExist[i] = TRUE;
+ }
+ break;
+ }
+ }
+ }
+ if ((CheckBoxOpcode->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0) {
+ //
+ // Check whether need to update the smallest default id.
+ //
+ if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
+ SmallestDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
+ }
+ //
+ // Update the QuestionDefaultInfo.
+ //
+ for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {
+ if (mAllDefaultIdArray[i] == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
+ if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {
+ QuestionDefaultInfo->mDefaultNumber ++;
+ QuestionDefaultInfo->mIsDefaultIdExist[i] = TRUE;
+ }
+ break;
+ }
+ }
+ }
+ break;
+ case EFI_IFR_ONE_OF_OPTION_OP:
+ if (!IsOneOfOpcode) {
+ //
+ // Only check the option in oneof.
+ //
+ break;
+ }
+ OneofOptionOpcode = (EFI_IFR_ONE_OF_OPTION *)pSNode->mIfrBinBuf;
+ if ((OneofOptionOpcode->Flags & EFI_IFR_OPTION_DEFAULT) != 0) {
+ //
+ // The option is used as the standard default.
+ // Check whether need to update the smallest default id and QuestionDefaultInfo.
+ //
+ if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_STANDARD) {
+ SmallestDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
+ QuestionDefaultInfo->mDefaultValueRecord = pSNode;
+ }
+ //
+ // Update the IsDefaultIdExist array in QuestionDefaultInfo.
+ //
+ for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {
+ if (mAllDefaultIdArray[i] == EFI_HII_DEFAULT_CLASS_STANDARD) {
+ if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {
+ QuestionDefaultInfo->mDefaultNumber ++;
+ QuestionDefaultInfo->mIsDefaultIdExist[i] = TRUE;
+ }
+ break;
+ }
+ }
+ }
+ if ((OneofOptionOpcode->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0) {
+ //
+ // This option is used as the manufacture default.
+ // Check whether need to update the smallest default id and QuestionDefaultInfo.
+ //
+ if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
+ SmallestDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
+ QuestionDefaultInfo->mDefaultValueRecord = pSNode;
+ }
+ //
+ // Update the QuestionDefaultInfo.
+ //
+ for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {
+ if (mAllDefaultIdArray[i] == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
+ if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {
+ QuestionDefaultInfo->mDefaultNumber ++;
+ QuestionDefaultInfo->mIsDefaultIdExist[i] = TRUE;
+ }
+ break;
+ }
+ }
+ }
+ break;
+ case EFI_IFR_DEFAULT_OP:
+ DefaultOpcode = (EFI_IFR_DEFAULT *) pSNode->mIfrBinBuf;
+ //
+ // Check whether need to update the smallest default id and QuestionDefaultInfo.
+ //
+ if (SmallestDefaultId >= DefaultOpcode->DefaultId ) {
+ SmallestDefaultId = DefaultOpcode->DefaultId;
+ QuestionDefaultInfo->mDefaultValueRecord= pSNode;
+ QuestionDefaultInfo->mIsDefaultOpcode= TRUE;
+ }
+ //
+ // Update the QuestionDefaultInfo.
+ //
+ for (UINT8 i = 0; i < mAllDefaultTypeCount; i++){
+ if (mAllDefaultIdArray[i] == ((EFI_IFR_DEFAULT *)pSNode->mIfrBinBuf)->DefaultId) {
+ if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {
+ QuestionDefaultInfo->mDefaultNumber ++;
+ QuestionDefaultInfo->mIsDefaultIdExist[i] = TRUE;
+ }
+ break;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ //
+ // Parse next opcode in this question.
+ //
+ pSNode = pSNode->mNext;
+ }
+}
+
+/**
+ Check or add default for question if need.
+
+ This function will check the default info for question.
+ If the question has default, but the default number < defaultstore opcode number.
+ will do following two action :
+
+ 1. if (AutoDefault) will add default for question to support all kinds of defaults.
+ 2. if (CheckDefault) will generate an error to tell user the question misses some default value.
+
+ We assume that the two options can not be TRUE at same time.
+ If they are TRUE at same time, only do the action corresponding to AutoDefault option.
+
+ @param AutoDefault Add default for question if needed
+ @param CheckDefault Check the default info, if missing default, generates an error.
+
+**/
+VOID
+CIfrRecordInfoDB::IfrCheckAddDefaultRecord (
+ BOOLEAN AutoDefault,
+ BOOLEAN CheckDefault
+ )
+{
+ SIfrRecord *pNode;
+ SIfrRecord *pTailNode;
+ SIfrRecord *pStartAdjustNode;
+ EFI_IFR_OP_HEADER *pOpHead;
+ QuestionDefaultRecord QuestionDefaultInfo;
+ UINT8 MissingDefaultCount;
+ CHAR8 Msg[MAX_STRING_LEN] = {0, };
+
+ pNode = mIfrRecordListHead;
+
+ //
+ // Record the number and default id of all defaultstore opcode.
+ //
+ IfrGetDefaultStoreInfo ();
+
+ while (pNode != NULL) {
+ pOpHead = (EFI_IFR_OP_HEADER *) pNode->mIfrBinBuf;
+ //
+ // Check whether is question opcode.
+ //
+ if (CheckQuestionOpCode (pOpHead->OpCode)) {
+ //
+ // Initialize some local variables here, because they vary with question.
+ // Record the mIfrRecordListTail for each question, because may create default node for question after mIfrRecordListTail.
+ //
+ memset (&QuestionDefaultInfo, 0, sizeof (QuestionDefaultRecord));
+ pTailNode = mIfrRecordListTail;
+ //
+ // Get the QuestionDefaultInfo for current question.
+ //
+ IfrParseDefaulInfoInQuestion (pNode, &QuestionDefaultInfo);
+
+ if (QuestionDefaultInfo.mDefaultNumber != mAllDefaultTypeCount && QuestionDefaultInfo.mDefaultNumber != 0) {
+ if (AutoDefault) {
+ //
+ // Create default for question which misses default.
+ //
+ IfrCreateDefaultForQuestion (pNode, &QuestionDefaultInfo);
+
+ //
+ // Adjust the buffer content.
+ // pStartAdjustNode->mIfrBinBuf points to the insert position.
+ // pTailNode->mNext->mIfrBinBuf points to the inset opcodes.
+ //
+ pStartAdjustNode =GetRecordInfoFromOffset (gAdjustOpcodeOffset);
+ gCFormPkg.AdjustDynamicInsertOpcode (pStartAdjustNode->mIfrBinBuf, pTailNode->mNext->mIfrBinBuf, TRUE);
+
+ //
+ // Update the record info.
+ //
+ IfrUpdateRecordInfoForDynamicOpcode (TRUE);
+ } else if (CheckDefault) {
+ //
+ // Generate an error for question which misses default.
+ //
+ MissingDefaultCount = mAllDefaultTypeCount - QuestionDefaultInfo.mDefaultNumber;
+ sprintf (Msg, "The question misses %d default, the question's opcode is %d", MissingDefaultCount, pOpHead->OpCode);
+ gCVfrErrorHandle.PrintMsg (pNode->mLineNo, NULL, "Error", Msg);
+ }
+ }
+ }
+ //
+ // parse next opcode.
+ //
+ pNode = pNode->mNext;
+ }
+}
+
CIfrRecordInfoDB gCIfrRecordInfoDB;

VOID
CIfrObj::_EMIT_PENDING_OBJ (
VOID
diff --git a/BaseTools/Source/C/VfrCompile/VfrFormPkg.h b/BaseTools/Source/C/VfrCompile/VfrFormPkg.h
index 644dfdd..051df28 100644
--- a/BaseTools/Source/C/VfrCompile/VfrFormPkg.h
+++ b/BaseTools/Source/C/VfrCompile/VfrFormPkg.h
@@ -1,10 +1,10 @@
/** @file

The definition of CFormPkg's member function

-Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php

@@ -152,11 +152,12 @@ public:
IN UINT32 LineNo,
OUT CHAR8 **InsertOpcodeAddr
);
EFI_VFR_RETURN_CODE AdjustDynamicInsertOpcode (
IN CHAR8 *LastFormEndAddr,
- IN CHAR8 *InsertOpcodeAddr
+ IN CHAR8 *InsertOpcodeAddr,
+ IN BOOLEAN CreateOpcodeAfterParsingVfr
);
CHAR8 * GetBufAddrBaseOnOffset (
IN UINT32 Offset
);
};
@@ -175,19 +176,36 @@ struct SIfrRecord {

SIfrRecord (VOID);
~SIfrRecord (VOID);
};

+
#define EFI_IFR_RECORDINFO_IDX_INVALUD 0xFFFFFF
#define EFI_IFR_RECORDINFO_IDX_START 0x0
+#define EFI_HII_MAX_SUPPORT_DEFAULT_TYPE 0x08
+
+struct QuestionDefaultRecord {
+ BOOLEAN mIsDefaultIdExist[EFI_HII_MAX_SUPPORT_DEFAULT_TYPE]; // Record the default id in mAllDefaultIdArray[EFI_HII_MAX_SUPPORT_DEFAULT_TYPE]
+ // whether exists in current question.
+
+ SIfrRecord *mDefaultValueRecord; // Point to the default value record in RecordList which has smallest default Id.
+ // (for checkbox it may be NULL, because the dedault value is always true when the flag is set.)
+
+ BOOLEAN mIsDefaultOpcode; // whether the default value with smallest default id is given by default opcode.
+ // (for oneof and checkbox default info may be given by flag.)
+
+ UINT16 mDefaultNumber; // The default number of this question.
+};

class CIfrRecordInfoDB {
private:
bool mSwitch;
UINT32 mRecordCount;
SIfrRecord *mIfrRecordListHead;
SIfrRecord *mIfrRecordListTail;
+ UINT8 mAllDefaultTypeCount;
+ UINT16 mAllDefaultIdArray[EFI_HII_MAX_SUPPORT_DEFAULT_TYPE];

SIfrRecord * GetRecordInfoFromIdx (IN UINT32);
BOOLEAN CheckQuestionOpCode (IN UINT8);
BOOLEAN CheckIdOpCode (IN UINT8);
EFI_QUESTION_ID GetOpcodeQuestionId (IN EFI_IFR_OP_HEADER *);
@@ -203,17 +221,24 @@ public:
mSwitch = FALSE;
}

SIfrRecord * GetRecordInfoFromOffset (IN UINT32);
VOID IfrAdjustOffsetForRecord (VOID);
- BOOLEAN IfrAdjustDynamicOpcodeInRecords (VOID);
+ BOOLEAN IfrAdjustDynamicOpcodeInRecords (IN BOOLEAN);

UINT32 IfrRecordRegister (IN UINT32, IN CHAR8 *, IN UINT8, IN UINT32);
VOID IfrRecordInfoUpdate (IN UINT32, IN UINT32, IN CHAR8*, IN UINT8, IN UINT32);
VOID IfrRecordOutput (IN FILE *, IN UINT32 LineNo);
VOID IfrRecordOutput (OUT PACKAGE_DATA &);
- EFI_VFR_RETURN_CODE IfrRecordAdjust (VOID);
+ EFI_VFR_RETURN_CODE IfrRecordAdjust (VOID);
+ VOID IfrUpdateRecordInfoForDynamicOpcode (IN BOOLEAN);
+ VOID IfrCheckAddDefaultRecord (IN BOOLEAN, IN BOOLEAN);
+ VOID IfrGetDefaultStoreInfo ();
+ VOID IfrCreateDefaultRecord (IN UINT8 Size,IN UINT16 DefaultId,IN UINT8 Type,IN UINT32 LineNo,IN EFI_IFR_TYPE_VALUE Value);
+ VOID IfrCreateDefaultForQuestion (IN SIfrRecord *, IN QuestionDefaultRecord *);
+ VOID IfrParseDefaulInfoInQuestion (IN SIfrRecord *, OUT QuestionDefaultRecord *);
+ VOID IfrAddDefaultToBufferConfig (IN UINT16, IN SIfrRecord *,IN EFI_IFR_TYPE_VALUE);
};

extern CIfrRecordInfoDB gCIfrRecordInfoDB;

/*
diff --git a/BaseTools/Source/C/VfrCompile/VfrSyntax.g b/BaseTools/Source/C/VfrCompile/VfrSyntax.g
index 55a9a23..4b42d3c 100644
--- a/BaseTools/Source/C/VfrCompile/VfrSyntax.g
+++ b/BaseTools/Source/C/VfrCompile/VfrSyntax.g
@@ -594,11 +594,11 @@ vfrFormSetDefinition :
// Declare undefined Question so that they can be used in expression.
//
if (gCFormPkg.HavePendingUnassigned()) {
mParserStatus += gCFormPkg.DeclarePendingQuestion (
gCVfrVarDataTypeDB,
- mCVfrDataStorage,
+ gCVfrDataStorage,
mCVfrQuestionDB,
&mFormsetGuid,
E->getLine(),
&InsertOpcodeAddr
);
@@ -612,11 +612,12 @@ vfrFormSetDefinition :
// Move the position from current to before the end of the last form in the form set.
//
if (gNeedAdjustOpcode) {
gCFormPkg.AdjustDynamicInsertOpcode (
mLastFormEndAddr,
- InsertOpcodeAddr
+ InsertOpcodeAddr,
+ FALSE
);
}

if (FSObj != NULL) {
delete FSObj;
@@ -832,18 +833,18 @@ vfrStatementDefaultStore :
Prompt "=" "STRING_TOKEN" "\(" S:Number "\)"
{
"," Attribute "=" A:Number << DefaultId = _STOU16(A->getText(), A->getLine()); >>
}
<<
- if (mCVfrDefaultStore.DefaultIdRegistered (DefaultId) == FALSE) {
+ if (gCVfrDefaultStore.DefaultIdRegistered (DefaultId) == FALSE) {
CIfrDefaultStore DSObj;
- _PCATCH(mCVfrDefaultStore.RegisterDefaultStore (DSObj.GetObjBinAddr(), N->getText(), _STOSID(S->getText(), S->getLine()), DefaultId)), D->getLine();
+ _PCATCH(gCVfrDefaultStore.RegisterDefaultStore (DSObj.GetObjBinAddr(), N->getText(), _STOSID(S->getText(), S->getLine()), DefaultId)), D->getLine();
DSObj.SetLineNo(D->getLine());
DSObj.SetDefaultName (_STOSID(S->getText(), S->getLine()));
DSObj.SetDefaultId (DefaultId);
} else {
- _PCATCH(mCVfrDefaultStore.ReRegisterDefaultStoreById (DefaultId, N->getText(), _STOSID(S->getText(), S->getLine()))), D->getLine();
+ _PCATCH(gCVfrDefaultStore.ReRegisterDefaultStoreById (DefaultId, N->getText(), _STOSID(S->getText(), S->getLine()))), D->getLine();
}
>>
";"
;

@@ -891,19 +892,19 @@ vfrStatementVarStoreLinear :
if (mCompatibleMode) {
StoreName = TypeName;
} else {
StoreName = SN->getText();
}
- _PCATCH(mCVfrDataStorage.DeclareBufferVarStore (
+ _PCATCH(gCVfrDataStorage.DeclareBufferVarStore (
StoreName,
&Guid,
&gCVfrVarDataTypeDB,
TypeName,
VarStoreId
), LineNum);
VSObj.SetGuid (&Guid);
- _PCATCH(mCVfrDataStorage.GetVarStoreId(StoreName, &VarStoreId, &Guid), SN);
+ _PCATCH(gCVfrDataStorage.GetVarStoreId(StoreName, &VarStoreId, &Guid), SN);
VSObj.SetVarStoreId (VarStoreId);
_PCATCH(gCVfrVarDataTypeDB.GetDataTypeSize(TypeName, &Size), LineNum);
VSObj.SetSize ((UINT16) Size);
VSObj.SetName (SN->getText());
>>
@@ -983,28 +984,28 @@ vfrStatementVarStoreEfi :
>>
)

Uuid "=" guidDefinition[Guid] <<
if (IsUEFI23EfiVarstore) {
- _PCATCH(mCVfrDataStorage.DeclareBufferVarStore (
+ _PCATCH(gCVfrDataStorage.DeclareBufferVarStore (
StoreName,
&Guid,
&gCVfrVarDataTypeDB,
TypeName,
VarStoreId
), LineNum);
- _PCATCH(mCVfrDataStorage.GetVarStoreId(StoreName, &VarStoreId, &Guid), SN);
+ _PCATCH(gCVfrDataStorage.GetVarStoreId(StoreName, &VarStoreId, &Guid), SN);
_PCATCH(gCVfrVarDataTypeDB.GetDataTypeSize(TypeName, &Size), LineNum);
} else {
- _PCATCH(mCVfrDataStorage.DeclareBufferVarStore (
+ _PCATCH(gCVfrDataStorage.DeclareBufferVarStore (
TN->getText(),
&Guid,
&gCVfrVarDataTypeDB,
TypeName,
VarStoreId
), LineNum);
- _PCATCH(mCVfrDataStorage.GetVarStoreId(TN->getText(), &VarStoreId, &Guid), VN);
+ _PCATCH(gCVfrDataStorage.GetVarStoreId(TN->getText(), &VarStoreId, &Guid), VN);
_PCATCH(gCVfrVarDataTypeDB.GetDataTypeSize(TypeName, &Size), N->getLine());
}
VSEObj.SetGuid (&Guid);
VSEObj.SetVarStoreId (VarStoreId);

@@ -1041,20 +1042,20 @@ vfrStatementVarStoreNameValue :
>>
}
(
Name "=" "STRING_TOKEN" "\(" N:Number "\)" "," <<
if (!Created) {
- _PCATCH(mCVfrDataStorage.DeclareNameVarStoreBegin (SN->getText(), VarStoreId), SN);
+ _PCATCH(gCVfrDataStorage.DeclareNameVarStoreBegin (SN->getText(), VarStoreId), SN);
Created = TRUE;
}
- _PCATCH(mCVfrDataStorage.NameTableAddItem (_STOSID(N->getText(), N->getLine())), SN);
+ _PCATCH(gCVfrDataStorage.NameTableAddItem (_STOSID(N->getText(), N->getLine())), SN);
>>
)+
- Uuid "=" guidDefinition[Guid] << _PCATCH(mCVfrDataStorage.DeclareNameVarStoreEnd (&Guid), SN); >>
+ Uuid "=" guidDefinition[Guid] << _PCATCH(gCVfrDataStorage.DeclareNameVarStoreEnd (&Guid), SN); >>
<<
VSNVObj.SetGuid (&Guid);
- _PCATCH(mCVfrDataStorage.GetVarStoreId(SN->getText(), &VarStoreId, &Guid), SN);
+ _PCATCH(gCVfrDataStorage.GetVarStoreId(SN->getText(), &VarStoreId, &Guid), SN);
VSNVObj.SetVarStoreId (VarStoreId);
>>
";"
;

@@ -1242,51 +1243,51 @@ vfrStorageVarId[EFI_VARSTORE_INFO & Info, CHAR8 *&QuestVarIdStr, BOOLEAN CheckFl
_STRCAT(&VarIdStr, "[");
_STRCAT(&VarIdStr, I1->getText());
_STRCAT(&VarIdStr, "]");
>>
<<
- VfrReturnCode = mCVfrDataStorage.GetVarStoreId(SName, &$Info.mVarStoreId);
+ VfrReturnCode = gCVfrDataStorage.GetVarStoreId(SName, &$Info.mVarStoreId);
if (mCompatibleMode && VfrReturnCode == VFR_RETURN_UNDEFINED) {
- mCVfrDataStorage.DeclareBufferVarStore (
+ gCVfrDataStorage.DeclareBufferVarStore (
SName,
&mFormsetGuid,
&gCVfrVarDataTypeDB,
SName,
EFI_VARSTORE_ID_INVALID,
FALSE
);
- VfrReturnCode = mCVfrDataStorage.GetVarStoreId(SName, &$Info.mVarStoreId, &mFormsetGuid);
+ VfrReturnCode = gCVfrDataStorage.GetVarStoreId(SName, &$Info.mVarStoreId, &mFormsetGuid);
}
if (CheckFlag || VfrReturnCode == VFR_RETURN_SUCCESS) {
_PCATCH(VfrReturnCode, SN1);
- _PCATCH(mCVfrDataStorage.GetNameVarStoreInfo (&$Info, Idx), SN1);
+ _PCATCH(gCVfrDataStorage.GetNameVarStoreInfo (&$Info, Idx), SN1);
}

QuestVarIdStr = VarIdStr;
>>
)
|
(
SN2:StringIdentifier << SName = SN2->getText(); _STRCAT(&VarIdStr, SName); >>
<<
- VfrReturnCode = mCVfrDataStorage.GetVarStoreId(SName, &$Info.mVarStoreId);
+ VfrReturnCode = gCVfrDataStorage.GetVarStoreId(SName, &$Info.mVarStoreId);
if (mCompatibleMode && VfrReturnCode == VFR_RETURN_UNDEFINED) {
- mCVfrDataStorage.DeclareBufferVarStore (
+ gCVfrDataStorage.DeclareBufferVarStore (
SName,
&mFormsetGuid,
&gCVfrVarDataTypeDB,
SName,
EFI_VARSTORE_ID_INVALID,
FALSE
);
- VfrReturnCode = mCVfrDataStorage.GetVarStoreId(SName, &$Info.mVarStoreId, &mFormsetGuid);
+ VfrReturnCode = gCVfrDataStorage.GetVarStoreId(SName, &$Info.mVarStoreId, &mFormsetGuid);
}
if (CheckFlag || VfrReturnCode == VFR_RETURN_SUCCESS) {
_PCATCH(VfrReturnCode, SN2);
- VarStoreType = mCVfrDataStorage.GetVarStoreType ($Info.mVarStoreId);
+ VarStoreType = gCVfrDataStorage.GetVarStoreType ($Info.mVarStoreId);
if (VarStoreType == EFI_VFR_VARSTORE_BUFFER) {
- _PCATCH(mCVfrDataStorage.GetBufferVarStoreDataTypeName(Info.mVarStoreId, &TName), SN2);
+ _PCATCH(gCVfrDataStorage.GetBufferVarStoreDataTypeName(Info.mVarStoreId, &TName), SN2);
_STRCAT(&VarStr, TName);
}
}
>>

@@ -1317,15 +1318,15 @@ vfrStorageVarId[EFI_VARSTORE_INFO & Info, CHAR8 *&QuestVarIdStr, BOOLEAN CheckFl
>>
}
)* <<
switch (VarStoreType) {
case EFI_VFR_VARSTORE_EFI:
- _PCATCH(mCVfrDataStorage.GetEfiVarStoreInfo (&$Info), SN2);
+ _PCATCH(gCVfrDataStorage.GetEfiVarStoreInfo (&$Info), SN2);
break;
case EFI_VFR_VARSTORE_BUFFER:
_PCATCH(gCVfrVarDataTypeDB.GetDataFieldInfo (VarStr, $Info.mInfo.mVarOffset, $Info.mVarType, $Info.mVarTotalSize), SN2->getLine(), VarStr);
- VarGuid = mCVfrDataStorage.GetVarStoreGuid($Info.mVarStoreId);
+ VarGuid = gCVfrDataStorage.GetVarStoreGuid($Info.mVarStoreId);
_PCATCH((EFI_VFR_RETURN_CODE)gCVfrBufferConfig.Register (
SName,
VarGuid,
NULL),
SN2->getLine());
@@ -1337,10 +1338,11 @@ vfrStorageVarId[EFI_VARSTORE_INFO & Info, CHAR8 *&QuestVarIdStr, BOOLEAN CheckFl
$Info.mVarType,
$Info.mInfo.mVarOffset,
$Info.mVarTotalSize,
Dummy),
SN2->getLine());
+ _PCATCH(gCVfrDataStorage.AddBufferVarStoreFieldInfo(&$Info ),SN2->getLine());
break;
case EFI_VFR_VARSTORE_NAME:
default: break;
}

@@ -1759,11 +1761,11 @@ vfrStatementDefault :
| << IsExp = TRUE; DObj2 = new CIfrDefault2; DObj2->SetLineNo(D->getLine()); DObj2->SetScope (1); >>
vfrStatementValue "," << CIfrEnd EndObj1; EndObj1.SetLineNo(D->getLine()); >>
)
{
DefaultStore "=" SN:StringIdentifier "," <<
- _PCATCH(mCVfrDefaultStore.GetDefaultId (SN->getText(), &DefaultId), SN);
+ _PCATCH(gCVfrDefaultStore.GetDefaultId (SN->getText(), &DefaultId), SN);
if (DObj != NULL) {
DObj->SetDefaultId (DefaultId);
}

if (DObj2 != NULL) {
@@ -1772,15 +1774,15 @@ vfrStatementDefault :
>>
}
<<
CheckDuplicateDefaultValue (DefaultId, D);
if (_GET_CURRQEST_VARTINFO().mVarStoreId != EFI_VARSTORE_ID_INVALID) {
- _PCATCH(mCVfrDataStorage.GetVarStoreName (_GET_CURRQEST_VARTINFO().mVarStoreId, &VarStoreName), D->getLine());
- VarGuid = mCVfrDataStorage.GetVarStoreGuid(_GET_CURRQEST_VARTINFO().mVarStoreId);
- VarStoreType = mCVfrDataStorage.GetVarStoreType (_GET_CURRQEST_VARTINFO().mVarStoreId);
+ _PCATCH(gCVfrDataStorage.GetVarStoreName (_GET_CURRQEST_VARTINFO().mVarStoreId, &VarStoreName), D->getLine());
+ VarGuid = gCVfrDataStorage.GetVarStoreGuid(_GET_CURRQEST_VARTINFO().mVarStoreId);
+ VarStoreType = gCVfrDataStorage.GetVarStoreType (_GET_CURRQEST_VARTINFO().mVarStoreId);
if ((IsExp == FALSE) && (VarStoreType == EFI_VFR_VARSTORE_BUFFER)) {
- _PCATCH(mCVfrDefaultStore.BufferVarStoreAltConfigAdd (
+ _PCATCH(gCVfrDefaultStore.BufferVarStoreAltConfigAdd (
DefaultId,
_GET_CURRQEST_VARTINFO(),
VarStoreName,
VarGuid,
_GET_CURRQEST_DATATYPE (),
@@ -2129,11 +2131,11 @@ vfrStatementResetButton :
UINT16 DefaultId;
>>
L:ResetButton << RBObj.SetLineNo(L->getLine()); >>
DefaultStore
"=" N:StringIdentifier "," <<
- _PCATCH(mCVfrDefaultStore.GetDefaultId (N->getText(), &DefaultId), N->getLine());
+ _PCATCH(gCVfrDefaultStore.GetDefaultId (N->getText(), &DefaultId), N->getLine());
RBObj.SetDefaultId (DefaultId);
>>
vfrStatementHeader[&RBObj] ","
{ vfrStatementStatTagList "," }
E:EndResetButton << CRT_END_OP (E); >>
@@ -2172,27 +2174,27 @@ vfrStatementCheckBox :
}
if (_GET_CURRQEST_VARTINFO().mVarStoreId != EFI_VARSTORE_ID_INVALID) {
_PCATCH (gCVfrVarDataTypeDB.GetDataTypeSize (_GET_CURRQEST_DATATYPE(), &DataTypeSize), L->getLine(), "CheckBox varid is not the valid data type");
if (DataTypeSize != 0 && DataTypeSize != _GET_CURRQEST_VARSIZE()) {
_PCATCH (VFR_RETURN_INVALID_PARAMETER, L->getLine(), "CheckBox varid doesn't support array");
- } else if ((mCVfrDataStorage.GetVarStoreType (_GET_CURRQEST_VARTINFO().mVarStoreId) == EFI_VFR_VARSTORE_BUFFER) &&
+ } else if ((gCVfrDataStorage.GetVarStoreType (_GET_CURRQEST_VARTINFO().mVarStoreId) == EFI_VFR_VARSTORE_BUFFER) &&
(_GET_CURRQEST_VARSIZE() != sizeof (BOOLEAN))) {
_PCATCH (VFR_RETURN_INVALID_PARAMETER, L->getLine(), "CheckBox varid only support BOOLEAN data type");
}
}
>>
{
F:FLAGS "=" vfrCheckBoxFlags[CBObj, F->getLine()] ","
<<
if (_GET_CURRQEST_VARTINFO().mVarStoreId != EFI_VARSTORE_ID_INVALID) {
- _PCATCH(mCVfrDataStorage.GetVarStoreName (_GET_CURRQEST_VARTINFO().mVarStoreId, &VarStoreName), VFR_RETURN_SUCCESS, L, "Failed to retrieve varstore name");
- VarStoreGuid = mCVfrDataStorage.GetVarStoreGuid(_GET_CURRQEST_VARTINFO().mVarStoreId);
+ _PCATCH(gCVfrDataStorage.GetVarStoreName (_GET_CURRQEST_VARTINFO().mVarStoreId, &VarStoreName), VFR_RETURN_SUCCESS, L, "Failed to retrieve varstore name");
+ VarStoreGuid = gCVfrDataStorage.GetVarStoreGuid(_GET_CURRQEST_VARTINFO().mVarStoreId);
Val.b = TRUE;
if (CBObj.GetFlags () & 0x01) {
CheckDuplicateDefaultValue (EFI_HII_DEFAULT_CLASS_STANDARD, F);
_PCATCH(
- mCVfrDefaultStore.BufferVarStoreAltConfigAdd (
+ gCVfrDefaultStore.BufferVarStoreAltConfigAdd (
EFI_HII_DEFAULT_CLASS_STANDARD,
_GET_CURRQEST_VARTINFO(),
VarStoreName,
VarStoreGuid,
_GET_CURRQEST_DATATYPE (),
@@ -2204,11 +2206,11 @@ vfrStatementCheckBox :
);
}
if (CBObj.GetFlags () & 0x02) {
CheckDuplicateDefaultValue (EFI_HII_DEFAULT_CLASS_MANUFACTURING, F);
_PCATCH(
- mCVfrDefaultStore.BufferVarStoreAltConfigAdd (
+ gCVfrDefaultStore.BufferVarStoreAltConfigAdd (
EFI_HII_DEFAULT_CLASS_MANUFACTURING,
_GET_CURRQEST_VARTINFO(),
VarStoreName,
VarStoreGuid,
_GET_CURRQEST_DATATYPE (),
@@ -2701,11 +2703,11 @@ vfrNumericFlags [CIfrNumeric & NObj, UINT32 LineNum] :
>>
numericFlagsField[HFlags, LFlags, IsSetType, IsDisplaySpecified] ( "\|" numericFlagsField[HFlags, LFlags, IsSetType, IsDisplaySpecified ] )*
<<
//check data type flag
if (_GET_CURRQEST_VARTINFO().mVarStoreId != EFI_VARSTORE_ID_INVALID) {
- VarStoreType = mCVfrDataStorage.GetVarStoreType (_GET_CURRQEST_VARTINFO().mVarStoreId);
+ VarStoreType = gCVfrDataStorage.GetVarStoreType (_GET_CURRQEST_VARTINFO().mVarStoreId);
if (VarStoreType == EFI_VFR_VARSTORE_BUFFER || VarStoreType == EFI_VFR_VARSTORE_EFI) {
if (_GET_CURRQEST_DATATYPE() != (LFlags & EFI_IFR_NUMERIC_SIZE)) {
_PCATCH(VFR_RETURN_INVALID_PARAMETER, LineNum, "Numeric Flag is not same to Numeric VarData type");
}
} else {
@@ -2791,11 +2793,11 @@ vfrOneofFlagsField [CIfrOneOf & OObj, UINT32 LineNum] :
>>
numericFlagsField[HFlags, LFlags, IsSetType, IsDisplaySpecified] ( "\|" numericFlagsField[HFlags, LFlags, IsSetType, IsDisplaySpecified] )*
<<
//check data type flag
if (_GET_CURRQEST_VARTINFO().mVarStoreId != EFI_VARSTORE_ID_INVALID) {
- VarStoreType = mCVfrDataStorage.GetVarStoreType (_GET_CURRQEST_VARTINFO().mVarStoreId);
+ VarStoreType = gCVfrDataStorage.GetVarStoreType (_GET_CURRQEST_VARTINFO().mVarStoreId);
if (VarStoreType == EFI_VFR_VARSTORE_BUFFER || VarStoreType == EFI_VFR_VARSTORE_EFI) {
if (_GET_CURRQEST_DATATYPE() != (LFlags & EFI_IFR_NUMERIC_SIZE)) {
_PCATCH(VFR_RETURN_INVALID_PARAMETER, LineNum, "Numeric Flag is not same to Numeric VarData type");
}
} else {
@@ -3443,26 +3445,26 @@ vfrStatementOneOfOption :
if ((OOOObj->GetFlags () & (EFI_IFR_OPTION_DEFAULT | EFI_IFR_OPTION_DEFAULT_MFG)) != 0 && !ArrayType && gIsOrderedList) {
OOOObj->SetFlags(OOOObj->GetFlags () & ~(EFI_IFR_OPTION_DEFAULT | EFI_IFR_OPTION_DEFAULT_MFG));
}

if (_GET_CURRQEST_VARTINFO().mVarStoreId != EFI_VARSTORE_ID_INVALID) {
- _PCATCH(mCVfrDataStorage.GetVarStoreName (_GET_CURRQEST_VARTINFO().mVarStoreId, &VarStoreName), L->getLine());
- VarStoreGuid = mCVfrDataStorage.GetVarStoreGuid(_GET_CURRQEST_VARTINFO().mVarStoreId);
+ _PCATCH(gCVfrDataStorage.GetVarStoreName (_GET_CURRQEST_VARTINFO().mVarStoreId, &VarStoreName), L->getLine());
+ VarStoreGuid = gCVfrDataStorage.GetVarStoreGuid(_GET_CURRQEST_VARTINFO().mVarStoreId);
if (OOOObj->GetFlags () & EFI_IFR_OPTION_DEFAULT) {
CheckDuplicateDefaultValue (EFI_HII_DEFAULT_CLASS_STANDARD, F);
- _PCATCH(mCVfrDefaultStore.BufferVarStoreAltConfigAdd (
+ _PCATCH(gCVfrDefaultStore.BufferVarStoreAltConfigAdd (
EFI_HII_DEFAULT_CLASS_STANDARD,
_GET_CURRQEST_VARTINFO(),
VarStoreName,
VarStoreGuid,
_GET_CURRQEST_DATATYPE (),
*Val
), L->getLine());
}
if (OOOObj->GetFlags () & EFI_IFR_OPTION_DEFAULT_MFG) {
CheckDuplicateDefaultValue (EFI_HII_DEFAULT_CLASS_MANUFACTURING, F);
- _PCATCH(mCVfrDefaultStore.BufferVarStoreAltConfigAdd (
+ _PCATCH(gCVfrDefaultStore.BufferVarStoreAltConfigAdd (
EFI_HII_DEFAULT_CLASS_MANUFACTURING,
_GET_CURRQEST_VARTINFO(),
VarStoreName,
VarStoreGuid,
_GET_CURRQEST_DATATYPE (),
@@ -3928,13 +3930,13 @@ vareqvalExp [UINT32 & RootLevel, UINT32 & ExpOpCount] :
>>
VK:Var
OpenParen
VN:Number <<
VarIdStr = NULL; _STRCAT(&VarIdStr, VK->getText()); _STRCAT(&VarIdStr, VN->getText());
- VfrReturnCode = mCVfrDataStorage.GetVarStoreId (VarIdStr, &VarStoreId);
+ VfrReturnCode = gCVfrDataStorage.GetVarStoreId (VarIdStr, &VarStoreId);
if (VfrReturnCode == VFR_RETURN_UNDEFINED) {
- _PCATCH (mCVfrDataStorage.DeclareEfiVarStore (
+ _PCATCH (gCVfrDataStorage.DeclareEfiVarStore (
VarIdStr,
&mFormsetGuid,
_STOSID(VN->getText(), VN->getLine()),
0x2, //default type is UINT16
FALSE
@@ -4247,11 +4249,11 @@ getExp[UINT32 & RootLevel, UINT32 & ExpOpCount] :
default:
_PCATCH(VFR_RETURN_UNSUPPORTED, L->getLine(), "Get/Set opcode can't get the enough varstore information");
break;
}
} else {
- if ((mCVfrDataStorage.GetVarStoreType(Info.mVarStoreId) == EFI_VFR_VARSTORE_NAME) && (VarType == EFI_IFR_TYPE_UNDEFINED)) {
+ if ((gCVfrDataStorage.GetVarStoreType(Info.mVarStoreId) == EFI_VFR_VARSTORE_NAME) && (VarType == EFI_IFR_TYPE_UNDEFINED)) {
_PCATCH(VFR_RETURN_UNSUPPORTED, L->getLine(), "Get/Set opcode don't support name string");
}
if (VarType != EFI_IFR_TYPE_UNDEFINED) {
Info.mVarType = VarType;
_PCATCH(gCVfrVarDataTypeDB.GetDataTypeSize (Info.mVarType, &VarSize), L->getLine(), "Get/Set opcode can't get var type size");
@@ -4422,11 +4424,11 @@ setExp[UINT32 & RootLevel, UINT32 & ExpOpCount] :
default:
_PCATCH(VFR_RETURN_UNSUPPORTED, L->getLine(), "Get/Set opcode can't get the enough varstore information");
break;
}
} else {
- if ((mCVfrDataStorage.GetVarStoreType(Info.mVarStoreId) == EFI_VFR_VARSTORE_NAME) && (VarType == EFI_IFR_TYPE_UNDEFINED)) {
+ if ((gCVfrDataStorage.GetVarStoreType(Info.mVarStoreId) == EFI_VFR_VARSTORE_NAME) && (VarType == EFI_IFR_TYPE_UNDEFINED)) {
_PCATCH(VFR_RETURN_UNSUPPORTED, L->getLine(), "Get/Set opcode don't support name string");
}
if (VarType != EFI_IFR_TYPE_UNDEFINED) {
Info.mVarType = VarType;
_PCATCH(gCVfrVarDataTypeDB.GetDataTypeSize (Info.mVarType, &VarSize), L->getLine(), "Get/Set opcode can't get var type size");
@@ -4551,12 +4553,10 @@ class EfiVfrParser {
<<
private:
UINT8 mParserStatus;
BOOLEAN mConstantOnlyInExpression;

- CVfrDefaultStore mCVfrDefaultStore;
- CVfrDataStorage mCVfrDataStorage;
CVfrQuestionDB mCVfrQuestionDB;
CVfrRulesDB mCVfrRulesDB;

CIfrOpHeader * mCIfrOpHdr[MAX_IFR_EXPRESSION_DEPTH];
UINT32 mCIfrOpHdrLineNo[MAX_IFR_EXPRESSION_DEPTH];
@@ -5113,11 +5113,11 @@ EfiVfrParser::_DeclareDefaultFrameworkVarStore (
UINT32 TypeSize;
BOOLEAN FirstNode;
CONST CHAR8 VarName[] = "Setup";

FirstNode = TRUE;
- pNode = mCVfrDataStorage.GetBufferVarStoreList();
+ pNode = gCVfrDataStorage.GetBufferVarStoreList();
if (pNode == NULL && gCVfrVarDataTypeDB.mFirstNewDataTypeName != NULL) {
//
// Create the default Buffer Var Store when no VarStore is defined.
// its name should be "Setup"
//
@@ -5155,11 +5155,11 @@ EfiVfrParser::_DeclareDefaultFrameworkVarStore (
#endif
}
}
}

- pNode = mCVfrDataStorage.GetEfiVarStoreList();
+ pNode = gCVfrDataStorage.GetEfiVarStoreList();
for (; pNode != NULL; pNode = pNode->mNext) {
//
// create the default efi varstore opcode for not exist varstore
//
if (!pNode->mAssignedFlag) {
@@ -5198,18 +5198,18 @@ EfiVfrParser::_DeclareDefaultLinearVarStore (
UINT32 Size;
EFI_VARSTORE_ID VarStoreId;
CIfrVarStore VSObj;

VSObj.SetLineNo (LineNo);
- mCVfrDataStorage.DeclareBufferVarStore (
+ gCVfrDataStorage.DeclareBufferVarStore (
TypeNameList[Index],
&mFormsetGuid,
&gCVfrVarDataTypeDB,
TypeNameList[Index],
EFI_VARSTORE_ID_INVALID
);
- mCVfrDataStorage.GetVarStoreId(TypeNameList[Index], &VarStoreId, &mFormsetGuid);
+ gCVfrDataStorage.GetVarStoreId(TypeNameList[Index], &VarStoreId, &mFormsetGuid);
VSObj.SetVarStoreId (VarStoreId);
gCVfrVarDataTypeDB.GetDataTypeSize(TypeNameList[Index], &Size);
VSObj.SetSize ((UINT16) Size);
VSObj.SetName (TypeNameList[Index]);
VSObj.SetGuid (&mFormsetGuid);
@@ -5223,18 +5223,18 @@ EfiVfrParser::_DeclareDefaultLinearVarStore (
UINT32 Size;
EFI_VARSTORE_ID VarStoreId;
CIfrVarStore VSObj;

VSObj.SetLineNo (LineNo);
- mCVfrDataStorage.DeclareBufferVarStore (
+ gCVfrDataStorage.DeclareBufferVarStore (
(CHAR8 *) DateName,
&mFormsetGuid,
&gCVfrVarDataTypeDB,
(CHAR8 *) DateType,
EFI_VARSTORE_ID_INVALID
);
- mCVfrDataStorage.GetVarStoreId((CHAR8 *) DateName, &VarStoreId, &mFormsetGuid);
+ gCVfrDataStorage.GetVarStoreId((CHAR8 *) DateName, &VarStoreId, &mFormsetGuid);
VSObj.SetVarStoreId (VarStoreId);
gCVfrVarDataTypeDB.GetDataTypeSize((CHAR8 *) DateType, &Size);
VSObj.SetSize ((UINT16) Size);
VSObj.SetName ((CHAR8 *) DateName);
VSObj.SetGuid (&mFormsetGuid);
@@ -5244,18 +5244,18 @@ EfiVfrParser::_DeclareDefaultLinearVarStore (
UINT32 Size;
EFI_VARSTORE_ID VarStoreId;
CIfrVarStore VSObj;

VSObj.SetLineNo (LineNo);
- mCVfrDataStorage.DeclareBufferVarStore (
+ gCVfrDataStorage.DeclareBufferVarStore (
(CHAR8 *) TimeName,
&mFormsetGuid,
&gCVfrVarDataTypeDB,
(CHAR8 *) TimeType,
EFI_VARSTORE_ID_INVALID
);
- mCVfrDataStorage.GetVarStoreId((CHAR8 *) TimeName, &VarStoreId, &mFormsetGuid);
+ gCVfrDataStorage.GetVarStoreId((CHAR8 *) TimeName, &VarStoreId, &mFormsetGuid);
VSObj.SetVarStoreId (VarStoreId);
gCVfrVarDataTypeDB.GetDataTypeSize((CHAR8 *) TimeType, &Size);
VSObj.SetSize ((UINT16) Size);
VSObj.SetName ((CHAR8 *) TimeName);
VSObj.SetGuid (&mFormsetGuid);
@@ -5270,21 +5270,21 @@ EfiVfrParser::_DeclareStandardDefaultStorage (
//
// Default Store is declared.
//
CIfrDefaultStore DSObj;

- mCVfrDefaultStore.RegisterDefaultStore (DSObj.GetObjBinAddr(), (CHAR8 *) "Standard Defaults", EFI_STRING_ID_INVALID, EFI_HII_DEFAULT_CLASS_STANDARD);
+ gCVfrDefaultStore.RegisterDefaultStore (DSObj.GetObjBinAddr(), (CHAR8 *) "Standard Defaults", EFI_STRING_ID_INVALID, EFI_HII_DEFAULT_CLASS_STANDARD);
DSObj.SetLineNo (LineNo);
DSObj.SetDefaultName (EFI_STRING_ID_INVALID);
DSObj.SetDefaultId (EFI_HII_DEFAULT_CLASS_STANDARD);

//
// Default MANUFACTURING Store is declared.
//
CIfrDefaultStore DSObjMF;

- mCVfrDefaultStore.RegisterDefaultStore (DSObjMF.GetObjBinAddr(), (CHAR8 *) "Standard ManuFacturing", EFI_STRING_ID_INVALID, EFI_HII_DEFAULT_CLASS_MANUFACTURING);
+ gCVfrDefaultStore.RegisterDefaultStore (DSObjMF.GetObjBinAddr(), (CHAR8 *) "Standard ManuFacturing", EFI_STRING_ID_INVALID, EFI_HII_DEFAULT_CLASS_MANUFACTURING);
DSObjMF.SetLineNo (LineNo);
DSObjMF.SetDefaultName (EFI_STRING_ID_INVALID);
DSObjMF.SetDefaultId (EFI_HII_DEFAULT_CLASS_MANUFACTURING);
}

diff --git a/BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp b/BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp
index f73b70d..b3d1ac5 100644
--- a/BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp
+++ b/BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp
@@ -1,10 +1,10 @@
/** @file

Vfr common library functions.

-Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php

@@ -1417,10 +1417,12 @@ CVfrDataStorage::CVfrDataStorage (
mBufferVarStoreList = NULL;
mEfiVarStoreList = NULL;
mNameVarStoreList = NULL;
mCurrVarStorageNode = NULL;
mNewVarStorageNode = NULL;
+ mBufferFieldInfoListHead = NULL;
+ mBufferFieldInfoListTail = NULL;
}

CVfrDataStorage::~CVfrDataStorage (
VOID
)
@@ -1998,10 +2000,52 @@ CVfrDataStorage::GetEfiVarStoreInfo (

return VFR_RETURN_SUCCESS;
}

EFI_VFR_RETURN_CODE
+CVfrDataStorage::AddBufferVarStoreFieldInfo (
+ IN EFI_VARSTORE_INFO *Info
+ )
+{
+ BufferVarStoreFieldInfoNode *pNew;
+
+ if ((pNew = new BufferVarStoreFieldInfoNode(Info)) == NULL) {
+ return VFR_RETURN_FATAL_ERROR;
+ }
+
+ if (mBufferFieldInfoListHead == NULL) {
+ mBufferFieldInfoListHead = pNew;
+ mBufferFieldInfoListTail= pNew;
+ } else {
+ mBufferFieldInfoListTail->mNext = pNew;
+ mBufferFieldInfoListTail = pNew;
+ }
+
+ return VFR_RETURN_SUCCESS;
+}
+
+EFI_VFR_RETURN_CODE
+CVfrDataStorage::GetBufferVarStoreFieldInfo (
+ IN OUT EFI_VARSTORE_INFO *Info
+ )
+{
+ BufferVarStoreFieldInfoNode *pNode;
+
+ pNode = mBufferFieldInfoListHead;
+ while (pNode != NULL) {
+ if (Info->mVarStoreId == pNode->mVarStoreInfo.mVarStoreId &&
+ Info->mInfo.mVarOffset == pNode->mVarStoreInfo.mInfo.mVarOffset) {
+ Info->mVarTotalSize = pNode->mVarStoreInfo.mVarTotalSize;
+ Info->mVarType = pNode->mVarStoreInfo.mVarType;
+ return VFR_RETURN_SUCCESS;
+ }
+ pNode = pNode->mNext;
+ }
+ return VFR_RETURN_FATAL_ERROR;
+}
+
+EFI_VFR_RETURN_CODE
CVfrDataStorage::GetNameVarStoreInfo (
OUT EFI_VARSTORE_INFO *Info,
IN UINT32 Index
)
{
@@ -2356,10 +2400,30 @@ EFI_VARSTORE_INFO::operator == (
}

return FALSE;
}

+BufferVarStoreFieldInfoNode::BufferVarStoreFieldInfoNode(
+ IN EFI_VARSTORE_INFO *Info
+ )
+{
+ mVarStoreInfo.mVarType = Info->mVarType;
+ mVarStoreInfo.mVarTotalSize = Info->mVarTotalSize;
+ mVarStoreInfo.mInfo.mVarOffset = Info->mInfo.mVarOffset;
+ mVarStoreInfo.mVarStoreId = Info->mVarStoreId;
+ mNext = NULL;
+}
+
+BufferVarStoreFieldInfoNode::~BufferVarStoreFieldInfoNode ()
+{
+ mVarStoreInfo.mVarType = EFI_IFR_TYPE_OTHER;
+ mVarStoreInfo.mVarTotalSize = 0;
+ mVarStoreInfo.mInfo.mVarOffset = EFI_VAROFFSET_INVALID;
+ mVarStoreInfo.mVarStoreId = EFI_VARSTORE_ID_INVALID;
+ mNext = NULL;
+}
+
static EFI_VARSTORE_INFO gEfiInvalidVarStoreInfo;

EFI_QUESTION_ID
CVfrQuestionDB::GetFreeQuestionId (
VOID
@@ -3630,7 +3694,9 @@ CVfrStringDB::GetUnicodeStringTextSize (
}

BOOLEAN VfrCompatibleMode = FALSE;

CVfrVarDataTypeDB gCVfrVarDataTypeDB;
+CVfrDefaultStore gCVfrDefaultStore;
+CVfrDataStorage gCVfrDataStorage;


diff --git a/BaseTools/Source/C/VfrCompile/VfrUtilityLib.h b/BaseTools/Source/C/VfrCompile/VfrUtilityLib.h
index c8f5333..5faa1f4 100644
--- a/BaseTools/Source/C/VfrCompile/VfrUtilityLib.h
+++ b/BaseTools/Source/C/VfrCompile/VfrUtilityLib.h
@@ -1,10 +1,10 @@
/** @file

Vfr common library functions.

-Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php

@@ -263,10 +263,18 @@ struct EFI_VARSTORE_INFO {
EFI_VARSTORE_INFO (VOID);
EFI_VARSTORE_INFO (IN EFI_VARSTORE_INFO &);
BOOLEAN operator == (IN EFI_VARSTORE_INFO *);
};

+struct BufferVarStoreFieldInfoNode {
+ EFI_VARSTORE_INFO mVarStoreInfo;
+ struct BufferVarStoreFieldInfoNode *mNext;
+
+ BufferVarStoreFieldInfoNode( IN EFI_VARSTORE_INFO *Info );
+ ~BufferVarStoreFieldInfoNode ();
+};
+
#define EFI_VARSTORE_ID_MAX 0xFFFF
#define EFI_FREE_VARSTORE_ID_BITMAP_SIZE ((EFI_VARSTORE_ID_MAX + 1) / EFI_BITS_PER_UINT32)

class CVfrDataStorage {
private:
@@ -276,10 +284,12 @@ private:
struct SVfrVarStorageNode *mEfiVarStoreList;
struct SVfrVarStorageNode *mNameVarStoreList;

struct SVfrVarStorageNode *mCurrVarStorageNode;
struct SVfrVarStorageNode *mNewVarStorageNode;
+ BufferVarStoreFieldInfoNode *mBufferFieldInfoListHead;
+ BufferVarStoreFieldInfoNode *mBufferFieldInfoListTail;

private:

EFI_VARSTORE_ID GetFreeVarStoreId (EFI_VFR_VARSTORE_TYPE VarType = EFI_VFR_VARSTORE_BUFFER);
BOOLEAN ChekVarStoreIdFree (IN EFI_VARSTORE_ID);
@@ -315,12 +325,16 @@ public:
EFI_VFR_RETURN_CODE GetVarStoreByDataType (IN CHAR8 *, OUT SVfrVarStorageNode **, IN EFI_GUID *VarGuid = NULL);

EFI_VFR_RETURN_CODE GetBufferVarStoreDataTypeName (IN EFI_VARSTORE_ID, OUT CHAR8 **);
EFI_VFR_RETURN_CODE GetEfiVarStoreInfo (IN EFI_VARSTORE_INFO *);
EFI_VFR_RETURN_CODE GetNameVarStoreInfo (IN EFI_VARSTORE_INFO *, IN UINT32);
+ EFI_VFR_RETURN_CODE AddBufferVarStoreFieldInfo (IN EFI_VARSTORE_INFO *);
+ EFI_VFR_RETURN_CODE GetBufferVarStoreFieldInfo (IN OUT EFI_VARSTORE_INFO *);
};

+extern CVfrDataStorage gCVfrDataStorage;
+
#define EFI_QUESTION_ID_MAX 0xFFFF
#define EFI_FREE_QUESTION_ID_BITMAP_SIZE ((EFI_QUESTION_ID_MAX + 1) / EFI_BITS_PER_UINT32)
#define EFI_QUESTION_ID_INVALID 0x0

#define DATE_YEAR_BITMASK 0x0000FFFF
@@ -400,10 +414,12 @@ public:
BOOLEAN DefaultIdRegistered (IN UINT16);
EFI_VFR_RETURN_CODE GetDefaultId (IN CHAR8 *, OUT UINT16 *);
EFI_VFR_RETURN_CODE BufferVarStoreAltConfigAdd (IN EFI_VARSTORE_ID, IN EFI_VARSTORE_INFO &, IN CHAR8 *, IN EFI_GUID *, IN UINT8, IN EFI_IFR_TYPE_VALUE);
};

+extern CVfrDefaultStore gCVfrDefaultStore;
+
#define EFI_RULE_ID_START 0x01
#define EFI_RULE_ID_INVALID 0x00

struct SVfrRuleNode {
UINT8 mRuleId;
--
1.9.5.msysgit.1


[patch 1/2] BaseTool/VfrCompile: Add missing question opcode

Dandan Bi
 

The function CheckQuestionOpCode is to check whether the opcode
is question opcode, but it misses two question opcodes:
'EFI_IFR_REF_OP' and 'EFI_IFR_RESET_BUTTON'. Now add them.

Cc: Liming Gao <liming.gao@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Dandan Bi <dandan.bi@intel.com>
Reviewed-by: Eric Dong <eric.dong@intel.com>
---
BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp b/BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp
index 1612217..892b7b8 100644
--- a/BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp
+++ b/BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp
@@ -1,10 +1,10 @@
/** @file

The definition of CFormPkg's member function

-Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php

@@ -1179,10 +1179,12 @@ CIfrRecordInfoDB::CheckQuestionOpCode (
case EFI_IFR_ACTION_OP:
case EFI_IFR_STRING_OP:
case EFI_IFR_DATE_OP:
case EFI_IFR_TIME_OP:
case EFI_IFR_ORDERED_LIST_OP:
+ case EFI_IFR_REF_OP:
+ case EFI_IFR_RESET_BUTTON_OP:
return TRUE;
default:
return FALSE;
}
}
--
1.9.5.msysgit.1


[patch 0/2] BaseTools/VfrCompile: Add two new option for VfrCompile

Dandan Bi
 

patch 1 is to fix a bug in current code.
patch 2 is to add two compile option for VfrCompile.

Cc: Liming Gao <liming.gao@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Dandan Bi <dandan.bi@intel.com>

Dandan Bi (2):
BaseTool/VfrCompile: Add missing question opcode
BaseTools/VfrCompile: Add two new option for VfrCompile

BaseTools/Source/C/VfrCompile/VfrCompiler.cpp | 56 +-
BaseTools/Source/C/VfrCompile/VfrCompiler.h | 3 +-
BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp | 792 ++++++++++++++++++++++--
BaseTools/Source/C/VfrCompile/VfrFormPkg.h | 33 +-
BaseTools/Source/C/VfrCompile/VfrSyntax.g | 118 ++--
BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp | 68 +-
BaseTools/Source/C/VfrCompile/VfrUtilityLib.h | 18 +-
7 files changed, 921 insertions(+), 167 deletions(-)

--
1.9.5.msysgit.1


Re: [PATCH v2 2/7] BaseTools-GenFw:Add new x86_64 Elf relocation types for PIC/PIE code

Ard Biesheuvel
 

(adding back our friends on cc)

On 1 August 2016 at 12:36, Shi, Steven <steven.shi@intel.com> wrote:
On 1 August 2016 at 12:16, Shi, Steven <steven.shi@intel.com> wrote:
OK, another example:

pie.s:

.globl foo
foo:
pushq n@GOTPCREL(%rip)
popq %rax
ret

.globl bar
bar:
pushq n@GOTPCREL(%rip)
popq %rax
ret

.globl n
n:
.quad 0

compile and link using

gcc -c -o pie.o /tmp/pie.s
ld -q -o pie pie.o -e foo

gives me

Relocation section '.rela.text' at offset 0x260 contains 2 entries:
Offset Info Type Sym. Value Sym. Name + Addend
0000004000b2 000700000009 R_X86_64_GOTPCREL 00000000004000be
n -
4
0000004000b9 000700000009 R_X86_64_GOTPCREL 00000000004000be
n -
4

Here, pie is a fully linked binary.
[Steven]: In this example, there are two R_X86_64_GOTPCREL relocation
address in the .text section need to fix up with same symbol runtime address,
these two relocation addresses are not same, and every relocation address
will be fixed up once. I don't see the problem of "Having multiple fixups for
the same symbol in the .reloc section", and current GenFw code should has
no problem on this example.
How many times will your code call CoffAddFixup() for the address of n?
[Steven]: My understanding is the n address (6000c8) is not a GOTPCREL relocation in .text section, but the 4000b2 and 4000b2 are GOTPCREL relocation in .text section. My CoffAddFixup() will only call twice for 4000b2 and 4000b2, but not for n address (6000c8).

Disassembly of section .text:

00000000004000b0 <foo>:
4000b0: ff 35 12 00 20 00 pushq 0x200012(%rip) # 6000c8 <n+0x200008>
4000b6: 58 pop %rax
4000b7: c3 retq

00000000004000b8 <bar>:
4000b8: ff 35 0a 00 20 00 pushq 0x20000a(%rip) # 6000c8 <n+0x200008>
4000be: 58 pop %rax
4000bf: c3 retq

00000000004000c0 <n>:
...
CoffAddFixup() must be used for absolute symbol references only. These
instructions contain relative symbol references, which are
recalculated in WriteSections64().

The only absolute symbol reference is the GOT entry for 'n', and your
code (in WriteRelocations64()) calculates the address of the GOT entry
(which is always in .text BTW) and adds a fixup for it, i.e.,

+ CoffAddFixup(
+ (UINT32)(UINTN)((UINT64)
mCoffSectionsOffset[RelShdr->sh_info] + GoTPcRelPtrOffset),
+ EFI_IMAGE_REL_BASED_DIR64);

This code adds a fixup to the PE/COFF .reloc section for the GOT entry
containing the address of 'n', and the instructions perform a IP
relative load of the contents of the GOT entry to retrieve the address
of 'n'.

By adding two fixups, the PE/COFF loader will apply the load offset
twice, resulting in an incorrect value.

--
Ard.


Re: [RFC 1/2] MdeModulePkg/EbcDxe: Add AARCH64 EBC VM support

Leif Lindholm <leif.lindholm@...>
 

(Apologies, missed out on this branch of the thread on first pass
since I was dropped from cc.)

On Sun, Jul 31, 2016 at 11:32:08PM -0700, Jordan Justen wrote:
On 2016-07-31 19:12:03, Tian, Feng wrote:
I may not speak it clear. Sorry for that.

I saw the patch with commit log "Submitted on behalf of a
third-party: xxxx". But this is part of "TianoCore Contribution
Agreement 1.0 section 4".

And the Contributions.txt clearly says "the commit message must
include your "Signed-off-by" signature, and "Contributed-under"
message". But the commit log hasn't.

So I am total confused how to solve this case. What's the correct
format for this?
Yes, Contributed-under and Signed-off-by are required.

I think it is possible in some cases to submit a third party
conribution, but you still have to add the Contributed-under and
Signed-off-by. See Contribtions.txt under either package for the text
of the 'TianoCore Contribution Agreement' to understand what the
'Contributed-under' tag is indicating. Basically you'd be asserting
that you are sure that the contribuion can be used under the
conditions specified in the TianoCore Contribution Agreement, despite
the fact that you don't own the copyright.
Since I was not certain of how this was historically, or should in the
future, be interpreted I left the Contributed-under out from the
submission.

The bit that is unclear to me is "You may submit it to TianoCore site
separately from any Contribution".
- Should this read "separately from any other contribution"?
- For practical purposes, Does separately mean "in a separate commit"?

If the answers to the two above questions are "yes", then I'm happy to
resubmit it with a Contributed-under.

Obviously it is easier if someone that owns the copyright makes the
patch submission.
Don't get me started...

/
Leif

We've taken code into OvmfPkg that wasn't contributed directly by the
copyright owner. (for example, some of the Xen .h files)
-Jordan


-----Original Message-----
From: Marvin H?user [mailto:Marvin.Haeuser@outlook.com]
Sent: Monday, August 1, 2016 9:58 AM
To: edk2-devel@lists.01.org
Cc: Tian, Feng <feng.tian@intel.com>
Subject: RE: [RFC 1/2] MdeModulePkg/EbcDxe: Add AARCH64 EBC VM support

Hey Feng,

According to the Contributions document, BSD 2-clause is one of the licenses that can be accepted, if the parent license cannot be used:
https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Contributions.txt#L25

Regards,
Marvin.

-----Original Message-----
From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
Tian, Feng
Sent: Monday, August 1, 2016 3:50 AM
To: Leif Lindholm <leif.lindholm@linaro.org>; edk2-devel@lists.01.org
Cc: Tian, Feng <feng.tian@intel.com>; Daniil Egranov
<daniil.egranov@linaro.org>; Jeff Brasen <jbrasen@codeaurora.org>;
Zeng, Star <star.zeng@intel.com>; Ard Biesheuvel
<ard.biesheuvel@linaro.org>
Subject: Re: [edk2] [RFC 1/2] MdeModulePkg/EbcDxe: Add AARCH64 EBC VM
support

Hi, Leif

If I understand correctly, EDKII doesn't allow such BSD license.

Correct me if anybody has different opinions.

Thanks
Feng

-----Original Message-----
From: Leif Lindholm [mailto:leif.lindholm@linaro.org]
Sent: Saturday, July 30, 2016 12:06 AM
To: edk2-devel@lists.01.org
Cc: Jeff Brasen <jbrasen@codeaurora.org>; Ard Biesheuvel
<ard.biesheuvel@linaro.org>; Daniil Egranov
<daniil.egranov@linaro.org>; Tian, Feng <feng.tian@intel.com>; Zeng,
Star <star.zeng@intel.com>
Subject: [RFC 1/2] MdeModulePkg/EbcDxe: Add AARCH64 EBC VM support

From: Jeff Brasen <jbrasen@codeaurora.org>

Adds support for the EBC VM for AARCH64 platforms

Submitted on behalf of a third-party: The Linux Foundation This
contribution is licensed under the BSD license as found at
http://opensource.org/licenses/bsd-license.php

[Taken from https://source.codeaurora.org/external/server/edk2-blue/]
Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
---
.../Universal/EbcDxe/AArch64/EbcLowLevel.S | 135 +++++
MdeModulePkg/Universal/EbcDxe/AArch64/EbcSupport.c | 563
+++++++++++++++++++++
MdeModulePkg/Universal/EbcDxe/EbcDxe.inf | 6 +-
3 files changed, 703 insertions(+), 1 deletion(-) create mode 100644
MdeModulePkg/Universal/EbcDxe/AArch64/EbcLowLevel.S
create mode 100644
MdeModulePkg/Universal/EbcDxe/AArch64/EbcSupport.c

diff --git a/MdeModulePkg/Universal/EbcDxe/AArch64/EbcLowLevel.S
b/MdeModulePkg/Universal/EbcDxe/AArch64/EbcLowLevel.S
new file mode 100644
index 0000000..e858227
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/AArch64/EbcLowLevel.S
@@ -0,0 +1,135 @@
+#/** @file
+#
+# This code provides low level routines that support the Virtual Machine
+# for option ROMs.
+#
+# Copyright (c) 2015, The Linux Foundation. All rights reserved.
+# Copyright (c) 2007 - 2014, Intel Corporation. All rights
+reserved.<BR> # This program and the accompanying materials # are
+licensed and made available under the terms and conditions of the BSD
+License # which accompanies this distribution. The full text of the
+license may be found at #
+http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+BASIS, # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND,
EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+#--------------------------------------------------------------------
+--
+-----
+# Equate files needed.
+#--------------------------------------------------------------------
+--
+-----
+
+ASM_GLOBAL ASM_PFX(CopyMem);
+ASM_GLOBAL ASM_PFX(EbcInterpret);
+ASM_GLOBAL ASM_PFX(ExecuteEbcImageEntryPoint);
+
+#********************************************************
**************
+******
+# EbcLLCALLEX
+#
+# This function is called to execute an EBC CALLEX instruction.
+# This instruction requires that we thunk out to external native #
+code. For AArch64, we copy the VM stack into the main stack and then
+pop # the first 8 arguments off according to the AArch64 Procedure
+Call Standard # On return, we restore the stack pointer to its original location.
+#
+#********************************************************
**************
+****** # UINTN EbcLLCALLEXNative(UINTN FuncAddr, UINTN
NewStackPointer,
+VOID *FramePtr) ASM_GLOBAL ASM_PFX(EbcLLCALLEXNative);
+ASM_PFX(EbcLLCALLEXNative):
+ stp x19, x20, [sp, #-16]!
+ stp x29, x30, [sp, #-16]!
+
+ mov x19, x0
+ mov x20, sp
+ sub x2, x2, x1 // Length = NewStackPointer-FramePtr
+ sub sp, sp, x2
+ sub sp, sp, #64 // Make sure there is room for at least 8
+ args in the new
stack
+ mov x0, sp
+
+ bl CopyMem // Sp, NewStackPointer, Length
+
+ ldp x0, x1, [sp], #16
+ ldp x2, x3, [sp], #16
+ ldp x4, x5, [sp], #16
+ ldp x6, x7, [sp], #16
+
+ blr x19
+
+ mov sp, x20
+ ldp x29, x30, [sp], #16
+ ldp x19, x20, [sp], #16
+
+ ret
+
+#********************************************************
**************
+******
+# EbcLLEbcInterpret
+#
+# This function is called by the thunk code to handle an Native to
+EBC call # This can handle up to 16 arguments (1-8 on in x0-x7, 9-16
+are on the stack) # x9 contains the Entry point that will be the
+first argument when # EBCInterpret is called.
+#
+#********************************************************
**************
+******
+ASM_GLOBAL ASM_PFX(EbcLLEbcInterpret);
+ASM_PFX(EbcLLEbcInterpret):
+ stp x29, x30, [sp, #-16]!
+
+ // copy the current arguments 9-16 from old location and add arg
+ 7 to
stack
+ // keeping 16 byte stack alignment
+ sub sp, sp, #80
+ str x7, [sp]
+ ldr x11, [sp, #96]
+ str x11, [sp, #8]
+ ldr x11, [sp, #104]
+ str x11, [sp, #16]
+ ldr x11, [sp, #112]
+ str x11, [sp, #24]
+ ldr x11, [sp, #120]
+ str x11, [sp, #32]
+ ldr x11, [sp, #128]
+ str x11, [sp, #40]
+ ldr x11, [sp, #136]
+ str x11, [sp, #48]
+ ldr x11, [sp, #144]
+ str x11, [sp, #56]
+ ldr x11, [sp, #152]
+ str x11, [sp, #64]
+
+ // Shift arguments and add entry point and as argument 1
+ mov x7, x6
+ mov x6, x5
+ mov x5, x4
+ mov x4, x3
+ mov x3, x2
+ mov x2, x1
+ mov x1, x0
+ mov x0, x9
+
+ # call C-code
+ bl ASM_PFX(EbcInterpret)
+ add sp, sp, #80
+
+ ldp x29, x30, [sp], #16
+
+ ret
+
+#********************************************************
**************
+******
+# EbcLLExecuteEbcImageEntryPoint
+#
+# This function is called by the thunk code to handle the image entry
+point # x9 contains the Entry point that will be the first argument
+when # ExecuteEbcImageEntryPoint is called.
+#
+#********************************************************
**************
+****** ASM_GLOBAL ASM_PFX(EbcLLExecuteEbcImageEntryPoint);
+ASM_PFX(EbcLLExecuteEbcImageEntryPoint):
+ stp x29, x30, [sp, #-16]!
+ # build new paramater calling convention
+ mov x2, x1
+ mov x1, x0
+ mov x0, x9
+
+ # call C-code
+ bl ASM_PFX(ExecuteEbcImageEntryPoint)
+ ldp x29, x30, [sp], #16
+ ret
diff --git a/MdeModulePkg/Universal/EbcDxe/AArch64/EbcSupport.c
b/MdeModulePkg/Universal/EbcDxe/AArch64/EbcSupport.c
new file mode 100644
index 0000000..23261a0
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/AArch64/EbcSupport.c
@@ -0,0 +1,563 @@
+/** @file
+ This module contains EBC support routines that are customized based
+on
+ the target AArch64 processor.
+
+Copyright (c) 2015, The Linux Foundation. All rights reserved.
+Copyright (c) 2006 - 2014, Intel Corporation. All rights
+reserved.<BR> This program and the accompanying materials are
+licensed and made available under the terms and conditions of the BSD
+License which accompanies this distribution. The full text of the
+license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+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 "EbcInt.h"
+#include "EbcExecute.h"
+
+//
+// Amount of space that is not used in the stack // #define
+STACK_REMAIN_SIZE (1024 * 4)
+
+//
+// This is instruction buffer used to create EBC thunk //
+#define EBC_MAGIC_SIGNATURE 0xCA112EBCCA112EBCull
+#define EBC_ENTRYPOINT_SIGNATURE 0xAFAFAFAFAFAFAFAFull
+#define EBC_LL_EBC_ENTRYPOINT_SIGNATURE 0xFAFAFAFAFAFAFAFAull
+UINT8 mInstructionBufferTemplate[] = {
+ 0x03, 0x00, 0x00, 0x14, //b pc+16
+ //
+ // Add a magic code here to help the VM recognize the thunk..
+ //
+ (UINT8)(EBC_MAGIC_SIGNATURE & 0xFF),
+ (UINT8)((EBC_MAGIC_SIGNATURE >> 8) & 0xFF),
+ (UINT8)((EBC_MAGIC_SIGNATURE >> 16) & 0xFF),
+ (UINT8)((EBC_MAGIC_SIGNATURE >> 24) & 0xFF),
+ (UINT8)((EBC_MAGIC_SIGNATURE >> 32) & 0xFF),
+ (UINT8)((EBC_MAGIC_SIGNATURE >> 40) & 0xFF),
+ (UINT8)((EBC_MAGIC_SIGNATURE >> 48) & 0xFF),
+ (UINT8)((EBC_MAGIC_SIGNATURE >> 56) & 0xFF),
+ 0x69, 0x00, 0x00, 0x58, //ldr x9, #32
+ 0x8A, 0x00, 0x00, 0x58, //ldr x10, #40
+ 0x05, 0x00, 0x00, 0x14, //b pc+32
+ (UINT8)(EBC_ENTRYPOINT_SIGNATURE & 0xFF),
+ (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 8) & 0xFF),
+ (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 16) & 0xFF),
+ (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 24) & 0xFF),
+ (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 32) & 0xFF),
+ (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 40) & 0xFF),
+ (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 48) & 0xFF),
+ (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 56) & 0xFF),
+ (UINT8)(EBC_LL_EBC_ENTRYPOINT_SIGNATURE & 0xFF),
+ (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 8) & 0xFF),
+ (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 16) & 0xFF),
+ (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 24) & 0xFF),
+ (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 32) & 0xFF),
+ (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 40) & 0xFF),
+ (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 48) & 0xFF),
+ (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 56) & 0xFF),
+ 0x40, 0x01, 0x1F, 0xD6 //br x10
+
+};
+
+/**
+ Begin executing an EBC image.
+ This is used for Ebc Thunk call.
+
+ @return The value returned by the EBC application we're going to run.
+
+**/
+UINT64
+EFIAPI
+EbcLLEbcInterpret (
+ VOID
+ );
+
+/**
+ Begin executing an EBC image.
+ This is used for Ebc image entrypoint.
+
+ @return The value returned by the EBC application we're going to run.
+
+**/
+UINT64
+EFIAPI
+EbcLLExecuteEbcImageEntryPoint (
+ VOID
+ );
+
+/**
+ Pushes a 64 bit unsigned value to the VM stack.
+
+ @param VmPtr The pointer to current VM context.
+ @param Arg The value to be pushed.
+
+**/
+VOID
+PushU64 (
+ IN VM_CONTEXT *VmPtr,
+ IN UINT64 Arg
+ )
+{
+ //
+ // Advance the VM stack down, and then copy the argument to the stack.
+ // Hope it's aligned.
+ //
+ VmPtr->Gpr[0] -= sizeof (UINT64);
+ *(UINT64 *) VmPtr->Gpr[0] = Arg;
+ return;
+}
+
+
+/**
+ Begin executing an EBC image.
+
+ This is a thunk function.
+
+ @param EntryPoint The entrypoint of EBC code.
+ @param Arg1 The 1st argument.
+ @param Arg2 The 2nd argument.
+ @param Arg3 The 3rd argument.
+ @param Arg4 The 4th argument.
+ @param Arg5 The 5th argument.
+ @param Arg6 The 6th argument.
+ @param Arg7 The 7th argument.
+ @param Arg8 The 8th argument.
+ @param Arg9 The 9th argument.
+ @param Arg10 The 10th argument.
+ @param Arg11 The 11th argument.
+ @param Arg12 The 12th argument.
+ @param Arg13 The 13th argument.
+ @param Arg14 The 14th argument.
+ @param Arg15 The 15th argument.
+ @param Arg16 The 16th argument.
+
+ @return The value returned by the EBC application we're going to run.
+
+**/
+UINT64
+EFIAPI
+EbcInterpret (
+ IN UINTN EntryPoint,
+ IN UINTN Arg1,
+ IN UINTN Arg2,
+ IN UINTN Arg3,
+ IN UINTN Arg4,
+ IN UINTN Arg5,
+ IN UINTN Arg6,
+ IN UINTN Arg7,
+ IN UINTN Arg8,
+ IN UINTN Arg9,
+ IN UINTN Arg10,
+ IN UINTN Arg11,
+ IN UINTN Arg12,
+ IN UINTN Arg13,
+ IN UINTN Arg14,
+ IN UINTN Arg15,
+ IN UINTN Arg16
+ )
+{
+ //
+ // Create a new VM context on the stack
+ //
+ VM_CONTEXT VmContext;
+ UINTN Addr;
+ EFI_STATUS Status;
+ UINTN StackIndex;
+
+ //
+ // Get the EBC entry point
+ //
+ Addr = EntryPoint;
+
+ //
+ // Now clear out our context
+ //
+ ZeroMem ((VOID *) &VmContext, sizeof (VM_CONTEXT));
+
+ //
+ // Set the VM instruction pointer to the correct location in memory.
+ //
+ VmContext.Ip = (VMIP) Addr;
+
+ //
+ // Initialize the stack pointer for the EBC. Get the current system
+ stack // pointer and adjust it down by the max needed for the interpreter.
+ //
+
+ //
+ // Adjust the VM's stack pointer down.
+ //
+
+ Status = GetEBCStack((EFI_HANDLE)(UINTN)-1, &VmContext.StackPool,
+ &StackIndex); if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ VmContext.StackTop = (UINT8*)VmContext.StackPool +
+ (STACK_REMAIN_SIZE); VmContext.Gpr[0] = (UINT64)
+ ((UINT8*)VmContext.StackPool + STACK_POOL_SIZE);
+ VmContext.HighStackBottom = (UINTN) VmContext.Gpr[0];
VmContext.Gpr[0]
+ -= sizeof (UINTN);
+
+ //
+ // Align the stack on a natural boundary.
+ //
+ VmContext.Gpr[0] &= ~(VM_REGISTER)(sizeof (UINTN) - 1);
+
+ //
+ // Put a magic value in the stack gap, then adjust down again.
+ //
+ *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN)
VM_STACK_KEY_VALUE;
+ VmContext.StackMagicPtr = (UINTN *) (UINTN) VmContext.Gpr[0];
+
+ //
+ // The stack upper to LowStackTop is belong to the VM.
+ //
+ VmContext.LowStackTop = (UINTN) VmContext.Gpr[0];
+
+ //
+ // For the worst case, assume there are 4 arguments passed in
+ registers, store // them to VM's stack.
+ //
+ PushU64 (&VmContext, (UINT64) Arg16);
+ PushU64 (&VmContext, (UINT64) Arg15);
+ PushU64 (&VmContext, (UINT64) Arg14);
+ PushU64 (&VmContext, (UINT64) Arg13);
+ PushU64 (&VmContext, (UINT64) Arg12);
+ PushU64 (&VmContext, (UINT64) Arg11);
+ PushU64 (&VmContext, (UINT64) Arg10);
+ PushU64 (&VmContext, (UINT64) Arg9);
+ PushU64 (&VmContext, (UINT64) Arg8);
+ PushU64 (&VmContext, (UINT64) Arg7);
+ PushU64 (&VmContext, (UINT64) Arg6);
+ PushU64 (&VmContext, (UINT64) Arg5);
+ PushU64 (&VmContext, (UINT64) Arg4);
+ PushU64 (&VmContext, (UINT64) Arg3);
+ PushU64 (&VmContext, (UINT64) Arg2);
+ PushU64 (&VmContext, (UINT64) Arg1);
+
+ //
+ // Interpreter assumes 64-bit return address is pushed on the stack.
+ // AArch64 does not do this so pad the stack accordingly.
+ //
+ PushU64 (&VmContext, (UINT64) 0);
+ PushU64 (&VmContext, (UINT64) 0x1234567887654321ULL);
+
+ //
+ // For AArch64, this is where we say our return address is //
+ VmContext.StackRetAddr = (UINT64) VmContext.Gpr[0];
+
+ //
+ // We need to keep track of where the EBC stack starts. This way,
+ if the EBC // accesses any stack variables above its initial stack
+ setting, then we know // it's accessing variables passed into it,
+ which means the data is on the // VM's stack.
+ // When we're called, on the stack (high to low) we have the
+ parameters, the // return address, then the saved ebp. Save the
+ pointer
to the return address.
+ // EBC code knows that's there, so should look above it for
+ function
parameters.
+ // The offset is the size of locals (VMContext + Addr + saved ebp).
+ // Note that the interpreter assumes there is a 16 bytes of return
+ address on // the stack too, so adjust accordingly.
+ // VmContext.HighStackBottom = (UINTN)(Addr + sizeof (VmContext) +
+ sizeof (Addr)); //
+
+ //
+ // Begin executing the EBC code
+ //
+ EbcExecute (&VmContext);
+
+ //
+ // Return the value in R[7] unless there was an error
+ //
+ ReturnEBCStack(StackIndex);
+ return (UINT64) VmContext.Gpr[7];
+}
+
+
+/**
+ Begin executing an EBC image.
+
+ @param EntryPoint The entrypoint of EBC code.
+ @param ImageHandle image handle for the EBC application we're
executing
+ @param SystemTable standard system table passed into an driver's
entry
+ point
+
+ @return The value returned by the EBC application we're going to run.
+
+**/
+UINT64
+EFIAPI
+ExecuteEbcImageEntryPoint (
+ IN UINTN EntryPoint,
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ //
+ // Create a new VM context on the stack
+ //
+ VM_CONTEXT VmContext;
+ UINTN Addr;
+ EFI_STATUS Status;
+ UINTN StackIndex;
+
+ //
+ // Get the EBC entry point
+ //
+ Addr = EntryPoint;
+
+ //
+ // Now clear out our context
+ //
+ ZeroMem ((VOID *) &VmContext, sizeof (VM_CONTEXT));
+
+ //
+ // Save the image handle so we can track the thunks created for
+ this image // VmContext.ImageHandle = ImageHandle;
VmContext.SystemTable
+ = SystemTable;
+
+ //
+ // Set the VM instruction pointer to the correct location in memory.
+ //
+ VmContext.Ip = (VMIP) Addr;
+
+ //
+ // Initialize the stack pointer for the EBC. Get the current system
+ stack // pointer and adjust it down by the max needed for the interpreter.
+ //
+
+ Status = GetEBCStack(ImageHandle, &VmContext.StackPool,
&StackIndex);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ VmContext.StackTop = (UINT8*)VmContext.StackPool +
+ (STACK_REMAIN_SIZE); VmContext.Gpr[0] = (UINT64)
+ ((UINT8*)VmContext.StackPool + STACK_POOL_SIZE);
+ VmContext.HighStackBottom = (UINTN) VmContext.Gpr[0];
VmContext.Gpr[0]
+ -= sizeof (UINTN);
+
+
+ //
+ // Put a magic value in the stack gap, then adjust down again //
+ *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN)
VM_STACK_KEY_VALUE;
+ VmContext.StackMagicPtr = (UINTN *) (UINTN) VmContext.Gpr[0];
+
+ //
+ // Align the stack on a natural boundary VmContext.Gpr[0] &=
+ ~(VM_REGISTER)(sizeof(UINTN) - 1); //
+ VmContext.LowStackTop = (UINTN) VmContext.Gpr[0];
+
+ //
+ // Simply copy the image handle and system table onto the EBC stack.
+ // Greatly simplifies things by not having to spill the args.
+ //
+ PushU64 (&VmContext, (UINT64) SystemTable);
+ PushU64 (&VmContext, (UINT64) ImageHandle);
+
+ //
+ // VM pushes 16-bytes for return address. Simulate that here.
+ //
+ PushU64 (&VmContext, (UINT64) 0);
+ PushU64 (&VmContext, (UINT64) 0x1234567887654321ULL);
+
+ //
+ // For AArch64, this is where we say our return address is //
+ VmContext.StackRetAddr = (UINT64) VmContext.Gpr[0];
+
+ //
+ // Entry function needn't access high stack context, simply // put
+ the stack pointer here.
+ //
+
+ //
+ // Begin executing the EBC code
+ //
+ EbcExecute (&VmContext);
+
+ //
+ // Return the value in R[7] unless there was an error
+ //
+ ReturnEBCStack(StackIndex);
+ return (UINT64) VmContext.Gpr[7];
+}
+
+
+/**
+ Create thunks for an EBC image entry point, or an EBC protocol service.
+
+ @param ImageHandle Image handle for the EBC image. If not null,
then
+ we're creating a thunk for an image entry point.
+ @param EbcEntryPoint Address of the EBC code that the thunk is to
call
+ @param Thunk Returned thunk we create here
+ @param Flags Flags indicating options for creating the thunk
+
+ @retval EFI_SUCCESS The thunk was created successfully.
+ @retval EFI_INVALID_PARAMETER The parameter of EbcEntryPoint is not
16-bit
+ aligned.
+ @retval EFI_OUT_OF_RESOURCES There is not enough memory to
created the EBC
+ Thunk.
+ @retval EFI_BUFFER_TOO_SMALL EBC_THUNK_SIZE is not larger enough.
+
+**/
+EFI_STATUS
+EbcCreateThunks (
+ IN EFI_HANDLE ImageHandle,
+ IN VOID *EbcEntryPoint,
+ OUT VOID **Thunk,
+ IN UINT32 Flags
+ )
+{
+ UINT8 *Ptr;
+ UINT8 *ThunkBase;
+ UINT32 Index;
+ INT32 ThunkSize;
+
+ //
+ // Check alignment of pointer to EBC code // if ((UINT32) (UINTN)
+ EbcEntryPoint & 0x01) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ThunkSize = sizeof(mInstructionBufferTemplate);
+
+ Ptr = AllocatePool (sizeof(mInstructionBufferTemplate));
+
+ if (Ptr == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Print(L"Allocate TH: 0x%X\n", (UINT32)Ptr); // // Save the
+ start address so we can add a pointer to it to a list later.
+ //
+ ThunkBase = Ptr;
+
+ //
+ // Give them the address of our buffer we're going to fix up //
+ *Thunk = (VOID *) Ptr;
+
+ //
+ // Copy whole thunk instruction buffer template // CopyMem (Ptr,
+ mInstructionBufferTemplate, sizeof(mInstructionBufferTemplate));
+
+ //
+ // Patch EbcEntryPoint and EbcLLEbcInterpret // for (Index = 0;
+ Index < sizeof(mInstructionBufferTemplate) - sizeof(UINTN); Index++) {
+ if (*(UINTN *)&Ptr[Index] == EBC_ENTRYPOINT_SIGNATURE) {
+ *(UINTN *)&Ptr[Index] = (UINTN)EbcEntryPoint;
+ }
+ if (*(UINTN *)&Ptr[Index] == EBC_LL_EBC_ENTRYPOINT_SIGNATURE) {
+ if ((Flags & FLAG_THUNK_ENTRY_POINT) != 0) {
+ *(UINTN *)&Ptr[Index] = (UINTN)EbcLLExecuteEbcImageEntryPoint;
+ } else {
+ *(UINTN *)&Ptr[Index] = (UINTN)EbcLLEbcInterpret;
+ }
+ }
+ }
+
+ //
+ // Add the thunk to the list for this image. Do this last since the
+ add // function flushes the cache for us.
+ //
+ EbcAddImageThunk (ImageHandle, (VOID *) ThunkBase, ThunkSize);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function is called to execute an EBC CALLEX instruction.
+ The function check the callee's content to see whether it is common
+native
+ code or a thunk to another piece of EBC code.
+ If the callee is common native code, use EbcLLCAllEXASM to
+manipulate,
+ otherwise, set the VM->IP to target EBC code directly to avoid
+another VM
+ be startup which cost time and stack space.
+
+ @param VmPtr Pointer to a VM context.
+ @param FuncAddr Callee's address
+ @param NewStackPointer New stack pointer after the call
+ @param FramePtr New frame pointer after the call
+ @param Size The size of call instruction
+
+**/
+VOID
+EbcLLCALLEX (
+ IN VM_CONTEXT *VmPtr,
+ IN UINTN FuncAddr,
+ IN UINTN NewStackPointer,
+ IN VOID *FramePtr,
+ IN UINT8 Size
+ )
+{
+ UINTN IsThunk;
+ UINTN TargetEbcAddr;
+ UINT8 InstructionBuffer[sizeof(mInstructionBufferTemplate)];
+ UINTN Index;
+ UINTN IndexOfEbcEntrypoint;
+
+ IsThunk = 1;
+ TargetEbcAddr = 0;
+ IndexOfEbcEntrypoint = 0;
+
+ //
+ // Processor specific code to check whether the callee is a thunk to EBC.
+ //
+ CopyMem (InstructionBuffer, (VOID *)FuncAddr,
+ sizeof(InstructionBuffer)); // // Fill the signature according to
+ mInstructionBufferTemplate // for (Index = 0; Index <
+ sizeof(mInstructionBufferTemplate) - sizeof(UINTN); Index++) {
+ if (*(UINTN *)&mInstructionBufferTemplate[Index] ==
EBC_ENTRYPOINT_SIGNATURE) {
+ *(UINTN *)&InstructionBuffer[Index] = EBC_ENTRYPOINT_SIGNATURE;
+ IndexOfEbcEntrypoint = Index;
+ }
+ if (*(UINTN *)&mInstructionBufferTemplate[Index] ==
EBC_LL_EBC_ENTRYPOINT_SIGNATURE) {
+ *(UINTN *)&InstructionBuffer[Index] =
EBC_LL_EBC_ENTRYPOINT_SIGNATURE;
+ }
+ }
+ //
+ // Check if we need thunk to native // if (CompareMem
+ (InstructionBuffer, mInstructionBufferTemplate,
sizeof(mInstructionBufferTemplate)) != 0) {
+ IsThunk = 0;
+ }
+
+ if (IsThunk == 1){
+ //
+ // The callee is a thunk to EBC, adjust the stack pointer down 16 bytes and
+ // put our return address and frame pointer on the VM stack.
+ // Then set the VM's IP to new EBC code.
+ //
+ VmPtr->Gpr[0] -= 8;
+ VmWriteMemN (VmPtr, (UINTN) VmPtr->Gpr[0], (UINTN) FramePtr);
+ VmPtr->FramePtr = (VOID *) (UINTN) VmPtr->Gpr[0];
+ VmPtr->Gpr[0] -= 8;
+ VmWriteMem64 (VmPtr, (UINTN) VmPtr->Gpr[0], (UINT64) (UINTN)
+ (VmPtr->Ip + Size));
+
+ CopyMem (&TargetEbcAddr, (UINT8 *)FuncAddr +
+ IndexOfEbcEntrypoint,
sizeof(UINTN));
+ VmPtr->Ip = (VMIP) (UINTN) TargetEbcAddr; } else {
+ //
+ // The callee is not a thunk to EBC, call native code,
+ // and get return value.
+ //
+ VmPtr->Gpr[7] = EbcLLCALLEXNative (FuncAddr, NewStackPointer,
+ FramePtr);
+
+ //
+ // Advance the IP.
+ //
+ VmPtr->Ip += Size;
+ }
+}
+
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
b/MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
index 15dc01c..e9a0b28 100644
--- a/MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
@@ -5,6 +5,7 @@
# platform and processor-independent mechanisms for loading and
executing EFI # device drivers.
#
+# Copyright (c) 2015, The Linux Foundation. All rights reserved.
# Copyright (c) 2006 - 2014, Intel Corporation. All rights
reserved.<BR> # This program and the accompanying materials # are
licensed and made available under the terms and conditions of the BSD
License @@ -28,7 +29,7 @@ [Defines] # # The following information is
for reference only and not required by the build tools.
#
-# VALID_ARCHITECTURES = IA32 X64 IPF
+# VALID_ARCHITECTURES = IA32 X64 IPF AARCH64
#

[Sources]
@@ -54,6 +55,9 @@ [Sources.IPF]
Ipf/EbcSupport.c
Ipf/EbcLowLevel.s

+[Sources.AARCH64]
+ AArch64/EbcSupport.c
+ AArch64/EbcLowLevel.S

[Packages]
MdePkg/MdePkg.dec
--
2.1.4

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel


Re: [patch] NetworkPkg: Fix assert issue in iSCSI driver

Siyuan, Fu
 

Reviewed-by: Fu Siyuan <siyuan.fu@intel.com>

-----Original Message-----
From: Zhang, Lubo
Sent: Monday, August 1, 2016 4:38 PM
To: edk2-devel@lists.01.org
Cc: Fu, Siyuan <siyuan.fu@intel.com>; Ye, Ting <ting.ye@intel.com>; Wu,
Jiaxin <jiaxin.wu@intel.com>
Subject: [patch] NetworkPkg: Fix assert issue in iSCSI driver

The bug is caused by using already freed memory.
If there is already an attempt and execute
'reconnect -r' command, all the AttemptConfig structure
will be freed, but the mCallbackInfo->Current is not
configured as null and this pointer will be used again in
IScsiFormExtractConfig.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Zhang Lubo <lubo.zhang@intel.com>
Cc: Fu Siyuan <siyuan.fu@intel.com>
Cc: Ye Ting <ting.ye@intel.com>
Cc: Wu Jiaxin <jiaxin.wu@intel.com>
---
NetworkPkg/IScsiDxe/IScsiMisc.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/NetworkPkg/IScsiDxe/IScsiMisc.c
b/NetworkPkg/IScsiDxe/IScsiMisc.c
index deebf5d..a39c268 100644
--- a/NetworkPkg/IScsiDxe/IScsiMisc.c
+++ b/NetworkPkg/IScsiDxe/IScsiMisc.c
@@ -898,10 +898,12 @@ IScsiCleanDriverData (

EXIT:

gBS->CloseEvent (Private->ExitBootServiceEvent);

+ mCallbackInfo->Current = NULL;
+
FreePool (Private);
return Status;
}

/**
--
1.9.5.msysgit.1


Re: [patch] NetworkPkg: Fix assert issue in iSCSI driver

Ye, Ting <ting.ye@...>
 

Reviewed-by: Ye Ting <ting.ye@intel.com>

-----Original Message-----
From: Zhang, Lubo
Sent: Monday, August 01, 2016 4:38 PM
To: edk2-devel@lists.01.org
Cc: Fu, Siyuan <siyuan.fu@intel.com>; Ye, Ting <ting.ye@intel.com>; Wu, Jiaxin <jiaxin.wu@intel.com>
Subject: [patch] NetworkPkg: Fix assert issue in iSCSI driver

The bug is caused by using already freed memory.
If there is already an attempt and execute 'reconnect -r' command, all the AttemptConfig structure will be freed, but the mCallbackInfo->Current is not configured as null and this pointer will be used again in IScsiFormExtractConfig.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Zhang Lubo <lubo.zhang@intel.com>
Cc: Fu Siyuan <siyuan.fu@intel.com>
Cc: Ye Ting <ting.ye@intel.com>
Cc: Wu Jiaxin <jiaxin.wu@intel.com>
---
NetworkPkg/IScsiDxe/IScsiMisc.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/NetworkPkg/IScsiDxe/IScsiMisc.c b/NetworkPkg/IScsiDxe/IScsiMisc.c index deebf5d..a39c268 100644
--- a/NetworkPkg/IScsiDxe/IScsiMisc.c
+++ b/NetworkPkg/IScsiDxe/IScsiMisc.c
@@ -898,10 +898,12 @@ IScsiCleanDriverData (

EXIT:

gBS->CloseEvent (Private->ExitBootServiceEvent);

+ mCallbackInfo->Current = NULL;
+
FreePool (Private);
return Status;
}

/**
--
1.9.5.msysgit.1


[patch] NetworkPkg: Fix assert issue in iSCSI driver

Zhang Lubo <lubo.zhang@...>
 

The bug is caused by using already freed memory.
If there is already an attempt and execute
'reconnect -r' command, all the AttemptConfig structure
will be freed, but the mCallbackInfo->Current is not
configured as null and this pointer will be used again in
IScsiFormExtractConfig.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Zhang Lubo <lubo.zhang@intel.com>
Cc: Fu Siyuan <siyuan.fu@intel.com>
Cc: Ye Ting <ting.ye@intel.com>
Cc: Wu Jiaxin <jiaxin.wu@intel.com>
---
NetworkPkg/IScsiDxe/IScsiMisc.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/NetworkPkg/IScsiDxe/IScsiMisc.c b/NetworkPkg/IScsiDxe/IScsiMisc.c
index deebf5d..a39c268 100644
--- a/NetworkPkg/IScsiDxe/IScsiMisc.c
+++ b/NetworkPkg/IScsiDxe/IScsiMisc.c
@@ -898,10 +898,12 @@ IScsiCleanDriverData (

EXIT:

gBS->CloseEvent (Private->ExitBootServiceEvent);

+ mCallbackInfo->Current = NULL;
+
FreePool (Private);
return Status;
}

/**
--
1.9.5.msysgit.1


Re: [RFC 1/2] MdeModulePkg/EbcDxe: Add AARCH64 EBC VM support

Ard Biesheuvel
 

On 29 July 2016 at 23:58, Daniil Egranov <daniil.egranov@arm.com> wrote:
Hi Leif,



On 07/29/2016 11:06 AM, Leif Lindholm wrote:

From: Jeff Brasen <jbrasen@codeaurora.org>

Adds support for the EBC VM for AARCH64 platforms

Submitted on behalf of a third-party: The Linux Foundation
This contribution is licensed under the BSD license as found at
http://opensource.org/licenses/bsd-license.php

[Taken from https://source.codeaurora.org/external/server/edk2-blue/]
Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
---
.../Universal/EbcDxe/AArch64/EbcLowLevel.S | 135 +++++
MdeModulePkg/Universal/EbcDxe/AArch64/EbcSupport.c | 563
+++++++++++++++++++++
MdeModulePkg/Universal/EbcDxe/EbcDxe.inf | 6 +-
3 files changed, 703 insertions(+), 1 deletion(-)
create mode 100644 MdeModulePkg/Universal/EbcDxe/AArch64/EbcLowLevel.S
create mode 100644 MdeModulePkg/Universal/EbcDxe/AArch64/EbcSupport.c

diff --git a/MdeModulePkg/Universal/EbcDxe/AArch64/EbcLowLevel.S
b/MdeModulePkg/Universal/EbcDxe/AArch64/EbcLowLevel.S
new file mode 100644
index 0000000..e858227
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/AArch64/EbcLowLevel.S
@@ -0,0 +1,135 @@
+#/** @file
+#
+# This code provides low level routines that support the Virtual
Machine
+# for option ROMs.
+#
+# Copyright (c) 2015, The Linux Foundation. All rights reserved.
+# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the
BSD License
+# which accompanies this distribution. The full text of the license may
be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR
IMPLIED.
+#
+#**/
+

+#---------------------------------------------------------------------------
+# Equate files needed.

+#---------------------------------------------------------------------------
+
+ASM_GLOBAL ASM_PFX(CopyMem);
+ASM_GLOBAL ASM_PFX(EbcInterpret);
+ASM_GLOBAL ASM_PFX(ExecuteEbcImageEntryPoint);
+

+#****************************************************************************
+# EbcLLCALLEX
+#
+# This function is called to execute an EBC CALLEX instruction.
+# This instruction requires that we thunk out to external native
+# code. For AArch64, we copy the VM stack into the main stack and then
pop
+# the first 8 arguments off according to the AArch64 Procedure Call
Standard
+# On return, we restore the stack pointer to its original location.
+#

+#****************************************************************************
+# UINTN EbcLLCALLEXNative(UINTN FuncAddr, UINTN NewStackPointer, VOID
*FramePtr)
The code has a mix of using UINTN and UINT64 types. Even the ProcessorBind.h
defines UINTN as UINT64 for Aarch64, this code is specific for the Aarch64
architecture. Should the UINT64 type be explicitly used instead of UINTN and
avoid mixing of this types?
I don't object to using UINTN and UINT64 interchangeably in a file
that is specific to an architecture where they resolve to the same
thing.

+ASM_GLOBAL ASM_PFX(EbcLLCALLEXNative);
+ASM_PFX(EbcLLCALLEXNative):
+ stp x19, x20, [sp, #-16]!
+ stp x29, x30, [sp, #-16]!
+
+ mov x19, x0
+ mov x20, sp
+ sub x2, x2, x1 // Length = NewStackPointer-FramePtr
+ sub sp, sp, x2
+ sub sp, sp, #64 // Make sure there is room for at least 8 args in
the new stack
+ mov x0, sp
+
+ bl CopyMem // Sp, NewStackPointer, Length
+
+ ldp x0, x1, [sp], #16
+ ldp x2, x3, [sp], #16
+ ldp x4, x5, [sp], #16
+ ldp x6, x7, [sp], #16
+
+ blr x19
+
+ mov sp, x20
+ ldp x29, x30, [sp], #16
+ ldp x19, x20, [sp], #16
+
+ ret
+

+#****************************************************************************
+# EbcLLEbcInterpret
+#
+# This function is called by the thunk code to handle an Native to EBC
call
+# This can handle up to 16 arguments (1-8 on in x0-x7, 9-16 are on the
stack)
+# x9 contains the Entry point that will be the first argument when
+# EBCInterpret is called.
+#

+#****************************************************************************
+ASM_GLOBAL ASM_PFX(EbcLLEbcInterpret);
+ASM_PFX(EbcLLEbcInterpret):
+ stp x29, x30, [sp, #-16]!
+
+ // copy the current arguments 9-16 from old location and add arg 7 to
stack
+ // keeping 16 byte stack alignment
+ sub sp, sp, #80
+ str x7, [sp]
+ ldr x11, [sp, #96]
+ str x11, [sp, #8]
+ ldr x11, [sp, #104]
+ str x11, [sp, #16]
+ ldr x11, [sp, #112]
+ str x11, [sp, #24]
+ ldr x11, [sp, #120]
+ str x11, [sp, #32]
+ ldr x11, [sp, #128]
+ str x11, [sp, #40]
+ ldr x11, [sp, #136]
+ str x11, [sp, #48]
+ ldr x11, [sp, #144]
+ str x11, [sp, #56]
+ ldr x11, [sp, #152]
+ str x11, [sp, #64]
+
+ // Shift arguments and add entry point and as argument 1
+ mov x7, x6
+ mov x6, x5
+ mov x5, x4
+ mov x4, x3
+ mov x3, x2
+ mov x2, x1
+ mov x1, x0
+ mov x0, x9
+
+ # call C-code
+ bl ASM_PFX(EbcInterpret)
+ add sp, sp, #80
+
+ ldp x29, x30, [sp], #16
+
+ ret
+

+#****************************************************************************
+# EbcLLExecuteEbcImageEntryPoint
+#
+# This function is called by the thunk code to handle the image entry
point
+# x9 contains the Entry point that will be the first argument when
+# ExecuteEbcImageEntryPoint is called.
+#

+#****************************************************************************
+ASM_GLOBAL ASM_PFX(EbcLLExecuteEbcImageEntryPoint);
+ASM_PFX(EbcLLExecuteEbcImageEntryPoint):
+ stp x29, x30, [sp, #-16]!
+ # build new paramater calling convention
+ mov x2, x1
+ mov x1, x0
+ mov x0, x9
+
+ # call C-code
+ bl ASM_PFX(ExecuteEbcImageEntryPoint)
+ ldp x29, x30, [sp], #16
+ ret
diff --git a/MdeModulePkg/Universal/EbcDxe/AArch64/EbcSupport.c
b/MdeModulePkg/Universal/EbcDxe/AArch64/EbcSupport.c
new file mode 100644
index 0000000..23261a0
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/AArch64/EbcSupport.c
@@ -0,0 +1,563 @@
+/** @file
+ This module contains EBC support routines that are customized based on
+ the target AArch64 processor.
+
+Copyright (c) 2015, The Linux Foundation. All rights reserved.
+Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD
License
+which accompanies this distribution. The full text of the license may be
found at
+http://opensource.org/licenses/bsd-license.php
+
+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 "EbcInt.h"
+#include "EbcExecute.h"
+
+//
+// Amount of space that is not used in the stack
+//
The "#define VM_STACK_SIZE ()" exists in Ia32, X64 and Ipf code but not
here. However, it's not been used anywhere in the code directly. Is it safe
to ignore it?

+#define STACK_REMAIN_SIZE (1024 * 4)
+
+//
+// This is instruction buffer used to create EBC thunk
+//
+#define EBC_MAGIC_SIGNATURE 0xCA112EBCCA112EBCull
+#define EBC_ENTRYPOINT_SIGNATURE 0xAFAFAFAFAFAFAFAFull
+#define EBC_LL_EBC_ENTRYPOINT_SIGNATURE 0xFAFAFAFAFAFAFAFAull
+UINT8 mInstructionBufferTemplate[] = {
+ 0x03, 0x00, 0x00, 0x14, //b pc+16
+ //
+ // Add a magic code here to help the VM recognize the thunk..
+ //
+ (UINT8)(EBC_MAGIC_SIGNATURE & 0xFF),
+ (UINT8)((EBC_MAGIC_SIGNATURE >> 8) & 0xFF),
+ (UINT8)((EBC_MAGIC_SIGNATURE >> 16) & 0xFF),
+ (UINT8)((EBC_MAGIC_SIGNATURE >> 24) & 0xFF),
+ (UINT8)((EBC_MAGIC_SIGNATURE >> 32) & 0xFF),
+ (UINT8)((EBC_MAGIC_SIGNATURE >> 40) & 0xFF),
+ (UINT8)((EBC_MAGIC_SIGNATURE >> 48) & 0xFF),
+ (UINT8)((EBC_MAGIC_SIGNATURE >> 56) & 0xFF),
+ 0x69, 0x00, 0x00, 0x58, //ldr x9, #32
+ 0x8A, 0x00, 0x00, 0x58, //ldr x10, #40
+ 0x05, 0x00, 0x00, 0x14, //b pc+32
+ (UINT8)(EBC_ENTRYPOINT_SIGNATURE & 0xFF),
+ (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 8) & 0xFF),
+ (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 16) & 0xFF),
+ (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 24) & 0xFF),
+ (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 32) & 0xFF),
+ (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 40) & 0xFF),
+ (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 48) & 0xFF),
+ (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 56) & 0xFF),
+ (UINT8)(EBC_LL_EBC_ENTRYPOINT_SIGNATURE & 0xFF),
+ (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 8) & 0xFF),
+ (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 16) & 0xFF),
+ (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 24) & 0xFF),
+ (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 32) & 0xFF),
+ (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 40) & 0xFF),
+ (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 48) & 0xFF),
+ (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 56) & 0xFF),
+ 0x40, 0x01, 0x1F, 0xD6 //br x10
+
+};
This template may need additional comments explaining the code. There are
couple of branching in the template above with jumping to PC+16 and PC+32.
Are the 16 and 32 correct values?

Assuming that this template should have a similar functionality as x64
template:
mov rax, 0xca112ebcca112ebc //store a magic signature (EBC_MAGIC_SIGNATURE)
mov r10, XXXXXXXXXXXXXXXX // store EBC entry point, the dummy address
replaced with a valid address during runtime (EBC_ENTRYPOINT_SIGNATURE
marker)
mov r11, XXXXXXXXXXXXXXXX //store VM function address, the dummy address
replaced with a valid address during runtime
(EBC_LL_EBC_ENTRYPOINT_SIGNATURE marker)
jmp r11
The thunking code is a bit clunky, and tries to deal with variable
length instructions which makes no sense on AARCH64. I rewrote some
parts of it. I will send it out as soon as I have managed to test it.

+
+/**
+ Begin executing an EBC image.
+ This is used for Ebc Thunk call.
+
+ @return The value returned by the EBC application we're going to run.
+
+**/
+UINT64
+EFIAPI
+EbcLLEbcInterpret (
+ VOID
+ );
+
+/**
+ Begin executing an EBC image.
+ This is used for Ebc image entrypoint.
+
+ @return The value returned by the EBC application we're going to run.
+
+**/
+UINT64
+EFIAPI
+EbcLLExecuteEbcImageEntryPoint (
+ VOID
+ );
+
+/**
+ Pushes a 64 bit unsigned value to the VM stack.
+
+ @param VmPtr The pointer to current VM context.
+ @param Arg The value to be pushed.
+
+**/
+VOID
+PushU64 (
+ IN VM_CONTEXT *VmPtr,
+ IN UINT64 Arg
+ )
+{
+ //
+ // Advance the VM stack down, and then copy the argument to the stack.
+ // Hope it's aligned.
+ //
+ VmPtr->Gpr[0] -= sizeof (UINT64);
+ *(UINT64 *) VmPtr->Gpr[0] = Arg;
+ return;
+}
+
+
+/**
+ Begin executing an EBC image.
+
+ This is a thunk function.
+
+ @param EntryPoint The entrypoint of EBC code.
+ @param Arg1 The 1st argument.
+ @param Arg2 The 2nd argument.
+ @param Arg3 The 3rd argument.
+ @param Arg4 The 4th argument.
+ @param Arg5 The 5th argument.
+ @param Arg6 The 6th argument.
+ @param Arg7 The 7th argument.
+ @param Arg8 The 8th argument.
+ @param Arg9 The 9th argument.
+ @param Arg10 The 10th argument.
+ @param Arg11 The 11th argument.
+ @param Arg12 The 12th argument.
+ @param Arg13 The 13th argument.
+ @param Arg14 The 14th argument.
+ @param Arg15 The 15th argument.
+ @param Arg16 The 16th argument.
+
+ @return The value returned by the EBC application we're going to run.
+
+**/
+UINT64
+EFIAPI
+EbcInterpret (
+ IN UINTN EntryPoint,
+ IN UINTN Arg1,
+ IN UINTN Arg2,
+ IN UINTN Arg3,
+ IN UINTN Arg4,
+ IN UINTN Arg5,
+ IN UINTN Arg6,
+ IN UINTN Arg7,
+ IN UINTN Arg8,
+ IN UINTN Arg9,
+ IN UINTN Arg10,
+ IN UINTN Arg11,
+ IN UINTN Arg12,
+ IN UINTN Arg13,
+ IN UINTN Arg14,
+ IN UINTN Arg15,
+ IN UINTN Arg16
+ )
+{
+ //
+ // Create a new VM context on the stack
+ //
+ VM_CONTEXT VmContext;
+ UINTN Addr;
+ EFI_STATUS Status;
+ UINTN StackIndex;
+
+ //
+ // Get the EBC entry point
+ //
+ Addr = EntryPoint;
+
+ //
+ // Now clear out our context
+ //
+ ZeroMem ((VOID *) &VmContext, sizeof (VM_CONTEXT));
+
+ //
+ // Set the VM instruction pointer to the correct location in memory.
+ //
+ VmContext.Ip = (VMIP) Addr;
+
+ //
+ // Initialize the stack pointer for the EBC. Get the current system
stack
+ // pointer and adjust it down by the max needed for the interpreter.
+ //
+
+ //
+ // Adjust the VM's stack pointer down.
+ //
+
+ Status = GetEBCStack((EFI_HANDLE)(UINTN)-1, &VmContext.StackPool,
&StackIndex);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ VmContext.StackTop = (UINT8*)VmContext.StackPool + (STACK_REMAIN_SIZE);
+ VmContext.Gpr[0] = (UINT64) ((UINT8*)VmContext.StackPool +
STACK_POOL_SIZE);
+ VmContext.HighStackBottom = (UINTN) VmContext.Gpr[0];
+ VmContext.Gpr[0] -= sizeof (UINTN);
+
+ //
+ // Align the stack on a natural boundary.
+ //
+ VmContext.Gpr[0] &= ~(VM_REGISTER)(sizeof (UINTN) - 1);
This code is the same as x64. Is this correct alignment for Aarch64?
This is the VM stack alignment, not the native stack alignment.

+
+ //
+ // Put a magic value in the stack gap, then adjust down again.
+ //
+ *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) VM_STACK_KEY_VALUE;
+ VmContext.StackMagicPtr = (UINTN *) (UINTN)
VmContext.Gpr[0];
+
+ //
+ // The stack upper to LowStackTop is belong to the VM.
+ //
+ VmContext.LowStackTop = (UINTN) VmContext.Gpr[0];
+
+ //
+ // For the worst case, assume there are 4 arguments passed in
registers, store
+ // them to VM's stack.
+ //
+ PushU64 (&VmContext, (UINT64) Arg16);
+ PushU64 (&VmContext, (UINT64) Arg15);
+ PushU64 (&VmContext, (UINT64) Arg14);
+ PushU64 (&VmContext, (UINT64) Arg13);
+ PushU64 (&VmContext, (UINT64) Arg12);
+ PushU64 (&VmContext, (UINT64) Arg11);
+ PushU64 (&VmContext, (UINT64) Arg10);
+ PushU64 (&VmContext, (UINT64) Arg9);
+ PushU64 (&VmContext, (UINT64) Arg8);
+ PushU64 (&VmContext, (UINT64) Arg7);
+ PushU64 (&VmContext, (UINT64) Arg6);
+ PushU64 (&VmContext, (UINT64) Arg5);
+ PushU64 (&VmContext, (UINT64) Arg4);
+ PushU64 (&VmContext, (UINT64) Arg3);
+ PushU64 (&VmContext, (UINT64) Arg2);
+ PushU64 (&VmContext, (UINT64) Arg1);
+
+ //
+ // Interpreter assumes 64-bit return address is pushed on the stack.
+ // AArch64 does not do this so pad the stack accordingly.
+ //
+ PushU64 (&VmContext, (UINT64) 0);
+ PushU64 (&VmContext, (UINT64) 0x1234567887654321ULL);
+
+ //
+ // For AArch64, this is where we say our return address is
+ //
+ VmContext.StackRetAddr = (UINT64) VmContext.Gpr[0];
+
+ //
+ // We need to keep track of where the EBC stack starts. This way, if
the EBC
+ // accesses any stack variables above its initial stack setting, then
we know
+ // it's accessing variables passed into it, which means the data is on
the
+ // VM's stack.
+ // When we're called, on the stack (high to low) we have the
parameters, the
+ // return address, then the saved ebp. Save the pointer to the return
address.
+ // EBC code knows that's there, so should look above it for function
parameters.
+ // The offset is the size of locals (VMContext + Addr + saved ebp).
+ // Note that the interpreter assumes there is a 16 bytes of return
address on
+ // the stack too, so adjust accordingly.
+ // VmContext.HighStackBottom = (UINTN)(Addr + sizeof (VmContext) +
sizeof (Addr));
+ //
+
+ //
+ // Begin executing the EBC code
+ //
+ EbcExecute (&VmContext);
+
+ //
+ // Return the value in R[7] unless there was an error
+ //
+ ReturnEBCStack(StackIndex);
+ return (UINT64) VmContext.Gpr[7];
+}
+
+
+/**
+ Begin executing an EBC image.
+
+ @param EntryPoint The entrypoint of EBC code.
+ @param ImageHandle image handle for the EBC application we're
executing
+ @param SystemTable standard system table passed into an driver's
entry
+ point
+
+ @return The value returned by the EBC application we're going to run.
+
+**/
+UINT64
+EFIAPI
+ExecuteEbcImageEntryPoint (
+ IN UINTN EntryPoint,
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ //
+ // Create a new VM context on the stack
+ //
+ VM_CONTEXT VmContext;
+ UINTN Addr;
+ EFI_STATUS Status;
+ UINTN StackIndex;
+
+ //
+ // Get the EBC entry point
+ //
+ Addr = EntryPoint;
+
+ //
+ // Now clear out our context
+ //
+ ZeroMem ((VOID *) &VmContext, sizeof (VM_CONTEXT));
+
+ //
+ // Save the image handle so we can track the thunks created for this
image
+ //
+ VmContext.ImageHandle = ImageHandle;
+ VmContext.SystemTable = SystemTable;
+
+ //
+ // Set the VM instruction pointer to the correct location in memory.
+ //
+ VmContext.Ip = (VMIP) Addr;
+
+ //
+ // Initialize the stack pointer for the EBC. Get the current system
stack
+ // pointer and adjust it down by the max needed for the interpreter.
+ //
+
+ Status = GetEBCStack(ImageHandle, &VmContext.StackPool, &StackIndex);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ VmContext.StackTop = (UINT8*)VmContext.StackPool + (STACK_REMAIN_SIZE);
+ VmContext.Gpr[0] = (UINT64) ((UINT8*)VmContext.StackPool +
STACK_POOL_SIZE);
+ VmContext.HighStackBottom = (UINTN) VmContext.Gpr[0];
+ VmContext.Gpr[0] -= sizeof (UINTN);
+
+
+ //
+ // Put a magic value in the stack gap, then adjust down again
+ //
+ *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) VM_STACK_KEY_VALUE;
+ VmContext.StackMagicPtr = (UINTN *) (UINTN)
VmContext.Gpr[0];
+
+ //
+ // Align the stack on a natural boundary
+ VmContext.Gpr[0] &= ~(VM_REGISTER)(sizeof(UINTN) - 1);
This code is the same as x64. Is this correct alignment for Aarch64?

+ //
+ VmContext.LowStackTop = (UINTN) VmContext.Gpr[0];
+
+ //
+ // Simply copy the image handle and system table onto the EBC stack.
+ // Greatly simplifies things by not having to spill the args.
+ //
+ PushU64 (&VmContext, (UINT64) SystemTable);
+ PushU64 (&VmContext, (UINT64) ImageHandle);
+
+ //
+ // VM pushes 16-bytes for return address. Simulate that here.
+ //
+ PushU64 (&VmContext, (UINT64) 0);
+ PushU64 (&VmContext, (UINT64) 0x1234567887654321ULL);
+
+ //
+ // For AArch64, this is where we say our return address is
+ //
+ VmContext.StackRetAddr = (UINT64) VmContext.Gpr[0];
+
+ //
+ // Entry function needn't access high stack context, simply
+ // put the stack pointer here.
+ //
+
+ //
+ // Begin executing the EBC code
+ //
+ EbcExecute (&VmContext);
+
+ //
+ // Return the value in R[7] unless there was an error
+ //
+ ReturnEBCStack(StackIndex);
+ return (UINT64) VmContext.Gpr[7];
+}
+
+
+/**
+ Create thunks for an EBC image entry point, or an EBC protocol service.
+
+ @param ImageHandle Image handle for the EBC image. If not
null, then
+ we're creating a thunk for an image entry
point.
+ @param EbcEntryPoint Address of the EBC code that the thunk is
to call
+ @param Thunk Returned thunk we create here
+ @param Flags Flags indicating options for creating the
thunk
+
+ @retval EFI_SUCCESS The thunk was created successfully.
+ @retval EFI_INVALID_PARAMETER The parameter of EbcEntryPoint is not
16-bit
+ aligned.
+ @retval EFI_OUT_OF_RESOURCES There is not enough memory to created the
EBC
+ Thunk.
+ @retval EFI_BUFFER_TOO_SMALL EBC_THUNK_SIZE is not larger enough.
+
+**/
+EFI_STATUS
+EbcCreateThunks (
+ IN EFI_HANDLE ImageHandle,
+ IN VOID *EbcEntryPoint,
+ OUT VOID **Thunk,
+ IN UINT32 Flags
+ )
+{
+ UINT8 *Ptr;
+ UINT8 *ThunkBase;
+ UINT32 Index;
+ INT32 ThunkSize;
+
+ //
+ // Check alignment of pointer to EBC code
+ //
+ if ((UINT32) (UINTN) EbcEntryPoint & 0x01) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ThunkSize = sizeof(mInstructionBufferTemplate);
+
+ Ptr = AllocatePool (sizeof(mInstructionBufferTemplate));
+
+ if (Ptr == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Print(L"Allocate TH: 0x%X\n", (UINT32)Ptr);
+ //
+ // Save the start address so we can add a pointer to it to a list
later.
+ //
+ ThunkBase = Ptr;
+
+ //
+ // Give them the address of our buffer we're going to fix up
+ //
+ *Thunk = (VOID *) Ptr;
+
+ //
+ // Copy whole thunk instruction buffer template
+ //
+ CopyMem (Ptr, mInstructionBufferTemplate,
sizeof(mInstructionBufferTemplate));
+
+ //
+ // Patch EbcEntryPoint and EbcLLEbcInterpret
+ //
+ for (Index = 0; Index < sizeof(mInstructionBufferTemplate) -
sizeof(UINTN); Index++) {
+ if (*(UINTN *)&Ptr[Index] == EBC_ENTRYPOINT_SIGNATURE) {
+ *(UINTN *)&Ptr[Index] = (UINTN)EbcEntryPoint;
+ }
+ if (*(UINTN *)&Ptr[Index] == EBC_LL_EBC_ENTRYPOINT_SIGNATURE) {
+ if ((Flags & FLAG_THUNK_ENTRY_POINT) != 0) {
+ *(UINTN *)&Ptr[Index] = (UINTN)EbcLLExecuteEbcImageEntryPoint;
+ } else {
+ *(UINTN *)&Ptr[Index] = (UINTN)EbcLLEbcInterpret;
+ }
+ }
+ }
+
+ //
+ // Add the thunk to the list for this image. Do this last since the add
+ // function flushes the cache for us.
+ //
+ EbcAddImageThunk (ImageHandle, (VOID *) ThunkBase, ThunkSize);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function is called to execute an EBC CALLEX instruction.
+ The function check the callee's content to see whether it is common
native
+ code or a thunk to another piece of EBC code.
+ If the callee is common native code, use EbcLLCAllEXASM to manipulate,
+ otherwise, set the VM->IP to target EBC code directly to avoid another
VM
+ be startup which cost time and stack space.
+
+ @param VmPtr Pointer to a VM context.
+ @param FuncAddr Callee's address
+ @param NewStackPointer New stack pointer after the call
+ @param FramePtr New frame pointer after the call
+ @param Size The size of call instruction
+
+**/
+VOID
+EbcLLCALLEX (
+ IN VM_CONTEXT *VmPtr,
+ IN UINTN FuncAddr,
+ IN UINTN NewStackPointer,
+ IN VOID *FramePtr,
+ IN UINT8 Size
+ )
+{
+ UINTN IsThunk;
+ UINTN TargetEbcAddr;
+ UINT8 InstructionBuffer[sizeof(mInstructionBufferTemplate)];
+ UINTN Index;
+ UINTN IndexOfEbcEntrypoint;
+
+ IsThunk = 1;
+ TargetEbcAddr = 0;
+ IndexOfEbcEntrypoint = 0;
+
+ //
+ // Processor specific code to check whether the callee is a thunk to
EBC.
+ //
+ CopyMem (InstructionBuffer, (VOID *)FuncAddr,
sizeof(InstructionBuffer));
+ //
+ // Fill the signature according to mInstructionBufferTemplate
+ //
+ for (Index = 0; Index < sizeof(mInstructionBufferTemplate) -
sizeof(UINTN); Index++) {
+ if (*(UINTN *)&mInstructionBufferTemplate[Index] ==
EBC_ENTRYPOINT_SIGNATURE) {
+ *(UINTN *)&InstructionBuffer[Index] = EBC_ENTRYPOINT_SIGNATURE;
+ IndexOfEbcEntrypoint = Index;
+ }
+ if (*(UINTN *)&mInstructionBufferTemplate[Index] ==
EBC_LL_EBC_ENTRYPOINT_SIGNATURE) {
+ *(UINTN *)&InstructionBuffer[Index] =
EBC_LL_EBC_ENTRYPOINT_SIGNATURE;
+ }
+ }
+ //
+ // Check if we need thunk to native
+ //
+ if (CompareMem (InstructionBuffer, mInstructionBufferTemplate,
sizeof(mInstructionBufferTemplate)) != 0) {
+ IsThunk = 0;
+ }
+
+ if (IsThunk == 1){
+ //
+ // The callee is a thunk to EBC, adjust the stack pointer down 16
bytes and
+ // put our return address and frame pointer on the VM stack.
+ // Then set the VM's IP to new EBC code.
+ //
+ VmPtr->Gpr[0] -= 8;
+ VmWriteMemN (VmPtr, (UINTN) VmPtr->Gpr[0], (UINTN) FramePtr);
+ VmPtr->FramePtr = (VOID *) (UINTN) VmPtr->Gpr[0];
+ VmPtr->Gpr[0] -= 8;
+ VmWriteMem64 (VmPtr, (UINTN) VmPtr->Gpr[0], (UINT64) (UINTN)
(VmPtr->Ip + Size));
+
+ CopyMem (&TargetEbcAddr, (UINT8 *)FuncAddr + IndexOfEbcEntrypoint,
sizeof(UINTN));
+ VmPtr->Ip = (VMIP) (UINTN) TargetEbcAddr;
+ } else {
+ //
+ // The callee is not a thunk to EBC, call native code,
+ // and get return value.
+ //
+ VmPtr->Gpr[7] = EbcLLCALLEXNative (FuncAddr, NewStackPointer,
FramePtr);
+
+ //
+ // Advance the IP.
+ //
+ VmPtr->Ip += Size;
+ }
+}
+
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
b/MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
index 15dc01c..e9a0b28 100644
--- a/MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
@@ -5,6 +5,7 @@
# platform and processor-independent mechanisms for loading and
executing EFI
# device drivers.
#
+# Copyright (c) 2015, The Linux Foundation. All rights reserved.
# Copyright (c) 2006 - 2014, Intel Corporation. All rights
reserved.<BR>
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the
BSD License
@@ -28,7 +29,7 @@ [Defines]
#
# The following information is for reference only and not required by
the build tools.
#
-# VALID_ARCHITECTURES = IA32 X64 IPF
+# VALID_ARCHITECTURES = IA32 X64 IPF AARCH64
#
[Sources]
@@ -54,6 +55,9 @@ [Sources.IPF]
Ipf/EbcSupport.c
Ipf/EbcLowLevel.s
+[Sources.AARCH64]
+ AArch64/EbcSupport.c
+ AArch64/EbcLowLevel.S
[Packages]
MdePkg/MdePkg.dec

Thanks,
Daniil


Re: [PATCH v2 2/7] BaseTools-GenFw:Add new x86_64 Elf relocation types for PIC/PIE code

Shi, Steven <steven.shi@...>
 

On 1 August 2016 at 09:54, Shi, Steven <steven.shi@intel.com> wrote:
On 1 August 2016 at 09:19, Shi, Steven
<steven.shi@intel.com<mailto:steven.shi@intel.com>> wrote:

The fact that it works does not make it safe. Having multiple fixups
for the same symbol in the .reloc section is a problem, and so is
reapplying GOTPCRELX to places where the original instruction has
been
replaced by the linker.
[Steven]: I still don't understand why there will be multiple fixups for
the
same symbol in the .reloc section?
Remember this example

int n;
int f () { return n; }
int g () { return n; }
int h () { return n; }
If every 'return n' results in a GOTPCREL relocation, how are you
going to make sure that the GOT entry for 'n' is only fixed up a
single time?
[Steven]: the 'return n' will not result in relocation, but the 'int n' will
result
in the relocation in GOT. The three 'return n' will point to the same 'int n'
relocation item. So, we need only fixup 'int n' once, all three 'return n' will
use the correct global 'n' value.

Every 'return n' will result in a GOTPCREL relocation against n. And
your code emits a relocation for the GOT entry every time.
[Steven]: I don't think so. please give a real case and offer its source code
to prove " Every 'return n' will result in a GOTPCREL relocation against n ".
Compiling the code above using

gcc -c -O -fpic /tmp/pie.c -o pie.o

and dumping it using

readelf -r pie.o

gives me

Relocation section '.rela.text' at offset 0x250 contains 3 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000000003 000a0000002a R_X86_64_REX_GOTP 0000000000000004 n -
4
00000000000d 000a0000002a R_X86_64_REX_GOTP 0000000000000004 n -
4
000000000017 000a0000002a R_X86_64_REX_GOTP 0000000000000004 n -
4
...
[Steven]: In this example, the pie.o is just the object file which is not linked. And if you link this pie.o file, the linker will solve all these three R_X86_64_REX_GOTP symbol with same 'int n' symbol address, and will create only one relocation item for 'int n' in the linked executable relocation section. So, we only need fixup once for the 'int n' in the linked executable.

Thanks
Steven


Re: [RFC 1/2] MdeModulePkg/EbcDxe: Add AARCH64 EBC VM support

Leif Lindholm <leif.lindholm@...>
 

Hi Feng,

For the record, http://opensource.org/licenses/bsd-license.php is the
same as http://opensource.org/licenses/BSD-2-Clause.

Which is mentioned explicitly under point 5 of the MdeModulePkg
Contributions.txt:
---
5. It is preferred that contributions are submitted using the same
copyright license as the base project. When that is not possible,
then contributions using the following licenses can be accepted:
* BSD (2-clause): http://opensource.org/licenses/BSD-2-Clause
* BSD (3-clause): http://opensource.org/licenses/BSD-3-Clause
* MIT: http://opensource.org/licenses/MIT
* Python-2.0: http://opensource.org/licenses/Python-2.0
* Zlib: http://opensource.org/licenses/Zlib
---

Regards,

Leif

On Mon, Aug 01, 2016 at 01:49:35AM +0000, Tian, Feng wrote:
Hi, Leif

If I understand correctly, EDKII doesn't allow such BSD license.

Correct me if anybody has different opinions.

Thanks
Feng

-----Original Message-----
From: Leif Lindholm [mailto:leif.lindholm@linaro.org]
Sent: Saturday, July 30, 2016 12:06 AM
To: edk2-devel@lists.01.org
Cc: Jeff Brasen <jbrasen@codeaurora.org>; Ard Biesheuvel <ard.biesheuvel@linaro.org>; Daniil Egranov <daniil.egranov@linaro.org>; Tian, Feng <feng.tian@intel.com>; Zeng, Star <star.zeng@intel.com>
Subject: [RFC 1/2] MdeModulePkg/EbcDxe: Add AARCH64 EBC VM support

From: Jeff Brasen <jbrasen@codeaurora.org>

Adds support for the EBC VM for AARCH64 platforms

Submitted on behalf of a third-party: The Linux Foundation This contribution is licensed under the BSD license as found at http://opensource.org/licenses/bsd-license.php

[Taken from https://source.codeaurora.org/external/server/edk2-blue/]
Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
---
.../Universal/EbcDxe/AArch64/EbcLowLevel.S | 135 +++++
MdeModulePkg/Universal/EbcDxe/AArch64/EbcSupport.c | 563 +++++++++++++++++++++
MdeModulePkg/Universal/EbcDxe/EbcDxe.inf | 6 +-
3 files changed, 703 insertions(+), 1 deletion(-) create mode 100644 MdeModulePkg/Universal/EbcDxe/AArch64/EbcLowLevel.S
create mode 100644 MdeModulePkg/Universal/EbcDxe/AArch64/EbcSupport.c

diff --git a/MdeModulePkg/Universal/EbcDxe/AArch64/EbcLowLevel.S b/MdeModulePkg/Universal/EbcDxe/AArch64/EbcLowLevel.S
new file mode 100644
index 0000000..e858227
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/AArch64/EbcLowLevel.S
@@ -0,0 +1,135 @@
+#/** @file
+#
+# This code provides low level routines that support the Virtual Machine
+# for option ROMs.
+#
+# Copyright (c) 2015, The Linux Foundation. All rights reserved.
+# Copyright (c) 2007 - 2014, Intel Corporation. All rights
+reserved.<BR> # This program and the accompanying materials # are
+licensed and made available under the terms and conditions of the BSD
+License # which accompanies this distribution. The full text of the
+license may be found at #
+http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+BASIS, # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+#----------------------------------------------------------------------
+-----
+# Equate files needed.
+#----------------------------------------------------------------------
+-----
+
+ASM_GLOBAL ASM_PFX(CopyMem);
+ASM_GLOBAL ASM_PFX(EbcInterpret);
+ASM_GLOBAL ASM_PFX(ExecuteEbcImageEntryPoint);
+
+#**********************************************************************
+******
+# EbcLLCALLEX
+#
+# This function is called to execute an EBC CALLEX instruction.
+# This instruction requires that we thunk out to external native #
+code. For AArch64, we copy the VM stack into the main stack and then
+pop # the first 8 arguments off according to the AArch64 Procedure Call
+Standard # On return, we restore the stack pointer to its original location.
+#
+#**********************************************************************
+****** # UINTN EbcLLCALLEXNative(UINTN FuncAddr, UINTN NewStackPointer,
+VOID *FramePtr) ASM_GLOBAL ASM_PFX(EbcLLCALLEXNative);
+ASM_PFX(EbcLLCALLEXNative):
+ stp x19, x20, [sp, #-16]!
+ stp x29, x30, [sp, #-16]!
+
+ mov x19, x0
+ mov x20, sp
+ sub x2, x2, x1 // Length = NewStackPointer-FramePtr
+ sub sp, sp, x2
+ sub sp, sp, #64 // Make sure there is room for at least 8 args in the new stack
+ mov x0, sp
+
+ bl CopyMem // Sp, NewStackPointer, Length
+
+ ldp x0, x1, [sp], #16
+ ldp x2, x3, [sp], #16
+ ldp x4, x5, [sp], #16
+ ldp x6, x7, [sp], #16
+
+ blr x19
+
+ mov sp, x20
+ ldp x29, x30, [sp], #16
+ ldp x19, x20, [sp], #16
+
+ ret
+
+#**********************************************************************
+******
+# EbcLLEbcInterpret
+#
+# This function is called by the thunk code to handle an Native to EBC
+call # This can handle up to 16 arguments (1-8 on in x0-x7, 9-16 are on
+the stack) # x9 contains the Entry point that will be the first
+argument when # EBCInterpret is called.
+#
+#**********************************************************************
+******
+ASM_GLOBAL ASM_PFX(EbcLLEbcInterpret);
+ASM_PFX(EbcLLEbcInterpret):
+ stp x29, x30, [sp, #-16]!
+
+ // copy the current arguments 9-16 from old location and add arg 7 to stack
+ // keeping 16 byte stack alignment
+ sub sp, sp, #80
+ str x7, [sp]
+ ldr x11, [sp, #96]
+ str x11, [sp, #8]
+ ldr x11, [sp, #104]
+ str x11, [sp, #16]
+ ldr x11, [sp, #112]
+ str x11, [sp, #24]
+ ldr x11, [sp, #120]
+ str x11, [sp, #32]
+ ldr x11, [sp, #128]
+ str x11, [sp, #40]
+ ldr x11, [sp, #136]
+ str x11, [sp, #48]
+ ldr x11, [sp, #144]
+ str x11, [sp, #56]
+ ldr x11, [sp, #152]
+ str x11, [sp, #64]
+
+ // Shift arguments and add entry point and as argument 1
+ mov x7, x6
+ mov x6, x5
+ mov x5, x4
+ mov x4, x3
+ mov x3, x2
+ mov x2, x1
+ mov x1, x0
+ mov x0, x9
+
+ # call C-code
+ bl ASM_PFX(EbcInterpret)
+ add sp, sp, #80
+
+ ldp x29, x30, [sp], #16
+
+ ret
+
+#**********************************************************************
+******
+# EbcLLExecuteEbcImageEntryPoint
+#
+# This function is called by the thunk code to handle the image entry
+point # x9 contains the Entry point that will be the first argument
+when # ExecuteEbcImageEntryPoint is called.
+#
+#**********************************************************************
+****** ASM_GLOBAL ASM_PFX(EbcLLExecuteEbcImageEntryPoint);
+ASM_PFX(EbcLLExecuteEbcImageEntryPoint):
+ stp x29, x30, [sp, #-16]!
+ # build new paramater calling convention
+ mov x2, x1
+ mov x1, x0
+ mov x0, x9
+
+ # call C-code
+ bl ASM_PFX(ExecuteEbcImageEntryPoint)
+ ldp x29, x30, [sp], #16
+ ret
diff --git a/MdeModulePkg/Universal/EbcDxe/AArch64/EbcSupport.c b/MdeModulePkg/Universal/EbcDxe/AArch64/EbcSupport.c
new file mode 100644
index 0000000..23261a0
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/AArch64/EbcSupport.c
@@ -0,0 +1,563 @@
+/** @file
+ This module contains EBC support routines that are customized based
+on
+ the target AArch64 processor.
+
+Copyright (c) 2015, The Linux Foundation. All rights reserved.
+Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made
+available under the terms and conditions of the BSD License which
+accompanies this distribution. The full text of the license may be
+found at http://opensource.org/licenses/bsd-license.php
+
+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 "EbcInt.h"
+#include "EbcExecute.h"
+
+//
+// Amount of space that is not used in the stack // #define
+STACK_REMAIN_SIZE (1024 * 4)
+
+//
+// This is instruction buffer used to create EBC thunk //
+#define EBC_MAGIC_SIGNATURE 0xCA112EBCCA112EBCull
+#define EBC_ENTRYPOINT_SIGNATURE 0xAFAFAFAFAFAFAFAFull
+#define EBC_LL_EBC_ENTRYPOINT_SIGNATURE 0xFAFAFAFAFAFAFAFAull
+UINT8 mInstructionBufferTemplate[] = {
+ 0x03, 0x00, 0x00, 0x14, //b pc+16
+ //
+ // Add a magic code here to help the VM recognize the thunk..
+ //
+ (UINT8)(EBC_MAGIC_SIGNATURE & 0xFF),
+ (UINT8)((EBC_MAGIC_SIGNATURE >> 8) & 0xFF),
+ (UINT8)((EBC_MAGIC_SIGNATURE >> 16) & 0xFF),
+ (UINT8)((EBC_MAGIC_SIGNATURE >> 24) & 0xFF),
+ (UINT8)((EBC_MAGIC_SIGNATURE >> 32) & 0xFF),
+ (UINT8)((EBC_MAGIC_SIGNATURE >> 40) & 0xFF),
+ (UINT8)((EBC_MAGIC_SIGNATURE >> 48) & 0xFF),
+ (UINT8)((EBC_MAGIC_SIGNATURE >> 56) & 0xFF),
+ 0x69, 0x00, 0x00, 0x58, //ldr x9, #32
+ 0x8A, 0x00, 0x00, 0x58, //ldr x10, #40
+ 0x05, 0x00, 0x00, 0x14, //b pc+32
+ (UINT8)(EBC_ENTRYPOINT_SIGNATURE & 0xFF),
+ (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 8) & 0xFF),
+ (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 16) & 0xFF),
+ (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 24) & 0xFF),
+ (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 32) & 0xFF),
+ (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 40) & 0xFF),
+ (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 48) & 0xFF),
+ (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 56) & 0xFF),
+ (UINT8)(EBC_LL_EBC_ENTRYPOINT_SIGNATURE & 0xFF),
+ (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 8) & 0xFF),
+ (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 16) & 0xFF),
+ (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 24) & 0xFF),
+ (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 32) & 0xFF),
+ (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 40) & 0xFF),
+ (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 48) & 0xFF),
+ (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 56) & 0xFF),
+ 0x40, 0x01, 0x1F, 0xD6 //br x10
+
+};
+
+/**
+ Begin executing an EBC image.
+ This is used for Ebc Thunk call.
+
+ @return The value returned by the EBC application we're going to run.
+
+**/
+UINT64
+EFIAPI
+EbcLLEbcInterpret (
+ VOID
+ );
+
+/**
+ Begin executing an EBC image.
+ This is used for Ebc image entrypoint.
+
+ @return The value returned by the EBC application we're going to run.
+
+**/
+UINT64
+EFIAPI
+EbcLLExecuteEbcImageEntryPoint (
+ VOID
+ );
+
+/**
+ Pushes a 64 bit unsigned value to the VM stack.
+
+ @param VmPtr The pointer to current VM context.
+ @param Arg The value to be pushed.
+
+**/
+VOID
+PushU64 (
+ IN VM_CONTEXT *VmPtr,
+ IN UINT64 Arg
+ )
+{
+ //
+ // Advance the VM stack down, and then copy the argument to the stack.
+ // Hope it's aligned.
+ //
+ VmPtr->Gpr[0] -= sizeof (UINT64);
+ *(UINT64 *) VmPtr->Gpr[0] = Arg;
+ return;
+}
+
+
+/**
+ Begin executing an EBC image.
+
+ This is a thunk function.
+
+ @param EntryPoint The entrypoint of EBC code.
+ @param Arg1 The 1st argument.
+ @param Arg2 The 2nd argument.
+ @param Arg3 The 3rd argument.
+ @param Arg4 The 4th argument.
+ @param Arg5 The 5th argument.
+ @param Arg6 The 6th argument.
+ @param Arg7 The 7th argument.
+ @param Arg8 The 8th argument.
+ @param Arg9 The 9th argument.
+ @param Arg10 The 10th argument.
+ @param Arg11 The 11th argument.
+ @param Arg12 The 12th argument.
+ @param Arg13 The 13th argument.
+ @param Arg14 The 14th argument.
+ @param Arg15 The 15th argument.
+ @param Arg16 The 16th argument.
+
+ @return The value returned by the EBC application we're going to run.
+
+**/
+UINT64
+EFIAPI
+EbcInterpret (
+ IN UINTN EntryPoint,
+ IN UINTN Arg1,
+ IN UINTN Arg2,
+ IN UINTN Arg3,
+ IN UINTN Arg4,
+ IN UINTN Arg5,
+ IN UINTN Arg6,
+ IN UINTN Arg7,
+ IN UINTN Arg8,
+ IN UINTN Arg9,
+ IN UINTN Arg10,
+ IN UINTN Arg11,
+ IN UINTN Arg12,
+ IN UINTN Arg13,
+ IN UINTN Arg14,
+ IN UINTN Arg15,
+ IN UINTN Arg16
+ )
+{
+ //
+ // Create a new VM context on the stack
+ //
+ VM_CONTEXT VmContext;
+ UINTN Addr;
+ EFI_STATUS Status;
+ UINTN StackIndex;
+
+ //
+ // Get the EBC entry point
+ //
+ Addr = EntryPoint;
+
+ //
+ // Now clear out our context
+ //
+ ZeroMem ((VOID *) &VmContext, sizeof (VM_CONTEXT));
+
+ //
+ // Set the VM instruction pointer to the correct location in memory.
+ //
+ VmContext.Ip = (VMIP) Addr;
+
+ //
+ // Initialize the stack pointer for the EBC. Get the current system
+ stack // pointer and adjust it down by the max needed for the interpreter.
+ //
+
+ //
+ // Adjust the VM's stack pointer down.
+ //
+
+ Status = GetEBCStack((EFI_HANDLE)(UINTN)-1, &VmContext.StackPool,
+ &StackIndex); if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ VmContext.StackTop = (UINT8*)VmContext.StackPool +
+ (STACK_REMAIN_SIZE); VmContext.Gpr[0] = (UINT64)
+ ((UINT8*)VmContext.StackPool + STACK_POOL_SIZE);
+ VmContext.HighStackBottom = (UINTN) VmContext.Gpr[0];
+ VmContext.Gpr[0] -= sizeof (UINTN);
+
+ //
+ // Align the stack on a natural boundary.
+ //
+ VmContext.Gpr[0] &= ~(VM_REGISTER)(sizeof (UINTN) - 1);
+
+ //
+ // Put a magic value in the stack gap, then adjust down again.
+ //
+ *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) VM_STACK_KEY_VALUE;
+ VmContext.StackMagicPtr = (UINTN *) (UINTN) VmContext.Gpr[0];
+
+ //
+ // The stack upper to LowStackTop is belong to the VM.
+ //
+ VmContext.LowStackTop = (UINTN) VmContext.Gpr[0];
+
+ //
+ // For the worst case, assume there are 4 arguments passed in
+ registers, store // them to VM's stack.
+ //
+ PushU64 (&VmContext, (UINT64) Arg16);
+ PushU64 (&VmContext, (UINT64) Arg15);
+ PushU64 (&VmContext, (UINT64) Arg14);
+ PushU64 (&VmContext, (UINT64) Arg13);
+ PushU64 (&VmContext, (UINT64) Arg12);
+ PushU64 (&VmContext, (UINT64) Arg11);
+ PushU64 (&VmContext, (UINT64) Arg10);
+ PushU64 (&VmContext, (UINT64) Arg9);
+ PushU64 (&VmContext, (UINT64) Arg8);
+ PushU64 (&VmContext, (UINT64) Arg7);
+ PushU64 (&VmContext, (UINT64) Arg6);
+ PushU64 (&VmContext, (UINT64) Arg5);
+ PushU64 (&VmContext, (UINT64) Arg4);
+ PushU64 (&VmContext, (UINT64) Arg3);
+ PushU64 (&VmContext, (UINT64) Arg2);
+ PushU64 (&VmContext, (UINT64) Arg1);
+
+ //
+ // Interpreter assumes 64-bit return address is pushed on the stack.
+ // AArch64 does not do this so pad the stack accordingly.
+ //
+ PushU64 (&VmContext, (UINT64) 0);
+ PushU64 (&VmContext, (UINT64) 0x1234567887654321ULL);
+
+ //
+ // For AArch64, this is where we say our return address is //
+ VmContext.StackRetAddr = (UINT64) VmContext.Gpr[0];
+
+ //
+ // We need to keep track of where the EBC stack starts. This way, if
+ the EBC // accesses any stack variables above its initial stack
+ setting, then we know // it's accessing variables passed into it,
+ which means the data is on the // VM's stack.
+ // When we're called, on the stack (high to low) we have the
+ parameters, the // return address, then the saved ebp. Save the pointer to the return address.
+ // EBC code knows that's there, so should look above it for function parameters.
+ // The offset is the size of locals (VMContext + Addr + saved ebp).
+ // Note that the interpreter assumes there is a 16 bytes of return
+ address on // the stack too, so adjust accordingly.
+ // VmContext.HighStackBottom = (UINTN)(Addr + sizeof (VmContext) +
+ sizeof (Addr)); //
+
+ //
+ // Begin executing the EBC code
+ //
+ EbcExecute (&VmContext);
+
+ //
+ // Return the value in R[7] unless there was an error
+ //
+ ReturnEBCStack(StackIndex);
+ return (UINT64) VmContext.Gpr[7];
+}
+
+
+/**
+ Begin executing an EBC image.
+
+ @param EntryPoint The entrypoint of EBC code.
+ @param ImageHandle image handle for the EBC application we're executing
+ @param SystemTable standard system table passed into an driver's entry
+ point
+
+ @return The value returned by the EBC application we're going to run.
+
+**/
+UINT64
+EFIAPI
+ExecuteEbcImageEntryPoint (
+ IN UINTN EntryPoint,
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ //
+ // Create a new VM context on the stack
+ //
+ VM_CONTEXT VmContext;
+ UINTN Addr;
+ EFI_STATUS Status;
+ UINTN StackIndex;
+
+ //
+ // Get the EBC entry point
+ //
+ Addr = EntryPoint;
+
+ //
+ // Now clear out our context
+ //
+ ZeroMem ((VOID *) &VmContext, sizeof (VM_CONTEXT));
+
+ //
+ // Save the image handle so we can track the thunks created for this
+ image // VmContext.ImageHandle = ImageHandle; VmContext.SystemTable
+ = SystemTable;
+
+ //
+ // Set the VM instruction pointer to the correct location in memory.
+ //
+ VmContext.Ip = (VMIP) Addr;
+
+ //
+ // Initialize the stack pointer for the EBC. Get the current system
+ stack // pointer and adjust it down by the max needed for the interpreter.
+ //
+
+ Status = GetEBCStack(ImageHandle, &VmContext.StackPool, &StackIndex);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ VmContext.StackTop = (UINT8*)VmContext.StackPool +
+ (STACK_REMAIN_SIZE); VmContext.Gpr[0] = (UINT64)
+ ((UINT8*)VmContext.StackPool + STACK_POOL_SIZE);
+ VmContext.HighStackBottom = (UINTN) VmContext.Gpr[0];
+ VmContext.Gpr[0] -= sizeof (UINTN);
+
+
+ //
+ // Put a magic value in the stack gap, then adjust down again //
+ *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) VM_STACK_KEY_VALUE;
+ VmContext.StackMagicPtr = (UINTN *) (UINTN) VmContext.Gpr[0];
+
+ //
+ // Align the stack on a natural boundary VmContext.Gpr[0] &=
+ ~(VM_REGISTER)(sizeof(UINTN) - 1); //
+ VmContext.LowStackTop = (UINTN) VmContext.Gpr[0];
+
+ //
+ // Simply copy the image handle and system table onto the EBC stack.
+ // Greatly simplifies things by not having to spill the args.
+ //
+ PushU64 (&VmContext, (UINT64) SystemTable);
+ PushU64 (&VmContext, (UINT64) ImageHandle);
+
+ //
+ // VM pushes 16-bytes for return address. Simulate that here.
+ //
+ PushU64 (&VmContext, (UINT64) 0);
+ PushU64 (&VmContext, (UINT64) 0x1234567887654321ULL);
+
+ //
+ // For AArch64, this is where we say our return address is //
+ VmContext.StackRetAddr = (UINT64) VmContext.Gpr[0];
+
+ //
+ // Entry function needn't access high stack context, simply // put
+ the stack pointer here.
+ //
+
+ //
+ // Begin executing the EBC code
+ //
+ EbcExecute (&VmContext);
+
+ //
+ // Return the value in R[7] unless there was an error
+ //
+ ReturnEBCStack(StackIndex);
+ return (UINT64) VmContext.Gpr[7];
+}
+
+
+/**
+ Create thunks for an EBC image entry point, or an EBC protocol service.
+
+ @param ImageHandle Image handle for the EBC image. If not null, then
+ we're creating a thunk for an image entry point.
+ @param EbcEntryPoint Address of the EBC code that the thunk is to call
+ @param Thunk Returned thunk we create here
+ @param Flags Flags indicating options for creating the thunk
+
+ @retval EFI_SUCCESS The thunk was created successfully.
+ @retval EFI_INVALID_PARAMETER The parameter of EbcEntryPoint is not 16-bit
+ aligned.
+ @retval EFI_OUT_OF_RESOURCES There is not enough memory to created the EBC
+ Thunk.
+ @retval EFI_BUFFER_TOO_SMALL EBC_THUNK_SIZE is not larger enough.
+
+**/
+EFI_STATUS
+EbcCreateThunks (
+ IN EFI_HANDLE ImageHandle,
+ IN VOID *EbcEntryPoint,
+ OUT VOID **Thunk,
+ IN UINT32 Flags
+ )
+{
+ UINT8 *Ptr;
+ UINT8 *ThunkBase;
+ UINT32 Index;
+ INT32 ThunkSize;
+
+ //
+ // Check alignment of pointer to EBC code // if ((UINT32) (UINTN)
+ EbcEntryPoint & 0x01) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ThunkSize = sizeof(mInstructionBufferTemplate);
+
+ Ptr = AllocatePool (sizeof(mInstructionBufferTemplate));
+
+ if (Ptr == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Print(L"Allocate TH: 0x%X\n", (UINT32)Ptr); // // Save the
+ start address so we can add a pointer to it to a list later.
+ //
+ ThunkBase = Ptr;
+
+ //
+ // Give them the address of our buffer we're going to fix up //
+ *Thunk = (VOID *) Ptr;
+
+ //
+ // Copy whole thunk instruction buffer template // CopyMem (Ptr,
+ mInstructionBufferTemplate, sizeof(mInstructionBufferTemplate));
+
+ //
+ // Patch EbcEntryPoint and EbcLLEbcInterpret // for (Index = 0;
+ Index < sizeof(mInstructionBufferTemplate) - sizeof(UINTN); Index++) {
+ if (*(UINTN *)&Ptr[Index] == EBC_ENTRYPOINT_SIGNATURE) {
+ *(UINTN *)&Ptr[Index] = (UINTN)EbcEntryPoint;
+ }
+ if (*(UINTN *)&Ptr[Index] == EBC_LL_EBC_ENTRYPOINT_SIGNATURE) {
+ if ((Flags & FLAG_THUNK_ENTRY_POINT) != 0) {
+ *(UINTN *)&Ptr[Index] = (UINTN)EbcLLExecuteEbcImageEntryPoint;
+ } else {
+ *(UINTN *)&Ptr[Index] = (UINTN)EbcLLEbcInterpret;
+ }
+ }
+ }
+
+ //
+ // Add the thunk to the list for this image. Do this last since the
+ add // function flushes the cache for us.
+ //
+ EbcAddImageThunk (ImageHandle, (VOID *) ThunkBase, ThunkSize);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function is called to execute an EBC CALLEX instruction.
+ The function check the callee's content to see whether it is common
+native
+ code or a thunk to another piece of EBC code.
+ If the callee is common native code, use EbcLLCAllEXASM to
+manipulate,
+ otherwise, set the VM->IP to target EBC code directly to avoid
+another VM
+ be startup which cost time and stack space.
+
+ @param VmPtr Pointer to a VM context.
+ @param FuncAddr Callee's address
+ @param NewStackPointer New stack pointer after the call
+ @param FramePtr New frame pointer after the call
+ @param Size The size of call instruction
+
+**/
+VOID
+EbcLLCALLEX (
+ IN VM_CONTEXT *VmPtr,
+ IN UINTN FuncAddr,
+ IN UINTN NewStackPointer,
+ IN VOID *FramePtr,
+ IN UINT8 Size
+ )
+{
+ UINTN IsThunk;
+ UINTN TargetEbcAddr;
+ UINT8 InstructionBuffer[sizeof(mInstructionBufferTemplate)];
+ UINTN Index;
+ UINTN IndexOfEbcEntrypoint;
+
+ IsThunk = 1;
+ TargetEbcAddr = 0;
+ IndexOfEbcEntrypoint = 0;
+
+ //
+ // Processor specific code to check whether the callee is a thunk to EBC.
+ //
+ CopyMem (InstructionBuffer, (VOID *)FuncAddr,
+ sizeof(InstructionBuffer)); // // Fill the signature according to
+ mInstructionBufferTemplate // for (Index = 0; Index <
+ sizeof(mInstructionBufferTemplate) - sizeof(UINTN); Index++) {
+ if (*(UINTN *)&mInstructionBufferTemplate[Index] == EBC_ENTRYPOINT_SIGNATURE) {
+ *(UINTN *)&InstructionBuffer[Index] = EBC_ENTRYPOINT_SIGNATURE;
+ IndexOfEbcEntrypoint = Index;
+ }
+ if (*(UINTN *)&mInstructionBufferTemplate[Index] == EBC_LL_EBC_ENTRYPOINT_SIGNATURE) {
+ *(UINTN *)&InstructionBuffer[Index] = EBC_LL_EBC_ENTRYPOINT_SIGNATURE;
+ }
+ }
+ //
+ // Check if we need thunk to native
+ //
+ if (CompareMem (InstructionBuffer, mInstructionBufferTemplate, sizeof(mInstructionBufferTemplate)) != 0) {
+ IsThunk = 0;
+ }
+
+ if (IsThunk == 1){
+ //
+ // The callee is a thunk to EBC, adjust the stack pointer down 16 bytes and
+ // put our return address and frame pointer on the VM stack.
+ // Then set the VM's IP to new EBC code.
+ //
+ VmPtr->Gpr[0] -= 8;
+ VmWriteMemN (VmPtr, (UINTN) VmPtr->Gpr[0], (UINTN) FramePtr);
+ VmPtr->FramePtr = (VOID *) (UINTN) VmPtr->Gpr[0];
+ VmPtr->Gpr[0] -= 8;
+ VmWriteMem64 (VmPtr, (UINTN) VmPtr->Gpr[0], (UINT64) (UINTN)
+ (VmPtr->Ip + Size));
+
+ CopyMem (&TargetEbcAddr, (UINT8 *)FuncAddr + IndexOfEbcEntrypoint, sizeof(UINTN));
+ VmPtr->Ip = (VMIP) (UINTN) TargetEbcAddr; } else {
+ //
+ // The callee is not a thunk to EBC, call native code,
+ // and get return value.
+ //
+ VmPtr->Gpr[7] = EbcLLCALLEXNative (FuncAddr, NewStackPointer,
+ FramePtr);
+
+ //
+ // Advance the IP.
+ //
+ VmPtr->Ip += Size;
+ }
+}
+
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDxe.inf b/MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
index 15dc01c..e9a0b28 100644
--- a/MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
@@ -5,6 +5,7 @@
# platform and processor-independent mechanisms for loading and executing EFI # device drivers.
#
+# Copyright (c) 2015, The Linux Foundation. All rights reserved.
# Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR> # This program and the accompanying materials # are licensed and made available under the terms and conditions of the BSD License @@ -28,7 +29,7 @@ [Defines] # # The following information is for reference only and not required by the build tools.
#
-# VALID_ARCHITECTURES = IA32 X64 IPF
+# VALID_ARCHITECTURES = IA32 X64 IPF AARCH64
#

[Sources]
@@ -54,6 +55,9 @@ [Sources.IPF]
Ipf/EbcSupport.c
Ipf/EbcLowLevel.s

+[Sources.AARCH64]
+ AArch64/EbcSupport.c
+ AArch64/EbcLowLevel.S

[Packages]
MdePkg/MdePkg.dec
--
2.1.4


Re: [PATCH] add top-level .gitattributes file, dealing with .depex

Leif Lindholm <leif.lindholm@...>
 

On Mon, Aug 01, 2016 at 12:03:06AM -0700, Jordan Justen wrote:
On 2016-07-31 16:52:23, Kinney, Michael D wrote:
Jordan,

UEFI Drivers distributed as binaries do not need depex sections.

PI modules distributed as binaries do require a .depex binary.
They may require a depex, but, as mentioned below, they can also add
it directly in the .fdf. As it stands, apparently we have 1 .depex
file in the tree, and it is unused.

Aside from this, under what conditions would we take such binaries
into the EDK II tree? Today we have the ShellPkg and FatPkg binaries
in the EDK II tree, but we recently discussed removing even those.
While I don't disagree, the PI dependency expression instruction set
(section 10.7, PI spec 1.4 vol2) does not look Turing complete to me.
Meaning it's "binary" in much the same way a .uni file is.

(This is historically where someone pulls out an operating system
kernel written entirely in PI depex binary.)

For an open source project, I think it is best to not have pre-built
binaries, unless there is some very compelling reason. Previously
there was some license funniness on FatPkg, but now that is gone. If
it took an hour to build FatPkg, then that might also be something to
discuss. :)

I don't think adding the .gitattributes is really a problem, aside
from the fact that it implies that we might actually have a reason to
add a .depex file to the source tree.
And I agree it would send that signal.

Regards,

Leif

-Jordan

So I would recommend .depex binary files be treated the same as
binary .efi files by GIT. So it does sound like we need some
minor updates to GIT attributes.

If we have an example of a binary module that is providing more
binary leaf sections than are actually required and/or used, then
yes, the binary module should be cleaned up to remove the unused
content.

Thanks,

Mike

-----Original Message-----
From: Justen, Jordan L
Sent: Sunday, July 31, 2016 3:58 PM
To: Leif Lindholm <leif.lindholm@linaro.org>; Tim Lewis <tim.lewis@insyde.com>
Cc: Laszlo Ersek <lersek@redhat.com>; Kinney, Michael D <michael.d.kinney@intel.com>;
edk2-devel@ml01.01.org <edk2-devel@lists.01.org>; Andrew Fish <afish@apple.com>
Subject: Re: [edk2] [PATCH] add top-level .gitattributes file, dealing with .depex

On 2016-07-30 11:33:43, Leif Lindholm wrote:
Hi Tim,

Thanks for the warning, and investigation.

Does this mean that you think we should ban the inclusion of .depex
files in EDK2, including future platform trees?
I don't know about banning it, but at least we could wait for someone
to make a reasonable argument why they are needed.

Even for binary only modules, it looks like the fdf method outlined
below is preferable to a pre-built .depex.

If (at a future point) the reason for using a .depex is to support a
binary only module in a supposedly open platform under EDK II, then I
guess we can decide if that is a good idea at that point.

Should we delete this one unused .depex from the tree?

-Jordan

(If not, this patch is
still needed for git to work predictably with these files.)

Regards,

Leif

On Fri, Jul 29, 2016 at 05:12:49PM +0000, Tim Lewis wrote:
It appears that this file is not actually used. It is only
referenced in the [Rule.Common.UEFI_DRIVER.NATIVE_BINARY] rule in
PlatformPkg.fdf. A little further research shows that an alternate
method was used for the actual GOP binary (see below). A grep of the
entire tree shows that no one uses this rule NATIVE_BINARY. So it
looks like it can just be cut out.

BTW, the downside of the method used for the binary version of the
GOP driver, is that those drivers cannot use PCDs, since the PCD
database is created based on references in the .inf. GOP works
because it is pure UEFI and (therefore) doesn't use PCDs.

Tim

FILE DRIVER = FF0C8745-3270-4439-B74F-3E45F8C77064 {
SECTION DXE_DEPEX_EXP = {gPlatformGOPPolicyGuid}
SECTION PE32 =
Vlv2MiscBinariesPkg/GOP/7.2.1011/RELEASE_VS2008x86/$(DXE_ARCHITECTURE)/IntelGopDriver.e
fi
SECTION UI = "IntelGopDriver"
}

-----Original Message-----
From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Leif
Lindholm
Sent: Friday, July 29, 2016 9:45 AM
To: Laszlo Ersek <lersek@redhat.com>
Cc: michael.d.kinney@intel.com; Jordan Justen <jordan.l.justen@intel.com>; edk2-
devel@ml01.01.org; Andrew Fish <afish@apple.com>
Subject: Re: [edk2] [PATCH] add top-level .gitattributes file, dealing with .depex

On Thu, Jul 07, 2016 at 05:03:13PM +0200, Laszlo Ersek wrote:
On 07/07/16 16:24, Leif Lindholm wrote:
Git tends to see .depex files as text, causing hideous patches being
generated (and breaking PatchCheck.py).

Add a .gitattributes file instructing git to treat them as binary.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
---
.gitattributes | 1 +
1 file changed, 1 insertion(+)
create mode 100644 .gitattributes

diff --git a/.gitattributes b/.gitattributes new file mode 100644
index 0000000..2d8a45b
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+*.depex binary
What generates .depex files? I've never seen any.

Also, unless you add .depex files with "git add" to the set of tracked
files, no patches / diffs should cover them. What am I missing? :)

... Hm, after

$ find . -iname "*.depex"

I see .depex files in Build/ (which should be ignored altogether), and

./Vlv2TbltDevicePkg/IntelGopDepex/IntelGopDriver.depex

Why does that file exist in the tree? Let me see... git log says nothing relevant
(the file dates back to commit 3cbfba02fef9, "Upload BSD-licensed Vlv2TbltDevicePkg and
Vlv2DeviceRefCodePkg to").

Grepping the tree for the filename itself leads to:

Vlv2TbltDevicePkg/PlatformPkg.fdf: DXE_DEPEX DXE_DEPEX Optional
$(WORKSPACE)/$(PLATFORM_PACKAGE)/IntelGopDepex/IntelGopDriver.depex
Vlv2TbltDevicePkg/PlatformPkgGcc.fdf: DXE_DEPEX DXE_DEPEX Optional
$(WORKSPACE)/$(PLATFORM_PACKAGE)/IntelGopDepex/IntelGopDriver.depex

Do these rules exist to override the DEPEX sections of binary-only modules? If
so: that's horrible.

Anyway, given that edk2 contains at least one .depex file, and your patch is
correct according to <https://git-scm.com/book/en/v2/Customizing-Git-Git-Attributes>:

Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Thanks!

I had hoped for comments from someone else on cc, since we don't have any
Maintainers.txt entry for the top level directory :)

But if I don't hear anything before Monday, I'll push it then.

Regards,

Leif

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel


[PATCH v5 8/8] BaseTools GCC: introduce GCC5 toolchain to support GCC v5.x in LTO mode

Ard Biesheuvel
 

This adds support for GCC 5.x in LTO mode for IA32, X64, ARM and
AARCH64. Due to the fact that the GCC project switched to a new
numbering scheme where the first digit is now incremented for every
major release, the new toolchain is simply called 'GCC5', and is
intended to support all GCC v5.x releases.

Since IA32 and X64 enable compiler optimizations (-Os) for both DEBUG
and RELEASE builds, LTO support is equally enabled for both targets.
On ARM and AARCH64, DEBUG builds are not optimized, and so the LTO
optimizations are only enabled for RELEASE.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
---
BaseTools/Conf/tools_def.template | 164 ++++++++++++++++++++
1 file changed, 164 insertions(+)

diff --git a/BaseTools/Conf/tools_def.template b/BaseTools/Conf/tools_def.template
index 10ac21e42c8f..314adaf6bfa8 100644
--- a/BaseTools/Conf/tools_def.template
+++ b/BaseTools/Conf/tools_def.template
@@ -197,6 +197,9 @@ DEFINE GCC48_X64_PREFIX = ENV(GCC48_BIN)
DEFINE GCC49_IA32_PREFIX = ENV(GCC49_BIN)
DEFINE GCC49_X64_PREFIX = ENV(GCC49_BIN)

+DEFINE GCC5_IA32_PREFIX = ENV(GCC5_BIN)
+DEFINE GCC5_X64_PREFIX = ENV(GCC5_BIN)
+
DEFINE UNIX_IASL_BIN = ENV(IASL_PREFIX)iasl
DEFINE WIN_ASL_BIN_DIR = C:\ASL
DEFINE WIN_IASL_BIN = DEF(WIN_ASL_BIN_DIR)\iasl.exe
@@ -366,6 +369,12 @@ DEFINE SOURCERY_CYGWIN_TOOLS = /cygdrive/c/Program Files/CodeSourcery/Sourcery G
# Required to build platforms or ACPI tables:
# Intel(r) ACPI Compiler from
# https://acpica.org/downloads
+# GCC5 -Linux,Windows- Requires:
+# GCC 5 with LTO support, targeting x86_64-linux-gnu, aarch64-linux-gnu, or arm-linux-gnueabi
+# Optional:
+# Required to build platforms or ACPI tables:
+# Intel(r) ACPI Compiler from
+# https://acpica.org/downloads
# CLANG35 -Linux,Windows- Requires:
# Clang v3.5 or later, and GNU binutils targeting aarch64-linux-gnu or arm-linux-gnueabi
# Optional:
@@ -4452,6 +4461,27 @@ DEFINE GCC49_AARCH64_DLINK2_FLAGS = DEF(GCC48_AARCH64_DLINK2_FLAGS)
DEFINE GCC49_ARM_ASLDLINK_FLAGS = DEF(GCC48_ARM_ASLDLINK_FLAGS)
DEFINE GCC49_AARCH64_ASLDLINK_FLAGS = DEF(GCC48_AARCH64_ASLDLINK_FLAGS)

+DEFINE GCC5_IA32_CC_FLAGS = DEF(GCC49_IA32_CC_FLAGS) -flto -fno-builtin
+DEFINE GCC5_X64_CC_FLAGS = DEF(GCC49_X64_CC_FLAGS) -flto -fno-builtin
+DEFINE GCC5_IA32_X64_DLINK_COMMON = DEF(GCC49_IA32_X64_DLINK_COMMON)
+DEFINE GCC5_IA32_X64_ASLDLINK_FLAGS = DEF(GCC49_IA32_X64_ASLDLINK_FLAGS)
+DEFINE GCC5_IA32_X64_DLINK_FLAGS = DEF(GCC49_IA32_X64_DLINK_FLAGS) -flto
+DEFINE GCC5_IA32_DLINK2_FLAGS = DEF(GCC49_IA32_DLINK2_FLAGS)
+DEFINE GCC5_X64_DLINK_FLAGS = DEF(GCC49_X64_DLINK_FLAGS) -flto
+DEFINE GCC5_X64_DLINK2_FLAGS = DEF(GCC49_X64_DLINK2_FLAGS)
+DEFINE GCC5_ASM_FLAGS = DEF(GCC49_ASM_FLAGS)
+DEFINE GCC5_ARM_ASM_FLAGS = DEF(GCC49_ARM_ASM_FLAGS)
+DEFINE GCC5_AARCH64_ASM_FLAGS = DEF(GCC49_AARCH64_ASM_FLAGS)
+DEFINE GCC5_ARM_CC_FLAGS = DEF(GCC49_ARM_CC_FLAGS)
+DEFINE GCC5_AARCH64_CC_FLAGS = DEF(GCC49_AARCH64_CC_FLAGS)
+DEFINE GCC5_AARCH64_CC_XIPFLAGS = DEF(GCC49_AARCH64_CC_XIPFLAGS)
+DEFINE GCC5_ARM_DLINK_FLAGS = DEF(GCC49_ARM_DLINK_FLAGS) -flto
+DEFINE GCC5_ARM_DLINK2_FLAGS = DEF(GCC49_ARM_DLINK2_FLAGS)
+DEFINE GCC5_AARCH64_DLINK_FLAGS = DEF(GCC49_AARCH64_DLINK_FLAGS) -flto
+DEFINE GCC5_AARCH64_DLINK2_FLAGS = DEF(GCC49_AARCH64_DLINK2_FLAGS)
+DEFINE GCC5_ARM_ASLDLINK_FLAGS = DEF(GCC49_ARM_ASLDLINK_FLAGS)
+DEFINE GCC5_AARCH64_ASLDLINK_FLAGS = DEF(GCC49_AARCH64_ASLDLINK_FLAGS)
+
####################################################################################
#
# Unix GCC And Intel Linux ACPI Compiler
@@ -5186,6 +5216,140 @@ RELEASE_GCC49_AARCH64_DLINK_FLAGS = DEF(GCC49_AARCH64_DLINK_FLAGS)

####################################################################################
#
+# GCC 5 - This configuration is used to compile under Linux to produce
+# PE/COFF binaries using GCC 5
+#
+####################################################################################
+*_GCC5_*_*_FAMILY = GCC
+
+*_GCC5_*_MAKE_PATH = DEF(GCC5_IA32_PREFIX)make
+*_GCC5_*_*_DLL = ENV(GCC5_DLL)
+*_GCC5_*_ASL_PATH = DEF(UNIX_IASL_BIN)
+
+*_GCC5_*_PP_FLAGS = DEF(GCC_PP_FLAGS)
+*_GCC5_*_ASLPP_FLAGS = DEF(GCC_ASLPP_FLAGS)
+*_GCC5_*_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS)
+*_GCC5_*_VFRPP_FLAGS = DEF(GCC_VFRPP_FLAGS)
+*_GCC5_*_APP_FLAGS =
+*_GCC5_*_ASL_FLAGS = DEF(IASL_FLAGS)
+*_GCC5_*_ASL_OUTFLAGS = DEF(IASL_OUTFLAGS)
+
+##################
+# GCC5 IA32 definitions
+##################
+*_GCC5_IA32_OBJCOPY_PATH = DEF(GCC5_IA32_PREFIX)objcopy
+*_GCC5_IA32_CC_PATH = DEF(GCC5_IA32_PREFIX)gcc
+*_GCC5_IA32_SLINK_PATH = DEF(GCC5_IA32_PREFIX)gcc-ar
+*_GCC5_IA32_DLINK_PATH = DEF(GCC5_IA32_PREFIX)gcc
+*_GCC5_IA32_ASLDLINK_PATH = DEF(GCC5_IA32_PREFIX)gcc
+*_GCC5_IA32_ASM_PATH = DEF(GCC5_IA32_PREFIX)gcc
+*_GCC5_IA32_PP_PATH = DEF(GCC5_IA32_PREFIX)gcc
+*_GCC5_IA32_VFRPP_PATH = DEF(GCC5_IA32_PREFIX)gcc
+*_GCC5_IA32_ASLCC_PATH = DEF(GCC5_IA32_PREFIX)gcc
+*_GCC5_IA32_ASLPP_PATH = DEF(GCC5_IA32_PREFIX)gcc
+*_GCC5_IA32_RC_PATH = DEF(GCC5_IA32_PREFIX)objcopy
+
+*_GCC5_IA32_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m32 -fno-lto
+*_GCC5_IA32_ASLDLINK_FLAGS = DEF(GCC5_IA32_X64_ASLDLINK_FLAGS) -Wl,-m,elf_i386
+*_GCC5_IA32_ASM_FLAGS = DEF(GCC5_ASM_FLAGS) -m32 -march=i386
+*_GCC5_IA32_DLINK_FLAGS = DEF(GCC5_IA32_X64_DLINK_FLAGS) -Os -Wl,-m,elf_i386,--oformat=elf32-i386
+*_GCC5_IA32_DLINK2_FLAGS = DEF(GCC5_IA32_DLINK2_FLAGS)
+*_GCC5_IA32_RC_FLAGS = DEF(GCC_IA32_RC_FLAGS)
+*_GCC5_IA32_OBJCOPY_FLAGS =
+*_GCC5_IA32_NASM_FLAGS = -f elf32
+
+ DEBUG_GCC5_IA32_CC_FLAGS = DEF(GCC5_IA32_CC_FLAGS) -Os
+RELEASE_GCC5_IA32_CC_FLAGS = DEF(GCC5_IA32_CC_FLAGS) -Os -Wno-unused-but-set-variable
+
+##################
+# GCC5 X64 definitions
+##################
+*_GCC5_X64_OBJCOPY_PATH = DEF(GCC5_X64_PREFIX)objcopy
+*_GCC5_X64_CC_PATH = DEF(GCC5_X64_PREFIX)gcc
+*_GCC5_X64_SLINK_PATH = DEF(GCC5_X64_PREFIX)gcc-ar
+*_GCC5_X64_DLINK_PATH = DEF(GCC5_X64_PREFIX)gcc
+*_GCC5_X64_ASLDLINK_PATH = DEF(GCC5_X64_PREFIX)gcc
+*_GCC5_X64_ASM_PATH = DEF(GCC5_X64_PREFIX)gcc
+*_GCC5_X64_PP_PATH = DEF(GCC5_X64_PREFIX)gcc
+*_GCC5_X64_VFRPP_PATH = DEF(GCC5_X64_PREFIX)gcc
+*_GCC5_X64_ASLCC_PATH = DEF(GCC5_X64_PREFIX)gcc
+*_GCC5_X64_ASLPP_PATH = DEF(GCC5_X64_PREFIX)gcc
+*_GCC5_X64_RC_PATH = DEF(GCC5_X64_PREFIX)objcopy
+
+*_GCC5_X64_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m64 -fno-lto
+*_GCC5_X64_ASLDLINK_FLAGS = DEF(GCC5_IA32_X64_ASLDLINK_FLAGS) -Wl,-m,elf_x86_64
+*_GCC5_X64_ASM_FLAGS = DEF(GCC5_ASM_FLAGS) -m64
+*_GCC5_X64_DLINK_FLAGS = DEF(GCC5_X64_DLINK_FLAGS) -Os
+*_GCC5_X64_DLINK2_FLAGS = DEF(GCC5_X64_DLINK2_FLAGS)
+*_GCC5_X64_RC_FLAGS = DEF(GCC_X64_RC_FLAGS)
+*_GCC5_X64_OBJCOPY_FLAGS =
+*_GCC5_X64_NASM_FLAGS = -f elf64
+
+ DEBUG_GCC5_X64_CC_FLAGS = DEF(GCC5_X64_CC_FLAGS)
+RELEASE_GCC5_X64_CC_FLAGS = DEF(GCC5_X64_CC_FLAGS) -Wno-unused-but-set-variable
+
+##################
+# GCC5 ARM definitions
+##################
+*_GCC5_ARM_CC_PATH = ENV(GCC5_ARM_PREFIX)gcc
+*_GCC5_ARM_SLINK_PATH = ENV(GCC5_ARM_PREFIX)gcc-ar
+*_GCC5_ARM_DLINK_PATH = ENV(GCC5_ARM_PREFIX)gcc
+*_GCC5_ARM_ASLDLINK_PATH = ENV(GCC5_ARM_PREFIX)gcc
+*_GCC5_ARM_ASM_PATH = ENV(GCC5_ARM_PREFIX)gcc
+*_GCC5_ARM_PP_PATH = ENV(GCC5_ARM_PREFIX)gcc
+*_GCC5_ARM_VFRPP_PATH = ENV(GCC5_ARM_PREFIX)gcc
+*_GCC5_ARM_ASLCC_PATH = ENV(GCC5_ARM_PREFIX)gcc
+*_GCC5_ARM_ASLPP_PATH = ENV(GCC5_ARM_PREFIX)gcc
+*_GCC5_ARM_RC_PATH = ENV(GCC5_ARM_PREFIX)objcopy
+
+*_GCC5_ARM_ARCHCC_FLAGS = -mthumb
+*_GCC5_ARM_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -fno-lto
+*_GCC5_ARM_ASLDLINK_FLAGS = DEF(GCC5_ARM_ASLDLINK_FLAGS)
+*_GCC5_ARM_ASM_FLAGS = DEF(GCC5_ARM_ASM_FLAGS)
+*_GCC5_ARM_DLINK2_FLAGS = DEF(GCC5_ARM_DLINK2_FLAGS)
+*_GCC5_ARM_PLATFORM_FLAGS = -march=armv7-a
+*_GCC5_ARM_PP_FLAGS = $(ARCHCC_FLAGS) $(PLATFORM_FLAGS) DEF(GCC_PP_FLAGS)
+*_GCC5_ARM_RC_FLAGS = DEF(GCC_ARM_RC_FLAGS)
+*_GCC5_ARM_VFRPP_FLAGS = $(ARCHCC_FLAGS) $(PLATFORM_FLAGS) DEF(GCC_VFRPP_FLAGS)
+
+ DEBUG_GCC5_ARM_CC_FLAGS = DEF(GCC5_ARM_CC_FLAGS) -O0
+RELEASE_GCC5_ARM_CC_FLAGS = DEF(GCC5_ARM_CC_FLAGS) -flto -Wno-unused-but-set-variable
+
+ DEBUG_GCC5_ARM_DLINK_FLAGS = DEF(GCC5_ARM_DLINK_FLAGS)
+RELEASE_GCC5_ARM_DLINK_FLAGS = DEF(GCC5_ARM_DLINK_FLAGS) -Os -L$(WORKSPACE)/ArmPkg/Library/GccLto -llto-arm -Wl,-plugin-opt=-pass-through=-llto-arm
+
+##################
+# GCC5 AARCH64 definitions
+##################
+*_GCC5_AARCH64_CC_PATH = ENV(GCC5_AARCH64_PREFIX)gcc
+*_GCC5_AARCH64_SLINK_PATH = ENV(GCC5_AARCH64_PREFIX)gcc-ar
+*_GCC5_AARCH64_DLINK_PATH = ENV(GCC5_AARCH64_PREFIX)gcc
+*_GCC5_AARCH64_ASLDLINK_PATH = ENV(GCC5_AARCH64_PREFIX)gcc
+*_GCC5_AARCH64_ASM_PATH = ENV(GCC5_AARCH64_PREFIX)gcc
+*_GCC5_AARCH64_PP_PATH = ENV(GCC5_AARCH64_PREFIX)gcc
+*_GCC5_AARCH64_VFRPP_PATH = ENV(GCC5_AARCH64_PREFIX)gcc
+*_GCC5_AARCH64_ASLCC_PATH = ENV(GCC5_AARCH64_PREFIX)gcc
+*_GCC5_AARCH64_ASLPP_PATH = ENV(GCC5_AARCH64_PREFIX)gcc
+*_GCC5_AARCH64_RC_PATH = ENV(GCC5_AARCH64_PREFIX)objcopy
+
+*_GCC5_AARCH64_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -fno-lto
+*_GCC5_AARCH64_ASLDLINK_FLAGS = DEF(GCC5_AARCH64_ASLDLINK_FLAGS)
+*_GCC5_AARCH64_ASM_FLAGS = DEF(GCC5_AARCH64_ASM_FLAGS)
+*_GCC5_AARCH64_DLINK2_FLAGS = DEF(GCC5_AARCH64_DLINK2_FLAGS)
+*_GCC5_AARCH64_PLATFORM_FLAGS =
+*_GCC5_AARCH64_PP_FLAGS = $(ARCHCC_FLAGS) $(PLATFORM_FLAGS) DEF(GCC_PP_FLAGS)
+*_GCC5_AARCH64_RC_FLAGS = DEF(GCC_AARCH64_RC_FLAGS)
+*_GCC5_AARCH64_VFRPP_FLAGS = $(ARCHCC_FLAGS) $(PLATFORM_FLAGS) DEF(GCC_VFRPP_FLAGS)
+*_GCC5_AARCH64_CC_XIPFLAGS = DEF(GCC5_AARCH64_CC_XIPFLAGS)
+
+ DEBUG_GCC5_AARCH64_CC_FLAGS = DEF(GCC5_AARCH64_CC_FLAGS) -O0 -mcmodel=small
+ DEBUG_GCC5_AARCH64_DLINK_FLAGS = DEF(GCC5_AARCH64_DLINK_FLAGS) -z common-page-size=0x1000
+
+RELEASE_GCC5_AARCH64_CC_FLAGS = DEF(GCC5_AARCH64_CC_FLAGS) -flto -Wno-unused-but-set-variable -mcmodel=tiny
+RELEASE_GCC5_AARCH64_DLINK_FLAGS = DEF(GCC5_AARCH64_DLINK_FLAGS) -Os -L$(WORKSPACE)/ArmPkg/Library/GccLto -llto-aarch64 -Wl,-plugin-opt=-pass-through=-llto-aarch64
+
+####################################################################################
+#
# CLANG35 - This configuration is used to compile under Linux to produce
# PE/COFF binaries using the clang compiler and assembler (v3.5 and up)
# and GNU linker
--
2.7.4


[PATCH v5 7/8] MdePkg GCC/X64: avoid 'hidden' visibility for module entry points

Ard Biesheuvel
 

When building with LTO enabled, the LTO routines infer from the 'hidden'
visibility of the _ModuleEntryPoint symbol that its code only needs to be
retained if it is referenced internally, and disregards the fact that
it is referenced by the entry point field in the ELF metadata.

This is arguably a bug in LTO, but we can work around it by ensuring that
the _ModuleEntryPoint symbol is emitted with protected visibility instead.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
MdePkg/Include/X64/ProcessorBind.h | 9 ++++++++-
MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf | 2 ++
MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf | 2 ++
MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf | 2 ++
MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf | 2 ++
MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf | 2 ++
6 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/MdePkg/Include/X64/ProcessorBind.h b/MdePkg/Include/X64/ProcessorBind.h
index 666cc8e8bd16..e45b9cba2bb3 100644
--- a/MdePkg/Include/X64/ProcessorBind.h
+++ b/MdePkg/Include/X64/ProcessorBind.h
@@ -29,13 +29,20 @@

#if defined(__GNUC__) && defined(__pic__)
//
-// Mark all symbol declarations and references as hidden, meaning they will
+// Mark all symbol declarations and references as hidden*, meaning they will
// not be subject to symbol preemption. This allows the compiler to refer to
// symbols directly using relative references rather than via the GOT, which
// contains absolute symbol addresses that are subject to runtime relocation.
//
+// * Under LTO, the entry point of a module must have protected or default
+// visibility to prevent it from being pruned.
+//
+#ifdef GCC_VISIBILITY_PROTECTED
+#pragma GCC visibility push (protected)
+#else
#pragma GCC visibility push (hidden)
#endif
+#endif

#if defined(__INTEL_COMPILER)
//
diff --git a/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf b/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
index 01f64c34c7a1..2d6f87ed062e 100644
--- a/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
+++ b/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
@@ -39,3 +39,5 @@ [LibraryClasses]
BaseLib
DebugLib

+[BuildOptions]
+ GCC:*_*_X64_CC_FLAGS = -DGCC_VISIBILITY_PROTECTED
diff --git a/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf b/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf
index d920306713c5..4e61783b3bd5 100644
--- a/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf
+++ b/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf
@@ -37,3 +37,5 @@ [LibraryClasses]
BaseLib
DebugLib

+[BuildOptions]
+ GCC:*_*_X64_CC_FLAGS = -DGCC_VISIBILITY_PROTECTED
diff --git a/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf b/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
index a2db9e058bbe..adfd91bdc57e 100644
--- a/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
+++ b/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
@@ -37,3 +37,5 @@ [Packages]
[LibraryClasses]
DebugLib

+[BuildOptions]
+ GCC:*_*_X64_CC_FLAGS = -DGCC_VISIBILITY_PROTECTED
diff --git a/MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf b/MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
index be92b3dc0760..9525c55c2051 100644
--- a/MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
+++ b/MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
@@ -38,3 +38,5 @@ [LibraryClasses]
DebugLib
BaseLib

+[BuildOptions]
+ GCC:*_*_X64_CC_FLAGS = -DGCC_VISIBILITY_PROTECTED
diff --git a/MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf b/MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
index 7a9dcbcd4df2..8d30b1197850 100644
--- a/MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
+++ b/MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
@@ -65,3 +65,5 @@ [Depex.common.UEFI_DRIVER]
gEfiVariableArchProtocolGuid AND
gEfiWatchdogTimerArchProtocolGuid

+[BuildOptions]
+ GCC:*_*_X64_CC_FLAGS = -DGCC_VISIBILITY_PROTECTED
--
2.7.4


[PATCH v5 6/8] BaseTools GCC: drop GNU notes section from EFI image

Ard Biesheuvel
 

Recent versions of GNU ld automatically emit a .notes section into
the ELF binary containing a build id. Since this is an allocatable
section by default, it will be identified by GenFw as a section
that requires PE/COFF conversion, which may cause sections to be
moved around unexpectedly.

So retain the section, but tag it as INFO, which tells the linker
that it should not be accounted for in the binary's memory layout.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Acked-by: Jordan Justen <jordan.l.justen@intel.com>
---
BaseTools/Scripts/GccBase.lds | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/BaseTools/Scripts/GccBase.lds b/BaseTools/Scripts/GccBase.lds
index 7e4cdde9bfea..281af8a9bd33 100644
--- a/BaseTools/Scripts/GccBase.lds
+++ b/BaseTools/Scripts/GccBase.lds
@@ -62,6 +62,12 @@ SECTIONS {
KEEP (*(.hii))
}

+ /*
+ * Retain the GNU build id but in a non-allocatable section so GenFw
+ * does not copy it into the PE/COFF image.
+ */
+ .build-id (INFO) : { *(.note.gnu.build-id) }
+
/DISCARD/ : {
*(.note.GNU-stack)
*(.gnu_debuglink)
--
2.7.4