code wiki / _hdl_build / _k_r2_001c3_gate.nx

_k_r2_001c3_gate.nx source

↩ module page · 376 lines · 19940 B

1// _k_r2_001c3_gate.nx -- the K-R2-001c3 gate (virtio-NET FRAME LOOPBACK; the THIRD and final 2// slice of the K-R2-001c net virtqueue epic). It is the K-R2-001b3 sector-data round-trip gate 3// applied to the SECOND virtio device, virtio-net (DeviceID=1) @ base 0x10002000. NO mocks: 4// runs the REAL nx_virtio_hs_emit (the SAME shared emitter the blk b-series + the net c1/c2 use 5// -- data-only on base/device-id/banner/queue-config/descriptor/avail-used/frame, so it stays 6// byte-for-byte backward-compatible), then RUNS the emitted image on the SOVEREIGN rv64 emulator 7// (rv64im_min_sim + the second rv64im_min_virtio net instance @ 0x10002000 -- the PRIMARY, gating 8// lane: Nishi owns the runtime). After the c2 queue-config the net driver lays a frame (a 9// virtio-net WIRE_TLV header word: flags/gso_type/hdr_len packed into the first 32-bit word) + 10// payload into a tx descriptor's data buffer in guest RAM, publishes the descriptor on the AVAIL 11// ring, kicks QueueNotify -> the net QueueNotify now triggers nx_virtio_notify_dma on s.virtio_net 12// (the device-instance-generic DMA walk: desc-read + avail/used + the data round-trip), so the 13// device FOLLOWS desc[head].addr into guest RAM, DMA-READS the frame's first word, and latches it 14// into QueueSectPeek. The driver reads QueueSectPeek BACK (lwu) and verifies it == the sent frame 15// word -> emits the trailing " FRAME" canary. The gate asserts the captured serial transcript 16// CONTAINS the emitter's golden ("VNET ACK DRV FEAT OK VQ DESC USED STAT FRAME\n") AND the 17// sovereign emu reports a clean SiFive-finisher halt. The blk device @ 0x10001000 is left 18// BYTE-UNTOUCHED (its own gates VIRTGATE..SECTGATE still pass, re-proven by re-run). 19// 20// Then the ALIGNMENT lane: qemu-system-riscv64 -machine virt -global 21// virtio-mmio.force-legacy=true with a REAL virtio-blk-device (first) + a REAL 22// virtio-net-device (second). qemu fills its virtio-mmio slots in REVERSE, so the first device 23// (blk) lands at the top slot 0x10008000 and the SECOND device (net) lands at the next slot DOWN, 24// 0x10007000. The gate authors a SECOND net image from a base-rewritten spec (base = the qemu net 25// reverse-slot 0x10007000) and runs THAT on qemu; the SAME loopback driver lays the SAME tx 26// descriptor + the SAME avail ring + the SAME frame word into qemu guest RAM and kicks the real 27// QueueNotify (the real transport walks the ring). The sovereign-only QueueDescPeek/ 28// QueueUsedIdxPeek/QueueStatPeek/QueueSectPeek RO peek registers (0x060/0x064/0x068/0x06C) are a 29// SIM modelling device -- they read 0 on the real qemu virtio-net transport -- so the descriptor- 30// DMA + used + status + FRAME read-back verifies drop " DESC"/" USED"/" STAT"/" FRAME" there; 31// the gate asserts the PREFIX golden ("VNET ACK DRV FEAT OK VQ") appears, proving the driver runs 32// IDENTICALLY against the REAL virtio-net transport through the handshake + queue-config + tx- 33// descriptor lay + avail publish + QueueNotify kick (lanes AGREE on the real-hardware-driveable 34// behaviour; the frame round-trip proof itself is the sovereign PRIMARY lane, the same alignment 35// semantics the blk b3 SECTGATE established). 36// 37// Finally a TAMPER test: corrupt the FRAME-EXPECTED constant in the sovereign image (the driver 38// loads its own QueueSectPeek frame read-back into t3 via `lwu t3,0x06C(t2)` and compares against 39// the li-loaded expected in t4; the expected li is the lui/addi following the unique SectPeek 40// read-back load). Bumping the addi's high immediate byte makes the read-back verify branch PAST 41// the frame stage straight to the finisher -> the transcript loses ONLY its " FRAME" canary (the 42// "...VQ DESC USED STAT" tail survives) -> the gate MUST go RED. Evidence -> 43// knowledge/status/virtio_net.log (NETLOOPGATE row; the queue row's ||MARK= reads it). 44// Sovereign orchestration (fork/dup3/execve/wait4). license_tier: ORIGINAL 45import "nx_syscalls.nx" 46 47// the unique rv64 encoding of `lwu t3, 0x06C(t2)` -- the QueueSectPeek (net frame) read-back load. 48// The frame-expected constant the driver compares against is the li that follows it (lui at +4, 49// addi at +8); corrupting the addi's immediate (byte +11) is the frame-loopback tamper. 50const G_QSECTPEEK_LOAD_WORD: i64 = 0x06c3ee03 // lwu t3, 0x06C(t2) (QueueSectPeek frame read-back) 51const G_QEMU_BASE: i64 = 0x10007000 // the slot qemu-virt assigns the SECOND device (net) 52 53func g_p(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 54func g_fp(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 } 55func g_fn(fd: i64, v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m}; let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48;k=1}; while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1}; var i: i64=0; while i<k{bb[i]=t[k-1-i];i=i+1}; sys_write(fd,bb,k); return 0 } 56 57// run nx_virtio_hs_emit <spec>; return child wait status (0 = ok) 58func g_run_emit(spec: *u8) -> i64 { 59 let pid: i64 = sys_fork() 60 if pid == 0 { 61 let dn: i64 = sys_openat_wr("/dev/null" as *u8, 0x1a4) 62 if dn >= 0 { sys_dup3(dn, 1, 0) } 63 let argv: *i64 = sys_mmap(32) as *i64 64 argv[0] = "_offc/nx_virtio_hs_emit.elf" as *u8 as i64 65 argv[1] = spec as i64 66 argv[2] = 0 67 let envp: *i64 = sys_mmap(16) as *i64 68 envp[0] = "PATH=/usr/bin:/bin" as *u8 as i64 69 envp[1] = 0 70 sys_execve("_offc/nx_virtio_hs_emit.elf" as *u8, argv, envp) 71 sys_exit(127) 72 } 73 let st: *i64 = sys_mmap(16) as *i64 74 sys_wait4(pid, st, 0) 75 return st[0] 76} 77 78// run the SOVEREIGN rv64 emulator on binpath; serial -> outpath; return wait status 79func g_run_sov(binpath: *u8, outpath: *u8) -> i64 { 80 let pid: i64 = sys_fork() 81 if pid == 0 { 82 let ofd: i64 = sys_openat_wr(outpath, 0x1a4) 83 if ofd >= 0 { sys_dup3(ofd, 1, 0); sys_dup3(ofd, 2, 0) } 84 let argv: *i64 = sys_mmap(32) as *i64 85 argv[0] = "_offc/nx_boot_run_sov.elf" as *u8 as i64 86 argv[1] = binpath as i64 87 argv[2] = 0 88 let envp: *i64 = sys_mmap(16) as *i64 89 envp[0] = "PATH=/usr/bin:/bin" as *u8 as i64 90 envp[1] = 0 91 sys_execve("_offc/nx_boot_run_sov.elf" as *u8, argv, envp) 92 sys_exit(127) 93 } 94 let st: *i64 = sys_mmap(16) as *i64 95 sys_wait4(pid, st, 0) 96 return st[0] 97} 98 99// run qemu-system-riscv64 virt + legacy virtio-blk-device (first) + virtio-net-device 100// (second) on binpath; serial -> outpath. The net device lands at qemu reverse slot 101// 0x10007000 (blk takes the top slot 0x10008000); the derived-base net image targets that 102// slot. The blk backing image must exist; the gate creates it first via g_make_backing. 103func g_run_qemu(binpath: *u8, outpath: *u8, backing: *u8) -> i64 { 104 let pid: i64 = sys_fork() 105 if pid == 0 { 106 let ofd: i64 = sys_openat_wr(outpath, 0x1a4) 107 if ofd >= 0 { sys_dup3(ofd, 1, 0); sys_dup3(ofd, 2, 0) } 108 let argv: *i64 = sys_mmap(128) as *i64 109 argv[0] = "/usr/bin/qemu-system-riscv64" as *u8 as i64 110 argv[1] = "-machine" as *u8 as i64 111 argv[2] = "virt" as *u8 as i64 112 argv[3] = "-global" as *u8 as i64 113 argv[4] = "virtio-mmio.force-legacy=true" as *u8 as i64 114 argv[5] = "-nographic" as *u8 as i64 115 argv[6] = "-bios" as *u8 as i64 116 argv[7] = binpath as i64 117 argv[8] = "-drive" as *u8 as i64 118 argv[9] = "file=/tmp/_vnetlpgate_backing.img,if=none,format=raw,id=hd0" as *u8 as i64 119 argv[10] = "-device" as *u8 as i64 120 argv[11] = "virtio-blk-device,drive=hd0" as *u8 as i64 121 argv[12] = "-device" as *u8 as i64 122 argv[13] = "virtio-net-device" as *u8 as i64 123 argv[14] = 0 124 let envp: *i64 = sys_mmap(16) as *i64 125 envp[0] = "PATH=/usr/bin:/bin" as *u8 as i64 126 envp[1] = 0 127 sys_execve("/usr/bin/qemu-system-riscv64" as *u8, argv, envp) 128 sys_exit(127) 129 } 130 let st: *i64 = sys_mmap(16) as *i64 131 sys_wait4(pid, st, 0) 132 return st[0] 133} 134 135// create a small raw backing file for the qemu virtio-blk device (4 sectors of zeros). 136func g_make_backing(path: *u8) -> i64 { 137 let fd: i64 = sys_openat_wr(path, 0x1a4) 138 if fd < 0 { return 0 - 1 } 139 let z: *u8 = sys_mmap(2048) 140 var i: i64 = 0 141 while i < 2048 { z[i] = 0 as u8; i = i + 1 } 142 sys_write(fd, z, 2048) 143 sys_close(fd) 144 return 0 145} 146 147// read whole file into buf (cap-1 max); return byte count (0 if absent) 148func g_read(path: *u8, buf: *u8, cap: i64) -> i64 { 149 let fd: i64 = sys_openat_rd(path) 150 if fd < 0 { return 0 } 151 var n: i64 = 0 152 var go: i64 = 1 153 while go == 1 { let r: i64 = sys_read(fd, (buf as i64 + n) as *u8, cap - 1 - n); if r <= 0 { go = 0 } else { n = n + r } if n >= cap - 1 { go = 0 } } 154 sys_close(fd) 155 return n 156} 157 158// does buf[0,n) contain pat (length pl)? 1/0 159func g_buf_has(buf: *u8, n: i64, pat: *u8, pl: i64) -> i64 { 160 if pl <= 0 { return 0 } 161 var i: i64 = 0 162 while i + pl <= n { 163 var k: i64 = 0 164 var hit: i64 = 1 165 while k < pl { if buf[i+k] != pat[k] { hit = 0; k = pl } else { k = k + 1 } } 166 if hit == 1 { return 1 } 167 i = i + 1 168 } 169 return 0 170} 171 172// read a little-endian 32-bit word from buf at byte offset o. 173func g_w32(buf: *u8, o: i64) -> i64 { 174 let b0: i64 = buf[o] as i64 175 let b1: i64 = buf[o+1] as i64 176 let b2: i64 = buf[o+2] as i64 177 let b3: i64 = buf[o+3] as i64 178 return b0 | (b1 << 8) | (b2 << 16) | (b3 << 24) 179} 180 181// find the byte offset of the (unique) QueueSectPeek (net frame) read-back load word in the 182// image; -1 if absent. The frame-expected li the driver compares against is at off+4 (lui) / 183// off+8 (addi); the addi's high immediate byte is at off+11. 184func g_find_sectpeek_load(buf: *u8, n: i64) -> i64 { 185 var o: i64 = 0 186 while o + 4 <= n { 187 if g_w32(buf, o) == G_QSECTPEEK_LOAD_WORD { return o } 188 o = o + 4 189 } 190 return 0 - 1 191} 192 193func g_strlen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 194 195// does line [ls,le) of buf begin with key? 1/0 196func g_line_is(buf: *u8, ls: i64, le: i64, key: *u8) -> i64 { 197 var k: i64 = 0 198 while key[k] != (0 as u8) { 199 if ls + k >= le { return 0 } 200 if buf[ls + k] != key[k] { return 0 } 201 k = k + 1 202 } 203 return 1 204} 205 206// author the qemu-alignment spec: copy the main net spec, but replace the `base ` line value 207// with G_QEMU_BASE (the qemu net reverse-slot 0x10007000) and the `out ` line with the qemu 208// image path. Writes derived spec. 209func g_write_qemu_spec(mainspec: *u8, derived: *u8, qemu_out: *u8) -> i64 { 210 let buf: *u8 = sys_mmap(16384) 211 let n: i64 = g_read(mainspec, buf, 16384) 212 if n <= 0 { return 0 - 1 } 213 let ofd: i64 = sys_openat_wr(derived, 0x1a4) 214 if ofd < 0 { return 0 - 1 } 215 var ls: i64 = 0 216 while ls < n { 217 var le: i64 = ls 218 var scan: i64 = 1 219 while scan == 1 { if le >= n { scan = 0 } else { if buf[le] == (10 as u8) { scan = 0 } else { le = le + 1 } } } 220 if g_line_is(buf, ls, le, "base " as *u8) == 1 { 221 g_fp(ofd, "base 0x10007000\n" as *u8) 222 } else { 223 if g_line_is(buf, ls, le, "out " as *u8) == 1 { 224 g_fp(ofd, "out " as *u8); g_fp(ofd, qemu_out); g_fp(ofd, "\n" as *u8) 225 } else { 226 sys_write(ofd, (buf as i64 + ls) as *u8, le - ls) 227 g_fp(ofd, "\n" as *u8) 228 } 229 } 230 ls = le + 1 231 } 232 sys_close(ofd) 233 return 0 234} 235 236func main() -> i64 { 237 let spec: *u8 = "knowledge/specs/virtio_net_loopback_virt.spec" as *u8 238 let binpath: *u8 = "runtime/_hdl_build/_virtio_net_loopback_virt.bin" as *u8 239 let goldpath: *u8 = "runtime/_hdl_build/_virtio_net_loopback_virt.bin.gold" as *u8 240 let qemu_spec: *u8 = "/tmp/_vnetlpgate_qemu.spec" as *u8 241 let qemu_bin: *u8 = "/tmp/_vnetlpgate_qemu.bin" as *u8 242 let backing: *u8 = "/tmp/_vnetlpgate_backing.img" as *u8 243 let tamper_bin: *u8 = "/tmp/_vnetlpgate_tamper.bin" as *u8 244 let sov_serial: *u8 = "/tmp/_vnetlpgate_sov.txt" as *u8 245 let qemu_serial: *u8 = "/tmp/_vnetlpgate_qemu.txt" as *u8 246 let sov_tamper: *u8 = "/tmp/_vnetlpgate_sov_tamper.txt" as *u8 247 let blk_spec: *u8 = "knowledge/specs/virtio_blk_sector_virt.spec" as *u8 248 let blk_bin: *u8 = "runtime/_hdl_build/_virtio_sector_virt.bin" as *u8 249 let blk_gold: *u8 = "runtime/_hdl_build/_virtio_sector_virt.bin.gold" as *u8 250 let blk_serial: *u8 = "/tmp/_vnetlpgate_blk.txt" as *u8 251 g_p("=== virtio-NET FRAME LOOPBACK gate (K-R2-001c3: SOVEREIGN rv64 net tx frame round-trip @0x10002000 + qemu virtio-net-device alignment @0x10007000) ===\n" as *u8) 252 253 let lfd: i64 = sys_openat_append("knowledge/status/virtio_net.log" as *u8, 0x1a4) 254 255 // STEP 1: author the SOVEREIGN net image (base 0x10002000) + the golden transcript. 256 let est: i64 = g_run_emit(spec) 257 if est != 0 { 258 g_p("NETLOOPGATE verdict=RED reason=emit-failed\n" as *u8) 259 if lfd >= 0 { g_fp(lfd, "NETLOOPGATE verdict=RED reason=emit-failed\n" as *u8); sys_close(lfd) } 260 sys_exit(1); return 1 261 } 262 let gold: *u8 = sys_mmap(512) 263 let gn: i64 = g_read(goldpath, gold, 512) 264 gold[gn] = 0 as u8 265 if gn <= 0 { 266 g_p("NETLOOPGATE verdict=RED reason=golden-missing\n" as *u8) 267 if lfd >= 0 { g_fp(lfd, "NETLOOPGATE verdict=RED reason=golden-missing\n" as *u8); sys_close(lfd) } 268 sys_exit(1); return 1 269 } 270 271 // STEP 2 (PRIMARY): the Nishi sovereign rv64 emulator RUNS the image -- net handshake + 272 // virtqueue config + tx-descriptor lay + avail publish + QueueNotify kick (now DMA-walks the 273 // net ring) + FRAME read-back -> transcript must CONTAIN the golden. 274 let sst: i64 = g_run_sov(binpath, sov_serial) 275 let sbuf: *u8 = sys_mmap(65536) 276 let sbn: i64 = g_read(sov_serial, sbuf, 65536) 277 let trans_ok: i64 = g_buf_has(sbuf, sbn, gold, gn) 278 let halt_ok: i64 = g_buf_has(sbuf, sbn, "BOOTSOV verdict=GREEN" as *u8, 21) 279 var sov_ok: i64 = 0 280 if sst == 0 { if trans_ok == 1 { if halt_ok == 1 { sov_ok = 1 } } } 281 282 // STEP 3 (ALIGNMENT): author the qemu-base net image (slot 0x10007000) + run qemu with a REAL 283 // legacy virtio-blk-device (first) + virtio-net-device (second); the SAME driver lays the SAME 284 // tx descriptor + the SAME avail ring + the SAME frame word into qemu guest RAM and kicks the 285 // real QueueNotify (the real transport walks the ring). The sovereign-only QueueDescPeek/ 286 // QueueUsedIdxPeek/QueueStatPeek/QueueSectPeek registers read 0 on the real device, so the 287 // descdma + used + status + FRAME read-back verifies drop " DESC"/" USED"/" STAT"/" FRAME" 288 // there; assert the PREFIX golden ("VNET ACK DRV FEAT OK VQ") appears, proving the driver runs 289 // identically against the real transport up to the avail publish + kick (the same alignment 290 // semantics the blk b3 SECTGATE established). The full frame round-trip is the sovereign 291 // PRIMARY lane (STEP 2). 292 let prefix_gold: *u8 = "VNET ACK DRV FEAT OK VQ" as *u8 293 g_make_backing(backing) 294 g_write_qemu_spec(spec, qemu_spec, qemu_bin) 295 let qest: i64 = g_run_emit(qemu_spec) 296 var align: i64 = 0 297 if qest == 0 { 298 let qst: i64 = g_run_qemu(qemu_bin, qemu_serial, backing) 299 let qbuf: *u8 = sys_mmap(65536) 300 let qbn: i64 = g_read(qemu_serial, qbuf, 65536) 301 let qtrans: i64 = g_buf_has(qbuf, qbn, prefix_gold, g_strlen(prefix_gold)) 302 if qst == 0 { if qtrans == 1 { align = 1 } } 303 } 304 305 // STEP 4 (TAMPER): corrupt the FRAME-EXPECTED constant in the sovereign image. Scan for the 306 // unique QueueSectPeek (frame) read-back load word; the expected li the driver compares 307 // against is the addi at load+8. Bump that addi's high immediate byte (load+11) so the 308 // expected != the frame word the driver actually wrote+round-tripped -> the read-back verify 309 // branches to the finisher -> ONLY the " FRAME" canary drops -> gate MUST go RED. 310 let ibuf: *u8 = sys_mmap(8192) 311 let ibn: i64 = g_read(binpath, ibuf, 8192) 312 let lpos: i64 = g_find_sectpeek_load(ibuf, ibn) 313 var tamper_built: i64 = 0 314 if lpos >= 0 { 315 let ebyte: i64 = lpos + 11 // high immediate byte of the expected addi 316 ibuf[ebyte] = (ibuf[ebyte] + 1) as u8 317 let tfd: i64 = sys_openat_wr(tamper_bin, 0x1a4) 318 if tfd >= 0 { sys_write(tfd, ibuf, ibn); sys_close(tfd); tamper_built = 1 } 319 } 320 var tamper_bites: i64 = 0 321 if tamper_built == 1 { 322 let tst: i64 = g_run_sov(tamper_bin, sov_tamper) 323 let tbuf: *u8 = sys_mmap(65536) 324 let tbn: i64 = g_read(sov_tamper, tbuf, 65536) 325 let tamper_trans: i64 = g_buf_has(tbuf, tbn, gold, gn) // golden should now MISS 326 if tamper_trans == 0 { tamper_bites = 1 } 327 } 328 329 // STEP 5 (BLK-UNTOUCHED regression): re-author + re-run the blk sector image @0x10001000 on 330 // the SAME sovereign sim and assert its full golden (VIO..SECT) STILL appears -- proving the 331 // net QueueNotify DMA trigger added to the net store window did NOT disturb the blk device. 332 let blk_est: i64 = g_run_emit(blk_spec) 333 var blk_ok: i64 = 0 334 if blk_est == 0 { 335 let bgold: *u8 = sys_mmap(512) 336 let bgn: i64 = g_read(blk_gold, bgold, 512) 337 bgold[bgn] = 0 as u8 338 let bst: i64 = g_run_sov(blk_bin, blk_serial) 339 let bbuf: *u8 = sys_mmap(65536) 340 let bbn: i64 = g_read(blk_serial, bbuf, 65536) 341 let btrans: i64 = g_buf_has(bbuf, bbn, bgold, bgn) 342 let bhalt: i64 = g_buf_has(bbuf, bbn, "BOOTSOV verdict=GREEN" as *u8, 21) 343 if bst == 0 { if btrans == 1 { if bhalt == 1 { blk_ok = 1 } } } 344 } 345 346 g_p(" sovereign_emu=" as *u8) 347 if sov_ok == 1 { g_p("GREEN(transcript==golden+clean-halt)" as *u8) } else { g_p("RED" as *u8) } 348 g_p(" qemu_align=" as *u8) 349 if align == 1 { g_p("yes(real-virtio-net @0x10007000, driver-identical thru-kick, prefix VNET..VQ)" as *u8) } else { g_p("no" as *u8) } 350 g_p(" tamper_bites=" as *u8) 351 if tamper_bites == 1 { g_p("yes(frame-expected corrupt -> FRAME drops)" as *u8) } else { g_p("no" as *u8) } 352 g_p(" blk_untouched=" as *u8) 353 if blk_ok == 1 { g_p("yes(VIO..SECT re-proven)\n" as *u8) } else { g_p("no\n" as *u8) } 354 355 var pass: i64 = 0 356 if sov_ok == 1 { if align == 1 { if tamper_bites == 1 { if blk_ok == 1 { pass = 1 } } } } 357 358 if pass == 1 { 359 g_p("NETLOOPGATE verdict=GREEN (sovereign rv64 emu drove the virtio-NET FRAME loopback @0x10002000; tx-descriptor lay + avail publish + QueueNotify DMA-walk + frame read-back verified; transcript==golden; clean halt; qemu virtio-net-device cross-check @0x10007000 driver-identical thru-kick (prefix VNET..VQ); frame-expected tamper REJECTED; blk @0x10001000 untouched)\n" as *u8) 360 if lfd >= 0 { 361 g_fp(lfd, "NETLOOPGATE verdict=GREEN runtime=sovereign-emu transport=legacy-virtio-mmio device=virtio-net device-id=1 net_base=0x10002000 layer=frame-loopback path=desc-lay|avail-publish|QueueNotify-DMA|frame-readback frame=virtio-net-WIRE_TLV-hdr(flags|gso_type|hdr_len) frame-word=0x0A0A0301 frame-readback=verified transcript==golden align_qemu=yes(virtio-net-device@0x10007000,driver-identical-thru-kick,prefix=VNET_ACK_DRV_FEAT_OK_VQ) tamper=rejected blk=untouched golden=" as *u8) 362 g_fp(lfd, gold) 363 g_fp(lfd, " epoch=" as *u8); g_fn(lfd, sys_now_realtime_sec()); g_fp(lfd, "\n" as *u8); sys_close(lfd) 364 } 365 sys_exit(0); return 0 366 } 367 g_p("NETLOOPGATE verdict=RED (sov_ok/align/tamper/blk not all green)\n" as *u8) 368 if lfd >= 0 { 369 g_fp(lfd, "NETLOOPGATE verdict=RED sov_ok=" as *u8); g_fn(lfd, sov_ok) 370 g_fp(lfd, " align=" as *u8); g_fn(lfd, align) 371 g_fp(lfd, " tamper_bites=" as *u8); g_fn(lfd, tamper_bites) 372 g_fp(lfd, " blk_ok=" as *u8); g_fn(lfd, blk_ok); g_fp(lfd, "\n" as *u8); sys_close(lfd) 373 } 374 sys_exit(1) 375 return 1 376}