Elmar Hanlhofer - Grinch Selfie
zoom

English / Deutsch
Twitter
twitter

The New Boot Manager


This page is just temporary. The URL will change in the future. The new boot manager will be different to the Plop Boot Manager series. It became an own product. The name is not defined now.

The Boot Manager should work on BIOS and UEFI systems.

The new boot manager will be written from scratch. Planed features are

  • Full USB 1.1/2.0/3.0 support (thumbs, hard disks, floppys, optical drives, keyboards, hubs, maybe mouse)
  • PC-Card (PCMCIA) flash disk support
  • PCI Express support
  • VHD support
  • (U)EFI support
  • GPT support
  • Simple text mode, enhanced text mode, gfx mode
  • Support various file systems (FAT12/16/32, Ext2/3/4, limited NTFS, limited HFS+)
  • Native Linux Kernel boot
  • Native AHCI support
  • Modular
  • Simple shell

Donations are rare and welcome: Donate



2018-11-29  -  Loader for CDROM


Implementing the loader to start the boot manager from CDROM was quite easy. Now continuing with the ISO 9660 file system. Its a simple file system and I am sure, I will need it later. Great to see that old and simple concepts like ISO 9660, El Torito and also FAT FS are still important nowadays.


2018-11-27  -  Window based menu system


USB HUB driver

The driver for USB 1.1 works fine. The driver for USB 2.0 is left to do.


Window based menu

I wrote routines for a window based menu system. As the Plop Boot Manager, it supports text and graphic mode, various resolutions (also wide screen), various fonts.

The new system supports background images and textures with alpha support to enable window shadows.


Todo

• Theme system to customize the look easily.
• Custom fonts.
• Font upscale on high resolutions.
• Window animation.
• Dynamic background.
• And a few other things...

This is a list of the functions from the current window library.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
dword W_GetX (dword object)
dword W_GetY (dword object)

byte W_GetType (dword object)
dword W_GetParent (dword object)
void W_SetIsActive (dword object, word status)
bool W_IsActive (dword object)


dword W_CreateWindow (word x, word y, word width, word height, word color, dword texture)
void W_WindowAddItem (dword window, dword item)

void W_DrawWindowNoBorders (dword window)
void W_DrawWindowWithBorders (dword window)
void W_DrawWindowWithTexture (dword window)
void W_ClearWindow (dword window)


dword W_CreateString (dword parent, word x, word y, word color, dword string)
void W_DrawString (dword string)
void W_DrawStringColor (dword string, word color)


dword W_CreateMenu (dword window, word x, word y, word width, word color, word bar_color)
void W_MenuAddItem (dword menu, dword item)
dword W_MenuAddEntry (dword menu, dword string, dword function, word barskip, dword data)
void W_MenuMoveBar (dword menu, word action)
void W_MenuUpdateItemsXY (dword menu)
void W_DrawMenu (dword menu)
dword W_MenuGetActiveEntry (dword menu)
void W_MenuRunEntryFunction (dword menu)


void W_Main (dword menu)


void W_Draw (dword object)
void W_DrawAll()


dword W_CreateBackground ()
void W_DrawBackground (dword dummy)


void W_DestroyMenuEntry (dword entry)
void W_DestroyString (dword string)
void W_Destroy (dword object)


Hello world window code sample

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
    ; Create the window object
push dword [.window_texture]
push word COLOR_BG (COLOR_GREEN) | COLOR_WHITE ; Background color | Foreground color
push word 20
push word 50
push word 10
push word 10
call W_CreateWindow ; (word x, word y, word width, word height, word color, dword texture)
jc .error

mov [.window], eax


; Add a string to the window.
; Use text color from the parent window.
push dword TxtHelloWorld
push word 1
push word 2
push dword [.window]
call W_CreateString ; (dword window, word x, word y, dword string)
jc .error

mov [.wstring], eax


; Draw all objects
call W_DrawAll


; Main loop, wait for input and handle menu system.
; This sample has no menu.
push dword 0
call W_Main ; (dword menu)


