mirror of
https://github.com/mytechnotalent/Embedded-Hacking.git
synced 2026-07-10 06:18:40 +02:00
Updated DS refs
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
# Embedded Systems Reverse Engineering
|
||||
[Repository](https://github.com/mytechnotalent/Embedded-Hacking)
|
||||
|
||||
## Week 3
|
||||
Embedded System Analysis: Understanding the RP2350 Architecture w/ Comprehensive Firmware Analysis
|
||||
|
||||
### Non-Credit Practice Exercise 1 Solution: Trace a Reset
|
||||
|
||||
#### Answers
|
||||
|
||||
##### Instruction Trace (First 10 Instructions from 0x1000015c)
|
||||
|
||||
| # | Address | Instruction | What It Does | Key Register Change |
|
||||
|---|-------------|----------------------------------------|------------------------------------------------------|---------------------|
|
||||
| 1 | 0x1000015c | `mov.w r0, #0xd0000000` | Loads SIO base address into r0 | r0 = 0xd0000000 |
|
||||
| 2 | 0x10000160 | `ldr r0, [r0, #0]` | Reads CPUID register at SIO base + 0 | r0 = 0 (Core 0) |
|
||||
| 3 | 0x10000162 | `cbz r0, 0x1000016a` | If CPUID == 0 (Core 0), branch to data copy section | PC = 0x1000016a |
|
||||
| 4 | 0x1000016a | `ldr r0, [pc, #...]` | Loads source address for data copy (flash) | r0 = flash addr |
|
||||
| 5 | 0x1000016c | `ldr r1, [pc, #...]` | Loads destination address for data copy (RAM) | r1 = RAM addr |
|
||||
| 6 | 0x1000016e | `ldr r2, [pc, #...]` | Loads end address for data copy | r2 = end addr |
|
||||
| 7 | 0x10000170 | `cmp r1, r2` | Checks if all data has been copied | Flags updated |
|
||||
| 8 | 0x10000172 | `bhs 0x10000178` | If done (dest >= end), skip to BSS clear | PC conditional |
|
||||
| 9 | 0x10000174 | `ldm r0!, {r3}` | Loads 4 bytes from flash source, auto-increments r0 | r3 = data, r0 += 4 |
|
||||
| 10| 0x10000176 | `stm r1!, {r3}` | Stores 4 bytes to RAM destination, auto-increments r1| r1 += 4 |
|
||||
|
||||
##### GDB Session
|
||||
|
||||
```gdb
|
||||
(gdb) b *0x1000015c
|
||||
(gdb) monitor reset halt
|
||||
(gdb) c
|
||||
Breakpoint 1, 0x1000015c in _reset_handler ()
|
||||
(gdb) si
|
||||
(gdb) disas $pc,+2
|
||||
(gdb) info registers r0
|
||||
```
|
||||
|
||||
#### Reflection Answers
|
||||
|
||||
1. **Why does the reset handler check the CPUID before doing anything else?**
|
||||
The RP2350 has two Cortex-M33 cores that share the same reset handler entry point. The CPUID check at SIO base `0xd0000000` returns 0 for Core 0 and 1 for Core 1. Only Core 0 should perform the one-time initialization (data copy, BSS clear, calling `main()`). Without this check, both cores would simultaneously try to initialize RAM, causing data corruption and race conditions.
|
||||
|
||||
2. **What would happen if Core 1 tried to run the same initialization code as Core 0?**
|
||||
Both cores would simultaneously write to the same RAM locations during the data copy and BSS clear phases. This would cause data corruption due to race conditions—values could be partially written or overwritten unpredictably. The `cbz` instruction at `0x10000162` prevents this: if CPUID != 0, the code branches to `hold_non_core0_in_bootrom`, which sends Core 1 back to the bootrom to wait until Core 0 explicitly launches it later.
|
||||
|
||||
3. **Which registers are used in the first 10 instructions, and why those specific ones?**
|
||||
The first 10 instructions use `r0`, `r1`, `r2`, and `r3`. These are the ARM "caller-saved" scratch registers (r0–r3) that don't need to be preserved across function calls. Since the reset handler is the very first code to run (no caller to preserve state for), using these low registers is both efficient (16-bit Thumb encodings) and safe. `r0` handles CPUID check and source pointer, `r1` is the destination pointer, `r2` is the end marker, and `r3` is the data transfer register.
|
||||
@@ -0,0 +1,130 @@
|
||||
# Embedded Systems Reverse Engineering
|
||||
[Repository](https://github.com/mytechnotalent/Embedded-Hacking)
|
||||
|
||||
## Week 3
|
||||
Embedded System Analysis: Understanding the RP2350 Architecture w/ Comprehensive Firmware Analysis
|
||||
|
||||
### Non-Credit Practice Exercise 1: Trace a Reset
|
||||
|
||||
#### Objective
|
||||
Single-step through the first 10 instructions of the reset handler to understand exactly what happens when the RP2350 powers on or resets.
|
||||
|
||||
#### Prerequisites
|
||||
- Raspberry Pi Pico 2 with debug probe connected
|
||||
- OpenOCD and `arm-none-eabi-gdb` available in your PATH
|
||||
- `build\0x0001_hello-world.elf` present and flashed to the board
|
||||
- Week 3 environment setup completed (OpenOCD running, GDB connected)
|
||||
|
||||
#### Task Description
|
||||
You will set a breakpoint at the reset handler (`0x1000015c`), trigger a reset, and step through each instruction one at a time while documenting what each instruction does.
|
||||
|
||||
#### Step-by-Step Instructions
|
||||
|
||||
##### Step 1: Start OpenOCD
|
||||
|
||||
```powershell
|
||||
openocd ^
|
||||
-s "C:\Users\flare-vm\.pico-sdk\openocd\0.12.0+dev\scripts" ^
|
||||
-f interface/cmsis-dap.cfg ^
|
||||
-f target/rp2350.cfg ^
|
||||
-c "adapter speed 5000"
|
||||
```
|
||||
|
||||
##### Step 2: Launch GDB
|
||||
|
||||
```powershell
|
||||
arm-none-eabi-gdb build\0x0001_hello-world.elf
|
||||
```
|
||||
|
||||
##### Step 3: Connect to Target
|
||||
|
||||
```gdb
|
||||
(gdb) target extended-remote :3333
|
||||
```
|
||||
|
||||
##### Step 4: Set Breakpoint at Reset Handler
|
||||
|
||||
```gdb
|
||||
(gdb) b *0x1000015c
|
||||
```
|
||||
|
||||
**What this does:** Places a breakpoint at the very first instruction of the reset handler (the entry point after bootrom).
|
||||
|
||||
##### Step 5: Reset and Break
|
||||
|
||||
```gdb
|
||||
(gdb) monitor reset halt
|
||||
(gdb) c
|
||||
```
|
||||
|
||||
**What this does:**
|
||||
- `monitor reset halt` resets the chip and immediately halts it
|
||||
- `c` continues execution until the breakpoint at the reset handler is hit
|
||||
|
||||
##### Step 6: Single-Step Through Instructions
|
||||
|
||||
Now step through the first 10 instructions, one at a time:
|
||||
|
||||
```gdb
|
||||
(gdb) si
|
||||
(gdb) disas $pc,+2
|
||||
(gdb) info registers r0
|
||||
```
|
||||
|
||||
Repeat `si` nine more times, examining each instruction.
|
||||
|
||||
**Example of what you'll see:**
|
||||
|
||||
**Instruction 1:**
|
||||
```
|
||||
0x1000015c <_reset_handler>: mov.w r0, #3489660928 @ 0xd0000000
|
||||
```
|
||||
**What it does:** Loads the SIO base address (0xd0000000) into r0
|
||||
|
||||
**Instruction 2:**
|
||||
```
|
||||
0x10000160 <_reset_handler+4>: ldr r0, [r0, #0]
|
||||
```
|
||||
**What it does:** Reads the CPUID register to determine which core is running
|
||||
|
||||
**Instruction 3:**
|
||||
```
|
||||
0x10000162 <_reset_handler+6>: cbz r0, 0x1000016a
|
||||
```
|
||||
**What it does:** If CPUID is 0 (Core 0), branch ahead to continue boot; otherwise handle Core 1
|
||||
|
||||
##### Step 7: Document Your Observations
|
||||
|
||||
For each of the 10 instructions:
|
||||
1. Write down the address
|
||||
2. Write down the assembly instruction
|
||||
3. Explain what it does
|
||||
4. Note any register changes using `info registers`
|
||||
|
||||
#### Expected Output
|
||||
- You should see the reset handler check which core is running
|
||||
- If you're on Core 0, you'll see it jump to the data copy section
|
||||
- Register `r0` will contain CPUID value (should be 0)
|
||||
- PC (program counter) advances with each `si` command
|
||||
|
||||
#### Questions for Reflection
|
||||
|
||||
###### Question 1: Why does the reset handler check the CPUID before doing anything else?
|
||||
|
||||
###### Question 2: What would happen if Core 1 tried to run the same initialization code as Core 0?
|
||||
|
||||
###### Question 3: Which registers are used in the first 10 instructions, and why those specific ones?
|
||||
|
||||
#### Tips and Hints
|
||||
- Use `disas $pc,+20` to see upcoming instructions without stepping through them
|
||||
- Use `info registers` to see all register values at any point
|
||||
- If you step past where you wanted to stop, just `monitor reset halt` and start over
|
||||
- Keep notes as you go—this is detective work!
|
||||
|
||||
#### Next Steps
|
||||
- Try stepping all the way through to the data copy loop
|
||||
- Set a breakpoint at `0x1000016c` (the data copy loop) and continue there directly
|
||||
- Move on to Exercise 2 to calculate the stack size from the vector table
|
||||
|
||||
#### Additional Challenge
|
||||
Set a breakpoint at `0x10000178` (the BSS clear phase) and continue execution to see how the reset handler transitions from data copying to BSS clearing.
|
||||
@@ -0,0 +1,76 @@
|
||||
# Embedded Systems Reverse Engineering
|
||||
[Repository](https://github.com/mytechnotalent/Embedded-Hacking)
|
||||
|
||||
## Week 3
|
||||
Embedded System Analysis: Understanding the RP2350 Architecture w/ Comprehensive Firmware Analysis
|
||||
|
||||
### Non-Credit Practice Exercise 2 Solution: Find the Stack Size
|
||||
|
||||
#### Answers
|
||||
|
||||
##### Initial Stack Pointer
|
||||
|
||||
```gdb
|
||||
(gdb) x/x 0x10000000
|
||||
0x10000000 <__vectors>: 0x20082000
|
||||
```
|
||||
|
||||
The initial stack pointer is **0x20082000**, stored as the first entry in the vector table.
|
||||
|
||||
##### Stack Limit
|
||||
|
||||
The stack limit is **0x20078000**, defined by the linker script.
|
||||
|
||||
```gdb
|
||||
(gdb) info symbol __StackLimit
|
||||
__StackLimit in section .stack
|
||||
```
|
||||
|
||||
##### Stack Size Calculation
|
||||
|
||||
| Value | Hex | Decimal |
|
||||
|-----------------|-------------|---------------|
|
||||
| Stack Top | 0x20082000 | 537,108,480 |
|
||||
| Stack Limit | 0x20078000 | 537,067,520 |
|
||||
| **Stack Size** | 0x0000A000 | **40,960 bytes** |
|
||||
|
||||
```
|
||||
Stack Size = 0x20082000 - 0x20078000 = 0xA000 = 40,960 bytes
|
||||
40,960 ÷ 1,024 = 40 KB
|
||||
```
|
||||
|
||||
##### Memory Region Verification
|
||||
|
||||
| Region | Start | End | Size |
|
||||
|-----------|-------------|-------------|--------|
|
||||
| RAM | 0x20000000 | 0x20080000 | 512 KB |
|
||||
| SCRATCH_X | 0x20080000 | 0x20081000 | 4 KB |
|
||||
| SCRATCH_Y | 0x20081000 | 0x20082000 | 4 KB |
|
||||
| **Stack** | 0x20078000 | 0x20082000 | **40 KB** |
|
||||
|
||||
The stack spans from the upper portion of main RAM through SCRATCH_X and into SCRATCH_Y.
|
||||
|
||||
##### Runtime Stack Usage at main()
|
||||
|
||||
```gdb
|
||||
(gdb) b main
|
||||
(gdb) c
|
||||
(gdb) info registers sp
|
||||
sp 0x20081fc8 0x20081fc8
|
||||
```
|
||||
|
||||
Stack used at `main()` entry: `0x20082000 - 0x20081fc8 = 0x38 = 56 bytes`
|
||||
|
||||
#### Reflection Answers
|
||||
|
||||
1. **Why is the stack 40 KB instead of just fitting in the 4 KB SCRATCH_Y region?**
|
||||
The stack pointer is initialized at the top of SCRATCH_Y (`0x20082000`), but the stack grows **downward**. As functions are called and local variables are allocated, the stack pointer decreases past the SCRATCH_Y boundary (`0x20081000`), through SCRATCH_X, and into the upper portion of main RAM. The linker sets the stack limit at `0x20078000` to give the stack 40 KB of room, which is sufficient for typical embedded applications with nested function calls.
|
||||
|
||||
2. **What happens if the stack grows beyond 0x20078000?**
|
||||
A **stack overflow** occurs. The stack would collide with the heap or global data stored in the lower portion of RAM. This can corrupt variables, overwrite heap metadata, or cause a HardFault if memory protection is enabled. On the RP2350 with Cortex-M33 MPU support, a MemManage fault could be triggered if stack guard regions are configured.
|
||||
|
||||
3. **How would you detect a stack overflow during runtime?**
|
||||
Several methods exist: (a) Write a known "canary" pattern (e.g., `0xDEADBEEF`) at the stack limit and periodically check if it's been overwritten. (b) Use the Cortex-M33 MPU to set a guard region at `0x20078000` that triggers a MemManage fault on access. (c) In GDB, use a watchpoint: `watch *(int*)0x20078000` to break if the stack reaches the limit. (d) Use the `stackusage` GDB macro from the exercise to monitor usage.
|
||||
|
||||
4. **Why does the stack grow downward instead of upward?**
|
||||
This is an ARM architecture convention inherited from early processor designs. Growing downward allows the stack and heap to grow toward each other from opposite ends of RAM, maximizing memory utilization without needing to know each region's size in advance. The stack starts at the highest address and grows down, while the heap starts at a lower address and grows up. If they meet, memory is exhausted—but this layout gives both regions the maximum possible space.
|
||||
@@ -0,0 +1,167 @@
|
||||
# Embedded Systems Reverse Engineering
|
||||
[Repository](https://github.com/mytechnotalent/Embedded-Hacking)
|
||||
|
||||
## Week 3
|
||||
Embedded System Analysis: Understanding the RP2350 Architecture w/ Comprehensive Firmware Analysis
|
||||
|
||||
### Non-Credit Practice Exercise 2: Find the Stack Size
|
||||
|
||||
#### Objective
|
||||
Calculate the size of the stack by examining the vector table, understanding the linker script's memory layout, and performing manual calculations.
|
||||
|
||||
#### Prerequisites
|
||||
- Raspberry Pi Pico 2 with debug probe connected
|
||||
- OpenOCD and `arm-none-eabi-gdb` available
|
||||
- `build\0x0001_hello-world.elf` flashed to the board
|
||||
- Understanding of memory regions from Week 3 Part 5 (Linker Script)
|
||||
|
||||
#### Task Description
|
||||
You will examine the initial stack pointer value from the vector table, identify the stack limit, calculate the total stack size in bytes and kilobytes, and verify your calculations.
|
||||
|
||||
#### Background Information
|
||||
|
||||
From the Week 3 lesson, we learned:
|
||||
- The initial stack pointer is stored at `0x10000000` (first entry in vector table)
|
||||
- The linker script defines: `SCRATCH_Y: ORIGIN = 0x20081000, LENGTH = 4k`
|
||||
- Stack top is calculated as: `ORIGIN + LENGTH = 0x20082000`
|
||||
- The stack grows downward from high addresses to low addresses
|
||||
|
||||
#### Step-by-Step Instructions
|
||||
|
||||
##### Step 1: Connect and Halt
|
||||
|
||||
```gdb
|
||||
(gdb) target extended-remote :3333
|
||||
(gdb) monitor reset halt
|
||||
```
|
||||
|
||||
##### Step 2: Examine the Initial Stack Pointer
|
||||
|
||||
```gdb
|
||||
(gdb) x/x 0x10000000
|
||||
```
|
||||
|
||||
**Expected output:**
|
||||
```
|
||||
0x10000000 <__vectors>: 0x20082000
|
||||
```
|
||||
|
||||
This is the **top of the stack** (where the stack starts before growing downward).
|
||||
|
||||
##### Step 3: Find the Stack Limit
|
||||
|
||||
The stack limit is defined in the linker script and can be found by examining stack-related symbols or calculating from memory regions.
|
||||
|
||||
From the Week 3 lesson, the stack limit is `0x20078000`.
|
||||
|
||||
You can verify this in GDB:
|
||||
|
||||
```gdb
|
||||
(gdb) info symbol __StackLimit
|
||||
```
|
||||
|
||||
or check registers after boot:
|
||||
|
||||
```gdb
|
||||
(gdb) info registers
|
||||
```
|
||||
|
||||
Look for stack limit values or calculate: The main RAM starts at `0x20000000`, and SCRATCH_Y starts at `0x20081000`.
|
||||
|
||||
##### Step 4: Calculate Stack Size in Bytes
|
||||
|
||||
**Formula:**
|
||||
```
|
||||
Stack Size = Stack Top - Stack Limit
|
||||
Stack Size = 0x20082000 - 0x20078000
|
||||
```
|
||||
|
||||
Let's convert to decimal:
|
||||
- `0x20082000` = 537,108,480 decimal
|
||||
- `0x20078000` = 537,067,520 decimal
|
||||
- Difference = 40,960 bytes
|
||||
|
||||
**Alternative hex calculation:**
|
||||
```
|
||||
0x20082000
|
||||
- 0x20078000
|
||||
-----------
|
||||
0x0000A000 = 40,960 bytes
|
||||
```
|
||||
|
||||
##### Step 5: Convert to Kilobytes
|
||||
|
||||
```
|
||||
Bytes to KB = 40,960 ÷ 1,024 = 40 KB
|
||||
```
|
||||
|
||||
So the stack is **40 KB** in size.
|
||||
|
||||
##### Step 6: Verify Using Memory Regions
|
||||
|
||||
Cross-check with the memory layout:
|
||||
- **RAM**: `0x20000000` - `0x20080000` (512 KB)
|
||||
- **SCRATCH_X**: `0x20080000` - `0x20081000` (4 KB)
|
||||
- **SCRATCH_Y**: `0x20081000` - `0x20082000` (4 KB) ? Stack lives here
|
||||
- **Stack range**: `0x20078000` - `0x20082000` (40 KB)
|
||||
|
||||
The stack extends from SCRATCH_Y down into the upper portion of main RAM.
|
||||
|
||||
##### Step 7: Examine Stack Usage at Runtime
|
||||
|
||||
You can see the current stack pointer value:
|
||||
|
||||
```gdb
|
||||
(gdb) b main
|
||||
(gdb) c
|
||||
(gdb) info registers sp
|
||||
```
|
||||
|
||||
**Expected output:**
|
||||
```
|
||||
sp 0x20081fc8 0x20081fc8
|
||||
```
|
||||
|
||||
This shows the stack has used:
|
||||
```
|
||||
0x20082000 - 0x20081fc8 = 0x38 = 56 bytes
|
||||
```
|
||||
|
||||
#### Expected Output
|
||||
- Initial stack pointer: `0x20082000`
|
||||
- Stack limit: `0x20078000`
|
||||
- Stack size: **40,960 bytes** or **40 KB**
|
||||
- Current stack usage (at main): approximately 56 bytes
|
||||
|
||||
#### Questions for Reflection
|
||||
|
||||
###### Question 1: Why is the stack 40 KB instead of just fitting in the 4 KB SCRATCH_Y region?
|
||||
|
||||
###### Question 2: What happens if the stack grows beyond 0x20078000?
|
||||
|
||||
###### Question 3: How would you detect a stack overflow during runtime?
|
||||
|
||||
###### Question 4: Why does the stack grow downward instead of upward?
|
||||
|
||||
#### Tips and Hints
|
||||
- Use Windows Calculator in Programmer mode to convert hex to decimal
|
||||
- Remember: 1 KB = 1,024 bytes (not 1,000)
|
||||
- The stack pointer (SP) decreases as the stack grows (push operations)
|
||||
- Use `bt` (backtrace) in GDB to see how much stack is currently in use
|
||||
|
||||
#### Next Steps
|
||||
- Monitor the stack pointer as you step through functions to see it change
|
||||
- Calculate stack usage for specific function calls
|
||||
- Move on to Exercise 3 to examine all vector table entries
|
||||
|
||||
#### Additional Challenge
|
||||
Write a GDB command to automatically calculate and display stack usage:
|
||||
|
||||
```gdb
|
||||
(gdb) define stackusage
|
||||
> set $used = 0x20082000 - $sp
|
||||
> printf "Stack used: %d bytes (%d KB)\n", $used, $used/1024
|
||||
> end
|
||||
|
||||
(gdb) stackusage
|
||||
```
|
||||
@@ -0,0 +1,78 @@
|
||||
# Embedded Systems Reverse Engineering
|
||||
[Repository](https://github.com/mytechnotalent/Embedded-Hacking)
|
||||
|
||||
## Week 3
|
||||
Embedded System Analysis: Understanding the RP2350 Architecture w/ Comprehensive Firmware Analysis
|
||||
|
||||
### Non-Credit Practice Exercise 3 Solution: Examine All Vectors
|
||||
|
||||
#### Answers
|
||||
|
||||
##### Vector Table Dump
|
||||
|
||||
```gdb
|
||||
(gdb) x/16x 0x10000000
|
||||
0x10000000 <__vectors>: 0x20082000 0x1000015d 0x1000011b 0x1000011d
|
||||
0x10000010 <__vectors+16>: 0x1000011f 0x10000121 0x10000123 0x00000000
|
||||
0x10000020 <__vectors+32>: 0x00000000 0x00000000 0x00000000 0x10000125
|
||||
0x10000030 <__vectors+48>: 0x00000000 0x00000000 0x10000127 0x10000129
|
||||
```
|
||||
|
||||
##### Complete Vector Table Map
|
||||
|
||||
| Offset | Vector # | Raw Value | Address Type | Actual Addr | Handler Name |
|
||||
|--------|----------|-------------|---------------|-------------|------------------|
|
||||
| 0x00 | — | 0x20082000 | Stack Pointer | N/A | __StackTop |
|
||||
| 0x04 | 1 | 0x1000015d | Code (Thumb) | 0x1000015c | _reset_handler |
|
||||
| 0x08 | 2 | 0x1000011b | Code (Thumb) | 0x1000011a | isr_nmi |
|
||||
| 0x0C | 3 | 0x1000011d | Code (Thumb) | 0x1000011c | isr_hardfault |
|
||||
| 0x10 | 4 | 0x1000011f | Code (Thumb) | 0x1000011e | isr_memmanage |
|
||||
| 0x14 | 5 | 0x10000121 | Code (Thumb) | 0x10000120 | isr_busfault |
|
||||
| 0x18 | 6 | 0x10000123 | Code (Thumb) | 0x10000122 | isr_usagefault |
|
||||
| 0x1C | 7 | 0x00000000 | Reserved | N/A | (Reserved) |
|
||||
| 0x20 | 8 | 0x00000000 | Reserved | N/A | (Reserved) |
|
||||
| 0x24 | 9 | 0x00000000 | Reserved | N/A | (Reserved) |
|
||||
| 0x28 | 10 | 0x00000000 | Reserved | N/A | (Reserved) |
|
||||
| 0x2C | 11 | 0x10000125 | Code (Thumb) | 0x10000124 | isr_svcall |
|
||||
| 0x30 | 12 | 0x00000000 | Reserved | N/A | (Reserved) |
|
||||
| 0x34 | 13 | 0x00000000 | Reserved | N/A | (Reserved) |
|
||||
| 0x38 | 14 | 0x10000127 | Code (Thumb) | 0x10000126 | isr_pendsv |
|
||||
| 0x3C | 15 | 0x10000129 | Code (Thumb) | 0x10000128 | isr_systick |
|
||||
|
||||
##### Handler Verification
|
||||
|
||||
```gdb
|
||||
(gdb) info symbol 0x1000015c
|
||||
_reset_handler in section .text
|
||||
(gdb) info symbol 0x1000011a
|
||||
isr_nmi in section .text
|
||||
(gdb) x/3i 0x1000011a
|
||||
0x1000011a <isr_nmi>: bkpt 0x0000
|
||||
0x1000011c <isr_hardfault>: bkpt 0x0000
|
||||
0x1000011e <isr_svcall>: bkpt 0x0000
|
||||
```
|
||||
|
||||
Most default handlers are single `bkpt` instructions—they halt the processor if triggered unexpectedly.
|
||||
|
||||
##### Summary Statistics
|
||||
|
||||
| Category | Count |
|
||||
|---------------------|-------|
|
||||
| Stack Pointer entry | 1 |
|
||||
| Valid code entries | 10 |
|
||||
| Reserved (0x0) | 5 |
|
||||
| **Total entries** | **16** |
|
||||
|
||||
#### Reflection Answers
|
||||
|
||||
1. **Why do all the code addresses end in odd numbers (LSB = 1)?**
|
||||
ARM Cortex-M processors exclusively execute in Thumb mode. The least significant bit (LSB) of vector table entries indicates the instruction set: LSB = 1 means Thumb mode. Since Cortex-M33 only supports Thumb/Thumb-2, all code addresses must have bit 0 set to 1. The actual instruction address is the value with bit 0 cleared (e.g., `0x1000015d` → instruction at `0x1000015c`). This is a hardware requirement—loading an even address into the PC on Cortex-M would cause a HardFault.
|
||||
|
||||
2. **What happens if an exception occurs for a reserved/null vector entry?**
|
||||
If the processor attempts to invoke a handler through a vector entry containing `0x00000000`, it tries to fetch instructions from address `0x00000000` (in the bootrom region). This would either execute bootrom code unexpectedly or trigger a HardFault because the address lacks the Thumb bit (LSB = 0). In practice, a HardFault would occur, and if the HardFault handler itself is invalid, the processor enters a lockup state.
|
||||
|
||||
3. **Why do most exception handlers just contain `bkpt` instructions?**
|
||||
The Pico SDK provides these as **default weak handlers**. They are intentionally minimal—a `bkpt` (breakpoint) instruction halts the processor immediately so a debugger can catch the event. This is a safety mechanism: rather than letting an unhandled exception corrupt state or silently continue, the default handlers stop execution so the developer can diagnose the problem. Application code can override any handler by defining a function with the matching name (the weak linkage gets replaced).
|
||||
|
||||
4. **How would you replace a default handler with your own custom handler?**
|
||||
Define a C function with the exact handler name (e.g., `void isr_hardfault(void)`) in your application code. Because the SDK declares these handlers as `__attribute__((weak))`, the linker will use your strong definition instead of the default `bkpt` stub. The new function's address (with Thumb bit set) will automatically appear in the vector table at the correct offset. No linker script modification is needed.
|
||||
@@ -0,0 +1,209 @@
|
||||
# Embedded Systems Reverse Engineering
|
||||
[Repository](https://github.com/mytechnotalent/Embedded-Hacking)
|
||||
|
||||
## Week 3
|
||||
Embedded System Analysis: Understanding the RP2350 Architecture w/ Comprehensive Firmware Analysis
|
||||
|
||||
### Non-Credit Practice Exercise 3: Examine All Vectors
|
||||
|
||||
#### Objective
|
||||
Examine the first 16 entries of the vector table to understand the exception handler layout, identify valid code addresses, and recognize the Thumb mode addressing convention.
|
||||
|
||||
#### Prerequisites
|
||||
- Raspberry Pi Pico 2 with debug probe connected
|
||||
- OpenOCD and `arm-none-eabi-gdb` available
|
||||
- `build\0x0001_hello-world.elf` loaded
|
||||
- Understanding of the vector table from Week 3 Part 4
|
||||
- Knowledge of Thumb mode addressing (LSB = 1 indicates Thumb code)
|
||||
|
||||
#### Task Description
|
||||
You will examine 16 consecutive 32-bit values from the vector table, decode each entry, determine if it's a valid code address, and identify which exception handler it points to.
|
||||
|
||||
#### Background Information
|
||||
|
||||
The ARM Cortex-M vector table structure:
|
||||
|
||||
| Offset | Vector # | Handler Name | Purpose |
|
||||
|--------|----------|---------------------|---------|
|
||||
| 0x00 | - | Initial SP | Stack pointer initialization |
|
||||
| 0x04 | 1 | Reset | Power-on/reset entry point |
|
||||
| 0x08 | 2 | NMI | Non-Maskable Interrupt |
|
||||
| 0x0C | 3 | HardFault | Serious errors |
|
||||
| 0x10 | 4 | MemManage | Memory protection fault |
|
||||
| 0x14 | 5 | BusFault | Bus error |
|
||||
| 0x18 | 6 | UsageFault | Undefined instruction, etc. |
|
||||
| 0x1C-0x28 | 7-10 | Reserved | Not used |
|
||||
| 0x2C | 11 | SVCall | Supervisor call |
|
||||
| 0x30 | 12 | Debug Monitor | Debug events |
|
||||
| 0x34 | 13 | Reserved | Not used |
|
||||
| 0x38 | 14 | PendSV | Pendable service call |
|
||||
| 0x3C | 15 | SysTick | System tick timer |
|
||||
|
||||
#### Step-by-Step Instructions
|
||||
|
||||
##### Step 1: Connect and Halt
|
||||
|
||||
```gdb
|
||||
(gdb) target extended-remote :3333
|
||||
(gdb) monitor reset halt
|
||||
```
|
||||
|
||||
##### Step 2: Examine 16 Vector Table Entries
|
||||
|
||||
```gdb
|
||||
(gdb) x/16x 0x10000000
|
||||
```
|
||||
|
||||
**Expected output (example):**
|
||||
```
|
||||
0x10000000 <__vectors>: 0x20082000 0x1000015d 0x1000011b 0x1000011d
|
||||
0x10000010 <__vectors+16>: 0x1000011f 0x10000121 0x10000123 0x00000000
|
||||
0x10000020 <__vectors+32>: 0x00000000 0x00000000 0x00000000 0x10000125
|
||||
0x10000030 <__vectors+48>: 0x00000000 0x00000000 0x10000127 0x10000129
|
||||
```
|
||||
|
||||
##### Step 3: Analyze Each Entry
|
||||
|
||||
Create a table documenting each entry:
|
||||
|
||||
**Entry 1 (Offset 0x00):**
|
||||
```
|
||||
Address: 0x10000000
|
||||
Value: 0x20082000
|
||||
Valid Code Address? NO - This is the stack pointer (in RAM region 0x2xxxxxxx)
|
||||
Handler: Initial Stack Pointer
|
||||
```
|
||||
|
||||
**Entry 2 (Offset 0x04):**
|
||||
```
|
||||
Address: 0x10000004
|
||||
Value: 0x1000015d
|
||||
Valid Code Address? YES (starts with 0x1000...)
|
||||
Thumb Mode? YES (LSB = 1, so actual address is 0x1000015c)
|
||||
Handler: Reset Handler (_reset_handler)
|
||||
```
|
||||
|
||||
**Entry 3 (Offset 0x08):**
|
||||
```
|
||||
Address: 0x10000008
|
||||
Value: 0x1000011b
|
||||
Valid Code Address? YES
|
||||
Thumb Mode? YES (actual address: 0x1000011a)
|
||||
Handler: NMI Handler (isr_nmi)
|
||||
```
|
||||
|
||||
Continue this analysis for all 16 entries...
|
||||
|
||||
##### Step 4: Verify Handlers with Symbols
|
||||
|
||||
For each code address, check what function it points to:
|
||||
|
||||
```gdb
|
||||
(gdb) info symbol 0x1000015c
|
||||
```
|
||||
|
||||
**Expected output:**
|
||||
```
|
||||
_reset_handler in section .text
|
||||
```
|
||||
|
||||
Repeat for other addresses:
|
||||
|
||||
```gdb
|
||||
(gdb) info symbol 0x1000011a
|
||||
(gdb) info symbol 0x1000011c
|
||||
(gdb) info symbol 0x1000011e
|
||||
```
|
||||
|
||||
##### Step 5: Examine Handler Code
|
||||
|
||||
Look at the actual code at each handler:
|
||||
|
||||
```gdb
|
||||
(gdb) x/3i 0x1000011a
|
||||
```
|
||||
|
||||
**Expected output for NMI handler:**
|
||||
```
|
||||
0x1000011a <isr_nmi>: bkpt 0x0000
|
||||
0x1000011c <isr_hardfault>: bkpt 0x0000
|
||||
0x1000011e <isr_svcall>: bkpt 0x0000
|
||||
```
|
||||
|
||||
##### Step 6: Identify Reserved Entries
|
||||
|
||||
Note any entries with value `0x00000000`:
|
||||
|
||||
```
|
||||
0x00000000 = Reserved/Unused vector
|
||||
```
|
||||
|
||||
These slots are reserved by ARM and not used on Cortex-M33.
|
||||
|
||||
##### Step 7: Create a Complete Map
|
||||
|
||||
Document all 16 entries in this format:
|
||||
|
||||
| Offset | Value | Address Type | Actual Addr | Handler Name |
|
||||
|--------|------------|--------------|-------------|------------------|
|
||||
| 0x00 | 0x20082000 | Stack Ptr | N/A | __StackTop |
|
||||
| 0x04 | 0x1000015d | Code (Thumb) | 0x1000015c | _reset_handler |
|
||||
| 0x08 | 0x1000011b | Code (Thumb) | 0x1000011a | isr_nmi |
|
||||
| 0x0C | 0x1000011d | Code (Thumb) | 0x1000011c | isr_hardfault |
|
||||
| ... | ... | ... | ... | ... |
|
||||
|
||||
#### Expected Output
|
||||
- First entry is the stack pointer in RAM (0x2xxxxxxx range)
|
||||
- Entries 2-16 are mostly code addresses in flash (0x1000xxxx range)
|
||||
- Code addresses have LSB = 1 (Thumb mode indicator)
|
||||
- Reserved entries show 0x00000000
|
||||
- Most handlers point to simple `bkpt` instructions (default handlers)
|
||||
|
||||
#### Questions for Reflection
|
||||
|
||||
###### Question 1: Why do all the code addresses end in odd numbers (LSB = 1)?
|
||||
|
||||
###### Question 2: What happens if an exception occurs for a reserved/null vector entry?
|
||||
|
||||
###### Question 3: Why do most exception handlers just contain `bkpt` instructions?
|
||||
|
||||
###### Question 4: How would you replace a default handler with your own custom handler?
|
||||
|
||||
#### Tips and Hints
|
||||
- Use `x/32x 0x10000000` to see even more vectors (up to 48)
|
||||
- Remember to subtract 1 from addresses before disassembling (remove Thumb bit)
|
||||
- Use `info functions` to see all available handler symbols
|
||||
- Compare GDB output with Ghidra's vector table view
|
||||
|
||||
#### Next Steps
|
||||
- Set breakpoints at different exception handlers to see if they're ever called
|
||||
- Trigger a fault intentionally to see which handler executes
|
||||
- Move on to Exercise 4 to analyze your main function
|
||||
|
||||
#### Additional Challenge
|
||||
Write a GDB script to automatically decode and display all vector table entries:
|
||||
|
||||
```gdb
|
||||
(gdb) define vectors
|
||||
> set $i = 0
|
||||
> while $i < 16
|
||||
> set $addr = 0x10000000 + ($i * 4)
|
||||
> set $val = *(int*)$addr
|
||||
> printf "[%2d] 0x%08x: 0x%08x", $i, $addr, $val
|
||||
> if $i == 0
|
||||
> printf " (Stack Pointer)\n"
|
||||
> else
|
||||
> if $val != 0
|
||||
> if ($val & 0x10000000) == 0x10000000
|
||||
> printf " -> 0x%08x\n", $val & 0xFFFFFFFE
|
||||
> else
|
||||
> printf " (Invalid/Reserved)\n"
|
||||
> end
|
||||
> else
|
||||
> printf " (Reserved)\n"
|
||||
> end
|
||||
> end
|
||||
> set $i = $i + 1
|
||||
> end
|
||||
> end
|
||||
```
|
||||
@@ -0,0 +1,94 @@
|
||||
# Embedded Systems Reverse Engineering
|
||||
[Repository](https://github.com/mytechnotalent/Embedded-Hacking)
|
||||
|
||||
## Week 3
|
||||
Embedded System Analysis: Understanding the RP2350 Architecture w/ Comprehensive Firmware Analysis
|
||||
|
||||
### Non-Credit Practice Exercise 4 Solution: Find Your Main Function and Trace Back
|
||||
|
||||
#### Answers
|
||||
|
||||
##### Main Function Location
|
||||
|
||||
```gdb
|
||||
(gdb) info functions main
|
||||
0x10000234 int main(void);
|
||||
```
|
||||
|
||||
`main()` is at address **0x10000234**.
|
||||
|
||||
##### Disassembly of main()
|
||||
|
||||
```gdb
|
||||
(gdb) x/10i 0x10000234
|
||||
0x10000234 <main>: push {r7, lr}
|
||||
0x10000236 <main+2>: sub sp, #8
|
||||
0x10000238 <main+4>: add r7, sp, #0
|
||||
0x1000023a <main+6>: bl 0x100012c4 <stdio_init_all>
|
||||
0x1000023e <main+10>: movw r0, #404 @ 0x194
|
||||
0x10000242 <main+14>: movt r0, #4096 @ 0x1000
|
||||
0x10000246 <main+18>: bl 0x1000023c <__wrap_puts>
|
||||
0x1000024a <main+22>: b.n 0x1000023e <main+10>
|
||||
```
|
||||
|
||||
##### First Function Call
|
||||
|
||||
The first function call is at offset +6:
|
||||
```
|
||||
0x1000023a <main+6>: bl 0x100012c4 <stdio_init_all>
|
||||
```
|
||||
|
||||
`stdio_init_all()` initializes all standard I/O systems (USB CDC, UART) so `printf()` and `puts()` can output to the serial console.
|
||||
|
||||
##### Link Register (Caller Identification)
|
||||
|
||||
```gdb
|
||||
(gdb) b main
|
||||
(gdb) c
|
||||
(gdb) info registers lr
|
||||
lr 0x1000018b 268435851
|
||||
```
|
||||
|
||||
LR = **0x1000018b** (Thumb address), actual return address = **0x1000018a**.
|
||||
|
||||
##### Caller Disassembly
|
||||
|
||||
```gdb
|
||||
(gdb) x/10i 0x10000186
|
||||
0x10000186 <platform_entry>: ldr r1, [pc, #80]
|
||||
0x10000188 <platform_entry+2>: blx r1 → calls runtime_init()
|
||||
0x1000018a <platform_entry+4>: ldr r1, [pc, #80] → LR points here (return from main)
|
||||
0x1000018c <platform_entry+6>: blx r1 → THIS called main()
|
||||
0x1000018e <platform_entry+8>: ldr r1, [pc, #80]
|
||||
0x10000190 <platform_entry+10>: blx r1 → calls exit()
|
||||
0x10000192 <platform_entry+12>: bkpt 0x0000
|
||||
```
|
||||
|
||||
##### Complete Boot Chain
|
||||
|
||||
```
|
||||
Power On
|
||||
→ Bootrom (0x00000000)
|
||||
→ Vector Table (0x10000000)
|
||||
→ _reset_handler (0x1000015c)
|
||||
→ Data Copy & BSS Clear
|
||||
→ platform_entry (0x10000186)
|
||||
→ runtime_init() (first blx)
|
||||
→ main() (second blx) ← 0x10000234
|
||||
→ stdio_init_all() (first call in main)
|
||||
→ puts() loop (infinite)
|
||||
```
|
||||
|
||||
#### Reflection Answers
|
||||
|
||||
1. **Why does the link register point 4 bytes after the `blx` instruction that called main?**
|
||||
The LR stores the **return address**—the instruction to execute after `main()` returns. The `blx r1` instruction at `0x10000188` (which calls `runtime_init`) is 2 bytes, and the `blx r1` at `0x1000018c` (which calls `main`) is also 2 bytes. The LR is set to the instruction immediately following the `blx` that called `main()`, which is `0x1000018a` (the `ldr` after `runtime_init`'s call). Actually, `platform_entry+4` at `0x1000018a` is where execution resumes, and the actual `blx` that calls main is at `+6` (`0x1000018c`), so LR = `0x1000018e` + Thumb bit. The key point: LR always points to the next instruction after the branch, so the caller can resume where it left off.
|
||||
|
||||
2. **What would happen if `main()` tried to return (instead of looping forever)?**
|
||||
Execution would return to `platform_entry` at the address stored in LR. Looking at the disassembly, `platform_entry` would proceed to execute the third `blx r1` at offset +10, which calls `exit()`. The `exit()` function would perform cleanup and ultimately halt the processor. After `exit()`, there's a `bkpt` instruction as a safety net. In practice on bare-metal embedded systems, returning from `main()` is generally avoided because there's no OS to return to.
|
||||
|
||||
3. **How can you tell from the disassembly that main contains an infinite loop?**
|
||||
The instruction at `0x1000024a` is `b.n 0x1000023e <main+10>`, which is an **unconditional branch** back to the `movw r0, #404` instruction that loads the string address. This is a `b` (branch) with no condition code, meaning it always jumps backward. There is no path that reaches the end of the function or a `pop {r7, pc}` (return). The `push {r7, lr}` at the start saves the return address but it's never restored—the function loops forever.
|
||||
|
||||
4. **Why is `stdio_init_all()` called before the printf loop?**
|
||||
`stdio_init_all()` configures the hardware interfaces (USB CDC and/or UART) that `printf()`/`puts()` uses for output. Without this initialization, the serial output drivers are not set up—writes to stdout would go nowhere or cause a fault. It must be called exactly once before any I/O operation. Calling it inside the loop would repeatedly reinitialize the hardware, wasting time and potentially disrupting active connections.
|
||||
@@ -0,0 +1,238 @@
|
||||
# Embedded Systems Reverse Engineering
|
||||
[Repository](https://github.com/mytechnotalent/Embedded-Hacking)
|
||||
|
||||
## Week 3
|
||||
Embedded System Analysis: Understanding the RP2350 Architecture w/ Comprehensive Firmware Analysis
|
||||
|
||||
### Non-Credit Practice Exercise 4: Find Your Main Function and Trace Back
|
||||
|
||||
#### Objective
|
||||
Locate the `main()` function, examine its first instructions, identify the first function call, and trace backward to discover where `main()` was called from.
|
||||
|
||||
#### Prerequisites
|
||||
- Raspberry Pi Pico 2 with debug probe connected
|
||||
- OpenOCD and `arm-none-eabi-gdb` available
|
||||
- `build\0x0001_hello-world.elf` loaded
|
||||
- Understanding of function calls and the link register (LR) from previous weeks
|
||||
|
||||
#### Task Description
|
||||
You will use GDB to find `main()`, examine its disassembly, identify the initial function call (`stdio_init_all`), and use the link register to trace backward through the boot sequence.
|
||||
|
||||
#### Background Information
|
||||
|
||||
Key concepts:
|
||||
- **Link Register (LR)**: Stores the return address when a function is called
|
||||
- **Program Counter (PC)**: Points to the currently executing instruction
|
||||
- **Function prologue**: The setup code at the start of every function
|
||||
- **bl instruction**: "Branch with Link" - calls a function and stores return address in LR
|
||||
|
||||
#### Step-by-Step Instructions
|
||||
|
||||
##### Step 1: Connect and Halt
|
||||
|
||||
```gdb
|
||||
(gdb) target extended-remote :3333
|
||||
(gdb) monitor reset halt
|
||||
```
|
||||
|
||||
##### Step 2: Find the Main Function
|
||||
|
||||
```gdb
|
||||
(gdb) info functions main
|
||||
```
|
||||
|
||||
**Expected output:**
|
||||
```
|
||||
All functions matching regular expression "main":
|
||||
|
||||
File 0x0001_hello-world.c:
|
||||
0x10000234 int main(void);
|
||||
|
||||
Non-debugging symbols:
|
||||
0x10000186 platform_entry_arm_a
|
||||
...
|
||||
```
|
||||
|
||||
Note the address of `main`: **`0x10000234`**
|
||||
|
||||
##### Step 3: Examine Instructions at Main
|
||||
|
||||
```gdb
|
||||
(gdb) x/10i 0x10000234
|
||||
```
|
||||
|
||||
**Expected output:**
|
||||
```
|
||||
0x10000234 <main>: push {r7, lr}
|
||||
0x10000236 <main+2>: sub sp, #8
|
||||
0x10000238 <main+4>: add r7, sp, #0
|
||||
0x1000023a <main+6>: bl 0x100012c4 <stdio_init_all>
|
||||
0x1000023e <main+10>: movw r0, #404 @ 0x194
|
||||
0x10000242 <main+14>: movt r0, #4096 @ 0x1000
|
||||
0x10000246 <main+18>: bl 0x1000023c <__wrap_puts>
|
||||
0x1000024a <main+22>: b.n 0x1000023e <main+10>
|
||||
0x1000024c <runtime_init>: push {r3, r4, r5, r6, r7, lr}
|
||||
```
|
||||
|
||||
##### Step 4: Identify the First Function Call
|
||||
|
||||
The first function call in `main()` is:
|
||||
```
|
||||
0x1000023a <main+6>: bl 0x100012c4 <stdio_init_all>
|
||||
```
|
||||
|
||||
**What does this function do?**
|
||||
|
||||
```gdb
|
||||
(gdb) info functions stdio_init_all
|
||||
```
|
||||
|
||||
**Answer:** `stdio_init_all()` initializes all standard I/O systems (USB, UART, etc.) so `printf()` works.
|
||||
|
||||
##### Step 5: Set a Breakpoint at Main
|
||||
|
||||
```gdb
|
||||
(gdb) b main
|
||||
(gdb) c
|
||||
```
|
||||
|
||||
**Expected output:**
|
||||
```
|
||||
Breakpoint 1, main () at 0x0001_hello-world.c:5
|
||||
5 stdio_init_all();
|
||||
```
|
||||
|
||||
##### Step 6: Examine the Link Register
|
||||
|
||||
When stopped at `main()`, check what's in the link register:
|
||||
|
||||
```gdb
|
||||
(gdb) info registers lr
|
||||
```
|
||||
|
||||
**Expected output:**
|
||||
```
|
||||
lr 0x1000018b 268435851
|
||||
```
|
||||
|
||||
The LR contains the return address - where execution will go when `main()` returns.
|
||||
|
||||
##### Step 7: Disassemble the Caller
|
||||
|
||||
Subtract 1 to remove the Thumb bit and disassemble:
|
||||
|
||||
```gdb
|
||||
(gdb) x/10i 0x1000018a
|
||||
```
|
||||
|
||||
**Expected output:**
|
||||
```
|
||||
0x10000186 <platform_entry>: ldr r1, [pc, #80]
|
||||
0x10000188 <platform_entry+2>: blx r1
|
||||
0x1000018a <platform_entry+4>: ldr r1, [pc, #80] ? LR points here
|
||||
0x1000018c <platform_entry+6>: blx r1 ? This called main
|
||||
0x1000018e <platform_entry+8>: ldr r1, [pc, #80]
|
||||
0x10000190 <platform_entry+10>: blx r1
|
||||
0x10000192 <platform_entry+12>: bkpt 0x0000
|
||||
```
|
||||
|
||||
##### Step 8: Understand the Call Chain
|
||||
|
||||
Working backward from `main()`:
|
||||
|
||||
```
|
||||
platform_entry (0x10000186)
|
||||
? calls (blx at +2)
|
||||
runtime_init() (0x1000024c)
|
||||
? calls (blx at +6)
|
||||
main() (0x10000234) ? We are here
|
||||
? will call (blx at +6)
|
||||
stdio_init_all() (0x100012c4)
|
||||
```
|
||||
|
||||
##### Step 9: Verify Platform Entry Calls Main
|
||||
|
||||
Look at what `platform_entry` loads before the `blx`:
|
||||
|
||||
```gdb
|
||||
(gdb) x/x 0x100001dc
|
||||
```
|
||||
|
||||
This is the address loaded into r1 before calling `blx`. It should point to `main()`.
|
||||
|
||||
**Expected output:**
|
||||
```
|
||||
0x100001dc <data_cpy_table+60>: 0x10000235
|
||||
```
|
||||
|
||||
Note: `0x10000235` = `0x10000234` + 1 (Thumb bit), which is the address of `main()`!
|
||||
|
||||
##### Step 10: Complete the Boot Trace
|
||||
|
||||
You've now traced the complete path:
|
||||
|
||||
```
|
||||
1. Reset (Power-on)
|
||||
?
|
||||
2. Bootrom (0x00000000)
|
||||
?
|
||||
3. Vector Table (0x10000000)
|
||||
?
|
||||
4. _reset_handler (0x1000015c)
|
||||
?
|
||||
5. Data Copy & BSS Clear
|
||||
?
|
||||
6. platform_entry (0x10000186)
|
||||
?
|
||||
7. runtime_init() (first call)
|
||||
?
|
||||
8. main() (second call) ? Exercise focus
|
||||
?
|
||||
9. stdio_init_all() (first line of main)
|
||||
```
|
||||
|
||||
#### Expected Output
|
||||
- `main()` is at address `0x10000234`
|
||||
- First function call is `stdio_init_all()` at offset +6
|
||||
- Link register points to `platform_entry+4` (0x1000018a)
|
||||
- `platform_entry` makes three function calls: runtime_init, main, and exit
|
||||
|
||||
#### Questions for Reflection
|
||||
|
||||
###### Question 1: Why does the link register point 4 bytes after the `blx` instruction that called main?
|
||||
|
||||
###### Question 2: What would happen if `main()` tried to return (instead of looping forever)?
|
||||
|
||||
###### Question 3: How can you tell from the disassembly that main contains an infinite loop?
|
||||
|
||||
###### Question 4: Why is `stdio_init_all()` called before the printf loop?
|
||||
|
||||
#### Tips and Hints
|
||||
- Use `bt` (backtrace) to see the call stack
|
||||
- Remember to account for Thumb mode when reading addresses from LR
|
||||
- Use `info frame` to see detailed information about the current stack frame
|
||||
- The `push {r7, lr}` at the start of main saves the return address
|
||||
|
||||
#### Next Steps
|
||||
- Set a breakpoint at `stdio_init_all()` and step through its initialization
|
||||
- Examine what happens after `main()` by looking at `exit()` function
|
||||
- Try Exercise 5 in Ghidra for static analysis of the boot sequence
|
||||
|
||||
#### Additional Challenge
|
||||
|
||||
Create a GDB command to automatically trace the call chain:
|
||||
|
||||
```gdb
|
||||
(gdb) define calltrace
|
||||
> set $depth = 0
|
||||
> set $addr = $pc
|
||||
> while $depth < 10
|
||||
> printf "%d: ", $depth
|
||||
> info symbol $addr
|
||||
> set $addr = *(int*)($lr - 4)
|
||||
> set $depth = $depth + 1
|
||||
> end
|
||||
> end
|
||||
```
|
||||
|
||||
Then try stepping through functions and running `calltrace` at each level to build a complete call graph.
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,79 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
|
||||
<style>
|
||||
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
|
||||
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
|
||||
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
|
||||
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
|
||||
.dim{font:20px 'Courier New',monospace;fill:#888}
|
||||
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
|
||||
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
|
||||
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
|
||||
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
|
||||
.badge{stroke:#00ff41;rx:14}
|
||||
</style>
|
||||
<rect class="bg" width="1200" height="800"/>
|
||||
|
||||
<!-- Background grid decoration -->
|
||||
<g opacity="0.06">
|
||||
<line x1="0" y1="100" x2="1200" y2="100" stroke="#00ff41" stroke-width="1"/>
|
||||
<line x1="0" y1="200" x2="1200" y2="200" stroke="#00ff41" stroke-width="1"/>
|
||||
<line x1="0" y1="300" x2="1200" y2="300" stroke="#00ff41" stroke-width="1"/>
|
||||
<line x1="0" y1="400" x2="1200" y2="400" stroke="#00ff41" stroke-width="1"/>
|
||||
<line x1="0" y1="500" x2="1200" y2="500" stroke="#00ff41" stroke-width="1"/>
|
||||
<line x1="0" y1="600" x2="1200" y2="600" stroke="#00ff41" stroke-width="1"/>
|
||||
<line x1="0" y1="700" x2="1200" y2="700" stroke="#00ff41" stroke-width="1"/>
|
||||
<line x1="200" y1="0" x2="200" y2="800" stroke="#00ff41" stroke-width="1"/>
|
||||
<line x1="400" y1="0" x2="400" y2="800" stroke="#00ff41" stroke-width="1"/>
|
||||
<line x1="600" y1="0" x2="600" y2="800" stroke="#00ff41" stroke-width="1"/>
|
||||
<line x1="800" y1="0" x2="800" y2="800" stroke="#00ff41" stroke-width="1"/>
|
||||
<line x1="1000" y1="0" x2="1000" y2="800" stroke="#00ff41" stroke-width="1"/>
|
||||
</g>
|
||||
|
||||
<!-- Hex rain decoration -->
|
||||
<g opacity="0.04" font-family="'Courier New',monospace" font-size="14" fill="#00ff41">
|
||||
<text x="50" y="80">4F 70 65 6E 4F 43 44</text>
|
||||
<text x="900" y="120">10 00 02 34 08 B5 01</text>
|
||||
<text x="150" y="180">47 44 42 20 52 45 56</text>
|
||||
<text x="800" y="240">20 08 20 00 FF AA 00</text>
|
||||
<text x="80" y="350">52 50 32 33 35 30 00</text>
|
||||
<text x="950" y="380">0A 0A 0F 12 12 1A 1A</text>
|
||||
<text x="100" y="520">41 52 4D 76 38 2D 4D</text>
|
||||
<text x="870" y="560">00 FF 41 00 D4 FF 88</text>
|
||||
<text x="60" y="680">47 48 49 44 52 41 00</text>
|
||||
<text x="920" y="720">FF 00 40 C0 C0 C0 00</text>
|
||||
</g>
|
||||
|
||||
<!-- Corner accents -->
|
||||
<polyline points="30,30 30,80 80,80" fill="none" stroke="#00ff41" stroke-width="2" opacity="0.3"/>
|
||||
<polyline points="1170,30 1170,80 1120,80" fill="none" stroke="#00ff41" stroke-width="2" opacity="0.3"/>
|
||||
<polyline points="30,770 30,720 80,720" fill="none" stroke="#00ff41" stroke-width="2" opacity="0.3"/>
|
||||
<polyline points="1170,770 1170,720 1120,720" fill="none" stroke="#00ff41" stroke-width="2" opacity="0.3"/>
|
||||
|
||||
<!-- Top accent line -->
|
||||
<rect x="100" y="140" width="1000" height="2" fill="#00ff41" opacity="0.4"/>
|
||||
|
||||
<!-- Course Title -->
|
||||
<text x="600" y="210" text-anchor="middle" font-family="'Courier New',monospace" font-size="56" font-weight="bold" fill="#00ff41">Embedded Systems</text>
|
||||
<text x="600" y="278" text-anchor="middle" font-family="'Courier New',monospace" font-size="56" font-weight="bold" fill="#00ff41">Reverse Engineering</text>
|
||||
|
||||
<!-- Divider -->
|
||||
<rect x="300" y="310" width="600" height="2" fill="#00d4ff" opacity="0.6"/>
|
||||
|
||||
<!-- Week Number -->
|
||||
<text x="600" y="380" text-anchor="middle" font-family="'Courier New',monospace" font-size="42" font-weight="bold" fill="#00d4ff">// WEEK 03</text>
|
||||
|
||||
<!-- Week Topic -->
|
||||
<text x="600" y="440" text-anchor="middle" font-family="'Courier New',monospace" font-size="28" fill="#c0c0c0">Embedded System Analysis:</text>
|
||||
<text x="600" y="478" text-anchor="middle" font-family="'Courier New',monospace" font-size="28" fill="#c0c0c0">Understanding the RP2350 Architecture</text>
|
||||
<text x="600" y="516" text-anchor="middle" font-family="'Courier New',monospace" font-size="28" fill="#c0c0c0">w/ Comprehensive Firmware Analysis</text>
|
||||
|
||||
<!-- Bottom accent line -->
|
||||
<rect x="100" y="570" width="1000" height="2" fill="#00ff41" opacity="0.4"/>
|
||||
|
||||
<!-- University -->
|
||||
<text x="600" y="635" text-anchor="middle" font-family="'Courier New',monospace" font-size="36" font-weight="bold" fill="#ffaa00">George Mason University</text>
|
||||
|
||||
<!-- Bottom badge -->
|
||||
<rect x="400" y="670" width="400" height="40" rx="20" fill="none" stroke="#00ff41" stroke-width="1.5" opacity="0.5"/>
|
||||
<text x="600" y="697" text-anchor="middle" font-family="'Courier New',monospace" font-size="20" fill="#00ff41" opacity="0.7">RP2350 // ARM Cortex-M33</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.4 KiB |
@@ -0,0 +1,70 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
|
||||
<style>
|
||||
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
|
||||
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
|
||||
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
|
||||
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
|
||||
.dim{font:20px 'Courier New',monospace;fill:#888}
|
||||
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
|
||||
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
|
||||
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
|
||||
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
|
||||
.badge{stroke:#00ff41;rx:14}
|
||||
</style>
|
||||
<rect class="bg" width="1200" height="800"/>
|
||||
|
||||
<!-- Title -->
|
||||
<text x="600" y="52" text-anchor="middle" class="title">RP2350 Boot Sequence</text>
|
||||
<text x="600" y="88" text-anchor="middle" class="dim">Power-On to main() — 5 Steps</text>
|
||||
|
||||
<!-- Step 1 -->
|
||||
<rect x="40" y="110" width="1120" height="70" rx="6" fill="#12121a" stroke="#ffaa00" stroke-width="2"/>
|
||||
<text x="60" y="137" class="amb">STEP 1</text>
|
||||
<text x="220" y="137" class="txt">Power On</text>
|
||||
<text x="60" y="167" class="dim">Cortex-M33 wakes, execution at 0x00000000 (Bootrom)</text>
|
||||
|
||||
<!-- Arrow -->
|
||||
<text x="600" y="198" text-anchor="middle" class="grn">▼</text>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<rect x="40" y="208" width="1120" height="70" rx="6" fill="#12121a" stroke="#ffaa00" stroke-width="2"/>
|
||||
<text x="60" y="235" class="amb">STEP 2</text>
|
||||
<text x="220" y="235" class="txt">Bootrom Executes</text>
|
||||
<text x="60" y="265" class="dim">32KB on-chip ROM — finds IMAGE_DEF at 0x10000000</text>
|
||||
|
||||
<!-- Arrow -->
|
||||
<text x="600" y="296" text-anchor="middle" class="grn">▼</text>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<rect x="40" y="306" width="1120" height="70" rx="6" fill="#12121a" stroke="#ffaa00" stroke-width="2"/>
|
||||
<text x="60" y="333" class="amb">STEP 3</text>
|
||||
<text x="220" y="333" class="txt">Flash XIP Setup (bootrom-managed)</text>
|
||||
<text x="60" y="363" class="dim">Bootrom configures flash interface & XIP (no boot2 on RP2350)</text>
|
||||
|
||||
<!-- Arrow -->
|
||||
<text x="600" y="394" text-anchor="middle" class="grn">▼</text>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<rect x="40" y="404" width="1120" height="90" rx="6" fill="#12121a" stroke="#ffaa00" stroke-width="2"/>
|
||||
<text x="60" y="431" class="amb">STEP 4</text>
|
||||
<text x="220" y="431" class="txt">Vector Table & Reset Handler</text>
|
||||
<text x="60" y="463" class="dim">Reads SP from offset 0x00 -> 0x20082000</text>
|
||||
<text x="60" y="489" class="dim">Reads Reset Handler from 0x04 -> 0x1000015d</text>
|
||||
|
||||
<!-- Arrow -->
|
||||
<text x="600" y="514" text-anchor="middle" class="grn">▼</text>
|
||||
|
||||
<!-- Step 5 -->
|
||||
<rect x="40" y="524" width="1120" height="110" rx="6" fill="#12121a" stroke="#ffaa00" stroke-width="2"/>
|
||||
<text x="60" y="551" class="amb">STEP 5</text>
|
||||
<text x="220" y="551" class="txt">C Runtime Startup (crt0.S)</text>
|
||||
<text x="60" y="583" class="dim">Copy .data from flash -> RAM</text>
|
||||
<text x="60" y="608" class="dim">Zero .bss section</text>
|
||||
<text x="60" y="633" class="dim">Call runtime_init() -> main()</text>
|
||||
|
||||
<!-- Bottom summary -->
|
||||
<rect x="40" y="660" width="1120" height="110" rx="6" fill="#12121a" stroke="#ffaa00" stroke-width="2"/>
|
||||
<text x="60" y="695" class="sub">Key Insight</text>
|
||||
<text x="60" y="730" class="txt">Your main() is the LAST thing to run.</text>
|
||||
<text x="60" y="760" class="txt">All 5 steps must complete first!</text>
|
||||
</svg>
|
||||
@@ -0,0 +1,84 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
|
||||
<style>
|
||||
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
|
||||
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
|
||||
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
|
||||
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
|
||||
.dim{font:20px 'Courier New',monospace;fill:#888}
|
||||
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
|
||||
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
|
||||
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
|
||||
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
|
||||
.badge{stroke:#00ff41;rx:14}
|
||||
</style>
|
||||
<rect class="bg" width="1200" height="800"/>
|
||||
|
||||
<!-- Title -->
|
||||
<text x="600" y="52" text-anchor="middle" class="title">The Bootrom</text>
|
||||
<text x="600" y="88" text-anchor="middle" class="dim">32KB Factory-Programmed ROM — Where It All Begins</text>
|
||||
|
||||
<!-- Left Panel: Properties -->
|
||||
<rect x="40" y="110" width="540" height="340" rx="8" class="pnl"/>
|
||||
<text x="60" y="148" class="sub">Bootrom Properties</text>
|
||||
|
||||
<rect x="60" y="170" width="500" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
|
||||
<text x="75" y="198" class="txt">Size</text>
|
||||
<text x="340" y="198" class="grn">32 KB</text>
|
||||
|
||||
<rect x="60" y="222" width="500" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
|
||||
<text x="75" y="250" class="txt">Location</text>
|
||||
<text x="340" y="250" class="cyn">0x00000000</text>
|
||||
|
||||
<rect x="60" y="274" width="500" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
|
||||
<text x="75" y="302" class="txt">Modifiable?</text>
|
||||
<text x="340" y="302" class="red">NO — mask ROM</text>
|
||||
|
||||
<rect x="60" y="326" width="500" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
|
||||
<text x="75" y="354" class="txt">Purpose</text>
|
||||
<text x="340" y="354" class="amb">Boot the chip</text>
|
||||
|
||||
<text x="60" y="420" class="dim">Burned into silicon at factory</text>
|
||||
<text x="60" y="445" class="dim">Like BIOS in your computer</text>
|
||||
|
||||
<!-- Right Panel: What It Does -->
|
||||
<rect x="620" y="110" width="540" height="340" rx="8" class="pnl"/>
|
||||
<text x="640" y="148" class="sub">What It Does</text>
|
||||
|
||||
<rect x="640" y="170" width="500" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
|
||||
<text x="655" y="198" class="grn">1.</text>
|
||||
<text x="700" y="198" class="txt">Initialize hardware</text>
|
||||
|
||||
<rect x="640" y="222" width="500" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
|
||||
<text x="655" y="250" class="grn">2.</text>
|
||||
<text x="700" y="250" class="txt">Check boot sources</text>
|
||||
|
||||
<rect x="640" y="274" width="500" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
|
||||
<text x="655" y="302" class="grn">3.</text>
|
||||
<text x="700" y="302" class="txt">Validate IMAGE_DEF</text>
|
||||
|
||||
<rect x="640" y="326" width="500" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
|
||||
<text x="655" y="354" class="grn">4.</text>
|
||||
<text x="700" y="354" class="txt">Configure flash</text>
|
||||
|
||||
<rect x="640" y="378" width="500" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
|
||||
<text x="655" y="406" class="grn">5.</text>
|
||||
<text x="700" y="406" class="txt">Jump to your code</text>
|
||||
|
||||
<!-- Bottom Panel: IMAGE_DEF -->
|
||||
<rect x="40" y="475" width="1120" height="295" rx="8" class="pnl"/>
|
||||
<text x="60" y="513" class="sub">IMAGE_DEF — Magic Markers</text>
|
||||
<text x="60" y="548" class="dim">Bootrom looks for these to validate firmware</text>
|
||||
|
||||
<rect x="60" y="565" width="1080" height="50" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="2"/>
|
||||
<text x="80" y="598" class="grn">Start Marker</text>
|
||||
<text x="380" y="598" class="cyn">0xFFFFDED3</text>
|
||||
<text x="680" y="598" class="dim">"I'm a valid Pico binary!"</text>
|
||||
|
||||
<rect x="60" y="625" width="1080" height="50" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="2"/>
|
||||
<text x="80" y="658" class="grn">End Marker</text>
|
||||
<text x="380" y="658" class="cyn">0xAB123579</text>
|
||||
<text x="680" y="658" class="dim">"End of header block"</text>
|
||||
|
||||
<text x="60" y="718" class="txt">Bootrom reads flash at 0x10000000,</text>
|
||||
<text x="60" y="748" class="txt">finds these markers, then boots.</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.9 KiB |
@@ -0,0 +1,74 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
|
||||
<style>
|
||||
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
|
||||
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
|
||||
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
|
||||
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
|
||||
.dim{font:20px 'Courier New',monospace;fill:#888}
|
||||
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
|
||||
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
|
||||
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
|
||||
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
|
||||
.badge{stroke:#00ff41;rx:14}
|
||||
</style>
|
||||
<rect class="bg" width="1200" height="800"/>
|
||||
|
||||
<!-- Title -->
|
||||
<text x="600" y="52" text-anchor="middle" class="title">XIP — Execute In Place</text>
|
||||
<text x="600" y="88" text-anchor="middle" class="dim">Run Code Directly from Flash — No Copy Needed</text>
|
||||
|
||||
<!-- Left Panel: Analogy -->
|
||||
<rect x="40" y="110" width="540" height="220" rx="8" class="pnl"/>
|
||||
<text x="60" y="148" class="sub">Book Analogy</text>
|
||||
|
||||
<rect x="60" y="168" width="500" height="60" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
|
||||
<text x="75" y="195" class="red">Without XIP</text>
|
||||
<text x="75" y="220" class="dim">Photocopy every page, read copy</text>
|
||||
|
||||
<rect x="60" y="240" width="500" height="60" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
|
||||
<text x="75" y="267" class="grn">With XIP</text>
|
||||
<text x="75" y="292" class="dim">Read directly from the book!</text>
|
||||
|
||||
<!-- Right Panel: Advantages -->
|
||||
<rect x="620" y="110" width="540" height="220" rx="8" class="pnl"/>
|
||||
<text x="640" y="148" class="sub">Why Use XIP?</text>
|
||||
|
||||
<rect x="640" y="168" width="500" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
|
||||
<text x="655" y="196" class="grn">Saves RAM</text>
|
||||
<text x="900" y="196" class="dim">Code stays in flash</text>
|
||||
|
||||
<rect x="640" y="220" width="500" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
|
||||
<text x="655" y="248" class="grn">Faster Boot</text>
|
||||
<text x="900" y="248" class="dim">No bulk copy needed</text>
|
||||
|
||||
<rect x="640" y="272" width="500" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
|
||||
<text x="655" y="300" class="grn">Simpler</text>
|
||||
<text x="900" y="300" class="dim">Less memory mgmt</text>
|
||||
|
||||
<!-- Bottom Panel: Flash Layout at 0x10000000 -->
|
||||
<rect x="40" y="355" width="1120" height="415" rx="8" class="pnl"/>
|
||||
<text x="60" y="393" class="sub">XIP Flash Region at 0x10000000</text>
|
||||
|
||||
<!-- Vector Table block -->
|
||||
<rect x="60" y="415" width="1080" height="80" rx="4" fill="#0f1a0f" stroke="#00ff41" stroke-width="2"/>
|
||||
<text x="80" y="445" class="grn">Vector Table</text>
|
||||
<text x="80" y="475" class="dim">SP at offset 0x00 | Reset Handler at offset 0x04 | Exception handlers...</text>
|
||||
|
||||
<!-- Your Code block -->
|
||||
<rect x="60" y="510" width="1080" height="80" rx="4" fill="#0a0a0f" stroke="#00d4ff" stroke-width="2"/>
|
||||
<text x="80" y="540" class="cyn">Your Code</text>
|
||||
<text x="80" y="570" class="dim">_reset_handler | main() | other functions</text>
|
||||
|
||||
<!-- Read-Only Data block -->
|
||||
<rect x="60" y="605" width="1080" height="80" rx="4" fill="#0a0a0f" stroke="#ffaa00" stroke-width="2"/>
|
||||
<text x="80" y="635" class="amb">Read-Only Data</text>
|
||||
<text x="80" y="665" class="dim">Strings like "hello, world" | constant values</text>
|
||||
|
||||
<!-- Address labels -->
|
||||
<text x="1040" y="445" class="dim" text-anchor="end">0x10000000</text>
|
||||
<text x="1040" y="540" class="dim" text-anchor="end">0x100001xx</text>
|
||||
<text x="1040" y="635" class="dim" text-anchor="end">0x10001xxx</text>
|
||||
|
||||
<text x="60" y="730" class="txt">CPU fetches instructions directly</text>
|
||||
<text x="60" y="760" class="txt">from flash via XIP cache.</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.6 KiB |
@@ -0,0 +1,80 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
|
||||
<style>
|
||||
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
|
||||
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
|
||||
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
|
||||
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
|
||||
.dim{font:20px 'Courier New',monospace;fill:#888}
|
||||
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
|
||||
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
|
||||
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
|
||||
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
|
||||
.badge{stroke:#00ff41;rx:14}
|
||||
</style>
|
||||
<rect class="bg" width="1200" height="800"/>
|
||||
|
||||
<!-- Title -->
|
||||
<text x="600" y="52" text-anchor="middle" class="title">The Vector Table</text>
|
||||
<text x="600" y="88" text-anchor="middle" class="dim">CPU's Instruction Manual at 0x10000000</text>
|
||||
|
||||
<!-- Main Panel -->
|
||||
<rect x="40" y="110" width="1120" height="440" rx="8" class="pnl"/>
|
||||
<text x="60" y="148" class="sub">Vector Table Layout</text>
|
||||
|
||||
<!-- Header row -->
|
||||
<rect x="60" y="168" width="1080" height="42" rx="4" fill="#1a1a2e"/>
|
||||
<text x="80" y="196" class="cyn">Offset</text>
|
||||
<text x="220" y="196" class="cyn">Address</text>
|
||||
<text x="440" y="196" class="cyn">Value</text>
|
||||
<text x="680" y="196" class="cyn">Meaning</text>
|
||||
|
||||
<!-- Row 0x00 -->
|
||||
<rect x="60" y="220" width="1080" height="50" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="2"/>
|
||||
<text x="80" y="252" class="grn">0x00</text>
|
||||
<text x="220" y="252" class="txt">0x10000000</text>
|
||||
<text x="440" y="252" class="grn">0x20082000</text>
|
||||
<text x="680" y="252" class="txt">Initial SP</text>
|
||||
|
||||
<!-- Row 0x04 -->
|
||||
<rect x="60" y="280" width="1080" height="50" rx="4" fill="#0a0a0f" stroke="#00d4ff" stroke-width="2"/>
|
||||
<text x="80" y="312" class="cyn">0x04</text>
|
||||
<text x="220" y="312" class="txt">0x10000004</text>
|
||||
<text x="440" y="312" class="cyn">0x1000015D</text>
|
||||
<text x="680" y="312" class="txt">Reset Handler</text>
|
||||
|
||||
<!-- Row 0x08 -->
|
||||
<rect x="60" y="340" width="1080" height="50" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
|
||||
<text x="80" y="372" class="dim">0x08</text>
|
||||
<text x="220" y="372" class="txt">0x10000008</text>
|
||||
<text x="440" y="372" class="txt">0x1000011B</text>
|
||||
<text x="680" y="372" class="txt">NMI Handler</text>
|
||||
|
||||
<!-- Row 0x0C -->
|
||||
<rect x="60" y="400" width="1080" height="50" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
|
||||
<text x="80" y="432" class="dim">0x0C</text>
|
||||
<text x="220" y="432" class="txt">0x1000000C</text>
|
||||
<text x="440" y="432" class="txt">0x1000011D</text>
|
||||
<text x="680" y="432" class="txt">HardFault Handler</text>
|
||||
|
||||
<!-- GDB command -->
|
||||
<rect x="60" y="470" width="1080" height="50" rx="4" fill="#0a0a0f" stroke="#ffaa00" stroke-width="1"/>
|
||||
<text x="80" y="502" class="amb">GDB:</text>
|
||||
<text x="180" y="502" class="txt">x/4x 0x10000000</text>
|
||||
|
||||
<!-- Bottom Panel: What happens -->
|
||||
<rect x="40" y="575" width="540" height="195" rx="8" class="pnl"/>
|
||||
<text x="60" y="613" class="sub">On Power-On</text>
|
||||
<text x="60" y="650" class="txt">1. CPU reads SP from 0x00</text>
|
||||
<text x="60" y="682" class="txt">2. Sets SP = 0x20082000</text>
|
||||
<text x="60" y="714" class="txt">3. Reads Reset from 0x04</text>
|
||||
<text x="60" y="746" class="txt">4. Jumps to 0x1000015C</text>
|
||||
|
||||
<!-- Bottom Right: Handlers -->
|
||||
<rect x="620" y="575" width="540" height="195" rx="8" class="pnl"/>
|
||||
<text x="640" y="613" class="sub">Default Handlers</text>
|
||||
<text x="640" y="650" class="txt">NMI, HardFault, SVCall,</text>
|
||||
<text x="640" y="682" class="txt">PendSV, SysTick all use:</text>
|
||||
<rect x="660" y="700" width="480" height="42" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
|
||||
<text x="680" y="728" class="red">bkpt 0x0000</text>
|
||||
<text x="880" y="728" class="dim"><- stops debugger</text>
|
||||
</svg>
|
||||
@@ -0,0 +1,70 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
|
||||
<style>
|
||||
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
|
||||
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
|
||||
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
|
||||
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
|
||||
.dim{font:20px 'Courier New',monospace;fill:#888}
|
||||
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
|
||||
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
|
||||
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
|
||||
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
|
||||
.badge{stroke:#00ff41;rx:14}
|
||||
</style>
|
||||
<rect class="bg" width="1200" height="800"/>
|
||||
|
||||
<!-- Title -->
|
||||
<text x="600" y="52" text-anchor="middle" class="title">Thumb Mode Addressing</text>
|
||||
<text x="600" y="88" text-anchor="middle" class="dim">Why Addresses End in Odd Numbers</text>
|
||||
|
||||
<!-- Top Panel: The Rule -->
|
||||
<rect x="40" y="110" width="1120" height="200" rx="8" class="pnl"/>
|
||||
<text x="60" y="148" class="sub">The LSB Rule</text>
|
||||
<text x="60" y="185" class="txt">ARM Cortex-M uses the Least Significant</text>
|
||||
<text x="60" y="215" class="txt">Bit (LSB) to indicate instruction mode:</text>
|
||||
|
||||
<!-- LSB = 1 -->
|
||||
<rect x="60" y="240" width="520" height="50" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="2"/>
|
||||
<text x="80" y="272" class="grn">LSB = 1 (odd)</text>
|
||||
<text x="370" y="272" class="txt">Thumb mode</text>
|
||||
|
||||
<!-- LSB = 0 -->
|
||||
<rect x="620" y="240" width="520" height="50" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
|
||||
<text x="640" y="272" class="red">LSB = 0 (even)</text>
|
||||
<text x="940" y="272" class="dim">ARM mode</text>
|
||||
|
||||
<!-- Middle Panel: Example -->
|
||||
<rect x="40" y="335" width="1120" height="210" rx="8" class="pnl"/>
|
||||
<text x="60" y="373" class="sub">Reset Handler Example</text>
|
||||
|
||||
<text x="60" y="415" class="txt">Vector table stores:</text>
|
||||
<text x="460" y="415" class="cyn">0x1000015D</text>
|
||||
|
||||
<text x="60" y="460" class="txt">Actual code address:</text>
|
||||
<text x="460" y="460" class="grn">0x1000015C</text>
|
||||
|
||||
<text x="60" y="505" class="txt">The +1 means:</text>
|
||||
<text x="460" y="505" class="amb">"Use Thumb mode"</text>
|
||||
|
||||
<!-- Bottom: GDB vs Ghidra -->
|
||||
<rect x="40" y="570" width="540" height="200" rx="8" class="pnl"/>
|
||||
<text x="60" y="608" class="sub">GDB Shows</text>
|
||||
<rect x="60" y="625" width="500" height="50" rx="4" fill="#0a0a0f" stroke="#00d4ff" stroke-width="1"/>
|
||||
<text x="80" y="657" class="cyn">0x1000015D</text>
|
||||
<text x="320" y="657" class="dim">with Thumb bit</text>
|
||||
|
||||
<rect x="60" y="685" width="500" height="50" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
|
||||
<text x="80" y="717" class="txt">Vector table raw value</text>
|
||||
|
||||
<!-- Ghidra -->
|
||||
<rect x="620" y="570" width="540" height="200" rx="8" class="pnl"/>
|
||||
<text x="640" y="608" class="sub">Ghidra Shows</text>
|
||||
<rect x="640" y="625" width="500" height="50" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
|
||||
<text x="660" y="657" class="grn">0x1000015C</text>
|
||||
<text x="900" y="657" class="dim">actual address</text>
|
||||
|
||||
<rect x="640" y="685" width="500" height="50" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
|
||||
<text x="660" y="717" class="txt">Real instruction location</text>
|
||||
|
||||
<text x="600" y="757" text-anchor="middle" class="amb">Both are correct — just displayed differently!</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.2 KiB |
@@ -0,0 +1,69 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
|
||||
<style>
|
||||
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
|
||||
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
|
||||
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
|
||||
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
|
||||
.dim{font:20px 'Courier New',monospace;fill:#888}
|
||||
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
|
||||
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
|
||||
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
|
||||
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
|
||||
.badge{stroke:#00ff41;rx:14}
|
||||
</style>
|
||||
<rect class="bg" width="1200" height="800"/>
|
||||
|
||||
<!-- Title -->
|
||||
<text x="600" y="52" text-anchor="middle" class="title">Linker Script Memory Map</text>
|
||||
<text x="600" y="88" text-anchor="middle" class="dim">memmap_default.ld — Where Everything Lives</text>
|
||||
|
||||
<!-- Main Panel: Memory Regions -->
|
||||
<rect x="40" y="110" width="1120" height="380" rx="8" class="pnl"/>
|
||||
<text x="60" y="148" class="sub">Memory Regions</text>
|
||||
|
||||
<!-- Flash -->
|
||||
<rect x="60" y="168" width="1080" height="60" rx="4" fill="#0f1a0f" stroke="#00ff41" stroke-width="2"/>
|
||||
<text x="80" y="198" class="grn">Flash (XIP)</text>
|
||||
<text x="380" y="198" class="cyn">0x10000000</text>
|
||||
<text x="640" y="198" class="txt">varies</text>
|
||||
<text x="820" y="198" class="dim">Your code (read-only)</text>
|
||||
|
||||
<!-- RAM -->
|
||||
<rect x="60" y="240" width="1080" height="60" rx="4" fill="#0a0a1f" stroke="#00d4ff" stroke-width="2"/>
|
||||
<text x="80" y="270" class="cyn">RAM</text>
|
||||
<text x="380" y="270" class="cyn">0x20000000</text>
|
||||
<text x="640" y="270" class="txt">512 KB</text>
|
||||
<text x="820" y="270" class="dim">Main RAM (r/w)</text>
|
||||
|
||||
<!-- SCRATCH_X -->
|
||||
<rect x="60" y="312" width="1080" height="60" rx="4" fill="#0a0a0f" stroke="#ffaa00" stroke-width="1"/>
|
||||
<text x="80" y="342" class="amb">SCRATCH_X</text>
|
||||
<text x="380" y="342" class="cyn">0x20080000</text>
|
||||
<text x="640" y="342" class="txt">4 KB</text>
|
||||
<text x="820" y="342" class="dim">Core 0 scratch (HW: SRAM8)</text>
|
||||
|
||||
<!-- SCRATCH_Y -->
|
||||
<rect x="60" y="384" width="1080" height="60" rx="4" fill="#1a0a0a" stroke="#ff0040" stroke-width="2"/>
|
||||
<text x="80" y="414" class="red">SCRATCH_Y</text>
|
||||
<text x="380" y="414" class="cyn">0x20081000</text>
|
||||
<text x="640" y="414" class="txt">4 KB</text>
|
||||
<text x="820" y="414" class="dim">Core 0 stack! (HW: SRAM9)</text>
|
||||
|
||||
<!-- Bottom Panel: Stack Calculation -->
|
||||
<rect x="40" y="515" width="1120" height="255" rx="8" class="pnl"/>
|
||||
<text x="60" y="553" class="sub">Stack Pointer Calculation</text>
|
||||
|
||||
<text x="60" y="593" class="txt">__StackTop = ORIGIN(SCRATCH_Y)</text>
|
||||
<text x="60" y="623" class="txt"> + LENGTH(SCRATCH_Y)</text>
|
||||
|
||||
<rect x="60" y="650" width="1080" height="100" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="2"/>
|
||||
<text x="80" y="682" class="amb">ORIGIN</text>
|
||||
<text x="260" y="682" class="cyn">0x20081000</text>
|
||||
|
||||
<text x="500" y="682" class="amb">+ LENGTH</text>
|
||||
<text x="700" y="682" class="cyn">0x1000</text>
|
||||
<text x="830" y="682" class="dim">(4 KB)</text>
|
||||
|
||||
<text x="80" y="728" class="grn">= __StackTop = 0x20082000</text>
|
||||
<text x="680" y="728" class="dim"><- matches vector table!</text>
|
||||
</svg>
|
||||
@@ -0,0 +1,87 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
|
||||
<style>
|
||||
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
|
||||
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
|
||||
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
|
||||
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
|
||||
.dim{font:20px 'Courier New',monospace;fill:#888}
|
||||
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
|
||||
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
|
||||
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
|
||||
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
|
||||
.badge{stroke:#00ff41;rx:14}
|
||||
</style>
|
||||
<rect class="bg" width="1200" height="800"/>
|
||||
|
||||
<!-- Title -->
|
||||
<text x="600" y="52" text-anchor="middle" class="title">Reset Handler — 4 Phases</text>
|
||||
<text x="600" y="88" text-anchor="middle" class="dim">_reset_handler at 0x1000015C</text>
|
||||
|
||||
<!-- Phase 1 -->
|
||||
<rect x="40" y="110" width="555" height="150" rx="8" class="pnl" stroke="#ffaa00" stroke-width="2"/>
|
||||
<text x="60" y="143" class="amb">Phase 1: Core Check</text>
|
||||
<text x="60" y="170" class="dim">0x1000015C — 0x10000168</text>
|
||||
<rect x="60" y="185" width="515" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
|
||||
<text x="75" y="213" class="txt">mov r0, #0xD0000000</text>
|
||||
<text x="75" y="248" class="dim">Read CPUID -> Core 0 continues</text>
|
||||
|
||||
<!-- Phase 2 -->
|
||||
<rect x="625" y="110" width="535" height="150" rx="8" class="pnl" stroke="#00d4ff" stroke-width="2"/>
|
||||
<text x="645" y="143" class="cyn">Phase 2: Data Copy</text>
|
||||
<text x="645" y="170" class="dim">0x1000016A — 0x10000176</text>
|
||||
<rect x="645" y="185" width="495" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
|
||||
<text x="660" y="213" class="txt">ldmia r4!, {r1,r2,r3}</text>
|
||||
<text x="645" y="248" class="dim">Copy .data from flash -> RAM</text>
|
||||
|
||||
<!-- Phase 3 -->
|
||||
<rect x="40" y="280" width="555" height="150" rx="8" class="pnl" stroke="#00ff41" stroke-width="2"/>
|
||||
<text x="60" y="313" class="grn">Phase 3: BSS Clear</text>
|
||||
<text x="60" y="340" class="dim">0x10000178 — 0x10000184</text>
|
||||
<rect x="60" y="355" width="515" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
|
||||
<text x="75" y="383" class="txt">stmia r1!, {r0}</text>
|
||||
<text x="340" y="383" class="dim">r0 = 0</text>
|
||||
<text x="60" y="418" class="dim">Zero all uninitialized globals</text>
|
||||
|
||||
<!-- Phase 4 -->
|
||||
<rect x="625" y="280" width="535" height="150" rx="8" class="pnl" stroke="#ff0040" stroke-width="2"/>
|
||||
<text x="645" y="313" class="red">Phase 4: Platform Entry</text>
|
||||
<text x="645" y="340" class="dim">0x10000186+</text>
|
||||
<rect x="645" y="355" width="495" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
|
||||
<text x="660" y="383" class="txt">blx r1</text>
|
||||
<text x="800" y="383" class="dim">-> main()</text>
|
||||
<text x="645" y="418" class="dim">runtime_init -> main -> exit</text>
|
||||
|
||||
<!-- Bottom: Flow Diagram -->
|
||||
<rect x="40" y="455" width="1120" height="315" rx="8" class="pnl"/>
|
||||
<text x="60" y="493" class="sub">Execution Flow</text>
|
||||
|
||||
<!-- Step boxes -->
|
||||
<rect x="60" y="513" width="220" height="70" rx="6" fill="#0a0a0f" stroke="#ffaa00" stroke-width="2"/>
|
||||
<text x="170" y="543" text-anchor="middle" class="amb">Core Check</text>
|
||||
<text x="170" y="569" text-anchor="middle" class="dim">CPUID == 0?</text>
|
||||
|
||||
<text x="300" y="553" class="grn">-></text>
|
||||
|
||||
<rect x="325" y="513" width="200" height="70" rx="6" fill="#0a0a0f" stroke="#00d4ff" stroke-width="2"/>
|
||||
<text x="425" y="543" text-anchor="middle" class="cyn">Data Copy</text>
|
||||
<text x="425" y="569" text-anchor="middle" class="dim">flash -> RAM</text>
|
||||
|
||||
<text x="545" y="553" class="grn">-></text>
|
||||
|
||||
<rect x="570" y="513" width="200" height="70" rx="6" fill="#0a0a0f" stroke="#00ff41" stroke-width="2"/>
|
||||
<text x="670" y="543" text-anchor="middle" class="grn">BSS Clear</text>
|
||||
<text x="670" y="569" text-anchor="middle" class="dim">zero globals</text>
|
||||
|
||||
<text x="790" y="553" class="grn">-></text>
|
||||
|
||||
<rect x="815" y="513" width="305" height="70" rx="6" fill="#0a0a0f" stroke="#ff0040" stroke-width="2"/>
|
||||
<text x="967" y="543" text-anchor="middle" class="red">Platform Entry</text>
|
||||
<text x="967" y="569" text-anchor="middle" class="dim">-> main()!</text>
|
||||
|
||||
<!-- Dual core note -->
|
||||
<rect x="60" y="610" width="1080" height="150" rx="6" fill="#0a0a0f" stroke="#ffaa00" stroke-width="1"/>
|
||||
<text x="80" y="645" class="amb">Why check cores?</text>
|
||||
<text x="80" y="680" class="txt">RP2350 has 2 cores.</text>
|
||||
<text x="80" y="710" class="txt">Only Core 0 runs startup.</text>
|
||||
<text x="80" y="740" class="dim">Core 1 returns to bootrom and waits.</text>
|
||||
</svg>
|
||||
@@ -0,0 +1,93 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
|
||||
<style>
|
||||
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
|
||||
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
|
||||
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
|
||||
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
|
||||
.dim{font:20px 'Courier New',monospace;fill:#888}
|
||||
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
|
||||
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
|
||||
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
|
||||
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
|
||||
.badge{stroke:#00ff41;rx:14}
|
||||
</style>
|
||||
<rect class="bg" width="1200" height="800"/>
|
||||
|
||||
<!-- Title -->
|
||||
<text x="600" y="52" text-anchor="middle" class="title">Data Copy & BSS Clear</text>
|
||||
<text x="600" y="88" text-anchor="middle" class="dim">Initializing RAM Before main() Can Run</text>
|
||||
|
||||
<!-- Left Panel: Data Copy -->
|
||||
<rect x="40" y="110" width="555" height="420" rx="8" class="pnl" stroke="#00d4ff" stroke-width="2"/>
|
||||
<text x="60" y="148" class="cyn">Phase 2: Data Copy</text>
|
||||
<text x="60" y="178" class="dim">Copy initialized variables flash -> RAM</text>
|
||||
|
||||
<text x="60" y="218" class="txt">C code:</text>
|
||||
<rect x="60" y="230" width="515" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
|
||||
<text x="75" y="258" class="amb">int counter = 42;</text>
|
||||
|
||||
<text x="60" y="300" class="txt">Value 42 stored in flash</text>
|
||||
<text x="60" y="330" class="txt">but variables live in RAM!</text>
|
||||
|
||||
<!-- Flash -> RAM diagram -->
|
||||
<rect x="60" y="358" width="210" height="60" rx="4" fill="#0f1a0f" stroke="#00ff41" stroke-width="2"/>
|
||||
<text x="165" y="395" text-anchor="middle" class="grn">Flash</text>
|
||||
|
||||
<text x="290" y="395" class="amb">-></text>
|
||||
|
||||
<rect x="320" y="358" width="210" height="60" rx="4" fill="#0a0a1f" stroke="#00d4ff" stroke-width="2"/>
|
||||
<text x="425" y="395" text-anchor="middle" class="cyn">RAM</text>
|
||||
|
||||
<!-- data_cpy_table -->
|
||||
<text x="60" y="448" class="dim">data_cpy_table has entries:</text>
|
||||
<rect x="60" y="458" width="515" height="55" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
|
||||
<text x="75" y="482" class="dim">src: 0x10001B4C (flash)</text>
|
||||
<text x="75" y="507" class="dim">dst: 0x20000110 (RAM)</text>
|
||||
|
||||
<!-- Right Panel: BSS Clear -->
|
||||
<rect x="625" y="110" width="535" height="420" rx="8" class="pnl" stroke="#00ff41" stroke-width="2"/>
|
||||
<text x="645" y="148" class="grn">Phase 3: BSS Clear</text>
|
||||
<text x="645" y="178" class="dim">Zero uninitialized global variables</text>
|
||||
|
||||
<text x="645" y="218" class="txt">C code:</text>
|
||||
<rect x="645" y="230" width="495" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
|
||||
<text x="660" y="258" class="amb">int my_counter;</text>
|
||||
|
||||
<text x="645" y="300" class="txt">C standard requires</text>
|
||||
<text x="645" y="330" class="txt">this to start at zero.</text>
|
||||
|
||||
<!-- BSS loop diagram -->
|
||||
<rect x="645" y="358" width="495" height="110" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
|
||||
<text x="665" y="388" class="txt">r1 = BSS start</text>
|
||||
<text x="665" y="418" class="txt">r2 = BSS end</text>
|
||||
<text x="665" y="448" class="txt">r0 = 0</text>
|
||||
|
||||
<text x="645" y="498" class="dim">Loop: store 0, advance r1</text>
|
||||
<text x="645" y="524" class="dim">Until r1 == r2 -> done!</text>
|
||||
|
||||
<!-- Bottom Panel: Assembly -->
|
||||
<rect x="40" y="555" width="1120" height="215" rx="8" class="pnl"/>
|
||||
<text x="60" y="593" class="sub">Key Assembly Instructions</text>
|
||||
|
||||
<!-- Data Copy ASM -->
|
||||
<rect x="60" y="610" width="530" height="42" rx="4" fill="#0a0a0f" stroke="#00d4ff" stroke-width="1"/>
|
||||
<text x="75" y="638" class="cyn">ldmia r4!, {r1,r2,r3}</text>
|
||||
|
||||
<text x="60" y="672" class="dim">Load source, dest, end from table</text>
|
||||
|
||||
<rect x="60" y="690" width="530" height="42" rx="4" fill="#0a0a0f" stroke="#00d4ff" stroke-width="1"/>
|
||||
<text x="75" y="718" class="cyn">bl data_cpy</text>
|
||||
|
||||
<text x="60" y="750" class="dim">Copy word-by-word until done</text>
|
||||
|
||||
<!-- BSS Clear ASM -->
|
||||
<rect x="630" y="610" width="510" height="42" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
|
||||
<text x="645" y="638" class="grn">movs r0, #0</text>
|
||||
|
||||
<text x="630" y="672" class="dim">Load zero into r0</text>
|
||||
|
||||
<rect x="630" y="690" width="510" height="42" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
|
||||
<text x="645" y="718" class="grn">stmia r1!, {r0}</text>
|
||||
|
||||
<text x="630" y="750" class="dim">Store zero, advance pointer</text>
|
||||
</svg>
|
||||
@@ -0,0 +1,82 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
|
||||
<style>
|
||||
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
|
||||
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
|
||||
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
|
||||
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
|
||||
.dim{font:20px 'Courier New',monospace;fill:#888}
|
||||
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
|
||||
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
|
||||
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
|
||||
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
|
||||
.badge{stroke:#00ff41;rx:14}
|
||||
</style>
|
||||
<rect class="bg" width="1200" height="800"/>
|
||||
|
||||
<!-- Title -->
|
||||
<text x="600" y="52" text-anchor="middle" class="title">Platform Entry -> main()</text>
|
||||
<text x="600" y="88" text-anchor="middle" class="dim">The Final Step — 3 Function Calls at 0x10000186</text>
|
||||
|
||||
<!-- Top Panel: Assembly -->
|
||||
<rect x="40" y="110" width="1120" height="250" rx="8" class="pnl"/>
|
||||
<text x="60" y="148" class="sub">platform_entry Assembly</text>
|
||||
|
||||
<rect x="60" y="168" width="1080" height="42" rx="4" fill="#0a0a0f" stroke="#ffaa00" stroke-width="1"/>
|
||||
<text x="80" y="196" class="amb">0x10000186</text>
|
||||
<text x="310" y="196" class="txt">ldr r1, [DAT]</text>
|
||||
<text x="640" y="196" class="dim">-> load runtime_init addr</text>
|
||||
|
||||
<rect x="60" y="218" width="1080" height="42" rx="4" fill="#0a0a0f" stroke="#ffaa00" stroke-width="1"/>
|
||||
<text x="80" y="246" class="amb">0x10000188</text>
|
||||
<text x="310" y="246" class="txt">blx r1</text>
|
||||
<text x="640" y="246" class="cyn">-> call runtime_init()</text>
|
||||
|
||||
<rect x="60" y="268" width="1080" height="42" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="2"/>
|
||||
<text x="80" y="296" class="grn">0x1000018C</text>
|
||||
<text x="310" y="296" class="txt">blx r1</text>
|
||||
<text x="640" y="296" class="grn">-> call main()</text>
|
||||
|
||||
<rect x="60" y="318" width="1080" height="42" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
|
||||
<text x="80" y="346" class="red">0x10000190</text>
|
||||
<text x="310" y="346" class="txt">blx r1</text>
|
||||
<text x="640" y="346" class="red">-> call exit()</text>
|
||||
|
||||
<!-- Middle: Flow boxes -->
|
||||
<rect x="40" y="385" width="1120" height="160" rx="8" class="pnl"/>
|
||||
<text x="60" y="423" class="sub">Call Sequence</text>
|
||||
|
||||
<rect x="60" y="443" width="300" height="80" rx="6" fill="#0a0a0f" stroke="#ffaa00" stroke-width="2"/>
|
||||
<text x="210" y="478" text-anchor="middle" class="amb">runtime_init()</text>
|
||||
<text x="210" y="508" text-anchor="middle" class="dim">SDK setup</text>
|
||||
|
||||
<text x="385" y="488" class="grn">-></text>
|
||||
|
||||
<rect x="420" y="443" width="300" height="80" rx="6" fill="#0a0a0f" stroke="#00ff41" stroke-width="2"/>
|
||||
<text x="570" y="478" text-anchor="middle" class="grn">main()</text>
|
||||
<text x="570" y="508" text-anchor="middle" class="dim">YOUR CODE</text>
|
||||
|
||||
<text x="745" y="488" class="grn">-></text>
|
||||
|
||||
<rect x="780" y="443" width="300" height="80" rx="6" fill="#0a0a0f" stroke="#ff0040" stroke-width="2"/>
|
||||
<text x="930" y="478" text-anchor="middle" class="red">exit()</text>
|
||||
<text x="930" y="508" text-anchor="middle" class="dim">cleanup</text>
|
||||
|
||||
<!-- Bottom Panel: Details -->
|
||||
<rect x="40" y="570" width="540" height="200" rx="8" class="pnl"/>
|
||||
<text x="60" y="608" class="sub">runtime_init()</text>
|
||||
<text x="60" y="645" class="txt">Initializes SDK systems:</text>
|
||||
<text x="60" y="677" class="dim">• Clock configuration</text>
|
||||
<text x="60" y="705" class="dim">• GPIO setup</text>
|
||||
<text x="60" y="733" class="dim">• C++ constructor calls</text>
|
||||
<text x="60" y="761" class="dim">• Peripheral initialization</text>
|
||||
|
||||
<rect x="620" y="570" width="540" height="200" rx="8" class="pnl"/>
|
||||
<text x="640" y="608" class="sub">After main() Returns</text>
|
||||
<text x="640" y="645" class="txt">exit() handles cleanup.</text>
|
||||
<text x="640" y="677" class="txt">Then:</text>
|
||||
<rect x="660" y="700" width="480" height="42" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
|
||||
<text x="680" y="728" class="red">bkpt 0x0000</text>
|
||||
<text x="900" y="728" class="dim"><- infinite halt</text>
|
||||
|
||||
<text x="640" y="760" class="dim">Should never be reached!</text>
|
||||
</svg>
|
||||
@@ -0,0 +1,92 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
|
||||
<style>
|
||||
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
|
||||
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
|
||||
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
|
||||
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
|
||||
.dim{font:20px 'Courier New',monospace;fill:#888}
|
||||
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
|
||||
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
|
||||
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
|
||||
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
|
||||
.badge{stroke:#00ff41;rx:14}
|
||||
</style>
|
||||
<rect class="bg" width="1200" height="800"/>
|
||||
|
||||
<!-- Title -->
|
||||
<text x="600" y="52" text-anchor="middle" class="title">Secure Boot & Attack Vectors</text>
|
||||
<text x="600" y="88" text-anchor="middle" class="dim">Why Boot Sequence Knowledge Matters for Security</text>
|
||||
|
||||
<!-- Left Panel: Attack Scenarios -->
|
||||
<rect x="40" y="110" width="555" height="380" rx="8" class="pnl" stroke="#ff0040" stroke-width="2"/>
|
||||
<text x="60" y="148" class="red">Attack Scenarios</text>
|
||||
|
||||
<rect x="60" y="168" width="515" height="60" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
|
||||
<text x="75" y="193" class="red">Firmware Replacement</text>
|
||||
<text x="75" y="218" class="dim">Replace flash with malicious code</text>
|
||||
|
||||
<rect x="60" y="238" width="515" height="60" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
|
||||
<text x="75" y="263" class="red">Vector Table Hijack</text>
|
||||
<text x="75" y="288" class="dim">Modify reset handler address</text>
|
||||
|
||||
<rect x="60" y="308" width="515" height="60" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
|
||||
<text x="75" y="333" class="red">Debug Port Attack</text>
|
||||
<text x="75" y="358" class="dim">SWD/JTAG to dump or inject code</text>
|
||||
|
||||
<rect x="60" y="378" width="515" height="60" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
|
||||
<text x="75" y="403" class="red">Startup Code Modification</text>
|
||||
<text x="75" y="428" class="dim">Change crt0 data copy / BSS init</text>
|
||||
|
||||
<text x="60" y="472" class="amb">Physical access = game over</text>
|
||||
|
||||
<!-- Right Panel: Defense Strategies -->
|
||||
<rect x="625" y="110" width="535" height="380" rx="8" class="pnl" stroke="#00ff41" stroke-width="2"/>
|
||||
<text x="645" y="148" class="grn">Defense Strategies</text>
|
||||
|
||||
<rect x="645" y="168" width="495" height="50" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
|
||||
<text x="660" y="200" class="grn">1. Secure Boot</text>
|
||||
|
||||
<rect x="645" y="228" width="495" height="50" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
|
||||
<text x="660" y="260" class="grn">2. Debug Port Lock</text>
|
||||
|
||||
<rect x="645" y="288" width="495" height="50" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
|
||||
<text x="660" y="320" class="grn">3. Flash Read Protect</text>
|
||||
|
||||
<rect x="645" y="348" width="495" height="50" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
|
||||
<text x="660" y="380" class="grn">4. MPU Configuration</text>
|
||||
|
||||
<rect x="645" y="408" width="495" height="50" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
|
||||
<text x="660" y="440" class="grn">5. Integrity Checks</text>
|
||||
|
||||
<text x="645" y="478" class="amb">Defense in depth!</text>
|
||||
|
||||
<!-- Bottom Panel: Secure Boot Flow -->
|
||||
<rect x="40" y="515" width="1120" height="255" rx="8" class="pnl"/>
|
||||
<text x="60" y="553" class="sub">Secure Boot Chain</text>
|
||||
|
||||
<rect x="60" y="573" width="220" height="70" rx="6" fill="#0a0a0f" stroke="#00ff41" stroke-width="2"/>
|
||||
<text x="170" y="603" text-anchor="middle" class="grn">Bootrom</text>
|
||||
<text x="170" y="629" text-anchor="middle" class="dim">immutable</text>
|
||||
|
||||
<text x="298" y="613" class="amb">-></text>
|
||||
|
||||
<rect x="320" y="573" width="220" height="70" rx="6" fill="#0a0a0f" stroke="#00d4ff" stroke-width="2"/>
|
||||
<text x="430" y="603" text-anchor="middle" class="cyn">Verify Sig</text>
|
||||
<text x="430" y="629" text-anchor="middle" class="dim">IMAGE_DEF</text>
|
||||
|
||||
<text x="558" y="613" class="amb">-></text>
|
||||
|
||||
<rect x="580" y="573" width="220" height="70" rx="6" fill="#0a0a0f" stroke="#ffaa00" stroke-width="2"/>
|
||||
<text x="690" y="603" text-anchor="middle" class="amb">Verify App</text>
|
||||
<text x="690" y="629" text-anchor="middle" class="dim">signature</text>
|
||||
|
||||
<text x="818" y="613" class="amb">-></text>
|
||||
|
||||
<rect x="840" y="573" width="280" height="70" rx="6" fill="#0a0a0f" stroke="#00ff41" stroke-width="2"/>
|
||||
<text x="980" y="603" text-anchor="middle" class="grn">Boot!</text>
|
||||
<text x="980" y="629" text-anchor="middle" class="dim">or refuse</text>
|
||||
|
||||
<text x="60" y="688" class="txt">Each stage cryptographically verifies</text>
|
||||
<text x="60" y="718" class="txt">the next before handing off control.</text>
|
||||
<text x="60" y="748" class="dim">Bootrom = trust anchor (can't be changed)</text>
|
||||
</svg>
|
||||
Reference in New Issue
Block a user