├── LICENSE ├── README.md ├── boards.txt ├── cores └── x86-pc │ ├── Arduino.h │ ├── Keyboard.cpp │ ├── Keyboard.h │ ├── Tone.cpp │ ├── Tone.h │ ├── Video.cpp │ ├── Video.h │ ├── delay.S │ ├── delay.cpp │ ├── delay.h │ ├── entry.S │ ├── keyboardasm.S │ ├── keyboardasm.h │ ├── main.cpp │ ├── toneasm.S │ ├── toneasm.h │ ├── videoasm.S │ └── videoasm.h ├── doc ├── hello.png └── keyboard.png ├── examples ├── hello.ino ├── keyboard.ino └── piano.ino ├── platform.txt ├── programmers.txt └── variants └── x86-pc └── linker.ld /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2021-2022 by Jean THOMAS 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. 4 | 5 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # boot2duino 2 | 3 | boot2duino serves no other purpose than to generate a bootable x86 floppy image using the Arduino IDE, which seemingly serves no purpose. 4 | 5 | **Watch it in action:** [writing a hello world](https://vimeo.com/656339999); [a very basic piano](https://vimeo.com/661030335). 6 | 7 | ## Examples 8 | 9 | ```c++ 10 | Video vid; 11 | 12 | void setup() { 13 | vid.print("Hello world, from Arduino!"); 14 | } 15 | 16 | void loop() { 17 | 18 | } 19 | ``` 20 | 21 | ![boot2duino hello world example running inside QEMU](doc/hello.png) 22 | 23 | Other examples: 24 | 25 | * [keyboard interaction](examples/keyboard.ino) 26 | * [piano](examples/piano.ino) 27 | 28 | ## How to install 29 | 30 | Linux : 31 | 32 | ```bash 33 | mkdir -p ~/Arduino/hardware/boot2duino 34 | cd ~/Arduino/hardware/boot2duino 35 | git clone https://github.com/jeanthom/boot2duino 36 | ``` 37 | 38 | Windows : 39 | 40 | ```batch 41 | mkdir %UserProfile%\Documents\Arduino\hardware 42 | cd %UserProfile%\Documents\Arduino\hardware 43 | git clone https://github.com/jeanthom/boot2duino 44 | ``` 45 | 46 | ## How to run 47 | 48 | Using qemu: 49 | 50 | ```bash 51 | qemu-system-x86_64 -drive file=boot2duino-demo.ino.x86-pc.img,index=0,if=floppy,format=raw -soundhw pcspk 52 | ``` 53 | 54 | ## Troubleshooting 55 | 56 | 1. Install an x86 compiler 57 | 2. Try upgrading your Arduino IDE 58 | 3. Windows is not very well supported, give Linux a try 59 | 4. Upgrade GCC to 11 ([see this issue](https://github.com/jeanthom/boot2duino/issues/6) and [this](https://github.com/jeanthom/boot2duino/issues/7)) 60 | -------------------------------------------------------------------------------- /boards.txt: -------------------------------------------------------------------------------- 1 | generic.name=Generic x86 computer 2 | generic.build.board=GENERIC_X86 3 | generic.build.core=x86-pc 4 | generic.build.variant=x86-pc 5 | generic.upload.tool=qemu 6 | -------------------------------------------------------------------------------- /cores/x86-pc/Arduino.h: -------------------------------------------------------------------------------- 1 | #ifndef Arduino_h 2 | #define Arduino_h 3 | 4 | #include "Video.h" 5 | #include "Keyboard.h" 6 | #include "Tone.h" 7 | #include "delay.h" 8 | 9 | #endif // Arduino_h 10 | -------------------------------------------------------------------------------- /cores/x86-pc/Keyboard.cpp: -------------------------------------------------------------------------------- 1 | extern "C" { 2 | #include "keyboardasm.h" 3 | } 4 | #include "Keyboard.h" 5 | 6 | const unsigned char Keyboard::kUpArrowKeycode = 0x48; 7 | const unsigned char Keyboard::kDownArrowKeycode = 0x50; 8 | const unsigned char Keyboard::kLeftArrowKeycode = 0x4B; 9 | const unsigned char Keyboard::kRightArrowKeycode = 0x4D; 10 | const unsigned char Keyboard::kEnterKeycode = 0x1C; 11 | 12 | bool Keyboard::available() const { 13 | return keyboardasm_available(); 14 | } 15 | 16 | char Keyboard::getch() const { 17 | return keyboardasm_getch(); 18 | } 19 | 20 | unsigned char Keyboard::getkeycode() const { 21 | return keyboardasm_getkeycode(); 22 | } 23 | -------------------------------------------------------------------------------- /cores/x86-pc/Keyboard.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class Keyboard { 4 | public: 5 | static const unsigned char kUpArrowKeycode; 6 | static const unsigned char kDownArrowKeycode; 7 | static const unsigned char kLeftArrowKeycode; 8 | static const unsigned char kRightArrowKeycode; 9 | static const unsigned char kEnterKeycode; 10 | 11 | bool available() const; 12 | char getch() const; 13 | unsigned char getkeycode() const; 14 | }; -------------------------------------------------------------------------------- /cores/x86-pc/Tone.cpp: -------------------------------------------------------------------------------- 1 | extern "C" { 2 | #include "toneasm.h" 3 | #include "delay.h" 4 | } 5 | #include "Tone.h" 6 | 7 | void tone(unsigned int freq, unsigned long duration) { 8 | toneasm_toneon(1193180/freq); 9 | if (duration) { 10 | delay(duration); 11 | noTone(); 12 | } 13 | } 14 | 15 | void noTone() { 16 | toneasm_toneoff(); 17 | } 18 | -------------------------------------------------------------------------------- /cores/x86-pc/Tone.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void tone(unsigned int freq, unsigned long duration = 0); 4 | void noTone(); 5 | -------------------------------------------------------------------------------- /cores/x86-pc/Video.cpp: -------------------------------------------------------------------------------- 1 | extern "C" { 2 | #include "videoasm.h" 3 | } 4 | 5 | #include "Video.h" 6 | 7 | void Video::print(char c) const { 8 | videoasm_putchar(c); 9 | } 10 | 11 | void Video::print(const char *str) const { 12 | for (const char *ptr = str; *ptr; ptr++) { 13 | videoasm_putchar(*ptr); 14 | } 15 | } 16 | 17 | void Video::println(const char *str) const { 18 | print(str); 19 | print("\r\n"); 20 | } 21 | 22 | void Video::clear(VideoColorScheme scheme) const { 23 | videoasm_clear(scheme); 24 | } 25 | 26 | void Video::setCursorPosition(char x, char y) const { 27 | videoasm_set_cursor_position(x, y); 28 | } 29 | 30 | void Video::setMode(VideoMode mode) const { 31 | videoasm_set_video_mode(mode); 32 | } 33 | -------------------------------------------------------------------------------- /cores/x86-pc/Video.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | enum VideoMode : unsigned char { 4 | TEXT_40X25_BW = 0x00, 5 | TEXT_40X25_COLOR = 0x01, 6 | TEXT_80X25_BW = 0x02, 7 | TEXT_80X25_COLOR = 0x03, 8 | GRAPHIC_320X200_COLOR = 0x04, 9 | GRAPHIC_320X200_BW = 0x05, 10 | GRAPHIC_640X200_COLOR = 0x06, 11 | }; 12 | 13 | enum VideoColorScheme : unsigned char { 14 | SCHEME_DEFAULT = 0x07, 15 | SCHEME_HYPERVISOR = 0xE8, 16 | SCHEME_UGLYBIOS = 0xE1, 17 | }; 18 | 19 | class Video { 20 | public: 21 | void print(const char *str) const; 22 | void println(const char *str) const; 23 | void print(char c) const; 24 | void clear(VideoColorScheme scheme = SCHEME_DEFAULT) const; 25 | void setCursorPosition(char x, char y) const; 26 | void setMode(VideoMode mode) const; 27 | }; 28 | -------------------------------------------------------------------------------- /cores/x86-pc/delay.S: -------------------------------------------------------------------------------- 1 | .code16 2 | .text 3 | 4 | .global delayMicroseconds 5 | delayMicroseconds: 6 | pusha 7 | mov %cx, %dx 8 | shr $16, %ecx 9 | xor %ax, %ax 10 | mov $0x86, %ah 11 | int $0x15 12 | popa 13 | ret 14 | -------------------------------------------------------------------------------- /cores/x86-pc/delay.cpp: -------------------------------------------------------------------------------- 1 | #include "delay.h" 2 | 3 | void delay(unsigned long ms) { 4 | for (int i = 0; i < ms; i++) { 5 | delayMicroseconds(1000); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /cores/x86-pc/delay.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern "C" { 4 | extern void delayMicroseconds(unsigned int us) __attribute__ ((fastcall)); 5 | } 6 | void delay(unsigned long ms); 7 | -------------------------------------------------------------------------------- /cores/x86-pc/entry.S: -------------------------------------------------------------------------------- 1 | .code16 2 | .section mbr 3 | .text 4 | 5 | .global biosentry 6 | biosentry: 7 | cli 8 | cld 9 | mov %cs, %ax 10 | mov %ax, %ds 11 | mov %ax, %es 12 | 13 | copyos: 14 | # Reset disk controller #0 (drive A:) 15 | xor %ax, %ax 16 | mov %al, %dl 17 | int $0x13 18 | 19 | # Read payload into RAM 20 | mov $0x02, %ah 21 | mov $63, %al # Sector read count 22 | mov $0x00, %ch # Cylinder 23 | mov $0x02, %cl # Sector 24 | mov $0x00, %dh # Head #0 25 | mov $0x00, %dl # Drive A: 26 | xor %bx, %bx 27 | mov %bx, %es 28 | mov $0x7E00, %bx 29 | int $0x13 # Load at 0000:7E00 30 | jne copyos_error 31 | 32 | # Call payload 33 | xor %ax, %ax 34 | mov %ax, %ds 35 | mov %ax, %es 36 | mov %ax, %ss 37 | mov $__stack_top, %esp 38 | cld 39 | call main 40 | 41 | copyos_error: 42 | xor %esi, %esi 43 | mov $copyos_error_string, %si 44 | mov $0x0E, %ah 45 | xor %bx, %bx 46 | mov %bx, %ds 47 | copyos_error_loop: 48 | lodsb 49 | or %al, %al 50 | jz loop_nil 51 | int $0x10 52 | jmp copyos_error_loop 53 | 54 | loop_nil: 55 | hlt 56 | jmp loop_nil 57 | 58 | copyos_error_string: 59 | .string "Payload readout error" 60 | -------------------------------------------------------------------------------- /cores/x86-pc/keyboardasm.S: -------------------------------------------------------------------------------- 1 | .code16 2 | .text 3 | 4 | .global keyboardasm_available 5 | keyboardasm_available: 6 | mov $0x01, %ah 7 | int $0x16 8 | retw 9 | 10 | .global keyboardasm_getch 11 | keyboardasm_getch: 12 | mov $0x00, %ah 13 | int $0x16 14 | xor %ah, %ah 15 | ret 16 | 17 | .global keyboardasm_getkeycode 18 | keyboardasm_getkeycode: 19 | mov $0x00, %ah 20 | int $0x16 21 | mov %ah, %al 22 | ret 23 | -------------------------------------------------------------------------------- /cores/x86-pc/keyboardasm.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern __attribute__ ((fastcall)) char keyboardasm_available(void); 4 | extern __attribute__ ((fastcall)) char keyboardasm_getch(void); 5 | extern __attribute__ ((fastcall)) unsigned char keyboardasm_getkeycode(void); 6 | -------------------------------------------------------------------------------- /cores/x86-pc/main.cpp: -------------------------------------------------------------------------------- 1 | extern void setup(void); 2 | extern void loop(void); 3 | 4 | int main(void) { 5 | setup(); 6 | 7 | while (true) { 8 | loop(); 9 | } 10 | 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /cores/x86-pc/toneasm.S: -------------------------------------------------------------------------------- 1 | .code16 2 | .align 4 3 | .text 4 | 5 | .set PIT_CH1_REG, 0x40 6 | .set PIT_CH1_REG, 0x41 7 | .set PIT_CH2_REG, 0x42 8 | .set PIT_MODE_CMD_REG, 0x43 9 | 10 | .set UNK_REG, 0x61 11 | 12 | .global toneasm_toneon 13 | toneasm_toneon: 14 | pusha 15 | pit_cfg: 16 | mov $182, %al 17 | out %al, $PIT_MODE_CMD_REG 18 | mov %cl, %al 19 | out %al, $PIT_CH2_REG 20 | mov %ch, %al 21 | out %al, $PIT_CH2_REG 22 | enable_output: 23 | in $UNK_REG, %al 24 | or $0x03, %al 25 | out %al, $UNK_REG 26 | popa 27 | ret 28 | 29 | .global toneasm_toneoff 30 | toneasm_toneoff: 31 | pusha 32 | in $UNK_REG, %al 33 | and $0xFC, %al 34 | out %al, $UNK_REG 35 | popa 36 | ret 37 | -------------------------------------------------------------------------------- /cores/x86-pc/toneasm.h: -------------------------------------------------------------------------------- 1 | extern void toneasm_toneon(unsigned short frequency) __attribute__ ((fastcall)); 2 | extern void toneasm_toneoff(void) __attribute__ ((fastcall)); 3 | -------------------------------------------------------------------------------- /cores/x86-pc/videoasm.S: -------------------------------------------------------------------------------- 1 | .code16 2 | .align 4 3 | .text 4 | 5 | .global videoasm_putchar 6 | videoasm_putchar: 7 | pusha 8 | mov $0x0E, %ah 9 | xor %bx, %bx 10 | int $0x10 11 | popa 12 | ret 13 | 14 | .global videoasm_clear 15 | videoasm_clear: 16 | push %bx 17 | push %dx 18 | mov $0x06, %ah # "Scroll up window" 19 | mov $0x00, %al # Clear 20 | mov %cl, %bh # Color scheme 21 | mov $0x00, %ch # Upper row number 22 | mov $0x00, %cl # Left column number 23 | mov $24, %dh 24 | mov $79, %dl 25 | int $0x10 26 | pop %dx 27 | pop %bx 28 | ret 29 | 30 | .global videoasm_set_cursor_position 31 | videoasm_set_cursor_position: 32 | push %ax 33 | push %bx 34 | push %dx 35 | mov %al, %dh 36 | mov $0x0200, %ax # Set cursor position 37 | mov $0x00, %bh # Page number 38 | int $0x10 39 | pop %dx 40 | pop %bx 41 | pop %ax 42 | ret 43 | 44 | .global videoasm_set_video_mode 45 | videoasm_set_video_mode: 46 | pusha 47 | mov $0x00, %ah 48 | mov 0x6(%esp), %al 49 | int $0x10 50 | popa 51 | ret 52 | -------------------------------------------------------------------------------- /cores/x86-pc/videoasm.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern void videoasm_putchar(char c); 4 | extern __attribute__ ((fastcall)) void videoasm_clear(unsigned char scheme); 5 | extern __attribute__ ((fastcall)) void videoasm_set_cursor_position(char x, char y); 6 | extern void videoasm_set_video_mode(unsigned char mode); 7 | -------------------------------------------------------------------------------- /doc/hello.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeanthom/boot2duino/6e7e1b8afb014bedddcae7fc6103ace4ffa0fd6c/doc/hello.png -------------------------------------------------------------------------------- /doc/keyboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeanthom/boot2duino/6e7e1b8afb014bedddcae7fc6103ace4ffa0fd6c/doc/keyboard.png -------------------------------------------------------------------------------- /examples/hello.ino: -------------------------------------------------------------------------------- 1 | Video vid; 2 | 3 | void setup() { 4 | vid.print("Hello world, from Arduino!"); 5 | } 6 | 7 | void loop() { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /examples/keyboard.ino: -------------------------------------------------------------------------------- 1 | Video vid; 2 | Keyboard key; 3 | 4 | char password[4]; 5 | 6 | void setup() { 7 | vid.clear(); 8 | vid.setCursorPosition(0, 0); 9 | vid.print("ENTER PASSWORD : "); 10 | 11 | for (int i = 0; i < sizeof(password); i++) { 12 | password[i] = key.getch(); 13 | vid.print('*'); 14 | } 15 | 16 | char x; 17 | do { 18 | x = key.getkeycode(); 19 | } while (x != Keyboard::kEnterKeycode); 20 | 21 | vid.print("\r\nYou typed... "); 22 | vid.print(password); 23 | } 24 | 25 | void loop() { 26 | 27 | } 28 | -------------------------------------------------------------------------------- /examples/piano.ino: -------------------------------------------------------------------------------- 1 | // Use the "-soundhw pcspk" flag in QEMU to get output 2 | 3 | Video vid; 4 | Keyboard key; 5 | 6 | void setup() { 7 | vid.clear(); 8 | vid.setCursorPosition(0, 0); 9 | vid.println("\r\nPiano time!\r\n"); 10 | vid.println("_________________________________________"); 11 | vid.println("| |#| |#| | |#| |#| |#| | |#| |#| |"); 12 | vid.println("| |#| |#| | |#| |#| |#| | |#| |#| |"); 13 | vid.println("| |#| |#| | |#| |#| |#| | |#| |#| |"); 14 | vid.println("| |#| |#| | |#| |#| |#| | |#| |#| |"); 15 | vid.println("| | | | | | | | | | |"); 16 | vid.println("| A | S | D | F | G | H | J | K | L | ; |"); 17 | vid.println("|___|___|___|___|___|___|___|___|___|___|"); 18 | } 19 | 20 | void loop() { 21 | if (key.available()) { 22 | switch (key.getch()) { 23 | case 'a': tone(261); break; // C4 24 | case 'w': tone(277); break; // C4# 25 | case 's': tone(293); break; // D4 26 | case 'e': tone(311); break; // D4# 27 | case 'd': tone(329); break; // E4 28 | case 'f': tone(349); break; // F4 29 | case 't': tone(369); break; // F4# 30 | case 'g': tone(392); break; // G4 31 | case 'y': tone(415); break; // G4# 32 | case 'h': tone(440); break; // A4 33 | case 'u': tone(466); break; // A4# 34 | case 'j': tone(493); break; // B4 35 | case 'k': tone(523); break; // C5 36 | case 'o': tone(554); break; // C5# 37 | case 'l': tone(587); break; // D5 38 | case 'p': tone(622); break; // D5# 39 | case ';': tone(659); break; // E5 40 | default: return; break; 41 | } 42 | delayMicroseconds(50000); 43 | noTone(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /platform.txt: -------------------------------------------------------------------------------- 1 | name=boot2duino 2 | version=1.0.0 3 | 4 | compiler.path=/usr/bin/ 5 | compiler.S.cmd=as 6 | compiler.S.flags=-c --32 7 | compiler.c.cmd=gcc 8 | compiler.c.flags=-c -m16 -ffreestanding -fno-PIE -nostartfiles -nostdlib -std=gnu11 -Os 9 | compiler.c.elf.cmd=gcc 10 | compiler.c.elf.flags=-m16 -ffreestanding -fno-PIE -nostartfiles -nostdlib -std=gnu11 11 | compiler.cpp.cmd=g++ 12 | compiler.cpp.flags=-c -m16 -ffreestanding -fno-PIE -nostartfiles -nostdlib -std=c++11 -Os 13 | compiler.ar.cmd=ar 14 | compiler.ar.flags=rcs 15 | compiler.objcopy=objcopy 16 | compiler.elf2hex.cmd=objcopy 17 | compiler.elf2hex.flags=-O binary 18 | compiler.ld.cmd=ld 19 | 20 | compiler.libs.c.flags= 21 | 22 | build.cpu_flags= 23 | build.hs_flag= 24 | build.upload_flags= 25 | build.flags.optimize= 26 | build.flags.ldspecs= 27 | build.extra_flags= 28 | build.common_flags= 29 | build.ldscript=linker.ld 30 | 31 | ## Compile c files 32 | recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.c.extra_flags} {build.extra_flags} {compiler.libs.c.flags} {includes} "{source_file}" -o "{object_file}" 33 | 34 | ## Compile c++ files 35 | recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {build.extra_flags} {build.cpu_flags} {build.hs_flag} {build.common_flags} {compiler.libs.c.flags} {includes} "{source_file}" -o "{object_file}" 36 | 37 | ## Compile S files 38 | recipe.S.o.pattern="{compiler.path}{compiler.S.cmd}" {compiler.S.flags} "{source_file}" -o "{object_file}" 39 | 40 | ## Combine gc-sections, archives, and objects 41 | recipe.c.combine.use_shell_execute=true 42 | recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -o "{build.path}/{build.project_name}.elf" "-L{build.path}" "-L{build.path}/core" -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group "{archive_file_path}" {object_files} -Wl,--end-group "-T{build.variant.path}/{build.ldscript}" 43 | 44 | recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} "{archive_file_path}" "{object_file}" 45 | 46 | ## Create img 47 | recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.img" 48 | 49 | ## Save Compiled Binary 50 | recipe.output.tmp_file={build.project_name}.img 51 | recipe.output.save_file={build.project_name}.{build.variant}.img 52 | 53 | tools.qemu.cmd=/usr/bin/qemu-system-x86_64 54 | tools.qemu.upload.pattern="{tools.qemu.cmd}" -drive file={build.path}/{build.project_name}.img,format=raw 55 | tools.qemu.program.params.quiet= 56 | tools.qemu.program.params.verbose= 57 | 58 | -------------------------------------------------------------------------------- /programmers.txt: -------------------------------------------------------------------------------- 1 | qemu.name=QEMU 2 | qemu.communication=USB 3 | qemu.protocol=qemu 4 | qemu.program.protocol=qemu 5 | qemu.program.tool=qemu 6 | qemu.program.setup_command= 7 | -------------------------------------------------------------------------------- /variants/x86-pc/linker.ld: -------------------------------------------------------------------------------- 1 | ENTRY(biosentry) 2 | 3 | SECTIONS { 4 | /* MBR zone */ 5 | . = 0x7c00; 6 | .mbr : { 7 | *entry.S.o(.text) 8 | } 9 | 10 | . = 0x7dfe; 11 | .sig : { 12 | SHORT(0xaa55); 13 | } 14 | 15 | /* Regular code zone */ 16 | . = 0x7e00; 17 | .text : { 18 | *(.text .stub .text.*) 19 | *(.data) 20 | *(.rodata .rodata.*) 21 | __bss_start = .; 22 | *(.bss) 23 | *(COMMON) 24 | __bss_end = .; 25 | } 26 | __stack_bottom = .; 27 | . = . + 0x1000; 28 | __stack_top = .; 29 | 30 | /* Deleting useless sections */ 31 | /DISCARD/ : { 32 | *(.eh_frame) 33 | *(.note.gnu.property) 34 | *(.note.gnu.build-id) 35 | *(.comment) 36 | } 37 | } 38 | --------------------------------------------------------------------------------