Date   

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

Ard Biesheuvel
 

On 1 August 2016 at 17:51, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
On 1 August 2016 at 16:56, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
On 1 August 2016 at 16:49, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
On 1 August 2016 at 16:18, Gao, Liming <liming.gao@intel.com> wrote:
Ard:
I don't think it is good way to define GCC_VISIBILITY_PROTECTED and apply it in EntryPointLib. We only need to expose _ModuleEntryPoint. It has been specified in LINK_FLAGS in tools_def.txt. Could we also specify its attribute in CC_FLAGS or LINK_FLAGS in tools_def.txt?
It seems this does the trick as well

diff --git a/BaseTools/Scripts/GccBase.lds b/BaseTools/Scripts/GccBase.lds
index 281af8a9bd33..02387d4f8d6f 100644
--- a/BaseTools/Scripts/GccBase.lds
+++ b/BaseTools/Scripts/GccBase.lds
@@ -80,3 +80,7 @@ SECTIONS {
*(COMMON)
}
}
+
+VERSION {
+ { global: _ModuleEntryPoint*; };
+};


Note that * at the end: this is necessary since _ModuleEntryPoint will
be called _ModuleEntryPoint.lto_priv.xxx in the LTO objects.
Hmm, looks like I spoke too soon. I don't know what I did wrong, but
this does not actually work.
The only alternative I can think of is to add a static non-lto object
to the tree that refers to _ModuleEntryPoint, similar to the way I
handle the ARM intrinsics in patch #5
As it turns out, the LTO linker does not need to visibility pragma to
prevent it from emitting GOT based relocations. This makes sense,
considering that the LTO linker can see that no symbol references are
ever satisfied across dynamic object boundaries. That means I could
work around this in the following way:

diff --git a/BaseTools/Conf/tools_def.template
b/BaseTools/Conf/tools_def.template
index 314adaf6bfa8..983e2fea7390 100644
--- a/BaseTools/Conf/tools_def.template
+++ b/BaseTools/Conf/tools_def.template
@@ -4462,7 +4462,7 @@ 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_X64_CC_FLAGS = DEF(GCC49_X64_CC_FLAGS) -flto
-fno-builtin -DUSING_LTO
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
diff --git a/MdePkg/Include/X64/ProcessorBind.h
b/MdePkg/Include/X64/ProcessorBind.h
index 666cc8e8bd16..77fab7055afc 100644
--- a/MdePkg/Include/X64/ProcessorBind.h
+++ b/MdePkg/Include/X64/ProcessorBind.h
@@ -27,12 +27,15 @@
#pragma pack()
#endif

-#if defined(__GNUC__) && defined(__pic__)
+#if defined(__GNUC__) && defined(__pic__) && !defined(USING_LTO)
//
// 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.
+// The LTO linker will not emit GOT based relocations anyway, so there is no
+// need to set the pragma in that case (and doing so will cause issues of its
+// own)
//
#pragma GCC visibility push (hidden)
#endif

and I can drop this patch.


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

Ard Biesheuvel
 

On 1 August 2016 at 16:56, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
On 1 August 2016 at 16:49, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
On 1 August 2016 at 16:18, Gao, Liming <liming.gao@intel.com> wrote:
Ard:
I don't think it is good way to define GCC_VISIBILITY_PROTECTED and apply it in EntryPointLib. We only need to expose _ModuleEntryPoint. It has been specified in LINK_FLAGS in tools_def.txt. Could we also specify its attribute in CC_FLAGS or LINK_FLAGS in tools_def.txt?
It seems this does the trick as well

diff --git a/BaseTools/Scripts/GccBase.lds b/BaseTools/Scripts/GccBase.lds
index 281af8a9bd33..02387d4f8d6f 100644
--- a/BaseTools/Scripts/GccBase.lds
+++ b/BaseTools/Scripts/GccBase.lds
@@ -80,3 +80,7 @@ SECTIONS {
*(COMMON)
}
}
+
+VERSION {
+ { global: _ModuleEntryPoint*; };
+};


Note that * at the end: this is necessary since _ModuleEntryPoint will
be called _ModuleEntryPoint.lto_priv.xxx in the LTO objects.
Hmm, looks like I spoke too soon. I don't know what I did wrong, but
this does not actually work.
The only alternative I can think of is to add a static non-lto object
to the tree that refers to _ModuleEntryPoint, similar to the way I
handle the ARM intrinsics in patch #5

