# Bootloader restore

**URL:** https://forums.sifive.com/t/bootloader-restore/2429
**Category:** HiFive1 Rev B
**Created:** [June 1, 2019, 7:19pm UTC](https://forums.sifive.com/t/bootloader-restore/2429 "2019-06-01T19:19:17Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![Almindor](https://sea2.discourse-cdn.com/flex020/user_avatar/forums.sifive.com/almindor/32/662_2.png) [@Almindor](https://forums.sifive.com/u/Almindor)
#### Post date: [June 1, 2019, 7:19pm UTC](https://forums.sifive.com/t/bootloader-restore/2429/1 "2019-06-01T19:19:17Z")

</div>

I’m working with hifive1-revB using rust and have just learned about the bootloader recovery “pre-main” piece of code that is inserted as part of metal/freedom-sdk programs.

Rust doesn’t make use of this by default and override memory at 0x20000000 meaning I lost this “bootloader”. My board is fine and I can flash in rust programs but because of how the metal ones work, I can’t make them work because they only override memory starting at 0x20010000 meaning “after” the rust code. Result is that the rust code still runs after flash & restart using the C code.

Is there any way to get this bootloader code so I can flash it back in? I’ll make rust think memory starts at 0x20010000 which should hopefully avoid this override in the future.

---

<div class="post-metadata">

### Author: ![bruce](https://sea2.discourse-cdn.com/flex020/user_avatar/forums.sifive.com/bruce/32/452_2.png) [@bruce](https://forums.sifive.com/u/bruce)
#### Post date: [June 1, 2019, 11:30pm UTC](https://forums.sifive.com/t/bootloader-restore/2429/2 "2019-06-01T23:30:43Z")

</div>

This is a very dangerous condition, because it means if your Rust code does something sufficiently bad then it can get into a state where the JLINK can not communicate with the CPU to load new programs.

An example of something sufficiently bad would be turning off the clock, or setting it to a speed the board can’t run at. Or things such as a trap or interrupt happening without an appropriate and correct trap handler installed.

The bootloader code used on the original HiFive1 is here:

> <https://github.com/sifive/freedom-e-sdk/blob/v1_0/software/double_tap_dontboot/double_tap_dontboot.c>

I don’t know what code is used on the Rev B. I don’t know of any reason this code would not work, other than the obvious one that FINAL\_ADDRESS needs changing to something that is inside the small flash the Rev B has (normally 0x2001000, as you mention).

If you wanted to, and you never wanted to run anything except Rust binaries, you could simply include (a translation of) this code at the start of each Rust binary.

---

<div class="post-metadata">

### Author: ![Almindor](https://sea2.discourse-cdn.com/flex020/user_avatar/forums.sifive.com/almindor/32/662_2.png) [@Almindor](https://forums.sifive.com/u/Almindor)
#### Post date: [June 2, 2019, 1:23am UTC](https://forums.sifive.com/t/bootloader-restore/2429/3 "2019-06-02T01:23:30Z")

</div>

Thanks. I suppose if I manage to flash the (fixed dest address) version of this over and coerce Rust to use 0x20010000 starting address it should “just work”.

Question is, how do I flash this to 0x20000000 given [this comment](https://github.com/sifive/freedom-e-sdk/blob/v1_0/software/double_tap_dontboot/double_tap_dontboot.c#L12-L16).

---

<div class="post-metadata">

### Author: ![bruce](https://sea2.discourse-cdn.com/flex020/user_avatar/forums.sifive.com/bruce/32/452_2.png) [@bruce](https://forums.sifive.com/u/bruce)
#### Post date: [June 2, 2019, 1:36am UTC](https://forums.sifive.com/t/bootloader-restore/2429/4 "2019-06-02T01:36:22Z")

</div>

If you (in the v1\_0 branch) make the following temporary patch:

```
--- a/bsp/env/freedom-e300-hifive1/flash.lds
+++ b/bsp/env/freedom-e300-hifive1/flash.lds
@@ -4,7 +4,7 @@ ENTRY( _start )
 
 MEMORY
 {
- flash (rxai!w) : ORIGIN = 0x20400000, LENGTH = 512M
+ flash (rxai!w) : ORIGIN = 0x20000000, LENGTH = 512M
   ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 16K
 }

```

Then when you do “make software PROGRAM=double\_tap\_dontboot” then it will be linked for 0x20000000.

The v1\_0 “make upload” won’t work for the RevB, but you can extract the elf file to a hex file and flash that.

Note that this is NOT TESTED but I don’t think there is any incompatibility between the FE310-G000 and FE310-G002 that would stop it working.

I’m trying to get a tested and supported solution to this. It will probably consist of a hex file that can be simply downloaded and copied onto the USB drive.

---

<div class="post-metadata">

### Author: ![Almindor](https://sea2.discourse-cdn.com/flex020/user_avatar/forums.sifive.com/almindor/32/662_2.png) [@Almindor](https://forums.sifive.com/u/Almindor)
#### Post date: [June 2, 2019, 1:40am UTC](https://forums.sifive.com/t/bootloader-restore/2429/5 "2019-06-02T01:40:45Z")

</div>

Thanks! I’ll probably wait for the tested solution.

In the meantime I’m asking the rust guys to see if there’s maybe something like this rescue “main-main” written in rust anywhere yet. If not it might be an interesting project to tackle at some point.

---

<div class="post-metadata">

### Author: ![Markis](https://avatars.discourse-cdn.com/v4/letter/m/258eb7/32.png) [@Markis](https://forums.sifive.com/u/Markis)
#### Post date: [June 2, 2019, 7:45am UTC](https://forums.sifive.com/t/bootloader-restore/2429/6 "2019-06-02T07:45:01Z")

</div>

In case you need it, I dumped the original bootloader in a .bin file. It can be easily loaded using Jlink/JFlash. (If it still responds)

Edit: Link  
[https://1drv.ms/u/s!AgAu-o-Onwezo01wyQDOJSn\_lRZa](https://1drv.ms/u/s!AgAu-o-Onwezo01wyQDOJSn_lRZa)

---

<div class="post-metadata">

### Author: ![bruce](https://sea2.discourse-cdn.com/flex020/user_avatar/forums.sifive.com/bruce/32/452_2.png) [@bruce](https://forums.sifive.com/u/bruce)
#### Post date: [June 2, 2019, 7:48am UTC](https://forums.sifive.com/t/bootloader-restore/2429/7 "2019-06-02T07:48:36Z")

</div>

I’ve just got hold of the hex file used to flash the production units. I’ve uploaded it temporarily at

[http://hoult.org/hifive1\_revb\_bootloader.hex](http://hoult.org/hifive1_revb_bootloader.hex)

We’ll find somewhere to put it permanently … probably linked from the product page I think.

I haven’t tested it myself yet. You might like to compare it to your .bin file (which you haven’t given a link to)

---

<div class="post-metadata">

### Author: ![Markis](https://avatars.discourse-cdn.com/v4/letter/m/258eb7/32.png) [@Markis](https://forums.sifive.com/u/Markis)
#### Post date: [June 2, 2019, 8:23am UTC](https://forums.sifive.com/t/bootloader-restore/2429/8 "2019-06-02T08:23:10Z")

</div>

I converted the .hex to a .bin file and ran checksum on my binary and the one generated. They are indeed the same.

---

<div class="post-metadata">

### Author: ![Almindor](https://sea2.discourse-cdn.com/flex020/user_avatar/forums.sifive.com/almindor/32/662_2.png) [@Almindor](https://forums.sifive.com/u/Almindor)
#### Post date: [June 2, 2019, 2:20pm UTC](https://forums.sifive.com/t/bootloader-restore/2429/9 "2019-06-02T14:20:03Z")

</div>

Thanks guys! I just flashed the hex file from Bruce and it worked fine! I get the green blink on start and it went back to my last “C” program (sifive-welcome) since I guess that was still sitting up in the flash memory.

I also found out that the proper rust setup uses .text sections correctly, but because I followed a real barebones guide and just used MEMORY with flash on 0x20000000 I overrode the bootloader.

The actual way to do this is part of the hifive1 crate at [https://github.com/riscv-rust/hifive1/blob/master/memory-hifive1-revb.x](https://github.com/riscv-rust/hifive1/blob/master/memory-hifive1-revb.x) which does skip to 0x20010000 to keep the bootloader.

I followed a guide (which sadly I can’t find a link to again) that described how to setup a bare bones main in great detail. Really good learning experience but they just used 0x20000000 directly.

---

<div class="post-metadata">

### Author: ![Almindor](https://sea2.discourse-cdn.com/flex020/user_avatar/forums.sifive.com/almindor/32/662_2.png) [@Almindor](https://forums.sifive.com/u/Almindor)
#### Post date: [June 5, 2019, 4:05am UTC](https://forums.sifive.com/t/bootloader-restore/2429/10 "2019-06-05T04:05:10Z")

</div>

Would it be possible to get the source code to the revB bootloader? I’m getting strange behavior where any kind of “write” operation (except for serial) seems to cause it to stop working. It works fine “direct” (if I risk it and go 0x20000000 again) and I’m wondering if it could be aborting/stopping due to say not being in machine mode or something because the bootloader set it to umode or such.

---

<div class="post-metadata">

### Author: ![bruce](https://sea2.discourse-cdn.com/flex020/user_avatar/forums.sifive.com/bruce/32/452_2.png) [@bruce](https://forums.sifive.com/u/bruce)
#### Post date: [June 5, 2019, 4:11am UTC](https://forums.sifive.com/t/bootloader-restore/2429/11 "2019-06-05T04:11:32Z")

</div>

What do you mean by “write operation”?

The bootloader certainly shouldn’t be doing any messing with PMP or switching to User mode, but unfortunately I don’t have source code for it.

---

<div class="post-metadata">

### Author: ![Almindor](https://sea2.discourse-cdn.com/flex020/user_avatar/forums.sifive.com/almindor/32/662_2.png) [@Almindor](https://forums.sifive.com/u/Almindor)
#### Post date: [June 5, 2019, 4:56am UTC](https://forums.sifive.com/t/bootloader-restore/2429/12 "2019-06-05T04:56:05Z")

</div>

Well the odd thing is that if I just use serial (e.g. “hello world” writes) it all works. As soon as I try to set a LED, GPIO or even read mstatus or friends it stops working.

I’ve confirmed that the same program works if I do the override 0x20000000 so I’m wondering if something funny is going on due to what the bootloader does.

I’ll try and get any of those things working with C code to see if I get the same outcome.

---

<div class="post-metadata">

### Author: ![Almindor](https://sea2.discourse-cdn.com/flex020/user_avatar/forums.sifive.com/almindor/32/662_2.png) [@Almindor](https://forums.sifive.com/u/Almindor)
#### Post date: [June 5, 2019, 4:24pm UTC](https://forums.sifive.com/t/bootloader-restore/2429/13 "2019-06-05T16:24:54Z")

</div>

Figured this out. It seems to be something wrong with clock setting in the rust code. Everything works fine both with or without the bootloader as long as the clock is set to full 320.

If I lower the clock things break but only behind the bootloader. We suspect it’s a bug in the clock setup in rust tho, will ping back if we figure this out. I forgot I even lowered the clock in this program so I was looking everywhere but 🙂

---

<div class="post-metadata">

### Author: ![cat](https://sea2.discourse-cdn.com/flex020/user_avatar/forums.sifive.com/cat/32/688_2.png) [@cat](https://forums.sifive.com/u/cat)
#### Post date: [June 6, 2019, 12:50am UTC](https://forums.sifive.com/t/bootloader-restore/2429/14 "2019-06-06T00:50:50Z")

</div>

Hi,  
I also managed to overwrite my bootloader trying to load a rust program so thanks for doing it before me 🙂 Anyway, I’m trying to use the hifive1 crate, but my programs are always trying to write to “Entry point address: 0x20400000”.

Do you have a repo with a project I can look at or can you explain how I can get the program to load into the correct addresses?

Thanks!

---

<div class="post-metadata">

### Author: ![Almindor](https://sea2.discourse-cdn.com/flex020/user_avatar/forums.sifive.com/almindor/32/662_2.png) [@Almindor](https://forums.sifive.com/u/Almindor)
#### Post date: [June 6, 2019, 1:51am UTC](https://forums.sifive.com/t/bootloader-restore/2429/15 "2019-06-06T01:51:31Z")

</div>

The rust situation is a bit of a pickle atm. Disasm is working on getting it working using `.cargo/config` that specifies the memory layout provided by a new version of the `hifive1` crate and a patched version of the `rust-rt` crate. You can find that all in his [workspace here](https://github.com/Disasm/hifive1-revb-workspace).

NOTE: all those repos are modified, so if you get the originals/master branches it won’t work.

You can also use the current versions of all the crates and get the same result by providing your own `memory.x` file with

```auto
{
	RAM : ORIGIN = 0x80000000, LENGTH = 0x4000
	FLASH : ORIGIN = 0x20010000, LENGTH = 0x6a120
}

```

that will force it to go to `0x20010000` as a workaround for now. The way this works is that the `risc-rt` crate provides a `link.x` with all the section definitions, but it expects a `INCLUDE memory.x` on linktime in there. By providing one with the right offset you override the default old-version `hifive1` one. That’s how I do it atm. but I don’t have any repo published yet.

You need the `memory.x` file to be placed in the right build directory by creating a `build.rs` file in your project root with:

```auto
use std::{env, fs};
use std::path::PathBuf;
use std::io::Write;

fn main() {
    // Put the linker script somewhere the linker can find it
    let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
    println!("cargo:rustc-link-search={}", out_dir.display());

    fs::File::create(out_dir.join("memory.x")).unwrap()
        .write_all(include_bytes!("memory.x")).unwrap();
    println!("cargo:rerun-if-changed=memory.x");
}

```

WARNING: make sure to check the final binary (elf) with riscv objdump to ensure it was linked properly and points to `0x20010000` as entrypoint before attempting an upload, otherwise you’ll wipe the bootloader again 😃

Hope this helps for now, I plan to put some things together and start a blog series about all the little tidbits as I go along.

---

<div class="post-metadata">

### Author: ![Disasm](https://sea2.discourse-cdn.com/flex020/user_avatar/forums.sifive.com/disasm/32/690_2.png) [@Disasm](https://forums.sifive.com/u/Disasm)
#### Post date: [June 6, 2019, 7:21am UTC](https://forums.sifive.com/t/bootloader-restore/2429/16 "2019-06-06T07:21:58Z")

</div>

@cat, what board are you using? HiFive1 and HiFive1 RevB use different entry addresses.

---

<div class="post-metadata">

### Author: ![cat](https://sea2.discourse-cdn.com/flex020/user_avatar/forums.sifive.com/cat/32/688_2.png) [@cat](https://forums.sifive.com/u/cat)
#### Post date: [June 6, 2019, 9:08am UTC](https://forums.sifive.com/t/bootloader-restore/2429/17 "2019-06-06T09:08:15Z")

</div>

Thanks a bunch! woo my program works!  
Okay so for others out there, what I’ve done might not be correct but it worked, so feel free to try it 🙂  
my memory.x file contains what almindor wrote but I put MEMORY on the first line above the {  
i add the build.rs file like suggested  
I add build = “build.rs” to my Cargo.toml  
I use this .cargo/config  
[target.riscv32imac-unknown-none-elf]  
runner = ‘riscv64-linux-gnu-gdb -q’  
rustflags = [  
“-C”, “link-arg=-Tlink.x”,  
]

[build]  
target = “riscv32imac-unknown-none-elf”

I build with  
`cargo build`  
I do  
`readelf -h /path/to/program`  
it shows me this line:  
`Entry point address: 0x20010000` So that’s good.

In one terminal I connect with `JLinkGDBServerCLExe -device FE310`  
you have to use sudo if you haven’t set up permissions from the sifive quickstart guide  
I’m on arch and it doesn’t have riscv64-unknown-elf-gdb in the main repository so I use riscv64-linux-gnu-gdb instead to run and it seems to work.  
so in another terminal:  
`$ riscv64-linux-gnu-gdb -q /path/to/program (if you setup the .cargo config just do cargo run) (gdb) target remote :2331 (or port listed by jlink) (gdb) load (gdb) c`

@Disasm yeah rev-b. Sorry I was writing at 2 am or something after 10+ hours at work, I could have been a bit more detailed 🙂

[If some formatting is messed up, I apologize.]

---

<div class="post-metadata">

### Author: ![Almindor](https://sea2.discourse-cdn.com/flex020/user_avatar/forums.sifive.com/almindor/32/662_2.png) [@Almindor](https://forums.sifive.com/u/Almindor)
#### Post date: [June 6, 2019, 5:11pm UTC](https://forums.sifive.com/t/bootloader-restore/2429/18 "2019-06-06T17:11:10Z")

</div>

Good news everyone! Disasm just updated the hifive1 and e310x crates. You don’t need any hacks anymore to get basic linking working.

Just use version `0.5.0` of `hifive1` crate and specify the board with the feature, e.g. in Cargo.toml

```auto
hifive1 = { version = "0.5.0", features = ["board-hifive1-revb"] }

```

Of course you still need the other jazz like `riscv-rt` etc. but this means now that you don’t need a custom build.rs or memory.x definitions. Always doublecheck with objdump/readelf before uploading tho!

---

<div class="post-metadata">

### Author: ![edsut](https://avatars.discourse-cdn.com/v4/letter/e/73ab20/32.png) [@edsut](https://forums.sifive.com/u/edsut)
#### Post date: [March 8, 2023, 12:48pm UTC](https://forums.sifive.com/t/bootloader-restore/2429/19 "2023-03-08T12:48:42Z")

</div>

@bruce Yea, I know this is an old post… Hoping you’re still listening to this forum…  
I am just getting started with a HiFive1 RevB board (and RISC-V) and would prefer not to “brick” it; however I do want to overwrite the double-tap bootloader just to be sure that I know how to boot this device from scratch. That being said; I have two questions that for some reason are not getting answered:

1. Are you saying that even the Segger-OB connected to the FE310-G002’s JTAG pins can’t recover a bricked SOC?
2. I can’t find the boot code for RevB (not sure why), so is it safe to assume that the double\_tap\_dontboot code on github branch v1\_0 will safely boot the RevB board?  
Thanks,

---

<div class="post-metadata">

### Author: ![pds](https://avatars.discourse-cdn.com/v4/letter/p/8edcca/32.png) [@pds](https://forums.sifive.com/u/pds)
#### Post date: [March 10, 2023, 8:17pm UTC](https://forums.sifive.com/t/bootloader-restore/2429/20 "2023-03-10T20:17:38Z")

</div>

As @Almindor notes above, [_It seems to be something wrong with clock setting_](https://forums.sifive.com/t/bootloader-restore/2429/12), indeed the clock path diagram in Figure 3 of Chapter 6 of the [FE310-G002 Manual](https://sifive.cdn.prismic.io/sifive/034760b5-ac6a-4b1c-911c-f4148bb2c4a5_fe310-g002-v1p5.pdf) is drawn with a few significant mistakes, thus giving very confusing observations when programming and/or changing configurations of the clock path.

See [Understanding the PRCI clock path](https://forums.sifive.com/t/understanding-the-prci-clock-path/5827/2) or the description and examples in the GitHub repo at [Demonstrating PRCI](https://github.com/psherman42/Demonstrating-PRCI).

Otherwise @edsut, there’s not much need to worry about bricking the FE310 SoC when removing the doubletap bootloader or replacing any of the code in FLASH at 0x2000 0000 upwards. See discussion at

> [@Is there C boot code (source) for RevB02 hardware?](https://forums.sifive.com/t/is-there-c-boot-code-source-for-revb02-hardware/5987/5):
>
> Good thinking @edsut. the U3 (Segger) chip is optional; you can bypass it by not connecting the U5 (micro-USB) and instead supplying power to J7 (barrel connector). Your JTAG signals are available on J1 (10-pin, 2x5, might not be populated) in the standard fashion. I recommend OpenOCD with an Olimex or similar FT(2)232-based device, or even bitbang from a Raspberry PI. Don’t confuse the doubletap bootloader (DTB) in the FLASH area (0x2000 0000) with the flash recovery mechanism (FRM) library in…
