VbError_t VbExStreamRead(VbExStream_t stream, uint32_t bytes, void *buffer)
{
	struct disk_stream *s = (struct disk_stream *)stream;
	uint64_t sectors;
	VbError_t rv;

	if (!s)
		return VBERROR_UNKNOWN;

	/* For now, require reads to be a multiple of the LBA size */
	if (bytes % LBA_BYTES)
		return VBERROR_UNKNOWN;

	/* Fail on overflow */
	sectors = bytes / LBA_BYTES;
	if (sectors > s->sectors_left)
		return VBERROR_UNKNOWN;

	rv = VbExDiskRead(s->handle, s->sector, sectors, buffer);
	if (rv != VBERROR_SUCCESS)
		return rv;

	s->sector += sectors;
	s->sectors_left -= sectors;

	return VBERROR_SUCCESS;
}
/*
 * Allocates 1-block-sized memory to block_buf_ptr and fills it as the first
 * block of the disk.
 * Returns 0 for success, non-zero for failure.
 */
static int get_nvcxt_block_of_disk(const VbDiskInfo *disk,
		uint8_t **block_buf_ptr)
{
	uint8_t *block_buf = NULL;

	block_buf = VbExMalloc(disk->bytes_per_lba);

	if (VbExDiskRead(disk->handle,
				CHROMEOS_VBNVCONTEXT_LBA, 1, block_buf)) {
		VBDEBUG("Failed to read internal disk!\n");
		VbExFree(block_buf);
		return 1;
	}

	*block_buf_ptr = block_buf;
	return 0;
}
Exemple #3
0
/**
 * Allocate and read GPT data from the drive.
 *
 * The sector_bytes and gpt_drive_sectors fields should be filled on input.  The
 * primary and secondary header and entries are filled on output.
 *
 * Returns 0 if successful, 1 if error.
 */
