1b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/** @file
2b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
3b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyCopyright (c) 2013-2015 Intel Corporation.
4b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
5b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyThis program and the accompanying materials
6b303605e1b7e113b4311daf161c6c3289350447bMichael Kinneyare licensed and made available under the terms and conditions of the BSD License
7b303605e1b7e113b4311daf161c6c3289350447bMichael Kinneywhich accompanies this distribution.  The full text of the license may be found at
8b303605e1b7e113b4311daf161c6c3289350447bMichael Kinneyhttp://opensource.org/licenses/bsd-license.php
9b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
10b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
13b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
14b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney**/
15b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
16b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney#include "FwBlockService.h"
17b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
18b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyESAL_FWB_GLOBAL         *mFvbModuleGlobal;
19b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
20b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_FW_VOL_BLOCK_DEVICE mFvbDeviceTemplate = {
21b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  FVB_DEVICE_SIGNATURE,  // Signature
22b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
23b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // FV_DEVICE_PATH                      FvDevicePath
24b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
25b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  {
26b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    {
27b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      {
28b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        HARDWARE_DEVICE_PATH,
29b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        HW_MEMMAP_DP,
30b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        {
31b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney          (UINT8)(sizeof (MEMMAP_DEVICE_PATH)),
32b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney          (UINT8)(sizeof (MEMMAP_DEVICE_PATH) >> 8)
33b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        }
34b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      },
35b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      EfiMemoryMappedIO,
36b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      (EFI_PHYSICAL_ADDRESS) 0,
37b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      (EFI_PHYSICAL_ADDRESS) 0
38b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    },
39b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    {
40b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      END_DEVICE_PATH_TYPE,
41b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      END_ENTIRE_DEVICE_PATH_SUBTYPE,
42b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      {
43b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        END_DEVICE_PATH_LENGTH,
44b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        0
45b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      }
46b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    }
47b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  },
48b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
49b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //   UEFI_FV_DEVICE_PATH                 UefiFvDevicePath
50b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
51b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  {
52b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    {
53b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      {
54b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        MEDIA_DEVICE_PATH,
55b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        MEDIA_PIWG_FW_VOL_DP,
56b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        {
57b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney          (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH)),
58b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney          (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH) >> 8)
59b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        }
60b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      },
61b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      { 0 }
62b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    },
63b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    {
64b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      END_DEVICE_PATH_TYPE,
65b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      END_ENTIRE_DEVICE_PATH_SUBTYPE,
66b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      {
67b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        END_DEVICE_PATH_LENGTH,
68b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        0
69b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      }
70b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    }
71b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  },
72b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  0,      // Instance
73b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
74b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  FwVolBlockInstance
75b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
76b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  {
77b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    FvbProtocolGetAttributes,
78b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    FvbProtocolSetAttributes,
79b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    FvbProtocolGetPhysicalAddress,
80b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    FvbProtocolGetBlockSize,
81b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    FvbProtocolRead,
82b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    FvbProtocolWrite,
83b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    FvbProtocolEraseBlocks,
84b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    NULL
85b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
86b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney};
87b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
88b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyUINT32 mInSmmMode = 0;
89b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_SMM_SYSTEM_TABLE2*   mSmst = NULL;
90b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
91b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyVOID
92b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyPublishFlashDeviceInfo (
93b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN SPI_INIT_TABLE   *Found
94b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  )
95b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++
96b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
97b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description:
98b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
99b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Publish info on found flash device to other drivers via PcdSpiFlashDeviceSize.
100b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
101b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments:
102b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Found                 - Pointer to entry in mSpiInitTable for found flash part.
103b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
104b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns:
105b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  None
106b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
107b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/
108b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{
109b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_STATUS  Status;
110b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
111b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
112b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Publish Byte Size of found flash device.
113b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
114b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Status = PcdSet32S (PcdSpiFlashDeviceSize, (UINT32)(Found->BiosStartOffset + Found->BiosSize));
115b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  ASSERT_EFI_ERROR (Status);
116b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney}
117b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
118b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyVOID
119b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFvbVirtualddressChangeEvent (
120b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN EFI_EVENT        Event,
121b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN VOID             *Context
122b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  )
123b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++
124b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
125b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description:
126b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
127b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Fixup internal data so that EFI and SAL can be call in virtual mode.
128b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Call the passed in Child Notify event and convert the mFvbModuleGlobal
129b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  date items to there virtual address.
130b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
131b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  mFvbModuleGlobal->FvInstance[FVB_PHYSICAL]  - Physical copy of instance data
132b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  mFvbModuleGlobal->FvInstance[FVB_VIRTUAL]   - Virtual pointer to common
133b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                                instance data.
134b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
135b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments:
136b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
137b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  (Standard EFI notify event - EFI_EVENT_NOTIFY)
138b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
139b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns:
140b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
141b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  None
142b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
143b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/
144b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{
145b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_FW_VOL_INSTANCE *FwhInstance;
146b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINTN               Index;
147b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
148b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID **) &mFvbModuleGlobal->FvInstance[FVB_VIRTUAL]);
149b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
150b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
151b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Convert the base address of all the instances
152b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
153b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Index       = 0;
154b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  FwhInstance = mFvbModuleGlobal->FvInstance[FVB_PHYSICAL];
155b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  while (Index < mFvbModuleGlobal->NumFv) {
156b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
157b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID **) &FwhInstance->FvBase[FVB_VIRTUAL]);
158b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //
159b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    // SpiWrite and SpiErase always use Physical Address instead of
160b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    // Virtual Address, even in Runtime. So we need not convert pointer
161b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    // for FvWriteBase[FVB_VIRTUAL]
162b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //
163b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    // EfiConvertPointer (0, (VOID **) &FwhInstance->FvWriteBase[FVB_VIRTUAL]);
164b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //
165b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    FwhInstance = (EFI_FW_VOL_INSTANCE *)
166b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      (
167b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        (UINTN) ((UINT8 *) FwhInstance) + FwhInstance->VolumeHeader.HeaderLength +
168b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney          (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER))
169b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      );
170b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    Index++;
171b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
172b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
173b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID **) &mFvbModuleGlobal->FvbScratchSpace[FVB_VIRTUAL]);
174b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
175b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Convert SPI_PROTOCOL instance for runtime
176b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
177b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID **) &mFvbModuleGlobal->SpiProtocol);
178b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID **) &mFvbModuleGlobal);
179b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney}
180b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
181b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyVOID
182b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFvbMemWrite8 (
183b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN  UINT64                              Dest,
184b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN  UINT8                               Byte
185b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  )
186b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{
187b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  MmioWrite8 ((UINTN)Dest, Byte);
188b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
189b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  return ;
190b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney}
191b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
192b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS
193b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyGetFvbInstance (
194b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN  UINTN                               Instance,
195b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN  ESAL_FWB_GLOBAL                     *Global,
196b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  OUT EFI_FW_VOL_INSTANCE                 **FwhInstance,
197b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN BOOLEAN                              Virtual
198b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  )
199b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++
200b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
201b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description:
202b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Retrieves the physical address of a memory mapped FV
203b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
204b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments:
205b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Instance              - The FV instance whose base address is going to be
206b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          returned
207b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Global                - Pointer to ESAL_FWB_GLOBAL that contains all
208b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          instance data
209b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  FwhInstance           - The EFI_FW_VOL_INSTANCE fimrware instance structure
210b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Virtual               - Whether CPU is in virtual or physical mode
211b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
212b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns:
213b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_SUCCESS           - Successfully returns
214b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_INVALID_PARAMETER - Instance not found
215b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
216b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/
217b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{
218b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_FW_VOL_INSTANCE *FwhRecord;
219b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
220b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if (Instance >= Global->NumFv) {
221b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    return EFI_INVALID_PARAMETER;
222b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
223b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
224b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Find the right instance of the FVB private data
225b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
226b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  FwhRecord = Global->FvInstance[Virtual];
227b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  while (Instance > 0) {
228b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    FwhRecord = (EFI_FW_VOL_INSTANCE *)
229b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      (
230b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        (UINTN) ((UINT8 *) FwhRecord) + FwhRecord->VolumeHeader.HeaderLength +
231b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney          (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER))
232b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      );
233b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    Instance--;
234b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
235b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
236b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  *FwhInstance = FwhRecord;
237b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
238b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  return EFI_SUCCESS;
239b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney}
240b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
241b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS
242b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFvbGetPhysicalAddress (
243b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN UINTN                                Instance,
244b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  OUT EFI_PHYSICAL_ADDRESS                *Address,
245b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN ESAL_FWB_GLOBAL                      *Global,
246b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN BOOLEAN                              Virtual
247b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  )
248b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++
249b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
250b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description:
251b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Retrieves the physical address of a memory mapped FV
252b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
253b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments:
254b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Instance              - The FV instance whose base address is going to be
255b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          returned
256b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Address               - Pointer to a caller allocated EFI_PHYSICAL_ADDRESS
257b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          that on successful return, contains the base address
258b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          of the firmware volume.
259b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Global                - Pointer to ESAL_FWB_GLOBAL that contains all
260b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          instance data
261b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Virtual               - Whether CPU is in virtual or physical mode
262b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
263b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns:
264b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_SUCCESS           - Successfully returns
265b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_INVALID_PARAMETER - Instance not found
266b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
267b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/
268b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{
269b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_FW_VOL_INSTANCE *FwhInstance;
270b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_STATUS          Status;
271b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
272b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  FwhInstance = NULL;
273b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
274b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
275b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Find the right instance of the FVB private data
276b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
277b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);
278b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  ASSERT_EFI_ERROR (Status);
279b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  *Address = FwhInstance->FvBase[Virtual];
280b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
281b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  return EFI_SUCCESS;
282b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney}
283b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
284b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS
285b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFvbGetVolumeAttributes (
286b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN UINTN                                Instance,
287b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  OUT EFI_FVB_ATTRIBUTES_2                  *Attributes,
288b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN ESAL_FWB_GLOBAL                      *Global,
289b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN BOOLEAN                              Virtual
290b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  )
291b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++
292b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
293b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description:
294b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Retrieves attributes, insures positive polarity of attribute bits, returns
295b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  resulting attributes in output parameter
296b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
297b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments:
298b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Instance              - The FV instance whose attributes is going to be
299b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          returned
300b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Attributes            - Output buffer which contains attributes
301b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Global                - Pointer to ESAL_FWB_GLOBAL that contains all
302b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          instance data
303b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Virtual               - Whether CPU is in virtual or physical mode
304b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
305b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns:
306b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_SUCCESS           - Successfully returns
307b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_INVALID_PARAMETER - Instance not found
308b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
309b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/
310b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{
311b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_FW_VOL_INSTANCE *FwhInstance;
312b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_STATUS          Status;
313b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
314b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  FwhInstance = NULL;
315b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
316b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
317b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Find the right instance of the FVB private data
318b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
319b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);
320b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  ASSERT_EFI_ERROR (Status);
321b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  *Attributes = FwhInstance->VolumeHeader.Attributes;
322b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
323b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  return EFI_SUCCESS;
324b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney}
325b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
326b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS
327b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFvbGetLbaAddress (
328b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN  UINTN                               Instance,
329b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN  EFI_LBA                             Lba,
330b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  OUT UINTN                               *LbaAddress,
331b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  OUT UINTN                               *LbaWriteAddress,
332b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  OUT UINTN                               *LbaLength,
333b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  OUT UINTN                               *NumOfBlocks,
334b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN  ESAL_FWB_GLOBAL                     *Global,
335b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN  BOOLEAN                             Virtual
336b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  )
337b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++
338b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
339b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description:
340b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Retrieves the starting address of an LBA in an FV
341b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
342b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments:
343b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Instance              - The FV instance which the Lba belongs to
344b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Lba                   - The logical block address
345b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  LbaAddress            - On output, contains the physical starting address
346b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          of the Lba
347b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  LbaWriteAddress       - On output, contains the physical starting address
348b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          of the Lba for writing
349b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  LbaLength             - On output, contains the length of the block
350b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  NumOfBlocks           - A pointer to a caller allocated UINTN in which the
351b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          number of consecutive blocks starting with Lba is
352b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          returned. All blocks in this range have a size of
353b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          BlockSize
354b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Global                - Pointer to ESAL_FWB_GLOBAL that contains all
355b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          instance data
356b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Virtual               - Whether CPU is in virtual or physical mode
357b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
358b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns:
359b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_SUCCESS           - Successfully returns
360b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_INVALID_PARAMETER - Instance not found
361b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
362b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/
363b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{
364b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINT32                  NumBlocks;
365b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINT32                  BlockLength;
366b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINTN                   Offset;
367b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_LBA                 StartLba;
368b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_LBA                 NextLba;
369b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_FW_VOL_INSTANCE     *FwhInstance;
370b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_FV_BLOCK_MAP_ENTRY  *BlockMap;
371b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_STATUS              Status;
372b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
373b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  FwhInstance = NULL;
374b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
375b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
376b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Find the right instance of the FVB private data
377b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
378b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);
379b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  ASSERT_EFI_ERROR (Status);
380b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
381b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  StartLba  = 0;
382b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Offset    = 0;
383b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  BlockMap  = &(FwhInstance->VolumeHeader.BlockMap[0]);
384b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
385b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
386b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Parse the blockmap of the FV to find which map entry the Lba belongs to
387b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
388b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  while (TRUE) {
389b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    NumBlocks   = BlockMap->NumBlocks;
390b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    BlockLength = BlockMap->Length;
391b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
392b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    if ((NumBlocks == 0) || (BlockLength == 0)) {
393b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      return EFI_INVALID_PARAMETER;
394b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    }
395b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
396b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    NextLba = StartLba + NumBlocks;
397b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
398b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //
399b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    // The map entry found
400b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //
401b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    if (Lba >= StartLba && Lba < NextLba) {
402b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      Offset = Offset + (UINTN) MultU64x32 ((Lba - StartLba), BlockLength);
403b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      if (LbaAddress) {
404b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        *LbaAddress = FwhInstance->FvBase[Virtual] + Offset;
405b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      }
406b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
407b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      if (LbaWriteAddress) {
408b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        *LbaWriteAddress = FwhInstance->FvWriteBase[Virtual] + Offset;
409b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      }
410b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
411b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      if (LbaLength) {
412b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        *LbaLength = BlockLength;
413b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      }
414b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
415b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      if (NumOfBlocks) {
416b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        *NumOfBlocks = (UINTN) (NextLba - Lba);
417b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      }
418b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
419b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      return EFI_SUCCESS;
420b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    }
421b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
422b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    StartLba  = NextLba;
423b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    Offset    = Offset + NumBlocks * BlockLength;
424b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    BlockMap++;
425b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
426b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney}
427b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
428b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS
429b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFvbReadBlock (
430b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN UINTN                                Instance,
431b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN EFI_LBA                              Lba,
432b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN UINTN                                BlockOffset,
433b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN OUT UINTN                            *NumBytes,
434b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN UINT8                                *Buffer,
435b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN ESAL_FWB_GLOBAL                      *Global,
436b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN BOOLEAN                              Virtual
437b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  )
438b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++
439b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
440b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description:
441b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Reads specified number of bytes into a buffer from the specified block
442b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
443b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments:
444b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Instance              - The FV instance to be read from
445b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Lba                   - The logical block address to be read from
446b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  BlockOffset           - Offset into the block at which to begin reading
447b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  NumBytes              - Pointer that on input contains the total size of
448b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          the buffer. On output, it contains the total number
449b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          of bytes read
450b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Buffer                - Pointer to a caller allocated buffer that will be
451b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          used to hold the data read
452b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Global                - Pointer to ESAL_FWB_GLOBAL that contains all
453b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          instance data
454b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Virtual               - Whether CPU is in virtual or physical mode
455b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
456b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns:
457b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_SUCCESS           - The firmware volume was read successfully and
458b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          contents are in Buffer
459b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_BAD_BUFFER_SIZE   - Read attempted across a LBA boundary. On output,
460b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          NumBytes contains the total number of bytes returned
461b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          in Buffer
462b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_ACCESS_DENIED     - The firmware volume is in the ReadDisabled state
463b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_DEVICE_ERROR      - The block device is not functioning correctly and
464b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          could not be read
465b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_INVALID_PARAMETER - Instance not found, or NumBytes, Buffer are NULL
466b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
467b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/
468b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{
469b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_FVB_ATTRIBUTES_2  Attributes;
470b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINTN               LbaAddress;
471b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINTN               LbaLength;
472b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_STATUS          Status;
473b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
474b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
475b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Check for invalid conditions
476b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
477b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if ((NumBytes == NULL) || (Buffer == NULL)) {
478b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    return EFI_INVALID_PARAMETER;
479b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
480b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
481b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if (*NumBytes == 0) {
482b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    return EFI_INVALID_PARAMETER;
483b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
484b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
485b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, NULL, &LbaLength, NULL, Global, Virtual);
486b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if (EFI_ERROR (Status)) {
487b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    return Status;
488b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
489b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
490b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Check if the FV is read enabled
491b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
492b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual);
493b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
494b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if ((Attributes & EFI_FVB2_READ_STATUS) == 0) {
495b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    return EFI_ACCESS_DENIED;
496b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
497b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
498b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Perform boundary checks and adjust NumBytes
499b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
500b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if (BlockOffset > LbaLength) {
501b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    return EFI_INVALID_PARAMETER;
502b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
503b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
504b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if (LbaLength < (*NumBytes + BlockOffset)) {
505b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    *NumBytes = (UINT32) (LbaLength - BlockOffset);
506b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    Status    = EFI_BAD_BUFFER_SIZE;
507b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
508b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
509b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  MmioReadBuffer8 (LbaAddress + BlockOffset, (UINTN) *NumBytes, Buffer);
510b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
511b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  return Status;
512b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney}
513b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
514b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS
515b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFlashFdWrite (
516b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN  UINTN                               WriteAddress,
517b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN  UINTN                               Address,
518b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN OUT UINTN                            *NumBytes,
519b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN  UINT8                               *Buffer,
520b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN  UINTN                               LbaLength
521b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  )
522b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++
523b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
524b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description:
525b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Writes specified number of bytes from the input buffer to the address
526b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
527b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments:
528b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
529b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns:
530b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
531b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/
532b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{
533b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_STATUS  Status;
534b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
535b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Status = EFI_SUCCESS;
536b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
537b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
538b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // TODO:  Suggested that this code be "critical section"
539b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
540b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  WriteAddress -= ( PcdGet32 (PcdFlashAreaBaseAddress) );
541b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if (mInSmmMode == 0) { // !(EfiInManagementInterrupt ())) {
542b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    Status = mFvbModuleGlobal->SpiProtocol->Execute (
543b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            mFvbModuleGlobal->SpiProtocol,
544b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            SPI_OPCODE_WRITE_INDEX, // OpcodeIndex
545b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            0,                      // PrefixOpcodeIndex
546b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            TRUE,                   // DataCycle
547b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            TRUE,                   // Atomic
548b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            TRUE,                   // ShiftOut
549b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            WriteAddress,           // Address
550b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            (UINT32) (*NumBytes),   // Data Number
551b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            Buffer,
552b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            EnumSpiRegionBios
553b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            );
554b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
555b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  } else {
556b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    Status = mFvbModuleGlobal->SmmSpiProtocol->Execute (
557b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            mFvbModuleGlobal->SmmSpiProtocol,
558b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            SPI_OPCODE_WRITE_INDEX, // OpcodeIndex
559b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            0,                      // PrefixOpcodeIndex
560b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            TRUE,                   // DataCycle
561b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            TRUE,                   // Atomic
562b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            TRUE,                   // ShiftOut
563b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            WriteAddress,           // Address
564b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            (UINT32) (*NumBytes),   // Data Number
565b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            Buffer,
566b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            EnumSpiRegionBios
567b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            );
568b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
569b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
570b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    AsmWbinvd ();
571b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
572b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  return Status;
573b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney}
574b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
575b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS
576b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFlashFdErase (
577b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN UINTN                                WriteAddress,
578b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN UINTN                                Address,
579b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN UINTN                                LbaLength
580b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  )
581b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++
582b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
583b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description:
584b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Erase a certain block from address LbaWriteAddress
585b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
586b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments:
587b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
588b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns:
589b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
590b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/
591b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{
592b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_STATUS  Status;
593b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINTN       NumBytes;
594b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
595b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  NumBytes = LbaLength;
596b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
597b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  WriteAddress -= (PcdGet32 (PcdFlashAreaBaseAddress));
598b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if (mInSmmMode == 0 ) { // !(EfiInManagementInterrupt ())) {
599b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    Status = mFvbModuleGlobal->SpiProtocol->Execute (
600b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            mFvbModuleGlobal->SpiProtocol,
601b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            SPI_OPCODE_ERASE_INDEX, // OpcodeIndex
602b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            0,                      // PrefixOpcodeIndex
603b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            FALSE,                  // DataCycle
604b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            TRUE,                   // Atomic
605b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            FALSE,                  // ShiftOut
606b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            WriteAddress,           // Address
607b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            0,                      // Data Number
608b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            NULL,
609b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            EnumSpiRegionBios       // SPI_REGION_TYPE
610b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            );
611b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  } else {
612b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    Status = mFvbModuleGlobal->SmmSpiProtocol->Execute (
613b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            mFvbModuleGlobal->SmmSpiProtocol,
614b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            SPI_OPCODE_ERASE_INDEX, // OpcodeIndex
615b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            0,                      // PrefixOpcodeIndex
616b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            FALSE,                  // DataCycle
617b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            TRUE,                   // Atomic
618b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            FALSE,                  // ShiftOut
619b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            WriteAddress,           // Address
620b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            0,                      // Data Number
621b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            NULL,
622b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            EnumSpiRegionBios       // SPI_REGION_TYPE
623b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            );
624b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
625b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
626b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  AsmWbinvd ();
627b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
628b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  return Status;
629b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney}
630b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
631b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS
632b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFvbWriteBlock (
633b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN UINTN                                Instance,
634b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN EFI_LBA                              Lba,
635b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN UINTN                                BlockOffset,
636b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN OUT UINTN                            *NumBytes,
637b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN UINT8                                *Buffer,
638b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN ESAL_FWB_GLOBAL                      *Global,
639b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN BOOLEAN                              Virtual
640b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  )
641b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++
642b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
643b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description:
644b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Writes specified number of bytes from the input buffer to the block
645b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
646b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments:
647b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Instance              - The FV instance to be written to
648b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Lba                   - The starting logical block index to write to
649b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  BlockOffset           - Offset into the block at which to begin writing
650b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  NumBytes              - Pointer that on input contains the total size of
651b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          the buffer. On output, it contains the total number
652b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          of bytes actually written
653b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Buffer                - Pointer to a caller allocated buffer that contains
654b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          the source for the write
655b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Global                - Pointer to ESAL_FWB_GLOBAL that contains all
656b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          instance data
657b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Virtual               - Whether CPU is in virtual or physical mode
658b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
659b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns:
660b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_SUCCESS           - The firmware volume was written successfully
661b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_BAD_BUFFER_SIZE   - Write attempted across a LBA boundary. On output,
662b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          NumBytes contains the total number of bytes
663b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          actually written
664b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_ACCESS_DENIED     - The firmware volume is in the WriteDisabled state
665b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_DEVICE_ERROR      - The block device is not functioning correctly and
666b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          could not be written
667b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_INVALID_PARAMETER - Instance not found, or NumBytes, Buffer are NULL
668b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
669b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/
670b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{
671b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_FVB_ATTRIBUTES_2  Attributes;
672b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINTN               LbaAddress;
673b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINTN               LbaWriteAddress;
674b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINTN               LbaLength;
675b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_FW_VOL_INSTANCE *FwhInstance;
676b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_STATUS          Status;
677b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_STATUS          ReturnStatus;
678b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
679b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  FwhInstance = NULL;
680b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
681b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
682b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Find the right instance of the FVB private data
683b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
684b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);
685b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  ASSERT_EFI_ERROR (Status);
686b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
687b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
688b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Writes are enabled in the init routine itself
689b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
690b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if (!FwhInstance->WriteEnabled) {
691b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    return EFI_ACCESS_DENIED;
692b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
693b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
694b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Check for invalid conditions
695b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
696b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if ((NumBytes == NULL) || (Buffer == NULL)) {
697b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    return EFI_INVALID_PARAMETER;
698b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
699b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
700b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if (*NumBytes == 0) {
701b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    return EFI_INVALID_PARAMETER;
702b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
703b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
704b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaWriteAddress, &LbaLength, NULL, Global, Virtual);
705b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if (EFI_ERROR (Status)) {
706b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    return Status;
707b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
708b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
709b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Check if the FV is write enabled
710b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
711b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual);
712b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
713b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if ((Attributes & EFI_FVB2_WRITE_STATUS) == 0) {
714b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    return EFI_ACCESS_DENIED;
715b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
716b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
717b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Perform boundary checks and adjust NumBytes
718b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
719b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if (BlockOffset > LbaLength) {
720b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    return EFI_INVALID_PARAMETER;
721b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
722b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
723b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if (LbaLength < (*NumBytes + BlockOffset)) {
724b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    *NumBytes = (UINT32) (LbaLength - BlockOffset);
725b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    Status    = EFI_BAD_BUFFER_SIZE;
726b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
727b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
728b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  ReturnStatus = FlashFdWrite (
729b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  LbaWriteAddress + BlockOffset,
730b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  LbaAddress,
731b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  NumBytes,
732b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  Buffer,
733b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  LbaLength
734b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  );
735b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if (EFI_ERROR (ReturnStatus)) {
736b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    return ReturnStatus;
737b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
738b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
739b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  return Status;
740b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney}
741b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
742b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS
743b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFvbEraseBlock (
744b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN UINTN                                Instance,
745b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN EFI_LBA                              Lba,
746b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN ESAL_FWB_GLOBAL                      *Global,
747b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN BOOLEAN                              Virtual
748b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  )
749b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++
750b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
751b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description:
752b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Erases and initializes a firmware volume block
753b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
754b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments:
755b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Instance              - The FV instance to be erased
756b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Lba                   - The logical block index to be erased
757b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Global                - Pointer to ESAL_FWB_GLOBAL that contains all
758b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          instance data
759b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Virtual               - Whether CPU is in virtual or physical mode
760b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
761b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns:
762b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_SUCCESS           - The erase request was successfully completed
763b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_ACCESS_DENIED     - The firmware volume is in the WriteDisabled state
764b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_DEVICE_ERROR      - The block device is not functioning correctly and
765b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          could not be written. Firmware device may have been
766b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          partially erased
767b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_INVALID_PARAMETER - Instance not found
768b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
769b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/
770b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{
771b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
772b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_FVB_ATTRIBUTES_2  Attributes;
773b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINTN               LbaAddress;
774b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINTN               LbaWriteAddress;
775b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_FW_VOL_INSTANCE *FwhInstance;
776b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINTN               LbaLength;
777b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_STATUS          Status;
778b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINTN               SectorNum;
779b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINTN               Index;
780b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
781b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  FwhInstance = NULL;
782b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
783b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
784b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Find the right instance of the FVB private data
785b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
786b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);
787b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  ASSERT_EFI_ERROR (Status);
788b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
789b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
790b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Writes are enabled in the init routine itself
791b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
792b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if (!FwhInstance->WriteEnabled) {
793b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    return EFI_ACCESS_DENIED;
794b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
795b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
796b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Check if the FV is write enabled
797b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
798b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual);
799b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
800b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if ((Attributes & EFI_FVB2_WRITE_STATUS) == 0) {
801b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    return EFI_ACCESS_DENIED;
802b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
803b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
804b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Get the starting address of the block for erase. For debug reasons,
805b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // LbaWriteAddress may not be the same as LbaAddress.
806b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
807b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaWriteAddress, &LbaLength, NULL, Global, Virtual);
808b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if (EFI_ERROR (Status)) {
809b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    return Status;
810b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
811b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
812b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  SectorNum = LbaLength / SPI_ERASE_SECTOR_SIZE;
813b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  for (Index = 0; Index < SectorNum; Index++){
814b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    Status = FlashFdErase (
815b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney               LbaWriteAddress + Index * SPI_ERASE_SECTOR_SIZE,
816b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney               LbaAddress,
817b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney               SPI_ERASE_SECTOR_SIZE
818b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney               );
819b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    if (Status != EFI_SUCCESS){
820b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      break;
821b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    }
822b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
823b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
824b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  return Status;
825b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney}
826b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
827b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS
828b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFvbEraseCustomBlockRange (
829b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN UINTN                                Instance,
830b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN EFI_LBA                              StartLba,
831b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN UINTN                                OffsetStartLba,
832b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN EFI_LBA                              LastLba,
833b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN UINTN                                OffsetLastLba,
834b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN ESAL_FWB_GLOBAL                      *Global,
835b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN BOOLEAN                              Virtual
836b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  )
837b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++
838b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
839b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description:
840b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Erases and initializes a specified range of a firmware volume
841b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
842b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments:
843b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Instance              - The FV instance to be erased
844b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  StartLba              - The starting logical block index to be erased
845b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  OffsetStartLba        - Offset into the starting block at which to
846b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          begin erasing
847b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  LastLba               - The last logical block index to be erased
848b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  OffsetStartLba        - Offset into the last block at which to end erasing
849b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Global                - Pointer to ESAL_FWB_GLOBAL that contains all
850b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          instance data
851b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Virtual               - Whether CPU is in virtual or physical mode
852b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
853b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns:
854b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_SUCCESS           - The firmware volume was erased successfully
855b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_ACCESS_DENIED     - The firmware volume is in the WriteDisabled state
856b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_DEVICE_ERROR      - The block device is not functioning correctly and
857b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          could not be written. Firmware device may have been
858b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          partially erased
859b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_INVALID_PARAMETER - Instance not found
860b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
861b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/
862b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{
863b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_LBA Index;
864b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINTN   LbaSize;
865b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINTN   ScratchLbaSizeData;
866b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
867b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
868b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // First LBA.
869b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
870b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  FvbGetLbaAddress (Instance, StartLba, NULL, NULL, &LbaSize, NULL, Global, Virtual);
871b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
872b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
873b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Use the scratch space as the intermediate buffer to transfer data
874b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Back up the first LBA in scratch space.
875b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
876b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  FvbReadBlock (Instance, StartLba, 0, &LbaSize, Global->FvbScratchSpace[Virtual], Global, Virtual);
877b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
878b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
879b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // erase now
880b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
881b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  FvbEraseBlock (Instance, StartLba, Global, Virtual);
882b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  ScratchLbaSizeData = OffsetStartLba;
883b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
884b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
885b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // write the data back to the first block
886b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
887b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if (ScratchLbaSizeData > 0) {
888b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    FvbWriteBlock (Instance, StartLba, 0, &ScratchLbaSizeData, Global->FvbScratchSpace[Virtual], Global, Virtual);
889b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
890b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
891b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Middle LBAs
892b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
893b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if (LastLba > (StartLba + 1)) {
894b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    for (Index = (StartLba + 1); Index <= (LastLba - 1); Index++) {
895b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      FvbEraseBlock (Instance, Index, Global, Virtual);
896b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    }
897b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
898b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
899b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Last LBAs, the same as first LBAs
900b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
901b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if (LastLba > StartLba) {
902b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    FvbGetLbaAddress (Instance, LastLba, NULL, NULL, &LbaSize, NULL, Global, Virtual);
903b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    FvbReadBlock (Instance, LastLba, 0, &LbaSize, Global->FvbScratchSpace[Virtual], Global, Virtual);
904b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    FvbEraseBlock (Instance, LastLba, Global, Virtual);
905b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
906b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
907b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  ScratchLbaSizeData = LbaSize - (OffsetStartLba + 1);
908b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
909b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  return FvbWriteBlock (
910b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney          Instance,
911b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney          LastLba,
912b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney          (OffsetLastLba + 1),
913b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney          &ScratchLbaSizeData,
914b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney          Global->FvbScratchSpace[Virtual],
915b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney          Global,
916b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney          Virtual
917b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney          );
918b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney}
919b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
920b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS
921b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFvbSetVolumeAttributes (
922b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN UINTN                                Instance,
923b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN OUT EFI_FVB_ATTRIBUTES_2               *Attributes,
924b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN ESAL_FWB_GLOBAL                      *Global,
925b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN BOOLEAN                              Virtual
926b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  )
927b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++
928b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
929b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description:
930b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Modifies the current settings of the firmware volume according to the
931b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  input parameter, and returns the new setting of the volume
932b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
933b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments:
934b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Instance              - The FV instance whose attributes is going to be
935b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          modified
936b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Attributes            - On input, it is a pointer to EFI_FVB_ATTRIBUTES_2
937b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          containing the desired firmware volume settings.
938b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          On successful return, it contains the new settings
939b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          of the firmware volume
940b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Global                - Pointer to ESAL_FWB_GLOBAL that contains all
941b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          instance data
942b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Virtual               - Whether CPU is in virtual or physical mode
943b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
944b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns:
945b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_SUCCESS           - Successfully returns
946b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_ACCESS_DENIED     - The volume setting is locked and cannot be modified
947b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_INVALID_PARAMETER - Instance not found, or The attributes requested are
948b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          in conflict with the capabilities as declared in the
949b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          firmware volume header
950b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
951b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/
952b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{
953b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_FW_VOL_INSTANCE *FwhInstance;
954b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_FVB_ATTRIBUTES_2  OldAttributes;
955b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_FVB_ATTRIBUTES_2  *AttribPtr;
956b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINT32              Capabilities;
957b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINT32              OldStatus;
958b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINT32              NewStatus;
959b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_STATUS          Status;
960b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
961b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  FwhInstance = NULL;
962b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
963b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
964b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Find the right instance of the FVB private data
965b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
966b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);
967b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  ASSERT_EFI_ERROR (Status);
968b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
969b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  AttribPtr     = (EFI_FVB_ATTRIBUTES_2 *) &(FwhInstance->VolumeHeader.Attributes);
970b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  OldAttributes = *AttribPtr;
971b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Capabilities  = OldAttributes & EFI_FVB2_CAPABILITIES;
972b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  OldStatus     = OldAttributes & EFI_FVB2_STATUS;
973b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  NewStatus     = *Attributes & EFI_FVB2_STATUS;
974b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
975b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
976b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // If firmware volume is locked, no status bit can be updated
977b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
978b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if (OldAttributes & EFI_FVB2_LOCK_STATUS) {
979b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    if (OldStatus ^ NewStatus) {
980b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      return EFI_ACCESS_DENIED;
981b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    }
982b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
983b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
984b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Test read disable
985b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
986b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if ((Capabilities & EFI_FVB2_READ_DISABLED_CAP) == 0) {
987b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    if ((NewStatus & EFI_FVB2_READ_STATUS) == 0) {
988b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      return EFI_INVALID_PARAMETER;
989b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    }
990b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
991b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
992b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Test read enable
993b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
994b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if ((Capabilities & EFI_FVB2_READ_ENABLED_CAP) == 0) {
995b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    if (NewStatus & EFI_FVB2_READ_STATUS) {
996b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      return EFI_INVALID_PARAMETER;
997b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    }
998b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
999b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
1000b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Test write disable
1001b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
1002b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if ((Capabilities & EFI_FVB2_WRITE_DISABLED_CAP) == 0) {
1003b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    if ((NewStatus & EFI_FVB2_WRITE_STATUS) == 0) {
1004b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      return EFI_INVALID_PARAMETER;
1005b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    }
1006b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
1007b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
1008b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Test write enable
1009b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
1010b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if ((Capabilities & EFI_FVB2_WRITE_ENABLED_CAP) == 0) {
1011b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    if (NewStatus & EFI_FVB2_WRITE_STATUS) {
1012b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      return EFI_INVALID_PARAMETER;
1013b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    }
1014b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
1015b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
1016b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Test lock
1017b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
1018b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if ((Capabilities & EFI_FVB2_LOCK_CAP) == 0) {
1019b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    if (NewStatus & EFI_FVB2_LOCK_STATUS) {
1020b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      return EFI_INVALID_PARAMETER;
1021b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    }
1022b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
1023b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1024b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  *AttribPtr  = (*AttribPtr) & (0xFFFFFFFF & (~EFI_FVB2_STATUS));
1025b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  *AttribPtr  = (*AttribPtr) | NewStatus;
1026b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  *Attributes = *AttribPtr;
1027b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1028b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  return EFI_SUCCESS;
1029b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney}
1030b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney//
1031b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney// FVB protocol APIs
1032b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney//
1033b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS
1034b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFIAPI
1035b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFvbProtocolGetPhysicalAddress (
1036b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL       *This,
1037b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  OUT EFI_PHYSICAL_ADDRESS                          *Address
1038b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  )
1039b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++
1040b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1041b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description:
1042b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1043b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Retrieves the physical address of the device.
1044b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1045b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments:
1046b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1047b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  This                  - Calling context
1048b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Address               - Output buffer containing the address.
1049b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1050b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns:
1051b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1052b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns:
1053b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_SUCCESS           - Successfully returns
1054b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1055b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/
1056b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{
1057b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
1058b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1059b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  FvbDevice = FVB_DEVICE_FROM_THIS (This);
1060b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1061b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  return FvbGetPhysicalAddress (FvbDevice->Instance, Address, mFvbModuleGlobal, EfiGoneVirtual ());
1062b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney}
1063b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1064b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS
1065b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFvbProtocolGetBlockSize (
1066b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL       *This,
1067b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN  EFI_LBA                                       Lba,
1068b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  OUT UINTN                                         *BlockSize,
1069b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  OUT UINTN                                         *NumOfBlocks
1070b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  )
1071b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++
1072b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1073b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description:
1074b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Retrieve the size of a logical block
1075b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1076b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments:
1077b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  This                  - Calling context
1078b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Lba                   - Indicates which block to return the size for.
1079b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  BlockSize             - A pointer to a caller allocated UINTN in which
1080b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          the size of the block is returned
1081b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  NumOfBlocks           - a pointer to a caller allocated UINTN in which the
1082b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          number of consecutive blocks starting with Lba is
1083b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          returned. All blocks in this range have a size of
1084b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          BlockSize
1085b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1086b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns:
1087b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_SUCCESS           - The firmware volume was read successfully and
1088b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          contents are in Buffer
1089b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1090b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/
1091b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{
1092b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
1093b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1094b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  FvbDevice = FVB_DEVICE_FROM_THIS (This);
1095b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1096b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  return FvbGetLbaAddress (
1097b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney          FvbDevice->Instance,
1098b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney          Lba,
1099b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney          NULL,
1100b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney          NULL,
1101b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney          BlockSize,
1102b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney          NumOfBlocks,
1103b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney          mFvbModuleGlobal,
1104b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney          EfiGoneVirtual ()
1105b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney          );
1106b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney}
1107b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1108b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS
1109b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFIAPI
1110b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFvbProtocolGetAttributes (
1111b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL       *This,
1112b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  OUT EFI_FVB_ATTRIBUTES_2                            *Attributes
1113b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  )
1114b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++
1115b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1116b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description:
1117b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    Retrieves Volume attributes.  No polarity translations are done.
1118b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1119b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments:
1120b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    This                - Calling context
1121b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    Attributes          - output buffer which contains attributes
1122b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1123b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns:
1124b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_SUCCESS           - Successfully returns
1125b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1126b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/
1127b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{
1128b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
1129b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1130b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  FvbDevice = FVB_DEVICE_FROM_THIS (This);
1131b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1132b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  return FvbGetVolumeAttributes (FvbDevice->Instance, Attributes, mFvbModuleGlobal, EfiGoneVirtual ());
1133b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney}
1134b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1135b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS
1136b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFIAPI
1137b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFvbProtocolSetAttributes (
1138b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL       *This,
1139b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN OUT EFI_FVB_ATTRIBUTES_2                         *Attributes
1140b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  )
1141b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++
1142b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1143b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description:
1144b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Sets Volume attributes. No polarity translations are done.
1145b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1146b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments:
1147b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  This                  - Calling context
1148b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Attributes            - output buffer which contains attributes
1149b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1150b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns:
1151b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_SUCCESS           - Successfully returns
1152b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1153b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/
1154b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{
1155b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
1156b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1157b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  FvbDevice = FVB_DEVICE_FROM_THIS (This);
1158b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1159b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  return FvbSetVolumeAttributes (FvbDevice->Instance, Attributes, mFvbModuleGlobal, EfiGoneVirtual ());
1160b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney}
1161b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1162b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS
1163b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFIAPI
1164b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFvbProtocolEraseBlocks (
1165b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL       *This,
1166b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  ...
1167b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  )
1168b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++
1169b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1170b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description:
1171b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1172b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  The EraseBlock() function erases one or more blocks as denoted by the
1173b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  variable argument list. The entire parameter list of blocks must be verified
1174b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  prior to erasing any blocks.  If a block is requested that does not exist
1175b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  within the associated firmware volume (it has a larger index than the last
1176b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  block of the firmware volume), the EraseBlock() function must return
1177b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_INVALID_PARAMETER without modifying the contents of the firmware volume.
1178b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1179b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments:
1180b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  This                  - Calling context
1181b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  ...                   - Starting LBA followed by Number of Lba to erase.
1182b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          a -1 to terminate the list.
1183b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1184b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns:
1185b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_SUCCESS           - The erase request was successfully completed
1186b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_ACCESS_DENIED     - The firmware volume is in the WriteDisabled state
1187b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_DEVICE_ERROR      - The block device is not functioning correctly and
1188b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          could not be written. Firmware device may have been
1189b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          partially erased
1190b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1191b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/
1192b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{
1193b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
1194b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_FW_VOL_INSTANCE     *FwhInstance;
1195b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINTN                   NumOfBlocks;
1196b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  VA_LIST                 args;
1197b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_LBA                 StartingLba;
1198b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINTN                   NumOfLba;
1199b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_STATUS              Status;
1200b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1201b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  FwhInstance = NULL;
1202b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  FvbDevice = FVB_DEVICE_FROM_THIS (This);
1203b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1204b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Status    = GetFvbInstance (FvbDevice->Instance, mFvbModuleGlobal, &FwhInstance, EfiGoneVirtual ());
1205b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  ASSERT_EFI_ERROR (Status);
1206b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1207b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  NumOfBlocks = FwhInstance->NumOfBlocks;
1208b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1209b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  VA_START (args, This);
1210b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1211b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  do {
1212b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    StartingLba = VA_ARG (args, EFI_LBA);
1213b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
1214b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      break;
1215b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    }
1216b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1217b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    NumOfLba = VA_ARG (args, UINT32);
1218b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1219b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //
1220b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    // Check input parameters
1221b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //
1222b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    if (NumOfLba == 0) {
1223b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      VA_END (args);
1224b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      return EFI_INVALID_PARAMETER;
1225b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    }
1226b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1227b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    if ((StartingLba + NumOfLba) > NumOfBlocks) {
1228b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      return EFI_INVALID_PARAMETER;
1229b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    }
1230b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  } while (TRUE);
1231b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1232b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  VA_END (args);
1233b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1234b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  VA_START (args, This);
1235b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  do {
1236b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    StartingLba = VA_ARG (args, EFI_LBA);
1237b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
1238b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      break;
1239b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    }
1240b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1241b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    NumOfLba = VA_ARG (args, UINT32);
1242b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1243b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    while (NumOfLba > 0) {
1244b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      Status = FvbEraseBlock (FvbDevice->Instance, StartingLba, mFvbModuleGlobal, EfiGoneVirtual ());
1245b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      if (EFI_ERROR (Status)) {
1246b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        VA_END (args);
1247b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        return Status;
1248b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      }
1249b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1250b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      StartingLba++;
1251b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      NumOfLba--;
1252b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    }
1253b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1254b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  } while (TRUE);
1255b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1256b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  VA_END (args);
1257b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1258b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  return EFI_SUCCESS;
1259b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney}
1260b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1261b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS
1262b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFIAPI
1263b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFvbProtocolWrite (
1264b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL       *This,
1265b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN EFI_LBA                                        Lba,
1266b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN UINTN                                          Offset,
1267b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN OUT UINTN                                      *NumBytes,
1268b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN UINT8                                          *Buffer
1269b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  )
1270b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++
1271b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1272b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description:
1273b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1274b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Writes data beginning at Lba:Offset from FV. The write terminates either
1275b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  when *NumBytes of data have been written, or when a block boundary is
1276b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  reached.  *NumBytes is updated to reflect the actual number of bytes
1277b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  written. The write opertion does not include erase. This routine will
1278b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  attempt to write only the specified bytes. If the writes do not stick,
1279b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  it will return an error.
1280b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1281b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments:
1282b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  This                  - Calling context
1283b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Lba                   - Block in which to begin write
1284b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Offset                - Offset in the block at which to begin write
1285b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  NumBytes              - On input, indicates the requested write size. On
1286b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          output, indicates the actual number of bytes written
1287b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Buffer                - Buffer containing source data for the write.
1288b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1289b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns:
1290b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_SUCCESS           - The firmware volume was written successfully
1291b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_BAD_BUFFER_SIZE   - Write attempted across a LBA boundary. On output,
1292b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          NumBytes contains the total number of bytes
1293b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          actually written
1294b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_ACCESS_DENIED     - The firmware volume is in the WriteDisabled state
1295b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_DEVICE_ERROR      - The block device is not functioning correctly and
1296b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          could not be written
1297b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL
1298b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1299b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/
1300b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{
1301b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1302b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
1303b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1304b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  FvbDevice = FVB_DEVICE_FROM_THIS (This);
1305b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1306b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  return FvbWriteBlock (FvbDevice->Instance, Lba, Offset, NumBytes, Buffer, mFvbModuleGlobal, EfiGoneVirtual ());
1307b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney}
1308b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1309b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS
1310b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFIAPI
1311b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFvbProtocolRead (
1312b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL       *This,
1313b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN EFI_LBA                                        Lba,
1314b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN UINTN                                          Offset,
1315b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN OUT UINTN                                      *NumBytes,
1316b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN UINT8                                          *Buffer
1317b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  )
1318b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++
1319b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1320b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description:
1321b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1322b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Reads data beginning at Lba:Offset from FV. The Read terminates either
1323b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  when *NumBytes of data have been read, or when a block boundary is
1324b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  reached.  *NumBytes is updated to reflect the actual number of bytes
1325b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  written. The write opertion does not include erase. This routine will
1326b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  attempt to write only the specified bytes. If the writes do not stick,
1327b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  it will return an error.
1328b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1329b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments:
1330b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  This                  - Calling context
1331b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Lba                   - Block in which to begin Read
1332b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Offset                - Offset in the block at which to begin Read
1333b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  NumBytes              - On input, indicates the requested write size. On
1334b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          output, indicates the actual number of bytes Read
1335b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Buffer                - Buffer containing source data for the Read.
1336b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1337b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns:
1338b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_SUCCESS           - The firmware volume was read successfully and
1339b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          contents are in Buffer
1340b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_BAD_BUFFER_SIZE   - Read attempted across a LBA boundary. On output,
1341b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          NumBytes contains the total number of bytes returned
1342b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          in Buffer
1343b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_ACCESS_DENIED     - The firmware volume is in the ReadDisabled state
1344b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_DEVICE_ERROR      - The block device is not functioning correctly and
1345b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                          could not be read
1346b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL
1347b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1348b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/
1349b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{
1350b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1351b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
1352b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_STATUS              Status;
1353b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1354b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  FvbDevice = FVB_DEVICE_FROM_THIS (This);
1355b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Status    = FvbReadBlock (FvbDevice->Instance, Lba, Offset, NumBytes, Buffer, mFvbModuleGlobal, EfiGoneVirtual ());
1356b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1357b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  return Status;
1358b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney}
1359b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1360b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS
1361b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyValidateFvHeader (
1362b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_FIRMWARE_VOLUME_HEADER            *FwVolHeader
1363b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  )
1364b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++
1365b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1366b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description:
1367b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Check the integrity of firmware volume header
1368b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1369b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments:
1370b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  FwVolHeader           - A pointer to a firmware volume header
1371b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1372b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns:
1373b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_SUCCESS           - The firmware volume is consistent
1374b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_NOT_FOUND         - The firmware volume has corrupted. So it is not an FV
1375b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1376b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/
1377b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{
1378b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINT16  *Ptr;
1379b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINT16  HeaderLength;
1380b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINT16  Checksum;
1381b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1382b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
1383b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Verify the header revision, header signature, length
1384b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Length of FvBlock cannot be 2**64-1
1385b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // HeaderLength cannot be an odd number
1386b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
1387b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  #ifndef R864_BUILD
1388b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if (((FwVolHeader->Revision != EFI_FVH_REVISION) && (FwVolHeader->Revision != EFI_FVH_REVISION)) ||
1389b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  #else
1390b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if ((FwVolHeader->Revision != EFI_FVH_REVISION) ||
1391b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  #endif
1392b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      (FwVolHeader->Signature != EFI_FVH_SIGNATURE) ||
1393b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      (FwVolHeader->FvLength == ((UINTN) -1)) ||
1394b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      ((FwVolHeader->HeaderLength & 0x01) != 0)
1395b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      ) {
1396b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    return EFI_NOT_FOUND;
1397b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
1398b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
1399b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Verify the header checksum
1400b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
1401b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  HeaderLength  = (UINT16) (FwVolHeader->HeaderLength / 2);
1402b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Ptr           = (UINT16 *) FwVolHeader;
1403b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Checksum      = 0;
1404b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  while (HeaderLength > 0) {
1405b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    Checksum = Checksum + (*Ptr);
1406b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    Ptr++;
1407b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    HeaderLength--;
1408b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
1409b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1410b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if (Checksum != 0) {
1411b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    return EFI_NOT_FOUND;
1412b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
1413b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1414b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  return EFI_SUCCESS;
1415b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney}
1416b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1417b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS
1418b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyGetFvbHeader (
1419b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  VOID                                **HobList,
1420b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  OUT EFI_FIRMWARE_VOLUME_HEADER      **FwVolHeader,
1421b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  OUT EFI_PHYSICAL_ADDRESS            *BaseAddress,
1422b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  OUT BOOLEAN                         *WriteBack
1423b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  )
1424b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{
1425b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_STATUS                Status;
1426b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1427b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Status        = EFI_SUCCESS;
1428b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  *WriteBack    = FALSE;
1429b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1430b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if (*FwVolHeader == NULL) {
1431b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    *BaseAddress = PcdGet32 (PcdFlashFvRecoveryBase);
1432b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  } else if (*FwVolHeader == (VOID *)(UINTN)PcdGet32 (PcdFlashFvRecoveryBase)) {
1433b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    *BaseAddress = PcdGet32 (PcdFlashFvMainBase);
1434b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  } else if (*FwVolHeader == (VOID *)(UINTN)PcdGet32 (PcdFlashFvMainBase)) {
1435b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    *BaseAddress = PcdGet32 (PcdFlashNvStorageVariableBase);
1436b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  } else {
1437b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    return EFI_NOT_FOUND;
1438b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
1439b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1440b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  DEBUG((EFI_D_INFO, "Fvb base : %08x\n",*BaseAddress));
1441b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1442b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  *FwVolHeader  = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) (*BaseAddress);
1443b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Status        = ValidateFvHeader (*FwVolHeader);
1444b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if (EFI_ERROR (Status)) {
1445b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //
1446b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    // Get FvbInfo
1447b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //
1448b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    *WriteBack  = TRUE;
1449b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1450b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    Status      = GetFvbInfo (*BaseAddress, FwVolHeader);
1451b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    DEBUG(( DEBUG_ERROR, "Through GetFvbInfo: %08x!\n",*BaseAddress));
1452b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1453b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    ASSERT_EFI_ERROR (Status);
1454b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
1455b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1456b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  return EFI_SUCCESS;
1457b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney}
1458b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1459b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1460b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS
1461b303605e1b7e113b4311daf161c6c3289350447bMichael KinneySmmSpiInit (
1462b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  VOID
1463b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  )
1464b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{
1465b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINT8       SpiStatus;
1466b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINT8       FlashIndex;
1467b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINT8       FlashID[3];
1468b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_STATUS  Status;
1469b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1470b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
1471b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Obtain a handle for ICH SPI Protocol
1472b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
1473b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  ASSERT(mSmst != NULL);
1474b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if (mFvbModuleGlobal->SmmSpiProtocol == NULL){
1475b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    Status = mSmst->SmmLocateProtocol (&gEfiSmmSpiProtocolGuid, NULL, (VOID **) &mFvbModuleGlobal->SmmSpiProtocol);
1476b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    ASSERT_EFI_ERROR(Status);
1477b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
1478b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
1479b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // attempt to identify flash part and initialize spi table
1480b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
1481b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  for (FlashIndex = 0; FlashIndex < EnumSpiFlashMax; FlashIndex++) {
1482b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    Status = mFvbModuleGlobal->SmmSpiProtocol->Init (
1483b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                                mFvbModuleGlobal->SmmSpiProtocol,
1484b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                                &(mSpiInitTable[FlashIndex])
1485b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                                );
1486b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    if (!EFI_ERROR (Status)) {
1487b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      //
1488b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      // read vendor/device IDs to check if flash device is supported
1489b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      //
1490b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      Status = mFvbModuleGlobal->SmmSpiProtocol->Execute (
1491b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                                  mFvbModuleGlobal->SmmSpiProtocol,
1492b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                                  SPI_OPCODE_JEDEC_ID_INDEX,
1493b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                                  SPI_WREN_INDEX,
1494b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                                  TRUE,
1495b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                                  FALSE,
1496b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                                  FALSE,
1497b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                                  0,
1498b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                                  3,
1499b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                                  FlashID,
1500b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                                  EnumSpiRegionAll
1501b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                                  );
1502b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      if (!EFI_ERROR (Status)) {
1503b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        if (((FlashID[0] == mSpiInitTable[FlashIndex].VendorId) &&
1504b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney               (FlashID[2] == mSpiInitTable[FlashIndex].DeviceId1)) ||
1505b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney              ((FlashID[0] == SPI_AT26DF321_ID1) &&
1506b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney               (FlashID[0] == mSpiInitTable[FlashIndex].VendorId) &&
1507b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney               (FlashID[1] == mSpiInitTable[FlashIndex].DeviceId0))) {
1508b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney          //
1509b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney          // Supported SPI device found
1510b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney          //
1511b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney          DEBUG (
1512b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney              ((EFI_D_INFO),
1513b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney              "Smm Mode: Supported SPI Flash device found, Vendor Id: 0x%02x, Device ID: 0x%02x%02x!\n",
1514b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney              FlashID[0],
1515b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney              FlashID[1],
1516b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney              FlashID[2])
1517b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney              );
1518b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney          break;
1519b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        }
1520b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      }
1521b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    }
1522b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
1523b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1524b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if (FlashIndex >= EnumSpiFlashMax) {
1525b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    Status = EFI_UNSUPPORTED;
1526b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    DEBUG (
1527b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        (EFI_D_ERROR,
1528b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        "ERROR - Unknown SPI Flash Device, Vendor Id: 0x%02x, Device ID: 0x%02x%02x!\n",
1529b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        FlashID[0],
1530b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        FlashID[1],
1531b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        FlashID[2])
1532b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        );
1533b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    ASSERT_EFI_ERROR (Status);
1534b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
1535b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1536b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  SpiStatus = 0;
1537b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Status = mFvbModuleGlobal->SmmSpiProtocol->Execute (
1538b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            mFvbModuleGlobal->SmmSpiProtocol,
1539b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            SPI_OPCODE_WRITE_S_INDEX, // OpcodeIndex
1540b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            1,                        // PrefixOpcodeIndex
1541b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            TRUE,                     // DataCycle
1542b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            TRUE,                     // Atomic
1543b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            TRUE,                     // ShiftOut
1544b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            0,                        // Address
1545b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            1,                        // Data Number
1546b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            &SpiStatus,
1547b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            EnumSpiRegionAll          // SPI_REGION_TYPE
1548b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                            );
1549b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  return Status;
1550b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney}
1551b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1552b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS
1553b303605e1b7e113b4311daf161c6c3289350447bMichael KinneySmmSpiNotificationFunction (
1554b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN CONST EFI_GUID  *Protocol,
1555b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN VOID            *Interface,
1556b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN EFI_HANDLE      Handle
1557b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  )
1558b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{
1559b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  return SmmSpiInit();
1560b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney}
1561b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1562b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1563b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyVOID
1564b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFIAPI
1565b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyGetFullDriverPath (
1566b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN  EFI_HANDLE                  ImageHandle,
1567b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN  EFI_SYSTEM_TABLE            *SystemTable,
1568b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  OUT EFI_DEVICE_PATH_PROTOCOL    **CompleteFilePath
1569b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  )
1570b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++
1571b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1572b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description:
1573b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1574b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Function is used to get the full device path for this driver.
1575b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1576b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments:
1577b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1578b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  ImageHandle        - The loaded image handle of this driver.
1579b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  SystemTable        - The pointer of system table.
1580b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  CompleteFilePath   - The pointer of returned full file path
1581b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1582b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns:
1583b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1584b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  none
1585b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1586b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/
1587b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{
1588b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_STATUS                Status;
1589b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
1590b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_DEVICE_PATH_PROTOCOL  *ImageDevicePath;
1591b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1592b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1593b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Status = gBS->HandleProtocol (
1594b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  ImageHandle,
1595b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  &gEfiLoadedImageProtocolGuid,
1596b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  (VOID **) &LoadedImage
1597b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  );
1598b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  ASSERT_EFI_ERROR (Status);
1599b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1600b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Status = gBS->HandleProtocol (
1601b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  LoadedImage->DeviceHandle,
1602b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  &gEfiDevicePathProtocolGuid,
1603b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  (VOID *) &ImageDevicePath
1604b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  );
1605b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  ASSERT_EFI_ERROR (Status);
1606b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1607b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  *CompleteFilePath = AppendDevicePath (
1608b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                        ImageDevicePath,
1609b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                        LoadedImage->FilePath
1610b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                        );
1611b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1612b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  return ;
1613b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney}
1614b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1615b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1616b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1617b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS
1618b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyFvbInitialize (
1619b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN EFI_HANDLE         ImageHandle,
1620b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN EFI_SYSTEM_TABLE   *SystemTable
1621b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  )
1622b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++
1623b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1624b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyRoutine Description:
1625b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  This function does common initialization for FVB services
1626b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1627b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyArguments:
1628b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1629b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyReturns:
1630b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1631b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/
1632b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{
1633b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_STATUS                          Status;
1634b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_FW_VOL_INSTANCE                 *FwhInstance;
1635b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_FIRMWARE_VOLUME_HEADER          *FwVolHeader;
1636b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_FIRMWARE_VOLUME_HEADER          *TempFwVolHeader;
1637b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  VOID                                *HobList;
1638b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  VOID                                *FirmwareVolumeHobList;
1639b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINT32                              BufferSize;
1640b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_FV_BLOCK_MAP_ENTRY              *PtrBlockMapEntry;
1641b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINTN                               LbaAddress;
1642b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  BOOLEAN                             WriteEnabled;
1643b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  BOOLEAN                             WriteLocked;
1644b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_HANDLE                          FwbHandle;
1645b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_FW_VOL_BLOCK_DEVICE             *FvbDevice;
1646b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *OldFwbInterface;
1647b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_DEVICE_PATH_PROTOCOL            *FwbDevicePath;
1648b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_DEVICE_PATH_PROTOCOL            *TempFwbDevicePath;
1649b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINT32                              MaxLbaSize;
1650b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_PHYSICAL_ADDRESS                BaseAddress;
1651b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  BOOLEAN                             WriteBack;
1652b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINTN                               NumOfBlocks;
1653b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINTN                               HeaderLength;
1654b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINT8                               SpiStatus;
1655b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINT8                               FlashIndex;
1656b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINT8                               FlashID[3];
1657b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_DEVICE_PATH_PROTOCOL            *CompleteFilePath;
1658b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINT8                               PrefixOpcodeIndex;
1659b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  BOOLEAN                             InSmm;
1660b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_SMM_BASE2_PROTOCOL              *mSmmBase2;
1661b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_HANDLE                          Handle;
1662b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1663b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  VOID                                *Registration;
1664b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_EVENT                           Event;
1665b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1666b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  CompleteFilePath = NULL;
1667b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  GetFullDriverPath (ImageHandle, SystemTable, &CompleteFilePath);
1668b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1669b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = EfiGetSystemConfigurationTable (&gEfiHobListGuid, &HobList);
1670b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1671b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
1672b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // No FV HOBs found
1673b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
1674b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  ASSERT_EFI_ERROR (Status);
1675b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1676b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1677b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
1678b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Allocate runtime services data for global variable, which contains
1679b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // the private data of all firmware volume block instances
1680b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
1681b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  mFvbModuleGlobal = (ESAL_FWB_GLOBAL *)AllocateRuntimeZeroPool(sizeof (ESAL_FWB_GLOBAL  ));
1682b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  ASSERT(mFvbModuleGlobal);
1683b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  mSmmBase2 = NULL;
1684b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Status = gBS->LocateProtocol (
1685b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  &gEfiSmmBase2ProtocolGuid,
1686b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  NULL,
1687b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  (VOID **) &mSmmBase2
1688b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  );
1689b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1690b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if (mSmmBase2 == NULL) {
1691b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    InSmm = FALSE;
1692b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  } else {
1693b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    mSmmBase2->InSmm (mSmmBase2, &InSmm);
1694b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    mSmmBase2->GetSmstLocation (mSmmBase2, &mSmst);
1695b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1696b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
1697b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1698b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if (!InSmm) {
1699b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    mInSmmMode = 0;
1700b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //
1701b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    // Obtain a handle for ICH SPI Protocol
1702b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //
1703b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    Status = gBS->LocateProtocol (&gEfiSpiProtocolGuid, NULL, (VOID **) &mFvbModuleGlobal->SpiProtocol);
1704b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    ASSERT_EFI_ERROR (Status);
1705b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1706b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //
1707b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    // attempt to identify flash part and initialize spi table
1708b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //
1709b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    for (FlashIndex = 0; FlashIndex < EnumSpiFlashMax; FlashIndex++) {
1710b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      Status = mFvbModuleGlobal->SpiProtocol->Init (
1711b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                                mFvbModuleGlobal->SpiProtocol,
1712b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                                &(mSpiInitTable[FlashIndex])
1713b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                                );
1714b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      if (!EFI_ERROR (Status)) {
1715b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        //
1716b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        // read vendor/device IDs to check if flash device is supported
1717b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        //
1718b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        Status = mFvbModuleGlobal->SpiProtocol->Execute (
1719b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                                  mFvbModuleGlobal->SpiProtocol,
1720b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                                  SPI_OPCODE_JEDEC_ID_INDEX,
1721b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                                  SPI_WREN_INDEX,
1722b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                                  TRUE,
1723b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                                  FALSE,
1724b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                                  FALSE,
1725b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                                  0,
1726b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                                  3,
1727b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                                  FlashID,
1728b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                                  EnumSpiRegionAll
1729b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                                  );
1730b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        if (!EFI_ERROR (Status)) {
1731b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney          if (((FlashID[0] == mSpiInitTable[FlashIndex].VendorId) &&
1732b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney               (FlashID[2] == mSpiInitTable[FlashIndex].DeviceId1)) ||
1733b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney              ((FlashID[0] == SPI_AT26DF321_ID1) &&
1734b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney               (FlashID[0] == mSpiInitTable[FlashIndex].VendorId) &&
1735b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney               (FlashID[1] == mSpiInitTable[FlashIndex].DeviceId0))) {
1736b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney            //
1737b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney            // Supported SPI device found
1738b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney            //
1739b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney            DEBUG (
1740b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney              ((EFI_D_INFO),
1741b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney              "Supported SPI Flash device found, Vendor Id: 0x%02x, Device ID: 0x%02x%02x!\n",
1742b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney              FlashID[0],
1743b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney              FlashID[1],
1744b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney              FlashID[2])
1745b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney              );
1746b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1747b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney            PublishFlashDeviceInfo (&mSpiInitTable[FlashIndex]);
1748b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney            break;
1749b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney          }
1750b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        }
1751b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      }
1752b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    }
1753b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1754b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    if (FlashIndex >= EnumSpiFlashMax) {
1755b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      Status = EFI_UNSUPPORTED;
1756b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      DEBUG (
1757b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        (DEBUG_ERROR,
1758b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        "ERROR - Unknown SPI Flash Device, Vendor Id: 0x%02x, Device ID: 0x%02x%02x!\n",
1759b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        FlashID[0],
1760b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        FlashID[1],
1761b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        FlashID[2])
1762b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        );
1763b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      ASSERT_EFI_ERROR (Status);
1764b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    }
1765b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1766b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //
1767b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    // Unlock all regions by writing to status register
1768b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    // This could be SPI device specific, need to follow the datasheet
1769b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    // To write to Write Status Register the Spi PrefixOpcode needs to be:
1770b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //   0 for Atmel parts
1771b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //   0 for Intel parts
1772b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //   0 for Macronix parts
1773b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //   0 for Winbond parts
1774b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //   1 for SST parts
1775b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    SpiStatus = 0;
1776b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    if (FlashID[0] == SPI_SST25VF016B_ID1) {
1777b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      PrefixOpcodeIndex = 1;
1778b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    } else {
1779b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      PrefixOpcodeIndex = 0;
1780b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    }
1781b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    Status = mFvbModuleGlobal->SpiProtocol->Execute (
1782b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                              mFvbModuleGlobal->SpiProtocol,
1783b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                              SPI_OPCODE_WRITE_S_INDEX, // OpcodeIndex
1784b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                              PrefixOpcodeIndex,        // PrefixOpcodeIndex
1785b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                              TRUE,                     // DataCycle
1786b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                              TRUE,                     // Atomic
1787b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                              TRUE,                     // ShiftOut
1788b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                              0,                        // Address
1789b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                              1,                        // Data Number
1790b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                              &SpiStatus,
1791b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                              EnumSpiRegionAll          // SPI_REGION_TYPE
1792b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                                              );
1793b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1794b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1795b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  } else  {
1796b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    mInSmmMode = 1;
1797b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1798b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    Status = mSmst->SmmLocateProtocol (&gEfiSmmSpiProtocolGuid, NULL, (VOID **) &mFvbModuleGlobal->SmmSpiProtocol);
1799b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    if (EFI_ERROR(Status)) {
1800b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      Registration = NULL;
1801b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      Status = mSmst->SmmRegisterProtocolNotify (
1802b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                   &gEfiSmmSpiProtocolGuid,
1803b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                   SmmSpiNotificationFunction,
1804b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                   &Registration
1805b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                   );
1806b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    } else  {
1807b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      Status  = SmmSpiInit();
1808b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    }
1809b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1810b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
1811b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1812b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
1813b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Calculate the total size for all firmware volume block instances
1814b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
1815b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  BufferSize            = 0;
1816b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  FirmwareVolumeHobList = HobList;
1817b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  FwVolHeader           = NULL;
1818b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  do {
1819b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    Status = GetFvbHeader (&FirmwareVolumeHobList, &FwVolHeader, &BaseAddress, &WriteBack);
1820b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    if (EFI_ERROR (Status)) {
1821b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      break;
1822b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    }
1823b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1824b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    if (FwVolHeader) {
1825b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      BufferSize += (FwVolHeader->HeaderLength + sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER));
1826b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    }
1827b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  } while (TRUE);
1828b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1829b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
1830b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Only need to allocate once. There is only one copy of physical memory for
1831b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // the private data of each FV instance. But in virtual mode or in physical
1832b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // mode, the address of the the physical memory may be different.
1833b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
1834b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  mFvbModuleGlobal->FvInstance[FVB_PHYSICAL] = (EFI_FW_VOL_INSTANCE *) AllocateRuntimeZeroPool (BufferSize);
1835b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  ASSERT(mFvbModuleGlobal->FvInstance[FVB_PHYSICAL]);
1836b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
1837b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Make a virtual copy of the FvInstance pointer.
1838b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
1839b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  FwhInstance = mFvbModuleGlobal->FvInstance[FVB_PHYSICAL];
1840b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  mFvbModuleGlobal->FvInstance[FVB_VIRTUAL] = FwhInstance;
1841b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1842b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  mFvbModuleGlobal->NumFv                   = 0;
1843b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  FirmwareVolumeHobList                     = HobList;
1844b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  TempFwVolHeader                           = NULL;
1845b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1846b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  MaxLbaSize = 0;
1847b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1848b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
1849b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Fill in the private data of each firmware volume block instance
1850b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
1851b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Foreach Fv HOB in the FirmwareVolumeHobList, loop
1852b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
1853b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  do {
1854b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    Status = GetFvbHeader (&FirmwareVolumeHobList, &TempFwVolHeader, &BaseAddress, &WriteBack);
1855b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    if (EFI_ERROR (Status)) {
1856b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      break;
1857b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    }
1858b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    FwVolHeader = TempFwVolHeader;
1859b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1860b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    if (!FwVolHeader) {
1861b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      continue;
1862b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    }
1863b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1864b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1865b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    CopyMem ((UINTN *) &(FwhInstance->VolumeHeader), (UINTN *) FwVolHeader, FwVolHeader->HeaderLength);
1866b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    FwVolHeader                       = &(FwhInstance->VolumeHeader);
1867b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1868b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    FwhInstance->FvBase[FVB_PHYSICAL] = (UINTN) BaseAddress;
1869b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    FwhInstance->FvBase[FVB_VIRTUAL]  = (UINTN) BaseAddress;
1870b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1871b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //
1872b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    // FwhInstance->FvWriteBase may not be the same as FwhInstance->FvBase
1873b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //
1874b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    FwhInstance->FvWriteBase[FVB_PHYSICAL]  = (UINTN) BaseAddress;
1875b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    WriteEnabled = TRUE;
1876b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1877b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //
1878b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    // Every pointer should have a virtual copy.
1879b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //
1880b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    FwhInstance->FvWriteBase[FVB_VIRTUAL] = FwhInstance->FvWriteBase[FVB_PHYSICAL];
1881b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1882b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    FwhInstance->WriteEnabled             = WriteEnabled;
1883b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    EfiInitializeLock (&(FwhInstance->FvbDevLock), TPL_HIGH_LEVEL);
1884b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1885b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    LbaAddress  = (UINTN) FwhInstance->FvWriteBase[0];
1886b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    NumOfBlocks = 0;
1887b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    WriteLocked = FALSE;
1888b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1889b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    if (WriteEnabled) {
1890b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      for (PtrBlockMapEntry = FwVolHeader->BlockMap; PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) {
1891b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        //
1892b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        // Get the maximum size of a block. The size will be used to allocate
1893b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        // buffer for Scratch space, the intermediate buffer for FVB extension
1894b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        // protocol
1895b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        //
1896b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        if (MaxLbaSize < PtrBlockMapEntry->Length) {
1897b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney          MaxLbaSize = PtrBlockMapEntry->Length;
1898b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        }
1899b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1900b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        NumOfBlocks = NumOfBlocks + PtrBlockMapEntry->NumBlocks;
1901b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      }
1902b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      //
1903b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      //  Write back a healthy FV header
1904b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      //
1905b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      if (WriteBack && (!WriteLocked)) {
1906b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1907b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        Status = FlashFdErase (
1908b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  (UINTN) FwhInstance->FvWriteBase[0],
1909b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  (UINTN) BaseAddress,
1910b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  FwVolHeader->BlockMap->Length
1911b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  );
1912b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1913b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        HeaderLength = (UINTN) FwVolHeader->HeaderLength;
1914b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        Status = FlashFdWrite (
1915b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  (UINTN) FwhInstance->FvWriteBase[0],
1916b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  (UINTN) BaseAddress,
1917b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  &HeaderLength,
1918b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  (UINT8 *) FwVolHeader,
1919b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  FwVolHeader->BlockMap->Length
1920b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  );
1921b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1922b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      }
1923b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    }
1924b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //
1925b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    // The total number of blocks in the FV.
1926b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //
1927b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    FwhInstance->NumOfBlocks = NumOfBlocks;
1928b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1929b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //
1930b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    // If the FV is write locked, set the appropriate attributes
1931b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //
1932b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    if (WriteLocked) {
1933b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      //
1934b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      // write disabled
1935b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      //
1936b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      FwhInstance->VolumeHeader.Attributes &= ~EFI_FVB2_WRITE_STATUS;
1937b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      //
1938b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      // lock enabled
1939b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      //
1940b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      FwhInstance->VolumeHeader.Attributes |= EFI_FVB2_LOCK_STATUS;
1941b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    }
1942b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1943b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //
1944b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    // Allocate and initialize FVB Device in a runtime data buffer
1945b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //
1946b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    FvbDevice = AllocateRuntimeCopyPool (sizeof (EFI_FW_VOL_BLOCK_DEVICE), &mFvbDeviceTemplate);
1947b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    ASSERT (FvbDevice);
1948b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1949b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    FvbDevice->Instance = mFvbModuleGlobal->NumFv;
1950b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    mFvbModuleGlobal->NumFv++;
1951b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1952b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //
1953b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    // FV does not contains extension header, then produce MEMMAP_DEVICE_PATH
1954b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //
1955b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    if (FwVolHeader->ExtHeaderOffset == 0) {
1956b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      FvbDevice->FvDevicePath.MemMapDevPath.StartingAddress = BaseAddress;
1957b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      FvbDevice->FvDevicePath.MemMapDevPath.EndingAddress   = BaseAddress + (FwVolHeader->FvLength - 1);
1958b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      FwbDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&FvbDevice->FvDevicePath;
1959b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    } else {
1960b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      CopyGuid (
1961b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        &FvbDevice->UefiFvDevicePath.FvDevPath.FvName,
1962b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        (EFI_GUID *)(UINTN)(BaseAddress + FwVolHeader->ExtHeaderOffset)
1963b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        );
1964b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      FwbDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&FvbDevice->UefiFvDevicePath;
1965b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    }
1966b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1967b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    if (!InSmm) {
1968b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      //
1969b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      // Find a handle with a matching device path that has supports FW Block protocol
1970b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      //
1971b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      TempFwbDevicePath = FwbDevicePath;
1972b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      Status = gBS->LocateDevicePath (&gEfiFirmwareVolumeBlockProtocolGuid, &TempFwbDevicePath, &FwbHandle);
1973b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      if (EFI_ERROR (Status)) {
1974b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        //
1975b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        // LocateDevicePath fails so install a new interface and device path
1976b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        //
1977b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        FwbHandle = NULL;
1978b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        Status = gBS->InstallMultipleProtocolInterfaces (
1979b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                        &FwbHandle,
1980b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                        &gEfiFirmwareVolumeBlockProtocolGuid,
1981b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                        &FvbDevice->FwVolBlockInstance,
1982b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                        &gEfiDevicePathProtocolGuid,
1983b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                        FwbDevicePath,
1984b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                        NULL
1985b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                        );
1986b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        ASSERT_EFI_ERROR (Status);
1987b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      } else if (EfiIsDevicePathEnd (TempFwbDevicePath)) {
1988b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        //
1989b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        // Device already exists, so reinstall the FVB protocol
1990b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        //
1991b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        Status = gBS->HandleProtocol (
1992b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                        FwbHandle,
1993b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                        &gEfiFirmwareVolumeBlockProtocolGuid,
1994b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                        (VOID **) &OldFwbInterface
1995b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                        );
1996b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        ASSERT_EFI_ERROR (Status);
1997b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
1998b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        Status = gBS->ReinstallProtocolInterface (
1999b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                        FwbHandle,
2000b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                        &gEfiFirmwareVolumeBlockProtocolGuid,
2001b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                        OldFwbInterface,
2002b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                        &FvbDevice->FwVolBlockInstance
2003b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                        );
2004b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        ASSERT_EFI_ERROR (Status);
2005b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
2006b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      } else {
2007b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        //
2008b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        // There was a FVB protocol on an End Device Path node
2009b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        //
2010b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        ASSERT (FALSE);
2011b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      }
2012b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    } else {
2013b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      FwbHandle = NULL;
2014b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      Status = mSmst->SmmInstallProtocolInterface (
2015b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                &FwbHandle,
2016b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                &gEfiSmmFirmwareVolumeBlockProtocolGuid,
2017b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                EFI_NATIVE_INTERFACE,
2018b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                &FvbDevice->FwVolBlockInstance
2019b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                );
2020b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      ASSERT_EFI_ERROR (Status);
2021b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    }
2022b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
2023b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    FwhInstance = (EFI_FW_VOL_INSTANCE *)
2024b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      (
2025b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        (UINTN) ((UINT8 *) FwhInstance) + FwVolHeader->HeaderLength +
2026b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney          (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER))
2027b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      );
2028b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  } while (TRUE);
2029b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
2030b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
2031b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Allocate for scratch space, an intermediate buffer for FVB extention
2032b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
2033b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
2034b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  mFvbModuleGlobal->FvbScratchSpace[FVB_PHYSICAL] = AllocateRuntimeZeroPool (MaxLbaSize);
2035b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
2036b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  ASSERT (mFvbModuleGlobal->FvbScratchSpace[FVB_PHYSICAL]);
2037b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
2038b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  mFvbModuleGlobal->FvbScratchSpace[FVB_VIRTUAL] = mFvbModuleGlobal->FvbScratchSpace[FVB_PHYSICAL];
2039b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
2040b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if (!InSmm) {
2041b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    Status = gBS->CreateEventEx (
2042b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  EVT_NOTIFY_SIGNAL,
2043b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  TPL_NOTIFY,
2044b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                 FvbVirtualddressChangeEvent,
2045b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  NULL,
2046b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  &gEfiEventVirtualAddressChangeGuid,
2047b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  &Event
2048b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  );
2049b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    ASSERT_EFI_ERROR (Status);
2050b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  } else {
2051b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //
2052b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    // Inform other platform drivers that SPI device discovered and
2053b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    // SPI interface ready for use.
2054b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //
2055b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    Handle = NULL;
2056b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    Status = gBS->InstallProtocolInterface (
2057b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                    &Handle,
2058b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                    &gEfiSmmSpiReadyProtocolGuid,
2059b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                    EFI_NATIVE_INTERFACE,
2060b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                    NULL
2061b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                    );
2062b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
2063b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  return EFI_SUCCESS;
2064b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney}
2065