efi_disk.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * EFI application disk support
  4. *
  5. * Copyright (c) 2016 Alexander Graf
  6. */
  7. #define LOG_CATEGORY LOGC_EFI
  8. #include <common.h>
  9. #include <blk.h>
  10. #include <dm.h>
  11. #include <efi_loader.h>
  12. #include <fs.h>
  13. #include <log.h>
  14. #include <part.h>
  15. #include <malloc.h>
  16. struct efi_system_partition efi_system_partition;
  17. const efi_guid_t efi_block_io_guid = EFI_BLOCK_IO_PROTOCOL_GUID;
  18. /**
  19. * struct efi_disk_obj - EFI disk object
  20. *
  21. * @header: EFI object header
  22. * @ops: EFI disk I/O protocol interface
  23. * @ifname: interface name for block device
  24. * @dev_index: device index of block device
  25. * @media: block I/O media information
  26. * @dp: device path to the block device
  27. * @part: partition
  28. * @volume: simple file system protocol of the partition
  29. * @offset: offset into disk for simple partition
  30. * @desc: internal block device descriptor
  31. */
  32. struct efi_disk_obj {
  33. struct efi_object header;
  34. struct efi_block_io ops;
  35. const char *ifname;
  36. int dev_index;
  37. struct efi_block_io_media media;
  38. struct efi_device_path *dp;
  39. unsigned int part;
  40. struct efi_simple_file_system_protocol *volume;
  41. lbaint_t offset;
  42. struct blk_desc *desc;
  43. };
  44. /**
  45. * efi_disk_reset() - reset block device
  46. *
  47. * This function implements the Reset service of the EFI_BLOCK_IO_PROTOCOL.
  48. *
  49. * As U-Boot's block devices do not have a reset function simply return
  50. * EFI_SUCCESS.
  51. *
  52. * See the Unified Extensible Firmware Interface (UEFI) specification for
  53. * details.
  54. *
  55. * @this: pointer to the BLOCK_IO_PROTOCOL
  56. * @extended_verification: extended verification
  57. * Return: status code
  58. */
  59. static efi_status_t EFIAPI efi_disk_reset(struct efi_block_io *this,
  60. char extended_verification)
  61. {
  62. EFI_ENTRY("%p, %x", this, extended_verification);
  63. return EFI_EXIT(EFI_SUCCESS);
  64. }
  65. enum efi_disk_direction {
  66. EFI_DISK_READ,
  67. EFI_DISK_WRITE,
  68. };
  69. static efi_status_t efi_disk_rw_blocks(struct efi_block_io *this,
  70. u32 media_id, u64 lba, unsigned long buffer_size,
  71. void *buffer, enum efi_disk_direction direction)
  72. {
  73. struct efi_disk_obj *diskobj;
  74. struct blk_desc *desc;
  75. int blksz;
  76. int blocks;
  77. unsigned long n;
  78. diskobj = container_of(this, struct efi_disk_obj, ops);
  79. desc = (struct blk_desc *) diskobj->desc;
  80. blksz = desc->blksz;
  81. blocks = buffer_size / blksz;
  82. lba += diskobj->offset;
  83. EFI_PRINT("blocks=%x lba=%llx blksz=%x dir=%d\n",
  84. blocks, lba, blksz, direction);
  85. /* We only support full block access */
  86. if (buffer_size & (blksz - 1))
  87. return EFI_BAD_BUFFER_SIZE;
  88. if (direction == EFI_DISK_READ)
  89. n = blk_dread(desc, lba, blocks, buffer);
  90. else
  91. n = blk_dwrite(desc, lba, blocks, buffer);
  92. /* We don't do interrupts, so check for timers cooperatively */
  93. efi_timer_check();
  94. EFI_PRINT("n=%lx blocks=%x\n", n, blocks);
  95. if (n != blocks)
  96. return EFI_DEVICE_ERROR;
  97. return EFI_SUCCESS;
  98. }
  99. /**
  100. * efi_disk_read_blocks() - reads blocks from device
  101. *
  102. * This function implements the ReadBlocks service of the EFI_BLOCK_IO_PROTOCOL.
  103. *
  104. * See the Unified Extensible Firmware Interface (UEFI) specification for
  105. * details.
  106. *
  107. * @this: pointer to the BLOCK_IO_PROTOCOL
  108. * @media_id: id of the medium to be read from
  109. * @lba: starting logical block for reading
  110. * @buffer_size: size of the read buffer
  111. * @buffer: pointer to the destination buffer
  112. * Return: status code
  113. */
  114. static efi_status_t EFIAPI efi_disk_read_blocks(struct efi_block_io *this,
  115. u32 media_id, u64 lba, efi_uintn_t buffer_size,
  116. void *buffer)
  117. {
  118. void *real_buffer = buffer;
  119. efi_status_t r;
  120. if (!this)
  121. return EFI_INVALID_PARAMETER;
  122. /* TODO: check for media changes */
  123. if (media_id != this->media->media_id)
  124. return EFI_MEDIA_CHANGED;
  125. if (!this->media->media_present)
  126. return EFI_NO_MEDIA;
  127. /* media->io_align is a power of 2 */
  128. if ((uintptr_t)buffer & (this->media->io_align - 1))
  129. return EFI_INVALID_PARAMETER;
  130. if (lba * this->media->block_size + buffer_size >
  131. this->media->last_block * this->media->block_size)
  132. return EFI_INVALID_PARAMETER;
  133. #ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER
  134. if (buffer_size > EFI_LOADER_BOUNCE_BUFFER_SIZE) {
  135. r = efi_disk_read_blocks(this, media_id, lba,
  136. EFI_LOADER_BOUNCE_BUFFER_SIZE, buffer);
  137. if (r != EFI_SUCCESS)
  138. return r;
  139. return efi_disk_read_blocks(this, media_id, lba +
  140. EFI_LOADER_BOUNCE_BUFFER_SIZE / this->media->block_size,
  141. buffer_size - EFI_LOADER_BOUNCE_BUFFER_SIZE,
  142. buffer + EFI_LOADER_BOUNCE_BUFFER_SIZE);
  143. }
  144. real_buffer = efi_bounce_buffer;
  145. #endif
  146. EFI_ENTRY("%p, %x, %llx, %zx, %p", this, media_id, lba,
  147. buffer_size, buffer);
  148. r = efi_disk_rw_blocks(this, media_id, lba, buffer_size, real_buffer,
  149. EFI_DISK_READ);
  150. /* Copy from bounce buffer to real buffer if necessary */
  151. if ((r == EFI_SUCCESS) && (real_buffer != buffer))
  152. memcpy(buffer, real_buffer, buffer_size);
  153. return EFI_EXIT(r);
  154. }
  155. /**
  156. * efi_disk_write_blocks() - writes blocks to device
  157. *
  158. * This function implements the WriteBlocks service of the
  159. * EFI_BLOCK_IO_PROTOCOL.
  160. *
  161. * See the Unified Extensible Firmware Interface (UEFI) specification for
  162. * details.
  163. *
  164. * @this: pointer to the BLOCK_IO_PROTOCOL
  165. * @media_id: id of the medium to be written to
  166. * @lba: starting logical block for writing
  167. * @buffer_size: size of the write buffer
  168. * @buffer: pointer to the source buffer
  169. * Return: status code
  170. */
  171. static efi_status_t EFIAPI efi_disk_write_blocks(struct efi_block_io *this,
  172. u32 media_id, u64 lba, efi_uintn_t buffer_size,
  173. void *buffer)
  174. {
  175. void *real_buffer = buffer;
  176. efi_status_t r;
  177. if (!this)
  178. return EFI_INVALID_PARAMETER;
  179. if (this->media->read_only)
  180. return EFI_WRITE_PROTECTED;
  181. /* TODO: check for media changes */
  182. if (media_id != this->media->media_id)
  183. return EFI_MEDIA_CHANGED;
  184. if (!this->media->media_present)
  185. return EFI_NO_MEDIA;
  186. /* media->io_align is a power of 2 */
  187. if ((uintptr_t)buffer & (this->media->io_align - 1))
  188. return EFI_INVALID_PARAMETER;
  189. if (lba * this->media->block_size + buffer_size >
  190. this->media->last_block * this->media->block_size)
  191. return EFI_INVALID_PARAMETER;
  192. #ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER
  193. if (buffer_size > EFI_LOADER_BOUNCE_BUFFER_SIZE) {
  194. r = efi_disk_write_blocks(this, media_id, lba,
  195. EFI_LOADER_BOUNCE_BUFFER_SIZE, buffer);
  196. if (r != EFI_SUCCESS)
  197. return r;
  198. return efi_disk_write_blocks(this, media_id, lba +
  199. EFI_LOADER_BOUNCE_BUFFER_SIZE / this->media->block_size,
  200. buffer_size - EFI_LOADER_BOUNCE_BUFFER_SIZE,
  201. buffer + EFI_LOADER_BOUNCE_BUFFER_SIZE);
  202. }
  203. real_buffer = efi_bounce_buffer;
  204. #endif
  205. EFI_ENTRY("%p, %x, %llx, %zx, %p", this, media_id, lba,
  206. buffer_size, buffer);
  207. /* Populate bounce buffer if necessary */
  208. if (real_buffer != buffer)
  209. memcpy(real_buffer, buffer, buffer_size);
  210. r = efi_disk_rw_blocks(this, media_id, lba, buffer_size, real_buffer,
  211. EFI_DISK_WRITE);
  212. return EFI_EXIT(r);
  213. }
  214. /**
  215. * efi_disk_flush_blocks() - flushes modified data to the device
  216. *
  217. * This function implements the FlushBlocks service of the
  218. * EFI_BLOCK_IO_PROTOCOL.
  219. *
  220. * As we always write synchronously nothing is done here.
  221. *
  222. * See the Unified Extensible Firmware Interface (UEFI) specification for
  223. * details.
  224. *
  225. * @this: pointer to the BLOCK_IO_PROTOCOL
  226. * Return: status code
  227. */
  228. static efi_status_t EFIAPI efi_disk_flush_blocks(struct efi_block_io *this)
  229. {
  230. EFI_ENTRY("%p", this);
  231. return EFI_EXIT(EFI_SUCCESS);
  232. }
  233. static const struct efi_block_io block_io_disk_template = {
  234. .reset = &efi_disk_reset,
  235. .read_blocks = &efi_disk_read_blocks,
  236. .write_blocks = &efi_disk_write_blocks,
  237. .flush_blocks = &efi_disk_flush_blocks,
  238. };
  239. /**
  240. * efi_fs_from_path() - retrieve simple file system protocol
  241. *
  242. * Gets the simple file system protocol for a file device path.
  243. *
  244. * The full path provided is split into device part and into a file
  245. * part. The device part is used to find the handle on which the
  246. * simple file system protocol is installed.
  247. *
  248. * @full_path: device path including device and file
  249. * Return: simple file system protocol
  250. */
  251. struct efi_simple_file_system_protocol *
  252. efi_fs_from_path(struct efi_device_path *full_path)
  253. {
  254. struct efi_object *efiobj;
  255. struct efi_handler *handler;
  256. struct efi_device_path *device_path;
  257. struct efi_device_path *file_path;
  258. efi_status_t ret;
  259. /* Split the path into a device part and a file part */
  260. ret = efi_dp_split_file_path(full_path, &device_path, &file_path);
  261. if (ret != EFI_SUCCESS)
  262. return NULL;
  263. efi_free_pool(file_path);
  264. /* Get the EFI object for the partition */
  265. efiobj = efi_dp_find_obj(device_path, NULL);
  266. efi_free_pool(device_path);
  267. if (!efiobj)
  268. return NULL;
  269. /* Find the simple file system protocol */
  270. ret = efi_search_protocol(efiobj, &efi_simple_file_system_protocol_guid,
  271. &handler);
  272. if (ret != EFI_SUCCESS)
  273. return NULL;
  274. /* Return the simple file system protocol for the partition */
  275. return handler->protocol_interface;
  276. }
  277. /**
  278. * efi_fs_exists() - check if a partition bears a file system
  279. *
  280. * @desc: block device descriptor
  281. * @part: partition number
  282. * Return: 1 if a file system exists on the partition
  283. * 0 otherwise
  284. */
  285. static int efi_fs_exists(struct blk_desc *desc, int part)
  286. {
  287. if (fs_set_blk_dev_with_part(desc, part))
  288. return 0;
  289. if (fs_get_type() == FS_TYPE_ANY)
  290. return 0;
  291. fs_close();
  292. return 1;
  293. }
  294. /**
  295. * efi_disk_add_dev() - create a handle for a partition or disk
  296. *
  297. * @parent: parent handle
  298. * @dp_parent: parent device path
  299. * @if_typename: interface name for block device
  300. * @desc: internal block device
  301. * @dev_index: device index for block device
  302. * @offset: offset into disk for simple partitions
  303. * @part: partition
  304. * @disk: pointer to receive the created handle
  305. * Return: disk object
  306. */
  307. static efi_status_t efi_disk_add_dev(
  308. efi_handle_t parent,
  309. struct efi_device_path *dp_parent,
  310. const char *if_typename,
  311. struct blk_desc *desc,
  312. int dev_index,
  313. lbaint_t offset,
  314. unsigned int part,
  315. struct efi_disk_obj **disk)
  316. {
  317. struct efi_disk_obj *diskobj;
  318. struct efi_object *handle;
  319. efi_status_t ret;
  320. /* Don't add empty devices */
  321. if (!desc->lba)
  322. return EFI_NOT_READY;
  323. diskobj = calloc(1, sizeof(*diskobj));
  324. if (!diskobj)
  325. return EFI_OUT_OF_RESOURCES;
  326. /* Hook up to the device list */
  327. efi_add_handle(&diskobj->header);
  328. /* Fill in object data */
  329. if (part) {
  330. struct efi_device_path *node = efi_dp_part_node(desc, part);
  331. diskobj->dp = efi_dp_append_node(dp_parent, node);
  332. efi_free_pool(node);
  333. } else {
  334. diskobj->dp = efi_dp_from_part(desc, part);
  335. }
  336. diskobj->part = part;
  337. /*
  338. * Install the device path and the block IO protocol.
  339. *
  340. * InstallMultipleProtocolInterfaces() checks if the device path is
  341. * already installed on an other handle and returns EFI_ALREADY_STARTED
  342. * in this case.
  343. */
  344. handle = &diskobj->header;
  345. ret = EFI_CALL(efi_install_multiple_protocol_interfaces(
  346. &handle, &efi_guid_device_path, diskobj->dp,
  347. &efi_block_io_guid, &diskobj->ops, NULL));
  348. if (ret != EFI_SUCCESS)
  349. return ret;
  350. /*
  351. * On partitions or whole disks without partitions install the
  352. * simple file system protocol if a file system is available.
  353. */
  354. if ((part || desc->part_type == PART_TYPE_UNKNOWN) &&
  355. efi_fs_exists(desc, part)) {
  356. diskobj->volume = efi_simple_file_system(desc, part,
  357. diskobj->dp);
  358. ret = efi_add_protocol(&diskobj->header,
  359. &efi_simple_file_system_protocol_guid,
  360. diskobj->volume);
  361. if (ret != EFI_SUCCESS)
  362. return ret;
  363. }
  364. diskobj->ops = block_io_disk_template;
  365. diskobj->ifname = if_typename;
  366. diskobj->dev_index = dev_index;
  367. diskobj->offset = offset;
  368. diskobj->desc = desc;
  369. /* Fill in EFI IO Media info (for read/write callbacks) */
  370. diskobj->media.removable_media = desc->removable;
  371. diskobj->media.media_present = 1;
  372. /*
  373. * MediaID is just an arbitrary counter.
  374. * We have to change it if the medium is removed or changed.
  375. */
  376. diskobj->media.media_id = 1;
  377. diskobj->media.block_size = desc->blksz;
  378. diskobj->media.io_align = desc->blksz;
  379. diskobj->media.last_block = desc->lba - offset;
  380. if (part)
  381. diskobj->media.logical_partition = 1;
  382. diskobj->ops.media = &diskobj->media;
  383. if (disk)
  384. *disk = diskobj;
  385. /* Store first EFI system partition */
  386. if (part && !efi_system_partition.if_type) {
  387. int r;
  388. struct disk_partition info;
  389. r = part_get_info(desc, part, &info);
  390. if (r)
  391. return EFI_DEVICE_ERROR;
  392. if (info.bootable & PART_EFI_SYSTEM_PARTITION) {
  393. efi_system_partition.if_type = desc->if_type;
  394. efi_system_partition.devnum = desc->devnum;
  395. efi_system_partition.part = part;
  396. EFI_PRINT("EFI system partition: %s %d:%d\n",
  397. blk_get_if_type_name(desc->if_type),
  398. desc->devnum, part);
  399. }
  400. }
  401. return EFI_SUCCESS;
  402. }
  403. /**
  404. * efi_disk_create_partitions() - create handles and protocols for partitions
  405. *
  406. * Create handles and protocols for the partitions of a block device.
  407. *
  408. * @parent: handle of the parent disk
  409. * @desc: block device
  410. * @if_typename: interface type
  411. * @diskid: device number
  412. * @pdevname: device name
  413. * Return: number of partitions created
  414. */
  415. int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc,
  416. const char *if_typename, int diskid,
  417. const char *pdevname)
  418. {
  419. int disks = 0;
  420. char devname[32] = { 0 }; /* dp->str is u16[32] long */
  421. struct disk_partition info;
  422. int part;
  423. struct efi_device_path *dp = NULL;
  424. efi_status_t ret;
  425. struct efi_handler *handler;
  426. /* Get the device path of the parent */
  427. ret = efi_search_protocol(parent, &efi_guid_device_path, &handler);
  428. if (ret == EFI_SUCCESS)
  429. dp = handler->protocol_interface;
  430. /* Add devices for each partition */
  431. for (part = 1; part <= MAX_SEARCH_PARTITIONS; part++) {
  432. if (part_get_info(desc, part, &info))
  433. continue;
  434. snprintf(devname, sizeof(devname), "%s:%d", pdevname,
  435. part);
  436. ret = efi_disk_add_dev(parent, dp, if_typename, desc, diskid,
  437. info.start, part, NULL);
  438. if (ret != EFI_SUCCESS) {
  439. log_err("Adding partition %s failed\n", pdevname);
  440. continue;
  441. }
  442. disks++;
  443. }
  444. return disks;
  445. }
  446. /**
  447. * efi_disk_register() - register block devices
  448. *
  449. * U-Boot doesn't have a list of all online disk devices. So when running our
  450. * EFI payload, we scan through all of the potentially available ones and
  451. * store them in our object pool.
  452. *
  453. * This function is called in efi_init_obj_list().
  454. *
  455. * TODO(sjg@chromium.org): Actually with CONFIG_BLK, U-Boot does have this.
  456. * Consider converting the code to look up devices as needed. The EFI device
  457. * could be a child of the UCLASS_BLK block device, perhaps.
  458. *
  459. * Return: status code
  460. */
  461. efi_status_t efi_disk_register(void)
  462. {
  463. struct efi_disk_obj *disk;
  464. int disks = 0;
  465. efi_status_t ret;
  466. #ifdef CONFIG_BLK
  467. struct udevice *dev;
  468. for (uclass_first_device_check(UCLASS_BLK, &dev); dev;
  469. uclass_next_device_check(&dev)) {
  470. struct blk_desc *desc = dev_get_uclass_platdata(dev);
  471. const char *if_typename = blk_get_if_type_name(desc->if_type);
  472. /* Add block device for the full device */
  473. log_info("Scanning disk %s...\n", dev->name);
  474. ret = efi_disk_add_dev(NULL, NULL, if_typename,
  475. desc, desc->devnum, 0, 0, &disk);
  476. if (ret == EFI_NOT_READY) {
  477. log_notice("Disk %s not ready\n", dev->name);
  478. continue;
  479. }
  480. if (ret) {
  481. log_err("ERROR: failure to add disk device %s, r = %lu\n",
  482. dev->name, ret & ~EFI_ERROR_MASK);
  483. return ret;
  484. }
  485. disks++;
  486. /* Partitions show up as block devices in EFI */
  487. disks += efi_disk_create_partitions(
  488. &disk->header, desc, if_typename,
  489. desc->devnum, dev->name);
  490. }
  491. #else
  492. int i, if_type;
  493. /* Search for all available disk devices */
  494. for (if_type = 0; if_type < IF_TYPE_COUNT; if_type++) {
  495. const struct blk_driver *cur_drvr;
  496. const char *if_typename;
  497. cur_drvr = blk_driver_lookup_type(if_type);
  498. if (!cur_drvr)
  499. continue;
  500. if_typename = cur_drvr->if_typename;
  501. log_info("Scanning disks on %s...\n", if_typename);
  502. for (i = 0; i < 4; i++) {
  503. struct blk_desc *desc;
  504. char devname[32] = { 0 }; /* dp->str is u16[32] long */
  505. desc = blk_get_devnum_by_type(if_type, i);
  506. if (!desc)
  507. continue;
  508. if (desc->type == DEV_TYPE_UNKNOWN)
  509. continue;
  510. snprintf(devname, sizeof(devname), "%s%d",
  511. if_typename, i);
  512. /* Add block device for the full device */
  513. ret = efi_disk_add_dev(NULL, NULL, if_typename, desc,
  514. i, 0, 0, &disk);
  515. if (ret == EFI_NOT_READY) {
  516. log_notice("Disk %s not ready\n", devname);
  517. continue;
  518. }
  519. if (ret) {
  520. log_err("ERROR: failure to add disk device %s, r = %lu\n",
  521. devname, ret & ~EFI_ERROR_MASK);
  522. return ret;
  523. }
  524. disks++;
  525. /* Partitions show up as block devices in EFI */
  526. disks += efi_disk_create_partitions
  527. (&disk->header, desc,
  528. if_typename, i, devname);
  529. }
  530. }
  531. #endif
  532. log_info("Found %d disks\n", disks);
  533. return EFI_SUCCESS;
  534. }
  535. /**
  536. * efi_disk_is_system_part() - check if handle refers to an EFI system partition
  537. *
  538. * @handle: handle of partition
  539. *
  540. * Return: true if handle refers to an EFI system partition
  541. */
  542. bool efi_disk_is_system_part(efi_handle_t handle)
  543. {
  544. struct efi_handler *handler;
  545. struct efi_disk_obj *diskobj;
  546. struct disk_partition info;
  547. efi_status_t ret;
  548. int r;
  549. /* check if this is a block device */
  550. ret = efi_search_protocol(handle, &efi_block_io_guid, &handler);
  551. if (ret != EFI_SUCCESS)
  552. return false;
  553. diskobj = container_of(handle, struct efi_disk_obj, header);
  554. r = part_get_info(diskobj->desc, diskobj->part, &info);
  555. if (r)
  556. return false;
  557. return !!(info.bootable & PART_EFI_SYSTEM_PARTITION);
  558. }