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;