diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 3e998f4..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "cmake.sourceDirectory": "C:/Users/assem.KEVINTHOMAS/OneDrive/Documents/Embedded-Hacking/0x0001_hello-world" -} \ No newline at end of file diff --git a/FINAL/FINAL-02.md b/FINAL/FINAL-02.md index 69575d6..8a3e9e0 100644 --- a/FINAL/FINAL-02.md +++ b/FINAL/FINAL-02.md @@ -261,9 +261,11 @@ These are the most frequent mistakes. Avoid them. --- -## ⏰ Time Limit +## ⏰ Deadline & Submission -You have **4 hours** to complete this examination. +- This is a **take-home final project**. See the course syllabus for the due date. +- Submit all deliverables as a single ZIP file or as specified by your instructor. +- Late submissions: see syllabus late work policy. --- diff --git a/WEEK02/WEEK02-SLIDES.pdf b/WEEK02/WEEK02-SLIDES.pdf index 1375a68..be346bc 100644 Binary files a/WEEK02/WEEK02-SLIDES.pdf and b/WEEK02/WEEK02-SLIDES.pdf differ diff --git a/WEEK03/WEEK03-SLIDES.pdf b/WEEK03/WEEK03-SLIDES.pdf index 7834a39..3d7e59a 100644 Binary files a/WEEK03/WEEK03-SLIDES.pdf and b/WEEK03/WEEK03-SLIDES.pdf differ diff --git a/WEEK03/WEEK03.md b/WEEK03/WEEK03.md index 1c0c562..55634fe 100644 --- a/WEEK03/WEEK03.md +++ b/WEEK03/WEEK03.md @@ -70,14 +70,17 @@ Each of these steps has a corresponding piece of code. Let's explore them all! │ STEP 2: Bootrom Executes (32KB on-chip ROM) │ │ - This code is burned into the chip - can't be changed! │ │ - It looks for valid firmware in flash memory │ -│ - It checks for the IMAGE_DEF structure at 0x10000000 │ +│ - It scans the first 4 kB of the image for a valid IMAGE_DEF │ +│ (Datasheet §4.1, p. 338: 32KB ROM; §5.9.5, p. 429: IMAGE_DEF) │ └─────────────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────────┐ -│ STEP 3: Boot Stage 2 (boot2) │ -│ - Configures the flash interface for fast reading │ +│ STEP 3: Flash XIP Setup (bootrom-managed) │ +│ - The bootrom configures the flash interface automatically │ │ - Sets up XIP (Execute In Place) mode │ -│ - Returns control to the bootrom │ +│ - NOTE: Unlike RP2040, there is NO separate boot2 in flash! │ +│ (Datasheet §5.2, p. 375: "removal of a boot2 in the first │ +│ 256 bytes of the image") │ └─────────────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────────┐ @@ -119,8 +122,8 @@ Think of the bootrom like the BIOS in your computer - it's the first thing that ### What Does the Bootrom Do? 1. **Initialize Hardware**: Sets up clocks, resets peripherals -2. **Check Boot Sources**: Looks for valid firmware in flash -3. **Validate Firmware**: Checks for magic markers (IMAGE_DEF) +2. **Check Boot Sources (Discovery)**: Scans configured boot sources (for this course: flash) to find a candidate firmware image region. +3. **Validate Firmware (Validation)**: Verifies that candidate by finding IMAGE_DEF start/end markers and parsing the block. 4. **Configure Flash**: Sets up the XIP interface 5. **Jump to Your Code**: Reads the vector table and jumps to your reset handler @@ -131,22 +134,70 @@ The bootrom looks for a special marker in your firmware called **IMAGE_DEF**. Th Here's what it looks like in the Pico SDK: ```assembly -.section .picobin_block, "a" // placed in flash -.word 0xffffded3 // PICOBIN_BLOCK_MARKER_START ← ROM looks for this! -.byte 0x42 // PICOBIN_BLOCK_ITEM_1BS_IMAGE_TYPE -.byte 0x1 // item is 1 word in size -.hword 0b0001000000100001 // SECURE mode (0x1021) -.byte 0xff // PICOBIN_BLOCK_ITEM_2BS_LAST -.hword 0x0001 // item is 1 word in size -.byte 0x0 // pad -.word 0x0 // relative pointer to next block (0 = loop to self) -.word 0xab123579 // PICOBIN_BLOCK_MARKER_END +.section .picobin_block, "a" // placed in flash +.word 0xffffded3 // PICOBIN_BLOCK_MARKER_START ← ROM looks for this! +.byte 0x42 // PICOBIN_BLOCK_ITEM_1BS_IMAGE_TYPE +.byte 0x1 // item is 1 word in size +.hword 0b0001000000100001 // SECURE mode (0x1021) +.byte 0xff // PICOBIN_BLOCK_ITEM_2BS_LAST +.hword 0x0001 // item is 1 word in size +.byte 0x0 // pad +.word 0x0 // relative pointer to next block (0 = loop to self) +.word 0xab123579 // PICOBIN_BLOCK_MARKER_END ``` **The magic numbers:** - `0xffffded3` = Start marker ("I'm a valid Pico binary!") - `0xab123579` = End marker ("End of the header block") +### See This Exact Block in Your ELF (Commands + Real Output) + +Use these commands to view the IMAGE_DEF bytes directly in the ELF: + +```powershell +arm-none-eabi-objdump -s --start-address=0x1000013c --stop-address=0x10000150 build/0x0001_hello-world.elf +arm-none-eabi-objdump -s --start-address=0x10000130 --stop-address=0x10000154 build/0x0001_hello-world.elf +arm-none-eabi-gdb build/0x0001_hello-world.elf -ex "x/20bx 0x1000013c" -ex quit +``` + +Actual output from this lesson build: + +```text +build/0x0001_hello-world.elf: file format elf32-littlearm + +Contents of section .text: + 1000013c 42012110 ff010000 b01b0000 793512ab B.!.........y5.. + 1000014c 4ff00000 O... + +build/0x0001_hello-world.elf: file format elf32-littlearm + +Contents of section .text: + 10000130 a0010010 90a31ae7 d3deffff 42012110 ............B.!. + 10000140 ff010000 b01b0000 793512ab 4ff00000 ........y5..O... + 10000150 1e490860 .I.` +``` + +Command 1 explained (`--start-address=0x1000013c --stop-address=0x10000150`): +- Starts at `0x1000013c`, so it does **not** include the start marker at `0x10000138` (`d3deffff`). +- Shows IMAGE_DEF body fields and the end marker: + - `42012110` = `42 01 21 10` (item type/size + secure mode field) + - `ff010000` = last-item marker + size + pad + - `b01b0000` = next word in the block payload for this build + - `793512ab` = `PICOBIN_BLOCK_MARKER_END` (`0xab123579` in little-endian) +- `4ff00000` at `0x1000014c` is already the next instruction word after IMAGE_DEF. + +Command 2 explained (`--start-address=0x10000130 --stop-address=0x10000154`): +- Starts earlier, so it captures context **and** both IMAGE_DEF markers. +- `a0010010 90a31ae7` = binary-info context before IMAGE_DEF. +- `d3deffff` at `0x10000138` = `PICOBIN_BLOCK_MARKER_START`. +- `793512ab` at `0x10000148` = `PICOBIN_BLOCK_MARKER_END`. +- `4ff00000 1e490860` = code words after the IMAGE_DEF block. +- This command proves the full block location for this build: `0x10000138` to `0x1000014b`. + +Important: IMAGE_DEF offset can vary by build. In this build, the start marker `d3deffff` +is at `0x10000138` (not `0x1000013c`), so always search for the marker bytes instead of +assuming a fixed address. + --- ## 📚 Part 3: Understanding XIP (Execute In Place) @@ -327,7 +378,7 @@ arm-none-eabi-gdb build\0x0001_hello-world.elf **Connect to target:** ```gdb -(gdb) target remote :3333 +(gdb) target extended-remote :3333 (gdb) monitor reset halt ``` @@ -360,7 +411,7 @@ Let's look at the first 4 entries of the vector table at `0x10000000`: ### Step 2: Understanding What We See -> 🔄 **REVIEW:** In Week 1, we saw `sp = 0x20081fc8` when stopped at `main`. That's *after* some stack was used during boot. Here we see the *initial* stack pointer before any code runs! +> 🔄 **REVIEW:** In Weeks 1-2, we saw both `sp = 0x20082000` at the clean breakpoint at `main` and lower values like `0x20081fc8` or `0x20081ff8` after additional stack activity. Here we are looking at the *initial* stack pointer from the vector table before any code runs. Let's decode each value: @@ -466,39 +517,39 @@ Let's look at more instructions to see the full picture: (gdb) x/20i 0x1000015c ``` -**You should see something like:** +**You should see:** ``` -0x1000015c <_reset_handler>: mov.w r0, #3489660928 @ 0xd0000000 -0x10000160 <_reset_handler+4>: ldr r0, [r0, #0] -0x10000162 <_reset_handler+6>: -cbz r0, 0x1000016a -0x10000164 : mov.w r0, #0 -0x10000168 : -b.n 0x10000150 <_enter_vtable_in_r0> -0x1000016a : -add r4, pc, #52 @ (adr r4, 0x100001a0 ) -0x1000016c : ldmia r4!, {r1, r2, r3} -0x1000016e : cmp r1, #0 -0x10000170 : -beq.n 0x10000178 -0x10000172 : -bl 0x1000019a -0x10000176 : -b.n 0x1000016c -0x10000178 : -ldr r1, [pc, #84] @ (0x100001d0 ) -0x1000017a : -ldr r2, [pc, #88] @ (0x100001d4 ) -0x1000017c : movs r0, #0 -0x1000017e : -b.n 0x10000182 -0x10000180 : stmia r1!, {r0} -0x10000182 : cmp r1, r2 -0x10000184 : bne.n 0x10000180 -0x10000186 : -ldr r1, [pc, #80] @ (0x100001d8 ) -0x10000188 : blx r1 + 0x1000015c <_reset_handler>: mov.w r0, #3489660928 @ 0xd0000000 + 0x10000160 <_reset_handler+4>: ldr r0, [r0, #0] + 0x10000162 <_reset_handler+6>: + cbz r0, 0x1000016a + 0x10000164 : mov.w r0, #0 + 0x10000168 : + b.n 0x10000150 <_enter_vtable_in_r0> + 0x1000016a : + add r4, pc, #52 @ (adr r4, 0x100001a0 ) + 0x1000016c : ldmia r4!, {r1, r2, r3} + 0x1000016e : cmp r1, #0 + 0x10000170 : + beq.n 0x10000178 + 0x10000172 : + bl 0x1000019a + 0x10000176 : + b.n 0x1000016c + 0x10000178 : + ldr r1, [pc, #84] @ (0x100001d0 ) + 0x1000017a : + ldr r2, [pc, #88] @ (0x100001d4 ) + 0x1000017c : movs r0, #0 + 0x1000017e : + b.n 0x10000182 + 0x10000180 : stmia r1!, {r0} + 0x10000182 : cmp r1, r2 + 0x10000184 : bne.n 0x10000180 + 0x10000186 : + ldr r1, [pc, #80] @ (0x100001d8 ) + 0x10000188 : blx r1 ``` ### Step 7: Understanding the Startup Phases @@ -513,22 +564,23 @@ The reset handler performs several phases: └─────────────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────────┐ -│ PHASE 2: Data Copy (0x1000016a - 0x10000176) │ +│ PHASE 2: Data Copy Setup & Loop (0x1000016a - 0x10000176) │ +│ - Set up the data_cpy_table pointer and load each copy triplet │ │ - Copy initialized variables from flash to RAM │ -│ - Uses data_cpy_table for source/destination info │ └─────────────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────────┐ -│ PHASE 3: BSS Clear (0x10000178 - 0x10000184) │ +│ PHASE 3: BSS Setup & Clear (0x10000178 - 0x10000184) │ +│ - Load the BSS start/end addresses into r1 and r2 │ +│ - GDB labels those literals as `data_cpy_table+48/+52` │ │ - Zero out all uninitialized global variables │ -│ - C standard requires BSS to start at zero │ └─────────────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────────┐ -│ PHASE 4: Runtime Init & Main (0x10000186+) │ -│ - Call runtime_init() for SDK setup │ -│ - Call __libc_init_array() for C++ constructors │ -│ - Finally call main()! │ +│ PHASE 4: Platform Entry Begins (0x10000186 - 0x10000188 shown) │ +│ - Load the runtime_init() pointer from the table │ +│ - Branch to runtime_init() with `blx r1` │ +│ - `main()` and `exit()` appear a few instructions later │ └─────────────────────────────────────────────────────────────────┘ ``` @@ -562,7 +614,8 @@ The data copy table contains entries that describe what to copy where. Let's exa ``` 0x100001a0 : 0x10001b4c 0x20000110 0x200002ac 0x10001ce8 -... +0x100001b0 : 0x20080000 0x20080000 0x10001ce8 0x20081000 +0x100001c0 : 0x20081000 0x00000000 0x00004770 0xe000ed08 ``` The data_cpy_table contains multiple entries. Each entry has three values: @@ -641,6 +694,8 @@ b.n 0x10000182 0x10000180 : stmia r1!, {r0} ``` +The first two `ldr` instructions are still part of the **BSS clear setup**, even though GDB shows the source words as `data_cpy_table+48` and `data_cpy_table+52`. That label means the two literal words live in the same nearby constant block as the copy-table entries; it does **not** mean the code is still performing `.data` copies. At this point, `r1` becomes the BSS start address, `r2` becomes the BSS end address, and the loop beginning at `0x10000180` zeros that range. + ### Understanding the Loop ``` @@ -762,7 +817,8 @@ Let's verify we understand the boot process by setting a breakpoint at main: **You should see:** ``` -Breakpoint 1 at 0x10000234: file 0x0001_hello-world.c, line 5. +Breakpoint 1 at 0x10000234: file C:/Users/flare-vm/Desktop/Embedded-Hacking-main/0x0001_hello-world/0x0001_hello-world.c, line 5. +Note: automatically using hardware breakpoints for read-only addresses. ``` **Now continue:** @@ -776,8 +832,10 @@ Breakpoint 1 at 0x10000234: file 0x0001_hello-world.c, line 5. ``` Continuing. -Breakpoint 1, main () at 0x0001_hello-world.c:5 -5 stdio_init_all(); +Thread 1 "rp2350.cm0" hit Breakpoint 1, main () + at C:/Users/flare-vm/Desktop/Embedded-Hacking-main/0x0001_hello-world/0x0001_hello-world.c:5 +5 stdio_init_all(); +(gdb) ``` 🎉 We've traced the entire boot process from power-on to `main()`! @@ -822,7 +880,7 @@ GDB doesn't know this is data, not code! It tries to disassemble it as Thumb ins ``` ``` -0x10000138 <__binary_info_header_end>: udf #211 @ 0xd3 + 0x10000138 <__binary_info_header_end>: udf #211 @ 0xd3 ``` That's not real code - it's the magic number `0xffffded3` being misinterpreted! @@ -884,6 +942,7 @@ While GDB is excellent for dynamic analysis (watching code execute), Ghidra exce 1000000d 01 ?? 01h 1000000e 00 ?? 00h 1000000f 10 ?? 10h +... ``` > 💡 **Notice:** Ghidra shows the vector table data as individual bytes by default. You can see it has labeled the start as `__vectors`, `__flash_binary_start`, `__VECTOR_TABLE`, and `__logical_binary_start`. The arrows (like `? -> 1000015d`) show that Ghidra recognizes these bytes as pointers to code addresses! To see the data formatted as 32-bit addresses instead of bytes, you can right-click and retype the data. @@ -953,9 +1012,9 @@ Let's find how the boot code eventually calls `main()`: | Location | Type | Label | | ------------------------- | ---- | ------------------ | -| `platform_entry+6` | CALL | `blx r1` (to main) | +| `1000018c` | CALL | `blx r1` (to main) | -4. Double-click on the reference to jump to `platform_entry` +4. Double-click on the reference to jump to `1000018c` ### Step 19: Examine Platform Entry @@ -991,7 +1050,7 @@ Ghidra can visualize the call flow: 1. With `_reset_handler` selected, go to **Window → Function Call Graph** 2. This shows a visual graph of all function calls from the reset handler -3. You can see the path: `_reset_handler` → `platform_entry` → `main` +3. You will see `_reset_handler` at the top with arrows going down to its four direct callees: `data_cpy`, `runtime_init`, `main`, and `exit` ### Comparing GDB and Ghidra for Boot Analysis @@ -1023,8 +1082,8 @@ Ghidra can visualize the call flow: ├─────────────────────────────────────────────────────────────────┤ │ 2. BOOTROM │ │ - Initializes hardware │ -│ - Finds IMAGE_DEF at 0x10000000 │ -│ - Runs boot2 to configure flash │ +│ - Configures flash XIP (no separate boot2 on RP2350) │ +│ - Finds IMAGE_DEF within first 4 kB of flash image │ ├─────────────────────────────────────────────────────────────────┤ │ 3. VECTOR TABLE (0x10000000) │ │ - Reads SP from offset 0x00 → 0x20082000 │ @@ -1129,21 +1188,18 @@ Ghidra can visualize the call flow: - Is it a valid code address (starts with `0x1000...`)? - What handler does it point to? -### Exercise 4: Find Your Main Function +### Exercise 4: Find Your Main Function and Trace Back 1. Use `info functions main` to find main 2. Examine 10 instructions at that address 3. Identify the first function call in main 4. What does that function do? +5. When stopped at main, examine `$lr` (link register) +6. What address is stored there? +7. Disassemble that address - what function is it? +8. This shows you where main was called from! -### Exercise 5: Trace Back from Main - -1. When stopped at main, examine `$lr` (link register) -2. What address is stored there? -3. Disassemble that address - what function is it? -4. This shows you where main was called from! - -### Exercise 6: Ghidra Boot Analysis +### Exercise 5: Ghidra Boot Analysis 1. In Ghidra, navigate to `_reset_handler` 2. Use **Window → Function Call Graph** to visualize the call tree @@ -1221,9 +1277,7 @@ Understanding the boot process is critical for both attackers and defenders. Kno │ ↓ │ │ Verify IMAGE_DEF signature │ │ ↓ │ -│ Verify boot2 signature │ -│ ↓ │ -│ Verify application signature │ +│ Verify application image signature │ │ ↓ │ │ If all valid: Jump to reset handler │ │ If any invalid: Refuse to boot │ @@ -1342,9 +1396,11 @@ https://datasheets.raspberrypi.com/rp2350/rp2350-datasheet.pdf ### Pico SDK Source Code The startup code lives in: -- `crt0.S` - Main startup assembly -- `memmap_default.ld` - Default linker script -- `boot2_generic_03h.S` - Second stage bootloader +- `crt0.S` - Main startup assembly (vector table at `.section .vectors`, reset handler, data copy, BSS clear, platform_entry) +- `memmap_default.ld` - Default linker script (section ordering: `.vectors` -> `.binary_info_header` -> `.embedded_block` -> `.reset`) +- `embedded_start_block.inc.S` - IMAGE_DEF block (replaces RP2040's `boot2_generic_03h.S`) + +> ⚠️ **Note:** The RP2040 used a `boot2_generic_03h.S` second-stage bootloader occupying the first 256 bytes of flash. The RP2350 eliminated this; the bootrom handles flash XIP setup directly. The SDK still includes a `boot2` mechanism for compatibility, but it is **not** placed at flash address 0 - it is embedded in the data copy table and executed from the stack during startup. ### Bootrom Source @@ -1353,6 +1409,180 @@ https://github.com/raspberrypi/pico-bootrom-rp2350 --- +## 🔬 Part 17: Proving the Boot Sequence with objdump + +Everything we have learned about the boot sequence can be proven directly from the compiled ELF binary using `arm-none-eabi-objdump`. The bootrom is not in your ELF (it is mask ROM burned into the chip at `0x00000000`), but everything your firmware provides — the vector table, the IMAGE_DEF, and the reset handler — lives in your ELF starting at `0x10000000`. + +### Step 1: List All Sections + +```bash +arm-none-eabi-objdump -h build/0x0001_hello-world.elf +``` + +Expected output (key sections): + +``` +Idx Name Size VMA LMA + 0 .text 000019cc 10000000 10000000 + 3 .binary_info 0000002c 10001b20 10001b20 + 4 .ram_vector_table 00000110 20000000 20000000 + 6 .data 0000019c 20000110 10001b4c +``` + +> 💡 The Pico SDK merges `.vectors`, `.embedded_block`, and `.reset` all into `.text` at `0x10000000`. They are not separate named ELF sections — they are sub-regions inside `.text`. + +### Step 2: Dump the First 0x150 Bytes of Flash — One Command, Zero Skips + +```bash +arm-none-eabi-objdump -s --start-address=0x10000000 --stop-address=0x10000150 build/0x0001_hello-world.elf +``` + +Raw output from that command: + +``` + 10000000 00200820 5d010010 1b010010 1d010010 . . ]........... + 10000010 11010010 11010010 11010010 11010010 ................ + 10000020 11010010 11010010 11010010 11010010 ................ + 10000030 11010010 11010010 11010010 11010010 ................ + 10000040 11010010 11010010 11010010 11010010 ................ + 10000050 11010010 11010010 11010010 11010010 ................ + 10000060 11010010 11010010 11010010 11010010 ................ + 10000070 11010010 11010010 11010010 11010010 ................ + 10000080 11010010 11010010 11010010 11010010 ................ + 10000090 11010010 11010010 11010010 11010010 ................ + 100000a0 11010010 11010010 11010010 11010010 ................ + 100000b0 11010010 11010010 11010010 11010010 ................ + 100000c0 11010010 11010010 11010010 11010010 ................ + 100000d0 11010010 11010010 11010010 11010010 ................ + 100000e0 11010010 11010010 11010010 11010010 ................ + 100000f0 11010010 11010010 11010010 11010010 ................ + 10000100 11010010 11010010 11010010 11010010 ................ + 10000110 eff30580 103800be 00be00be 00be00be .....8.......... + 10000120 00be00be f2eb8871 201b0010 4c1b0010 .......q ...L... + 10000130 a0010010 90a31ae7 d3deffff 42012110 ............B.!. + 10000140 ff010000 b01b0000 793512ab ........y5.. +``` + +Every address annotated, no skips: + +#### 0x10000000 — Vector Table, Mandatory Entries + +| Address | Raw Bytes (LE) | Decoded | What it is | +|---------|----------------|---------|------------| +| `0x10000000` | `00 20 08 20` | `0x20082000` | **Initial SP** — top of SCRATCH_Y RAM. Bootrom loads MSP from here before doing anything else. | +| `0x10000004` | `5d 01 00 10` | `0x1000015d` | **Reset_Handler** address with Thumb bit set. Strip bit 0 → real address `0x1000015c`. Bootrom jumps here. | +| `0x10000008` | `1b 01 00 10` | `0x1000011b` | **NMI** handler address (Thumb, → `0x1000011a`). | +| `0x1000000c` | `1d 01 00 10` | `0x1000011d` | **HardFault** handler address (Thumb, → `0x1000011c`). | + +#### 0x10000010–0x1000010f — Vector Table, IRQ Slots (all 52 external IRQs) + +``` + 10000010 11010010 11010010 ...(repeats through 0x1000010f)... +``` + +Every 4-byte word here is `11 01 00 10` = pointer `0x10000111`. +That is the **default IRQ handler** address with Thumb bit set (→ `0x10000110`). +The RP2350 Cortex-M33 has 16 system vectors (offsets 0x00–0x3f) plus up to 52 +external IRQ vectors (offsets 0x40–0xff = addresses `0x10000040`–`0x1000010f`). +Every IRQ the application does not register gets this default handler pointer. +This block is 240 bytes (`0x10000010` to `0x1000010f`) of nothing but that one +repeated pointer. + +#### 0x10000110–0x10000127 — Default IRQ Handler Code + +``` + 10000110 eff30580 103800be 00be00be 00be00be + 10000120 00be00be f2eb8871 +``` + +| Address | Bytes | ARM Thumb-2 Instruction | What it does | +|---------|-------|-------------------------|--------------| +| `0x10000110` | `ef f3 05 80` | `MRS r0, IPSR` | Read the Interrupt Program Status Register into r0. The low 9 bits = the active vector number. | +| `0x10000114` | `10 38` | `SUBS r0, #16` | Vector 16 = IRQ0, so subtract 16 to convert vector number → IRQ index. | +| `0x10000116` | `00 be` | `BKPT #0` | Software breakpoint. If a debugger is attached, it stops here and you can inspect r0 to see which IRQ fired. If no debugger is attached, the CPU enters a fault loop and the chip hangs. | +| `0x10000118`–`0x10000127` | `00 be` ×12 | `BKPT #0` repeating | Alignment padding to the next 4-byte boundary. | + +This is the **entire** default IRQ handler. It is intentionally minimal: if your +code triggers an IRQ you did not register, it crashes visibly instead of silently. + +#### 0x10000128–0x1000013b — Binary Info Pointer Table + +``` + 10000120 201b0010 4c1b0010 + 10000130 a0010010 90a31ae7 +``` + +| Address | Bytes (LE) | Decoded Value | What it is | +|---------|------------|---------------|------------| +| `0x10000128` | `20 1b 00 10` | `0x10001b20` | Pointer to **start** of `.binary_info` data section in flash. | +| `0x1000012c` | `4c 1b 00 10` | `0x10001b4c` | Pointer to **end** of `.binary_info` data section in flash. | +| `0x10000130` | `a0 01 00 10` | `0x100001a0` | Pointer to `binary_info_callback` function. | +| `0x10000134` | `90 a3 1a e7` | (magic marker) | `BINARY_INFO_MARKER_END` — marks the end of this pointer table. | + +`picotool` reads this table to extract the program name, version string, URL, +and GPIO pin map from any compiled binary without running it. + +#### 0x10000138–0x1000014c — IMAGE_DEF Block (this build) + +``` + 10000130 a0010010 90a31ae7 d3deffff 42012110 + 10000140 ff010000 b01b0000 793512ab 4ff00000 +``` + +| Address | Bytes | What it is | +|---------|-------|------------| +| `0x10000138` | `d3 de ff ff` | `PICOBIN_BLOCK_MARKER_START` — the bootrom scans flash for this exact 4-byte sequence to locate the IMAGE_DEF. | +| `0x1000013c` | `42 01 21 10` | IMAGE_DEF content (image type, flags, version). | +| `0x10000140` | `ff 01 00 00` | IMAGE_DEF content (continuation). | +| `0x10000144` | `b0 1b 00 00` | IMAGE_DEF content (continuation). | +| `0x10000148` | `79 35 12 ab` | `PICOBIN_BLOCK_MARKER_END` — bootrom stops scanning here. | + +The IMAGE_DEF sits at `0x10000138`–`0x1000014b` in this build, +well within the 4 KB scan window the bootrom uses (Datasheet §5.9.5, p. 429). + +#### Full Flash Map: 0x10000000–0x1000015c + +``` + 0x10000000–0x1000000f Vector Table: mandatory entries (SP, Reset, NMI, HardFault) + 0x10000010–0x1000010f Vector Table: 52 external IRQ slots → all point to default handler + 0x10000110–0x10000127 Default IRQ handler code (MRS / SUBS / BKPT) + 0x10000128–0x10000137 Binary info pointer table (start / end / callback / magic end) + 0x10000138–0x1000014b IMAGE_DEF block (d3 de ff ff ... 79 35 12 ab) + 0x10000150–0x1000015b (padding / alignment) + 0x1000015c Reset_Handler (_reset_handler in crt0.S) ← bootrom jumps here +``` + +### Step 4: Confirmed Boot Sequence (proven from ELF) + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ PROVEN BOOT SEQUENCE (0x0001_hello-world) │ +├─────────────────────────────────────────────────────────────────┤ +│ 1. Bootrom reads 0x10000000 │ +│ → SP = 0x20082000 (offset +0x00 of vector table) │ +│ → RST = 0x1000015d (offset +0x04, Thumb → 0x1000015c) │ +├─────────────────────────────────────────────────────────────────┤ +│ 2. Bootrom scans first 4 kB for IMAGE_DEF │ +│ → Found at 0x10000138 (this build) │ +│ → Start marker: d3 de ff ff │ +│ → End marker: 79 35 12 ab │ +├─────────────────────────────────────────────────────────────────┤ +│ 3. Bootrom jumps to reset handler at 0x1000015c │ +│ → _reset_handler (crt0.S) runs │ +│ → Checks CPUID — Core 1 sent back to bootrom │ +│ → Core 0: .data copied, .bss zeroed, platform_entry called │ +├─────────────────────────────────────────────────────────────────┤ +│ 4. platform_entry calls runtime_init → main → exit │ +└─────────────────────────────────────────────────────────────────┘ +``` + +> 📖 **Datasheet References:** +> - §5.1.5.1 (p. 357): Block markers `0xffffded3` (start) and `0xab123579` (end) +> - §5.9.5 (p. 429): IMAGE_DEF must appear within first 4 kB of flash image +> - §5.9.5.1 (p. 429): Bootrom enters via reset handler at vector table offset +4 + +--- + **Remember:** Understanding the boot process is fundamental to embedded systems work. Whether you're debugging a system that won't start, reverse engineering firmware, or building secure boot chains, this knowledge is essential! Happy exploring! 🔍 diff --git a/WEEK03/slides/WEEK03-IMG00.svg b/WEEK03/slides/WEEK03-IMG00.svg new file mode 100644 index 0000000..d40fbfd --- /dev/null +++ b/WEEK03/slides/WEEK03-IMG00.svg @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + 4F 70 65 6E 4F 43 44 + 10 00 02 34 08 B5 01 + 47 44 42 20 52 45 56 + 20 08 20 00 FF AA 00 + 52 50 32 33 35 30 00 + 0A 0A 0F 12 12 1A 1A + 41 52 4D 76 38 2D 4D + 00 FF 41 00 D4 FF 88 + 47 48 49 44 52 41 00 + FF 00 40 C0 C0 C0 00 + + + + + + + + + + + + +Embedded Systems +Reverse Engineering + + + + + +// WEEK 03 + + +Embedded System Analysis: +Understanding the RP2350 Architecture +w/ Comprehensive Firmware Analysis + + + + + +George Mason University + + + +RP2350 // ARM Cortex-M33 + diff --git a/WEEK03/slides/WEEK03-IMG01.svg b/WEEK03/slides/WEEK03-IMG01.svg new file mode 100644 index 0000000..0b8b8bd --- /dev/null +++ b/WEEK03/slides/WEEK03-IMG01.svg @@ -0,0 +1,70 @@ + + + + + +RP2350 Boot Sequence +Power-On to main() — 5 Steps + + + +STEP 1 +Power On +Cortex-M33 wakes, execution at 0x00000000 (Bootrom) + + + + + + +STEP 2 +Bootrom Executes +32KB on-chip ROM — finds IMAGE_DEF at 0x10000000 + + + + + + +STEP 3 +Flash XIP Setup (bootrom-managed) +Bootrom configures flash interface & XIP (no boot2 on RP2350) + + + + + + +STEP 4 +Vector Table & Reset Handler +Reads SP from offset 0x00 -> 0x20082000 +Reads Reset Handler from 0x04 -> 0x1000015d + + + + + + +STEP 5 +C Runtime Startup (crt0.S) +Copy .data from flash -> RAM +Zero .bss section +Call runtime_init() -> main() + + + +Key Insight +Your main() is the LAST thing to run. +All 5 steps must complete first! + \ No newline at end of file diff --git a/WEEK03/slides/WEEK03-IMG02.svg b/WEEK03/slides/WEEK03-IMG02.svg new file mode 100644 index 0000000..b7c0025 --- /dev/null +++ b/WEEK03/slides/WEEK03-IMG02.svg @@ -0,0 +1,84 @@ + + + + + +The Bootrom +32KB Factory-Programmed ROM — Where It All Begins + + + +Bootrom Properties + + +Size +32 KB + + +Location +0x00000000 + + +Modifiable? +NO — mask ROM + + +Purpose +Boot the chip + +Burned into silicon at factory +Like BIOS in your computer + + + +What It Does + + +1. +Initialize hardware + + +2. +Check boot sources + + +3. +Validate IMAGE_DEF + + +4. +Configure flash + + +5. +Jump to your code + + + +IMAGE_DEF — Magic Markers +Bootrom looks for these to validate firmware + + +Start Marker +0xFFFFDED3 +"I'm a valid Pico binary!" + + +End Marker +0xAB123579 +"End of header block" + +Bootrom reads flash at 0x10000000, +finds these markers, then boots. + \ No newline at end of file diff --git a/WEEK03/slides/WEEK03-IMG03.svg b/WEEK03/slides/WEEK03-IMG03.svg new file mode 100644 index 0000000..4db555b --- /dev/null +++ b/WEEK03/slides/WEEK03-IMG03.svg @@ -0,0 +1,74 @@ + + + + + +XIP — Execute In Place +Run Code Directly from Flash — No Copy Needed + + + +Book Analogy + + +Without XIP +Photocopy every page, read copy + + +With XIP +Read directly from the book! + + + +Why Use XIP? + + +Saves RAM +Code stays in flash + + +Faster Boot +No bulk copy needed + + +Simpler +Less memory mgmt + + + +XIP Flash Region at 0x10000000 + + + +Vector Table +SP at offset 0x00 | Reset Handler at offset 0x04 | Exception handlers... + + + +Your Code +_reset_handler | main() | other functions + + + +Read-Only Data +Strings like "hello, world" | constant values + + +0x10000000 +0x100001xx +0x10001xxx + +CPU fetches instructions directly +from flash via XIP cache. + \ No newline at end of file diff --git a/WEEK03/slides/WEEK03-IMG04.svg b/WEEK03/slides/WEEK03-IMG04.svg new file mode 100644 index 0000000..22034ba --- /dev/null +++ b/WEEK03/slides/WEEK03-IMG04.svg @@ -0,0 +1,80 @@ + + + + + +The Vector Table +CPU's Instruction Manual at 0x10000000 + + + +Vector Table Layout + + + +Offset +Address +Value +Meaning + + + +0x00 +0x10000000 +0x20082000 +Initial SP + + + +0x04 +0x10000004 +0x1000015D +Reset Handler + + + +0x08 +0x10000008 +0x1000011B +NMI Handler + + + +0x0C +0x1000000C +0x1000011D +HardFault Handler + + + +GDB: +x/4x 0x10000000 + + + +On Power-On +1. CPU reads SP from 0x00 +2. Sets SP = 0x20082000 +3. Reads Reset from 0x04 +4. Jumps to 0x1000015C + + + +Default Handlers +NMI, HardFault, SVCall, +PendSV, SysTick all use: + +bkpt 0x0000 +<- stops debugger + \ No newline at end of file diff --git a/WEEK03/slides/WEEK03-IMG05.svg b/WEEK03/slides/WEEK03-IMG05.svg new file mode 100644 index 0000000..c3d03a0 --- /dev/null +++ b/WEEK03/slides/WEEK03-IMG05.svg @@ -0,0 +1,70 @@ + + + + + +Thumb Mode Addressing +Why Addresses End in Odd Numbers + + + +The LSB Rule +ARM Cortex-M uses the Least Significant +Bit (LSB) to indicate instruction mode: + + + +LSB = 1 (odd) +Thumb mode + + + +LSB = 0 (even) +ARM mode + + + +Reset Handler Example + +Vector table stores: +0x1000015D + +Actual code address: +0x1000015C + +The +1 means: +"Use Thumb mode" + + + +GDB Shows + +0x1000015D +with Thumb bit + + +Vector table raw value + + + +Ghidra Shows + +0x1000015C +actual address + + +Real instruction location + +Both are correct — just displayed differently! + \ No newline at end of file diff --git a/WEEK03/slides/WEEK03-IMG06.svg b/WEEK03/slides/WEEK03-IMG06.svg new file mode 100644 index 0000000..f7d8b17 --- /dev/null +++ b/WEEK03/slides/WEEK03-IMG06.svg @@ -0,0 +1,69 @@ + + + + + +Linker Script Memory Map +memmap_default.ld — Where Everything Lives + + + +Memory Regions + + + +Flash (XIP) +0x10000000 +varies +Your code (read-only) + + + +RAM +0x20000000 +512 KB +Main RAM (r/w) + + + +SCRATCH_X +0x20080000 +4 KB +Core 0 scratch (HW: SRAM8) + + + +SCRATCH_Y +0x20081000 +4 KB +Core 0 stack! (HW: SRAM9) + + + +Stack Pointer Calculation + +__StackTop = ORIGIN(SCRATCH_Y) + + LENGTH(SCRATCH_Y) + + +ORIGIN +0x20081000 + ++ LENGTH +0x1000 +(4 KB) + += __StackTop = 0x20082000 +<- matches vector table! + \ No newline at end of file diff --git a/WEEK03/slides/WEEK03-IMG07.svg b/WEEK03/slides/WEEK03-IMG07.svg new file mode 100644 index 0000000..262aac0 --- /dev/null +++ b/WEEK03/slides/WEEK03-IMG07.svg @@ -0,0 +1,87 @@ + + + + + +Reset Handler — 4 Phases +_reset_handler at 0x1000015C + + + +Phase 1: Core Check +0x1000015C — 0x10000168 + +mov r0, #0xD0000000 +Read CPUID -> Core 0 continues + + + +Phase 2: Data Copy +0x1000016A — 0x10000176 + +ldmia r4!, {r1,r2,r3} +Copy .data from flash -> RAM + + + +Phase 3: BSS Clear +0x10000178 — 0x10000184 + +stmia r1!, {r0} +r0 = 0 +Zero all uninitialized globals + + + +Phase 4: Platform Entry +0x10000186+ + +blx r1 +-> main() +runtime_init -> main -> exit + + + +Execution Flow + + + +Core Check +CPUID == 0? + +-> + + +Data Copy +flash -> RAM + +-> + + +BSS Clear +zero globals + +-> + + +Platform Entry +-> main()! + + + +Why check cores? +RP2350 has 2 cores. +Only Core 0 runs startup. +Core 1 returns to bootrom and waits. + \ No newline at end of file diff --git a/WEEK03/slides/WEEK03-IMG08.svg b/WEEK03/slides/WEEK03-IMG08.svg new file mode 100644 index 0000000..b85e7ce --- /dev/null +++ b/WEEK03/slides/WEEK03-IMG08.svg @@ -0,0 +1,93 @@ + + + + + +Data Copy & BSS Clear +Initializing RAM Before main() Can Run + + + +Phase 2: Data Copy +Copy initialized variables flash -> RAM + +C code: + +int counter = 42; + +Value 42 stored in flash +but variables live in RAM! + + + +Flash + +-> + + +RAM + + +data_cpy_table has entries: + +src: 0x10001B4C (flash) +dst: 0x20000110 (RAM) + + + +Phase 3: BSS Clear +Zero uninitialized global variables + +C code: + +int my_counter; + +C standard requires +this to start at zero. + + + +r1 = BSS start +r2 = BSS end +r0 = 0 + +Loop: store 0, advance r1 +Until r1 == r2 -> done! + + + +Key Assembly Instructions + + + +ldmia r4!, {r1,r2,r3} + +Load source, dest, end from table + + +bl data_cpy + +Copy word-by-word until done + + + +movs r0, #0 + +Load zero into r0 + + +stmia r1!, {r0} + +Store zero, advance pointer + \ No newline at end of file diff --git a/WEEK03/slides/WEEK03-IMG09.svg b/WEEK03/slides/WEEK03-IMG09.svg new file mode 100644 index 0000000..8f0373c --- /dev/null +++ b/WEEK03/slides/WEEK03-IMG09.svg @@ -0,0 +1,82 @@ + + + + + +Platform Entry -> main() +The Final Step — 3 Function Calls at 0x10000186 + + + +platform_entry Assembly + + +0x10000186 +ldr r1, [DAT] +-> load runtime_init addr + + +0x10000188 +blx r1 +-> call runtime_init() + + +0x1000018C +blx r1 +-> call main() + + +0x10000190 +blx r1 +-> call exit() + + + +Call Sequence + + +runtime_init() +SDK setup + +-> + + +main() +YOUR CODE + +-> + + +exit() +cleanup + + + +runtime_init() +Initializes SDK systems: +• Clock configuration +• GPIO setup +• C++ constructor calls +• Peripheral initialization + + +After main() Returns +exit() handles cleanup. +Then: + +bkpt 0x0000 +<- infinite halt + +Should never be reached! + \ No newline at end of file diff --git a/WEEK03/slides/WEEK03-IMG10.svg b/WEEK03/slides/WEEK03-IMG10.svg new file mode 100644 index 0000000..73b2c7c --- /dev/null +++ b/WEEK03/slides/WEEK03-IMG10.svg @@ -0,0 +1,92 @@ + + + + + +Secure Boot & Attack Vectors +Why Boot Sequence Knowledge Matters for Security + + + +Attack Scenarios + + +Firmware Replacement +Replace flash with malicious code + + +Vector Table Hijack +Modify reset handler address + + +Debug Port Attack +SWD/JTAG to dump or inject code + + +Startup Code Modification +Change crt0 data copy / BSS init + +Physical access = game over + + + +Defense Strategies + + +1. Secure Boot + + +2. Debug Port Lock + + +3. Flash Read Protect + + +4. MPU Configuration + + +5. Integrity Checks + +Defense in depth! + + + +Secure Boot Chain + + +Bootrom +immutable + +-> + + +Verify Sig +IMAGE_DEF + +-> + + +Verify App +signature + +-> + + +Boot! +or refuse + +Each stage cryptographically verifies +the next before handing off control. +Bootrom = trust anchor (can't be changed) + \ No newline at end of file diff --git a/WEEKS/WEEK02/WEEK02-SLIDES.pdf b/WEEKS/WEEK02/WEEK02-SLIDES.pdf index 25756f8..be346bc 100644 Binary files a/WEEKS/WEEK02/WEEK02-SLIDES.pdf and b/WEEKS/WEEK02/WEEK02-SLIDES.pdf differ diff --git a/WEEKS/WEEK03/WEEK03-SLIDES.pdf b/WEEKS/WEEK03/WEEK03-SLIDES.pdf index 9ad8b53..3d7e59a 100644 Binary files a/WEEKS/WEEK03/WEEK03-SLIDES.pdf and b/WEEKS/WEEK03/WEEK03-SLIDES.pdf differ diff --git a/WEEKS/WEEK03/WEEK03.md b/WEEKS/WEEK03/WEEK03.md index a760a49..c5d4463 100644 --- a/WEEKS/WEEK03/WEEK03.md +++ b/WEEKS/WEEK03/WEEK03.md @@ -130,8 +130,8 @@ Think of the bootrom like the BIOS in your computer - it's the first thing that ### What Does the Bootrom Do? 1. **Initialize Hardware**: Sets up clocks, resets peripherals -2. **Check Boot Sources**: Looks for valid firmware in flash -3. **Validate Firmware**: Checks for magic markers (IMAGE_DEF) +2. **Check Boot Sources (Discovery)**: Scans configured boot sources (for this course: flash) to find a candidate firmware image region. +3. **Validate Firmware (Validation)**: Verifies that candidate by finding IMAGE_DEF start/end markers and parsing the block. 4. **Configure Flash**: Sets up the XIP interface 5. **Jump to Your Code**: Reads the vector table and jumps to your reset handler @@ -158,6 +158,54 @@ Here's what it looks like in the Pico SDK: - `0xffffded3` = Start marker ("I'm a valid Pico binary!") - `0xab123579` = End marker ("End of the header block") +### See This Exact Block in Your ELF (Commands + Real Output) + +Use these commands to view the IMAGE_DEF bytes directly in the ELF: + +```powershell +arm-none-eabi-objdump -s --start-address=0x1000013c --stop-address=0x10000150 build/0x0001_hello-world.elf +arm-none-eabi-objdump -s --start-address=0x10000130 --stop-address=0x10000154 build/0x0001_hello-world.elf +arm-none-eabi-gdb build/0x0001_hello-world.elf -ex "x/20bx 0x1000013c" -ex quit +``` + +Actual output from this lesson build: + +```text +build/0x0001_hello-world.elf: file format elf32-littlearm + +Contents of section .text: + 1000013c 42012110 ff010000 b01b0000 793512ab B.!.........y5.. + 1000014c 4ff00000 O... + +build/0x0001_hello-world.elf: file format elf32-littlearm + +Contents of section .text: + 10000130 a0010010 90a31ae7 d3deffff 42012110 ............B.!. + 10000140 ff010000 b01b0000 793512ab 4ff00000 ........y5..O... + 10000150 1e490860 .I.` +``` + +Command 1 explained (`--start-address=0x1000013c --stop-address=0x10000150`): +- Starts at `0x1000013c`, so it does **not** include the start marker at `0x10000138` (`d3deffff`). +- Shows IMAGE_DEF body fields and the end marker: + - `42012110` = `42 01 21 10` (item type/size + secure mode field) + - `ff010000` = last-item marker + size + pad + - `b01b0000` = next word in the block payload for this build + - `793512ab` = `PICOBIN_BLOCK_MARKER_END` (`0xab123579` in little-endian) +- `4ff00000` at `0x1000014c` is already the next instruction word after IMAGE_DEF. + +Command 2 explained (`--start-address=0x10000130 --stop-address=0x10000154`): +- Starts earlier, so it captures context **and** both IMAGE_DEF markers. +- `a0010010 90a31ae7` = binary-info context before IMAGE_DEF. +- `d3deffff` at `0x10000138` = `PICOBIN_BLOCK_MARKER_START`. +- `793512ab` at `0x10000148` = `PICOBIN_BLOCK_MARKER_END`. +- `4ff00000 1e490860` = code words after the IMAGE_DEF block. +- This command proves the full block location for this build: `0x10000138` to `0x1000014b`. + +Important: IMAGE_DEF offset can vary by build. In this build, the start marker `d3deffff` +is at `0x10000138` (not `0x1000013c`), so always search for the marker bytes instead of +assuming a fixed address. + > 📖 **Datasheet Reference:** Block markers are defined in Section 5.1.5.1 "Blocks" (p. 357): *"it must begin with the 4 byte magic header, PICOBIN_BLOCK_MARKER_START (0xffffded3)"* and *"it must end with the 4 byte magic footer, PICOBIN_BLOCK_MARKER_END (0xab123579)"*. The minimum Arm IMAGE_DEF is detailed in Section 5.9.5.1 (p. 429). > ⚠️ **RP2350 vs RP2040 Key Difference:** Unlike the RP2040, the RP2350 does **not** require a checksummed "boot2" function at flash address 0. The RP2350 bootrom performs its own flash XIP setup. Instead, the RP2350 requires a valid IMAGE_DEF block **anywhere within the first 4 kB** of the image (Datasheet §5.9.5, p. 429: *"This must appear within the first 4 kB of a flash image"*; §5.2, p. 375: *"the main differences being the removal of a boot2 in the first 256 bytes of the image"*). @@ -350,7 +398,7 @@ arm-none-eabi-gdb build\0x0001_hello-world.elf **Connect to target:** ```gdb -(gdb) target remote :3333 +(gdb) target extended-remote :3333 (gdb) monitor reset halt ``` @@ -383,7 +431,7 @@ Let's look at the first 4 entries of the vector table at `0x10000000`: ### Step 2: Understanding What We See -> 🔄 **REVIEW:** In Week 1, we saw `sp = 0x20081fc8` when stopped at `main`. That's *after* some stack was used during boot. Here we see the *initial* stack pointer before any code runs! +> 🔄 **REVIEW:** In Weeks 1-2, we saw both `sp = 0x20082000` at the clean breakpoint at `main` and lower values like `0x20081fc8` or `0x20081ff8` after additional stack activity. Here we are looking at the *initial* stack pointer from the vector table before any code runs. Let's decode each value: @@ -491,39 +539,39 @@ Let's look at more instructions to see the full picture: (gdb) x/20i 0x1000015c ``` -**You should see something like:** +**You should see:** ``` -0x1000015c <_reset_handler>: mov.w r0, #3489660928 @ 0xd0000000 -0x10000160 <_reset_handler+4>: ldr r0, [r0, #0] -0x10000162 <_reset_handler+6>: -cbz r0, 0x1000016a -0x10000164 : mov.w r0, #0 -0x10000168 : -b.n 0x10000150 <_enter_vtable_in_r0> -0x1000016a : -add r4, pc, #52 @ (adr r4, 0x100001a0 ) -0x1000016c : ldmia r4!, {r1, r2, r3} -0x1000016e : cmp r1, #0 -0x10000170 : -beq.n 0x10000178 -0x10000172 : -bl 0x1000019a -0x10000176 : -b.n 0x1000016c -0x10000178 : -ldr r1, [pc, #84] @ (0x100001d0 ) -0x1000017a : -ldr r2, [pc, #88] @ (0x100001d4 ) -0x1000017c : movs r0, #0 -0x1000017e : -b.n 0x10000182 -0x10000180 : stmia r1!, {r0} -0x10000182 : cmp r1, r2 -0x10000184 : bne.n 0x10000180 -0x10000186 : -ldr r1, [pc, #80] @ (0x100001d8 ) -0x10000188 : blx r1 + 0x1000015c <_reset_handler>: mov.w r0, #3489660928 @ 0xd0000000 + 0x10000160 <_reset_handler+4>: ldr r0, [r0, #0] + 0x10000162 <_reset_handler+6>: + cbz r0, 0x1000016a + 0x10000164 : mov.w r0, #0 + 0x10000168 : + b.n 0x10000150 <_enter_vtable_in_r0> + 0x1000016a : + add r4, pc, #52 @ (adr r4, 0x100001a0 ) + 0x1000016c : ldmia r4!, {r1, r2, r3} + 0x1000016e : cmp r1, #0 + 0x10000170 : + beq.n 0x10000178 + 0x10000172 : + bl 0x1000019a + 0x10000176 : + b.n 0x1000016c + 0x10000178 : + ldr r1, [pc, #84] @ (0x100001d0 ) + 0x1000017a : + ldr r2, [pc, #88] @ (0x100001d4 ) + 0x1000017c : movs r0, #0 + 0x1000017e : + b.n 0x10000182 + 0x10000180 : stmia r1!, {r0} + 0x10000182 : cmp r1, r2 + 0x10000184 : bne.n 0x10000180 + 0x10000186 : + ldr r1, [pc, #80] @ (0x100001d8 ) + 0x10000188 : blx r1 ``` > 💡 **About GDB Label Offsets:** You may notice GDB shows instructions like `` for code that is clearly part of the data copy loop, not the core-parking function. This is **not** a GDB bug or "symbol snapping" — `hold_non_core0_in_bootrom` is a **real label** defined in the SDK's `crt0.S` (line 454). The `+8` offset simply means "8 bytes past that label." GDB always displays addresses relative to the nearest preceding symbol. The data copy code falls through from the `cbz` branch at the core check, landing right after the `hold_non_core0_in_bootrom` label, hence the offset. @@ -540,22 +588,23 @@ The reset handler performs several phases: └─────────────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────────┐ -│ PHASE 2: Data Copy (0x1000016a - 0x10000176) │ +│ PHASE 2: Data Copy Setup & Loop (0x1000016a - 0x10000176) │ +│ - Set up the data_cpy_table pointer and load each copy triplet │ │ - Copy initialized variables from flash to RAM │ -│ - Uses data_cpy_table for source/destination info │ └─────────────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────────┐ -│ PHASE 3: BSS Clear (0x10000178 - 0x10000184) │ +│ PHASE 3: BSS Setup & Clear (0x10000178 - 0x10000184) │ +│ - Load the BSS start/end addresses into r1 and r2 │ +│ - GDB labels those literals as `data_cpy_table+48/+52` │ │ - Zero out all uninitialized global variables │ -│ - C standard requires BSS to start at zero │ └─────────────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────────┐ -│ PHASE 4: Runtime Init & Main (0x10000186+) │ -│ - Call runtime_init() for SDK setup │ -│ - Call __libc_init_array() for C++ constructors │ -│ - Finally call main()! │ +│ PHASE 4: Platform Entry Begins (0x10000186 - 0x10000188 shown) │ +│ - Load the runtime_init() pointer from the table │ +│ - Branch to runtime_init() with `blx r1` │ +│ - `main()` and `exit()` appear a few instructions later │ └─────────────────────────────────────────────────────────────────┘ ``` @@ -668,6 +717,8 @@ b.n 0x10000182 0x10000180 : stmia r1!, {r0} ``` +The first two `ldr` instructions are still part of the **BSS clear setup**, even though GDB shows the source words as `data_cpy_table+48` and `data_cpy_table+52`. That label means the two literal words live in the same nearby constant block as the copy-table entries; it does **not** mean the code is still performing `.data` copies. At this point, `r1` becomes the BSS start address, `r2` becomes the BSS end address, and the loop beginning at `0x10000180` zeros that range. + ### Understanding the Loop ``` @@ -1018,7 +1069,7 @@ Ghidra can visualize the call flow: 1. With `_reset_handler` selected, go to **Window → Function Call Graph** 2. This shows a visual graph of all function calls from the reset handler -3. You can see the path: `_reset_handler` → `platform_entry` → `main` +3. You will see `_reset_handler` at the top with arrows going down to its four direct callees: `data_cpy`, `runtime_init`, `main`, and `exit` ### Comparing GDB and Ghidra for Boot Analysis @@ -1156,21 +1207,18 @@ Ghidra can visualize the call flow: - Is it a valid code address (starts with `0x1000...`)? - What handler does it point to? -### Exercise 4: Find Your Main Function +### Exercise 4: Find Your Main Function and Trace Back 1. Use `info functions main` to find main 2. Examine 10 instructions at that address 3. Identify the first function call in main 4. What does that function do? +5. When stopped at main, examine `$lr` (link register) +6. What address is stored there? +7. Disassemble that address - what function is it? +8. This shows you where main was called from! -### Exercise 5: Trace Back from Main - -1. When stopped at main, examine `$lr` (link register) -2. What address is stored there? -3. Disassemble that address - what function is it? -4. This shows you where main was called from! - -### Exercise 6: Ghidra Boot Analysis +### Exercise 5: Ghidra Boot Analysis 1. In Ghidra, navigate to `_reset_handler` 2. Use **Window → Function Call Graph** to visualize the call tree @@ -1398,6 +1446,180 @@ https://github.com/raspberrypi/pico-bootrom-rp2350 --- +## 🔬 Part 17: Proving the Boot Sequence with objdump + +Everything we have learned about the boot sequence can be proven directly from the compiled ELF binary using `arm-none-eabi-objdump`. The bootrom is not in your ELF (it is mask ROM burned into the chip at `0x00000000`), but everything your firmware provides — the vector table, the IMAGE_DEF, and the reset handler — lives in your ELF starting at `0x10000000`. + +### Step 1: List All Sections + +```bash +arm-none-eabi-objdump -h build/0x0001_hello-world.elf +``` + +Expected output (key sections): + +``` +Idx Name Size VMA LMA + 0 .text 000019cc 10000000 10000000 + 3 .binary_info 0000002c 10001b20 10001b20 + 4 .ram_vector_table 00000110 20000000 20000000 + 6 .data 0000019c 20000110 10001b4c +``` + +> 💡 The Pico SDK merges `.vectors`, `.embedded_block`, and `.reset` all into `.text` at `0x10000000`. They are not separate named ELF sections — they are sub-regions inside `.text`. + +### Step 2: Dump the First 0x150 Bytes of Flash — One Command, Zero Skips + +```bash +arm-none-eabi-objdump -s --start-address=0x10000000 --stop-address=0x10000150 build/0x0001_hello-world.elf +``` + +Raw output from that command: + +``` + 10000000 00200820 5d010010 1b010010 1d010010 . . ]........... + 10000010 11010010 11010010 11010010 11010010 ................ + 10000020 11010010 11010010 11010010 11010010 ................ + 10000030 11010010 11010010 11010010 11010010 ................ + 10000040 11010010 11010010 11010010 11010010 ................ + 10000050 11010010 11010010 11010010 11010010 ................ + 10000060 11010010 11010010 11010010 11010010 ................ + 10000070 11010010 11010010 11010010 11010010 ................ + 10000080 11010010 11010010 11010010 11010010 ................ + 10000090 11010010 11010010 11010010 11010010 ................ + 100000a0 11010010 11010010 11010010 11010010 ................ + 100000b0 11010010 11010010 11010010 11010010 ................ + 100000c0 11010010 11010010 11010010 11010010 ................ + 100000d0 11010010 11010010 11010010 11010010 ................ + 100000e0 11010010 11010010 11010010 11010010 ................ + 100000f0 11010010 11010010 11010010 11010010 ................ + 10000100 11010010 11010010 11010010 11010010 ................ + 10000110 eff30580 103800be 00be00be 00be00be .....8.......... + 10000120 00be00be f2eb8871 201b0010 4c1b0010 .......q ...L... + 10000130 a0010010 90a31ae7 d3deffff 42012110 ............B.!. + 10000140 ff010000 b01b0000 793512ab ........y5.. +``` + +Every address annotated, no skips: + +#### 0x10000000 — Vector Table, Mandatory Entries + +| Address | Raw Bytes (LE) | Decoded | What it is | +|---------|----------------|---------|------------| +| `0x10000000` | `00 20 08 20` | `0x20082000` | **Initial SP** — top of SCRATCH_Y RAM. Bootrom loads MSP from here before doing anything else. | +| `0x10000004` | `5d 01 00 10` | `0x1000015d` | **Reset_Handler** address with Thumb bit set. Strip bit 0 → real address `0x1000015c`. Bootrom jumps here. | +| `0x10000008` | `1b 01 00 10` | `0x1000011b` | **NMI** handler address (Thumb, → `0x1000011a`). | +| `0x1000000c` | `1d 01 00 10` | `0x1000011d` | **HardFault** handler address (Thumb, → `0x1000011c`). | + +#### 0x10000010–0x1000010f — Vector Table, IRQ Slots (all 52 external IRQs) + +``` + 10000010 11010010 11010010 ...(repeats through 0x1000010f)... +``` + +Every 4-byte word here is `11 01 00 10` = pointer `0x10000111`. +That is the **default IRQ handler** address with Thumb bit set (→ `0x10000110`). +The RP2350 Cortex-M33 has 16 system vectors (offsets 0x00–0x3f) plus up to 52 +external IRQ vectors (offsets 0x40–0xff = addresses `0x10000040`–`0x1000010f`). +Every IRQ the application does not register gets this default handler pointer. +This block is 240 bytes (`0x10000010` to `0x1000010f`) of nothing but that one +repeated pointer. + +#### 0x10000110–0x10000127 — Default IRQ Handler Code + +``` + 10000110 eff30580 103800be 00be00be 00be00be + 10000120 00be00be f2eb8871 +``` + +| Address | Bytes | ARM Thumb-2 Instruction | What it does | +|---------|-------|-------------------------|--------------| +| `0x10000110` | `ef f3 05 80` | `MRS r0, IPSR` | Read the Interrupt Program Status Register into r0. The low 9 bits = the active vector number. | +| `0x10000114` | `10 38` | `SUBS r0, #16` | Vector 16 = IRQ0, so subtract 16 to convert vector number → IRQ index. | +| `0x10000116` | `00 be` | `BKPT #0` | Software breakpoint. If a debugger is attached, it stops here and you can inspect r0 to see which IRQ fired. If no debugger is attached, the CPU enters a fault loop and the chip hangs. | +| `0x10000118`–`0x10000127` | `00 be` ×12 | `BKPT #0` repeating | Alignment padding to the next 4-byte boundary. | + +This is the **entire** default IRQ handler. It is intentionally minimal: if your +code triggers an IRQ you did not register, it crashes visibly instead of silently. + +#### 0x10000128–0x1000013b — Binary Info Pointer Table + +``` + 10000120 201b0010 4c1b0010 + 10000130 a0010010 90a31ae7 +``` + +| Address | Bytes (LE) | Decoded Value | What it is | +|---------|------------|---------------|------------| +| `0x10000128` | `20 1b 00 10` | `0x10001b20` | Pointer to **start** of `.binary_info` data section in flash. | +| `0x1000012c` | `4c 1b 00 10` | `0x10001b4c` | Pointer to **end** of `.binary_info` data section in flash. | +| `0x10000130` | `a0 01 00 10` | `0x100001a0` | Pointer to `binary_info_callback` function. | +| `0x10000134` | `90 a3 1a e7` | (magic marker) | `BINARY_INFO_MARKER_END` — marks the end of this pointer table. | + +`picotool` reads this table to extract the program name, version string, URL, +and GPIO pin map from any compiled binary without running it. + +#### 0x10000138–0x1000014c — IMAGE_DEF Block (this build) + +``` + 10000130 a0010010 90a31ae7 d3deffff 42012110 + 10000140 ff010000 b01b0000 793512ab 4ff00000 +``` + +| Address | Bytes | What it is | +|---------|-------|------------| +| `0x10000138` | `d3 de ff ff` | `PICOBIN_BLOCK_MARKER_START` — the bootrom scans flash for this exact 4-byte sequence to locate the IMAGE_DEF. | +| `0x1000013c` | `42 01 21 10` | IMAGE_DEF content (image type, flags, version). | +| `0x10000140` | `ff 01 00 00` | IMAGE_DEF content (continuation). | +| `0x10000144` | `b0 1b 00 00` | IMAGE_DEF content (continuation). | +| `0x10000148` | `79 35 12 ab` | `PICOBIN_BLOCK_MARKER_END` — bootrom stops scanning here. | + +The IMAGE_DEF sits at `0x10000138`–`0x1000014b` in this build, +well within the 4 KB scan window the bootrom uses (Datasheet §5.9.5, p. 429). + +#### Full Flash Map: 0x10000000–0x1000015c + +``` + 0x10000000–0x1000000f Vector Table: mandatory entries (SP, Reset, NMI, HardFault) + 0x10000010–0x1000010f Vector Table: 52 external IRQ slots → all point to default handler + 0x10000110–0x10000127 Default IRQ handler code (MRS / SUBS / BKPT) + 0x10000128–0x10000137 Binary info pointer table (start / end / callback / magic end) + 0x10000138–0x1000014b IMAGE_DEF block (d3 de ff ff ... 79 35 12 ab) + 0x10000150–0x1000015b (padding / alignment) + 0x1000015c Reset_Handler (_reset_handler in crt0.S) ← bootrom jumps here +``` + +### Step 4: Confirmed Boot Sequence (proven from ELF) + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ PROVEN BOOT SEQUENCE (0x0001_hello-world) │ +├─────────────────────────────────────────────────────────────────┤ +│ 1. Bootrom reads 0x10000000 │ +│ → SP = 0x20082000 (offset +0x00 of vector table) │ +│ → RST = 0x1000015d (offset +0x04, Thumb → 0x1000015c) │ +├─────────────────────────────────────────────────────────────────┤ +│ 2. Bootrom scans first 4 kB for IMAGE_DEF │ +│ → Found at 0x10000138 (this build) │ +│ → Start marker: d3 de ff ff │ +│ → End marker: 79 35 12 ab │ +├─────────────────────────────────────────────────────────────────┤ +│ 3. Bootrom jumps to reset handler at 0x1000015c │ +│ → _reset_handler (crt0.S) runs │ +│ → Checks CPUID — Core 1 sent back to bootrom │ +│ → Core 0: .data copied, .bss zeroed, platform_entry called │ +├─────────────────────────────────────────────────────────────────┤ +│ 4. platform_entry calls runtime_init → main → exit │ +└─────────────────────────────────────────────────────────────────┘ +``` + +> 📖 **Datasheet References:** +> - §5.1.5.1 (p. 357): Block markers `0xffffded3` (start) and `0xab123579` (end) +> - §5.9.5 (p. 429): IMAGE_DEF must appear within first 4 kB of flash image +> - §5.9.5.1 (p. 429): Bootrom enters via reset handler at vector table offset +4 + +--- + **Remember:** Understanding the boot process is fundamental to embedded systems work. Whether you're debugging a system that won't start, reverse engineering firmware, or building secure boot chains, this knowledge is essential! Happy exploring! 🔍 diff --git a/WEEKS/WEEK03/slides/WEEK03-IMG01.svg b/WEEKS/WEEK03/slides/WEEK03-IMG01.svg index 00427ba..0b8b8bd 100644 --- a/WEEKS/WEEK03/slides/WEEK03-IMG01.svg +++ b/WEEKS/WEEK03/slides/WEEK03-IMG01.svg @@ -24,7 +24,7 @@ Cortex-M33 wakes, execution at 0x00000000 (Bootrom) - + @@ -33,7 +33,7 @@ 32KB on-chip ROM — finds IMAGE_DEF at 0x10000000 - + @@ -42,7 +42,7 @@ Bootrom configures flash interface & XIP (no boot2 on RP2350) - + @@ -58,9 +58,9 @@ STEP 5 C Runtime Startup (crt0.S) -Copy .data from flash -> RAM -Zero .bss section -Call runtime_init() -> main() +Copy .data from flash -> RAM +Zero .bss section +Call runtime_init() -> main() diff --git a/WEEKS/WEEK03/slides/WEEK03-IMG04.svg b/WEEKS/WEEK03/slides/WEEK03-IMG04.svg index f843576..22034ba 100644 --- a/WEEKS/WEEK03/slides/WEEK03-IMG04.svg +++ b/WEEKS/WEEK03/slides/WEEK03-IMG04.svg @@ -76,5 +76,5 @@ PendSV, SysTick all use: bkpt 0x0000 -<- stops debugger +<- stops debugger \ No newline at end of file diff --git a/WEEKS/WEEK03/slides/WEEK03-IMG07.svg b/WEEKS/WEEK03/slides/WEEK03-IMG07.svg index eea62be..262aac0 100644 --- a/WEEKS/WEEK03/slides/WEEK03-IMG07.svg +++ b/WEEKS/WEEK03/slides/WEEK03-IMG07.svg @@ -60,19 +60,19 @@ Core Check CPUID == 0? --> +-> Data Copy flash -> RAM --> +-> BSS Clear zero globals --> +-> Platform Entry diff --git a/WEEKS/WEEK03/slides/WEEK03-IMG09.svg b/WEEKS/WEEK03/slides/WEEK03-IMG09.svg index d2f8f1f..8f0373c 100644 --- a/WEEKS/WEEK03/slides/WEEK03-IMG09.svg +++ b/WEEKS/WEEK03/slides/WEEK03-IMG09.svg @@ -49,13 +49,13 @@ runtime_init() SDK setup --> +-> main() YOUR CODE --> +-> exit() @@ -76,7 +76,7 @@ Then: bkpt 0x0000 -<- infinite halt +<- infinite halt Should never be reached! \ No newline at end of file diff --git a/WEEKS/WEEK03/slides/WEEK03-IMG10.svg b/WEEKS/WEEK03/slides/WEEK03-IMG10.svg index 7dd1bcb..73b2c7c 100644 --- a/WEEKS/WEEK03/slides/WEEK03-IMG10.svg +++ b/WEEKS/WEEK03/slides/WEEK03-IMG10.svg @@ -68,19 +68,19 @@ Bootrom immutable --> +-> Verify Sig IMAGE_DEF --> +-> Verify App signature --> +-> Boot! diff --git a/drivers/0x01_uart_cbm/Src/rp2350_reset_handler.c b/drivers/0x01_uart_cbm/Src/rp2350_reset_handler.c index 46645b1..62b58d2 100644 --- a/drivers/0x01_uart_cbm/Src/rp2350_reset_handler.c +++ b/drivers/0x01_uart_cbm/Src/rp2350_reset_handler.c @@ -38,10 +38,38 @@ extern int main(void); +extern uint32_t __data_lma; +extern uint32_t __data_start; +extern uint32_t __data_end; +extern uint32_t __bss_start; +extern uint32_t __bss_end; + +static void _data_copy_init(void) +{ + uint32_t *src = &__data_lma; + uint32_t *dst = &__data_start; + while (dst < &__data_end) + *dst++ = *src++; +} + +static void _bss_zero_init(void) +{ + uint32_t *dst = &__bss_start; + while (dst < &__bss_end) + *dst++ = 0U; +} + +void _ram_init(void) +{ + stack_init(); + _data_copy_init(); + _bss_zero_init(); +} + void __attribute__((naked, noreturn)) Reset_Handler(void) { __asm__ volatile ( - "bl stack_init\n\t" + "bl _ram_init\n\t" "bl xosc_init\n\t" "bl xosc_enable_peri_clk\n\t" "bl reset_init_subsystem\n\t" diff --git a/drivers/0x01_uart_cbm/build.log b/drivers/0x01_uart_cbm/build.log new file mode 100644 index 0000000..c38a16d Binary files /dev/null and b/drivers/0x01_uart_cbm/build.log differ diff --git a/drivers/0x01_uart_cbm/linker.ld b/drivers/0x01_uart_cbm/linker.ld index 09ea7a6..0ad5c05 100644 --- a/drivers/0x01_uart_cbm/linker.ld +++ b/drivers/0x01_uart_cbm/linker.ld @@ -50,6 +50,7 @@ MEMORY PHDRS { text PT_LOAD FLAGS(5); + data PT_LOAD FLAGS(6); } /** @@ -94,6 +95,35 @@ SECTIONS KEEP(*(.embedded_block)) } > FLASH :text + /** + * Initialized data and RAM-resident code (LMA in flash, VMA in RAM). + * Startup copies from __data_lma to __data_start..__data_end. + */ + .data : + { + . = ALIGN(4); + __data_start = .; + *(.ram_func*) + *(.data*) + . = ALIGN(4); + __data_end = .; + } > RAM AT> FLASH :data + + __data_lma = LOADADDR(.data); + + /** + * Uninitialized data (BSS) in RAM. + */ + .bss (NOLOAD) : + { + . = ALIGN(4); + __bss_start = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + } > RAM + /** * Non-secure stack symbols. */ diff --git a/drivers/0x02_blink_cbm/Src/rp2350_reset_handler.c b/drivers/0x02_blink_cbm/Src/rp2350_reset_handler.c index 46645b1..62b58d2 100644 --- a/drivers/0x02_blink_cbm/Src/rp2350_reset_handler.c +++ b/drivers/0x02_blink_cbm/Src/rp2350_reset_handler.c @@ -38,10 +38,38 @@ extern int main(void); +extern uint32_t __data_lma; +extern uint32_t __data_start; +extern uint32_t __data_end; +extern uint32_t __bss_start; +extern uint32_t __bss_end; + +static void _data_copy_init(void) +{ + uint32_t *src = &__data_lma; + uint32_t *dst = &__data_start; + while (dst < &__data_end) + *dst++ = *src++; +} + +static void _bss_zero_init(void) +{ + uint32_t *dst = &__bss_start; + while (dst < &__bss_end) + *dst++ = 0U; +} + +void _ram_init(void) +{ + stack_init(); + _data_copy_init(); + _bss_zero_init(); +} + void __attribute__((naked, noreturn)) Reset_Handler(void) { __asm__ volatile ( - "bl stack_init\n\t" + "bl _ram_init\n\t" "bl xosc_init\n\t" "bl xosc_enable_peri_clk\n\t" "bl reset_init_subsystem\n\t" diff --git a/drivers/0x02_blink_cbm/build.log b/drivers/0x02_blink_cbm/build.log new file mode 100644 index 0000000..5289e0a Binary files /dev/null and b/drivers/0x02_blink_cbm/build.log differ diff --git a/drivers/0x02_blink_cbm/linker.ld b/drivers/0x02_blink_cbm/linker.ld index 09ea7a6..0ad5c05 100644 --- a/drivers/0x02_blink_cbm/linker.ld +++ b/drivers/0x02_blink_cbm/linker.ld @@ -50,6 +50,7 @@ MEMORY PHDRS { text PT_LOAD FLAGS(5); + data PT_LOAD FLAGS(6); } /** @@ -94,6 +95,35 @@ SECTIONS KEEP(*(.embedded_block)) } > FLASH :text + /** + * Initialized data and RAM-resident code (LMA in flash, VMA in RAM). + * Startup copies from __data_lma to __data_start..__data_end. + */ + .data : + { + . = ALIGN(4); + __data_start = .; + *(.ram_func*) + *(.data*) + . = ALIGN(4); + __data_end = .; + } > RAM AT> FLASH :data + + __data_lma = LOADADDR(.data); + + /** + * Uninitialized data (BSS) in RAM. + */ + .bss (NOLOAD) : + { + . = ALIGN(4); + __bss_start = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + } > RAM + /** * Non-secure stack symbols. */ diff --git a/drivers/0x03_button_cbm/Src/rp2350_reset_handler.c b/drivers/0x03_button_cbm/Src/rp2350_reset_handler.c index 46645b1..62b58d2 100644 --- a/drivers/0x03_button_cbm/Src/rp2350_reset_handler.c +++ b/drivers/0x03_button_cbm/Src/rp2350_reset_handler.c @@ -38,10 +38,38 @@ extern int main(void); +extern uint32_t __data_lma; +extern uint32_t __data_start; +extern uint32_t __data_end; +extern uint32_t __bss_start; +extern uint32_t __bss_end; + +static void _data_copy_init(void) +{ + uint32_t *src = &__data_lma; + uint32_t *dst = &__data_start; + while (dst < &__data_end) + *dst++ = *src++; +} + +static void _bss_zero_init(void) +{ + uint32_t *dst = &__bss_start; + while (dst < &__bss_end) + *dst++ = 0U; +} + +void _ram_init(void) +{ + stack_init(); + _data_copy_init(); + _bss_zero_init(); +} + void __attribute__((naked, noreturn)) Reset_Handler(void) { __asm__ volatile ( - "bl stack_init\n\t" + "bl _ram_init\n\t" "bl xosc_init\n\t" "bl xosc_enable_peri_clk\n\t" "bl reset_init_subsystem\n\t" diff --git a/drivers/0x03_button_cbm/build.log b/drivers/0x03_button_cbm/build.log new file mode 100644 index 0000000..ddf0e65 Binary files /dev/null and b/drivers/0x03_button_cbm/build.log differ diff --git a/drivers/0x03_button_cbm/linker.ld b/drivers/0x03_button_cbm/linker.ld index 09ea7a6..0ad5c05 100644 --- a/drivers/0x03_button_cbm/linker.ld +++ b/drivers/0x03_button_cbm/linker.ld @@ -50,6 +50,7 @@ MEMORY PHDRS { text PT_LOAD FLAGS(5); + data PT_LOAD FLAGS(6); } /** @@ -94,6 +95,35 @@ SECTIONS KEEP(*(.embedded_block)) } > FLASH :text + /** + * Initialized data and RAM-resident code (LMA in flash, VMA in RAM). + * Startup copies from __data_lma to __data_start..__data_end. + */ + .data : + { + . = ALIGN(4); + __data_start = .; + *(.ram_func*) + *(.data*) + . = ALIGN(4); + __data_end = .; + } > RAM AT> FLASH :data + + __data_lma = LOADADDR(.data); + + /** + * Uninitialized data (BSS) in RAM. + */ + .bss (NOLOAD) : + { + . = ALIGN(4); + __bss_start = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + } > RAM + /** * Non-secure stack symbols. */ diff --git a/drivers/0x04_pwm_cbm/Src/rp2350_reset_handler.c b/drivers/0x04_pwm_cbm/Src/rp2350_reset_handler.c index 25dfd35..4688437 100644 --- a/drivers/0x04_pwm_cbm/Src/rp2350_reset_handler.c +++ b/drivers/0x04_pwm_cbm/Src/rp2350_reset_handler.c @@ -39,6 +39,34 @@ extern int main(void); +extern uint32_t __data_lma; +extern uint32_t __data_start; +extern uint32_t __data_end; +extern uint32_t __bss_start; +extern uint32_t __bss_end; + +static void _data_copy_init(void) +{ + uint32_t *src = &__data_lma; + uint32_t *dst = &__data_start; + while (dst < &__data_end) + *dst++ = *src++; +} + +static void _bss_zero_init(void) +{ + uint32_t *dst = &__bss_start; + while (dst < &__bss_end) + *dst++ = 0U; +} + +void _ram_init(void) +{ + stack_init(); + _data_copy_init(); + _bss_zero_init(); +} + void _late_init(void) { pwm_release_reset(); @@ -48,7 +76,7 @@ void _late_init(void) void __attribute__((naked, noreturn)) Reset_Handler(void) { __asm__ volatile ( - "bl stack_init\n\t" + "bl _ram_init\n\t" "bl xosc_init\n\t" "bl xosc_enable_peri_clk\n\t" "bl reset_init_subsystem\n\t" diff --git a/drivers/0x04_pwm_cbm/build.log b/drivers/0x04_pwm_cbm/build.log new file mode 100644 index 0000000..fd7204c Binary files /dev/null and b/drivers/0x04_pwm_cbm/build.log differ diff --git a/drivers/0x04_pwm_cbm/linker.ld b/drivers/0x04_pwm_cbm/linker.ld index 09ea7a6..0ad5c05 100644 --- a/drivers/0x04_pwm_cbm/linker.ld +++ b/drivers/0x04_pwm_cbm/linker.ld @@ -50,6 +50,7 @@ MEMORY PHDRS { text PT_LOAD FLAGS(5); + data PT_LOAD FLAGS(6); } /** @@ -94,6 +95,35 @@ SECTIONS KEEP(*(.embedded_block)) } > FLASH :text + /** + * Initialized data and RAM-resident code (LMA in flash, VMA in RAM). + * Startup copies from __data_lma to __data_start..__data_end. + */ + .data : + { + . = ALIGN(4); + __data_start = .; + *(.ram_func*) + *(.data*) + . = ALIGN(4); + __data_end = .; + } > RAM AT> FLASH :data + + __data_lma = LOADADDR(.data); + + /** + * Uninitialized data (BSS) in RAM. + */ + .bss (NOLOAD) : + { + . = ALIGN(4); + __bss_start = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + } > RAM + /** * Non-secure stack symbols. */ diff --git a/drivers/0x05_servo_cbm/Src/rp2350_reset_handler.c b/drivers/0x05_servo_cbm/Src/rp2350_reset_handler.c index adb5099..d3ac7a2 100644 --- a/drivers/0x05_servo_cbm/Src/rp2350_reset_handler.c +++ b/drivers/0x05_servo_cbm/Src/rp2350_reset_handler.c @@ -39,6 +39,34 @@ extern int main(void); +extern uint32_t __data_lma; +extern uint32_t __data_start; +extern uint32_t __data_end; +extern uint32_t __bss_start; +extern uint32_t __bss_end; + +static void _data_copy_init(void) +{ + uint32_t *src = &__data_lma; + uint32_t *dst = &__data_start; + while (dst < &__data_end) + *dst++ = *src++; +} + +static void _bss_zero_init(void) +{ + uint32_t *dst = &__bss_start; + while (dst < &__bss_end) + *dst++ = 0U; +} + +void _ram_init(void) +{ + stack_init(); + _data_copy_init(); + _bss_zero_init(); +} + void _late_init(void) { servo_release_reset(); @@ -48,7 +76,7 @@ void _late_init(void) void __attribute__((naked, noreturn)) Reset_Handler(void) { __asm__ volatile ( - "bl stack_init\n\t" + "bl _ram_init\n\t" "bl xosc_init\n\t" "bl xosc_enable_peri_clk\n\t" "bl reset_init_subsystem\n\t" diff --git a/drivers/0x05_servo_cbm/build.log b/drivers/0x05_servo_cbm/build.log new file mode 100644 index 0000000..e76adc0 Binary files /dev/null and b/drivers/0x05_servo_cbm/build.log differ diff --git a/drivers/0x05_servo_cbm/linker.ld b/drivers/0x05_servo_cbm/linker.ld index 09ea7a6..0ad5c05 100644 --- a/drivers/0x05_servo_cbm/linker.ld +++ b/drivers/0x05_servo_cbm/linker.ld @@ -50,6 +50,7 @@ MEMORY PHDRS { text PT_LOAD FLAGS(5); + data PT_LOAD FLAGS(6); } /** @@ -94,6 +95,35 @@ SECTIONS KEEP(*(.embedded_block)) } > FLASH :text + /** + * Initialized data and RAM-resident code (LMA in flash, VMA in RAM). + * Startup copies from __data_lma to __data_start..__data_end. + */ + .data : + { + . = ALIGN(4); + __data_start = .; + *(.ram_func*) + *(.data*) + . = ALIGN(4); + __data_end = .; + } > RAM AT> FLASH :data + + __data_lma = LOADADDR(.data); + + /** + * Uninitialized data (BSS) in RAM. + */ + .bss (NOLOAD) : + { + . = ALIGN(4); + __bss_start = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + } > RAM + /** * Non-secure stack symbols. */ diff --git a/drivers/0x06_adc_cbm/Src/rp2350_reset_handler.c b/drivers/0x06_adc_cbm/Src/rp2350_reset_handler.c index f4043a1..f831947 100644 --- a/drivers/0x06_adc_cbm/Src/rp2350_reset_handler.c +++ b/drivers/0x06_adc_cbm/Src/rp2350_reset_handler.c @@ -39,10 +39,38 @@ extern int main(void); +extern uint32_t __data_lma; +extern uint32_t __data_start; +extern uint32_t __data_end; +extern uint32_t __bss_start; +extern uint32_t __bss_end; + +static void _data_copy_init(void) +{ + uint32_t *src = &__data_lma; + uint32_t *dst = &__data_start; + while (dst < &__data_end) + *dst++ = *src++; +} + +static void _bss_zero_init(void) +{ + uint32_t *dst = &__bss_start; + while (dst < &__bss_end) + *dst++ = 0U; +} + +void _ram_init(void) +{ + stack_init(); + _data_copy_init(); + _bss_zero_init(); +} + void __attribute__((naked, noreturn)) Reset_Handler(void) { __asm__ volatile ( - "bl stack_init\n\t" + "bl _ram_init\n\t" "bl xosc_init\n\t" "bl xosc_enable_peri_clk\n\t" "bl reset_init_subsystem\n\t" diff --git a/drivers/0x06_adc_cbm/build.log b/drivers/0x06_adc_cbm/build.log new file mode 100644 index 0000000..9b93096 Binary files /dev/null and b/drivers/0x06_adc_cbm/build.log differ diff --git a/drivers/0x06_adc_cbm/linker.ld b/drivers/0x06_adc_cbm/linker.ld index 09ea7a6..0ad5c05 100644 --- a/drivers/0x06_adc_cbm/linker.ld +++ b/drivers/0x06_adc_cbm/linker.ld @@ -50,6 +50,7 @@ MEMORY PHDRS { text PT_LOAD FLAGS(5); + data PT_LOAD FLAGS(6); } /** @@ -94,6 +95,35 @@ SECTIONS KEEP(*(.embedded_block)) } > FLASH :text + /** + * Initialized data and RAM-resident code (LMA in flash, VMA in RAM). + * Startup copies from __data_lma to __data_start..__data_end. + */ + .data : + { + . = ALIGN(4); + __data_start = .; + *(.ram_func*) + *(.data*) + . = ALIGN(4); + __data_end = .; + } > RAM AT> FLASH :data + + __data_lma = LOADADDR(.data); + + /** + * Uninitialized data (BSS) in RAM. + */ + .bss (NOLOAD) : + { + . = ALIGN(4); + __bss_start = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + } > RAM + /** * Non-secure stack symbols. */ diff --git a/drivers/0x07_i2c_cbm/Src/rp2350_reset_handler.c b/drivers/0x07_i2c_cbm/Src/rp2350_reset_handler.c index 46645b1..62b58d2 100644 --- a/drivers/0x07_i2c_cbm/Src/rp2350_reset_handler.c +++ b/drivers/0x07_i2c_cbm/Src/rp2350_reset_handler.c @@ -38,10 +38,38 @@ extern int main(void); +extern uint32_t __data_lma; +extern uint32_t __data_start; +extern uint32_t __data_end; +extern uint32_t __bss_start; +extern uint32_t __bss_end; + +static void _data_copy_init(void) +{ + uint32_t *src = &__data_lma; + uint32_t *dst = &__data_start; + while (dst < &__data_end) + *dst++ = *src++; +} + +static void _bss_zero_init(void) +{ + uint32_t *dst = &__bss_start; + while (dst < &__bss_end) + *dst++ = 0U; +} + +void _ram_init(void) +{ + stack_init(); + _data_copy_init(); + _bss_zero_init(); +} + void __attribute__((naked, noreturn)) Reset_Handler(void) { __asm__ volatile ( - "bl stack_init\n\t" + "bl _ram_init\n\t" "bl xosc_init\n\t" "bl xosc_enable_peri_clk\n\t" "bl reset_init_subsystem\n\t" diff --git a/drivers/0x07_i2c_cbm/build.log b/drivers/0x07_i2c_cbm/build.log new file mode 100644 index 0000000..f46ea5a Binary files /dev/null and b/drivers/0x07_i2c_cbm/build.log differ diff --git a/drivers/0x07_i2c_cbm/linker.ld b/drivers/0x07_i2c_cbm/linker.ld index 09ea7a6..0ad5c05 100644 --- a/drivers/0x07_i2c_cbm/linker.ld +++ b/drivers/0x07_i2c_cbm/linker.ld @@ -50,6 +50,7 @@ MEMORY PHDRS { text PT_LOAD FLAGS(5); + data PT_LOAD FLAGS(6); } /** @@ -94,6 +95,35 @@ SECTIONS KEEP(*(.embedded_block)) } > FLASH :text + /** + * Initialized data and RAM-resident code (LMA in flash, VMA in RAM). + * Startup copies from __data_lma to __data_start..__data_end. + */ + .data : + { + . = ALIGN(4); + __data_start = .; + *(.ram_func*) + *(.data*) + . = ALIGN(4); + __data_end = .; + } > RAM AT> FLASH :data + + __data_lma = LOADADDR(.data); + + /** + * Uninitialized data (BSS) in RAM. + */ + .bss (NOLOAD) : + { + . = ALIGN(4); + __bss_start = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + } > RAM + /** * Non-secure stack symbols. */ diff --git a/drivers/0x08_lcd1602_cbm/Src/rp2350_reset_handler.c b/drivers/0x08_lcd1602_cbm/Src/rp2350_reset_handler.c index 46645b1..62b58d2 100644 --- a/drivers/0x08_lcd1602_cbm/Src/rp2350_reset_handler.c +++ b/drivers/0x08_lcd1602_cbm/Src/rp2350_reset_handler.c @@ -38,10 +38,38 @@ extern int main(void); +extern uint32_t __data_lma; +extern uint32_t __data_start; +extern uint32_t __data_end; +extern uint32_t __bss_start; +extern uint32_t __bss_end; + +static void _data_copy_init(void) +{ + uint32_t *src = &__data_lma; + uint32_t *dst = &__data_start; + while (dst < &__data_end) + *dst++ = *src++; +} + +static void _bss_zero_init(void) +{ + uint32_t *dst = &__bss_start; + while (dst < &__bss_end) + *dst++ = 0U; +} + +void _ram_init(void) +{ + stack_init(); + _data_copy_init(); + _bss_zero_init(); +} + void __attribute__((naked, noreturn)) Reset_Handler(void) { __asm__ volatile ( - "bl stack_init\n\t" + "bl _ram_init\n\t" "bl xosc_init\n\t" "bl xosc_enable_peri_clk\n\t" "bl reset_init_subsystem\n\t" diff --git a/drivers/0x08_lcd1602_cbm/build.log b/drivers/0x08_lcd1602_cbm/build.log new file mode 100644 index 0000000..4c8710c Binary files /dev/null and b/drivers/0x08_lcd1602_cbm/build.log differ diff --git a/drivers/0x08_lcd1602_cbm/linker.ld b/drivers/0x08_lcd1602_cbm/linker.ld index 09ea7a6..0ad5c05 100644 --- a/drivers/0x08_lcd1602_cbm/linker.ld +++ b/drivers/0x08_lcd1602_cbm/linker.ld @@ -50,6 +50,7 @@ MEMORY PHDRS { text PT_LOAD FLAGS(5); + data PT_LOAD FLAGS(6); } /** @@ -94,6 +95,35 @@ SECTIONS KEEP(*(.embedded_block)) } > FLASH :text + /** + * Initialized data and RAM-resident code (LMA in flash, VMA in RAM). + * Startup copies from __data_lma to __data_start..__data_end. + */ + .data : + { + . = ALIGN(4); + __data_start = .; + *(.ram_func*) + *(.data*) + . = ALIGN(4); + __data_end = .; + } > RAM AT> FLASH :data + + __data_lma = LOADADDR(.data); + + /** + * Uninitialized data (BSS) in RAM. + */ + .bss (NOLOAD) : + { + . = ALIGN(4); + __bss_start = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + } > RAM + /** * Non-secure stack symbols. */ diff --git a/drivers/0x09_dht11_cbm/Src/rp2350_reset_handler.c b/drivers/0x09_dht11_cbm/Src/rp2350_reset_handler.c index 46645b1..62b58d2 100644 --- a/drivers/0x09_dht11_cbm/Src/rp2350_reset_handler.c +++ b/drivers/0x09_dht11_cbm/Src/rp2350_reset_handler.c @@ -38,10 +38,38 @@ extern int main(void); +extern uint32_t __data_lma; +extern uint32_t __data_start; +extern uint32_t __data_end; +extern uint32_t __bss_start; +extern uint32_t __bss_end; + +static void _data_copy_init(void) +{ + uint32_t *src = &__data_lma; + uint32_t *dst = &__data_start; + while (dst < &__data_end) + *dst++ = *src++; +} + +static void _bss_zero_init(void) +{ + uint32_t *dst = &__bss_start; + while (dst < &__bss_end) + *dst++ = 0U; +} + +void _ram_init(void) +{ + stack_init(); + _data_copy_init(); + _bss_zero_init(); +} + void __attribute__((naked, noreturn)) Reset_Handler(void) { __asm__ volatile ( - "bl stack_init\n\t" + "bl _ram_init\n\t" "bl xosc_init\n\t" "bl xosc_enable_peri_clk\n\t" "bl reset_init_subsystem\n\t" diff --git a/drivers/0x09_dht11_cbm/build.log b/drivers/0x09_dht11_cbm/build.log new file mode 100644 index 0000000..ce4d94c Binary files /dev/null and b/drivers/0x09_dht11_cbm/build.log differ diff --git a/drivers/0x09_dht11_cbm/linker.ld b/drivers/0x09_dht11_cbm/linker.ld index 09ea7a6..0ad5c05 100644 --- a/drivers/0x09_dht11_cbm/linker.ld +++ b/drivers/0x09_dht11_cbm/linker.ld @@ -50,6 +50,7 @@ MEMORY PHDRS { text PT_LOAD FLAGS(5); + data PT_LOAD FLAGS(6); } /** @@ -94,6 +95,35 @@ SECTIONS KEEP(*(.embedded_block)) } > FLASH :text + /** + * Initialized data and RAM-resident code (LMA in flash, VMA in RAM). + * Startup copies from __data_lma to __data_start..__data_end. + */ + .data : + { + . = ALIGN(4); + __data_start = .; + *(.ram_func*) + *(.data*) + . = ALIGN(4); + __data_end = .; + } > RAM AT> FLASH :data + + __data_lma = LOADADDR(.data); + + /** + * Uninitialized data (BSS) in RAM. + */ + .bss (NOLOAD) : + { + . = ALIGN(4); + __bss_start = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + } > RAM + /** * Non-secure stack symbols. */ diff --git a/drivers/0x0a_ir_cbm/Src/rp2350_reset_handler.c b/drivers/0x0a_ir_cbm/Src/rp2350_reset_handler.c index 46645b1..62b58d2 100644 --- a/drivers/0x0a_ir_cbm/Src/rp2350_reset_handler.c +++ b/drivers/0x0a_ir_cbm/Src/rp2350_reset_handler.c @@ -38,10 +38,38 @@ extern int main(void); +extern uint32_t __data_lma; +extern uint32_t __data_start; +extern uint32_t __data_end; +extern uint32_t __bss_start; +extern uint32_t __bss_end; + +static void _data_copy_init(void) +{ + uint32_t *src = &__data_lma; + uint32_t *dst = &__data_start; + while (dst < &__data_end) + *dst++ = *src++; +} + +static void _bss_zero_init(void) +{ + uint32_t *dst = &__bss_start; + while (dst < &__bss_end) + *dst++ = 0U; +} + +void _ram_init(void) +{ + stack_init(); + _data_copy_init(); + _bss_zero_init(); +} + void __attribute__((naked, noreturn)) Reset_Handler(void) { __asm__ volatile ( - "bl stack_init\n\t" + "bl _ram_init\n\t" "bl xosc_init\n\t" "bl xosc_enable_peri_clk\n\t" "bl reset_init_subsystem\n\t" diff --git a/drivers/0x0a_ir_cbm/build.log b/drivers/0x0a_ir_cbm/build.log new file mode 100644 index 0000000..5c237c4 Binary files /dev/null and b/drivers/0x0a_ir_cbm/build.log differ diff --git a/drivers/0x0a_ir_cbm/linker.ld b/drivers/0x0a_ir_cbm/linker.ld index 09ea7a6..0ad5c05 100644 --- a/drivers/0x0a_ir_cbm/linker.ld +++ b/drivers/0x0a_ir_cbm/linker.ld @@ -50,6 +50,7 @@ MEMORY PHDRS { text PT_LOAD FLAGS(5); + data PT_LOAD FLAGS(6); } /** @@ -94,6 +95,35 @@ SECTIONS KEEP(*(.embedded_block)) } > FLASH :text + /** + * Initialized data and RAM-resident code (LMA in flash, VMA in RAM). + * Startup copies from __data_lma to __data_start..__data_end. + */ + .data : + { + . = ALIGN(4); + __data_start = .; + *(.ram_func*) + *(.data*) + . = ALIGN(4); + __data_end = .; + } > RAM AT> FLASH :data + + __data_lma = LOADADDR(.data); + + /** + * Uninitialized data (BSS) in RAM. + */ + .bss (NOLOAD) : + { + . = ALIGN(4); + __bss_start = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + } > RAM + /** * Non-secure stack symbols. */ diff --git a/drivers/0x0b_spi_cbm/Src/rp2350_reset_handler.c b/drivers/0x0b_spi_cbm/Src/rp2350_reset_handler.c index d715c90..a736fba 100644 --- a/drivers/0x0b_spi_cbm/Src/rp2350_reset_handler.c +++ b/drivers/0x0b_spi_cbm/Src/rp2350_reset_handler.c @@ -39,10 +39,38 @@ extern int main(void); +extern uint32_t __data_lma; +extern uint32_t __data_start; +extern uint32_t __data_end; +extern uint32_t __bss_start; +extern uint32_t __bss_end; + +static void _data_copy_init(void) +{ + uint32_t *src = &__data_lma; + uint32_t *dst = &__data_start; + while (dst < &__data_end) + *dst++ = *src++; +} + +static void _bss_zero_init(void) +{ + uint32_t *dst = &__bss_start; + while (dst < &__bss_end) + *dst++ = 0U; +} + +void _ram_init(void) +{ + stack_init(); + _data_copy_init(); + _bss_zero_init(); +} + void __attribute__((naked, noreturn)) Reset_Handler(void) { __asm__ volatile ( - "bl stack_init\n\t" + "bl _ram_init\n\t" "bl xosc_init\n\t" "bl xosc_enable_peri_clk\n\t" "bl reset_init_subsystem\n\t" diff --git a/drivers/0x0b_spi_cbm/build.log b/drivers/0x0b_spi_cbm/build.log new file mode 100644 index 0000000..271ea0d Binary files /dev/null and b/drivers/0x0b_spi_cbm/build.log differ diff --git a/drivers/0x0b_spi_cbm/linker.ld b/drivers/0x0b_spi_cbm/linker.ld index 09ea7a6..0ad5c05 100644 --- a/drivers/0x0b_spi_cbm/linker.ld +++ b/drivers/0x0b_spi_cbm/linker.ld @@ -50,6 +50,7 @@ MEMORY PHDRS { text PT_LOAD FLAGS(5); + data PT_LOAD FLAGS(6); } /** @@ -94,6 +95,35 @@ SECTIONS KEEP(*(.embedded_block)) } > FLASH :text + /** + * Initialized data and RAM-resident code (LMA in flash, VMA in RAM). + * Startup copies from __data_lma to __data_start..__data_end. + */ + .data : + { + . = ALIGN(4); + __data_start = .; + *(.ram_func*) + *(.data*) + . = ALIGN(4); + __data_end = .; + } > RAM AT> FLASH :data + + __data_lma = LOADADDR(.data); + + /** + * Uninitialized data (BSS) in RAM. + */ + .bss (NOLOAD) : + { + . = ALIGN(4); + __bss_start = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + } > RAM + /** * Non-secure stack symbols. */ diff --git a/drivers/0x0c_multicore_cbm/Src/rp2350_reset_handler.c b/drivers/0x0c_multicore_cbm/Src/rp2350_reset_handler.c index 46645b1..62b58d2 100644 --- a/drivers/0x0c_multicore_cbm/Src/rp2350_reset_handler.c +++ b/drivers/0x0c_multicore_cbm/Src/rp2350_reset_handler.c @@ -38,10 +38,38 @@ extern int main(void); +extern uint32_t __data_lma; +extern uint32_t __data_start; +extern uint32_t __data_end; +extern uint32_t __bss_start; +extern uint32_t __bss_end; + +static void _data_copy_init(void) +{ + uint32_t *src = &__data_lma; + uint32_t *dst = &__data_start; + while (dst < &__data_end) + *dst++ = *src++; +} + +static void _bss_zero_init(void) +{ + uint32_t *dst = &__bss_start; + while (dst < &__bss_end) + *dst++ = 0U; +} + +void _ram_init(void) +{ + stack_init(); + _data_copy_init(); + _bss_zero_init(); +} + void __attribute__((naked, noreturn)) Reset_Handler(void) { __asm__ volatile ( - "bl stack_init\n\t" + "bl _ram_init\n\t" "bl xosc_init\n\t" "bl xosc_enable_peri_clk\n\t" "bl reset_init_subsystem\n\t" diff --git a/drivers/0x0c_multicore_cbm/build.log b/drivers/0x0c_multicore_cbm/build.log new file mode 100644 index 0000000..31c61d1 Binary files /dev/null and b/drivers/0x0c_multicore_cbm/build.log differ diff --git a/drivers/0x0c_multicore_cbm/linker.ld b/drivers/0x0c_multicore_cbm/linker.ld index 15d3ac3..56ac361 100644 --- a/drivers/0x0c_multicore_cbm/linker.ld +++ b/drivers/0x0c_multicore_cbm/linker.ld @@ -50,6 +50,7 @@ MEMORY PHDRS { text PT_LOAD FLAGS(5); + data PT_LOAD FLAGS(6); } /** @@ -100,11 +101,29 @@ SECTIONS .bss (NOLOAD) : { . = ALIGN(4); + __bss_start = .; *(.bss*) *(COMMON) . = ALIGN(4); + __bss_end = .; } > RAM + /** + * Initialized data and RAM-resident code (LMA in flash, VMA in RAM). + * Startup copies from __data_lma to __data_start..__data_end. + */ + .data : + { + . = ALIGN(4); + __data_start = .; + *(.ram_func*) + *(.data*) + . = ALIGN(4); + __data_end = .; + } > RAM AT> FLASH :data + + __data_lma = LOADADDR(.data); + /** * Non-secure stack symbols. */ diff --git a/drivers/0x0d_timer_cbm/Src/rp2350_reset_handler.c b/drivers/0x0d_timer_cbm/Src/rp2350_reset_handler.c index 4433e3b..1e40e17 100644 --- a/drivers/0x0d_timer_cbm/Src/rp2350_reset_handler.c +++ b/drivers/0x0d_timer_cbm/Src/rp2350_reset_handler.c @@ -39,6 +39,34 @@ extern int main(void); +extern uint32_t __data_lma; +extern uint32_t __data_start; +extern uint32_t __data_end; +extern uint32_t __bss_start; +extern uint32_t __bss_end; + +static void _data_copy_init(void) +{ + uint32_t *src = &__data_lma; + uint32_t *dst = &__data_start; + while (dst < &__data_end) + *dst++ = *src++; +} + +static void _bss_zero_init(void) +{ + uint32_t *dst = &__bss_start; + while (dst < &__bss_end) + *dst++ = 0U; +} + +void _ram_init(void) +{ + stack_init(); + _data_copy_init(); + _bss_zero_init(); +} + void _late_init(void) { timer_release_reset(); @@ -48,7 +76,7 @@ void _late_init(void) void __attribute__((naked, noreturn)) Reset_Handler(void) { __asm__ volatile ( - "bl stack_init\n\t" + "bl _ram_init\n\t" "bl xosc_init\n\t" "bl xosc_enable_peri_clk\n\t" "bl reset_init_subsystem\n\t" diff --git a/drivers/0x0d_timer_cbm/build.log b/drivers/0x0d_timer_cbm/build.log new file mode 100644 index 0000000..1321343 Binary files /dev/null and b/drivers/0x0d_timer_cbm/build.log differ diff --git a/drivers/0x0d_timer_cbm/linker.ld b/drivers/0x0d_timer_cbm/linker.ld index 15d3ac3..56ac361 100644 --- a/drivers/0x0d_timer_cbm/linker.ld +++ b/drivers/0x0d_timer_cbm/linker.ld @@ -50,6 +50,7 @@ MEMORY PHDRS { text PT_LOAD FLAGS(5); + data PT_LOAD FLAGS(6); } /** @@ -100,11 +101,29 @@ SECTIONS .bss (NOLOAD) : { . = ALIGN(4); + __bss_start = .; *(.bss*) *(COMMON) . = ALIGN(4); + __bss_end = .; } > RAM + /** + * Initialized data and RAM-resident code (LMA in flash, VMA in RAM). + * Startup copies from __data_lma to __data_start..__data_end. + */ + .data : + { + . = ALIGN(4); + __data_start = .; + *(.ram_func*) + *(.data*) + . = ALIGN(4); + __data_end = .; + } > RAM AT> FLASH :data + + __data_lma = LOADADDR(.data); + /** * Non-secure stack symbols. */ diff --git a/drivers/0x0e_watchdog_cbm/Src/rp2350_reset_handler.c b/drivers/0x0e_watchdog_cbm/Src/rp2350_reset_handler.c index 50584ab..6c08527 100644 --- a/drivers/0x0e_watchdog_cbm/Src/rp2350_reset_handler.c +++ b/drivers/0x0e_watchdog_cbm/Src/rp2350_reset_handler.c @@ -39,10 +39,38 @@ extern int main(void); +extern uint32_t __data_lma; +extern uint32_t __data_start; +extern uint32_t __data_end; +extern uint32_t __bss_start; +extern uint32_t __bss_end; + +static void _data_copy_init(void) +{ + uint32_t *src = &__data_lma; + uint32_t *dst = &__data_start; + while (dst < &__data_end) + *dst++ = *src++; +} + +static void _bss_zero_init(void) +{ + uint32_t *dst = &__bss_start; + while (dst < &__bss_end) + *dst++ = 0U; +} + +void _ram_init(void) +{ + stack_init(); + _data_copy_init(); + _bss_zero_init(); +} + void __attribute__((naked, noreturn)) Reset_Handler(void) { __asm__ volatile ( - "bl stack_init\n\t" + "bl _ram_init\n\t" "bl xosc_init\n\t" "bl xosc_enable_peri_clk\n\t" "bl reset_init_subsystem\n\t" diff --git a/drivers/0x0e_watchdog_cbm/build.log b/drivers/0x0e_watchdog_cbm/build.log new file mode 100644 index 0000000..e70d06e Binary files /dev/null and b/drivers/0x0e_watchdog_cbm/build.log differ diff --git a/drivers/0x0e_watchdog_cbm/linker.ld b/drivers/0x0e_watchdog_cbm/linker.ld index 15d3ac3..56ac361 100644 --- a/drivers/0x0e_watchdog_cbm/linker.ld +++ b/drivers/0x0e_watchdog_cbm/linker.ld @@ -50,6 +50,7 @@ MEMORY PHDRS { text PT_LOAD FLAGS(5); + data PT_LOAD FLAGS(6); } /** @@ -100,11 +101,29 @@ SECTIONS .bss (NOLOAD) : { . = ALIGN(4); + __bss_start = .; *(.bss*) *(COMMON) . = ALIGN(4); + __bss_end = .; } > RAM + /** + * Initialized data and RAM-resident code (LMA in flash, VMA in RAM). + * Startup copies from __data_lma to __data_start..__data_end. + */ + .data : + { + . = ALIGN(4); + __data_start = .; + *(.ram_func*) + *(.data*) + . = ALIGN(4); + __data_end = .; + } > RAM AT> FLASH :data + + __data_lma = LOADADDR(.data); + /** * Non-secure stack symbols. */ diff --git a/drivers/0x0f_flash_cbm/Src/rp2350_reset_handler.c b/drivers/0x0f_flash_cbm/Src/rp2350_reset_handler.c index fae4d80..9d6866d 100644 --- a/drivers/0x0f_flash_cbm/Src/rp2350_reset_handler.c +++ b/drivers/0x0f_flash_cbm/Src/rp2350_reset_handler.c @@ -38,26 +38,13 @@ extern int main(void); -/** - * @brief Linker-defined symbol: flash LMA of .data section. - */ extern uint32_t __data_lma; - -/** - * @brief Linker-defined symbol: RAM VMA start of .data section. - */ extern uint32_t __data_start; - -/** - * @brief Linker-defined symbol: RAM VMA end of .data section. - */ extern uint32_t __data_end; +extern uint32_t __bss_start; +extern uint32_t __bss_end; -/** - * @brief Copy initialized data and RAM-resident code from flash to RAM. - * @retval None - */ -static void data_copy_init(void) +static void _data_copy_init(void) { uint32_t *src = &__data_lma; uint32_t *dst = &__data_start; @@ -65,16 +52,24 @@ static void data_copy_init(void) *dst++ = *src++; } -void ram_init(void) +static void _bss_zero_init(void) +{ + uint32_t *dst = &__bss_start; + while (dst < &__bss_end) + *dst++ = 0U; +} + +void _ram_init(void) { stack_init(); - data_copy_init(); + _data_copy_init(); + _bss_zero_init(); } void __attribute__((naked, noreturn)) Reset_Handler(void) { __asm__ volatile ( - "bl ram_init\n\t" + "bl _ram_init\n\t" "bl xosc_init\n\t" "bl xosc_enable_peri_clk\n\t" "bl reset_init_subsystem\n\t" diff --git a/drivers/0x0f_flash_cbm/build.log b/drivers/0x0f_flash_cbm/build.log new file mode 100644 index 0000000..457ded8 Binary files /dev/null and b/drivers/0x0f_flash_cbm/build.log differ diff --git a/drivers/0x0f_flash_cbm/linker.ld b/drivers/0x0f_flash_cbm/linker.ld index 0e24993..ba468d2 100644 --- a/drivers/0x0f_flash_cbm/linker.ld +++ b/drivers/0x0f_flash_cbm/linker.ld @@ -117,9 +117,11 @@ SECTIONS .bss (NOLOAD) : { . = ALIGN(4); + __bss_start = .; *(.bss*) *(COMMON) . = ALIGN(4); + __bss_end = .; } > RAM /**