This commit is contained in:
Ing 2023-08-19 21:11:28 +08:00
parent 9d8605df58
commit 254be512cb
8 changed files with 335 additions and 275 deletions

8
.gitmodules vendored
View File

@ -1,6 +1,6 @@
[submodule "redpill-lkm"] [submodule "redpill-lkm"]
path = redpill-lkm path = redpill-lkm
url = https://github.com/wjz304/redpill-lkm url = https://github.com/wjz304/redpill-lkm
[submodule "addons"] [submodule "addons"]
path = addons path = addons
url = https://github.com/wjz304/arpl-addons url = https://github.com/wjz304/arpl-addons

View File

@ -15,11 +15,11 @@ BOARD_PATH="${CONFIG_DIR}/board/arpl"
echo "Creating image file" echo "Creating image file"
# unzip base image # unzip base image
gzip -dc "${BOARD_PATH}/grub.img.gz" > "${IMAGE_FILE}" gzip -dc "${BOARD_PATH}/grub.img.gz" >"${IMAGE_FILE}"
# fdisk # fdisk
fdisk -l "${IMAGE_FILE}" fdisk -l "${IMAGE_FILE}"
# Find idle of loop device # Find idle of loop device
LOOPX=`sudo losetup -f` LOOPX=$(sudo losetup -f)
# Setup the ${LOOPX} loop device # Setup the ${LOOPX} loop device
sudo losetup -P "${LOOPX}" "${IMAGE_FILE}" sudo losetup -P "${LOOPX}" "${IMAGE_FILE}"

View File