int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData *gptdata)
{
	uint64_t max_entries_bytes = MAX_NUMBER_OF_ENTRIES * sizeof(GptEntry);
	int primary_valid = 0, secondary_valid = 0;

	/* No data to be written yet */
	gptdata->modified = 0;

	/* Allocate all buffers */
	gptdata->primary_header = (uint8_t *)VbExMalloc(gptdata->sector_bytes);
	gptdata->secondary_header =
		(uint8_t *)VbExMalloc(gptdata->sector_bytes);
	gptdata->primary_entries = (uint8_t *)VbExMalloc(max_entries_bytes);
	gptdata->secondary_entries = (uint8_t *)VbExMalloc(max_entries_bytes);

	if (gptdata->primary_header == NULL ||
	    gptdata->secondary_header == NULL ||
	    gptdata->primary_entries == NULL ||
	    gptdata->secondary_entries == NULL)
		return 1;

	/* Read primary header from the drive, skipping the protective MBR */
	if (0 != VbExDiskRead(disk_handle, 1, 1, gptdata->primary_header)) {
		VBDEBUG(("Read error in primary GPT header\n"));
		Memset(gptdata->primary_header, 0, gptdata->sector_bytes);
	}

	/* Only read primary GPT if the primary header is valid */
	GptHeader* primary_header = (GptHeader*)gptdata->primary_header;
	if (0 == CheckHeader(primary_header, 0,
			gptdata->streaming_drive_sectors,
			gptdata->gpt_drive_sectors,
			gptdata->flags)) {
		primary_valid = 1;
		uint64_t entries_bytes = primary_header->number_of_entries
				* primary_header->size_of_entry;
		uint64_t entries_sectors = entries_bytes
					/ gptdata->sector_bytes;
		if (0 != VbExDiskRead(disk_handle,
				      primary_header->entries_lba,
				      entries_sectors,
				      gptdata->primary_entries)) {
			VBDEBUG(("Read error in primary GPT entries\n"));
			primary_valid = 0;
		}
	} else {
		VBDEBUG(("Primary GPT header invalid!\n"));
	}

	/* Read secondary header from the end of the drive */
	if (0 != VbExDiskRead(disk_handle, gptdata->gpt_drive_sectors - 1, 1,
			      gptdata->secondary_header)) {
		VBDEBUG(("Read error in secondary GPT header\n"));
		Memset(gptdata->secondary_header, 0, gptdata->sector_bytes);
	}

	/* Only read secondary GPT if the secondary header is valid */
	GptHeader* secondary_header = (GptHeader*)gptdata->secondary_header;
	if (0 == CheckHeader(secondary_header, 1,
			gptdata->streaming_drive_sectors,
			gptdata->gpt_drive_sectors,
			gptdata->flags)) {
		secondary_valid = 1;
		uint64_t entries_bytes = secondary_header->number_of_entries
				* secondary_header->size_of_entry;
		uint64_t entries_sectors = entries_bytes
				/ gptdata->sector_bytes;
		if (0 != VbExDiskRead(disk_handle,
				      secondary_header->entries_lba,
				      entries_sectors,
				      gptdata->secondary_entries)) {
			VBDEBUG(("Read error in secondary GPT entries\n"));
			secondary_valid = 0;
		}
	} else {
		VBDEBUG(("Secondary GPT header invalid!\n"));
	}

	/* Return 0 if least one GPT header was valid */
	return (primary_valid || secondary_valid) ? 0 : 1;
}
static int do_vbexport_test_diskrw(cmd_tbl_t *cmdtp, int flag,
		int argc, char * const argv[])
{
	int ret = 0;
	VbDiskInfo *disk_info;
	VbExDiskHandle_t handle;
	uint32_t disk_count, test_lba_count, buf_byte_count, i;
	uint8_t *original_buf, *target_buf, *verify_buf;
	uint64_t t0, t1;

	switch (argc) {
	case 1:  /* if no argument given, use the default lba count */
		test_lba_count = DEFAULT_TEST_LBA_COUNT;
		break;
	case 2:  /* use argument */
		test_lba_count = simple_strtoul(argv[1], NULL, 10);
		if (!test_lba_count) {
			VbExDebug("The first argument is not a number!\n");
			return cmd_usage(cmdtp);
		}
		break;
	default:
		return cmd_usage(cmdtp);
	}

	/* We perform read/write operations on the first internal disk. */
	if (VbExDiskGetInfo(&disk_info, &disk_count, VB_DISK_FLAG_FIXED) ||
			disk_count == 0) {
		VbExDebug("No internal disk found!\n");
		return 1;
	}
	handle = disk_info[0].handle;
	buf_byte_count = disk_info[0].bytes_per_lba * test_lba_count;
	VbExDiskFreeInfo(disk_info, handle);

	/* Allocate the buffer and fill the target test pattern. */
	original_buf = VbExMalloc(buf_byte_count);
	target_buf = VbExMalloc(buf_byte_count);
	verify_buf = VbExMalloc(buf_byte_count);

	/* Fill the target test pattern. */
	for (i = 0; i < buf_byte_count; i++)
		target_buf[i] = i & 0xff;

	t0 = VbExGetTimer();
	if (VbExDiskRead(handle, TEST_LBA_START, test_lba_count,
			original_buf)) {
		VbExDebug("Failed to read disk.\n");
		goto out;
	}
	t1 = VbExGetTimer();
	VbExDebug("test_diskrw: disk_read, lba_count: %u, time: %llu\n",
			test_lba_count, t1 - t0);

	t0 = VbExGetTimer();
	ret = VbExDiskWrite(handle, TEST_LBA_START, test_lba_count, target_buf);
	t1 = VbExGetTimer();
	VbExDebug("test_diskrw: disk_write, lba_count: %u, time: %llu\n",
			test_lba_count, t1 - t0);

	if (ret) {
		VbExDebug("Failed to write disk.\n");
		ret = 1;
	} else {
		/* Read back and verify the data. */
		VbExDiskRead(handle, TEST_LBA_START, test_lba_count,
				verify_buf);
		if (memcmp(target_buf, verify_buf, buf_byte_count) != 0) {
			VbExDebug("Verify failed. The target data wrote "
					"wrong.\n");
			ret = 1;
		}
	}

	/* Write the original data back. */
	if (VbExDiskWrite(handle, TEST_LBA_START, test_lba_count,
			original_buf)) {
		VbExDebug("Failed to write the original data back. The disk "
				"may now be corrupt.\n");
	}

out:
	VbExDiskFreeInfo(disk_info, NULL);

	VbExFree(original_buf);
	VbExFree(target_buf);
	VbExFree(verify_buf);

	if (ret == 0)
		VbExDebug("Read and write disk test SUCCESS.\n");

	return ret;
}