Which one do you hate the least? :-)


[patch] BaseTool/UPT: Not expand macro for UserExtension

hesschen <hesheng.chen@...>
 

All MACRO values defined by the DEFINE statements
n any section (except [Userextensions] sections
other than TianoCore."ExtraFiles) of the INF or
DEC file must be expanded before processing of the file.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: hesschen <hesheng.chen@intel.com>
---
BaseTools/Source/Python/UPT/Parser/DecParser.py | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/BaseTools/Source/Python/UPT/Parser/DecParser.py b/BaseTools/Source/Python/UPT/Parser/DecParser.py
index e6658a9..937047f 100644
--- a/BaseTools/Source/Python/UPT/Parser/DecParser.py
+++ b/BaseTools/Source/Python/UPT/Parser/DecParser.py
@@ -270,7 +270,21 @@ class _DecBase:
self._LoggerError(ST.ERR_DECPARSE_BACKSLASH_EMPTY)
CatLine += Line

- self._RawData.CurrentLine = self._ReplaceMacro(CatLine)
+ #
+ # All MACRO values defined by the DEFINE statements in any section
+ # (except [Userextensions] sections for Intel) of the INF or DEC file
+ # must be expanded before processing of the file.
+ #
+ __IsReplaceMacro = True
+ Header = self._RawData.CurrentScope[0] if self._RawData.CurrentScope else None
+ if Header and len(Header) > 2:
+ if Header[0].upper() == 'USEREXTENSIONS' and not (Header[1] == 'TianoCore' and Header[2] == '"ExtraFiles"'):
+ __IsReplaceMacro = False
+ if __IsReplaceMacro:
+ self._RawData.CurrentLine = self._ReplaceMacro(CatLine)
+ else:
+ self._RawData.CurrentLine = CatLine
+
return CatLine, CommentList

## Parse
--
2.7.2.windows.1


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

Ard Biesheuvel
 

On 1 August 2016 at 16:49, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
On 1 August 2016 at 16:18, Gao, Liming <liming.gao@intel.com> wrote:
Ard:
I don't think it is good way to define GCC_VISIBILITY_PROTECTED and apply it in EntryPointLib. We only need to expose _ModuleEntryPoint. It has been specified in LINK_FLAGS in tools_def.txt. Could we also specify its attribute in CC_FLAGS or LINK_FLAGS in tools_def.txt?
It seems this does the trick as well

diff --git a/BaseTools/Scripts/GccBase.lds b/BaseTools/Scripts/GccBase.lds
index 281af8a9bd33..02387d4f8d6f 100644
--- a/BaseTools/Scripts/GccBase.lds
+++ b/BaseTools/Scripts/GccBase.lds
@@ -80,3 +80,7 @@ SECTIONS {
*(COMMON)
}
}
+
+VERSION {
+ { global: _ModuleEntryPoint*; };
+};


Note that * at the end: this is necessary since _ModuleEntryPoint will
be called _ModuleEntryPoint.lto_priv.xxx in the LTO objects.
Hmm, looks like I spoke too soon. I don't know what I did wrong, but
this does not actually work.

--
Ard.


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

Ard Biesheuvel
 

On 1 August 2016 at 16:18, Gao, Liming <liming.gao@intel.com> wrote:
Ard:
I don't think it is good way to define GCC_VISIBILITY_PROTECTED and apply it in EntryPointLib. We only need to expose _ModuleEntryPoint. It has been specified in LINK_FLAGS in tools_def.txt. Could we also specify its attribute in CC_FLAGS or LINK_FLAGS in tools_def.txt?
It seems this does the trick as well

diff --git a/BaseTools/Scripts/GccBase.lds b/BaseTools/Scripts/GccBase.lds
index 281af8a9bd33..02387d4f8d6f 100644
--- a/BaseTools/Scripts/GccBase.lds
+++ b/BaseTools/Scripts/GccBase.lds
@@ -80,3 +80,7 @@ SECTIONS {
*(COMMON)
}
}
+
+VERSION {
+ { global: _ModuleEntryPoint*; };
+};


Note that * at the end: this is necessary since _ModuleEntryPoint will
be called _ModuleEntryPoint.lto_priv.xxx in the LTO objects.

I will drop this patch, and add this hunk to GccBase.lds instead.

