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