Analysis and Implementation of Magic‐1 Bootloader Size Limitations - retrotruestory/M1DEV GitHub Wiki
You've probably already figured it out, but the issue you are running into is that there is limited space available in the boot rom - 16K total. Because code and data must live together, the linker has a special flag to tell you where to start the data region (the -d 0x2e00). I assume you've added enough new code to the bootloader that it runs past the old start of the data segment.
Now, yes, you can change the -d 0x2e00 to something larger to avoid the conflict, but the problem is that if you make it too large the resulting image won't fit into the 16K boot EPROM. Let's look at some examples using the unmodified bloader.
I'll do a "make clean" and "make". Next, do a "m1_nm -n bloader" to list the symbols. We want to examine the symbols between "etext" and "ebss". "etext" marks the end of the code, and "ebss" marks the end of the data. Here's what it looks like for unmodified bloader:
2d00 T etext
2e00 D _Version
2e04 D _verbose
2e06 D _pause_before_boot
2e08 D _time_mask
2e18 D _cf_base
2e1a D _active_drive
2e1c D _drive_names
2e24 D _ide_err_msgs
2e34 D _tohex
2e36 D __hexmap
3a6e D _errno
3a70 D ___ctype
3b72 D __brksize
3b74 D edata
3b74 B _intel_load_error
3b76 B _ide_drives
3ca5 B _r_uart1
3cba B _r_uart0
3ccf B _num_commands
3cd1 B _image_table
3d86 B ebss
In this example, the code ends at 0x2d00, the data starts at 0x2e00 and the data ends at 0x3d86. This means we've got 0x100 (256) bytes of usable code space between 0x2d00 and 0x2e00. But, if we add more than 256 bytes of new code, the code and data will conflict. We can change the "-d 0x2e00" to something larger, but we have to make sure that the end of data "ebss" stays below 16K, or 0x4000. Right now in this example, there is 0x4000-0x3d86 bytes of empty space, 0x27a or 634 bytes. So, we can shift the data no more than 634 bytes.
Now, 0x2e00 plus 0x27a is 0x307a. Let's rebuild using "-d 0x307a" and look at m1_nm -n again.
The new symbols are:
2d00 T etext
307a D _Version
307e D _verbose
3080 D _pause_before_boot
3082 D _time_mask
3092 D _cf_base
3094 D _active_drive
3096 D _drive_names
309e D _ide_err_msgs
30ae D _tohex
30b0 D __hexmap
3ce8 D _errno
3cea D ___ctype
3dec D __brksize
3dee D edata
3dee B _intel_load_error
3df0 B _ide_drives
3f1f B _r_uart1
3f34 B _r_uart0
3f49 B _num_commands
3f4b B _image_table
4000 B ebss
And, we now have 0x307a-0x2d00, or 890 bytes available for new code.
As you can see, you won't be able to add too much to the bootloader without removing existing code or data. As far as using a different tohex, I would suggest not doing so. I suspect the errors you were getting were because the linker left a corrupted result file because of the code/data overlap issue.
...Bill
The Magic-1 bootloader faces size constraints due to its fixed memory layout:
- Code starts at address 0x0000
- Data segment starts at address 0x307a
- A "Code and data overlap" error occurs when the code section grows too large
- Current bootloader size: 15,860 bytes (text) + 530 bytes (BSS) = 16,390 bytes total
This is confirmed by the current Makefile configuration:
1 LDFLAGS = -m -d 0x307a makefile
Increase available code space by adjusting the data segment start address:
1 CC = clcc 2 CFLAGS = -c -O2 # Enable optimizations 3 LDFLAGS = -m -d 0x4000 # Increase space for code section makefile
This modification provides approximately 4.5KB of additional code space.
Implement memory usage optimizations:
// Optimize memory usage with shared buffers static char shared_buffer[512]; // Use inline for frequently called small functions static inline void optimize_critical_function(void) { // Implementation } // Remove redundant variables void load_boot_image(void) { // Use shared_buffer instead of local arrays read_sector(0, shared_buffer); // ...existing code... } c
Improve code organization in assembly files:
.section .text // Critical initialization code .section .text.cold // Less frequently used code .section .data // Read-write data assembly
- Update Memory Map:
1 # Check current memory usage 2 m1_size bloader.o 3 4 # Generate detailed memory map 5 m1_ld -m -d 0x4000 -o bloader bcrt0.o bloader.o -lc -le crtn.o > memory.map bash
- **Modify Linker Script (if needed):
SECTIONS { . = 0x0000; .text : { *(.text) *(.text.*) } . = 0x4000; .data : { *(.data) *(.bss) } }
- Test Implementation:
# Compile with new settings cd /home/buzbee/workspace/M1Dev/non_minix/bootloader make clean make # Verify size m1_size bootloader # Test bootloader functionality bash
Add verification code to confirm the correct memory layout:
void verify_memory_layout(void) { extern char _text_start[], _text_end[]; extern char _data_start[]; printf("Text: 0x%04x - 0x%04x\n", (uint16_t)_text_start, (uint16_t)_text_end); printf("Data: 0x%04x\n", (uint16_t)_data_start); } c
This comprehensive approach:
- Significantly increases the available space for code.
- Optimizes memory usage by sharing buffers and encoding techniques.
- Maintains compatibility with the Magic-1 architecture.
- Provides verification tools for monitoring the memory layout.
- Facilitates future development of the bootloader.
- Avoids conflicts between code and data sections.
These modifications effectively address the main cause of size limitations, offering both immediate and long-term solutions for the Magic-1 bootloader.
Based on the memory layout information from both files, I can help determine the maximum safe value for the linker's -d
parameter:
- Current limitations and constraints:
- ROM code space:
0x0000 - 0x3FFF
(16KB) - Device SRAM:
0x4000 - 0x7FFF
(16KB) - Original data segment starts at:
0x307a
- Current proposed value in documentation:
0x4000
- Analysis:
- The maximum theoretical value would be
0x3FFF
since that's the end of ROM code space - However, we need to leave some space for:
- Data segment
- BSS section
- Stack initialization
- Vectors and interrupt handlers
- Recommended safe maximum value:
CC = clcc
CFLAGS = -c -O2 # Enable optimizations
LDFLAGS = -m -d 0x3800 # Safe maximum value
Explanation:
-
0x3800
leaves 2KB (0x800 bytes) for data/BSS/stack - This provides approximately 14KB for code (0x0000-0x3800)
- Setting it higher (closer to 0x3FFF) could cause:
- Data/code overlap issues
- Stack corruption
- Initialization problems
- Interrupt vector conflicts
The value 0x3800
provides a good balance between:
- Maximum code space
- Safe data segment placement
- Required system overhead
- Future expansion needs