diff options
author | Thierry Reding <treding@nvidia.com> | 2015-03-20 16:26:21 +0100 |
---|---|---|
committer | Thierry Reding <treding@nvidia.com> | 2015-03-20 16:26:21 +0100 |
commit | 9ce6de2c121026008bc39193f5d367f37bac2ae0 (patch) | |
tree | 59a28f9b57ec55f5a80472b952a9048949111981 | |
parent | b007364b9fd63afd42036e128d3ed6be69278af5 (diff) | |
download | tegrarcm-dev/treding/wip.tar.gz |
Restructure code basedev/treding/wip
-rw-r--r-- | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/common.h | 43 | ||||
-rw-r--r-- | src/main.c | 406 | ||||
-rw-r--r-- | src/rcm.c | 476 | ||||
-rw-r--r-- | src/rcm.h | 56 | ||||
-rw-r--r-- | src/soc.c | 99 | ||||
-rw-r--r-- | src/soc.h | 49 | ||||
-rw-r--r-- | src/usb.c | 7 | ||||
-rw-r--r-- | src/usb.h | 5 |
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 @@ -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; } @@ -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); +} @@ -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 @@ -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 { @@ -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; |