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