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