; Remove the window and free the memory of the window and its childrens.
push dword [.window]
call W_Destroy ; (dword object)


I am coming closer to put all together. The window based menu system is good enough for the moment. It will be improved later. Now, I focus on booting. I have to write a simple loader to start the menu from CD-ROM.


2018-10-05  -  USB HUB driver status - continued


Device enumeration works. The driver works for USB 1.1.

Next: Improving and cleanup the code. Do some testing. Add support for USB 2.0 to the driver.


2018-10-04  -  USB HUB driver status


The USB HUB driver is still under development. Yesterday, I found myself in some kind of a dead end. The HUB worked and I was able to enumerate a fresh connected device. But my code was not good enough to run in an Interrupt Service Routine (ISR). Today, I rewrote mostly and now I am a big step forward. Device connect/disconnect on any port is recognized in the ISR. Device enumeration does not work at the moment, but this comes tomorrow.

Here are two pictures of my current test machine running the HUB driver. It is my old Gericom Webboy, bought (I think) in the year 2000.


2018-09-18  -  UHCI, USB HUB, Synthetic DNA Menu


For a long time nothing Boot Manager related happened. But last week, I made the required code update for the UHCI driver. Then I started to write the USB HUB driver. For testing, I want an USB HUB that supports only USB 1.1. I gave my old USB 1.1 HUB away for a few cents many years ago :(. So bought and received a new one last week.


Last week (Thursday), I also had an idea about an extra ordinary menu. The Synthetic DNA Menu. I realized a concept with Blender. But it's only an idea/dream. Too heavy for a boot manager that has only some basic 3D processing routines. It's just a boot manager :) Maybe, I use this menu with the Armored Eye project. More about the Synthetic DNA Menu is here.

Video

Images


2018-08-07  -  USB mass storage with UHCI/EHCI and the USB floppy drive


The mass storage function call synchronization for UHCI, OHCI and EHCI is almost complete. Hard disks, thumb drives and CDROM drives are working fine with the same function calls for all three controller types.

My USB 1.1 floppy drive did not work on OHCI and UHCI. My fault was to ignore the Interface Protocol value from the device. This drive has to be accessed in another way than Bulk-Only drives. You have to send the ATAPI Command Block over the Control Endpoint and send/receive the data over the Bulk Endpoints. Now, the floppy drive access works fine for OHCI. Some code cleanup and updating the UHCI code is needed.

What comes after the code update? There is still the USB HUB driver missing. The USB keyboard driver needs a lot of updates.


2018-07-24  -  USB DVD drive


The first work I did today was to check why the USB DVD drive did not work. I found the problem quickly. I allocated only 512 bytes instead of 2048 bytes for the sector read destination buffer. 2048 bytes is the block size of CD ROMs. Because of the wrong size there was overlapped memory that created invalid data. The invalid data was the reason for the drive reset. Now the drive works perfect.

The USB Floppy drive still makes problems. I have to check whats going on on the USB bus. But now there is some work to do for EHCI and UHCI.


2018-07-23  -  Just a status update


I synchronized the OHCI and EHCI code that the access to the shared USB functions works in the same way. UHCI is left to synchronize. The base programs for those drivers lived in their own environment and function calls changed during development. Word sized parameters became dword size, here and there is an additional parameter required. Assembler is not flexible as a high level language, even with my macros ;). So you have to take care by yourself to submit the correct parameters in the correct size to a function call. That means more and overall a clean work, but at the end its also more fun for the software developer, in a funny or strange matter ;).

I also cleaned up and simplified the USB Bulk driver, needed to access mass storage devices. I added nearly all required functions like inquiry, read capacity, read sector, write sector and so on. It works fine with the OHCI driver and hard disks/thumb drives. I also tried my USB Floppy Drive and USB DVD Drive. Unfortunately, one drive hung and the other resets itself. In other words, both did not work. That's life. It was a bit disappointing, but I will fix it. For EHCI, I have to update the USB Pipe logic and then test the bulk driver. But that comes later.


2018-07-21  -  ReactOS/FreeLoader/Plop Boot Manager


