From b98d6ed2ed42e0730e7b31b9d8f94f0d2afbd3a7 Mon Sep 17 00:00:00 2001 From: Jianhang Wu Date: Mon, 13 Jan 2025 20:40:40 +0800 Subject: [PATCH] Scripts: modified the matching method for version info in the format of x.x.x_yyyy-mm-dd and optimized coding format of "gen/pack_firmware*". Signed-off-by: Jianhang Wu --- scripts/envsetup.sh | 8 +- scripts/pack_firmware_bin/gen_firmware_xml.c | 567 +++++++++--------- scripts/pack_firmware_bin/pack_firmware_bin.c | 122 ++-- 3 files changed, 369 insertions(+), 328 deletions(-) diff --git a/scripts/envsetup.sh b/scripts/envsetup.sh index fcf68ea1..f53f1a81 100755 --- a/scripts/envsetup.sh +++ b/scripts/envsetup.sh @@ -1471,11 +1471,11 @@ function build_rv_firmware_bin() if [ ! -e "$RELEASED_NOTE_MD" ] || [ ! -s "$RELEASED_NOTE_MD" ];then version="1.0.0" - else - cp $RELEASED_NOTE_MD $RV_FIRMWARE_INSTALL_DIR/ - version=$(awk 'END {split($1, a, "_"); print a[1]}' $RELEASED_NOTE_MD) + else + cp $RELEASED_NOTE_MD $RV_FIRMWARE_INSTALL_DIR/ + LAST_MATCH=$(grep -oE '[0-9]+\.[0-9]+\.[0-9]+_[0-9]{4}-[0-9]{2}-[0-9]{2}' "$RELEASED_NOTE_MD" | tail -n 1) + version="$(echo "$LAST_MATCH" | cut -d'_' -f1)" fi - pushd $RV_FIRMWARE_INSTALL_DIR rm -f firmware*.bin *.xml diff --git a/scripts/pack_firmware_bin/gen_firmware_xml.c b/scripts/pack_firmware_bin/gen_firmware_xml.c index 54915a49..2ea8c206 100644 --- a/scripts/pack_firmware_bin/gen_firmware_xml.c +++ b/scripts/pack_firmware_bin/gen_firmware_xml.c @@ -7,296 +7,329 @@ #include "ezxml/ezxml.h" #include "ezxml/ezxml.c" #include +#include #define NAMESIZE 32 -#define LOADERSIZE 20 -#define INVALID "invalid" +#define LOADERSIZE 20 +#define INVALID "invalid" #define FLASHSIZE 0x4000000 -#ifdef SG2044R - #define PARTION{"efie","0x80000","0x1000",\ - "fsbl.bin", "0x81000" ,"0x7010080000" ,\ - "fw_dynamic.bin", "0x15d000", "0x82200000", \ - "ap_Image" ,"0x2f0000" ,"0x82400000", \ - "ap_rootfs.cpio", "0x2a00000" ,"0xa0000000", \ - "sg2044r_xmrig" ,"0x34b4000" ,"0x0"} - #define PARTNUM 6 - #define DTB_OFFSET 0x25b1000 - #define DTB_LOADER "0x90000000" - #define OUTPUT "sg2044r-layout.xml" - #define NAME "SG2044R" - #define RELEASENOTE "sg2044r_release_note.md" +#ifdef SG2044R +#define PARTION { \ + "efie", "0x80000", "0x1000", \ + "fsbl.bin", "0x81000", "0x7010080000", \ + "fw_dynamic.bin", "0x15d000", "0x82200000", \ + "ap_Image", "0x2f0000", "0x82400000", \ + "ap_rootfs.cpio", "0x2a00000", "0xa0000000", \ + "sg2044r_xmrig", "0x34b4000", "0x0" \ +} +#define PARTNUM 6 +#define DTB_OFFSET 0x25b1000 +#define DTB_LOADER "0x90000000" +#define OUTPUT "sg2044r-layout.xml" +#define NAME "SG2044R" +#define RELEASENOTE "sg2044r_release_note.md" #endif #ifdef MANGO - #define PARTION {"fip.bin","0x00030000",\ - "efie","0x600000","0x1000",\ - "zsbl.bin","0x2a00000","0x40000000",\ - "fw_dynamic.bin","0x670000","0x00000000",\ - "riscv64_Image","0x6c0000","0x02000000",\ - "initrd.img","0x2b00000","0x30000000",\ - "SG2042.fd","0x2000000","0x2000000"} - #define PARTNUM 7 - #define DTB_OFFSET 0x601000 - #define DTB_LOADER "0x20000000" - #define OUTPUT "sg2042-layout.xml" - #define NAME "SG2042" - #define RELEASENOTE "sg2042_release_note.md" +#define PARTION { \ + "fip.bin", "0x00030000", \ + "efie", "0x600000", "0x1000", \ + "zsbl.bin", "0x2a00000", "0x40000000", \ + "fw_dynamic.bin", "0x670000", "0x00000000", \ + "riscv64_Image", "0x6c0000", "0x02000000", \ + "initrd.img", "0x2b00000", "0x30000000", \ + "SG2042.fd", "0x2000000", "0x2000000" \ +} +#define PARTNUM 7 +#define DTB_OFFSET 0x601000 +#define DTB_LOADER "0x20000000" +#define OUTPUT "sg2042-layout.xml" +#define NAME "SG2042" +#define RELEASENOTE "sg2042_release_note.md" #endif #ifdef SG2044 - #define PARTION {"efie","0x80000","0x1000",\ - "zsbl.bin","0x2f0000","0x40000000",\ - "fsbl.bin","0x81000","0x7010080000",\ - "fw_dynamic.bin","0x15d000","0x80000000",\ - "SG2044.fd","0x600000","0x80200000"} - #define PARTNUM 5 - #define DTB_OFFSET 0x500000 - #define DTB_LOADER "0x88000000" - #define OUTPUT "sg2044-layout.xml" - #define NAME "SG2044" - #define RELEASENOTE "sg2044_release_note.md" +#define PARTION { \ + "efie", "0x80000", "0x1000", \ + "zsbl.bin", "0x2f0000", "0x40000000", \ + "fsbl.bin", "0x81000", "0x7010080000", \ + "fw_dynamic.bin", "0x15d000", "0x80000000", \ + "SG2044.fd", "0x600000", "0x80200000" \ +} +#define PARTNUM 5 +#define DTB_OFFSET 0x500000 +#define DTB_LOADER "0x88000000" +#define OUTPUT "sg2044-layout.xml" +#define NAME "SG2044" +#define RELEASENOTE "sg2044_release_note.md" #endif -typedef struct p_info{ - char p_name[NAMESIZE]; - uint32_t p_off; - char p_ldr[LOADERSIZE]; - char p_size[LOADERSIZE]; -}p_info; - -void get_dtb_info(struct p_info *info, char *dtb_name, uint32_t dtb_off, char* dtb_ldr){ - strcpy(info->p_name,dtb_name); - info->p_off=dtb_off; - strcpy(info->p_ldr,dtb_ldr); +typedef struct p_info { + char p_name[NAMESIZE]; + uint32_t p_off; + char p_ldr[LOADERSIZE]; + char p_size[LOADERSIZE]; +} p_info; + +void get_dtb_info(struct p_info *info, char *dtb_name, uint32_t dtb_off, char *dtb_ldr) +{ + strcpy(info->p_name, dtb_name); + info->p_off = dtb_off; + strcpy(info->p_ldr, dtb_ldr); } -int get_part_info(struct p_info *info, int p_num, char *part[]){ - int i,j,ret; - struct stat file_stat; - char p_stat[LOADERSIZE]; - for(i=0,j=0;ip_name,part[j++]); - (info+i)->p_off=strtoul(part[j++],NULL,16); - strcpy((info+i)->p_ldr,INVALID); - ret=stat((info+i)->p_name,&file_stat); - if (ret || !file_stat.st_size) { - printf("failed to get the file %s size !\n",(info+i)->p_name); - return -1; - } - sprintf(p_stat,"0x%lX",file_stat.st_size); - strcpy((info+i)->p_size,p_stat); - i++; - } - if(part[j]=="efie"){ - strcpy((info+i)->p_name,part[j++]); - (info+i)->p_off=strtoul(part[j++],NULL,16); - strcpy((info+i)->p_ldr,INVALID); - strcpy((info+i)->p_size,part[j++]); - i++; - } - strcpy((info+i)->p_name,part[j++]); - (info+i)->p_off=strtoul(part[j++],NULL,16); - strcpy((info+i)->p_ldr,part[j++]); - stat((info+i)->p_name,&file_stat); - sprintf(p_stat,"0x%lX",file_stat.st_size); - strcpy((info+i)->p_size,p_stat); - } - return 0; +int get_part_info(struct p_info *info, int p_num, char *part[]) +{ + int i, j, ret; + struct stat file_stat; + char p_stat[LOADERSIZE]; + + for (i = 0, j = 0; i < p_num; i++) { + if (part[j] == "fip.bin") { + strcpy((info + i)->p_name, part[j++]); + (info + i)->p_off = strtoul(part[j++], NULL, 16); + strcpy((info + i)->p_ldr, INVALID); + ret = stat((info + i)->p_name, &file_stat); + + if (ret || !file_stat.st_size) { + printf("failed to get the file %s size !\n", (info + i)->p_name); + return -1; + } + + sprintf(p_stat, "0x%lX", file_stat.st_size); + strcpy((info + i)->p_size, p_stat); + i++; + } + + if (part[j] == "efie") { + strcpy((info + i)->p_name, part[j++]); + (info + i)->p_off = strtoul(part[j++], NULL, 16); + strcpy((info + i)->p_ldr, INVALID); + strcpy((info + i)->p_size, part[j++]); + i++; + } + + strcpy((info + i)->p_name, part[j++]); + (info + i)->p_off = strtoul(part[j++], NULL, 16); + strcpy((info + i)->p_ldr, part[j++]); + stat((info + i)->p_name, &file_stat); + sprintf(p_stat, "0x%lX", file_stat.st_size); + strcpy((info + i)->p_size, p_stat); + } + return 0; } -void parse_info(ezxml_t parent, struct p_info *info, char*sp_off){ - char *txt; - if( !strcmp(info->p_name,"efie") ){ - txt="efie"; - }else{ - txt="component"; - } - ezxml_t child=ezxml_add_child(parent,txt,0); - ezxml_set_txt(ezxml_add_child(child,"name",0), info->p_name); - sprintf(sp_off,"0x%X",info->p_off); - ezxml_set_txt(ezxml_add_child(child,"offset",0), sp_off); - if(strcmp(info->p_ldr,INVALID)){ - ezxml_set_txt(ezxml_add_child(child,"loader",0), info->p_ldr); - } - if(strcmp(info->p_size,INVALID)){ - ezxml_set_txt(ezxml_add_child(child,"size",0), info->p_size); - } +void parse_info(ezxml_t parent, struct p_info *info, char *sp_off) +{ + char *txt; + ezxml_t child ; + + if (!strcmp(info->p_name, "efie")) + txt = "efie"; + else + txt = "component"; + + child = ezxml_add_child(parent, txt, 0); + ezxml_set_txt(ezxml_add_child(child, "name", 0), info->p_name); + sprintf(sp_off, "0x%X", info->p_off); + ezxml_set_txt(ezxml_add_child(child, "offset", 0), sp_off); + + if (strcmp(info->p_ldr, INVALID)) + ezxml_set_txt(ezxml_add_child(child, "loader", 0), info->p_ldr); + if (strcmp(info->p_size, INVALID)) + ezxml_set_txt(ezxml_add_child(child, "size", 0), info->p_size); } -void format_xml(const char *input, char *output){ - const char *ptr = input; - char *out_ptr = output; - int indent=0,marked=0; - while(*ptr){ - if(*ptr=='>'){ - if(*(ptr+1)=='<'){ - if(*(ptr+2)=='/'){ - *out_ptr++=*ptr++; - indent-=1; - marked=1; - } - else{ - if(marked){ - *out_ptr++=*ptr++; - marked=0; - } - else{ - indent+=1; - *out_ptr++=*ptr++; - } - } - *out_ptr++='\n'; - memset(out_ptr,'\t',indent); - out_ptr+=indent; - } - else{ - marked=1; - *out_ptr++=*ptr++; - } - }else{ - *out_ptr++=*ptr++; - } - } - *out_ptr = '\0'; +void format_xml(const char *input, char *output) +{ + const char *ptr = input; + char *out_ptr = output; + int indent = 0, marked = 0; + + while (*ptr) { + if (*ptr == '>') { + if (*(ptr + 1) == '<') { + if (*(ptr + 2) == '/') { + *out_ptr++ = *ptr++; + indent -= 1; + marked = 1; + } + else { + if (marked) { + *out_ptr++ = *ptr++; + marked = 0; + } + else { + indent += 1; + *out_ptr++ = *ptr++; + } + } + *out_ptr++ = '\n'; + memset(out_ptr, '\t', indent); + out_ptr += indent; + } + else { + marked = 1; + *out_ptr++ = *ptr++; + } + } else + *out_ptr++ = *ptr++; + } + *out_ptr = '\0'; } -int gen_xml(FILE *fp,ezxml_t parent, struct p_info *info, int p_num){ - int i,j,tar=0; - uint32_t min_off,cur_off=0; - char origin[p_num*LOADERSIZE]; - char* sp_off=origin; - uint32_t all_off[p_num]; - uint64_t all_size[p_num]; - for(i=0;icur_off && info[j].p_offall_off[i+1]){ - printf("failed for overlap: check the layer of the %dth file and the %dth file !\n",i,i+1); - return -1; - } - } - if(all_off[p_num-1]+all_size[p_num-1]>FLASHSIZE){ - printf("failed for overlap: the layer of the %dth file over the flash !\n",p_num-1); - return -1; - } - return 0; +int gen_xml(FILE *fp, ezxml_t parent, struct p_info *info, int p_num) +{ + int i, j, tar = 0; + uint32_t min_off, cur_off = 0; + char origin[p_num * LOADERSIZE]; + char *sp_off = origin; + uint32_t all_off[p_num]; + uint64_t all_size[p_num]; + + for (i = 0; i < p_num; i++) { + min_off = FLASHSIZE; + + for (j = 0; j < p_num; j++) { + if (info[j].p_off > cur_off && info[j].p_off < min_off) { + min_off = info[j].p_off; + tar = j; + } + } + + cur_off = min_off; + all_off[i] = info[tar].p_off; + all_size[i] = strtoul(info[tar].p_size, NULL, 16); + parse_info(parent, &info[tar], sp_off); + sp_off += LOADERSIZE; + printf("generate the %dth partion info name:%s offset:0x%X loader:%s size:%s\n", i, + info[tar].p_name, info[tar].p_off, info[tar].p_ldr, info[tar].p_size); + } + + const char *raw_xml = ezxml_toxml(parent); + char formatted_xml[8192]; + + format_xml(raw_xml, formatted_xml); + fprintf(fp, "%s", formatted_xml); + + for (i = 0; i < p_num - 1; i++) { + if (all_off[i] + all_size[i] > all_off[i + 1]) { + printf("failed for overlap: check the layer of the %dth file and the %dth file !\n", i, i + 1); + return -1; + } + } + if (all_off[p_num - 1] + all_size[p_num - 1] > FLASHSIZE) { + printf("failed for overlap: the layer of the %dth file over the flash !\n", p_num - 1); + return -1; + } + return 0; } -int get_version(char *file_name, char* version){ - FILE *file=fopen(file_name,"r"); - char buffer[64]; - if(file == NULL || ftell(file) <= 1){ - strcpy(version,"1.0.0"); - printf("generate the default version: 1.0.0\n"); - return 0; - } - else{ - long size = ftell(file); - fseek(file,0,SEEK_END); - if(size <= 5){ - printf("failed to get correct version number, release-note can't end with 'enter'\n"); - return -1; +int get_version(char *file_name, char *version) +{ + FILE *file = fopen(file_name, "r"); + char buffer[256]; + char match_ver[16]; + int start, end; + char *first_word; + + if (file == NULL) { + strcpy(version, "1.0.0"); + printf("generate the default version: 1.0.0\n"); + return 0; } - long pos; - for (pos = size - 1; pos >= 0; pos--) { - fseek(file, pos, SEEK_SET); - if (pos == 0 || fgetc(file) == '\n') { - break; - } - } - if (fgets(buffer, sizeof(buffer), file) != NULL) { - char *first_word = strtok(buffer, " "); - strcpy(version,strtok(first_word,"_")); - printf("generate the firmware version: %s\n",version); - } - } - return 0; + else { + regex_t regex; + int reti; + regmatch_t matches[1]; + const char *pattern = "([0-9]+\\.[0-9]+\\.[0-9]+_[0-9]{4}-[0-9]{2}-[0-9]{2})"; + + reti = regcomp(®ex, pattern, REG_EXTENDED); + if (reti) { + printf("could not compile regex\n"); + return -1; + } + + while (fgets(buffer, sizeof(buffer), file)) { + reti = regexec(®ex, buffer, 1, matches, 0); + if (!reti) { + start = matches[0].rm_so; + end = matches[0].rm_eo; + strncpy(match_ver, buffer + start, end - start); + first_word = strtok(match_ver, " "); + strcpy(version, strtok(first_word, "_")); + } + } + printf("generate the firmware version: %s\n", version); + regfree(®ex); + } + return 0; } -int main(int argc, char* argv[]) { - int ret,i; - char *part[]=PARTION; - int p_num=PARTNUM; - int dtb_num=argc-1; - struct p_info info[dtb_num+p_num]; - uint32_t dtb_off=DTB_OFFSET; - char* dtb_ldr=DTB_LOADER; - struct stat dtb_stat; - char *output=OUTPUT; - char flash_size[LOADERSIZE]; - char version[LOADERSIZE]; - - time_t t = time(NULL); - struct tm *tm_info = localtime(&t); - char date[LOADERSIZE]; - strftime(date, sizeof(date), "%Y%m%d", tm_info); - - for (i=0;itxt,NULL,16); - p = ezxml_child(ezxml_child(parent,"efie"),"size"); - *p_size = strtol(p->txt,NULL,0); + p = ezxml_child(ezxml_child(parent, "efie"), "offset"); + *p_off = strtol(p->txt, NULL, 16); + p = ezxml_child(ezxml_child(parent, "efie"), "size"); + *p_size = strtol(p->txt, NULL, 0); return 0; // printf("get the efie partion offset: 0x%x size: %d\n",*p_off,*p_size); } -int get_component_info(ezxml_t parent, struct part_info *info, int *flag){ +int get_component_info(ezxml_t parent, struct part_info *info, int *flag) +{ char* p_name; uint32_t magic, p_offset, p_size; int len, size, ret; uint64_t p_lma; ezxml_t p; - memset(info, 0, sizeof(struct part_info)); + memset(info, 0, sizeof(struct part_info)); info->magic = DPT_MAGIC; //add offset info - p=ezxml_child(parent,"offset"); - p_offset=strtoul(p->txt,NULL,16); - info->offset=p_offset; + p = ezxml_child(parent, "offset"); + p_offset = strtoul(p->txt, NULL, 16); + info->offset = p_offset; //add name info - p=ezxml_child(parent,"name"); - p_name=p->txt; + p = ezxml_child(parent, "name"); + p_name = p->txt; len = strlen(p_name); size = sizeof(info->name); memcpy(info->name, p_name, len > size ? size : len); - if( !strcmp(p_name, "fip.bin")){ + if (!strcmp(p_name, "fip.bin")) { // printf("skip %s info\n",p_name); *flag = 1; return 0; @@ -122,85 +129,86 @@ int get_component_info(ezxml_t parent, struct part_info *info, int *flag){ //add size info struct stat file_stat; - p=ezxml_child(parent,"size"); - p_size=strtoul(p->txt,NULL,0); + p = ezxml_child(parent, "size"); + p_size = strtoul(p->txt, NULL, 0); ret = stat(p_name, &file_stat); - if (ret || file_stat.st_size != p_size) { + if (ret || file_stat.st_size != p_size) { printf("failed to get file %s size or size: %ld not equal size from xml:%d\n", p_name, - file_stat.st_size,p_size); + file_stat.st_size, p_size); return -1; } info->size = file_stat.st_size; //add loader info - p=ezxml_child(parent,"loader"); - p_lma=strtoul(p->txt,NULL,16); - info->lma=p_lma; + p = ezxml_child(parent, "loader"); + p_lma = strtoul(p->txt, NULL, 16); + info->lma = p_lma; return 0; } -int main(int argc, char *argv[]){ - +int main(int argc, char *argv[]) +{ char * __attribute__((unused)) firmware_name = "firmware"; - char *firmware_version,*firmware_date; - ezxml_t p,comp; - char *file=argv[1]; - unsigned int comp_count=0; - int fd,ret,fd_fip,flag; + char *firmware_version, *firmware_date; + ezxml_t p, comp; + char *file = argv[1]; + unsigned int comp_count = 0; + int fd, ret, fd_fip, flag; + uint32_t efie_offset,efie_size; - ezxml_t firmware=ezxml_parse_file(file); + ezxml_t firmware = ezxml_parse_file(file); if (strcmp(firmware->name, "firmware")) { - printf("failed: %s is not a valid layout file\n",file); + printf("failed: %s is not a valid layout file\n", file); return -1; } - p=ezxml_child(firmware,"name"); - firmware_name=p->txt; + p = ezxml_child(firmware, "name"); + firmware_name = p->txt; - p=ezxml_child(firmware,"version"); - firmware_version=p->txt; - if(strlen(firmware_version)+1>LOADERSIZE){ + p = ezxml_child(firmware, "version"); + firmware_version = p->txt; + if (strlen(firmware_version) + 1> LOADERSIZE) { printf("failed: version number is too long, check the name length limit\n"); return -1; } - p=ezxml_child(firmware,"date"); - firmware_date=p->txt; - if(strlen(firmware_date)+1>LOADERSIZE){ + p = ezxml_child(firmware, "date"); + firmware_date = p->txt; + if (strlen(firmware_date) + 1 > LOADERSIZE) { printf("failed: date size is too big, check the name length limit\n"); return -1; } fd = open(OUTPUT, O_CREAT | O_RDWR | O_TRUNC, 0644); - if( fd == -1){ + if (fd == -1) { printf("failed to open %s\n",OUTPUT); return -1; } - if(ret=spi_flash_version(fd, firmware_version)){ + if (ret = spi_flash_version(fd, firmware_version)) { printf("failed to get version\n"); goto failed_pack; } - if(ret=spi_flash_date(fd, firmware_date)){ + if (ret = spi_flash_date(fd, firmware_date)) { printf("failed to get date\n"); goto failed_pack; } - uint32_t efie_offset,efie_size; - if(ret=get_efie_info(firmware, &efie_offset, &efie_size)){ + if (ret = get_efie_info(firmware, &efie_offset, &efie_size)) { printf("failed to get efie info\n"); goto failed_pack; } - for (comp=ezxml_child(firmware,"component"); comp; comp=comp->next){ + for (comp = ezxml_child(firmware, "component"); comp; comp = comp->next) { struct part_info info; - flag=0; - if(ret=get_component_info(comp,&info,&flag)){ + + flag = 0; + if (ret = get_component_info(comp, &info, &flag)) { goto failed_pack; } - if( !flag ){ - lseek(fd, efie_offset+comp_count*sizeof(struct part_info), SEEK_SET); + if (!flag) { + lseek(fd, efie_offset + comp_count * sizeof(struct part_info), SEEK_SET); write(fd, &info, sizeof(struct part_info)); // printf("wtite %s info to the %dth partion table at 0x%lx\n",info.name,comp_count, // efie_offset+comp_count*sizeof(struct part_info));