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