From patchwork Fri Jul 7 04:00:42 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahisa Kojima X-Patchwork-Id: 700014 Delivered-To: patch@linaro.org Received: by 2002:ab3:710f:0:b0:238:a68b:2c7d with SMTP id n15csp1717670lte; Thu, 6 Jul 2023 21:01:59 -0700 (PDT) X-Google-Smtp-Source: APBJJlHjLVakmIyeP9U92BiYtTvENdckpTTI4emmyWsw/waccn49iP9a96cGIZZiTOIcJ0Ujd5Jo X-Received: by 2002:a92:d092:0:b0:341:fdd4:9acb with SMTP id h18-20020a92d092000000b00341fdd49acbmr3923892ilh.14.1688702518897; Thu, 06 Jul 2023 21:01:58 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1688702518; cv=none; d=google.com; s=arc-20160816; b=at/9Ab5ZNaNbDsKHUnvyu4o2FIcaR2JAD9/B3f/imgzO8U5gl6Z6+JzDkX90SSLtcO 3oxOPVD/ko3DRbCukA307Kwn3TBPE+cZAsk3IgdeT/W2HnEwTYLcgaw5VTLjed9YeUB8 XRxaufzvpzDEnuH3TdB3+AbuNL0KoJsHB32QQO/lHWivefIhA0VYe8T1dZQJb3/kgyKN wFMMbRT1pOtoevhs1pkqIEgkHtP9OfGV235d0yxJPZvW+HeOAsTYFH/FVuTQiSMZA1rA VaexDrIA6qYCPytEerdCUbStwegueBmg5xZQluzS3kQtB1XOc9tnh+XzEpyyQETvNxmp cosA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=z45djteDPV2ZH+S0mdpp3t0P1Qe2g9TdyhC2kEar2mc=; fh=RF61Sdo7Z9vPdEXjtBUxOV6kGajVxCA/ZkXy91yx00o=; b=tcNCHtymt8D7km9fnWA8oxUzjeU/DgsYKXF7p2c4WWrpjITvo/b4yAZz9C3wi2sZfX KtpHMZlPQPTtdNxB33S9HTkqBq5fqbmKm/d0ClRiR9ET8LSkRfSjjFhispZ3MHRcth1g YPnfuoWkWllJlrNJQj6/GzpPqu3hPqUimw2fGiPipfCtSpk5CCwYhd+qmQCzjbbx1Q1L XEAl2STUlJIamo/aMQE624mL4wB+4Hf7o3Dngp965ISyCt/5B5DJEXrA2fp7WD3MhLf/ Jj5aq9QWdI1AbU38omTEPDLi14uk26ezCd77E/8mlE7A77N/CjWFpKbKjQBKhQ93ANnn JzBA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=wJkdwoAW; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from phobos.denx.de (phobos.denx.de. [85.214.62.61]) by mx.google.com with ESMTPS id c27-20020a023b1b000000b0042b64cb1212si1140201jaa.119.2023.07.06.21.01.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 06 Jul 2023 21:01:58 -0700 (PDT) Received-SPF: pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 as permitted sender) client-ip=85.214.62.61; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=wJkdwoAW; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 41123863ED; Fri, 7 Jul 2023 06:01:42 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="wJkdwoAW"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 1424A863E9; Fri, 7 Jul 2023 06:01:41 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pg1-x52f.google.com (mail-pg1-x52f.google.com [IPv6:2607:f8b0:4864:20::52f]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 578E6863C7 for ; Fri, 7 Jul 2023 06:01:37 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=masahisa.kojima@linaro.org Received: by mail-pg1-x52f.google.com with SMTP id 41be03b00d2f7-55767141512so863432a12.3 for ; Thu, 06 Jul 2023 21:01:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1688702495; x=1691294495; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=z45djteDPV2ZH+S0mdpp3t0P1Qe2g9TdyhC2kEar2mc=; b=wJkdwoAWyJvc41m+23AIrhG8luU70V9bzFkSeHJ9+i775C+Mftf4kMu4hRX0Kr8LSp 5fjEm9cQAbzdXFdUB0fF7GW9SbJZddZD3LvtFTGF0kvs7a2OmapXD9cpDOhxHb+2wKJs RdPYETwbU4KXEj2qs37Su0Dn5uATfeCmJJS2qk6bvvjHLC+aGNHLjACqOa6OSF2PDuTt reBszV1FjdTGQW1f1oGTEYpkKflu2ML+SZiVHZEWAVgtKxhRzgigQbNRjnuQQ8hau4n2 WdbQICjX2I70W1AodhXmVZIhzDkvWnHHJjAIs+a+ThJihYEQb1q0Yo5m1jXzjskJkXM9 8CEA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1688702495; x=1691294495; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=z45djteDPV2ZH+S0mdpp3t0P1Qe2g9TdyhC2kEar2mc=; b=Jkuyla++OoHAOIeJ2iN+pUUQ3oEv8kZxWlTAwPiVbJuekJz3HnKrVzMkkwedBrgwI3 toO/E5Z815OmzGPpp5tXtQLEIKWK6iNRGN4T2+1E4lUJh4iRHqhJH1eb77hvBiq9NucM 7J17rB/WSKFm3cAbOaI93LiwmSCHN7xWUGtXPapNz4SX4QiBXkr1oxDBNn6qgdSJ6o10 F/M9e/MYMTszfISb78UYbzBN7amT8UiG5Dn5l4Oj2AGrsp8xZqsnM6REjWk3uvy/i/wI FFajeXPf+MnyPgyZK5B0B/+uGyLhQZ+kk24SThnknFq/Ttesv335r67I0QSMph1enxXA iZxg== X-Gm-Message-State: ABy/qLYI8v5/DmmxtCVvDmIKWoaqT+sVHSoMTNxg1b4rio2GitzxVqNA CvMwS1iPrMEi4B+KvuoS0HoeWvSOp2Q8Be8TI8w= X-Received: by 2002:a05:6a20:138c:b0:126:a5e3:3927 with SMTP id hn12-20020a056a20138c00b00126a5e33927mr2910554pzc.8.1688702495348; Thu, 06 Jul 2023 21:01:35 -0700 (PDT) Received: from localhost ([164.70.16.189]) by smtp.gmail.com with ESMTPSA id n11-20020a170902e54b00b001aaecc0b6ffsm2131114plf.160.2023.07.06.21.01.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 06 Jul 2023 21:01:34 -0700 (PDT) From: Masahisa Kojima To: u-boot@lists.denx.de Cc: Heinrich Schuchardt , Ilias Apalodimas , AKASHI Takahiro , Masahisa Kojima , Simon Glass , Jose Marinho Subject: [PATCH 2/4] efi_loader: add EFI_RAM_DISK_PROTOCOL implementation Date: Fri, 7 Jul 2023 13:00:42 +0900 Message-Id: <20230707040045.485790-3-masahisa.kojima@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230707040045.485790-1-masahisa.kojima@linaro.org> References: <20230707040045.485790-1-masahisa.kojima@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean This commit adds the EFI_RAM_DISK_PROTOCOL implementation. User can mount the distro installer by registering the memory mapped ISO image through EFI_RAM_DISK_PROTOCOL. Note that the installation process may not proceed after the distro installer calls ExitBootServices() since there is no hand-off process for the block device of memory mapped ISO image. Signed-off-by: Masahisa Kojima --- include/efi_api.h | 13 ++ include/efi_loader.h | 4 + lib/efi_driver/efi_uclass.c | 7 +- lib/efi_loader/Kconfig | 6 + lib/efi_loader/Makefile | 1 + lib/efi_loader/efi_ram_disk.c | 334 ++++++++++++++++++++++++++++++++++ lib/efi_loader/efi_setup.c | 6 + lib/uuid.c | 4 + 8 files changed, 373 insertions(+), 2 deletions(-) create mode 100644 lib/efi_loader/efi_ram_disk.c diff --git a/include/efi_api.h b/include/efi_api.h index 4ee4a1b5e9..3982ab89bc 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -764,6 +764,19 @@ struct efi_block_io { efi_status_t (EFIAPI *flush_blocks)(struct efi_block_io *this); }; +#define EFI_RAM_DISK_PROTOCOL_GUID \ + EFI_GUID(0xab38a0df, 0x6873, 0x44a9, \ + 0x87, 0xe6, 0xd4, 0xeb, 0x56, 0x14, 0x84, 0x49) + +struct efi_ram_disk_protocol { + /* "register" is a reserved keyword in C, use "disk_register" instead */ + efi_status_t(EFIAPI *disk_register)( + u64 ram_disk_base, u64 ram_disk_size, efi_guid_t *ram_disk_type, + struct efi_device_path *parent_device_path, + struct efi_device_path **device_path); + efi_status_t (EFIAPI *unregister)(struct efi_device_path *device_path); +}; + struct simple_text_output_mode { s32 max_mode; s32 mode; diff --git a/include/efi_loader.h b/include/efi_loader.h index 604fd765f7..70c8c83099 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -333,6 +333,8 @@ extern const efi_guid_t smbios_guid; /*GUID of console */ extern const efi_guid_t efi_guid_text_input_protocol; extern const efi_guid_t efi_guid_text_output_protocol; +/* GUID of Ram Disk protocol */ +extern const efi_guid_t efi_guid_ram_disk_protocol; extern char __efi_runtime_start[], __efi_runtime_stop[]; extern char __efi_runtime_rel_start[], __efi_runtime_rel_stop[]; @@ -1159,4 +1161,6 @@ efi_status_t efi_disk_get_device_name(const efi_handle_t handle, char *buf, int */ void efi_add_known_memory(void); +efi_status_t efi_ram_disk_register(void); + #endif /* _EFI_LOADER_H */ diff --git a/lib/efi_driver/efi_uclass.c b/lib/efi_driver/efi_uclass.c index 45f9351988..f7597811b7 100644 --- a/lib/efi_driver/efi_uclass.c +++ b/lib/efi_driver/efi_uclass.c @@ -44,8 +44,11 @@ static efi_status_t check_node_type(efi_handle_t handle) /* Get the last node */ const struct efi_device_path *node = efi_dp_last_node(dp); /* We do not support partitions as controller */ - if (!node || node->type == DEVICE_PATH_TYPE_MEDIA_DEVICE) - ret = EFI_UNSUPPORTED; + if (!node || node->type == DEVICE_PATH_TYPE_MEDIA_DEVICE) { + /* We support RAM disk as controller */ + if (node->sub_type != DEVICE_PATH_SUB_TYPE_RAM_DISK_PATH) + ret = EFI_UNSUPPORTED; + } } return ret; } diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index c5835e6ef6..1a81b65688 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -433,4 +433,10 @@ config EFI_RISCV_BOOT_PROTOCOL replace the transfer via the device-tree. The latter is not possible on systems using ACPI. +config EFI_RAM_DISK_PROTOCOL + bool "EFI_RAM_DISK_PROTOCOL support" + depends on PARTITIONS + help + Provide a EFI_RAM_DISK_PROTOCOL implementation to register the + RAM disk and create the block device. endif diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index 1a8c8d7cab..4197f594a2 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -86,6 +86,7 @@ obj-$(CONFIG_EFI_RISCV_BOOT_PROTOCOL) += efi_riscv.o obj-$(CONFIG_EFI_LOAD_FILE2_INITRD) += efi_load_initrd.o obj-$(CONFIG_EFI_SIGNATURE_SUPPORT) += efi_signature.o obj-$(CONFIG_EFI_ECPT) += efi_conformance.o +obj-$(CONFIG_EFI_RAM_DISK_PROTOCOL) += efi_ram_disk.o EFI_VAR_SEED_FILE := $(subst $\",,$(CONFIG_EFI_VAR_SEED_FILE)) $(obj)/efi_var_seed.o: $(srctree)/$(EFI_VAR_SEED_FILE) diff --git a/lib/efi_loader/efi_ram_disk.c b/lib/efi_loader/efi_ram_disk.c new file mode 100644 index 0000000000..10a6944aea --- /dev/null +++ b/lib/efi_loader/efi_ram_disk.c @@ -0,0 +1,334 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * RAM Disk Protocol + * + * Copyright (c) 2023, Linaro Limited + */ + +#include +#include +#include +#include + +#define MEM_BLOCK_SIZE_SHIFT 9 /* 512 bytes */ + +const efi_guid_t efi_guid_ram_disk_protocol = EFI_RAM_DISK_PROTOCOL_GUID; +static struct list_head obj_list; + +/** + * struct efi_ram_disk_obj - ram disk protocol object + * + * @ops: EFI disk I/O protocol interface + * @media: block I/O media information + * @dp: device path + * @image: image base address + * @image_size: image size + * @list: list structure + */ +struct efi_ram_disk_obj { + struct efi_block_io ops; + struct efi_block_io_media media; + struct efi_device_path *dp; + u8 *image; + u64 image_size; + struct list_head list; +}; + +/* + * reset - Reset service of the block IO protocol + * + * @this: pointer to the BLOCK_IO_PROTOCOL + * @extended_verification: extended verification + * Return: status code + */ +static efi_status_t EFIAPI reset(struct efi_block_io *this, + char extended_verification) +{ + return EFI_SUCCESS; +} + +/* + * read_blocks - Read service of the block IO protocol + * + * @this: pointer to the BLOCK_IO_PROTOCOL + * @media_id: id of the medium to be read from + * @lba: starting logical block for reading + * @buffer_size: size of the read buffer + * @buffer: pointer to the destination buffer + * Return: status code + */ +static efi_status_t EFIAPI read_blocks(struct efi_block_io *this, u32 media_id, + u64 lba, efi_uintn_t buffer_size, + void *buffer) +{ + u8 *start; + struct efi_ram_disk_obj *ram_disk_obj; + + if (!this || !buffer) + return EFI_INVALID_PARAMETER; + + if (!buffer_size) + return EFI_SUCCESS; + + /* TODO: check for media changes */ + if (media_id != this->media->media_id) + return EFI_MEDIA_CHANGED; + + if (!this->media->media_present) + return EFI_NO_MEDIA; + + EFI_ENTRY("%p, %x, %llx, %zx, %p", this, media_id, lba, + buffer_size, buffer); + + ram_disk_obj = container_of(this, struct efi_ram_disk_obj, ops); + + if ((lba << MEM_BLOCK_SIZE_SHIFT) + buffer_size > + ram_disk_obj->image_size) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + start = ram_disk_obj->image + (lba << MEM_BLOCK_SIZE_SHIFT); + memmove(buffer, start, buffer_size); + + return EFI_EXIT(EFI_SUCCESS); +} + +/* + * write_blocks - Write service of the block IO protocol + * + * @this: pointer to the BLOCK_IO_PROTOCOL + * @media_id: id of the medium to be written to + * @lba: starting logical block for writing + * @buffer_size: size of the write buffer + * @buffer: pointer to the source buffer + * Return: status code + */ +static efi_status_t EFIAPI write_blocks(struct efi_block_io *this, u32 media_id, + u64 lba, efi_uintn_t buffer_size, + void *buffer) +{ + u8 *start; + struct efi_ram_disk_obj *ram_disk_obj; + + if (!this || !buffer) + return EFI_INVALID_PARAMETER; + + if (this->media->read_only) + return EFI_WRITE_PROTECTED; + + if (!buffer_size) + return EFI_SUCCESS; + + /* TODO: check for media changes */ + if (media_id != this->media->media_id) + return EFI_MEDIA_CHANGED; + + if (!this->media->media_present) + return EFI_NO_MEDIA; + + EFI_ENTRY("%p, %x, %llx, %zx, %p", this, media_id, lba, + buffer_size, buffer); + + ram_disk_obj = container_of(this, struct efi_ram_disk_obj, ops); + + if ((lba << MEM_BLOCK_SIZE_SHIFT) + buffer_size > + ram_disk_obj->image_size) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + start = ram_disk_obj->image + (lba << MEM_BLOCK_SIZE_SHIFT); + memmove(start, buffer, buffer_size); + + return EFI_EXIT(EFI_SUCCESS); +} + +/* + * flush_blocks - Flush service of the block IO protocol + * + * @this: pointer to the BLOCK_IO_PROTOCOL + * Return: status code + */ +static efi_status_t EFIAPI flush_blocks(struct efi_block_io *this) +{ + return EFI_SUCCESS; +} + +/* + * ram_disk_register - Register service of the RAM disk protocol + * + * @ram_disk_base: The base address of registered RAM disk + * @ram_disk_size: The size of registered RAM disk + * @ram_disk_type: The type of registered RAM disk + * @parent_device_path: Pointer to the parent device path + * @device_path: Pointer to the device path + * Return: status code + */ +static efi_status_t EFIAPI +ram_disk_register(u64 ram_disk_base, u64 ram_disk_size, + efi_guid_t *ram_disk_type, + struct efi_device_path *parent_device_path, + struct efi_device_path **device_path) +{ + efi_status_t ret; + efi_handle_t disk_handle = NULL; + struct efi_device_path *dp; + struct efi_device_path end_node; + struct efi_ram_disk_obj *ram_disk_obj; + struct efi_device_path_ram_disk_path ram_disk_node; + + EFI_ENTRY("%llu %llu %pUs %p, %p", ram_disk_base, ram_disk_size, + ram_disk_type, parent_device_path, device_path); + + if (!ram_disk_size || !ram_disk_type || !device_path) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + *device_path = NULL; + + ram_disk_obj = calloc(1, sizeof(*ram_disk_obj)); + if (!ram_disk_obj) + return EFI_EXIT(EFI_OUT_OF_RESOURCES); + + ram_disk_obj->image = (u8 *)ram_disk_base; + ram_disk_obj->image_size = ram_disk_size; + ram_disk_obj->ops.media = &ram_disk_obj->media; + + ram_disk_obj->ops.media->block_size = 1 << MEM_BLOCK_SIZE_SHIFT; + ram_disk_obj->ops.media->last_block = + (ram_disk_size >> MEM_BLOCK_SIZE_SHIFT) - 1; + ram_disk_obj->ops.media->media_present = 1; + + ram_disk_obj->ops.reset = reset; + ram_disk_obj->ops.read_blocks = read_blocks; + ram_disk_obj->ops.write_blocks = write_blocks; + ram_disk_obj->ops.flush_blocks = flush_blocks; + + dp = calloc(1, sizeof(struct efi_device_path_ram_disk_path) + + sizeof(struct efi_device_path)); + if (!dp) { + free(ram_disk_obj); + return EFI_EXIT(EFI_OUT_OF_RESOURCES); + } + + ram_disk_node.dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE; + ram_disk_node.dp.sub_type = DEVICE_PATH_SUB_TYPE_RAM_DISK_PATH; + ram_disk_node.dp.length = sizeof(struct efi_device_path_ram_disk_path); + put_unaligned_le64(ram_disk_base, &ram_disk_node.starting_address); + put_unaligned_le64(ram_disk_base + ram_disk_size - 1, &ram_disk_node.ending_address); + guidcpy(&ram_disk_node.disk_type_guid, ram_disk_type); + ram_disk_node.disk_instance = 0; + memcpy(dp, &ram_disk_node, sizeof(struct efi_device_path_ram_disk_path)); + + end_node.type = DEVICE_PATH_TYPE_END; + end_node.sub_type = DEVICE_PATH_SUB_TYPE_END; + end_node.length = sizeof(struct efi_device_path); + memcpy((char *)dp + sizeof(struct efi_device_path_ram_disk_path), + &end_node, sizeof(struct efi_device_path)); + + ram_disk_obj->dp = efi_dp_append(parent_device_path, dp); + free(dp); + if (!ram_disk_obj->dp) { + free(ram_disk_obj); + return EFI_EXIT(EFI_OUT_OF_RESOURCES); + } + + if (efi_dp_find_obj(ram_disk_obj->dp, NULL, NULL)) { + log_err("Already Started\n"); + ret = EFI_ALREADY_STARTED; + goto err; + } + + ret = efi_install_multiple_protocol_interfaces( + &disk_handle, &efi_guid_device_path, ram_disk_obj->dp, + &efi_block_io_guid, &ram_disk_obj->ops, NULL); + if (ret != EFI_SUCCESS) { + log_err("InstallProtocolInterface failed\n"); + goto err; + } + + ret = EFI_CALL(systab.boottime->connect_controller(disk_handle, NULL, + NULL, 1)); + if (ret != EFI_SUCCESS) { + log_err("ConnectController failed\n"); + goto err; + } + + *device_path = ram_disk_obj->dp; + list_add(&ram_disk_obj->list, &obj_list); + + return EFI_EXIT(ret); +err: + efi_free_pool(ram_disk_obj->dp); + free(ram_disk_obj); + + return EFI_EXIT(ret); +} + +/* + * ram_disk_unregister - Unregister service of the RAM disk protocol + * + * @device_path: Pointer to the device path + * Return: status code + */ +static efi_status_t EFIAPI +ram_disk_unregister(struct efi_device_path *device_path) +{ + int ret; + efi_handle_t disk_handle; + struct list_head *pos, *n; + struct efi_ram_disk_obj *entry; + struct efi_ram_disk_obj *ram_disk_obj = NULL; + + EFI_ENTRY("%p", device_path); + + if (!device_path) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + list_for_each_safe(pos, n, &obj_list) { + entry = list_entry(pos, struct efi_ram_disk_obj, list); + if (!efi_dp_match(device_path, entry->dp)) { + ram_disk_obj = entry; + break; + } + } + + if (!ram_disk_obj) + return EFI_EXIT(EFI_NOT_FOUND); + + disk_handle = efi_dp_find_obj(device_path, &efi_block_io_guid, NULL); + if (!disk_handle) + return EFI_EXIT(EFI_NOT_FOUND); + + ret = efi_uninstall_multiple_protocol_interfaces( + disk_handle, &efi_guid_device_path, ram_disk_obj->dp, + &efi_block_io_guid, &ram_disk_obj->ops, NULL); + if (ret != EFI_SUCCESS) + log_err("UninstallProtocolInterface failed\n"); + + list_del(&ram_disk_obj->list); + efi_free_pool(ram_disk_obj->dp); + free(ram_disk_obj); + + return EFI_EXIT(ret); +} + +static const struct efi_ram_disk_protocol efi_ram_disk_protocol = { + .disk_register = ram_disk_register, + .unregister = ram_disk_unregister, +}; + +/** + * efi_ram_disk_register() - register EFI_RAM_DISK_PROTOCOL + * + * Return: status code + */ +efi_status_t efi_ram_disk_register(void) +{ + efi_status_t ret; + + ret = efi_add_protocol(efi_root, &efi_guid_ram_disk_protocol, + (void *)&efi_ram_disk_protocol); + if (ret != EFI_SUCCESS) + log_err("Cannot install EFI_RAM_DISK_PROTOCOL\n"); + + INIT_LIST_HEAD(&obj_list); + + return ret; +} diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c index 877f3878d6..8c430d4a9c 100644 --- a/lib/efi_loader/efi_setup.c +++ b/lib/efi_loader/efi_setup.c @@ -344,6 +344,12 @@ efi_status_t efi_init_obj_list(void) if (ret != EFI_SUCCESS) goto out; + if (IS_ENABLED(CONFIG_EFI_RAM_DISK_PROTOCOL)) { + ret = efi_ram_disk_register(); + if (ret != EFI_SUCCESS) + goto out; + } + /* Initialize EFI runtime services */ ret = efi_reset_system_init(); if (ret != EFI_SUCCESS) diff --git a/lib/uuid.c b/lib/uuid.c index 96e1af3c8b..9827588186 100644 --- a/lib/uuid.c +++ b/lib/uuid.c @@ -195,6 +195,10 @@ static const struct { "Firmware Management", EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GUID }, + { + "Ram Disk", + EFI_RAM_DISK_PROTOCOL_GUID + }, /* Configuration table GUIDs */ { "ACPI table",