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

Reply via email to