EzDevInfo.com

grub interview questions

Top grub frequently asked interview questions

Error 13: Invalid or unsupported executable while booting simple kernel in grub with string literal

I've written a simple kernel that tries to write two characters to the frame buffer.

If I define a string literal in the kernel, I get the following output when it boots:

  Booting 'os'                                                                  

kernel /boot/kernel.elf                                                         

Error 13: Invalid or unsupported executable format                              

Press any key to continue... 

Otherwise, if I define two characters I get the following (note 'ab' at the start of the output):

abBooting 'os'                                                                  

kernel /boot/kernel.elf                                                      
   [Multiboot-elf, <0x100000:0x201:0x0>, <0x101000:0x0:0x1000>,     shtab=0x102168, 
   entry=0x1001f0]

loader

I wrote the loader in assembly:

global loader                   ; the entry symbol for ELF

MAGIC_NUMBER equ 0x1BADB002     ; define the magic number constant
FLAGS        equ 0x0            ; multiboot flags
CHECKSUM     equ -MAGIC_NUMBER  ; calculate the checksum
                                ; (magic number + checksum + flags should equal 0)
KERNEL_STACK_SIZE equ 4096      ; size of stack in bytes

section .text:                  ; start of the text (code) section
align 4                         ; the code must be 4 byte aligned
    dd MAGIC_NUMBER             ; write the magic number to the machine code,
    dd FLAGS                    ; the flags,
    dd CHECKSUM                 ; and the checksum

loader:                         ; the loader label (defined as entry point in linker script)
    mov eax, 0xCAFEBABE         ; place the number 0xCAFEBABE in the register eax

    mov esp, kernel_stack + KERNEL_STACK_SIZE   ; point esp to the start of the
                                                ; stack (end of memory area)
    extern run  
    call run

.loop:
    jmp .loop                   ; loop forever

section .bss
align 4                         ; align at 4 bytes
kernel_stack:                   ; label points to beginning of memory
    resb KERNEL_STACK_SIZE          ; reserve stack for the kernel

The kernel is written in c

#include "io.h"
#include "fb.h"

void run()
{   
    // try writing message to port
    char* c = (char *) 10000;
    c[0] = 'a';
    c[1] = 'b';

    fb_write(c, 2);  // this does not cause the error

    // fb_write("ab",2); // this line would cause the error
}

External headers

There are two external headers. One for IO ports called io.h and one for writing to the frame buffer called fb.h

Here is io.h and the implementation io.s

io.h:

#ifndef INCLUDE_IO_H
#define INCLUDE_IO_H

/** outb:
 *  Sends the given data to the given I/O port. Defined in io.s
 *
 *  @param port The I/O port to send the data to
 *  @param data The data to send to the I/O port
 */
void outb(unsigned short port, unsigned char data);

#endif /* INCLUDE_IO_H */

io.s:

global outb     ; make the label outb visible outside this file

; outb - send a byte to an I/O port
; stack: [esp + 8] the data byte
;        [esp + 4] the I/O port
;        [esp    ] return address
outb:
    mov al, [esp + 8]
    mov dx, [esp + 4]
    out dx, al
    ret

fb.h

#include "io.h"

// FRAME BUFFER ================================

// Text colors
#define FB_BLACK        0
#define FB_BLUE         1
#define FB_GREEN        2
#define FB_CYAN         3
#define FB_RED          4
#define FB_MAGENTA      5
#define FB_BROWN        6
#define FB_LT_GREY      7
#define FB_DARK_GREY    8
#define FB_LT_BLUE      9
#define FB_LT_GREEN    10
#define FB_LT_CYAN     11
#define FB_LT_RED      12
#define FB_LT_MAGENTA  13
#define FB_LT_BROWN    14
#define FB_WHITE       15

// IO PORTS
#define FB_COMMAND_PORT 0x3D4
#define FB_DATA_PORT    0x3D5

// IO PORT COMMANDS
#define FB_HIGH_BYTE_COMMAND    14 // move cursor command low
#define FB_LOW_BYTE_COMMAND     15 // move cursor command high


/** fb_write_cell:
 *  used to write a character to a cell in the framebuffer
 *
 * param i which cell to write to
 * param c the ascii char to write
 * param fg foreground color
 * param bf background color
 */
void fb_write_cell(unsigned int i, char c, unsigned char fg, unsigned char bg);


/** fb_move_cursor:
 *  used to move the cursor within the frame buffer
 *
 *  param pos position within frame buffer to move cursor to
 */
void fb_move_cursor(unsigned short pos);