@ -4,7 +4,6 @@ set -e
. scripts/func.sh . scripts/func.sh
if [ ! -d .buildroot ]; then if [ ! -d .buildroot ]; then
echo "Downloading buildroot" echo "Downloading buildroot"
git clone --single-branch -b 2023.02.x https://github.com/buildroot/buildroot.git .buildroot git clone --single-branch -b 2023.02.x https://github.com/buildroot/buildroot.git .buildroot
@ -25,15 +24,15 @@ rm -rf ".buildroot/board/arpl/p3"
# Copy files # Copy files
echo "Copying files" echo "Copying files"
VERSION=`cat VERSION` VERSION=$(cat VERSION)
sed 's/^ARPL_VERSION=.*/ARPL_VERSION="'${VERSION}'"/' -i files/board/arpl/overlayfs/opt/arpl/include/consts.sh sed 's/^ARPL_VERSION=.*/ARPL_VERSION="'${VERSION}'"/' -i files/board/arpl/overlayfs/opt/arpl/include/consts.sh
echo "${VERSION}" > files/board/arpl/p1/ARPL-VERSION echo "${VERSION}" >files/board/arpl/p1/ARPL-VERSION
cp -Ru files/* .buildroot/ cp -Ru files/* .buildroot/
cd .buildroot cd .buildroot
echo "Generating default config" echo "Generating default config"
make BR2_EXTERNAL=../external -j`nproc` arpl_defconfig make BR2_EXTERNAL=../external -j$(nproc) arpl_defconfig
echo "Version: ${VERSION}" echo "Version: ${VERSION}"
echo "Building... Drink a coffee and wait!" echo "Building... Drink a coffee and wait!"
make BR2_EXTERNAL=../external -j`nproc` make BR2_EXTERNAL=../external -j$(nproc)
cd - cd -

View File

@ -55,7 +55,8 @@ uint64_t orPos[4], fileSize, rodataAddr, rodataOffs, initTextOffs;
unsigned char *fileData; unsigned char *fileData;
/*****************************************************************************/ /*****************************************************************************/
void errorMsg(char *fmt, ...) { void errorMsg(char *fmt, ...)
{
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
vfprintf(stderr, fmt, args); vfprintf(stderr, fmt, args);
@ -65,32 +66,38 @@ void errorMsg(char *fmt, ...) {
} }
/*****************************************************************************/ /*****************************************************************************/
void errorNum() { void errorNum()
{
char str[100] = {0}; char str[100] = {0};
perror(str); perror(str);
exit(2); exit(2);
} }
/*****************************************************************************/ /*****************************************************************************/
void elfErrno() { void elfErrno()
{
int err; int err;
if ((err = elf_errno()) != 0) { if ((err = elf_errno()) != 0)
{
fprintf(stderr, "%s\n", elf_errmsg(err)); fprintf(stderr, "%s\n", elf_errmsg(err));
exit(3); exit(3);
} }
} }
/*****************************************************************************/ /*****************************************************************************/
//Finding a function boundary is non-trivial really as patters can vary, we can have multiple exit points, and in CISC // Finding a function boundary is non-trivial really as patters can vary, we can have multiple exit points, and in CISC
// there are many things which may match e.g. "PUSH EBP". Implementing even a rough disassembler is pointless. // there are many things which may match e.g. "PUSH EBP". Implementing even a rough disassembler is pointless.
//However, we can certainly cheat here as we know with CDECL a non-empty function will always contain one or more // However, we can certainly cheat here as we know with CDECL a non-empty function will always contain one or more
// PUSH (0x41) R12-R15 (0x54-57) sequences. Then we can search like a 1K forward for these characteristic LOCK OR. // PUSH (0x41) R12-R15 (0x54-57) sequences. Then we can search like a 1K forward for these characteristic LOCK OR.
uint64_t findPUSH_R12_R15_SEQ(uint64_t start) { uint64_t findPUSH_R12_R15_SEQ(uint64_t start)
{
uint64_t i; uint64_t i;
for (i = start; i < fileSize; i++) { for (i = start; i < fileSize; i++)
if (fileData[i] == 0x41 && (fileData[i+1] >= 0x54 && fileData[i+1] <= 0x57)) { {
if (fileData[i] == 0x41 && (fileData[i + 1] >= 0x54 && fileData[i + 1] <= 0x57))
{
return i; return i;
} }
} }
@ -99,21 +106,26 @@ uint64_t findPUSH_R12_R15_SEQ(uint64_t start) {
/*****************************************************************************/ /*****************************************************************************/
//[0xF0, 0x80, null, null, null, null, null, 0xXX], //[0xF0, 0x80, null, null, null, null, null, 0xXX],
uint64_t findORs(uint64_t start, uint32_t maxCheck) { uint64_t findORs(uint64_t start, uint32_t maxCheck)
{
uint64_t i; uint64_t i;
int c = 0; int c = 0;
uint8_t lb = 0x01; uint8_t lb = 0x01;
for (i = start; i < fileSize; i++) { for (i = start; i < fileSize; i++)
if (fileData[i] == 0xF0 && fileData[i+1] == 0x80 && fileData[i+7] == lb) { {
if (fileData[i] == 0xF0 && fileData[i + 1] == 0x80 && fileData[i + 7] == lb)
{
orPos[c++] = i; orPos[c++] = i;
i += 7; i += 7;
lb <<= 1; lb <<= 1;
} }
if (c == 4) { if (c == 4)
{
break; break;
} }
if (--maxCheck == 0) { if (--maxCheck == 0)
{
break; break;
} }
} }
@ -121,53 +133,62 @@ uint64_t findORs(uint64_t start, uint32_t maxCheck) {
} }
/*****************************************************************************/ /*****************************************************************************/
void patchBootParams() { void patchBootParams()
{
uint64_t addr, pos; uint64_t addr, pos;
uint64_t newPtrOffset, ptrOffset; uint64_t newPtrOffset, ptrOffset;
int n; int n;
printf("Patching boot params.\n"); printf("Patching boot params.\n");
//The function will reside in init code part. We don't care we may potentially search beyond as we expect it to be found // The function will reside in init code part. We don't care we may potentially search beyond as we expect it to be found
while (initTextOffs < fileSize) { while (initTextOffs < fileSize)
{
addr = findPUSH_R12_R15_SEQ(initTextOffs); addr = findPUSH_R12_R15_SEQ(initTextOffs);
if (addr == -1) if (addr == -1)
break; //no more "functions" left break; // no more "functions" left
printf("\rAnalyzing f() candidate @ %lX, PUSH @ %lX", initTextOffs, addr); printf("\rAnalyzing f() candidate @ %lX, PUSH @ %lX", initTextOffs, addr);
//we found something looking like PUSH R12-R15, now find the ORs // we found something looking like PUSH R12-R15, now find the ORs
n = findORs(initTextOffs, 1024); n = findORs(initTextOffs, 1024);
if (n != 4) { if (n != 4)
//We can always move forward by the function token length (obvious) but if we couldn't find any LOCK-OR tokens {
// We can always move forward by the function token length (obvious) but if we couldn't find any LOCK-OR tokens
// we can skip the whole look ahead distance. We CANNOT do that if we found even a single token because the next one // we can skip the whole look ahead distance. We CANNOT do that if we found even a single token because the next one
// might have been just after the look ahead distance // might have been just after the look ahead distance
initTextOffs += 2; initTextOffs += 2;
if (n == 0) { if (n == 0)
{
initTextOffs += 1024; initTextOffs += 1024;
} }
continue; //Continue the main search loop to find next function candidate continue; // Continue the main search loop to find next function candidate
} }
//We found LOCK(); OR ptr sequences so we can print some logs and collect ptrs (as this is quite expensive) // We found LOCK(); OR ptr sequences so we can print some logs and collect ptrs (as this is quite expensive)
printf("\n[?] Found possible f() @ %lX\n", initTextOffs); printf("\n[?] Found possible f() @ %lX\n", initTextOffs);
ptrOffset=0; ptrOffset = 0;
int ec = 0; int ec = 0;
for (n = 0; n < 4; n++) { for (n = 0; n < 4; n++)
//data will have the following bytes: {
// data will have the following bytes:
// [0-LOCK()] [1-OR()] [2-BYTE-PTR] [3-OFFS-b3] [4-OFFS-b2] [5-OFFS-b1] [6-OFFS-b1] [7-NUMBER] // [0-LOCK()] [1-OR()] [2-BYTE-PTR] [3-OFFS-b3] [4-OFFS-b2] [5-OFFS-b1] [6-OFFS-b1] [7-NUMBER]
pos = orPos[n]; pos = orPos[n];
//how far it "jumps" // how far it "jumps"
newPtrOffset = pos + (fileData[pos+6] << 24 | fileData[pos+5] << 16 | fileData[pos+4] << 8 | fileData[pos+3]); newPtrOffset = pos + (fileData[pos + 6] << 24 | fileData[pos + 5] << 16 | fileData[pos + 4] << 8 | fileData[pos + 3]);
if (ptrOffset == 0) { if (ptrOffset == 0)
{
ptrOffset = newPtrOffset; ptrOffset = newPtrOffset;
++ec; ++ec;
} else if (ptrOffset == newPtrOffset) { }
else if (ptrOffset == newPtrOffset)
{
++ec; ++ec;
} }
printf("\t[+] Found LOCK-OR#%d sequence @ %lX => %02X %02X %02X %02X %02X %02X %02X %02X [RIP+%lX]\n", printf("\t[+] Found LOCK-OR#%d sequence @ %lX => %02X %02X %02X %02X %02X %02X %02X %02X [RIP+%lX]\n",
n, pos, fileData[pos], fileData[pos+1], fileData[pos+2], fileData[pos+3], fileData[pos+4], n, pos, fileData[pos], fileData[pos + 1], fileData[pos + 2], fileData[pos + 3], fileData[pos + 4],
fileData[pos+5], fileData[pos+6], fileData[pos+7], newPtrOffset); fileData[pos + 5], fileData[pos + 6], fileData[pos + 7], newPtrOffset);
} }
if (ec != 4) { if (ec != 4)
{
printf("\t[-] LOCK-OR PTR offset mismatch - %d/4 matched\n", ec); printf("\t[-] LOCK-OR PTR offset mismatch - %d/4 matched\n", ec);
//If the pointer checking failed we can at least move beyond the last LOCK-OR found as we know there's no valid // If the pointer checking failed we can at least move beyond the last LOCK-OR found as we know there's no valid
// sequence of LOCK-ORs there // sequence of LOCK-ORs there
initTextOffs = orPos[3]; initTextOffs = orPos[3];
continue; continue;
@ -175,12 +196,16 @@ void patchBootParams() {
printf("\t[+] All %d LOCK-OR PTR offsets equal - match found!\n", ec); printf("\t[+] All %d LOCK-OR PTR offsets equal - match found!\n", ec);
break; break;
} }
if (addr == -1) { if (addr == -1)
{
errorMsg("\nFailed to find matching sequences\n"); errorMsg("\nFailed to find matching sequences\n");
} else { }
//Patch offsets else
for (n = 0; n < 4; n++) { {
//The offset will point at LOCK(), we need to change the OR (0x80 0x0d) to AND (0x80 0x25) so the two bytes after // Patch offsets
for (n = 0; n < 4; n++)
{
// The offset will point at LOCK(), we need to change the OR (0x80 0x0d) to AND (0x80 0x25) so the two bytes after
pos = orPos[n] + 2; pos = orPos[n] + 2;
printf("Patching OR to AND @ %lX\n", pos); printf("Patching OR to AND @ %lX\n", pos);
fileData[pos] = 0x25; fileData[pos] = 0x25;
@ -189,121 +214,142 @@ void patchBootParams() {
} }
/*****************************************************************************/ /*****************************************************************************/
uint32_t changeEndian(uint32_t num) { uint32_t changeEndian(uint32_t num)
return ((num>>24)&0xff) | // move byte 3 to byte 0 {
((num<<8)&0xff0000) | // move byte 1 to byte 2 return ((num >> 24) & 0xff) | // move byte 3 to byte 0
((num>>8)&0xff00) | // move byte 2 to byte 1 ((num << 8) & 0xff0000) | // move byte 1 to byte 2
((num<<24)&0xff000000); // move byte 0 to byte 3 ((num >> 8) & 0xff00) | // move byte 2 to byte 1
((num << 24) & 0xff000000); // move byte 0 to byte 3
} }
/*****************************************************************************/ /*****************************************************************************/
uint64_t findSeq(const char* seq, int len, uint32_t pos, int dir, uint64_t max) { uint64_t findSeq(const char *seq, int len, uint32_t pos, int dir, uint64_t max)
{
uint64_t i = pos; uint64_t i = pos;
do { do
if (memcmp((const char*)fileData+i, seq, len) == 0) { {
if (memcmp((const char *)fileData + i, seq, len) == 0)
{
return i; return i;
} }
i += dir; i += dir;
--max; --max;
} while(i > 0 && i < fileSize && max > 0); } while (i > 0 && i < fileSize && max > 0);
return -1; return -1;
} }
/*****************************************************************************/ /*****************************************************************************/
void patchRamdiskCheck() { void patchRamdiskCheck()
{
uint64_t pos, errPrintAddr; uint64_t pos, errPrintAddr;
uint64_t printkPos, testPos, jzPos; uint64_t printkPos, testPos, jzPos;
const char str[] = "3ramdisk corrupt"; const char str[] = "3ramdisk corrupt";
printf("Patching ramdisk check.\n"); printf("Patching ramdisk check.\n");
for (pos = rodataOffs; pos < fileSize; pos++) { for (pos = rodataOffs; pos < fileSize; pos++)
if (memcmp(str, (const char*)(fileData + pos), 16) == 0) { {
if (memcmp(str, (const char *)(fileData + pos), 16) == 0)
{
pos -= rodataOffs; pos -= rodataOffs;
break; break;
} }
} }
errPrintAddr = rodataAddr + pos - 1; errPrintAddr = rodataAddr + pos - 1;
printf("LE arg addr: %08lX\n", errPrintAddr); printf("LE arg addr: %08lX\n", errPrintAddr);
printkPos = findSeq((const char*)&errPrintAddr, 4, 0, DIR_FWD, -1); printkPos = findSeq((const char *)&errPrintAddr, 4, 0, DIR_FWD, -1);
if (printkPos == -1) { if (printkPos == -1)
{
errorMsg("printk pos not found!\n"); errorMsg("printk pos not found!\n");
} }
//double check if it's a MOV reg,VAL (where reg is EAX/ECX/EDX/EBX/ESP/EBP/ESI/EDI) // double check if it's a MOV reg,VAL (where reg is EAX/ECX/EDX/EBX/ESP/EBP/ESI/EDI)
printkPos -= 3; printkPos -= 3;
if (memcmp((const char*)fileData+printkPos, "\x48\xc7", 2) != 0) { if (memcmp((const char *)fileData + printkPos, "\x48\xc7", 2) != 0)
errorMsg("Expected MOV=>reg before printk error, got %02X %02X\n", fileData[printkPos], fileData[printkPos+1]); {
errorMsg("Expected MOV=>reg before printk error, got %02X %02X\n", fileData[printkPos], fileData[printkPos + 1]);
} }
if (fileData[printkPos+2] < 0xC0 || fileData[printkPos+2] > 0xC7) { if (fileData[printkPos + 2] < 0xC0 || fileData[printkPos + 2] > 0xC7)
errorMsg("Expected MOV w/reg operand [C0-C7], got %02X\n", fileData[printkPos+2]); {
errorMsg("Expected MOV w/reg operand [C0-C7], got %02X\n", fileData[printkPos + 2]);
} }
printf("Found printk MOV @ %08lX\n", printkPos); printf("Found printk MOV @ %08lX\n", printkPos);
//now we should seek a reasonable amount (say, up to 32 bytes) for a sequence of CALL x => TEST EAX,EAX => JZ // now we should seek a reasonable amount (say, up to 32 bytes) for a sequence of CALL x => TEST EAX,EAX => JZ
testPos = findSeq("\x85\xc0", 2, printkPos, DIR_RWD, 32); testPos = findSeq("\x85\xc0", 2, printkPos, DIR_RWD, 32);
if (testPos == -1) { if (testPos == -1)
{
errorMsg("Failed to find TEST eax,eax\n"); errorMsg("Failed to find TEST eax,eax\n");
} }
printf("Found TEST eax,eax @ %08lX\n", testPos); printf("Found TEST eax,eax @ %08lX\n", testPos);
jzPos = testPos + 2; jzPos = testPos + 2;
if (fileData[jzPos] != 0x74) { if (fileData[jzPos] != 0x74)
{
errorMsg("Failed to find JZ\n"); errorMsg("Failed to find JZ\n");
} }
printf("OK - patching %02X%02X (JZ) to %02X%02X (JMP) @ %08lX\n", printf("OK - patching %02X%02X (JZ) to %02X%02X (JMP) @ %08lX\n",
fileData[jzPos], fileData[jzPos+1], 0xEB, fileData[jzPos+1], jzPos); fileData[jzPos], fileData[jzPos + 1], 0xEB, fileData[jzPos + 1], jzPos);
fileData[jzPos] = 0xEB; fileData[jzPos] = 0xEB;
} }
/*****************************************************************************/ /*****************************************************************************/
void patchCmosWrite() { void patchCmosWrite()
{
uint64_t pos, errPrintAddr; uint64_t pos, errPrintAddr;
uint64_t pr_errPos, testPos, callPos; uint64_t pr_errPos, testPos, callPos;
const char str[] = "3smpboot: %s: this boot have memory training"; const char str[] = "3smpboot: %s: this boot have memory training";
printf("Patching call to rtc_cmos_write.\n"); printf("Patching call to rtc_cmos_write.\n");
for (pos = rodataOffs; pos < fileSize; pos++) { for (pos = rodataOffs; pos < fileSize; pos++)
if (memcmp(str, (const char*)(fileData + pos), 16) == 0) { {
if (memcmp(str, (const char *)(fileData + pos), 16) == 0)
{
pos -= rodataOffs; pos -= rodataOffs;
break; break;
} }
} }
errPrintAddr = rodataAddr + pos - 1; errPrintAddr = rodataAddr + pos - 1;
printf("LE arg addr: %08lX\n", errPrintAddr); printf("LE arg addr: %08lX\n", errPrintAddr);
pr_errPos = findSeq((const char*)&errPrintAddr, 4, 0, DIR_FWD, -1); pr_errPos = findSeq((const char *)&errPrintAddr, 4, 0, DIR_FWD, -1);
if (pr_errPos == -1) { if (pr_errPos == -1)
{
printf("pr_err pos not found - ignoring.\n"); // Some kernels do not have the call, exit without error printf("pr_err pos not found - ignoring.\n"); // Some kernels do not have the call, exit without error
return; return;
} }
//double check if it's a MOV reg,VAL (where reg is EAX/ECX/EDX/EBX/ESP/EBP/ESI/EDI) // double check if it's a MOV reg,VAL (where reg is EAX/ECX/EDX/EBX/ESP/EBP/ESI/EDI)
pr_errPos -= 3; pr_errPos -= 3;
if (memcmp((const char*)fileData+pr_errPos, "\x48\xc7", 2) != 0) { if (memcmp((const char *)fileData + pr_errPos, "\x48\xc7", 2) != 0)
errorMsg("Expected MOV=>reg before pr_err error, got %02X %02X\n", fileData[pr_errPos], fileData[pr_errPos+1]); {
errorMsg("Expected MOV=>reg before pr_err error, got %02X %02X\n", fileData[pr_errPos], fileData[pr_errPos + 1]);
} }
if (fileData[pr_errPos+2] < 0xC0 || fileData[pr_errPos+2] > 0xC7) { if (fileData[pr_errPos + 2] < 0xC0 || fileData[pr_errPos + 2] > 0xC7)
errorMsg("Expected MOV w/reg operand [C0-C7], got %02X\n", fileData[pr_errPos+2]); {
errorMsg("Expected MOV w/reg operand [C0-C7], got %02X\n", fileData[pr_errPos + 2]);
} }
printf("Found pr_err MOV @ %08lX\n", pr_errPos); printf("Found pr_err MOV @ %08lX\n", pr_errPos);
// now we should seek a reasonable amount (say, up to 64 bytes) for a sequence of // now we should seek a reasonable amount (say, up to 64 bytes) for a sequence of
// MOV ESI, 0x48 => MOV EDI, 0xFF => MOV EBX, EAX // MOV ESI, 0x48 => MOV EDI, 0xFF => MOV EBX, EAX
testPos = findSeq("\xBE\x48\x00\x00\x00\xBF\xFF\x00\x00\x00\x89\xC3", 12, pr_errPos, DIR_RWD, 64); testPos = findSeq("\xBE\x48\x00\x00\x00\xBF\xFF\x00\x00\x00\x89\xC3", 12, pr_errPos, DIR_RWD, 64);
if (testPos == -1) { if (testPos == -1)
{
printf("Failed to find MOV ESI, 0x48 => MOV EDI, 0xFF => MOV EBX, EAX\n"); printf("Failed to find MOV ESI, 0x48 => MOV EDI, 0xFF => MOV EBX, EAX\n");
return; return;
} }
printf("Found MOV ESI, 0x48 => MOV EDI, 0xFF => MOV EBX, EAX @ %08lX\n", testPos); printf("Found MOV ESI, 0x48 => MOV EDI, 0xFF => MOV EBX, EAX @ %08lX\n", testPos);
callPos = testPos + 12; callPos = testPos + 12;
if (fileData[callPos] != 0xE8) { if (fileData[callPos] != 0xE8)
{
errorMsg("Failed to find CALL\n"); errorMsg("Failed to find CALL\n");
} }
printf("OK - patching %02X (CALL) to 0x90.. (NOPs) @ %08lX\n", printf("OK - patching %02X (CALL) to 0x90.. (NOPs) @ %08lX\n",
fileData[callPos], callPos); fileData[callPos], callPos);
for(uint64_t i = 0; i < 5; i++) for (uint64_t i = 0; i < 5; i++)
fileData[callPos+i] = 0x90; fileData[callPos + i] = 0x90;
} }
/*****************************************************************************/ /*****************************************************************************/
int main(int argc, char *argv[]) { int main(int argc, char *argv[])
{
struct stat fileInf; struct stat fileInf;
Elf_Scn *section; Elf_Scn *section;
GElf_Shdr sectionHeader; GElf_Shdr sectionHeader;
@ -311,29 +357,42 @@ int main(int argc, char *argv[]) {
char *fileIn = NULL, *fileOut = NULL; char *fileIn = NULL, *fileOut = NULL;
int onlyBoot = 0, onlyRD = 0, onlyCMOS = 0, c; int onlyBoot = 0, onlyRD = 0, onlyCMOS = 0, c;
if (argc < 3) { if (argc < 3)
{
errorMsg("Use: kpatch (option) <vmlinux> <output>\nOptions:\n -b Only bootparams\n -r Only ramdisk\n -c Only CMOS"); errorMsg("Use: kpatch (option) <vmlinux> <output>\nOptions:\n -b Only bootparams\n -r Only ramdisk\n -c Only CMOS");
} }
c = 1; c = 1;
while (c < argc) { while (c < argc)
if (strcmp(argv[c], "-b") == 0) { {
if (strcmp(argv[c], "-b") == 0)
{
onlyBoot = 1; onlyBoot = 1;
} else if (strcmp(argv[c], "-r") == 0) { }
else if (strcmp(argv[c], "-r") == 0)
{
onlyRD = 1; onlyRD = 1;
} else if (strcmp(argv[c], "-c") == 0) { }
else if (strcmp(argv[c], "-c") == 0)
{
onlyCMOS = 1; onlyCMOS = 1;
} else if (fileIn == NULL) { }
else if (fileIn == NULL)
{
fileIn = argv[c]; fileIn = argv[c];
} else { }
else
{
fileOut = argv[c]; fileOut = argv[c];
break; break;
} }
++c; ++c;
} }
if (NULL == fileIn) { if (NULL == fileIn)
{
errorMsg("Please give a input filename"); errorMsg("Please give a input filename");
} }
if (NULL == fileOut) { if (NULL == fileOut)
{
errorMsg("Please give a output filename"); errorMsg("Please give a output filename");
} }
@ -348,7 +407,8 @@ int main(int argc, char *argv[]) {
if (gelf_getehdr(elfHandle, &elfExecHeader) == NULL) if (gelf_getehdr(elfHandle, &elfExecHeader) == NULL)
elfErrno(); elfErrno();
switch(elf_kind(elfHandle)) { switch (elf_kind(elfHandle))
{
case ELF_K_NUM: case ELF_K_NUM:
case ELF_K_NONE: case ELF_K_NONE:
errorMsg("file type unknown\n"); errorMsg("file type unknown\n");
@ -364,14 +424,18 @@ int main(int argc, char *argv[]) {
} }
section = NULL; section = NULL;
while ((section = elf_nextscn(elfHandle, section)) != NULL) { while ((section = elf_nextscn(elfHandle, section)) != NULL)
{
if (gelf_getshdr(section, &sectionHeader) != &sectionHeader) if (gelf_getshdr(section, &sectionHeader) != &sectionHeader)
elfErrno(); elfErrno();
if ((sectionName = elf_strptr(elfHandle, elfExecHeader.e_shstrndx, sectionHeader.sh_name)) == NULL) if ((sectionName = elf_strptr(elfHandle, elfExecHeader.e_shstrndx, sectionHeader.sh_name)) == NULL)
elfErrno(); elfErrno();
if (strcmp(sectionName, ".init.text") == 0) { if (strcmp(sectionName, ".init.text") == 0)
{
initTextOffs = sectionHeader.sh_offset; initTextOffs = sectionHeader.sh_offset;
} else if (strcmp(sectionName, ".rodata") == 0) { }
else if (strcmp(sectionName, ".rodata") == 0)
{
rodataAddr = sectionHeader.sh_addr & 0xFFFFFFFF; rodataAddr = sectionHeader.sh_addr & 0xFFFFFFFF;
rodataOffs = sectionHeader.sh_offset; rodataOffs = sectionHeader.sh_offset;
} }
@ -384,7 +448,8 @@ int main(int argc, char *argv[]) {
fileSize = fileInf.st_size; fileSize = fileInf.st_size;
fileData = malloc(fileSize); fileData = malloc(fileSize);
if (fileSize != read(fd, fileData, fileSize)) { if (fileSize != read(fd, fileData, fileSize))
{
errorNum(); errorNum();
} }
close(fd); close(fd);
@ -392,25 +457,33 @@ int main(int argc, char *argv[]) {
printf("Found .init.text offset @ %lX\n", initTextOffs); printf("Found .init.text offset @ %lX\n", initTextOffs);
printf("Found .rodata address @ %lX\n", rodataAddr); printf("Found .rodata address @ %lX\n", rodataAddr);
printf("Found .rodata offset @ %lX\n", rodataOffs); printf("Found .rodata offset @ %lX\n", rodataOffs);
if (onlyBoot == 0 && onlyCMOS == 0 && onlyRD == 0) { if (onlyBoot == 0 && onlyCMOS == 0 && onlyRD == 0)
{
patchBootParams(); patchBootParams();
patchRamdiskCheck(); patchRamdiskCheck();
patchCmosWrite(); patchCmosWrite();
} else { }
if (onlyBoot == 1) { else
{
if (onlyBoot == 1)
{
patchBootParams(); patchBootParams();
} }
if (onlyRD == 1) { if (onlyRD == 1)
{
patchRamdiskCheck(); patchRamdiskCheck();
} }
if (onlyCMOS == 1) { if (onlyCMOS == 1)
{
patchCmosWrite(); patchCmosWrite();
} }
} }
if ((fd = open(fileOut, O_WRONLY | O_CREAT, 0644)) == -1) { if ((fd = open(fileOut, O_WRONLY | O_CREAT, 0644)) == -1)
{
errorNum(); errorNum();
} }
if (fileSize != write(fd, fileData, fileSize)) { if (fileSize != write(fd, fileData, fileSize))
{
errorNum(); errorNum();
} }
close(fd); close(fd);

View File

@ -6,15 +6,13 @@
# See /LICENSE for more information. # See /LICENSE for more information.
# #
# Convert po2mo # Convert po2mo
# $1 path # $1 path
function convertpo2mo() { function convertpo2mo() {
echo "Convert po2mo begin" echo "Convert po2mo begin"
local DEST_PATH="${1:-lang}" local DEST_PATH="${1:-lang}"
if [ `find ${DEST_PATH}/ -name "*.po" | wc -l` -gt 0 ]; then if [ $(find ${DEST_PATH}/ -name "*.po" | wc -l) -gt 0 ]; then
for P in `ls ${DEST_PATH}/*.po` for P in $(ls ${DEST_PATH}/*.po); do
do
# Use msgfmt command to compile the .po file into a binary .mo file # Use msgfmt command to compile the .po file into a binary .mo file
echo "msgfmt ${P} to ${P/.po/.mo}" echo "msgfmt ${P} to ${P/.po/.mo}"
msgfmt ${P} -o ${P/.po/.mo} msgfmt ${P} -o ${P/.po/.mo}
@ -23,19 +21,19 @@ function convertpo2mo() {
echo "Convert po2mo end" echo "Convert po2mo end"
} }
# Get extractor # Get extractor
# $1 path # $1 path
function getExtractor(){ function getExtractor() {
echo "Getting syno extractor begin" echo "Getting syno extractor begin"
local DEST_PATH="${1:-extractor}" local DEST_PATH="${1:-extractor}"
local CACHE_DIR="/tmp/pat" local CACHE_DIR="/tmp/pat"
rm -rf "${CACHE_DIR}"; mkdir -p "${CACHE_DIR}" rm -rf "${CACHE_DIR}"
mkdir -p "${CACHE_DIR}"
# Download pat file # Download pat file
# global.synologydownload.com, global.download.synology.com, cndl.synology.cn # global.synologydownload.com, global.download.synology.com, cndl.synology.cn
local PAT_URL="https://global.synologydownload.com/download/DSM/release/7.0.1/42218/DSM_DS3622xs%2B_42218.pat" local PAT_URL="https://global.synologydownload.com/download/DSM/release/7.0.1/42218/DSM_DS3622xs%2B_42218.pat"
local PAT_FILE="DSM_DS3622xs+_42218.pat" local PAT_FILE="DSM_DS3622xs+_42218.pat"
local STATUS=`curl -# -w "%{http_code}" -L "${PAT_URL}" -o "${CACHE_DIR}/${PAT_FILE}"` local STATUS=$(curl -# -w "%{http_code}" -L "${PAT_URL}" -o "${CACHE_DIR}/${PAT_FILE}")
if [ $? -ne 0 -o ${STATUS} -ne 200 ]; then if [ $? -ne 0 -o ${STATUS} -ne 200 ]; then
echo "[E] DSM_DS3622xs%2B_42218.pat download error!" echo "[E] DSM_DS3622xs%2B_42218.pat download error!"
rm -rf ${CACHE_DIR} rm -rf ${CACHE_DIR}
@ -49,9 +47,13 @@ function getExtractor(){
rm -rf ${CACHE_DIR} rm -rf ${CACHE_DIR}
exit 1 exit 1
fi fi
(cd "${CACHE_DIR}/ramdisk"; xz -dc < rd.gz | cpio -idm) >/dev/null 2>&1 || true (
cd "${CACHE_DIR}/ramdisk"
xz -dc <rd.gz | cpio -idm
) >/dev/null 2>&1 || true
rm -rf "${DEST_PATH}"; mkdir -p "${DEST_PATH}" rm -rf "${DEST_PATH}"
mkdir -p "${DEST_PATH}"
# Copy only necessary files # Copy only necessary files
for f in libcurl.so.4 libmbedcrypto.so.5 libmbedtls.so.13 libmbedx509.so.1 libmsgpackc.so.2 libsodium.so libsynocodesign-ng-virtual-junior-wins.so.7; do for f in libcurl.so.4 libmbedcrypto.so.5 libmbedtls.so.13 libmbedx509.so.1 libmsgpackc.so.2 libsodium.so libsynocodesign-ng-virtual-junior-wins.so.7; do
@ -64,7 +66,6 @@ function getExtractor(){
echo "Getting syno extractor end" echo "Getting syno extractor end"
} }
# Get latest LKMs # Get latest LKMs
# $1 path # $1 path
function getLKMs() { function getLKMs() {
@ -72,18 +73,18 @@ function getLKMs() {
local DEST_PATH="${1:-lkms}" local DEST_PATH="${1:-lkms}"
local CACHE_FILE="/tmp/rp-lkms.zip" local CACHE_FILE="/tmp/rp-lkms.zip"
rm -f "${CACHE_FILE}" rm -f "${CACHE_FILE}"
TAG=`curl -s "https://api.github.com/repos/wjz304/redpill-lkm/releases/latest" | grep -oP '"tag_name": "\K(.*)(?=")'` TAG=$(curl -s "https://api.github.com/repos/wjz304/redpill-lkm/releases/latest" | grep -oP '"tag_name": "\K(.*)(?=")')
STATUS=`curl -w "%{http_code}" -L "https://github.com/wjz304/redpill-lkm/releases/download/${TAG}/rp-lkms.zip" -o "${CACHE_FILE}"` STATUS=$(curl -w "%{http_code}" -L "https://github.com/wjz304/redpill-lkm/releases/download/${TAG}/rp-lkms.zip" -o "${CACHE_FILE}")
echo "TAG=${TAG}; Status=${STATUS}" echo "TAG=${TAG}; Status=${STATUS}"
[ ${STATUS} -ne 200 ] && exit 1 [ ${STATUS} -ne 200 ] && exit 1
# Unzip LKMs # Unzip LKMs
rm -rf "${DEST_PATH}"; mkdir -p "${DEST_PATH}" rm -rf "${DEST_PATH}"
mkdir -p "${DEST_PATH}"
unzip "${CACHE_FILE}" -d "${DEST_PATH}" unzip "${CACHE_FILE}" -d "${DEST_PATH}"
rm -f "${CACHE_FILE}" rm -f "${CACHE_FILE}"
echo "Getting LKMs end" echo "Getting LKMs end"
} }
# Get latest addons and install its # Get latest addons and install its
# $1 path # $1 path
function getAddons() { function getAddons() {
@ -91,18 +92,20 @@ function getAddons() {
local DEST_PATH="${1:-addons}" local DEST_PATH="${1:-addons}"
local CACHE_DIR="/tmp/addons" local CACHE_DIR="/tmp/addons"
local CACHE_FILE="/tmp/addons.zip" local CACHE_FILE="/tmp/addons.zip"
TAG=`curl -s https://api.github.com/repos/wjz304/arpl-addons/releases/latest | grep -oP '"tag_name": "\K(.*)(?=")'` TAG=$(curl -s https://api.github.com/repos/wjz304/arpl-addons/releases/latest | grep -oP '"tag_name": "\K(.*)(?=")')
STATUS=`curl -w "%{http_code}" -L "https://github.com/wjz304/arpl-addons/releases/download/${TAG}/addons.zip" -o "${CACHE_FILE}"` STATUS=$(curl -w "%{http_code}" -L "https://github.com/wjz304/arpl-addons/releases/download/${TAG}/addons.zip" -o "${CACHE_FILE}")
echo "TAG=${TAG}; Status=${STATUS}" echo "TAG=${TAG}; Status=${STATUS}"
[ ${STATUS} -ne 200 ] && exit 1 [ ${STATUS} -ne 200 ] && exit 1
rm -rf "${DEST_PATH}"; mkdir -p "${DEST_PATH}" rm -rf "${DEST_PATH}"
mkdir -p "${DEST_PATH}"
# Install Addons # Install Addons
rm -rf "${CACHE_DIR}"; mkdir -p "${CACHE_DIR}" rm -rf "${CACHE_DIR}"
mkdir -p "${CACHE_DIR}"
unzip "${CACHE_FILE}" -d "${CACHE_DIR}" unzip "${CACHE_FILE}" -d "${CACHE_DIR}"
echo "Installing addons to ${DEST_PATH}" echo "Installing addons to ${DEST_PATH}"
[ -f /tmp/addons/VERSION ] && cp -f /tmp/addons/VERSION ${DEST_PATH}/ [ -f /tmp/addons/VERSION ] && cp -f /tmp/addons/VERSION ${DEST_PATH}/
for PKG in `ls ${CACHE_DIR}/*.addon`; do for PKG in $(ls ${CACHE_DIR}/*.addon); do
ADDON=`basename "${PKG}" .addon` ADDON=$(basename "${PKG}" .addon)
mkdir -p "${DEST_PATH}/${ADDON}" mkdir -p "${DEST_PATH}/${ADDON}"
echo "Extracting ${PKG} to ${DEST_PATH}/${ADDON}" echo "Extracting ${PKG} to ${DEST_PATH}/${ADDON}"
tar -xaf "${PKG}" -C "${DEST_PATH}/${ADDON}" tar -xaf "${PKG}" -C "${DEST_PATH}/${ADDON}"
@ -110,7 +113,6 @@ function getAddons() {
echo "Getting Addons end" echo "Getting Addons end"
} }
# Get latest modules # Get latest modules
# $1 path # $1 path
function getModules() { function getModules() {
@ -118,27 +120,14 @@ function getModules() {
local DEST_PATH="${1:-addons}" local DEST_PATH="${1:-addons}"
local CACHE_FILE="/tmp/modules.zip" local CACHE_FILE="/tmp/modules.zip"
rm -f "${CACHE_FILE}" rm -f "${CACHE_FILE}"
TAG=`curl -s https://api.github.com/repos/wjz304/arpl-modules/releases/latest | grep -oP '"tag_name": "\K(.*)(?=")'` TAG=$(curl -s https://api.github.com/repos/wjz304/arpl-modules/releases/latest | grep -oP '"tag_name": "\K(.*)(?=")')
STATUS=`curl -w "%{http_code}" -L "https://github.com/wjz304/arpl-modules/releases/download/${TAG}/modules.zip" -o "${CACHE_FILE}"` STATUS=$(curl -w "%{http_code}" -L "https://github.com/wjz304/arpl-modules/releases/download/${TAG}/modules.zip" -o "${CACHE_FILE}")
echo "TAG=${TAG}; Status=${STATUS}" echo "TAG=${TAG}; Status=${STATUS}"
[ ${STATUS} -ne 200 ] && exit 1 [ ${STATUS} -ne 200 ] && exit 1
# Unzip Modules # Unzip Modules
rm -rf "${DEST_PATH}"; mkdir -p "${DEST_PATH}" rm -rf "${DEST_PATH}"
mkdir -p "${DEST_PATH}"
unzip "${CACHE_FILE}" -d "${DEST_PATH}" unzip "${CACHE_FILE}" -d "${DEST_PATH}"
rm -f "${CACHE_FILE}" rm -f "${CACHE_FILE}"
echo "Getting Modules end" echo "Getting Modules end"
} }

View File

@ -6,7 +6,6 @@
# See /LICENSE for more information. # See /LICENSE for more information.
# #
GRUB=${1:-"grub-2.06"} GRUB=${1:-"grub-2.06"}
BIOS=${2:-"i386-pc i386-efi x86_64-efi"} BIOS=${2:-"i386-pc i386-efi x86_64-efi"}
@ -14,8 +13,7 @@ curl -#kLO https://ftp.gnu.org/gnu/grub/${GRUB}.tar.gz
tar -zxvf ${GRUB}.tar.gz tar -zxvf ${GRUB}.tar.gz
pushd ${GRUB} pushd ${GRUB}
for B in ${BIOS} for B in ${BIOS}; do
do
b=${B} b=${B}
b=(${b//-/ }) b=(${b//-/ })
echo "Make ${b[@]} ..." echo "Make ${b[@]} ..."
@ -29,13 +27,12 @@ do
done done
popd popd
rm -f grub.img rm -f grub.img
dd if=/dev/zero of=grub.img bs=1M seek=1024 count=0 dd if=/dev/zero of=grub.img bs=1M seek=1024 count=0
echo -e "n\np\n1\n\n+50M\nn\np\n2\n\n+50M\nn\np\n3\n\n\na\n1\nw\nq\n" | fdisk grub.img echo -e "n\np\n1\n\n+50M\nn\np\n2\n\n+50M\nn\np\n3\n\n\na\n1\nw\nq\n" | fdisk grub.img
fdisk -l grub.img fdisk -l grub.img
LOOPX=`sudo losetup -f` LOOPX=$(sudo losetup -f)
sudo losetup -P ${LOOPX} grub.img sudo losetup -P ${LOOPX} grub.img
sudo mkdosfs -F32 -n ARPL1 ${LOOPX}p1 sudo mkdosfs -F32 -n ARPL1 ${LOOPX}p1
sudo mkfs.ext2 -F -L ARPL2 ${LOOPX}p2 sudo mkfs.ext2 -F -L ARPL2 ${LOOPX}p2
@ -47,13 +44,12 @@ sudo mount ${LOOPX}p1 ARPL1
sudo mkdir -p ARPL1/EFI sudo mkdir -p ARPL1/EFI
sudo mkdir -p ARPL1/boot/grub sudo mkdir -p ARPL1/boot/grub
cat > device.map <<EOF cat >device.map <<EOF
(hd0) ${LOOPX} (hd0) ${LOOPX}
EOF EOF
sudo mv device.map ARPL1/boot/grub/device.map sudo mv device.map ARPL1/boot/grub/device.map
for B in ${BIOS} for B in ${BIOS}; do
do
args="" args=""
args+=" ${LOOPX} --target=${B} --no-floppy --recheck --grub-mkdevicemap=ARPL1/boot/grub/device.map --boot-directory=ARPL1/boot" args+=" ${LOOPX} --target=${B} --no-floppy --recheck --grub-mkdevicemap=ARPL1/boot/grub/device.map --boot-directory=ARPL1/boot"
if [[ "${B}" == *"efi" ]]; then if [[ "${B}" == *"efi" ]]; then

View File

@ -9,7 +9,10 @@ if loaderIsConfigured; then
if [ -f "${ORI_RDGZ_FILE}" ]; then if [ -f "${ORI_RDGZ_FILE}" ]; then
rm -rf "${RAMDISK_PATH}" rm -rf "${RAMDISK_PATH}"
mkdir -p "${RAMDISK_PATH}" mkdir -p "${RAMDISK_PATH}"
(cd "${RAMDISK_PATH}"; xz -dc <"${ORI_RDGZ_FILE}" | cpio -idm) >/dev/null 2>&1 (
cd "${RAMDISK_PATH}"
xz -dc <"${ORI_RDGZ_FILE}" | cpio -idm
) >/dev/null 2>&1
. "${RAMDISK_PATH}/etc/VERSION" . "${RAMDISK_PATH}/etc/VERSION"
[ -n "$(readConfigKey "build" "${USER_CONFIG_FILE}")" ] && deleteConfigKey "build" "${USER_CONFIG_FILE}" [ -n "$(readConfigKey "build" "${USER_CONFIG_FILE}")" ] && deleteConfigKey "build" "${USER_CONFIG_FILE}"
[ -n "$(readConfigKey "smallfixnumber" "${USER_CONFIG_FILE}")" ] && deleteConfigKey "smallfixnumber" "${USER_CONFIG_FILE}" [ -n "$(readConfigKey "smallfixnumber" "${USER_CONFIG_FILE}")" ] && deleteConfigKey "smallfixnumber" "${USER_CONFIG_FILE}"