|
|
@@ -1,3 +1,12 @@
|
|
|
+/*
|
|
|
+ * ArkOS Build System
|
|
|
+ * ------------------
|
|
|
+ * Orchestrates the full OS build pipeline.
|
|
|
+ * All paths are relative to the base directory passed as argv[1].
|
|
|
+ *
|
|
|
+ * Usage: build <arkos-base-dir>
|
|
|
+ */
|
|
|
+
|
|
|
#include "ark_parser.h"
|
|
|
#include <dirent.h>
|
|
|
#include <stdio.h>
|
|
|
@@ -6,191 +15,364 @@
|
|
|
#include <sys/stat.h>
|
|
|
#include <unistd.h>
|
|
|
|
|
|
-void run_cmd(const char *cmd) {
|
|
|
- printf("Executing: %s\n", cmd);
|
|
|
+/* ── Build step counter ─────────────────────────────────────────── */
|
|
|
+
|
|
|
+#define TOTAL_STEPS 14
|
|
|
+
|
|
|
+static int current_step = 0;
|
|
|
+
|
|
|
+static void step(const char *desc) {
|
|
|
+ current_step++;
|
|
|
+ printf("\n\033[1;36m[%2d/%d]\033[0m %s\n", current_step, TOTAL_STEPS, desc);
|
|
|
+}
|
|
|
+
|
|
|
+/* ── Helpers ────────────────────────────────────────────────────── */
|
|
|
+
|
|
|
+static void run(const char *cmd) {
|
|
|
+ printf(" \033[0;90m$ %s\033[0m\n", cmd);
|
|
|
int ret = system(cmd);
|
|
|
if (ret != 0) {
|
|
|
- printf("Command failed: %s\n", cmd);
|
|
|
+ fprintf(stderr, " \033[1;31m✗ Command failed (exit %d)\033[0m\n", ret);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-int main() {
|
|
|
- const char *base_dir = "/home/arkos/repo/arkos";
|
|
|
- const char *out_dir = "/home/arkos/repo/arkos/finished";
|
|
|
- const char *staging_sys = "/home/arkos/repo/arkos/out_staging/system";
|
|
|
- const char *staging_vend = "/home/arkos/repo/arkos/out_staging/vendor";
|
|
|
- const char *staging_boot = "/home/arkos/repo/arkos/out_staging/boot";
|
|
|
-
|
|
|
- printf("Cleaning up previous build directories...\n");
|
|
|
- run_cmd("chmod -R 777 /home/arkos/repo/arkos/out_staging 2>/dev/null || true");
|
|
|
- run_cmd("rm -rf /home/arkos/repo/arkos/finished /home/arkos/repo/arkos/out_staging");
|
|
|
- run_cmd("mkdir -p /home/arkos/repo/arkos/finished "
|
|
|
- "/home/arkos/repo/arkos/out_staging/system/frameworks "
|
|
|
- "/home/arkos/repo/arkos/out_staging/vendor "
|
|
|
- "/home/arkos/repo/arkos/out_staging/boot");
|
|
|
-
|
|
|
- printf("Phase 1: Frameworks Integration\n");
|
|
|
- DIR *d = opendir("/home/arkos/repo/arkos/frameworks");
|
|
|
- if (d) {
|
|
|
- struct dirent *dir;
|
|
|
- while ((dir = readdir(d)) != NULL) {
|
|
|
- if (strcmp(dir->d_name, ".") == 0 || strcmp(dir->d_name, "..") == 0)
|
|
|
- continue;
|
|
|
- if (strcmp(dir->d_name, "DRM") == 0 ||
|
|
|
- strcmp(dir->d_name, "SwiftUIFramework") == 0) {
|
|
|
- printf("Skipping explicitly excluded framework: %s\n", dir->d_name);
|
|
|
- continue;
|
|
|
+/* Join two path components. Caller must free. */
|
|
|
+static char *pjoin(const char *a, const char *b) {
|
|
|
+ size_t len = strlen(a) + 1 + strlen(b) + 1;
|
|
|
+ char *out = malloc(len);
|
|
|
+ snprintf(out, len, "%s/%s", a, b);
|
|
|
+ return out;
|
|
|
+}
|
|
|
+
|
|
|
+/* ── Main ───────────────────────────────────────────────────────── */
|
|
|
+
|
|
|
+int main(int argc, char *argv[]) {
|
|
|
+ if (argc < 2) {
|
|
|
+ fprintf(stderr, "Usage: %s <arkos-base-dir>\n", argv[0]);
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ const char *base = argv[1]; /* e.g. /home/user/repo/arkos */
|
|
|
+
|
|
|
+ /* Derive the repo root (one level up from base) */
|
|
|
+ char *repo = pjoin(base, "..");
|
|
|
+
|
|
|
+ /* Key directories */
|
|
|
+ char *out_dir = pjoin(base, "finished");
|
|
|
+ char *staging = pjoin(base, "out_staging");
|
|
|
+ char *staging_sys = pjoin(staging, "system");
|
|
|
+ char *staging_fw = pjoin(staging, "system/frameworks");
|
|
|
+ char *staging_vend = pjoin(staging, "vendor");
|
|
|
+ char *staging_boot = pjoin(staging, "boot");
|
|
|
+
|
|
|
+ /* Compiler for OS components (host gcc for now) */
|
|
|
+ const char *cc = "gcc";
|
|
|
+
|
|
|
+ /* Source directories */
|
|
|
+ char *fw_dir = pjoin(base, "frameworks");
|
|
|
+ char *boot_dir = pjoin(base, "boot");
|
|
|
+ char *vendor_dir = pjoin(base, "vendor");
|
|
|
+ char *system_dir = pjoin(base, "system");
|
|
|
+ char *kernel_dir = pjoin(base, "kernel");
|
|
|
+
|
|
|
+ printf("\n\033[1;35mArkOS Build System v2.0\033[0m\n");
|
|
|
+
|
|
|
+ /* ─── Step 1: Clean ─────────────────────────────────────────── */
|
|
|
+ step("Cleaning previous build");
|
|
|
+ {
|
|
|
+ char cmd[1024];
|
|
|
+ snprintf(cmd, sizeof(cmd),
|
|
|
+ "chmod -R 777 %s 2>/dev/null || true", staging);
|
|
|
+ run(cmd);
|
|
|
+ snprintf(cmd, sizeof(cmd), "rm -rf %s %s", out_dir, staging);
|
|
|
+ run(cmd);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* ─── Step 2: Create staging directories ────────────────────── */
|
|
|
+ step("Creating staging directories");
|
|
|
+ {
|
|
|
+ char cmd[1024];
|
|
|
+ snprintf(cmd, sizeof(cmd),
|
|
|
+ "mkdir -p %s %s %s %s",
|
|
|
+ out_dir, staging_fw, staging_vend, staging_boot);
|
|
|
+ run(cmd);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* ─── Step 3: Copy frameworks ───────────────────────────────── */
|
|
|
+ step("Integrating frameworks");
|
|
|
+ {
|
|
|
+ DIR *d = opendir(fw_dir);
|
|
|
+ if (d) {
|
|
|
+ struct dirent *ent;
|
|
|
+ while ((ent = readdir(d)) != NULL) {
|
|
|
+ if (ent->d_name[0] == '.')
|
|
|
+ continue;
|
|
|
+ /* Skip excluded frameworks */
|
|
|
+ if (strcmp(ent->d_name, "DRM") == 0 ||
|
|
|
+ strcmp(ent->d_name, "SwiftUIFramework") == 0) {
|
|
|
+ printf(" Skipping excluded framework: %s\n", ent->d_name);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ char cmd[1024];
|
|
|
+ snprintf(cmd, sizeof(cmd), "cp -r %s/%s %s/",
|
|
|
+ fw_dir, ent->d_name, staging_fw);
|
|
|
+ run(cmd);
|
|
|
}
|
|
|
- char cmd[512];
|
|
|
- snprintf(cmd, sizeof(cmd),
|
|
|
- "cp -r /home/arkos/repo/arkos/frameworks/%s "
|
|
|
- "/home/arkos/repo/arkos/out_staging/system/frameworks/",
|
|
|
- dir->d_name);
|
|
|
- run_cmd(cmd);
|
|
|
+ closedir(d);
|
|
|
}
|
|
|
- closedir(d);
|
|
|
}
|
|
|
|
|
|
- printf("Phase 2: Boot Folder Perfectification\n");
|
|
|
- d = opendir("/home/arkos/repo/arkos/boot");
|
|
|
- if (d) {
|
|
|
- struct dirent *dir;
|
|
|
- while ((dir = readdir(d)) != NULL) {
|
|
|
- if (strcmp(dir->d_name, ".") == 0 || strcmp(dir->d_name, "..") == 0)
|
|
|
- continue;
|
|
|
- if (strcmp(dir->d_name, "DRM") == 0) {
|
|
|
- printf("Skipping boot/DRM folder\n");
|
|
|
- continue;
|
|
|
+ /* ─── Step 4: Copy boot files ───────────────────────────────── */
|
|
|
+ step("Preparing boot files");
|
|
|
+ {
|
|
|
+ DIR *d = opendir(boot_dir);
|
|
|
+ if (d) {
|
|
|
+ struct dirent *ent;
|
|
|
+ while ((ent = readdir(d)) != NULL) {
|
|
|
+ if (ent->d_name[0] == '.')
|
|
|
+ continue;
|
|
|
+ if (strcmp(ent->d_name, "DRM") == 0) {
|
|
|
+ printf(" Skipping boot/DRM\n");
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ char cmd[1024];
|
|
|
+ snprintf(cmd, sizeof(cmd), "cp -r %s/%s %s/",
|
|
|
+ boot_dir, ent->d_name, staging_boot);
|
|
|
+ run(cmd);
|
|
|
}
|
|
|
- char cmd[512];
|
|
|
- snprintf(
|
|
|
- cmd, sizeof(cmd),
|
|
|
- "cp -r /home/arkos/repo/arkos/boot/%s /home/arkos/repo/arkos/out_staging/boot/",
|
|
|
- dir->d_name);
|
|
|
- run_cmd(cmd);
|
|
|
+ closedir(d);
|
|
|
}
|
|
|
- closedir(d);
|
|
|
}
|
|
|
|
|
|
- printf("Phase 3: Vendor Folder Preparation\n");
|
|
|
- run_cmd("cp -r /home/arkos/repo/arkos/vendor/* "
|
|
|
- "/home/arkos/repo/arkos/out_staging/vendor/ 2>/dev/null || true");
|
|
|
-
|
|
|
- printf("Phase 4: Kernel Config Verification\n");
|
|
|
- if (access("/home/arkos/repo/arkos/kernel/.config", F_OK) != -1) {
|
|
|
- printf("Kernel config found at /home/arkos/repo/arkos/kernel/.config. Kernel is "
|
|
|
- "prepared.\n");
|
|
|
- } else {
|
|
|
- printf("WARNING: Kernel .config not found!\n");
|
|
|
+ /* ─── Step 5: Copy vendor files ─────────────────────────────── */
|
|
|
+ step("Preparing vendor files");
|
|
|
+ {
|
|
|
+ char cmd[1024];
|
|
|
+ snprintf(cmd, sizeof(cmd),
|
|
|
+ "cp -r %s/* %s/ 2>/dev/null || true",
|
|
|
+ vendor_dir, staging_vend);
|
|
|
+ run(cmd);
|
|
|
}
|
|
|
|
|
|
- printf("Phase 5: Prebuilts Tagging\n");
|
|
|
- run_cmd("mkdir -p /home/arkos/repo/arkos/prebuilts");
|
|
|
- ArkConfig *prebuilts_ark =
|
|
|
- ark_parse("/home/arkos/repo/arkos/prebuilts/prebuilts.ark");
|
|
|
- d = opendir("/home/arkos/src");
|
|
|
- if (d) {
|
|
|
- struct dirent *dir;
|
|
|
- while ((dir = readdir(d)) != NULL) {
|
|
|
- char path[512];
|
|
|
- snprintf(path, sizeof(path), "/home/arkos/src/%s", dir->d_name);
|
|
|
- if (strstr(dir->d_name, "LLVM"))
|
|
|
- ark_set_global(prebuilts_ark, "LLVM", path);
|
|
|
- else if (strstr(dir->d_name, "Swift"))
|
|
|
- ark_set_global(prebuilts_ark, "Swift", path);
|
|
|
- else if (strstr(dir->d_name, "glibc"))
|
|
|
- ark_set_global(prebuilts_ark, "glibc", path);
|
|
|
- else if (strstr(dir->d_name, "linux-kernel"))
|
|
|
- ark_set_global(prebuilts_ark, "Kernel-Src", path);
|
|
|
+ /* ─── Step 6: Verify kernel config ──────────────────────────── */
|
|
|
+ step("Verifying kernel configuration");
|
|
|
+ {
|
|
|
+ char *kconfig = pjoin(kernel_dir, ".config");
|
|
|
+ if (access(kconfig, F_OK) != -1) {
|
|
|
+ printf(" \033[0;32m✓\033[0m Kernel .config found\n");
|
|
|
+ } else {
|
|
|
+ printf(" \033[1;33m⚠ WARNING:\033[0m Kernel .config not found!\n");
|
|
|
}
|
|
|
- closedir(d);
|
|
|
+ free(kconfig);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* ─── Step 7: Compile fb_helper.c ───────────────────────────── */
|
|
|
+ step("Compiling : system/fb_helper.c");
|
|
|
+ {
|
|
|
+ char cmd[1024];
|
|
|
+ snprintf(cmd, sizeof(cmd),
|
|
|
+ "%s -c %s/fb_helper.c -o %s/fb_helper.o",
|
|
|
+ cc, system_dir, staging);
|
|
|
+ run(cmd);
|
|
|
}
|
|
|
- ark_dump(prebuilts_ark, "/home/arkos/repo/arkos/prebuilts/prebuilts.ark");
|
|
|
- ark_free(prebuilts_ark);
|
|
|
- printf("Prebuilts tagged and mapped to "
|
|
|
- "/home/arkos/repo/arkos/prebuilts/prebuilts.ark\n");
|
|
|
-
|
|
|
- printf("Phase 6: Image Generation\n");
|
|
|
- run_cmd(
|
|
|
- "dd if=/dev/zero of=/home/arkos/repo/arkos/finished/sys.img bs=1M count=2048");
|
|
|
- run_cmd("mkfs.ext4 -d /home/arkos/repo/arkos/out_staging/system "
|
|
|
- "/home/arkos/repo/arkos/finished/sys.img");
|
|
|
-
|
|
|
- run_cmd(
|
|
|
- "dd if=/dev/zero of=/home/arkos/repo/arkos/finished/vend.img bs=1M count=100");
|
|
|
- run_cmd("mkfs.ext4 -d /home/arkos/repo/arkos/out_staging/vendor "
|
|
|
- "/home/arkos/repo/arkos/finished/vend.img");
|
|
|
-
|
|
|
- printf("Preparing Linux Kernel & Native Swift Initramfs...\n");
|
|
|
-
|
|
|
- // Compile fb_helper.c and Native Swift Initramfs executable
|
|
|
- run_cmd("gcc -c /home/arkos/repo/arkos/system/fb_helper.c -o /home/arkos/repo/arkos/system/fb_helper.o");
|
|
|
- run_cmd("swiftc -static-executable /home/arkos/repo/arkos/system/swift_splash.swift /home/arkos/repo/arkos/system/fb_helper.o -o /home/arkos/repo/arkos/system/swift_splash");
|
|
|
-
|
|
|
- // Parse the key for Verified Boot
|
|
|
- ArkConfig *securebuild_boot = ark_parse("/home/arkos/repo/arkos/vendor/verify/securebuild.ark");
|
|
|
+
|
|
|
+ /* ─── Step 8: Compile swift_splash.swift ────────────────────── */
|
|
|
+ step("Compiling : system/swift_splash.swift");
|
|
|
+ {
|
|
|
+ char cmd[1024];
|
|
|
+ snprintf(cmd, sizeof(cmd),
|
|
|
+ "swiftc -O -static-executable %s/swift_splash.swift %s/fb_helper.o "
|
|
|
+ "-o %s/swift_splash",
|
|
|
+ system_dir, staging, staging);
|
|
|
+ run(cmd);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* ─── Step 9: Sign swift_splash (Verified Boot) ─────────────── */
|
|
|
+ step("Signing swift_splash (Verified Boot)");
|
|
|
+ {
|
|
|
+ /* Parse the key */
|
|
|
+ char *securebuild_path = pjoin(vendor_dir, "verify/securebuild.ark");
|
|
|
+ ArkConfig *sbc = ark_parse(securebuild_path);
|
|
|
char ark_key[256] = "NO_KEY";
|
|
|
- for (int i = 0; i < securebuild_boot->standalone_count; i++) {
|
|
|
- if (strstr(securebuild_boot->standalone[i], "ARK-OS-") != NULL) {
|
|
|
- strncpy(ark_key, securebuild_boot->standalone[i], sizeof(ark_key)-1);
|
|
|
- break;
|
|
|
- }
|
|
|
+ for (int i = 0; i < sbc->standalone_count; i++) {
|
|
|
+ if (strstr(sbc->standalone[i], "ARK-OS-") != NULL) {
|
|
|
+ strncpy(ark_key, sbc->standalone[i], sizeof(ark_key) - 1);
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
- ark_free(securebuild_boot);
|
|
|
-
|
|
|
- // Run the signing script
|
|
|
- run_cmd("python3 /home/arkos/repo/arkos/vendor/verify/sign.py /home/arkos/repo/arkos/vendor/verify/securebuild.ark /home/arkos/repo/arkos/system/swift_splash /home/arkos/repo/arkos/system/signature.bin");
|
|
|
-
|
|
|
- // Compile C init wrapper with the SHA256 code and the key macro
|
|
|
- char init_cmd[1024];
|
|
|
- snprintf(init_cmd, sizeof(init_cmd), "gcc -static /home/arkos/repo/arkos/system/sha256.c /home/arkos/repo/arkos/system/init.c -DARK_KEY=\\\"%s\\\" -o /home/arkos/repo/arkos/system/init", ark_key);
|
|
|
- run_cmd(init_cmd);
|
|
|
-
|
|
|
- // Pack into initramfs with glibc libraries
|
|
|
- run_cmd("rm -rf /home/arkos/repo/arkos/out_staging/initramfs_ext && mkdir -p /home/arkos/repo/arkos/out_staging/initramfs_ext");
|
|
|
- run_cmd("cd /home/arkos/repo/arkos/out_staging/initramfs_ext && zcat /home/arkos/repo/arkos/boot/initramfs.img | cpio -id 2>/dev/null");
|
|
|
- run_cmd("cp /home/arkos/repo/arkos/system/init /home/arkos/repo/arkos/out_staging/initramfs_ext/init && chmod +x /home/arkos/repo/arkos/out_staging/initramfs_ext/init");
|
|
|
- run_cmd("cp /home/arkos/repo/arkos/system/swift_splash /home/arkos/repo/arkos/out_staging/initramfs_ext/swift_splash && chmod +x /home/arkos/repo/arkos/out_staging/initramfs_ext/swift_splash");
|
|
|
- run_cmd("cp /home/arkos/repo/arkos/system/signature.bin /home/arkos/repo/arkos/out_staging/initramfs_ext/signature.bin");
|
|
|
- run_cmd("cd /home/arkos/repo/arkos/out_staging/initramfs_ext && find . | cpio -H newc -o > /home/arkos/repo/arkos/finished/initramfs.img 2>/dev/null");
|
|
|
-
|
|
|
- // Assemble Stage 1 and Stage 2 Bootloader
|
|
|
- run_cmd("python3 /home/arkos/repo/arkos/boot/source/animationframes/generate_frames.py");
|
|
|
- run_cmd("nasm -f bin /home/arkos/repo/arkos/boot/source/bootloader.asm -o /home/arkos/repo/arkos/out_staging/bootloader.bin");
|
|
|
- run_cmd("nasm -f bin /home/arkos/repo/arkos/boot/source/stage2.asm -o /home/arkos/repo/arkos/out_staging/stage2.bin");
|
|
|
-
|
|
|
- // Construct the self-booting boot.img
|
|
|
- run_cmd("python3 /home/arkos/repo/tools/pack_boot.py");
|
|
|
-
|
|
|
- printf("Phase 7: Verify keys and generate avb.img\n");
|
|
|
- ArkConfig *securebuild =
|
|
|
- ark_parse("/home/arkos/repo/arkos/vendor/verify/securebuild.ark");
|
|
|
- int has_keys = 0;
|
|
|
- for (int i = 0; i < securebuild->standalone_count; i++) {
|
|
|
- if (strstr(securebuild->standalone[i], "ARK-OS-") != NULL) {
|
|
|
- has_keys = 1;
|
|
|
- break;
|
|
|
+ ark_free(sbc);
|
|
|
+
|
|
|
+ char cmd[1024];
|
|
|
+ snprintf(cmd, sizeof(cmd),
|
|
|
+ "python3 %s/verify/sign.py %s/verify/securebuild.ark "
|
|
|
+ "%s/swift_splash %s/signature.bin",
|
|
|
+ vendor_dir, vendor_dir, staging, staging);
|
|
|
+ run(cmd);
|
|
|
+
|
|
|
+ free(securebuild_path);
|
|
|
+
|
|
|
+ /* ─── Step 10: Compile init.c + vendor/verify/sha256.c ──── */
|
|
|
+ step("Compiling : system/init.c + vendor/verify/sha256.c");
|
|
|
+ {
|
|
|
+ char cmd2[1024];
|
|
|
+ snprintf(cmd2, sizeof(cmd2),
|
|
|
+ "%s -static %s/verify/sha256.c %s/init.c "
|
|
|
+ "-I%s/verify -DARK_KEY=\"\\\"%s\\\"\" -o %s/init",
|
|
|
+ cc, vendor_dir, system_dir, vendor_dir, ark_key, staging);
|
|
|
+ run(cmd2);
|
|
|
}
|
|
|
}
|
|
|
- if (has_keys) {
|
|
|
- printf("Found signing keys, generating avb.img\n");
|
|
|
- run_cmd(
|
|
|
- "dd if=/dev/zero of=/home/arkos/repo/arkos/finished/avb.img bs=1M count=1");
|
|
|
- } else {
|
|
|
- printf("No signing keys found, skipping avb.img\n");
|
|
|
+
|
|
|
+ /* ─── Step 11: Pack initramfs ───────────────────────────────── */
|
|
|
+ step("Packing initramfs");
|
|
|
+ {
|
|
|
+ char *initramfs_ext = pjoin(staging, "initramfs_ext");
|
|
|
+ char *base_initramfs = pjoin(boot_dir, "initramfs.img");
|
|
|
+
|
|
|
+ char cmd[2048];
|
|
|
+
|
|
|
+ /* Extract base initramfs */
|
|
|
+ snprintf(cmd, sizeof(cmd),
|
|
|
+ "rm -rf %s && mkdir -p %s", initramfs_ext, initramfs_ext);
|
|
|
+ run(cmd);
|
|
|
+
|
|
|
+ snprintf(cmd, sizeof(cmd),
|
|
|
+ "cd %s && zcat %s | cpio -id 2>/dev/null",
|
|
|
+ initramfs_ext, base_initramfs);
|
|
|
+ run(cmd);
|
|
|
+
|
|
|
+ /* Copy compiled binaries from staging into initramfs */
|
|
|
+ snprintf(cmd, sizeof(cmd),
|
|
|
+ "cp %s/init %s/init && chmod +x %s/init",
|
|
|
+ staging, initramfs_ext, initramfs_ext);
|
|
|
+ run(cmd);
|
|
|
+
|
|
|
+ snprintf(cmd, sizeof(cmd),
|
|
|
+ "cp %s/swift_splash %s/swift_splash && chmod +x %s/swift_splash",
|
|
|
+ staging, initramfs_ext, initramfs_ext);
|
|
|
+ run(cmd);
|
|
|
+
|
|
|
+ snprintf(cmd, sizeof(cmd),
|
|
|
+ "cp %s/signature.bin %s/signature.bin",
|
|
|
+ staging, initramfs_ext);
|
|
|
+ run(cmd);
|
|
|
+
|
|
|
+ /* Repack */
|
|
|
+ snprintf(cmd, sizeof(cmd),
|
|
|
+ "cd %s && find . | cpio -H newc -o > %s/initramfs.img 2>/dev/null",
|
|
|
+ initramfs_ext, out_dir);
|
|
|
+ run(cmd);
|
|
|
+
|
|
|
+ free(initramfs_ext);
|
|
|
+ free(base_initramfs);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* ─── Step 12: Assemble bootloader + stage2 ─────────────────── */
|
|
|
+ step("Assembling bootloader");
|
|
|
+ {
|
|
|
+ char cmd[1024];
|
|
|
+
|
|
|
+ /* Generate animation frames */
|
|
|
+ snprintf(cmd, sizeof(cmd),
|
|
|
+ "python3 %s/source/animationframes/generate_frames.py %s",
|
|
|
+ boot_dir, staging);
|
|
|
+ run(cmd);
|
|
|
+
|
|
|
+ snprintf(cmd, sizeof(cmd),
|
|
|
+ "nasm -f bin %s/source/bootloader.asm -o %s/bootloader.bin",
|
|
|
+ boot_dir, staging);
|
|
|
+ run(cmd);
|
|
|
+
|
|
|
+ snprintf(cmd, sizeof(cmd),
|
|
|
+ "nasm -f bin %s/source/stage2.asm -o %s/stage2.bin",
|
|
|
+ boot_dir, staging);
|
|
|
+ run(cmd);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* ─── Step 13: Generate boot.img ────────────────────────────── */
|
|
|
+ step("Generating boot.img");
|
|
|
+ {
|
|
|
+ char cmd[1024];
|
|
|
+ snprintf(cmd, sizeof(cmd),
|
|
|
+ "python3 %s/tools/pack_boot.py --base-dir %s",
|
|
|
+ repo, base);
|
|
|
+ run(cmd);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* ─── Step 14: Generate disk images ─────────────────────────── */
|
|
|
+ step("Generating disk images");
|
|
|
+ {
|
|
|
+ char cmd[1024];
|
|
|
+
|
|
|
+ /* sys.img */
|
|
|
+ snprintf(cmd, sizeof(cmd),
|
|
|
+ "dd if=/dev/zero of=%s/sys.img bs=1M count=2048 2>/dev/null",
|
|
|
+ out_dir);
|
|
|
+ run(cmd);
|
|
|
+ snprintf(cmd, sizeof(cmd),
|
|
|
+ "mkfs.ext4 -d %s %s/sys.img 2>/dev/null",
|
|
|
+ staging_sys, out_dir);
|
|
|
+ run(cmd);
|
|
|
+
|
|
|
+ /* vend.img */
|
|
|
+ snprintf(cmd, sizeof(cmd),
|
|
|
+ "dd if=/dev/zero of=%s/vend.img bs=1M count=100 2>/dev/null",
|
|
|
+ out_dir);
|
|
|
+ run(cmd);
|
|
|
+ snprintf(cmd, sizeof(cmd),
|
|
|
+ "mkfs.ext4 -d %s %s/vend.img 2>/dev/null",
|
|
|
+ staging_vend, out_dir);
|
|
|
+ run(cmd);
|
|
|
+
|
|
|
+ /* avb.img (Verified Boot) */
|
|
|
+ char *securebuild_path = pjoin(vendor_dir, "verify/securebuild.ark");
|
|
|
+ ArkConfig *sbc = ark_parse(securebuild_path);
|
|
|
+ int has_keys = 0;
|
|
|
+ for (int i = 0; i < sbc->standalone_count; i++) {
|
|
|
+ if (strstr(sbc->standalone[i], "ARK-OS-") != NULL) {
|
|
|
+ has_keys = 1;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (has_keys) {
|
|
|
+ printf(" \033[0;32m✓\033[0m Signing keys found, generating avb.img\n");
|
|
|
+ snprintf(cmd, sizeof(cmd),
|
|
|
+ "dd if=/dev/zero of=%s/avb.img bs=1M count=1 2>/dev/null",
|
|
|
+ out_dir);
|
|
|
+ run(cmd);
|
|
|
+ } else {
|
|
|
+ printf(" \033[1;33m⚠\033[0m No signing keys found, skipping avb.img\n");
|
|
|
+ }
|
|
|
+ ark_free(sbc);
|
|
|
+ free(securebuild_path);
|
|
|
+
|
|
|
+ /* vbmeta.img + dtbo.img */
|
|
|
+ snprintf(cmd, sizeof(cmd),
|
|
|
+ "dd if=/dev/zero of=%s/vbmeta.img bs=1M count=1 2>/dev/null",
|
|
|
+ out_dir);
|
|
|
+ run(cmd);
|
|
|
+ snprintf(cmd, sizeof(cmd),
|
|
|
+ "dd if=/dev/zero of=%s/dtbo.img bs=1M count=1 2>/dev/null",
|
|
|
+ out_dir);
|
|
|
+ run(cmd);
|
|
|
}
|
|
|
- ark_free(securebuild);
|
|
|
|
|
|
- printf("Phase 8: vbmeta and dtbo (extra)\n");
|
|
|
- run_cmd(
|
|
|
- "dd if=/dev/zero of=/home/arkos/repo/arkos/finished/vbmeta.img bs=1M count=1");
|
|
|
- run_cmd(
|
|
|
- "dd if=/dev/zero of=/home/arkos/repo/arkos/finished/dtbo.img bs=1M count=1");
|
|
|
+ printf("\n\033[1;32mBuild complete!\033[0m Run \033[1mmake run\033[0m to test.\n\n");
|
|
|
|
|
|
- printf("Phase 9: Zipping output\n");
|
|
|
- run_cmd("cd /home/arkos/repo/arkos && zip -r finished/ArkOS.zip finished/ > "
|
|
|
- "/dev/null");
|
|
|
+ /* Cleanup heap */
|
|
|
+ free(repo);
|
|
|
+ free(out_dir);
|
|
|
+ free(staging);
|
|
|
+ free(staging_sys);
|
|
|
+ free(staging_fw);
|
|
|
+ free(staging_vend);
|
|
|
+ free(staging_boot);
|
|
|
+ /* cc is a string literal, no free needed */
|
|
|
+ free(fw_dir);
|
|
|
+ free(boot_dir);
|
|
|
+ free(vendor_dir);
|
|
|
+ free(system_dir);
|
|
|
+ free(kernel_dir);
|
|
|
|
|
|
- printf("Build complete. Outputs are in %s\n", out_dir);
|
|
|
return 0;
|
|
|
}
|