common: import CyanogenMod dtbtool

* This allows for maximum compatibility with all SoCs and devices.

Change-Id: I4a2d25c214d337e99217f7ec3767de8027570f97
This commit is contained in:
Jake Weinstein 2016-01-09 09:04:07 +00:00
parent 0adb50d776
commit c8bfc7211c
2 changed files with 426 additions and 126 deletions

View File

@ -39,12 +39,15 @@
#include <getopt.h>
#include <errno.h>
#include <unistd.h>
#include <limits.h>
#define QCDT_MAGIC "QCDT" /* Master DTB magic */
#define QCDT_VERSION 2 /* QCDT version */
#define QCDT_VERSION 3 /* QCDT version */
#define QCDT_DT_TAG "qcom,msm-id = <"
#define QCDT_BOARD_TAG "qcom,board-id = <"
#define QCDT_PMIC_TAG "qcom,pmic-id = <"
#define PAGE_SIZE_DEF 2048
#define PAGE_SIZE_MAX (1024*1024)
@ -63,6 +66,7 @@ struct chipInfo_t {
uint32_t platform;
uint32_t subtype;
uint32_t revNum;
uint32_t pmic_model[4];
uint32_t dtb_size;
char *dtb_file;
struct chipInfo_t *prev;
@ -89,22 +93,35 @@ struct chipSt_t {
struct chipSt_t *t_next;
};
struct chipPt_t {
uint32_t pmic0;
uint32_t pmic1;
uint32_t pmic2;
uint32_t pmic3;
struct chipPt_t *next;
struct chipPt_t *t_next;
};
char *input_dir;
char *output_file;
char *dtc_path;
char *dt_tag = QCDT_DT_TAG;
int verbose;
int page_size = PAGE_SIZE_DEF;
int version_override = 0;
void print_help()
{
log_info("dtbTool version %d\n", QCDT_VERSION);
log_info("dtbTool version %d (kinda :) )\n", QCDT_VERSION);
log_info("dtbTool [options] -o <output file> <input DTB path>\n");
log_info(" options:\n");
log_info(" --output-file/-o output file\n");
log_info(" --dtc-path/-p path to dtc\n");
log_info(" --page-size/-s page size in bytes\n");
log_info(" --dt-tag/-d alternate QCDT_DT_TAG\n");
log_info(" --verbose/-v verbose\n");
log_info(" --force-v2/-2 output dtb v2 format\n");
log_info(" --force-v3/-3 output dtb v3 format\n");
log_info(" --help/-h this help screen\n");
}
@ -116,12 +133,15 @@ int parse_commandline(int argc, char *const argv[])
{"output-file", 1, 0, 'o'},
{"dtc-path", 1, 0, 'p'},
{"page-size", 1, 0, 's'},
{"dt-tag", 1, 0, 'd'},
{"force-v2", 0, 0, '2'},
{"force-v3", 0, 0, '3'},
{"verbose", 0, 0, 'v'},
{"help", 0, 0, 'h'},
{0, 0, 0, 0}
};
while ((c = getopt_long(argc, argv, "-o:p:s:vh", long_options, NULL))
while ((c = getopt_long(argc, argv, "-o:p:s:d:23vh", long_options, NULL))
!= -1) {
switch (c) {
case 1:
@ -141,6 +161,17 @@ int parse_commandline(int argc, char *const argv[])
return RC_ERROR;
}
break;
case 'd':
dt_tag = optarg;
break;
case '2':
case '3':
if (version_override != 0) {
log_err("A version output argument may only be passed once\n");
return RC_ERROR;
}
version_override = c - '0';
break;
case 'v':
verbose = 1;
break;
@ -201,7 +232,11 @@ int chip_add(struct chipInfo_t *c)
if ((c->chipset == x->chipset) &&
(c->platform == x->platform) &&
(c->subtype == x->subtype) &&
(c->revNum == x->revNum)) {
(c->revNum == x->revNum) &&
(c->pmic_model[0] == x->pmic_model[0]) &&
(c->pmic_model[1] == x->pmic_model[1]) &&
(c->pmic_model[2] == x->pmic_model[2]) &&
(c->pmic_model[3] == x->pmic_model[3])) {
return RC_ERROR; /* duplicate */
}
if (!x->next) {
@ -247,15 +282,20 @@ struct chipInfo_t *getChipInfo(const char *filename, int *num, uint32_t msmversi
size_t line_size;
FILE *pfile;
int llen;
struct chipInfo_t *chip = NULL, *tmp;
struct chipInfo_t *chip = NULL, *tmp, *chip_t;
uint32_t data[3] = {0, 0, 0};
uint32_t data_st[2] = {0, 0};
uint32_t data_pt[4] = {0, 0, 0, 0};
char *tok, *sptr = NULL;
int i, entryValid, entryEnded;
int count = 0, count1 = 0, count2 =0;
int entryValidST, entryEndedST, entryValidDT, entryEndedDT;
int count = 0, count1 = 0, count2 = 0, count3 = 0;
int entryValidST, entryEndedST, entryValidDT, entryEndedDT, entryValidPT, entryEndedPT;
struct chipId_t *chipId = NULL, *cId = NULL, *tmp_id = NULL;
struct chipSt_t *chipSt = NULL, *cSt = NULL, *tmp_st = NULL;
struct chipPt_t *chipPt = NULL, *cPt = NULL, *tmp_pt = NULL;
struct chipId_t *chipId_tmp = NULL;
struct chipSt_t *chipSt_tmp = NULL;
struct chipPt_t *chipPt_tmp = NULL;
line_size = 1024;
line = (char *)malloc(line_size);
@ -289,8 +329,8 @@ struct chipInfo_t *getChipInfo(const char *filename, int *num, uint32_t msmversi
/* Find "qcom,msm-id" */
while ((llen = getline(&line, &line_size, pfile)) != -1) {
if (msmversion == 1) {
if ((pos = strstr(line, QCDT_DT_TAG)) != NULL) {
pos += strlen(QCDT_DT_TAG);
if ((pos = strstr(line, dt_tag)) != NULL) {
pos += strlen(dt_tag);
entryEnded = 0;
while (1) {
@ -335,6 +375,10 @@ struct chipInfo_t *getChipInfo(const char *filename, int *num, uint32_t msmversi
tmp->platform = data[1];
tmp->subtype = 0;
tmp->revNum = data[2];
tmp->pmic_model[0] = 0;
tmp->pmic_model[1] = 0;
tmp->pmic_model[2] = 0;
tmp->pmic_model[3] = 0;
tmp->dtb_size = 0;
tmp->dtb_file = NULL;
tmp->master = chip;
@ -344,12 +388,12 @@ struct chipInfo_t *getChipInfo(const char *filename, int *num, uint32_t msmversi
}
}
log_err("... skip, incorrect '%s' format\n", QCDT_DT_TAG);
log_err("... skip, incorrect '%s' format\n", dt_tag);
break;
}
} else if (msmversion == 2) {
if ((pos = strstr(line, QCDT_DT_TAG)) != NULL) {
pos += strlen(QCDT_DT_TAG);
} else if (msmversion == 2 || msmversion == 3) {
if ((pos = strstr(line, dt_tag)) != NULL) {
pos += strlen(dt_tag);
entryEndedDT = 0;
for (;entryEndedDT < 1;) {
@ -437,6 +481,53 @@ struct chipInfo_t *getChipInfo(const char *filename, int *num, uint32_t msmversi
}
}
}
if ((pos = strstr(line,QCDT_PMIC_TAG)) != NULL) {
pos += strlen(QCDT_PMIC_TAG);
entryEndedPT = 0;
for (;entryEndedPT < 1;) {
entryValidPT = 1;
for (i = 0; i < 4; i++) {
tok = strtok_r(pos, " \t", &sptr);
pos = NULL;
if (tok != NULL) {
if (*tok == '>') {
entryEndedPT = 1;
entryValidPT = 0;
break;
}
data_pt[i] = strtoul(tok, NULL, 0);
} else {
data_pt[i] = 0;
entryValidPT = 0;
entryEndedPT = 1;
}
}
if (entryValidPT) {
tmp_pt = (struct chipPt_t *)
malloc(sizeof(struct chipPt_t));
if (!tmp_pt) {
log_err("Out of memory\n");
break;
}
if (!chipPt) {
chipPt = tmp_pt;
cPt = tmp_pt;
chipPt->t_next = NULL;
} else {
tmp_pt->t_next = chipPt->t_next;
chipPt->t_next = tmp_pt;
}
tmp_pt->pmic0 = data_pt[0];
tmp_pt->pmic1 = data_pt[1];
tmp_pt->pmic2 = data_pt[2];
tmp_pt->pmic3 = data_pt[3];
count3++;
}
}
}
}
}
}
@ -445,61 +536,128 @@ struct chipInfo_t *getChipInfo(const char *filename, int *num, uint32_t msmversi
free(line);
if (count1 == 0) {
log_err("... skip, incorrect '%s' format\n", QCDT_DT_TAG);
log_err("... skip, incorrect '%s' format\n", dt_tag);
return NULL;
}
if (count2 == 0) {
log_err("... skip, incorrect '%s' format\n", QCDT_BOARD_TAG);
return NULL;
}
if (count3 == 0 && msmversion == 3) {
log_err("... skip, incorrect '%s' format\n", QCDT_PMIC_TAG);
return NULL;
}
tmp_st = cSt;
tmp_pt = cPt;
while (cId != NULL) {
while (cSt != NULL) {
tmp = (struct chipInfo_t *)
malloc(sizeof(struct chipInfo_t));
if (!tmp) {
log_err("Out of memory\n");
break;
}
if (!chip) {
chip = tmp;
chip->t_next = NULL;
if (msmversion == 3) {
while (cPt != NULL) {
tmp = (struct chipInfo_t *)
malloc(sizeof(struct chipInfo_t));
if (!tmp) {
log_err("Out of memory\n");
break;
}
if (!chip) {
chip = tmp;
chip->t_next = NULL;
} else {
tmp->t_next = chip->t_next;
chip->t_next = tmp;
}
tmp->chipset = cId->chipset;
tmp->platform = cSt->platform;
tmp->revNum = cId->revNum;
tmp->subtype = cSt->subtype;
tmp->pmic_model[0] = cPt->pmic0;
tmp->pmic_model[1] = cPt->pmic1;
tmp->pmic_model[2] = cPt->pmic2;
tmp->pmic_model[3] = cPt->pmic3;
tmp->dtb_size = 0;
tmp->dtb_file = NULL;
tmp->master = chip;
tmp->wroteDtb = 0;
tmp->master_offset = 0;
cPt = cPt->t_next;
}
cPt = tmp_pt;
} else {
tmp->t_next = chip->t_next;
chip->t_next = tmp;
tmp = (struct chipInfo_t *)
malloc(sizeof(struct chipInfo_t));
if (!tmp) {
log_err("Out of memory\n");
break;
}
if (!chip) {
chip = tmp;
chip->t_next = NULL;
} else {
tmp->t_next = chip->t_next;
chip->t_next = tmp;
}
tmp->chipset = cId->chipset;
tmp->platform = cSt->platform;
tmp->revNum = cId->revNum;
tmp->subtype = cSt->subtype;
tmp->pmic_model[0] = 0;
tmp->pmic_model[1] = 0;
tmp->pmic_model[2] = 0;
tmp->pmic_model[3] = 0;
tmp->dtb_size = 0;
tmp->dtb_file = NULL;
tmp->master = chip;
tmp->wroteDtb = 0;
tmp->master_offset = 0;
}
tmp->chipset = cId->chipset;
tmp->platform = cSt->platform;
tmp->revNum = cId->revNum;
tmp->subtype = cSt->subtype;
tmp->dtb_size = 0;
tmp->dtb_file = NULL;
tmp->master = chip;
tmp->wroteDtb = 0;
tmp->master_offset = 0;
cSt = cSt->t_next;
}
cSt = tmp_st;
cId = cId->t_next;
}
if (entryEndedST == 1 && entryEndedDT == 1) {
pclose(pfile);
if (msmversion == 2)
entryEndedPT = 1;
/* clear memory*/
pclose(pfile);
while (chipId) {
chipId_tmp = chipId;
chipId = chipId->t_next;
free(chipId_tmp);
}
while (chipSt) {
chipSt_tmp= chipSt;
chipSt = chipSt->t_next;
free(chipSt_tmp);
}
while (chipPt) {
chipPt_tmp= chipPt;
chipPt = chipPt->t_next;
free(chipPt_tmp);
}
if (entryEndedST == 1 && entryEndedDT == 1 && entryEndedPT == 1) {
*num = count1;
free(chipSt);
free(chipId);
return chip;
}
/* clear memory*/
while (chip) {
chip_t = chip;
chip = chip->next;
if (chip_t->dtb_file)
free(chip_t->dtb_file);
free(chip_t);
}
return NULL;
}
/* Get the version-id based on dtb files */
int GetVersionInfo(const char *filename)
uint32_t GetVersionInfo(const char *filename)
{
const char str1[] = "dtc -I dtb -O dts \"";
const char str2[] = "\" 2>&1";
@ -508,7 +666,7 @@ int GetVersionInfo(const char *filename)
size_t line_size;
FILE *pfile;
int llen;
int v = 1;
uint32_t v = 1;
line_size = 1024;
line = (char *)malloc(line_size);
@ -543,105 +701,98 @@ int GetVersionInfo(const char *filename)
while ((llen = getline(&line, &line_size, pfile)) != -1) {
if ((pos = strstr(line,QCDT_BOARD_TAG)) != NULL) {
v = 2;
}
if ((pos = strstr(line,QCDT_PMIC_TAG)) != NULL) {
v = 3;
break;
}
}
}
if (v == 1)
log_info(" Old Version:%d\n", v);
free(line);
log_info("Version:%d\n", v);
return v;
}
/* Extract 'qcom,msm-id' 'qcom,board-id' parameter from DTB
v1 format:
qcom,msm-id = <x y z> [, <x2 y2 z2> ...];
v2 format:
qcom,msm-id = <x z> [, <x2 z2> ...;
qcom,board-id = <y y'> [, <y2 y2'> ...;
Fields:
x = chipset
y = platform
y' = subtype
z = soc rev
*/
int main(int argc, char **argv)
static int find_dtb(const char *path, uint32_t *version)
{
char buf[COPY_BLK];
struct chipInfo_t *chip, *t_chip;
struct dirent *dp;
FILE *pInputFile;
char *filename;
int padding;
uint8_t *filler = NULL;
int numBytesRead = 0;
int totBytesRead = 0;
int out_fd;
int flen;
int rc = RC_SUCCESS;
int dtb_count = 0, dtb_offset = 0;
size_t wrote = 0, expected = 0;
char *filename;
struct chipInfo_t *chip, *t_chip;
struct stat st;
uint32_t version = QCDT_VERSION;
int num;
uint32_t dtb_size;
int msmversion = 0;
int rc = RC_SUCCESS;
uint32_t msmversion = 0;
int dtb_count = 0;
log_info("DTB combiner:\n");
if (parse_commandline(argc, argv) != RC_SUCCESS) {
print_help();
return RC_ERROR;
}
log_info(" Input directory: '%s'\n", input_dir);
log_info(" Output file: '%s'\n", output_file);
DIR *dir = opendir(input_dir);
DIR *dir = opendir(path);
if (!dir) {
log_err("Failed to open input directory '%s'\n", input_dir);
log_err("Failed to open input directory '%s'\n", path);
return RC_ERROR;
}
filler = (uint8_t *)malloc(page_size);
if (!filler) {
log_err("Out of memory\n");
closedir(dir);
return RC_ERROR;
}
memset(filler, 0, page_size);
/* Open the .dtb files in the specified path, decompile and
extract "qcom,msm-id" parameter
*/
while ((dp = readdir(dir)) != NULL) {
if ((dp->d_type == DT_REG)) {
if (dp->d_type == DT_UNKNOWN) {
struct stat statbuf;
char name[PATH_MAX];
snprintf(name, sizeof(name), "%s%s%s",
path,
(path[strlen(path) - 1] == '/' ? "" : "/"),
dp->d_name);
if (!stat(name, &statbuf)) {
if (S_ISREG(statbuf.st_mode)) {
dp->d_type = DT_REG;
} else if (S_ISDIR(statbuf.st_mode)) {
dp->d_type = DT_DIR;
}
}
}
if (dp->d_type == DT_DIR) {
char name[PATH_MAX];
if (dp->d_name[0] == '.') {
continue;
}
snprintf(name, sizeof(name), "%s%s%s%s",
path,
(path[strlen(path) - 1] == '/' ? "" : "/"),
dp->d_name,
"/");
log_info("Searching subdir: %s ... \n", name);
dtb_count += find_dtb(name, version);
} else if (dp->d_type == DT_REG) {
flen = strlen(dp->d_name);
if ((flen > 4) &&
(strncmp(&dp->d_name[flen-4], ".dtb", 4) == 0)) {
log_info("Found file: %s ... ", dp->d_name);
log_info("Found file: %s ... \n", dp->d_name);
flen = strlen(input_dir) + strlen(dp->d_name) + 1;
flen = strlen(path) + strlen(dp->d_name) + 1;
filename = (char *)malloc(flen);
if (!filename) {
log_err("Out of memory\n");
rc = RC_ERROR;
break;
}
strncpy(filename, input_dir, flen);
strncpy(filename, path, flen);
strncat(filename, dp->d_name, flen);
/* To identify the version number */
msmversion = GetVersionInfo(filename);
if (*version < msmversion) {
*version = msmversion;
}
num = 1;
chip = getChipInfo(filename, &num, msmversion);
if (msmversion == 1) {
if (!chip) {
log_err("skip, failed to scan for '%s' tag\n",
QCDT_DT_TAG);
log_err("skip, failed to scan for '%s' tag\n", dt_tag);
free(filename);
continue;
}
@ -649,7 +800,15 @@ int main(int argc, char **argv)
if (msmversion == 2) {
if (!chip) {
log_err("skip, failed to scan for '%s' or '%s' tag\n",
QCDT_DT_TAG, QCDT_BOARD_TAG);
dt_tag, QCDT_BOARD_TAG);
free(filename);
continue;
}
}
if (msmversion == 3) {
if (!chip) {
log_err("skip, failed to scan for '%s', '%s' or '%s' tag\n",
dt_tag, QCDT_BOARD_TAG, QCDT_PMIC_TAG);
free(filename);
continue;
}
@ -662,12 +821,14 @@ int main(int argc, char **argv)
continue;
}
log_info("chipset: %u, rev: %u, platform: %u, subtype: %u\n",
chip->chipset, chip->revNum, chip->platform, chip->subtype);
log_info("chipset: %u, rev: %u, platform: %u, subtype: %u, pmic0: %u, pmic1: %u, pmic2: %u, pmic3: %u\n",
chip->chipset, chip->revNum, chip->platform, chip->subtype,
chip->pmic_model[0], chip->pmic_model[1], chip->pmic_model[2], chip->pmic_model[3]);
for (t_chip = chip->t_next; t_chip; t_chip = t_chip->t_next) {
log_info(" additional chipset: %u, rev: %u, platform: %u, subtype: %u\n",
t_chip->chipset, t_chip->revNum, t_chip->platform, t_chip->subtype);
log_info("additional chipset: %u, rev: %u, platform: %u, subtype: %u, pmic0: %u, pmic1: %u, pmic2: %u, pmic3: %u\n",
t_chip->chipset, t_chip->revNum, t_chip->platform, t_chip->subtype,
t_chip->pmic_model[0], t_chip->pmic_model[1], t_chip->pmic_model[2], t_chip->pmic_model[3]);
}
rc = chip_add(chip);
@ -686,7 +847,7 @@ int main(int argc, char **argv)
for (t_chip = chip->t_next; t_chip; t_chip = t_chip->t_next) {
rc = chip_add(t_chip);
if (rc != RC_SUCCESS) {
log_err("... duplicate info, skipped (chipset %u, rev: %u, platform: %u, subtype %u:\n",
log_err("... duplicate info, skipped (chipset %u, rev: %u, platform: %u, subtype: %u\n",
t_chip->chipset, t_chip->revNum, t_chip->platform, t_chip->subtype);
continue;
}
@ -696,6 +857,58 @@ int main(int argc, char **argv)
}
}
closedir(dir);
return dtb_count;
}
/* Extract 'qcom,msm-id' 'qcom,board-id' parameter from DTB
v1 format:
qcom,msm-id = <x y z> [, <x2 y2 z2> ...];
v2 format:
qcom,msm-id = <x z> [, <x2 z2> ...;
qcom,board-id = <y y'> [, <y2 y2'> ...;
Fields:
x = chipset
y = platform
y' = subtype
z = soc rev
*/
int main(int argc, char **argv)
{
char buf[COPY_BLK];
struct chipInfo_t *chip;
FILE *pInputFile;
int padding;
uint8_t *filler = NULL;
int numBytesRead = 0;
int totBytesRead = 0;
int out_fd;
int rc = RC_SUCCESS;
int dtb_count = 0, dtb_offset = 0, entry_size;
size_t wrote = 0, expected = 0;
uint32_t dtb_size;
uint32_t version = 0;
char *filename;
log_info("DTB combiner:\n");
if (parse_commandline(argc, argv) != RC_SUCCESS) {
print_help();
return RC_ERROR;
}
log_info(" Input directory: '%s'\n", input_dir);
log_info(" Output file: '%s'\n", output_file);
filler = (uint8_t *)malloc(page_size);
if (!filler) {
log_err("Out of memory\n");
return RC_ERROR;
}
memset(filler, 0, page_size);
dtb_count = find_dtb(input_dir, &version);
log_info("=> Found %d unique DTB(s)\n", dtb_count);
if (!dtb_count)
@ -711,12 +924,24 @@ int main(int argc, char **argv)
log_info("\nGenerating master DTB... ");
out_fd = open(output_file, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR);
if (!out_fd < 0) {
if (out_fd == -1) {
log_err("Cannot create '%s'\n", output_file);
rc = RC_ERROR;
goto cleanup;
}
if (version_override != 0) {
version = version_override;
}
if (version == 1) {
entry_size = 20;
} else if (version == 2) {
entry_size = 24;
} else {
entry_size = 40;
}
/* Write header info */
wrote += write(out_fd, QCDT_MAGIC, sizeof(uint8_t) * 4); /* magic */
wrote += write(out_fd, &version, sizeof(uint32_t)); /* version */
@ -724,9 +949,10 @@ int main(int argc, char **argv)
/* #DTB */
/* Calculate offset of first DTB block */
dtb_offset = 12 + /* header */
(24 * dtb_count) + /* DTB table entries */
4; /* end of table indicator */
dtb_offset = 12 + /* header */
(entry_size * dtb_count) + /* DTB table entries */
4; /* end of table indicator */
/* Round up to page size */
padding = page_size - (dtb_offset % page_size);
dtb_offset += padding;
@ -735,16 +961,28 @@ int main(int argc, char **argv)
/* Write index table:
chipset
platform
subtype
subtype (v2/v3 only)
soc rev
pmic model0 (v3 only)
pmic model1 (v3 only)
pmic model2 (v3 only)
pmic model3 (v3 only)
dtb offset
dtb size
*/
for (chip = chip_list; chip; chip = chip->next) {
wrote += write(out_fd, &chip->chipset, sizeof(uint32_t));
wrote += write(out_fd, &chip->platform, sizeof(uint32_t));
wrote += write(out_fd, &chip->subtype, sizeof(uint32_t));
if (version >= 2) {
wrote += write(out_fd, &chip->subtype, sizeof(uint32_t));
}
wrote += write(out_fd, &chip->revNum, sizeof(uint32_t));
if (version >= 3) {
wrote += write(out_fd, &chip->pmic_model[0], sizeof(uint32_t));
wrote += write(out_fd, &chip->pmic_model[1], sizeof(uint32_t));
wrote += write(out_fd, &chip->pmic_model[2], sizeof(uint32_t));
wrote += write(out_fd, &chip->pmic_model[3], sizeof(uint32_t));
}
if (chip->master->master_offset != 0) {
wrote += write(out_fd, &chip->master->master_offset, sizeof(uint32_t));
} else {
@ -798,11 +1036,11 @@ int main(int argc, char **argv)
close(out_fd);
if (expected != wrote) {
log_err("error writing output file, please rerun: size mismatch %d vs %d\n",
log_err("error writing output file, please rerun: size mismatch %zu vs %zu\n",
expected, wrote);
rc = RC_ERROR;
} else
log_dbg("Total wrote %u bytes\n", wrote);
log_dbg("Total wrote %zu bytes\n", wrote);
if (rc != RC_SUCCESS)
unlink(output_file);

View File

@ -1,4 +1,4 @@
Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
Redistribution and use in source form and compiled forms (SGML, HTML,
PDF, PostScript, RTF and so forth) with or without modification, are
@ -73,7 +73,7 @@ Android - Table of Device Tree
x +------------------+
| | MAGIC ("QCDT") | 4B
| +------------------+
header | VERSION | uint32 (version 2)
header | VERSION | uint32 (version 3)
| +------------------+
| | num of DTBs | uint32 (number of DTB entries)
x +------------------+
@ -85,6 +85,14 @@ Android - Table of Device Tree
device +------------------+
#1 | soc rev #1 | uint32 (e.g. MSM8974 v2)
entry +------------------+
| | pmic0 #1 | uint32 (pmic0-> first smallest SID of existing pmic)
| +------------------+
| | pmic1 #1 | uint32 (pmic1-> secondary smallest SID of existing pmic)
| +------------------+
| | pmic2 #1 | uint32 (pmic2-> third smallest SID of existing pmic)
| +------------------+
| | pmic3 #1 | uint32 (pmic3-> fourth smallest SID of existing pmic)
| +------------------+
| | offset #1 | uint32 (byte offset from start/before MAGIC
| +------------------+ to DTB entry)
| | size #1 | uint32 (size in bytes of DTB blob)
@ -98,10 +106,18 @@ Android - Table of Device Tree
| +------------------+
device | variant id #Z | uint32 (e.g. ID for CDP, MTP)
#Z +------------------+
entry | variant id #Z | uint32 (e.g. ID for subtype) (QCDT v2)
entry | subtype id #Z | uint32 (e.g. ID for subtype) (QCDT v2)
(last) +------------------+
| | soc rev #Z | uint32 (e.g. MSM8974 v2)
| +------------------+
| | pmic0 #1 | uint32 (pmic0-> first smallest SID of existing pmic)
| +------------------+
| | pmic1 #1 | uint32 (pmic1-> secondary smallest SID of existing pmic)
| +------------------+
| | pmic2 #1 | uint32 (pmic2-> third smallest SID of existing pmic)
| +------------------+
| | pmic3 #1 | uint32 (pmic3-> fourth smallest SID of existing pmic)
| +------------------+
| | offset #Z | uint32 (byte offset from start/before MAGIC
x +------------------+ to DTB entry)
| 0 ("zero") | uint32 (end of list delimiter)
@ -133,28 +149,57 @@ Android - Table of Device Tree
or
qcom,msm-id = <x z>;
qcom,board-id = <y y'>;
or
qcom,msm-id = <x z>;
qcom,board-id = <y y'>;
qcom,pmic-id = <a b c d>;
x = ID for msm8974
y = ID for CDP, MTP, etc.
y' = ID for subtype (assumed zero if absent)
z = ID for soc revision
a = pmic0
b = pmic1
c = pmic2
d = pmic3
SBL populates the pmic entries always in ascending order of SID, so
pmic0-> SID0, pmic1-> SID1, pmic2-> SID2, pmic3-> SID3.
e.g. for qcom,pmic-id = <pmic0 pmic1 pmic2 pmic3>
Board X = MSM8994 + PM8994 + PMI8994 (Existing boards [ROW])
Board Y = MSM8994 + PM8994 + PMI8994 + PM8004 (Internal SS board variant)
Board Z = MSM8994 + PM8994 + PM8004 (Boards that SS will be making)
For all boards X, Y, and Z, PMICs have the following SIDs and REVID SUBTYPEs
(i.e. PMIC Model):
PM8994 - SID 0 and 1; subtype = 9
PMI8994 - SID 2 and 3; subtype = 10
PM8004 - SID 4 and 5; subtype = 12
LK using SMEM PMIC info(1 as major and 0 as minor version for example):
Board X: qcom,pmic-id = <0x0109 0x010A 0x0 0x0>;
Board Y: qcom,pmic-id = <0x0109 0x010A 0x010C 0x0>;
Board Z: qcom,pmic-id = <0x0109 0x010C 0x0 0x0>;
The entry can optionally be an array:
qcom,msm-id = <x1 y1 z1>, <x2 y2 z2>, ...;
or
qcom,msm-id = <x1 z1>, <x2 z2>, ...;
qcom,board-id = <y1 y1'>, ...;
Note that qcom,msm-id and qcom,board-id are not matched
pairs.
or
qcom,msm-id = <x1 z1>, <x2 z2>, ...;
qcom,board-id = <y1 y1'>, ...;
qcom,pmic-id = <a1 b1 c1 d1>, ...;
Note that qcom,msm-id, qcom,board-id and qcom,pmic-id are not matched pairs.
2) Kernel compile will generate the DTB
3) Android build will run a new tool (dtbTool)
a) scan the DTB output directory for all compiled DTB
b) decompile the DTB for "qcom,msm-id"/"qcom,board-id"
b) decompile the DTB for "qcom,msm-id"/"qcom,board-id"/"qcom,pmic-id"
c) generate the QC table of device tree in sorted
order (platform, variant, subtype, soc rev)
order (platform, variant, subtype, soc rev, pmic0, pmic1, pmic2, pmic3)
d) modified mkbootimg will merge new table of DT
3.2) Run-time:
1) LK bootloader will obtain MSM id/variant/subtype/soc rev
info either from early bootloaders or via other means
1) LK bootloader will obtain platform id/variant/subtype/soc rev/major ver/minor ver
/pmic0/pmic1/pmic2/pmic3 info either from early bootloaders or via other means
2) LK bootloader will check entries #10 for non-zero
value (set to zero for standard boot.img). If the
value is non-zero, refer to page section after
@ -164,10 +209,27 @@ Android - Table of Device Tree
QCDT version)
5) LK scans through the QCDT table to look for matching
entry. Search order is:
1) platform ID exact match
2) variant ID exact match
1) msm ID exact match
2) Platform type exact match
3) subtype ID exact match
4) select the highest soc rev in QCDT that is
4) HLOS subtype exact match
5) Pmic0 model ID exact match
6) Pmic1 model ID exact match
7) Pmic2 model ID exact match
8) Pmic3 model ID exact match
9) foundry ID, look for exact match, if not found choose
device tree with foundry-id(0x0)
10) select the highest soc rev in QCDT that is
equal to or lower than the runtime detected soc rev
11) select the highest major&minor ver in QCDT that is
equal to or lower than the runtime detected major ver
12) select the highest pmic0 major&minor in QCDT that is
equal to or lower than the runtime detected pmic0
13) select the highest pmic1 major&minor in QCDT that is
equal to or lower than the runtime detected pmic1
14) select the highest pmic2 major&minor in QCDT that is
equal to or lower than the runtime detected pmic2
15) select the highest pmic3 major&minor in QCDT that is
equal to or lower than the runtime detected pmic3
6) Load the matching DTB blob to the tags addr
7) LK pass the correct DTB to the kernel