error: no multiboot header found - bare-metal

This day found something that caught my attention. is build a simple bare OS
i read how to make multiboot compliant, I'm using NASM and GCC, i need make a loader that has the multiboot header and call the main point of my system for that i have two files loader.asm and loader.ld
loader.asm
[BITS 32]
global start
start:
mov esp, _sys_stack
jmp stublet
ALIGN 4
mboot:
MBOOT_PAGE_ALIGN equ 1<<0
MBOOT_MEMORY_INFO equ 1<<1
MBOOT_HEADER_MAGIC equ 0x1BADB002
MBOOT_HEADER_FLAGS equ MBOOT_PAGE_ALIGN | MBOOT_MEMORY_INFO
MBOOT_CHECKSUM equ -(MBOOT_HEADER_MAGIC + MBOOT_HEADER_FLAGS)
; This is the GRUB Multiboot header. A boot signature
dd MBOOT_HEADER_MAGIC
dd MBOOT_HEADER_FLAGS
dd MBOOT_CHECKSUM
stublet:
EXTERN cmain
call cmain
jmp $
SECTION .bss
resb 8192
_sys_stack:
loader.ld
ENTRY(start)
phys = 0x00100000;
SECTIONS
{
.text phys : AT(phys) {
code = .;
*(.text)
*(.rodata)
. = ALIGN(4096);
}
.data : AT(phys + (data - code))
{
data = .;
*(.data)
. = ALIGN(4096);
}
.bss : AT(phys + (bss - code))
{
bss = .;
*(.bss)
. = ALIGN(4096);
}
end = .;
}
main.c
int GenyKernel_Main()
{
char *str = "Hello world!", *ch;
unsigned short *vidmem = (unsigned short*) VIDEO_MEMORY;
unsigned i;
for (ch = str, i = 0; *ch; ch++, i++) {
vidmem[i] = (unsigned char) *ch | 0x0700;
}
return 0;
}
for build i'm using
# loader.o
nasm -f elf64 -o loader.o loader.asm
# main.o
gcc -fno-stack-protector -fno-builtin -nostdinc -O -g -Wall -I. -c -o main.o main.c
and the finally link
ld -T loader.ld -o kernel loader.o main.o
I've built a simple iso with grub-mkrescue and run with qemu but always I get
I think the problem is in the file loader.ld but i can't found where

After read lots about the same .asm file i finally understood the problem, the following snippet
align 4
multiboot_header:
dd MBOOT_MAGIC
dd MBOOT_FLAGS
dd MBOOT_CHECKSUM
must exist below a section to include appropriately with the linker
section .text ; .multiboot o whatever
align 4
multiboot_header:
dd MBOOT_MAGIC
dd MBOOT_FLAGS
dd MBOOT_CHECKSUM
and in the linker script
ENTRY(your_entry_point)
SECTIONS
{
. = 0x00100000;
.text ALIGN(0x1000) :
{
*(.multiboot)
*(.text)
}
// rest of sections
}

Related

How to avoid warning [-Wpointer-sign] of SvPV() versus utf8n_to_uvchr() - bug of XS?

