]> git.proxmox.com Git - mirror_edk2.git/blame - DuetPkg/FSVariable/FileStorage.c
Patch to remove STATIC modifier. This is on longer recommended by EFI Framework codin...
[mirror_edk2.git] / DuetPkg / FSVariable / FileStorage.c
CommitLineData
9071550e 1/*++\r
2\r
3Copyright (c) 2006 - 2007, Intel Corporation\r
4All rights reserved. This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12Module Name:\r
13\r
14 FileStorage.c\r
15\r
16Abstract:\r
17\r
18 handles variable store/reads on file\r
19\r
20Revision History\r
21\r
22--*/\r
23#include "FSVariable.h"\r
24\r
25VOID *mSFSRegistration;\r
26\r
27//\r
28// Prototypes\r
29//\r
30\r
31STATIC\r
32VOID\r
33EFIAPI\r
34OnVirtualAddressChange (\r
35 IN EFI_EVENT Event,\r
36 IN VOID *Context\r
37 );\r
38\r
39STATIC\r
40EFI_STATUS\r
41EFIAPI\r
42FileEraseStore(\r
43 IN VARIABLE_STORAGE *This\r
44 );\r
45\r
46STATIC\r
47EFI_STATUS\r
48EFIAPI\r
49FileWriteStore (\r
50 IN VARIABLE_STORAGE *This,\r
51 IN UINTN Offset,\r
52 IN UINTN BufferSize,\r
53 IN VOID *Buffer\r
54 );\r
55\r
56STATIC\r
57EFI_STATUS\r
58OpenStore (\r
59 IN EFI_DEVICE_PATH_PROTOCOL *Device,\r
60 IN CHAR16 *FilePathName,\r
61 IN UINT64 OpenMode,\r
62 OUT EFI_FILE **File\r
63 );\r
64\r
65//\r
66// Implementation below:\r
67//\r
68STATIC\r
69VOID\r
70FileClose (\r
71 IN EFI_FILE *File\r
72 )\r
73{\r
74 EFI_STATUS Status;\r
75\r
76 Status = File->Flush (File);\r
77 ASSERT_EFI_ERROR (Status);\r
78\r
79 Status = File->Close (File);\r
80 ASSERT_EFI_ERROR (Status);\r
81}\r
82\r
83EFI_STATUS\r
84CheckStore (\r
85 IN EFI_HANDLE SimpleFileSystemHandle,\r
86 IN UINT32 VolumeId,\r
87 OUT EFI_DEVICE_PATH_PROTOCOL **Device\r
88 )\r
89{\r
90#define BLOCK_SIZE 0x200\r
91#define FAT16_VOLUME_ID_OFFSET 39\r
92#define FAT32_VOLUME_ID_OFFSET 67\r
93 EFI_STATUS Status;\r
94 EFI_BLOCK_IO_PROTOCOL *BlkIo;\r
95 UINT8 BootSector[BLOCK_SIZE];\r
96\r
97 *Device = NULL;\r
98 Status = gBS->HandleProtocol (\r
99 SimpleFileSystemHandle,\r
100 &gEfiBlockIoProtocolGuid, // BlockIo should be supported if it supports SimpleFileSystem\r
101 (VOID*)&BlkIo\r
102 );\r
103\r
104 if (EFI_ERROR (Status)) {\r
105 goto ErrHandle;\r
106 }\r
107 if (!BlkIo->Media->MediaPresent) {\r
108 DEBUG ((EFI_D_ERROR, "FileStorage: Media not present!\n"));\r
109 Status = EFI_NO_MEDIA;\r
110 goto ErrHandle;\r
111 }\r
112 if (BlkIo->Media->ReadOnly) {\r
113 DEBUG ((EFI_D_ERROR, "FileStorage: Media is read-only!\n"));\r
114 Status = EFI_ACCESS_DENIED;\r
115 goto ErrHandle;\r
116 }\r
117\r
118 Status = BlkIo->ReadBlocks(\r
119 BlkIo,\r
120 BlkIo->Media->MediaId,\r
121 0,\r
122 BLOCK_SIZE,\r
123 BootSector\r
124 );\r
125 ASSERT_EFI_ERROR (Status);\r
126 if ((*(UINT32 *) &BootSector[FAT16_VOLUME_ID_OFFSET] != VolumeId) &&\r
127 (*(UINT32 *) &BootSector[FAT32_VOLUME_ID_OFFSET] != VolumeId)\r
128 ) {\r
129 Status = EFI_NOT_FOUND;\r
130 goto ErrHandle;\r
131 }\r
132\r
133 *Device = DuplicateDevicePath (DevicePathFromHandle (SimpleFileSystemHandle));\r
134 ASSERT (*Device != NULL);\r
135\r
136ErrHandle:\r
137 return Status;\r
138}\r
139\r
140EFI_STATUS\r
141CheckStoreExists (\r
142 IN EFI_DEVICE_PATH_PROTOCOL *Device\r
143 )\r
144{\r
145 EFI_HANDLE Handle;\r
146 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume;\r
147 EFI_STATUS Status;\r
148\r
149 Status = gBS->LocateDevicePath (\r
150 &gEfiSimpleFileSystemProtocolGuid,\r
151 &Device, \r
152 &Handle\r
153 );\r
154\r
155 if (EFI_ERROR (Status)) {\r
156 return Status;\r
157 }\r
158\r
159 Status = gBS->HandleProtocol (\r
160 Handle,\r
161 &gEfiSimpleFileSystemProtocolGuid,\r
162 &Volume\r
163 );\r
164 if (EFI_ERROR (Status)) {\r
165 return Status;\r
166 }\r
167\r
168 return EFI_SUCCESS;\r
169}\r
170\r
171// this routine is still running in BS period, no limitation\r
172// call FileInitStorage(), which load variable content file to memory\r
173// read the store_header, init store_header if it has not been inited (read sth. about format/heathy)\r
174// reclaim space using scratch memory\r
175\r
176STATIC\r
177VOID\r
178EFIAPI\r
179OnSimpleFileSystemInstall (\r
180 IN EFI_EVENT Event,\r
181 IN VOID *Context\r
182 )\r
183{\r
184 EFI_STATUS Status;\r
185 UINTN HandleSize;\r
186 EFI_HANDLE Handle;\r
187 EFI_DEVICE_PATH_PROTOCOL *Device;\r
188 VS_DEV *Dev;\r
189 EFI_FILE *File;\r
190 UINTN NumBytes;\r
191\r
192 Dev = (VS_DEV *) Context;\r
193 \r
194 if (VAR_FILE_DEVICEPATH (Dev) != NULL &&\r
195 !EFI_ERROR (CheckStoreExists (VAR_FILE_DEVICEPATH (Dev)))\r
196 ) {\r
197 DEBUG ((EFI_D_ERROR, "FileStorage: Already mapped!\n"));\r
198 return ;\r
199 }\r
200\r
201 while (TRUE) {\r
202 HandleSize = sizeof (EFI_HANDLE);\r
203 Status = gBS->LocateHandle (\r
204 ByRegisterNotify,\r
205 NULL,\r
206 mSFSRegistration,\r
207 &HandleSize,\r
208 &Handle\r
209 );\r
210 if (EFI_ERROR (Status)) {\r
211 return ;\r
212 }\r
213 \r
214 Status = CheckStore (Handle, VAR_FILE_VOLUMEID (Dev), &Device);\r
215 if (!EFI_ERROR (Status)) {\r
216 break;\r
217 }\r
218 }\r
219\r
220 VAR_FILE_DEVICEPATH (Dev) = Device;\r
221 Status = OpenStore (\r
222 VAR_FILE_DEVICEPATH (Dev), \r
223 VAR_FILE_FILEPATH (Dev), \r
224 EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ | EFI_FILE_MODE_CREATE,\r
225 &File\r
226 );\r
227 ASSERT_EFI_ERROR (Status);\r
228 \r
229 NumBytes = Dev->Size;\r
230 Status = File->Write (File, &NumBytes, VAR_DATA_PTR (Dev));\r
231 ASSERT_EFI_ERROR (Status);\r
be768885 232 // KEN: bugbug here if closing file, volume handle will be free,\r
233 // and system will be hang when accessing volume handle in future.\r
234 //FileClose (File);\r
9071550e 235 DEBUG ((EFI_D_ERROR, "FileStorage: Mapped to file!\n"));\r
236}\r
237\r
238EFI_STATUS\r
239FileStorageConstructor (\r
240 OUT VARIABLE_STORAGE **VarStore,\r
241 OUT EFI_EVENT_NOTIFY *GoVirtualEvent,\r
242 IN EFI_PHYSICAL_ADDRESS NvStorageBase,\r
243 IN UINTN Size,\r
244 IN UINT32 VolumeId,\r
245 IN CHAR16 *FilePath\r
246 )\r
247{\r
248 VS_DEV *Dev;\r
249 EFI_STATUS Status;\r
250 EFI_EVENT Event;\r
251\r
252 Status = gBS->AllocatePool (EfiRuntimeServicesData, sizeof(VS_DEV), &Dev);\r
253 ASSERT_EFI_ERROR (Status);\r
254 ZeroMem (Dev, sizeof(VS_DEV));\r
255\r
256 Dev->Signature = VARIABLE_STORE_SIGNATURE;\r
257 Dev->Size = Size;\r
258 VAR_DATA_PTR (Dev) = (UINT8 *) (UINTN) NvStorageBase;\r
259 VAR_FILE_VOLUMEID (Dev) = VolumeId;\r
260 StrCpy (VAR_FILE_FILEPATH (Dev), FilePath);\r
261 Dev->VarStore.Erase = FileEraseStore;\r
262 Dev->VarStore.Write = FileWriteStore;\r
263\r
264 DEBUG ((EFI_D_ERROR, "FileStorageConstructor(0x%0x:0x%0x): added!\n", NvStorageBase, Size));\r
265\r
266 // add notify on SFS's installation.\r
267\r
268 Status = gBS->CreateEvent (\r
e53a6ea9 269 EVT_NOTIFY_SIGNAL,\r
9071550e 270 TPL_CALLBACK,\r
271 OnSimpleFileSystemInstall,\r
272 Dev,\r
273 &Event\r
274 );\r
275 ASSERT_EFI_ERROR (Status);\r
276\r
277 Status = gBS->RegisterProtocolNotify (\r
278 &gEfiSimpleFileSystemProtocolGuid,\r
279 Event,\r
280 &mSFSRegistration\r
281 );\r
282 ASSERT_EFI_ERROR (Status);\r
283\r
284 *VarStore = &Dev->VarStore;\r
285 *GoVirtualEvent = OnVirtualAddressChange;\r
286 return EFI_SUCCESS;\r
287}\r
288\r
289STATIC\r
290EFI_STATUS\r
291EFIAPI\r
292FileEraseStore(\r
293 IN VARIABLE_STORAGE *This\r
294 )\r
295{\r
296 EFI_STATUS Status;\r
297 VS_DEV *Dev;\r
298 EFI_FILE *File;\r
299 UINTN NumBytes;\r
300\r
301 Status = EFI_SUCCESS;\r
302 Dev = DEV_FROM_THIS(This);\r
303\r
304 SetMem (VAR_DATA_PTR (Dev), Dev->Size, VAR_DEFAULT_VALUE);\r
305\r
306 if (!EfiAtRuntime () && VAR_FILE_DEVICEPATH (Dev) != NULL) {\r
307 Status = OpenStore (\r
308 VAR_FILE_DEVICEPATH (Dev), \r
309 VAR_FILE_FILEPATH (Dev), \r
310 EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ,\r
311 &File\r
312 );\r
313 ASSERT_EFI_ERROR (Status);\r
314 NumBytes = Dev->Size;\r
315 Status = File->Write (File, &NumBytes, VAR_DATA_PTR (Dev));\r
316 ASSERT_EFI_ERROR (Status);\r
317 FileClose (File);\r
318 }\r
319 \r
320 return Status;\r
321}\r
322\r
323STATIC\r
324EFI_STATUS\r
325EFIAPI\r
326FileWriteStore (\r
327 IN VARIABLE_STORAGE *This,\r
328 IN UINTN Offset,\r
329 IN UINTN BufferSize,\r
330 IN VOID *Buffer\r
331 )\r
332{\r
333 EFI_STATUS Status;\r
334 VS_DEV *Dev;\r
335 EFI_FILE *File;\r
336\r
337 Status = EFI_SUCCESS;\r
338 Dev = DEV_FROM_THIS(This);\r
339\r
340 ASSERT (Buffer != NULL);\r
341 ASSERT (Offset + BufferSize <= Dev->Size);\r
342\r
343 CopyMem (VAR_DATA_PTR (Dev) + Offset, Buffer, BufferSize);\r
344 \r
345 if (!EfiAtRuntime () && VAR_FILE_DEVICEPATH (Dev) != NULL) {\r
346 Status = OpenStore (\r
347 VAR_FILE_DEVICEPATH (Dev), \r
348 VAR_FILE_FILEPATH (Dev), \r
349 EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ,\r
350 &File\r
351 );\r
352 Status = File->SetPosition (File, Offset);\r
353 ASSERT_EFI_ERROR (Status);\r
354 Status = File->Write (File, &BufferSize, Buffer);\r
355 ASSERT_EFI_ERROR (Status);\r
356 FileClose (File);\r
357 }\r
358 return Status;\r
359}\r
360\r
361STATIC\r
362VOID\r
363EFIAPI\r
364OnVirtualAddressChange (\r
365 IN EFI_EVENT Event,\r
366 IN VOID *Context\r
367 )\r
368{\r
369 VS_DEV *Dev;\r
370\r
371 Dev = DEV_FROM_THIS (Context);\r
372\r
373 EfiConvertPointer (0, &VAR_DATA_PTR (Dev));\r
374 EfiConvertPointer (0, (VOID **) &Dev->VarStore.Erase);\r
375 EfiConvertPointer (0, (VOID **) &Dev->VarStore.Write);\r
376}\r
377\r
378STATIC\r
379EFI_STATUS\r
380OpenStore (\r
381 IN EFI_DEVICE_PATH_PROTOCOL *Device,\r
382 IN CHAR16 *FilePathName,\r
383 IN UINT64 OpenMode,\r
384 OUT EFI_FILE **File\r
385 )\r
386{\r
387 EFI_HANDLE Handle;\r
388 EFI_FILE_HANDLE Root;\r
389 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume;\r
390 EFI_STATUS Status;\r
391\r
392 *File = NULL;\r
393\r
394 Status = gBS->LocateDevicePath (\r
395 &gEfiSimpleFileSystemProtocolGuid,\r
396 &Device, \r
397 &Handle\r
398 );\r
399\r
400 if (EFI_ERROR (Status)) {\r
401 return Status;\r
402 }\r
403\r
404 Status = gBS->HandleProtocol (\r
405 Handle,\r
406 &gEfiSimpleFileSystemProtocolGuid,\r
407 &Volume\r
408 );\r
409 if (EFI_ERROR (Status)) {\r
410 return Status;\r
411 }\r
be768885 412\r
9071550e 413 //\r
414 // Open the root directory of the volume\r
415 //\r
416 Root = NULL;\r
417 Status = Volume->OpenVolume (\r
418 Volume,\r
419 &Root\r
420 );\r
421 ASSERT_EFI_ERROR (Status);\r
422 ASSERT (Root != NULL);\r
423\r
424 //\r
425 // Open file\r
426 //\r
427 Status = Root->Open (\r
428 Root,\r
429 File,\r
430 FilePathName,\r
431 OpenMode,\r
432 0\r
433 );\r
434 if (EFI_ERROR (Status)) {\r
435 *File = NULL;\r
436 }\r
437\r
438 //\r
439 // Close the Root directory\r
440 //\r
441 Root->Close (Root);\r
442 return Status;\r
443}\r