It has partially to do with the new boot manager. But its also important. I created a dirty fix to start the Plop Boot Manager from the FreeLdr boot menu. It has to be tested.

See https://forum.plop.at/index.php/topic,1840.msg7424.html


Some notes about ReactOS

ReactOS error message "Userinit failed to start the installer!". You are using the wrong ReactOS CD for installation. Don't use the ReactOS Live CD, choose the other one.

ReactOS boot error message "hive header failed" or blue screen. Maybe your virtual hard disk is too small. Use at least a size of 4 GB.


2018-07-11  -  USB OHCI driver 16/32 bit test


Today, I tested my USB OHCI code in my 32 bit environment. The code was written and tested in a 16 bit environment. The plan was/is to run the code in 16 and 32 bit CPU mode. In this experimental stage, the driver is not loaded dynamically. I had to prepare and hard code a few things and then.... It gave me a chill! It was great to see that the code worked fine in the same way as in the 16 bit environment. I am really happy :)

Note: 16/32 bit code runs also on a 64 bit CPU.


2018-07-09  -  USB OHCI driver implementation


I started to add the USB OHCI routines to the boot manager test program as a driver. I was struggling for many hours with a mysteries bug. Finally I fixed the bug (again). The bug was an old "friend". Elmar, just set the device as PCI bus master! Rolling eyes! That was the problem. That hurts. Okay, now I can continue with the driver stuff. There are still tests and a stable workflow required to implement a dynamic driver loading. The OHCI routines have to be tested in various CPU modes too. Its time for a Pizza...


2018-07-06  -  Minor updates


I finished only a few things. INT 13h hook for drive swapping works fine. I extended the FAT read support to FAT12 and FAT32.


2018-06-18  -  FAT16, Linux Kernel, NTLDR


No update since one month. What happened? Nothing special. Just some booting. But don't expect too much!

FAT16 reading works fine. I can change directories and read files. FAT16 writing and FAT12/32 support is left to do. But with the FAT16 reading support, I was able to do some interesting things.

Native Linux Kernel booting works (from FAT16). I can load the kernel and an initrd file and boot Linux. I can also set the Linux Kernel Command Line.

Native Windows XP booting with direct loading of the NTLDR works (from FAT16). More recent Windows booting should work too. That's not an important feature, but nice to have.

MBR loading and booting works too.


What comes next? There are still a lot of things to do. I am far away from any beta testing. Many things that are working are splitted up in own parts and have to put together. But this comes later.

Next steps are

• Boot sector loading and booting. That should not be difficult.
• Writing various loaders to start the Boot Manager Test Program from different locations (MBR, boot sector, floppy, CDROM, ...).
• FAT16 write support.
• FAT12/32 support.
• Some INT 13h hooks for testing. For example drive swapping to boot from the second hard disk.
• Trying to add the USB drivers carefully.
• Looking forward to Ext and NTFS drivers.
That's a heavy to-do list for the next steps!


2018-05-07  -  Are you dreaming in hex?


Maybe sometimes! Hexadecimal is part of my life. File Allocation Table Artwork :)

Dreaming in hex

I started with FAT file system support. Currently required for native Linux kernel loading tests. The boot manager will need FAT support too. I began with FAT16. Directory listing works. Of course with long file name support (optional only 8.3 format). Cluster reading works too. Next step is a working "read file" routine. And then modify the code for FAT12 and FAT32.


2018-05-03  -  MBR Partition Table / GUID Partition Table


The Master Boot Record partition table support has been finished. Classic and cascaded extended partitions are supported. Now, I am numbering the partitions in the same way as Linux. Primary partitions get a number from 1 to 4, according to the position in the partition table. The first logical partition starts with 5.

I also wrote the support for GUID Partition Tables (GPT).

All various partitions are accessed by the same shared ReadSector/WriteSector function call. It works very well :)


2018-04-28  -  Drive access layer


I did some code cleanup and various fixes. I also added a layer to access various drives with the same function call. Now it doesn't matter if its a DVD drive or a hard disk (floppy is not done yet). The drives are registered during PATA/SATA enumeration. I also added a simple support for the classic MBR to access primary partitions. The partitions are registered too and can be also accessed by a shared function call. Full MBR support and GPT support will be implemented on Monday/Thursday.

