mirror of
https://github.com/edk2-porting/edk2-msm
synced 2024-11-11 12:59:20 +00:00
7b379f95d4
Signed-off-by: Xilin Wu <strongtz@yeah.net>
127 lines
3.0 KiB
C
Executable File
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;
|
|
}
|