/** fb_write:
 *  write some text to the cursor
 *
 *  param buf pointer to character string
 *  param len length of string to write
 */
int fb_write(char *buf, unsigned int len);

fb.c

#include "fb.h"

void fb_write_cell(unsigned int i, char c, unsigned char fg, unsigned char bg)
{
    char *fb = (char *) 0x000B8000;
    fb[i*2] = c;
    fb[i*2 + 1] = ((fg & 0x0F) << 4) | (bg & 0x0F);
}

void fb_move_cursor(unsigned short pos) {
    outb(FB_COMMAND_PORT, FB_HIGH_BYTE_COMMAND);
    outb(FB_DATA_PORT, ((pos>>8) & 0x00FF));
    outb(FB_COMMAND_PORT, FB_LOW_BYTE_COMMAND);
    outb(FB_DATA_PORT, pos & 0x00FF);
}

int fb_write(char *buf, unsigned int len) {

    unsigned int i = 0;
    for(i = 0; i < len; i++) {
        fb_write_cell(i, buf[i], FB_BLACK, FB_WHITE);
    }

    return 0;

}

Building it

I have a linker script called link.ld and a Makefile. I'm using gcc cross compiler for i386-elf That I compiled using this guide (http://wiki.osdev.org/GCC_Cross-Compiler).

ENTRY(loader)                /* the name of the entry label */

SECTIONS {
    . = 0x00100000;          /* the code should be loaded at 1 MB */

    .text ALIGN (0x1000) :   /* align at 4 KB */
    {
        *(.text)             /* all text sections from all files */
    }

    .rodata ALIGN (0x1000) : /* align at 4 KB */
    {
        *(.rodata*)          /* all read-only data sections from all files */
    }

    .data ALIGN (0x1000) :   /* align at 4 KB */
    {
        *(.data)             /* all data sections from all files */
    }

    .bss ALIGN (0x1000) :    /* align at 4 KB */
    {
        sbss = .;
        *(COMMON)            /* all COMMON sections from all files */
        *(.bss)              /* all bss sections from all files */
        ebss = .;


    }
}

And here is my makefile

OBJECTS = io.o fb.o loader.o kmain.o
#CC = gcc
CC = /home/albertlockett/opt/cross/bin/i386-elf-gcc
CFLAGS = -m32 -nostdlib -nostdinc -fno-builtin -fno-stack-protector \
         -nostartfiles -nodefaultlibs -Wall -Wextra -Werror -c
LDFLAGS = -T link.ld -melf_i386
AS = nasm
ASFLAGS = -f elf

all: kernel.elf

kernel.elf: $(OBJECTS)
    ld $(LDFLAGS) $(OBJECTS) -o kernel.elf

os.iso: kernel.elf
    cp kernel.elf iso/boot/kernel.elf
    genisoimage -R                              \
                -b boot/grub/stage2_eltorito    \
                -no-emul-boot                   \
                -boot-load-size 4               \
                -A os                           \
                -input-charset utf8             \
                -quiet                          \
                -boot-info-table                \
                -o os.iso                       \
                iso

run: os.iso
    bochs -f bochsrc.txt -q

%.o: %.c
    $(CC) $(CFLAGS)  $< -o $@

%.o: %.s
    $(AS) $(ASFLAGS) $< -o $@

clean:
    rm -rf *.o kernel.elf os.iso

Run it