Read boot sector of partition 1 from drive 3.
Note: Drive number and partition number starts with "0".

1
2
3
4
5
6
7
8
9
10
11
12
    push dword 512
call MEM_Allocate
jc .error
mov dword [.buffer], eax

push eax
push word 1
push dword 0
push word 0
push word 2
call PReadSector28 ; (word drive_number, word partition_number, dword lba, word num_sectors, dword buffer)
jc .error


Drive registration. Using wrapper functions for standardized calls. Dynamic registering for USB drives is not done yet.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    M_PrintfNL "SATA device found."

push word ATA_CMD_IDENTIFY
push esi
call AHCI_Identify ; (dword port_address, word identify_command)
jc .check_for_atapi
mov [.identify], eax

; Register drive
push esi
push word 0
push word 0
push dword AHCI_Write28Wrapper
push dword AHCI_Read28Wrapper
push word 512
push dword [.identify]
push word DRIVE_SATA
call RegisterDrive ; (word drive_type, dword identify, word bytes_per_sector,
; dword read_sector_28, dword write_sector_28,
; word pata_channel, word pata_drive,
; dword ahci_port)

Current drive register routine

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
;=====================================
;dword RegisterDrive (word drive_type, dword identify, word bytes_per_sector,
; dword read_sector_28, dword write_sector_28,
; word pata_channel, word pata_drive,
; dword ahci_port)
;-------------------------------------
;Returns drive structure address
;Carry on error
;=====================================
RegisterDrive:
M_Vars

M_Arg drive_type, S_WORD
M_Arg identify , S_DWORD

M_Arg bytes_per_sector, S_WORD

M_Arg read_sector_28 , S_DWORD
M_Arg write_sector_28, S_DWORD

M_Arg pata_channel, S_WORD
M_Arg pata_drive , S_WORD

M_Arg ahci_port, S_DWORD

M_Local drive, S_DWORD

M_Code
push ebx
push edi

mov dword [.drive], 0

; Allocate memory for the drive structure
push dword SYS_DRIVE.size
call MEM_Allocate
jc .error

mov edi, eax ; edi became the drive address
mov [.drive], eax

; Fill the structure
mov word [fs:edi + SYS_DRIVE.wType], SYS_TYPE_DRIVE

mov bx, [.drive_type]
mov [fs:edi + SYS_DRIVE.wSubType], bx

mov ebx, [.identify]
mov [fs:edi + SYS_DRIVE.dIdentify], ebx

mov bx, [.bytes_per_sector]
mov [fs:edi + SYS_DRIVE.wBytesPerSector], bx


mov ebx, [.read_sector_28]
mov [fs:edi + SYS_DRIVE.dReadSector28], ebx

mov ebx, [.write_sector_28]
mov [fs:edi + SYS_DRIVE.dWriteSector28], ebx


mov bx, [.pata_channel]
mov [fs:edi + SYS_DRIVE.wChannel], bx

mov bx, [.pata_drive]
mov [fs:edi + SYS_DRIVE.wDrive], bx

mov ebx, [.ahci_port]
mov [fs:edi + SYS_DRIVE.dAHCI_Port], ebx

call GetFreeDriveNumber
jc .error
mov [fs:edi + SYS_DRIVE.bDriveNumber], al


; Add the drive to the drives list
mov ebx, SYS_RAM
add ebx, SYS_KERNEL.dDrives

push edi
push ebx
call LIST_AddEntry ; (dword list, dword entry)
jc .error

; Return drive address
mov eax, edi
jmp .done

.error:
; Release allocated memory
push dword [.drive]
call MEM_Free

; Set carry for error
stc

.done:
pop edi
pop ebx
M_Ret


2018-04-19  -  ATAPI CDROM drive drivers


The ATAPI drivers for IDE (PATA) and AHCI (SATA) for CDROM (and similar) drives are almost done. There is a strange behavior with the AHCI ATAPI driver. The first ATAPI command ends in an error. After this, all tested ATAPI commands are working fine. At the moment, I have no idea why the first command fails.

