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; }
/** * 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; }