blob: 50e04298062d37b986ee2d06a230d3b2a20185d5 [file] [log] [blame]
/*
* Copyright 2010, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*/
/*
* Support Chrome OS Verify Boot
*/
#include <common.h>
#include <command.h>
#include <part.h>
#include <boot_device.h>
#define USAGE(ret, cmdtp, fmt, ...) do { \
printf(fmt, ##__VA_ARGS__); \
cmd_usage(cmdtp); \
return (ret); \
} while (0);
block_dev_desc_t *get_bootdev(void);
int set_bootdev(char *ifname, int dev, int part);
int do_cros (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
int do_bootdev (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
int do_cros_help(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
U_BOOT_CMD(cros, CONFIG_SYS_MAXARGS, 1, do_cros,
"perform action (try \"cros help\")",
"[action [args...]]\n - perform action with arguments"
);
cmd_tbl_t cmd_cros_sub[] = {
U_BOOT_CMD_MKENT(bootdev, 4, 1, do_bootdev,
"show/set/read/write boot device",
"[sub-action args...]\n - perform sub-action\n"
"\n"
"Subactions:\n"
" - show boot device (when no sub-action)\n"
"set iface dev [part]\n - set boot device\n"
"read addr block count\n - read from boot device\n"
"write addr block count\n - write to boot device"),
U_BOOT_CMD_MKENT(help, 1, 1, do_cros_help,
"show this message",
"[action]")
};
int do_cros(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
cmd_tbl_t *c;
if (argc < 2)
USAGE(0, cmdtp, "Missing action\n");
c = find_cmd_tbl(argv[1], &cmd_cros_sub[0], ARRAY_SIZE(cmd_cros_sub));
if (!c)
USAGE(1, cmdtp, "Unrecognized action: %s\n", argv[1]);
return c->cmd(c, flag, argc - 1, argv + 1);
}
int do_bootdev(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
enum {
SET, READ, WRITE
} opcode;
block_dev_desc_t *dev_desc;
int dev, part, retcode;
uint64_t blk, cnt;
void *buf;
if (argc < 2) { /* show boot device information */
if ((dev_desc = get_bootdev()) == NULL)
puts("No boot device set\n");
else
dev_print(dev_desc);
return 0;
}
if (!strcmp(argv[1], "set"))
opcode = SET;
else if (!strcmp(argv[1], "read"))
opcode = READ;
else if (!strcmp(argv[1], "write"))
opcode = WRITE;
else
USAGE(1, cmdtp, "Unrecognized action: %s\n", argv[1]);
/* apply De Morgan's laws on
* !((argc == 4 && opcode == SET) || argc == 5) */
if ((argc != 4 || opcode != SET) && argc != 5)
USAGE(1, cmdtp, "Wrong number of arguments\n");
if (opcode == SET) {
dev = (int) simple_strtoul(argv[3], NULL, 16);
part = (argc == 5) ?
0 : (int) simple_strtoul(argv[4], NULL, 16);
if (set_bootdev(argv[2], dev, part)) {
puts("Set bootdev failed\n");
return 1;
}
return 0;
}
/* assert(opcode == READ || opcode == WRITE); */
buf = (void *) simple_strtoul(argv[2], NULL, 16);
blk = (uint64_t) simple_strtoul(argv[3], NULL, 16);
cnt = (uint64_t) simple_strtoul(argv[4], NULL, 16);
retcode = (opcode == READ) ?
BootDeviceReadLBA(blk, cnt, buf) :
BootDeviceWriteLBA(blk, cnt, buf);
if (retcode)
USAGE(1, cmdtp, opcode == READ ?
"Read failed\n" : "Write failed\n");
return 0;
}
int do_cros_help(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
cmd_tbl_t *c;
if (argc < 2)
return _do_help(&cmd_cros_sub[0], ARRAY_SIZE(cmd_cros_sub),
cmdtp, flag, argc, argv);
c = find_cmd_tbl(argv[1], &cmd_cros_sub[0], ARRAY_SIZE(cmd_cros_sub));
if (!c)
USAGE(1, cmdtp, "Unrecognized action: %s\n", argv[1]);
cmd_usage(c);
return 0;
}