static int do_vbexport_test_diskinfo_flags(uint32_t flags)
{
	int ret = 0;
	VbDiskInfo *info;
	uint32_t count, i;

	ret = VbExDiskGetInfo(&info, &count, flags);
	if (ret)
		return ret;

	if (count == 0) {
		VbExDebug("No disk found!\n");
	} else {
		VbExDebug("handle    byte/lba  lba_count  f  name\n");
		for (i = 0; i < count; i++) {
			VbExDebug("%08lx  %-9llu %-10llu %-2lu %s",
					info[i].handle,
					info[i].bytes_per_lba,
					info[i].lba_count,
					info[i].flags,
					info[i].name);

			if ((flags & info[i].flags) != flags) {
				VbExDebug("    INCORRECT: flag mismatched\n");
				ret = 1;
			} else
				VbExDebug("\n");
		}
	}

	return VbExDiskFreeInfo(info, NULL) || ret;
}
/*
 * Gets the first internal disk and caches the result in a static variable.
 * Returns 0 for success, non-zero for failure.
 */
static int get_internal_disk(VbDiskInfo **disk_ptr)
{
	static VbDiskInfo internal_disk;

	if (internal_disk.handle == NULL) {
		VbDiskInfo *disk_info;
		uint32_t disk_count;

		if (VbExDiskGetInfo(&disk_info, &disk_count,
				VB_DISK_FLAG_FIXED) || disk_count == 0) {
			VBDEBUG("No internal disk found!\n");
			return 1;
		}
		internal_disk = disk_info[0];
		VbExDiskFreeInfo(disk_info, internal_disk.handle);
	}

	*disk_ptr = &internal_disk;
	return 0;
}
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;
}
Ejemplo n.º 4
0
/**
 * Attempt loading a kernel from the specified type(s) of disks.
 *
 * If successful, sets p->disk_handle to the disk for the kernel and returns
 * VBERROR_SUCCESS.
 *
 * Returns VBERROR_NO_DISK_FOUND if no disks of the specified type were found.
 *
 * May return other VBERROR_ codes for other failures.
 */
