]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskBlockIo.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Universal / Disk / RamDiskDxe / RamDiskBlockIo.c
CommitLineData
20752cb8
HW
1/** @file\r
2 Produce EFI_BLOCK_IO_PROTOCOL on a RAM disk device.\r
3\r
38c9fbdc 4 Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>\r
9d510e61 5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
20752cb8
HW
6\r
7**/\r
8\r
9#include "RamDiskImpl.h"\r
10\r
11//\r
12// The EFI_BLOCK_IO_PROTOCOL instances that is installed onto the handle\r
13// for newly registered RAM disks\r
14//\r
15EFI_BLOCK_IO_PROTOCOL mRamDiskBlockIoTemplate = {\r
16 EFI_BLOCK_IO_PROTOCOL_REVISION,\r
1436aea4 17 (EFI_BLOCK_IO_MEDIA *)0,\r
20752cb8
HW
18 RamDiskBlkIoReset,\r
19 RamDiskBlkIoReadBlocks,\r
20 RamDiskBlkIoWriteBlocks,\r
21 RamDiskBlkIoFlushBlocks\r
22};\r
23\r
216fefa3
HW
24//\r
25// The EFI_BLOCK_IO_PROTOCOL2 instances that is installed onto the handle\r
26// for newly registered RAM disks\r
27//\r
28EFI_BLOCK_IO2_PROTOCOL mRamDiskBlockIo2Template = {\r
1436aea4 29 (EFI_BLOCK_IO_MEDIA *)0,\r
216fefa3
HW
30 RamDiskBlkIo2Reset,\r
31 RamDiskBlkIo2ReadBlocksEx,\r
32 RamDiskBlkIo2WriteBlocksEx,\r
33 RamDiskBlkIo2FlushBlocksEx\r
34};\r
35\r
20752cb8 36/**\r
216fefa3 37 Initialize the BlockIO & BlockIO2 protocol of a RAM disk device.\r
20752cb8
HW
38\r
39 @param[in] PrivateData Points to RAM disk private data.\r
40\r
41**/\r
42VOID\r
43RamDiskInitBlockIo (\r
1436aea4 44 IN RAM_DISK_PRIVATE_DATA *PrivateData\r
20752cb8
HW
45 )\r
46{\r
1436aea4
MK
47 EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
48 EFI_BLOCK_IO2_PROTOCOL *BlockIo2;\r
49 EFI_BLOCK_IO_MEDIA *Media;\r
50 UINT32 Remainder;\r
20752cb8 51\r
216fefa3
HW
52 BlockIo = &PrivateData->BlockIo;\r
53 BlockIo2 = &PrivateData->BlockIo2;\r
54 Media = &PrivateData->Media;\r
20752cb8
HW
55\r
56 CopyMem (BlockIo, &mRamDiskBlockIoTemplate, sizeof (EFI_BLOCK_IO_PROTOCOL));\r
216fefa3 57 CopyMem (BlockIo2, &mRamDiskBlockIo2Template, sizeof (EFI_BLOCK_IO2_PROTOCOL));\r
20752cb8
HW
58\r
59 BlockIo->Media = Media;\r
216fefa3 60 BlockIo2->Media = Media;\r
20752cb8
HW
61 Media->RemovableMedia = FALSE;\r
62 Media->MediaPresent = TRUE;\r
63 Media->LogicalPartition = FALSE;\r
64 Media->ReadOnly = FALSE;\r
65 Media->WriteCaching = FALSE;\r
38c9fbdc
HW
66\r
67 for (Media->BlockSize = RAM_DISK_DEFAULT_BLOCK_SIZE;\r
68 Media->BlockSize >= 1;\r
1436aea4
MK
69 Media->BlockSize = Media->BlockSize >> 1)\r
70 {\r
38c9fbdc
HW
71 Media->LastBlock = DivU64x32Remainder (PrivateData->Size, Media->BlockSize, &Remainder) - 1;\r
72 if (Remainder == 0) {\r
73 break;\r
74 }\r
75 }\r
1436aea4 76\r
38c9fbdc
HW
77 ASSERT (Media->BlockSize != 0);\r
78\r
79 return;\r
20752cb8
HW
80}\r
81\r
20752cb8
HW
82/**\r
83 Reset the Block Device.\r
84\r
85 @param This Indicates a pointer to the calling context.\r
86 @param ExtendedVerification Driver may perform diagnostics on reset.\r
87\r
88 @retval EFI_SUCCESS The device was reset.\r
89 @retval EFI_DEVICE_ERROR The device is not functioning properly and could\r
90 not be reset.\r
91\r
92**/\r
93EFI_STATUS\r
94EFIAPI\r
95RamDiskBlkIoReset (\r
1436aea4
MK
96 IN EFI_BLOCK_IO_PROTOCOL *This,\r
97 IN BOOLEAN ExtendedVerification\r
20752cb8
HW
98 )\r
99{\r
100 return EFI_SUCCESS;\r
101}\r
102\r
20752cb8
HW
103/**\r
104 Read BufferSize bytes from Lba into Buffer.\r
105\r
106 @param[in] This Indicates a pointer to the calling context.\r
107 @param[in] MediaId Id of the media, changes every time the media is\r
108 replaced.\r
109 @param[in] Lba The starting Logical Block Address to read from.\r
110 @param[in] BufferSize Size of Buffer, must be a multiple of device block\r
111 size.\r
112 @param[out] Buffer A pointer to the destination buffer for the data.\r
113 The caller is responsible for either having\r
114 implicit or explicit ownership of the buffer.\r
115\r
116 @retval EFI_SUCCESS The data was read correctly from the device.\r
117 @retval EFI_DEVICE_ERROR The device reported an error while performing\r
118 the read.\r
119 @retval EFI_NO_MEDIA There is no media in the device.\r
120 @retval EFI_MEDIA_CHANGED The MediaId does not matched the current\r
121 device.\r
122 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block\r
123 size of the device.\r
124 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not\r
125 valid, or the buffer is not on proper alignment.\r
126\r
127**/\r
128EFI_STATUS\r
129EFIAPI\r
130RamDiskBlkIoReadBlocks (\r
1436aea4
MK
131 IN EFI_BLOCK_IO_PROTOCOL *This,\r
132 IN UINT32 MediaId,\r
133 IN EFI_LBA Lba,\r
134 IN UINTN BufferSize,\r
135 OUT VOID *Buffer\r
20752cb8
HW
136 )\r
137{\r
1436aea4
MK
138 RAM_DISK_PRIVATE_DATA *PrivateData;\r
139 UINTN NumberOfBlocks;\r
20752cb8 140\r
0feca62c
HW
141 PrivateData = RAM_DISK_PRIVATE_FROM_BLKIO (This);\r
142\r
143 if (MediaId != PrivateData->Media.MediaId) {\r
144 return EFI_MEDIA_CHANGED;\r
145 }\r
146\r
20752cb8
HW
147 if (Buffer == NULL) {\r
148 return EFI_INVALID_PARAMETER;\r
149 }\r
150\r
151 if (BufferSize == 0) {\r
152 return EFI_SUCCESS;\r
153 }\r
154\r
20752cb8
HW
155 if ((BufferSize % PrivateData->Media.BlockSize) != 0) {\r
156 return EFI_BAD_BUFFER_SIZE;\r
157 }\r
158\r
159 if (Lba > PrivateData->Media.LastBlock) {\r
160 return EFI_INVALID_PARAMETER;\r
161 }\r
162\r
163 NumberOfBlocks = BufferSize / PrivateData->Media.BlockSize;\r
164 if ((Lba + NumberOfBlocks - 1) > PrivateData->Media.LastBlock) {\r
165 return EFI_INVALID_PARAMETER;\r
166 }\r
167\r
168 CopyMem (\r
169 Buffer,\r
170 (VOID *)(UINTN)(PrivateData->StartingAddr + MultU64x32 (Lba, PrivateData->Media.BlockSize)),\r
171 BufferSize\r
172 );\r
173\r
174 return EFI_SUCCESS;\r
175}\r
176\r
20752cb8
HW
177/**\r
178 Write BufferSize bytes from Lba into Buffer.\r
179\r
180 @param[in] This Indicates a pointer to the calling context.\r
181 @param[in] MediaId The media ID that the write request is for.\r
182 @param[in] Lba The starting logical block address to be written.\r
183 The caller is responsible for writing to only\r
184 legitimate locations.\r
185 @param[in] BufferSize Size of Buffer, must be a multiple of device block\r
186 size.\r
187 @param[in] Buffer A pointer to the source buffer for the data.\r
188\r
189 @retval EFI_SUCCESS The data was written correctly to the device.\r
190 @retval EFI_WRITE_PROTECTED The device can not be written to.\r
191 @retval EFI_DEVICE_ERROR The device reported an error while performing\r
192 the write.\r
193 @retval EFI_NO_MEDIA There is no media in the device.\r
194 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current\r
195 device.\r
196 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block\r
197 size of the device.\r
198 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not\r
199 valid, or the buffer is not on proper alignment.\r
200\r
201**/\r
202EFI_STATUS\r
203EFIAPI\r
204RamDiskBlkIoWriteBlocks (\r
1436aea4
MK
205 IN EFI_BLOCK_IO_PROTOCOL *This,\r
206 IN UINT32 MediaId,\r
207 IN EFI_LBA Lba,\r
208 IN UINTN BufferSize,\r
209 IN VOID *Buffer\r
20752cb8
HW
210 )\r
211{\r
1436aea4
MK
212 RAM_DISK_PRIVATE_DATA *PrivateData;\r
213 UINTN NumberOfBlocks;\r
20752cb8 214\r
20752cb8
HW
215 PrivateData = RAM_DISK_PRIVATE_FROM_BLKIO (This);\r
216\r
217 if (MediaId != PrivateData->Media.MediaId) {\r
218 return EFI_MEDIA_CHANGED;\r
219 }\r
220\r
221 if (TRUE == PrivateData->Media.ReadOnly) {\r
222 return EFI_WRITE_PROTECTED;\r
223 }\r
224\r
0feca62c
HW
225 if (Buffer == NULL) {\r
226 return EFI_INVALID_PARAMETER;\r
227 }\r
228\r
229 if (BufferSize == 0) {\r
230 return EFI_SUCCESS;\r
231 }\r
232\r
20752cb8
HW
233 if ((BufferSize % PrivateData->Media.BlockSize) != 0) {\r
234 return EFI_BAD_BUFFER_SIZE;\r
235 }\r
236\r
237 if (Lba > PrivateData->Media.LastBlock) {\r
238 return EFI_INVALID_PARAMETER;\r
239 }\r
240\r
241 NumberOfBlocks = BufferSize / PrivateData->Media.BlockSize;\r
242 if ((Lba + NumberOfBlocks - 1) > PrivateData->Media.LastBlock) {\r
243 return EFI_INVALID_PARAMETER;\r
244 }\r
245\r
246 CopyMem (\r
247 (VOID *)(UINTN)(PrivateData->StartingAddr + MultU64x32 (Lba, PrivateData->Media.BlockSize)),\r
248 Buffer,\r
249 BufferSize\r
250 );\r
251\r
252 return EFI_SUCCESS;\r
253}\r
254\r
20752cb8
HW
255/**\r
256 Flush the Block Device.\r
257\r
258 @param[in] This Indicates a pointer to the calling context.\r
259\r
260 @retval EFI_SUCCESS All outstanding data was written to the device.\r
261 @retval EFI_DEVICE_ERROR The device reported an error while writting\r
262 back the data\r
263 @retval EFI_NO_MEDIA There is no media in the device.\r
264\r
265**/\r
266EFI_STATUS\r
267EFIAPI\r
268RamDiskBlkIoFlushBlocks (\r
1436aea4 269 IN EFI_BLOCK_IO_PROTOCOL *This\r
20752cb8
HW
270 )\r
271{\r
272 return EFI_SUCCESS;\r
273}\r
216fefa3 274\r
216fefa3
HW
275/**\r
276 Resets the block device hardware.\r
277\r
278 @param[in] This The pointer of EFI_BLOCK_IO2_PROTOCOL.\r
279 @param[in] ExtendedVerification The flag about if extend verificate.\r
280\r
281 @retval EFI_SUCCESS The device was reset.\r
282 @retval EFI_DEVICE_ERROR The block device is not functioning correctly\r
283 and could not be reset.\r
284\r
285**/\r
286EFI_STATUS\r
287EFIAPI\r
288RamDiskBlkIo2Reset (\r
1436aea4
MK
289 IN EFI_BLOCK_IO2_PROTOCOL *This,\r
290 IN BOOLEAN ExtendedVerification\r
216fefa3
HW
291 )\r
292{\r
293 return EFI_SUCCESS;\r
294}\r
295\r
216fefa3
HW
296/**\r
297 Reads the requested number of blocks from the device.\r
298\r
299 @param[in] This Indicates a pointer to the calling context.\r
300 @param[in] MediaId The media ID that the read request is for.\r
301 @param[in] Lba The starting logical block address to read\r
302 from on the device.\r
303 @param[in, out] Token A pointer to the token associated with the\r
304 transaction.\r
305 @param[in] BufferSize The size of the Buffer in bytes. This must be\r
306 a multiple of the intrinsic block size of the\r
307 device.\r
308 @param[out] Buffer A pointer to the destination buffer for the\r
309 data. The caller is responsible for either\r
310 having implicit or explicit ownership of the\r
311 buffer.\r
312\r
313 @retval EFI_SUCCESS The read request was queued if Token->Event\r
314 is not NULL. The data was read correctly from\r
315 the device if the Token->Event is NULL.\r
316 @retval EFI_DEVICE_ERROR The device reported an error while attempting\r
317 to perform the read operation.\r
318 @retval EFI_NO_MEDIA There is no media in the device.\r
319 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.\r
320 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of\r
321 the intrinsic block size of the device.\r
322 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not\r
323 valid, or the buffer is not on proper\r
324 alignment.\r
325 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a\r
326 lack of resources.\r
327\r
328**/\r
329EFI_STATUS\r
330EFIAPI\r
331RamDiskBlkIo2ReadBlocksEx (\r
1436aea4
MK
332 IN EFI_BLOCK_IO2_PROTOCOL *This,\r
333 IN UINT32 MediaId,\r
334 IN EFI_LBA Lba,\r
335 IN OUT EFI_BLOCK_IO2_TOKEN *Token,\r
336 IN UINTN BufferSize,\r
337 OUT VOID *Buffer\r
216fefa3
HW
338 )\r
339{\r
1436aea4
MK
340 RAM_DISK_PRIVATE_DATA *PrivateData;\r
341 EFI_STATUS Status;\r
216fefa3
HW
342\r
343 PrivateData = RAM_DISK_PRIVATE_FROM_BLKIO2 (This);\r
344\r
345 Status = RamDiskBlkIoReadBlocks (\r
1436aea4
MK
346 &PrivateData->BlockIo,\r
347 MediaId,\r
348 Lba,\r
349 BufferSize,\r
350 Buffer\r
351 );\r
216fefa3
HW
352 if (EFI_ERROR (Status)) {\r
353 return Status;\r
354 }\r
355\r
356 //\r
357 // If caller's event is given, signal it after the memory read completes.\r
358 //\r
359 if ((Token != NULL) && (Token->Event != NULL)) {\r
360 Token->TransactionStatus = EFI_SUCCESS;\r
361 gBS->SignalEvent (Token->Event);\r
362 }\r
363\r
364 return EFI_SUCCESS;\r
365}\r
366\r
216fefa3
HW
367/**\r
368 Writes a specified number of blocks to the device.\r
369\r
370 @param[in] This Indicates a pointer to the calling context.\r
371 @param[in] MediaId The media ID that the write request is for.\r
372 @param[in] Lba The starting logical block address to be\r
373 written. The caller is responsible for\r
374 writing to only legitimate locations.\r
375 @param[in, out] Token A pointer to the token associated with the\r
376 transaction.\r
377 @param[in] BufferSize The size in bytes of Buffer. This must be a\r
378 multiple of the intrinsic block size of the\r
379 device.\r
380 @param[in] Buffer A pointer to the source buffer for the data.\r
381\r
382 @retval EFI_SUCCESS The write request was queued if Event is not\r
383 NULL. The data was written correctly to the\r
384 device if the Event is NULL.\r
385 @retval EFI_WRITE_PROTECTED The device cannot be written to.\r
386 @retval EFI_NO_MEDIA There is no media in the device.\r
387 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.\r
388 @retval EFI_DEVICE_ERROR The device reported an error while attempting\r
389 to perform the write operation.\r
390 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of\r
391 the intrinsic block size of the device.\r
392 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not\r
393 valid, or the buffer is not on proper\r
394 alignment.\r
395 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a\r
396 lack of resources.\r
397\r
398**/\r
399EFI_STATUS\r
400EFIAPI\r
401RamDiskBlkIo2WriteBlocksEx (\r
1436aea4
MK
402 IN EFI_BLOCK_IO2_PROTOCOL *This,\r
403 IN UINT32 MediaId,\r
404 IN EFI_LBA Lba,\r
405 IN OUT EFI_BLOCK_IO2_TOKEN *Token,\r
406 IN UINTN BufferSize,\r
407 IN VOID *Buffer\r
216fefa3
HW
408 )\r
409{\r
1436aea4
MK
410 RAM_DISK_PRIVATE_DATA *PrivateData;\r
411 EFI_STATUS Status;\r
216fefa3
HW
412\r
413 PrivateData = RAM_DISK_PRIVATE_FROM_BLKIO2 (This);\r
414\r
415 Status = RamDiskBlkIoWriteBlocks (\r
1436aea4
MK
416 &PrivateData->BlockIo,\r
417 MediaId,\r
418 Lba,\r
419 BufferSize,\r
420 Buffer\r
421 );\r
216fefa3
HW
422 if (EFI_ERROR (Status)) {\r
423 return Status;\r
424 }\r
425\r
426 //\r
427 // If caller's event is given, signal it after the memory write completes.\r
428 //\r
429 if ((Token != NULL) && (Token->Event != NULL)) {\r
430 Token->TransactionStatus = EFI_SUCCESS;\r
431 gBS->SignalEvent (Token->Event);\r
432 }\r
433\r
434 return EFI_SUCCESS;\r
435}\r
436\r
216fefa3
HW
437/**\r
438 Flushes all modified data to a physical block device.\r
439\r
440 @param[in] This Indicates a pointer to the calling context.\r
441 @param[in, out] Token A pointer to the token associated with the\r
442 transaction.\r
443\r
444 @retval EFI_SUCCESS The flush request was queued if Event is not\r
445 NULL. All outstanding data was written\r
446 correctly to the device if the Event is NULL.\r
447 @retval EFI_DEVICE_ERROR The device reported an error while attempting\r
448 to write data.\r
449 @retval EFI_WRITE_PROTECTED The device cannot be written to.\r
450 @retval EFI_NO_MEDIA There is no media in the device.\r
451 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.\r
452 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a\r
453 lack of resources.\r
454\r
455**/\r
456EFI_STATUS\r
457EFIAPI\r
458RamDiskBlkIo2FlushBlocksEx (\r
1436aea4
MK
459 IN EFI_BLOCK_IO2_PROTOCOL *This,\r
460 IN OUT EFI_BLOCK_IO2_TOKEN *Token\r
216fefa3
HW
461 )\r
462{\r
1436aea4 463 RAM_DISK_PRIVATE_DATA *PrivateData;\r
216fefa3
HW
464\r
465 PrivateData = RAM_DISK_PRIVATE_FROM_BLKIO2 (This);\r
466\r
467 if (TRUE == PrivateData->Media.ReadOnly) {\r
468 return EFI_WRITE_PROTECTED;\r
469 }\r
470\r
471 //\r
472 // If caller's event is given, signal it directly.\r
473 //\r
474 if ((Token != NULL) && (Token->Event != NULL)) {\r
475 Token->TransactionStatus = EFI_SUCCESS;\r
476 gBS->SignalEvent (Token->Event);\r
477 }\r
478\r
479 return EFI_SUCCESS;\r
480}\r