sylveos

Toy Operating System
Log | Files | Refs

bootloader.zig (1721B)


      1 const std = @import("std");
      2 const pi = @import("pi");
      3 
      4 const net = @import("shared").bootloader_protocol;
      5 
      6 const uart = pi.devices.mini_uart;
      7 const clock = pi.devices.clock;
      8 
      9 const Message = net.Message;
     10 const Error = net.Error;
     11 
     12 const MAX_ADDR = 0x200000;
     13 
     14 pub fn main() !void {
     15     // w - UART (safe)
     16     // r - UART (safe)
     17     const w = &uart.writer;
     18     const r = &uart.reader;
     19 
     20     while (true) {
     21         // UART cannot fail
     22         try net.put_message(w, .GET_PROG_INFO);
     23 
     24         if (uart.read_queue_length() >= 4) {
     25             const response = try net.get_u32(r);
     26 
     27             if (response == @intFromEnum(Message.PUT_PROG_INFO)) break;
     28         }
     29 
     30         clock.delay_ms(300);
     31     }
     32 
     33     const header = net.receive_header(r, MAX_ADDR) catch |e| switch (e) {
     34         Error.BadAddress => {
     35             try net.put_message(w, .BAD_CODE_ADDR);
     36 
     37             return pi.reboot();
     38         },
     39         else => unreachable,
     40     };
     41 
     42     try net.request_code(w, header.checksum);
     43 
     44     while (true) {
     45         if (uart.read_queue_length() >= 4) {
     46             const response = try net.get_u32(r);
     47 
     48             if (response == @intFromEnum(Message.PUT_CODE)) break;
     49         }
     50     }
     51 
     52     var start_ptr: [*]u8 = @ptrFromInt(header.arm_base);
     53     net.receive_code(r, start_ptr[0..(header.n_bytes)], header) catch |e| switch (e) {
     54         Error.BadChecksum => {
     55             try net.put_message(w, .BAD_CODE_CKSUM);
     56 
     57             return pi.reboot();
     58         },
     59         else => unreachable,
     60     };
     61 
     62     try net.put_message(w, .BOOT_SUCCESS);
     63     uart.flush();
     64 
     65     branch_to(@ptrCast(start_ptr));
     66 }
     67 
     68 comptime {
     69     asm (
     70         \\ .globl branch_to
     71         \\ branch_to:
     72         \\ bx r0
     73     );
     74 }
     75 extern fn branch_to(to: *u8) noreturn;