feat(renaser): Fase 7a — el userspace nace del Grafo de Objetos
El kernel deja de empotrar las apps. Las cinco aplicaciones ya no llegan por include_bytes! en main.rs: nacen del grafo, gobernadas por un Manifiesto de Génesis que también vive en el grafo. - almacen: el SuperBloque gana el ancla `manifiesto: Option<Hash>` (gemela de `raiz`, del lado del kernel) + accesores. VERSION 1→2 — un disco v1 se reformatea. - manifiesto.rs: implementados `cargar` (lee el manifiesto del grafo) y `sembrar_genesis` (puebla un disco virgen con las 5 apps de génesis). El bytecode viaja empotrado AÚN, sólo como semilla transitoria (la Fase 7b lo mueve al constructor de imagen `boot`). - kernel_main: `cargar_userspace` reemplaza las 5 `encender_app` escritas a mano; `encender_app` recupera el bytecode del grafo — `recuperar` verifica el hash, un módulo corrupto se niega y el arranque sigue. - wasm: el techo de memoria pasa a ser por-app (del manifiesto). Compila limpio. Verificación en QEMU pendiente (la corre el operador): la pantalla debe verse idéntica a la Fase 6.2 + la línea «manifiesto». Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -11,16 +11,13 @@
|
||||
// del manifiesto, lo deserializa, y por cada `EntradaApp` recupera el objeto
|
||||
// de bytecode —verificado por su hash— y lo inyecta en `wasmi`.
|
||||
//
|
||||
// ESTADO: andamiaje de la Fase 7a. Los tipos y la (de)serializacion estan
|
||||
// completos; `cargar` y `sembrar_genesis` son esbozos — se implementan al
|
||||
// abordar la 7a, cuando el superbloque gane su campo `manifiesto`. Ver
|
||||
// `FASE7.md` para el plan completo.
|
||||
// ESTADO: Fase 7a. Tipos, (de)serializacion, carga desde el grafo y siembra
|
||||
// de la genesis, implementados. La siembra es TRANSITORIA — el bytecode aun
|
||||
// viaja empotrado (`include_bytes!`, abajo); la Fase 7b lo movera al
|
||||
// constructor de imagen `boot` y el kernel dejara de empotrar una sola app.
|
||||
// Ver `FASE7.md` para el plan completo.
|
||||
// =============================================================================
|
||||
|
||||
// Fase 7a en construccion: el modulo aun no se cablea a `kernel_main`. El
|
||||
// `allow` cae en cuanto `cargar`/`sembrar_genesis` tengan llamador real.
|
||||
#![allow(dead_code)]
|
||||
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
@@ -104,21 +101,118 @@ impl Manifiesto {
|
||||
/// Lee el manifiesto del grafo: toma su hash del ancla del superbloque,
|
||||
/// recupera el objeto y lo deserializa. `Ok(None)` si el disco aun no tiene
|
||||
/// manifiesto anclado — el caller debe entonces sembrar la genesis.
|
||||
///
|
||||
/// ANDAMIAJE (Fase 7a-4): depende de `almacen::manifiesto()` —el nuevo ancla
|
||||
/// del superbloque— todavia por implementar (tarea 7a-2).
|
||||
pub fn cargar() -> Result<Option<Manifiesto>, &'static str> {
|
||||
todo!("Fase 7a-4: leer almacen::manifiesto(), recuperar el objeto y deserializar")
|
||||
let hash = match crate::almacen::manifiesto() {
|
||||
Some(hash) => hash,
|
||||
None => return Ok(None),
|
||||
};
|
||||
// `recuperar` recomputa el hash del objeto y verifica su integridad: un
|
||||
// manifiesto corrupto se delata aqui.
|
||||
let objeto = crate::almacen::recuperar(&hash)?
|
||||
.ok_or("manifiesto :: el objeto anclado no existe en el grafo")?;
|
||||
let manifiesto = Manifiesto::deserializar(&objeto.datos)?;
|
||||
Ok(Some(manifiesto))
|
||||
}
|
||||
|
||||
/// Siembra el grafo en un disco sin manifiesto: graba el bytecode de las
|
||||
/// aplicaciones de genesis, compone un `Manifiesto` por defecto con sus
|
||||
/// regiones y cuotas, lo graba y lo ancla en el superbloque. Devuelve el
|
||||
/// hash del manifiesto recien anclado.
|
||||
///
|
||||
/// ANDAMIAJE (Fase 7a-3): la semilla TRANSITORIA — en la 7a el bytecode aun
|
||||
/// llega vacia `include_bytes!`; la 7b mueve la siembra al constructor de
|
||||
/// imagen `boot` y elimina el empotrado del kernel.
|
||||
// =============================================================================
|
||||
// La genesis — la semilla transitoria de la Fase 7a
|
||||
// -----------------------------------------------------------------------------
|
||||
// El bytecode de las apps de genesis viaja, POR AHORA, empotrado en el kernel.
|
||||
// Es el unico `include_bytes!` que sobrevive a la Fase 7a — y solo como
|
||||
// semilla: en un disco virgen, `sembrar_genesis` lo graba en el grafo una vez.
|
||||
// La Fase 7b lo movera al constructor de imagen `boot` y este bloque morira.
|
||||
// =============================================================================
|
||||
|
||||
static APP_WASM: &[u8] = include_bytes!("../assets/app.wasm");
|
||||
static DISCOLA_WASM: &[u8] = include_bytes!("../assets/discola.wasm");
|
||||
static GLOTONA_WASM: &[u8] = include_bytes!("../assets/glotona.wasm");
|
||||
static CRONISTA_WASM: &[u8] = include_bytes!("../assets/cronista.wasm");
|
||||
|
||||
/// Descriptor de una app de genesis: lo que el kernel sabe de ella ANTES de
|
||||
/// que exista en el grafo. `region` es `(x, y, ancho, alto)` en pixeles.
|
||||
struct AppGenesis {
|
||||
nombre: &'static str,
|
||||
bytecode: &'static [u8],
|
||||
region: (u32, u32, u32, u32),
|
||||
techo_memoria: u32,
|
||||
}
|
||||
|
||||
/// El userspace de genesis: las cinco aplicaciones que pueblan un disco
|
||||
/// virgen, con las regiones de la Fase 6.2. `app.wasm` aparece dos veces
|
||||
/// —dos instancias del mismo bytecode—; el grafo, direccionado por contenido,
|
||||
/// lo guarda una sola vez.
|
||||
fn genesis() -> [AppGenesis; 5] {
|
||||
let techo = crate::wasm::TECHO_MEMORIA as u32;
|
||||
[
|
||||
AppGenesis {
|
||||
nombre: "hola-izq",
|
||||
bytecode: APP_WASM,
|
||||
region: (100, 120, 480, 560),
|
||||
techo_memoria: techo,
|
||||
},
|
||||
AppGenesis {
|
||||
nombre: "hola-der",
|
||||
bytecode: APP_WASM,
|
||||
region: (700, 120, 480, 560),
|
||||
techo_memoria: techo,
|
||||
},
|
||||
AppGenesis {
|
||||
nombre: "discola",
|
||||
bytecode: DISCOLA_WASM,
|
||||
region: (60, 700, 360, 80),
|
||||
techo_memoria: techo,
|
||||
},
|
||||
AppGenesis {
|
||||
nombre: "glotona",
|
||||
bytecode: GLOTONA_WASM,
|
||||
region: (460, 700, 360, 80),
|
||||
techo_memoria: techo,
|
||||
},
|
||||
AppGenesis {
|
||||
nombre: "cronista",
|
||||
bytecode: CRONISTA_WASM,
|
||||
region: (860, 700, 360, 80),
|
||||
techo_memoria: techo,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
/// Siembra el grafo en un disco sin manifiesto: graba el bytecode de cada app
|
||||
/// de genesis como un objeto, compone un `Manifiesto` con sus regiones y
|
||||
/// cuotas, lo graba —con las aristas hacia los objetos de bytecode— y lo
|
||||
/// ancla en el superbloque. Devuelve el hash del manifiesto recien anclado.
|
||||
pub fn sembrar_genesis() -> Result<Hash, &'static str> {
|
||||
todo!("Fase 7a-3: grabar los bytecodes de genesis + el manifiesto por defecto, y anclarlo")
|
||||
let mut apps: Vec<EntradaApp> = Vec::new();
|
||||
let mut hijos: Vec<Hash> = Vec::new();
|
||||
|
||||
for app in genesis() {
|
||||
// Grabar el bytecode como objeto del grafo. Idempotente: dos
|
||||
// instancias de la misma app comparten un unico objeto.
|
||||
let bytecode = crate::almacen::almacenar(app.bytecode.to_vec(), Vec::new())?;
|
||||
if !hijos.contains(&bytecode) {
|
||||
hijos.push(bytecode);
|
||||
}
|
||||
let (x, y, ancho, alto) = app.region;
|
||||
apps.push(EntradaApp {
|
||||
nombre: String::from(app.nombre),
|
||||
bytecode,
|
||||
region_x: x,
|
||||
region_y: y,
|
||||
region_ancho: ancho,
|
||||
region_alto: alto,
|
||||
techo_memoria: app.techo_memoria,
|
||||
estado: None,
|
||||
});
|
||||
}
|
||||
|
||||
// El objeto del manifiesto: sus `hijos` son los objetos de bytecode, de
|
||||
// modo que el grafo lo lea como el nodo padre del userspace.
|
||||
let manifiesto = Manifiesto {
|
||||
version: VERSION_MANIFIESTO,
|
||||
apps,
|
||||
};
|
||||
let bytes = manifiesto.serializar()?;
|
||||
let hash = crate::almacen::almacenar(bytes, hijos)?;
|
||||
crate::almacen::fijar_manifiesto(hash)?;
|
||||
Ok(hash)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user