The makefile builds an iso from the contents of a directory called iso. That folder contains a preconfigured version of grub that I got here (https://github.com/littleosbook/littleosbook/blob/master/files/stage2_eltorito) and a menu.lst file for grub

menu.lst:

default=0
timeout=0

title os
kernel /boot/kernel.elf

contents of iso directory:

iso
`-- boot
    |-- grub
    |   |-- menu.lst
    |   `-- stage2_eltorito
    `-- kernel.elf

The iso image boots in bochs. Here is my bochsrc.txt file

megs:            32
display_library: term
romimage:        file=/usr/share/bochs/BIOS-bochs-latest
vgaromimage:     file=/usr/share/bochs/VGABIOS-lgpl-latest
ata0-master:     type=cdrom, path=os.iso, status=inserted
boot:            cdrom
log:             bochslog.txt
clock:           sync=realtime, time0=local
cpu:             count=1, ips=1000000
com1:            enabled=1, mode=file, dev=com1.out

Does anyone know why the string literal in the kernel file produces the error when I try to boot the iso?


Source: (StackOverflow)

Does GRUB switch to protected mode?

I would like to ask if it is GRUB that switch the CPU to protected mode during boot up or is it the Linux kernel that does it. And also I would like to ask - is the kernel itself (vmlinuz) an ELF or is it plain binary format? Thanks.


Source: (StackOverflow)

Advertisements

grub_script.yy.c:2354:13: error: 'yy_fatal_error' defined but not used

When building the latest grub2 (2.00) I get this error.

I have tried adding -Wno-unused-function to both HOST_CFLAGS, HOST_CPPFLAGS, TARGET_CPPFLAGS and TARGET_CFLAGS in the Makefile. I even tried deleting that function whilst make was running!

Unfortunately the error remains.


Source: (StackOverflow)

if statements in grub2 script always evaluate to true

I'm trying to write a grub2 bootloader script but if statements always evaluate to true:

if [ -s blabla ] ; then set zzz0="1" ; fi
if [ ! -s blabla ] ; then set zzz1="1" ; fi

set TEST_VAR=foo

if [ "x${TEST_VAR}" = "xfoo" ] ; then set zzz2="1" ; fi
if [ "x${TEST_VAR}" = "xbar" ] ; then set zzz3="1" ; fi

if [ $TEST_VAR = foo ] ; then set zzz4="1" ; fi
if [ $TEST_VAR = bar ] ; then set zzz5="1" ; fi

So, after running this script, I see all zzz (zzz0, zzz1, zzz2, zzz3, zzz4, zzz5)variables set to 1. What am I doing wrong?

Thanks, Johnny


Source: (StackOverflow)

One time boot into Read Only?

I'm trying to boot into read only mode to test some software. I don't want to remount a drive after booting as that would not meet the requirements to test the software which checks the file system at boot.

Is there a way to do this without editing grub.conf? Preferably adding something via the grub UI when interrupting boot?

If I do edit the grub.conf to boot in read only, how am I supposed to edit it back?


I understand that the kernel mounts root as RO but it's remounted as RW later in the boot process.


Source: (StackOverflow)

Custom code with GRUB?

Can I run some some custom code at the time when GRUB loads up? In other words does GRUB provide a facility to run some custom code before loading any operating system?


Source: (StackOverflow)

Grub 2 not detecting Multiboot header in kernel

I'm having an issue with Grub 2 (and QEMU's -kernel) not detecting the Multiboot v1 header in my kernel. I have the header in a separate section before .text.

linker.ld:

SECTIONS
{
    . = 1M;

    .multiboot ALIGN(4K) :
    {
        *(.multiboot)
    }

    .text ALIGN(4K) :
    {
        *(.text)
    }

    [snip]

boot.s (GNU as syntax):

.set MAGIC, 0x1badb002
.set FLAGS, (1<<0 | 1<<1) # align, provide mem map
.set CHECKSUM, -(MAGIC + FLAGS)

.section .multiboot
    .long MAGIC
    .long FLAGS
    .long CHECKSUM

.section .text
    [snip]

I have verified that the header section is being added as specified with the magic number:

kernel.bin:     file format elf32-i386

Contents of section .multiboot:
 101000 02b0ad1b 03000000 fb4f52e4           .........OR.    
Contents of section .text:
 [snip]

Yet Grub 2 says that the kernel does not have a valid Multiboot header, and using QEMU's -kernel option causes:

qemu: fatal: Trying to execute code outside RAM or ROM at 0x000a000

which seems to be an address in the BIOS-mapped range, not where Multiboot should be.

I've compared against the usual code in Bran's and OSDev (plus a previous kernel of mine) yet I can't seem to figure out what I'm doing wrong.


Source: (StackOverflow)

How are low-level graphical interfaces programmed? [closed]

Recently, I have been experimenting with things like arch Linux and this raised a few questions. I constantly see the use of graphics in very low level parts of an OS(things like the GRUB or almost all boot menus). Some of these even feature images. I can also see graphical manipulation in things like the "pacman" command, where the loading bar will change with out disturbing the text above it. Another example would be a program like cfdisk. I would just like to know how these types of features are programmed?

Edit: By this I mean what system calls are used to make this possible?

Boot menu


Source: (StackOverflow)

grubby fatal error: unable to find a suitable template

So I upgraded kernel yum -y update kernel on my AWS EC2 base image, and I get the following:

Running Transaction
  Installing : kernel-2.6.32-504.3.3.el6.x86_64
grubby fatal error: unable to find a suitable template

Here is the contents of /boot/grub/grub.conf:

default=0
timeout=0
hiddenmenu
title CentOS (2.6.32-358.el6.x86_64)
        root (hd0,0)
        kernel /boot/vmlinuz-2.6.32-358.el6.x86_64 ro root=LABEL=rootfs console=ttyS0
        initrd /boot/initramfs-2.6.32-358.el6.x86_64.img

So grub.conf is not getting updated, and since I already have kernel-2.6.32-504.1.3.el6.x86_64 installed, grub did not get updated the last time I updated kernel either. I tried adding the kernel manually:

grubby --grub --add-kernel="/boot/vmlinuz-2.6.32-504.3.3.el6.x86_64 ro root=LABEL=rootfs \
  console=ttyS0" --title="CentOS (2.6.32-504.3.3.el6.x86_64)" \
  --initrd=/boot/initramfs-2.6.32-504.3.3.el6.x86_64.img

and then /boot/grub/grub.conf looked like this:

default=0
timeout=0
hiddenmenu
title CentOS (2.6.32-504.3.3.el6.x86_64)
        kernel /vmlinuz-2.6.32-504.3.3.el6.x86_64 ro root=LABEL=rootfs console=ttyS0
        initrd /initramfs-2.6.32-504.3.3.el6.x86_64.img
title CentOS (2.6.32-358.el6.x86_64)
        root (hd0,0)
        kernel /boot/vmlinuz-2.6.32-358.el6.x86_64 ro root=LABEL=rootfs console=ttyS0
        initrd /boot/initramfs-2.6.32-358.el6.x86_64.img

However, /vmlinuz-2.6.32-504.3.3.el6.x86_64 is not the kernel I entered. So I removed that and tried again with:

grubby --grub --add-kernel="/boot/boot/vmlinuz-2.6.32-504.3.3.el6.x86_64 ro root=LABEL=rootfs \
  console=ttyS0" --title="CentOS (2.6.32-504.3.3.el6.x86_64)" \
  --initrd=/boot/boot/initramfs-2.6.32-504.3.3.el6.x86_64.img

which resulted in this:

timeout=0
default=1
hiddenmenu
title CentOS (2.6.32-504.3.3.el6.x86_64)
        kernel /boot/vmlinuz-2.6.32-504.3.3.el6.x86_64 ro root=LABEL=rootfs console=ttyS0 root=(hd0,0)
        initrd /boot/initramfs-2.6.32-504.3.3.el6.x86_64.img
title CentOS (2.6.32-358.el6.x86_64)
        root (hd0,0)
        kernel /boot/vmlinuz-2.6.32-358.el6.x86_64 ro root=LABEL=rootfs console=ttyS0
        initrd /boot/initramfs-2.6.32-358.el6.x86_64.img

At this point, I manually edited /boot/grub/grub.conf to default=0 and rebooted, and my EC2 wouldn't boot. So I tried a new instance copy and got all these same errors, so I copied the existing settings to a new entry:

default=0
timeout=0
hiddenmenu
title CentOS (2.6.32-504.3.3.el6.x86_64)
        root (hd0,0)
        kernel /boot/vmlinuz-2.6.32-504.3.3.el6.x86_64 ro root=LABEL=rootfs console=ttyS0
        initrd /boot/initramfs-2.6.32-504.3.3.el6.x86_64.img

And rebooted, and it fails to boot again. Yet another try, I repeated the above but with root=/dev/xvda3, and that failed to boot as well. So at this point, I have no way at all of upgrading my kernel. What do I do?


UPDATE: I figured out the /boot/boot/ stuff, and my /boot/grub/grub.conf now looks like this:

default=0
timeout=0
hiddenmenu
title CentOS (2.6.32-504.3.3.el6.x86_64)
        root (hd0,0)
        kernel /vmlinuz-2.6.32-504.3.3.el6.x86_64 ro root=LABEL=rootfs console=ttyS0
        initrd /initramfs-2.6.32-504.3.3.el6.x86_64.img

And I can successfully boot my system, however everything else about this remains true: installing a new kernel still results in "grubby fatal error: unable to find a suitable template", and grubby --default-kernel still results in no output. I have to edit my /boot/grub/grub.conf manually for any kernel update.


Source: (StackOverflow)

Compiling kernel to a binary file on mac

I was following these tutorials to make a simple kernel that I would then load using GRUB. The instructions for compiling didn't work (ld couldn't find the -T option) and when I finally got a compiled file it was in Macho format. What are the correct steps to take when compiling these files on Mac.
Edit:
I compiled the code on an Ubuntu virtual machine and I so I have the kernel.bin file. Now how can I make a bootable image that runs the kernel?


Source: (StackOverflow)

Booting a non-multiboot kernel with GRUB2 [closed]

I want to boot a custom kernel (non-multiboot) with GRUB2, I've read that I need grub.cfg like this:

menuentry "custom kernel" {
    set root=(hd0,0)
    chainloader +1
}

So, I have some questions:

  1. How grub detect kernel? (with multiboot spec I used kernel /boot/kernel.bin)
  2. How my kernel must look like (sorry for my bad english)? Must it be 512 bytes at all (like custom bootloader, which loaded into 0x7c00)?
  3. (hd0,0) is hard drive partition and what I must put if I use CD? Maybe (cdrom0,0)?
  4. To boot Linux kernel we can use linux command, can I use it to boot my custom kernel (with some changes)?
  5. Will Grub enter Protected mode or not?

Source: (StackOverflow)

Generating an iso from Kernel built with GRUB/NASM/C

I was following along with this series of articles, and on the last page, he linked an iso image of the kernel that he produced. He doesn't mention this in the series, so that's my question... how do I generate an iso image from my kernel executable?


Source: (StackOverflow)

How does GRUB's stage 1 boot loader loads the stage 2 bootloader?

From the past week I am puzzled with the question that how the grub first stage boot loader which is only 446 bytes is able to search for the second stage, when the second stage is in a complex file system! How does it locate the second stage?

When a complex partitioning scheme of windows and linux is in place, and the linux system is entirely in the extended partition, then how does the stage 1 finds the stage 2? Even stage 1.5?

All of the grub tutorials skim through this important part. I have searched though the internet but couldn't find anything that explains this. Sadly, I am not an assembly programmer.

I want to understand the boot process intricately in terms of which sectors of the hard disk are tickled (and roughly how) during bootup. *Please point me to a good resource or answer here. It will greatly help me to play with grub wisely.*

Some Resources Searched:

  1. How Linux Works : What every superuser should know by Brian Ward
  2. http://www.dedoimedo.com/computers/grub.html
  3. some past stackoverflow questions.

Source: (StackOverflow)

Where does code of GRUB stage 1.5 reside on disk and what is the address it is loaded?

I have grub v1.98 installed and after disassembling the MBR I find the following code snippet that I don't understand:

xor ax,ax
mov [si+0x4],ax
inc ax
mov [si-0x1],al
mov [si+0x2],ax
mov word [si],0x10
mov ebx,[0x7c5c]
mov [si+0x8],ebx
mov ebx,[0x7c60]
mov [si+0xc],ebx
mov word [si+0x6],0x7000
mov ah,0x42
int 0x13

It seems this piece of code tries to set up disk address of stage 1.5 code, then load and run it. However, how could I figure out which physical block it tries to read? What's more, what is the destination of the stage 1.5 code? 0x7000?

I refer to MBR for Windows 7, where subsequent boot up code is loaded 0x7c00. Given MBR is first loaded at address 0x7c00, it contains a piece of code copying MBR from 0x7c00 to 0x0600 and then branch to 0x0600 in case the original code corrupted. Will loading stage 1.5 code to address 0x7000 conflict the original code? What's more, I also find:

jmp short 0x65
nop
sar byte [si+0x7c00],1
mov es,ax
mov ds,ax
mov si,0x7c00
mov di,0x600
mov cx,0x200
cld
rep movsb
push ax
push word 0x61c
retf

at the beginning of the MBR. It seems the code tries to do the same thing as in MBR of windows 7 to copy the original MBR from 0x7c00 to 0x0600, except for the first jmp instruction. Will these codes in fact executed? If yes, when will control jumps here.(I believe the answer is YES, but am confused by the leading jmp).


Source: (StackOverflow)

How do I programmatically create a bootable CD?

I'm using a barebones tutorial as the basis for an OS I'm working on, and it seems to be an older tutorial: it has be compiling the kernel down to a floppy image, and then loading it with GRUB.

Basically, I still want to use GRUB, but I'd like to have my OS run from a CD instead. The main reason is that I don't actually have a real floppy drive available (I'm testing in VirtualBox currently) and I thus have no way to test my OS on real hardware.

I've been poking around on the net, and I can find lots of utilities that create a bootable CD from a floppy image, but these all seem to require an actual floppy drive, plus it's not really what I'm looking for. I'd like to be able to end up with a bootable CD during my make step ideally, without needing to first place the image on a floppy, which seems rather pointless.

I guess the easy way to answer this: How do I set up GRUB to read my kernel image from a CD? Will I need a special utility to do this from Windows? (The kernel can't compile itself yet, that's not for a looong while)

Thanks!


Source: (StackOverflow)