diff --git a/ESTADO.md b/ESTADO.md new file mode 100644 index 00000000..796d4a1d --- /dev/null +++ b/ESTADO.md @@ -0,0 +1,62 @@ +# ¿Dónde está hammer hoy? (mapa amigable) + +> Una foto en lenguaje humano de qué funciona, qué falta y por dónde seguir. +> Fecha: 2026-06-22. Para el detalle de arquitectura, ver [`docs/`](docs/). + +## La idea en una frase + +`hammer` es una distro de Linux con dos pisos: un **sótano de laboratorio** que compila +todo desde fuente de forma reproducible y guarda cada binario por su hash, y un **piso de +arriba** clásico y mutable (un Linux normal con `/bin`, `/lib`, `/etc`) donde puedes romper +cosas y revertir. Está pensada para que una **IA** entienda y modifique el sistema entero. + +## El semáforo: qué está listo + +| Pieza | Estado | En cristiano | +|---|---|---| +| 🟢 Núcleo del laboratorio | **Listo** | Compila aislado (bubblewrap + zig cc + musl), direcciona por hash BLAKE3 | +| 🟢 Auto-hospedaje (self-host) | **Listo y verificado** | El toolchain se reconstruye a sí mismo *bit a bit* dentro de una VM | +| 🟢 Kernel propio | **Listo** | Linux 6.16.12 compilado por nosotros, **arranca** la VM y se reproduce idéntico | +| 🟢 Frente Rust/LLVM | **Cerrado** | Cadena pura mrustc → rustc 1.91.1, sin binarios ajenos de confianza | +| 🟢 Paquetería `.swm` | **Listo (6/6 piezas)** | Empaquetar, repo firmado, instalar/desinstalar, deps, repo por red | +| 🟢 Catálogo de software | **145 recetas** | Subió de 88 a 145 en una sola sesión (sobre todo CLIs de Rust) | +| 🟡 Instalar en disco real | **En curso** | Imágenes EFI/ISO existen; falta pulir "instalar desde el live" | +| 🟡 Userland Rust-nativo | **En curso** | coreutils/findutils de uutils ya construyen y corren | +| ⚪ Distro instalable redonda | **Pendiente** | Las etapas B/D/E del roadmap | + +## Lo más importante que se logró + +1. **Soberanía del arranque.** No dependemos de binarios precocidos de nadie. Partiendo de + un compilador mínimo, hammer reconstruye su propio Rust, su propio kernel y sus propias + herramientas — y al hacerlo dos veces da **exactamente el mismo resultado** (reproducible + bit a bit). Eso se probó dentro de una máquina virtual, no solo en teoría. + +2. **Una "granja" de software que escala.** Hay un pipeline que toma recetas de `nixpkgs` y + Alpine, las adapta al formato de hammer, las compila y promueve las que funcionan al + catálogo. En esta sesión pasó de 88 a 145 paquetes, casi todo CLIs de Rust populares + (ripgrep, bat, fd, zoxide, helix, zellij, uv, ruff, biome…). + +3. **El "techo" actual es conocido.** Lo que frena más builds ya no es un misterio: es la + versión mínima de Rust que pide cada programa (MSRV) y los paquetes que arrastran C/C++ + (`openssl`, `git2`). Subir el toolchain de 1.91.1 a 1.96 destrabó una tanda entera. + +## Por dónde sigue + +- **Escalar el catálogo a cientos** de paquetes con la cola ya pre-cargada + (`JOBS=4 scripts/build-farm.sh`). +- **Terminar "instalar desde el live"**: que arrancar el ISO y darle a instalar deje un + sistema usable en disco (Etapa B del roadmap). +- **Seguir reemplazando el userland** por equivalentes Rust-nativos (xargs es el próximo). +- Pulidos opcionales: squashfs+overlay, arranque EFI fino, rollback al boot. + +## Para orientarte en el repo + +- `crates/` — el código de hammer (CLI, daemon, build lab, journal, overlay…). +- `recipes/` — el catálogo (145 `.toml`); `recipes/incoming/` es la cola por procesar. +- `scripts/` — orquestadores: `selfhost-verify.sh` (la prueba de fuego), `build-farm.sh` + (la granja), `import-batch.sh` (importa tandas), `rust-frontier/` (la cadena Rust pura). +- `docs/` — el diseño completo (SDD); empieza por `00-vision.md` y `10-roadmap.md`. + +--- +*Este archivo es el resumen humano. El estado técnico denso vive en la memoria del proyecto +y en los mensajes de commit (en español, granulares).* diff --git a/recipes/linux-metal.toml b/recipes/linux-metal.toml new file mode 100644 index 00000000..907c86ce --- /dev/null +++ b/recipes/linux-metal.toml @@ -0,0 +1,77 @@ +# Linux kernel 6.16.12 — VARIANTE "METAL": booteable en hardware real (no sólo QEMU). +# +# Hermana de recipes/linux.toml (el kernel QEMU-tuned del selfhost-verify, INTOCADO: su of_tree es +# load-bearing para la reproducibilidad bit-a-bit). Esta variante NO recorta el hardware; al revés, lo +# habilita built-in (=y) porque el producto hammer es monolítico (arje-zero PID1, sin udev/modprobe en +# el camino de boot ⇒ todo lo que haga falta para arrancar/ver/teclear/conectar debe ser =y, no =m). +# +# Target concreto: laptop TigerLake-LP (Intel Iris Xe + Wi-Fi 6 AX201 [8086:a0f0]), boot EFI. +# - Pantalla: DRM_SIMPLEDRM + SYSFB_SIMPLEFB + FB_EFI (framebuffer del GOP de EFI; NO i915 → sin +# firmware GuC/DMC/HuC, consola fbcon basta). i915/amdgpu/nouveau/radeon quedan OFF. +# - Teclado: USB_HID + HID_GENERIC + i8042/atkbd (teclado integrado del portátil suele ser PS/2). +# - Discos: AHCI/ATA + NVMe + USB_STORAGE + SCSI/sd (NVMe es lo más probable en TigerLake). +# - WiFi: cfg80211 + mac80211 + iwlwifi + iwlmvm (AX201 usa el path mvm). El firmware +# (iwlwifi-QuZ-a0-hr-b0-*.ucode, cc-a0-*) + regulatory.db NO van acá — son blobs no +# compilables; se inyectan en /lib/firmware del rootfs (ver scripts/metal-firmware.sh). +# - Red extra: e1000e/r8169/igb/igc/tg3 (Ethernet común) + USB-CDC/RNDIS (tether del celu) — baratos. +# - Boot: EFI_STUB + EFI_PARTITION + VFAT (ESP) + ISO9660/Joliet (leer el medio live). +# +# Conserva TODO lo que hammer necesita (de linux.toml): E1000/OVERLAY_FS(+subfeatures)/USER_NS/ +# NAMESPACES/FANOTIFY/VIRTIO* ⇒ esta misma imagen sigue booteando en QEMU (para poder testear el boot +# antes de quemar el USB). MODULES=off ⇒ monolítico puro (sin .ko que nadie cargaría). +# +# Compilador: CC=gcc/HOSTCC=gcc — MISMA decisión del gueto-GCC que linux.toml (zig cc choca con el +# kbuild x86). Build ~45min (config ancha). Build-deps idénticos (flex/bison/m4/openssl/elfutils + +# bootstrap-libs apk del bootstrap-devfs.sh). + +name = "linux-metal" +version = "6.16.12" + +[source] +tarball = "https://mirrors.edge.kernel.org/pub/linux/kernel/v6.x/linux-6.16.12.tar.gz" +sha256 = "ffc6af80b014ddebd55e116aa29a9f7a5256c87a29a8a9dd97270b6d49625109" + +[build] +compiler = "zig-cc" +target = "x86_64-linux-musl" +link = "dynamic" + +[deps] +build = ["flex", "bison", "m4", "openssl", "elfutils"] + +[build.phases] +configure = """ +make ARCH=x86_64 defconfig && \ +scripts/config -d MODULE_SIG -d MODULE_SIG_ALL -d DEBUG_INFO_BTF -d DEBUG_INFO -d MODULES \ + -d UNWINDER_ORC -e UNWINDER_FRAME_POINTER \ + -e BLK_DEV_INITRD -e DEVTMPFS -e DEVTMPFS_MOUNT -e TMPFS \ + -e OVERLAY_FS -e USER_NS -e NAMESPACES \ + -e FANOTIFY -e FANOTIFY_ACCESS_PERMISSIONS \ + -e OVERLAY_FS_REDIRECT_DIR -e OVERLAY_FS_INDEX -e OVERLAY_FS_XINO_AUTO -e OVERLAY_FS_METACOPY \ + -e VIRTIO -e VIRTIO_PCI -e VIRTIO_BLK -e VIRTIO_NET -e EXT4_FS \ + -e PCI -e PCIEPORTBUS -e ACPI \ + -e SATA_AHCI -e ATA -e ATA_PIIX -e SCSI -e BLK_DEV_SD -e BLK_DEV_LOOP \ + -e NVME_CORE -e BLK_DEV_NVME \ + -e USB_SUPPORT -e USB -e USB_PCI -e USB_XHCI_HCD -e USB_XHCI_PCI \ + -e USB_EHCI_HCD -e USB_EHCI_PCI -e USB_OHCI_HCD -e USB_UHCI_HCD -e USB_STORAGE \ + -e HID -e HID_GENERIC -e USB_HID -e INPUT_EVDEV \ + -e INPUT_KEYBOARD -e KEYBOARD_ATKBD -e INPUT_MOUSE -e MOUSE_PS2 \ + -e SERIO -e SERIO_I8042 -e VT -e VT_CONSOLE \ + -e DRM -e DRM_SIMPLEDRM -e SYSFB_SIMPLEFB -e FB -e FB_EFI \ + -e FRAMEBUFFER_CONSOLE -e FRAMEBUFFER_CONSOLE_DETECT_PRIMARY \ + -e EFI -e EFI_STUB -e EFI_PARTITION -e EFIVAR_FS \ + -e VFAT_FS -e FAT_FS -e MSDOS_FS -e NLS_CODEPAGE_437 -e NLS_ISO8859_1 -e NLS_UTF8 \ + -e ISO9660_FS -e JOLIET \ + -e WLAN -e WIRELESS -e CFG80211 -e MAC80211 -e RFKILL \ + -e WLAN_VENDOR_INTEL -e IWLWIFI -e IWLMVM \ + -e ETHERNET -e NET_VENDOR_INTEL -e E1000 -e E1000E -e IGB -e IGC \ + -e NET_VENDOR_REALTEK -e R8169 -e NET_VENDOR_BROADCOM -e TG3 \ + -e USB_NET_DRIVERS -e USB_USBNET -e USB_NET_CDCETHER -e USB_NET_CDC_NCM -e USB_NET_RNDIS_HOST \ + -d DRM_I915 -d DRM_AMDGPU -d DRM_NOUVEAU -d DRM_RADEON -d AGP \ + -d SOUND -d SND -d MEDIA_SUPPORT -d INFINIBAND -d BT -d NFC -d CAN \ + -d WATCHDOG -d THUNDERBOLT -d FIREWIRE \ + -d XFS_FS -d BTRFS_FS -d F2FS_FS -d JFS_FS -d REISERFS_FS -d GFS2_FS -d NTFS3_FS && \ +make ARCH=x86_64 olddefconfig +""" +compile = "make ARCH=x86_64 CC=gcc HOSTCC=gcc -j\"$(nproc)\" bzImage" +install = "mkdir -p /out/boot && cp arch/x86/boot/bzImage /out/boot/bzImage && cp .config /out/boot/config-6.16.12-metal" diff --git a/scripts/metal-firmware.sh b/scripts/metal-firmware.sh new file mode 100755 index 00000000..d7c9b7cc --- /dev/null +++ b/scripts/metal-firmware.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env sh +# metal-firmware.sh — inyecta el firmware del WiFi AX201 (y reg.db) en /lib/firmware de un rootfs. +# +# El firmware de iwlwifi son BLOBS binarios NO compilables desde fuente (Intel no libera el código); la +# soberanía de hammer (build-from-source) no aplica acá — son datos fijos como el microcódigo de la CPU. +# Se fijan por contenido (igual que un tarball pinned): se copian de un linux-firmware ya presente y se +# descomprimen a .ucode plano (el kernel metal NO habilita FW_LOADER_COMPRESS, así evitamos esa dep). +# +# Target: Intel Wi-Fi 6 AX201 [8086:a0f0] en TigerLake ⇒ familias QuZ-a0-hr-b0 + cc-a0 (el driver elige +# la API más alta que soporta) + regulatory.db(+.p7s) que cfg80211 verifica con la clave built-in. +# +# Uso: scripts/metal-firmware.sh +# Vars: FWSRC dir origen del firmware (default /lib/firmware del host) +# +# TODO(soberanía): reemplazar FWSRC=host por un pin a un commit de linux-firmware (recipe fetch+extract). +set -eu + +DST="${1:?uso: metal-firmware.sh }" +FWSRC="${FWSRC:-/lib/firmware}" +OUT="$DST/lib/firmware" +mkdir -p "$OUT" + +# patrones de firmware que el AX201 puede pedir (ambas familias, todas las API presentes) +PATTERNS="iwlwifi-QuZ-a0-hr-b0-*.ucode iwlwifi-cc-a0-*.ucode" +n=0 +for pat in $PATTERNS; do + for src in "$FWSRC"/$pat "$FWSRC"/$pat.zst "$FWSRC"/$pat.xz; do + [ -e "$src" ] || continue + base=$(basename "$src") + case "$base" in + *.zst) dst="$OUT/${base%.zst}"; zstd -q -d -f -o "$dst" "$src" ;; + *.xz) dst="$OUT/${base%.xz}"; xz -dc "$src" > "$dst" ;; + *) dst="$OUT/$base"; cp "$src" "$dst" ;; + esac + n=$((n+1)) + done +done + +# regulatory db (texto firmado; cfg80211 lo carga vía firmware loader y verifica .p7s con clave built-in) +for f in regulatory.db regulatory.db.p7s; do + if [ -e "$FWSRC/$f" ]; then cp "$FWSRC/$f" "$OUT/$f"; n=$((n+1)); fi +done + +[ "$n" -gt 0 ] || { echo "metal-firmware: NO encontré firmware AX201 en $FWSRC" >&2; exit 1; } +echo "metal-firmware: $n blobs → $OUT" +ls "$OUT" | sed 's/^/ /'