Example #1
0
/* Open the tos partition and load the tos image into memory
 * Parameters:
 * label    - Label for the partition in the GPT
 * image    - the image pointer after loading from the GPT
 * Return values:
 * EFI_SUCCESS           - image is loaded
 * EFI_ACCESS_DENIED     - Error in image loading
 * EFI_INVALID_PARAMETER - wrong image size
 * EFI_OUT_OF_RESOURCES  - Out of memory
 */
static EFI_STATUS tos_image_load_partition(IN const CHAR16 *label, OUT VOID **image)
{
        UINT32 MediaId;
        UINT32 img_size;
        EFI_STATUS ret;
        struct gpt_partition_interface gpart;
        UINT64 partition_start;
        UINT64 partition_size;
        VOID *bootimg;
        struct boot_img_hdr aosp_header;

        ret = gpt_get_partition_by_label(label, &gpart, LOGICAL_UNIT_USER);
        if (EFI_ERROR(ret)) {
                efi_perror(ret, L"Partition %s not found", label);
                return ret;
        }
        MediaId = gpart.bio->Media->MediaId;
        partition_start = gpart.part.starting_lba * gpart.bio->Media->BlockSize;
        partition_size = (gpart.part.ending_lba + 1 - gpart.part.starting_lba) *
                gpart.bio->Media->BlockSize;
        debug(L"Reading TOS image header");
        ret = uefi_call_wrapper(gpart.dio->ReadDisk, 5, gpart.dio, MediaId,
                                partition_start,
                                sizeof(aosp_header), &aosp_header);
        if (EFI_ERROR(ret)) {
                efi_perror(ret, L"ReadDisk (aosp_header)");
                return ret;
        }
        img_size = bootimage_size(&aosp_header) + BOOT_SIGNATURE_MAX_SIZE;
        if (img_size > partition_size) {
                error(L"TOS image is larger than partition size");
                return EFI_INVALID_PARAMETER;
        }
        bootimg = AllocatePool(img_size);
        if (!bootimg) {
                error(L"Alloc memory for TOS image failed");
                return EFI_OUT_OF_RESOURCES;
        }

        debug(L"Reading Tos image: %d bytes", img_size);
        ret = uefi_call_wrapper(gpart.dio->ReadDisk, 5, gpart.dio, MediaId, partition_start,
                                img_size, bootimg);
        if (EFI_ERROR(ret)) {
                efi_perror(ret, L"ReadDisk Error for TOS image read");
                FreePool(bootimg);
                return ret;
        }
        *image = bootimg;
        return EFI_SUCCESS;
}
int read_image_gpt(const char *name, void **data)
{
	ssize_t size;
	struct boot_img_hdr hdr;
	int ret = -1;
	int fd;

	fd = open_bootimage(name);
	if (fd < 0) {
		error("Failed to open %s image\n", name);
		goto out;
	}

	size = bootimage_size(fd, &hdr, true);
	if (size <= 0) {
		error("Invalid %s image\n", name);
		goto out;
	}

	if (lseek(fd, 0, SEEK_SET) < 0) {
		error("Seek to beginning of file failed: %s\n", strerror(errno));
		goto out;
	}

	*data = malloc(size);
	if (!*data) {
		error("Memory allocation failure\n");
		goto close;
	}

	ret = safe_read(fd, *data, size);
	if (ret)
		free(*data);
	else
		ret = size;
close:
	close(fd);
out:
	return ret;
}
static EFI_STATUS flash_zimage(VOID *data, UINTN size)
{
	struct boot_img_hdr *bootimage, *new_bootimage;
	VOID *new_cur, *cur;
	UINTN new_size, partlen;
	EFI_STATUS ret;

	ret = gpt_get_partition_by_label(L"boot", &gparti, LOGICAL_UNIT_USER);
	if (EFI_ERROR(ret)) {
		error(L"Unable to get information on the boot partition");
		return ret;
	}

	partlen = (gparti.part.ending_lba + 1 - gparti.part.starting_lba)
		* gparti.bio->Media->BlockSize;
	bootimage = AllocatePool(partlen);
	if (!bootimage) {
		error(L"Unable to allocate bootimage buffer");
		return EFI_OUT_OF_RESOURCES;
	}

	ret = uefi_call_wrapper(gparti.dio->ReadDisk, 5, gparti.dio,
				gparti.bio->Media->MediaId,
				gparti.part.starting_lba * gparti.bio->Media->BlockSize,
				partlen, bootimage);
	if (EFI_ERROR(ret)) {
		efi_perror(ret, L"Failed to load the current bootimage");
		goto out;
	}

	if (strncmpa((CHAR8 *)BOOT_MAGIC, bootimage->magic, BOOT_MAGIC_SIZE)) {
		error(L"boot partition does not contain a valid bootimage");
		ret = EFI_UNSUPPORTED;
		goto out;
	}

	new_size = bootimage_size(bootimage) - bootimage->kernel_size
		+ pagealign(bootimage, size);
	if (new_size > partlen) {
		error(L"Kernel image is too large to fit in the boot partition");
		ret = EFI_INVALID_PARAMETER;
		goto out;
	}

	new_bootimage = AllocateZeroPool(new_size);
	if (!new_bootimage) {
		ret = EFI_OUT_OF_RESOURCES;
		goto out;
	}

	/* Create the new bootimage. */
	memcpy((VOID *)new_bootimage, bootimage, bootimage->page_size);

	new_bootimage->kernel_size = size;
	new_bootimage->kernel_addr = bootimage->kernel_addr;
	new_cur = (VOID *)new_bootimage + bootimage->page_size;
	memcpy(new_cur, data, size);

	new_cur += pagealign(new_bootimage, size);
	cur = (VOID *)bootimage + bootimage->page_size
		+ pagealign(bootimage, bootimage->kernel_size);
	memcpy(new_cur, cur, bootimage->ramdisk_size);

	new_cur += pagealign(new_bootimage, new_bootimage->ramdisk_size);
	cur += pagealign(bootimage, bootimage->ramdisk_size);
	memcpy(new_cur, cur, bootimage->second_size);

	/* Flash new the bootimage. */
	cur_offset = gparti.part.starting_lba * gparti.bio->Media->BlockSize;
	ret = flash_write(new_bootimage, new_size);

	FreePool(new_bootimage);

 out:
	FreePool(bootimage);
	return ret;
}