VbError_t nvstorage_write_disk(const uint8_t *buf) { VbDiskInfo *internal_disk; uint8_t *block_buf; if (get_internal_disk(&internal_disk)) return 1; if (get_nvcxt_block_of_disk(internal_disk, &block_buf)) return 1; memcpy(block_buf, buf, VBNV_BLOCK_SIZE); if (VbExDiskWrite(internal_disk->handle, CHROMEOS_VBNVCONTEXT_LBA, 1, block_buf)) { VBDEBUG("Failed to write internal disk!\n"); VbExFree(block_buf); return 1; } VbExFree(block_buf); #ifdef CONFIG_EXYNOS5 /* * XXX(chrome-os-partner:10415): On Exynos, reliable write operations * need write busy time; so add a delay here. In the long run, we * should avoid using eMMC as VbNvContext storage media. */ mdelay(1); #endif return VBERROR_SUCCESS; }
/** * Write any changes for the GPT data back to the drive, then free the buffers. * * Returns 0 if successful, 1 if error. */ int WriteAndFreeGptData(VbExDiskHandle_t disk_handle, GptData *gptdata) { int legacy = 0; GptHeader *header = (GptHeader *)gptdata->primary_header; uint64_t entries_bytes = header->number_of_entries * header->size_of_entry; uint64_t entries_sectors = entries_bytes / gptdata->sector_bytes; int ret = 1; /* * TODO(namnguyen): Preserve padding between primary GPT header and * its entries. */ uint64_t entries_lba = GPT_PMBR_SECTORS + GPT_HEADER_SECTORS; if (gptdata->primary_header) { GptHeader *h = (GptHeader *)(gptdata->primary_header); entries_lba = h->entries_lba; /* * Avoid even looking at this data if we don't need to. We * may in fact not have read it from disk if the read failed, * and this avoids a valgrind complaint. */ if (gptdata->modified) { legacy = !Memcmp(h->signature, GPT_HEADER_SIGNATURE2, GPT_HEADER_SIGNATURE_SIZE); } if (gptdata->modified & GPT_MODIFIED_HEADER1) { if (legacy) { VBDEBUG(("Not updating GPT header 1: " "legacy mode is enabled.\n")); } else { VBDEBUG(("Updating GPT header 1\n")); if (0 != VbExDiskWrite(disk_handle, 1, 1, gptdata->primary_header)) goto fail; } } } if (gptdata->primary_entries) { if (gptdata->modified & GPT_MODIFIED_ENTRIES1) { if (legacy) { VBDEBUG(("Not updating GPT entries 1: " "legacy mode is enabled.\n")); } else { VBDEBUG(("Updating GPT entries 1\n")); if (0 != VbExDiskWrite(disk_handle, entries_lba, entries_sectors, gptdata->primary_entries)) goto fail; } } } entries_lba = (gptdata->gpt_drive_sectors - entries_sectors - GPT_HEADER_SECTORS); if (gptdata->secondary_header) { GptHeader *h = (GptHeader *)(gptdata->secondary_header); entries_lba = h->entries_lba; if (gptdata->modified & GPT_MODIFIED_HEADER2) { VBDEBUG(("Updating GPT entries 2\n")); if (0 != VbExDiskWrite(disk_handle, gptdata->gpt_drive_sectors - 1, 1, gptdata->secondary_header)) goto fail; } } if (gptdata->secondary_entries) { if (gptdata->modified & GPT_MODIFIED_ENTRIES2) { VBDEBUG(("Updating GPT header 2\n")); if (0 != VbExDiskWrite(disk_handle, entries_lba, entries_sectors, gptdata->secondary_entries)) goto fail; } } ret = 0; fail: /* Avoid leaking memory on disk write failure */ if (gptdata->primary_header) VbExFree(gptdata->primary_header); if (gptdata->primary_entries) VbExFree(gptdata->primary_entries); if (gptdata->secondary_entries) VbExFree(gptdata->secondary_entries); if (gptdata->secondary_header) VbExFree(gptdata->secondary_header); /* Success */ return ret; }
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; }