Update WEEK06

This commit is contained in:
Kevin Thomas
2026-05-30 16:50:15 -04:00
parent af0d84f9cc
commit f22ef2907e
21 changed files with 1554 additions and 425 deletions
+42 -45
View File
@@ -1,6 +1,6 @@
# Week 3: Embedded System Analysis: Understanding the RP2350 Architecture w/ Comprehensive Firmware Analysis
## 🎯 What You'll Learn This Week
## What You'll Learn This Week
By the end of this tutorial, you will be able to:
- Understand how the RP2350 boots from the on-chip bootrom
@@ -12,7 +12,7 @@ By the end of this tutorial, you will be able to:
- Use Ghidra to statically analyze the boot sequence
- Understand the difference between Thumb mode addressing and actual addresses
## 🔄 Review from Weeks 1-2
## Review from Weeks 1-2
This week builds on your GDB and Ghidra skills from previous weeks:
- **GDB Commands** (`x`, `b`, `c`, `si`, `disas`, `i r`) - We'll use all of these to trace the boot process
- **Memory Layout** (Flash at `0x10000000`, RAM at `0x20000000`) - Understanding where code and data live
@@ -154,7 +154,7 @@ Here's what it looks like in the Pico SDK:
Use these commands to view the IMAGE_DEF bytes directly in the ELF:
```powershell
```cmd
arm-none-eabi-objdump -s --start-address=0x1000013c --stop-address=0x10000150 build/0x0001_hello-world.elf
arm-none-eabi-objdump -s --start-address=0x10000130 --stop-address=0x10000154 build/0x0001_hello-world.elf
arm-none-eabi-gdb build/0x0001_hello-world.elf -ex "x/20bx 0x1000013c" -ex quit
@@ -202,7 +202,7 @@ assuming a fixed address.
## Part 3: Understanding XIP (Execute In Place)
> 🔄 **REVIEW:** In Week 1, we learned that our code lives at `0x10000000` in flash memory. We used `x/1000i 0x10000000` to find our `main` function. Now we'll understand WHY code is at this address!
> **REVIEW:** In Week 1, we learned that our code lives at `0x10000000` in flash memory. We used `x/1000i 0x10000000` to find our `main` function. Now we'll understand WHY code is at this address!
### What is XIP?
@@ -346,7 +346,7 @@ This value (`0x20082000`) is what we see at offset `0x00` in the vector table!
## Part 6: Setting Up Your Environment (GDB - Dynamic Analysis)
> 🔄 **REVIEW:** This setup is identical to Weeks 1-2. If you need a refresher on OpenOCD and GDB connection, refer back to Week 1 Part 4 or Week 2 Part 5.
> **REVIEW:** This setup is identical to Weeks 1-2. If you need a refresher on OpenOCD and GDB connection, refer back to Week 1 Part 4 or Week 2 Part 5.
### Prerequisites
@@ -361,17 +361,13 @@ Before we start, make sure you have:
**Terminal 1 - Start OpenOCD:**
```powershell
openocd ^
-s "C:\Users\assem.KEVINTHOMAS\.pico-sdk\openocd\0.12.0+dev\scripts" ^
-f interface/cmsis-dap.cfg ^
-f target/rp2350.cfg ^
-c "adapter speed 5000"
```cmd
openocd -s "%USERPROFILE%\.pico-sdk\openocd\0.12.0+dev\scripts" -f interface/cmsis-dap.cfg -f target/rp2350.cfg -c "adapter speed 5000"
```
**Terminal 2 - Start GDB:**
```powershell
```cmd
arm-none-eabi-gdb build\0x0001_hello-world.elf
```
@@ -384,9 +380,9 @@ arm-none-eabi-gdb build\0x0001_hello-world.elf
---
## 🔬 Part 7: Hands-On GDB Tutorial - Examining the Vector Table
## Part 7: Hands-On GDB Tutorial - Examining the Vector Table
> 🔄 **REVIEW:** We're using the same `x` (examine) command from Week 1. Remember: `x/Nx` shows N hex values, `x/Ni` shows N instructions, `x/s` shows strings.
> **REVIEW:** We're using the same `x` (examine) command from Week 1. Remember: `x/Nx` shows N hex values, `x/Ni` shows N instructions, `x/s` shows strings.
### Step 1: Examine the Vector Table
@@ -411,7 +407,7 @@ Let's look at the first 4 entries of the vector table at `0x10000000`:
### Step 2: Understanding What We See
> 🔄 **REVIEW:** In Weeks 1-2, we saw both `sp = 0x20082000` at the clean breakpoint at `main` and lower values like `0x20081fc8` or `0x20081ff8` after additional stack activity. Here we are looking at the *initial* stack pointer from the vector table before any code runs.
> **REVIEW:** In Weeks 1-2, we saw both `sp = 0x20082000` at the clean breakpoint at `main` and lower values like `0x20081fc8` or `0x20081ff8` after additional stack activity. Here we are looking at the *initial* stack pointer from the vector table before any code runs.
Let's decode each value:
@@ -443,13 +439,13 @@ Let's confirm our math by examining what's at `0x10000000`:
This matches:
- `SCRATCH_Y` starts at `0x20081000`
- `SCRATCH_Y` is 4 KB (`0x1000` bytes)
- `0x20081000` + `0x1000` = `0x20082000`
- `0x20081000` + `0x1000` = `0x20082000`
---
## 🔬 Part 8: Examining the Reset Handler
## Part 8: Examining the Reset Handler
> 🔄 **REVIEW:** We used `x/5i` extensively in Weeks 1-2 to examine our `main` function. Now we'll use the same technique to examine the code that runs BEFORE `main`!
> **REVIEW:** We used `x/5i` extensively in Weeks 1-2 to examine our `main` function. Now we'll use the same technique to examine the code that runs BEFORE `main`!
### Step 4: Disassemble the Reset Handler
@@ -505,7 +501,7 @@ So the reset handler checks:
---
## 🔬 Part 9: The Complete Reset Handler Flow
## Part 9: The Complete Reset Handler Flow
### Step 6: Examine More of the Reset Handler
@@ -586,11 +582,11 @@ The reset handler performs several phases:
---
## 🔬 Part 10: Understanding the Data Copy Phase
## Part 10: Understanding the Data Copy Phase
### What is the Data Copy Phase?
> 🔄 **REVIEW:** In Week 2, we learned that flash is read-only and SRAM is read-write. That's why the startup code must COPY initialized variables from flash to RAM - they can't be modified in flash!
> **REVIEW:** In Week 2, we learned that flash is read-only and SRAM is read-write. That's why the startup code must COPY initialized variables from flash to RAM - they can't be modified in flash!
When you write C code like this:
@@ -659,7 +655,7 @@ b.n 0x1000016c <hold_non_core0_in_bootrom+8>
---
## 🔬 Part 11: Understanding the BSS Clear Phase
## Part 11: Understanding the BSS Clear Phase
### What is BSS?
@@ -713,7 +709,7 @@ The first two `ldr` instructions are still part of the **BSS clear setup**, even
---
## 🔬 Part 12: Examining Exception Handlers
## Part 12: Examining Exception Handlers
### Step 11: Look at the Default Exception Handlers
@@ -761,7 +757,7 @@ Each type of exception has its own handler:
---
## 🔬 Part 13: Finding Where Main is Called
## Part 13: Finding Where Main is Called
### Step 12: Look at Platform Entry
@@ -804,7 +800,7 @@ After `main()` returns, `exit()` is called to handle cleanup. The `bkpt` instruc
### Step 13: Set a Breakpoint at Main
> 🔄 **REVIEW:** We've used `b main` and `b *ADDRESS` many times in Weeks 1-2. This is the same technique!
> **REVIEW:** We've used `b main` and `b *ADDRESS` many times in Weeks 1-2. This is the same technique!
Let's verify we understand the boot process by setting a breakpoint at main:
@@ -838,11 +834,11 @@ Thread 1 "rp2350.cm0" hit Breakpoint 1, main ()
(gdb)
```
🎉 We've traced the entire boot process from power-on to `main()`!
We've traced the entire boot process from power-on to `main()`!
---
## 🔬 Part 14: Understanding the Binary Info Header
## Part 14: Understanding the Binary Info Header
### Step 14: Examine the Binary Info Header
@@ -887,9 +883,9 @@ That's not real code - it's the magic number `0xffffded3` being misinterpreted!
---
## 🔬 Part 15: Static Analysis with Ghidra - Examining the Boot Sequence
## Part 15: Static Analysis with Ghidra - Examining the Boot Sequence
> 🔄 **REVIEW:** In Week 1, we set up a Ghidra project and analyzed our hello-world binary. Now we'll use Ghidra to understand the boot sequence from a static analysis perspective!
> **REVIEW:** In Week 1, we set up a Ghidra project and analyzed our hello-world binary. Now we'll use Ghidra to understand the boot sequence from a static analysis perspective!
### Why Use Ghidra for Boot Analysis?
@@ -901,7 +897,7 @@ While GDB is excellent for dynamic analysis (watching code execute), Ghidra exce
### Step 15: Open Your Project in Ghidra
> 🔄 **REVIEW:** If you haven't created the project yet, refer back to Week 1 Part 5 for setup instructions.
> **REVIEW:** If you haven't created the project yet, refer back to Week 1 Part 5 for setup instructions.
1. Launch Ghidra and open your `0x0001_hello-world` project
2. Double-click on the `.elf` file to open it in the CodeBrowser
@@ -1042,7 +1038,7 @@ In Ghidra, look at `platform_entry`:
10000194 fd e7 b LAB_10000192
```
> 🎯 **Key Insight:** Ghidra's decompiler makes the boot sequence crystal clear! You can see exactly what functions are called before `main()`.
> **Key Insight:** Ghidra's decompiler makes the boot sequence crystal clear! You can see exactly what functions are called before `main()`.
### Step 20: Create a Boot Sequence Graph
@@ -1056,8 +1052,8 @@ Ghidra can visualize the call flow:
| Aspect | GDB (Dynamic) | Ghidra (Static) |
| ------ | ------------- | --------------- |
| **Sees runtime values** | Yes - register contents, memory | No - must infer from code |
| **Needs hardware** | Yes - Pico 2 must be connected | No - works offline |
| **Sees runtime values** | Yes - register contents, memory | No - must infer from code |
| **Needs hardware** | Yes - Pico 2 must be connected | No - works offline |
| **Shows code flow** | Step-by-step execution | Full graph visualization |
| **Best for** | Watching what happens | Understanding structure |
| **Thumb bit handling** | Shows with +1 (0x1000015d) | Shows actual addr (0x1000015c) |
@@ -1071,7 +1067,7 @@ Ghidra can visualize the call flow:
---
## 📊 Part 16: Summary and Review
## Part 16: Summary and Review
### The Complete Boot Sequence
@@ -1167,7 +1163,7 @@ Ghidra can visualize the call flow:
---
## 🎓 Key Takeaways
## Key Takeaways
### Building on Weeks 1-2
@@ -1193,7 +1189,7 @@ Ghidra can visualize the call flow:
---
## 🔐 Security Implications
## Security Implications
### How Boot Sequence Knowledge Applies to Security
@@ -1314,7 +1310,7 @@ Understanding how an attacker would analyze and exploit the boot sequence is ess
---
## 📖 Glossary
## Glossary
### New Terms This Week
@@ -1358,7 +1354,7 @@ The startup code lives in:
- `memmap_default.ld` - Default linker script (section ordering: `.vectors` -> `.binary_info_header` -> `.embedded_block` -> `.reset`)
- `embedded_start_block.inc.S` - IMAGE_DEF block (replaces RP2040's `boot2_generic_03h.S`)
> ⚠️ **Note:** The RP2040 used a `boot2_generic_03h.S` second-stage bootloader occupying the first 256 bytes of flash. The RP2350 eliminated this; the bootrom handles flash XIP setup directly. The SDK still includes a `boot2` mechanism for compatibility, but it is **not** placed at flash address 0 - it is embedded in the data copy table and executed from the stack during startup.
> **Note:** The RP2040 used a `boot2_generic_03h.S` second-stage bootloader occupying the first 256 bytes of flash. The RP2350 eliminated this; the bootrom handles flash XIP setup directly. The SDK still includes a `boot2` mechanism for compatibility, but it is **not** placed at flash address 0 - it is embedded in the data copy table and executed from the stack during startup.
### Bootrom Source
@@ -1367,7 +1363,7 @@ https://github.com/raspberrypi/pico-bootrom-rp2350
---
## 🔬 Part 17: Proving the Boot Sequence with objdump
## Part 17: Proving the Boot Sequence with objdump
Everything we have learned about the boot sequence can be proven directly from the compiled ELF binary using `arm-none-eabi-objdump`. The bootrom is not in your ELF (it is mask ROM burned into the chip at `0x00000000`), but everything your firmware provides - the vector table, the IMAGE_DEF, and the reset handler - lives in your ELF starting at `0x10000000`.
@@ -1496,7 +1492,7 @@ and GPIO pin map from any compiled binary without running it.
| `0x10000148` | `79 35 12 ab` | `PICOBIN_BLOCK_MARKER_END` - bootrom stops scanning here. |
The IMAGE_DEF sits at `0x10000138`-`0x1000014b` in this build,
well within the 4 KB scan window the bootrom uses (Datasheet §5.9.5, p. 429).
well within the 4 KB scan window the bootrom uses (Datasheet 5.9.5, p. 429).
#### Full Flash Map: 0x10000000-0x1000015c
@@ -1534,15 +1530,16 @@ well within the 4 KB scan window the bootrom uses (Datasheet §5.9.5, p. 429).
+-----------------------------------------------------------------+
```
> 📖 **Datasheet References:**
> - §5.1.5.1 (p. 357): Block markers `0xffffded3` (start) and `0xab123579` (end)
> - §5.9.5 (p. 429): IMAGE_DEF must appear within first 4 kB of flash image
> - §5.9.5.1 (p. 429): Bootrom enters via reset handler at vector table offset +4
> **Datasheet References:**
> - 5.1.5.1 (p. 357): Block markers `0xffffded3` (start) and `0xab123579` (end)
> - 5.9.5 (p. 429): IMAGE_DEF must appear within first 4 kB of flash image
> - 5.9.5.1 (p. 429): Bootrom enters via reset handler at vector table offset +4
---
**Remember:** Understanding the boot process is fundamental to embedded systems work. Whether you're debugging a system that won't start, reverse engineering firmware, or building secure boot chains, this knowledge is essential!
Happy exploring! 🔍
Happy exploring!