X-Git-Url: https://glassweightruler.freedombox.rocks/gitweb/Ventoy.git/blobdiff_plain/8ef9732931bb298c8d5ffd66efcc4d79ad2cdbe2..c5fd64d21c4e0fb79d6d84015da85caa7023f0bc:/VtoyTool/vtoykmod.c diff --git a/VtoyTool/vtoykmod.c b/VtoyTool/vtoykmod.c index a1e2ea8..1e73db2 100644 --- a/VtoyTool/vtoykmod.c +++ b/VtoyTool/vtoykmod.c @@ -164,6 +164,13 @@ struct modversion_info { char name[64 - sizeof(unsigned long)]; }; +struct modversion_info2 { + /* Offset of the next modversion entry in relation to this one. */ + uint32_t next; + uint32_t crc; + char name[0]; +}; + typedef struct ko_param { @@ -181,6 +188,12 @@ typedef struct ko_param unsigned long sym_put_size; unsigned long kv_major; unsigned long ibt; + unsigned long kv_minor; + unsigned long blkdev_get_addr; + unsigned long blkdev_put_addr; + unsigned long bdev_open_addr; + unsigned long kv_subminor; + unsigned long bdev_file_open_addr; unsigned long padding[1]; }ko_param; @@ -236,7 +249,7 @@ static int vtoykmod_read_file(char *name, char **buf) return size; } -static int vtoykmod_find_section64(char *buf, char *section, int *offset, int *len) +static int vtoykmod_find_section64(char *buf, char *section, int *offset, int *len, Elf64_Shdr **shdr) { uint16_t i; int cmplen; @@ -258,6 +271,10 @@ static int vtoykmod_find_section64(char *buf, char *section, int *offset, int *l { *offset = (int)(sec[i].sh_offset); *len = (int)(sec[i].sh_size); + if (shdr) + { + *shdr = sec + i; + } return 0; } } @@ -265,7 +282,7 @@ static int vtoykmod_find_section64(char *buf, char *section, int *offset, int *l return 1; } -static int vtoykmod_find_section32(char *buf, char *section, int *offset, int *len) +static int vtoykmod_find_section32(char *buf, char *section, int *offset, int *len, Elf32_Shdr **shdr) { uint16_t i; int cmplen; @@ -287,6 +304,10 @@ static int vtoykmod_find_section32(char *buf, char *section, int *offset, int *l { *offset = (int)(sec[i].sh_offset); *len = (int)(sec[i].sh_size); + if (shdr) + { + *shdr = sec + i; + } return 0; } } @@ -294,14 +315,15 @@ static int vtoykmod_find_section32(char *buf, char *section, int *offset, int *l return 1; } -static int vtoykmod_update_modcrc(char *oldmodver, int oldcnt, char *newmodver, int newcnt) +static int vtoykmod_update_modcrc1(char *oldmodver, int oldcnt, char *newmodver, int newcnt) { int i, j; struct modversion_info *pold, *pnew; - + pold = (struct modversion_info *)oldmodver; pnew = (struct modversion_info *)newmodver; + debug("module update modver format 1\n"); for (i = 0; i < oldcnt; i++) { for (j = 0; j < newcnt; j++) @@ -318,6 +340,51 @@ static int vtoykmod_update_modcrc(char *oldmodver, int oldcnt, char *newmodver, return 0; } + +static int vtoykmod_update_modcrc2(char *oldmodver, int oldlen, char *newmodver, int newlen) +{ + struct modversion_info2 *pold, *pnew, *pnewend; + + pold = (struct modversion_info2 *)oldmodver; + pnew = (struct modversion_info2 *)newmodver; + pnewend = (struct modversion_info2 *)(newmodver + newlen); + + debug("module update modver format 2\n"); + /* here we think that there is only module_layout in oldmodver */ + + for (; pnew < pnewend && pnew->next; pnew = (struct modversion_info2 *)((char *)pnew + pnew->next)) + { + if (strcmp(pnew->name, "module_layout") == 0) + { + debug("CRC 0x%08x --> 0x%08x %s\n", pold->crc, pnew->crc, pnew->name); + memset(pold, 0, oldlen); + pold->next = 0x18; /* 8 + module_layout align 8 */ + pold->crc = pnew->crc; + strcpy(pold->name, pnew->name); + break; + } + } + + return 0; +} + + +static int vtoykmod_update_modcrc(char *oldmodver, int oldlen, char *newmodver, int newlen) +{ + uint32_t uiCrc = 0; + + memcpy(&uiCrc, newmodver + 4, 4); + + if (uiCrc > 0) + { + return vtoykmod_update_modcrc2(oldmodver, oldlen, newmodver, newlen); + } + else + { + return vtoykmod_update_modcrc1(oldmodver, oldlen / 64, newmodver, newlen / 64); + } +} + static int vtoykmod_update_vermagic(char *oldbuf, int oldsize, char *newbuf, int newsize, int *modver) { int i = 0; @@ -358,7 +425,7 @@ static int vtoykmod_update_vermagic(char *oldbuf, int oldsize, char *newbuf, int return 0; } -int vtoykmod_update(char *oldko, char *newko) +int vtoykmod_update(int kvMajor, int kvMinor, char *oldko, char *newko) { int rc = 0; int modver = 0; @@ -366,6 +433,7 @@ int vtoykmod_update(char *oldko, char *newko) int newoff, newlen; int oldsize, newsize; char *newbuf, *oldbuf; + Elf64_Shdr *sec = NULL; oldsize = vtoykmod_read_file(oldko, &oldbuf); newsize = vtoykmod_read_file(newko, &newbuf); @@ -382,18 +450,18 @@ int vtoykmod_update(char *oldko, char *newko) { if (oldbuf[EI_CLASS] == ELFCLASS64) { - rc = vtoykmod_find_section64(oldbuf, "__versions", &oldoff, &oldlen); - rc += vtoykmod_find_section64(newbuf, "__versions", &newoff, &newlen); + rc = vtoykmod_find_section64(oldbuf, "__versions", &oldoff, &oldlen, NULL); + rc += vtoykmod_find_section64(newbuf, "__versions", &newoff, &newlen, NULL); } else { - rc = vtoykmod_find_section32(oldbuf, "__versions", &oldoff, &oldlen); - rc += vtoykmod_find_section32(newbuf, "__versions", &newoff, &newlen); + rc = vtoykmod_find_section32(oldbuf, "__versions", &oldoff, &oldlen, NULL); + rc += vtoykmod_find_section32(newbuf, "__versions", &newoff, &newlen, NULL); } if (rc == 0) { - vtoykmod_update_modcrc(oldbuf + oldoff, oldlen / 64, newbuf + newoff, newlen / 64); + vtoykmod_update_modcrc(oldbuf + oldoff, oldlen, newbuf + newoff, newlen); } } else @@ -406,8 +474,8 @@ int vtoykmod_update(char *oldko, char *newko) { Elf64_Rela *oldRela, *newRela; - rc = vtoykmod_find_section64(oldbuf, ".rela.gnu.linkonce.this_module", &oldoff, &oldlen); - rc += vtoykmod_find_section64(newbuf, ".rela.gnu.linkonce.this_module", &newoff, &newlen); + rc = vtoykmod_find_section64(oldbuf, ".rela.gnu.linkonce.this_module", &oldoff, &oldlen, NULL); + rc += vtoykmod_find_section64(newbuf, ".rela.gnu.linkonce.this_module", &newoff, &newlen, NULL); if (rc == 0) { oldRela = (Elf64_Rela *)(oldbuf + oldoff); @@ -425,13 +493,31 @@ int vtoykmod_update(char *oldko, char *newko) { debug("section .rela.gnu.linkonce.this_module not found\n"); } + + if (kvMajor > 6 || (kvMajor == 6 && kvMinor >= 3)) + { + rc = vtoykmod_find_section64(oldbuf, ".gnu.linkonce.this_module", &oldoff, &oldlen, &sec); + rc += vtoykmod_find_section64(newbuf, ".gnu.linkonce.this_module", &newoff, &newlen, NULL); + if (rc == 0) + { + debug("section .gnu.linkonce.this_module change oldlen:0x%x to newlen:0x%x\n", oldlen, newlen); + if (sec) + { + sec->sh_size = newlen; + } + } + else + { + debug("section .gnu.linkonce.this_module not found\n"); + } + } } else { Elf32_Rel *oldRel, *newRel; - rc = vtoykmod_find_section32(oldbuf, ".rel.gnu.linkonce.this_module", &oldoff, &oldlen); - rc += vtoykmod_find_section32(newbuf, ".rel.gnu.linkonce.this_module", &newoff, &newlen); + rc = vtoykmod_find_section32(oldbuf, ".rel.gnu.linkonce.this_module", &oldoff, &oldlen, NULL); + rc += vtoykmod_find_section32(newbuf, ".rel.gnu.linkonce.this_module", &newoff, &newlen, NULL); if (rc == 0) { oldRel = (Elf32_Rel *)(oldbuf + oldoff); @@ -489,8 +575,14 @@ int vtoykmod_fill_param(char **argv) param->sym_put_size = strtoul(argv[8], NULL, 10); param->reg_kprobe_addr = strtoul(argv[9], NULL, 16); param->unreg_kprobe_addr = strtoul(argv[10], NULL, 16); - param->kv_major = (unsigned long)(argv[11][0] - '0'); + param->kv_major = strtoul(argv[11], NULL, 10); param->ibt = strtoul(argv[12], NULL, 16);; + param->kv_minor = strtoul(argv[13], NULL, 10); + param->blkdev_get_addr = strtoul(argv[14], NULL, 16); + param->blkdev_put_addr = strtoul(argv[15], NULL, 16); + param->kv_subminor = strtoul(argv[16], NULL, 10); + param->bdev_open_addr = strtoul(argv[17], NULL, 16); + param->bdev_file_open_addr = strtoul(argv[18], NULL, 16); debug("pgsize=%lu (%s)\n", param->pgsize, argv[1]); debug("printk_addr=0x%lx (%s)\n", param->printk_addr, argv[2]); @@ -504,6 +596,12 @@ int vtoykmod_fill_param(char **argv) debug("unreg_kprobe_addr=0x%lx (%s)\n", param->unreg_kprobe_addr, argv[10]); debug("kv_major=%lu (%s)\n", param->kv_major, argv[11]); debug("ibt=0x%lx (%s)\n", param->ibt, argv[12]); + debug("kv_minor=%lu (%s)\n", param->kv_minor, argv[13]); + debug("blkdev_get_addr=0x%lx (%s)\n", param->blkdev_get_addr, argv[14]); + debug("blkdev_put_addr=0x%lx (%s)\n", param->blkdev_put_addr, argv[15]); + debug("kv_subminor=%lu (%s)\n", param->kv_subminor, argv[16]); + debug("bdev_open_addr=0x%lx (%s)\n", param->bdev_open_addr, argv[17]); + debug("bdev_file_open_addr=0x%lx (%s)\n", param->bdev_file_open_addr, argv[18]); break; } @@ -543,6 +641,8 @@ static int vtoykmod_check_ibt(void) int vtoykmod_main(int argc, char **argv) { int i; + int kvMajor = 0; + int kvMinor = 0; for (i = 0; i < argc; i++) { @@ -553,13 +653,25 @@ int vtoykmod_main(int argc, char **argv) } } + if (verbose) + { + printf("==== Dump Argv ====\n"); + for (i = 0; i < argc; i++) + { + printf("<%s> ", argv[i]); + } + printf("\n"); + } + if (argv[1][0] == '-' && argv[1][1] == 'f') { return vtoykmod_fill_param(argv + 2); } else if (argv[1][0] == '-' && argv[1][1] == 'u') { - return vtoykmod_update(argv[2], argv[3]); + kvMajor = (int)strtol(argv[2], NULL, 10); + kvMinor = (int)strtol(argv[3], NULL, 10); + return vtoykmod_update(kvMajor, kvMinor, argv[4], argv[5]); } else if (argv[1][0] == '-' && argv[1][1] == 'I') {