boot2

Playing with the boostrap
git clone https://git.ryansepassi.com/git/boot2.git
Log | Files | Refs | README

catm.P1pp (4729B)


      1 # catm.P1pp -- P1pp implementation of `catm`.
      2 #
      3 # Mirrors vendor/seed/$ARCH/catm.hex2 (Jeremiah Orians' stage0 catm):
      4 #   catm OUT IN1 IN2 ...   -> writes the concatenation of IN1..INn to OUT.
      5 #
      6 # OUT is opened O_WRONLY|O_CREAT|O_TRUNC with mode 0640. With zero inputs
      7 # OUT is created and left empty. Errors (open/read/write) print to stderr
      8 # and exit nonzero.
      9 #
     10 # Built once M1pp + hex2pp exist (boot1) so later stages can replace the
     11 # seed boot0 catm. The pipeline is the standard P1pp shape:
     12 #
     13 #   catm  P1-<arch>.M1pp P1.M1pp P1pp.P1pp catm/catm.P1pp -> combined.M1pp
     14 #   M1pp  combined.M1pp                                   -> expanded.hex2pp
     15 #   catm  ELF.hex2 expanded.hex2pp                        -> linked.hex2pp
     16 #   hex2pp -B 0x600000 linked.hex2pp                      -> ELF binary
     17 
     18 %macro CATM_BUFSIZE() 0x100000 %endm                  # 1 MiB read/write chunk
     19 %macro CATM_O_RDONLY() 0 %endm
     20 %macro CATM_O_WRONLY_CREAT_TRUNC() 0x241 %endm        # O_WRONLY|O_CREAT|O_TRUNC
     21 %macro CATM_MODE_0640() 0x1A0 %endm                   # 0640 octal
     22 
     23 # 8-aligned NUL-terminated string (mirrors scheme1.P1pp's helper).
     24 %macro cstr8(str)
     25     str
     26     00
     27     .align 8
     28 %endm
     29 
     30 # argc / argv / out_fd / i live in callee-saved s0..s3 across the whole
     31 # function. The inner copy/write loop spills in_fd / remaining-bytes /
     32 # write-cursor to the frame because t-regs are clobbered by the sys_*
     33 # %calls. %fn2 synthesizes a p1_main_FRAME struct from the local list.
     34 %fn2(p1_main, {in_fd, remain, wptr}, {
     35     %mov(s0, a0)                            # s0 = argc
     36     %mov(s1, a1)                            # s1 = argv
     37 
     38     # Initialize buf_ptr from &ELF_end via libp1pp's arena helper.
     39     %la(a0, &ELF_end)
     40     %la(a1, &arena_table)
     41     %la(a2, &arena_table_end)
     42     %call(&init_arenas)
     43 
     44     # Need at least: catm OUT
     45     %li(t0, 2)
     46     %bltu(s0, t0, &.usage)
     47 
     48     # Open OUT = argv[1].
     49     %ld(a0, s1, 8)
     50     %li(a1, %CATM_O_WRONLY_CREAT_TRUNC)
     51     %li(a2, %CATM_MODE_0640)
     52     %call(&sys_open)
     53     %bltz(a0, &.open_fail)
     54     %mov(s2, a0)                            # s2 = out_fd
     55 
     56     # i = 2; while (i < argc) { copy argv[i] -> out_fd; i++ }
     57     %li(s3, 2)
     58     :.arg_loop
     59         %beq(s3, s0, &.arg_done)            # i == argc -> done
     60 
     61         # in_path = argv[i]
     62         %shli(t0, s3, 3)
     63         %add(t0, s1, t0)
     64         %ld(a0, t0, 0)
     65         %li(a1, %CATM_O_RDONLY)
     66         %li(a2, 0)
     67         %call(&sys_open)
     68         %bltz(a0, &.open_fail)
     69         %stl(a0, in_fd)
     70 
     71         :.copy_loop
     72             %ldl(a0, in_fd)
     73             %ld_global(a1, &buf_ptr)
     74             %li(a2, %CATM_BUFSIZE)
     75             %call(&sys_read)
     76             %beqz(a0, &.copy_done)          # EOF
     77             %bltz(a0, &.read_fail)
     78 
     79             # write_all(out_fd, buf, n)
     80             %stl(a0, remain)
     81             %ld_global(t0, &buf_ptr)
     82             %stl(t0, wptr)
     83             :.write_loop
     84                 %ldl(a2, remain)
     85                 %beqz(a2, &.write_done)
     86                 %mov(a0, s2)
     87                 %ldl(a1, wptr)
     88                 %call(&sys_write)
     89                 %bltz(a0, &.write_fail)
     90                 %ldl(t0, wptr)
     91                 %add(t0, t0, a0)
     92                 %stl(t0, wptr)
     93                 %ldl(t0, remain)
     94                 %sub(t0, t0, a0)
     95                 %stl(t0, remain)
     96                 %b(&.write_loop)
     97             :.write_done
     98 
     99             %b(&.copy_loop)
    100         :.copy_done
    101 
    102         %ldl(a0, in_fd)
    103         %call(&sys_close)
    104 
    105         %addi(s3, s3, 1)
    106         %b(&.arg_loop)
    107     :.arg_done
    108 
    109     %mov(a0, s2)
    110     %call(&sys_close)
    111     %li(a0, 0)
    112     %b(&.exit)
    113 
    114     :.usage
    115     %la(a0, &msg_usage)
    116     %call(&eprint_cstr)
    117     %li(a0, 2)
    118     %b(&.exit)
    119 
    120     :.open_fail
    121     %la(a0, &msg_open_fail)
    122     %call(&eprint_cstr)
    123     %li(a0, 1)
    124     %b(&.exit)
    125 
    126     :.read_fail
    127     %la(a0, &msg_read_fail)
    128     %call(&eprint_cstr)
    129     %li(a0, 1)
    130     %b(&.exit)
    131 
    132     :.write_fail
    133     %la(a0, &msg_write_fail)
    134     %call(&eprint_cstr)
    135     %li(a0, 1)
    136 
    137     :.exit
    138 })
    139 
    140 # ---- read-only data -------------------------------------------------------
    141 
    142 :msg_usage      %cstr8("usage: catm OUT [IN ...]
    143 ")
    144 :msg_open_fail  %cstr8("catm: open failed
    145 ")
    146 :msg_read_fail  %cstr8("catm: read failed
    147 ")
    148 :msg_write_fail %cstr8("catm: write failed
    149 ")
    150 
    151 # ---- BSS arena table ------------------------------------------------------
    152 #
    153 # One arena past :ELF_end: a single 1 MiB read/write buffer. init_arenas
    154 # walks the (slot, size) rows once at startup and writes &ELF_end into
    155 # &buf_ptr. The ELF p_memsz reservation in vendor/seed/$ARCH/ELF.hex2
    156 # (512 MiB) covers it with plenty of headroom.
    157 
    158 :arena_table
    159 %arena_entry(&buf_ptr, %CATM_BUFSIZE)
    160 :arena_table_end
    161 
    162 # ---- BSS slots (file-resident, zero-initialized) --------------------------
    163 
    164 :buf_ptr  $(0)
    165 
    166 :ELF_end