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