boot2

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

hex0.hex0 (8065B)


      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 02                 ## e_ident[EI_CLASS] Indicating 64 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 78 00 60 00 00 00 00 00 ## e_entry Address of the entry point (Number of bytes this header is + Base Address)
     44 40 00 00 00 00 00 00 00 ## e_phoff Address of program header table
     45 00 00 00 00 00 00 00 00 ## e_shoff Address of section header table
     46 
     47 00 00 00 00        ## e_flags
     48 40 00              ## e_ehsize Indicating our 64 Byte header
     49 
     50 38 00              ## e_phentsize size of a program header table
     51 01 00              ## e_phnum number of entries in program table
     52 
     53 00 00              ## e_shentsize size of a section header table
     54 00 00              ## e_shnum number of entries in section table
     55 
     56 00 00              ## e_shstrndx index of the section names
     57 
     58 ## Program Header
     59 #:ELF_program_headers
     60 01 00 00 00             ## p_type
     61 07 00 00 00             ## Flags
     62 00 00 00 00 00 00 00 00 ## p_offset
     63 
     64 00 00 60 00 00 00 00 00 ## p_vaddr
     65 00 00 60 00 00 00 00 00 ## p_physaddr
     66 
     67 88 01 00 00 00 00 00 00 ## p_filesz
     68 88 01 00 00 00 00 00 00 ## p_memsz
     69 
     70 01 00 00 00 00 00 00 00 ## Required alignment
     71 
     72 # :_start ; (0x0600078)
     73     13 0A 00 00    # rd_s4 mv                 ; Initialize register
     74     83 35 01 01    # rd_a1 rs1_sp !16 ld      ; Input file name
     75 
     76     ; Open input file and store FD in s2
     77     93 08 80 03    # rd_a7 !56 addi           ; sys_openat
     78     13 05 C0 F9    # rd_a0 !-100 addi         ; AT_FDCWD
     79     13 06 00 00    # rd_a2 mv                 ; read only
     80     73 00 00 00    # ecall
     81     13 09 05 00    # rd_s2 rs1_a0 mv          ; Save fd in s2 for later
     82 
     83     ; Open output file and store the FD in s3
     84     13 05 C0 F9    # rd_a0 !-100 addi         ; AT_FDCWD
     85     83 35 81 01    # rd_a1 rs1_sp !24 ld      ; Output file (argument 3)
     86     13 06 10 24    # rd_a2 !577 addi          ; octal 00001101
     87     ; O_TRUNC   00001000
     88     ; O_CREAT   00000100
     89     ; O_WRONLY  00000001
     90     ; OCTAL!
     91 
     92     93 06 00 1C    # rd_a3 !448 addi          ; Set read, write, execute permission on user
     93     ; S_IRWXU  00700
     94     ; OCTAL!
     95 
     96     73 00 00 00    # ecall
     97     93 09 05 00    # rd_s3 rs1_a0 mv          ; Save fd in s3 for later
     98 
     99 # :next_byte ; (0x06000AC)
    100     93 08 F0 03    # rd_a7 !63 addi           ; sys_read
    101     13 05 09 00    # rd_a0 rs1_s2 mv          ; File descriptor
    102     93 05 01 00    # rd_a1 rs1_sp mv          ; Buffer
    103     13 06 10 00    # rd_a2 !1 addi            ; Size of what we want to read (set for all subsequent syscalls)
    104     73 00 00 00    # ecall
    105 
    106     ; If the file ended (0 bytes read) terminate
    107     63 00 05 0C    # rs1_a0 @terminate beqz
    108                    # +192B
    109 
    110     ; Check if it's a comment
    111     03 05 01 00    # rd_a0 rs1_sp lb
    112     93 02 30 02    # rd_t0 !0x23 addi
    113     63 08 55 00    # rs1_a0 rs2_t0 @loop beq  ; a0 eq to '#'
    114                    # +16B
    115     93 02 B0 03    # rd_t0 !0x3B addi
    116     63 04 55 00    # rs1_a0 rs2_t0 @loop beq  ; a0 eq to ';'
    117                    # +8B
    118     6F 00 80 02    # $not_comment jal
    119                    # +40B
    120 # :loop ; (0x06000DC)
    121         13 05 09 00    # rd_a0 rs1_s2 mv   ; File descriptor
    122         73 00 00 00    # ecall             ; sys_read
    123 
    124         ; If the file ended (0 bytes read) terminate
    125         63 0E 05 08    # rs1_a0 @terminate beqz
    126                        # +156B
    127         ; Check if read byte is the end of the comment (i.e. a newline character),
    128         ; in that case we continue processing
    129         03 05 01 00     # rd_a0 rs1_sp lb
    130         93 02 A0 00     # rd_t0 !0xA addi
    131         E3 0E 55 FA     # rs1_a0 rs2_t0 @next_byte beq ; a0 eq to \n
    132                         # -68B
    133         93 02 D0 00     # rd_t0 !0xD addi
    134         E3 0A 55 FA     # rs1_a0 rs2_t0 @next_byte beq ; a0 eq to \r
    135                         # -76B
    136     6F F0 1F FE    # $loop jal
    137 # :not_comment ; (0x0600100)
    138     ; Check if it's a hex character:
    139     ; in the case it's not, ignores and reads next byte
    140     03 05 01 00    # rd_a0 rs1_sp lb
    141 
    142     ; Is it between '0' and '9'?
    143     93 02 00 03    # rd_t0 !48 addi           ; '0' character
    144     63 4A 55 00    # rs1_a0 rs2_t0 @uppercase_alpha blt
    145                    # +20B
    146     93 02 90 03    # rd_t0 !57 addi           ; '9' character
    147     63 C6 A2 00    # rs1_t0 rs2_a0 @uppercase_alpha blt
    148                    # +12B
    149     13 05 05 FD    # rd_a0 rs1_a0 !-48 addi
    150     6F 00 00 03    # $hex_read jal
    151                    # +48B
    152 # :uppercase_alpha ; (0x060011C)
    153     ; Is it between 'A' and 'F'?
    154     93 02 10 04    # rd_t0 !65 addi           ; 'A' character
    155     63 4A 55 00    # rs1_a0 rs2_t0 @lowercase_alpha blt
    156                    # +20B
    157     93 02 60 04    # rd_t0 !70 addi           ; 'F' character
    158     63 C6 A2 00    # rs1_t0 rs2_a0 @lowercase_alpha blt
    159                    # +12B
    160     13 05 95 FC    # rd_a0 rs1_a0 !-55 addi
    161     6F 00 80 01    # $hex_read jal
    162                    # +24B
    163 # :lowercase_alpha ; (0x0600134)
    164     ; Is it between 'a' and 'f'?
    165     93 02 10 06    # rd_t0 !97 addi           ; 'a' character
    166     E3 4A 55 F6    # rs1_a0 rs2_t0 @next_byte blt ; Not hex, continue reading
    167                    # -140B
    168     93 02 60 06    # rd_t0 !102 addi          ; 'f' character
    169     E3 C6 A2 F6    # rs1_t0 rs2_a0 @next_byte blt ; Not hex, continue reading
    170                    # -148B
    171     13 05 95 FA    # rd_a0 rs1_a0 !-87 addi
    172 # :hex_read ; (0x0600148)
    173     ; END check hex -- leaves the half byte in a0
    174 
    175     63 18 0A 00    # rs1_s4 @combine bnez     ; if toggle != 0 -> combine
    176                    # +16B
    177     ; Toggle == 0, we need to prepare for later
    178     93 0A 05 00    # rd_s5 rs1_a0 mv          ; Load hold
    179 
    180     13 0A 10 00    # rd_s4 !1 addi            ; Set toggle
    181     6F F0 9F F5    # $next_byte jal           ; Read next byte
    182                    # -168B
    183 
    184 # :combine ; (0x0600158)
    185     ; Combine half bytes
    186     93 95 4A 00    # rd_a1 rs1_s5 rs2_x4 slli ; Shift logical left 4 times
    187     33 05 B5 00    # rd_a0 rs1_a0 rs2_a1 add  ; Combine two half bytes
    188     ; Leaves the full byte in a0
    189 
    190     ; Values are combined, now we write in the file
    191     23 00 A1 00    # rs1_sp rs2_a0 sb         ; Store prepared byte in buffer
    192     93 08 00 04    # rd_a7 !64 addi           ; sys_write
    193     13 85 09 00    # rd_a0 rs1_s3 mv          ; file descriptor (stdout)
    194     93 05 01 00    # rd_a1 rs1_sp mv          ; string address
    195     73 00 00 00    # ecall
    196 
    197     ; Update globals
    198     13 0A 00 00    # rd_s4 mv                 ; Clear toggle
    199     93 0A 00 00    # rd_s5 mv                 ; Clear hold
    200 
    201     ; Read next byte
    202     6F F0 1F F3    # $next_byte jal
    203                    # -208B
    204 
    205 # :terminate  ; (0x600180)
    206     ; Terminate program with 0 return code
    207     93 08 D0 05    # rd_a7 !93 addi           ; sys_exit
    208     73 00 00 00    # ecall
    209 # PROGRAM END
    210 
    211 # :ELF_end ; (0x600188)