This is the relevant part of XS, which should convert an Perl string from UTF-8 to codepoints (unsigned 32-bit integers):
UV *
text2UV (SV *sv, STRLEN *lenp)
{
STRLEN len;
// char *str = SvPV(foo_sv, strlen);
// char *s = SvPV (sv, len); // This original version warns
U8 *s = (U8 *)SvPV (sv, len); // This casts without warning
UV *r = (UV *)SvPVX (sv_2mortal (NEWSV (0, (len + 1) * sizeof (UV))));
UV *p = r;
if (SvUTF8 (sv))
{
STRLEN clen;
while (len)
{
// UV utf8_to_uvchr_buf(const U8 *s, const U8 *send, STRLEN *retlen)
*p++ = utf8n_to_uvchr (s, len, &clen, 0);
if (clen < 0)
croak ("illegal unicode character in string");
s += clen;
len -= clen;
}
}
else
while (len--)
*p++ = *(unsigned char *)s++;
*lenp = p - r;
return r;
}
It throws this warning:
~/github/perl/Text-Levenshtein-BVXS$ make
cp BVXS.pm blib/lib/Text/Levenshtein/BVXS.pm
Running Mkbootstrap for BVXS ()
chmod 644 "BVXS.bs"
"/Users/helmut/perl5/perlbrew/perls/perl-5.32.0/bin/perl" -MExtUtils::Command::MM -e 'cp_nonempty' -- BVXS.bs blib/arch/auto/Text/Levenshtein/BVXS/BVXS.bs 644
"/Users/helmut/perl5/perlbrew/perls/perl-5.32.0/bin/perl" "/Users/helmut/perl5/perlbrew/perls/perl-5.32.0/lib/5.32.0/ExtUtils/xsubpp" -typemap '/Users/helmut/perl5/perlbrew/perls/perl-5.32.0/lib/5.32.0/ExtUtils/typemap' BVXS.xs > BVXS.xsc
mv BVXS.xsc BVXS.c
cc -c -I. -fno-common -DPERL_DARWIN -mmacosx-version-min=10.14 -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -I/opt/local/include -DPERL_USE_SAFE_PUTENV -O3 -DVERSION=\"0.01\" -DXS_VERSION=\"0.01\" "-I/Users/helmut/perl5/perlbrew/perls/perl-5.32.0/lib/5.32.0/darwin-2level/CORE" BVXS.c
BVXS.xs:26:35: warning: passing 'char *' to parameter of type 'const U8 *' (aka 'const unsigned char *') converts between pointers to integer types with different sign [-Wpointer-sign]
*p++ = utf8n_to_uvchr (s, len, &clen, 0);
^
/Users/helmut/perl5/perlbrew/perls/perl-5.32.0/lib/5.32.0/darwin-2level/CORE/utf8.h:74:54: note: expanded from macro 'utf8n_to_uvchr'
utf8n_to_uvchr_error(s, len, lenp, flags, 0)
^
/Users/helmut/perl5/perlbrew/perls/perl-5.32.0/lib/5.32.0/darwin-2level/CORE/utf8.h:76:45: note: expanded from macro 'utf8n_to_uvchr_error'
utf8n_to_uvchr_msgs(s, len, lenp, flags, errors, 0)
^
/Users/helmut/perl5/perlbrew/perls/perl-5.32.0/lib/5.32.0/darwin-2level/CORE/inline.h:1781:36: note: passing argument to parameter 's' here
Perl_utf8n_to_uvchr_msgs(const U8 *s,
^
1 warning generated.
rm -f blib/arch/auto/Text/Levenshtein/BVXS/BVXS.bundle
cc -mmacosx-version-min=10.14 -bundle -undefined dynamic_lookup -L/usr/local/lib -L/opt/local/lib -fstack-protector-strong BVXS.o -o blib/arch/auto/Text/Levenshtein/BVXS/BVXS.bundle \
\
It works and passes my tests. But if I want to deliver it to CPAN the distribution should not throw warnings.
Decode it with own code in C would be a work-around (and faster).
For me it looks like a bug in the XS macros and/or the example in the documentation are wrong.
The interplay of U8 and char in the API is a bit weird. You might ask #p5p to see why it works that way.
Failing that, though, would some plain typecasting suppress the warnings? Is this in a public repository somewhere?
Aside: SvPV is evil. Its prevalence in XS modules causes quite a lot of pain. Avoid it when possible. See: https://dev.to/fgasper/perl-s-svpv-menace-5515
Update: This looks to be a case where it’s necessary to break the abstraction. Alas.

How to change a mac address using the command line parameters in the linux kernel

I want to change a mac address at the u-boot level like the following.
# setenv bootargs 'console=ttyAMA0,115200n8 root=/dev/ram0 rw initrd=0x40000000 ethaddr=${ethaddr}'
# setenv ethaddr 11:22:33:44:55:66
# saveenv
And at the driver,
static unsigned char my_ethaddr[MAX_ADDR_LEN];
/* need to get the ether addr from armboot */
static int __init ethaddr_setup(char *line)
{
char *ep;
int i;
printk("command line : %s\n", line);
memset(my_ethaddr, 0, MAX_ADDR_LEN);
/* there should really be routines to do this stuff */
for (i = 0; i < 6; i++)
{
my_ethaddr[i] = line ? simple_strtoul(line, &ep, 16) : 0;
if (line)
line = (*ep) ? ep+1 : ep;
printk("mac[%d] = 0x%02Xn", i, my_ethaddr[i]);
}
return 0;
}
__setup("ethaddr=", ethaddr_setup);
When booting, the log message is like following.
[ 0.000000] Kernel command line: console=ttyAMA0,115200n8 root=/dev/ram0 rw initrd=0x40000000 ethaddr=${ethaddr}
[ 0.000000] command line : ${ethaddr}
[ 0.000000] mac[0] = 0x00, mac[1] = 0x00, mac[2] = 0x0E, mac[3] = 0x00, mac[4] = 0xDD, mac[5] = 0x00
The command line message is ${ethaddr}, is it right?
The mac address isn't correct.
How can I fix it?
You are using single quotes in:
setenv bootargs '... ethaddr=${ethaddr}'
so ${ethaddr} is not expanded and the bootargs variable contains the literal string ethaddr=${ethaddr}, which is then passed into the kernel and is what you see in your debug output. See the U-Boot documentation on How the Command Line Parsing Works for more details.
You could use double quotes, or no quotes at all, in which case ${ethaddr} would be expanded when assigning to bootargs, although you would need to set it first:
# setenv ethaddr 11:22:33:44:55:66
# setenv bootargs console=ttyAMA0,115200n8 root=/dev/ram0 rw initrd=0x40000000 ethaddr=${ethaddr}
# printenv bootargs
bootargs=console=ttyAMA0,115200n8 root=/dev/ram0 rw initrd=0x40000000 ethaddr=11:22:33:44:55:66
Note that in some systems the ethaddr variable is used by U-Boot itself to configure the MAC address of the first network device, and the Linux network driver may continue to use that address, so you don't need to explicitly pass it into the kernel. See the documentation on U-Boot Environment Variables.
In addition U-Boot may be configured to prevent modification of the ethaddr variable, although that's probably not the case here because when it is U-Boot prints the error message:
Can't overwrite "ethaddr"

Segfault when running hello world shellcode in C program

sorry if this question sounds dumb but I am very new to shellcoding and I was trying to get a hello world example to work on a 32 bit linux machine.
As this is shellcoding, I used a few tricks to remove null bytes and shorten the code. Here it is:
section .data
section .text
global _start
_start:
;Instead of xor eax,eax
;mov al,0x4
push byte 0x4
pop eax
;xor ebx,ebx
push byte 0x1
pop ebx
;xor ecx,ecx
cdq ; instead of xor edx,edx
;mov al, 0x4
;mov bl, 0x1
mov dl, 0x8
push 0x65726568
push 0x74206948
;mov ecx, esp
push esp
pop ecx
int 0x80
mov al, 0x1
xor ebx,ebx
int 0x80
This code works fine when I compile and link it with the following commands:
$ nasm -f elf print4.asm
$ ld -o print4 -m elf_i386 print4.o
However, I tried running it within the following C code:
$ cat shellcodetest.c
#include
#include
char *shellcode = "\x04\x6a\x58\x66\x01\x6a\x5b\x66\x99\x66\x08\xb2\x68\x68\x68\x65\x69\x48\x54\x66\x59\x66\x80\xcd\x01\xb0\x31\x66\xcd\xdb\x80";
int main(void) {
( *( void(*)() ) shellcode)();
}
$ gcc shellcodetest.c –m32 –z execstack -o shellcodetest
$ ./shellcodetest
Segmentation fault (core dumped)
Could someone please explain what is happening there? I tried running the code in gdb and noticed something weird happening with esp. But as I said before, I still lack experience to really understand what is going on here.
Thanks in advance!
Your shellcode does not work, because it is not entered in the correct endianness. You did not state how you extracted the bytes from the file print4, but both objdump and xxd gives the bytes in correct order.
$ xxd print4 | grep -A1 here
0000060: 6a04 586a 015b 99b2 0868 6865 7265 6848 j.Xj.[...hherehH
0000070: 6920 7454 59cd 80b0 0131 dbcd 8000 2e73 i tTY....1.....s
$ objdump -d print4
print4: file format elf32-i386
Disassembly of section .text:
08048060 <_start>:
8048060: 6a 04 push $0x4
8048062: 58 pop %eax
8048063: 6a 01 push $0x1
...
The changes you need to do is to swap the byte order, '\x04\x6a' -> '\x6a\x04'.
When I run your code with this change, it works!
$ cat shellcodetest.c
char *shellcode = "\x6a\x04\x58\x6a\x01\x5b\x99\xb2\x08\x68\x68\x65\x72\x65\x68\x48\x69\x20\x74\x54\x59\xcd\x80\xb0\x01\x31\xdb\xcd\x80";
int main(void) {
( *( void(*)() ) shellcode)();
}
$ gcc shellcodetest.c -m32 -z execstack -o shellcodetest
$ ./shellcodetest
Hi there$

GRUB error 13: invalid or unsupported executable format on custom kernel

I am trying to learn OS Dev and I started building my own kernel based on The Little book about OS Development.
When I loaded the kernel using bochs GRUB complains with:
error 13: invalid or unsupported executable format
The files I'm using:
loader.s
global loader
MAGIC_NUMBER equ 0xBADB002
FLAGS equ 0x0
CHECKSUM equ -MAGIC_NUMBER
section .text
align 4
dd MAGIC_NUMBER
dd FLAGS
dd CHECKSUM
loader:
mov eax, 0xCAFEBABE
.loop:
jmp .loop
link.ld
ENTRY(loader)
SECTIONS
{
. = 0x00100000;
.text ALIGN (0x1000) :
{
*(.text)
}
.rodata ALIGN (0x1000) :
{
*(.rodata*)
}
.data ALIGN (0x1000) :
{
*(.data)
}
.bss ALIGN (0x1000) :
{
*(COMMON)
*(.bss)
}
}
bochsrc.txt
megs: 32
display_library: sdl
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
menu.lst
default=0
timeout=0
title First OS
kernel /boot/kernel.elf
commands to execute:
nasm -f elf32 loader.s
ld -T link.ld -melf_i386 loader.o -o 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
bochs -f bochsrc.txt
My files structure is like this:
os_dev
|--(rest of the files)
|--iso
|-- boot
|-- kernel.elf
|-- grub
|-- menu.lst
|-- stage2_eltorito
The file stage2_eltorito was downloaded from https://github.com/littleosbook/littleosbook/blob/master/files/stage2_eltorito
Michael Petch noticed that B. Kostas was using an incorrect Magic Number for Grub Legacy.
Changing MAGIC_NUMBER equ 0xBADB002 in loader.s to MAGIC_NUMBER equ 0x1BADB002 solved the issue.

Eclipse Makefile Error

I need some help with solving an error. I was trying to create a simple bluetooth server using the library bluez-5.31 . I am using eclipse on Raspbian Jessie which is similar to Debian but I have little to no experience with either one. I tried fixing it for a couple days now and nothing seems to be working so i really need some help...
This is the error description:
error 1: make:*** [Bluetooth Server 2]Error 1 Resource: Bluetooth Server 2
error 2: recipe for target 'Bluetooth Server 2' failed Resource: makefile Path: /Bluetooth Server 2/Debug Location: line 45
where "Bluetooth Server 2" is the name of the project[/code]
This is main:
#include "/usr/include/stdint.h"
#include "/usr/include/bluez-5.31/lib/bluetooth.h"
#include "/usr/include/bluez-5.31/lib/hci.h"
#include "/usr/include/bluez-5.31/lib/hci_lib.h"
#include "/usr/include/bluez-5.31/lib/rfcomm.h"
int main(int argc, char **argv)
{
struct sockaddr_rc loc_addr = { 0 }, rem_addr = { 0 };
char buf[1024] = { 0 };
int s, client, bytes_read;
unsigned int opt = sizeof(rem_addr);
//allocate socket
s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
//bind socket to port 1 of the first available adapter
bdaddr_t tmp = {0,0,0,0,0,0};
loc_addr.rc_family = AF_BLUETOOTH;
loc_addr.rc_bdaddr = tmp;
loc_addr.rc_channel = 1;
bind(s, (struct sockaddr* )&loc_addr, sizeof(loc_addr));
//put socket into listening mode
listen(s, 1);
//accept one connection
client = accept(s, (struct sockaddr *)&rem_addr, &opt);
ba2str( &rem_addr.rc_bdaddr, buf );
fprintf( stderr, "accepter connection from %s\n", buf);
memset( buf, 0, sizeof(buf));
//read data from the client
bytes_read = recv(client, buf, sizeof(buf), 0);
if( bytes_read > 0 )
{
printf("received [%s]\n", buf);
}
//close connection
//close(client);
//close(s);
return 0;
}
This is the make file:
-include ../makefile.init
RM := rm -rf
# All of the sources participating in the build are defined here
-include sources.mk
-include src/subdir.mk
-include subdir.mk
-include objects.mk
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(strip $(C++_DEPS)),)
-include $(C++_DEPS)
endif
ifneq ($(strip $(C_DEPS)),)
-include $(C_DEPS)
endif
ifneq ($(strip $(CC_DEPS)),)
-include $(CC_DEPS)
endif
ifneq ($(strip $(CPP_DEPS)),)
-include $(CPP_DEPS)
endif
ifneq ($(strip $(CXX_DEPS)),)
-include $(CXX_DEPS)
endif
ifneq ($(strip $(C_UPPER_DEPS)),)
-include $(C_UPPER_DEPS)
endif
endif
-include ../makefile.defs
# Add inputs and outputs from these tool invocations to the build variables
# All Target
all: Bluetooth\ Server\ 2
# Tool invocations
Bluetooth\ Server\ 2: $(OBJS) $(USER_OBJS)
#echo 'Building target: $#'
#echo 'Invoking: GCC C++ Linker'
g++ -L/usr/include/ -bluez-5.31 -o "Bluetooth Server 2" $(OBJS) $(USER_OBJS) $(LIBS)
#echo 'Finished building target: $#'
#echo ' '
# Other Targets
clean:
-$(RM) $(OBJS)$(C++_DEPS)$(C_DEPS)$(CC_DEPS)$(CPP_DEPS)$(EXECUTABLES)$(CXX_DEPS)$(C_U PPER_DEPS) "Bluetooth Server 2"
-#echo ' '
.PHONY: all clean dependents
.SECONDARY:
-include ../makefile.targets
And this is what changes i made to project properties:
- C/C++ Build >> Settings >> Tool Settings >> GCC C++ Linker >> Miscellaneous: In the linker flags box i wrote: "-bluez-5.31"
- C/C++ Build >> Settings >> Tool Settings >> GCC C++ Linker >> Libraries: Added " "bluez-5.31" " in -l
- C/C++ Build >> Settings >> Tool Settings >> GCC C++ Linker >> Libraries: Added " /usr/include " in -L