Quantcast
Channel: Raspberry Pi Forums
Viewing all articles
Browse latest Browse all 5044

Troubleshooting • Integrating the "C" script into initramfs

$
0
0
I was recently able to create my initramfs.img and run the following code in it:

Code:

#!/bin/shecho "initramfs custom script activate!"echo "Checking system hardware ID..."sleep 10mkdir -p /proc /sys /dev /new_rootHW_INFO_FILE="/new_root/etc/hw_info"/bin/busybox mount -t proc none /proc/bin/busybox mount -t sysfs none /sys/bin/busybox mount -t devtmpfs none /devHW_ID=$(awk -F ': ' '/Serial/ {print $2}' /proc/cpuinfo)/bin/busybox mount -o ro /dev/mmcblk0p2 /new_root || {   echo "ERROR: Failed to mount root filesystem!"   exec /bin/busybox halt}if [ ! -f "$HW_INFO_FILE" ]; then   echo "First boot detected. Saving hardware ID..."   mkdir -p $(dirname "$HW_INFO_FILE")    echo "$HW_ID" > "$HW_INFO_FILE"else   SAVED_HW_ID=$(cat "$HW_INFO_FILE")   if [ "$HW_ID" != "$SAVED_HW_ID" ]; then       echo "ERROR: Hardware mismatch detected!"       echo "This system was installed on different hardware."       echo "Stopping boot process."       exec /bin/busybox halt   fifiecho "Hardware check passed. Continuing boot..."/bin/busybox mount -o remount,rw /new_rootexec /bin/busybox switch_root /new_root /sbin/init || {   echo "ERROR: switch_root failed!"   exec /bin/busybox sh}
The idea is that I wanted to check certain data of the device on which the code is running and if everything matches, the system starts and if not, we don't. Plus, remembering the native device at the first launch of the system or script.
I wanted to rewrite this code in C and make it run through the main init. I got the following:

Code:

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/reboot.h>#include <sys/mount.h>#include <fcntl.h>#define HW_INFO_FILE "/new_root/etc/hw_info"#define REBOOT_DELAY 5 void infinite_reboot() {    printf("ERROR: Hardware mismatch detected! Rebooting...\n");    sync();    sleep(REBOOT_DELAY);    reboot(RB_AUTOBOOT);}void read_hw_id(char *buffer, size_t size) {    FILE *cpuinfo = fopen("/proc/cpuinfo", "r");    if (!cpuinfo) {        perror("Failed to open /proc/cpuinfo");        infinite_reboot();    }    while (fgets(buffer, size, cpuinfo)) {        if (strncmp(buffer, "Serial", 6) == 0) {            char *id = strchr(buffer, ':');            if (id) {                strncpy(buffer, id + 2, size);                buffer[strcspn(buffer, "\n")] = 0;             }            break;        }    }    fclose(cpuinfo);}int main() {    printf("initramfs custom C program starting...\n");    mount("proc", "/proc", "proc", 0, NULL);    mount("sysfs", "/sys", "sysfs", 0, NULL);    mount("devtmpfs", "/dev", "devtmpfs", 0, NULL);    char hw_id[32] = {0};    read_hw_id(hw_id, sizeof(hw_id));    if (mount("/dev/mmcblk0p2", "/new_root", "ext4", MS_RDONLY, NULL) < 0) {        perror("ERROR: Failed to mount root filesystem");        infinite_reboot();    }    FILE *file = fopen(HW_INFO_FILE, "r");    if (!file) {        printf("First boot detected. Saving hardware ID...\n");        file = fopen(HW_INFO_FILE, "w");        if (!file) {            perror("ERROR: Cannot write HW info");            infinite_reboot();        }        fprintf(file, "%s\n", hw_id);        fclose(file);    } else {        char saved_id[32] = {0};        fgets(saved_id, sizeof(saved_id), file);        fclose(file);        if (strcmp(hw_id, saved_id) != 0) {            infinite_reboot();        }    }    printf("Hardware check passed. Continuing boot...\n");    mount("/dev/mmcblk0p2", "/new_root", "ext4", MS_REMOUNT, NULL);    execl("/bin/busybox", "busybox", "switch_root", "/new_root", "/sbin/init", NULL);        perror("ERROR: switch_root failed");    infinite_reboot();    return 0;}
To package the script, I installed:

Code:

sudo apt install build-essential musl-tools busybox-static
And then packed it in:

Code:

musl-gcc -static -o init_checker init_checker.c
The result is something like:

Code:

init_checker: ELF 64-bit LSB executable, statically linked
Later, I moved my init_checker to a folder, the folder tree is something like this:

Code:

/home/admin/initramfsbin:- busybox- echo -> busybox- init_checker- sh -> busybox- sleep -> busyboxetcinitprocsbinsysusr:- bin- sbin
Then I write it in init:

Code:

echo ‘#!/bin/shexec /bin/init_checker' > initramfs/initchmod +x initramfs/init
And I pack it in img:

Code:

find . | cpio -o -H newc --owner root:root | gzip > ~/initramfs.img
The first time I got an error like ‘can't open splash no such file or directory.’ . Someone recommended me to set the following value for the parameter in cmdline.txt - ‘quiet splash=0’. And now the only thing I get is an error:

Code:

[ 2.904905] Failed to execute init (error -8)BusyBox v1.35.0 (Debian 1:1.35.0-4+b3) built-in shell (ash) Enter ‘help’ for a list of built-in commands./bin/sh: can't access tty: job control turned off
What could have gone wrong? Some of the recommendations I googled are checking whether the C script is packaged correctly and whether it is static and whether it matches the bit depth of the system, I checked it, it is packaged as 64-bit and I have the same system and everything indicates that it is static.

Statistics: Posted by Araders — Sun Feb 16, 2025 9:08 pm — Replies 0 — Views 29



Viewing all articles
Browse latest Browse all 5044

Trending Articles