blob: 47b583cc5e12d2c09117fadadcf3e557b6fc8256 [file] [log] [blame]
Tom Rini70df9d62018-05-07 17:02:21 -04001// SPDX-License-Identifier: GPL-2.0+
Alexander Grafe83be452016-03-04 01:10:02 +01002/*
3 * EFI application disk support
4 *
5 * Copyright (c) 2016 Alexander Graf
Alexander Grafe83be452016-03-04 01:10:02 +01006 */
7
Heinrich Schuchardt37240572020-07-17 20:33:05 +02008#define LOG_CATEGORY LOGC_EFI
9
Simon Glasse3dfa912016-05-01 13:52:32 -060010#include <blk.h>
Simon Glass302d4f82016-05-14 14:03:05 -060011#include <dm.h>
AKASHI Takahiro2381f2e2022-04-19 10:05:12 +090012#include <dm/device-internal.h>
13#include <dm/tag.h>
Simon Glass37972f42025-05-24 11:28:21 -060014#include <efi_device_path.h>
AKASHI Takahiro2381f2e2022-04-19 10:05:12 +090015#include <event.h>
Heinrich Schuchardt175b0a92022-10-08 09:11:54 +020016#include <efi_driver.h>
Alexander Grafe83be452016-03-04 01:10:02 +010017#include <efi_loader.h>
AKASHI Takahiro120a01a2019-10-07 14:59:38 +090018#include <fs.h>
Heinrich Schuchardt37240572020-07-17 20:33:05 +020019#include <log.h>
Alexander Grafe83be452016-03-04 01:10:02 +010020#include <part.h>
21#include <malloc.h>
22
Heinrich Schuchardt0397d812022-10-21 08:33:44 +020023struct efi_system_partition efi_system_partition = {
24 .uclass_id = UCLASS_INVALID,
25};
Heinrich Schuchardta9931732020-03-19 15:16:31 +010026
Heinrich Schuchardt788ad412019-04-20 07:39:11 +020027const efi_guid_t efi_block_io_guid = EFI_BLOCK_IO_PROTOCOL_GUID;
Heinrich Schuchardt26397622021-02-02 17:53:14 +010028const efi_guid_t efi_system_partition_guid = PARTITION_SYSTEM_GUID;
Alexander Grafe83be452016-03-04 01:10:02 +010029
Heinrich Schuchardt72928722018-09-26 05:27:56 +020030/**
31 * struct efi_disk_obj - EFI disk object
32 *
33 * @header: EFI object header
34 * @ops: EFI disk I/O protocol interface
Heinrich Schuchardt72928722018-09-26 05:27:56 +020035 * @media: block I/O media information
36 * @dp: device path to the block device
Heinrich Schuchardt72928722018-09-26 05:27:56 +020037 * @volume: simple file system protocol of the partition
Heinrich Schuchardt72928722018-09-26 05:27:56 +020038 */
Alexander Grafe83be452016-03-04 01:10:02 +010039struct efi_disk_obj {
Heinrich Schuchardt72928722018-09-26 05:27:56 +020040 struct efi_object header;
Alexander Grafe83be452016-03-04 01:10:02 +010041 struct efi_block_io ops;
Alexander Grafe83be452016-03-04 01:10:02 +010042 struct efi_block_io_media media;
Rob Clarka83272f2017-09-13 18:05:31 -040043 struct efi_device_path *dp;
Rob Clark53142032017-09-13 18:05:34 -040044 struct efi_simple_file_system_protocol *volume;
Alexander Grafe83be452016-03-04 01:10:02 +010045};
46
Heinrich Schuchardt670198c2019-09-05 20:13:46 +020047/**
48 * efi_disk_reset() - reset block device
49 *
50 * This function implements the Reset service of the EFI_BLOCK_IO_PROTOCOL.
51 *
52 * As U-Boot's block devices do not have a reset function simply return
53 * EFI_SUCCESS.
54 *
55 * See the Unified Extensible Firmware Interface (UEFI) specification for
56 * details.
57 *
58 * @this: pointer to the BLOCK_IO_PROTOCOL
59 * @extended_verification: extended verification
60 * Return: status code
61 */
Alexander Grafe83be452016-03-04 01:10:02 +010062static efi_status_t EFIAPI efi_disk_reset(struct efi_block_io *this,
63 char extended_verification)
64{
65 EFI_ENTRY("%p, %x", this, extended_verification);
Heinrich Schuchardt670198c2019-09-05 20:13:46 +020066 return EFI_EXIT(EFI_SUCCESS);
Alexander Grafe83be452016-03-04 01:10:02 +010067}
68
AKASHI Takahiroba647af2022-05-12 11:29:01 +090069/**
70 * efi_disk_is_removable() - check if the device is removable media
71 * @handle: efi object handle;
72 *
73 * Examine the device and determine if the device is a local block device
74 * and removable media.
75 *
76 * Return: true if removable, false otherwise
77 */
78bool efi_disk_is_removable(efi_handle_t handle)
79{
80 struct efi_handler *handler;
81 struct efi_block_io *io;
82 efi_status_t ret;
83
84 ret = efi_search_protocol(handle, &efi_block_io_guid, &handler);
85 if (ret != EFI_SUCCESS)
86 return false;
87
88 io = handler->protocol_interface;
89
90 if (!io || !io->media)
91 return false;
92
93 return (bool)io->media->removable_media;
94}
95
Alexander Grafe83be452016-03-04 01:10:02 +010096enum efi_disk_direction {
97 EFI_DISK_READ,
98 EFI_DISK_WRITE,
99};
100
Heinrich Schuchardt9ce06172017-08-26 22:33:13 +0200101static efi_status_t efi_disk_rw_blocks(struct efi_block_io *this,
Alexander Grafe83be452016-03-04 01:10:02 +0100102 u32 media_id, u64 lba, unsigned long buffer_size,
103 void *buffer, enum efi_disk_direction direction)
104{
105 struct efi_disk_obj *diskobj;
Alexander Grafe83be452016-03-04 01:10:02 +0100106 int blksz;
107 int blocks;
108 unsigned long n;
109
Alexander Grafe83be452016-03-04 01:10:02 +0100110 diskobj = container_of(this, struct efi_disk_obj, ops);
AKASHI Takahiro808ece12022-04-19 10:05:17 +0900111 blksz = diskobj->media.block_size;
Alexander Grafe83be452016-03-04 01:10:02 +0100112 blocks = buffer_size / blksz;
113
Heinrich Schuchardtee6ef8b2019-09-05 19:43:17 +0200114 EFI_PRINT("blocks=%x lba=%llx blksz=%x dir=%d\n",
115 blocks, lba, blksz, direction);
Alexander Grafe83be452016-03-04 01:10:02 +0100116
117 /* We only support full block access */
118 if (buffer_size & (blksz - 1))
Heinrich Schuchardt35922522019-09-05 19:31:23 +0200119 return EFI_BAD_BUFFER_SIZE;
Alexander Grafe83be452016-03-04 01:10:02 +0100120
AKASHI Takahiro8c591132022-04-28 13:49:16 +0900121 if (CONFIG_IS_ENABLED(PARTITIONS) &&
Masahisa Kojimac9611082022-07-22 11:39:10 +0900122 device_get_uclass_id(diskobj->header.dev) == UCLASS_PARTITION) {
AKASHI Takahiro8c591132022-04-28 13:49:16 +0900123 if (direction == EFI_DISK_READ)
Simon Glass4e93eea2022-10-20 18:22:52 -0600124 n = disk_blk_read(diskobj->header.dev, lba, blocks,
125 buffer);
AKASHI Takahiro8c591132022-04-28 13:49:16 +0900126 else
Simon Glass4e93eea2022-10-20 18:22:52 -0600127 n = disk_blk_write(diskobj->header.dev, lba, blocks,
128 buffer);
AKASHI Takahiro8c591132022-04-28 13:49:16 +0900129 } else {
130 /* dev is a block device (UCLASS_BLK) */
131 struct blk_desc *desc;
AKASHI Takahiro808ece12022-04-19 10:05:17 +0900132
Masahisa Kojimac9611082022-07-22 11:39:10 +0900133 desc = dev_get_uclass_plat(diskobj->header.dev);
AKASHI Takahiro8c591132022-04-28 13:49:16 +0900134 if (direction == EFI_DISK_READ)
135 n = blk_dread(desc, lba, blocks, buffer);
136 else
137 n = blk_dwrite(desc, lba, blocks, buffer);
138 }
Alexander Grafe83be452016-03-04 01:10:02 +0100139
140 /* We don't do interrupts, so check for timers cooperatively */
141 efi_timer_check();
142
Heinrich Schuchardtee6ef8b2019-09-05 19:43:17 +0200143 EFI_PRINT("n=%lx blocks=%x\n", n, blocks);
Alexander Graf62a67482016-06-02 11:38:27 +0200144
Alexander Grafe83be452016-03-04 01:10:02 +0100145 if (n != blocks)
Rob Clark99c43872017-07-25 20:28:29 -0400146 return EFI_DEVICE_ERROR;
Alexander Grafe83be452016-03-04 01:10:02 +0100147
Rob Clark99c43872017-07-25 20:28:29 -0400148 return EFI_SUCCESS;
Alexander Grafe83be452016-03-04 01:10:02 +0100149}
150
Heinrich Schuchardt76f57892020-04-10 17:10:34 +0200151/**
152 * efi_disk_read_blocks() - reads blocks from device
153 *
154 * This function implements the ReadBlocks service of the EFI_BLOCK_IO_PROTOCOL.
155 *
156 * See the Unified Extensible Firmware Interface (UEFI) specification for
157 * details.
158 *
159 * @this: pointer to the BLOCK_IO_PROTOCOL
160 * @media_id: id of the medium to be read from
161 * @lba: starting logical block for reading
162 * @buffer_size: size of the read buffer
163 * @buffer: pointer to the destination buffer
164 * Return: status code
165 */
Simon Glassc2194bf2016-09-25 15:27:32 -0600166static efi_status_t EFIAPI efi_disk_read_blocks(struct efi_block_io *this,
Heinrich Schuchardt0844f792018-01-19 20:24:48 +0100167 u32 media_id, u64 lba, efi_uintn_t buffer_size,
Alexander Grafe83be452016-03-04 01:10:02 +0100168 void *buffer)
169{
Alexander Graf7c00a3c2016-05-11 18:25:48 +0200170 void *real_buffer = buffer;
171 efi_status_t r;
172
Heinrich Schuchardt35922522019-09-05 19:31:23 +0200173 if (!this)
174 return EFI_INVALID_PARAMETER;
175 /* TODO: check for media changes */
176 if (media_id != this->media->media_id)
177 return EFI_MEDIA_CHANGED;
178 if (!this->media->media_present)
179 return EFI_NO_MEDIA;
Heinrich Schuchardt0bb73892021-01-23 19:33:11 +0100180 /* media->io_align is a power of 2 or 0 */
181 if (this->media->io_align &&
182 (uintptr_t)buffer & (this->media->io_align - 1))
Heinrich Schuchardt35922522019-09-05 19:31:23 +0200183 return EFI_INVALID_PARAMETER;
184 if (lba * this->media->block_size + buffer_size >
Jesper Schmitz Mouridsenf1424932021-02-09 17:17:17 +0100185 (this->media->last_block + 1) * this->media->block_size)
Heinrich Schuchardt35922522019-09-05 19:31:23 +0200186 return EFI_INVALID_PARAMETER;
187
Alexander Graf7c00a3c2016-05-11 18:25:48 +0200188#ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER
189 if (buffer_size > EFI_LOADER_BOUNCE_BUFFER_SIZE) {
190 r = efi_disk_read_blocks(this, media_id, lba,
191 EFI_LOADER_BOUNCE_BUFFER_SIZE, buffer);
192 if (r != EFI_SUCCESS)
193 return r;
194 return efi_disk_read_blocks(this, media_id, lba +
195 EFI_LOADER_BOUNCE_BUFFER_SIZE / this->media->block_size,
196 buffer_size - EFI_LOADER_BOUNCE_BUFFER_SIZE,
197 buffer + EFI_LOADER_BOUNCE_BUFFER_SIZE);
198 }
199
200 real_buffer = efi_bounce_buffer;
201#endif
202
Masahiro Yamadac7570a32018-08-06 20:47:40 +0900203 EFI_ENTRY("%p, %x, %llx, %zx, %p", this, media_id, lba,
Alexander Graf7c00a3c2016-05-11 18:25:48 +0200204 buffer_size, buffer);
205
206 r = efi_disk_rw_blocks(this, media_id, lba, buffer_size, real_buffer,
207 EFI_DISK_READ);
208
209 /* Copy from bounce buffer to real buffer if necessary */
210 if ((r == EFI_SUCCESS) && (real_buffer != buffer))
211 memcpy(buffer, real_buffer, buffer_size);
212
213 return EFI_EXIT(r);
Alexander Grafe83be452016-03-04 01:10:02 +0100214}
215
Heinrich Schuchardt76f57892020-04-10 17:10:34 +0200216/**
217 * efi_disk_write_blocks() - writes blocks to device
218 *
219 * This function implements the WriteBlocks service of the
220 * EFI_BLOCK_IO_PROTOCOL.
221 *
222 * See the Unified Extensible Firmware Interface (UEFI) specification for
223 * details.
224 *
225 * @this: pointer to the BLOCK_IO_PROTOCOL
226 * @media_id: id of the medium to be written to
227 * @lba: starting logical block for writing
228 * @buffer_size: size of the write buffer
229 * @buffer: pointer to the source buffer
230 * Return: status code
231 */
Simon Glassc2194bf2016-09-25 15:27:32 -0600232static efi_status_t EFIAPI efi_disk_write_blocks(struct efi_block_io *this,
Heinrich Schuchardt0844f792018-01-19 20:24:48 +0100233 u32 media_id, u64 lba, efi_uintn_t buffer_size,
Alexander Grafe83be452016-03-04 01:10:02 +0100234 void *buffer)
235{
Alexander Graf7c00a3c2016-05-11 18:25:48 +0200236 void *real_buffer = buffer;
237 efi_status_t r;
238
Heinrich Schuchardt35922522019-09-05 19:31:23 +0200239 if (!this)
240 return EFI_INVALID_PARAMETER;
241 if (this->media->read_only)
242 return EFI_WRITE_PROTECTED;
243 /* TODO: check for media changes */
244 if (media_id != this->media->media_id)
245 return EFI_MEDIA_CHANGED;
246 if (!this->media->media_present)
247 return EFI_NO_MEDIA;
Heinrich Schuchardt0bb73892021-01-23 19:33:11 +0100248 /* media->io_align is a power of 2 or 0 */
249 if (this->media->io_align &&
250 (uintptr_t)buffer & (this->media->io_align - 1))
Heinrich Schuchardt35922522019-09-05 19:31:23 +0200251 return EFI_INVALID_PARAMETER;
252 if (lba * this->media->block_size + buffer_size >
Jesper Schmitz Mouridsenf1424932021-02-09 17:17:17 +0100253 (this->media->last_block + 1) * this->media->block_size)
Heinrich Schuchardt35922522019-09-05 19:31:23 +0200254 return EFI_INVALID_PARAMETER;
255
Alexander Graf7c00a3c2016-05-11 18:25:48 +0200256#ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER
257 if (buffer_size > EFI_LOADER_BOUNCE_BUFFER_SIZE) {
258 r = efi_disk_write_blocks(this, media_id, lba,
259 EFI_LOADER_BOUNCE_BUFFER_SIZE, buffer);
260 if (r != EFI_SUCCESS)
261 return r;
262 return efi_disk_write_blocks(this, media_id, lba +
263 EFI_LOADER_BOUNCE_BUFFER_SIZE / this->media->block_size,
264 buffer_size - EFI_LOADER_BOUNCE_BUFFER_SIZE,
265 buffer + EFI_LOADER_BOUNCE_BUFFER_SIZE);
266 }
267
268 real_buffer = efi_bounce_buffer;
269#endif
270
Masahiro Yamadac7570a32018-08-06 20:47:40 +0900271 EFI_ENTRY("%p, %x, %llx, %zx, %p", this, media_id, lba,
Alexander Graf7c00a3c2016-05-11 18:25:48 +0200272 buffer_size, buffer);
273
274 /* Populate bounce buffer if necessary */
275 if (real_buffer != buffer)
276 memcpy(real_buffer, buffer, buffer_size);
277
278 r = efi_disk_rw_blocks(this, media_id, lba, buffer_size, real_buffer,
279 EFI_DISK_WRITE);
280
281 return EFI_EXIT(r);
Alexander Grafe83be452016-03-04 01:10:02 +0100282}
283
Heinrich Schuchardt76f57892020-04-10 17:10:34 +0200284/**
285 * efi_disk_flush_blocks() - flushes modified data to the device
286 *
287 * This function implements the FlushBlocks service of the
288 * EFI_BLOCK_IO_PROTOCOL.
289 *
290 * As we always write synchronously nothing is done here.
291 *
292 * See the Unified Extensible Firmware Interface (UEFI) specification for
293 * details.
294 *
295 * @this: pointer to the BLOCK_IO_PROTOCOL
296 * Return: status code
297 */
Alexander Grafe83be452016-03-04 01:10:02 +0100298static efi_status_t EFIAPI efi_disk_flush_blocks(struct efi_block_io *this)
299{
Alexander Grafe83be452016-03-04 01:10:02 +0100300 EFI_ENTRY("%p", this);
301 return EFI_EXIT(EFI_SUCCESS);
302}
303
304static const struct efi_block_io block_io_disk_template = {
305 .reset = &efi_disk_reset,
306 .read_blocks = &efi_disk_read_blocks,
307 .write_blocks = &efi_disk_write_blocks,
308 .flush_blocks = &efi_disk_flush_blocks,
309};
310
Heinrich Schuchardt62036062020-03-19 13:49:34 +0100311/**
312 * efi_fs_from_path() - retrieve simple file system protocol
313 *
314 * Gets the simple file system protocol for a file device path.
Heinrich Schuchardt39578762018-01-19 20:24:39 +0100315 *
316 * The full path provided is split into device part and into a file
317 * part. The device part is used to find the handle on which the
318 * simple file system protocol is installed.
319 *
Heinrich Schuchardt62036062020-03-19 13:49:34 +0100320 * @full_path: device path including device and file
321 * Return: simple file system protocol
Rob Clark53142032017-09-13 18:05:34 -0400322 */
323struct efi_simple_file_system_protocol *
Heinrich Schuchardt39578762018-01-19 20:24:39 +0100324efi_fs_from_path(struct efi_device_path *full_path)
Rob Clark53142032017-09-13 18:05:34 -0400325{
326 struct efi_object *efiobj;
Heinrich Schuchardt39578762018-01-19 20:24:39 +0100327 struct efi_handler *handler;
328 struct efi_device_path *device_path;
329 struct efi_device_path *file_path;
330 efi_status_t ret;
Rob Clark53142032017-09-13 18:05:34 -0400331
Heinrich Schuchardt39578762018-01-19 20:24:39 +0100332 /* Split the path into a device part and a file part */
333 ret = efi_dp_split_file_path(full_path, &device_path, &file_path);
334 if (ret != EFI_SUCCESS)
335 return NULL;
336 efi_free_pool(file_path);
337
338 /* Get the EFI object for the partition */
Heinrich Schuchardt0a04a412022-03-19 06:35:43 +0100339 efiobj = efi_dp_find_obj(device_path, NULL, NULL);
Heinrich Schuchardt39578762018-01-19 20:24:39 +0100340 efi_free_pool(device_path);
Rob Clark53142032017-09-13 18:05:34 -0400341 if (!efiobj)
342 return NULL;
343
Heinrich Schuchardt39578762018-01-19 20:24:39 +0100344 /* Find the simple file system protocol */
345 ret = efi_search_protocol(efiobj, &efi_simple_file_system_protocol_guid,
346 &handler);
347 if (ret != EFI_SUCCESS)
348 return NULL;
Rob Clark53142032017-09-13 18:05:34 -0400349
Heinrich Schuchardt39578762018-01-19 20:24:39 +0100350 /* Return the simple file system protocol for the partition */
351 return handler->protocol_interface;
Rob Clark53142032017-09-13 18:05:34 -0400352}
353
AKASHI Takahiro120a01a2019-10-07 14:59:38 +0900354/**
355 * efi_fs_exists() - check if a partition bears a file system
356 *
357 * @desc: block device descriptor
358 * @part: partition number
359 * Return: 1 if a file system exists on the partition
360 * 0 otherwise
361 */
362static int efi_fs_exists(struct blk_desc *desc, int part)
363{
364 if (fs_set_blk_dev_with_part(desc, part))
365 return 0;
366
367 if (fs_get_type() == FS_TYPE_ANY)
368 return 0;
369
370 fs_close();
371
372 return 1;
373}
374
Masahisa Kojima78761472024-01-19 09:45:45 +0900375static void efi_disk_free_diskobj(struct efi_disk_obj *diskobj)
376{
377 struct efi_device_path *dp = diskobj->dp;
378 struct efi_simple_file_system_protocol *volume = diskobj->volume;
379
380 /*
381 * ignore error of efi_delete_handle() since this function
382 * is expected to be called in error path.
383 */
384 efi_delete_handle(&diskobj->header);
385 efi_free_pool(dp);
386 free(volume);
387}
388
Heinrich Schuchardt76f57892020-04-10 17:10:34 +0200389/**
Heinrich Schuchardt62036062020-03-19 13:49:34 +0100390 * efi_disk_add_dev() - create a handle for a partition or disk
Heinrich Schuchardt34f51832017-10-26 19:25:46 +0200391 *
Heinrich Schuchardt62036062020-03-19 13:49:34 +0100392 * @parent: parent handle
393 * @dp_parent: parent device path
Heinrich Schuchardt62036062020-03-19 13:49:34 +0100394 * @desc: internal block device
Heinrich Schuchardtb56e7192021-01-23 06:52:21 +0100395 * @part_info: partition info
Heinrich Schuchardt76f57892020-04-10 17:10:34 +0200396 * @part: partition
397 * @disk: pointer to receive the created handle
Heinrich Schuchardt175b0a92022-10-08 09:11:54 +0200398 * @agent_handle: handle of the EFI block driver
Heinrich Schuchardt62036062020-03-19 13:49:34 +0100399 * Return: disk object
Heinrich Schuchardt34f51832017-10-26 19:25:46 +0200400 */
Heinrich Schuchardtcde7a362018-02-09 20:55:47 +0100401static efi_status_t efi_disk_add_dev(
Heinrich Schuchardt6f3de6b2018-01-19 20:24:47 +0100402 efi_handle_t parent,
403 struct efi_device_path *dp_parent,
Heinrich Schuchardt6f3de6b2018-01-19 20:24:47 +0100404 struct blk_desc *desc,
Heinrich Schuchardtb56e7192021-01-23 06:52:21 +0100405 struct disk_partition *part_info,
Heinrich Schuchardtcde7a362018-02-09 20:55:47 +0100406 unsigned int part,
Heinrich Schuchardt175b0a92022-10-08 09:11:54 +0200407 struct efi_disk_obj **disk,
408 efi_handle_t agent_handle)
Alexander Graf06fe57b2016-04-11 16:16:17 +0200409{
410 struct efi_disk_obj *diskobj;
Heinrich Schuchardt2321b552020-05-21 09:22:06 +0200411 struct efi_object *handle;
Heinrich Schuchardt31d63b82022-10-07 11:03:01 +0200412 const efi_guid_t *esp_guid = NULL;
Heinrich Schuchardt9fb0f2f2017-11-26 14:05:12 +0100413 efi_status_t ret;
Alexander Graf06fe57b2016-04-11 16:16:17 +0200414
Alexander Graf601db1f2016-08-05 14:51:47 +0200415 /* Don't add empty devices */
416 if (!desc->lba)
Heinrich Schuchardtcde7a362018-02-09 20:55:47 +0100417 return EFI_NOT_READY;
Alexander Graf601db1f2016-08-05 14:51:47 +0200418
Rob Clarka83272f2017-09-13 18:05:31 -0400419 diskobj = calloc(1, sizeof(*diskobj));
Heinrich Schuchardt9fb0f2f2017-11-26 14:05:12 +0100420 if (!diskobj)
Heinrich Schuchardtcde7a362018-02-09 20:55:47 +0100421 return EFI_OUT_OF_RESOURCES;
Heinrich Schuchardt9fb0f2f2017-11-26 14:05:12 +0100422
423 /* Hook up to the device list */
Heinrich Schuchardt72928722018-09-26 05:27:56 +0200424 efi_add_handle(&diskobj->header);
Alexander Graf06fe57b2016-04-11 16:16:17 +0200425
426 /* Fill in object data */
Heinrich Schuchardtb56e7192021-01-23 06:52:21 +0100427 if (part_info) {
Heinrich Schuchardt6f3de6b2018-01-19 20:24:47 +0100428 struct efi_device_path *node = efi_dp_part_node(desc, part);
Heinrich Schuchardtcb9ff4e2020-01-10 12:36:01 +0100429 struct efi_handler *handler;
430 void *protocol_interface;
431
Heinrich Schuchardte29fbb32022-10-06 13:36:02 +0200432 if (!node) {
433 ret = EFI_OUT_OF_RESOURCES;
Simon Glass438e0492023-01-17 10:47:32 -0700434 log_debug("no node\n");
Heinrich Schuchardte29fbb32022-10-06 13:36:02 +0200435 goto error;
436 }
437
Heinrich Schuchardtcb9ff4e2020-01-10 12:36:01 +0100438 /* Parent must expose EFI_BLOCK_IO_PROTOCOL */
439 ret = efi_search_protocol(parent, &efi_block_io_guid, &handler);
Simon Glass438e0492023-01-17 10:47:32 -0700440 if (ret != EFI_SUCCESS) {
441 log_debug("search failed\n");
Heinrich Schuchardtcb9ff4e2020-01-10 12:36:01 +0100442 goto error;
Simon Glass438e0492023-01-17 10:47:32 -0700443 }
Heinrich Schuchardtcb9ff4e2020-01-10 12:36:01 +0100444
445 /*
446 * Link the partition (child controller) to the block device
447 * (controller).
448 */
449 ret = efi_protocol_open(handler, &protocol_interface, NULL,
450 &diskobj->header,
451 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER);
Simon Glass438e0492023-01-17 10:47:32 -0700452 if (ret != EFI_SUCCESS) {
453 log_debug("prot open failed\n");
454 goto error;
455 }
Heinrich Schuchardt6f3de6b2018-01-19 20:24:47 +0100456
457 diskobj->dp = efi_dp_append_node(dp_parent, node);
458 efi_free_pool(node);
Heinrich Schuchardtb56e7192021-01-23 06:52:21 +0100459 diskobj->media.last_block = part_info->size - 1;
Heinrich Schuchardt26397622021-02-02 17:53:14 +0100460 if (part_info->bootable & PART_EFI_SYSTEM_PARTITION)
Heinrich Schuchardt31d63b82022-10-07 11:03:01 +0200461 esp_guid = &efi_system_partition_guid;
Heinrich Schuchardt6f3de6b2018-01-19 20:24:47 +0100462 } else {
463 diskobj->dp = efi_dp_from_part(desc, part);
Heinrich Schuchardtb56e7192021-01-23 06:52:21 +0100464 diskobj->media.last_block = desc->lba - 1;
Heinrich Schuchardt6f3de6b2018-01-19 20:24:47 +0100465 }
Heinrich Schuchardt2321b552020-05-21 09:22:06 +0200466
467 /*
468 * Install the device path and the block IO protocol.
469 *
470 * InstallMultipleProtocolInterfaces() checks if the device path is
471 * already installed on an other handle and returns EFI_ALREADY_STARTED
472 * in this case.
473 */
474 handle = &diskobj->header;
Heinrich Schuchardt31d63b82022-10-07 11:03:01 +0200475 ret = efi_install_multiple_protocol_interfaces(
476 &handle,
477 &efi_guid_device_path, diskobj->dp,
478 &efi_block_io_guid, &diskobj->ops,
479 /*
480 * esp_guid must be last entry as it
481 * can be NULL. Its interface is NULL.
482 */
483 esp_guid, NULL,
484 NULL);
Simon Glass438e0492023-01-17 10:47:32 -0700485 if (ret != EFI_SUCCESS) {
486 log_debug("install failed %lx\n", ret);
Heinrich Schuchardte47b68b2021-11-20 13:56:02 +0100487 goto error;
Simon Glass438e0492023-01-17 10:47:32 -0700488 }
Heinrich Schuchardt2321b552020-05-21 09:22:06 +0200489
490 /*
491 * On partitions or whole disks without partitions install the
492 * simple file system protocol if a file system is available.
493 */
AKASHI Takahiro356ef902019-10-07 14:59:39 +0900494 if ((part || desc->part_type == PART_TYPE_UNKNOWN) &&
495 efi_fs_exists(desc, part)) {
Heinrich Schuchardtf9e8ada2023-07-30 14:03:53 +0200496 ret = efi_create_simple_file_system(desc, part, diskobj->dp,
497 &diskobj->volume);
498 if (ret != EFI_SUCCESS)
499 goto error;
500
Heinrich Schuchardt72928722018-09-26 05:27:56 +0200501 ret = efi_add_protocol(&diskobj->header,
Heinrich Schuchardt9fb0f2f2017-11-26 14:05:12 +0100502 &efi_simple_file_system_protocol_guid,
Heinrich Schuchardtce721a82018-01-19 20:24:38 +0100503 diskobj->volume);
Heinrich Schuchardtf9e8ada2023-07-30 14:03:53 +0200504 if (ret != EFI_SUCCESS)
505 goto error;
Rob Clark53142032017-09-13 18:05:34 -0400506 }
Alexander Graf06fe57b2016-04-11 16:16:17 +0200507 diskobj->ops = block_io_disk_template;
Alexander Graf06fe57b2016-04-11 16:16:17 +0200508
509 /* Fill in EFI IO Media info (for read/write callbacks) */
510 diskobj->media.removable_media = desc->removable;
511 diskobj->media.media_present = 1;
Heinrich Schuchardt35922522019-09-05 19:31:23 +0200512 /*
513 * MediaID is just an arbitrary counter.
514 * We have to change it if the medium is removed or changed.
515 */
516 diskobj->media.media_id = 1;
Alexander Graf06fe57b2016-04-11 16:16:17 +0200517 diskobj->media.block_size = desc->blksz;
518 diskobj->media.io_align = desc->blksz;
Heinrich Schuchardtaf8c5b62020-03-19 15:45:52 +0100519 if (part)
Emmanuel Vadot5bf29642017-12-11 19:22:33 +0100520 diskobj->media.logical_partition = 1;
Alexander Graf06fe57b2016-04-11 16:16:17 +0200521 diskobj->ops.media = &diskobj->media;
Heinrich Schuchardtcde7a362018-02-09 20:55:47 +0100522 if (disk)
523 *disk = diskobj;
Heinrich Schuchardta9931732020-03-19 15:16:31 +0100524
Heinrich Schuchardtb56e7192021-01-23 06:52:21 +0100525 EFI_PRINT("BlockIO: part %u, present %d, logical %d, removable %d"
Paul Barbieriab814f12022-06-30 07:02:04 -0400526 ", last_block %llu\n",
Masahisa Kojima23ee41f2023-12-25 13:43:54 +0900527 part,
Heinrich Schuchardtb56e7192021-01-23 06:52:21 +0100528 diskobj->media.media_present,
529 diskobj->media.logical_partition,
530 diskobj->media.removable_media,
Heinrich Schuchardtb56e7192021-01-23 06:52:21 +0100531 diskobj->media.last_block);
532
Heinrich Schuchardta9931732020-03-19 15:16:31 +0100533 /* Store first EFI system partition */
Heinrich Schuchardt0397d812022-10-21 08:33:44 +0200534 if (part && efi_system_partition.uclass_id == UCLASS_INVALID) {
Maks Mishin55bd6b32025-02-02 20:59:40 +0300535 if (part_info &&
536 part_info->bootable & PART_EFI_SYSTEM_PARTITION) {
Simon Glassfada3f92022-09-17 09:00:09 -0600537 efi_system_partition.uclass_id = desc->uclass_id;
Heinrich Schuchardta9931732020-03-19 15:16:31 +0100538 efi_system_partition.devnum = desc->devnum;
539 efi_system_partition.part = part;
Heinrich Schuchardt54f180d2021-05-25 18:00:13 +0200540 EFI_PRINT("EFI system partition: %s %x:%x\n",
Simon Glassfada3f92022-09-17 09:00:09 -0600541 blk_get_uclass_name(desc->uclass_id),
Heinrich Schuchardta9931732020-03-19 15:16:31 +0100542 desc->devnum, part);
543 }
544 }
Heinrich Schuchardtcde7a362018-02-09 20:55:47 +0100545 return EFI_SUCCESS;
Heinrich Schuchardtcb9ff4e2020-01-10 12:36:01 +0100546error:
Masahisa Kojima78761472024-01-19 09:45:45 +0900547 efi_disk_free_diskobj(diskobj);
Heinrich Schuchardtcb9ff4e2020-01-10 12:36:01 +0100548 return ret;
Alexander Graf06fe57b2016-04-11 16:16:17 +0200549}
550
Heinrich Schuchardt175b0a92022-10-08 09:11:54 +0200551/**
552 * efi_disk_create_raw() - create a handle for a whole raw disk
Heinrich Schuchardt6f3de6b2018-01-19 20:24:47 +0100553 *
Heinrich Schuchardt175b0a92022-10-08 09:11:54 +0200554 * @dev: udevice (UCLASS_BLK)
555 * @agent_handle: handle of the EFI block driver
Heinrich Schuchardt62036062020-03-19 13:49:34 +0100556 *
AKASHI Takahiro2381f2e2022-04-19 10:05:12 +0900557 * Create an efi_disk object which is associated with @dev.
558 * The type of @dev must be UCLASS_BLK.
559 *
Heinrich Schuchardt175b0a92022-10-08 09:11:54 +0200560 * Return: 0 on success, -1 otherwise
Heinrich Schuchardt6f3de6b2018-01-19 20:24:47 +0100561 */
Heinrich Schuchardt175b0a92022-10-08 09:11:54 +0200562static int efi_disk_create_raw(struct udevice *dev, efi_handle_t agent_handle)
Alexander Grafeb8d82c2016-04-11 16:16:18 +0200563{
AKASHI Takahiro2381f2e2022-04-19 10:05:12 +0900564 struct efi_disk_obj *disk;
565 struct blk_desc *desc;
Heinrich Schuchardt6f3de6b2018-01-19 20:24:47 +0100566 efi_status_t ret;
Heinrich Schuchardt6f3de6b2018-01-19 20:24:47 +0100567
AKASHI Takahiro2381f2e2022-04-19 10:05:12 +0900568 desc = dev_get_uclass_plat(dev);
Alexander Grafeb8d82c2016-04-11 16:16:18 +0200569
AKASHI Takahiro7ec925d2022-08-19 09:48:30 +0900570 ret = efi_disk_add_dev(NULL, NULL, desc,
Masahisa Kojima23ee41f2023-12-25 13:43:54 +0900571 NULL, 0, &disk, agent_handle);
AKASHI Takahiro2381f2e2022-04-19 10:05:12 +0900572 if (ret != EFI_SUCCESS) {
Simon Glass438e0492023-01-17 10:47:32 -0700573 if (ret == EFI_NOT_READY) {
AKASHI Takahiro2381f2e2022-04-19 10:05:12 +0900574 log_notice("Disk %s not ready\n", dev->name);
Simon Glass438e0492023-01-17 10:47:32 -0700575 ret = -EBUSY;
576 } else {
Heinrich Schuchardtc9a01a72024-02-02 15:12:52 +0100577 log_err("Adding block device %s failed, r = %lu\n",
578 dev->name, ret & ~EFI_ERROR_MASK);
Simon Glass438e0492023-01-17 10:47:32 -0700579 ret = -ENOENT;
580 }
Heinrich Schuchardtb56e7192021-01-23 06:52:21 +0100581
Simon Glass438e0492023-01-17 10:47:32 -0700582 return ret;
Alexander Grafeb8d82c2016-04-11 16:16:18 +0200583 }
Masahisa Kojimac9611082022-07-22 11:39:10 +0900584 if (efi_link_dev(&disk->header, dev)) {
Masahisa Kojima78761472024-01-19 09:45:45 +0900585 efi_disk_free_diskobj(disk);
Rob Clarka83272f2017-09-13 18:05:31 -0400586
Simon Glass438e0492023-01-17 10:47:32 -0700587 return -EINVAL;
AKASHI Takahiro2381f2e2022-04-19 10:05:12 +0900588 }
589
590 return 0;
Alexander Grafeb8d82c2016-04-11 16:16:18 +0200591}
592
Heinrich Schuchardt175b0a92022-10-08 09:11:54 +0200593/**
594 * efi_disk_create_part() - create a handle for a disk partition
Heinrich Schuchardt62036062020-03-19 13:49:34 +0100595 *
Heinrich Schuchardt175b0a92022-10-08 09:11:54 +0200596 * @dev: udevice (UCLASS_PARTITION)
597 * @agent_handle: handle of the EFI block driver
Alexander Grafe83be452016-03-04 01:10:02 +0100598 *
AKASHI Takahiro2381f2e2022-04-19 10:05:12 +0900599 * Create an efi_disk object which is associated with @dev.
600 * The type of @dev must be UCLASS_PARTITION.
Heinrich Schuchardt62036062020-03-19 13:49:34 +0100601 *
Heinrich Schuchardt175b0a92022-10-08 09:11:54 +0200602 * Return: 0 on success, -1 otherwise
Alexander Grafe83be452016-03-04 01:10:02 +0100603 */
Heinrich Schuchardt175b0a92022-10-08 09:11:54 +0200604static int efi_disk_create_part(struct udevice *dev, efi_handle_t agent_handle)
Alexander Grafe83be452016-03-04 01:10:02 +0100605{
AKASHI Takahiro2381f2e2022-04-19 10:05:12 +0900606 efi_handle_t parent;
607 struct blk_desc *desc;
AKASHI Takahiro2381f2e2022-04-19 10:05:12 +0900608 struct disk_part *part_data;
609 struct disk_partition *info;
610 unsigned int part;
AKASHI Takahiro2381f2e2022-04-19 10:05:12 +0900611 struct efi_handler *handler;
612 struct efi_device_path *dp_parent;
Heinrich Schuchardt6f3de6b2018-01-19 20:24:47 +0100613 struct efi_disk_obj *disk;
Heinrich Schuchardtcde7a362018-02-09 20:55:47 +0100614 efi_status_t ret;
AKASHI Takahiro2381f2e2022-04-19 10:05:12 +0900615
616 if (dev_tag_get_ptr(dev_get_parent(dev), DM_TAG_EFI, (void **)&parent))
617 return -1;
618
619 desc = dev_get_uclass_plat(dev_get_parent(dev));
AKASHI Takahiro2381f2e2022-04-19 10:05:12 +0900620
621 part_data = dev_get_uclass_plat(dev);
622 part = part_data->partnum;
623 info = &part_data->gpt_part_info;
624
625 ret = efi_search_protocol(parent, &efi_guid_device_path, &handler);
626 if (ret != EFI_SUCCESS)
627 return -1;
628 dp_parent = (struct efi_device_path *)handler->protocol_interface;
629
Masahisa Kojima23ee41f2023-12-25 13:43:54 +0900630 ret = efi_disk_add_dev(parent, dp_parent, desc,
Heinrich Schuchardt175b0a92022-10-08 09:11:54 +0200631 info, part, &disk, agent_handle);
AKASHI Takahiro2381f2e2022-04-19 10:05:12 +0900632 if (ret != EFI_SUCCESS) {
633 log_err("Adding partition for %s failed\n", dev->name);
634 return -1;
635 }
Masahisa Kojimac9611082022-07-22 11:39:10 +0900636 if (efi_link_dev(&disk->header, dev)) {
Masahisa Kojima78761472024-01-19 09:45:45 +0900637 efi_disk_free_diskobj(disk);
638
639 /* TODO: closing the parent EFI_BLOCK_IO_PROTOCOL is missing. */
AKASHI Takahiro2381f2e2022-04-19 10:05:12 +0900640
641 return -1;
642 }
643
644 return 0;
645}
646
Heinrich Schuchardt175b0a92022-10-08 09:11:54 +0200647/**
648 * efi_disk_probe() - create efi_disk objects for a block device
AKASHI Takahiro2381f2e2022-04-19 10:05:12 +0900649 *
Heinrich Schuchardt175b0a92022-10-08 09:11:54 +0200650 * @ctx: event context - driver binding protocol
651 * @event: EV_PM_POST_PROBE event
AKASHI Takahiro2381f2e2022-04-19 10:05:12 +0900652 *
653 * Create efi_disk objects for partitions as well as a raw disk
654 * which is associated with @dev.
655 * The type of @dev must be UCLASS_BLK.
656 * This function is expected to be called at EV_PM_POST_PROBE.
657 *
Heinrich Schuchardt175b0a92022-10-08 09:11:54 +0200658 * Return: 0 on success, -1 otherwise
AKASHI Takahiro2381f2e2022-04-19 10:05:12 +0900659 */
Heinrich Schuchardtda620cf2022-10-06 07:29:41 +0200660int efi_disk_probe(void *ctx, struct event *event)
AKASHI Takahiro2381f2e2022-04-19 10:05:12 +0900661{
Simon Glass302d4f82016-05-14 14:03:05 -0600662 struct udevice *dev;
AKASHI Takahiro2381f2e2022-04-19 10:05:12 +0900663 enum uclass_id id;
AKASHI Takahirocdd245a2022-04-19 10:05:13 +0900664 struct blk_desc *desc;
AKASHI Takahiro2381f2e2022-04-19 10:05:12 +0900665 struct udevice *child;
Heinrich Schuchardt175b0a92022-10-08 09:11:54 +0200666 struct efi_driver_binding_extended_protocol *db_prot = ctx;
667 efi_handle_t agent_handle = db_prot->bp.driver_binding_handle;
AKASHI Takahiro2381f2e2022-04-19 10:05:12 +0900668 int ret;
Simon Glass302d4f82016-05-14 14:03:05 -0600669
AKASHI Takahiro2381f2e2022-04-19 10:05:12 +0900670 dev = event->data.dm.dev;
671 id = device_get_uclass_id(dev);
Simon Glass302d4f82016-05-14 14:03:05 -0600672
Heinrich Schuchardt175b0a92022-10-08 09:11:54 +0200673 /* We won't support partitions in a partition */
AKASHI Takahiro2381f2e2022-04-19 10:05:12 +0900674 if (id != UCLASS_BLK)
675 return 0;
676
AKASHI Takahirocdd245a2022-04-19 10:05:13 +0900677 /*
Heinrich Schuchardt175b0a92022-10-08 09:11:54 +0200678 * Avoid creating duplicated objects now that efi_driver
AKASHI Takahirocdd245a2022-04-19 10:05:13 +0900679 * has already created an efi_disk at this moment.
680 */
681 desc = dev_get_uclass_plat(dev);
Simon Glassfada3f92022-09-17 09:00:09 -0600682 if (desc->uclass_id != UCLASS_EFI_LOADER) {
Heinrich Schuchardt175b0a92022-10-08 09:11:54 +0200683 ret = efi_disk_create_raw(dev, agent_handle);
AKASHI Takahirocdd245a2022-04-19 10:05:13 +0900684 if (ret)
685 return -1;
686 }
Simon Glass302d4f82016-05-14 14:03:05 -0600687
AKASHI Takahiro2381f2e2022-04-19 10:05:12 +0900688 device_foreach_child(child, dev) {
Heinrich Schuchardt175b0a92022-10-08 09:11:54 +0200689 ret = efi_disk_create_part(child, agent_handle);
AKASHI Takahiro2381f2e2022-04-19 10:05:12 +0900690 if (ret)
691 return -1;
Simon Glass302d4f82016-05-14 14:03:05 -0600692 }
Alexander Grafe83be452016-03-04 01:10:02 +0100693
Raymond Mao1fcaf952023-11-10 13:25:37 +0900694 /* only do the boot option management when UEFI sub-system is initialized */
695 if (IS_ENABLED(CONFIG_CMD_BOOTEFI_BOOTMGR) && efi_obj_list_initialized == EFI_SUCCESS) {
696 ret = efi_bootmgr_update_media_device_boot_option();
697 if (ret != EFI_SUCCESS)
698 return -1;
699 }
700
AKASHI Takahiro2381f2e2022-04-19 10:05:12 +0900701 return 0;
702}
703
Ilias Apalodimasf1db7df2023-06-12 18:35:58 +0300704/**
705 * efi_disk_remove - delete an efi_disk object for a block device or partition
AKASHI Takahiro7cebb752022-04-19 10:05:14 +0900706 *
Ilias Apalodimasf1db7df2023-06-12 18:35:58 +0300707 * @ctx: event context: driver binding protocol
708 * @event: EV_PM_PRE_REMOVE event
AKASHI Takahiro7cebb752022-04-19 10:05:14 +0900709 *
Ilias Apalodimasf1db7df2023-06-12 18:35:58 +0300710 * Delete an efi_disk object which is associated with the UCLASS_BLK or
711 * UCLASS_PARTITION device for which the EV_PM_PRE_REMOVE event is raised.
AKASHI Takahiro7cebb752022-04-19 10:05:14 +0900712 *
Ilias Apalodimasf1db7df2023-06-12 18:35:58 +0300713 * Return: 0 on success, -1 otherwise
AKASHI Takahiro7cebb752022-04-19 10:05:14 +0900714 */
Ilias Apalodimasf1db7df2023-06-12 18:35:58 +0300715int efi_disk_remove(void *ctx, struct event *event)
AKASHI Takahiro7cebb752022-04-19 10:05:14 +0900716{
Ilias Apalodimasf1db7df2023-06-12 18:35:58 +0300717 enum uclass_id id;
718 struct udevice *dev = event->data.dm.dev;
AKASHI Takahiro7cebb752022-04-19 10:05:14 +0900719 efi_handle_t handle;
AKASHI Takahiroaff330a2022-04-19 10:05:15 +0900720 struct blk_desc *desc;
Masahisa Kojima60755702024-01-19 09:45:44 +0900721 struct efi_device_path *dp = NULL;
Ilias Apalodimasf1db7df2023-06-12 18:35:58 +0300722 struct efi_disk_obj *diskobj = NULL;
Masahisa Kojima60755702024-01-19 09:45:44 +0900723 struct efi_simple_file_system_protocol *volume = NULL;
Ilias Apalodimasb09ecf12023-07-24 13:17:36 +0300724 efi_status_t ret;
AKASHI Takahiro7cebb752022-04-19 10:05:14 +0900725
726 if (dev_tag_get_ptr(dev, DM_TAG_EFI, (void **)&handle))
Ilias Apalodimasf1db7df2023-06-12 18:35:58 +0300727 return 0;
AKASHI Takahiro7cebb752022-04-19 10:05:14 +0900728
Ilias Apalodimasf1db7df2023-06-12 18:35:58 +0300729 id = device_get_uclass_id(dev);
730 switch (id) {
731 case UCLASS_BLK:
732 desc = dev_get_uclass_plat(dev);
Masahisa Kojima306cd1e2024-01-19 09:45:46 +0900733 if (desc && desc->uclass_id == UCLASS_EFI_LOADER)
734 /*
735 * EFI application/driver manages the EFI handle,
736 * no need to delete EFI handle.
737 */
738 return 0;
739
740 diskobj = (struct efi_disk_obj *)handle;
Ilias Apalodimasf1db7df2023-06-12 18:35:58 +0300741 break;
742 case UCLASS_PARTITION:
Masahisa Kojima60755702024-01-19 09:45:44 +0900743 diskobj = (struct efi_disk_obj *)handle;
744
745 /* TODO: closing the parent EFI_BLOCK_IO_PROTOCOL is missing. */
746
Ilias Apalodimasf1db7df2023-06-12 18:35:58 +0300747 break;
748 default:
749 return 0;
AKASHI Takahiroaff330a2022-04-19 10:05:15 +0900750 }
AKASHI Takahiro7cebb752022-04-19 10:05:14 +0900751
Masahisa Kojima306cd1e2024-01-19 09:45:46 +0900752 dp = diskobj->dp;
753 volume = diskobj->volume;
Masahisa Kojima60755702024-01-19 09:45:44 +0900754
Ilias Apalodimasb09ecf12023-07-24 13:17:36 +0300755 ret = efi_delete_handle(handle);
756 /* Do not delete DM device if there are still EFI drivers attached. */
757 if (ret != EFI_SUCCESS)
758 return -1;
759
Masahisa Kojima60755702024-01-19 09:45:44 +0900760 efi_free_pool(dp);
761 free(volume);
AKASHI Takahiro7cebb752022-04-19 10:05:14 +0900762 dev_tag_del(dev, DM_TAG_EFI);
763
764 return 0;
Raymond Mao1fcaf952023-11-10 13:25:37 +0900765
766 /*
767 * TODO A flag to distinguish below 2 different scenarios of this
768 * function call is needed:
769 * a) Unplugging of a removable media under U-Boot
770 * b) U-Boot exiting and booting an OS
771 * In case of scenario a), efi_bootmgr_update_media_device_boot_option()
772 * needs to be invoked here to update the boot options and remove the
773 * unnecessary ones.
774 */
775
AKASHI Takahiro7cebb752022-04-19 10:05:14 +0900776}
777
Masahisa Kojimac5ff0a02022-09-12 17:33:50 +0900778/**
779 * efi_disk_get_device_name() - get U-Boot device name associated with EFI handle
780 *
781 * @handle: pointer to the EFI handle
782 * @buf: pointer to the buffer to store the string
783 * @size: size of buffer
784 * Return: status code
785 */
786efi_status_t efi_disk_get_device_name(const efi_handle_t handle, char *buf, int size)
787{
788 int count;
789 int diskid;
790 enum uclass_id id;
791 unsigned int part;
792 struct udevice *dev;
793 struct blk_desc *desc;
794 const char *if_typename;
795 bool is_partition = false;
796 struct disk_part *part_data;
797
798 if (!handle || !buf || !size)
799 return EFI_INVALID_PARAMETER;
800
801 dev = handle->dev;
802 id = device_get_uclass_id(dev);
803 if (id == UCLASS_BLK) {
804 desc = dev_get_uclass_plat(dev);
805 } else if (id == UCLASS_PARTITION) {
806 desc = dev_get_uclass_plat(dev_get_parent(dev));
807 is_partition = true;
808 } else {
809 return EFI_INVALID_PARAMETER;
810 }
Simon Glassfada3f92022-09-17 09:00:09 -0600811 if_typename = blk_get_uclass_name(desc->uclass_id);
Masahisa Kojimac5ff0a02022-09-12 17:33:50 +0900812 diskid = desc->devnum;
813
814 if (is_partition) {
815 part_data = dev_get_uclass_plat(dev);
816 part = part_data->partnum;
Heinrich Schuchardt217cb202022-10-07 12:55:16 +0200817 count = snprintf(buf, size, "%s %d:%u", if_typename, diskid,
818 part);
Masahisa Kojimac5ff0a02022-09-12 17:33:50 +0900819 } else {
820 count = snprintf(buf, size, "%s %d", if_typename, diskid);
821 }
822
823 if (count < 0 || (count + 1) > size)
824 return EFI_INVALID_PARAMETER;
825
826 return EFI_SUCCESS;
827}
Tom Rini586c22b2022-09-19 13:19:39 -0400828
829/**
Heinrich Schuchardta02228f2022-08-31 16:37:35 +0200830 * efi_disks_register() - ensure all block devices are available in UEFI
831 *
832 * The function probes all block devices. As we store UEFI variables on the
833 * EFI system partition this function has to be called before enabling
834 * variable services.
835 */
836efi_status_t efi_disks_register(void)
837{
838 struct udevice *dev;
839
840 uclass_foreach_dev_probe(UCLASS_BLK, dev) {
841 }
842
843 return EFI_SUCCESS;
844}