common: import CyanogenMod dtbtool
* This allows for maximum compatibility with all SoCs and devices. Change-Id: I4a2d25c214d337e99217f7ec3767de8027570f97
This commit is contained in:
parent
0adb50d776
commit
c8bfc7211c
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue