On 09/18/13 01:24, Jordan Justen wrote:
> KVM has a bug that prevents using page tables in the ROM if the ROM
> region utilizes the KVM READONLY memory feature. Therefore, we
> avoid using page tables stored in the ROM.
>
> Since OVMF doesn't require memory initialization, we just build
> page table entries in RAM at 0x80000 very early in the OVMF boot
> process. This address is just after the 'temp RAM' which is set
> up by the SEC module.
>
> Currently we only set up 4GB of page tables for OVMF's PEI,
> but DxeIpl will build identity mapped page tables that cover all
> of the available processor physical address space.
>
> Reported-by: Gary Ching-Pang Lin <[email protected]>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Jordan Justen <[email protected]>
> ---
> OvmfPkg/ResetVector/Bin/ResetVector.inf | 29 +++++++
> OvmfPkg/ResetVector/Bin/ResetVector.x64.raw | Bin 0 -> 628 bytes
> OvmfPkg/ResetVector/Build.py | 58 ++++++++++++++
> OvmfPkg/ResetVector/Ia32/PageTables64.asm | 93
> +++++++++++++++++++++++
> OvmfPkg/ResetVector/ResetVectorCode.asm | 53 +++++++++++++
> OvmfPkg/ResetVector/Tools/FixupForRawSection.py | 26 +++++++
> 6 files changed, 259 insertions(+)
> create mode 100644 OvmfPkg/ResetVector/Bin/ResetVector.inf
> create mode 100644 OvmfPkg/ResetVector/Bin/ResetVector.x64.raw
> create mode 100644 OvmfPkg/ResetVector/Build.py
> create mode 100644 OvmfPkg/ResetVector/Ia32/PageTables64.asm
> create mode 100644 OvmfPkg/ResetVector/ResetVectorCode.asm
> create mode 100644 OvmfPkg/ResetVector/Tools/FixupForRawSection.py
>
> diff --git a/OvmfPkg/ResetVector/Bin/ResetVector.inf
> b/OvmfPkg/ResetVector/Bin/ResetVector.inf
> new file mode 100644
> index 0000000..afc80e3
> --- /dev/null
> +++ b/OvmfPkg/ResetVector/Bin/ResetVector.inf
> @@ -0,0 +1,29 @@
> +## @file
> +# Reset Vector binary
> +#
> +# Copyright (c) 2006 - 2013, 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.
> +#
> +##
> +
> +[Defines]
> + INF_VERSION = 0x00010005
> + BASE_NAME = ResetVector
> + FILE_GUID = 1BA0062E-C779-4582-8566-336AE8F78F09
> + MODULE_TYPE = SEC
> + VERSION_STRING = 1.1
> +
> +#
> +# The following information is for reference only and not required by the
> build tools.
> +#
> +# VALID_ARCHITECTURES = IA32 X64
> +#
> +
> +[Binaries.X64]
> + RAW|ResetVector.x64.raw|*
This is a customized copy of
"UefiCpuPkg/ResetVector/Vtf0/Bin/ResetVector.inf". The GUID is (remains)
gEfiFirmwareVolumeTopFileGuid, which seems good.
Maybe the VALID_ARCHITECTURES (comment-only) clause could be updated to
X64-only too. You could fix it up at commit time, or ignore it
altogether.
> diff --git a/OvmfPkg/ResetVector/Bin/ResetVector.x64.raw
> b/OvmfPkg/ResetVector/Bin/ResetVector.x64.raw
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..ff083636008d2f4cd6836ab8daeee15b29bda600
> GIT binary patch
> literal 628
> zcmYk3&ubGw6vtn(NxJpmE~S!yh5RswdWa+`iV};_qU0jxASF~qyzIqW+<`rK$g<`z
> zNev60#D78X*sVQe$~H9?#DIrJf)e8ovKa+Is8wp#w<&_}@aFq?GoSZkOw%+oECn*a
> zA^^DM1znT1&#SA1>)PyMZSEQw=vw6QX?lme)wQ{*oq9t$hL!}fLv5iHBQ~G5nrO7e
> z$F$|_`T#OL`koGz`mMCDTh4JIUp`Z1YSv&=<y3ONRtoRgF?Ccg%<3Op*M;eq>O0@2
> z>M!qBv>Abfc(}?)h_?AohSBZn9`UPV=K*pNa@$~$bM1SjiYCbFar854wjR+xdK@g4
> zH<(b)B@cMdU;#xxdv%4Rq_xs{pRMPLmjOsrSeoZiOj29XbIU8_sIVj&Y+hQs5jxrB
> zK?|1v&V9u3loabr&xb)N(O<6sFe!_XD5a$sLlKn{Y}6UMZUmff_+}j<I5?w$hX?Ky
> z41T@{0*J66i+~FKLd;X5r_!F1J(c%V#8X8P2_gV(7dHFHf<KT*1F!a@A`HG_Pa;T(
> zu5%aL`n>_)8@&zHJ*7y#uwtD6$YU$Y=q4s*u<{|myM4tHq0w!yM!zv^bohlRR4|X9
> zjfU)r;mQCWy@tv8<lp%WnwN_FNb_Qm2Nk--{rnfNIo&_5>m+ep=My>$S#BY|U5K{|
> d@vQ>wyI&5`6VL6#z$>zR{R)^SfBIkA{0lHk5jp?>
>
> literal 0
> HcmV?d00001
I'll trust you on this :)
(Unfortunately BTW, git-am chokes on this hunk horribly. I found the bug
report in some mailing list archive from 2010. It still fails. git-am
tries to strip leading pathname components, and falls on its face near
the end of the binary hunk.)
>
> diff --git a/OvmfPkg/ResetVector/Build.py b/OvmfPkg/ResetVector/Build.py
> new file mode 100644
> index 0000000..e0a9496
> --- /dev/null
> +++ b/OvmfPkg/ResetVector/Build.py
> @@ -0,0 +1,58 @@
> +## @file
> +# Automate the process of building the various reset vector types
> +#
> +# Copyright (c) 2009 - 2013, 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.
> +#
> +
> +import glob
> +import os
> +import subprocess
> +import sys
> +
> +def RunCommand(commandLine):
> + #print ' '.join(commandLine)
> + return subprocess.call(commandLine)
> +
> +for filename in glob.glob(os.path.join('Bin', '*.raw')):
> + os.remove(filename)
> +
> +ThisDir = os.path.realpath(os.path.split(sys.argv[0])[0])
> +WorkspaceDir = os.path.realpath(os.path.join(ThisDir, '..', '..'))
> +UefiCpuPkgVtf0Dir = os.path.join(WorkspaceDir, 'UefiCpuPkg', 'ResetVector',
> 'Vtf0')
> +
> +for arch in ('x64',):
> + for debugType in (None,):
> + output = os.path.join('Bin', 'ResetVector')
> + output += '.' + arch
> + if debugType is not None:
> + output += '.' + debugType
> + output += '.raw'
> + commandLine = (
> + 'nasm',
> + '-D', 'ARCH_%s' % arch.upper(),
> + '-D', 'DEBUG_%s' % str(debugType).upper(),
> + '-I', UefiCpuPkgVtf0Dir + os.path.sep,
> + '-o', output,
> + 'ResetVectorCode.asm',
> + )
> + ret = RunCommand(commandLine)
> + print '\tASM\t' + output
> + if ret != 0: sys.exit(ret)
> +
> + commandLine = (
> + 'python',
> + 'Tools/FixupForRawSection.py',
> + output,
> + )
> + print '\tFIXUP\t' + output
> + ret = RunCommand(commandLine)
> + if ret != 0: sys.exit(ret)
> +
Slightly adapted copy of "UefiCpuPkg/ResetVector/Vtf0/Build.py":
> --- UefiCpuPkg/ResetVector/Vtf0/Build.py 2013-08-30 23:17:44.000000000
> +0200
> +++ OvmfPkg/ResetVector/Build.py 2013-09-20 16:43:30.347699656 +0200
> @@ -1,7 +1,7 @@
> ## @file
> # Automate the process of building the various reset vector types
> #
> -# Copyright (c) 2009, Intel Corporation. All rights reserved.<BR>
> +# Copyright (c) 2009 - 2013, 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
> @@ -24,8 +24,12 @@
> for filename in glob.glob(os.path.join('Bin', '*.raw')):
> os.remove(filename)
>
> -for arch in ('ia32', 'x64'):
> - for debugType in (None, 'port80', 'serial'):
> +ThisDir = os.path.realpath(os.path.split(sys.argv[0])[0])
> +WorkspaceDir = os.path.realpath(os.path.join(ThisDir, '..', '..'))
> +UefiCpuPkgVtf0Dir = os.path.join(WorkspaceDir, 'UefiCpuPkg', 'ResetVector',
> 'Vtf0')
I wonder if we could key off the WORKSPACE environment variable; set by
edksetup.{bat,sh}; but maybe we want to be able to rebuild the binary
with "nasm" without those settings in effect.
> +
> +for arch in ('x64',):
> + for debugType in (None,):
> output = os.path.join('Bin', 'ResetVector')
> output += '.' + arch
> if debugType is not None:
> @@ -35,6 +39,7 @@
> 'nasm',
> '-D', 'ARCH_%s' % arch.upper(),
> '-D', 'DEBUG_%s' % str(debugType).upper(),
> + '-I', UefiCpuPkgVtf0Dir + os.path.sep,
> '-o', output,
> 'ResetVectorCode.asm',
> )
Looks good.
> diff --git a/OvmfPkg/ResetVector/Ia32/PageTables64.asm
> b/OvmfPkg/ResetVector/Ia32/PageTables64.asm
> new file mode 100644
> index 0000000..5ebf211
> --- /dev/null
> +++ b/OvmfPkg/ResetVector/Ia32/PageTables64.asm
OK, so nasm will find this first, when encountering the new include
directive added by patch #1.
> @@ -0,0 +1,93 @@
> +;------------------------------------------------------------------------------
> +; @file
> +; Sets the CR3 register for 64-bit paging
> +;
> +; Copyright (c) 2008 - 2013, 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.
> +;
> +;------------------------------------------------------------------------------
> +
> +BITS 32
> +
> +%define PAGE_PRESENT 0x01
> +%define PAGE_READ_WRITE 0x02
> +%define PAGE_USER_SUPERVISOR 0x04
> +%define PAGE_WRITE_THROUGH 0x08
> +%define PAGE_CACHE_DISABLE 0x010
> +%define PAGE_ACCESSED 0x020
> +%define PAGE_DIRTY 0x040
> +%define PAGE_PAT 0x080
> +%define PAGE_GLOBAL 0x0100
> +%define PAGE_2M_MBO 0x080
> +%define PAGE_2M_PAT 0x01000
Copied from the x64 branch of
"UefiCpuPkg/ResetVector/Vtf0/Tools/FixupForRawSection.py".
> +
> +%define PAGE_2M_PDE_ATTR (PAGE_2M_MBO + \
> + PAGE_CACHE_DISABLE + \
> + PAGE_ACCESSED + \
> + PAGE_DIRTY + \
> + PAGE_READ_WRITE + \
> + PAGE_PRESENT)
> +
> +%define PAGE_PDP_ATTR (PAGE_CACHE_DISABLE + \
> + PAGE_ACCESSED + \
> + PAGE_READ_WRITE + \
> + PAGE_PRESENT)
We're apparently moving said branch from build time to runtime, from
Python to assembly. PageDirectoryEntries4GbOf2MbPages is called with
baseAddress=0L.
> +
> +
> +;
> +; Modified: EAX, ECX
> +;
> +SetCr3ForPageTables64:
> +
> + ;
> + ; For OVMF, build some initial page tables at 0x80000. This is just
> + ; after the early stack/temp RAM.
> + ;
> + ; At the end of PEI, the pages tables will be rebuilt into a
> + ; more permanent location by DxeIpl.
> + ;
> +
> + mov ecx, 6 * 0x1000 / 4
> + xor eax, eax
> +clearPageTablesMemoryLoop:
> + mov dword[ecx * 4 + 0x80000 - 4], eax
> + loop clearPageTablesMemoryLoop
We seem to be clearing [0x80000..86000[, ie. six pages.
> +
> + ;
> + ; Top level Page Directory Pointers (1 * 512GB entry)
> + ;
> + mov dword[0x80000], 0x81000 + PAGE_PDP_ATTR
The first page stores Top level Page Directory Pointers (all one of
them), which points to the second page.
> +
> + ;
> + ; Next level Page Directory Pointers (4 * 1GB entries => 4GB)
> + ;
> + mov dword[0x81000], 0x82000 + PAGE_PDP_ATTR
> + mov dword[0x81008], 0x83000 + PAGE_PDP_ATTR
> + mov dword[0x81010], 0x84000 + PAGE_PDP_ATTR
> + mov dword[0x81018], 0x85000 + PAGE_PDP_ATTR
Second page contains four pointers, designating the 3rd to 6th pages.
> +
> + ;
> + ; Page Table Entries (2048 * 2MB entries => 4GB)
> + ;
> + mov ecx, 0x800
> +pageTableEntriesLoop:
> + mov eax, ecx
> + dec eax
> + shl eax, 21
> + add eax, PAGE_2M_PDE_ATTR
> + mov [ecx * 8 + 0x82000 - 8], eax
> + loop pageTableEntriesLoop
The loop sees ecx go from 0x800 down to 0x001, and eax go from 0x7FF
down to 0x000. Eax is used as the index/address of the next 2MB (== 1 <<
21) page, with the necessary flags ORd in.
Entries for 2048 2MB pages (covering 4GB) are stored in 2048*8 = 16384
bytes, ie. 4 pages of size 4K each. These 4 pages are pages #3 to #6
that we pre-cleared.
The last mov doesn't have the "dword" target size specifier (?) that
seems to be used elsewhere, but I assume it's no problem. (Maybe that's
the default size when eax is the source?)
> +
> + ;
> + ; Set CR3 now that the paging structures are available
> + ;
> + mov eax, 0x80000
> + mov cr3, eax
> +
> + OneTimeCallRet SetCr3ForPageTables64
OK.
> diff --git a/OvmfPkg/ResetVector/ResetVectorCode.asm
> b/OvmfPkg/ResetVector/ResetVectorCode.asm
> new file mode 100644
> index 0000000..052c821
> --- /dev/null
> +++ b/OvmfPkg/ResetVector/ResetVectorCode.asm
Verbatim copy of "UefiCpuPkg/ResetVector/Vtf0/ResetVectorCode.asm" (the
root file of the reset vector build), with patch #1 in effect.
> diff --git a/OvmfPkg/ResetVector/Tools/FixupForRawSection.py
> b/OvmfPkg/ResetVector/Tools/FixupForRawSection.py
> new file mode 100644
> index 0000000..f88c8a4
> --- /dev/null
> +++ b/OvmfPkg/ResetVector/Tools/FixupForRawSection.py
> @@ -0,0 +1,26 @@
> +## @file
> +# Apply fixup to VTF binary image for FFS Raw section
> +#
> +# Copyright (c) 2008, 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.
> +#
> +
> +import sys
> +
> +filename = sys.argv[1]
> +
> +d = open(sys.argv[1], 'rb').read()
> +c = ((len(d) + 4 + 7) & ~7) - 4
> +if c > len(d):
> + c -= len(d)
> + f = open(sys.argv[1], 'wb')
> + f.write('\x90' * c)
> + f.write(d)
> + f.close()
>
Invoked by "OvmfPkg/ResetVector/Build.py"; keeps only & hard-wires the
(filename.lower().find('ia32') >= 0)
branch from "UefiCpuPkg/ResetVector/Vtf0/Tools/FixupForRawSection.py".
This code seems to prepend a NOP slide to the reset vector. The check
can be rewritten as:
if ((len(d) + 4 + 7) & ~7) - 4 > len(d): // substituting c
if ((len(d) + 4 + 7) & ~7) > len(d) + 4: // adding 4
if ((new_size + 7) & ~7) > new_size: // defining new_size := len(d) + 4
which checks if new_size is a multiple of 8. If not, then the following
number of NOPs is prepended:
((len(d) + 4 + 7) & ~7) - 4 - len(d) ==
((len(d) + 4 + 7) & ~7) - (len(d) + 4) ==
((new_size + 7) & ~7) - new_size
So... the fixup ensures with an optional NOP slide that, after
"something else" adds further 4 bytes later on, the final file size
becomes a multiple of 8. No idea where those other 4 bytes come from.
Reviewed-by: Laszlo Ersek <[email protected]>
------------------------------------------------------------------------------
LIMITED TIME SALE - Full Year of Microsoft Training For Just $49.99!
1,500+ hours of tutorials including VisualStudio 2012, Windows 8, SharePoint
2013, SQL 2012, MVC 4, more. BEST VALUE: New Multi-Library Power Pack includes
Mobile, Cloud, Java, and UX Design. Lowest price ever! Ends 9/20/13.
http://pubads.g.doubleclick.net/gampad/clk?id=58041151&iu=/4140/ostg.clktrk
_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/edk2-devel