Monorepo for Aesthetic.Computer aesthetic.computer
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

native: eMMC install target (Chromebooks + budget laptops)

Chromebooks boot off eMMC (/dev/mmcblk0), not NVMe — the install flow
only looked at /dev/nvme* + /dev/sda*, so install-to-disk silently
failed on Drawcia (Celeron N4500 Jasper Lake) and left a backup ROM
on the USB as the only sign anything happened.

Add /dev/mmcblk{0,1}p{1,2} everywhere the install flow probed for an
internal ESP:
- detect_boot_device() picks mmcblk0p1 when no NVMe is present.
- flashTargets array in js-bindings exposes "Internal (eMMC)" so the
OS panel's disk install action can target it.
- is_installed_on_hd() checks the eMMC ESP too.
- install_to_hd() probes mmcblk0/1 alongside nvme and sd* (eMMC
always internal, same priority as NVMe).
- Partition construction honors the "<name>p<N>" suffix for both NVMe
and mmcblk (name ends in a digit); get_parent_block() strips it
symmetrically.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

+37 -9
+21 -9
fedac/native/src/ac-native.c
··· 332 332 "/dev/sdd1", "/dev/sdd2", 333 333 "/dev/nvme0n1p1", "/dev/nvme0n1p2", 334 334 "/dev/nvme1n1p1", "/dev/nvme1n1p2", 335 + "/dev/mmcblk0p1", "/dev/mmcblk0p2", 336 + "/dev/mmcblk1p1", "/dev/mmcblk1p2", 335 337 NULL 336 338 }; 337 339 ··· 1151 1153 } 1152 1154 } 1153 1155 1154 - // Scan for internal (non-removable) block devices with partitions 1155 - // Try NVMe first (always internal), then SATA/USB 1156 + // Scan for internal (non-removable) block devices with partitions. 1157 + // NVMe first (always internal), then eMMC (always internal — common 1158 + // on Chromebooks + budget laptops), then SATA/USB last. 1156 1159 const char *part_candidates[] = { 1157 1160 "nvme0n1", "nvme1n1", // NVMe SSDs 1161 + "mmcblk0", "mmcblk1", // eMMC (Chromebooks, budget laptops) 1158 1162 "sda", "sdb", "sdc", "sdd", // SATA/USB 1159 1163 NULL 1160 1164 }; ··· 1175 1179 // Try partitions 1-8 1176 1180 for (int p = 1; p <= 8 && !installed; p++) { 1177 1181 char devpath[32]; 1178 - if (blk[0] == 'n') // NVMe: nvme0n1p1 1182 + // NVMe + eMMC use "p<N>" suffix (name ends in a digit); SATA 1183 + // just appends the number to the base name. 1184 + if (blk[0] == 'n' || strncmp(blk, "mmcblk", 6) == 0) 1179 1185 snprintf(devpath, sizeof(devpath), "/dev/%sp%d", blk, p); 1180 1186 else // SATA: sda1 1181 1187 snprintf(devpath, sizeof(devpath), "/dev/%s%d", blk, p); ··· 2067 2073 2068 2074 // Check if we booted from an installed (non-removable) disk 2069 2075 // by looking for ac-installed marker on an internal ESP 2070 - // Extract parent block device name from a partition path 2071 - // "nvme0n1p1" → "nvme0n1", "sda1" → "sda" 2076 + // Extract parent block device name from a partition path: 2077 + // "nvme0n1p1" → "nvme0n1" 2078 + // "mmcblk0p1" → "mmcblk0" 2079 + // "sda1" → "sda" 2080 + // NVMe and eMMC both use the "<dev>p<N>" partition-suffix scheme (because 2081 + // the parent name ends in a digit), so strip the trailing "pN" for both. 2072 2082 static void get_parent_block(const char *part, char *out, int out_sz) { 2073 2083 out[0] = 0; 2074 2084 int len = (int)strlen(part); 2075 2085 if (len >= out_sz) return; 2076 - // NVMe: strip trailing "pN" (e.g. nvme0n1p1 → nvme0n1) 2077 - if (strncmp(part, "nvme", 4) == 0) { 2078 - // Find last 'p' followed by digits 2079 - for (int i = len - 1; i > 4; i--) { 2086 + // NVMe / eMMC: strip trailing "pN" (e.g. nvme0n1p1 → nvme0n1, 2087 + // mmcblk0p1 → mmcblk0). 2088 + if (strncmp(part, "nvme", 4) == 0 || strncmp(part, "mmcblk", 6) == 0) { 2089 + int base_min = (part[0] == 'n') ? 4 : 6; 2090 + for (int i = len - 1; i > base_min; i--) { 2080 2091 if (part[i - 1] == 'p' && part[i] >= '0' && part[i] <= '9') { 2081 2092 memcpy(out, part, i - 1); 2082 2093 out[i - 1] = 0; ··· 2098 2109 mkdir("/tmp/chk", 0755); 2099 2110 const char *parts[] = { 2100 2111 "/dev/nvme0n1p1", "/dev/nvme0n1p2", 2112 + "/dev/mmcblk0p1", "/dev/mmcblk0p2", 2101 2113 "/dev/sda1", "/dev/sdb1", NULL 2102 2114 }; 2103 2115 for (int i = 0; parts[i]; i++) {
+16
fedac/native/src/js-bindings.c
··· 3769 3769 // Detect the EFI partition we booted from: 3770 3770 // - If /sys/block/sda/removable == 1 → USB → /dev/sda1 3771 3771 // - Else if /dev/nvme0n1p1 exists → NVMe internal → /dev/nvme0n1p1 3772 + // - Else if /dev/mmcblk0p1 exists → eMMC internal (Chromebooks) → /dev/mmcblk0p1 3772 3773 // - Fallback: /dev/sda1 3773 3774 static void detect_boot_device(char *out, size_t len) { 3774 3775 char removable[8] = {0}; ··· 3781 3782 if (access("/dev/nvme0n1p1", F_OK) == 0) { 3782 3783 snprintf(out, len, "/dev/nvme0n1p1"); 3783 3784 ac_log("[flash] boot device: NVMe (/dev/nvme0n1p1)"); 3785 + return; 3786 + } 3787 + if (access("/dev/mmcblk0p1", F_OK) == 0) { 3788 + snprintf(out, len, "/dev/mmcblk0p1"); 3789 + ac_log("[flash] boot device: eMMC (/dev/mmcblk0p1)"); 3784 3790 return; 3785 3791 } 3786 3792 // Fallback — try sda1 anyway ··· 5985 5991 JSValue t = JS_NewObject(ctx); 5986 5992 JS_SetPropertyStr(ctx, t, "device", JS_NewString(ctx, "/dev/nvme0n1p1")); 5987 5993 JS_SetPropertyStr(ctx, t, "label", JS_NewString(ctx, "Internal (NVMe)")); 5994 + JS_SetPropertyStr(ctx, t, "removable", JS_NewBool(ctx, 0)); 5995 + JS_SetPropertyUint32(ctx, targets, idx++, t); 5996 + } 5997 + // Check eMMC (/dev/mmcblk0p1) — Chromebooks + some budget laptops use 5998 + // eMMC instead of NVMe. Parent device is mmcblk0, partitions are 5999 + // mmcblk0p1 etc. — same "p<N>" suffix scheme as NVMe. 6000 + if (access("/dev/mmcblk0p1", F_OK) == 0) { 6001 + JSValue t = JS_NewObject(ctx); 6002 + JS_SetPropertyStr(ctx, t, "device", JS_NewString(ctx, "/dev/mmcblk0p1")); 6003 + JS_SetPropertyStr(ctx, t, "label", JS_NewString(ctx, "Internal (eMMC)")); 5988 6004 JS_SetPropertyStr(ctx, t, "removable", JS_NewBool(ctx, 0)); 5989 6005 JS_SetPropertyUint32(ctx, targets, idx++, t); 5990 6006 }