Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 

README.md

Pure64 Manual

This manual has the purpose of helping software developers understand how they should be using Pure64 to load their kernel.

Prerequisites

This manual assumes you have some understanding of a typical boot process.

You'll have to have NASM installed to build the software.

Building

In the top directory of Pure64, just run the following:

./build.sh

System Requirements

A computer with at least one 64-bit Intel or AMD CPU (or anything else that uses the x86-64 architecture)

At least 2 MiB of RAM

The ability to boot via a hard drive, USB stick, or the network

Writing the Kernel with NASM

Here's a minimal kernel, written for NASM, that you could use with Pure64. Once it's loaded, it enters an infinite loop. The file can be called kernel.asm.

BITS 64
ORG 0x100000

start:
	jmp start

The ORG statement tells NASM that the code should be made to run at the address, 0x100000.

Assemble it like this:

nasm kernel.asm -o kernel.bin

Writing a Kernel with GCC

Here's a similar example written in C with GCC. The file can be called kernel.c.

void _start(void) {

	for (;;) {

	}
}

The kernel needs a linker script to be loaded to 1 MiB, replacing NASMs ORG instruction. The file can be called kernel.ld.

OUTPUT_FORMAT("binary")
OUTPUT_ARCH("i386:x86-64")

SECTIONS
{
	. = 0x100000;
	.text : {
		*(.text)
	}
	.data : {
		*(.data)
	}
	.rodata : {
		*(.rodata)
	}
	.bss : {
		*(.bss)
	}
}

Compile is like this:

gcc -c kernel.c -o kernel.o -mno-red-zone -fno-stack-protector -fomit-frame-pointer
ld -T kernel.ld -o kernel.bin kernel.o

The flags added to the first command are there to help GCC produce could that will run in kernel space. The second command simply takes kernel.o and orders it as the linker script tells it to.

Contributors note

The _start symbol must always appear first within flat binaries as Pure64 will call the start of the file so it must contain executable code. Function definitions (such as inline ones) in header files could interfere with the placement of the _start symbol. The best solution is to put the entry point in a separate file that calls the main function. Such a file could be called start.c.

extern int main(void);

void _start(void)
{
	main();
}

This file would always have to be linked in front of everything else. For the above example that would mean the linker command above would have to become:

ld -T kernel.ld -o kernel.bin start.o kernel.o

Creating a bootable image

All Pure64 binaries are in the bin directory.

BIOS

For BIOS systems you'll need pure64-bios.sys and mbr.sys to be in the same directory as your kernel with the name kernel.bin

dd if=/dev/zero of=disk.img count=128 bs=1048576
cat pure64.sys kernel.bin > software.sys

dd if=mbr.sys of=disk.img conv=notrunc
dd if=software.sys of=disk.img bs=512 seek=16 conv=notrunc

After creating a bootable image it can be tested using qemu: qemu-system-x86_64 -drive format=raw,file=disk.img

UEFI

For UEFI systems you'll need pure64-uefi.sys, uefi.sys, and a FAT-formatted drive/partition.

cat pure64-uefi.sys kernel.bin > software-uefi.sys
cp uefi.sys BOOTX64.EFI
dd if=software-uefi.sys of=BOOTX64.EFI bs=4096 seek=1 conv=notrunc > /dev/null 2>&1

The resulting BOOTX64.EFI can be copied to the \EFI\BOOT\ folder on the storage device you plan on booting from.

Memory Map

This memory map shows how physical memory looks after Pure64 is finished.

Start AddressEnd AddressSizeDescription
0x00000000000000000x0000000000000FFF4 KiBIDT - 256 descriptors (each descriptor is 16 bytes)
0x00000000000010000x0000000000001FFF4 KiBGDT - 256 descriptors (each descriptor is 16 bytes)
0x00000000000020000x0000000000002FFF4 KiBPML4 - 512 entries, first entry points to PDP at 0x3000
0x00000000000030000x0000000000003FFF4 KiBPDP Low - 512 entries
0x00000000000040000x0000000000004FFF4 KiBPDP High - 512 entries
0x00000000000050000x0000000000007FFF12 KiBPure64 Data
0x00000000000080000x000000000000FFFF32 KiBPure64 - After the OS is loaded and running this memory is free again
0x00000000000100000x000000000001FFFF64 KiBPD Low - Entries are 8 bytes per 2MiB page
0x00000000000200000x000000000005FFFF256 KiBPD High - Entries are 8 bytes per 2MiB page
0x00000000000600000x000000000009FFFF256 KiBFree
0x00000000000A00000x00000000000FFFFF384 KiBBIOS ROM Area
   VGA mem at 0xA0000 (128 KiB) Color text starts at 0xB8000
   Video BIOS at 0xC0000 (64 KiB)
   Motherboard BIOS at F0000 (64 KiB)
0x00000000001000000xFFFFFFFFFFFFFFFF1+ MiBThe software payload is loaded here

When creating your Operating System or Demo you can use the sections marked free, however it is the safest to use memory above 1 MiB.

Information Table

Pure64 stores an information table in memory that contains various pieces of data about the computer before it passes control over to the software you want it to load.

The Pure64 information table is located at 0x0000000000005000 and ends at 0x00000000000057FF (2048 bytes).

