mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-11-04 05:50:17 +00:00 
			
		
		
		
	dm.h and env.h serve no purpose here. Remove them and sort the remaining in alphabetical order. Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org> Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
		
			
				
	
	
		
			199 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			199 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
// SPDX-License-Identifier: GPL-2.0+
 | 
						|
/*
 | 
						|
 * Copyright (c) 2020, Linaro Limited
 | 
						|
 */
 | 
						|
 | 
						|
#include <common.h>
 | 
						|
#include <efi_loader.h>
 | 
						|
#include <efi_load_initrd.h>
 | 
						|
#include <fs.h>
 | 
						|
#include <malloc.h>
 | 
						|
#include <mapmem.h>
 | 
						|
 | 
						|
static efi_status_t EFIAPI
 | 
						|
efi_load_file2_initrd(struct efi_load_file_protocol *this,
 | 
						|
		      struct efi_device_path *file_path, bool boot_policy,
 | 
						|
		      efi_uintn_t *buffer_size, void *buffer);
 | 
						|
 | 
						|
static const struct efi_load_file_protocol efi_lf2_protocol = {
 | 
						|
	.load_file = efi_load_file2_initrd,
 | 
						|
};
 | 
						|
 | 
						|
/*
 | 
						|
 * Device path defined by Linux to identify the handle providing the
 | 
						|
 * EFI_LOAD_FILE2_PROTOCOL used for loading the initial ramdisk.
 | 
						|
 */
 | 
						|
