ramdisk.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. /*++
  2. Copyright (c) 2014 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. ramdisk.c
  9. Abstract:
  10. This module implements support for creating a Block I/O protocol from a
  11. RAM Disk device.
  12. Author:
  13. Evan Green 3-Apr-2014
  14. Environment:
  15. Firmware
  16. --*/
  17. //
  18. // ------------------------------------------------------------------- Includes
  19. //
  20. #include "ueficore.h"
  21. #include <minoca/uefi/protocol/ramdisk.h>
  22. #include <minoca/uefi/protocol/blockio.h>
  23. //
  24. // --------------------------------------------------------------------- Macros
  25. //
  26. //
  27. // This macro converts from a block I/O protocol to the RAM disk context.
  28. //
  29. #define EFI_RAM_DISK_FROM_THIS(_BlockIo) \
  30. PARENT_STRUCTURE(_BlockIo, EFI_RAM_DISK_CONTEXT, BlockIo);
  31. //
  32. // ---------------------------------------------------------------- Definitions
  33. //
  34. #define EFI_RAM_DISK_MAGIC 0x444D4152 // 'DMAR'
  35. #define EFI_RAM_DISK_BLOCK_SIZE 512
  36. //
  37. // ------------------------------------------------------ Data Type Definitions
  38. //
  39. /*++
  40. Structure Description:
  41. This structure describes the RAM disk device context.
  42. Members:
  43. Magic - Stores the magic constand EFI_RAM_DISK_MAGIC.
  44. Handle - Stores the handle to the block I/O device.
  45. DevicePath - Stores a pointer to the device path.
  46. BlockCount - Stores the cached block count of the media.
  47. RamDisk - Stores the instance of the RAM disk protocol.
  48. BlockIo - Stores the block I/O protocol.
  49. Media - Stores the block I/O media information.
  50. --*/
  51. typedef struct _EFI_RAM_DISK_CONTEXT {
  52. UINT32 Magic;
  53. EFI_HANDLE Handle;
  54. EFI_DEVICE_PATH_PROTOCOL *DevicePath;
  55. UINT64 BlockCount;
  56. EFI_RAM_DISK_PROTOCOL RamDisk;
  57. EFI_BLOCK_IO_PROTOCOL BlockIo;
  58. EFI_BLOCK_IO_MEDIA Media;
  59. } EFI_RAM_DISK_CONTEXT, *PEFI_RAM_DISK_CONTEXT;
  60. /*++
  61. Structure Description:
  62. This structure defines the SD OMAP4 block I/O device path.
  63. Members:
  64. DevicePath - Stores the standard vendor-specific device path.
  65. Base - Stores the base physical address of the RAM disk.
  66. --*/
  67. typedef struct _EFI_RAM_DISK_DEVICE_PATH_NODE {
  68. VENDOR_DEVICE_PATH DevicePath;
  69. EFI_PHYSICAL_ADDRESS Base;
  70. } EFI_RAM_DISK_DEVICE_PATH_NODE, *PEFI_RAM_DISK_DEVICE_PATH_NODE;
  71. /*++
  72. Structure Description:
  73. This structure defines the RAM disk device path format.
  74. Members:
  75. Disk - Stores the RAM disk device path node.
  76. End - Stores the end device path node.
  77. --*/
  78. #pragma pack(push, 1)
  79. typedef struct _EFI_RAM_DISK_DEVICE_PATH {
  80. EFI_RAM_DISK_DEVICE_PATH_NODE Disk;
  81. EFI_DEVICE_PATH_PROTOCOL End;
  82. } PACKED EFI_RAM_DISK_DEVICE_PATH, *PEFI_RAM_DISK_DEVICE_PATH;
  83. #pragma pack(pop)
  84. //
  85. // ----------------------------------------------- Internal Function Prototypes
  86. //
  87. EFIAPI
  88. EFI_STATUS
  89. EfipRamDiskReset (
  90. EFI_BLOCK_IO_PROTOCOL *This,
  91. BOOLEAN ExtendedVerification
  92. );
  93. EFIAPI
  94. EFI_STATUS
  95. EfipRamDiskReadBlocks (
  96. EFI_BLOCK_IO_PROTOCOL *This,
  97. UINT32 MediaId,
  98. EFI_LBA Lba,
  99. UINTN BufferSize,
  100. VOID *Buffer
  101. );
  102. EFIAPI
  103. EFI_STATUS
  104. EfipRamDiskWriteBlocks (
  105. EFI_BLOCK_IO_PROTOCOL *This,
  106. UINT32 MediaId,
  107. EFI_LBA Lba,
  108. UINTN BufferSize,
  109. VOID *Buffer
  110. );
  111. EFIAPI
  112. EFI_STATUS
  113. EfipRamDiskFlushBlocks (
  114. EFI_BLOCK_IO_PROTOCOL *This
  115. );
  116. //
  117. // -------------------------------------------------------------------- Globals
  118. //
  119. EFI_RAM_DISK_DEVICE_PATH EfiRamDiskDevicePathTemplate = {
  120. {
  121. {
  122. {
  123. HARDWARE_DEVICE_PATH,
  124. HW_VENDOR_DP,
  125. sizeof(EFI_RAM_DISK_DEVICE_PATH_NODE)
  126. },
  127. EFI_RAM_DISK_PROTOCOL_GUID,
  128. },
  129. 0
  130. },
  131. {
  132. END_DEVICE_PATH_TYPE,
  133. END_ENTIRE_DEVICE_PATH_SUBTYPE,
  134. END_DEVICE_PATH_LENGTH
  135. }
  136. };
  137. EFI_GUID EfiRamDiskProtocolGuid = EFI_RAM_DISK_PROTOCOL_GUID;
  138. //
  139. // ------------------------------------------------------------------ Functions
  140. //
  141. EFI_STATUS
  142. EfiCoreEnumerateRamDisk (
  143. EFI_PHYSICAL_ADDRESS Base,
  144. UINT64 Size
  145. )
  146. /*++
  147. Routine Description:
  148. This routine enumerates a RAM disk at the given address.
  149. Arguments:
  150. Base - Supplies the base physical address of the RAM disk.
  151. Size - Supplies the size of the RAM disk.
  152. Return Value:
  153. EFI Status code.
  154. --*/
  155. {
  156. PEFI_RAM_DISK_CONTEXT Context;
  157. EFI_RAM_DISK_DEVICE_PATH *DevicePath;
  158. EFI_STATUS Status;
  159. Context = NULL;
  160. DevicePath = NULL;
  161. //
  162. // Allocate the context structure.
  163. //
  164. Status = EfiAllocatePool(EfiBootServicesData,
  165. sizeof(EFI_RAM_DISK_CONTEXT),
  166. (VOID **)&Context);
  167. if (EFI_ERROR(Status)) {
  168. goto EnumerateRamDiskEnd;
  169. }
  170. EfiSetMem(Context, sizeof(EFI_RAM_DISK_CONTEXT), 0);
  171. Context->Magic = EFI_RAM_DISK_MAGIC;
  172. //
  173. // Allocate the device path.
  174. //
  175. Status = EfiAllocatePool(EfiBootServicesData,
  176. sizeof(EFI_RAM_DISK_DEVICE_PATH),
  177. (VOID **)(&DevicePath));
  178. if (EFI_ERROR(Status)) {
  179. goto EnumerateRamDiskEnd;
  180. }
  181. EfiCopyMem(DevicePath,
  182. &EfiRamDiskDevicePathTemplate,
  183. sizeof(EFI_RAM_DISK_DEVICE_PATH));
  184. DevicePath->Disk.Base = Base;
  185. Context->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)DevicePath;
  186. Context->BlockCount = (Size + (EFI_RAM_DISK_BLOCK_SIZE - 1)) /
  187. EFI_RAM_DISK_BLOCK_SIZE;
  188. Context->RamDisk.Revision = EFI_RAM_DISK_PROTOCOL_REVISION;
  189. Context->RamDisk.Base = Base;
  190. Context->RamDisk.Length = Size;
  191. Context->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION3;
  192. Context->BlockIo.Media = &(Context->Media);
  193. Context->BlockIo.Reset = EfipRamDiskReset;
  194. Context->BlockIo.ReadBlocks = EfipRamDiskReadBlocks;
  195. Context->BlockIo.WriteBlocks = EfipRamDiskWriteBlocks;
  196. Context->BlockIo.FlushBlocks = EfipRamDiskFlushBlocks;
  197. Context->Media.MediaId = 1;
  198. Context->Media.MediaPresent = 1;
  199. Context->Media.BlockSize = EFI_RAM_DISK_BLOCK_SIZE;
  200. Context->Media.LastBlock = Context->BlockCount - 1;
  201. Status = EfiInstallMultipleProtocolInterfaces(&(Context->Handle),
  202. &EfiBlockIoProtocolGuid,
  203. &(Context->BlockIo),
  204. &EfiDevicePathProtocolGuid,
  205. Context->DevicePath,
  206. &EfiRamDiskProtocolGuid,
  207. &(Context->RamDisk),
  208. NULL);
  209. EnumerateRamDiskEnd:
  210. if (EFI_ERROR(Status)) {
  211. if (Context != NULL) {
  212. EfiFreePool(Context);
  213. }
  214. if (DevicePath != NULL) {
  215. EfiFreePool(DevicePath);
  216. }
  217. }
  218. return Status;
  219. }
  220. //
  221. // --------------------------------------------------------- Internal Functions
  222. //
  223. EFIAPI
  224. EFI_STATUS
  225. EfipRamDiskReset (
  226. EFI_BLOCK_IO_PROTOCOL *This,
  227. BOOLEAN ExtendedVerification
  228. )
  229. /*++
  230. Routine Description:
  231. This routine resets the block device.
  232. Arguments:
  233. This - Supplies a pointer to the protocol instance.
  234. ExtendedVerification - Supplies a boolean indicating whether or not the
  235. driver should perform diagnostics on reset.
  236. Return Value:
  237. EFI_SUCCESS on success.
  238. EFI_DEVICE_ERROR if the device had an error and could not complete the
  239. request.
  240. --*/
  241. {
  242. return EFI_SUCCESS;
  243. }
  244. EFIAPI
  245. EFI_STATUS
  246. EfipRamDiskReadBlocks (
  247. EFI_BLOCK_IO_PROTOCOL *This,
  248. UINT32 MediaId,
  249. EFI_LBA Lba,
  250. UINTN BufferSize,
  251. VOID *Buffer
  252. )
  253. /*++
  254. Routine Description:
  255. This routine performs a block I/O read from the device.
  256. Arguments:
  257. This - Supplies a pointer to the protocol instance.
  258. MediaId - Supplies the media identifier, which changes each time the media
  259. is replaced.
  260. Lba - Supplies the logical block address of the read.
  261. BufferSize - Supplies the size of the buffer in bytes.
  262. Buffer - Supplies the buffer where the read data will be returned.
  263. Return Value:
  264. EFI_SUCCESS on success.
  265. EFI_DEVICE_ERROR if the device had an error and could not complete the
  266. request.
  267. EFI_NO_MEDIA if there is no media in the device.
  268. EFI_MEDIA_CHANGED if the media ID does not match the current device.
  269. EFI_BAD_BUFFER_SIZE if the buffer was not a multiple of the device block
  270. size.
  271. EFI_INVALID_PARAMETER if the read request contains LBAs that are not valid,
  272. or the buffer is not properly aligned.
  273. --*/
  274. {
  275. EFI_RAM_DISK_CONTEXT *Context;
  276. VOID *DiskBuffer;
  277. Context = EFI_RAM_DISK_FROM_THIS(This);
  278. if (Lba + (BufferSize / EFI_RAM_DISK_BLOCK_SIZE) > Context->BlockCount) {
  279. return EFI_INVALID_PARAMETER;
  280. }
  281. if ((BufferSize % EFI_RAM_DISK_BLOCK_SIZE) != 0) {
  282. return EFI_BAD_BUFFER_SIZE;
  283. }
  284. DiskBuffer = (VOID *)(UINTN)(Context->RamDisk.Base +
  285. (Lba * EFI_RAM_DISK_BLOCK_SIZE));
  286. EfiCopyMem(Buffer, DiskBuffer, BufferSize);
  287. return EFI_SUCCESS;
  288. }
  289. EFIAPI
  290. EFI_STATUS
  291. EfipRamDiskWriteBlocks (
  292. EFI_BLOCK_IO_PROTOCOL *This,
  293. UINT32 MediaId,
  294. EFI_LBA Lba,
  295. UINTN BufferSize,
  296. VOID *Buffer
  297. )
  298. /*++
  299. Routine Description:
  300. This routine performs a block I/O write to the device.
  301. Arguments:
  302. This - Supplies a pointer to the protocol instance.
  303. MediaId - Supplies the media identifier, which changes each time the media
  304. is replaced.
  305. Lba - Supplies the logical block address of the write.
  306. BufferSize - Supplies the size of the buffer in bytes.
  307. Buffer - Supplies the buffer containing the data to write.
  308. Return Value:
  309. EFI_SUCCESS on success.
  310. EFI_WRITE_PROTECTED if the device cannot be written to.
  311. EFI_DEVICE_ERROR if the device had an error and could not complete the
  312. request.
  313. EFI_NO_MEDIA if there is no media in the device.
  314. EFI_MEDIA_CHANGED if the media ID does not match the current device.
  315. EFI_BAD_BUFFER_SIZE if the buffer was not a multiple of the device block
  316. size.
  317. EFI_INVALID_PARAMETER if the read request contains LBAs that are not valid,
  318. or the buffer is not properly aligned.
  319. --*/
  320. {
  321. EFI_RAM_DISK_CONTEXT *Context;
  322. VOID *DiskBuffer;
  323. Context = EFI_RAM_DISK_FROM_THIS(This);
  324. if (Lba + (BufferSize / EFI_RAM_DISK_BLOCK_SIZE) >= Context->BlockCount) {
  325. return EFI_INVALID_PARAMETER;
  326. }
  327. if ((BufferSize % EFI_RAM_DISK_BLOCK_SIZE) != 0) {
  328. return EFI_BAD_BUFFER_SIZE;
  329. }
  330. DiskBuffer = (VOID *)(UINTN)(Context->RamDisk.Base +
  331. (Lba * EFI_RAM_DISK_BLOCK_SIZE));
  332. EfiCopyMem(DiskBuffer, Buffer, BufferSize);
  333. return EFI_SUCCESS;
  334. }
  335. EFIAPI
  336. EFI_STATUS
  337. EfipRamDiskFlushBlocks (
  338. EFI_BLOCK_IO_PROTOCOL *This
  339. )
  340. /*++
  341. Routine Description:
  342. This routine flushes the block device.
  343. Arguments:
  344. This - Supplies a pointer to the protocol instance.
  345. Return Value:
  346. EFI_SUCCESS on success.
  347. EFI_DEVICE_ERROR if the device had an error and could not complete the
  348. request.
  349. EFI_NO_MEDIA if there is no media in the device.
  350. --*/
  351. {
  352. return EFI_SUCCESS;
  353. }