Memory AddressVariable SizeNameDescription
0x500064-bitACPIAddress of the ACPI tables
0x500832-bitCPU_BSP_IDAPIC ID of the BSP
0x501016-bitCPU_SPEEDSpeed of the CPUs in MegaHertz (MHz)
0x501216-bitCPU_CORES_ACTIVEThe number of CPU cores that were activated in the system
0x501416-bitCPU_CORES_DETECTThe number of CPU cores that were detected in the system
0x50168-bitCPU_MEM_PHYSICALThe number of bits that are valid for a physical address
0x50178-bitCPU_MEM_VIRTUALThe number of bits that are valid for a virtual address
0x501832-bitCPU_ID_MAX_STANDARDThe maximum CPUID standard leaf
0x501C32-bitCPU_ID_MAX_EXTENDEDThe maximum CPUID extended leaf
0x502032-bitRAMAMOUNTAmount of system RAM in Mebibytes (MiB)
0x5022 - 0x502F  For future use
0x50308-bitIOAPIC_COUNTNumber of I/O APICs in the system
0x50318-bitIOAPIC_INTSOURCE_COUNTNumber of I/O APIC Interrupt Source Override
0x5032 - 0x503F  For future use
0x504064-bitHPET AddressBase memory address for the High Precision Event Timer
0x504832-bitHPET FrequencyFrequency for the High Precision Event Timer
0x504C16-bitHPET Counter MinumumMinimum Counter for the High Precision Event Timer
0x504E8-bitHPET CountersNumber of Counter in the High Precision Event Timer
0x504F  For future use
0x506064-bitLAPICLocal APIC address
0x5068 - 0x507F  For future use
0x508064-bitVIDEO_BASEBase memory for video (if graphics mode set)
0x508816-bitVIDEO_XX resolution
0x508A16-bitVIDEO_YY resolution
0x508C16-bitVIDEO_PPSL# of pixels per scan line
0x508E16-bitVIDEO_BPP# of bits per pixel
0x509016-bitPCIE_COUNTNumber of PCIe buses
0x509216-bitIAPC_BOOT_ARCHIA-PC Boot Architecture Flags
0x5094 - 0x50DF  For future use
0x50E08-bitFLAG_1GBPAGE1 if 1GB Pages are supported
0x50E18-bitFLAG_X2APIC1 if X2APIC is supported
0x50E28-bitFLAG_BOOTMODE'B' if BIOS, 'U' for UEFI
0x50E3 - 0x50FF  For future use
0x5100 - 0x51FF8-bitAPIC_IDAPIC ID's for valid CPU cores (based on CORES_ACTIVE)
0x5200 - 0x53FF  For future use
0x5400 - 0x55FF16 byte entriesPCIEPCIe bus data
0x5600 - 0x56FF16 byte entriesIOAPICI/O APIC addresses (based on IOAPIC_COUNT)
0x5700 - 0x57FF8 byte entriesIOAPIC_INTSOURCEI/O APIC Interrupt Source Override Entries (based on IOAPIC_INTSOURCE_COUNT)

PCIE list format:

OffsetVariable SizeNameDescription
0x0064-bitBaseThe base address of enhanced configuration mechanism
0x0816-bitGroupThe PCI segment group number
0x0A8-bitStart BusStart PCI bus number decoded by this host bridge
0x0B8-bitEnd BusEnd PCI bus number decoded by this host bridge
0x0C32-bitReservedThis value should be 0

IOAPIC list format:

OffsetVariable SizeNameDescription
0x0032-bitI/O APIC IDThe ID of an I/O APIC
0x0032-bitI/O APIC AddressThe 32-bit physical address to access this I/O APIC
0x0032-bitGlobal System Interrupt BaseThe global system interrupt number where this I/O APIC’s interrupt inputs start
0x0032-bitReservedThis value should be 0

IOAPIC_INTSOURCE list format:

OffsetVariable SizeNameDescription
0x008-bitBus0
0x008-bitSourceBus-relative interrupt source
0x0032-bitGlobal System InterruptThe Global System Interrupt that this bus-relative interrupt source will signal
0x0016-bitFlagsMPS INTI flags

MPS INTI flags:

FlagsBit LengthBit OffsetDescription
Polarity2001 Active high, 11 Active low
Trigger Mode2201 Edge-triggered, 11 Level-triggered

System Memory Map

BIOS

A copy of the BIOS System Memory Map is stored at memory address 0x0000000000006000. Each BIOS record is 32 bytes in length and the memory map is terminated by a blank record.

VariableVariable SizeDescription
Base64-bitBase Address
Length64-bitLength in bytes
Type32-bitType of memory (1 is usable)
ACPI32-bitSee document linked below
For more information on the BIOS Memory Map: BIOS Specs

UEFI

A copy of the UEFI System Memory Map is stored at memory address 0x0000000000220000. Each UEFI record is 48 bytes in length and the memory map is terminated by a blank record.

VariableVariable SizeDescription
Type64-bitThe type of the memory region
Physical Start64-bitPhysical Address - 4K aligned
Virtual Start64-bitVirtual Address - 4K aligned
NumberOfPages64-bitThe number of 4K pages in this section
Attribute64-bitSee document linked below
Padding64-bitPadding
For more information on the UEFI Memory Map: UEFI Specs

Debugging

Pure64 initializes the serial port COM1 at 115200bps, 8 data bytes, 1 stop bit, no parity, and no flow control. It will display messages on boot-up.

// EOF