From 0706329497b946ba0b7e5d1b100d1e9a60c7ee42 Mon Sep 17 00:00:00 2001 From: AYIDouble Date: Thu, 13 Sep 2018 10:28:04 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9E=95=20Add?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assembler Intel Code/apm_shutdown.S | 62 +++ Assembler Intel Code/bios_keyboard_loop.S | 7 + Assembler Intel Code/infinite_loop.S | 4 + Assembler Intel Code/intel-protected/build.sh | 8 + .../intel-protected/eprom.bld | 38 ++ Assembler Intel Code/intel-protected/main.asm | 12 + .../intel-protected/startup.asm | 393 ++++++++++++++++++ Assembler Intel Code/interrupt_keyboard.S | 15 + 8 files changed, 539 insertions(+) create mode 100644 Assembler Intel Code/apm_shutdown.S create mode 100644 Assembler Intel Code/bios_keyboard_loop.S create mode 100644 Assembler Intel Code/infinite_loop.S create mode 100644 Assembler Intel Code/intel-protected/build.sh create mode 100644 Assembler Intel Code/intel-protected/eprom.bld create mode 100644 Assembler Intel Code/intel-protected/main.asm create mode 100644 Assembler Intel Code/intel-protected/startup.asm create mode 100644 Assembler Intel Code/interrupt_keyboard.S diff --git a/Assembler Intel Code/apm_shutdown.S b/Assembler Intel Code/apm_shutdown.S new file mode 100644 index 0000000..bef53bb --- /dev/null +++ b/Assembler Intel Code/apm_shutdown.S @@ -0,0 +1,62 @@ +#include "common.h" + +BEGIN + +movb $0x53,%ah #this is an APM command +movb $0x0,%al #installation check command +xorw %bx,%bx #device id (0 = APM BIOS) +int $0x15 #call the BIOS function through interrupt 15h +jc APM_error #if the carry flag is set there was an error + #the function was successful + #AX = APM version number + #AH = Major revision number (in BCD format) + #AL = Minor revision number (also BCD format) + #BX = ASCII characters "P" (in BH) and "M" (in BL) + #CX = APM flags (see the official documentation for more details) + +#disconnect from any APM interface +movb $0x53,%ah #this is an APM command +movb $0x4,%al #interface disconnect command +xorw %bx,%bx #device id (0 = APM BIOS) +int $0x15 #call the BIOS function through interrupt 15h +jc .disconnect_error #if the carry flag is set see what the fuss is about. +jmp .no_error + +.disconnect_error: #the error code is in ah. +cmpb $0x3,%ah #if the error code is anything but 03h there was an error. +jne APM_error #the error code 03h means that no interface was connected in the first place. + +.no_error: + #the function was successful + #Nothing is returned. + +#connect to an APM interface +movb $0x53,%ah #this is an APM command +movb $0x01,%al #see above description +xorw %bx,%bx #device id (0 = APM BIOS) +int $0x15 #call the BIOS function through interrupt 15h +jc APM_error #if the carry flag is set there was an error + #the function was successful + #The return values are different for each interface. + #The Real Mode Interface returns nothing. + #See the official documentation for the + #return values for the protected mode interfaces. + +#Enable power management for all devices +movb $0x53,%ah #this is an APM command +movb $0x8,%al #Change the state of power management... +movw $0x001,%bx #...on all devices to... +movw $0x001,%cx #...power management on. +int $0x15 #call the BIOS function through interrupt 15h +jc APM_error #if the carry flag is set there was an error + +#Set the power state for all devices +movb $0x53,%ah #this is an APM command +movb $0x07,%al #Set the power state... +movw $0x0001,%bx #...on all devices to... +movw $0x0003,%cx #see above +int $0x15 #call the BIOS function through interrupt 15h +jc APM_error #if the carry flag is set there was an error + +APM_error: +hlt \ No newline at end of file diff --git a/Assembler Intel Code/bios_keyboard_loop.S b/Assembler Intel Code/bios_keyboard_loop.S new file mode 100644 index 0000000..a862c34 --- /dev/null +++ b/Assembler Intel Code/bios_keyboard_loop.S @@ -0,0 +1,7 @@ +#include "common.h" +BEGIN +start: + mov $0x00, %ah + int $0x16 + PUTC <%al> +jmp start \ No newline at end of file diff --git a/Assembler Intel Code/infinite_loop.S b/Assembler Intel Code/infinite_loop.S new file mode 100644 index 0000000..62ed558 --- /dev/null +++ b/Assembler Intel Code/infinite_loop.S @@ -0,0 +1,4 @@ +#include "common.h" +BEGIN +loop: +jmp loop \ No newline at end of file diff --git a/Assembler Intel Code/intel-protected/build.sh b/Assembler Intel Code/intel-protected/build.sh new file mode 100644 index 0000000..ec3738a --- /dev/null +++ b/Assembler Intel Code/intel-protected/build.sh @@ -0,0 +1,8 @@ +ASM386 STARTUP.ASM +ASM386 MAIN.ASM +BLD386 STARTUP.OBJ, MAIN.OBJ buildfile(EPROM.BLD) bootstrap(STARTUP) Bootload +# BLD386 performs several operations in this example: +# It allocates physical memory location to segments and tables. +# It generates tables using the build file and the input files. +# It links object files and resolves references. +# It generates a boot-loadable file to be programmed into the EPROM. diff --git a/Assembler Intel Code/intel-protected/eprom.bld b/Assembler Intel Code/intel-protected/eprom.bld new file mode 100644 index 0000000..32a6b6b --- /dev/null +++ b/Assembler Intel Code/intel-protected/eprom.bld @@ -0,0 +1,38 @@ +INIT_BLD_EXAMPLE; + +SEGMENT + *SEGMENTS(DPL = 0), + startup.startup_code(BASE = 0FFFF0000H) + ; + +TASK + BOOT_TASK(OBJECT = startup, INITIAL,DPL = 0, + NOT INTENABLED), + PROTECTED_MODE_TASK(OBJECT = main_module,DPL = 0, + NOT INTENABLED) + +TABLE + GDT ( + LOCATION = GDT_EPROM, + ENTRY = ( + 10: PROTECTED_MODE_TASK, + startup.startup_code, + startup.startup_data, + main_module.data, + main_module.code, + main_module.stack + ) + ), + IDT ( + LOCATION = IDT_EPROM + ); + +MEMORY +( + RESERVE = (0..3FFFH, + -- Area for the GDT, IDT, TSS copied from ROM + 60000H..0FFFEFFFFH), + RANGE = (ROM_AREA = ROM (0FFFF0000H..0FFFFFFFFH)), + -- Eprom size 64K + RANGE = (RAM_AREA = RAM (4000H..05FFFFH)) +) diff --git a/Assembler Intel Code/intel-protected/main.asm b/Assembler Intel Code/intel-protected/main.asm new file mode 100644 index 0000000..816c3b9 --- /dev/null +++ b/Assembler Intel Code/intel-protected/main.asm @@ -0,0 +1,12 @@ +NAME main_module +data SEGMENT RW + dw 1000 dup(?) +DATA ENDS +stack stackseg 800 +CODE SEGMENT ER use32 PUBLIC +main_start: + nop + nop + nop +CODE ENDS +END main_start, ds:data, ss:stack diff --git a/Assembler Intel Code/intel-protected/startup.asm b/Assembler Intel Code/intel-protected/startup.asm new file mode 100644 index 0000000..2d3441b --- /dev/null +++ b/Assembler Intel Code/intel-protected/startup.asm @@ -0,0 +1,393 @@ +; TODO finish converting this to a text file that looks like the PDF... + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; ASSUMPTIONS: +; +; 1. The bottom 64K of memory is ram, and can be used for +; scratch space by this module. +; +; 2. The system has sufficient free usable ram to copy the +; initial GDT, IDT, and TSS +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; configuration data - must match with build definition + +CS_BASE EQU 0FFFF0000H +; CS_BASE is the linear address of the segment STARTUP_CODE +; - this is specified in the build language file + +RAM_START EQU 400H +; RAM_START is the start of free, usable ram in the linear +; memory space. The GDT, IDT, and initial TSS will be +; copied above this space, and a small data segment will be +; discarded at this linear address. The 32-bit word at +; RAM_START will contain the linear address of the first +; free byte above the copied tables - this may be useful if +; a memory manager is used. + +TSS_INDEX EQU 10 +; TSS_INDEX is the index of the TSS of the first task to +; run after startup + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; ------------------------- STRUCTURES and EQU --------------- +; structures for system data + +; TSS structure +TASK_STATE STRUC + link DW ? + link_h DW ? + ESP0 DD ? + SS0 DW ? + SS0_h DW ? + ESP1 DD ? + SS1 DW ? + SS1_h DW ? + ESP2 DD ? + SS2 DW ? + SS2_h DW ? + CR3_reg DD ? + EIP_reg DD ? + EFLAGS_regDD ? + EAX_reg DD ? + ECX_reg DD ? + EDX_reg DD ? + EBX_reg DD ? + ESP_reg DD ? + EBP_reg DD ? + ESI_reg DD ? + EDI_reg DD ? + ES_reg DW ? + ES_h DW ? + CS_reg DW ? + CS_h DW ? + SS_reg DW ? + SS_h DW ? + DS_reg DW ? + DS_h DW ? + FS_reg DW ? + FS_h DW ? + GS_reg DW ? + GS_h DW ? + LDT_reg DW ? + LDT_h DW ? + TRAP_reg DW ? + IO_map_baseDW ? +TASK_STATE ENDS + +; basic structure of a descriptor +DESC STRUC + lim_0_15 DW ? + bas_0_15 DW ? + bas_16_23 DB ? + access DB ? + gran DB ? + bas_24_31 DB ? +DESC ENDS + +; structure for use with LGDT and LIDT instructions +TABLE_REG STRUC +table_lim DW ? +table_linearDD ? +TABLE_REG +ENDS +; offset of GDT and IDT descriptors in builder generated GDT +GDT_DESC_OFF +EQU 1*SIZE(DESC) +IDT_DESC_OFF +EQU 2*SIZE(DESC) +; equates for building temporary GDT in RAM +LINEAR_SEL +EQU +1*SIZE (DESC) +LINEAR_PROTO_LO +EQU +00000FFFFH ; LINEAR_ALIAS +LINEAR_PROTO_HI +EQU +000CF9200H +; Protection Enable Bit in CR0 +PE_BIT EQU 1B +; ------------------------------------------------------------ +; ------------------------- DATA SEGMENT---------------------- +; Initially, this data segment starts at linear 0, according +; to the processor’s power-up state. +STARTUP_DATA +SEGMENT RW +free_mem_linear_base +LABEL +DWORD +TEMP_GDT +LABEL +BYTE ; must be first in segment +TEMP_GDT_NULL_DESC +DESC +<> +TEMP_GDT_LINEAR_DESC DESC +<> +; scratch areas for LGDT and +LIDT instructions +TEMP_GDT_SCRATCH TABLE_REG +<> +APP_GDT_RAM +TABLE_REG +<> +APP_IDT_RAM +TABLE_REG +<> +; align end_data +fill +DW +? +; last thing in this segment - should be on a dword boundary +end_data +LABEL +BYTE +STARTUP_DATA +ENDS +; ------------------------------------------------------------ +; ------------------------- CODE SEGMENT---------------------- +STARTUP_CODE SEGMENT ER PUBLIC USE16 +; filled in by builder +PUBLIC GDT_EPROM +GDT_EPROM +TABLE_REG +<> +; filled in by builder +PUBLIC IDT_EPROM +IDT_EPROM +TABLE_REG +<> +; entry point into startup code - the bootstrap will vector +; here with a near JMP generated by the builder. +This +; label must be in the top 64K of linear memory. +PUBLIC +STARTUP +STARTUP: +; DS,ES address the bottom 64K of flat linear memory +ASSUME DS:STARTUP_DATA, ES:STARTUP_DATA +; See Figure 9-4 +; load GDTR with temporary GDT +LEA +EBX,TEMP_GDT ; build the TEMP_GDT in low ram, +MOV +DWORD PTR [EBX],0 +; where we can address +MOV +DWORD PTR [EBX]+4,0 +MOV +DWORD PTR [EBX]+8, LINEAR_PROTO_LO +MOV +DWORD PTR [EBX]+12, LINEAR_PROTO_HI +MOV +TEMP_GDT_scratch.table_linear,EBX +MOV +TEMP_GDT_scratch.table_lim,15 +DB 66H; execute a 32 bit LGDT +LGDT +TEMP_GDT_scratch +; enter protected mode +MOV +EBX,CR0 +OR +EBX,PE_BIT +MOV +CR0,EBX +; clear prefetch queue +JMP +CLEAR_LABEL +CLEAR_LABEL: +; make DS and ES address 4G of linear memory +MOV +CX,LINEAR_SEL +MOV +DS,CX +MOV +ES,CX +; do board specific initialization +; +; +; ...... +; +; See Figure 9-5 +; copy EPROM GDT to ram at: +; +RAM_START + size (STARTUP_DATA) +MOV +EAX,RAM_START +ADD +EAX,OFFSET (end_data) +MOV +EBX,RAM_START +MOV +ECX, CS_BASE +ADD +ECX, OFFSET (GDT_EPROM) +MOV +ESI, [ECX].table_linear +MOV +EDI,EAX +MOVZX +ECX, [ECX].table_lim +MOV +APP_GDT_ram[EBX].table_lim,CX +INC +ECX +MOV +EDX,EAX +MOV +APP_GDT_ram[EBX].table_linear,EAX +ADD +EAX,ECX +REP MOVS +BYTE PTR ES:[EDI],BYTE PTR DS:[ESI] +; fixup +GDT base in descriptor +MOV +ECX,EDX +MOV +[EDX].bas_0_15+GDT_DESC_OFF,CX +ROR +ECX,16 + +; PAGE 4 TODO remove later. + +MOV +[EDX].bas_16_23+GDT_DESC_OFF,CL +[EDX].bas_24_31+GDT_DESC_OFF,CH +; copy EPROM IDT to ram at: +; RAM_START+size(STARTUP_DATA)+SIZE (EPROM GDT) +MOV + ECX, CS_BASE +ADD + ECX, OFFSET (IDT_EPROM) +MOV + ESI, [ECX].table_linear +MOV + EDI,EAX +MOVZX + ECX, [ECX].table_lim +MOV + APP_IDT_ram[EBX].table_lim,CX +INC + ECX +MOV + APP_IDT_ram[EBX].table_linear,EAX +MOV + EBX,EAX +ADD + EAX,ECX +REP MOVS + BYTE PTR ES:[EDI],BYTE PTR DS:[ESI] +MOV +ROR +MOV +MOV +MOV +LGDT +LIDT +REPMOV +MOV +MOV +MOV +MOV +MOV +ROL +MOV +MOV +LSL +INC +MOV +ADD +MOVS +MOV +ROL +MOV +MOV +ROL +;save start +MOV +; fixup IDT pointer in GDT +[EDX].bas_0_15+IDT_DESC_OFF,BX +EBX,16 +[EDX].bas_16_23+IDT_DESC_OFF,BL +[EDX].bas_24_31+IDT_DESC_OFF,BH +; load GDTR and IDTR +EBX,RAM_START +DB + 66H + ; execute a 32 bit LGDT +APP_GDT_ram[EBX] +DB + 66H + ; execute a 32 bit LIDT +APP_IDT_ram[EBX] +; move the TSS +EDI,EAX +EBX,TSS_INDEX*SIZE(DESC) +ECX,GDT_DESC_OFF ;build linear address for TSS +GS,CX +DH,GS:[EBX].bas_24_31 +DL,GS:[EBX].bas_16_23 +EDX,16 +DX,GS:[EBX].bas_0_15 +ESI,EDX +ECX,EBX +ECX +EDX,EAX +EAX,ECX +BYTE PTR ES:[EDI],BYTE PTR DS:[ESI] +; fixup TSS pointer +GS:[EBX].bas_0_15,DX +EDX,16 +GS:[EBX].bas_24_31,DH +GS:[EBX].bas_16_23,DL +EDX,16 +of free ram at linear location RAMSTART +free_mem_linear_base+RAM_START,EAX + + +;assume no LDT used in the initial task - if necessary, +;code to move the LDT could be added, and should resemble +;that used to move the TSS +; load task register +LTR +BX +; No task switch, only descriptor loading +; See Figure 9-6 +; load minimal set of registers necessary to simulate task +; switch +MOV +AX,[EDX].SS_reg +; start loading registers +MOV +EDI,[EDX].ESP_reg +MOV +SS,AX +MOV +ESP,EDI +; stack now valid +PUSH +DWORD PTR [EDX].EFLAGS_reg +PUSH +DWORD PTR [EDX].CS_reg +PUSH +DWORD PTR [EDX].EIP_reg +MOV +AX,[EDX].DS_reg +MOV +BX,[EDX].ES_reg +MOV +DS,AX +; DS and ES no longer linear memory +MOV +ES,BX +; simulate far jump to initial task +IRETD +STARTUP_CODE ENDS +END STARTUP, DS:STARTUP_DATA, SS:STARTUP_DATA + diff --git a/Assembler Intel Code/interrupt_keyboard.S b/Assembler Intel Code/interrupt_keyboard.S new file mode 100644 index 0000000..d449f46 --- /dev/null +++ b/Assembler Intel Code/interrupt_keyboard.S @@ -0,0 +1,15 @@ +#include "common.h" +BEGIN + CLEAR + /* I've read that the keyboard handler is the number 1 (second one), + * and each entry is 4 byte wide. + */ + movw $handler, 0x04 + movw $0x00, 0x06 + sti +loop: + jmp loop +handler: + PUTC $'a + iret +jmp loop \ No newline at end of file