1 /**@file
2 Copyright (c) 2007 - 2009, Intel Corporation. All rights reserved.<BR>
3 This program and the accompanying materials
4 are licensed and made available under the terms and conditions of the BSD License
5 which accompanies this distribution.  The full text of the license may be found at
6 http://opensource.org/licenses/bsd-license.php
7 
8 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
9 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
10 
11 Module Name:
12 
13     FileIo.c
14 
15 Abstract:
16 
17   File operation for Firmware volume block driver
18 
19 **/
20 #include "FileIo.h"
21 
22 //
23 // Variable storage hot plug is supported but there are still some restrictions:
24 // After plugging the storage back,
25 // 1. Still use memory as NV if newly plugged storage is not same as the original one
26 // 2. Still use memory as NV if there are some update operation during storage is unplugged.
27 //
28 
29 
30 EFI_STATUS
FileWrite(IN EFI_FILE_PROTOCOL * File,IN UINTN Offset,IN UINTN Buffer,IN UINTN Size)31 FileWrite (
32   IN EFI_FILE_PROTOCOL  *File,
33   IN UINTN              Offset,
34   IN UINTN              Buffer,
35   IN UINTN              Size
36   )
37 {
38   EFI_STATUS Status;
39 
40   Status = File->SetPosition (File, Offset);
41   ASSERT_EFI_ERROR (Status);
42   if (!EFI_ERROR (Status)) {
43     Status = File->Write (File, &Size, (VOID *) Buffer);
44     ASSERT_EFI_ERROR (Status);
45   }
46   return Status;
47 }
48 
49 EFI_STATUS
CheckStore(IN EFI_HANDLE SimpleFileSystemHandle,IN UINT32 VolumeId,OUT EFI_DEVICE_PATH_PROTOCOL ** Device)50 CheckStore (
51   IN  EFI_HANDLE                 SimpleFileSystemHandle,
52   IN  UINT32                     VolumeId,
53   OUT EFI_DEVICE_PATH_PROTOCOL   **Device
54   )
55 {
56 #define BLOCK_SIZE              0x200
57 #define FAT16_VOLUME_ID_OFFSET  39
58 #define FAT32_VOLUME_ID_OFFSET  67
59   EFI_STATUS                      Status;
60   EFI_BLOCK_IO_PROTOCOL           *BlkIo;
61   UINT8                           BootSector[BLOCK_SIZE];
62 
63   *Device = NULL;
64   Status  = gBS->HandleProtocol (
65                    SimpleFileSystemHandle,
66                    &gEfiBlockIoProtocolGuid, // BlockIo should be supported if it supports SimpleFileSystem
67                    (VOID*)&BlkIo
68                    );
69 
70   if (EFI_ERROR (Status)) {
71     goto ErrHandle;
72   }
73   if (!BlkIo->Media->MediaPresent) {
74     DEBUG ((EFI_D_ERROR, "FwhMappedFile: Media not present!\n"));
75     Status = EFI_NO_MEDIA;
76     goto ErrHandle;
77   }
78   if (BlkIo->Media->ReadOnly) {
79     DEBUG ((EFI_D_ERROR, "FwhMappedFile: Media is read-only!\n"));
80     Status = EFI_ACCESS_DENIED;
81     goto ErrHandle;
82   }
83 
84   Status = BlkIo->ReadBlocks(
85                     BlkIo,
86                     BlkIo->Media->MediaId,
87                     0,
88                     BLOCK_SIZE,
89                     BootSector
90                     );
91   ASSERT_EFI_ERROR (Status);
92   if ((*(UINT32 *) &BootSector[FAT16_VOLUME_ID_OFFSET] != VolumeId) &&
93       (*(UINT32 *) &BootSector[FAT32_VOLUME_ID_OFFSET] != VolumeId)
94       ) {
95     Status = EFI_NOT_FOUND;
96     goto ErrHandle;
97   }
98 
99   *Device = DuplicateDevicePath (DevicePathFromHandle (SimpleFileSystemHandle));
100   ASSERT (*Device != NULL);
101 
102 ErrHandle:
103   return Status;
104 }
105 
106 EFI_STATUS
CheckStoreExists(IN EFI_DEVICE_PATH_PROTOCOL * Device)107 CheckStoreExists (
108   IN  EFI_DEVICE_PATH_PROTOCOL   *Device
109   )
110 {
111   EFI_HANDLE                        Handle;
112   EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Volume;
113   EFI_STATUS                        Status;
114 
115   Status = gBS->LocateDevicePath (
116                   &gEfiSimpleFileSystemProtocolGuid,
117                   &Device,
118                   &Handle
119                   );
120 
121   if (EFI_ERROR (Status)) {
122     return Status;
123   }
124 
125   Status = gBS->HandleProtocol (
126                   Handle,
127                   &gEfiSimpleFileSystemProtocolGuid,
128                   &Volume
129                   );
130   if (EFI_ERROR (Status)) {
131     return Status;
132   }
133 
134   return EFI_SUCCESS;
135 }
136 
137 VOID
FileClose(IN EFI_FILE_PROTOCOL * File)138 FileClose (
139   IN  EFI_FILE_PROTOCOL          *File
140   )
141 {
142   File->Flush (File);
143   File->Close (File);
144 }
145 EFI_STATUS
FileOpen(IN EFI_DEVICE_PATH_PROTOCOL * Device,IN CHAR16 * MappedFile,OUT EFI_FILE_PROTOCOL ** File,IN UINT64 OpenMode)146 FileOpen (
147   IN  EFI_DEVICE_PATH_PROTOCOL   *Device,
148   IN  CHAR16                     *MappedFile,
149   OUT EFI_FILE_PROTOCOL          **File,
150   IN  UINT64                     OpenMode
151   )
152 {
153   EFI_HANDLE                        Handle;
154   EFI_FILE_HANDLE                   Root;
155   EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Volume;
156   EFI_STATUS                        Status;
157 
158   *File = NULL;
159 
160   Status = gBS->LocateDevicePath (
161                   &gEfiSimpleFileSystemProtocolGuid,
162                   &Device,
163                   &Handle
164                   );
165 
166   if (EFI_ERROR (Status)) {
167     return Status;
168   }
169 
170   Status = gBS->HandleProtocol (
171                   Handle,
172                   &gEfiSimpleFileSystemProtocolGuid,
173                   &Volume
174                   );
175   ASSERT_EFI_ERROR (Status);
176   if (EFI_ERROR (Status)) {
177     return Status;
178   }
179 
180   //
181   // Open the root directory of the volume
182   //
183   Root = NULL;
184   Status = Volume->OpenVolume (
185                      Volume,
186                      &Root
187                      );
188   ASSERT_EFI_ERROR (Status);
189   ASSERT (Root != NULL);
190 
191   //
192   // Open file
193   //
194   Status = Root->Open (
195                    Root,
196                    File,
197                    MappedFile,
198                    OpenMode,
199                    0
200                    );
201   if (EFI_ERROR (Status)) {
202     *File = NULL;
203   }
204 
205   //
206   // Close the Root directory
207   //
208   Root->Close (Root);
209   return Status;
210 }
211