Pascal Bare Bones: Difference between revisions

m
Bot: Replace deprecated source tag with syntaxhighlight
[unchecked revision][unchecked revision]
No edit summary
m (Bot: Replace deprecated source tag with syntaxhighlight)
 
(8 intermediate revisions by 4 users not shown)
Line 9:
 
=== stub.asm ===
<sourcesyntaxhighlight lang="asm">
;/////////////////////////////////////////////////////////
;// //
Line 89:
KERNEL_STACK:
resb KERNEL_STACKSIZE
</syntaxhighlight>
</source>
 
=== kernel.pas ===
<sourcesyntaxhighlight lang="pascal">
{
/////////////////////////////////////////////////////////
Line 163:
 
end.
</syntaxhighlight>
</source>
 
=== console.pas ===
<sourcesyntaxhighlight lang="pascal">
{
/////////////////////////////////////////////////////////
Line 314:
 
end.
</syntaxhighlight>
</source>
 
=== multiboot.pas ===
<sourcesyntaxhighlight lang="pascal">
unit multiboot;
 
Line 373:
 
end.
</syntaxhighlight>
</source>
 
=== system.pas ===
Since fpc-3.2.0 there was added necessary parts (in code block that part was highlighted by comment lines), because without them developer could met error like:
<source lang="pascal">
<syntaxhighlight lang="bash">
system.pas(18,1) (system) Parsing implementation of SYSTEM
system.pas(18,1) Fatal: Internal type "TEXCEPTADDR" was not found. Check if you use the correct run time library.
Fatal: Compilation aborted
</syntaxhighlight>
Valid version of '''system.pas''' on 2022/12/29:
<syntaxhighlight lang="pascal">
unit system;
 
{$MODE FPC}
 
interface
 
type
cardinal = 0..$FFFFFFFF;
hresult = cardinal;
dword = cardinal;
integer = longint;
 
pchar = ^char;
 
{ That part comes from fpc 3.2.0 as nessesary}
TTypeKind = (tkUnknown, tkInteger, tkChar, tkEnumeration, tkFloat, tkSet,
tkMethod, tkSString, tkLString, tkAString, tkWString, tkVariant, tkArray,
tkRecord, tkInterface, tkClass, tkObject, tkWChar, tkBool, tkInt64, tkQWord,
tkDynArray, tkInterfaceRaw, tkProcVar, tkUString, tkUChar, tkHelper, tkFile,
tkClassRef, tkPointer);
 
jmp_buf = packed record
rbx, rbp, r12, r13, r14, r15, rsp, rip: QWord;
{$IFDEF win64}
rsi, rdi: QWord;
xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15: record
m1, m2: QWord;
end;
 
mxcsr: LongWord;
fpucw: word;
padding: word;
{$ENDIF win64}
end;
 
Pjmp_buf = ^jmp_buf;
PExceptAddr = ^TExceptAddr;
TExceptAddr = record
buf: Pjmp_buf;
next: PExceptAddr;
{$IFDEF CPU16}
frametype: SmallInt;
{$ELSE CPU16}
frametype: LongInt;
{$ENDIF CPU16}
end;
 
PGuid = ^TGuid;
TGuid = packed record
case Integer of
1:
(Data1: DWord;
Data2: word;
Data3: word;
Data4: array [0 .. 7] of byte;
);
2:
(D1: DWord;
D2: word;
D3: word;
D4: array [0 .. 7] of byte;
);
3:
( { uuid fields according to RFC4122 }
time_low: DWord; // The low field of the timestamp
time_mid: word; // The middle field of the timestamp
time_hi_and_version: word;
// The high field of the timestamp multiplexed with the version number
clock_seq_hi_and_reserved: byte;
// The high field of the clock sequence multiplexed with the variant
clock_seq_low: byte; // The low field of the clock sequence
node: array [0 .. 5] of byte; // The spatially unique node identifier
);
end;
 
{ --- End of nessesary part --- }
 
implementation
 
end.
</syntaxhighlight>
</source>
 
=== Linker script ===
linker.script
<sourcesyntaxhighlight lang="c">
ENTRY(kstart)
SECTIONS
Line 428 ⟶ 500:
end = .; _end = .; __end = .;
}
</syntaxhighlight>
</source>
 
=== Compiling and Linking the modules ===
Assemble stub.asm with:
<sourcesyntaxhighlight lang="bash">nasm -f elf32 stub.asm -o stub.o</sourcesyntaxhighlight>
 
* -f elf32 - needed ''exact'' under x86_64 systems to make correct object file
 
The Pascal modules with:
<sourcesyntaxhighlight lang="bash">fpc -Aelf -n -O3 -Op3 -Si -Sc -Sg -Xd -CX -XXs -Pi386 -Rintel -Tlinux kernel.pas</sourcesyntaxhighlight>
 
* -Aelf - instructs the internal fpc assembler to output an ELF object.;
Line 451 ⟶ 523:
* -Pi386 - tells the compiler to force i386 mode (actual for x86_64 host systems)
* -Rintel - sets the inline assembly syntax to intel style;
* -Tlinux - specifies that the target operating system is Linux. (Don'tProvides evena ask!sensible system unit to use)
 
Then link the whole thing with:
<sourcesyntaxhighlight lang="bash">i386-elf-ld --gc-sections -s -Tlinker.script -o kernel.obj stub.o kernel.o multiboot.o system.o console.o</sourcesyntaxhighlight>
 
* --gc-sections -s, in combination with -CX -XXs above, eliminates RTTI symbols from resulting binary
 
In case of trouble linking under x86_64 system try this line:
<sourcesyntaxhighlight lang="bash">i686-elf-ld -A elf-386 --gc-sections -s -Tlinker.script -o kernel.obj stub.o kernel.o multiboot.o system.o console.o</sourcesyntaxhighlight>
 
'''Special sutuation''': last time after building '''binutils''' I've got error
<syntaxhighlight lang="bash">
i386-linux-ld --gc-sections -s -Tlinker.script -o kernel.obj stub.o kernel.o multiboot.o console.o system.o
ld: i386 architecture of input file `stub.o' is incompatible with i386:x86-64 output
ld: i386 architecture of input file `kernel.o' is incompatible with i386:x86-64 output
ld: i386 architecture of input file `multiboot.o' is incompatible with i386:x86-64 output
ld: i386 architecture of input file `console.o' is incompatible with i386:x86-64 output
ld: i386 architecture of input file `system.o' is incompatible with i386:x86-64 output
make: *** [Makefile:27: _LD] Error 1
</syntaxhighlight>
That type of error can encounter if ''i386-linux-ld'' have wrong content. In my situation file content edited to:
<syntaxhighlight lang="bash">
#!/bin/bash
/full/path/to/compiled/cross/binutils/ld-new -A elf32-i386 $@
</syntaxhighlight>
 
=== makeiso.sh ===
Also a good option is create a bootable ISO file to make run it with VirtualBox or qemu:
 
<sourcesyntaxhighlight lang="bash">
#!/bin/sh
TMPISO=iso
Line 484 ⟶ 572:
grub-mkrescue --output=pascal-kernel.iso iso
rm -rf $TMPISO
</syntaxhighlight>
</source>
 
And simple run:
<sourcesyntaxhighlight lang="bash">qemu-system-i386 pascal-kernel.iso</sourcesyntaxhighlight>
 
=== Alternative compiling: Makefile ===
 
Accumulating the lines from previous part we can make a '''Makefile''':
<syntaxhighlight lang="bash">
# Freepascal BareboneOS
# Makefile
# 2019
# by: furaidi <iluatitok@gmail.com>
# License: Public domain
 
NASMPARAMS = -f elf32 -o stub.o
LDPARAMS = -A elf32-i386 --gc-sections -s -Tlinker.script -o kernel.obj
FPCPARAMS = -Aelf -n -O2 -Op3 -Si -Sc -Sg -Xd -CX -XXs -Pi386 -Rintel -Tlinux
TMPISO = iso
TMPBOOT = $(TMPISO)/boot
TMPGRUB = $(TMPBOOT)/grub
TMPCFG = $(TMPGRUB)/grub.cfg
 
objects = stub.o kernel.o multiboot.o console.o system.o
 
_FPC:
@echo 'Compile kernel'
fpc $(FPCPARAMS) kernel.pas
 
_NASM:
@echo 'Compile stub'
nasm $(NASMPARAMS) stub.asm
 
_LD:
@echo 'Link them together'
i386-linux-ld $(LDPARAMS) $(objects)
 
all: _FPC _NASM _LD
 
install:
mkdir $(TMPISO)
mkdir $(TMPBOOT)
mkdir $(TMPGRUB)
cp kernel.obj $(TMPBOOT)/kernel.obj
echo 'set timeout=0' > $(TMPCFG)
echo 'set default =0' >> $(TMPCFG)
echo '' >> $(TMPCFG)
echo 'menuentry "Pascal Bare" {' >> $(TMPCFG)
echo ' multiboot /boot/kernel.obj' >> $(TMPCFG)
echo ' boot' >> $(TMPCFG)
echo '}' >> $(TMPCFG)
grub-mkrescue --output=pascal-kernel.iso $(TMPISO)
rm -rf $(TMPISO)
 
clean:
rm -rf $(TMPISO)
rm -f *.o
rm -f *.ppu
 
</syntaxhighlight>
 
==Further Steps==
After when bare bones are ready and tested, you'd probably want to go with a few ways separately or combine:
* Add terminal workaround. Pure *nix way like changing terminals, built-in commands, simple user management
* Add graphic interface from start. That is Windows NT family way. You need to add SVGA-like drivers and/or mouse input and everything you need (or thinks so)
Also you may want to adapt *nix libraries such as '''binutils''', make build target for compiling your fpc programs for your new os like ''i386-myos''. From that point you are on your own.
 
==See Also==
===External Links===
* https://github.com/torokernel/torokernel/wiki/Writing-Drivers-In-Freepascal, notes about how to write drivers by using the Frepascal language.
* https://wiki.freepascal.org/System_unit, a tutorial to write a simple system unit
 
[[Category:Bare bones tutorials]]