.load 0x1740 .entry _drake_bootsector_entry_point .fixed 5120, 0xFF @include <../bios_api.dss> @include @include @define OS_LOAD_ADDR 0x2C00 ## ========================================================================================================================= .data ## Disk data structures $ddd $dpt_block $bootstrap_block:32 $bootstrap_addr:4 $textCell $counter 0x00 $current_char 65 $dpt_version_str "DPT Version " $drake_version_str "Drake 0.2 -- " $invalid_dpt_block_str "Error: Invalid DPT Block..." $no_part_found_str "Error: No bootable partitions found..." ## ========================================================================================================================= .code ## ========================================================================================================================= _drake_bootsector_entry_point: ## Load DPT block from disk 0 push $ddd ## Empty DiskDriverData used to load from disk push $dpt_block ## Empty DPT Block to store the partition table push 2 call $_load_dpt_block ## Enable Text16 Video Mode movb [VGA_Registers.VIDEO_MODE], VGA_VideoModes.TEXT_16_COLORS ## Validate DPT Block mov ACC, [$dpt_block] jne $_invalid_dpt_block, 0xF1CA ## Init Keyboard driver ## push $_key_pressed ## KeyPressed handler address passed to the _init_keyboard subroutine ## push 1 ## call $_init_keyboard ## Enable Double buffering ## mov R2, [VGA_Registers.FLAGS] ## or R2, 0b0000000000000001 ## mov [VGA_Registers.FLAGS], ACC ## @call(_clear_screen, DefaultPalette.DarkBlue) ## @_clear_screen(DefaultPalette.DarkBlue) ## mov R10, 0x22 ## mov R8, { $dpt_block + DPTStructure.ENTRIES_START + (2 * DPTStructure.ENTRY_SIZE_B) + DPTStructure.ENTRY_PART_LBL } ## mov R9, $textCell ## int 0x30 jmp $_endless_loop _invalid_dpt_block: ## TODO: Fix screen drawing on error push $invalid_dpt_block_str push 1 call $_print_error_msg jmp $_main_end _endless_loop: ## Clear screen push DefaultPalette.Black push 1 call $_clear_screen ## Print system info push 0 call $_print_system_info ## Draw main box ## push 0 ## call $_print_main_box ## Swap the buffers ## push 0 ## call $_swap_buffers mov R10, $dpt_block.PartCount movb ACC, *R10 jge $_no_partitions_found, 1 mov R10, $dpt_block.PartCount movb R10, *R10 push $dpt_block.Entries push R10 push $bootstrap_addr push 3 call $_test_partitions mov ACC, RV jeq $_no_partitions_found, 0xFF mov R1, $ddd mov R4, $bootstrap_addr mov R3, R1 ## Copy $ddd address into R3 movb *R1, DiskMode.READ ## $ddd.Mode inc R1 movb *R1, 0x00 ## $ddd.Disk inc R1 mov *R1, *R4 ## $ddd.Sector addip R1, 2 addip R4, 2 mov *R1, *R4 ## $ddd.Address addip R1, 2 mov *R1, 1024 ## $ddd.DataSize addip R1, 2 mov *R1, OS_LOAD_ADDR ## $ddd.MemoryAddress mov R9, R3 ## Move original $ddd address into R9 (for int 0x20) mov R10, 0x12 ## int 0x20 parameter for load_from_ddd_blocking int 0x20 ## Bios interrupt debug_break jmp OS_LOAD_ADDR jmp $_main_end _no_partitions_found: push $no_part_found_str push 1 call $_print_error_msg jmp $_main_end ## jmp $_endless_loop _main_end: hlt ## ========================================================================================================================= ## ========================================================================================================================= _test_partitions: ## _test_partitions(DPTBlock* dpt_entries_block, (1 Byte) dpt_entries_count, (4 Bytes*) part_addr) arg R1 ## dpt_entries_block arg R2 ## dpt_entries_count arg R4 ## part_addr mov R3, 0 ## Entry counter _test_partitions_loop: push $ddd push $bootstrap_block push R3 push 3 call $_load_bootstrap_block mov ACC, $bootstrap_block mov ACC, *ACC jeq $_test_partitions_found, DPTBootPartStructure.ID_CODE inc R3 mov ACC, R3 jle $_test_partitions_not_found, R2 jmp $_test_partitions_loop _test_partitions_found: mov R10, R3 mulip R10, DPTStructure.ENTRY_SIZE_B addip R10, R1 mov *R4, *R10 addip R4, 2 addip R10, 2 mov *R4, *R10 mov R9, *R4 addip R9, DPTBootPartStructure.HEADER_SIZE_B ## TODO: This doesn't take into account integer overflow, since it is a 32-Bit address mov *R4, R9 mov RV, R3 ret _test_partitions_not_found: mov *R4, 0xFFFF addip R4, 2 mov *R4, 0xFFFF mov RV, 0xFF ret ## ========================================================================================================================= ## ========================================================================================================================= _load_bootstrap_block: ## _load_bootstrap_block(DiskDriverData* ddd, (32 Byte*) bootstrap_block, (1 Byte) dpt_entry) arg R1 ## @Param: ddd arg R2 ## @Param: bootstrap_block arg R7 ## @Param: dpt_entry mov R3, R1 ## Copy $ddd address into R3 movb *R1, DiskMode.READ ## $ddd.Mode inc R1 movb *R1, 0x00 ## $ddd.Disk inc R1 mov R10, $dpt_block.Entries mulip R7, DPTStructure.ENTRY_SIZE_B addip R10, R7 mov *R1, *R10 ## $ddd.Sector addip R1, 2 addip R10, 2 mov *R1, *R10 ## $ddd.Address addip R1, 2 mov *R1, DPTBootPartStructure.HEADER_SIZE_B ## $ddd.DataSize addip R1, 2 mov *R1, R2 ## $ddd.MemoryAddress mov R9, R3 ## Move original $ddd address into R9 (for int 0x20) mov R10, 0x12 ## int 0x20 parameter for load_from_ddd_blocking int 0x20 ## Bios interrupt ret ## ========================================================================================================================= ## ========================================================================================================================= _load_dpt_block: ## _load_dpt_block(DiskDriverData* ddd, DPTBlock* dpt_block) arg R1 ## @Param: ddd arg R2 ## @Param: dpt_block mov R3, R1 ## Copy $ddd address into R3 movb *R1, DiskMode.READ ## $ddd.Mode inc R1 movb *R1, 0x00 ## $ddd.Disk inc R1 mov *R1, 0x0000 ## $ddd.Sector addip R1, 2 mov *R1, 0x0200 ## $ddd.Address addip R1, 2 mov *R1, 512 ## $ddd.DataSize addip R1, 2 mov *R1, R2 ## $ddd.MemoryAddress mov R9, R3 ## Move original $ddd address into R9 (for int 0x20) mov R10, 0x12 ## int 0x20 parameter for load_from_ddd_blocking int 0x20 ## Bios interrupt ret ## ========================================================================================================================= ## ========================================================================================================================= _print_error_msg: ## _print_error_msg(string* error_msg) arg R1 ## @Param: error_msg ## TODO: Clear the screen movb [$textCell.CoordX], 0 movb [$textCell.CoordY], 1 movb [$textCell.Foreground], DefaultPalette.Red movb [$textCell.Background], DefaultPalette.Black mov R10, 0x22 mov R8, R1 mov R9, $textCell int 0x30 ret ## ========================================================================================================================= ## ========================================================================================================================= _print_system_info: movb [$textCell.CoordX], 0 movb [$textCell.CoordY], 0 movb [$textCell.Foreground], DefaultPalette.Green movb [$textCell.Background], DefaultPalette.Black mov R10, 0x22 mov R8, $drake_version_str mov R9, $textCell int 0x30 movb [$textCell.CoordX], 13 mov R10, 0x22 mov R8, $dpt_version_str mov R9, $textCell int 0x30 movb [$textCell.CoordX], 26 mov R10, 0x23 movb R8, [{ $dpt_block + 2 }] mov R9, $textCell int 0x30 movb [$textCell.CoordX], 27 movb [$textCell.Character], 0x2E mov R10, 0x21 mov R9, $textCell int 0x30 movb [$textCell.CoordX], 28 mov R10, 0x23 movb R8, [{ $dpt_block + 3 }] mov R9, $textCell int 0x30 ret ## ========================================================================================================================= ## ========================================================================================================================= _clear_screen: ## _clear_screen(int8_t color) arg R1 movb [$textCell.Foreground], R1 movb [$textCell.Background], R1 movb [$textCell.Character], 0x20 mov R10, 0x24 mov R9, $textCell int 0x30 ret ## ========================================================================================================================= ## ========================================================================================================================= _redraw_screen: movb [VGA_Registers.SIGNAL], Sig_VGA_Text_16_Color.FORCE_REDRAW_SCREEN ret ## ========================================================================================================================= ## ========================================================================================================================= ## _swap_buffers: ## movb [VGA_Registers.SIGNAL], Sig_VGA_Text_16_Color.SWAP_BUFFERS ## ret ## ========================================================================================================================= ## ========================================================================================================================= ## _key_pressed: ## mov ACC, [Keyboard_Registers.KEYCODE] ## jne $_key_pressed_end, 0x0127 ## _key_pressed_end: ## ret ## ========================================================================================================================= ## ========================================================================================================================= ## _print_main_box: ## movb [$textCell.CoordX], 5 ## movb [$textCell.CoordY], 2 ## movb [$textCell.Foreground], DefaultPalette.Sky ## movb [$textCell.Background], DefaultPalette.DarkBlue ## movb [$textCell.Character], 0x3D ## ## mov R8, [CMOS_Settings.SCREEN_WIDTH] ## subip R8, 10 ## ## push $textCell ## push R8 ## push 2 ## call $_draw_horizontal_line ## ## movb [$textCell.CoordX], 5 ## movb [$textCell.CoordY], 12 ## push $textCell ## push R8 ## push 2 ## call $_draw_horizontal_line ## ## movb [$textCell.CoordX], 4 ## movb [$textCell.CoordY], 2 ## movb [$textCell.Character], 0x7C ## push $textCell ## push 11 ## push 2 ## call $_draw_vertical_line ## ## addip R8, 5 ## movb [$textCell.CoordX], R8 ## movb [$textCell.CoordY], 2 ## push $textCell ## push 11 ## push 2 ## call $_draw_vertical_line ## ret ## ========================================================================================================================= ## ========================================================================================================================= ## _draw_horizontal_line: ## _draw_horizontal_line(TextCell16* cell, int8_t length) ## arg R1 ## @Param: cell ## arg R2 ## @Param: length ## mov R3, R1 ## addip R3, 3 ## movb R4, *R3 ## ## mov R10, 0x21 ## mov R9, R1 ## _draw_horizontal_line_loop: ## int 0x30 ## movb R5, *R3 ## inc R5 ## movb *R3, R5 ## sub R5, R4 ## jgr $_draw_horizontal_line_loop, R2 ## ret ## ========================================================================================================================= ## ========================================================================================================================= ## _draw_vertical_line: ## _draw_line(TextCell16* cell, int8_t length) ## arg R1 ## @Param: cell ## arg R2 ## @Param: length ## mov R3, R1 ## addip R3, 4 ## movb R4, *R3 ## ## mov R10, 0x21 ## mov R9, R1 ## _draw_vertical_line_loop: ## int 0x30 ## movb R5, *R3 ## inc R5 ## movb *R3, R5 ## sub R5, R4 ## jgr $_draw_vertical_line_loop, R2 ## ret ## =========================================================================================================================