--
Ard.


Thanks
Liming
-----Original Message-----
From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
Ard Biesheuvel
Sent: Monday, August 01, 2016 4:02 PM
To: Shi, Steven ; Zhu, Yonghong
; Gao, Liming ; Justen,
Jordan L ; edk2-devel@lists.01.org
Cc: lersek@redhat.com; leif.lindholm@linaro.org; Ard Biesheuvel

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

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
---
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

_______________________________________________
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


[PATCH 2/2] MdeModulePkg/EbcDxe: cleanup

Ard Biesheuvel
 

- indentation
- premature optimization of the thunking code, i.e., align function prototypes
so we don't have to move arguments around or duplicate them on the stack,
and perform tail calls where possible
- adhere to calling convention (stack frame layout)
- replace instruction buffer with a fixed struct, so that we no longer have
to traverse it to find the entry point slots

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
MdeModulePkg/Universal/EbcDxe/AArch64/EbcLowLevel.S | 188 ++++++++++---------
MdeModulePkg/Universal/EbcDxe/AArch64/EbcSupport.c | 193 ++++++--------------
2 files changed, 159 insertions(+), 222 deletions(-)

diff --git a/MdeModulePkg/Universal/EbcDxe/AArch64/EbcLowLevel.S b/MdeModulePkg/Universal/EbcDxe/AArch64/EbcLowLevel.S
index 3c1a461f5e87..d0a5a4c5a37d 100644
--- a/MdeModulePkg/Universal/EbcDxe/AArch64/EbcLowLevel.S
+++ b/MdeModulePkg/Universal/EbcDxe/AArch64/EbcLowLevel.S
@@ -1,10 +1,12 @@
///** @file
//
-// This code provides low level routines that support the Virtual Machine
-// for option ROMs.
+// 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) 2016, Linaro, Ltd. All rights reserved.<BR>
+// Copyright (c) 2015, The Linux Foundation. All rights reserved.<BR>
// 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
@@ -15,9 +17,10 @@
//
//**/

-ASM_GLOBAL ASM_PFX(CopyMem);
-ASM_GLOBAL ASM_PFX(EbcInterpret);
-ASM_GLOBAL ASM_PFX(ExecuteEbcImageEntryPoint);
+ASM_GLOBAL ASM_PFX(EbcLLEbcInterpret);
+ASM_GLOBAL ASM_PFX(EbcLLExecuteEbcImageEntryPoint);
+
+ASM_GLOBAL ASM_PFX(mEbcInstructionBufferTemplate);

