summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAllen Martin <amartin@nvidia.com>2013-08-01 13:28:20 -0700
committerAllen Martin <amartin@nvidia.com>2013-09-20 13:02:43 -0700
commit20ba26c645da700119ec5009872d854688a45a6d (patch)
tree46037f86939751354d9330cc6901caaec4a5c903
parentc73154420b3f9c227da05d3a45d61b8d719d2985 (diff)
downloadtegrarcm-20ba26c645da700119ec5009872d854688a45a6d.tar.gz
tegrarcm: Add readbct support
Add a new command "readbct" which will read the BCT from the target system and write it to bctfile. Signed-off-by: Allen Martin <amartin@nvidia.com> Reviewed-by: Stephen Warren <swarren@nvidia.com>
-rw-r--r--src/main.c125
-rw-r--r--src/nv3p.c10
-rw-r--r--src/nv3p.h16
-rw-r--r--src/tegrarcm.1.in17
4 files changed, 147 insertions, 21 deletions
diff --git a/src/main.c b/src/main.c
index 80de04c..46db14c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -69,6 +69,7 @@ static void dump_platform_info(nv3p_platform_info_t *info);
static int download_bct(nv3p_handle_t h3p, char *filename);
static int download_bootloader(nv3p_handle_t h3p, char *filename,
uint32_t entry, uint32_t loadaddr);
+static int read_bct(nv3p_handle_t h3p, char *filename);
enum cmdline_opts {
OPT_BCT,
@@ -88,6 +89,14 @@ static void print_version(char *progname)
static void usage(char *progname)
{
fprintf(stderr, "usage: %s [options] --bct=bctfile --bootloader=blfile --loadaddr=<loadaddr>\n", progname);
+ fprintf(stderr, " %s [options] --bct=bctfile readbct\n", progname);
+ fprintf(stderr, "\n");
+ fprintf(stderr, "Commands:\n");
+ fprintf(stderr, "\treadbct\n");
+ fprintf(stderr, "\t\tRead the BCT from the target device and write to bctfile\n");
+ fprintf(stderr, "\n");
+ fprintf(stderr, "\tDefault operation if no command is specified will download BCT and\n");
+ fprintf(stderr, "\tbootloader to device and start execution of bootloader\n");
fprintf(stderr, "\n");
fprintf(stderr, "Options:\n");
fprintf(stderr, "\t--entryaddr=<entryaddr>\n");
@@ -116,6 +125,7 @@ int main(int argc, char **argv)
uint32_t loadaddr = 0;
uint32_t entryaddr = 0;
uint16_t devid;
+ int do_read = 0;
static struct option long_options[] = {
[OPT_BCT] = {"bct", 1, 0, 0},
@@ -152,6 +162,7 @@ int main(int argc, char **argv)
case OPT_VERSION:
print_version(argv[0]);
exit(0);
+ break;
case OPT_HELP:
default:
usage(argv[0]);
@@ -165,29 +176,43 @@ int main(int argc, char **argv)
}
}
+ while (optind < argc) {
+ if (!(strcmp(argv[optind], "readbct")))
+ do_read = 1;
+ else {
+ fprintf(stderr, "%s: Unknown command line argument: %s\n",
+ argv[0], argv[optind]);
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ optind++;
+ }
+
if (bctfile == NULL) {
fprintf(stderr, "BCT file must be specified\n");
usage(argv[0]);
exit(EXIT_FAILURE);
}
- if (blfile == NULL) {
- fprintf(stderr, "bootloader file must be specified\n");
- usage(argv[0]);
- exit(EXIT_FAILURE);
- }
- if (loadaddr == 0) {
- fprintf(stderr, "loadaddr must be specified\n");
- usage(argv[0]);
- exit(EXIT_FAILURE);
- }
- if (entryaddr == 0) {
- entryaddr = loadaddr;
- }
-
printf("bct file: %s\n", bctfile);
- printf("booloader file: %s\n", blfile);
- printf("load addr 0x%x\n", loadaddr);
- printf("entry addr 0x%x\n", entryaddr);
+
+ if (!do_read) {
+ if (blfile == NULL) {
+ fprintf(stderr, "bootloader file must be specified\n");
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ if (loadaddr == 0) {
+ fprintf(stderr, "loadaddr must be specified\n");
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ if (entryaddr == 0) {
+ entryaddr = loadaddr;
+ }
+ printf("booloader file: %s\n", blfile);
+ printf("load addr 0x%x\n", loadaddr);
+ printf("entry addr 0x%x\n", entryaddr);
+ }
usb = usb_open(USB_VENID_NVIDIA, &devid);
if (!usb)
@@ -219,6 +244,16 @@ int main(int argc, char **argv)
if (ret)
error(1, errno, "3p open failed");
+ // read the BCT
+ if (do_read) {
+ printf("reading BCT from system, writing to %s...", bctfile);
+ ret = read_bct(h3p, bctfile);
+ if (ret)
+ error(1, errno, "error reading bct");
+ printf("done!\n");
+ exit(0);
+ }
+
// get platform info and dump it
ret = nv3p_cmd_send(h3p, NV3P_CMD_GET_PLATFORM_INFO, (uint8_t *)&info);
if (ret)
@@ -595,6 +630,62 @@ static int download_bct(nv3p_handle_t h3p, char *filename)
}
+static int read_bct(nv3p_handle_t h3p, char *filename)
+{
+ int ret;
+ nv3p_bct_info_t bct_info;
+ uint8_t *bct_data = NULL;
+ int fd = -1;
+ uint8_t *buf;
+
+ ret = nv3p_cmd_send(h3p, NV3P_CMD_GET_BCT, (uint8_t *)&bct_info);
+ if (ret) {
+ dprintf("error sending get bct command\n");
+ goto out;
+ }
+ ret = wait_status(h3p);
+ if (ret) {
+ dprintf("error waiting for status after get bct\n");
+ goto out;
+ }
+
+ bct_data = (uint8_t *)malloc(bct_info.length);
+ ret = nv3p_data_recv(h3p, bct_data, bct_info.length);
+ if (ret) {
+ dprintf("error retreiving bct data\n");
+ goto out;
+ }
+
+ fd = open(filename, O_WRONLY | O_CREAT, 0644);
+ if (fd < 0) {
+ dprintf("error opening %s for reading\n", filename);
+ ret = errno;
+ goto out;
+ }
+
+ buf = bct_data;
+ while(bct_info.length > 0) {
+ ssize_t written = write(fd, buf, bct_info.length);
+ if (written == -1) {
+ if (errno == EINTR)
+ continue;
+ dprintf("error writing to %s\n", filename);
+ ret = errno;
+ goto out;
+ }
+ buf += written;
+ bct_info.length -= written;
+ }
+
+ ret = 0;
+out:
+ if (bct_data)
+ free(bct_data);
+ if (fd >= 0)
+ close(fd);
+ return ret;
+}
+
static int download_bootloader(nv3p_handle_t h3p, char *filename,
uint32_t entry, uint32_t loadaddr)
{
diff --git a/src/nv3p.c b/src/nv3p.c
index b3f6045..b2dff42 100644
--- a/src/nv3p.c
+++ b/src/nv3p.c
@@ -123,7 +123,7 @@ typedef struct nv3p_state {
* double the currently-largest command size, just to have some wiggle-room
* (updates to commands without fixing this on accident, etc.)
*/
-#define NV3P_MAX_COMMAND_SIZE 128
+#define NV3P_MAX_COMMAND_SIZE (2 << 12)
#define NV3P_MAX_ACK_SIZE \
NV3P_PACKET_SIZE_BASIC + \
@@ -209,7 +209,6 @@ static int nv3p_recv_hdr(nv3p_handle_t h3p, nv3p_header_t *hdr,
uint32_t *checksum );
static int nv3p_drain_packet(nv3p_handle_t h3p, nv3p_header_t *hdr );
static void nv3p_nack(nv3p_handle_t h3p, uint32_t code);
-static int nv3p_data_recv(nv3p_handle_t h3p, uint8_t *data, uint32_t length);
static int nv3p_read(usb_device_t *usb, uint8_t *buf, int len);
static int nv3p_get_args(nv3p_handle_t h3p, uint32_t command, void **args,
uint8_t *packet );
@@ -321,6 +320,7 @@ static void nv3p_write_cmd(nv3p_handle_t h3p, uint32_t command, void *args,
switch(command) {
case NV3P_CMD_GET_PLATFORM_INFO:
+ case NV3P_CMD_GET_BCT:
// no args or output only
*length = 0;
WRITE32(tmp, *length);
@@ -418,6 +418,9 @@ static int nv3p_get_cmd_return(nv3p_handle_t h3p, uint32_t command, void *args)
case NV3P_CMD_GET_PLATFORM_INFO:
length = sizeof(nv3p_platform_info_t);
break;
+ case NV3P_CMD_GET_BCT:
+ length = sizeof(nv3p_bct_info_t);
+ break;
case NV3P_CMD_DL_BCT:
case NV3P_CMD_DL_BL:
break;
@@ -467,7 +470,7 @@ static int nv3p_recv_hdr(nv3p_handle_t h3p, nv3p_header_t *hdr,
return 0;
}
-static int nv3p_data_recv(nv3p_handle_t h3p, uint8_t *data, uint32_t length)
+int nv3p_data_recv(nv3p_handle_t h3p, uint8_t *data, uint32_t length)
{
int ret;
uint8_t *tmp;
@@ -629,6 +632,7 @@ static int nv3p_get_args(nv3p_handle_t h3p, uint32_t command, void **args,
switch(command) {
case NV3P_CMD_GET_PLATFORM_INFO:
+ case NV3P_CMD_GET_BCT:
// output only
break;
case NV3P_CMD_STATUS:
diff --git a/src/nv3p.h b/src/nv3p.h
index 2f4c94e..e3498bc 100644
--- a/src/nv3p.h
+++ b/src/nv3p.h
@@ -39,6 +39,7 @@
// commands
#define NV3P_CMD_GET_PLATFORM_INFO 0x01
+#define NV3P_CMD_GET_BCT 0x02
#define NV3P_CMD_DL_BCT 0x04
#define NV3P_CMD_DL_BL 0x06
#define NV3P_CMD_STATUS 0x0a
@@ -155,6 +156,20 @@ typedef struct {
/*
+ * nv3p_bct_info_t: holds information about BCT size
+ */
+typedef struct {
+ uint32_t length;
+} nv3p_bct_info_t;
+
+/*
+ * nv3p_cmd_get_bct_t: retrieves the BCT from the device
+ */
+typedef struct {
+ uint32_t length;
+} nv3p_cmd_get_bct_t;
+
+/*
* nv3p_cmd_dl_bct_t: downloads the system's BCT.
*/
typedef struct {
@@ -176,5 +191,6 @@ int nv3p_cmd_send(nv3p_handle_t h3p, uint32_t command, void *args);
int nv3p_cmd_recv(nv3p_handle_t h3p, uint32_t *command, void **args);
int nv3p_data_send(nv3p_handle_t h3p, uint8_t *data, uint32_t length);
void nv3p_ack(nv3p_handle_t h3p);
+int nv3p_data_recv(nv3p_handle_t h3p, uint8_t *data, uint32_t length);
#endif // NV3P_H
diff --git a/src/tegrarcm.1.in b/src/tegrarcm.1.in
index 011d169..7993110 100644
--- a/src/tegrarcm.1.in
+++ b/src/tegrarcm.1.in
@@ -40,6 +40,11 @@ Build some firmware for your device (such as u-boot)
.IP \(em
Run tegrarcm to download the firmware
+.SH COMMANDS
+.TP
+.B readbct
+Read the BCT from the target device and write it to \fIbctfile\fP.
+
.SH OPTIONS
.TP
.B \-\-bct \fIbctfile\fP
@@ -67,8 +72,9 @@ Print the version number and exit.
.TP
.B \-\-help
Print help text and exit.
+.TP
-.SH EXAMPLE
+.SH EXAMPLES
To download u-boot firmware to a Tegra20 seaboard:
.nf
@@ -101,6 +107,15 @@ sending file: u-boot.bin
u-boot.bin sent successfully
.fi
+To read the BCT from a system:
+
+.nf
+$ sudo tegrarcm --bct ventana.bct readbct
+bct file: ventana.bct
+device id: 0x7820
+reading BCT from system, writing to ventana.bct...done!
+.fi
+
.SH RETURN VALUE
If any error occurs a non zero exit status is returned.