uint32_t VbTryLoadKernel(VbCommonParams *cparams, LoadKernelParams *p,
                         uint32_t get_info_flags)
{
    VbError_t retval = VBERROR_UNKNOWN;
    VbDiskInfo* disk_info = NULL;
    uint32_t disk_count = 0;
    uint32_t i;

    VBDEBUG(("VbTryLoadKernel() start, get_info_flags=0x%x\n",
             (unsigned)get_info_flags));

    p->disk_handle = NULL;

    /* Find disks */
    if (VBERROR_SUCCESS != VbExDiskGetInfo(&disk_info, &disk_count,
                                           get_info_flags))
        disk_count = 0;

    VBDEBUG(("VbTryLoadKernel() found %d disks\n", (int)disk_count));
    if (0 == disk_count) {
        VbSetRecoveryRequest(VBNV_RECOVERY_RW_NO_DISK);
        return VBERROR_NO_DISK_FOUND;
    }

    /* Loop over disks */
    for (i = 0; i < disk_count; i++) {
        VBDEBUG(("VbTryLoadKernel() trying disk %d\n", (int)i));
        /*
         * Sanity-check what we can. FWIW, VbTryLoadKernel() is always
         * called with only a single bit set in get_info_flags.
         *
         * Ensure 512-byte sectors and non-trivially sized disk (for
         * cgptlib) and that we got a partition with only the flags we
         * asked for.
         */
        if (512 != disk_info[i].bytes_per_lba ||
                16 > disk_info[i].lba_count ||
                get_info_flags != (disk_info[i].flags & ~VB_DISK_FLAG_EXTERNAL_GPT)) {
            VBDEBUG(("  skipping: bytes_per_lba=%" PRIu64
                     " lba_count=%" PRIu64 " flags=0x%x\n",
                     disk_info[i].bytes_per_lba,
                     disk_info[i].lba_count,
                     disk_info[i].flags));
            continue;
        }
        p->disk_handle = disk_info[i].handle;
        p->bytes_per_lba = disk_info[i].bytes_per_lba;
        p->gpt_lba_count = disk_info[i].lba_count;
        p->streaming_lba_count = disk_info[i].streaming_lba_count
                                 ?: p->gpt_lba_count;
        p->boot_flags |= disk_info[i].flags & VB_DISK_FLAG_EXTERNAL_GPT
                         ? BOOT_FLAG_EXTERNAL_GPT : 0;
        retval = LoadKernel(p, cparams);
        VBDEBUG(("VbTryLoadKernel() LoadKernel() = %d\n", retval));

        /*
         * Stop now if we found a kernel.
         *
         * TODO: If recovery requested, should track the farthest we
         * get, instead of just returning the value from the last disk
         * attempted.
         */
        if (VBERROR_SUCCESS == retval)
            break;
    }

    /* If we didn't find any good kernels, don't return a disk handle. */
    if (VBERROR_SUCCESS != retval) {
        VbSetRecoveryRequest(VBNV_RECOVERY_RW_NO_KERNEL);
        p->disk_handle = NULL;
    }

    VbExDiskFreeInfo(disk_info, p->disk_handle);

    /*
     * Pass through return code.  Recovery reason (if any) has already been
     * set by LoadKernel().
     */
    return retval;
}
Ejemplo n.º 5
0
VbError_t VbBootRecovery(VbCommonParams *cparams, LoadKernelParams *p)
{
    VbSharedDataHeader *shared =
        (VbSharedDataHeader *)cparams->shared_data_blob;
    uint32_t retval;
    uint32_t key;
    int i;

    VBDEBUG(("VbBootRecovery() start\n"));

    /*
     * If the dev-mode switch is off and the user didn't press the recovery
     * button, require removal of all external media.
     */
    if (!(shared->flags & VBSD_BOOT_DEV_SWITCH_ON) &&
            !(shared->flags & VBSD_BOOT_REC_SWITCH_ON)) {
        VbDiskInfo *disk_info = NULL;
        uint32_t disk_count = 0;

        VBDEBUG(("VbBootRecovery() forcing device removal\n"));

        /* If no media is detected initially, delay and make one extra
         * attempt, in case devices appear later than expected. */
        if (VBERROR_SUCCESS != VbExDiskGetInfo(&disk_info, &disk_count,
                                               VB_DISK_FLAG_REMOVABLE))
            disk_count = 0;

        VbExDiskFreeInfo(disk_info, NULL);
        if (0 == disk_count)
            VbExSleepMs(REC_MEDIA_INIT_DELAY);

        while (1) {
            disk_info = NULL;
            disk_count = 0;
            if (VBERROR_SUCCESS !=
                    VbExDiskGetInfo(&disk_info, &disk_count,
                                    VB_DISK_FLAG_REMOVABLE))
                disk_count = 0;

            VbExDiskFreeInfo(disk_info, NULL);

            if (0 == disk_count) {
                VbDisplayScreen(cparams, VB_SCREEN_BLANK,
                                0, &vnc);
                break;
            }

            VBDEBUG(("VbBootRecovery() "
                     "waiting for %d disks to be removed\n",
                     (int)disk_count));

            VbDisplayScreen(cparams, VB_SCREEN_RECOVERY_REMOVE,
                            0, &vnc);

            /*
             * Scan keyboard more frequently than media, since x86
             * platforms don't like to scan USB too rapidly.
             */
            for (i = 0; i < REC_DISK_DELAY; i += REC_KEY_DELAY) {
                VbCheckDisplayKey(cparams, VbExKeyboardRead(),
                                  &vnc);
                if (VbWantShutdown(cparams->gbb->flags))
                    return VBERROR_SHUTDOWN_REQUESTED;
                VbExSleepMs(REC_KEY_DELAY);
            }
        }
    }

    /* Loop and wait for a recovery image */
    while (1) {
        VBDEBUG(("VbBootRecovery() attempting to load kernel2\n"));
        retval = VbTryLoadKernel(cparams, p, VB_DISK_FLAG_REMOVABLE);

        /*
         * Clear recovery requests from failed kernel loading, since
         * we're already in recovery mode.  Do this now, so that
         * powering off after inserting an invalid disk doesn't leave
         * us stuck in recovery mode.
         */
        VbSetRecoveryRequest(VBNV_RECOVERY_NOT_REQUESTED);

        if (VBERROR_SUCCESS == retval)
            break; /* Found a recovery kernel */

        VbDisplayScreen(cparams, VBERROR_NO_DISK_FOUND == retval ?
                        VB_SCREEN_RECOVERY_INSERT :
                        VB_SCREEN_RECOVERY_NO_GOOD,
                        0, &vnc);

        /*
         * Scan keyboard more frequently than media, since x86
         * platforms don't like to scan USB too rapidly.
         */
        for (i = 0; i < REC_DISK_DELAY; i += REC_KEY_DELAY) {
            key = VbExKeyboardRead();
            /*
             * We might want to enter dev-mode from the Insert
             * screen if all of the following are true:
             *   - user pressed Ctrl-D
             *   - we can honor the virtual dev switch
             *   - not already in dev mode
             *   - user forced recovery mode
             *   - EC isn't pwned
             */
            if (key == 0x04 &&
                    shared->flags & VBSD_HONOR_VIRT_DEV_SWITCH &&
                    !(shared->flags & VBSD_BOOT_DEV_SWITCH_ON) &&
                    (shared->flags & VBSD_BOOT_REC_SWITCH_ON) &&
                    VbExTrustEC(0)) {
                if (!(shared->flags &
                        VBSD_BOOT_REC_SWITCH_VIRTUAL) &&
                        VbExGetSwitches(
                            VB_INIT_FLAG_REC_BUTTON_PRESSED)) {
                    /*
                     * Is the recovery button stuck?  In
                     * any case we don't like this.  Beep
                     * and ignore.
                     */
                    VBDEBUG(("%s() - ^D but rec switch "
                             "is pressed\n", __func__));
                    VbExBeep(120, 400);
                    continue;
                }

                /* Ask the user to confirm entering dev-mode */
                VbDisplayScreen(cparams,
                                VB_SCREEN_RECOVERY_TO_DEV,
                                0, &vnc);
                /* SPACE means no... */
                uint32_t vbc_flags =
                    VB_CONFIRM_SPACE_MEANS_NO |
                    VB_CONFIRM_MUST_TRUST_KEYBOARD;
                switch (VbUserConfirms(cparams, vbc_flags)) {
                case 1:
                    VBDEBUG(("%s() Enabling dev-mode...\n",
                             __func__));
                    if (TPM_SUCCESS != SetVirtualDevMode(1))
                        return VBERROR_TPM_SET_BOOT_MODE_STATE;
                    VBDEBUG(("%s() Reboot so it will take "
                             "effect\n", __func__));
                    if (VbExGetSwitches
                            (VB_INIT_FLAG_ALLOW_USB_BOOT))
                        VbAllowUsbBoot();
                    return VBERROR_TPM_REBOOT_REQUIRED;
                case -1:
                    VBDEBUG(("%s() - Shutdown requested\n",
                             __func__));
                    return VBERROR_SHUTDOWN_REQUESTED;
                default: /* zero, actually */
                    VBDEBUG(("%s() - Not enabling "
                             "dev-mode\n", __func__));
                    /*
                     * Jump out of the outer loop to
                     * refresh the display quickly.
                     */
                    i = 4;
                    break;
                }
            } else {
                VbCheckDisplayKey(cparams, key, &vnc);
            }
            if (VbWantShutdown(cparams->gbb->flags))
                return VBERROR_SHUTDOWN_REQUESTED;
            VbExSleepMs(REC_KEY_DELAY);
        }
    }

    return VBERROR_SUCCESS;
}