Drivers tested only on two machines.
BIOS INT 13h implementation is not done.


2018-03-28  -  Relocate addresses for program/driver loading


For long time, nothing important happened. Now, I spent two days for a simple address relocation system which is needed to support dynamic loading of programs and drivers.

I wrote two PHP scripts which are analyzing the list file, generated by NASM with the '-l' parameter.

The first PHP script (syscalls.php) generates a file with jumps to the kernel system functions (syscalls.inc). This generated file is included by the program/driver (my_program.asm) to make it easy to call the kernel functions. NASM generates all addresses according to the ORG command. Those addresses must be updated when the program/driver has been loaded into the memory.

The second PHP script (relocate.php) creates a file with two tables (relocate_table.inc). This tables are holding the positions of all addresses used by the program/driver. This file has to be included too.

The addresses, which are now stored in the header of the program, are updated by a simple routine in the kernel (relocation code), before the kernel can start the program.

Here is an overview with source codes. It may change in the future. It is just the first version. Maybe it looks difficult, but I tried to keep it simple. Explaining is not my strength.


Sample code to load a program:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
    ; Allocate memory for the program                
push dword [.file_size]
call MEM_Allocate
jc .error

mov [.address], eax

; Load the program
push dword [.address]
push dword [.file_size]
push dword [.file_name]
call SYS_LoadFile
jc .error

; Update addresses
push dword [.address]
call PROGRAM_AddressRelocate

; Start the program
call dword [.address]


Simple program header:

1
2
3
4
5
6
7
8
9
10
11
struc PROGRAM_HEADER                                 

.jump resb 5
.align_bytes resb 3

.reloc_table_syscalls_size resd 1
.reloc_table_local_size resd 1

.reloc_table_syscalls:

endstruc


Address relocation code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
;=====================================
;void PROGRAM_AddressRelocate (dword program_address)
;=====================================
PROGRAM_AddressRelocate:
M_Vars
M_Arg program_address, S_DWORD

M_Code
push ebx
push ecx
push esi
push edi

; Address of the relocation table.
mov esi, [.program_address]
add esi, PROGRAM_HEADER.reloc_table_syscalls

; Get number of syscall addresses.
mov ebx, [.program_address]
mov ecx, [ebx + PROGRAM_HEADER.reloc_table_syscalls_size]
shr ecx, 2 ; We have 4 byte addresses, so divide with 4.
je .skip_syscall_addr ; Skip if we have no address.

.relocate_syscall_addr_loop:
; Get the address in the program.
mov edi, [esi]

; All syscall addresses are lower than the program address.
; Substract the program memory address to restore the kernel address.
sub dword [ebx + edi], ebx

; Next entry.
add esi, 4
dec ecx
jne .relocate_syscall_addr_loop

.skip_syscall_addr:

; The table with the program addresses comes directly after the syscall table,
; there is no need to set ESI.

; Get number of program addresses.
mov ecx, [ebx + PROGRAM_HEADER.reloc_table_local_size]
shr ecx, 2 ; We have 4 byte addresses, so divide with 4.
je .skip_program_addr ; Skip if we have no address.

.relocate_program_addr_loop:
; Get the address in the program.
mov edi, [esi]

; All addresses have to be set relative to the new memory address of the program.
; Add the program memory address.
add dword [ebx + edi], ebx

; Next entry.
add esi, 4
dec ecx
jne .relocate_program_addr_loop

.skip_program_addr:

pop edi
pop esi
pop ecx
pop ebx
M_Ret


Sample syscalls.inc:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
; 0000003D MEM_Allocate:                             
MEM_Allocate:
jmp 0000003Dh

; 000000FE MEM_AllocateAligned:
MEM_AllocateAligned:
jmp 000000FEh

;----------- SNIP ---------------

; 00000FCC PrintHex16p:
PrintHex16p:
jmp 00000FCCh

; 00000FFC PrintHex16:
PrintHex16:
jmp 00000FFCh