//****************************************************************************
// EbcLLCALLEX
@@ -30,102 +33,121 @@ ASM_GLOBAL ASM_PFX(ExecuteEbcImageEntryPoint);
//
//****************************************************************************
// 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
+ mov x8, x0 // Preserve x0
+ mov x9, x1 // Preserve x1
+
+ //
+ // If the EBC stack frame is smaller than or equal to 64 bytes, we know there
+ // are no stacked arguments #9 and beyond that we need to copy to the native
+ // stack. In this case, we can perform a tail call which is much more
+ // efficient, since there is no need to touch the native stack at all.
+ //
+ sub x3, x2, x1 // Length = NewStackPointer - FramePtr
+ cmp x3, #64
+ b.gt 1f
+
+ adr x0, 0f
+ sub x0, x0, x3, lsr #1
+ br x0
+
+ ldr x7, [x9, #56]
+ ldr x6, [x9, #48]
+ ldr x5, [x9, #40]
+ ldr x4, [x9, #32]
+ ldr x3, [x9, #24]
+ ldr x2, [x9, #16]
+ ldr x1, [x9, #8]
+ ldr x0, [x9]
+
+0: br x8
+
+ //
+ // More than 64 bytes: we need to build the full native stack frame and copy
+ // the part of the VM stack exceeding 64 bytes (which may contain stacked
+ // arguments) to the native stack
+ //
+1: stp x29, x30, [sp, #-16]!
+ mov x29, sp
+
+ //
+ // Ensure that the stack pointer remains 16 byte aligned,
+ // even if the size of the VM stack frame is not a multiple of 16
+ //
+ add x1, x1, #64 // Skip over [potential] reg params
+ tbz x3, #3, 2f // Multiple of 16?
+ ldr x4, [x2, #-8]! // No? Then push one word
+ str x4, [sp, #-16]! // ... but use two slots
+ b 3f
+
+2: ldp x4, x5, [x2, #-16]!
+ stp x4, x5, [sp, #-16]!
+3: cmp x2, x1
+ b.gt 2b
+
+ ldp x0, x1, [x9]
+ ldp x2, x3, [x9, #16]
+ ldp x4, x5, [x9, #32]
+ ldp x6, x7, [x9, #48]
+
+ blr x8
+
+ mov sp, x29
+ ldp x29, x30, [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
+// x16 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
+ stp x29, x30, [sp, #-16]!
+ mov x29, sp
+
+ // push the entry point and the address of args #9 - #16 onto the stack
+ add x17, sp, #16
+ stp x16, x17, [sp, #-16]!

+ // call C-code
+ bl ASM_PFX(EbcInterpret)
+
+ ldp x29, x30, [sp, #16]
+ add sp, sp, #32
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
+// x16 contains the Entry point that will be the third 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
+ mov x2, x16
+
+ // tail call to C code
+ b ASM_PFX(ExecuteEbcImageEntryPoint)
+
+//****************************************************************************
+// mEbcInstructionBufferTemplate
+//****************************************************************************
+ .section ".rodata", "a"
+ .align 3
+ASM_PFX(mEbcInstructionBufferTemplate):
+ adr x17, 0f
+ ldp x16, x17, [x17]
+ br x17
+
+ //
+ // Add a magic code here to help the VM recognize the thunk.
+ //
+ .long 0xCA112EBC
+
+0: .quad 0 // EBC_ENTRYPOINT_SIGNATURE
+ .quad 0 // EBC_LL_EBC_ENTRYPOINT_SIGNATURE
diff --git a/MdeModulePkg/Universal/EbcDxe/AArch64/EbcSupport.c b/MdeModulePkg/Universal/EbcDxe/AArch64/EbcSupport.c
index 23261a070143..d15bbc861f33 100644
--- a/MdeModulePkg/Universal/EbcDxe/AArch64/EbcSupport.c
+++ b/MdeModulePkg/Universal/EbcDxe/AArch64/EbcSupport.c
@@ -2,8 +2,10 @@
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) 2016, Linaro, Ltd. All rights reserved.<BR>
+Copyright (c) 2015, The Linux Foundation. All rights reserved.<BR>
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
@@ -22,47 +24,16 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
//
#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
-
-};
+#pragma pack(1)
+typedef struct {
+ UINT32 Instr[3];
+ UINT32 Magic;
+ UINT64 EbcEntryPoint;
+ UINT64 EbcLlEntryPoint;
+} EBC_INSTRUCTION_BUFFER;
+#pragma pack()
+
+extern CONST EBC_INSTRUCTION_BUFFER mEbcInstructionBufferTemplate;

/**
Begin executing an EBC image.
@@ -109,7 +80,6 @@ PushU64 (
//
VmPtr->Gpr[0] -= sizeof (UINT64);
*(UINT64 *) VmPtr->Gpr[0] = Arg;
- return;
}


@@ -118,7 +88,6 @@ PushU64 (

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.
@@ -127,14 +96,8 @@ PushU64 (
@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.
+ @param EntryPoint The entrypoint of EBC code.
+ @param Args9_16[] Array containing arguments #9 to #16.

@return The value returned by the EBC application we're going to run.

@@ -142,7 +105,6 @@ PushU64 (
UINT64
EFIAPI
EbcInterpret (
- IN UINTN EntryPoint,
IN UINTN Arg1,
IN UINTN Arg2,
IN UINTN Arg3,
@@ -151,14 +113,8 @@ EbcInterpret (
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
+ IN UINTN EntryPoint,
+ IN UINTN Args9_16[]
)
{
//
@@ -222,14 +178,14 @@ EbcInterpret (
// 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) Args9_16[7]);
+ PushU64 (&VmContext, (UINT64) Args9_16[6]);
+ PushU64 (&VmContext, (UINT64) Args9_16[5]);
+ PushU64 (&VmContext, (UINT64) Args9_16[4]);
+ PushU64 (&VmContext, (UINT64) Args9_16[3]);
+ PushU64 (&VmContext, (UINT64) Args9_16[2]);
+ PushU64 (&VmContext, (UINT64) Args9_16[1]);
+ PushU64 (&VmContext, (UINT64) Args9_16[0]);
PushU64 (&VmContext, (UINT64) Arg8);
PushU64 (&VmContext, (UINT64) Arg7);
PushU64 (&VmContext, (UINT64) Arg6);
@@ -281,10 +237,10 @@ EbcInterpret (
/**
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
+ @param EntryPoint The entrypoint of EBC code.

@return The value returned by the EBC application we're going to run.

@@ -292,9 +248,9 @@ EbcInterpret (
UINT64
EFIAPI
ExecuteEbcImageEntryPoint (
- IN UINTN EntryPoint,
IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
+ IN EFI_SYSTEM_TABLE *SystemTable,
+ IN UINTN EntryPoint
)
{
//
@@ -335,7 +291,7 @@ ExecuteEbcImageEntryPoint (
if (EFI_ERROR(Status)) {
return Status;
}
- VmContext.StackTop = (UINT8*)VmContext.StackPool + (STACK_REMAIN_SIZE);
+ 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);
@@ -372,11 +328,6 @@ ExecuteEbcImageEntryPoint (
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);
@@ -414,10 +365,7 @@ EbcCreateThunks (
IN UINT32 Flags
)
{
- UINT8 *Ptr;
- UINT8 *ThunkBase;
- UINT32 Index;
- INT32 ThunkSize;
+ EBC_INSTRUCTION_BUFFER *InstructionBuffer;

//
// Check alignment of pointer to EBC code
@@ -426,51 +374,38 @@ EbcCreateThunks (
return EFI_INVALID_PARAMETER;
}

- ThunkSize = sizeof(mInstructionBufferTemplate);
-
- Ptr = AllocatePool (sizeof(mInstructionBufferTemplate));
-
- if (Ptr == NULL) {
+ InstructionBuffer = AllocatePool (sizeof (EBC_INSTRUCTION_BUFFER));
+ if (InstructionBuffer == 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;
+ *Thunk = InstructionBuffer;

//
// Copy whole thunk instruction buffer template
//
- CopyMem (Ptr, mInstructionBufferTemplate, sizeof(mInstructionBufferTemplate));
+ CopyMem (InstructionBuffer, &mEbcInstructionBufferTemplate,
+ sizeof (EBC_INSTRUCTION_BUFFER));

//
// 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;
- }
- }
+ InstructionBuffer->EbcEntryPoint = (UINT64)EbcEntryPoint;
+ if ((Flags & FLAG_THUNK_ENTRY_POINT) != 0) {
+ InstructionBuffer->EbcLlEntryPoint = (UINT64)EbcLLExecuteEbcImageEntryPoint;
+ } else {
+ InstructionBuffer->EbcLlEntryPoint = (UINT64)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);
+ EbcAddImageThunk (ImageHandle, InstructionBuffer,
+ sizeof (EBC_INSTRUCTION_BUFFER));

return EFI_SUCCESS;
}
@@ -500,40 +435,15 @@ EbcLLCALLEX (
IN UINT8 Size
)
{
- UINTN IsThunk;
- UINTN TargetEbcAddr;
- UINT8 InstructionBuffer[sizeof(mInstructionBufferTemplate)];
- UINTN Index;
- UINTN IndexOfEbcEntrypoint;
-
- IsThunk = 1;
- TargetEbcAddr = 0;
- IndexOfEbcEntrypoint = 0;
+ CONST EBC_INSTRUCTION_BUFFER *InstructionBuffer;

//
// 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;
- }
+ InstructionBuffer = (EBC_INSTRUCTION_BUFFER *)FuncAddr;

- if (IsThunk == 1){
+ if (CompareMem (InstructionBuffer, &mEbcInstructionBufferTemplate,
+ sizeof(EBC_INSTRUCTION_BUFFER) - 2 * sizeof (UINT64)) == 0) {
//
// 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.
@@ -545,14 +455,19 @@ EbcLLCALLEX (
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;
+ VmPtr->Ip = (VMIP) InstructionBuffer->EbcEntryPoint;
} else {
//
// The callee is not a thunk to EBC, call native code,
// and get return value.
//
- VmPtr->Gpr[7] = EbcLLCALLEXNative (FuncAddr, NewStackPointer, FramePtr);
+ // Note that we will not be able to distinguish which part of the interval
+ // [NewStackPointer, FramePtr) consists of stacked function arguments for
+ // this call, and which part simply consists of locals in the caller's
+ // stack frame. All we know is that there is an 8 byte gap at the top that
+ // we can ignore.
+ //
+ VmPtr->Gpr[7] = EbcLLCALLEXNative (FuncAddr, NewStackPointer, FramePtr - 8);

//
// Advance the IP.
--
2.7.4


[PATCH 1/2] MdeModulePkg/EbcDxe AARCH64: fix comment style

Ard Biesheuvel
 

Replace '#' comments with '//'

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
MdeModulePkg/Universal/EbcDxe/AArch64/EbcLowLevel.S | 92 ++++++++++----------
1 file changed, 44 insertions(+), 48 deletions(-)

diff --git a/MdeModulePkg/Universal/EbcDxe/AArch64/EbcLowLevel.S b/MdeModulePkg/Universal/EbcDxe/AArch64/EbcLowLevel.S
index e858227586a8..3c1a461f5e87 100644
--- a/MdeModulePkg/Universal/EbcDxe/AArch64/EbcLowLevel.S
+++ b/MdeModulePkg/Universal/EbcDxe/AArch64/EbcLowLevel.S
@@ -1,39 +1,35 @@
-#/** @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.
-#---------------------------------------------------------------------------
+///** @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.
+//
+//**/

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)
+//****************************************************************************
+// 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]!
@@ -61,15 +57,15 @@ ASM_PFX(EbcLLCALLEXNative):

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.
-#
-#****************************************************************************
+//****************************************************************************
+// 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]!
@@ -113,14 +109,14 @@ ASM_PFX(EbcLLEbcInterpret):

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.
-#
-#****************************************************************************
+//****************************************************************************
+// 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]!
--
2.7.4


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

Leif Lindholm <leif.lindholm@...>
 

Apologies, lost track of this one.

On Mon, Aug 01, 2016 at 01:53:09PM +0200, Ard Biesheuvel wrote:
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
It's absolutely horrid, but extremely useful.
For the series:
Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>

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.


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

Liming Gao
 

Ard:
I don't think it is good way to define GCC_VISIBILITY_PROTECTED and apply it in EntryPointLib. We only need to expose _ModuleEntryPoint. It has been specified in LINK_FLAGS in tools_def.txt. Could we also specify its attribute in CC_FLAGS or LINK_FLAGS in tools_def.txt?

Thanks
Liming

-----Original Message-----
From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
Ard Biesheuvel
Sent: Monday, August 01, 2016 4:02 PM
To: Shi, Steven ; Zhu, Yonghong
; Gao, Liming ; Justen,
Jordan L ; edk2-devel@lists.01.org
Cc: lersek@redhat.com; leif.lindholm@linaro.org; Ard Biesheuvel

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

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
---
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

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


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

Liming Gao
 

Ard:
Your change is OK to me. I have no comment.

Thanks
Liming
From: Ard Biesheuvel [mailto:ard.biesheuvel@linaro.org]
Sent: Monday, August 1, 2016 7:53 PM
To: edk2-devel-01 <edk2-devel@lists.01.org>; Gao, Liming <liming.gao@intel.com>; Zhu, Yonghong <yonghong.zhu@intel.com>
Cc: Leif Lindholm <leif.lindholm@linaro.org>; Cohen, Eugene <eugene@hp.com>; Ard Biesheuvel <ard.biesheuvel@linaro.org>
Subject: Re: [PATCH 1/2] BaseTools/GenFw AARCH64: convert ADRP to ADR if binary size allows it

On 27 July 2016 at 13:26, Ard Biesheuvel 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
@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.


Re: [PATCH v5 0/8] BaseTools: add support for GCC5 in LTO mode

Ard Biesheuvel
 

On 1 August 2016 at 16:01, Shi, Steven <steven.shi@intel.com> wrote:
Ard,
Where can I check out your v5 patch?
https://git.linaro.org/people/ard.biesheuvel/uefi-next.git/shortlog/refs/heads/gcc5-lto-v5

or

git://git.linaro.org/people/ard.biesheuvel/uefi-next.git gcc5-lto-v5

Thanks,
Ard.


Re: [PATCH v5 0/8] BaseTools: add support for GCC5 in LTO mode

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

Ard,
Where can I check out your v5 patch?


Steven Shi
Intel\SSG\STO\UEFI Firmware

Tel: +86 021-61166522
iNet: 821-6522

-----Original Message-----
From: Ard Biesheuvel [mailto:ard.biesheuvel@linaro.org]
Sent: Monday, August 01, 2016 4:01 PM
To: Shi, Steven <steven.shi@intel.com>; Zhu, Yonghong
<yonghong.zhu@intel.com>; Gao, Liming <liming.gao@intel.com>; Justen,
Jordan L <jordan.l.justen@intel.com>; edk2-devel@lists.01.org
Cc: leif.lindholm@linaro.org; lersek@redhat.com; Ard Biesheuvel
<ard.biesheuvel@linaro.org>
Subject: [PATCH v5 0/8] BaseTools: add support for GCC5 in LTO mode

This v5 to introduce GCC5 is now a 8 piece series, including some
preparatory cleanup patches that allow all GCC4x and CLANG35 toolchains
to switch to using 'gcc' as the linker. This allows us to get rid of
the wrapper script to marshall ld arguments in order to make them
understandable by gcc, which is fragile and likely to cause problems in
the future.

Since there appears to be a natural split between the 'legacy' GCC
toolchains UNIXGCC, ELFGCC, and CYGGCC[xASL], both in term of supported
architectures [IA32, X64, IPF] vs [IA32, X64, ARM, AARCH64], and in
terms of maintenance, these toolchains are not moved to using 'gcc' as
the linker, and instead, a new BUILDRULEFAMILY is introduced called GCCLD
that will retain the old behavior.

The result is that GCC5 can align much more closely with its predecessors,
making the expected maintenance burden of supporting GCC back to v4.4
much lower.

Changes since v4:
- added patch to use 'protected' visibility only for the libraries that
define the module entry points (_ModuleEntryPoint), to prevent them from
being optimized away by the LTO routines
- added Jordan's ack/RBs
- add some extra comments to tools_def.template (#8)

Changes since v3:
- like Steven does in his GCC5LTO patch, add -fno-builtin to IA32 and X64
CC_FLAGS; this addresses a build issue reported by Liming
- add -Os the the linker flags as well, for AARCH64 this does not seem to
make
a difference, but it is arguably correct since the LTO processing at link
time involves code generation as well
- add Laszlo's ack to #2
- new patch #6 to omit the autogenerated build-id from the PE/COFF binary

Changes since v2:
- add license headers to LTO glue files for ARM and AARCH64 (#5)
- get rid of lto-ld-wrapper script

Ard Biesheuvel (8):
BaseTools CLANG35: drop problematic use-movt and save-temps options
ArmVirtPkg/ArmVirtPrePiUniCoreRelocatable: ignore .hash and .note
sections
BaseTools UNIXGCC ELFGCC CYGGCC: clone GCC build rule family into
GCCLD
BaseTools GCC: use 'gcc' as the linker command for GCC44 and later
ArmPkg: add prebuilt glue binaries for GCC5 LTO support
BaseTools GCC: drop GNU notes section from EFI image
MdePkg GCC/X64: avoid 'hidden' visibility for module entry points
BaseTools GCC: introduce GCC5 toolchain to support GCC v5.x in LTO
mode

ArmPkg/GccLto/liblto-aarch64.a | Bin 0 -> 1016 bytes
ArmPkg/GccLto/liblto-aarch64.s | 27 ++
ArmPkg/GccLto/liblto-arm.a | Bin 0 -> 2096 bytes
ArmPkg/GccLto/liblto-arm.s | 61 ++++
ArmVirtPkg/PrePi/ArmVirtPrePiUniCoreRelocatable.inf | 2 +-
ArmVirtPkg/PrePi/Scripts/PrePi-PIE.lds | 3 +
BaseTools/Conf/build_rule.template | 31 +-
BaseTools/Conf/tools_def.template | 350
+++++++++++++++-----
BaseTools/Scripts/GccBase.lds | 6 +
EmulatorPkg/Unix/Host/Host.inf | 6 +-
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 +
16 files changed, 396 insertions(+), 109 deletions(-)
create mode 100644 ArmPkg/GccLto/liblto-aarch64.a
create mode 100644 ArmPkg/GccLto/liblto-aarch64.s
create mode 100644 ArmPkg/GccLto/liblto-arm.a
create mode 100644 ArmPkg/GccLto/liblto-arm.s

--
2.7.4


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