1 /** @file
2   Data structures for FAT recovery PEIM
3 
4 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
5 
6 This program and the accompanying materials are licensed and made available
7 under the terms and conditions of the BSD License which accompanies this
8 distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10 
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 
14 **/
15 
16 #ifndef _FAT_PEIM_H_
17 #define _FAT_PEIM_H_
18 
19 #include <PiPei.h>
20 
21 #include <Guid/RecoveryDevice.h>
22 #include <Ppi/BlockIo.h>
23 #include <Ppi/BlockIo2.h>
24 #include <Ppi/DeviceRecoveryModule.h>
25 
26 #include <Library/DebugLib.h>
27 #include <Library/BaseLib.h>
28 #include <Library/PeimEntryPoint.h>
29 #include <Library/BaseMemoryLib.h>
30 #include <Library/PcdLib.h>
31 #include <Library/PeiServicesTablePointerLib.h>
32 #include <Library/PeiServicesLib.h>
33 
34 #include "FatLiteApi.h"
35 #include "FatLiteFmt.h"
36 
37 //
38 // Definitions
39 //
40 
41 #define PEI_FAT_CACHE_SIZE                            4
42 #define PEI_FAT_MAX_BLOCK_SIZE                        8192
43 #define FAT_MAX_FILE_NAME_LENGTH                      128
44 #define PEI_FAT_MAX_BLOCK_DEVICE                      64
45 #define PEI_FAT_MAX_BLOCK_IO_PPI                      32
46 #define PEI_FAT_MAX_VOLUME                            64
47 
48 #define PEI_FAT_MEMMORY_PAGE_SIZE                     0x1000
49 
50 //
51 // Data Structures
52 //
53 //
54 // The block device
55 //
56 typedef struct {
57 
58   UINT32                        BlockSize;
59   UINT64                        LastBlock;
60   UINT32                        IoAlign;
61   BOOLEAN                       Logical;
62   BOOLEAN                       PartitionChecked;
63 
64   //
65   // Following fields only valid for logical device
66   //
67   CHAR8                         PartitionFlag[8];
68   UINT64                        StartingPos;
69   UINTN                         ParentDevNo;
70 
71   //
72   // Following fields only valid for physical device
73   //
74   EFI_PEI_BLOCK_DEVICE_TYPE     DevType;
75   UINT8                         InterfaceType;
76   //
77   // EFI_PEI_READ_BLOCKS         ReadFunc;
78   //
79   EFI_PEI_RECOVERY_BLOCK_IO_PPI  *BlockIo;
80   EFI_PEI_RECOVERY_BLOCK_IO2_PPI *BlockIo2;
81   UINT8                          PhysicalDevNo;
82 } PEI_FAT_BLOCK_DEVICE;
83 
84 //
85 // the Volume structure
86 //
87 typedef struct {
88 
89   UINTN         BlockDeviceNo;
90   UINTN         VolumeNo;
91   UINT64        VolumeSize;
92   UINTN         MaxCluster;
93   CHAR16        VolumeLabel[FAT_MAX_FILE_NAME_LENGTH];
94   PEI_FAT_TYPE  FatType;
95   UINT64        FatPos;
96   UINT32        SectorSize;
97   UINT32        ClusterSize;
98   UINT64        FirstClusterPos;
99   UINT64        RootDirPos;
100   UINT32        RootEntries;
101   UINT32        RootDirCluster;
102 
103 } PEI_FAT_VOLUME;
104 
105 //
106 // File instance
107 //
108 typedef struct {
109 
110   PEI_FAT_VOLUME  *Volume;
111   CHAR16          FileName[FAT_MAX_FILE_NAME_LENGTH];
112 
113   BOOLEAN         IsFixedRootDir;
114 
115   UINT32          StartingCluster;
116   UINT32          CurrentPos;
117   UINT32          StraightReadAmount;
118   UINT32          CurrentCluster;
119 
120   UINT8           Attributes;
121   UINT32          FileSize;
122 
123 } PEI_FAT_FILE;
124 
125 //
126 // Cache Buffer
127 //
128 typedef struct {
129 
130   BOOLEAN Valid;
131   UINTN   BlockDeviceNo;
132   UINT64  Lba;
133   UINT32  Lru;
134   UINT64  Buffer[PEI_FAT_MAX_BLOCK_SIZE / 8];
135   UINTN   Size;
136 
137 } PEI_FAT_CACHE_BUFFER;
138 
139 //
140 // Private Data.
141 // This structure abstracts the whole memory usage in FAT PEIM.
142 // The entry point routine will get a chunk of memory (by whatever
143 // means) whose size is sizeof(PEI_FAT_PRIVATE_DATA), which is clean
144 // in both 32 and 64 bit environment. The boundary of the memory chunk
145 // should be 64bit aligned.
146 //
147 #define PEI_FAT_PRIVATE_DATA_SIGNATURE  SIGNATURE_32 ('p', 'f', 'a', 't')
148 
149 typedef struct {
150 
151   UINTN                               Signature;
152   EFI_PEI_DEVICE_RECOVERY_MODULE_PPI  DeviceRecoveryPpi;
153   EFI_PEI_PPI_DESCRIPTOR              PpiDescriptor;
154   EFI_PEI_NOTIFY_DESCRIPTOR           NotifyDescriptor[2];
155 
156   UINT8                               UnicodeCaseMap[0x300];
157   CHAR8                               *EngUpperMap;
158   CHAR8                               *EngLowerMap;
159   CHAR8                               *EngInfoMap;
160 
161   UINT64                              BlockData[PEI_FAT_MAX_BLOCK_SIZE / 8];
162   UINTN                               BlockDeviceCount;
163   PEI_FAT_BLOCK_DEVICE                BlockDevice[PEI_FAT_MAX_BLOCK_DEVICE];
164   UINTN                               VolumeCount;
165   PEI_FAT_VOLUME                      Volume[PEI_FAT_MAX_VOLUME];
166   PEI_FAT_FILE                        File;
167   PEI_FAT_CACHE_BUFFER                CacheBuffer[PEI_FAT_CACHE_SIZE];
168 
169 } PEI_FAT_PRIVATE_DATA;
170 
171 #define PEI_FAT_PRIVATE_DATA_FROM_THIS(a) \
172   CR (a,  PEI_FAT_PRIVATE_DATA, DeviceRecoveryPpi, PEI_FAT_PRIVATE_DATA_SIGNATURE)
173 
174 //
175 // Extract INT32 from char array
176 //
177 #define UNPACK_INT32(a) \
178   (INT32) ((((UINT8 *) a)[0] << 0) | (((UINT8 *) a)[1] << 8) | (((UINT8 *) a)[2] << 16) | (((UINT8 *) a)[3] << 24))
179 
180 //
181 // Extract UINT32 from char array
182 //
183 #define UNPACK_UINT32(a) \
184   (UINT32) ((((UINT8 *) a)[0] << 0) | (((UINT8 *) a)[1] << 8) | (((UINT8 *) a)[2] << 16) | (((UINT8 *) a)[3] << 24))
185 
186 
187 //
188 // API functions
189 //
190 
191 /**
192   Finds the recovery file on a FAT volume.
193   This function finds the the recovery file named FileName on a specified FAT volume and returns
194   its FileHandle pointer.
195 
196   @param  PrivateData             Global memory map for accessing global
197                                   variables.
198   @param  VolumeIndex             The index of the volume.
199   @param  FileName                The recovery file name to find.
200   @param  Handle                  The output file handle.
201 
202   @retval EFI_DEVICE_ERROR        Some error occured when operating the FAT
203                                   volume.
204   @retval EFI_NOT_FOUND           The recovery file was not found.
205   @retval EFI_SUCCESS             The recovery file was successfully found on the
206                                   FAT volume.
207 
208 **/
209 EFI_STATUS
210 FindRecoveryFile (
211   IN  PEI_FAT_PRIVATE_DATA  *PrivateData,
212   IN  UINTN                 VolumeIndex,
213   IN  CHAR16                *FileName,
214   OUT PEI_FILE_HANDLE       *Handle
215   );
216 
217 
218 /**
219   Returns the number of DXE capsules residing on the device.
220   This function, by whatever mechanism, searches for DXE capsules from the associated device and
221   returns the number and maximum size in bytes of the capsules discovered.Entry 1 is assumed to be
222   the highest load priority and entry N is assumed to be the lowest priority.
223 
224   @param  PeiServices             General-purpose services that are available to
225                                   every PEIM.
226   @param  This                    Indicates the
227                                   EFI_PEI_DEVICE_RECOVERY_MODULE_PPI instance.
228   @param  NumberRecoveryCapsules  Pointer to a caller-allocated UINTN.On output,
229                                   *NumberRecoveryCapsules contains the number of
230                                   recovery capsule images available for retrieval
231                                   from this PEIM instance.
232 
233   @retval EFI_SUCCESS             The function completed successfully.
234 
235 **/
236 EFI_STATUS
237 EFIAPI
238 GetNumberRecoveryCapsules (
239   IN EFI_PEI_SERVICES                               **PeiServices,
240   IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI             *This,
241   OUT UINTN                                         *NumberRecoveryCapsules
242   );
243 
244 
245 /**
246   Returns the size and type of the requested recovery capsule.
247   This function returns the size and type of the capsule specified by CapsuleInstance.
248 
249   @param  PeiServices             General-purpose services that are available to
250                                   every PEIM.
251   @param  This                    Indicates the
252                                   EFI_PEI_DEVICE_RECOVERY_MODULE_PPI instance.
253   @param  CapsuleInstance         Specifies for which capsule instance to
254                                   retrieve the information.T his parameter must
255                                   be between one and the value returned by
256                                   GetNumberRecoveryCapsules() in
257                                   NumberRecoveryCapsules.
258   @param  Size                    A pointer to a caller-allocated UINTN in which
259                                   the size of the requested recovery module is
260                                   returned.
261   @param  CapsuleType             A pointer to a caller-allocated EFI_GUID in
262                                   which the type of the requested recovery
263                                   capsule is returned.T he semantic meaning of
264                                   the value returned is defined by the
265                                   implementation.
266 
267   @retval EFI_SUCCESS             The capsule type and size were retrieved.
268   @retval EFI_INVALID_PARAMETER   The input CapsuleInstance does not match any
269                                   discovered recovery capsule.
270 
271 **/
272 EFI_STATUS
273 EFIAPI
274 GetRecoveryCapsuleInfo (
275   IN  EFI_PEI_SERVICES                              **PeiServices,
276   IN  EFI_PEI_DEVICE_RECOVERY_MODULE_PPI            *This,
277   IN  UINTN                                         CapsuleInstance,
278   OUT UINTN                                         *Size,
279   OUT EFI_GUID                                      *CapsuleType
280   );
281 
282 
283 /**
284   Loads a DXE capsule from some media into memory.
285 
286   This function, by whatever mechanism, retrieves a DXE capsule from some device
287   and loads it into memory. Note that the published interface is device neutral.
288 
289   @param[in]     PeiServices       General-purpose services that are available
290                                    to every PEIM
291   @param[in]     This              Indicates the EFI_PEI_DEVICE_RECOVERY_MODULE_PPI
292                                    instance.
293   @param[in]     CapsuleInstance   Specifies which capsule instance to retrieve.
294   @param[out]    Buffer            Specifies a caller-allocated buffer in which
295                                    the requested recovery capsule will be returned.
296 
297   @retval EFI_SUCCESS        The capsule was loaded correctly.
298   @retval EFI_DEVICE_ERROR   A device error occurred.
299   @retval EFI_NOT_FOUND      A requested recovery DXE capsule cannot be found.
300 
301 **/
302 EFI_STATUS
303 EFIAPI
304 LoadRecoveryCapsule (
305   IN EFI_PEI_SERVICES                             **PeiServices,
306   IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI           *This,
307   IN UINTN                                        CapsuleInstance,
308   OUT VOID                                        *Buffer
309   );
310 
311 
312 /**
313   This version is different from the version in Unicode collation
314   protocol in that this version strips off trailing blanks.
315   Converts an 8.3 FAT file name using an OEM character set
316   to a Null-terminated Unicode string.
317   Here does not expand DBCS FAT chars.
318 
319   @param  FatSize           The size of the string Fat in bytes.
320   @param  Fat               A pointer to a Null-terminated string that contains
321                             an 8.3 file name using an OEM character set.
322   @param  Str               A pointer to a Null-terminated Unicode string. The
323                             string must be allocated in advance to hold FatSize
324                             Unicode characters
325 
326 **/
327 VOID
328 EngFatToStr (
329   IN UINTN                            FatSize,
330   IN CHAR8                            *Fat,
331   OUT CHAR16                          *Str
332   );
333 
334 
335 /**
336   Performs a case-insensitive comparison of two Null-terminated Unicode strings.
337 
338   @param  PrivateData       Global memory map for accessing global variables
339   @param  Str1              First string to perform case insensitive comparison.
340   @param  Str2              Second string to perform case insensitive comparison.
341 
342 **/
343 BOOLEAN
344 EngStriColl (
345   IN  PEI_FAT_PRIVATE_DATA  *PrivateData,
346   IN CHAR16                 *Str1,
347   IN CHAR16                 *Str2
348   );
349 
350 
351 /**
352   Reads a block of data from the block device by calling
353   underlying Block I/O service.
354 
355   @param  PrivateData       Global memory map for accessing global variables
356   @param  BlockDeviceNo     The index for the block device number.
357   @param  Lba               The logic block address to read data from.
358   @param  BufferSize        The size of data in byte to read.
359   @param  Buffer            The buffer of the
360 
361   @retval EFI_DEVICE_ERROR  The specified block device number exceeds the maximum
362                             device number.
363   @retval EFI_DEVICE_ERROR  The maximum address has exceeded the maximum address
364                             of the block device.
365 
366 **/
367 EFI_STATUS
368 FatReadBlock (
369   IN  PEI_FAT_PRIVATE_DATA   *PrivateData,
370   IN  UINTN                  BlockDeviceNo,
371   IN  EFI_PEI_LBA            Lba,
372   IN  UINTN                  BufferSize,
373   OUT VOID                   *Buffer
374   );
375 
376 
377 /**
378   Check if there is a valid FAT in the corresponding Block device
379   of the volume and if yes, fill in the relevant fields for the
380   volume structure. Note there should be a valid Block device number
381   already set.
382 
383   @param  PrivateData            Global memory map for accessing global
384                                  variables.
385   @param  Volume                 On input, the BlockDeviceNumber field of the
386                                  Volume  should be a valid value. On successful
387                                  output, all  fields except the VolumeNumber
388                                  field is initialized.
389 
390   @retval EFI_SUCCESS            A FAT is found and the volume structure is
391                                  initialized.
392   @retval EFI_NOT_FOUND          There is no FAT on the corresponding device.
393   @retval EFI_DEVICE_ERROR       There is something error while accessing device.
394 
395 **/
396 EFI_STATUS
397 FatGetBpbInfo (
398   IN      PEI_FAT_PRIVATE_DATA  *PrivateData,
399   IN OUT  PEI_FAT_VOLUME        *Volume
400   );
401 
402 
403 /**
404   Gets the next cluster in the cluster chain.
405 
406   @param  PrivateData            Global memory map for accessing global variables
407   @param  Volume                 The volume
408   @param  Cluster                The cluster
409   @param  NextCluster            The cluster number of the next cluster
410 
411   @retval EFI_SUCCESS            The address is got
412   @retval EFI_INVALID_PARAMETER  ClusterNo exceeds the MaxCluster of the volume.
413   @retval EFI_DEVICE_ERROR       Read disk error
414 
415 **/
416 EFI_STATUS
417 FatGetNextCluster (
418   IN  PEI_FAT_PRIVATE_DATA  *PrivateData,
419   IN  PEI_FAT_VOLUME        *Volume,
420   IN  UINT32                Cluster,
421   OUT UINT32                *NextCluster
422   );
423 
424 
425 /**
426   Disk reading.
427 
428   @param  PrivateData       the global memory map;
429   @param  BlockDeviceNo     the block device to read;
430   @param  StartingAddress   the starting address.
431   @param  Size              the amount of data to read.
432   @param  Buffer            the buffer holding the data
433 
434   @retval EFI_SUCCESS       The function completed successfully.
435   @retval EFI_DEVICE_ERROR  Something error.
436 
437 **/
438 EFI_STATUS
439 FatReadDisk (
440   IN  PEI_FAT_PRIVATE_DATA  *PrivateData,
441   IN  UINTN                 BlockDeviceNo,
442   IN  UINT64                StartingAddress,
443   IN  UINTN                 Size,
444   OUT VOID                  *Buffer
445   );
446 
447 
448 /**
449   Set a file's CurrentPos and CurrentCluster, then compute StraightReadAmount.
450 
451   @param  PrivateData            the global memory map
452   @param  File                   the file
453   @param  Pos                    the Position which is offset from the file's
454                                  CurrentPos
455 
456   @retval EFI_SUCCESS            Success.
457   @retval EFI_INVALID_PARAMETER  Pos is beyond file's size.
458   @retval EFI_DEVICE_ERROR       Something error while accessing media.
459 
460 **/
461 EFI_STATUS
462 FatSetFilePos (
463   IN  PEI_FAT_PRIVATE_DATA  *PrivateData,
464   IN  PEI_FAT_FILE          *File,
465   IN  UINT32                Pos
466   );
467 
468 
469 /**
470   Reads file data. Updates the file's CurrentPos.
471 
472   @param  PrivateData            Global memory map for accessing global variables
473   @param  File                   The file.
474   @param  Size                   The amount of data to read.
475   @param  Buffer                 The buffer storing the data.
476 
477   @retval EFI_SUCCESS            The data is read.
478   @retval EFI_INVALID_PARAMETER  File is invalid.
479   @retval EFI_DEVICE_ERROR       Something error while accessing media.
480 
481 **/
482 EFI_STATUS
483 FatReadFile (
484   IN  PEI_FAT_PRIVATE_DATA  *PrivateData,
485   IN  PEI_FAT_FILE          *File,
486   IN  UINTN                 Size,
487   OUT VOID                  *Buffer
488   );
489 
490 
491 /**
492   This function reads the next item in the parent directory and
493   initializes the output parameter SubFile (CurrentPos is initialized to 0).
494   The function updates the CurrentPos of the parent dir to after the item read.
495   If no more items were found, the function returns EFI_NOT_FOUND.
496 
497   @param  PrivateData            Global memory map for accessing global variables
498   @param  ParentDir              The parent directory.
499   @param  SubFile                The File structure containing the sub file that
500                                  is caught.
501 
502   @retval EFI_SUCCESS            The next sub file is obtained.
503   @retval EFI_INVALID_PARAMETER  The ParentDir is not a directory.
504   @retval EFI_NOT_FOUND          No more sub file exists.
505   @retval EFI_DEVICE_ERROR       Something error while accessing media.
506 
507 **/
508 EFI_STATUS
509 FatReadNextDirectoryEntry (
510   IN  PEI_FAT_PRIVATE_DATA  *PrivateData,
511   IN  PEI_FAT_FILE          *ParentDir,
512   OUT PEI_FAT_FILE          *SubFile
513   );
514 
515 
516 /**
517   This function finds partitions (logical devices) in physical block devices.
518 
519   @param  PrivateData       Global memory map for accessing global variables.
520 
521 **/
522 VOID
523 FatFindPartitions (
524   IN  PEI_FAT_PRIVATE_DATA  *PrivateData
525   );
526 
527 #endif // _FAT_PEIM_H_
528