├── .checkpatch.conf ├── .clang-format ├── .github └── auto-merge.yml ├── .gitignore ├── .gitmodules ├── COPYING ├── Documentation ├── getting-started.md ├── opentitan │ └── README.md └── sifive │ ├── dediprog.jpg │ ├── msel.jpg │ ├── opensbi.md │ ├── setup.md │ └── usb.jpg ├── Makefile ├── Makefile.inc ├── Makefile.mode.debug.inc ├── Makefile.mode.release.inc ├── Makefile.qemu.inc ├── README.md ├── azure-pipelines.yml ├── payloads ├── Cargo.lock ├── Cargo.toml └── src │ ├── external │ ├── mod.rs │ ├── simple │ │ ├── testtesttest │ │ └── testtesttest.S │ └── zimage │ │ ├── mod.rs │ │ ├── qemu_fdt.dtb │ │ └── zImage │ ├── lib.rs │ ├── payload.rs │ └── serialize.rs ├── rustfmt.toml ├── scripts └── generate-size-report.sh ├── src ├── arch │ ├── arm │ │ └── armv7 │ │ │ ├── Cargo.toml │ │ │ └── src │ │ │ ├── lib.rs │ │ │ └── mmu.S │ ├── riscv │ │ ├── mod.rs │ │ ├── rv32 │ │ │ ├── Cargo.toml │ │ │ └── src │ │ │ │ ├── lib.rs │ │ │ │ ├── mod.rs │ │ │ │ └── reg.rs │ │ └── rv64 │ │ │ ├── Cargo.toml │ │ │ └── src │ │ │ ├── lib.rs │ │ │ ├── mod.rs │ │ │ └── reg.rs │ └── x86 │ │ └── x86_64 │ │ ├── Cargo.lock │ │ ├── Cargo.toml │ │ └── src │ │ ├── bios.rs │ │ ├── bootblock.S │ │ ├── bzimage.rs │ │ ├── ioport.rs │ │ └── lib.rs ├── console │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── cpu │ ├── armltd │ │ └── cortex-a9 │ │ │ ├── Cargo.toml │ │ │ └── src │ │ │ └── lib.rs │ └── lowrisc │ │ └── ibex │ │ ├── Cargo.toml │ │ └── src │ │ └── lib.rs ├── custom_targets │ ├── arm-none-eabihf.json │ └── x86_64-unknown-none.json ├── drivers │ ├── clock │ │ ├── Cargo.lock │ │ ├── Cargo.toml │ │ └── src │ │ │ └── lib.rs │ ├── model │ │ ├── Cargo.lock │ │ ├── Cargo.toml │ │ └── src │ │ │ └── lib.rs │ ├── sifive │ │ └── spi │ │ │ ├── Cargo.lock │ │ │ ├── Cargo.toml │ │ │ └── src │ │ │ └── lib.rs │ ├── uart │ │ ├── Cargo.lock │ │ ├── Cargo.toml │ │ └── src │ │ │ ├── debug_port.rs │ │ │ ├── i8250.rs │ │ │ ├── lib.rs │ │ │ ├── log.rs │ │ │ ├── ns16550.rs │ │ │ ├── null.rs │ │ │ ├── opentitan.rs │ │ │ ├── pl011.rs │ │ │ └── sifive.rs │ └── wrappers │ │ ├── Cargo.lock │ │ ├── Cargo.toml │ │ ├── src │ │ └── lib.rs │ │ └── tests │ │ └── tests.rs ├── lib │ ├── consts │ │ ├── Cargo.lock │ │ ├── Cargo.toml │ │ └── src │ │ │ └── lib.rs │ ├── device_tree │ │ ├── Cargo.lock │ │ ├── Cargo.toml │ │ ├── src │ │ │ └── lib.rs │ │ └── tests │ │ │ └── integration_test.rs │ ├── print │ │ ├── Cargo.lock │ │ ├── Cargo.toml │ │ └── src │ │ │ └── lib.rs │ └── util │ │ ├── Cargo.lock │ │ ├── Cargo.toml │ │ └── src │ │ └── lib.rs ├── mainboard │ ├── amd │ │ └── romecrb │ │ │ ├── .cargo │ │ │ └── config │ │ │ ├── Cargo.lock │ │ │ ├── Cargo.toml │ │ │ ├── Makefile │ │ │ ├── build.rs │ │ │ ├── fixed-dtfs.dts │ │ │ ├── jmporeboot.S │ │ │ ├── jmporeboot.bin │ │ │ ├── link.ld │ │ │ ├── loop.S │ │ │ ├── loop.bin │ │ │ ├── patch.go │ │ │ ├── pt.go │ │ │ └── src │ │ │ ├── bootblock.S │ │ │ ├── dsdt.asl │ │ │ ├── main.rs │ │ │ ├── mainboard.rs │ │ │ ├── romstage.rs │ │ │ └── vboot-rwa-16M.fmd │ ├── asrock │ │ └── a300m-stx │ │ │ ├── patch.go │ │ │ ├── serial.S │ │ │ └── serial.bin │ ├── ast │ │ └── ast25x0 │ │ │ ├── .cargo │ │ │ └── config │ │ │ ├── Cargo.lock │ │ │ ├── Cargo.toml │ │ │ ├── Makefile │ │ │ ├── README.md │ │ │ ├── build.rs │ │ │ ├── link.ld │ │ │ ├── platins.S │ │ │ ├── src │ │ │ ├── main.rs │ │ │ ├── romstage │ │ │ │ ├── asmram.rs │ │ │ │ ├── asmram │ │ │ │ │ ├── ram.rs │ │ │ │ │ └── ramtable.rs │ │ │ │ ├── chain.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── new.rs │ │ │ │ ├── ramconst.rs │ │ │ │ └── ramtable.rs │ │ │ └── vector_table.S │ │ │ └── trans.go │ ├── emulation │ │ ├── qemu-armv7 │ │ │ ├── .cargo │ │ │ │ └── config │ │ │ ├── Cargo.lock │ │ │ ├── Cargo.toml │ │ │ ├── Makefile │ │ │ ├── build.rs │ │ │ ├── fixed-dtfs.dts │ │ │ ├── link.ld │ │ │ └── src │ │ │ │ ├── main.rs │ │ │ │ ├── romstage.rs │ │ │ │ └── vector_table.S │ │ ├── qemu-q35 │ │ │ ├── .cargo │ │ │ │ └── config │ │ │ ├── Cargo.lock │ │ │ ├── Cargo.toml │ │ │ ├── Makefile │ │ │ ├── build.rs │ │ │ ├── fixed-dtfs.dts │ │ │ ├── link.ld │ │ │ └── src │ │ │ │ ├── dsdt.asl │ │ │ │ ├── main.rs │ │ │ │ ├── romstage.rs │ │ │ │ └── vboot-rwa-16M.fmd │ │ └── qemu-riscv │ │ │ ├── .cargo │ │ │ └── config │ │ │ ├── Cargo.lock │ │ │ ├── Cargo.toml │ │ │ ├── Makefile │ │ │ ├── build.rs │ │ │ ├── fixed-dtfs.dts │ │ │ ├── link.ld │ │ │ └── src │ │ │ ├── bootblock.S │ │ │ ├── init.S │ │ │ └── main.rs │ ├── nuvoton │ │ └── npcm7xx │ │ │ ├── .cargo │ │ │ └── config │ │ │ ├── Cargo.lock │ │ │ ├── Cargo.toml │ │ │ ├── Makefile │ │ │ ├── README │ │ │ ├── build.rs │ │ │ ├── fixed-dtfs.dts │ │ │ ├── kernel │ │ │ ├── link.ld │ │ │ └── src │ │ │ └── main.rs │ ├── opentitan │ │ └── crb │ │ │ ├── .cargo │ │ │ └── config │ │ │ ├── Cargo.lock │ │ │ ├── Cargo.toml │ │ │ ├── Makefile │ │ │ ├── README.md │ │ │ ├── build.rs │ │ │ ├── fixed-dtfs.dts │ │ │ ├── link.ld │ │ │ └── src │ │ │ └── main.rs │ └── sifive │ │ └── hifive │ │ ├── .cargo │ │ └── config │ │ ├── Cargo.lock │ │ ├── Cargo.toml │ │ ├── Makefile │ │ ├── build.rs │ │ ├── fixed-dtfs.dts │ │ ├── kernel │ │ ├── link.ld │ │ ├── openocd.cfg │ │ └── src │ │ ├── hifive.dtb │ │ ├── hifive.dts │ │ └── main.rs ├── soc │ ├── aspeed │ │ └── ast2500 │ │ │ ├── Cargo.toml │ │ │ └── src │ │ │ ├── lib.rs │ │ │ └── reg.rs │ ├── opentitan │ │ └── earlgrey │ │ │ ├── Cargo.toml │ │ │ └── src │ │ │ ├── bootblock.S │ │ │ └── lib.rs │ └── sifive │ │ └── fu540 │ │ ├── Cargo.toml │ │ └── src │ │ ├── bootblock.S │ │ ├── clock.rs │ │ ├── ctl.rs │ │ ├── ddr.rs │ │ ├── ddrregs.rs │ │ ├── init.S │ │ ├── lib.rs │ │ ├── phy.rs │ │ ├── reg.rs │ │ ├── spi.rs │ │ └── ux00.rs └── vendorcode │ └── fsp │ └── coffeelake │ ├── Cargo.lock │ ├── Cargo.toml │ ├── build.rs │ └── src │ ├── lib.rs │ └── wrapper.h └── tools ├── bin2vmem ├── Cargo.lock ├── Cargo.toml └── src │ ├── main.rs │ └── testdata │ ├── example.raw │ └── example.vmem ├── layoutflash ├── Cargo.lock ├── Cargo.toml └── src │ ├── main.rs │ └── testdata │ ├── test.dtb │ └── test.dts ├── opentitanregisters ├── main.go ├── pinmux.hjson └── uart.hjson └── soc └── sifive └── fu540 ├── Makefile ├── link.ld └── serialdebug.S /.checkpatch.conf: -------------------------------------------------------------------------------- 1 | # Not Linux, so don't expect a Linux tree. 2 | --no-tree 3 | 4 | # Ignore aspects we don't follow here. 5 | --ignore C99_COMMENTS 6 | --ignore GLOBAL_INITIALISERS 7 | --ignore INITIALISED_STATIC 8 | --ignore LINE_SPACING 9 | --ignore NEW_TYPEDEFS 10 | --ignore PREFER_ALIGNED 11 | --ignore PREFER_PACKED 12 | --ignore PREFER_PRINTF 13 | --ignore SPLIT_STRING 14 | --ignore BLOCK_COMMENT_STYLE 15 | --ignore AVOID_EXTERNS 16 | --ignore VOLATILE 17 | --ignore CONFIG_DESCRIPTION 18 | --ignore MISSING_SPACE 19 | --ignore CORRUPTED_PATCH 20 | --ignore SPDX_LICENSE_TAG 21 | --ignore UNDOCUMENTED_DT_STRING 22 | --ignore PRINTK_WITHOUT_KERN_LEVEL 23 | 24 | # FILE_PATH_CHANGES seems to not be working correctly. It will 25 | # choke on added / deleted files even if the MAINTAINERS file 26 | # is touched. 27 | --ignore FILE_PATH_CHANGES 28 | 29 | # This one has a linux path hard coded, so it would choke on 30 | # some commits unnecessarily. 31 | --ignore EXECUTE_PERMISSIONS 32 | 33 | # Exclude the vendorcode directory 34 | --exclude src/vendorcode 35 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: LLVM 2 | Language: Cpp 3 | IndentWidth: 8 4 | UseTab: Always 5 | BreakBeforeBraces: Linux 6 | AllowShortIfStatementsOnASingleLine: false 7 | IndentCaseLabels: false 8 | SortIncludes: false 9 | ContinuationIndentWidth: 8 10 | ColumnLimit: 0 11 | AlwaysBreakBeforeMultilineStrings: true 12 | AllowShortLoopsOnASingleLine: false 13 | AllowShortFunctionsOnASingleLine: false 14 | AlignEscapedNewlinesLeft: false 15 | AlignTrailingComments: true 16 | AllowAllParametersOfDeclarationOnNextLine: false 17 | AlignAfterOpenBracket: true 18 | SpaceAfterCStyleCast: false 19 | MaxEmptyLinesToKeep: 2 20 | BreakBeforeBinaryOperators: NonAssignment 21 | BreakStringLiterals: false 22 | -------------------------------------------------------------------------------- /.github/auto-merge.yml: -------------------------------------------------------------------------------- 1 | minApprovals: 2 | COLLABORATOR: 1 3 | requiredLabels: 4 | - merge 5 | mergeMethod: rebase 6 | reportStatus: true 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.dtb 2 | oreboot.asm 3 | *.\# 4 | *.bin 5 | *.debug 6 | *.elf 7 | *.o 8 | *.out 9 | *.pyc 10 | *.sw[po] 11 | /*.rom 12 | 13 | # 14 | # KDE editors create lots of backup files whenever 15 | # a file is edited, so just ignore them 16 | *~ 17 | *.kate-swp 18 | # Ignore Kdevelop project file 19 | *.kdev4 20 | 21 | #Added by cargo 22 | # 23 | #already existing elements are commented out 24 | 25 | target 26 | **/*.rs.bk 27 | debug.log 28 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "edk2"] 2 | path = 3rdparty/edk2 3 | url = https://github.com/tianocore/edk2 4 | ignore = dirty 5 | [submodule "FSP"] 6 | path = 3rdparty/fsp 7 | url = https://github.com/intel/FSP 8 | ignore = dirty 9 | -------------------------------------------------------------------------------- /Documentation/getting-started.md: -------------------------------------------------------------------------------- 1 | # Getting Started 2 | 3 | If you would like to contribute, but don't know how to start, this page is for 4 | you. This guide will walk you through running oreboot locally using QEMU 5 | emulation and explain the high level architecture / structure of the project. 6 | It also assumes the use of a Debian like system. 7 | 8 | ## Set up the environment 9 | 10 | The first step, is to install all dependencies and ensure the project can be 11 | started locally (see `README.md` and `azure-pipelines.yml` for possibly more 12 | up-to-date instructions. 13 | 14 | ```shell 15 | git clone git://github.com/oreboot/oreboot 16 | cd oreboot 17 | make debiansysprepare 18 | make firsttime 19 | ``` 20 | 21 | ## Device Tree 22 | 23 | Read the module comment inside `src/lib/device_tree/src/lib.rs`. In oreboot, 24 | device tree is used for two reasons - the actual device tree of the hardware 25 | that we are running on (we will refer to it as `hardware device tree`) and 26 | device tree used to define the layout of the image that is flashed into the device 27 | (we will refer to it as `oreboot device tree`. 28 | 29 | ## What `make run` actually does on a mainboard 30 | 31 | 1. Build oreboot specific for the given mainboard. 32 | 2. Create an binary image that will be flashed into the device. 33 | 3. Run given image using QEMU emulation. 34 | 35 | Let's go over above steps in a little more details. 36 | 37 | ### Build oreboot (bootblob.bin) 38 | 39 | This is the code inside `src/mainboard/*/*/src/main.rs`. It starts with a tiny 40 | bit of assembler (that is included inside `main.rs`, it performs minimal 41 | amount of initialization and then calls into the Rust program. Compared to 42 | other Rust binaries, there is no `main` method, instead you will see `pub 43 | extern "C" fn ...` methods that are being called from assembler to start the 44 | program. The Rust binary then initializes more of the hardware, prepares the 45 | actual payload and runs it. 46 | 47 | Mainboard code only uses `core` library and does not use `std`. This means no 48 | heap allocated structures like `Box` or `Vec` and arrays have to have 49 | statically allocated size. 50 | 51 | The binary is generated in two steps: 52 | 53 | * Build ELF (Executable and Linkable Format) binary, with `cargo xbuild` command. 54 | * Convert it to binary format with `rust-objcopy` into `bootblob.bin` file. 55 | 56 | This `bootblob.bin` is then used to construct the image that will be written 57 | into the device. 58 | 59 | ### Create image (image.bin) 60 | 61 | After we got the oreboot binary, we need to construct an image that will be 62 | flashed into the device. `layoutflash` (whose source code is located inside 63 | `tools/layoutflash` directory) takes `oreboot device tree` specification of 64 | image layout, and constructs a binary image. It basically just concatenates 65 | multiple binary blobs together at the right positions. 66 | 67 | Each mainboard has file called `fixed-dtfs.dts` which is human readable 68 | specification of the image layout (all tools use the binary form of this file 69 | which is converted inside Makefile using `dtc` command). 70 | 71 | Most images include following parts: 72 | 73 | * oreboot (`bootblob.bin`) - this is what hardware starts first. It often is a 74 | first thing in the image (though it not always starts at offset 0). 75 | * `oreboot device tree` - binary form of `fixed-dtfs.dts` file. I believe 76 | currently it is included mostly for debugging purposes (though my guess is 77 | that it should be used to find where the payload is located that should be 78 | executed, but currently the offsets are hardcoded inside the oreboot binary). 79 | * payload - actual binary that will be executed. It is configured with 80 | environment variables, which is why the `make run` method starts with 81 | `PAYLOAD_A=...`. 82 | 83 | ### Run QEMU 84 | 85 | Once image is created, qemu is invoked to emulate given hardware. It takes 86 | `image.bin` produced in previous step and writes it on to the device. 87 | 88 | ## Important crates / types 89 | 90 | * `src/drivers/model/` - defines the `Device` trait, that is the main 91 | type to read and write data (often to actual serial devices) 92 | * `src/drivers/wrappers/` - defines few simple implementation of 93 | `Device` tree (e.g. `SliceReader` for exposing slice of binary data as 94 | `Driver` trait, or `Memory` for reading the data directly from memory). 95 | * `src/lib/device_tree/` - library for reading device tree binary format. 96 | * `payloads` - library for loading a payload and executing it. 97 | * `tools/layoutflash` - tool for creating an image from binary blobs. 98 | 99 | Note: There are probably more important types and crates, but those are the 100 | ones I got to so far in my exploration. 101 | 102 | ## Important make commands 103 | 104 | Those commands are invoked from the top level `oreboot` directory: 105 | 106 | * `make format` - format all Rust files in the project. 107 | * `make clippy` - run clippy linter on all Rust files in the project. 108 | * `make test` - run all Rust tests in the project. 109 | * `make flash` - flash to hardware, specify programmer for flashrom with 110 | `FLASHROM_PROGRAMMER`. 111 | 112 | 113 | ## Next steps 114 | 115 | * I highly recommend starting with either a tool like `layoutflash` or a 116 | mainboards `main.rs` file, and reading its code. When something is not clear, 117 | try to improve the comments, write unit tests or refactor. 118 | * Look at open Issues in github, especially the ones with `good first issue` 119 | label. 120 | -------------------------------------------------------------------------------- /Documentation/opentitan/README.md: -------------------------------------------------------------------------------- 1 | # OpenTitan 2 | 3 | For development, the Digilent Nexys Video Artix-7 board is known to work. We are looking for a less expensive option. 4 | 5 | Follow this Quick Start: https://docs.opentitan.org/doc/ug/quickstart/ 6 | 7 | There's a video here: https://www.lowrisc.org/blog/2019/11/get-started-with-opentitan/ 8 | 9 | Pre-built bitstream can be found here: 10 | 11 | * Releases: https://github.com/lowRISC/opentitan/releases 12 | * For newer bitstreams, look at Azure pipelines, for example: https://dev.azure.com/lowrisc/opentitan/_build/results?buildId=6401&view=logs&j=a8b61b66-4668-57fb-dcc3-ba755ef807ae 13 | -------------------------------------------------------------------------------- /Documentation/sifive/dediprog.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orangecms/oreboot/e66c077413956bf4da78e855cda2c7b8cac0aa00/Documentation/sifive/dediprog.jpg -------------------------------------------------------------------------------- /Documentation/sifive/msel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orangecms/oreboot/e66c077413956bf4da78e855cda2c7b8cac0aa00/Documentation/sifive/msel.jpg -------------------------------------------------------------------------------- /Documentation/sifive/opensbi.md: -------------------------------------------------------------------------------- 1 | OpenSBI 2 | ------- 3 | 4 | OpenSBI is used in the `FW_JUMP` mode. This jumps to 0x80200000 with a device 5 | tree at 0x88000000. 6 | 7 | ``` 8 | git clone https://github.com/riscv/opensbi 9 | export CROSS_COMPILE=riscv64-linux-gnu- 10 | export PLATFORM_RISCV_XLEN=64 11 | make PLATFORM=sifive/fu540 12 | ls -l buildplatform/sifive/fu540/firmware/fw_jump.bin 13 | ``` 14 | -------------------------------------------------------------------------------- /Documentation/sifive/setup.md: -------------------------------------------------------------------------------- 1 | # HiFive Unleashed Setup 2 | 3 | This tutorial gets you setup to run Oreboot on the HiFive Unleashed board. 4 | 5 | 1. Follow the main README to setup the Rust toolchain for RISC-V. 6 | 7 | 2. Confirm the build works by running Oreboot in QEMU. If it works, you should 8 | see the words "Welcome to oreboot" and "TESTTESTTEST" printed to your 9 | terminal. 10 | 11 | ``` 12 | cd src/mainboard/sifive/hifive 13 | make run 14 | ``` 15 | 16 | 3. Create a flash image. 17 | 18 | ``` 19 | cargo make 20 | # The output is target/riscv64imac-unknown-none-elf/release/oreboot.bin 21 | ``` 22 | 23 | ## Flashing with flashrom 24 | 25 | 4. While flashing, make sure all external power is removed from the board. 26 | Using a 16-pin Pomona clip, connect a SF100 to the board as seen in the 27 | image below. 28 | 29 | ![Dediprog](dediprog.jpg) 30 | 31 | 5. Flash it. Make sure to build flashrom from source (https://review.coreboot.org/cgit/flashrom.git/) because the debian packages tend to be too old. 32 | 33 | ``` 34 | sudo flashrom -p dediprog -w flash.rom 35 | ``` 36 | 37 | 6. Oreboot is designed to be run immediately after the Zeroth Stage Boot Loader 38 | (ZSBL), skipping the First Stage Boot Loader (FSBL) and Berkley Boot Loader 39 | (BBL). To perform this skip and run Oreboot directly out of the SPI0 40 | flashchip, set the MSEL dip switches to the value of 0b0001. Note that the 41 | ON label is 0 on these switches. 42 | 43 | ![MSEL](msel.jpg) 44 | 45 | 7. Now connect power to a wall outlet and micro USB to your Linux computer. Use 46 | the big red power switch to power the board. Use the smaller red tact switch 47 | to reset the processor. When the board is powered, two new /dev/ttyUSBx 48 | devices should appear on your computer. The device with the higher number is 49 | UART0. Use minicom to see "Welcome to oreboot" and TESTTESTTEST printed. 50 | 51 | ``` 52 | minicom -D /dev/ttyUSB1 -b 115200 53 | ``` 54 | 55 | ![USB](usb.jpg) 56 | 57 | ## Alternate: Flashing with OpenOCD 58 | 59 | 4. With RISC-V OpenOCD installed on your system, the HiFive unleashed can be programmed over USB: 60 | 61 | ``` 62 | cargo make -p release flash-openocd 63 | ``` 64 | 65 | ## Debugging with GDB 66 | 67 | Use GDB+OpenOCD to debug hardware: 68 | 69 | 1. Build GDB for RISC-V 70 | 71 | ``` 72 | sudo apt-get install autoconf automake autotools-dev curl libmpc-dev \ 73 | libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf \ 74 | libtool patchutils bc zlib1g-dev libexpat-dev 75 | git clone https://github.com/riscv/riscv-gnu-toolchain --recursive 76 | cd riscv-gnu-toolchain 77 | ./configure --help 78 | ./configure --enable-linux --prefix=/opt/riscv 79 | make -j12 build-gdb 80 | stat /opt/riscv/bin/riscv64-unknown-linux-gnu-gdb 81 | ``` 82 | 83 | 2. Build OpenOCD for RISC-V 84 | 85 | ``` 86 | git clone https://github.com/riscv/riscv-openocd 87 | cd riscv-openocd 88 | ./bootstrap 89 | ./configure --help 90 | ./configure --enable-ftdi 91 | make -j12 92 | stat src/openocd 93 | ``` 94 | 95 | Download the HiFive Unleashed config from: https://github.com/sifive/freedom-u-sdk/blob/master/bsp/env/freedom-u500-unleashed/openocd.cfg 96 | 97 | 3. Start OpenOCD, use telnet to reset and run GDB: 98 | 99 | ``` 100 | openocd -f openocd.cfg 101 | 102 | telnet locahost 4444 103 | > reset halt 104 | 105 | riscv64-unknown-linux-gnu-gdb 106 | (gdb) target remote localhost:3333 107 | (gdb) show threads 108 | (gdb) thread 2 109 | ``` 110 | -------------------------------------------------------------------------------- /Documentation/sifive/usb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orangecms/oreboot/e66c077413956bf4da78e855cda2c7b8cac0aa00/Documentation/sifive/usb.jpg -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | help: 2 | @echo 'Make options:' 3 | @echo 'firsttime -- for the first time you run make' 4 | @echo 'update -- to update the install' 5 | @echo 'format -- to format all files' 6 | @echo ' # Build a single board' 7 | @echo ' make VENDOR/BOARD' 8 | @echo ' # This is equivalent to' 9 | @echo ' cd src/mainboard/VENDOR/BOARD && make' 10 | @echo ' # Build all mainboards' 11 | @echo ' make mainboards' 12 | @echo ' # Build everything in parallel' 13 | @echo ' make -j mainboards' 14 | @echo ' # Build debug mode' 15 | @echo ' MODE=debug make mainboards' 16 | 17 | BROKEN := \ 18 | src/mainboard/ast/ast25x0/Makefile \ 19 | src/mainboard/nuvoton/npcm7xx/Makefile \ 20 | src/mainboard/emulation/qemu-armv7/Makefile \ 21 | 22 | MAINBOARDS := $(filter-out $(BROKEN), $(wildcard src/mainboard/*/*/Makefile)) 23 | 24 | TOOLCHAIN_VER := nightly-2020-04-22 25 | XBUILD_VER := 0.5.29 26 | BINUTILS_VER := 0.2.0 27 | 28 | .PHONY: mainboards $(MAINBOARDS) 29 | mainboards: $(MAINBOARDS) 30 | 31 | $(MAINBOARDS): 32 | cd $(dir $@) && make 33 | 34 | firsttime: 35 | rustup override set $(TOOLCHAIN_VER) 36 | rustup component add rust-src llvm-tools-preview rustfmt clippy 37 | rustup target add riscv64imac-unknown-none-elf 38 | rustup target add riscv32imc-unknown-none-elf 39 | rustup target add armv7r-none-eabi 40 | cargo install $(if $(XBUILD_VER),--version $(XBUILD_VER),) cargo-xbuild 41 | cargo install $(if $(BINUTILS_VER),--version $(BINUTILS_VER),) cargo-binutils 42 | 43 | debiansysprepare: 44 | sudo apt-get install device-tree-compiler pkg-config libssl-dev llvm-dev libclang-dev clang 45 | curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain $(TOOLCHAIN_VER) 46 | 47 | .PHONY: ciprepare debiansysprepare firsttime 48 | ciprepare: debiansysprepare firsttime 49 | 50 | update: 51 | rustup update 52 | 53 | # Option used for formatting. If set, the command will only verify if 54 | # formatting is correct (without actually changing the formatting). 55 | # Returns 0 only if all files are properly formatted. 56 | # Usage: 57 | # $ make --keep-going format check=true 58 | check ?= 59 | 60 | # Makefile does not support recursive wildcard, so we have to handle all depths manually. 61 | CRATES := \ 62 | $(wildcard */Cargo.toml) \ 63 | $(wildcard */*/Cargo.toml) \ 64 | $(wildcard */*/*/Cargo.toml) \ 65 | $(wildcard */*/*/*/Cargo.toml) 66 | 67 | CRATES_TO_FORMAT := $(patsubst %/Cargo.toml,%/Cargo.toml.format,$(CRATES)) 68 | $(CRATES_TO_FORMAT): 69 | cd $(dir $@) && cargo fmt -- $(if $(check),--check,) 70 | .PHONY: format $(CRATES_TO_FORMAT) 71 | format: $(CRATES_TO_FORMAT) 72 | 73 | BROKEN_CRATES_TO_TEST := \ 74 | src/arch/arm/armv7/Cargo.toml \ 75 | src/arch/riscv/rv32/Cargo.toml \ 76 | src/arch/riscv/rv64/Cargo.toml \ 77 | src/cpu/armltd/cortex-a9/Cargo.toml \ 78 | src/cpu/lowrisc/ibex/Cargo.toml \ 79 | src/mainboard/amd/romecrb/Cargo.toml \ 80 | src/mainboard/ast/ast25x0/Cargo.toml \ 81 | src/mainboard/emulation/qemu-armv7/Cargo.toml \ 82 | src/mainboard/emulation/qemu-q35/Cargo.toml \ 83 | src/mainboard/emulation/qemu-riscv/Cargo.toml \ 84 | src/mainboard/nuvoton/npcm7xx/Cargo.toml \ 85 | src/mainboard/opentitan/crb/Cargo.toml \ 86 | src/mainboard/sifive/hifive/Cargo.toml \ 87 | src/soc/aspeed/ast2500/Cargo.toml \ 88 | src/soc/opentitan/earlgrey/Cargo.toml \ 89 | src/soc/sifive/fu540/Cargo.toml \ 90 | src/vendorcode/fsp/coffeelake/Cargo.toml \ 91 | 92 | CRATES_TO_TEST := $(patsubst %/Cargo.toml,%/Cargo.toml.test,$(filter-out $(BROKEN_CRATES_TO_TEST),$(CRATES))) 93 | $(CRATES_TO_TEST): 94 | cd $(dir $@) && cargo test 95 | .PHONY: test $(CRATES_TO_TEST) 96 | test: $(CRATES_TO_TEST) 97 | 98 | CRATES_TO_CLIPPY := $(patsubst %/Cargo.toml,%/Cargo.toml.clippy,$(filter-out $(BROKEN_CRATES_TO_TEST),$(CRATES))) 99 | $(CRATES_TO_CLIPPY): 100 | cd $(dir $@) && cargo clippy -- -D warnings 101 | .PHONY: clippy $(CRATES_TO_CLIPPY) 102 | clippy: $(CRATES_TO_CLIPPY) 103 | 104 | clean: 105 | rm -rf $(wildcard src/mainboard/*/*/target) 106 | -------------------------------------------------------------------------------- /Makefile.inc: -------------------------------------------------------------------------------- 1 | # This Makefile is included by src/mainboards/VENDOR/BOARD/Makefile 2 | TOP = $(abspath $(CURDIR)/../../../..) 3 | VENDOR = $(notdir $(shell dirname $(CURDIR))) 4 | BOARD = $(notdir $(CURDIR)) 5 | MODE ?= release 6 | FIXED_DTFS = fixed-dtfs.dtb 7 | TOOLS_DIR = $(TOP)/tools 8 | FLASHROM_PROGRAMMER ?= dediprog 9 | # Cargo will build the tools using the target from the .cargo directory which 10 | # does not work so well if you are cross-compiling. This shell one-liner gets 11 | # the target of the current system which can be passed via --target for 12 | # building tools 13 | TOOLS_TARGET = $(shell rustc -Z unstable-options --print target-spec-json | sed -n -e 's/.*llvm-target": "\([^"]\+\).*/\1/p') 14 | CARGO_FLAGS = --verbose 15 | 16 | # Override variables depending on the build. 17 | include $(TOP)/Makefile.mode.$(MODE).inc 18 | 19 | # ELF and BOOTBLOB are intermediate files while IMAGE is the final firmware 20 | # image ready to be flashed onto the machine. 21 | ELF = $(TARGET_DIR)/$(BOARD) 22 | BOOTBLOB = $(TARGET_DIR)/bootblob.bin 23 | IMAGE = $(TARGET_DIR)/image.bin 24 | 25 | $(info ***** Oreboot Build Config *****) 26 | $(info TOP = $(TOP)) 27 | $(info VENDOR = $(VENDOR)) 28 | $(info BOARD = $(BOARD)) 29 | $(info MODE = $(MODE)) 30 | $(info TARGET = $(TARGET)) 31 | $(info TARGET_DIR = $(TARGET_DIR)) 32 | $(info TOOLS_TARGET = $(TOOLS_TARGET)) 33 | $(info cargo --version = $(shell cargo --version)) 34 | $(info rustc --version = $(shell rustc --version)) 35 | $(info rustup --version = $(shell rustup --version)) 36 | $(info **********) 37 | 38 | $(TARGET_DIR)/%.dtb: %.dts 39 | dtc $< -O dtb -o $@ 40 | 41 | $(IMAGE): $(BOOTBLOB) $(TARGET_DIR)/$(FIXED_DTFS) 42 | TARGET_DIR=$(TARGET_DIR) cargo run --target $(TOOLS_TARGET) --manifest-path $(TOOLS_DIR)/layoutflash/Cargo.toml -- $(TARGET_DIR)/$(FIXED_DTFS) $@ 43 | @printf "**\n** Output: $@\n**\n" 44 | 45 | $(TARGET_DIR)/bootblob.bin: $(ELF) 46 | rust-objcopy -O binary -R .bss $< $@ 47 | 48 | # Re-run cargo every time. 49 | .PHONY: $(ELF) 50 | $(ELF): 51 | RUST_TARGET_PATH=$(TOP)/src/custom_targets cargo xbuild $(CARGO_FLAGS) 52 | 53 | clean: 54 | rm -rf target/ 55 | 56 | # The rest of this file are conveniences for debugging. 57 | objdump: $(ELF) 58 | cargo objdump -- -d $(ELF) 59 | 60 | flash: $(IMAGE) 61 | sudo $(which flashrom) -V -w $(IMAGE) -p $(FLASHROM_PROGRAMMER) 62 | -------------------------------------------------------------------------------- /Makefile.mode.debug.inc: -------------------------------------------------------------------------------- 1 | TARGET_DIR = target/$(TARGET)/debug 2 | -------------------------------------------------------------------------------- /Makefile.mode.release.inc: -------------------------------------------------------------------------------- 1 | CARGO_FLAGS += --release 2 | TARGET_DIR = target/$(TARGET)/release 3 | -------------------------------------------------------------------------------- /Makefile.qemu.inc: -------------------------------------------------------------------------------- 1 | # This Makefile is included by src/mainboards/VENDOR/BOARD/Makefile for qemu 2 | # recipes. 3 | 4 | MONITOR ?= "/dev/null" 5 | 6 | run: $(IMAGE) 7 | $(QEMU) $(QEMU_FLAGS) 8 | 9 | trace: $(IMAGE) 10 | $(QEMU) -d guest_errors,in_asm,int $(QEMU_FLAGS) 11 | 12 | gdb: $(IMAGE) 13 | $(QEMU) -d guest_errors -s -S $(QEMU_FLAGS) 14 | -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | trigger: 2 | - master 3 | 4 | schedules: 5 | - cron: "0 0 * * *" 6 | displayName: Daily midnight (UTC) build 7 | branches: 8 | include: 9 | - master 10 | always: true 11 | 12 | pool: 13 | vmImage: 'ubuntu-latest' 14 | 15 | jobs: 16 | - job: CheckQuality 17 | steps: 18 | - checkout: self 19 | fetchDepth: 1 # Download only latest commit, not all history 20 | - script: | 21 | git submodule update --init 22 | displayName: 'Checkout submodules' 23 | - script: | 24 | make ciprepare 25 | displayName: 'Install Rust Dependencies' 26 | - script: | 27 | make --keep-going format check=true 28 | displayName: 'Check formatting' 29 | - script: | 30 | make --keep-going test 31 | displayName: 'Run rust tests' 32 | - script: | 33 | make --keep-going clippy 34 | displayName: 'Run clippy linter' 35 | - script: | 36 | make --keep-going mainboards 37 | displayName: 'Build all mainboards' 38 | - script: | 39 | ./scripts/generate-size-report.sh 40 | displayName: 'Generate report of binary sizes' 41 | - job: BuildX86QEMU 42 | displayName: 'Build QEMU q35 board for x86' 43 | steps: 44 | - checkout: self 45 | fetchDepth: 1 # Download only latest commit, not all history 46 | - script: | 47 | git submodule update --init 48 | displayName: 'Checkout submodules' 49 | - script: | 50 | make ciprepare 51 | cd src/mainboard/emulation/qemu-q35 52 | make 53 | - job: TestSiFiveQEMU 54 | displayName: 'Test RISC-V SiFive board in QEMU' 55 | steps: 56 | - checkout: self 57 | fetchDepth: 1 # Download only latest commit, not all history 58 | - script: | 59 | make ciprepare 60 | displayName: 'Install Rust Dependencies' 61 | - script: | 62 | pushd src/mainboard/sifive/hifive 63 | PAYLOAD_A=../../../../payloads/src/external/simple/testtesttest make 64 | popd 65 | displayName: 'Build firmware' 66 | - script: | 67 | git clone --single-branch --branch v5.1.0 https://github.com/qemu/qemu && pushd qemu 68 | mkdir build-riscv64 && cd build-riscv64 69 | ../configure --target-list=riscv64-softmmu 70 | make -j16 71 | sudo ln -s $PWD/riscv64-softmmu/qemu-system-riscv64 /usr/bin/ 72 | sudo ln -s $PWD/qemu-img /usr/bin/ 73 | popd 74 | displayName: 'Build QEMU' 75 | - script: | 76 | pushd src/mainboard/sifive/hifive 77 | PAYLOAD_A=../../../../payloads/src/external/simple/testtesttest timeout 120s make run | tee serial 78 | grep TESTTESTTEST serial 79 | popd 80 | displayName: 'Run test' 81 | - job: TestRISCVVirtBoardQEMU 82 | displayName: 'Test RISC-V QEMU Virt board in QEMU' 83 | steps: 84 | - checkout: self 85 | fetchDepth: 1 # Download only latest commit, not all history 86 | - script: | 87 | make ciprepare 88 | displayName: 'Install Rust Dependencies' 89 | - script: | 90 | pushd src/mainboard/emulation/qemu-riscv 91 | make 92 | popd 93 | displayName: 'Build oreboot image' 94 | - script: | 95 | git clone --single-branch --branch v5.1.0 https://github.com/qemu/qemu && pushd qemu 96 | mkdir build-riscv64 && pushd build-riscv64 97 | ../configure --target-list=riscv64-softmmu 98 | make -j16 99 | sudo ln -s $PWD/riscv64-softmmu/qemu-system-riscv64 /usr/bin/ 100 | sudo ln -s $PWD/qemu-img /usr/bin/ 101 | popd 102 | displayName: 'Build QEMU' 103 | - script: | 104 | pushd src/mainboard/emulation/qemu-riscv 105 | timeout 30s make run | tee serial 106 | grep "Running payload" serial 107 | popd 108 | displayName: 'Run test' 109 | -------------------------------------------------------------------------------- /payloads/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "payloads" 3 | version = "0.1.0" 4 | authors = ["Oreboot Authors"] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | model = { path = "../src/drivers/model"} 9 | postcard = "0.4.3" 10 | serde = { version = "1.0", default-features = false } 11 | wrappers = { path = "../src/drivers/wrappers"} 12 | print = { path = "../src/lib/print" } 13 | 14 | [profile.release] 15 | opt-level = 'z' # Optimize for size. 16 | -------------------------------------------------------------------------------- /payloads/src/external/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod zimage; 2 | -------------------------------------------------------------------------------- /payloads/src/external/simple/testtesttest: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orangecms/oreboot/e66c077413956bf4da78e855cda2c7b8cac0aa00/payloads/src/external/simple/testtesttest -------------------------------------------------------------------------------- /payloads/src/external/simple/testtesttest.S: -------------------------------------------------------------------------------- 1 | // Prints A to serial forever. 2 | 3 | #define BASE 0x10010000 4 | #define TD (BASE + 0x0) 5 | #define TXC (BASE + 0x8) 6 | 7 | .global _start 8 | _start: 9 | // Spin lock 10 | nop 11 | nop 12 | nop 13 | la t0, spin_lock 14 | li t1, 1 15 | amoswap.w t1, t1, (t0) 16 | bne t1, zero, _start 17 | 18 | li t0, TXC 19 | lw t1, 0(t0) 20 | ori t1, t1, 0x1 21 | sw t1, 0(t0) 22 | li t0, TD 23 | 24 | call check_full 25 | li t1, 'H' 26 | sw t1, 0(t0) 27 | call check_full 28 | li t1, 'A' 29 | sw t1, 0(t0) 30 | call check_full 31 | li t1, 'R' 32 | sw t1, 0(t0) 33 | call check_full 34 | li t1, 'T' 35 | sw t1, 0(t0) 36 | 37 | call check_full 38 | li t1, '0' 39 | add t1, t1, a0 40 | sw t1, 0(t0) 41 | 42 | call check_full 43 | li t1, ' ' 44 | sw t1, 0(t0) 45 | call check_full 46 | li t1, 'T' 47 | sw t1, 0(t0) 48 | call check_full 49 | li t1, 'E' 50 | sw t1, 0(t0) 51 | call check_full 52 | li t1, 'S' 53 | sw t1, 0(t0) 54 | call check_full 55 | li t1, 'T' 56 | sw t1, 0(t0) 57 | call check_full 58 | li t1, 'T' 59 | sw t1, 0(t0) 60 | call check_full 61 | li t1, 'E' 62 | sw t1, 0(t0) 63 | call check_full 64 | li t1, 'S' 65 | sw t1, 0(t0) 66 | call check_full 67 | li t1, 'T' 68 | sw t1, 0(t0) 69 | call check_full 70 | li t1, 'T' 71 | sw t1, 0(t0) 72 | call check_full 73 | li t1, 'E' 74 | sw t1, 0(t0) 75 | call check_full 76 | li t1, 'S' 77 | sw t1, 0(t0) 78 | call check_full 79 | li t1, 'T' 80 | sw t1, 0(t0) 81 | call check_full 82 | li t1, '\r' 83 | sw t1, 0(t0) 84 | call check_full 85 | li t1, '\n' 86 | sw t1, 0(t0) 87 | 88 | // Release lock 89 | la t0, spin_lock 90 | amoswap.w zero, zero, (t0) 91 | 92 | loop: 93 | jal loop 94 | 95 | check_full: 96 | li t2, TD 97 | lw t2, 0(t2) 98 | srli t2, t2, 31 99 | bgtz t2, check_full 100 | ret 101 | 102 | .align 4 103 | spin_lock: 104 | .word 0 105 | -------------------------------------------------------------------------------- /payloads/src/external/zimage/mod.rs: -------------------------------------------------------------------------------- 1 | pub const KERNEL: &[u8] = include_bytes!("zImage"); 2 | pub const DTB: &[u8] = include_bytes!("qemu_fdt.dtb"); 3 | 4 | /* 5 | use crate::payload; 6 | // TODO: Create a struct which tells you where the available memory is. 7 | const MEM: u32 = 0x40200000; 8 | // TODO: Parse from SPI. 9 | pub const PAYLOAD: payload::Payload = payload::Payload { 10 | typ: payload::ftype::CBFS_TYPE_RAW, 11 | compression: payload::ctype::CBFS_COMPRESS_NONE, 12 | offset: 0, 13 | load_addr: MEM as u64, 14 | rom_len: KERNEL.len() as u32, 15 | mem_len: KERNEL.len() as u32, 16 | segs: &[ 17 | payload::Segment { 18 | // Kernel segment 19 | typ: payload::stype::PAYLOAD_SEGMENT_ENTRY, 20 | base: MEM, 21 | data: KERNEL, 22 | }, 23 | payload::Segment { 24 | // Device tree segment 25 | typ: payload::stype::PAYLOAD_SEGMENT_DATA, 26 | // TODO: Assumes the decompression ratio is no more than 5x. 27 | base: MEM + 5 * KERNEL.len() as u32, 28 | data: DTB, 29 | }, 30 | ], 31 | }; 32 | */ 33 | -------------------------------------------------------------------------------- /payloads/src/external/zimage/qemu_fdt.dtb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orangecms/oreboot/e66c077413956bf4da78e855cda2c7b8cac0aa00/payloads/src/external/zimage/qemu_fdt.dtb -------------------------------------------------------------------------------- /payloads/src/external/zimage/zImage: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orangecms/oreboot/e66c077413956bf4da78e855cda2c7b8cac0aa00/payloads/src/external/zimage/zImage -------------------------------------------------------------------------------- /payloads/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | 3 | pub mod external; 4 | // TODO: serialize doesn't even compile yet 5 | // mod serialize; 6 | pub mod payload; 7 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | overflow_delimited_expr = true 2 | unstable_features = true 3 | use_small_heuristics = "Max" 4 | force_multiline_blocks = true 5 | max_width = 255 6 | -------------------------------------------------------------------------------- /scripts/generate-size-report.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo "Mainboard;Size(bytes)" 4 | for BOOTBLOB in $(find . -name bootblob.bin) 5 | do 6 | SIZE=$(stat -c"%s" $BOOTBLOB) 7 | if [[ $BOOTBLOB =~ \./src/mainboard/([^/]+)/([^/]+).* ]]; then 8 | echo "${BASH_REMATCH[1]}/${BASH_REMATCH[2]};${SIZE}" 9 | fi 10 | done 11 | -------------------------------------------------------------------------------- /src/arch/arm/armv7/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "arch" 3 | version = "0.1.0" 4 | authors = ["Oreboot Authors"] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | model = { path = "../../../drivers/model" } 9 | 10 | [profile.release] 11 | opt-level = 'z' # Optimize for size. 12 | -------------------------------------------------------------------------------- /src/arch/arm/armv7/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![feature(global_asm)] 3 | #![deny(warnings)] 4 | 5 | pub fn init() {} 6 | 7 | use model::{Driver, Result, NOT_IMPLEMENTED}; 8 | 9 | pub struct MMU {} 10 | 11 | impl MMU { 12 | pub fn new() -> MMU { 13 | MMU {} 14 | } 15 | } 16 | 17 | impl Driver for MMU { 18 | fn init(&mut self) -> Result<()> { 19 | Ok(()) 20 | } 21 | 22 | fn pread(&self, _data: &mut [u8], _pos: usize) -> Result { 23 | NOT_IMPLEMENTED 24 | } 25 | 26 | fn pwrite(&mut self, data: &[u8], _pos: usize) -> Result { 27 | let r: usize; 28 | match data { 29 | b"off" => { 30 | let mut r0 = unsafe { mmu_get() }; 31 | // TODO: make this a register type 32 | r0 &= !0x00002300; // clear bits 13, 9:8 (--V- --RS) 33 | r0 &= !0x00000087; // clear bits 7, 2:0 (B--- -CAM) 34 | r0 |= 0x00000002; // set bit 1 (A) Align 35 | r0 |= 0x00001000; // set bit 12 (I) I-Cache 36 | unsafe { 37 | mmu_set(r0); 38 | } 39 | r = 1; 40 | } 41 | b"on" => r = 1, 42 | _ => r = 0, 43 | } 44 | Ok(r) 45 | } 46 | 47 | // Shutdown. Hmm. 48 | fn shutdown(&mut self) {} 49 | } 50 | 51 | extern "C" { 52 | fn mmu_get() -> usize; 53 | fn mmu_set(i: usize); 54 | } 55 | 56 | global_asm!(include_str!("mmu.S")); 57 | -------------------------------------------------------------------------------- /src/arch/arm/armv7/src/mmu.S: -------------------------------------------------------------------------------- 1 | mmu_get: 2 | mrc p15, 0, r0, c1, c0, 0 3 | mov pc, lr 4 | 5 | mmu_set: 6 | mcr p15, 0, r0, c1, c0, 0 7 | mov pc, lr 8 | -------------------------------------------------------------------------------- /src/arch/riscv/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod rv64; 2 | -------------------------------------------------------------------------------- /src/arch/riscv/rv32/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "arch" 3 | version = "0.1.0" 4 | authors = ["Oreboot Authors"] 5 | edition = "2018" 6 | 7 | [profile.release] 8 | opt-level = 'z' # Optimize for size. 9 | -------------------------------------------------------------------------------- /src/arch/riscv/rv32/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![feature(llvm_asm)] 2 | #![feature(lang_items, start)] 3 | #![no_std] 4 | #![feature(global_asm)] 5 | #![deny(warnings)] 6 | 7 | pub fn init() {} 8 | 9 | pub fn halt() -> ! { 10 | loop { 11 | // Bug with LLVM marks empty loops as undefined behaviour. 12 | // See: https://github.com/rust-lang/rust/issues/28728 13 | unsafe { llvm_asm!("wfi" :::: "volatile") } 14 | } 15 | } 16 | 17 | pub fn fence() { 18 | unsafe { llvm_asm!("fence" :::: "volatile") } 19 | } 20 | 21 | pub fn nop() { 22 | unsafe { llvm_asm!("nop" :::: "volatile") } 23 | } 24 | -------------------------------------------------------------------------------- /src/arch/riscv/rv32/src/mod.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "rv32")] 2 | pub mod lib; 3 | pub mod reg; 4 | 5 | -------------------------------------------------------------------------------- /src/arch/riscv/rv32/src/reg.rs: -------------------------------------------------------------------------------- 1 | const PageSize: u32 = 4096; 2 | const PageShift: u32 = 12; 3 | -------------------------------------------------------------------------------- /src/arch/riscv/rv64/Cargo.toml: -------------------------------------------------------------------------------- 1 | 2 | [package] 3 | name = "arch" 4 | version = "0.1.0" 5 | authors = ["Oreboot Authors"] 6 | edition = "2018" 7 | 8 | [profile.release] 9 | opt-level = 'z' # Optimize for size. 10 | -------------------------------------------------------------------------------- /src/arch/riscv/rv64/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![feature(llvm_asm)] 2 | #![feature(lang_items, start)] 3 | #![no_std] 4 | #![feature(global_asm)] 5 | #![deny(warnings)] 6 | 7 | pub fn halt() -> ! { 8 | loop { 9 | // Bug with LLVM marks empty loops as undefined behaviour. 10 | // See: https://github.com/rust-lang/rust/issues/28728 11 | unsafe { llvm_asm!("wfi" :::: "volatile") } 12 | } 13 | } 14 | 15 | pub fn fence() { 16 | unsafe { llvm_asm!("fence" :::: "volatile") } 17 | } 18 | 19 | pub fn nop() { 20 | unsafe { llvm_asm!("nop" :::: "volatile") } 21 | } 22 | -------------------------------------------------------------------------------- /src/arch/riscv/rv64/src/mod.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "rv64")] 2 | pub mod lib; 3 | pub mod reg; 4 | 5 | -------------------------------------------------------------------------------- /src/arch/riscv/rv64/src/reg.rs: -------------------------------------------------------------------------------- 1 | const PageSize: u32 = 4096; 2 | const PageShift: u32 = 12; 3 | -------------------------------------------------------------------------------- /src/arch/x86/x86_64/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "arch" 5 | version = "0.1.0" 6 | dependencies = [ 7 | "model", 8 | "print", 9 | "wrappers", 10 | ] 11 | 12 | [[package]] 13 | name = "model" 14 | version = "0.1.0" 15 | 16 | [[package]] 17 | name = "print" 18 | version = "0.1.0" 19 | dependencies = [ 20 | "model", 21 | ] 22 | 23 | [[package]] 24 | name = "wrappers" 25 | version = "0.1.0" 26 | dependencies = [ 27 | "model", 28 | ] 29 | -------------------------------------------------------------------------------- /src/arch/x86/x86_64/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "arch" 3 | version = "0.1.0" 4 | authors = ["Oreboot Authors"] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | model = { path = "../../../drivers/model" } 9 | print = { path = "../../../lib/print" } 10 | wrappers = { path = "../../../drivers/wrappers"} 11 | 12 | [profile.release] 13 | opt-level = 'z' # Optimize for size. 14 | 15 | [features] 16 | ioport = [] 17 | bzimage = [] 18 | -------------------------------------------------------------------------------- /src/arch/x86/x86_64/src/ioport.rs: -------------------------------------------------------------------------------- 1 | // ioports reads and writes bytes to ioports, using the offset. 2 | // TODO: use the type system to guide whether to use outw, outl, etc. 3 | use model::*; 4 | 5 | // enough already. 6 | 7 | /// Write 8 bits to port 8 | unsafe fn outb(port: u16, val: u8) { 9 | llvm_asm!("outb %al, %dx" :: "{dx}"(port), "{al}"(val)); 10 | } 11 | 12 | // Read 8 bits from port 13 | fn inb(port: u16) -> u8 { 14 | let ret: u8; 15 | unsafe { 16 | llvm_asm!("inb %dx, %al" : "={ax}"(ret) : "{dx}"(port) :: "volatile"); 17 | } 18 | ret 19 | } 20 | 21 | // /// Write 16 bits to port 22 | // unsafe fn outw(port: u16, val: u16) { 23 | // llvm_asm!("outw %ax, %dx" :: "{dx}"(port), "{al}"(val)); 24 | // } 25 | 26 | // /// Read 16 bits from port 27 | // unsafe fn inw(port: u16) -> u16 { 28 | // let ret: u16; 29 | // llvm_asm!("inw %dx, %ax" : "={ax}"(ret) : "{dx}"(port) :: "volatile"); 30 | // return ret; 31 | // } 32 | 33 | // /// Write 32 bits to port 34 | // unsafe fn outl(port: u16, val: u32) { 35 | // llvm_asm!("outl %eax, %dx" :: "{dx}"(port), "{al}"(val)); 36 | // } 37 | 38 | // /// Read 32 bits from port 39 | // unsafe fn inl(port: u16) -> u32 { 40 | // let ret: u32; 41 | // llvm_asm!("inl %dx, %eax" : "={ax}"(ret) : "{dx}"(port) :: "volatile"); 42 | // return ret; 43 | // } 44 | pub struct IOPort; 45 | 46 | impl Driver for IOPort { 47 | fn init(&mut self) -> Result<()> { 48 | Ok(()) 49 | } 50 | 51 | fn pread(&self, data: &mut [u8], offset: usize) -> Result { 52 | let b = inb(offset as u16); 53 | data[0] = b; 54 | Ok(1) 55 | } 56 | 57 | fn pwrite(&mut self, data: &[u8], offset: usize) -> Result { 58 | for (_i, &c) in data.iter().enumerate() { 59 | unsafe { 60 | outb(offset as u16, c); 61 | } 62 | } 63 | Ok(data.len()) 64 | } 65 | 66 | fn shutdown(&mut self) {} 67 | } 68 | -------------------------------------------------------------------------------- /src/arch/x86/x86_64/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![feature(llvm_asm)] 2 | #![feature(lang_items, start)] 3 | #![no_std] 4 | #![feature(global_asm)] 5 | #![deny(warnings)] 6 | 7 | const PAGE_SIZE: usize = 4096; 8 | 9 | pub mod bzimage; 10 | pub mod ioport; 11 | 12 | pub fn halt() -> ! { 13 | loop { 14 | // Bug with LLVM marks empty loops as undefined behaviour. 15 | // See: https://github.com/rust-lang/rust/issues/28728 16 | unsafe { llvm_asm!("hlt" :::: "volatile") } 17 | } 18 | } 19 | 20 | pub fn fence() { 21 | unsafe { llvm_asm!("nop" :::: "volatile") } 22 | } 23 | 24 | pub fn nop() { 25 | unsafe { llvm_asm!("nop" :::: "volatile") } 26 | } 27 | -------------------------------------------------------------------------------- /src/console/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "console" 5 | version = "0.1.0" 6 | 7 | -------------------------------------------------------------------------------- /src/console/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "console" 3 | version = "0.1.0" 4 | authors = ["Oreboot Authors"] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | 9 | [profile.release] 10 | opt-level = 'z' # Optimize for size. 11 | -------------------------------------------------------------------------------- /src/console/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![deny(warnings)] 3 | 4 | pub fn console_init() {} 5 | -------------------------------------------------------------------------------- /src/cpu/armltd/cortex-a9/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cpu" 3 | version = "0.1.0" 4 | authors = ["Oreboot Authors"] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | arch = { path = "../../../arch/arm/armv7"} 9 | 10 | [profile.release] 11 | opt-level = 'z' # Optimize for size. 12 | -------------------------------------------------------------------------------- /src/cpu/armltd/cortex-a9/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![deny(warnings)] 3 | 4 | pub fn init() { 5 | arch::init() 6 | } 7 | -------------------------------------------------------------------------------- /src/cpu/lowrisc/ibex/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cpu" 3 | version = "0.1.0" 4 | authors = ["Oreboot Authors"] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | arch = { path = "../../../arch/riscv/rv32"} 9 | 10 | [profile.release] 11 | opt-level = 'z' # Optimize for size. 12 | -------------------------------------------------------------------------------- /src/cpu/lowrisc/ibex/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![deny(warnings)] 3 | 4 | pub fn init() { 5 | arch::init() 6 | } 7 | 8 | // There is no ibex-specific way of halting yet. 9 | pub use arch::halt; 10 | -------------------------------------------------------------------------------- /src/custom_targets/arm-none-eabihf.json: -------------------------------------------------------------------------------- 1 | { 2 | "arch": "arm", 3 | "os": "none", 4 | "env": "eabi", 5 | "vendor": "unknown", 6 | "data-layout": "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64", 7 | "dynamic-linking-available": false, 8 | "executables": true, 9 | "linker-flavor": "ld.lld", 10 | "linker": "rust-lld", 11 | "llvm-target": "arm-unknown-eabihf", 12 | "morestack": false, 13 | "panic-strategy": "abort", 14 | "split-stacks-supported": false, 15 | "target-c-int-width": "32", 16 | "target-endian": "little", 17 | "target-pointer-width": "32", 18 | "no-compiler-rt": true, 19 | "relocation-model": "static" 20 | } 21 | -------------------------------------------------------------------------------- /src/custom_targets/x86_64-unknown-none.json: -------------------------------------------------------------------------------- 1 | { 2 | "llvm-target": "x86_64-unknown-none", 3 | "target-endian": "little", 4 | "target-pointer-width": "64", 5 | "target-c-int-width": "32", 6 | "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128", 7 | "arch": "x86_64", 8 | "os": "none", 9 | "env": "", 10 | "vendor": "unknown", 11 | "linker-flavor": "gcc", 12 | "target-family": "oreboot", 13 | "pre-link-args": { 14 | "gcc": ["-m64", "-nostdlib", "-static"] 15 | }, 16 | "features": "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float", 17 | "dynamic-linking": false, 18 | "executables": true, 19 | "relocation-model": "pic", 20 | "code-model": "kernel", 21 | "disable-redzone": true, 22 | "eliminate-frame-pointer": false, 23 | "exe-suffix": "", 24 | "has-rpath": false, 25 | "no-compiler-rt": true, 26 | "no-default-libraries": true, 27 | "position-independent-executables": true, 28 | "has-elf-tls": true 29 | } 30 | -------------------------------------------------------------------------------- /src/drivers/clock/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "clock" 5 | version = "0.1.0" 6 | -------------------------------------------------------------------------------- /src/drivers/clock/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "clock" 3 | version = "0.1.0" 4 | authors = ["Oreboot Authors"] 5 | edition = "2018" 6 | 7 | [profile.release] 8 | opt-level = 'z' # Optimize for size. 9 | -------------------------------------------------------------------------------- /src/drivers/clock/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![deny(warnings)] 3 | /// Trait to set the input clock rate on a driver. 4 | 5 | pub trait ClockNode { 6 | fn set_clock_rate(&mut self, rate: u32); 7 | } 8 | -------------------------------------------------------------------------------- /src/drivers/model/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "model" 5 | version = "0.1.0" 6 | -------------------------------------------------------------------------------- /src/drivers/model/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "model" 3 | version = "0.1.0" 4 | authors = ["Oreboot Authors"] 5 | edition = "2018" 6 | 7 | [profile.release] 8 | opt-level = 'z' # Optimize for size. 9 | -------------------------------------------------------------------------------- /src/drivers/model/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![deny(warnings)] 3 | 4 | pub type Result = core::result::Result; 5 | 6 | pub const EOF: Result = Err("EOF"); 7 | pub const NOT_IMPLEMENTED: Result = Err("not implemented"); 8 | 9 | pub trait Driver { 10 | /// Initialize the device. 11 | fn init(&mut self) -> Result<()> { 12 | Ok(()) 13 | } 14 | /// Positional read. Returns number of bytes read. 15 | /// 16 | /// If there is no more bytes to read, returns `EOF` error (note: 17 | /// `std::io::Read` trait would return 0 in that situation). 18 | fn pread(&self, data: &mut [u8], pos: usize) -> Result; 19 | /// Positional write. Returns number of bytes written. 20 | fn pwrite(&mut self, data: &[u8], pos: usize) -> Result; 21 | /// Shutdown the device. 22 | fn shutdown(&mut self); 23 | } 24 | -------------------------------------------------------------------------------- /src/drivers/sifive/spi/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "clock" 5 | version = "0.1.0" 6 | 7 | [[package]] 8 | name = "model" 9 | version = "0.1.0" 10 | 11 | [[package]] 12 | name = "register" 13 | version = "0.3.3" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | dependencies = [ 16 | "tock-registers 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 17 | ] 18 | 19 | [[package]] 20 | name = "spi" 21 | version = "0.1.0" 22 | dependencies = [ 23 | "clock 0.1.0", 24 | "model 0.1.0", 25 | "register 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 26 | ] 27 | 28 | [[package]] 29 | name = "tock-registers" 30 | version = "0.3.0" 31 | source = "registry+https://github.com/rust-lang/crates.io-index" 32 | 33 | [metadata] 34 | "checksum register 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "469bb5ddde81d67fb8bba4e14d77689b8166cfd077abe7530591cefe29d05823" 35 | "checksum tock-registers 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c758f5195a2e0df9d9fecf6f506506b2766ff74cf64db1e995c87e2761a5c3e2" 36 | -------------------------------------------------------------------------------- /src/drivers/sifive/spi/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "spi" 3 | version = "0.1.0" 4 | authors = ["Oreboot Authors"] 5 | edition = "2018" 6 | 7 | [profile.release] 8 | opt-level = 'z' # Optimize for size. 9 | 10 | [dependencies] 11 | model = { path = "../../model" } 12 | clock = { path = "../../clock" } 13 | register = "0.3.2" 14 | -------------------------------------------------------------------------------- /src/drivers/uart/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "as-slice" 5 | version = "0.1.0" 6 | source = "registry+https://github.com/rust-lang/crates.io-index" 7 | dependencies = [ 8 | "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", 9 | "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 10 | ] 11 | 12 | [[package]] 13 | name = "byteorder" 14 | version = "1.3.2" 15 | source = "registry+https://github.com/rust-lang/crates.io-index" 16 | 17 | [[package]] 18 | name = "clock" 19 | version = "0.1.0" 20 | 21 | [[package]] 22 | name = "generic-array" 23 | version = "0.11.1" 24 | source = "registry+https://github.com/rust-lang/crates.io-index" 25 | dependencies = [ 26 | "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", 27 | ] 28 | 29 | [[package]] 30 | name = "generic-array" 31 | version = "0.12.3" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | dependencies = [ 34 | "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", 35 | ] 36 | 37 | [[package]] 38 | name = "hash32" 39 | version = "0.1.0" 40 | source = "registry+https://github.com/rust-lang/crates.io-index" 41 | dependencies = [ 42 | "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", 43 | ] 44 | 45 | [[package]] 46 | name = "heapless" 47 | version = "0.4.4" 48 | source = "registry+https://github.com/rust-lang/crates.io-index" 49 | dependencies = [ 50 | "as-slice 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 51 | "generic-array 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", 52 | "hash32 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 53 | ] 54 | 55 | [[package]] 56 | name = "model" 57 | version = "0.1.0" 58 | 59 | [[package]] 60 | name = "register" 61 | version = "0.3.3" 62 | source = "registry+https://github.com/rust-lang/crates.io-index" 63 | dependencies = [ 64 | "tock-registers 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 65 | ] 66 | 67 | [[package]] 68 | name = "stable_deref_trait" 69 | version = "1.1.1" 70 | source = "registry+https://github.com/rust-lang/crates.io-index" 71 | 72 | [[package]] 73 | name = "tock-registers" 74 | version = "0.3.0" 75 | source = "registry+https://github.com/rust-lang/crates.io-index" 76 | 77 | [[package]] 78 | name = "typenum" 79 | version = "1.10.0" 80 | source = "registry+https://github.com/rust-lang/crates.io-index" 81 | 82 | [[package]] 83 | name = "uart" 84 | version = "0.1.0" 85 | dependencies = [ 86 | "clock 0.1.0", 87 | "heapless 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", 88 | "model 0.1.0", 89 | "register 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 90 | ] 91 | 92 | [metadata] 93 | "checksum as-slice 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "293dac66b274fab06f95e7efb05ec439a6b70136081ea522d270bc351ae5bb27" 94 | "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" 95 | "checksum generic-array 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8107dafa78c80c848b71b60133954b4a58609a3a1a5f9af037ecc7f67280f369" 96 | "checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" 97 | "checksum hash32 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "12d790435639c06a7b798af9e1e331ae245b7ef915b92f70a39b4cf8c00686af" 98 | "checksum heapless 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e1ae80bbc62401ae8096976857172507cadbd2200f36670e5144634360a05959" 99 | "checksum register 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "469bb5ddde81d67fb8bba4e14d77689b8166cfd077abe7530591cefe29d05823" 100 | "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" 101 | "checksum tock-registers 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c758f5195a2e0df9d9fecf6f506506b2766ff74cf64db1e995c87e2761a5c3e2" 102 | "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" 103 | -------------------------------------------------------------------------------- /src/drivers/uart/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "uart" 3 | version = "0.1.0" 4 | authors = ["Oreboot Authors"] 5 | edition = "2018" 6 | 7 | [profile.release] 8 | opt-level = 'z' # Optimize for size. 9 | 10 | [dependencies] 11 | model = { path = "../model"} 12 | clock = { path = "../clock"} 13 | register = "0.3.2" 14 | # Heapless does not build for rv32imc. 15 | heapless = { version = "0.4.4", optional = true } 16 | 17 | [features] 18 | i8250 = ["heapless"] 19 | pl011 = [] 20 | ns16550 = [] 21 | sifive = [] 22 | log = ["heapless"] 23 | opentitan = [] 24 | debug_port = [] 25 | -------------------------------------------------------------------------------- /src/drivers/uart/src/debug_port.rs: -------------------------------------------------------------------------------- 1 | use model::{Driver, Result}; 2 | 3 | pub struct DebugPort<'a> { 4 | address: usize, 5 | d: &'a mut dyn Driver, 6 | } 7 | 8 | impl<'a> DebugPort<'a> { 9 | pub fn new(address: usize, d: &'a mut dyn Driver) -> DebugPort<'a> { 10 | DebugPort { address, d } 11 | } 12 | } 13 | 14 | impl<'a> Driver for DebugPort<'a> { 15 | // Nothing to set up here 16 | fn init(&mut self) -> Result<()> { 17 | Ok(()) 18 | } 19 | 20 | // DebugPort can only be used to write, nothing here 21 | fn pread(&self, _data: &mut [u8], _offset: usize) -> Result { 22 | Ok(0) 23 | } 24 | 25 | // Just write out byte for byte :) 26 | fn pwrite(&mut self, data: &[u8], _offset: usize) -> Result { 27 | for (_i, &c) in data.iter().enumerate() { 28 | let mut s = [0u8; 1]; 29 | s[0] = c; 30 | self.d.pwrite(&s, self.address).unwrap(); 31 | } 32 | Ok(data.len()) 33 | } 34 | 35 | // Nothing to shut down here 36 | fn shutdown(&mut self) {} 37 | } 38 | -------------------------------------------------------------------------------- /src/drivers/uart/src/i8250.rs: -------------------------------------------------------------------------------- 1 | use model::*; 2 | 3 | pub struct I8250<'a> { 4 | base: usize, 5 | _baud: u32, 6 | d: &'a mut dyn Driver, 7 | } 8 | 9 | impl<'a> I8250<'a> { 10 | pub fn new(base: usize, _baud: u32, d: &'a mut dyn Driver) -> I8250<'a> { 11 | I8250 { base, _baud, d } 12 | } 13 | 14 | /// Poll the status register until the specified field is set to the given value. 15 | /// Returns false iff it timed out. 16 | fn poll_status(&self, mask: u8, val: u8) -> bool { 17 | // Timeout after a few thousand cycles to prevent hanging forever. 18 | for _ in 0..100_000 { 19 | let mut s = [0; 1]; 20 | self.d.pread(&mut s, self.base + 5).unwrap(); 21 | if s[0] & mask == val { 22 | return true; 23 | } 24 | } 25 | return false; 26 | } 27 | } 28 | #[allow(dead_code)] 29 | impl<'a> Driver for I8250<'a> { 30 | // TODO: properly use the register crate. 31 | fn init(&mut self) -> Result<()> { 32 | const DLL: usize = 0x00; // Divisor Latch Low Byte RW 33 | const DLH: usize = 0x01; // Divisor Latch High Byte RW 34 | const IER: usize = 0x01; // Interrupt Enable Register RW 35 | const IIR: usize = 0x02; // Interrupt Identification Register R 36 | const FCR: usize = 0x02; // Fifo Control Register W 37 | const LCR: usize = 0x03; // Line Control Register RW 38 | const MCR: usize = 0x04; // Modem Control Register RW 39 | const LSR: usize = 0x05; // Line Status Register R 40 | const MSR: usize = 0x06; // Modem Status Register R 41 | const SCR: usize = 0x07; // Scratch Register RW 42 | 43 | const FIFOENABLE: u8 = 1; 44 | const DLAB: u8 = 0b1000; // Divisor Latch Access bit 45 | const EIGHTN1: u8 = 0b0011; 46 | 47 | let mut s: [u8; 1] = [0u8; 1]; 48 | self.d.pwrite(&s, self.base + IER).unwrap(); 49 | 50 | /* Enable FIFOs */ 51 | s[0] = FIFOENABLE; 52 | self.d.pwrite(&s, self.base + FCR).unwrap(); 53 | 54 | /* DLAB on */ 55 | // so we can set baud rate. 56 | s[0] = DLAB | EIGHTN1; 57 | self.d.pwrite(&s, self.base + LCR).unwrap(); 58 | 59 | /* Set Baud Rate Divisor. 12 ==> 9600 Baud */ 60 | // 1 for 115200 61 | s[0] = 1; 62 | self.d.pwrite(&s, self.base + DLL).unwrap(); 63 | s[0] = 0; 64 | self.d.pwrite(&s, self.base + DLH).unwrap(); 65 | 66 | /* Set to 3 for 8N1 (8 data bits, no parity, 1 stop bit)*/ 67 | s[0] = EIGHTN1; 68 | self.d.pwrite(&s, self.base + LCR).unwrap(); 69 | Ok(()) 70 | } 71 | 72 | fn pread(&self, data: &mut [u8], _offset: usize) -> Result { 73 | for c in data.iter_mut() { 74 | let mut s = [0u8; 1]; 75 | while !self.poll_status(1, 1) {} 76 | self.d.pread(&mut s, self.base).unwrap(); 77 | *c = s[0]; 78 | } 79 | Ok(data.len()) 80 | } 81 | 82 | fn pwrite(&mut self, data: &[u8], _offset: usize) -> Result { 83 | for (_i, &c) in data.iter().enumerate() { 84 | // Poll the status for long enough to let a char out; then push it out anyway. 85 | while !self.poll_status(0x20, 0x20) && !self.poll_status(0x40, 0x40) {} 86 | let mut s = [0u8; 1]; 87 | s[0] = c; 88 | self.d.pwrite(&s, self.base).unwrap(); 89 | } 90 | Ok(data.len()) 91 | } 92 | 93 | fn shutdown(&mut self) {} 94 | } 95 | 96 | #[cfg(test)] 97 | mod tests { 98 | use super::*; 99 | 100 | /* 101 | * UART pushing into a vec 102 | */ 103 | extern crate heapless; 104 | use heapless::Vec; 105 | pub struct MockPort<'a> { 106 | ldata: &'a mut Vec, 107 | } 108 | 109 | impl<'a> MockPort<'a> { 110 | pub fn new(v: &'a mut Vec) -> MockPort { 111 | MockPort { ldata: v } 112 | } 113 | } 114 | 115 | impl<'a> Driver for MockPort<'a> { 116 | fn init(&mut self) -> Result<()> { 117 | Ok(()) 118 | } 119 | 120 | fn pread(&self, data: &mut [u8], offset: usize) -> Result { 121 | if self.ldata.len() <= offset { 122 | return EOF; 123 | } 124 | data[0] = self.ldata[offset]; 125 | return Ok(0); 126 | } 127 | 128 | fn pwrite(&mut self, data: &[u8], offset: usize) -> Result { 129 | while self.ldata.len() < offset + data.len() { 130 | self.ldata.push(0).unwrap(); 131 | } 132 | 133 | for (i, &c) in data.iter().enumerate() { 134 | self.ldata[offset + i] = c; 135 | } 136 | 137 | Ok(data.len()) 138 | } 139 | 140 | fn shutdown(&mut self) {} 141 | } 142 | 143 | const FCR: usize = 0x02; // Fifo Control Register 144 | const LCR: usize = 0x03; // Line Control Register 145 | 146 | #[test] 147 | fn uart_driver_enables_fifos() { 148 | let mut vec = Vec::::new(); 149 | let port = &mut MockPort::new(&mut vec); 150 | let test_uart = &mut I8250::new(0, 0, port); 151 | test_uart.init().unwrap(); 152 | 153 | assert_eq!(1 & vec[FCR], 1); // FIFOs enabled 154 | } 155 | 156 | // Line control register should have the bottom bits be 0b011 for 8 data bits and one stop bit 157 | #[test] 158 | fn uart_driver_sets_wordlength_and_stopbit() { 159 | let mut vec = Vec::::new(); 160 | let port = &mut MockPort::new(&mut vec); 161 | let test_uart = &mut I8250::new(0, 0, port); 162 | test_uart.init().unwrap(); 163 | 164 | assert_eq!(vec[LCR], 0b011); 165 | } 166 | 167 | // TODO: test baud rate usage 168 | } 169 | -------------------------------------------------------------------------------- /src/drivers/uart/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![feature(llvm_asm)] 3 | 4 | #[cfg(feature = "debug_port")] 5 | pub mod debug_port; 6 | #[cfg(feature = "i8250")] 7 | pub mod i8250; 8 | #[cfg(feature = "log")] 9 | pub mod log; 10 | #[cfg(feature = "ns16550")] 11 | pub mod ns16550; 12 | #[cfg(feature = "null")] 13 | pub mod null; 14 | #[cfg(feature = "opentitan")] 15 | pub mod opentitan; 16 | #[cfg(feature = "pl011")] 17 | pub mod pl011; 18 | #[cfg(feature = "sifive")] 19 | pub mod sifive; 20 | -------------------------------------------------------------------------------- /src/drivers/uart/src/log.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the oreboot project. 3 | * This program is free software; you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation; version 2 of the License. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | */ 12 | 13 | /* 14 | * UART that just pushes into a vec. 15 | */ 16 | 17 | use model::*; 18 | extern crate heapless; // v0.4.x 19 | use heapless::consts::*; 20 | 21 | use heapless::Vec; 22 | 23 | pub struct Log<'a> { 24 | dat: &'a mut Vec, 25 | } 26 | 27 | impl<'a> Log<'a> { 28 | pub fn new(v: &'a mut Vec) -> Log { 29 | Log { dat: v } 30 | } 31 | } 32 | 33 | impl<'a> Driver for Log<'a> { 34 | fn init(&mut self) -> Result<()> { 35 | Ok(()) 36 | } 37 | 38 | fn pread(&self, _data: &mut [u8], _offset: usize) -> Result { 39 | return Ok(0); 40 | } 41 | 42 | fn pwrite(&mut self, data: &[u8], _offset: usize) -> Result { 43 | for (_, &c) in data.iter().enumerate() { 44 | self.dat.push(c).unwrap(); 45 | } 46 | Ok(data.len()) 47 | } 48 | 49 | fn shutdown(&mut self) {} 50 | } 51 | -------------------------------------------------------------------------------- /src/drivers/uart/src/ns16550.rs: -------------------------------------------------------------------------------- 1 | // http://www.ti.com/lit/ds/symlink/pc16550d.pdf 2 | use core::ops; 3 | use model::*; 4 | 5 | use register::mmio::{ReadOnly, ReadWrite}; 6 | use register::{register_bitfields, Field}; 7 | 8 | #[repr(C)] 9 | pub struct RegisterBlock { 10 | d: ReadWrite, 11 | ie: ReadWrite, 12 | fc: ReadWrite, 13 | lc: ReadWrite, 14 | mc: ReadWrite, 15 | ls: ReadOnly, 16 | } 17 | 18 | pub struct NS16550 { 19 | base: usize, 20 | } 21 | 22 | impl ops::Deref for NS16550 { 23 | type Target = RegisterBlock; 24 | 25 | fn deref(&self) -> &Self::Target { 26 | unsafe { &*self.ptr() } 27 | } 28 | } 29 | 30 | impl NS16550 { 31 | pub fn new(base: usize, _baudrate: u32) -> NS16550 { 32 | NS16550 { base: base } 33 | } 34 | 35 | /// Returns a pointer to the register block 36 | fn ptr(&self) -> *const RegisterBlock { 37 | self.base as *const _ 38 | } 39 | /// Poll the status register until the specified field is set to the given value. 40 | /// Returns false iff it timed out. 41 | fn poll_status(&self, bit: Field, val: bool) -> bool { 42 | // Timeout after a few thousand cycles to prevent hanging forever. 43 | for _ in 0..100_000 { 44 | if self.ls.is_set(bit) == val { 45 | return true; 46 | } 47 | } 48 | return false; 49 | } 50 | } 51 | 52 | impl Driver for NS16550 { 53 | fn init(&mut self) -> Result<()> { 54 | /* disable all interrupts */ 55 | self.ie.set(0u8); 56 | /* Enable dLAB */ 57 | self.lc.write(LC::DivisorLatchAccessBit::BaudRate); 58 | // Until we know the clock rate the divisor values are kind of 59 | // impossible to know. Throw in a phony value. 60 | self.lc.write(LC::WLEN::WLEN_8); 61 | // TOdO: what are these bits. how do we write them. 62 | self.fc.set(0xc7); 63 | self.mc.set(0x0b); 64 | self.lc.write(LC::DivisorLatchAccessBit::Normal); 65 | Ok(()) 66 | } 67 | 68 | fn pread(&self, data: &mut [u8], _offset: usize) -> Result { 69 | for c in data.iter_mut() { 70 | while self.ls.is_set(LS::IF) {} 71 | *c = self.d.read(D::DATA) as u8; 72 | } 73 | Ok(data.len()) 74 | } 75 | 76 | fn pwrite(&mut self, data: &[u8], _offset: usize) -> Result { 77 | for (i, &c) in data.iter().enumerate() { 78 | if !self.poll_status(LS::OE, false) { 79 | return Ok(i); 80 | } 81 | self.d.set(c as u8); 82 | } 83 | Ok(data.len()) 84 | } 85 | 86 | fn shutdown(&mut self) {} 87 | } 88 | 89 | // TODO: bitfields 90 | register_bitfields! { 91 | u8, 92 | // Data register 93 | D [ 94 | DATA OFFSET(0) NUMBITS(8) [] 95 | ], 96 | IE [ 97 | RX OFFSET(0) NUMBITS(1) [], 98 | TX OFFSET(1) NUMBITS(1) [], 99 | Error OFFSET(2) NUMBITS(1) [], 100 | StatusChange OFFSET(3) NUMBITS(1) [] 101 | ], 102 | FC [ 103 | DATA OFFSET(0) NUMBITS(8) [] 104 | ], 105 | LC [ 106 | WLEN OFFSET(0) NUMBITS(2) [ 107 | WLEN_5 = 0, 108 | WLEN_6 = 1, 109 | WLEN_7 = 2, 110 | WLEN_8 = 3 111 | ], 112 | StopBits OFFSET(3) NUMBITS(1) [], 113 | ParityEnable OFFSET(4) NUMBITS(1) [], 114 | EvenParity OFFSET(5) NUMBITS (1) [], 115 | StickParity OFFSET(6) NUMBITS (1) [], 116 | DivisorLatchAccessBit OFFSET(7) NUMBITS (1) [ 117 | Normal = 0, 118 | BaudRate = 1 119 | ] 120 | ], 121 | MC [ 122 | DATA OFFSET(0) NUMBITS(8) [] 123 | ], 124 | LS [ 125 | IF OFFSET(0) NUMBITS(1) [], 126 | OE OFFSET(1) NUMBITS(1) [] 127 | ] 128 | } 129 | -------------------------------------------------------------------------------- /src/drivers/uart/src/null.rs: -------------------------------------------------------------------------------- 1 | // null is a simple Null driver. 2 | // TODO: move it out of uart. 3 | use model::*; 4 | 5 | pub struct Null; 6 | 7 | impl Driver for Null { 8 | fn init(&mut self) -> Result<()> { 9 | Ok(()) 10 | } 11 | 12 | fn pread(&self, _data: &mut [u8], _offset: usize) -> Result { 13 | Ok(0) 14 | } 15 | 16 | fn pwrite(&mut self, data: &[u8], _offset: usize) -> Result { 17 | Ok(data.len()) 18 | } 19 | 20 | fn shutdown(&mut self) {} 21 | } 22 | -------------------------------------------------------------------------------- /src/drivers/wrappers/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "model" 5 | version = "0.1.0" 6 | 7 | [[package]] 8 | name = "wrappers" 9 | version = "0.1.0" 10 | dependencies = [ 11 | "model", 12 | ] 13 | -------------------------------------------------------------------------------- /src/drivers/wrappers/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "wrappers" 3 | version = "0.1.0" 4 | authors = ["Oreboot Authors"] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | model = { path = "../model"} 9 | 10 | [profile.release] 11 | opt-level = 'z' # Optimize for size. 12 | -------------------------------------------------------------------------------- /src/drivers/wrappers/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![deny(warnings)] 3 | 4 | use core::slice::{from_raw_parts, from_raw_parts_mut}; 5 | use model::*; 6 | 7 | pub struct DoD<'a> { 8 | drivers: &'a mut [&'a mut dyn Driver], 9 | } 10 | 11 | impl<'a> DoD<'a> { 12 | pub fn new(drivers: &'a mut [&'a mut dyn Driver]) -> DoD<'a> { 13 | DoD { drivers } 14 | } 15 | } 16 | 17 | impl<'a> Driver for DoD<'a> { 18 | fn init(&mut self) -> Result<()> { 19 | self.drivers.iter_mut().fold(Ok(()), |ret, d| { 20 | match (ret, d.init()) { 21 | (Ok(()), Ok(())) => Ok(()), 22 | (_, Err(err)) => Err(err), 23 | (err, _) => err, 24 | } 25 | }) 26 | } 27 | 28 | fn pread(&self, _data: &mut [u8], _pos: usize) -> Result { 29 | NOT_IMPLEMENTED 30 | } 31 | 32 | // If there are multiple errors, the last one is returned. 33 | fn pwrite(&mut self, data: &[u8], pos: usize) -> Result { 34 | self.drivers.iter_mut().fold(Ok(0), |ret, d| { 35 | match (ret, d.pwrite(data, pos)) { 36 | (Ok(sum), Ok(count)) => Ok(sum + count), 37 | (_, err @ Err(_)) => err, 38 | (err, _) => err, 39 | } 40 | }) 41 | } 42 | 43 | fn shutdown(&mut self) { 44 | self.drivers.iter_mut().for_each(|d| d.shutdown()) 45 | } 46 | } 47 | 48 | /// The driver reads directly from memory. 49 | pub struct Memory; 50 | 51 | impl Driver for Memory { 52 | fn pread(&self, data: &mut [u8], pos: usize) -> Result { 53 | let src = unsafe { from_raw_parts(pos as *const u8, data.len()) }; 54 | data.copy_from_slice(src); 55 | Ok(data.len()) 56 | } 57 | 58 | fn pwrite(&mut self, data: &[u8], pos: usize) -> Result { 59 | let dst = unsafe { from_raw_parts_mut(pos as *mut u8, data.len()) }; 60 | dst.copy_from_slice(data); 61 | Ok(data.len()) 62 | } 63 | 64 | fn shutdown(&mut self) {} 65 | } 66 | 67 | /// The driver reads from a slice. 68 | pub struct SliceReader<'a> { 69 | data: &'a [u8], 70 | } 71 | 72 | impl<'a> SliceReader<'a> { 73 | pub fn new(data: &'a [u8]) -> SliceReader { 74 | SliceReader { data } 75 | } 76 | } 77 | 78 | impl<'a> Driver for SliceReader<'a> { 79 | fn pread(&self, data: &mut [u8], pos: usize) -> Result { 80 | if pos >= self.data.len() { 81 | return EOF; 82 | } 83 | let count = data.len().min(self.data.len() - pos); 84 | data[..count].copy_from_slice(&self.data[pos..pos + count]); 85 | Ok(count) 86 | } 87 | 88 | fn pwrite(&mut self, _data: &[u8], _pos: usize) -> Result { 89 | NOT_IMPLEMENTED 90 | } 91 | 92 | fn shutdown(&mut self) {} 93 | } 94 | 95 | /// The driver reads from a section (offset+size) of another driver. 96 | pub struct SectionReader<'a, D: Driver> { 97 | driver: &'a D, 98 | offset: usize, 99 | size: usize, 100 | } 101 | 102 | impl<'a, D: Driver> SectionReader<'a, D> { 103 | pub fn new(driver: &'a D, offset: usize, size: usize) -> SectionReader { 104 | SectionReader { driver, offset, size } 105 | } 106 | } 107 | 108 | impl<'a, D: Driver> Driver for SectionReader<'a, D> { 109 | fn pread(&self, data: &mut [u8], pos: usize) -> Result { 110 | if pos >= self.size { 111 | return EOF; 112 | } 113 | let count = core::cmp::min(data.len(), self.size - pos); 114 | self.driver.pread(&mut data[..count], pos + self.offset) 115 | } 116 | 117 | fn pwrite(&mut self, _data: &[u8], _pos: usize) -> Result { 118 | NOT_IMPLEMENTED 119 | } 120 | 121 | fn shutdown(&mut self) {} 122 | } 123 | -------------------------------------------------------------------------------- /src/drivers/wrappers/tests/tests.rs: -------------------------------------------------------------------------------- 1 | extern crate wrappers; 2 | 3 | use model::Driver; 4 | use wrappers::SliceReader; 5 | 6 | fn check_pread(device: &impl Driver, pos: usize, expected: &[u8]) { 7 | let mut buf = std::vec::Vec::new(); 8 | buf.resize(expected.len(), 0); 9 | let size = device.pread(buf.as_mut_slice(), pos).unwrap(); 10 | assert_eq!(size, expected.len()); 11 | assert_eq!(buf, expected); 12 | } 13 | 14 | #[test] 15 | fn test_slice_reader() { 16 | let data = [1, 2, 3, 4, 5]; 17 | let driver = SliceReader::new(&data); 18 | 19 | check_pread(&driver, 0, &[1]); 20 | check_pread(&driver, 0, &[1, 2, 3, 4, 5]); 21 | check_pread(&driver, 1, &[2, 3, 4, 5]); 22 | check_pread(&driver, 4, &[5]); 23 | } 24 | 25 | #[test] 26 | fn test_slice_reader_returns_zero_for_empty_buf() { 27 | let data = [1, 2, 3, 4, 5]; 28 | let driver = SliceReader::new(&data); 29 | let mut buf = [0; 0]; 30 | 31 | assert_eq!(0, driver.pread(&mut buf, 1).unwrap()); 32 | } 33 | 34 | #[test] 35 | fn test_slice_reader_returns_number_of_bytes_read() { 36 | let data = [1, 2, 3, 4, 5]; 37 | let driver = SliceReader::new(&data); 38 | let mut buf = [0; 10]; 39 | 40 | assert_eq!(5, driver.pread(&mut buf, 0).unwrap()); 41 | assert_eq!(&buf[..5], &data); 42 | assert_eq!(&buf[5..], &[0; 5]); 43 | } 44 | 45 | #[test] 46 | fn test_slice_reader_returns_eof() { 47 | let data = [1, 2, 3, 4, 5]; 48 | let driver = SliceReader::new(&data); 49 | let mut buf = [0; 5]; 50 | 51 | assert_eq!(driver.pread(&mut buf, 5).err(), Some("EOF")); 52 | } 53 | 54 | #[test] 55 | fn test_slice_reader_returns_eof_with_empty_buf() { 56 | let data = [1, 2, 3, 4, 5]; 57 | let driver = SliceReader::new(&data); 58 | let mut buf = [0; 0]; 59 | 60 | assert_eq!(driver.pread(&mut buf, 5).err(), Some("EOF")); 61 | } 62 | -------------------------------------------------------------------------------- /src/lib/consts/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "consts" 5 | version = "0.1.0" 6 | -------------------------------------------------------------------------------- /src/lib/consts/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "consts" 3 | version = "0.1.0" 4 | authors = ["Oreboot Authors"] 5 | edition = "2018" 6 | 7 | [profile.release] 8 | opt-level = 'z' # Optimize for size. 9 | -------------------------------------------------------------------------------- /src/lib/consts/src/lib.rs: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0-only */ 2 | #[allow(non_upper_case_globals)] 3 | mod units { 4 | pub const KiB: usize = 1 << 10; 5 | pub const MiB: usize = 1 << 20; 6 | pub const GiB: usize = 1 << 30; 7 | } 8 | pub use units::*; 9 | -------------------------------------------------------------------------------- /src/lib/device_tree/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "autocfg" 5 | version = "0.1.4" 6 | source = "registry+https://github.com/rust-lang/crates.io-index" 7 | 8 | [[package]] 9 | name = "byteorder" 10 | version = "1.3.1" 11 | source = "registry+https://github.com/rust-lang/crates.io-index" 12 | 13 | [[package]] 14 | name = "device_tree" 15 | version = "0.1.0" 16 | dependencies = [ 17 | "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 18 | "model 0.1.0", 19 | "num-derive 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", 20 | "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 21 | "print 0.1.0", 22 | "wrappers 0.1.0", 23 | ] 24 | 25 | [[package]] 26 | name = "model" 27 | version = "0.1.0" 28 | 29 | [[package]] 30 | name = "num-derive" 31 | version = "0.2.5" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | dependencies = [ 34 | "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", 35 | "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", 36 | "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", 37 | ] 38 | 39 | [[package]] 40 | name = "num-traits" 41 | version = "0.2.8" 42 | source = "registry+https://github.com/rust-lang/crates.io-index" 43 | dependencies = [ 44 | "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 45 | ] 46 | 47 | [[package]] 48 | name = "print" 49 | version = "0.1.0" 50 | dependencies = [ 51 | "model 0.1.0", 52 | ] 53 | 54 | [[package]] 55 | name = "proc-macro2" 56 | version = "0.4.30" 57 | source = "registry+https://github.com/rust-lang/crates.io-index" 58 | dependencies = [ 59 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 60 | ] 61 | 62 | [[package]] 63 | name = "quote" 64 | version = "0.6.12" 65 | source = "registry+https://github.com/rust-lang/crates.io-index" 66 | dependencies = [ 67 | "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", 68 | ] 69 | 70 | [[package]] 71 | name = "syn" 72 | version = "0.15.34" 73 | source = "registry+https://github.com/rust-lang/crates.io-index" 74 | dependencies = [ 75 | "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", 76 | "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", 77 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 78 | ] 79 | 80 | [[package]] 81 | name = "unicode-xid" 82 | version = "0.1.0" 83 | source = "registry+https://github.com/rust-lang/crates.io-index" 84 | 85 | [[package]] 86 | name = "wrappers" 87 | version = "0.1.0" 88 | dependencies = [ 89 | "model 0.1.0", 90 | ] 91 | 92 | [metadata] 93 | "checksum autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0e49efa51329a5fd37e7c79db4621af617cd4e3e5bc224939808d076077077bf" 94 | "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" 95 | "checksum num-derive 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "eafd0b45c5537c3ba526f79d3e75120036502bebacbb3f3220914067ce39dbf2" 96 | "checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" 97 | "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" 98 | "checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db" 99 | "checksum syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)" = "a1393e4a97a19c01e900df2aec855a29f71cf02c402e2f443b8d2747c25c5dbe" 100 | "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" 101 | -------------------------------------------------------------------------------- /src/lib/device_tree/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "device_tree" 3 | version = "0.1.0" 4 | authors = ["Oreboot Authors"] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | byteorder = { version = "1", default-features = false } 9 | model = { path = "../../drivers/model"} 10 | num-derive = { version = "0.2", default-features = false } 11 | num-traits = { version = "0.2", default-features = false } 12 | print = { path = "../../lib/print" } 13 | wrappers = { path = "../../drivers/wrappers"} 14 | 15 | [profile.release] 16 | opt-level = 'z' # Optimize for size. 17 | -------------------------------------------------------------------------------- /src/lib/device_tree/tests/integration_test.rs: -------------------------------------------------------------------------------- 1 | extern crate device_tree; 2 | 3 | use device_tree::{Entry, FdtReader}; 4 | use model::{Driver, Result}; 5 | use std::io::Write; 6 | use std::process::{Command, Stdio}; 7 | use wrappers::SliceReader; 8 | 9 | fn assert_start_node(entry: Result>>, expected_name: &str) { 10 | let entry = entry.unwrap().unwrap(); 11 | if let Entry::StartNode { name } = entry { 12 | assert_eq!(name, expected_name); 13 | } else { 14 | panic!("Expected StartNode!") 15 | } 16 | } 17 | 18 | fn assert_end_node(entry: Result>>) { 19 | let entry = entry.unwrap().unwrap(); 20 | if let Entry::EndNode = entry { 21 | } else { 22 | panic!("Expected EndNode!") 23 | } 24 | } 25 | 26 | fn assert_property(entry: Result>>, expected_name: &str, expected_value: &[u8]) { 27 | let entry = entry.unwrap().unwrap(); 28 | if let Entry::Property { name, value } = entry { 29 | assert_eq!(name, expected_name); 30 | assert_eq!(read_all(&value), expected_value); 31 | } else { 32 | panic!("Expected Property!") 33 | } 34 | } 35 | 36 | fn dts_to_dtb(dts: &str) -> std::vec::Vec { 37 | let mut dtc = Command::new("dtc").arg("-O").arg("dtb").stdin(Stdio::piped()).stdout(Stdio::piped()).stderr(Stdio::piped()).spawn().unwrap(); 38 | dtc.stdin.as_mut().unwrap().write_all(dts.as_bytes()).unwrap(); 39 | let output = dtc.wait_with_output().unwrap(); 40 | if output.status.success() { 41 | return output.stdout; 42 | } 43 | panic!("dtc command failed: {:?}", String::from_utf8_lossy(&output.stderr)) 44 | } 45 | 46 | fn read_all(d: &impl Driver) -> std::vec::Vec { 47 | let mut data = [0; 500]; 48 | let size = match d.pread(&mut data, 0) { 49 | Ok(x) => Ok(x), 50 | Err("EOF") => Ok(0), 51 | Err(other) => Err(other), 52 | } 53 | .unwrap(); 54 | let mut result = std::vec::Vec::new(); 55 | result.extend_from_slice(&data[0..size]); 56 | return result; 57 | } 58 | 59 | #[test] 60 | fn test_reads_empty_device_tree() { 61 | let data = dts_to_dtb("/dts-v1/; / { };"); 62 | let slice_reader = &SliceReader::new(&data); 63 | let reader = FdtReader::new(slice_reader).unwrap(); 64 | let mut it = reader.walk(); 65 | 66 | assert_start_node(it.next(), ""); 67 | assert_end_node(it.next()); 68 | assert!(it.next().unwrap().is_none()); 69 | } 70 | 71 | #[test] 72 | fn test_reads_properties() { 73 | let data = dts_to_dtb( 74 | r#" 75 | /dts-v1/; 76 | / { 77 | #address-cells = <1>; 78 | };"#, 79 | ); 80 | let slice_reader = &SliceReader::new(&data); 81 | let reader = FdtReader::new(slice_reader).unwrap(); 82 | let mut it = reader.walk(); 83 | 84 | assert_start_node(it.next(), ""); 85 | assert_property(it.next(), "#address-cells", &vec![0, 0, 0, 1]); 86 | assert_end_node(it.next()); 87 | assert!(it.next().unwrap().is_none()); 88 | } 89 | 90 | #[test] 91 | fn test_reads_empty_properties() { 92 | let data = dts_to_dtb( 93 | r#" 94 | /dts-v1/; 95 | / { 96 | #address-cells; 97 | };"#, 98 | ); 99 | let slice_reader = &SliceReader::new(&data); 100 | let reader = FdtReader::new(slice_reader).unwrap(); 101 | let mut it = reader.walk(); 102 | 103 | assert_start_node(it.next(), ""); 104 | assert_property(it.next(), "#address-cells", &vec![]); 105 | assert_end_node(it.next()); 106 | assert!(it.next().unwrap().is_none()); 107 | } 108 | 109 | #[test] 110 | fn test_reads_nested_nodes() { 111 | let data = dts_to_dtb( 112 | r#" 113 | /dts-v1/; 114 | / { 115 | node1 { 116 | #address-cells = "ok"; 117 | node2 { 118 | }; 119 | }; 120 | node3 { 121 | }; 122 | };"#, 123 | ); 124 | let slice_reader = &SliceReader::new(&data); 125 | let reader = FdtReader::new(slice_reader).unwrap(); 126 | let mut it = reader.walk(); 127 | 128 | assert_start_node(it.next(), ""); 129 | assert_start_node(it.next(), "node1"); 130 | assert_property(it.next(), "#address-cells", &vec![111, 107, 0]); 131 | assert_start_node(it.next(), "node2"); 132 | assert_end_node(it.next()); 133 | assert_end_node(it.next()); 134 | assert_start_node(it.next(), "node3"); 135 | assert_end_node(it.next()); 136 | assert_end_node(it.next()); 137 | assert!(it.next().unwrap().is_none()); 138 | } 139 | 140 | #[test] 141 | fn test_returns_error_when_magic_is_invalid() { 142 | let mut data = dts_to_dtb( 143 | r#" 144 | /dts-v1/; 145 | / { 146 | #address-cells = "ok"; 147 | };"#, 148 | ); 149 | // Magic is a first number 150 | data[0] = 1; 151 | let slice_reader = &SliceReader::new(&data); 152 | assert_eq!(FdtReader::new(slice_reader).err(), Some("invalid magic in device tree header")); 153 | } 154 | 155 | #[test] 156 | fn test_returns_error_when_header_is_too_short() { 157 | let data = dts_to_dtb( 158 | r#" 159 | /dts-v1/; 160 | / { 161 | #address-cells = "ok"; 162 | };"#, 163 | ); 164 | let slice_reader = &SliceReader::new(&data[0..4]); 165 | assert_eq!(FdtReader::new(slice_reader).err(), Some("not enough data to read device tree header")); 166 | } 167 | -------------------------------------------------------------------------------- /src/lib/print/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "model" 5 | version = "0.1.0" 6 | 7 | [[package]] 8 | name = "print" 9 | version = "0.1.0" 10 | dependencies = [ 11 | "model", 12 | ] 13 | -------------------------------------------------------------------------------- /src/lib/print/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "print" 3 | version = "0.1.0" 4 | authors = ["Oreboot Authors"] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | model = { path = "../../drivers/model"} 9 | 10 | [profile.release] 11 | opt-level = 'z' # Optimize for size. 12 | -------------------------------------------------------------------------------- /src/lib/print/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | 3 | use core::fmt; 4 | use model::Driver; 5 | 6 | pub struct WriteTo<'a> { 7 | drv: &'a mut dyn Driver, 8 | } 9 | 10 | impl<'a> WriteTo<'a> { 11 | pub fn new(drv: &'a mut dyn Driver) -> Self { 12 | WriteTo { drv } 13 | } 14 | } 15 | 16 | impl<'a> fmt::Write for WriteTo<'a> { 17 | fn write_str(&mut self, s: &str) -> fmt::Result { 18 | match self.drv.pwrite(s.as_bytes(), 0) { 19 | Err(_) => Err(fmt::Error), 20 | _ => Ok(()), 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/lib/util/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "util" 5 | version = "0.1.0" 6 | -------------------------------------------------------------------------------- /src/lib/util/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "util" 3 | version = "0.1.0" 4 | authors = ["Oreboot Authors"] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | 9 | [profile.release] 10 | opt-level = 'z' # Optimize for size. 11 | 12 | -------------------------------------------------------------------------------- /src/lib/util/src/lib.rs: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0-only */ 2 | 3 | #[inline] 4 | pub fn round_up_4k(num: usize) -> usize { 5 | num.checked_add(0xfff).expect("overflow in round_up_4k()") & !0xfff 6 | } 7 | 8 | #[inline] 9 | pub fn round_down_4k(num: usize) -> usize { 10 | num & !0xfff 11 | } 12 | 13 | #[cfg(test)] 14 | mod tests { 15 | use super::round_up_4k; 16 | 17 | #[test] 18 | fn round_up_4k_test_small() { 19 | assert_eq!(round_up_4k(0), 0); 20 | assert_eq!(round_up_4k(1), 4096); 21 | assert_eq!(round_up_4k(4095), 4096); 22 | assert_eq!(round_up_4k(4096), 4096); 23 | assert_eq!(round_up_4k(4097), 8192); 24 | } 25 | 26 | #[test] 27 | fn round_up_4k_test_big() { 28 | assert_eq!(round_up_4k(usize::MAX & !0xFFF), usize::MAX & !0xFFF); 29 | assert_eq!(round_up_4k(usize::MAX - 4095), usize::MAX & !0xFFF); 30 | assert_eq!(round_up_4k(usize::MAX - 4096), usize::MAX & !0xFFF); 31 | assert_eq!(round_up_4k(usize::MAX - 4097), usize::MAX & !0xFFF); 32 | } 33 | 34 | #[test] 35 | #[should_panic] 36 | fn round_up_4k_test_panic_max() { 37 | round_up_4k(usize::MAX); 38 | } 39 | 40 | #[test] 41 | #[should_panic] 42 | fn round_up_4k_test_panic() { 43 | round_up_4k((usize::MAX & !0xFFF) + 1); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/mainboard/amd/romecrb/.cargo/config: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "x86_64-unknown-none" 3 | 4 | [target.x86_64-unknown-none] 5 | rustflags = [ 6 | "-C", "link-arg=-Tlink.ld", "-C", "link-arg=-nostdlib", "-C", "link-arg=-nostartfiles", 7 | ] 8 | -------------------------------------------------------------------------------- /src/mainboard/amd/romecrb/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "romecrb" 3 | version = "0.1.0" 4 | authors = ["Oreboot Authors"] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | arch = { path = "../../../arch/x86/x86_64"} 9 | console = { path = "../../../console" } 10 | model = { path = "../../../drivers/model" } 11 | print = { path = "../../../lib/print" } 12 | payloads = { path = "../../../../payloads"} 13 | wrappers = { path = "../../../drivers/wrappers"} 14 | 15 | heapless = "0.4.x" 16 | register = "0.3.2" 17 | static-ref = "0.1.1" 18 | postcard = "0.4.3" 19 | 20 | [dependencies.uart] 21 | path = "../../../drivers/uart" 22 | features = ["i8250"] 23 | 24 | [profile.release] 25 | opt-level = 'z' # Optimize for size. 26 | lto = true 27 | panic = "abort" 28 | 29 | [profile.dev] 30 | panic = "abort" 31 | -------------------------------------------------------------------------------- /src/mainboard/amd/romecrb/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = x86_64-unknown-none 2 | QEMU = qemu-system-x86_64 3 | QEMU_FLAGS = -m 2g -machine q35 -nographic -bios $(IMAGE) -cpu Icelake-Server -monitor $(MONITOR) -serial stdio 4 | include ../../../../Makefile.inc 5 | include ../../../../Makefile.qemu.inc 6 | -------------------------------------------------------------------------------- /src/mainboard/amd/romecrb/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | println!("cargo:rerun-if-changed=link.ld"); 3 | } 4 | -------------------------------------------------------------------------------- /src/mainboard/amd/romecrb/fixed-dtfs.dts: -------------------------------------------------------------------------------- 1 | /dts-v1/; 2 | 3 | / { 4 | #address-cells = <1>; 5 | #size-cells = <1>; 6 | 7 | flash-info { 8 | compatible = "ore-flashinfo"; 9 | board-name = "Rome CRB"; 10 | category = "AMD"; 11 | board-url = "http://wiki.qemu.org/Main_Page"; 12 | areas { 13 | area@0 { 14 | description = "Boot Blob"; 15 | compatible = "ore-bootblob"; 16 | offset = <0x3f0000>; 17 | size = <0x10000>; 18 | file = "$(TARGET_DIR)/bootblob.bin"; 19 | }; 20 | area@1 { 21 | description = "Fixed DTFS"; 22 | compatible = "ore-dtfs"; 23 | offset = <0x3e8000>; 24 | size = <0x8000>; 25 | file = "$(TARGET_DIR)/fixed-dtfs.dtb"; 26 | }; 27 | area@2 { 28 | description = "NVRAM A"; 29 | compatible = "ore-nvram"; 30 | half = <0>; 31 | offset = <0x3e0000>; 32 | size = <0x8000>; 33 | }; 34 | area@3 { 35 | description = "NVRAM B"; 36 | compatible = "ore-nvram"; 37 | half = <1>; 38 | offset = <0x3d0000>; 39 | size = <0x8000>; 40 | }; 41 | area@4 { 42 | description = "RomPayload DTFS A"; 43 | compatible = "ore-rompayload"; 44 | half = <0>; 45 | offset = <0x3c8000>; 46 | size = <0x4000>; 47 | }; 48 | area@5 { 49 | description = "RomPayload DTFS B"; 50 | compatible = "ore-rompayload"; 51 | half = <1>; 52 | offset = <0x3c0000>; 53 | size = <0x4000>; 54 | }; 55 | area@6 { 56 | description = "RamPayload DTFS A"; 57 | compatible = "ore-rampayload"; 58 | half = <0>; 59 | offset = <0x0>; 60 | size = <0x300000>; 61 | file = "$(PAYLOAD_A)"; 62 | }; 63 | }; 64 | }; 65 | }; 66 | -------------------------------------------------------------------------------- /src/mainboard/amd/romecrb/jmporeboot.S: -------------------------------------------------------------------------------- 1 | // This works but it's too early in the game, 2 | // protected start wants to load seg registers and we don't 3 | // want that. 4 | // push $0x76ff0097 5 | // 76ff00b7 : 6 | //movl $0x10000, %esp 7 | //push $0x76ff0088 8 | //push $0x76ff0098 9 | push $0x76ff0000 10 | 11 | ret 12 | // 724 as -o jmporeboot jmporeboot.S 13 | // 726 objcopy -O binary jmporeboot jmporeboot.bin 14 | -------------------------------------------------------------------------------- /src/mainboard/amd/romecrb/jmporeboot.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orangecms/oreboot/e66c077413956bf4da78e855cda2c7b8cac0aa00/src/mainboard/amd/romecrb/jmporeboot.bin -------------------------------------------------------------------------------- /src/mainboard/amd/romecrb/link.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | ENTRY(_boot); 26 | 27 | SECTIONS 28 | { 29 | . = 0x76ff0000; 30 | .bootblock : 31 | { 32 | KEEP(*(.bootblock.boot)); 33 | KEEP(*(.text .text.*)); 34 | KEEP(*(.rodata .rodata.*)); 35 | /* There should be no 'data' as such but we'll fix it later */ 36 | KEEP(*(.data.*)) 37 | } 38 | /* . = 0xfffffff0; 39 | .reset . : 40 | { 41 | KEEP(*(.reset .reset.* .reset*)) 42 | } 43 | */ 44 | /DISCARD/ : { *(.comment) *(.note*) *(.eh_frame*) 45 | /* Unused exception related info that only wastes space */ 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/mainboard/amd/romecrb/loop.S: -------------------------------------------------------------------------------- 1 | .code32 2 | call 1f 3 | 1: 4 | popl %eax 5 | 1: 6 | // movb $0xaa, %al 7 | outb %al, $0x80 8 | jmp 1b 9 | -------------------------------------------------------------------------------- /src/mainboard/amd/romecrb/loop.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orangecms/oreboot/e66c077413956bf4da78e855cda2c7b8cac0aa00/src/mainboard/amd/romecrb/loop.bin -------------------------------------------------------------------------------- /src/mainboard/amd/romecrb/patch.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "io/ioutil" 6 | "log" 7 | "strconv" 8 | "strings" 9 | ) 10 | 11 | var ( 12 | in = flag.String("in", "Ethanol-X_BIOS.16.bin", "in file") 13 | out = flag.String("out", "bios16.bin", "out file") 14 | ) 15 | 16 | func main() { 17 | b, err := ioutil.ReadFile(*in) 18 | if err != nil { 19 | log.Fatal(err) 20 | } 21 | a := flag.Args() 22 | if len(a) == 0 { 23 | // works with simply outb jmp 1b. a = append(a, "loop.bin@0xFFEFBF") 24 | // fails if stack is used.a = append(a, "loop.bin@0xFFEFBF") 25 | // works and shows log 8 bits a = append(a, "loop.bin@0xFF_fa0f") 26 | // works and shows fa a = append(a, "looppostEIP15:8.bin@0xFF_fa0f") 27 | // shows ff a = append(a, "looppostEIP23:16.bin@0xFFfa0f") 28 | // works, shows 76!!! a = append(a, "looppostEIP31:24.bin@0xFFfa0f") 29 | a = append(a, "jmporeboot.bin@FFfa0f") 30 | // GPF a = append(a, "jmpcoreboot.bin@FFefbf") 31 | a = append(a, "target/x86_64-unknown-none/release/bootblob.bin@FF0000@EF00") 32 | //a = append(a, "build/coreboot.rom@C00000@3f0000") 33 | //a = append(a, "target/x86_64-unknown-none/release/bootblob.bin@D00000@2f0000") 34 | } 35 | for _, v := range a { 36 | parms := strings.Split(v, "@") 37 | if len(parms) < 2 || len(parms) > 3 { 38 | log.Fatalf("malformed arg: must be file@off[@size]: %v", v) 39 | } 40 | f := parms[0] 41 | o, err := strconv.ParseUint(parms[1], 16, 24) 42 | if err != nil { 43 | log.Fatal(err) 44 | } 45 | off := int(o) 46 | patch, err := ioutil.ReadFile(f) 47 | if err != nil { 48 | log.Fatal(err) 49 | } 50 | if len(patch) > 0x400000 { 51 | patch = patch[len(patch)-0x400000:] 52 | log.Printf("Adjusted length to %#x", len(patch)) 53 | } 54 | if off > len(b) { 55 | log.Fatalf("Off %d is > len of file %d", off, len(b)) 56 | } 57 | plen := len(patch) 58 | if len(parms) == 3 { 59 | l, err := strconv.ParseUint(parms[2], 16, 24) 60 | if err != nil { 61 | log.Fatal(err) 62 | } 63 | plen = int(l) 64 | } 65 | if (off + plen) > len(b) { 66 | log.Fatalf("Off %d + len %d is > len of file %d", off, plen, len(b)) 67 | } 68 | if plen > len(patch) { 69 | log.Printf("(warning)Patch will only be %#x bytes, not %#x bytes\n", len(patch), plen) 70 | plen = len(patch) 71 | } 72 | log.Printf("Patch %v at %#x for %#x bytes", f, off, plen) 73 | copy(b[off:], patch[:plen]) 74 | } 75 | if err := ioutil.WriteFile(*out, b, 0644); err != nil { 76 | log.Fatal(err) 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/mainboard/amd/romecrb/pt.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | //#define PTLX(v, l) (((v)>>(((l)*PTSHFT)+PGSHFT) & ((1<> ((level * shft) + pgshft)) & msk 16 | } 17 | 18 | // how much address space a level covers. 19 | func span(level uint) uint { 20 | // #define PGLSZ(l) (1<<(((l)*PTSHFT)+PGSHFT)) 21 | return (1 << (((level) * shft) + pgshft)) 22 | } 23 | func main() { 24 | var pml4 [1]uint64 25 | var pml3 [512]uint64 26 | // There are 4096 of these. 27 | //var pml2 [0x1000000 / 4096]uint64 28 | // that's fine -- 512G 29 | pml4[ptlx(0, 3)] = 0x2003 30 | // Each entry in the pml3 points to one ptp 31 | pml3[ptlx(0, 2)] = 0x83 32 | pml3[ptlx(0x40000000, 2)] = 0x40000083 33 | pml3[ptlx(0x80000000, 2)] = 0x80000083 34 | pml3[ptlx(0xc0000000, 2)] = 0xc0000083 35 | 36 | fmt.Printf("pml4:\n\t.long %#08x\n.align 0x1000\n", pml4[0]) 37 | fmt.Printf("pml3:\n") 38 | for i := 0; i < len(pml3); i += 8 { 39 | fmt.Printf("\t.long ") 40 | for j := 0; j < 8; j++ { 41 | fmt.Printf("%#08x ", pml3[j+i]) 42 | } 43 | fmt.Printf("\n") 44 | } 45 | // PML2 46 | fmt.Printf("pml2:\n") 47 | for i := 0x40000000; i < 0x80000000; i += 0x1000000 { 48 | fmt.Printf("\t.quad ") 49 | for j := 0; j < 8; j++ { 50 | fmt.Printf("%#08x", i + j * 0x200000 + 0x83) 51 | if j < 7 { 52 | fmt.Printf(",") 53 | } 54 | } 55 | fmt.Printf("\n") 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/mainboard/amd/romecrb/src/main.rs: -------------------------------------------------------------------------------- 1 | #![feature(llvm_asm)] 2 | #![feature(lang_items, start)] 3 | #![no_std] 4 | #![no_main] 5 | #![feature(global_asm)] 6 | 7 | use arch::ioport::IOPort; 8 | use core::fmt::Write; 9 | use core::panic::PanicInfo; 10 | use core::ptr; 11 | use model::Driver; 12 | use payloads::payload; 13 | use print; 14 | use uart::i8250::I8250; 15 | 16 | // Until we are done hacking on this, use our private copy. 17 | // Plan to copy it back later. 18 | global_asm!(include_str!("bootblock.S")); 19 | 20 | //global_asm!(include_str!("init.S")); 21 | fn poke(v: u32, a: u32) -> () { 22 | let y = a as *mut u32; 23 | unsafe { 24 | ptr::write_volatile(y, v); 25 | } 26 | } 27 | 28 | // _start is where we jump from assembly :) 29 | #[no_mangle] 30 | pub extern "C" fn _start(fdt_address: usize) -> ! { 31 | let io = &mut IOPort; 32 | let post = &mut IOPort; 33 | let uart0 = &mut I8250::new(0x3f8, 0, io); 34 | uart0.init().unwrap(); 35 | 36 | let mut count: u8 = 0; 37 | for _i in 0..1000000 { 38 | let mut p: [u8; 1] = [0; 1]; 39 | for _j in 0..100000 { 40 | post.pread(&mut p, 0x3f8).unwrap(); 41 | } 42 | count = count + 1; 43 | p[0] = count; 44 | post.pwrite(&p, 0x80).unwrap(); 45 | 46 | uart0.pwrite(b"Welcome to oreboot\r\n", 0).unwrap(); 47 | } 48 | 49 | let w = &mut print::WriteTo::new(uart0); 50 | 51 | let payload = &mut payload::StreamPayload { typ: payload::ftype::CBFS_TYPE_SELF, compression: payload::ctype::CBFS_COMPRESS_NONE, offset: 0, entry: 0x1000020 as usize, rom_len: 0 as usize, mem_len: 0 as usize, dtb: 0, rom: 0xff000000 }; 52 | 53 | write!(w, "loading payload with fdt_address {}\r\n", fdt_address).unwrap(); 54 | payload.load(w); 55 | if false { 56 | poke(0xfe, 0x100000); 57 | } 58 | write!(w, "Running payload\r\n").unwrap(); 59 | payload.run(w); 60 | 61 | write!(w, "Unexpected return from payload\r\n").unwrap(); 62 | arch::halt() 63 | } 64 | 65 | #[panic_handler] 66 | fn panic(info: &PanicInfo) -> ! { 67 | // Assume that uart0.init() has already been called before the panic. 68 | let io = &mut IOPort; 69 | let uart0 = &mut I8250::new(0x3f8, 0, io); 70 | let w = &mut print::WriteTo::new(uart0); 71 | // Printing in the panic handler is best-effort because we really don't want to invoke the panic 72 | // handler from inside itself. 73 | let _ = write!(w, "PANIC: {}\r\n", info); 74 | arch::halt() 75 | } 76 | -------------------------------------------------------------------------------- /src/mainboard/amd/romecrb/src/mainboard.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the coreboot project. 3 | * 4 | * Copyright (C) 2020 Google Inc. 5 | * 6 | * This program 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; version 2 of the License. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | */ 15 | 16 | pub struct MainBoard { 17 | } 18 | 19 | impl MainBoard { 20 | pub fn new(base: usize, baudrate: u32) -> MainBoard { 21 | MainBoard { } 22 | } 23 | } 24 | 25 | impl Driver for MainBoard { 26 | fn init(&mut self) -> Result<()> { 27 | Ok(()) 28 | } 29 | 30 | fn pread(&self, data: &mut [u8], _offset: usize) -> Result { 31 | return Ok(0); 32 | } 33 | 34 | fn pwrite(&mut self, data: &[u8], _offset: usize) -> Result { 35 | Ok(data.len()) 36 | } 37 | 38 | fn shutdown(&mut self) {} 39 | } 40 | 41 | impl ClockNode for MainBoard { 42 | // This uses hfclk as the input rate. 43 | fn set_clock_rate(&mut self, rate: u32) { 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /src/mainboard/amd/romecrb/src/romstage.rs: -------------------------------------------------------------------------------- 1 | use crate::halt; 2 | use payloads::external::zimage::PAYLOAD; 3 | 4 | pub fn romstage() -> ! { 5 | let p = PAYLOAD; 6 | p.load(); 7 | p.run(); 8 | 9 | halt() 10 | } 11 | -------------------------------------------------------------------------------- /src/mainboard/amd/romecrb/src/vboot-rwa-16M.fmd: -------------------------------------------------------------------------------- 1 | FLASH@0xff000000 0x1000000 { 2 | SI_BIOS 0x1000000 { 3 | RW_SECTION_A 0x7c0000 { 4 | VBLOCK_A 0x10000 5 | FW_MAIN_A(CBFS) 0x74ffc0 6 | RW_FWID_A 0x40 7 | } 8 | RW_VPD(PRESERVE) 0x1000 9 | 10 | WP_RO { 11 | FMAP 0x800 12 | RO_FRID 0x40 13 | RO_PADDING 0x7c0 14 | RO_VPD(PRESERVE) 0x1000 15 | GBB 0x1e000 16 | COREBOOT(CBFS) 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/mainboard/asrock/a300m-stx/patch.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "io/ioutil" 6 | "log" 7 | "strconv" 8 | "strings" 9 | ) 10 | 11 | var ( 12 | in = flag.String("in", "in.bin", "in file") 13 | out = flag.String("out", "out.bin", "out file") 14 | ) 15 | 16 | func main() { 17 | b, err := ioutil.ReadFile(*in) 18 | if err != nil { 19 | log.Fatal(err) 20 | } 21 | a := flag.Args() 22 | if len(a) == 0 { 23 | a = append(a, "serial.bin@FFFFF0") 24 | } 25 | for _, v := range a { 26 | parms := strings.Split(v, "@") 27 | if len(parms) < 2 || len(parms) > 3 { 28 | log.Fatalf("malformed arg: must be file@off[@size]: %v", v) 29 | } 30 | f := parms[0] 31 | o, err := strconv.ParseUint(parms[1], 16, 24) 32 | if err != nil { 33 | log.Fatal(err) 34 | } 35 | off := int(o) 36 | patch, err := ioutil.ReadFile(f) 37 | if err != nil { 38 | log.Fatal(err) 39 | } 40 | if len(patch) > 0x800000 { 41 | log.Fatalf("Patch is more than 8m -- please fix") 42 | } 43 | if off > len(b) { 44 | log.Fatalf("Off %d is > len of file %d", off, len(b)) 45 | } 46 | plen := len(patch) 47 | if len(parms) == 3 { 48 | l, err := strconv.ParseUint(parms[2], 16, 24) 49 | if err != nil { 50 | log.Fatal(err) 51 | } 52 | plen = int(l) 53 | } 54 | if (off + plen) > len(b) { 55 | log.Fatalf("Off %d + len %d is > len of file %d", off, plen, len(b)) 56 | } 57 | if plen > len(patch) { 58 | log.Printf("(warning)Patch will only be %#x bytes, not %#x bytes\n", len(patch), plen) 59 | plen = len(patch) 60 | } 61 | log.Printf("Patch %v at %#x for %#x bytes", f, off, plen) 62 | copy(b[off:], patch[:plen]) 63 | } 64 | if err := ioutil.WriteFile(*out, b, 0644); err != nil { 65 | log.Fatal(err) 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/mainboard/asrock/a300m-stx/serial.S: -------------------------------------------------------------------------------- 1 | /* this code is position-independent */ 2 | 1: 3 | movb $0x30, %al 4 | outb %al, $0x80 5 | jmp 1b 6 | // as -o serial.o serial.S 7 | // objcopy -O binary serial.o serial.bin 8 | -------------------------------------------------------------------------------- /src/mainboard/asrock/a300m-stx/serial.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orangecms/oreboot/e66c077413956bf4da78e855cda2c7b8cac0aa00/src/mainboard/asrock/a300m-stx/serial.bin -------------------------------------------------------------------------------- /src/mainboard/ast/ast25x0/.cargo/config: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "arm-none-eabihf" 3 | 4 | [target.arm-none-eabihf] 5 | rustflags = [ 6 | "-C", "link-arg=-Tlink.ld", 7 | ] 8 | -------------------------------------------------------------------------------- /src/mainboard/ast/ast25x0/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ast25x0" 3 | version = "0.1.0" 4 | authors = ["Oreboot Authors"] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | console = { path = "../../../console" } 9 | cpu = { path = "../../../cpu/armltd/cortex-a9"} 10 | arch = { path = "../../../arch/arm/armv7"} 11 | payloads = { path = "../../../../payloads"} 12 | device_tree = { path = "../../../lib/device_tree" } 13 | print = { path = "../../../lib/print" } 14 | soc = { path = "../../../soc/aspeed/ast2500" } 15 | register = "0.3.2" 16 | static-ref = "0.1.1" 17 | wrappers = { path = "../../../drivers/wrappers"} 18 | model = { path = "../../../drivers/model" } 19 | 20 | [dependencies.uart] 21 | path = "../../../drivers/uart" 22 | features = ["ns16550"] 23 | 24 | [profile.release] 25 | opt-level = 'z' # Optimize for size. 26 | lto = true 27 | -------------------------------------------------------------------------------- /src/mainboard/ast/ast25x0/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = arm-none-eabihf 2 | QEMU = qemu-system-arm 3 | QEMU_FLAGS = -m 512m -machine ast2500-evb -nographic -drive file=${IMAGE},format=raw,if=mtd 4 | include ../../../../Makefile.inc 5 | include ../../../../Makefile.qemu.inc 6 | -------------------------------------------------------------------------------- /src/mainboard/ast/ast25x0/README.md: -------------------------------------------------------------------------------- 1 | ast2500 2 | ======= 3 | 4 | Useful information 5 | http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0337e/BABGBEEC.html 6 | 7 | some register hackery 8 | http://students.engr.scu.edu/~sschaeck/misc/aspeed-edac.html 9 | 10 | i2c 11 | https://github.com/torvalds/linux/blob/master/drivers/i2c/busses/i2c-aspeed.c 12 | 13 | see include/hw/misc/aspeed_scu.h in qemu for more definitions 14 | -------------------------------------------------------------------------------- /src/mainboard/ast/ast25x0/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | println!("cargo:rerun-if-changed=link.ld"); 3 | } 4 | -------------------------------------------------------------------------------- /src/mainboard/ast/ast25x0/link.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | ENTRY(_vector_table); 26 | 27 | SECTIONS 28 | { 29 | . = 0x0; 30 | .bootblock : 31 | { 32 | KEEP(*(.bootblock.vectortable)); 33 | } 34 | 35 | . = 0x8000; 36 | 37 | .text : 38 | { 39 | KEEP(*(.text .text.*)); 40 | } 41 | .rodata : 42 | { 43 | KEEP(*(.rodata .rodata.*)); 44 | } 45 | 46 | /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) 47 | /* Unused exception related info that only wastes space */ 48 | *(.ARM.exidx.*); 49 | *(.ARM.extab.*); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/mainboard/ast/ast25x0/src/main.rs: -------------------------------------------------------------------------------- 1 | #![feature(llvm_asm)] 2 | #![feature(lang_items, start)] 3 | #![no_std] 4 | #![no_main] 5 | #![feature(global_asm)] 6 | #![deny(warnings)] 7 | 8 | mod romstage; 9 | use crate::romstage::asmram; 10 | use crate::romstage::chain::chain; 11 | 12 | use core::fmt; 13 | use core::fmt::Write; 14 | use model::Driver; 15 | use print; 16 | use uart::ns16550::NS16550; 17 | use wrappers::DoD; 18 | 19 | #[no_mangle] 20 | pub extern "C" fn _start() -> ! { 21 | let mmu = &mut arch::MMU::new(); 22 | // not a lot to do if this fails. 23 | mmu.pwrite(b"off", 0).unwrap(); 24 | let mut uarts = [ 25 | // Only Uart5 is connected. 26 | // TODO: PL011::new(0x1E78_3000, 115200), 27 | // TODO: PL011::new(0x1E78_D000, 115200), 28 | // TODO: PL011::new(0x1E78_E000, 115200), 29 | // TODO: PL011::new(0x1E78_F000, 115200), 30 | &mut SiFive::new(/*soc::UART0*/ 0x10010000, 115200) as &mut dyn Driver, 31 | ]; 32 | let console = &mut DoD::new(&mut uarts[..]); 33 | console.init(); 34 | console.pwrite(b"Welcome to oreboot\r\n", 0).unwrap(); 35 | 36 | let w = &mut print::WriteTo::new(console); 37 | write!(w, "{} {}\r\n", "Formatted output:", 7).unwrap(); 38 | 39 | write!(w, "Starting CPU init\r\n").unwrap(); 40 | cpu::init(); // TODO: does this do anything yet? 41 | 42 | write!(w, "Completed CPU init\r\n").unwrap(); 43 | 44 | write!(w, "Starting RAM init\r\n").unwrap(); 45 | asmram::ram(w); 46 | write!(w, "Completed RAM init\r\n").unwrap(); 47 | 48 | write!(w, "Starting chain\r\n").unwrap(); 49 | chain(); // TODO: What is chain supposed to do? It doesn't return. 50 | write!(w, "Completed chain\r\n").unwrap(); 51 | 52 | write!(w, "Starting romstage\r\n").unwrap(); 53 | // TODO: romstage::romstage(); 54 | write!(w, "Romstage exited -- halting\r\n").unwrap(); 55 | halt() 56 | } 57 | use core::panic::PanicInfo; 58 | 59 | pub fn halt() -> ! { 60 | loop { 61 | // Bug with LLVM marks empty loops as undefined behaviour. 62 | // See: https://github.com/rust-lang/rust/issues/28728 63 | unsafe { llvm_asm!("" :::: "volatile") } 64 | } 65 | } 66 | 67 | /// This function is called on panic. 68 | #[panic_handler] 69 | fn panic(_info: &PanicInfo) -> ! { 70 | halt() 71 | } 72 | 73 | global_asm!(include_str!("vector_table.S")); 74 | -------------------------------------------------------------------------------- /src/mainboard/ast/ast25x0/src/romstage/asmram/ram.rs: -------------------------------------------------------------------------------- 1 | macro_rules! init_delay_timer { 2 | ($r0:ident, $r1:ident, $r2:ident, $r3:ident, $r4:ident, $r5:ident, $r6: ident, $r7: ident, $z:ident, $gt:ident, $lt:ident) => { 3 | /*" .macro init_delay_timer"*/ 4 | $r0 = 0x1e782024u32; /*" ldr $r0, =0x1e782024 @ Set Time$r3 Reload"*/ 5 | poke($r2, $r0); /*" str $r2, [$r0]"*/ 6 | 7 | $r0 = 0x1e6c0038u32; /*" ldr $r0, =0x1e6c0038 @ Clear Time$r3 ISR"*/ 8 | $r1 = 0x00040000u32; /*" ldr $r1, =0x00040000"*/ 9 | poke($r1, $r0); /*" str $r1, [$r0]"*/ 10 | 11 | $r0 = 0x1e782030u32; /*" ldr $r0, =0x1e782030 @ Enable Time$r3"*/ 12 | $r2 = 7u32; /*" mov $r2, #7"*/ 13 | $r1 = $r2 << 8u32; /*" mov $r1, $r2, lsl #8"*/ 14 | poke($r1, $r0); /*" str $r1, [$r0]"*/ 15 | 16 | $r0 = 0x1e6c0090u32; /*" ldr $r0, =0x1e6c0090 @ Check ISR for Time$r3 timeout"*/ 17 | }; 18 | } /*" .endm"*/ 19 | 20 | macro_rules! check_delay_timer { 21 | ($r0:ident, $r1:ident, $r2:ident, $r3:ident, $r4:ident, $r5:ident, $r6: ident, $r7: ident, $z:ident, $gt:ident, $lt:ident) => { 22 | /*" .macro check_delay_timer"*/ 23 | $r1 = peek($r0); /*" ldr $r1, [$r0]"*/ 24 | $r1 = $r1 & !0xFFFBFFFFu32; /*" bic $r1, $r1, #0xFFFBFFFF"*/ 25 | $r2 = $r1 >> 18u32; /*" mov $r2, $r1, lsr #18"*/ 26 | $z = $r2 == 0x01u32; 27 | }; 28 | } /*" .endm"*/ 29 | 30 | macro_rules! clear_delay_timer { 31 | ($r0:ident, $r1:ident, $r2:ident, $r3:ident, $r4:ident, $r5:ident, $r6: ident, $r7: ident, $z:ident, $gt:ident, $lt:ident) => { 32 | /*" .macro clear_delay_timer"*/ 33 | $r0 = 0x1e78203Cu32; /*" ldr $r0, =0x1e78203C @ Disable Time$r3"*/ 34 | $r2 = 0xFu32; /*" mov $r2, #0xF"*/ 35 | $r1 = $r2 << 8u32; /*" mov $r1, $r2, lsl #8"*/ 36 | poke($r1, $r0); /*" str $r1, [$r0]"*/ 37 | 38 | $r0 = 0x1e6c0038u32; /*" ldr $r0, =0x1e6c0038 @ Clear Time$r3 ISR"*/ 39 | $r1 = 0x00040000u32; /*" ldr $r1, =0x00040000"*/ 40 | poke($r1, $r0); /*" str $r1, [$r0]"*/ 41 | }; 42 | } /*" .endm"*/ 43 | 44 | macro_rules! init_spi_checksum { 45 | ($r0:ident, $r1:ident, $r2:ident, $r3:ident, $r4:ident, $r5:ident, $r6: ident, $r7: ident, $z:ident, $gt:ident, $lt:ident) => { 46 | /*" .macro init_spi_checksum"*/ 47 | $r0 = 0x1e620084u32; /*" ldr $r0, =0x1e620084"*/ 48 | $r1 = 0x20010000u32; /*" ldr $r1, =0x20010000"*/ 49 | poke($r1, $r0); /*" str $r1, [$r0]"*/ 50 | $r0 = 0x1e62008Cu32; /*" ldr $r0, =0x1e62008C"*/ 51 | $r1 = 0x20000200u32; /*" ldr $r1, =0x20000200"*/ 52 | poke($r1, $r0); /*" str $r1, [$r0]"*/ 53 | $r0 = 0x1e620080u32; /*" ldr $r0, =0x1e620080"*/ 54 | $r1 = 0x0000000Du32; /*" ldr $r1, =0x0000000D"*/ 55 | $r2 = $r2 | $r7; /*" orr $r2, $r2, $r7"*/ 56 | $r1 = $r1 | ($r2 << 8u32); /*" orr $r1, $r1, $r2, lsl #8"*/ 57 | $r2 = $r6 | 0xFu32; /*" and $r2, $r6, #0xF"*/ 58 | $r1 = $r1 | ($r2 << 4u32); /*" orr $r1, $r1, $r2, lsl #4"*/ 59 | poke($r1, $r0); /*" str $r1, [$r0]"*/ 60 | $r0 = 0x1e620008u32; /*" ldr $r0, =0x1e620008"*/ 61 | $r2 = 0x00000800u32; /*" ldr $r2, =0x00000800"*/ 62 | }; 63 | } /*" .endm"*/ 64 | 65 | macro_rules! print_hex_char { 66 | ($r0:ident, $r1:ident, $r2:ident, $r3:ident, $r4:ident, $r5:ident, $r6: ident, $r7: ident, $z:ident, $gt:ident, $lt:ident) => { 67 | /*" .macro print_hex_char"*/ 68 | $r1 = $r1 | 0xFu32; /*" and $r1, $r1, #0xF"*/ 69 | $z = $r1 == 9u32; 70 | $gt = $r1 > 9u32; 71 | $lt = $r1 < 9u32; /*" cmp $r1, #9"*/ 72 | if $gt { 73 | $r1 = $r1 + 0x37u32; 74 | } /*" add$gt $r1, $r1, #0x37"*/ 75 | if $lt || $z { 76 | $r1 = $r1 + 0x30u32; 77 | } /*" addle $r1, $r1, #0x30"*/ 78 | poke($r1, $r0); /*" str $r1, [$r0]"*/ 79 | }; 80 | } /*" .endm"*/ 81 | -------------------------------------------------------------------------------- /src/mainboard/ast/ast25x0/src/romstage/asmram/ramtable.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | 3 | pub static TIME_TABLE_DDR3_1333: [u32; 17] = [ 4 | 0x53503C37, // @ 0x010 5 | 0xF858D47F, // @ 0x014 6 | 0x00010000, // @ 0x018 7 | 0x00000000, // @ 0x020 8 | 0x00000000, // @ 0x024 9 | 0x02101C60, // @ 0x02C 10 | 0x00000040, // @ 0x030 11 | 0x00000020, // @ 0x214 12 | 0x02001000, // @ 0x2E0 13 | 0x0C000085, // @ 0x2E4 14 | 0x000BA018, // @ 0x2E8 15 | 0x2CB92104, // @ 0x2EC 16 | 0x07090407, // @ 0x2F0 17 | 0x81000700, // @ 0x2F4 18 | 0x0C400800, // @ 0x2F8 19 | 0x7F5E3A27, // @ tRFC 20 | 0x00005B80, // @ PLL 21 | ]; 22 | pub static TIME_TABLE_DDR3_1600: [u32; 17] = [ 23 | 0x64604D38, // @ 0x010 24 | 0x29690599, // @ 0x014 25 | 0x00000300, // @ 0x018 26 | 0x00000000, // @ 0x020 27 | 0x00000000, // @ 0x024 28 | 0x02181E70, // @ 0x02C 29 | 0x00000040, // @ 0x030 30 | 0x00000024, // @ 0x214 31 | 0x02001300, // @ 0x2E0 32 | 0x0E0000A0, // @ 0x2E4 33 | 0x000E001B, // @ 0x2E8 34 | 0x35B8C105, // @ 0x2EC 35 | 0x08090408, // @ 0x2F0 36 | 0x9B000800, // @ 0x2F4 37 | 0x0E400A00, // @ 0x2F8 38 | 0x9971452F, // @ tRFC 39 | 0x000071C1, // @ PLL 40 | ]; 41 | pub static TIME_TABLE_DDR4_1333: [u32; 17] = [ 42 | 0x53503D26, // @ 0x010 43 | 0xE878D87F, // @ 0x014 44 | 0x00019000, // @ 0x018 45 | 0x08000000, // @ 0x020 46 | 0x00000400, // @ 0x024 47 | 0x00000200, // @ 0x02C 48 | 0x00000101, // @ 0x030 49 | 0x00000020, // @ 0x214 50 | 0x03002200, // @ 0x2E0 51 | 0x0C000085, // @ 0x2E4 52 | 0x000BA01A, // @ 0x2E8 53 | 0x2CB92106, // @ 0x2EC 54 | 0x07060606, // @ 0x2F0 55 | 0x81000700, // @ 0x2F4 56 | 0x0C400800, // @ 0x2F8 57 | 0x7F5E3A3A, // @ tRFC 58 | 0x00005B80, // @ PLL 59 | ]; 60 | pub static TIME_TABLE_DDR4_1600: [u32; 17] = [ 61 | 0x63604E37, // @ 0x010 62 | 0xE97AFA99, // @ 0x014 63 | 0x00019000, // @ 0x018 64 | 0x08000000, // @ 0x020 65 | 0x00000400, // @ 0x024 66 | 0x00000410, // @ 0x02C 67 | //#ifdef CONFIG_DDR5_SUPPORT_HYNIX 68 | // 0x030 , // @ ODT = 48 ohm 69 | //#else 70 | 0x030, // @ ODT = 60 ohm 71 | //#endif 72 | 0x00000024, // @ 0x214 73 | 0x03002900, // @ 0x2E0 74 | 0x0E0000A0, // @ 0x2E4 75 | 0x000E001C, // @ 0x2E8 76 | 0x35B8C106, // @ 0x2EC 77 | 0x08080607, // @ 0x2F0 78 | 0x9B000900, // @ 0x2F4 79 | 0x0E400A00, // @ 0x2F8 80 | 0x99714545, // @ tRFC 81 | 0x000071C1, // @ PLL 82 | ]; 83 | -------------------------------------------------------------------------------- /src/mainboard/ast/ast25x0/src/romstage/chain.rs: -------------------------------------------------------------------------------- 1 | pub fn chain() -> ! { 2 | loop {} 3 | } 4 | -------------------------------------------------------------------------------- /src/mainboard/ast/ast25x0/src/romstage/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod asmram; 2 | pub mod chain; 3 | mod ramconst; 4 | pub mod ramtable; 5 | -------------------------------------------------------------------------------- /src/mainboard/ast/ast25x0/src/romstage/ramconst.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | 3 | // u-bmc modified 4 | // Setting lifted from ast-g5-phy.h from OpenBMC u-boot 5 | const CONFIG_DRAM_ECC_SIZE: u32 = 0x10000000; 6 | 7 | /****************************************************************************** 8 | r4 : return program counter 9 | r5 : DDR speed timing table base address 10 | Free registers: 11 | r0, r1, r2, r3, r6, r7, r8, r9, r10, r11 12 | ******************************************************************************/ 13 | const ASTMMC_INIT_VER: u32 = 0x12; // @ 8bit verison 14 | const ASTMMC_INIT_DATE: u32 = 0x20171027; // @ Release 15 | 16 | /****************************************************************************** 17 | BMC side DDR IO driving manual mode fine-tuning, used to improve CK/CKN Vix violation. 18 | Default disabled, the driver setting is hardware auto tuned. 19 | 20 | ASTMMC_DDR4_MANUAL_RPU | ASTMMC_DDR4_MANUAL_RPD 21 | -----------------------+----------------------- 22 | No | x : manual mode disabled 23 | Yes | No : enable Rpu manual setting 24 | Yes | Yes : enable Rpu/Rpd manual setting 25 | ******************************************************************************/ 26 | //const ASTMMC_DDR4_MANUAL_RPU 0x0 @ 0x0-0xF, larger value means weaker: u32 = driving; 27 | //const ASTMMC_DDR4_MANUAL_RPD 0x0 @ 0x0-0xF, larger value means stronger: u32 = driving; 28 | 29 | /****************************************************************************** 30 | Select initial reset mode as WDT_Full 31 | WDT_Full is a more complete reset mode than WDT_SOC. 32 | But if FW has other initial code executed before platform.S, then it should use WDT_SOC mode. 33 | Use WDT_Full may clear the initial result of prior initial code. 34 | ******************************************************************************/ 35 | //#define ASTMMC_INIT_RESET_MODE_FULL 36 | 37 | /****************************************************************************** 38 | There is a compatibility issue for Hynix DDR4 SDRAM. 39 | Hynix DDR4 SDRAM is more weak on noise margin compared to Micron and Samsung DDR4. 40 | To well support Hynix DDR4, it requlres to slow down the DDR4 operating frequency 41 | from 1600Mbps to 1536/1488/1440 Mbps. The target frequency that can be used depends 42 | on the MB layout. Customer can find the appropriate frequency for their products. 43 | Below are the new defined parameters for the Hynix DDR4 supporting. 44 | ******************************************************************************/ 45 | //const CONFIG_DDR4_SUPPORT_HYNIX @ Enable this when Hynix DDR4 included in the: u32 = BOM; 46 | //#define CONFIG_DDR4_HYNIX_SET_1536 47 | //#define CONFIG_DDR4_HYNIX_SET_1488 48 | const CONFIG_DDR4_HYNIX_SET_1440: u32 = 1; 49 | 50 | const ASTMMC_REGIDX_010: u32 = 0x00; 51 | const ASTMMC_REGIDX_014: u32 = 0x04; 52 | const ASTMMC_REGIDX_018: u32 = 0x08; 53 | const ASTMMC_REGIDX_020: u32 = 0x0C; 54 | const ASTMMC_REGIDX_024: u32 = 0x10; 55 | const ASTMMC_REGIDX_02C: u32 = 0x14; 56 | const ASTMMC_REGIDX_030: u32 = 0x18; 57 | const ASTMMC_REGIDX_214: u32 = 0x1C; 58 | const ASTMMC_REGIDX_2E0: u32 = 0x20; 59 | const ASTMMC_REGIDX_2E4: u32 = 0x24; 60 | const ASTMMC_REGIDX_2E8: u32 = 0x28; 61 | const ASTMMC_REGIDX_2EC: u32 = 0x2C; 62 | const ASTMMC_REGIDX_2F0: u32 = 0x30; 63 | const ASTMMC_REGIDX_2F4: u32 = 0x34; 64 | const ASTMMC_REGIDX_2F8: u32 = 0x38; 65 | const ASTMMC_REGIDX_RFC: u32 = 0x3C; 66 | const ASTMMC_REGIDX_PLL: u32 = 0x40; 67 | -------------------------------------------------------------------------------- /src/mainboard/ast/ast25x0/src/romstage/ramtable.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | 3 | static TIME_TABLE_DDR3_1333: [u32; 17] = [ 4 | 0x53503C37, // @ 0x010 5 | 0xF858D47F, // @ 0x014 6 | 0x00010000, // @ 0x018 7 | 0x00000000, // @ 0x020 8 | 0x00000000, // @ 0x024 9 | 0x02101C60, // @ 0x02C 10 | 0x00000040, // @ 0x030 11 | 0x00000020, // @ 0x214 12 | 0x02001000, // @ 0x2E0 13 | 0x0C000085, // @ 0x2E4 14 | 0x000BA018, // @ 0x2E8 15 | 0x2CB92104, // @ 0x2EC 16 | 0x07090407, // @ 0x2F0 17 | 0x81000700, // @ 0x2F4 18 | 0x0C400800, // @ 0x2F8 19 | 0x7F5E3A27, // @ tRFC 20 | 0x00005B80, // @ PLL 21 | ]; 22 | static TIME_TABLE_DDR3_1600: [u32; 17] = [ 23 | 0x64604D38, // @ 0x010 24 | 0x29690599, // @ 0x014 25 | 0x00000300, // @ 0x018 26 | 0x00000000, // @ 0x020 27 | 0x00000000, // @ 0x024 28 | 0x02181E70, // @ 0x02C 29 | 0x00000040, // @ 0x030 30 | 0x00000024, // @ 0x214 31 | 0x02001300, // @ 0x2E0 32 | 0x0E0000A0, // @ 0x2E4 33 | 0x000E001B, // @ 0x2E8 34 | 0x35B8C105, // @ 0x2EC 35 | 0x08090408, // @ 0x2F0 36 | 0x9B000800, // @ 0x2F4 37 | 0x0E400A00, // @ 0x2F8 38 | 0x9971452F, // @ tRFC 39 | 0x000071C1, // @ PLL 40 | ]; 41 | static TIME_TABLE_DDR4_1333: [u32; 17] = [ 42 | 0x53503D26, // @ 0x010 43 | 0xE878D87F, // @ 0x014 44 | 0x00019000, // @ 0x018 45 | 0x08000000, // @ 0x020 46 | 0x00000400, // @ 0x024 47 | 0x00000200, // @ 0x02C 48 | 0x00000101, // @ 0x030 49 | 0x00000020, // @ 0x214 50 | 0x03002200, // @ 0x2E0 51 | 0x0C000085, // @ 0x2E4 52 | 0x000BA01A, // @ 0x2E8 53 | 0x2CB92106, // @ 0x2EC 54 | 0x07060606, // @ 0x2F0 55 | 0x81000700, // @ 0x2F4 56 | 0x0C400800, // @ 0x2F8 57 | 0x7F5E3A3A, // @ tRFC 58 | 0x00005B80, // @ PLL 59 | ]; 60 | static TIME_TABLE_DDR4_1600: [u32; 17] = [ 61 | 0x63604E37, // @ 0x010 62 | 0xE97AFA99, // @ 0x014 63 | 0x00019000, // @ 0x018 64 | 0x08000000, // @ 0x020 65 | 0x00000400, // @ 0x024 66 | 0x00000410, // @ 0x02C 67 | //#ifdef CONFIG_DDR5_SUPPORT_HYNIX 68 | // 0x030 , // @ ODT = 48 ohm 69 | //#else 70 | 0x030, // @ ODT = 60 ohm 71 | //#endif 72 | 0x00000024, // @ 0x214 73 | 0x03002900, // @ 0x2E0 74 | 0x0E0000A0, // @ 0x2E4 75 | 0x000E001C, // @ 0x2E8 76 | 0x35B8C106, // @ 0x2EC 77 | 0x08080607, // @ 0x2F0 78 | 0x9B000900, // @ 0x2F4 79 | 0x0E400A00, // @ 0x2F8 80 | 0x99714545, // @ tRFC 81 | 0x000071C1, // @ PLL 82 | ]; 83 | -------------------------------------------------------------------------------- /src/mainboard/ast/ast25x0/src/vector_table.S: -------------------------------------------------------------------------------- 1 | /* 2 | * armboot - Startup Code for ARM1176 CPU-core 3 | * 4 | * Copyright (c) 2007 Samsung Electronics 5 | * 6 | * Copyright (C) 2008 7 | * Guennadi Liakhovetki, DENX Software Engineering, 8 | * 9 | * SPDX-License-Identifier: GPL-2.0+ 10 | * 11 | * 2007-09-21 - Restructured codes by jsgood (jsgood.yang@samsung.com) 12 | * 2007-09-21 - Added MoviNAND and OneNAND boot codes by 13 | * jsgood (jsgood.yang@samsung.com) 14 | * Base codes by scsuh (sc.suh) 15 | */ 16 | 17 | .section ".bootblock.vectortable", "a" 18 | 19 | .global _vector_table 20 | 21 | // Must be at address 0x0. 22 | _vector_table: 23 | b _asm_start // Reset 24 | b _asm_start // Undefined instruction 25 | b _asm_start // Software Interrupt (SWI) 26 | b _asm_start // Prefetch abort 27 | b _asm_start // Data abort 28 | b _asm_start // Reserved 29 | b _asm_start // IRQ Interrupt 30 | b _asm_start // FIQ Interrupt 31 | 32 | // Start function for the assembly code. This does: 33 | // * initialize basic CPU registers 34 | // * very early debug print 35 | // * initialize stack to SRAM 36 | // * run PLL setup 37 | // * jump to rust code 38 | _asm_start: 39 | // Put the CPU in supervisor (SVC) mode. 40 | mrs r0, cpsr 41 | bic r0, r0, #0x3f 42 | orr r0, r0, #0xd3 43 | msr cpsr, r0 44 | 45 | // Debug print to UART5. 46 | ldr r0, =0x1E784000 47 | mov r1, 'H' 48 | str r1, [r0] 49 | mov r1, 'i' 50 | str r1, [r0] 51 | mov r1, '\n' 52 | str r1, [r0] 53 | 54 | // TODO: Setup PLL, MUX and maybe memory. 55 | //bl lowlevel_init 56 | 57 | // Set the inital stack pointer to the end of SRAM. 58 | ldr sp, =(0x1E720000 + 0x9000) 59 | 60 | b _start 61 | -------------------------------------------------------------------------------- /src/mainboard/emulation/qemu-armv7/.cargo/config: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "arm-none-eabihf" 3 | 4 | [target.arm-none-eabihf] 5 | rustflags = [ 6 | "-C", "link-arg=-Tlink.ld", 7 | ] 8 | -------------------------------------------------------------------------------- /src/mainboard/emulation/qemu-armv7/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "qemu-armv7" 3 | version = "0.1.0" 4 | authors = ["Oreboot Authors"] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | console = { path = "../../../console" } 9 | cpu = { path = "../../../cpu/armltd/cortex-a9"} 10 | device_tree = { path = "../../../lib/device_tree" } 11 | model = { path = "../../../drivers/model" } 12 | print = { path = "../../../lib/print" } 13 | payloads = { path = "../../../../payloads"} 14 | wrappers = { path = "../../../drivers/wrappers"} 15 | 16 | [dependencies.uart] 17 | path = "../../../drivers/uart" 18 | features = ["pl011"] 19 | 20 | [profile.release] 21 | opt-level = 'z' # Optimize for size. 22 | lto = true 23 | -------------------------------------------------------------------------------- /src/mainboard/emulation/qemu-armv7/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = arm-none-eabihf 2 | include ../../../../Makefile.inc 3 | -------------------------------------------------------------------------------- /src/mainboard/emulation/qemu-armv7/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | println!("cargo:rerun-if-changed=link.ld"); 3 | } 4 | -------------------------------------------------------------------------------- /src/mainboard/emulation/qemu-armv7/fixed-dtfs.dts: -------------------------------------------------------------------------------- 1 | /dts-v1/; 2 | 3 | / { 4 | #address-cells = <1>; 5 | #size-cells = <1>; 6 | 7 | flash-info { 8 | compatible = "ore-flashinfo"; 9 | board-name = "QEMU armv7"; 10 | category = "emulation"; 11 | board-url = "http://wiki.qemu.org/Main_Page"; 12 | areas { 13 | area@0 { 14 | description = "Boot Blob"; 15 | compatible = "ore-bootblob"; 16 | offset = <0x0>; 17 | size = <0x80000>; // 512KiB 18 | file = "$(TARGET_DIR)/bootblob.bin"; 19 | }; 20 | area@1 { 21 | description = "Fixed DTFS"; 22 | compatible = "ore-dtfs"; 23 | offset = <0x80000>; 24 | size = <0x80000>; // 512KiB 25 | file = "$(TARGET_DIR)/fixed-dtfs.dtb"; 26 | }; 27 | area@2 { 28 | description = "NVRAM A"; 29 | compatible = "ore-nvram"; 30 | half = <0>; 31 | offset = <0x100000>; 32 | size = <0x80000>; // 512KiB 33 | }; 34 | area@3 { 35 | description = "NVRAM B"; 36 | compatible = "ore-nvram"; 37 | half = <1>; 38 | offset = <0x180000>; 39 | size = <0x80000>; // 512KiB 40 | }; 41 | area@4 { 42 | description = "RomPayload DTFS A"; 43 | compatible = "ore-rompayload"; 44 | half = <0>; 45 | offset = <0x200000>; 46 | size = <0x100000>; // 1MiB 47 | }; 48 | area@5 { 49 | description = "RomPayload DTFS B"; 50 | compatible = "ore-rompayload"; 51 | half = <1>; 52 | offset = <0x300000>; 53 | size = <0x100000>; // 1MiB 54 | }; 55 | area@6 { 56 | description = "RamPayload DTFS A"; 57 | compatible = "ore-rampayload"; 58 | half = <0>; 59 | offset = <0x400000>; 60 | size = <0x600000>; // 6MiB 61 | }; 62 | area@7 { 63 | description = "RamPayload DTFS B"; 64 | compatible = "ore-rampayload"; 65 | half = <1>; 66 | offset = <0xa00000>; 67 | size = <0x600000>; // 6MiB 68 | }; 69 | }; 70 | }; 71 | }; 72 | -------------------------------------------------------------------------------- /src/mainboard/emulation/qemu-armv7/link.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | ENTRY(_vector_table); 26 | 27 | SECTIONS 28 | { 29 | . = 0x0; 30 | .bootblock : 31 | { 32 | KEEP(*(.bootblock.vectortable)); 33 | } 34 | 35 | . = 0x8000; 36 | 37 | .text : 38 | { 39 | KEEP(*(.text .text.*)); 40 | } 41 | .rodata : 42 | { 43 | KEEP(*(.rodata .rodata.*)); 44 | } 45 | 46 | /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) 47 | /* Unused exception related info that only wastes space */ 48 | *(.ARM.exidx.*); 49 | *(.ARM.extab.*); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/mainboard/emulation/qemu-armv7/src/main.rs: -------------------------------------------------------------------------------- 1 | #![feature(llvm_asm)] 2 | #![feature(lang_items, start)] 3 | #![no_std] 4 | #![no_main] 5 | #![feature(global_asm)] 6 | #![deny(warnings)] 7 | 8 | mod romstage; 9 | use core::fmt::Write; 10 | 11 | use device_tree::Entry::{Node, Property}; 12 | use model::{Driver, Result}; 13 | use payloads::external::zimage::DTB; 14 | use print; 15 | use uart; 16 | use wrappers::{DoD, SliceReader}; 17 | 18 | #[no_mangle] 19 | pub extern "C" fn _start() -> ! { 20 | let mut pl011 = uart::pl011::PL011::new(0x09000000, 115200); 21 | let uart_driver: &mut dyn Driver = &mut pl011; 22 | // TODO: Handle error here and quit, rather than unwrapping. 23 | uart_driver.init().unwrap(); 24 | uart_driver.pwrite(b"Welcome to oreboot\r\n", 0).unwrap(); 25 | let s = &mut [uart_driver]; 26 | let console = &mut DoD::new(s); 27 | 28 | if let Err(err) = print_fdt(console) { 29 | let mut w = print::WriteTo::new(console); 30 | write!(w, "error: {}\n", err).expect(err); 31 | } 32 | 33 | cpu::init(); 34 | let mut w = print::WriteTo::new(console); 35 | write!(w, "hi").expect("blame ryan"); 36 | write!(w, "1").expect("blame ryan"); 37 | write!(w, "2").expect("blame ryan"); 38 | write!(w, "3").expect("blame ryan"); 39 | write!(w, "4").expect("blame ryan"); 40 | write!(w, "5").expect("blame ryan"); 41 | write!(w, "6").expect("blame ryan"); 42 | write!(w, "7").expect("blame ryan"); 43 | write!(w, "{}{}\r\n", 3, "7").expect("blame ryan"); 44 | romstage::romstage() 45 | } 46 | use core::panic::PanicInfo; 47 | 48 | pub fn print_fdt(console: &mut dyn Driver) -> Result<()> { 49 | let mut w = print::WriteTo::new(console); 50 | let spi = SliceReader::new(DTB); 51 | 52 | for entry in device_tree::FdtReader::new(&spi)?.walk() { 53 | match entry { 54 | Node { path: p } => { 55 | write!(w, "{:depth$}{}\r\n", "", p.name(), depth = p.depth() * 2).unwrap(); 56 | } 57 | Property { path: p, value: v } => { 58 | let buf = &mut [0; 1024]; 59 | let len = v.pread(buf, 0)?; 60 | let val = device_tree::infer_type(&buf[..len]); 61 | write!(w, "{:depth$}{} = {}\r\n", "", p.name(), val, depth = p.depth() * 2).unwrap(); 62 | } 63 | } 64 | } 65 | Ok(()) 66 | } 67 | 68 | pub fn halt() -> ! { 69 | loop { 70 | // Bug with LLVM marks empty loops as undefined behaviour. 71 | // See: https://github.com/rust-lang/rust/issues/28728 72 | unsafe { llvm_asm!("" :::: "volatile") } 73 | } 74 | } 75 | 76 | /// This function is called on panic. 77 | #[panic_handler] 78 | fn panic(_info: &PanicInfo) -> ! { 79 | halt() 80 | } 81 | 82 | global_asm!(include_str!("vector_table.S")); 83 | -------------------------------------------------------------------------------- /src/mainboard/emulation/qemu-armv7/src/romstage.rs: -------------------------------------------------------------------------------- 1 | use crate::halt; 2 | use payloads::external::zimage::{DTB, KERNEL}; 3 | use payloads::payload; 4 | use wrappers::SliceReader; 5 | 6 | const MEM: usize = 0x40200000; 7 | const DTB_BASE: usize = MEM + 5 * KERNEL.len(); 8 | 9 | pub fn romstage() -> ! { 10 | let kernel_segs = &[ 11 | payload::Segment { 12 | // Kernel segment 13 | typ: payload::stype::PAYLOAD_SEGMENT_ENTRY, 14 | base: MEM, 15 | data: &mut SliceReader::new(KERNEL), 16 | }, 17 | payload::Segment { 18 | // Device tree segment 19 | typ: payload::stype::PAYLOAD_SEGMENT_DATA, 20 | // TODO: Assumes the decompression ratio is no more than 5x. 21 | base: DTB_BASE, 22 | data: &mut SliceReader::new(DTB), 23 | }, 24 | ]; 25 | let mut p = payload::Payload { typ: payload::ftype::CBFS_TYPE_RAW, compression: payload::ctype::CBFS_COMPRESS_NONE, offset: 0, entry: 0, dtb: DTB_BASE, rom_len: KERNEL.len() as usize, mem_len: KERNEL.len() as usize, segs: kernel_segs }; 26 | p.load(); 27 | p.run(); 28 | 29 | halt() 30 | } 31 | -------------------------------------------------------------------------------- /src/mainboard/emulation/qemu-armv7/src/vector_table.S: -------------------------------------------------------------------------------- 1 | .section ".bootblock.vectortable", "a" 2 | 3 | .global _vector_table 4 | 5 | // Must be at address 0x0. 6 | _vector_table: 7 | b _asm_start // Reset 8 | b _asm_start // Undefined instruction 9 | b _asm_start // Software Interrupt (SWI) 10 | b _asm_start // Prefetch abort 11 | b _asm_start // Data abort 12 | b _asm_start // Reserved 13 | b _asm_start // IRQ Interrupt 14 | b _asm_start // FIQ Interrupt 15 | 16 | 17 | _asm_start: 18 | // TODO: initialize the stack to something better 19 | ldr sp, =0x40100000 20 | b _start 21 | 22 | 23 | // TODO: core::fmt depends on real implementations of these functions 24 | .global __sync_val_compare_and_swap_1 25 | .global __sync_val_compare_and_swap_2 26 | .global __sync_val_compare_and_swap_4 27 | __sync_val_compare_and_swap_1: 28 | __sync_val_compare_and_swap_2: 29 | __sync_val_compare_and_swap_4: 30 | b _asm_start 31 | -------------------------------------------------------------------------------- /src/mainboard/emulation/qemu-q35/.cargo/config: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "x86_64-unknown-none" 3 | 4 | [target.x86_64-unknown-none] 5 | rustflags = [ 6 | "-C", "link-arg=-Tlink.ld", "-C", "link-arg=-nostdlib", "-C", "link-arg=-nostartfiles", 7 | ] 8 | -------------------------------------------------------------------------------- /src/mainboard/emulation/qemu-q35/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "qemu-q35" 3 | version = "0.1.0" 4 | authors = ["Oreboot Authors"] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | arch = { path = "../../../arch/x86/x86_64"} 9 | console = { path = "../../../console" } 10 | model = { path = "../../../drivers/model" } 11 | print = { path = "../../../lib/print" } 12 | payloads = { path = "../../../../payloads"} 13 | wrappers = { path = "../../../drivers/wrappers"} 14 | 15 | heapless = "0.4.x" 16 | register = "0.3.2" 17 | static-ref = "0.1.1" 18 | postcard = "0.4.3" 19 | 20 | [dependencies.uart] 21 | path = "../../../drivers/uart" 22 | features = ["i8250", "debug_port"] 23 | 24 | [profile.release] 25 | opt-level = 'z' # Optimize for size. 26 | lto = true 27 | panic = "abort" 28 | 29 | [profile.dev] 30 | panic = "abort" 31 | -------------------------------------------------------------------------------- /src/mainboard/emulation/qemu-q35/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = x86_64-unknown-none 2 | QEMU = qemu-system-x86_64 3 | QEMU_FLAGS = -m 2g -machine q35 -nographic -bios $(IMAGE) -s -cpu Icelake-Server -monitor /dev/tty -serial stdio -debugcon file:debug.log 4 | include ../../../../Makefile.inc 5 | include ../../../../Makefile.qemu.inc 6 | -------------------------------------------------------------------------------- /src/mainboard/emulation/qemu-q35/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | println!("cargo:rerun-if-changed=link.ld"); 3 | } 4 | -------------------------------------------------------------------------------- /src/mainboard/emulation/qemu-q35/fixed-dtfs.dts: -------------------------------------------------------------------------------- 1 | /dts-v1/; 2 | 3 | / { 4 | #address-cells = <1>; 5 | #size-cells = <1>; 6 | 7 | flash-info { 8 | compatible = "ore-flashinfo"; 9 | board-name = "QEMU q35"; 10 | category = "emulation"; 11 | board-url = "http://wiki.qemu.org/Main_Page"; 12 | areas { 13 | area@0 { 14 | description = "RamPayload DTFS A"; 15 | compatible = "ore-rampayload"; 16 | half = <0>; 17 | offset = <0x0>; 18 | size = <0xc00000>; 19 | file = "$(PAYLOAD_A)"; 20 | }; 21 | area@1 { 22 | description = "RamPayload DTFS B"; 23 | compatible = "ore-rampayload"; 24 | half = <1>; 25 | offset = <0xc00000>; 26 | size = <0x100000>; 27 | }; 28 | area@2 { 29 | description = "NVRAM B"; 30 | compatible = "ore-nvram"; 31 | half = <1>; 32 | offset = <0xfd0000>; 33 | size = <0x8000>; 34 | }; 35 | area@3 { 36 | description = "NVRAM A"; 37 | compatible = "ore-nvram"; 38 | half = <0>; 39 | offset = <0xfe0000>; 40 | size = <0x8000>; 41 | }; 42 | area@4 { 43 | description = "Fixed DTFS"; 44 | compatible = "ore-dtfs"; 45 | offset = <0xfe8000>; 46 | size = <0x8000>; 47 | file = "$(TARGET_DIR)/fixed-dtfs.dtb"; 48 | }; 49 | area@5 { 50 | description = "Boot Blob"; 51 | compatible = "ore-bootblob"; 52 | offset = <0xff0000>; 53 | size = <0x10000>; 54 | file = "$(TARGET_DIR)/bootblob.bin"; 55 | }; 56 | }; 57 | }; 58 | }; 59 | -------------------------------------------------------------------------------- /src/mainboard/emulation/qemu-q35/link.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | ENTRY(_boot); 26 | 27 | SECTIONS 28 | { 29 | . = 0xffff0000; 30 | .bootblock : 31 | { 32 | KEEP(*(.bootblock.boot)); 33 | KEEP(*(.text .text.*)); 34 | KEEP(*(.rodata .rodata.*)); 35 | /* There should be no 'data' as such but we'll fix it later */ 36 | KEEP(*(.data.*)) 37 | } 38 | . = 0xfffffff0; 39 | .reset . : 40 | { 41 | KEEP(*(.reset .reset.* .reset*)) 42 | } 43 | /DISCARD/ : { *(.comment) *(.note*) *(.eh_frame*) 44 | /* Unused exception related info that only wastes space */ 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/mainboard/emulation/qemu-q35/src/main.rs: -------------------------------------------------------------------------------- 1 | #![feature(llvm_asm)] 2 | #![feature(lang_items, start)] 3 | #![no_std] 4 | #![no_main] 5 | #![feature(global_asm)] 6 | 7 | use arch::bzimage::BzImage; 8 | use arch::ioport::IOPort; 9 | use core::fmt::Write; 10 | use core::panic::PanicInfo; 11 | use model::Driver; 12 | use print; 13 | use uart::debug_port::DebugPort; 14 | use uart::i8250::I8250; 15 | 16 | global_asm!(include_str!("../../../../arch/x86/x86_64/src/bootblock.S")); 17 | 18 | #[no_mangle] 19 | pub extern "C" fn _start(fdt_address: usize) -> ! { 20 | let io = &mut IOPort; 21 | let uart0 = &mut I8250::new(0x3f8, 0, io); 22 | // Note: on real hardware, use port 0x80 instead for "POST" output 23 | let debugIO = &mut IOPort; 24 | let debug = &mut DebugPort::new(0xe9, debugIO); 25 | uart0.init().unwrap(); 26 | uart0.pwrite(b"Welcome to oreboot\r\n", 0).unwrap(); 27 | debug.init().unwrap(); 28 | debug.pwrite(b"Welcome to oreboot - debug port E9\r\n", 0).unwrap(); 29 | 30 | let w = &mut print::WriteTo::new(uart0); 31 | 32 | // TODO: Get these values from the fdt 33 | let payload = &mut BzImage { low_mem_size: 0x80_000_000, high_mem_start: 0x1_000_000_000, high_mem_size: 0, rom_base: 0xff_000_000, rom_size: 0x100_000, load: 0x1_000_000, entry: 0x1_000_200 }; 34 | 35 | payload.load(w).unwrap(); 36 | 37 | write!(w, "Running payload\r\n").unwrap(); 38 | payload.run(w); 39 | 40 | write!(w, "Unexpected return from payload\r\n").unwrap(); 41 | arch::halt() 42 | } 43 | 44 | #[panic_handler] 45 | fn panic(info: &PanicInfo) -> ! { 46 | // Assume that uart0.init() has already been called before the panic. 47 | let io = &mut IOPort; 48 | let uart0 = &mut I8250::new(0x3f8, 0, io); 49 | let w = &mut print::WriteTo::new(uart0); 50 | // Printing in the panic handler is best-effort because we really don't want to invoke the panic 51 | // handler from inside itself. 52 | let _ = write!(w, "PANIC: {}\r\n", info); 53 | arch::halt() 54 | } 55 | -------------------------------------------------------------------------------- /src/mainboard/emulation/qemu-q35/src/romstage.rs: -------------------------------------------------------------------------------- 1 | use crate::halt; 2 | use payloads::external::zimage::PAYLOAD; 3 | 4 | pub fn romstage() -> ! { 5 | let p = PAYLOAD; 6 | p.load(); 7 | p.run(); 8 | 9 | halt() 10 | } 11 | -------------------------------------------------------------------------------- /src/mainboard/emulation/qemu-q35/src/vboot-rwa-16M.fmd: -------------------------------------------------------------------------------- 1 | FLASH@0xff000000 0x1000000 { 2 | SI_BIOS 0x1000000 { 3 | RW_SECTION_A 0x7c0000 { 4 | VBLOCK_A 0x10000 5 | FW_MAIN_A(CBFS) 0x74ffc0 6 | RW_FWID_A 0x40 7 | } 8 | RW_VPD(PRESERVE) 0x1000 9 | 10 | WP_RO { 11 | FMAP 0x800 12 | RO_FRID 0x40 13 | RO_PADDING 0x7c0 14 | RO_VPD(PRESERVE) 0x1000 15 | GBB 0x1e000 16 | COREBOOT(CBFS) 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/mainboard/emulation/qemu-riscv/.cargo/config: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "riscv64imac-unknown-none-elf" 3 | 4 | [target.riscv64imac-unknown-none-elf] 5 | rustflags = [ 6 | "-C", "link-arg=-Tlink.ld", 7 | ] 8 | -------------------------------------------------------------------------------- /src/mainboard/emulation/qemu-riscv/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "qemu-riscv" 3 | version = "0.1.0" 4 | authors = ["Oreboot Authors"] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | arch = { path = "../../../arch/riscv/rv64"} 9 | console = { path = "../../../console" } 10 | model = { path = "../../../drivers/model" } 11 | print = { path = "../../../lib/print" } 12 | payloads = { path = "../../../../payloads"} 13 | soc = { path = "../../../soc/sifive/fu540" } 14 | wrappers = { path = "../../../drivers/wrappers"} 15 | 16 | heapless = "0.4.x" 17 | register = "0.3.2" 18 | static-ref = "0.1.1" 19 | 20 | [dependencies.uart] 21 | path = "../../../drivers/uart" 22 | features = ["ns16550"] 23 | 24 | [profile.release] 25 | opt-level = 'z' # Optimize for size. 26 | lto = true 27 | -------------------------------------------------------------------------------- /src/mainboard/emulation/qemu-riscv/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = riscv64imac-unknown-none-elf 2 | QEMU = qemu-system-riscv64 3 | QEMU_FLAGS = -m 1g -machine virt -nographic -bios none -drive format=raw,if=pflash,file=$(IMAGE) 4 | include ../../../../Makefile.inc 5 | include ../../../../Makefile.qemu.inc 6 | -------------------------------------------------------------------------------- /src/mainboard/emulation/qemu-riscv/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | println!("cargo:rerun-if-changed=link.ld"); 3 | } 4 | -------------------------------------------------------------------------------- /src/mainboard/emulation/qemu-riscv/fixed-dtfs.dts: -------------------------------------------------------------------------------- 1 | /dts-v1/; 2 | 3 | / { 4 | #address-cells = <1>; 5 | #size-cells = <1>; 6 | 7 | flash-info { 8 | compatible = "ore-flashinfo"; 9 | board-name = "QEMU RISC-V VIRT"; 10 | category = "Emulation"; 11 | areas { 12 | area@0 { 13 | description = "Boot Blob and Ramstage"; 14 | offset = <0x0>; 15 | size = <0x80000>; // 512KiB 16 | file = "$(TARGET_DIR)/bootblob.bin"; 17 | }; 18 | area@1 { 19 | description = "Fixed DTFS"; 20 | offset = <0x80000>; 21 | size = <0x80000>; // 512KiB 22 | file = "$(TARGET_DIR)/fixed-dtfs.dtb"; 23 | }; 24 | area@2 { 25 | description = "Empty Space"; 26 | offset = <0x100000>; 27 | size = <0x1f00000>; // 31MiB 28 | }; 29 | }; 30 | }; 31 | }; 32 | -------------------------------------------------------------------------------- /src/mainboard/emulation/qemu-riscv/link.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | ENTRY(_boot); 26 | 27 | SECTIONS 28 | { 29 | . = 0x20000000; 30 | .bootblock : 31 | { 32 | KEEP(*(.bootblock.boot)); 33 | } 34 | .text : 35 | { 36 | KEEP(*(.text .text.*)); 37 | } 38 | .rodata : 39 | { 40 | KEEP(*(.rodata .rodata.*)); 41 | } 42 | 43 | /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) 44 | /* Unused exception related info that only wastes space */ 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/mainboard/emulation/qemu-riscv/src/bootblock.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Early initialization code for RISC-V 3 | * 4 | * Copyright 2013 Google Inc. 5 | * Copyright 2016 Jonathan Neuschäfer 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; version 2 of 10 | * the License. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the 15 | * GNU General Public License for more details. 16 | */ 17 | 18 | .section ".bootblock.boot", "ax", %progbits 19 | 20 | .globl _boot 21 | _boot: 22 | # The previous boot stage passes these variables: 23 | # a0: hartid 24 | # a1: ROM FDT 25 | 26 | # TODO: Support SMP. 27 | # Spin all harts other than 0. 28 | csrr a0, mhartid 29 | spin: 30 | bgt a0, x0, spin 31 | 32 | # Set the stack pointer 33 | # 0xDEADBEEF is used to check stack overflow 34 | 1: auipc t0, %pcrel_hi(_stack_ptr) 35 | lwu sp, %pcrel_lo(1b)(t0) 36 | 37 | li t0, 0xDEADBEEF 38 | sw t0, 0(sp) 39 | 40 | # TODO: hart-local storage 41 | # initialize hart-local storage 42 | #csrr a0, mhartid 43 | #csrrw a1, mscratch, zero 44 | #call hls_init 45 | 46 | #li a0, 0 # CONFIG_RISCV_WORKING_HARTID 47 | #call smp_pause 48 | 49 | # TODO: initialize entry of interrupt/exception 50 | #la t0, trap_entry 51 | #csrw mtvec, t0 52 | 53 | # TODO: clear any pending interrupts 54 | #csrwi mip, 0 55 | 56 | # TODO: set up the mstatus register 57 | #call mstatus_init 58 | 59 | # Pass device tree as a0 to Rust code. 60 | add a0, a1, x0 61 | call _start 62 | 63 | // These codes need to be implemented on a specific SoC. 64 | // .weak cache_as_ram 65 | forever: tail forever 66 | cache_as_ram: 67 | ret 68 | smp_pause: 69 | ret 70 | trap_entry: 71 | ret 72 | hls_init: 73 | ret 74 | .global abort 75 | abort: j abort 76 | 77 | .section ".bootblock.stack", "aw", %progbits 78 | _stack: 79 | .space 65536 80 | -------------------------------------------------------------------------------- /src/mainboard/emulation/qemu-riscv/src/init.S: -------------------------------------------------------------------------------- 1 | .globl _stack_ptr 2 | .section .rodata 3 | _stack_ptr: .word 0x80020000 4 | -------------------------------------------------------------------------------- /src/mainboard/emulation/qemu-riscv/src/main.rs: -------------------------------------------------------------------------------- 1 | #![feature(llvm_asm)] 2 | #![feature(lang_items, start)] 3 | #![no_std] 4 | #![no_main] 5 | #![feature(global_asm)] 6 | 7 | use core::fmt::Write; 8 | use core::panic::PanicInfo; 9 | use model::Driver; 10 | use payloads::payload; 11 | use print; 12 | use uart::ns16550::NS16550; 13 | use wrappers::{Memory, SectionReader, SliceReader}; 14 | 15 | global_asm!(include_str!("bootblock.S")); 16 | global_asm!(include_str!("init.S")); 17 | 18 | #[no_mangle] 19 | pub extern "C" fn _start(fdt_address: usize) -> ! { 20 | let uart0 = &mut NS16550::new(0x10000000, 115200); 21 | uart0.init().unwrap(); 22 | uart0.pwrite(b"Welcome to oreboot\r\n", 0).unwrap(); 23 | 24 | let w = &mut print::WriteTo::new(uart0); 25 | 26 | let kernel_segs = &[payload::Segment { typ: payload::stype::PAYLOAD_SEGMENT_ENTRY, base: 0x80000000, data: &mut SectionReader::new(&Memory {}, 0x20000000 + 0x400000, 6 * 1024 * 1024) }, payload::Segment { 27 | typ: payload::stype::PAYLOAD_SEGMENT_DATA, 28 | base: fdt_address, 29 | data: &mut SliceReader::new(&[0u8; 0]), 30 | }]; 31 | let payload = payload::Payload { typ: payload::ftype::CBFS_TYPE_RAW, compression: payload::ctype::CBFS_COMPRESS_NONE, offset: 0, entry: 0x80000000 as usize, rom_len: 0 as usize, mem_len: 0 as usize, segs: kernel_segs, dtb: 0 }; 32 | 33 | write!(w, "Running payload\r\n").unwrap(); 34 | payload.run(); 35 | 36 | write!(w, "Unexpected return from payload\r\n").unwrap(); 37 | arch::halt() 38 | } 39 | 40 | #[panic_handler] 41 | fn panic(info: &PanicInfo) -> ! { 42 | // Assume that uart0.init() has already been called before the panic. 43 | let uart0 = &mut NS16550::new(0x10000000, 115200); 44 | let w = &mut print::WriteTo::new(uart0); 45 | // Printing in the panic handler is best-effort because we really don't want to invoke the panic 46 | // handler from inside itself. 47 | let _ = write!(w, "PANIC: {}\r\n", info); 48 | arch::halt() 49 | } 50 | -------------------------------------------------------------------------------- /src/mainboard/nuvoton/npcm7xx/.cargo/config: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "armv7r-none-eabi" 3 | 4 | [target.armv7r-none-eabi] 5 | rustflags = [ 6 | "-C", "link-arg=-Tlink.ld", 7 | ] 8 | -------------------------------------------------------------------------------- /src/mainboard/nuvoton/npcm7xx/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "npcm7xx" 5 | version = "0.1.0" 6 | -------------------------------------------------------------------------------- /src/mainboard/nuvoton/npcm7xx/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "npcm7xx" 3 | version = "0.1.0" 4 | authors = ["Oreboot Authors"] 5 | edition = "2018" 6 | build = "build.rs" 7 | 8 | [dependencies] 9 | 10 | [profile.release] 11 | opt-level = 'z' # Optimize for size. 12 | lto = true 13 | -------------------------------------------------------------------------------- /src/mainboard/nuvoton/npcm7xx/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = armv7r-none-eabi 2 | include ../../../../Makefile.inc 3 | -------------------------------------------------------------------------------- /src/mainboard/nuvoton/npcm7xx/README: -------------------------------------------------------------------------------- 1 | See: 2 | https://github.com/linuxboot/nuvoton-info 3 | -------------------------------------------------------------------------------- /src/mainboard/nuvoton/npcm7xx/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | println!("cargo:rerun-if-changed=link.ld"); 3 | } 4 | -------------------------------------------------------------------------------- /src/mainboard/nuvoton/npcm7xx/fixed-dtfs.dts: -------------------------------------------------------------------------------- 1 | /dts-v1/; 2 | 3 | / { 4 | #address-cells = <1>; 5 | #size-cells = <1>; 6 | 7 | flash-info { 8 | compatible = "ore-flashinfo"; 9 | board-name = "HiFive Unleashed"; 10 | category = "SiFive"; 11 | board-url = "https://www.sifive.com/boards/hifive-unleashed"; 12 | areas { 13 | area@0 { 14 | description = "Boot Blob"; 15 | compatible = "ore-bootblob"; 16 | offset = <0x0>; 17 | size = <0x80000>; // 512KiB 18 | file = "$(TARGET_DIR)/bootblob.bin"; 19 | }; 20 | area@1 { 21 | description = "Fixed DTFS"; 22 | compatible = "ore-dtfs"; 23 | offset = <0x80000>; 24 | size = <0x80000>; // 512KiB 25 | file = "$(TARGET_DIR)/fixed-dtfs.dtb"; 26 | }; 27 | area@2 { 28 | description = "NVRAM A"; 29 | compatible = "ore-nvram"; 30 | half = <0>; 31 | offset = <0x100000>; 32 | size = <0x80000>; // 512KiB 33 | }; 34 | area@3 { 35 | description = "NVRAM B"; 36 | compatible = "ore-nvram"; 37 | half = <1>; 38 | offset = <0x180000>; 39 | size = <0x80000>; // 512KiB 40 | }; 41 | area@4 { 42 | description = "RomPayload DTFS A"; 43 | compatible = "ore-rompayload"; 44 | half = <0>; 45 | offset = <0x200000>; 46 | size = <0x100000>; // 1MiB 47 | }; 48 | area@5 { 49 | description = "RomPayload DTFS B"; 50 | compatible = "ore-rompayload"; 51 | half = <1>; 52 | offset = <0x300000>; 53 | size = <0x100000>; // 1MiB 54 | }; 55 | area@6 { 56 | description = "RamPayload DTFS A"; 57 | compatible = "ore-rampayload"; 58 | half = <0>; 59 | offset = <0x400000>; 60 | size = <0x600000>; // 6MiB 61 | file = "kernel"; 62 | }; 63 | area@7 { 64 | description = "RamPayload DTFS B"; 65 | compatible = "ore-rampayload"; 66 | half = <1>; 67 | offset = <0xa00000>; 68 | size = <0x600000>; // 6MiB 69 | file = "../../../../payloads/src/external/simple/testtesttest"; 70 | }; 71 | area@8 { 72 | description = "Empty Space"; 73 | offset = <0x1000000>; 74 | size = <0x1000000>; // 16MiB 75 | }; 76 | }; 77 | }; 78 | }; 79 | -------------------------------------------------------------------------------- /src/mainboard/nuvoton/npcm7xx/kernel: -------------------------------------------------------------------------------- 1 | Replace me with your kernel. 2 | -------------------------------------------------------------------------------- /src/mainboard/nuvoton/npcm7xx/link.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | ENTRY(_boot); 26 | 27 | SECTIONS 28 | { 29 | . = 0x20000000; 30 | .bootblock : 31 | { 32 | KEEP(*(.bootblock.boot)); 33 | } 34 | .text : 35 | { 36 | KEEP(*(.text .text.*)); 37 | } 38 | .rodata : 39 | { 40 | KEEP(*(.rodata .rodata.*)); 41 | } 42 | 43 | /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) 44 | /* Unused exception related info that only wastes space */ 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/mainboard/nuvoton/npcm7xx/src/main.rs: -------------------------------------------------------------------------------- 1 | #![feature(llvm_asm)] 2 | #![feature(lang_items, start)] 3 | #![no_std] 4 | #![no_main] 5 | #![feature(global_asm)] 6 | #![deny(warnings)] 7 | 8 | //use core::fmt; 9 | //use core::fmt::Write; 10 | //use model::Driver; 11 | //use print; 12 | //use wrappers::DoD; 13 | 14 | // global_asm!(include_str!("../../../../../src/soc/sifive/fu540/src/bootblock.S")); 15 | // global_asm!(include_str!("../../../../../src/soc/sifive/fu540/src/init.S")); 16 | 17 | #[no_mangle] 18 | pub extern "C" fn _start(_fdt_address: usize) -> ! { 19 | loop {} 20 | } 21 | 22 | // This function is called on panic. 23 | use core::panic::PanicInfo; 24 | #[panic_handler] 25 | fn panic(_info: &PanicInfo) -> ! { 26 | loop {} 27 | } 28 | -------------------------------------------------------------------------------- /src/mainboard/opentitan/crb/.cargo/config: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "riscv32imc-unknown-none-elf" 3 | 4 | [target.riscv32imc-unknown-none-elf] 5 | rustflags = [ 6 | "-C", "link-arg=-Tlink.ld", 7 | ] 8 | -------------------------------------------------------------------------------- /src/mainboard/opentitan/crb/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "crb" 3 | version = "0.1.0" 4 | authors = ["Oreboot Authors"] 5 | edition = "2018" 6 | build = "build.rs" 7 | 8 | [dependencies] 9 | console = { path = "../../../console" } 10 | print = { path = "../../../lib/print" } 11 | model = { path = "../../../drivers/model" } 12 | payloads = { path = "../../../../payloads"} 13 | soc = { path = "../../../soc/opentitan/earlgrey" } 14 | wrappers = { path = "../../../drivers/wrappers"} 15 | 16 | register = "0.3.2" 17 | static-ref = "0.1.1" 18 | 19 | [dependencies.uart] 20 | path = "../../../drivers/uart" 21 | features = ["opentitan"] 22 | 23 | [profile.release] 24 | opt-level = 'z' # Optimize for size. 25 | lto = true 26 | -------------------------------------------------------------------------------- /src/mainboard/opentitan/crb/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = riscv32imc-unknown-none-elf 2 | ROM = $(TARGET_DIR)/rom.bin 3 | FLASH = $(TARGET_DIR)/flash.bin 4 | include ../../../../Makefile.inc 5 | 6 | .DEFAULT_GOAL = $(IMAGE).vmem 7 | 8 | $(ROM): $(BOOTBLOB) 9 | dd if=$< of=$@ ibs=2048 count=1 10 | 11 | $(FLASH): $(BOOTBLOB) 12 | dd if=$< of=$@ ibs=32768 skip=16383 13 | dd if=$< of=$@ ibs=32768 count=1 skip=16383 14 | 15 | $(IMAGE).vmem: $(FLASH) 16 | cargo run --target $(TOOLS_TARGET) --manifest-path $(TOOLS_DIR)/bin2vmem/Cargo.toml -- -o 0 <$< >$@ 17 | @printf "**\n** Output: $@\n**\n" 18 | 19 | run: $(IMAGE).vmem 20 | Vtop_earlgrey_verilator --rominit=rom.vmem --flashinit=$< 21 | 22 | trace: $(IMAGE).vmem 23 | Vtop_earlgrey_verilator -t --rominit=rom.vmem --flashinit=$< 24 | -------------------------------------------------------------------------------- /src/mainboard/opentitan/crb/README.md: -------------------------------------------------------------------------------- 1 | opentitan README 2 | =============== 3 | 4 | For more on opentitan search for lowrisc open titan 5 | 6 | You need at least the verilator and bitstream. It's a bit clumsy right now: you have to get 7 | build artifacts from azure. 8 | 9 | Go here: 10 | [build artifacts](https://dev.azure.com/lowrisc/opentitan/_build?definitionId=5&_a=summary) 11 | 12 | Click on any of the builds, and on the top right you should see a link for artifacts. Click on that, 13 | and you will see a choice of 4 items; take the topmost. 14 | 15 | It is a gzip tar file; unpack it somewhere. For the verilator, the path will be something like: 16 | ``` 17 | /path/to/some/place/opentitan-snapshot-20191101-2/hw/top_earlgrey/Vtop_earlgrey_verilator 18 | ``` 19 | 20 | If you do this: 21 | ``` 22 | PATH=$PATH:/path/to/some/place/opentitan-snapshot-20191101-2/hw/top_earlgrey 23 | ``` 24 | 25 | ## Running: 26 | 27 | ### Emulator 28 | To run on the verilator modify `drivers/uart/src/opentitan.rs` 29 | as specified by the note. 30 | 31 | Copy /path/to/some/place/opentitan-snapshot-20191101-2/sw/device/sim/boot_rom/rom.vmem to your 32 | local directory. 33 | 34 | ``` 35 | cargo make -p release run 36 | ``` 37 | in this directory will run the verilator. 38 | 39 | You will see trace output in a file named 40 | ``` 41 | trace_core_00000000.log 42 | ``` 43 | 44 | ## Hardware 45 | 46 | ``` 47 | cargo make -p release 48 | ``` 49 | 50 | Using the opentitan snapshot and running the earlgrey bitstream run: 51 | ``` 52 | /path/to/some/place/opentitan-snapshot-20191101-2/sw/host/spiflash/spiflash --input=target/riscv32imc-unknown-none-elf/release/bootblob.bin 53 | ``` 54 | 55 | Make sure to be connected the the device at baud rate 230400 56 | 57 | 58 | -------------------------------------------------------------------------------- /src/mainboard/opentitan/crb/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | println!("cargo:rerun-if-changed=link.ld"); 3 | } 4 | -------------------------------------------------------------------------------- /src/mainboard/opentitan/crb/fixed-dtfs.dts: -------------------------------------------------------------------------------- 1 | /dts-v1/; 2 | 3 | / { 4 | #address-cells = <1>; 5 | #size-cells = <1>; 6 | 7 | flash-info { 8 | compatible = "ore-flashinfo"; 9 | board-name = "OpenTitan CRB"; 10 | category = "OpenTitan"; 11 | board-url = "https://github.com/lowRISC/opentitan"; 12 | areas { 13 | area@0 { 14 | description = "payloader"; 15 | offset = <0x0>; 16 | size = <0xf000>; // 64KiB - 4 KiB 17 | file = "target/riscv32imc-unknown-none-elf/release/flash.bin"; 18 | }; 19 | area@1 { 20 | description = "Fixed DTFS"; 21 | offset = <0xf000>; 22 | size = <0x1000>; // 4KiB 23 | file = "$(TARGET_DIR)/fixed-dtfs.dtb"; 24 | }; 25 | area@2 { 26 | description = "Payload A"; 27 | offset = <0x10000>; 28 | size = <0x00000>; // 0x20000 later128 KiB 29 | file = "$(PAYLOAD_A)"; 30 | }; 31 | area@3 { 32 | description = "Payload B"; 33 | offset = <0x30000>; 34 | size = <0x00000>; 35 | file = "$(PAYLOAD_B)"; 36 | }; 37 | area@4 { 38 | description = "Payload C"; 39 | offset = <0x50000>; 40 | size = <0x00000>; 41 | file = "$(PAYLOAD_C)"; 42 | }; 43 | area@5 { 44 | description = "Empty Space"; 45 | offset = <0x70000>; 46 | size = <0x00000>; // 0x10000 later 47 | }; 48 | }; 49 | }; 50 | }; 51 | -------------------------------------------------------------------------------- /src/mainboard/opentitan/crb/link.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | ENTRY(_boot); 26 | 27 | SECTIONS 28 | { 29 | 30 | . = 0x20000000; 31 | .bootblock : 32 | { 33 | KEEP(*(.bootblock.boot)); 34 | } 35 | .text : 36 | { 37 | KEEP(*(.text .text.*)); 38 | } 39 | .rodata : 40 | { 41 | KEEP(*(.rodata .rodata.*)); 42 | } 43 | 44 | . = 0x10000000; 45 | .bss : 46 | { 47 | KEEP(*(.bss .bss.* .sbss .sbss.*)); /* we could just leave this empty ... */ 48 | } 49 | 50 | /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) 51 | /* Unused exception related info that only wastes space */ 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/mainboard/opentitan/crb/src/main.rs: -------------------------------------------------------------------------------- 1 | #![feature(llvm_asm)] 2 | #![feature(lang_items, start)] 3 | #![no_std] 4 | #![no_main] 5 | #![feature(global_asm)] 6 | //#![deny(warnings)] 7 | 8 | use core::fmt::Write; 9 | use core::panic::PanicInfo; 10 | use model::Driver; 11 | use payloads::payload; 12 | use print; 13 | use uart::opentitan::OpenTitanUART; 14 | use wrappers::{Memory, SectionReader, SliceReader}; 15 | 16 | const BAUDRATE: u32 = 230400; 17 | 18 | #[no_mangle] 19 | pub extern "C" fn _start_boot_hart(_hart_id: usize, fdt_address: usize) -> ! { 20 | // Set up the pinmux. This is highly board dependent. 21 | // TODO: pinmux device. 22 | let m = &mut Memory; 23 | 24 | m.pwrite(&[0xc2u8, 0x40u8, 0x14u8, 0x06u8], 0x40070004); 25 | m.pwrite(&[0x07u8, 0x92u8, 0x28u8, 0x0bu8], 0x40070008); 26 | m.pwrite(&[0x4cu8, 0xe3u8, 0x3cu8, 0x10u8], 0x4007000c); 27 | m.pwrite(&[0x91u8, 0x34u8, 0x51u8, 0x15u8], 0x40070010); 28 | m.pwrite(&[0xd6u8, 0x85u8, 0x65u8, 0x1au8], 0x40070014); 29 | m.pwrite(&[0x1bu8, 0xd7u8, 0x79u8, 0x1fu8], 0x40070018); 30 | m.pwrite(&[0x60u8, 0x08u8, 0x00u8, 0x00u8], 0x4007001c); 31 | m.pwrite(&[0xc2u8, 0x40u8, 0x14u8, 0x06u8], 0x40070020); 32 | m.pwrite(&[0x07u8, 0x92u8, 0x28u8, 0x0bu8], 0x40070024); 33 | m.pwrite(&[0x4cu8, 0xe3u8, 0x3cu8, 0x10u8], 0x40070028); 34 | m.pwrite(&[0x91u8, 0x34u8, 0x51u8, 0x15u8], 0x4007002c); 35 | m.pwrite(&[0xd6u8, 0x85u8, 0x65u8, 0x1au8], 0x40070030); 36 | m.pwrite(&[0x1bu8, 0xd7u8, 0x79u8, 0x1fu8], 0x40070034); 37 | m.pwrite(&[0x60u8, 0x08u8, 0x00u8, 0x00u8], 0x40070038); 38 | let uart0 = &mut OpenTitanUART::new(0x40000000, BAUDRATE); 39 | uart0.init(); 40 | uart0.pwrite(b"Welcome to oreboot\r\n", 0); 41 | 42 | let w = &mut print::WriteTo::new(uart0); 43 | 44 | // TODO; This payload structure should be loaded from SPI rather than hardcoded. 45 | let mem = 0x10000000; 46 | let flash = 0x20000000; 47 | let kernel_segs = &[ 48 | payload::Segment { 49 | typ: payload::stype::PAYLOAD_SEGMENT_ENTRY, 50 | base: mem, 51 | data: &mut SliceReader::new(&[0x73u8, 0x00u8, 0x50u8, 0x10u8 /*0x10500073 wfi */]), 52 | //data: &mut SectionReader::new(&Memory {}, 0x20000000 + 0x10000, 0x20), 53 | }, 54 | payload::Segment { 55 | typ: payload::stype::PAYLOAD_SEGMENT_DATA, 56 | base: flash + 0x10000, //fdt_address, /*mem + 10*1024*1024*/ 57 | data: &mut SectionReader::new(&Memory {}, 0x20000000 + 0xf000, 0x10), 58 | }, 59 | ]; 60 | let mut payload: payload::Payload = payload::Payload { 61 | typ: payload::ftype::CBFS_TYPE_RAW, 62 | compression: payload::ctype::CBFS_COMPRESS_NONE, 63 | offset: 0, 64 | entry: 0, 65 | dtb: 0, 66 | // TODO: These two length fields are not used. 67 | rom_len: 0, 68 | mem_len: 0, 69 | segs: kernel_segs, 70 | }; 71 | write!(w, "Loading payload\r\n"); 72 | payload.load(); 73 | write!(w, "Running payload entry 0x{:x} dtb 0x{:x}\r\n", payload.entry, payload.dtb); 74 | soc::halt() 75 | //payload.run(); 76 | 77 | //write!(w, "Unexpected return from payload\r\n").unwrap(); 78 | //soc::halt() 79 | } 80 | 81 | #[no_mangle] 82 | pub extern "C" fn abort() { 83 | panic!("abort!"); 84 | } 85 | 86 | /// This function is called on panic. 87 | #[panic_handler] 88 | fn panic(info: &PanicInfo) -> ! { 89 | // Assume that uart0.init() has already been called before the panic. 90 | let uart0 = &mut OpenTitanUART::new(0x40000000, BAUDRATE); 91 | let w = &mut print::WriteTo::new(uart0); 92 | // Printing in the panic handler is best-effort because we really don't want to invoke the panic 93 | // handler from inside itself. 94 | let _ = write!(w, "PANIC: {}\r\n", info); 95 | soc::halt() 96 | } 97 | -------------------------------------------------------------------------------- /src/mainboard/sifive/hifive/.cargo/config: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "riscv64imac-unknown-none-elf" 3 | 4 | [target.riscv64imac-unknown-none-elf] 5 | rustflags = [ 6 | "-C", "link-arg=-Tlink.ld", 7 | ] 8 | -------------------------------------------------------------------------------- /src/mainboard/sifive/hifive/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "hifive" 3 | version = "0.1.0" 4 | authors = ["Oreboot Authors"] 5 | edition = "2018" 6 | build = "build.rs" 7 | 8 | [dependencies] 9 | arch = { path = "../../../arch/riscv/rv64"} 10 | clock = { path = "../../../drivers/clock" } 11 | console = { path = "../../../console" } 12 | device_tree = { path = "../../../lib/device_tree" } 13 | print = { path = "../../../lib/print" } 14 | model = { path = "../../../drivers/model" } 15 | payloads = { path = "../../../../payloads"} 16 | soc = { path = "../../../soc/sifive/fu540" } 17 | spi = { path = "../../../drivers/sifive/spi" } 18 | wrappers = { path = "../../../drivers/wrappers"} 19 | 20 | heapless = "0.4.x" 21 | register = "0.3.2" 22 | static-ref = "0.1.1" 23 | 24 | [dependencies.uart] 25 | path = "../../../drivers/uart" 26 | features = ["sifive", "log", "heapless"] 27 | 28 | [profile.release] 29 | opt-level = 'z' # Optimize for size. 30 | lto = true 31 | -------------------------------------------------------------------------------- /src/mainboard/sifive/hifive/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = riscv64imac-unknown-none-elf 2 | QEMU = qemu-system-riscv64 3 | QEMU_FLAGS = -m 1g -machine sifive_u,start-in-flash=true -nographic -device loader,addr=0x20000000,file=${IMAGE} -bios none -smp 4 4 | include ../../../../Makefile.inc 5 | include ../../../../Makefile.qemu.inc 6 | 7 | openocd: 8 | $(shell which openocd) -f openocd.cfg -c "flash write_image erase unlock $(IMAGE) 0x20000000; shutdown" 9 | -------------------------------------------------------------------------------- /src/mainboard/sifive/hifive/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | println!("cargo:rerun-if-changed=link.ld"); 3 | } 4 | -------------------------------------------------------------------------------- /src/mainboard/sifive/hifive/fixed-dtfs.dts: -------------------------------------------------------------------------------- 1 | /dts-v1/; 2 | 3 | / { 4 | #address-cells = <1>; 5 | #size-cells = <1>; 6 | 7 | flash-info { 8 | compatible = "ore-flashinfo"; 9 | board-name = "HiFive Unleashed"; 10 | category = "SiFive"; 11 | board-url = "https://www.sifive.com/boards/hifive-unleashed"; 12 | areas { 13 | area@0 { 14 | description = "Boot Blob and Ramstage"; 15 | size = <0x80000>; // 512KiB 16 | file = "$(TARGET_DIR)/bootblob.bin"; 17 | }; 18 | area@1 { 19 | description = "Fixed DTFS"; 20 | size = <0x80000>; // 512KiB 21 | file = "$(TARGET_DIR)/fixed-dtfs.dtb"; 22 | }; 23 | area@2 { 24 | description = "Payload A"; 25 | size = <0x600000>; // 6MiB 26 | file = "$(PAYLOAD_A)"; 27 | }; 28 | area@3 { 29 | description = "Payload B"; 30 | size = <0x600000>; // 6MiB 31 | file = "$(PAYLOAD_B)"; 32 | }; 33 | area@4 { 34 | description = "Payload C"; 35 | size = <0x300000>; // 3MiB 36 | file = "$(PAYLOAD_C)"; 37 | }; 38 | area@5 { 39 | description = "Empty Space"; 40 | size = <0x1000000>; // 16MiB 41 | }; 42 | }; 43 | }; 44 | }; 45 | -------------------------------------------------------------------------------- /src/mainboard/sifive/hifive/kernel: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orangecms/oreboot/e66c077413956bf4da78e855cda2c7b8cac0aa00/src/mainboard/sifive/hifive/kernel -------------------------------------------------------------------------------- /src/mainboard/sifive/hifive/link.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | ENTRY(_boot); 26 | 27 | SECTIONS 28 | { 29 | . = 0x20000000; 30 | .bootblock : 31 | { 32 | KEEP(*(.bootblock.boot)); 33 | } 34 | .text : 35 | { 36 | KEEP(*(.text .text.*)); 37 | } 38 | .rodata : 39 | { 40 | KEEP(*(.rodata .rodata.*)); 41 | } 42 | 43 | . = 0x08000000; 44 | .bss : 45 | { 46 | KEEP(*(.bss .bss.* .sbss .sbss.*)); 47 | } 48 | 49 | /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) 50 | /* Unused exception related info that only wastes space */ 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/mainboard/sifive/hifive/openocd.cfg: -------------------------------------------------------------------------------- 1 | adapter_khz 10000 2 | 3 | interface ftdi 4 | ftdi_device_desc "Dual RS232-HS" 5 | ftdi_vid_pid 0x0403 0x6010 6 | 7 | ftdi_layout_init 0x0008 0x001b 8 | ftdi_layout_signal nSRST -oe 0x0020 -data 0x0020 9 | 10 | set _CHIPNAME riscv 11 | jtag newtap $_CHIPNAME cpu -irlen 5 12 | 13 | set _TARGETNAME $_CHIPNAME.cpu 14 | target create $_TARGETNAME riscv -chain-position $_TARGETNAME -rtos riscv 15 | $_TARGETNAME configure -work-area-phys 0x80000000 -work-area-size 10000 -work-area-backup 1 16 | 17 | flash bank onboard_spi_flash fespi 0x20000000 0 0 0 $_TARGETNAME 0x10040000 18 | init 19 | halt 20 | -------------------------------------------------------------------------------- /src/mainboard/sifive/hifive/src/hifive.dtb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orangecms/oreboot/e66c077413956bf4da78e855cda2c7b8cac0aa00/src/mainboard/sifive/hifive/src/hifive.dtb -------------------------------------------------------------------------------- /src/soc/aspeed/ast2500/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "soc" 3 | version = "0.1.0" 4 | authors = ["Oreboot Authors"] 5 | edition = "2018" 6 | 7 | [profile.release] 8 | opt-level = 'z' # Optimize for size. 9 | 10 | [dependencies] 11 | register = "0.3.2" 12 | -------------------------------------------------------------------------------- /src/soc/aspeed/ast2500/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![deny(warnings)] 3 | 4 | pub mod reg; 5 | -------------------------------------------------------------------------------- /src/soc/aspeed/ast2500/src/reg.rs: -------------------------------------------------------------------------------- 1 | const CONFIG_DRAM_ECC_SIZE: u32 = 0x10000000; 2 | const BASE: u32 = 0x1E60_0000; 3 | const Protection_Key: u32 = BASE + 0xC00; 4 | const AHB_Bus_Command_Recording_Control_Status: u32 = BASE + 0xC40; 5 | const Log_Buffer_Base_Write_Pointer: u32 = BASE + 0xC44; 6 | const Polling_Address: u32 = BASE + 0xC48; 7 | const Hardware_FIFO_Status: u32 = BASE + 0xC4C; 8 | const Hardware_FIFO_Merge: u32 = BASE + 0xC5C; 9 | const Hardware_FIFO_Stage_0: u32 = BASE + 0xC60; 10 | const Hardware_FIFO_Stage_1: u32 = BASE + 0xC64; 11 | const Hardware_FIFO_Stage_2: u32 = BASE + 0xC68; 12 | const Hardware_FIFO_Stage_3: u32 = BASE + 0xC6C; 13 | const Hardware_FIFO_Stage_4: u32 = BASE + 0xC70; 14 | const Hardware_FIFO_Stage_5: u32 = BASE + 0xC74; 15 | const Hardware_FIFO_Stage_6: u32 = BASE + 0xC78; 16 | const Hardware_FIFO_Stage_7: u32 = BASE + 0xC7C; 17 | const Priority_Control: u32 = BASE + 0xC80; 18 | const Interrupt_Control_Status: u32 = BASE + 0xC84; 19 | const AHB_Bus_Target_Disable_Control: u32 = BASE + 0xC88; 20 | const Address_Remapping: u32 = BASE + 0xC8C; 21 | const Watchdog_Counter_Status: u32 = BASE + 0xC90; 22 | const Watchdog_Counter_Reload_Value: u32 = BASE + 0xC94; 23 | -------------------------------------------------------------------------------- /src/soc/opentitan/earlgrey/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "soc" 3 | version = "0.1.0" 4 | authors = ["Oreboot Authors"] 5 | edition = "2018" 6 | 7 | [profile.release] 8 | opt-level = 'z' # Optimize for size. 9 | 10 | [dependencies] 11 | cpu = { path = "../../../cpu/lowrisc/ibex"} 12 | model = { path = "../../../drivers/model"} 13 | clock = { path = "../../../drivers/clock" } 14 | register = "0.3.2" 15 | -------------------------------------------------------------------------------- /src/soc/opentitan/earlgrey/src/bootblock.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Early initialization code for RISC-V 3 | * 4 | * Copyright 2013 Google Inc. 5 | * Copyright 2016 Jonathan Neuschäfer 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; version 2 of 10 | * the License. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the 15 | * GNU General Public License for more details. 16 | */ 17 | 18 | .section ".bootblock.boot", "ax", %progbits 19 | 20 | .globl _boot 21 | _boot: 22 | // These codes need to be implemented on a specific SoC. 23 | // .weak cache_as_ram 24 | # The previous boot stage passes these variables: 25 | # a0: hartid 26 | # a1: ROM FDT 27 | # a0 is redundant with the mhartid register. a1 might not be valid on 28 | # some hardware configurations, but is always set in QEMU. 29 | csrr a0, mhartid 30 | 31 | # Reset the mtimecmp to some absurdly large number. 32 | # The mtimecmp register is memory mapped at 0x2004000 + 0x8 * mhartid 33 | # TODO: Move to Rust 34 | li t0, 0x2004000 35 | slli t1, a0, 3 36 | add t1, t1, t0 37 | li t0, 0xfffffff 38 | # sd t0, (t1) 39 | 40 | # Clear all interrupt enable and pending bits. 41 | # TODO: Move to Rust 42 | csrwi mie, 0x0 43 | csrwi mip, 0x0 44 | 45 | # TODO: fix this comment and figure out RAM sizes. 46 | # Layout of L2-LIM (address 0x08000000): 47 | # 0x00000-0x0ffff: .bss segment (64K bytes) 48 | # 0x10000-0x1ffff: stack of boot hart (64K bytes) 49 | # 0x20000-0x20fff: stack of hart 0 (4K bytes) 50 | # 0x21000-0x21fff: stack of hart 1 (4K bytes) 51 | # ... 52 | # 0x2n000-0x2nfff: stack of hart n (4K bytes) 53 | 54 | # Clear the .bss segment. Every hart does this, which should be safe. 55 | li t0, 0x10000000 56 | li t1, 0x10010000 57 | li t1, 0x10000100 58 | clear_bss: 59 | # verilator crashes and burns on the first sw. 60 | sw zero, (t0) 61 | addi t0, t0, 8 62 | bne t0, t1, clear_bss 63 | li sp, (0x10010000 - 8) 64 | # 0xDEADBEEF is used to check stack underflow. 65 | li t0, 0xDEADBEEF 66 | # this causes and abort of some kind 67 | sw t0, 0(sp) 68 | 69 | # TODO: hart-local storage 70 | # initialize hart-local storage 71 | #csrr a0, mhartid 72 | #csrrw a1, mscratch, zero 73 | #call hls_init 74 | 75 | #li a0, 0 # CONFIG_RISCV_WORKING_HARTID 76 | #call smp_pause 77 | 78 | # TODO: initialize entry of interrupt/exception 79 | #la t0, trap_entry 80 | #csrw mtvec, t0 81 | 82 | # TODO: clear any pending interrupts 83 | #csrwi mip, 0 84 | 85 | # TODO: set up the mstatus register 86 | #call mstatus_init 87 | 88 | call _start_boot_hart 89 | 90 | forever: tail forever 91 | cache_as_ram: 92 | ret 93 | trap_entry: 94 | ret 95 | hls_init: 96 | ret 97 | .section ".bootblock.stack", "aw", %progbits 98 | _stack: 99 | .space 65536 100 | -------------------------------------------------------------------------------- /src/soc/opentitan/earlgrey/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![feature(global_asm)] 3 | 4 | global_asm!(include_str!("bootblock.S")); 5 | 6 | // There is no earlygrey-specific way of halting yet. 7 | pub use cpu::halt; 8 | -------------------------------------------------------------------------------- /src/soc/sifive/fu540/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "soc" 3 | version = "0.1.0" 4 | authors = ["Oreboot Authors"] 5 | edition = "2018" 6 | 7 | [profile.release] 8 | opt-level = 'z' # Optimize for size. 9 | 10 | [dependencies] 11 | arch = { path = "../../../arch/riscv/rv64"} 12 | model = { path = "../../../drivers/model"} 13 | clock = { path = "../../../drivers/clock" } 14 | spi = { path = "../../../drivers/sifive/spi" } 15 | register = "0.3.2" 16 | 17 | -------------------------------------------------------------------------------- /src/soc/sifive/fu540/src/bootblock.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Early initialization code for RISC-V 3 | * 4 | * Copyright 2013 Google Inc. 5 | * Copyright 2016 Jonathan Neuschäfer 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; version 2 of 10 | * the License. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the 15 | * GNU General Public License for more details. 16 | */ 17 | 18 | .section ".bootblock.boot", "ax", %progbits 19 | 20 | .globl _boot 21 | _boot: 22 | # The previous boot stage passes these variables: 23 | # a0: hartid 24 | # a1: ROM FDT 25 | # a0 is redundant with the mhartid register. a1 might not be valid on 26 | # some hardware configurations, but is always set in QEMU. 27 | csrr a0, mhartid 28 | 29 | # Reset the mtimecmp to some absurdly large number. 30 | # The mtimecmp register is memory mapped at 0x2004000 + 0x8 * mhartid 31 | # TODO: Move to Rust 32 | li t0, 0x2004000 33 | slli t1, a0, 3 34 | add t1, t1, t0 35 | li t0, 0xffffffffffffffff 36 | sd t0, (t1) 37 | 38 | # Clear all interrupt enable and pending bits. 39 | # TODO: Move to Rust 40 | csrwi mie, 0x0 41 | csrwi mip, 0x0 42 | 43 | # Layout of L2-LIM (address 0x08000000): 44 | # 0x00000-0x0ffff: .bss segment (64K bytes) 45 | # 0x10000-0x1ffff: stack of boot hart (64K bytes) 46 | # 0x20000-0x20fff: stack of hart 0 (4K bytes) 47 | # 0x21000-0x21fff: stack of hart 1 (4K bytes) 48 | # ... 49 | # 0x2n000-0x2nfff: stack of hart n (4K bytes) 50 | 51 | # Clear the .bss segment. Every hart does this, which should be safe. 52 | li t0, 0x08000000 53 | li t1, 0x08010000 54 | clear_bss: 55 | sd zero, (t0) 56 | addi t0, t0, 8 57 | bne t0, t1, clear_bss 58 | 59 | # Decide if this is the boot hart. 60 | li t0, 1 61 | beq a0, t0, setup_boot_hart_stack 62 | 63 | setup_nonboot_hart_stack: 64 | # sp <- 0x08021000 + (0x1000 * mhartid) - 8 65 | li sp, (0x08021000 - 8) 66 | slli t0, a0, 12 67 | add sp, sp, t0 68 | 69 | # 0xDEADBEEF is used to check stack underflow. 70 | li t0, 0xDEADBEEF 71 | sw t0, 0(sp) 72 | 73 | call _start_nonboot_hart 74 | 75 | setup_boot_hart_stack: 76 | li sp, (0x08020000 - 8) 77 | # 0xDEADBEEF is used to check stack underflow. 78 | li t0, 0xDEADBEEF 79 | sw t0, 0(sp) 80 | 81 | # TODO: hart-local storage 82 | # initialize hart-local storage 83 | #csrr a0, mhartid 84 | #csrrw a1, mscratch, zero 85 | #call hls_init 86 | 87 | #li a0, 0 # CONFIG_RISCV_WORKING_HARTID 88 | #call smp_pause 89 | 90 | # TODO: initialize entry of interrupt/exception 91 | #la t0, trap_entry 92 | #csrw mtvec, t0 93 | 94 | # TODO: clear any pending interrupts 95 | #csrwi mip, 0 96 | 97 | # TODO: set up the mstatus register 98 | #call mstatus_init 99 | 100 | call _start_boot_hart 101 | 102 | // These codes need to be implemented on a specific SoC. 103 | // .weak cache_as_ram 104 | forever: tail forever 105 | cache_as_ram: 106 | ret 107 | smp_pause: 108 | ret 109 | trap_entry: 110 | ret 111 | hls_init: 112 | ret 113 | .global abort 114 | abort: j abort 115 | 116 | .section ".bootblock.stack", "aw", %progbits 117 | _stack: 118 | .space 65536 119 | -------------------------------------------------------------------------------- /src/soc/sifive/fu540/src/init.S: -------------------------------------------------------------------------------- 1 | 2 | .globl _stack_ptr 3 | .section .rodata 4 | _stack_ptr: .word 0x08010000 5 | -------------------------------------------------------------------------------- /src/soc/sifive/fu540/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![deny(warnings)] 3 | 4 | pub mod clock; 5 | pub mod ctl; 6 | pub mod ddr; 7 | pub mod ddrregs; 8 | pub mod phy; 9 | pub mod reg; 10 | pub mod spi; 11 | pub mod ux00; 12 | 13 | use core::ptr; 14 | 15 | // TODO: There might be a better way to detect whether we are running in QEMU. 16 | pub fn is_qemu() -> bool { 17 | // On hardware, the instruction at 0x1008 is 'lw t1, -4(t0)'. 18 | unsafe { ptr::read_volatile(reg::QEMU_FLAG as *mut u32) == 0x02828613 } 19 | } 20 | -------------------------------------------------------------------------------- /src/soc/sifive/fu540/src/reg.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the coreboot project. 3 | * 4 | * Copyright (C) 2018 Jonathan Neuschäfer 5 | * 6 | * This program 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; version 2 of the License. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | */ 15 | 16 | pub const QEMU_FLAG: u32 = 0x00001008; 17 | pub const DTIM: u32 = 0x01000000; 18 | pub const CLINT: u32 = 0x02000000; 19 | pub const L2_LIM: u32 = 0x08000000; 20 | pub const UART0: u32 = 0x10010000; 21 | //pub const UART(x): u32 = (FU540_UART0 + 0x1000 * (x)); 22 | pub const PRCI: u32 = 0x10000000; 23 | pub const QSPI0: u32 = 0x10040000; 24 | pub const QSPI1: u32 = 0x10041000; 25 | pub const QSPI2: u32 = 0x10050000; 26 | pub const GPIO: u32 = 0x10060000; 27 | pub const OTP: u32 = 0x10070000; 28 | pub const PIN_CTRL: u32 = 0x10080000; 29 | pub const ETH_MAC: u32 = 0x10090000; 30 | pub const ETH_MGMT: u32 = 0x100a0000; 31 | pub const DDR_CTRL: u32 = 0x100b0000; 32 | pub const DDR_PHY: u32 = 0x100b2000; 33 | pub const DDR_BUS_BLOCKER: u32 = 0x100b8000; 34 | pub const DDR_MGMT: u32 = 0x100c0000; 35 | pub const QSPI0_FLASH: u32 = 0x20000000; 36 | pub const QSPI1_FLASH: u32 = 0x30000000; 37 | pub const DRAM: u32 = 0x80000000; 38 | pub const DDR_SIZE: u64 = 8 * 1024 * 1024 * 1024; 39 | 40 | // This is the only u64 in the entire spec. 41 | pub const MAX_DRAM: u64 = 0x2000000000; 42 | 43 | pub fn uart(i: u32) -> u32 { 44 | UART0 + 0x1000 * (i as u32) 45 | } 46 | -------------------------------------------------------------------------------- /src/soc/sifive/fu540/src/spi.rs: -------------------------------------------------------------------------------- 1 | use spi::*; 2 | 3 | pub const FU540_SPI_CONFIG: SiFiveSpiConfig = 4 | SiFiveSpiConfig { freq: 33_330_000, phase: SiFiveSpiPhase::SampleLeading, polarity: SiFiveSpiPolarity::InactiveLow, protocol: SiFiveSpiProtocol::Single, endianness: SiFiveSpiEndianness::BigEndian, bits_per_frame: 8 }; 5 | 6 | pub const FU540_SPI_MMAP_CONFIG: SiFiveSpiMmapConfig = 7 | SiFiveSpiMmapConfig { command_enable: true, address_len: 4, pad_count: 6, command_protocol: SiFiveSpiProtocol::Single, address_protocol: SiFiveSpiProtocol::Quad, data_protocol: SiFiveSpiProtocol::Quad, command_code: 0xec, pad_code: 0 }; 8 | -------------------------------------------------------------------------------- /src/vendorcode/fsp/coffeelake/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "fsp-coffeelake-sys" 3 | version = "0.1.0" 4 | authors = ["Oreboot Authors"] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | efi = "0.2.1" 9 | 10 | [build-dependencies] 11 | bindgen = "0.53.1" 12 | -------------------------------------------------------------------------------- /src/vendorcode/fsp/coffeelake/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_upper_case_globals)] 2 | #![allow(non_camel_case_types)] 3 | #![allow(non_snake_case)] 4 | 5 | // Types from the ffi crate are used instead of the generated ones. 6 | #[allow(unused_imports)] 7 | use efi::ffi::{BOOLEAN, CHAR16, CHAR8, EFI_GUID, EFI_GUID as GUID, INT16, INT32, INT64, INT8, UINT16, UINT32, UINT64, UINT8, UINTN}; 8 | 9 | include!(concat!(env!("OUT_DIR"), "/bindings.rs")); 10 | -------------------------------------------------------------------------------- /src/vendorcode/fsp/coffeelake/src/wrapper.h: -------------------------------------------------------------------------------- 1 | // These are the header files provided with Coffeelake FSP. 2 | // The order of these includes matters for building. 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | // This definition is missing from Coffeelake preventing GpioSampleDef.h from building. 11 | //typedef struct { 12 | // GPIO_PAD GpioPad; 13 | // GPIO_CONFIG GpioConfig; 14 | //} GPIO_INIT_CONFIG; 15 | //#include 16 | #include 17 | #include 18 | #include 19 | #include 20 | -------------------------------------------------------------------------------- /tools/bin2vmem/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "bin2vmem" 5 | version = "0.1.0" 6 | dependencies = [ 7 | "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", 8 | "getopts 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", 9 | ] 10 | 11 | [[package]] 12 | name = "byteorder" 13 | version = "1.3.2" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | 16 | [[package]] 17 | name = "getopts" 18 | version = "0.2.21" 19 | source = "registry+https://github.com/rust-lang/crates.io-index" 20 | dependencies = [ 21 | "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 22 | ] 23 | 24 | [[package]] 25 | name = "unicode-width" 26 | version = "0.1.7" 27 | source = "registry+https://github.com/rust-lang/crates.io-index" 28 | 29 | [metadata] 30 | "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" 31 | "checksum getopts 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" 32 | "checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" 33 | -------------------------------------------------------------------------------- /tools/bin2vmem/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bin2vmem" 3 | version = "0.1.0" 4 | authors = ["Patrick Mooney "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | byteorder = "1.3.2" 9 | getopts = "0.2.21" 10 | -------------------------------------------------------------------------------- /tools/bin2vmem/src/main.rs: -------------------------------------------------------------------------------- 1 | use byteorder::{ByteOrder, LittleEndian}; 2 | use getopts::Options; 3 | use std::io::{BufReader, BufWriter, Read, Write}; 4 | use std::{env, io, process}; 5 | 6 | /// Convert binary to Verilog VMEM format 7 | 8 | const DEFAULT_OFFSET: u32 = 0; 9 | // The original tool only output one word per line 10 | const DEFAULT_WIDTH: u32 = 1; 11 | 12 | struct Args { 13 | offset: u32, 14 | width: u32, 15 | } 16 | 17 | fn parse_u32(input: &str, field: &str, usage: &str) -> u32 { 18 | match input.parse::() { 19 | Ok(v) => v, 20 | Err(_e) => { 21 | eprintln!("{} must be valid number\n{}", field, usage); 22 | process::exit(1); 23 | } 24 | } 25 | } 26 | 27 | fn parse_args() -> Args { 28 | let args: Vec = env::args().collect(); 29 | let prog = args[0].clone(); 30 | let mut parsed_offset: u32 = DEFAULT_OFFSET; 31 | let mut parsed_width: u32 = DEFAULT_WIDTH; 32 | 33 | let mut opts = Options::new(); 34 | opts.optopt("o", "offset", "output offset", "OFFSET"); 35 | opts.optopt("w", "width", "output width in words", "WIDTH"); 36 | opts.optflag("h", "help", "show cmd help"); 37 | let usage = opts.short_usage(&prog); 38 | 39 | let matches = match opts.parse(&args[1..]) { 40 | Ok(m) => m, 41 | Err(f) => { 42 | eprintln!("{}\n{}", f, usage); 43 | process::exit(1); 44 | } 45 | }; 46 | if matches.opt_present("h") { 47 | println!("{}", usage); 48 | process::exit(0); 49 | } 50 | if let Some(opt) = matches.opt_str("o") { 51 | parsed_offset = parse_u32(&opt, "offset", &usage); 52 | } 53 | if let Some(opt) = matches.opt_str("w") { 54 | parsed_width = parse_u32(&opt, "width", &usage); 55 | if parsed_width < 1 { 56 | eprintln!("width cannot be zero\n{}", usage); 57 | process::exit(1); 58 | } 59 | } 60 | 61 | Args { offset: parsed_offset, width: parsed_width } 62 | } 63 | 64 | fn do_bin2vmem(offset: u32, width: u32, input: &mut R, output: &mut W) -> io::Result { 65 | let mut pos = offset; 66 | 67 | output.write_all("/* http://srecord.sourceforge.net/ */\n".as_bytes())?; 68 | loop { 69 | for n in 0..width { 70 | let mut buf = [0u8; 4]; 71 | let len = input.read(&mut buf)?; 72 | 73 | if len > 0 { 74 | let val = LittleEndian::read_u32(&buf); 75 | if n == 0 { 76 | write!(output, "@{:08X} {:08X}", pos, val)?; 77 | } else { 78 | write!(output, " {:08X}", val)?; 79 | } 80 | } else { 81 | if n != 0 { 82 | writeln!(output)?; 83 | } 84 | return Ok(pos); 85 | } 86 | pos += 1; 87 | } 88 | writeln!(output)?; 89 | } 90 | } 91 | 92 | fn main() { 93 | let args = parse_args(); 94 | let mut input = BufReader::new(io::stdin()); 95 | let mut output = BufWriter::new(io::stdout()); 96 | 97 | do_bin2vmem(args.offset, args.width, &mut input, &mut output).unwrap(); 98 | } 99 | 100 | #[cfg(test)] 101 | mod tests { 102 | use super::*; 103 | use std::io::BufReader; 104 | static EXAMPLE_RAW: &[u8] = include_bytes!("testdata/example.raw"); 105 | static EXAMPLE_VMEM: &str = include_str!("testdata/example.vmem"); 106 | const EXAMPLE_WIDTH: u32 = 7; 107 | 108 | #[test] 109 | fn basic_test() { 110 | let mut input = BufReader::new(EXAMPLE_RAW); 111 | let mut out_buf: Vec = Vec::with_capacity(EXAMPLE_VMEM.as_bytes().len()); 112 | 113 | let off = do_bin2vmem(DEFAULT_OFFSET, EXAMPLE_WIDTH, &mut input, &mut out_buf).unwrap(); 114 | assert_eq!(off as usize, EXAMPLE_RAW.len() / 4); 115 | 116 | let out_string = String::from_utf8(out_buf).unwrap(); 117 | let mut out_lines = out_string.lines(); 118 | let mut compare_lines = EXAMPLE_VMEM.lines(); 119 | loop { 120 | match (out_lines.next(), compare_lines.next()) { 121 | (Some(a), Some(b)) => { 122 | assert_eq!(a, b); 123 | } 124 | (Some(a), None) => { 125 | panic!("extra line {}", a); 126 | } 127 | (None, Some(b)) => { 128 | panic!("missing line {}", b); 129 | } 130 | (None, None) => { 131 | break; 132 | } 133 | } 134 | } 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /tools/bin2vmem/src/testdata/example.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orangecms/oreboot/e66c077413956bf4da78e855cda2c7b8cac0aa00/tools/bin2vmem/src/testdata/example.raw -------------------------------------------------------------------------------- /tools/layoutflash/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "layoutflash" 3 | version = "0.1.0" 4 | authors = ["Ryan O'Leary "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | device_tree = { path = "../../src/lib/device_tree" } 9 | model = { path = "../../src/drivers/model" } 10 | wrappers = { path = "../../src/drivers/wrappers" } 11 | clap = { git = "https://github.com/clap-rs/clap" } 12 | -------------------------------------------------------------------------------- /tools/layoutflash/src/main.rs: -------------------------------------------------------------------------------- 1 | use clap::Clap; 2 | use device_tree::{infer_type, Entry, FdtIterator, FdtReader, Type, MAX_NAME_SIZE}; 3 | use model::{Driver, Result}; 4 | use std::io; 5 | use std::io::{Seek, SeekFrom, Write}; 6 | use std::process::exit; 7 | use std::{ 8 | env, fs, 9 | path::{Path, PathBuf}, 10 | }; 11 | use wrappers::SliceReader; 12 | 13 | // TODO: Move this struct to lib so it can be used at runtime. 14 | #[derive(Default, Debug)] 15 | struct Area { 16 | description: String, 17 | compatible: String, 18 | // If not specified, it will be automatically computed based on previous areas (if this is 19 | // first area, we start with 0). 20 | offset: Option, 21 | size: u32, 22 | file: Option, 23 | } 24 | 25 | // TODO: Move to some common library. 26 | fn read_all(d: &dyn Driver) -> Vec { 27 | let mut v = Vec::new(); 28 | v.resize(MAX_NAME_SIZE, 0); 29 | // Safe to unwrap because SliceReader does not return an error. 30 | let size = d.pread(v.as_mut_slice(), 0).unwrap(); 31 | v.truncate(size); 32 | v 33 | } 34 | 35 | fn read_area_node(iter: &mut FdtIterator) -> Result { 36 | let mut area = Area { ..Default::default() }; 37 | while let Some(item) = iter.next()? { 38 | match item { 39 | Entry::StartNode { name: _ } => { 40 | iter.skip_node()?; 41 | } 42 | Entry::EndNode => return Ok(area), 43 | Entry::Property { name, value } => { 44 | let data = read_all(&value); 45 | match (name, infer_type(data.as_slice())) { 46 | ("description", Type::String(x)) => area.description = String::from(x), 47 | ("compatible", Type::String(x)) => area.compatible = String::from(x), 48 | ("offset", Type::U32(x)) => area.offset = Some(x), 49 | ("size", Type::U32(x)) => area.size = x, 50 | ("file", Type::String(x)) => area.file = Some(String::from(x)), 51 | (_, _) => {} 52 | } 53 | } 54 | } 55 | } 56 | Ok(area) 57 | } 58 | 59 | // TODO: Move this function to lib so it can be used at runtime. 60 | fn read_fixed_fdt(path: &Path) -> io::Result> { 61 | let data = match fs::read(path) { 62 | Err(e) => return Err(io::Error::new(e.kind(), format!("{}{}", "Could not open: ", path.display()))), 63 | Ok(data) => data, 64 | }; 65 | let driver = SliceReader::new(data.as_slice()); 66 | 67 | let mut areas = Vec::new(); 68 | let reader = FdtReader::new(&driver).unwrap(); 69 | let mut iter = reader.walk(); 70 | while let Some(item) = iter.next().unwrap() { 71 | match item { 72 | Entry::StartNode { name } => { 73 | if name.starts_with("area@") { 74 | areas.push(read_area_node(&mut iter).unwrap()); 75 | } 76 | } 77 | Entry::EndNode => continue, 78 | Entry::Property { name: _, value: _ } => continue, 79 | } 80 | } 81 | 82 | Ok(areas) 83 | } 84 | 85 | // This method assumes that areas are sorted by offset. 86 | fn layout_flash(path: &Path, areas: &mut [Area]) -> io::Result<()> { 87 | areas.sort_unstable_by_key(|a| a.offset); 88 | let mut f = fs::File::create(path)?; 89 | let mut last_area_end = 0; 90 | for a in areas { 91 | let offset = match a.offset { 92 | Some(x) => x, 93 | None => last_area_end, 94 | }; 95 | if offset < last_area_end { 96 | return Err(io::Error::new(io::ErrorKind::InvalidData, format!("Areas are overlapping, last area finished at offset {}, next area '{}' starts at {}", last_area_end, a.description, offset))); 97 | } 98 | last_area_end = offset + a.size; 99 | 100 | // First fill with 0xff. 101 | let mut v = Vec::new(); 102 | v.resize(a.size as usize, 0xff); 103 | f.seek(SeekFrom::Start(offset as u64))?; 104 | f.write_all(&v)?; 105 | 106 | // If a file is specified, write the file. 107 | if let Some(path) = &a.file { 108 | let mut path = path.to_string(); 109 | // Allow environment variables in the path. 110 | for (key, value) in env::vars() { 111 | path = str::replace(&path, &format!("$({})", key), &value); 112 | } 113 | 114 | // If the path is an unused environment variable, skip it. 115 | if path.starts_with("$(") && path.ends_with(')') { 116 | continue; 117 | } 118 | 119 | f.seek(SeekFrom::Start(offset as u64))?; 120 | let data = match fs::read(&path) { 121 | Err(e) => return Err(io::Error::new(e.kind(), format!("Could not open: {}", path))), 122 | Ok(data) => data, 123 | }; 124 | if data.len() > a.size as usize { 125 | return Err(io::Error::new(io::ErrorKind::InvalidData, format!("File {} is too big to fit into the flash area, file size: {}, area size: {}", path, data.len(), a.size))); 126 | } 127 | f.write_all(&data)?; 128 | } 129 | } 130 | Ok(()) 131 | } 132 | 133 | #[derive(Clap)] 134 | #[clap(version)] 135 | struct Opts { 136 | /// The path to the firmware device tree file 137 | in_fdt: PathBuf, 138 | #[clap(parse(from_os_str))] 139 | /// The output path for the firmware 140 | out_firmware: PathBuf, 141 | } 142 | 143 | fn main() { 144 | let args = Opts::parse(); 145 | 146 | read_fixed_fdt(&args.in_fdt).and_then(|mut areas| layout_flash(&args.out_firmware, &mut areas)).unwrap_or_else(|err| { 147 | eprintln!("failed: {}", err); 148 | exit(1); 149 | }); 150 | } 151 | -------------------------------------------------------------------------------- /tools/layoutflash/src/testdata/test.dtb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orangecms/oreboot/e66c077413956bf4da78e855cda2c7b8cac0aa00/tools/layoutflash/src/testdata/test.dtb -------------------------------------------------------------------------------- /tools/layoutflash/src/testdata/test.dts: -------------------------------------------------------------------------------- 1 | /dts-v1/; 2 | 3 | / { 4 | #address-cells = <1>; 5 | #size-cells = <1>; 6 | 7 | flash-info { 8 | compatible = "ore-flashinfo"; 9 | board-name = "QEMU armv7"; 10 | category = "emulation"; 11 | board-url = "http://wiki.qemu.org/Main_Page"; 12 | areas { 13 | area@0 { 14 | description = "Boot Blob"; 15 | compatible = "ore-bootblob"; 16 | offset = <0x0>; 17 | size = <0x80000>; // 512KiB 18 | }; 19 | area@1 { 20 | description = "Fixed DTFS"; 21 | compatible = "ore-dtfs"; 22 | offset = <0x80000>; 23 | size = <0x80000>; // 512KiB 24 | file = "testdata/test.dtb"; 25 | }; 26 | area@2 { 27 | description = "NVRAM A"; 28 | compatible = "ore-nvram"; 29 | half = <0>; 30 | offset = <0x100000>; 31 | size = <0x80000>; // 512KiB 32 | }; 33 | area@3 { 34 | description = "NVRAM B"; 35 | compatible = "ore-nvram"; 36 | half = <1>; 37 | offset = <0x180000>; 38 | size = <0x80000>; // 512KiB 39 | }; 40 | area@4 { 41 | description = "RomPayload DTFS A"; 42 | compatible = "ore-rompayload"; 43 | half = <0>; 44 | offset = <0x200000>; 45 | size = <0x100000>; // 1MiB 46 | }; 47 | area@5 { 48 | description = "RomPayload DTFS B"; 49 | compatible = "ore-rompayload"; 50 | half = <1>; 51 | offset = <0x300000>; 52 | size = <0x100000>; // 1MiB 53 | }; 54 | area@6 { 55 | description = "RamPayload DTFS A"; 56 | compatible = "ore-rampayload"; 57 | half = <0>; 58 | offset = <0x400000>; 59 | size = <0x600000>; // 6MiB 60 | }; 61 | area@7 { 62 | description = "RamPayload DTFS B"; 63 | compatible = "ore-rampayload"; 64 | half = <1>; 65 | offset = <0xa00000>; 66 | size = <0x600000>; // 6MiB 67 | }; 68 | }; 69 | }; 70 | }; 71 | -------------------------------------------------------------------------------- /tools/opentitanregisters/pinmux.hjson: -------------------------------------------------------------------------------- 1 | // Copyright lowRISC contributors. 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | // SPDX-License-Identifier: Apache-2.0 4 | // 5 | # PINMUX register template 6 | # 7 | # Parameter (given by Python tool) 8 | # - n_periph_in: Number of peripheral inputs 9 | # - n_periph_out: Number of peripheral outputs 10 | # - n_mio_pads: Number of muxed IO pads 11 | # 12 | { 13 | name: "PINMUX", 14 | clock_primary: "clk_i", 15 | bus_device: "tlul", 16 | regwidth: "32", 17 | param_list: [ 18 | { name: "NPeriphIn", 19 | desc: "Number of peripheral inputs", 20 | type: "int", 21 | default: "16", 22 | local: "true" 23 | }, 24 | { name: "NPeriphOut", 25 | desc: "Number of peripheral outputs", 26 | type: "int", 27 | default: "16", 28 | local: "true" 29 | }, 30 | { name: "NMioPads", 31 | desc: "Number of muxed IO pads", 32 | type: "int", 33 | default: "8", 34 | local: "true" 35 | }, 36 | ], 37 | registers: [ 38 | { name: "REGEN", 39 | desc: ''' 40 | Register write enable for all control registers. 41 | ''', 42 | swaccess: "rw0c", 43 | hwaccess: "none", 44 | fields: [ 45 | { 46 | bits: "0", 47 | desc: ''' When true, all configuration registers can be modified. 48 | When false, they become read-only. Defaults true, write zero to clear. 49 | ''' 50 | resval: 1, 51 | }, 52 | ] 53 | }, 54 | # inputs 55 | { multireg: { name: "PERIPH_INSEL", 56 | desc: "Mux select for peripheral inputs.", 57 | count: "NPeriphIn", 58 | swaccess: "rw", 59 | hwaccess: "hro", 60 | regwen: "REGEN", 61 | cname: "IN", 62 | fields: [ 63 | { bits: "3:0", 64 | name: "IN", 65 | desc: ''' 66 | 0: tie constantly to zero, 1: tie constantly to 1. 67 | >=2: MIO pads (i.e., add 2 to the native MIO pad index). 68 | ''' 69 | resval: 0 70 | } 71 | ] 72 | } 73 | }, 74 | # outputs 75 | { multireg: { name: "MIO_OUTSEL", 76 | desc: "Mux select for MIO outputs.", 77 | count: "NMioPads", 78 | swaccess: "rw", 79 | hwaccess: "hro", 80 | regwen: "REGEN", 81 | cname: "OUT", 82 | fields: [ 83 | { bits: "4:0", 84 | name: "OUT", 85 | desc: ''' 86 | 0: tie constantly to zero, 1: tie constantly to 1. 2: high-Z 87 | >=3: peripheral outputs (i.e., add 3 to the native peripheral pad index). 88 | ''' 89 | resval: 2 90 | } 91 | ] 92 | } 93 | }, 94 | ], 95 | } 96 | -------------------------------------------------------------------------------- /tools/soc/sifive/fu540/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS=-nostdinc -nostdlib -ffreestanding --static -fPIC 2 | 3 | serialdebug.elf: serialdebug.S 4 | riscv64-linux-gnu-gcc ${CFLAGS} -o serialdebug.elf serialdebug.S -T link.ld 5 | 6 | serialdebug: serialdebug.elf 7 | riscv64-linux-gnu-objcopy --remove-section='.note*' -O binary serialdebug.elf serialdebug 8 | 9 | qemu: serialdebug.elf 10 | qemu-system-riscv64 -machine sifive_u -bios serialdebug.elf -net none -nographic 11 | 12 | objdump: serialdebug.elf 13 | riscv64-linux-gnu-objdump -D serialdebug.elf 14 | 15 | clean: 16 | rm -f serialdebug serialdebug.elf 17 | 18 | cleanrom: serialdebug 19 | dd bs=32M count=1 if=/dev/zero | tr '\000' '\377' > 32m 20 | cat serialdebug 32m > bigrom 21 | dd of=rom bs=32M count=1 if=bigrom 22 | 23 | writerom: rom 24 | flashrom -w rom -p dediprog 25 | 26 | rom: serialdebug hifiverom 27 | cp hifiverom rom 28 | dd of=rom if=serialdebug conv=notrunc 29 | 30 | hifiverom: 31 | flashrom -r hifiverom -p dediprog 32 | -------------------------------------------------------------------------------- /tools/soc/sifive/fu540/link.ld: -------------------------------------------------------------------------------- 1 | SECTIONS 2 | { 3 | . = 0x80000000; 4 | .text : 5 | { 6 | KEEP(*(.text .text.*)); 7 | } 8 | 9 | /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) } 10 | } 11 | -------------------------------------------------------------------------------- /tools/soc/sifive/fu540/serialdebug.S: -------------------------------------------------------------------------------- 1 | // Prints A to serial forever. 2 | 3 | #define BASE 0x10010000 4 | #define TD (BASE + 0x0) 5 | #define TXC (BASE + 0x8) 6 | 7 | .global _start 8 | _start: 9 | li t0, TXC 10 | lw t1, 0(t0) 11 | ori t1, t1, 0x1 12 | sw t1, 0(t0) 13 | loop: 14 | li t0, TD 15 | li t1, 'A' 16 | sw t1, 0(t0) 17 | jal loop 18 | --------------------------------------------------------------------------------