Sanitized research log, build/reproducibility docs, DTS, kernel configs, patches, initramfs sources, bootchain migration plans and test logs. B5 direct boot PASS; B6 modem lifecycle in progress. No dumps, NV/EFS, vendor firmware or device identifiers included.
120 lines
6.5 KiB
C
120 lines
6.5 KiB
C
/* Host shim for running exact lk2nd 23.1 boot scan / extlinux / ext2 code against eMMC image files. */
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdarg.h>
|
|
#include <stdint.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <openssl/sha.h>
|
|
#include "shim/partition_parser.h"
|
|
|
|
int _dprintf(const char *fmt, ...) { va_list ap; va_start(ap, fmt); printf("[lk] "); int r = vprintf(fmt, ap); va_end(ap); return r; }
|
|
void platform_halt(void) { printf("HARNESS: platform_halt (panic)\n"); exit(3); }
|
|
void _panic(void *caller, const char *fmt, ...) { va_list ap; va_start(ap, fmt); printf("HARNESS: PANIC "); vprintf(fmt, ap); va_end(ap); exit(3); }
|
|
|
|
/* ---- virtual disk: LBA ranges -> files ---- */
|
|
struct seg { uint64_t lba, n; const char *file; int fd; };
|
|
static struct seg segs[64]; static int nsegs;
|
|
static uint64_t disk_sectors = 7634944;
|
|
static struct partition_entry ents[128]; static unsigned nents;
|
|
uint64_t reads_bytes;
|
|
|
|
static void load_map(const char *mapfile) {
|
|
FILE *f = fopen(mapfile, "r"); char path[512]; unsigned long long lba, n;
|
|
if (!f) { perror(mapfile); exit(2); }
|
|
while (fscanf(f, "%llu %llu %511s", &lba, &n, path) == 3) {
|
|
segs[nsegs].lba = lba; segs[nsegs].n = n; segs[nsegs].file = strdup(path);
|
|
segs[nsegs].fd = open(path, O_RDONLY); if (segs[nsegs].fd < 0) { perror(path); exit(2); }
|
|
off_t sz = lseek(segs[nsegs].fd, 0, SEEK_END);
|
|
if ((uint64_t)sz < n * 512) { fprintf(stderr, "short file %s\n", path); exit(2); }
|
|
nsegs++;
|
|
}
|
|
fclose(f);
|
|
}
|
|
static void load_gpt(const char *gptfile) {
|
|
unsigned char g[17408]; int fd = open(gptfile, O_RDONLY); if (fd < 0 || read(fd, g, sizeof g) != sizeof g) { perror(gptfile); exit(2); }
|
|
close(fd);
|
|
for (int i = 0; i < 128; i++) {
|
|
unsigned char *e = g + 1024 + 128 * i; int z = 1; for (int k = 0; k < 16; k++) if (e[k]) z = 0; if (z) continue;
|
|
memcpy(&ents[nents].first_lba, e + 32, 8); memcpy(&ents[nents].last_lba, e + 40, 8);
|
|
ents[nents].size = ents[nents].last_lba - ents[nents].first_lba + 1;
|
|
for (int k = 0; k < 36; k++) ents[nents].name[k] = e[56 + 2 * k];
|
|
nents++;
|
|
}
|
|
}
|
|
struct partition_entry *partition_get_partition_entries(void) { return ents; }
|
|
unsigned partition_get_partition_count(void) { return nents; }
|
|
uint32_t mmc_get_device_blocksize(void) { return 512; }
|
|
uint64_t mmc_get_device_capacity(void) { return disk_sectors * 512; }
|
|
uint32_t mmc_read(uint64_t addr, uint32_t *out, uint32_t len) {
|
|
uint8_t *o = (uint8_t *)out; reads_bytes += len;
|
|
while (len) {
|
|
uint64_t lba = addr / 512; struct seg *s = NULL;
|
|
for (int i = 0; i < nsegs; i++) if (lba >= segs[i].lba && lba < segs[i].lba + segs[i].n) s = &segs[i];
|
|
if (!s) { fprintf(stderr, "HARNESS: read of unmapped LBA %llu\n", (unsigned long long)lba); exit(4); }
|
|
uint64_t end = (s->lba + s->n) * 512, chunk = end - addr; if (chunk > len) chunk = len;
|
|
if (pread(s->fd, o, chunk, addr - s->lba * 512) != (ssize_t)chunk) { perror("pread"); exit(4); }
|
|
o += chunk; addr += chunk; len -= chunk;
|
|
}
|
|
return 0;
|
|
}
|
|
/* writes must never happen */
|
|
uint32_t mmc_write(uint64_t a, uint32_t l, void *b) { (void)a;(void)l;(void)b; fprintf(stderr, "HARNESS: WRITE ATTEMPT\n"); abort(); }
|
|
|
|
/* ---- target / platform ---- */
|
|
uint8_t *fake_ddr; static uint8_t *scratch;
|
|
void *target_get_scratch_address(void) { return scratch; }
|
|
unsigned target_get_max_flash_size(void) { return 256u * 1024 * 1024; }
|
|
unsigned board_machtype(void) { return 0; }
|
|
void arch_clean_invalidate_cache_range(uintptr_t a, size_t l) { (void)a; (void)l; }
|
|
const char *const *lk2nd_device_get_dtb_hints(void) { return NULL; }
|
|
int fdt_open_into(const void *f, void *b, int s) { (void)f;(void)b;(void)s; return -1; }
|
|
int fdt_overlay_apply(void *f, void *o) { (void)f;(void)o; return -1; }
|
|
int fdt_pack(void *f) { (void)f; return -1; }
|
|
|
|
static void hx(const char *what, const void *p, size_t n) {
|
|
unsigned char h[32]; SHA256(p, n, h); printf("HARNESS: %-8s sha256 ", what); for (int i = 0; i < 32; i++) printf("%02x", h[i]); printf(" (%zu bytes)\n", n);
|
|
}
|
|
void boot_linux(void *kernel, unsigned *tags, const char *cmdline, unsigned machtype, void *ramdisk, unsigned ramdisk_size, int boot_type) {
|
|
(void)machtype;
|
|
uint32_t *k = kernel; uint64_t image_size; memcpy(&image_size, (uint8_t *)kernel + 16, 8);
|
|
uint32_t dtsz = __builtin_bswap32(tags[1]);
|
|
printf("HARNESS: boot_linux reached: kernel @DDR+0x%lx tags @DDR+0x%lx ramdisk @DDR+0x%lx (%u) boot_type %d\n",
|
|
(long)((uint8_t *)kernel - fake_ddr), (long)((uint8_t *)tags - fake_ddr), (long)((uint8_t *)ramdisk - fake_ddr), ramdisk_size, boot_type);
|
|
printf("HARNESS: kernel magic 0x%08x image_size 0x%llx end @DDR+0x%llx\n", k[14], (unsigned long long)image_size,
|
|
(unsigned long long)((uint8_t *)kernel - fake_ddr) + image_size);
|
|
printf("HARNESS: cmdline '%s'\n", cmdline);
|
|
extern unsigned harness_kernel_len; hx("kernel", kernel, harness_kernel_len);
|
|
hx("dtb", tags, dtsz); hx("ramdisk", ramdisk, ramdisk_size);
|
|
exit(0);
|
|
}
|
|
unsigned harness_kernel_len = 23015432;
|
|
|
|
void lk2nd_boot(void);
|
|
void bio_init(void);
|
|
void fs_init(void);
|
|
void ext2_init(void);
|
|
int main(int argc, char **argv) {
|
|
if (argc < 3) { fprintf(stderr, "usage: %s map gpt [kernel_len]\n", argv[0]); return 2; }
|
|
if (argc > 3) harness_kernel_len = strtoul(argv[3], 0, 0);
|
|
setvbuf(stdout, NULL, _IONBF, 0);
|
|
fake_ddr = calloc(1, 0x3200000); scratch = calloc(1, 256u * 1024 * 1024);
|
|
load_map(argv[1]); load_gpt(argv[2]);
|
|
bio_init(); fs_init();
|
|
lk2nd_boot();
|
|
printf("HARNESS: lk2nd_boot() returned -> aboot would continue to boot_linux_from_mmc() (Android boot partition)\n");
|
|
{ /* diagnostics: mount result per scan candidate, same criteria as lk2nd_scan_devices */
|
|
extern struct bdev_struct *bio_get_bdevs(void); extern int fs_mount(const char*,const char*,const char*); extern int fs_unmount(const char*);
|
|
struct hl { struct hl *prev, *next; };
|
|
struct hb { struct hl node; volatile int ref; char *name; long long size; size_t block_size; uint32_t block_count; char *label; _Bool is_leaf; };
|
|
struct hl *head = (struct hl *)bio_get_bdevs();
|
|
for (struct hl *n = head->next; n != head; n = n->next) { struct hb *b = (struct hb *)n; char mp[32];
|
|
if (!b->is_leaf) continue;
|
|
if (b->size < 16*1024*1024 && !(b->label && !strncmp(b->label, "boot", 4))) continue;
|
|
snprintf(mp, sizeof mp, "/diag-%s", b->name); int r = fs_mount(mp, "ext2", b->name);
|
|
printf("HARNESS: scan-candidate %-8s (%s) ext2 mount rc=%d\n", b->name, b->label ? b->label : "", r); if (r == 0) fs_unmount(mp); } }
|
|
printf("HARNESS: total bytes read %llu\n", (unsigned long long)reads_bytes);
|
|
return 1;
|
|
}
|
|
int atomic_add(volatile int *p, int v) { int o = *p; *p = o + v; return o; }
|