Gujin: Difference between revisions

145 bytes added ,  21 days ago
m
add section argument to maintenance template
[unchecked revision][unchecked revision]
m (add section argument to maintenance template)
 
(5 intermediate revisions by 4 users not shown)
Line 1:
{{You}}
Gujin is a GPLed [[bootloader]] for the PC.
 
Line 14 ⟶ 15:
Same for interrupts, Gujin switches to protected mode but does not re-enable interrupts, that is the job of the kernel being booted to set-up the Interrupt Decriptor Table and handle each interrupts, because BIOS will not help the kernel any more.
 
Gujin can also relocate the ELF file if it contains relocation information, see option [http://sourceware.org/binutils/docs-2.19/ld/Options.html#index-g_t_002d_002demit_002drelocs-79 --emit-relocs] of the "ld" linker of the "binutilsBinutils" toolchain.
 
Because most applications will want to collect BIOS informations before the switch to protected mode, Gujin can call in real-mode a function of the ELF file, and if this function returns zero - continue the loading process - else display an error message (for instance: "trying to execute a 64 bits application on a processor without this feature!").
Line 26 ⟶ 27:
 
----
 
{{FirstPerson|section=1}}
 
So enough text description, let's try it!
Line 42 ⟶ 45:
 
Then, we reformat that dedicated USB stick as a bootable FAT filesystem, erasing all its content: first go in "root" by typing "su" or "sudo" (distribution dependant), then get the device name of you USB stick (let's say it is /dev/sdg) (sometimes /dev/mmcblk0 for SD cards), and type:
<syntaxhighlight lang="bash">
./gujin /dev/sdg --disk=BIOS:0x00,auto
./gujin /dev/sdg --disk=BIOS:0x00,auto
</syntaxhighlight>
Depending on the size of the USB stick, that will have created either a FAT16 or a FAT32 (or even a FAT12) filesystem, but that point is not really important.
 
Line 48 ⟶ 53:
 
To check that this filesystem is correctly created, you can type:
<syntaxhighlight lang="bash">
/sbin/fsck.vfat /dev/sdg
/sbin/fsck.vfat /dev/sdg
</syntaxhighlight>
 
With the Gujin installer parameters we used, that would have created a "superfloppy" format on our USB stick, that is currently the format most PC will be able to understand and boot from.
Line 70 ⟶ 77:
Then, we want to generate this ELF kernel - let's try to generate a "hello world":
Create a file with that content:
 
const char msg1[] = "Hello protected-mode text world! please reboot ...";
<syntaxhighlight lang="c">
#define STACKSIZE 64 * 1024
const char msg1[] = "Hello protected-mode text world! please reboot ...";
static unsigned stack[STACKSIZE / 4] __attribute__ ((aligned(32)));
#define STACKSIZE 64 * 1024
static unsigned stack[STACKSIZE / 4] __attribute__ ((aligned(32)));
void _start (void)
 
{
void _start (void)
/* We are flat non-paged memory and interrupt disabled */
{
asm (" mov %0,%%esp " : : "i" (&stack[STACKSIZE / 4]));
/* We are flat non-paged memory and interrupt disabled */
volatile unsigned short *video_array = (volatile unsigned short *)0xB8000;
asm (" mov %0,%%esp " : : "i" (&stack[STACKSIZE / 4]));
unsigned cpt1;
volatile unsigned short *video_array = (volatile unsigned short *)0xB8000;
unsigned cpt1;
video_array += 10 * 80; /* few empty lines */
 
/* We want blue background color and lightgray foreground, so 0x1700: */
video_array += 10 * 80; /* few empty lines */
for (cpt1 = 0; cpt1 < sizeof(msg1) - 1; cpt1++)
/* We want blue background color and lightgray foreground, so 0x1700: */
video_array[cpt1] = 0x1700 + msg1[cpt1];
for (cpt1 = 0; cpt1 < sizeof(msg1) - 1; cpt1++)
video_array[cpt1] = 0x1700 + msg1[cpt1];
while (1)
 
continue;
while (1)
}
continue;
}
</syntaxhighlight>
 
Then compile it like (you may need to add "-fno-stack-protector" too, distribution dependant):
<syntaxhighlight lang="bash">
$ gcc -m32 -Wall -O2 -s -static -nostartfiles -nodefaultlibs -Wl,-Ttext=0x110000 hello.c -o hello.elf
gcc -m32 -Wall -O2 -s -static -nostartfiles -nodefaultlibs -Wl,-Ttext=0x110000 hello.c -o hello.elf
</syntaxhighlight>
and compress it by:
<syntaxhighlight lang="bash">
$ gzip -9 hello.elf -c > hello.kgz
gzip -9 hello.elf -c > hello.kgz
</syntaxhighlight>
 
You just need to copy that hello.kgz file into the USB stick, and reboot with this USB stick, you will get a menu with "hello.kgz" displayed.
Line 115 ⟶ 129:
Just create a file which [http://www.mirrorservice.org/sites/download.sourceforge.net/pub/sourceforge/g/project/gu/gujin/gujin/2.8.2/gujin-2.8.2.tar.gz/gujin/hello_bios.c?extract=true contains]:
 
<syntaxhighlight lang="c">
/* hello_bios.c - public domain - no support whatsoever */
/* hello_bios.c - public domain - no support whatsoever */
 
/* Constant entry block, max 64 KB code+data+stack, do not touch: */
/* Constant entry block, max 64 KB code+data+stack, do not touch: */
asm (
asm (
" .code16gcc \n"
" .code16gcc \n"
" .section .init,\"ax\",@progbits \n"
" .globalsection _start .init,\"ax\",@progbits \n"
" .global "_start: \n"
"_start: \n"
// "int $3 # if debugging with borland td.exe, started by tiny.exe \n"
// "int $3 # if debugging with borland td.exe, started by tiny.exe \n"
" pushw %ds \n"
" pushw %esds \n"
" pushw %fses \n"
" pushw %gsfs \n"
" pushflpushw %gs \n"
" pushalpushfl \n"
" movwpushal %ss,%cs:1f+1 \n"
" movw %spss,%cs:2f1f+21 \n"
" movw %cssp,%ax cs:2f+2 \n"
" movw %axcs,%dsax \n"
" movw %ax,%esds \n"
" movw %ax,%fses \n"
" movw %ax,%gsfs \n"
" movw %ax,%ssgs \n"
" movlmovw $0%ax,%espss \n"
" cldmovl $0,%esp \n"
" calllcld main \n"
" movlcalll main %eax,%cs:3f+2 \n"
"1: movwmovl $0%eax,%ax cs:3f+2 \n"
"1: movw $0,%ax,%ss \n"
"2: movlmovw $0%ax,%espss \n"
"2: popalmovl $0,%esp \n"
" popflpopal \n"
" popwpopfl %gs \n"
" popw %fsgs \n"
" popw %esfs \n"
" popw %dses \n"
"3: movlpopw $0,%eaxds \n"
"3: lretwmovl $0,%eax \n"
" .previouslretw \n"
" .previous \n"
);
);
 
/* For information about asm() construct, see GCC manual:
/* For information about asm() construct, see GCC manual:
[http://gcc.gnu.org/onlinedocs/gcc-4.5.0/gcc/Extended-Asm.html http://gcc.gnu.org/onlinedocs/gcc-4.5.0/gcc/Extended-Asm.html]
[http://gcc.gnu.org/onlinedocs/gcc-4.5.0/gcc/Extended-Asm.html http://gcc.gnu.org/onlinedocs/gcc-4.5.0/gcc/Extended-Asm.html]
For information about BIOS services, see
For information about BIOS services, see
[http://stanislavs.org/helppc/ http://stanislavs.org/helppc/]
[http://stanislavs.org/helppc/ http://stanislavs.org/helppc/]
*/
*/
enum standard_color {
enum standard_color {
black, blue, green, cyan,
redblack, magentablue, brown green, lightgraycyan,
red, magenta, brown, lightgray,
darkgray, lightblue, lightgreen, lightcyan,
darkgray, lightblue, lightgreen, lightcyan,
lightred, lightmagenta, yellow, white
lightred, lightmagenta, yellow, white
};
};
 
/* This assumes 16 colors modes, text or graphic - i.e. not 256 colors: */
/* This assumes 16 colors modes, text or graphic - i.e. not 256 colors: */
static inline void
static inline void
VGA_writestring (const char *string, unsigned char row, unsigned char col)
VGA_writestring (const char *string, unsigned char row, unsigned char col)
{
{
unsigned short page_attribute = 16 * blue + lightgray, strlen_string;
unsigned short page_attribute = 16 * blue + lightgray, strlen_string;
const char *endstring = string;
const char *endstring = string;
 
/* We cannot rely on libc to provide strlen(): */
/* We cannot rely on libc to provide strlen(): */
while (*endstring)
while (*endstring++;)
strlen_string = endstring - string++;
strlen_string = endstring - string;
 
asm (
asm (
" xchgl %%ebp,%4 \n"
" xchgl %%ebp,%4 \n"
" int $0x10 # writestring \n"
" int $0x10 # writestring \n"
" xchgl %%ebp,%4 \n"
" xchgl %%ebp,%4 \n"
: : "a" (0x1301), "b" (page_attribute),
: : "ca" (strlen_string0x1301), "db" (((unsigned short)row << 8) | colpage_attribute),
"c" (strlen_string), "d" (((unsigned short)row << 8) | col),
"r" (string) /* in fact %es:%bp, but "B" (string) doesn't work */
"r" (string) /* in fact %es:%bp, but "B" (string) doesn't work */
);
);
}
}
 
static inline void BIOS_wait (unsigned nb_microsecond)
static inline void BIOS_wait (unsigned nb_microsecond)
{
{
unsigned short status;
unsigned short status;
 
/* Use volatile when there is at least one result, but even if the result
/* Use isvolatile notwhen used,there theis codeat hasleast toone beresult, insertedbut (statuseven isif the result): */
is not used, the code has to be inserted (status is the result): */
asm volatile (" int $0x15 "
asm volatile (" int $0x15 "
: "=a" (status)
: "=a" (status)
: "a" (0x8600), "d" (nb_microsecond & 0xFFFF), "c" (nb_microsecond >> 16)
: "a" (0x8600), "d" (nb_microsecond & 0xFFFF), "c" (nb_microsecond >> 16)
);
);
}
}
int main (void)
{
VGA_writestring ("Hello BIOS world! Please wait...\r\n", 0, 0);
BIOS_wait (3 * 1000 * 1000); /* 3 seconds before returning to Gujin*/
// return 0x80000000; /* to return to Gujin menu */
return 0xA0000000; /* to return to Gujin menu, do not display "press a key to continue" */
}
 
int main (void)
{
VGA_writestring ("Hello BIOS world! Please wait...\r\n", 0, 0);
BIOS_wait (3 * 1000 * 1000); /* 3 seconds before returning to Gujin*/
// return 0x80000000; /* to return to Gujin menu */
return 0xA0000000; /* to return to Gujin menu, do not display "press a key to continue" */
}
</syntaxhighlight>
 
And then compile it by:
<syntaxhighlight lang="bash">
$ gcc -m32 -Wall -Os -s -static -nostartfiles -nodefaultlibs -Wa,-R -Wl,--section-start,.init=0 hello_bios.c -o hello_bios.elf
gcc -m32 -Wall -Os -s -static -nostartfiles -nodefaultlibs -Wa,-R -Wl,--section-start,.init=0 hello_bios.c -o hello_bios.elf
</syntaxhighlight>
and compress it:
<syntaxhighlight lang="bash">
$ gzip -9 hello_bios.elf -c > hello_bios.kgz
gzip -9 hello_bios.elf -c > hello_bios.kgz
</syntaxhighlight>
you can copy this hello_bios.kgz to the USB stick and run it, I hope the different functions of the source file are obvious.