boot2

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

hex0.hex0 (7994B)


      1 ## Copyright (C) 2021 Ekaitz Zarraga
      2 ## Copyright (C) 2021 Andrius Štikonas
      3 ## Copyright (C) 2021,2022 Gabriel Wicki
      4 ## This file is part of stage0.
      5 ##
      6 ## stage0 is free software: you can redistribute it and/or modify
      7 ## it under the terms of the GNU General Public License as published by
      8 ## the Free Software Foundation, either version 3 of the License, or
      9 ## (at your option) any later version.
     10 ##
     11 ## stage0 is distributed in the hope that it will be useful,
     12 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 ## GNU General Public License for more details.
     15 ##
     16 ## You should have received a copy of the GNU General Public License
     17 ## along with stage0.  If not, see <http://www.gnu.org/licenses/>.
     18 
     19 ; Register use:
     20 ; s2: input fd
     21 ; s3: output fd
     22 ; s4: toggle
     23 ; s5: hold
     24 
     25 ; Uses top of the stack as i/o buffer
     26 
     27 ## ELF Header
     28 #:ELF_base
     29 7F 45 4C 46        # e_ident[EI_MAG0-3] ELF's magic number
     30 
     31 01                 # e_ident[EI_CLASS] Indicating 32 bit
     32 01                 # e_ident[EI_DATA] Indicating little endianness
     33 01                 # e_ident[EI_VERSION] Indicating original elf
     34 
     35 03                 # e_ident[EI_OSABI] Set at 3 for Linux
     36 00                 # e_ident[EI_ABIVERSION] Ignored for Statically linked executables
     37 
     38 00 00 00 00 00 00 00 # e_ident[EI_PAD]
     39 02 00              # e_type Indicating Executable
     40 F3 00              # e_machine Indicating RISC-V
     41 01 00 00 00        # e_version Indicating original elf
     42 
     43 54 00 60 00        # e_entry Address of the entry point
     44 34 00 00 00        # e_phoff Address of program header table
     45 00 00 00 00        # e_shoff Address of section header table
     46 
     47 00 00 00 00        # e_flags
     48 
     49 34 00              # e_ehsize Indicating our 52 Byte header
     50 
     51 20 00              # e_phentsize size of a program header table
     52 01 00              # e_phnum number of entries in program table
     53 
     54 00 00              # e_shentsize size of a section header table
     55 00 00              # e_shnum number of entries in section table
     56 
     57 00 00              # e_shstrndx index of the section names
     58 
     59 ## Program Header
     60 #:ELF_program_headers
     61 #:ELF_program_header__text
     62 01 00 00 00        # ph_type: PT-LOAD = 1
     63 00 00 00 00        # ph_offset
     64 
     65 00 00 60 00        # ph_vaddr
     66 00 00 60 00        # ph_physaddr
     67 
     68 64 01 00 00        # ph_filesz
     69 64 01 00 00        # ph_memsz
     70 
     71 07 00 00 00        # ph_flags: PF-X|PF-W|PF-R = 7
     72 01 00 00 00        # ph_align
     73 
     74 # :_start ; (0x0600054)
     75     13 0A 00 00    # rd_s4 mv                 ; Initialize register
     76     83 25 81 00    # rd_a1 rs1_sp !8 lw       ; Input file name
     77 
     78     ; Open input file and store FD in s2
     79     93 08 80 03    # rd_a7 !56 addi           ; sys_openat
     80     13 05 C0 F9    # rd_a0 !-100 addi         ; AT_FDCWD
     81     13 06 00 00    # rd_a2 mv                 ; read only
     82     73 00 00 00    # ecall
     83     13 09 05 00    # rd_s2 rs1_a0 mv          ; Save fd in s2 for later
     84 
     85     ; Open output file and store the FD in s3
     86     13 05 C0 F9    # rd_a0 !-100 addi         ; AT_FDCWD
     87     83 25 C1 00    # rd_a1 rs1_sp !12 lw      ; Output file (argument 3)
     88     13 06 10 24    # rd_a2 !577 addi          ; octal 00001101
     89     ; O_TRUNC   00001000
     90     ; O_CREAT   00000100
     91     ; O_WRONLY  00000001
     92     ; OCTAL!
     93 
     94     93 06 00 1C    # rd_a3 !448 addi          ; Set read, write, execute permission on user
     95     ; S_IRWXU  00700
     96     ; OCTAL!
     97 
     98     73 00 00 00    # ecall
     99     93 09 05 00    # rd_s3 rs1_a0 mv          ; Save fd in s3 for later
    100 
    101 # :next_byte ; (0x0600088)
    102     93 08 F0 03    # rd_a7 !63 addi           ; sys_read
    103     13 05 09 00    # rd_a0 rs1_s2 mv          ; File descriptor
    104     93 05 01 00    # rd_a1 rs1_sp mv          ; Buffer
    105     13 06 10 00    # rd_a2 !1 addi            ; Size of what we want to read (set for all subsequent syscalls)
    106     73 00 00 00    # ecall
    107 
    108     ; If the file ended (0 bytes read) terminate
    109     63 00 05 0C    # rs1_a0 @terminate beqz
    110                    # +192B
    111 
    112     ; Check if it's a comment
    113     03 05 01 00    # rd_a0 rs1_sp lb
    114     93 02 30 02    # rd_t0 !0x23 addi
    115     63 08 55 00    # rs1_a0 rs2_t0 @loop beq  ; a0 eq to '#'
    116                    # +16B
    117     93 02 B0 03    # rd_t0 !0x3B addi
    118     63 04 55 00    # rs1_a0 rs2_t0 @loop beq  ; a0 eq to ';'
    119                    # +8B
    120     6F 00 80 02    # $not_comment jal
    121                    # +40B
    122 # :loop ; (0x06000B8)
    123         13 05 09 00    # rd_a0 rs1_s2 mv   ; File descriptor
    124         73 00 00 00    # ecall             ; sys_read
    125 
    126         ; If the file ended (0 bytes read) terminate
    127         63 0E 05 08    # rs1_a0 @terminate beqz
    128                        # +156B
    129         ; Check if read byte is the end of the comment (i.e. a newline character),
    130         ; in that case we continue processing
    131         03 05 01 00     # rd_a0 rs1_sp lb
    132         93 02 A0 00     # rd_t0 !0xA addi
    133         E3 0E 55 FA     # rs1_a0 rs2_t0 @next_byte beq ; a0 eq to \n
    134                         # -68B
    135         93 02 D0 00     # rd_t0 !0xD addi
    136         E3 0A 55 FA     # rs1_a0 rs2_t0 @next_byte beq ; a0 eq to \r
    137                         # -76B
    138     6F F0 1F FE    # $loop jal
    139 # :not_comment ; (0x06000DC)
    140     ; Check if it's a hex character:
    141     ; in the case it's not, ignores and reads next byte
    142     03 05 01 00    # rd_a0 rs1_sp lb
    143 
    144     ; Is it between '0' and '9'?
    145     93 02 00 03    # rd_t0 !48 addi           ; '0' character
    146     63 4A 55 00    # rs1_a0 rs2_t0 @uppercase_alpha blt
    147                    # +20B
    148     93 02 90 03    # rd_t0 !57 addi           ; '9' character
    149     63 C6 A2 00    # rs1_t0 rs2_a0 @uppercase_alpha blt
    150                    # +12B
    151     13 05 05 FD    # rd_a0 rs1_a0 !-48 addi
    152     6F 00 00 03    # $hex_read jal
    153                    # +48B
    154 # :uppercase_alpha ; (0x06000F8)
    155     ; Is it between 'A' and 'F'?
    156     93 02 10 04    # rd_t0 !65 addi           ; 'A' character
    157     63 4A 55 00    # rs1_a0 rs2_t0 @lowercase_alpha blt
    158                    # +20B
    159     93 02 60 04    # rd_t0 !70 addi           ; 'F' character
    160     63 C6 A2 00    # rs1_t0 rs2_a0 @lowercase_alpha blt
    161                    # +12B
    162     13 05 95 FC    # rd_a0 rs1_a0 !-55 addi
    163     6F 00 80 01    # $hex_read jal
    164                    # +24B
    165 # :lowercase_alpha ; (0x0600110)
    166     ; Is it between 'a' and 'f'?
    167     93 02 10 06    # rd_t0 !97 addi           ; 'a' character
    168     E3 4A 55 F6    # rs1_a0 rs2_t0 @next_byte blt ; Not hex, continue reading
    169                    # -140B
    170     93 02 60 06    # rd_t0 !102 addi          ; 'f' character
    171     E3 C6 A2 F6    # rs1_t0 rs2_a0 @next_byte blt ; Not hex, continue reading
    172                    # -148B
    173     13 05 95 FA    # rd_a0 rs1_a0 !-87 addi
    174 # :hex_read ; (0x0600124)
    175     ; END check hex -- leaves the half byte in a0
    176 
    177     63 18 0A 00    # rs1_s4 @combine bnez     ; if toggle != 0 -> combine
    178                    # +16B
    179     ; Toggle == 0, we need to prepare for later
    180     93 0A 05 00    # rd_s5 rs1_a0 mv          ; Load hold
    181 
    182     13 0A 10 00    # rd_s4 !1 addi            ; Set toggle
    183     6F F0 9F F5    # $next_byte jal           ; Read next byte
    184                    # -168B
    185 
    186 # :combine ; (0x0600134)
    187     ; Combine half bytes
    188     93 95 4A 00    # rd_a1 rs1_s5 rs2_x4 slli ; Shift logical left 4 times
    189     33 05 B5 00    # rd_a0 rs1_a0 rs2_a1 add  ; Combine two half bytes
    190     ; Leaves the full byte in a0
    191 
    192     ; Values are combined, now we write in the file
    193     23 00 A1 00    # rs1_sp rs2_a0 sb         ; Store prepared byte in buffer
    194     93 08 00 04    # rd_a7 !64 addi           ; sys_write
    195     13 85 09 00    # rd_a0 rs1_s3 mv          ; file descriptor (stdout)
    196     93 05 01 00    # rd_a1 rs1_sp mv          ; string address
    197     73 00 00 00    # ecall
    198 
    199     ; Update globals
    200     13 0A 00 00    # rd_s4 mv                 ; Clear toggle
    201     93 0A 00 00    # rd_s5 mv                 ; Clear hold
    202 
    203     ; Read next byte
    204     6F F0 1F F3    # $next_byte jal
    205                    # -208B
    206 
    207 # :terminate  ; (0x60015C)
    208     ; Terminate program with 0 return code
    209     93 08 D0 05    # rd_a7 !93 addi           ; sys_exit
    210     73 00 00 00    # ecall
    211 # PROGRAM END
    212 
    213 # :ELF_end ; (0x600164)