0
0
mirror of https://github.com/edk2-porting/edk2-msm synced 2024-11-11 12:59:20 +00:00
edk2-msm/tools/sosi-patcher.c
Xilin Wu 7b379f95d4 Initial repo structure refactor
Signed-off-by: Xilin Wu <strongtz@yeah.net>
2022-10-07 12:46:39 +08:00

127 lines
3.0 KiB
C
Executable File

#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;
}