; 0000100F PrintHex32:
PrintHex32:
jmp 0000100Fh

; 00001021 PrintInt8:
PrintInt8:
jmp 00001021h


Sample program (my_program.asm):
Command: nasm -f bin my_program.asm -o my_program.bin -l my_program.lst

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
%include "sys32/sys32.inc"

%define STRING_END 0
%include "macro/printf.inc"

[ORG 0h]
; Simple program header
jmp start ; Initial jump
db 0, 0, 0 ; Align bytes

%include "relocate_table.inc"

%include "syscalls.inc"

var1 dw 3344h ; Sample variable

;======================
; Program start
;======================
start:

; Use a kernel function
push word [var1]
call PrintHex16p

; Start a function of the program
call TestRoutine

; End program
ret


TestRoutine:

; Use kernel system print
M_PrintfNL "Test"

; Use another system call
mov ax, [var2]
call PrintHex16

ret

var2 dw 2244h ; Sample variable


Simple PHP script to export kernel function calls (syscalls.php):
Command: php syscalls.php kernel.lst > syscalls.inc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<?php
/*
    Generate jump instructions for kernel system calls.
    Source file is the list file generated by NASM with -l.

    Written by Elmar Hanlhofer 2018/03/28
    Free to use.
    
    Using: php syscalls.php kernel.lst > syscalls.inc
*/
    
if (!$argv[1])
    {
        die (
"No input file!");
    }

    