static const struct efi_initrd_dp dp = {
 | 
						|
	.vendor = {
 | 
						|
		{
 | 
						|
		   DEVICE_PATH_TYPE_MEDIA_DEVICE,
 | 
						|
		   DEVICE_PATH_SUB_TYPE_VENDOR_PATH,
 | 
						|
		   sizeof(dp.vendor),
 | 
						|
		},
 | 
						|
		EFI_INITRD_MEDIA_GUID,
 | 
						|
	},
 | 
						|
	.end = {
 | 
						|
		DEVICE_PATH_TYPE_END,
 | 
						|
		DEVICE_PATH_SUB_TYPE_END,
 | 
						|
		sizeof(dp.end),
 | 
						|
	}
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * get_file_size() - retrieve the size of initramfs, set efi status on error
 | 
						|
 *
 | 
						|
 * @dev:			device to read from, e.g. "mmc"
 | 
						|
 * @part:			device partition, e.g. "0:1"
 | 
						|
 * @file:			name of file
 | 
						|
 * @status:			EFI exit code in case of failure
 | 
						|
 *
 | 
						|
 * Return:			size of file
 | 
						|
 */
 | 
						|
static loff_t get_file_size(const char *dev, const char *part, const char *file,
 | 
						|
			    efi_status_t *status)
 | 
						|
{
 | 
						|
	loff_t sz = 0;
 | 
						|
	int ret;
 | 
						|
 | 
						|
	ret = fs_set_blk_dev(dev, part, FS_TYPE_ANY);
 | 
						|
	if (ret) {
 | 
						|
		*status = EFI_NO_MEDIA;
 | 
						|
		goto out;
 | 
						|
	}
 | 
						|
 | 
						|
	ret = fs_size(file, &sz);
 | 
						|
	if (ret) {
 | 
						|
		sz = 0;
 | 
						|
		*status = EFI_NOT_FOUND;
 | 
						|
		goto out;
 | 
						|
	}
 | 
						|
 | 
						|
out:
 | 
						|
	return sz;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * efi_load_file2initrd() - load initial RAM disk
 | 
						|
 *
 | 
						|
 * This function implements the LoadFile service of the EFI_LOAD_FILE2_PROTOCOL
 | 
						|
 * in order to load an initial RAM disk requested by the Linux kernel stub.
 | 
						|
 *
 | 
						|
 * See the UEFI spec for details.
 | 
						|
 *
 | 
						|
 * @this:			EFI_LOAD_FILE2_PROTOCOL instance
 | 
						|
 * @file_path:			media device path of the file, "" in this case
 | 
						|
 * @boot_policy:		must be false
 | 
						|
 * @buffer_size:		size of allocated buffer
 | 
						|
 * @buffer:			buffer to load the file
 | 
						|
 *
 | 
						|
 * Return:			status code
 | 
						|
 */
 | 
						|
static efi_status_t EFIAPI
 | 
						|
efi_load_file2_initrd(struct efi_load_file_protocol *this,
 | 
						|
		      struct efi_device_path *file_path, bool boot_policy,
 | 
						|
		      efi_uintn_t *buffer_size, void *buffer)
 | 
						|
{
 | 
						|
	char *filespec;
 | 
						|
	efi_status_t status = EFI_NOT_FOUND;
 | 
						|
	loff_t file_sz = 0, read_sz = 0;
 | 
						|
	char *dev, *part, *file;
 | 
						|
	char *pos;
 | 
						|
	int ret;
 | 
						|
 | 
						|
	EFI_ENTRY("%p, %p, %d, %p, %p", this, file_path, boot_policy,
 | 
						|
		  buffer_size, buffer);
 | 
						|
 | 
						|
	filespec = strdup(CONFIG_EFI_INITRD_FILESPEC);
 | 
						|
	if (!filespec)
 | 
						|
		goto out;
 | 
						|
	pos = filespec;
 | 
						|
 | 
						|
	if (!this || this != &efi_lf2_protocol ||
 | 
						|
	    !buffer_size) {
 | 
						|
		status = EFI_INVALID_PARAMETER;
 | 
						|
		goto out;
 | 
						|
	}
 | 
						|
 | 
						|
	if (file_path->type != dp.end.type ||
 | 
						|
	    file_path->sub_type != dp.end.sub_type) {
 | 
						|
		status = EFI_INVALID_PARAMETER;
 | 
						|
		goto out;
 | 
						|
	}
 | 
						|
 | 
						|
	if (boot_policy) {
 | 
						|
		status = EFI_UNSUPPORTED;
 | 
						|
		goto out;
 | 
						|
	}
 | 
						|
 | 
						|
	/*
 | 
						|
	 * expect a string with three space separated parts:
 | 
						|
	 *
 | 
						|
	 * * a block device type, e.g. "mmc"
 | 
						|
	 * * a device and partition identifier, e.g. "0:1"
 | 
						|
	 * * a file path on the block device, e.g. "/boot/initrd.cpio.gz"
 | 
						|
	 */
 | 
						|
	dev = strsep(&pos, " ");
 | 
						|
	if (!dev)
 | 
						|
		goto out;
 | 
						|
	part = strsep(&pos, " ");
 | 
						|
	if (!part)
 | 
						|
		goto out;
 | 
						|
	file = strsep(&pos, " ");
 | 
						|
	if (!file)
 | 
						|
		goto out;
 | 
						|
 | 
						|
	file_sz = get_file_size(dev, part, file, &status);
 | 
						|
	if (!file_sz)
 | 
						|
		goto out;
 | 
						|
 | 
						|
	if (!buffer || *buffer_size < file_sz) {
 | 
						|
		status = EFI_BUFFER_TOO_SMALL;
 | 
						|
		*buffer_size = file_sz;
 | 
						|
	} else {
 | 
						|
		ret = fs_set_blk_dev(dev, part, FS_TYPE_ANY);
 | 
						|
		if (ret) {
 | 
						|
			status = EFI_NO_MEDIA;
 | 
						|
			goto out;
 | 
						|
		}
 | 
						|
 | 
						|
		ret = fs_read(file, map_to_sysmem(buffer), 0, *buffer_size,
 | 
						|
			      &read_sz);
 | 
						|
		if (ret || read_sz != file_sz)
 | 
						|
			goto out;
 | 
						|
		*buffer_size = read_sz;
 | 
						|
 | 
						|
		status = EFI_SUCCESS;
 | 
						|
	}
 | 
						|
 | 
						|
out:
 | 
						|
	free(filespec);
 | 
						|
	return EFI_EXIT(status);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * efi_initrd_register() - create handle for loading initial RAM disk
 | 
						|
 *
 | 
						|
 * This function creates a new handle and installs a Linux specific vendor
 | 
						|
 * device path and an EFI_LOAD_FILE_2_PROTOCOL. Linux uses the device path
 | 
						|
 * to identify the handle and then calls the LoadFile service of the
 | 
						|
 * EFI_LOAD_FILE_2_PROTOCOL to read the initial RAM disk.
 | 
						|
 *
 | 
						|
 * Return:	status code
 | 
						|
 */
 | 
						|
efi_status_t efi_initrd_register(void)
 | 
						|
{
 | 
						|
	efi_handle_t efi_initrd_handle = NULL;
 | 
						|
	efi_status_t ret;
 | 
						|
 | 
						|
	ret = EFI_CALL(efi_install_multiple_protocol_interfaces
 | 
						|
		       (&efi_initrd_handle,
 | 
						|
			/* initramfs */
 | 
						|
			&efi_guid_device_path, &dp,
 | 
						|
			/* LOAD_FILE2 */
 | 
						|
			&efi_guid_load_file2_protocol,
 | 
						|
			(void *)&efi_lf2_protocol,
 | 
						|
			NULL));
 | 
						|
 | 
						|
	return ret;
 | 
						|
}
 |