Add SOSI addr patcher
authorXilin Wu <wuxilin123@gmail.com>
星期四, 12 May 2022 08:26:29 +0000 (16:26 +0800)
committerXilin Wu <wuxilin123@gmail.com>
星期四, 12 May 2022 08:26:29 +0000 (16:26 +0800)
bin/sosi-patcher-arm64 [new file with mode: 0755]
bin/sosi-patcher-x64 [new file with mode: 0755]
bin/sosi-patcher.c [new file with mode: 0755]

diff --git a/bin/sosi-patcher-arm64 b/bin/sosi-patcher-arm64
new file mode 100755 (executable)
index 0000000..8ec4118
Binary files /dev/null and b/bin/sosi-patcher-arm64 differ
diff --git a/bin/sosi-patcher-x64 b/bin/sosi-patcher-x64
new file mode 100755 (executable)
index 0000000..732223a
Binary files /dev/null and b/bin/sosi-patcher-x64 differ
diff --git a/bin/sosi-patcher.c b/bin/sosi-patcher.c
new file mode 100755 (executable)
index 0000000..e359ddc
--- /dev/null
@@ -0,0 +1,126 @@
+#include<errno.h>
+#include<fcntl.h>
+#include<stdio.h>
+#include<stdint.h>
+#include<stdlib.h>
+#include<string.h>
+#include<unistd.h>
+#include<sys/mman.h>
+#include<sys/stat.h>
+#include<sys/sendfile.h>
+struct acpi_header{
+       uint32_t sign;
+       uint32_t len;
+       uint8_t  rev;
+       uint8_t  checksum;
+       char     oemid[6];
+       char     oemtableid[8];
+       uint32_t oemrev;
+       uint32_t creatorid;
+       uint32_t creatorrev;
+};
+int main(int argc,char**argv){
+       if(argc!=4){
+               fprintf(stderr,"Usage: sosi-patcher <INPUT> <OUTPUT> <SOSI addr>\n");
+               return 1;
+       }
+       char*es=NULL;
+       uint64_t val=(uint64_t)strtoll(argv[3],&es,0);
+       if(errno!=0||es==argv[3]){
+               perror("invalid value");
+               return 1;
+       }
+       printf("target value: 0x%016lX\n",val);
+       printf("input file: %s\n",argv[1]);
+       printf("output file: %s\n",argv[2]);
+       int fdin=open(argv[1],O_RDONLY);
+       if(fdin<0){
+               perror("open input failed");
+               return 1;
+       }
+       int fdout=open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0644);
+       if(fdout<0){
+               perror("open output failed");
+               close(fdin);
+               return 1;
+       }
+       struct stat st;
+       if(fstat(fdin,&st)<0){
+               perror("fstat failed");
+               close(fdin);
+               close(fdout);
+               return 1;
+       }
+       if(st.st_size<=16){
+               fprintf(stderr,"input file too small\n");
+               close(fdin);
+               close(fdout);
+               return 1;
+       }
+       printf("file size: %zu bytes\n",st.st_size);
+       ssize_t r=sendfile(fdout,fdin,0,st.st_size);
+       if(r<0||(size_t)r!=(size_t)st.st_size){
+               perror("sendfile failed");
+               close(fdin);
+               close(fdout);
+               return 1;
+       }
+       fdatasync(fdout);
+       void*addr=mmap(NULL,st.st_size,PROT_READ|PROT_WRITE,MAP_SHARED,fdout,0);
+       if(addr==MAP_FAILED||!addr){
+               perror("mmap failed");
+               close(fdin);
+               close(fdout);
+               return 1;
+       }
+       struct acpi_header*header=addr;
+       char*pos=addr,oldsum=header->checksum,sum=0;
+       uint32_t size=header->len;
+       printf(
+               "acpi sign: \"%.*s\"\n",
+               (int)sizeof(header->sign),(char*)&header->sign
+       );
+       printf("acpi rev: 0x%08x\n",header->rev);
+       printf("acpi len: %d bytes\n",size);
+       printf("acpi checksum: %02X\n",oldsum);
+       printf(
+               "acpi oem id: \"%.*s\" tableid: \"%.*s\" rev: 0x%08x\n",
+               (int)sizeof(header->oemid),header->oemid,
+               (int)sizeof(header->oemtableid),header->oemtableid,
+               header->oemrev
+       );
+       printf(
+               "acpi creator id: \"%.*s\" rev: 0x%08x\n",
+               (int)sizeof(header->creatorid),(char*)&header->creatorid,
+               header->creatorrev
+       );
+       header->checksum=0;
+       while((size--)!=0)sum=(uint8_t)(sum+(*pos++));
+       sum=(uint8_t)(0xFF-sum+1);
+       printf("current checksum: %02X\n",sum);
+       if(header->len!=st.st_size)
+               printf("warning: acpi length mismatch\n");
+       if(sum!=oldsum)
+               printf("warning: acpi checksum mismatch\n");
+       pos=addr;
+       for(size_t s=0;s<(size_t)st.st_size-16;s++,pos++){
+               if(strncmp(pos,"SOSI",4)!=0)continue;
+               printf("found SOSI at 0x%08zX\n",s);
+               uint64_t*value=(uint64_t*)&pos[5];
+               printf("old value: 0x%016lx\n",*value);
+               *value=val;
+               printf("new value: 0x%016lx\n",*value);
+               break;
+       }
+       pos=addr,size=header->len,header->checksum=0;
+       while((size--)!=0)sum=(uint8_t)(sum+(*pos++));
+       sum=(uint8_t)(0xFF-sum+1);
+       printf("new checksum: %02X\n",sum);
+       header->checksum=sum;
+       munmap(addr,st.st_size);
+       fdatasync(fdout);
+       close(fdin);
+       close(fdout);
+       printf("done\n");
+       return 0;
+}