$f file ($argv[1]);

    foreach (
$f as $v)
    {
        
$v str_replace ("\n"""rtrim ($v));

        
$line_nr substr ($v07);
        
$addr    trim (substr ($v78));
        
$opcode  substr ($v1619);
        
$asm     trim (substr ($v40));

        if (
strpos ($asm":") && ($asm[0] == strtoupper ($asm[0]))) // Use only labels which have 
                                                                     // an upper char at the beginning
        
{
            
$label $asm;
        }

        if (
strpos ($opcode"<") !== false)
        {
            unset (
$label);
        }

        if (
$addr && $label)
        {
            if (
strpos (" .;%"$label[0]) === false// Skip various
            
{
                echo 
"; $addr $label\n";
                echo 
"$label\n";
                echo 
"    jmp $addr"h" "\n\n";
            }
            unset (
$label);
        }

    }

    echo 
"SYSCALLS_End:\n\n";

// Sample input:
//    87                              <1> MEM_Allocate:
//    93 0000003D C8040000            <1>     M_Code

?>


Simple PHP script to create the relocation table (relocate.php):
Command: php relocate.php my_program.lst > relocate_table.inc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
<?php
/*
    Generate the relocation address table.
    Source file is the list file generated by NASM with -l.

    Written by Elmar Hanlhofer 2018/03/28
    Free to use.
    
    Using: php relocate.php my_program.lst > relocate_table.inc
*/


define ("SYSCALLS_END""SYSCALLS_End:"); // Marker, written by syscalls.php

function TableEntry ($code_addr$opcode$char_begin$char_end$address_size)
{
    if (
$offset_addr strpos ($opcode$char_begin)) // Is there an address in the opcode?
    
{
        
$end  strpos ($opcode$char_end);
        
$size $end $offset_addr 1;
        if (
$size == $address_size// Is it the requested size?
        
{
            echo 
"    dd 0$code_addr"h + " . ($offset_addr 2) . "\n"// OPCODE COMMAND + POSITION OF ADDRESS
                                                                            // div 2 because 1 byte is 2 chars
        
}
    }
}


    if (!
$argv[1])
    {
        die (
"No input file!"); 
    }
    
    
$f file ($argv[1]);
    
    echo 
"RelocateTableSize_Syscalls dd RelocateTableEnd_Syscalls - RelocateTableStart_Syscalls\n";
    echo 
"RelocateTableSize_Local    dd RelocateTableEnd_Local    - RelocateTableStart_Local\n\n";

    echo 
"RelocateTableStart_Syscalls:\n";
    foreach (
$f as $v)
    {
        
$v str_replace ("\n"""rtrim ($v));
        
        
$line_nr substr ($v07);
        
$addr    trim (substr ($v78));
        
$opcode  substr ($v1619);
        
$asm     substr ($v40);

        if (
$asm == SYSCALLS_END// End of syscalls reached?
        
{
            break;
        }

        
// Build the table for the syscall addresses
        
TableEntry ($addr$opcode"("")"8);
        
TableEntry ($addr$opcode"[""]"8);       
    }
    echo 
"RelocateTableEnd_Syscalls:\n\n";
    

    
$syscalls true;
    echo 
"RelocateTableStart_Local:\n";
    foreach (
$f as $v)
    {
        
$v str_replace ("\n"""rtrim ($v));
        
        
$line_nr substr ($v07);
        
$addr    trim (substr ($v78));
        
$opcode  substr ($v1619);
        
$asm     substr ($v40);

        if (
$asm == SYSCALLS_END// End of syscalls reached?
        
{
            
$syscalls false;
        }
        
        if (!
$syscalls// Build the table for program addresses
        
{        
            
TableEntry ($addr$opcode"("")"8);
            
TableEntry ($addr$opcode"[""]"8);
        }
    }
    echo 
"RelocateTableEnd_Local:\n";

?>


2017-12-29  -  NASM Helper


At the beginning of the new boot manager development, I wrote some macros to make the use of function calls easier in Assembler. The macros are written for NASM. Now, I released them under the name "NASM Helper".

NASM Helper

At the bottom of the page, you will find a complex routine called QueueControlTransfer. Its from my OHCI USB driver. I know, its useless without the other functions, but its a nice example for a more complex function.


2017-12-20


OHCI Enumeration bug fixed.

Rewriting UHCI code done.


2017-12-18  -  Bug killed


I found the bug, without converting the old code. I figured out that the host suddenly stopped sending frames. Very mysterious. Finally I found the reason for this behavior. Unintentionally, I set the USB port into suspend mode. I used "OR" to write a bit, without modifying the other bits, in the port register. But for this register, its required to set the bit with "MOV" without other bits set. The strange thing is, that the "OR" works on other hardware, which seem to be more tolerant in this case. This bug wasted a lot of time, but it works now. Now there is a new issue with the enumeration process on that machine, but it should not be difficult to fix it.

Asking again, is the code from 2007 better? No, the new code is better now :)


2017-12-16  -  Hmm, bugs


Hmm, what should I say. I hoped to have finished a lot of things. But I didn't. I was ill in November. Then I had various things to do in the rest of November and in December. And now I am struggeling with a crazy "new boot manager" driver bug since a week. Its the OHCI USB driver. I thought it works fine, but then I used it on my old Gericom Webboy Laptop. A simple USB resquest ends in a DeviceNotResponding error. The frustrating thing is, my driver of 2007 works flawless. I cannot figure out whats wrong. Data structures and register values are the same. Frustrating. I am not able to fix that for one week!!!! The old code was written for LZASM. Now I am using NASM. Since days I try to find the bug without converting the old code to NASM. But I fear, I reached the point to accept that I have to convert the old code to find the difference....

Is the code from 2007 better? Hmmm, yes and no.


2017-10-13  -  What do I have so far


Its time for a development status.

The code is written in pure assembler. I am using NASM. The goal is to operate in various CPU modes on i386 CPUs and better. Most of the code is currently tested in the 'unreal mode' (16/32 bit). With just a few modifications, the code will run in native 32 bit too. This code will also run fine on 64 bit CPUs.

The device access (except video mode switching) happens native without BIOS. This is required to work in various CPU modes in the same way, regardless if I have a BIOS in the background or not. Why do I need various CPU modes? Because I want to support old and modern computers. DOS should be able to use the boot manager drivers without additional software. But don't dream about DOS and UEFI. This will not work.

Basic system routines

Memory management: Done.
PCI device enumeration: Done.
CPU mode switching: Done.
Basic text mode output routines: Done.
Graphic mode (VBE): Mode detection, initialization, pixel drawing, text drawing done.
Image files: Reading and display TIFF images done. TIFF format: uncompressed, RGB, Intel.

Driver development stage 1

Keyboard PS/2: Key read done.
PATA (IDE) HDD: Read and write.
PATA (IDE) optical drives: Not done.
SATA AHCI HDD: Read and write.
SATA AHCI optical drives: Not done.
Classic floppy drive: Not done.
USB 1.1 UHCI: Most done, but I am unhappy with the code. I have to rewrite the most.
USB 1.1 OHCI: Initialization, control transfers, interrupt transfers, bulk transfers, USB device enumeration done. Some things are left to do.
USB 2.0 EHCI: Initialization, control transfers, bulk transfers, USB device enumeration done. Lets say over 50% is done. Difficult things like split transactions and other things are left to do.
USB 3.x: Not started.
USB Keyboard: Detection and key read works. TODO: Key mapping.
USB Mass Storage: Basic functions like device identify works. This implementation shouldn't be a big deal.
USB HUB: Starting in the next days.

What means development stage 1? In this stage the drivers are working in their own environment. But its too early to put them together.


2017-10-06  -  A driver development adventure


Last week I started to write the USB 2.0 EHCI driver from scratch. Everything looked fine and worked as expected, but then I tried it with VirtualBox. You know, the Plop Boot Manager 5.0.x hangs when you use the USB 2.0 EHCI driver to boot from USB in VirtualBox. I tried my new code and ........... it hangs too.

I said okay, I try to figure out whats wrong. I am motivated and I want to fix this problem. Then I struggled with the problem for one week. It was frustrating. The queue heads haven't been processed. Only malformed queue heads resulted in a transaction error. But nothing happened on correct queue heads with correct transfer descriptors. For some time I thought the port reset is the problem and the USB device is in a problematic state. You have to know, in VirtualBox, the port reset ends immediately after starting the reset. According to the EHCI Specification, the reset has to be ended by the software and not the host. Then I thought that the host cannot transmit to device 0 because the USB device is still configured with an address because of the strange port reset behavior. So I created queue heads for every possible device number. Hmmmm, I received no errors and no transactions. Nothing! When there is no response, then its really frustrating.

Accepting that my code does not work in VirtualBox became an option for me. But finally I can not accept it. Meanwhile it looks like I am in an endless loop. Doing the same things with the same disappointing result. Then by luck, I made a mistake. And now comes an important information for those who plan to write an EHCI driver. As first transfer descriptor, I linked a transfer descriptor without any data except the 'Next qTD Pointer' to a SETUP transfer descriptor. And suddenly, the SETUP transfer descriptor has been processed as expected. Strange. When the first transfer descriptor is empty, then the following transfer descriptors are processed.

I don't know why, but this works on other EHCI controllers too, so I accept that and I am happy that my code works now also in VirtualBox. I will fix the EHCI driver of the Plop Boot Manager 5.0.15 that the USB 2.0 boot works also in VirtualBox. But thats enough for today.


2017-09-17  -  UEFI


I spent some time for UEFI and created a simple menu to boot Plop Linux and Windows with UEFI. This was just a funny test. There is no dynamic OS detection or config file. All is hard coded, just to see how software development with UEFI works.


2017-07-12


Programming the new boot manager, but it's a slow process. Nothing to show at the moment...


2017-02-12


New development start is April 2017.


2016-07-29


My desk. Developing a driver at night.

During rewriting the USB drivers, I found some bugs in the old code. The chances are good, that I release a 5.1 version of the old 5.0.15 boot manager with fixed USB drivers. But who knows...


2016-06-28


No news, no time to update this page. Coding has been stop at beginning of 05/2016. Maybe I find time in august 2016.


2016-04-22


Continue coding :)


2016-03-14


Coding paused because of other work.


2016-03-13


I created a concept art of the GUI. The final product will look different, but this could be a nice design. No line of code has been written for the GUI, booting has priority ;) A release date is far far away.

There will be also a hidden mode and a simple text mode interface like in the current Plop Boot Manager.


2016-02-02


Work in progress...



© 2018 by Elmar Hanlhofer
This page was last modified on 20/09/2018.