summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2015-03-20 16:26:21 +0100
committerThierry Reding <treding@nvidia.com>2015-03-20 16:26:21 +0100
commit9ce6de2c121026008bc39193f5d367f37bac2ae0 (patch)
tree59a28f9b57ec55f5a80472b952a9048949111981
parentb007364b9fd63afd42036e128d3ed6be69278af5 (diff)
downloadtegrarcm-dev/treding/wip.tar.gz
Restructure code basedev/treding/wip
-rw-r--r--src/Makefile.am3
-rw-r--r--src/common.h43
-rw-r--r--src/main.c406
-rw-r--r--src/rcm.c476
-rw-r--r--src/rcm.h56
-rw-r--r--src/soc.c99
-rw-r--r--src/soc.h49
-rw-r--r--src/usb.c7
-rw-r--r--src/usb.h5
9 files changed, 596 insertions, 548 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index ba167f0..d5e8d37 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -21,6 +21,9 @@ tegrarcm_SOURCES = \
miniloader/tegra132-miniloader.h \
miniloader/tegra132-preboot-mts.h \
miniloader/tegra132-mts.h \
+ common.h \
+ soc.c \
+ soc.h \
usb.h
man_MANS = tegrarcm.1
diff --git a/src/common.h b/src/common.h
new file mode 100644
index 0000000..fea8f0e
--- /dev/null
+++ b/src/common.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015, NVIDIA CORPORATION. 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 NVIDIA CORPORATION 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 ``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.
+ */
+
+#ifndef _COMMON_H
+#define _COMMON_H
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+struct binary {
+ const void *data;
+ size_t size;
+ uint32_t entry;
+};
+
+#endif
diff --git a/src/main.c b/src/main.c
index 4c69905..a75f153 100644
--- a/src/main.c
+++ b/src/main.c
@@ -26,6 +26,8 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+
+#include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
@@ -47,42 +49,22 @@
#include "rcm.h"
#include "debug.h"
#include "config.h"
+#include "soc.h"
-// tegra20 miniloader
-#include "miniloader/tegra20-miniloader.h"
-
-// tegra30 miniloader
-#include "miniloader/tegra30-miniloader.h"
-
-// tegra114 miniloader
-#include "miniloader/tegra114-miniloader.h"
-
-// tegra124 miniloader
-#include "miniloader/tegra124-miniloader.h"
-
-// tegra132 miniloader
-#include "miniloader/tegra132-miniloader.h"
-
-// tegra132 preboot mts
-#include "miniloader/tegra132-preboot-mts.h"
-
-// tegra132 mts
-#include "miniloader/tegra132-mts.h"
-
-static int initialize_rcm(uint16_t devid, usb_device_t *usb);
-static int initialize_miniloader(uint16_t devid, usb_device_t *usb, char *mlfile, uint32_t mlentry);
-static int initialize_preboot(usb_device_t *usb, char *pbfile, uint32_t pbentry, char *mtsdir);
+static int initialize_rcm(const struct soc *soc, usb_device_t *usb);
+static int initialize_miniloader(const struct soc *soc, usb_device_t *usb,
+ const char *filename, uint32_t entry);
+static int initialize_preboot(const struct soc *soc, usb_device_t *usb,
+ const char *filename, uint32_t entry);
static int wait_status(nv3p_handle_t h3p);
static int send_file(nv3p_handle_t h3p, const char *filename);
-static int send_buf(nv3p_handle_t h3p, uint8_t *buf, uint64_t total);
-static int download_binary(uint32_t cmd, usb_device_t *usb,
- uint8_t *miniloader, uint32_t size, uint32_t entry);
+static int download_binary(const struct soc *soc, uint32_t cmd,
+ usb_device_t *usb, struct binary *binary);
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 download_mts(nv3p_handle_t h3p, char *filename,
- uint32_t loadaddr, uint16_t devid, char *mtsdir);
+static int download_mts(nv3p_handle_t h3p, char *filename, uint32_t loadaddr);
static int read_bct(nv3p_handle_t h3p, char *filename);
enum cmdline_opts {
@@ -99,7 +81,6 @@ enum cmdline_opts {
OPT_PREBOOTENTRY,
OPT_MTS,
OPT_MTSENTRY,
- OPT_MTSDIR,
OPT_END,
};
@@ -141,10 +122,6 @@ static void usage(char *progname)
fprintf(stderr, "\t\tRead the cpu ucode from given file\n");
fprintf(stderr, "\t--mts-entry=<mtsentry>\n");
fprintf(stderr, "\t\tSpecify the entry point for the cpu ucode\n");
- fprintf(stderr, "\t--mts-dir=full_mts_directory\n");
- fprintf(stderr, "\t\tRead ucode files from given location with pre-defined\n");
- fprintf(stderr, "\t\tfile name preboot_cr.bin and mts_cr.bin. mts-dir takes\n");
- fprintf(stderr, "\t\tprecedence over mts and preboot options\n");
fprintf(stderr, "\n");
}
@@ -163,6 +140,7 @@ int main(int argc, char **argv)
char *blfile = NULL;
uint32_t loadaddr = 0;
uint32_t entryaddr = 0;
+ const struct soc *soc;
uint16_t devid;
int do_read = 0;
char *mlfile = NULL;
@@ -171,7 +149,6 @@ int main(int argc, char **argv)
uint32_t pbentry = 0;
char *mtsfile = NULL;
uint32_t mtsentry = 0;
- char *mtsdir = NULL;
static struct option long_options[] = {
[OPT_BCT] = {"bct", 1, 0, 0},
@@ -187,7 +164,6 @@ int main(int argc, char **argv)
[OPT_PREBOOTENTRY] = {"preboot-entry", 1, 0, 0},
[OPT_MTS] = {"mts", 1, 0, 0},
[OPT_MTSENTRY] = {"mts-entry", 1, 0, 0},
- [OPT_MTSDIR] = {"mts-dir", 1, 0, 0},
[OPT_END] = {0, 0, 0, 0}
};
@@ -236,9 +212,6 @@ int main(int argc, char **argv)
case OPT_MTSENTRY:
mtsentry = strtoul(optarg, NULL, 0);
break;
- case OPT_MTSDIR:
- mtsdir = optarg;
- break;
case OPT_HELP:
default:
usage(argv[0]);
@@ -295,6 +268,14 @@ int main(int argc, char **argv)
error(1, errno, "could not open USB device");
printf("device id: 0x%x\n", devid);
+ soc = soc_detect(devid);
+ if (!soc) {
+ fprintf(stderr, "unsupported SoC: %04x\n", devid);
+ return 1;
+ }
+
+ printf("NVIDIA %s detected\n", soc->name);
+
ret = usb_read(usb, (uint8_t *)uid, sizeof(uid), &actual_len);
if (!ret) {
if (actual_len == 8)
@@ -306,24 +287,25 @@ int main(int argc, char **argv)
error(1, errno, "USB read truncated");
// initialize rcm
- ret2 = initialize_rcm(devid, usb);
+ ret2 = initialize_rcm(soc, usb);
if (ret2)
error(1, errno, "error initializing RCM protocol");
// download the mts_preboot ucode
- if ((devid & 0xff) == USB_DEVID_NVIDIA_TEGRA132) {
- ret2 = initialize_preboot(usb, pbfile, pbentry, mtsdir);
+ if (soc->needs_mts) {
+ ret2 = initialize_preboot(soc, usb, pbfile, pbentry);
if (ret2)
error(1, errno, "error initializing preboot mts");
}
// download the miniloader to start nv3p
- ret2 = initialize_miniloader(devid, usb, mlfile, mlentry);
+ ret2 = initialize_miniloader(soc, usb, mlfile, mlentry);
if (ret2)
error(1, errno, "error initializing miniloader");
// device may have re-enumerated, so reopen USB
usb_close(usb);
+ sleep(1);
usb = usb_open(USB_VENID_NVIDIA, &devid);
if (!usb)
error(1, errno, "could not open USB device");
@@ -367,8 +349,8 @@ int main(int argc, char **argv)
}
// download mts
- if ((devid & 0xff) == USB_DEVID_NVIDIA_TEGRA132) {
- ret = download_mts(h3p, mtsfile, mtsentry, devid, mtsdir);
+ if (soc->needs_mts) {
+ ret = download_mts(h3p, mtsfile, mtsentry);
if (ret)
error(1, ret, "error downloading mts: %s", mtsfile);
}
@@ -384,40 +366,18 @@ int main(int argc, char **argv)
return 0;
}
-static int initialize_rcm(uint16_t devid, usb_device_t *usb)
+static int initialize_rcm(const struct soc *soc, usb_device_t *usb)
{
- int ret;
- uint8_t *msg_buff;
- int msg_len;
+ int ret, msg_len, actual_len;
uint32_t status;
- int actual_len;
-
- // initialize RCM
- if ((devid & 0xff) == USB_DEVID_NVIDIA_TEGRA20 ||
- (devid & 0xff) == USB_DEVID_NVIDIA_TEGRA30) {
- dprintf("initializing RCM version 1\n");
- ret = rcm_init(RCM_VERSION_1);
- } else if ((devid & 0xff) == USB_DEVID_NVIDIA_TEGRA114) {
- dprintf("initializing RCM version 35\n");
- ret = rcm_init(RCM_VERSION_35);
- } else if ((devid & 0xff) == USB_DEVID_NVIDIA_TEGRA124 ||
- (devid & 0xff) == USB_DEVID_NVIDIA_TEGRA132) {
- dprintf("initializing RCM version 40\n");
- ret = rcm_init(RCM_VERSION_40);
- } else {
- fprintf(stderr, "unknown tegra device: 0x%x\n", devid);
- return errno;
- }
- if (ret) {
- fprintf(stderr, "RCM initialize failed\n");
- return ret;
- }
+ void *msg_buff;
// create query version message
- rcm_create_msg(RCM_CMD_QUERY_RCM_VERSION, NULL, 0, NULL, 0, &msg_buff);
+ rcm_create_msg(soc->rcm, RCM_CMD_QUERY_RCM_VERSION, NULL, 0, NULL, 0,
+ &msg_buff);
// write query version message to device
- msg_len = rcm_get_msg_len(msg_buff);
+ msg_len = rcm_get_msg_len(soc->rcm, msg_buff);
if (msg_len == 0) {
fprintf(stderr, "write RCM query version: unknown message length\n");
return EINVAL;
@@ -446,92 +406,66 @@ static int initialize_rcm(uint16_t devid, usb_device_t *usb)
return 0;
}
-static int initialize_preboot(usb_device_t *usb, char *pbfile, uint32_t pbentry,
- char *mtsdir)
+static int initialize_preboot(const struct soc *soc, usb_device_t *usb,
+ const char *filename, uint32_t entry)
{
- int fd;
+ struct binary preboot;
struct stat sb;
- int ret;
- uint8_t *preboot, *_preboot = NULL;
- uint32_t pb_size;
- uint32_t pb_entry;
- char *_mtsdir = NULL;
-
- if (!mtsdir && !pbfile) {
- mtsdir = _mtsdir = (char *)malloc(strlen(TEGRA132_MTS_DIR) + 1);
- sprintf(mtsdir, "%s", TEGRA132_MTS_DIR);
+ int fd, ret;
+ void *data;
+
+ if (!filename)
+ return -EINVAL;
+
+ fd = open(filename, O_RDONLY, 0);
+ if (fd < 0) {
+ dprintf("error opening %s for reading\n", filename);
+ return -errno;
}
- if (mtsdir) {
- pbfile = (char *)malloc(strlen(mtsdir) + 2
- + strlen(TEGRA132_PREBOOT_MTS_FILE));
- sprintf(pbfile, "%s/%s", mtsdir, TEGRA132_PREBOOT_MTS_FILE);
- pbentry = TEGRA132_PREBOOT_MTS_ENTRY;
+ ret = fstat(fd, &sb);
+ if (ret) {
+ dprintf("error on fstat of %s\n", filename);
+ return -errno;
}
- // use prebuilt preboot mts if not loading from a file
- if (pbfile) {
- fd = open(pbfile, O_RDONLY, 0);
- if (fd < 0) {
- fprintf(stderr, "error: %s\n", pbfile);
- dprintf("error opening %s for reading\n", pbfile);
- ret = errno;
- goto done;
- }
- ret = fstat(fd, &sb);
- if (ret) {
- dprintf("error on fstat of %s\n", pbfile);
- goto done;
- }
- pb_size = sb.st_size;
- preboot = _preboot = (uint8_t *)malloc(pb_size);
- if (!preboot) {
- dprintf("error allocating %d bytes for preboot mts\n", pb_size);
- ret = errno;
- goto done;
- }
- if (read(fd, preboot, pb_size) != pb_size) {
- dprintf("error reading from preboot mts file");
- ret = errno;
- goto done;
- }
- pb_entry = pbentry;
- } else {
- dprintf("error opening %s for reading\n", pbfile);
- ret = errno;
- goto done;
+ data = malloc(sb.st_size);
+ if (!data) {
+ dprintf("error allocating %zu bytes for preboot mts\n",
+ sb.st_size);
+ return -errno;
+ }
+
+ if (read(fd, data, sb.st_size) != sb.st_size) {
+ dprintf("error reading from preboot mts file");
+ return -errno;
}
- printf("downloading preboot mts to target at address 0x%x (%d bytes)...\n",
- pb_entry, pb_size);
- ret = download_binary(RCM_CMD_DL_MTS, usb, preboot,
- pb_size, pb_entry);
+ preboot.size = sb.st_size;
+ preboot.entry = entry;
+ preboot.data = data;
+
+ printf("downloading preboot mts to target at address 0x%x (%zu bytes)...\n",
+ preboot.entry, preboot.size);
+
+ ret = download_binary(soc, RCM_CMD_DL_MTS, usb, &preboot);
if (ret) {
fprintf(stderr, "Error downloading preboot mts\n");
- goto done;
+ return ret;
}
- printf("preboot mts downloaded successfully\n");
-done:
- if (_mtsdir)
- free(_mtsdir);
- if (mtsdir && pbfile)
- free(pbfile);
-
- if (_preboot)
- free(_preboot);
+ printf("preboot mts downloaded successfully\n");
- return ret;
+ return 0;
}
-static int initialize_miniloader(uint16_t devid, usb_device_t *usb, char *mlfile, uint32_t mlentry)
+static int initialize_miniloader(const struct soc *soc, usb_device_t *usb,
+ const char *mlfile, uint32_t mlentry)
{
- int fd;
+ struct binary miniloader;
+ void *data = NULL;
struct stat sb;
- int ret;
- uint8_t *miniloader;
- uint32_t miniloader_size;
- uint32_t miniloader_entry;
+ int fd, ret;
// use prebuilt miniloader if not loading from a file
if (mlfile) {
@@ -545,47 +479,31 @@ static int initialize_miniloader(uint16_t devid, usb_device_t *usb, char *mlfile
dprintf("error on fstat of %s\n", mlfile);
return ret;
}
- miniloader_size = sb.st_size;
- miniloader = (uint8_t *)malloc(miniloader_size);
- if (!miniloader) {
- dprintf("error allocating %d bytes for miniloader\n", miniloader_size);
+ miniloader.size = sb.st_size;
+ data = malloc(miniloader.size);
+ if (!data) {
+ dprintf("error allocating %zu bytes for miniloader\n", miniloader.size);
return errno;
}
- if (read(fd, miniloader, miniloader_size) != miniloader_size) {
+ if (read(fd, data, miniloader.size) != miniloader.size) {
dprintf("error reading from miniloader file");
return errno;
}
- miniloader_entry = mlentry;
+ miniloader.entry = mlentry;
+ miniloader.data = data;
} else {
- if ((devid & 0xff) == USB_DEVID_NVIDIA_TEGRA20) {
- miniloader = miniloader_tegra20;
- miniloader_size = sizeof(miniloader_tegra20);
- miniloader_entry = TEGRA20_MINILOADER_ENTRY;
- } else if ((devid & 0xff) == USB_DEVID_NVIDIA_TEGRA30) {
- miniloader = miniloader_tegra30;
- miniloader_size = sizeof(miniloader_tegra30);
- miniloader_entry = TEGRA30_MINILOADER_ENTRY;
- } else if ((devid & 0xff) == USB_DEVID_NVIDIA_TEGRA114) {
- miniloader = miniloader_tegra114;
- miniloader_size = sizeof(miniloader_tegra114);
- miniloader_entry = TEGRA114_MINILOADER_ENTRY;
- } else if ((devid & 0xff) == USB_DEVID_NVIDIA_TEGRA124) {
- miniloader = miniloader_tegra124;
- miniloader_size = sizeof(miniloader_tegra124);
- miniloader_entry = TEGRA124_MINILOADER_ENTRY;
- } else if ((devid & 0xff) == USB_DEVID_NVIDIA_TEGRA132) {
- miniloader = miniloader_tegra132;
- miniloader_size = sizeof(miniloader_tegra132);
- miniloader_entry = TEGRA132_MINILOADER_ENTRY;
- } else {
- fprintf(stderr, "unknown tegra device: 0x%x\n", devid);
- return ENODEV;
+ /* check for a built-in miniloader */
+ if (!soc->miniloader.data) {
+ fprintf(stderr, "no built-in miniloader for %s\n",
+ soc->name);
+ return -ENOENT;
}
+
+ memcpy(&miniloader, &soc->miniloader, sizeof(miniloader));
}
- printf("downloading miniloader to target at address 0x%x (%d bytes)...\n",
- miniloader_entry, miniloader_size);
- ret = download_binary(RCM_CMD_DL_MINILOADER, usb, miniloader,
- miniloader_size, miniloader_entry);
+ printf("downloading miniloader to target at address 0x%x (%zu bytes)...\n",
+ miniloader.entry, miniloader.size);
+ ret = download_binary(soc, RCM_CMD_DL_MINILOADER, usb, &miniloader);
if (ret) {
fprintf(stderr, "Error downloading miniloader\n");
return ret;
@@ -631,48 +549,9 @@ fail:
return ret;
}
-
/*
-* send_buf: send data present in buffer to nv3p server
-*/
-static int send_buf(nv3p_handle_t h3p, uint8_t *buf, uint64_t total)
-{
- int ret = 0;
- uint32_t size;
- uint64_t count;
- char *spinner = "-\\|/";
- int spin_idx = 0;
-
-#define NVFLASH_DOWNLOAD_CHUNK (1024 * 64)
-
- printf("sending data:\n");
-
- count = 0;
- while(count != total) {
- size = (uint32_t)MIN(total - count, NVFLASH_DOWNLOAD_CHUNK);
-
- ret = nv3p_data_send(h3p, buf, size);
- if (ret)
- goto fail;
-
- count += size;
- buf += size;
-
- printf("\r%c %" PRIu64 "/%" PRIu64" bytes sent", spinner[spin_idx],
- count, total);
- spin_idx = (spin_idx + 1) % 4;
- }
- printf("\ndata sent successfully\n");
-
-#undef NVFLASH_DOWNLOAD_CHUNK
-
-fail:
- return ret;
-}
-
-/*
-* send_file: send data present in file "filename" to nv3p server.
-*/
+ * send_file: send data present in file "filename" to nv3p server.
+ */
static int send_file(nv3p_handle_t h3p, const char *filename)
{
int ret;
@@ -746,18 +625,17 @@ fail:
}
-static int download_binary(uint32_t cmd, usb_device_t *usb,
- uint8_t *binary, uint32_t size, uint32_t entry)
+static int download_binary(const struct soc *soc, uint32_t cmd,
+ usb_device_t *usb, struct binary *binary)
{
int ret, actual_len;
uint32_t status;
void *msg_buff;
// create download message
- rcm_create_msg(cmd,
- (uint8_t *)&entry, sizeof(entry), binary, size,
- &msg_buff);
- ret = usb_write(usb, msg_buff, rcm_get_msg_len(msg_buff));
+ rcm_create_msg(soc->rcm, cmd, &binary->entry, sizeof(binary->entry),
+ binary->data, binary->size, &msg_buff);
+ ret = usb_write(usb, msg_buff, rcm_get_msg_len(soc->rcm, msg_buff));
if (ret) {
dprintf("error sending %x command to target\n", cmd);
goto fail;
@@ -995,85 +873,59 @@ static int download_bootloader(nv3p_handle_t h3p, char *filename,
return ret;
}
+ ret = wait_status(h3p);
+ if (ret) {
+ dprintf("error waiting for status on bootloader dl\n");
+ return ret;
+ }
+
return 0;
}
-static int download_mts(nv3p_handle_t h3p, char *filename,
- uint32_t loadaddr, uint16_t devid, char *mtsdir)
+static int download_mts(nv3p_handle_t h3p, char *filename, uint32_t loadaddr)
{
nv3p_cmd_dl_mts_t arg;
struct stat sb;
- char *_mtsdir = NULL;
int ret, fd;
- if (!mtsdir && !filename) {
- mtsdir = _mtsdir = (char *)malloc(strlen(TEGRA132_MTS_DIR) + 1);
- sprintf(mtsdir, "%s", TEGRA132_MTS_DIR);
- }
+ if (!filename)
+ return -EINVAL;
- if (mtsdir) {
- filename = (char *)malloc(strlen(mtsdir) + 2
- + strlen(TEGRA132_MTS_FILE));
- sprintf(filename, "%s/%s", mtsdir, TEGRA132_MTS_FILE);
- loadaddr = TEGRA132_MTS_ENTRY;
+ fd = open(filename, O_RDONLY, 0);
+ if (fd < 0) {
+ dprintf("error opening %s for reading\n", filename);
+ return errno;
}
- if (filename) {
- fd = open(filename, O_RDONLY, 0);
- if (fd < 0) {
- fprintf(stderr, "error: %s\n", filename);
- dprintf("error opening %s for reading\n", filename);
- ret = errno;
- goto done;
- }
+ ret = fstat(fd, &sb);
+ if (ret) {
+ dprintf("error on fstat of %s\n", filename);
+ return errno;
+ }
- ret = fstat(fd, &sb);
- if (ret) {
- dprintf("error on fstat of %s\n", filename);
- goto done;
- }
- close(fd);
+ close(fd);
- arg.length = sb.st_size;
- arg.address = loadaddr;
- } else {
- dprintf("error opening %s for reading\n", filename);
- ret = errno;
- goto done;
- }
+ arg.length = sb.st_size;
+ arg.address = loadaddr;
ret = nv3p_cmd_send(h3p, NV3P_CMD_DL_MTS, (uint8_t *)&arg);
if (ret) {
dprintf("error sending 3p mts download command\n");
- goto done;
+ return ret;
}
- if (filename) {
- // send the mts file
- ret = send_file(h3p, filename);
- if (ret) {
- dprintf("error downloading mts\n");
- goto done;
- }
- } else {
- ret = send_buf(h3p, buf, arg.length);
- if (ret) {
- dprintf("error downloading mts\n");
- goto done;
- }
+ // send the mts file
+ ret = send_file(h3p, filename);
+ if (ret) {
+ dprintf("error downloading mts\n");
+ return ret;
}
ret = wait_status(h3p);
if (ret) {
dprintf("error waiting for status on mts dl\n");
+ return ret;
}
-done:
- if (_mtsdir)
- free(_mtsdir);
-
- if (mtsdir && filename)
- free(filename);
-
- return ret;
+ return 0;
}
diff --git a/src/rcm.c b/src/rcm.c
index cb53d8f..76e21a6 100644
--- a/src/rcm.c
+++ b/src/rcm.c
@@ -33,354 +33,326 @@
#include "rcm.h"
#include "aes-cmac.h"
-static int rcm_sign_msg(uint8_t *buf);
-static int rcm1_sign_msg(uint8_t *buf);
-static int rcm35_sign_msg(uint8_t *buf);
-static int rcm40_sign_msg(uint8_t *buf);
-static void rcm_init_msg(
- uint8_t *buf,
- uint32_t msg_len,
- uint32_t opcode,
- void *args,
- uint32_t args_len,
- uint32_t payload_len);
-static void rcm1_init_msg(
- uint8_t *buf,
- uint32_t msg_len,
- uint32_t opcode,
- void *args,
- uint32_t args_len,
- uint32_t payload_len);
-static void rcm35_init_msg(
- uint8_t *buf,
- uint32_t msg_len,
- uint32_t opcode,
- void *args,
- uint32_t args_len,
- uint32_t payload_len);
-static void rcm40_init_msg(
- uint8_t *buf,
- uint32_t msg_len,
- uint32_t opcode,
- void *args,
- uint32_t args_len,
- uint32_t payload_len);
-static uint8_t *rcm_get_msg_payload(uint8_t *buf);
-static void rcm_msg_pad(uint8_t *data, uint32_t len);
-static uint32_t rcm_get_pad_len(uint32_t payload_len);
-static uint32_t rcm_get_msg_buf_len(uint32_t payload_len);
-
-static uint32_t rcm_version = 0;
-static uint32_t message_size = 0;
-
-int rcm_init(uint32_t version)
+static uint32_t rcm_get_pad_len(const struct rcm *rcm, uint32_t payload_len)
{
- int ret = -EINVAL;
+ uint32_t msg_len = rcm->message_size + payload_len;
+ uint32_t pad_len = 0;
- if (version == RCM_VERSION_1) {
- rcm_version = version;
- message_size = sizeof(rcm1_msg_t);
- ret = 0;
- }
- else if (version == RCM_VERSION_35) {
- rcm_version = version;
- message_size = sizeof(rcm35_msg_t);
- ret = 0;
- }
- else if (version == RCM_VERSION_40) {
- rcm_version = version;
- message_size = sizeof(rcm40_msg_t);
- ret = 0;
+ // First, use padding to bump the message size up to the minimum.
+ if (msg_len < RCM_MIN_MSG_LENGTH) {
+ pad_len = RCM_MIN_MSG_LENGTH - msg_len;
+ msg_len += pad_len;
}
- return ret;
+
+ /*
+ * Next, add any extra padding needed to bump the relevant subset
+ * of the data up to a multiple of 16 bytes. Subtracting off the
+ * rcm_msg_t size handles the initial data that is not part of
+ * the hashing and encryption.
+ */
+ pad_len += 16 - ((msg_len - rcm->message_size) & 0xf);
+
+ return pad_len;
}
-uint32_t rcm_get_msg_len(uint8_t *msg)
+static void rcm_msg_pad(uint8_t *data, uint32_t len)
{
- if (rcm_version == RCM_VERSION_1)
- return ((rcm1_msg_t*)msg)->len_insecure;
- else if (rcm_version == RCM_VERSION_35)
- return ((rcm35_msg_t*)msg)->len_insecure;
- else if (rcm_version == RCM_VERSION_40)
- return ((rcm40_msg_t*)msg)->len_insecure;
- else
- return 0;
+ if (!len)
+ return;
+
+ *data = 0x80;
+ memset(data+1, 0, len-1);
}
-int rcm_create_msg(
- uint32_t opcode,
- uint8_t *args,
- uint32_t args_len,
- uint8_t *payload,
- uint32_t payload_len,
- uint8_t **buf)
+static void rcm1_init_msg(const struct rcm *rcm, void *buf,
+ uint32_t msg_len, uint32_t opcode,
+ const void *args, uint32_t args_len,
+ uint32_t payload_len)
{
- int ret = 0;
- uint32_t msg_len;
- uint8_t *msg = NULL;
- uint8_t *msg_payload;
+ rcm1_msg_t *msg = buf;
+ uint32_t padding_len;
- // create message buffer
- msg_len = rcm_get_msg_buf_len(payload_len);
- msg = malloc(msg_len);
- if (!msg) {
- ret = -ENOMEM;
- goto done;
- }
+ padding_len = rcm_get_pad_len(rcm, payload_len);
- // initialize message
- rcm_init_msg(msg, msg_len, opcode, args, args_len, payload_len);
+ msg->len_insecure = sizeof(rcm1_msg_t) + payload_len + padding_len;
- // fill message payload
- msg_payload = rcm_get_msg_payload(msg);
- if (payload_len)
- memcpy(msg_payload, payload, payload_len);
+ memset(&msg->cmac_hash, 0x0, sizeof(msg->cmac_hash));
+ memset(&msg->reserved, 0x0, sizeof(msg->reserved));
- // sign message
- rcm_sign_msg(msg);
+ msg->opcode = opcode;
+ msg->len_secure = msg->len_insecure;
+ msg->payload_len = payload_len;
+ msg->rcm_version = RCM_VERSION_1;
-done:
- if (ret) {
- free(msg);
- msg = NULL;
- }
+ if (args_len)
+ memcpy(msg->args, args, args_len);
- *buf = msg;
+ memset(msg->args + args_len, 0x0, sizeof(msg->args) - args_len);
- return ret;
+ rcm_msg_pad(msg->padding, sizeof(msg->padding));
+ rcm_msg_pad(buf + sizeof(rcm1_msg_t) + payload_len, padding_len);
}
-static int rcm_sign_msg(uint8_t *buf)
+static uint32_t rcm1_get_msg_len(const struct rcm *rcm, const void *msg)
{
- if (rcm_version == RCM_VERSION_35)
- return rcm35_sign_msg(buf);
- else if (rcm_version == RCM_VERSION_40)
- return rcm40_sign_msg(buf);
- else if (rcm_version == RCM_VERSION_1)
- return rcm1_sign_msg(buf);
- else
- return -EINVAL;
+ return ((const rcm1_msg_t *)msg)->len_insecure;
}
-static int rcm1_sign_msg(uint8_t *buf)
+static int rcm1_sign_msg(const struct rcm *rcm, void *buf)
{
- rcm1_msg_t *msg;
+ rcm1_msg_t *msg = buf;
uint32_t crypto_len;
- msg = (rcm1_msg_t*)buf;
-
// signing does not include the len_insecure and
// cmac_hash fields at the beginning of the message.
crypto_len = msg->len_insecure - sizeof(msg->len_insecure) -
- sizeof(msg->cmac_hash);
- if (crypto_len % RCM_AES_BLOCK_SIZE) {
+ sizeof(msg->cmac_hash);
+ if (crypto_len % RCM_AES_BLOCK_SIZE)
return -EMSGSIZE;
- }
cmac_hash(msg->reserved, crypto_len, msg->cmac_hash);
return 0;
}
-static int rcm35_sign_msg(uint8_t *buf)
+const struct rcm rcm1 = {
+ .version = RCM_VERSION_1,
+ .message_size = sizeof(rcm1_msg_t),
+ .init_msg = rcm1_init_msg,
+ .get_msg_len = rcm1_get_msg_len,
+ .sign_msg = rcm1_sign_msg,
+};
+
+static void rcm35_init_msg(const struct rcm *rcm, void *buf,
+ uint32_t msg_len, uint32_t opcode,
+ const void *args, uint32_t args_len,
+ uint32_t payload_len)
{
- rcm35_msg_t *msg;
- uint32_t crypto_len;
-
- msg = (rcm35_msg_t*)buf;
+ rcm35_msg_t *msg = buf;
+ uint32_t padding_len;
- // signing does not include the len_insecure, modulus
- // and object signature at the beginning of the message
- crypto_len = msg->len_insecure - sizeof(msg->len_insecure) -
- sizeof(msg->modulus) -
- sizeof(msg->object_sig);
- if (crypto_len % RCM_AES_BLOCK_SIZE) {
- return -EMSGSIZE;
- }
+ padding_len = rcm_get_pad_len(rcm, payload_len);
- cmac_hash(msg->reserved, crypto_len, msg->object_sig.cmac_hash);
- return 0;
-}
+ msg->len_insecure = sizeof(rcm35_msg_t) + payload_len + padding_len;
-static int rcm40_sign_msg(uint8_t *buf)
-{
- rcm40_msg_t *msg;
- uint32_t crypto_len;
+ memset(&msg->object_sig.cmac_hash, 0x0, sizeof(msg->object_sig.cmac_hash));
+ memset(&msg->reserved, 0x0, sizeof(msg->reserved));
- msg = (rcm40_msg_t*)buf;
+ msg->opcode = opcode;
+ msg->len_secure = msg->len_insecure;
+ msg->payload_len = payload_len;
+ msg->rcm_version = RCM_VERSION_35;
- // signing does not include the len_insecure, modulus
- // and object signature at the beginning of the message
- crypto_len = msg->len_insecure - sizeof(msg->len_insecure) -
- sizeof(msg->modulus) -
- sizeof(msg->object_sig);
- if (crypto_len % RCM_AES_BLOCK_SIZE) {
- return -EMSGSIZE;
- }
+ if (args_len)
+ memcpy(msg->args, args, args_len);
- cmac_hash(msg->reserved, crypto_len, msg->object_sig.cmac_hash);
- return 0;
-}
+ memset(msg->args + args_len, 0x0, sizeof(msg->args) - args_len);
-static uint32_t rcm_get_msg_buf_len(uint32_t payload_len)
-{
- return message_size + payload_len +
- rcm_get_pad_len(payload_len);
+ rcm_msg_pad(msg->padding, sizeof(msg->padding));
+ rcm_msg_pad(buf + sizeof(rcm35_msg_t) + payload_len, padding_len);
}
-static uint8_t *rcm_get_msg_payload(uint8_t *buf)
+static uint32_t rcm35_get_msg_len(const struct rcm *rcm, const void *msg)
{
- return buf + message_size;
+ return ((const rcm35_msg_t *)msg)->len_insecure;
}
-static void rcm_msg_pad(uint8_t *data, uint32_t len)
+static int rcm35_sign_msg(const struct rcm *rcm, void *buf)
{
- if (!len)
- return;
+ rcm35_msg_t *msg = buf;
+ uint32_t crypto_len;
- *data = 0x80;
- memset(data+1, 0, len-1);
-}
+ // signing does not include the len_insecure, modulus
+ // and object signature at the beginning of the message
+ crypto_len = msg->len_insecure - sizeof(msg->len_insecure) -
+ sizeof(msg->modulus) - sizeof(msg->object_sig);
+ if (crypto_len % RCM_AES_BLOCK_SIZE)
+ return -EMSGSIZE;
-static void rcm_init_msg(
- uint8_t *buf,
- uint32_t msg_len,
- uint32_t opcode,
- void *args,
- uint32_t args_len,
- uint32_t payload_len)
-{
- if (rcm_version == RCM_VERSION_35)
- rcm35_init_msg(buf, msg_len, opcode, args,
- args_len, payload_len);
- else if (rcm_version == RCM_VERSION_40)
- rcm40_init_msg(buf, msg_len, opcode, args,
- args_len, payload_len);
- else if (rcm_version == RCM_VERSION_1)
- rcm1_init_msg(buf, msg_len, opcode, args,
- args_len, payload_len);
+ cmac_hash(msg->reserved, crypto_len, msg->object_sig.cmac_hash);
+ return 0;
}
-static void rcm35_init_msg(
- uint8_t *buf,
- uint32_t msg_len,
- uint32_t opcode,
- void *args,
- uint32_t args_len,
- uint32_t payload_len)
+const struct rcm rcm35 = {
+ .version = RCM_VERSION_35,
+ .message_size = sizeof(rcm35_msg_t),
+ .init_msg = rcm35_init_msg,
+ .get_msg_len = rcm35_get_msg_len,
+ .sign_msg = rcm35_sign_msg,
+};
+
+static void rcm40_init_msg(const struct rcm *rcm, void *buf,
+ uint32_t msg_len, uint32_t opcode,
+ const void *args, uint32_t args_len,
+ uint32_t payload_len)
{
+ rcm40_msg_t *msg = buf;
uint32_t padding_len;
- rcm35_msg_t *msg;
-
- msg = (rcm35_msg_t *)buf;
- padding_len = rcm_get_pad_len(payload_len);
+ padding_len = rcm_get_pad_len(rcm, payload_len);
- msg->len_insecure = sizeof(rcm35_msg_t) + payload_len +
- padding_len;
+ msg->len_insecure = sizeof(rcm40_msg_t) + payload_len + padding_len;
memset(&msg->object_sig.cmac_hash, 0x0, sizeof(msg->object_sig.cmac_hash));
memset(&msg->reserved, 0x0, sizeof(msg->reserved));
- msg->opcode = opcode;
- msg->len_secure = msg->len_insecure;
- msg->payload_len = payload_len;
- msg->rcm_version = RCM_VERSION_35;
+ msg->opcode = opcode;
+ msg->len_secure = msg->len_insecure;
+ msg->payload_len = payload_len;
+ msg->rcm_version = RCM_VERSION_40;
if (args_len)
memcpy(msg->args, args, args_len);
+
memset(msg->args + args_len, 0x0, sizeof(msg->args) - args_len);
rcm_msg_pad(msg->padding, sizeof(msg->padding));
- rcm_msg_pad(buf + sizeof(rcm35_msg_t) + payload_len, padding_len);
+ rcm_msg_pad(buf + sizeof(rcm40_msg_t) + payload_len, padding_len);
}
-static void rcm40_init_msg(
- uint8_t *buf,
- uint32_t msg_len,
- uint32_t opcode,
- void *args,
- uint32_t args_len,
- uint32_t payload_len)
+static int rcm40_sign_msg(const struct rcm *rcm, void *buf)
{
- uint32_t padding_len;
- rcm40_msg_t *msg;
+ rcm40_msg_t *msg = buf;
+ uint32_t crypto_len;
- msg = (rcm40_msg_t *)buf;
+ // signing does not include the len_insecure, modulus
+ // and object signature at the beginning of the message
+ crypto_len = msg->len_insecure - sizeof(msg->len_insecure) -
+ sizeof(msg->modulus) - sizeof(msg->object_sig);
+ if (crypto_len % RCM_AES_BLOCK_SIZE)
+ return -EMSGSIZE;
- padding_len = rcm_get_pad_len(payload_len);
+ cmac_hash(msg->reserved, crypto_len, msg->object_sig.cmac_hash);
+ return 0;
+}
- msg->len_insecure = sizeof(rcm40_msg_t) + payload_len +
- padding_len;
+static uint32_t rcm40_get_msg_len(const struct rcm *rcm, const void *msg)
+{
+ return ((const rcm40_msg_t *)msg)->len_insecure;
+}
+
+const struct rcm rcm40 = {
+ .version = RCM_VERSION_40,
+ .message_size = sizeof(rcm40_msg_t),
+ .init_msg = rcm40_init_msg,
+ .get_msg_len = rcm40_get_msg_len,
+ .sign_msg = rcm40_sign_msg,
+};
+
+static void rcm21_init_msg(const struct rcm *rcm, void *buf,
+ uint32_t msg_len, uint32_t opcode,
+ const void *args, uint32_t args_len,
+ uint32_t payload_len)
+{
+ rcm21_msg_t *msg = buf;
+ uint32_t padding_len;
+
+ padding_len = rcm_get_pad_len(rcm, payload_len);
+
+ msg->len_insecure = sizeof(rcm21_msg_t) + payload_len + padding_len;
+ msg->fsp.num = 0;
+ memset(msg->fsp.key, 0x0, sizeof(msg->fsp.key));
memset(&msg->object_sig.cmac_hash, 0x0, sizeof(msg->object_sig.cmac_hash));
memset(&msg->reserved, 0x0, sizeof(msg->reserved));
- msg->opcode = opcode;
- msg->len_secure = msg->len_insecure;
- msg->payload_len = payload_len;
- msg->rcm_version = RCM_VERSION_40;
+ msg->opcode = opcode;
+ msg->len_secure = msg->len_insecure;
+ msg->payload_len = payload_len;
+ msg->rcm_version = RCM_VERSION_21;
if (args_len)
memcpy(msg->args, args, args_len);
+
memset(msg->args + args_len, 0x0, sizeof(msg->args) - args_len);
+ msg->secure_debug_control = 0;
+ msg->secure_prov_key_num = 0;
+
rcm_msg_pad(msg->padding, sizeof(msg->padding));
- rcm_msg_pad(buf + sizeof(rcm40_msg_t) + payload_len, padding_len);
+ rcm_msg_pad(buf + sizeof(rcm21_msg_t) + payload_len, padding_len);
}
-static void rcm1_init_msg(
- uint8_t *buf,
- uint32_t msg_len,
- uint32_t opcode,
- void *args,
- uint32_t args_len,
- uint32_t payload_len)
+static uint32_t rcm21_get_msg_len(const struct rcm *rcm, const void *msg)
{
- uint32_t padding_len;
- rcm1_msg_t *msg;
-
- msg = (rcm1_msg_t *)buf;
+ return ((const rcm21_msg_t *)msg)->len_insecure;
+}
- padding_len = rcm_get_pad_len(payload_len);
+static int rcm21_sign_msg(const struct rcm *rcm, void *buf)
+{
+ rcm21_msg_t *msg = buf;
+ uint32_t crypto_len;
- msg->len_insecure = sizeof(rcm1_msg_t) + payload_len +
- padding_len;
+ // signing does not include the len_insecure, modulus
+ // and object signature at the beginning of the message
+ crypto_len = msg->len_insecure - sizeof(msg->len_insecure) -
+ sizeof(msg->fsp) - sizeof(msg->modulus) -
+ sizeof(msg->object_sig);
+ if (crypto_len % RCM_AES_BLOCK_SIZE)
+ return -EMSGSIZE;
- memset(&msg->cmac_hash, 0x0, sizeof(msg->cmac_hash));
- memset(&msg->reserved, 0x0, sizeof(msg->reserved));
+ cmac_hash(msg->reserved, crypto_len, msg->object_sig.cmac_hash);
+ return 0;
+}
- msg->opcode = opcode;
- msg->len_secure = msg->len_insecure;
- msg->payload_len = payload_len;
- msg->rcm_version = RCM_VERSION_1;
+const struct rcm rcm21 = {
+ .version = RCM_VERSION_21,
+ .message_size = sizeof(rcm21_msg_t),
+ .init_msg = rcm21_init_msg,
+ .get_msg_len = rcm21_get_msg_len,
+ .sign_msg = rcm21_sign_msg,
+};
- if (args_len)
- memcpy(msg->args, args, args_len);
- memset(msg->args + args_len, 0x0, sizeof(msg->args) - args_len);
+static uint32_t rcm_get_msg_buf_len(const struct rcm *rcm,
+ uint32_t payload_len)
+{
+ return rcm->message_size + payload_len +
+ rcm_get_pad_len(rcm, payload_len);
+}
- rcm_msg_pad(msg->padding, sizeof(msg->padding));
- rcm_msg_pad(buf + sizeof(rcm1_msg_t) + payload_len, padding_len);
+static uint8_t *rcm_get_msg_payload(const struct rcm *rcm, uint8_t *buf)
+{
+ return buf + rcm->message_size;
}
-static uint32_t rcm_get_pad_len(uint32_t payload_len)
+int rcm_create_msg(const struct rcm *rcm, uint32_t opcode, const void *args,
+ uint32_t args_len, const void *payload,
+ uint32_t payload_len, void **buf)
{
- uint32_t pad_len = 0;
- uint32_t msg_len = message_size + payload_len;
+ uint8_t *msg = NULL, *msg_payload;
+ uint32_t msg_len;
+ int ret = 0;
- // First, use padding to bump the message size up to the minimum.
- if (msg_len < RCM_MIN_MSG_LENGTH) {
- pad_len = RCM_MIN_MSG_LENGTH - msg_len;
- msg_len += pad_len;
+ // create message buffer
+ msg_len = rcm_get_msg_buf_len(rcm, payload_len);
+ msg = malloc(msg_len);
+ if (!msg) {
+ ret = -ENOMEM;
+ goto done;
}
- /*
- * Next, add any extra padding needed to bump the relevant subset
- * of the data up to a multiple of 16 bytes. Subtracting off the
- * rcm_msg_t size handles the initial data that is not part of
- * the hashing and encryption.
- */
- pad_len += 16 - ((msg_len - message_size) & 0xf);
+ // initialize message
+ rcm->init_msg(rcm, msg, msg_len, opcode, args, args_len, payload_len);
- return pad_len;
+ // fill message payload
+ msg_payload = rcm_get_msg_payload(rcm, msg);
+ if (payload_len)
+ memcpy(msg_payload, payload, payload_len);
+
+ // sign message
+ rcm->sign_msg(rcm, msg);
+
+done:
+ if (ret) {
+ free(msg);
+ msg = NULL;
+ }
+
+ *buf = msg;
+
+ return ret;
}
+uint32_t rcm_get_msg_len(const struct rcm *rcm, const void *msg)
+{
+ return rcm->get_msg_len(rcm, msg);
+}
diff --git a/src/rcm.h b/src/rcm.h
index 7a66045..bfd2d81 100644
--- a/src/rcm.h
+++ b/src/rcm.h
@@ -37,6 +37,7 @@
#define RCM_VERSION_1 (NVBOOT_VERSION(1, 0))
#define RCM_VERSION_35 (NVBOOT_VERSION(0x35, 1))
#define RCM_VERSION_40 (NVBOOT_VERSION(0x40, 1))
+#define RCM_VERSION_21 (NVBOOT_VERSION(0x21, 1))
#define RCM_VERSION_MAJOR(ver) ((ver) >> 16)
#define RCM_VERSION_MINOR(ver) ((ver) & 0xffff)
@@ -105,20 +106,57 @@ typedef struct {
uint8_t padding[16]; // 274-283
} rcm40_msg_t;
+typedef struct rcm21_msg {
+ uint32_t len_insecure; // 000-003
+ /* factory secure provisioning */
+ struct {
+ uint32_t num; // 004-007
+ uint8_t key[32]; // 008-027
+ } fsp;
+ uint8_t modulus[2048 / 8]; // 028-127
+ struct {
+ uint8_t cmac_hash[RCM_AES_BLOCK_SIZE];
+ uint8_t rsa_pss_sig[2048 / 8];
+ } object_sig; // 128-237
+ uint8_t reserved[16]; // 238-247
+ uint32_t ecid[4]; // 248-257
+ uint32_t opcode; // 258-25b
+ uint32_t len_secure; // 25c-25f
+ uint32_t payload_len; // 260-263
+ uint32_t rcm_version; // 264-267
+ uint8_t args[48]; // 268-297
+ uint32_t secure_debug_control; // 298-29b
+ uint32_t secure_prov_key_num; // 29c-29f
+ uint8_t padding[8]; // 2a0-2a7
+} rcm21_msg_t;
+
// security operating modes
#define RCM_OP_MODE_PRE_PRODUCTION 0x1
#define RCM_OP_MODE_DEVEL 0x3
#define RCM_OP_MODE_ODM_SECURE 0x4
#define RCM_OP_MODE_ODM_OPEN 0x5
-int rcm_init(uint32_t version);
-uint32_t rcm_get_msg_len(uint8_t *msg);
-int rcm_create_msg(
- uint32_t opcode,
- uint8_t *args,
- uint32_t args_len,
- uint8_t *payload,
- uint32_t payload_len,
- uint8_t **msg);
+struct rcm {
+ uint32_t version;
+ uint32_t message_size;
+
+ void (*init_msg)(const struct rcm *rcm, void *buf,
+ uint32_t msg_len, uint32_t opcode,
+ const void *args, uint32_t args_len,
+ uint32_t payload_len);
+ uint32_t (*get_msg_len)(const struct rcm *rcm, const void *msg);
+ int (*sign_msg)(const struct rcm *rcm, void *buf);
+};
+
+extern const struct rcm rcm1;
+extern const struct rcm rcm35;
+extern const struct rcm rcm40;
+extern const struct rcm rcm21;
+
+int rcm_create_msg(const struct rcm *rcm, uint32_t opcode,
+ const void *args, uint32_t args_len,
+ const void *payload, uint32_t payload_len,
+ void **msg);
+uint32_t rcm_get_msg_len(const struct rcm *rcm, const void *msg);
#endif // _RCM_H
diff --git a/src/soc.c b/src/soc.c
new file mode 100644
index 0000000..0693039
--- /dev/null
+++ b/src/soc.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2015, NVIDIA CORPORATION. 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 NVIDIA CORPORATION 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 ``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.
+ */
+
+#include "soc.h"
+
+#include "miniloader/tegra20-miniloader.h"
+#include "miniloader/tegra30-miniloader.h"
+#include "miniloader/tegra114-miniloader.h"
+#include "miniloader/tegra124-miniloader.h"
+
+static const struct soc tegra_socs[] = {
+ {
+ .name = "Tegra20",
+ .chip_id = 0x20,
+ .needs_mts = false,
+ .rcm = &rcm1,
+ .miniloader = {
+ .data = miniloader_tegra20,
+ .size = sizeof(miniloader_tegra20),
+ .entry = TEGRA20_MINILOADER_ENTRY,
+ },
+ }, {
+ .name = "Tegra30",
+ .chip_id = 0x30,
+ .needs_mts = false,
+ .rcm = &rcm1,
+ .miniloader = {
+ .data = miniloader_tegra30,
+ .size = sizeof(miniloader_tegra30),
+ .entry = TEGRA30_MINILOADER_ENTRY,
+ },
+ }, {
+ .name = "Tegra114",
+ .chip_id = 0x35,
+ .needs_mts = false,
+ .rcm = &rcm35,
+ .miniloader = {
+ .data = miniloader_tegra114,
+ .size = sizeof(miniloader_tegra114),
+ .entry = TEGRA114_MINILOADER_ENTRY,
+ },
+ }, {
+ .name = "Tegra124",
+ .chip_id = 0x40,
+ .needs_mts = false,
+ .rcm = &rcm40,
+ .miniloader = {
+ .data = miniloader_tegra124,
+ .size = sizeof(miniloader_tegra124),
+ .entry = TEGRA124_MINILOADER_ENTRY,
+ },
+ }, {
+ .name = "Tegra132",
+ .chip_id = 0x13,
+ .needs_mts = true,
+ .rcm = &rcm40,
+ }, {
+ .name = "Tegra210",
+ .chip_id = 0x21,
+ .needs_mts = false,
+ .rcm = &rcm21,
+ },
+};
+
+const struct soc *soc_detect(uint16_t dev_id)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(tegra_socs); i++)
+ if ((dev_id & 0xff) == tegra_socs[i].chip_id)
+ return &tegra_socs[i];
+
+ return NULL;
+}
diff --git a/src/soc.h b/src/soc.h
new file mode 100644
index 0000000..e1f4b37
--- /dev/null
+++ b/src/soc.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015, NVIDIA CORPORATION. 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 NVIDIA CORPORATION 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 ``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.
+ */
+
+#ifndef _SOC_H
+#define _SOC_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "common.h"
+#include "rcm.h"
+
+struct soc {
+ const char *name;
+ uint8_t chip_id;
+ bool needs_mts;
+
+ const struct rcm *rcm;
+ struct binary miniloader;
+};
+
+const struct soc *soc_detect(uint16_t dev_id);
+
+#endif
diff --git a/src/usb.c b/src/usb.c
index d036da0..1bfafa6 100644
--- a/src/usb.c
+++ b/src/usb.c
@@ -33,6 +33,7 @@
#include <sys/param.h>
#include "usb.h"
#include "debug.h"
+#include "soc.h"
// USB xfer timeout in ms
#define USB_TIMEOUT 1000
@@ -156,11 +157,7 @@ usb_device_t *usb_open(uint16_t venid, uint16_t *devid)
for (i = 0; i < cnt; i++) {
libusb_device *device = list[i];
if (usb_match(device, venid, devid)) {
- if ((*devid & 0xff) == USB_DEVID_NVIDIA_TEGRA20 ||
- (*devid & 0xff) == USB_DEVID_NVIDIA_TEGRA30 ||
- (*devid & 0xff) == USB_DEVID_NVIDIA_TEGRA114 ||
- (*devid & 0xff) == USB_DEVID_NVIDIA_TEGRA124 ||
- (*devid & 0xff) == USB_DEVID_NVIDIA_TEGRA132) {
+ if (soc_detect(*devid)) {
found = device;
break;
} else {
diff --git a/src/usb.h b/src/usb.h
index dd274b0..2823969 100644
--- a/src/usb.h
+++ b/src/usb.h
@@ -32,11 +32,6 @@
#include <libusb.h>
#define USB_VENID_NVIDIA 0x955
-#define USB_DEVID_NVIDIA_TEGRA20 0x20
-#define USB_DEVID_NVIDIA_TEGRA30 0x30
-#define USB_DEVID_NVIDIA_TEGRA114 0x35
-#define USB_DEVID_NVIDIA_TEGRA124 0x40
-#define USB_DEVID_NVIDIA_TEGRA132 0x13
typedef struct {
libusb_device_handle *handle;