2 Commits

Author SHA1 Message Date
Enrico Fraccaroli 9cbc8e8a61 Merge branch 'develop' into feature/remove_nasm 2024-01-15 15:26:56 +01:00
Enrico Fraccaroli 13441daa37 First commit 2023-12-22 18:11:50 +01:00
52 changed files with 1005 additions and 1061 deletions
+68 -22
View File
@@ -61,6 +61,54 @@ else()
set(CMAKE_LINKER ld) set(CMAKE_LINKER ld)
endif() endif()
# Enable the assembly language.
enable_language(ASM)
# Find the NASM compiler.
find_program(ASM_COMPILER NAMES nasm HINTS /usr/bin/ /usr/local/bin/)
# Mark the variable ASM_COMPILER as advanced.
mark_as_advanced(ASM_COMPILER)
# Check that we have found the compiler.
if(NOT ASM_COMPILER)
message(FATAL_ERROR "ASM compiler not found!")
endif(NOT ASM_COMPILER)
# Set the assembly compiler flags.
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -m32")
# Warning flags.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wpedantic")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pedantic-errors")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wshadow")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99")
# Disable some specific warnings.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-function")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-variable")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unknown-pragmas")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-missing-braces")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-command-line-argument")
# Set the compiler options.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -static")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -nostdlib")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -nostdinc")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-builtin")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-stack-protector")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-pic")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fomit-frame-pointer")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=i686")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffreestanding")
if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 10)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fcommon")
endif()
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g3")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ggdb")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0")
elseif(CMAKE_BUILD_TYPE STREQUAL "Release")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3")
endif(CMAKE_BUILD_TYPE STREQUAL "Debug")
# ============================================================================= # =============================================================================
# COMPILATION # COMPILATION
# ============================================================================= # =============================================================================
@@ -135,8 +183,8 @@ set(EMULATOR_FLAGS ${EMULATOR_FLAGS} -drive file=${CMAKE_BINARY_DIR}/rootfs.img,
add_custom_target( add_custom_target(
qemu qemu
COMMAND test -e ${CMAKE_BINARY_DIR}/rootfs.img || ${CMAKE_COMMAND} -E cmake_echo_color --red "No filesystem file detected, you need to run: make filesystem" COMMAND test -e ${CMAKE_BINARY_DIR}/rootfs.img || ${CMAKE_COMMAND} -E cmake_echo_color --red "No filesystem file detected, you need to run: make filesystem"
COMMAND ${EMULATOR} ${EMULATOR_FLAGS} -kernel ${CMAKE_BINARY_DIR}/mentos/kernel-bootloader.bin COMMAND ${EMULATOR} ${EMULATOR_FLAGS} -kernel ${CMAKE_BINARY_DIR}/mentos/kernel_bootloader.bin
DEPENDS kernel-bootloader.bin DEPENDS kernel_bootloader.bin
) )
# ============================================================================= # =============================================================================
@@ -147,17 +195,17 @@ add_custom_target(
# executables. # executables.
add_custom_target( add_custom_target(
gdbinit gdbinit
BYPRODUCTS ${CMAKE_BINARY_DIR}/.gdbinit ${CMAKE_BINARY_DIR}/gdb.run BYPRODUCTS ${CMAKE_BINARY_DIR}/.gdbinit
# Create the generic gdb configuration. COMMAND bash ${CMAKE_SOURCE_DIR}/scripts/get_text_address.sh ${CMAKE_BINARY_DIR}/mentos/kernel.bin > ${CMAKE_BINARY_DIR}/.gdbinit
COMMAND echo "add-symbol-file ${CMAKE_BINARY_DIR}/mentos/kernel.bin" > ${CMAKE_BINARY_DIR}/.gdbinit COMMAND bash ${CMAKE_SOURCE_DIR}/scripts/get_text_address.sh ${CMAKE_BINARY_DIR}/mentos/kernel_bootloader.bin >> ${CMAKE_BINARY_DIR}/.gdbinit
COMMAND echo "add-symbol-file ${CMAKE_BINARY_DIR}/mentos/kernel-bootloader.bin" >> ${CMAKE_BINARY_DIR}/.gdbinit COMMAND bash ${CMAKE_SOURCE_DIR}/scripts/get_text_address.sh ${CMAKE_BINARY_DIR}/programs/tests/test_* >> ${CMAKE_BINARY_DIR}/.gdbinit
COMMAND ls -1 ${CMAKE_BINARY_DIR}/programs/tests/test_* | sed 's/^/add-symbol-file /' >> ${CMAKE_BINARY_DIR}/.gdbinit COMMAND bash ${CMAKE_SOURCE_DIR}/scripts/get_text_address.sh ${CMAKE_BINARY_DIR}/programs/prog_* >> ${CMAKE_BINARY_DIR}/.gdbinit
COMMAND ls -1 ${CMAKE_BINARY_DIR}/programs/prog_* | sed 's/^/add-symbol-file /' >> ${CMAKE_BINARY_DIR}/.gdbinit
COMMAND echo "break boot.c: boot_main" >> ${CMAKE_BINARY_DIR}/.gdbinit COMMAND echo "break boot.c: boot_main" >> ${CMAKE_BINARY_DIR}/.gdbinit
COMMAND echo "break kernel.c: kmain" >> ${CMAKE_BINARY_DIR}/.gdbinit COMMAND echo "break kernel.c: kmain" >> ${CMAKE_BINARY_DIR}/.gdbinit
# Create the GDB connection file. # Create the GDB connection file.
COMMAND echo "target remote localhost:1234" > ${CMAKE_BINARY_DIR}/gdb.run COMMAND echo "target remote localhost:1234" > ${CMAKE_BINARY_DIR}/gdb.run
DEPENDS kernel-bootloader.bin DEPENDS ${CMAKE_BINARY_DIR}/mentos/kernel_bootloader.bin
DEPENDS ${CMAKE_BINARY_DIR}/mentos/kernel.bin
DEPENDS all_programs DEPENDS all_programs
DEPENDS all_tests DEPENDS all_tests
DEPENDS libc DEPENDS libc
@@ -169,17 +217,15 @@ add_custom_target(
add_custom_target( add_custom_target(
qemu-gdb qemu-gdb
COMMAND test -e ${CMAKE_BINARY_DIR}/rootfs.img || ${CMAKE_COMMAND} -E cmake_echo_color --red "No filesystem file detected, you need to run: make filesystem" COMMAND test -e ${CMAKE_BINARY_DIR}/rootfs.img || ${CMAKE_COMMAND} -E cmake_echo_color --red "No filesystem file detected, you need to run: make filesystem"
COMMAND echo "" COMMAND echo "\n\n"
COMMAND echo "Now, QEMU has loaded the kernel, and it is waiting that you" COMMAND echo "Now, QEMU has loaded the kernel, and it is waiting that you\n"
COMMAND echo "remotely connect to it. To start debugging, open a new shell" COMMAND echo "remotely connect to it. To start debugging, open a new shell\n"
COMMAND echo "in THIS same folder, and just type:" COMMAND echo "in THIS same folder, and just type :\n"
COMMAND echo " gdb --quiet --command=gdb.run" COMMAND printf " cgdb -q -iex %q" "add-auto-load-safe-path ."
COMMAND echo "or if you want to use cgdb, type:" COMMAND echo "\n\n"
COMMAND echo " cgdb --quiet --command=gdb.run" COMMAND ${EMULATOR} ${EMULATOR_FLAGS} -s -S -kernel ${CMAKE_BINARY_DIR}/mentos/kernel_bootloader.bin
COMMAND echo "" DEPENDS kernel_bootloader.bin
COMMAND ${EMULATOR} ${EMULATOR_FLAGS} -s -S -kernel ${CMAKE_BINARY_DIR}/mentos/kernel-bootloader.bin DEPENDS .gdbinit
DEPENDS kernel-bootloader.bin
DEPENDS gdbinit
) )
# ============================================================================= # =============================================================================
@@ -190,9 +236,9 @@ add_custom_target(
add_custom_target( add_custom_target(
cdrom.iso cdrom.iso
COMMAND cp -rf ${CMAKE_SOURCE_DIR}/iso . COMMAND cp -rf ${CMAKE_SOURCE_DIR}/iso .
COMMAND cp ${CMAKE_BINARY_DIR}/mentos/kernel-bootloader.bin ${CMAKE_BINARY_DIR}/iso/boot COMMAND cp ${CMAKE_BINARY_DIR}/mentos/kernel_bootloader.bin ${CMAKE_BINARY_DIR}/iso/boot
COMMAND grub-mkrescue -o ${CMAKE_BINARY_DIR}/cdrom.iso ${CMAKE_BINARY_DIR}/iso COMMAND grub-mkrescue -o ${CMAKE_BINARY_DIR}/cdrom.iso ${CMAKE_BINARY_DIR}/iso
DEPENDS kernel-bootloader.bin DEPENDS kernel_bootloader.bin
) )
# This third target runs the emualtor, but this time, the kernel binary file is # This third target runs the emualtor, but this time, the kernel binary file is
+67 -145
View File
@@ -1,148 +1,70 @@
# ============================================================================= # Add the libc library.
# Author: Enrico Fraccaroli add_library(libc
# ============================================================================= ${PROJECT_SOURCE_DIR}/libc/src/stdio.c
${PROJECT_SOURCE_DIR}/libc/src/ctype.c
# Set the minimum required version of cmake. ${PROJECT_SOURCE_DIR}/libc/src/string.c
cmake_minimum_required(VERSION 3.1...3.22) ${PROJECT_SOURCE_DIR}/libc/src/stdlib.c
${PROJECT_SOURCE_DIR}/libc/src/math.c
# Initialize the project. ${PROJECT_SOURCE_DIR}/libc/src/fcvt.c
project(libc C ASM) ${PROJECT_SOURCE_DIR}/libc/src/time.c
${PROJECT_SOURCE_DIR}/libc/src/strerror.c
# ============================================================================= ${PROJECT_SOURCE_DIR}/libc/src/termios.c
# ASSEMBLY ${PROJECT_SOURCE_DIR}/libc/src/libgen.c
# ============================================================================= ${PROJECT_SOURCE_DIR}/libc/src/vsprintf.c
${PROJECT_SOURCE_DIR}/libc/src/vscanf.c
# Enable the assembly language. ${PROJECT_SOURCE_DIR}/libc/src/pwd.c
enable_language(ASM) ${PROJECT_SOURCE_DIR}/libc/src/grp.c
# Find the NASM compiler. ${PROJECT_SOURCE_DIR}/libc/src/sched.c
find_program(ASM_COMPILER NAMES nasm HINTS /usr/bin/ /usr/local/bin/) ${PROJECT_SOURCE_DIR}/libc/src/readline.c
# Mark the variable ASM_COMPILER as advanced. ${PROJECT_SOURCE_DIR}/libc/src/setenv.c
mark_as_advanced(ASM_COMPILER) ${PROJECT_SOURCE_DIR}/libc/src/assert.c
# Check that we have found the compiler. ${PROJECT_SOURCE_DIR}/libc/src/abort.c
if(NOT ASM_COMPILER) ${PROJECT_SOURCE_DIR}/libc/src/io/mm_io.c
message(FATAL_ERROR "ASM compiler not found!") ${PROJECT_SOURCE_DIR}/libc/src/io/debug.c
endif(NOT ASM_COMPILER) ${PROJECT_SOURCE_DIR}/libc/src/sys/ipc.c
# Set the asm compiler. ${PROJECT_SOURCE_DIR}/libc/src/sys/unistd.c
set(CMAKE_ASM_COMPILER ${ASM_COMPILER}) ${PROJECT_SOURCE_DIR}/libc/src/sys/errno.c
# Set the assembly compiler flags. ${PROJECT_SOURCE_DIR}/libc/src/sys/utsname.c
if(CMAKE_BUILD_TYPE STREQUAL "Debug") ${PROJECT_SOURCE_DIR}/libc/src/sys/mman.c
set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> -f elf -g -O0 -F dwarf -o <OBJECT> <SOURCE>") ${PROJECT_SOURCE_DIR}/libc/src/sys/ioctl.c
else() ${PROJECT_SOURCE_DIR}/libc/src/unistd/creat.c
set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> -f elf -g -O3 -o <OBJECT> <SOURCE>") ${PROJECT_SOURCE_DIR}/libc/src/unistd/getppid.c
endif() ${PROJECT_SOURCE_DIR}/libc/src/unistd/getpid.c
${PROJECT_SOURCE_DIR}/libc/src/unistd/exit.c
# ============================================================================= ${PROJECT_SOURCE_DIR}/libc/src/unistd/setsid.c
# C WARNINGs ${PROJECT_SOURCE_DIR}/libc/src/unistd/getsid.c
# ============================================================================= ${PROJECT_SOURCE_DIR}/libc/src/unistd/setpgid.c
${PROJECT_SOURCE_DIR}/libc/src/unistd/getpgid.c
# Warning flags. ${PROJECT_SOURCE_DIR}/libc/src/unistd/setgid.c
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") ${PROJECT_SOURCE_DIR}/libc/src/unistd/getgid.c
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror") ${PROJECT_SOURCE_DIR}/libc/src/unistd/setuid.c
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wpedantic") ${PROJECT_SOURCE_DIR}/libc/src/unistd/getuid.c
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pedantic-errors") ${PROJECT_SOURCE_DIR}/libc/src/unistd/fork.c
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wshadow") ${PROJECT_SOURCE_DIR}/libc/src/unistd/read.c
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99") ${PROJECT_SOURCE_DIR}/libc/src/unistd/write.c
${PROJECT_SOURCE_DIR}/libc/src/unistd/exec.c
# Disable some specific warnings. ${PROJECT_SOURCE_DIR}/libc/src/unistd/nice.c
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-function") ${PROJECT_SOURCE_DIR}/libc/src/unistd/open.c
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-variable") ${PROJECT_SOURCE_DIR}/libc/src/unistd/reboot.c
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unknown-pragmas") ${PROJECT_SOURCE_DIR}/libc/src/unistd/waitpid.c
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-missing-braces") ${PROJECT_SOURCE_DIR}/libc/src/unistd/chdir.c
${PROJECT_SOURCE_DIR}/libc/src/unistd/getcwd.c
# Set the compiler options. ${PROJECT_SOURCE_DIR}/libc/src/unistd/close.c
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -static") ${PROJECT_SOURCE_DIR}/libc/src/unistd/stat.c
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -nostdlib") ${PROJECT_SOURCE_DIR}/libc/src/unistd/rmdir.c
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -nostdinc") ${PROJECT_SOURCE_DIR}/libc/src/unistd/mkdir.c
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-builtin") ${PROJECT_SOURCE_DIR}/libc/src/unistd/unlink.c
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-stack-protector") ${PROJECT_SOURCE_DIR}/libc/src/unistd/getdents.c
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-pic") ${PROJECT_SOURCE_DIR}/libc/src/unistd/lseek.c
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fomit-frame-pointer") ${PROJECT_SOURCE_DIR}/libc/src/unistd/kill.c
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32") ${PROJECT_SOURCE_DIR}/libc/src/unistd/signal.c
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=i686") ${PROJECT_SOURCE_DIR}/libc/src/unistd/interval.c
if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 10) ${PROJECT_SOURCE_DIR}/libc/src/unistd/symlink.c
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fcommon") ${PROJECT_SOURCE_DIR}/libc/src/unistd/readlink.c
endif() ${PROJECT_SOURCE_DIR}/libc/src/libc_start.c
${PROJECT_SOURCE_DIR}/libc/src/crt0.s
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g3")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ggdb")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0")
elseif(CMAKE_BUILD_TYPE STREQUAL "Release")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3")
endif(CMAKE_BUILD_TYPE STREQUAL "Debug")
# =============================================================================
# Add the library.
add_library(
${PROJECT_NAME}
${PROJECT_SOURCE_DIR}/src/stdio.c
${PROJECT_SOURCE_DIR}/src/ctype.c
${PROJECT_SOURCE_DIR}/src/string.c
${PROJECT_SOURCE_DIR}/src/stdlib.c
${PROJECT_SOURCE_DIR}/src/math.c
${PROJECT_SOURCE_DIR}/src/fcvt.c
${PROJECT_SOURCE_DIR}/src/time.c
${PROJECT_SOURCE_DIR}/src/strerror.c
${PROJECT_SOURCE_DIR}/src/termios.c
${PROJECT_SOURCE_DIR}/src/libgen.c
${PROJECT_SOURCE_DIR}/src/vsprintf.c
${PROJECT_SOURCE_DIR}/src/vscanf.c
${PROJECT_SOURCE_DIR}/src/pwd.c
${PROJECT_SOURCE_DIR}/src/grp.c
${PROJECT_SOURCE_DIR}/src/sched.c
${PROJECT_SOURCE_DIR}/src/readline.c
${PROJECT_SOURCE_DIR}/src/setenv.c
${PROJECT_SOURCE_DIR}/src/assert.c
${PROJECT_SOURCE_DIR}/src/abort.c
${PROJECT_SOURCE_DIR}/src/io/mm_io.c
${PROJECT_SOURCE_DIR}/src/io/debug.c
${PROJECT_SOURCE_DIR}/src/sys/ipc.c
${PROJECT_SOURCE_DIR}/src/sys/unistd.c
${PROJECT_SOURCE_DIR}/src/sys/errno.c
${PROJECT_SOURCE_DIR}/src/sys/utsname.c
${PROJECT_SOURCE_DIR}/src/sys/mman.c
${PROJECT_SOURCE_DIR}/src/sys/ioctl.c
${PROJECT_SOURCE_DIR}/src/unistd/creat.c
${PROJECT_SOURCE_DIR}/src/unistd/getppid.c
${PROJECT_SOURCE_DIR}/src/unistd/getpid.c
${PROJECT_SOURCE_DIR}/src/unistd/exit.c
${PROJECT_SOURCE_DIR}/src/unistd/setsid.c
${PROJECT_SOURCE_DIR}/src/unistd/getsid.c
${PROJECT_SOURCE_DIR}/src/unistd/setpgid.c
${PROJECT_SOURCE_DIR}/src/unistd/getpgid.c
${PROJECT_SOURCE_DIR}/src/unistd/setgid.c
${PROJECT_SOURCE_DIR}/src/unistd/getgid.c
${PROJECT_SOURCE_DIR}/src/unistd/setuid.c
${PROJECT_SOURCE_DIR}/src/unistd/getuid.c
${PROJECT_SOURCE_DIR}/src/unistd/fork.c
${PROJECT_SOURCE_DIR}/src/unistd/read.c
${PROJECT_SOURCE_DIR}/src/unistd/write.c
${PROJECT_SOURCE_DIR}/src/unistd/exec.c
${PROJECT_SOURCE_DIR}/src/unistd/nice.c
${PROJECT_SOURCE_DIR}/src/unistd/open.c
${PROJECT_SOURCE_DIR}/src/unistd/reboot.c
${PROJECT_SOURCE_DIR}/src/unistd/waitpid.c
${PROJECT_SOURCE_DIR}/src/unistd/chdir.c
${PROJECT_SOURCE_DIR}/src/unistd/getcwd.c
${PROJECT_SOURCE_DIR}/src/unistd/close.c
${PROJECT_SOURCE_DIR}/src/unistd/stat.c
${PROJECT_SOURCE_DIR}/src/unistd/rmdir.c
${PROJECT_SOURCE_DIR}/src/unistd/mkdir.c
${PROJECT_SOURCE_DIR}/src/unistd/unlink.c
${PROJECT_SOURCE_DIR}/src/unistd/getdents.c
${PROJECT_SOURCE_DIR}/src/unistd/lseek.c
${PROJECT_SOURCE_DIR}/src/unistd/kill.c
${PROJECT_SOURCE_DIR}/src/unistd/signal.c
${PROJECT_SOURCE_DIR}/src/unistd/interval.c
${PROJECT_SOURCE_DIR}/src/unistd/symlink.c
${PROJECT_SOURCE_DIR}/src/unistd/readlink.c
${PROJECT_SOURCE_DIR}/src/libc_start.c
${PROJECT_SOURCE_DIR}/src/crt0.S
) )
# Add the includes. # Add the includes.
target_include_directories(${PROJECT_NAME} PUBLIC inc) target_include_directories(libc PRIVATE ${PROJECT_SOURCE_DIR}/libc/inc)
# Remove the 'lib' prefix. # Remove the 'lib' prefix.
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "") set_target_properties(libc PROPERTIES PREFIX "")
+15
View File
@@ -0,0 +1,15 @@
.extern main
.extern __libc_start_main
.global _start
# -----------------------------------------------------------------------------
# SECTION (text)
# -----------------------------------------------------------------------------
.text
_start: # _start is the entry point known to the linker
mov $0, %ebp # Set ebp to 0 as x86 programs require
push $main
call __libc_start_main # Call the libc initialization function.
mov %eax, %ebx # Move `main` return value to ebx.
mov $1, %eax # Call the `exit` function by using `int 80` (i.e., a system call)
int $0x80
+116 -171
View File
@@ -1,19 +1,9 @@
# =============================================================================
# Author: Enrico Fraccaroli
# =============================================================================
# Set the minimum required version of cmake.
cmake_minimum_required(VERSION 3.1...3.22)
# Initialize the project.
project(kernel C ASM)
# ============================================================================= # =============================================================================
# Set the main file names. # Set the main file names.
set(KERNEL_NAME kernel) set(KERNEL_NAME kernel)
set(BOOTLOADER_NAME kernel_bootloader) set(BOOTLOADER_NAME kernel_bootloader)
set(BUDDY_SYSTEM_NAME kernel_memory) set(BUDDY_SYSTEM_NAME kernel_memory)
set(BUDDY_SYSTEM_FILE ${PROJECT_SOURCE_DIR}/src/mem/libbuddysystem.a) set(BUDDY_SYSTEM_FILE ${CMAKE_CURRENT_SOURCE_DIR}/src/mem/libbuddysystem.a)
# ============================================================================= # =============================================================================
# OPTIONS # OPTIONS
@@ -28,164 +18,103 @@ option(ENABLE_ALLOC_TRACE "Enables memory allocation tracing." OFF)
# Enables scheduling feedback on terminal. # Enables scheduling feedback on terminal.
option(ENABLE_SCHEDULER_FEEDBACK "Enables scheduling feedback on terminal." OFF) option(ENABLE_SCHEDULER_FEEDBACK "Enables scheduling feedback on terminal." OFF)
# =============================================================================
# ASSEMBLY
# =============================================================================
# Find the NASM compiler.
find_program(ASM_COMPILER NAMES nasm HINTS /usr/bin/ /usr/local/bin/)
# Mark the variable ASM_COMPILER as advanced.
mark_as_advanced(ASM_COMPILER)
# Check that we have found the compiler.
if(NOT ASM_COMPILER)
message(FATAL_ERROR "ASM compiler not found!")
endif(NOT ASM_COMPILER)
# Set the asm compiler.
set(CMAKE_ASM_COMPILER ${ASM_COMPILER})
# Set the assembly compiler flags.
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> -f elf -g -O0 -F dwarf -o <OBJECT> <SOURCE>")
else()
set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> -f elf -g -O3 -o <OBJECT> <SOURCE>")
endif()
# =============================================================================
# C WARNINGs
# =============================================================================
# Warning flags.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wpedantic")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pedantic-errors")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wshadow")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99")
# Disable some specific warnings.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-function")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-variable")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unknown-pragmas")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-missing-braces")
# Set the compiler options.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -static")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -nostdlib")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -nostdinc")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-builtin")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-stack-protector")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-pic")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fomit-frame-pointer")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=i686")
if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 10)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fcommon")
endif()
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g3")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ggdb")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0")
elseif(CMAKE_BUILD_TYPE STREQUAL "Release")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3")
endif(CMAKE_BUILD_TYPE STREQUAL "Debug")
# ============================================================================= # =============================================================================
# SOURCES # SOURCES
# ============================================================================= # =============================================================================
# Define the list of files. # Define the list of files.
set(KERNEL_SOURCES set(KERNEL_SOURCES
${PROJECT_SOURCE_DIR}/src/kernel.c ${PROJECT_SOURCE_DIR}/mentos/src/kernel.c
${PROJECT_SOURCE_DIR}/src/multiboot.c ${PROJECT_SOURCE_DIR}/mentos/src/multiboot.c
${PROJECT_SOURCE_DIR}/src/devices/pci.c ${PROJECT_SOURCE_DIR}/mentos/src/devices/pci.c
${PROJECT_SOURCE_DIR}/src/devices/fpu.c ${PROJECT_SOURCE_DIR}/mentos/src/devices/fpu.c
${PROJECT_SOURCE_DIR}/src/drivers/ata.c ${PROJECT_SOURCE_DIR}/mentos/src/drivers/ata.c
${PROJECT_SOURCE_DIR}/src/drivers/rtc.c ${PROJECT_SOURCE_DIR}/mentos/src/drivers/rtc.c
${PROJECT_SOURCE_DIR}/src/drivers/fdc.c ${PROJECT_SOURCE_DIR}/mentos/src/drivers/fdc.c
${PROJECT_SOURCE_DIR}/src/drivers/mouse.c ${PROJECT_SOURCE_DIR}/mentos/src/drivers/mouse.c
${PROJECT_SOURCE_DIR}/src/drivers/ps2.c ${PROJECT_SOURCE_DIR}/mentos/src/drivers/ps2.c
${PROJECT_SOURCE_DIR}/src/drivers/keyboard/keyboard.c ${PROJECT_SOURCE_DIR}/mentos/src/drivers/keyboard/keyboard.c
${PROJECT_SOURCE_DIR}/src/drivers/keyboard/keymap.c ${PROJECT_SOURCE_DIR}/mentos/src/drivers/keyboard/keymap.c
${PROJECT_SOURCE_DIR}/src/fs/vfs.c ${PROJECT_SOURCE_DIR}/mentos/src/fs/vfs.c
${PROJECT_SOURCE_DIR}/src/fs/read_write.c ${PROJECT_SOURCE_DIR}/mentos/src/fs/read_write.c
${PROJECT_SOURCE_DIR}/src/fs/open.c ${PROJECT_SOURCE_DIR}/mentos/src/fs/open.c
${PROJECT_SOURCE_DIR}/src/fs/stat.c ${PROJECT_SOURCE_DIR}/mentos/src/fs/stat.c
${PROJECT_SOURCE_DIR}/src/fs/readdir.c ${PROJECT_SOURCE_DIR}/mentos/src/fs/readdir.c
${PROJECT_SOURCE_DIR}/src/fs/procfs.c ${PROJECT_SOURCE_DIR}/mentos/src/fs/procfs.c
${PROJECT_SOURCE_DIR}/src/fs/ioctl.c ${PROJECT_SOURCE_DIR}/mentos/src/fs/ioctl.c
${PROJECT_SOURCE_DIR}/src/fs/namei.c ${PROJECT_SOURCE_DIR}/mentos/src/fs/namei.c
${PROJECT_SOURCE_DIR}/src/fs/ext2.c ${PROJECT_SOURCE_DIR}/mentos/src/fs/ext2.c
${PROJECT_SOURCE_DIR}/src/hardware/timer.c ${PROJECT_SOURCE_DIR}/mentos/src/hardware/timer.c
${PROJECT_SOURCE_DIR}/src/hardware/cpuid.c ${PROJECT_SOURCE_DIR}/mentos/src/hardware/cpuid.c
${PROJECT_SOURCE_DIR}/src/hardware/pic8259.c ${PROJECT_SOURCE_DIR}/mentos/src/hardware/pic8259.c
${PROJECT_SOURCE_DIR}/src/io/debug.c ${PROJECT_SOURCE_DIR}/mentos/src/io/debug.c
${PROJECT_SOURCE_DIR}/src/io/mm_io.c ${PROJECT_SOURCE_DIR}/mentos/src/io/mm_io.c
${PROJECT_SOURCE_DIR}/src/io/video.c ${PROJECT_SOURCE_DIR}/mentos/src/io/video.c
${PROJECT_SOURCE_DIR}/src/io/stdio.c ${PROJECT_SOURCE_DIR}/mentos/src/io/stdio.c
${PROJECT_SOURCE_DIR}/src/io/proc_video.c ${PROJECT_SOURCE_DIR}/mentos/src/io/proc_video.c
${PROJECT_SOURCE_DIR}/src/io/proc_running.c ${PROJECT_SOURCE_DIR}/mentos/src/io/proc_running.c
${PROJECT_SOURCE_DIR}/src/io/proc_feedback.c ${PROJECT_SOURCE_DIR}/mentos/src/io/proc_feedback.c
${PROJECT_SOURCE_DIR}/src/io/proc_system.c ${PROJECT_SOURCE_DIR}/mentos/src/io/proc_system.c
${PROJECT_SOURCE_DIR}/src/io/proc_ipc.c ${PROJECT_SOURCE_DIR}/mentos/src/io/proc_ipc.c
${PROJECT_SOURCE_DIR}/src/io/vga/vga.c ${PROJECT_SOURCE_DIR}/mentos/src/io/vga/vga.c
${PROJECT_SOURCE_DIR}/src/ipc/ipc.c ${PROJECT_SOURCE_DIR}/mentos/src/ipc/ipc.c
${PROJECT_SOURCE_DIR}/src/ipc/msg.c ${PROJECT_SOURCE_DIR}/mentos/src/ipc/msg.c
${PROJECT_SOURCE_DIR}/src/ipc/sem.c ${PROJECT_SOURCE_DIR}/mentos/src/ipc/sem.c
${PROJECT_SOURCE_DIR}/src/ipc/shm.c ${PROJECT_SOURCE_DIR}/mentos/src/ipc/shm.c
${PROJECT_SOURCE_DIR}/src/kernel/sys.c ${PROJECT_SOURCE_DIR}/mentos/src/kernel/sys.c
${PROJECT_SOURCE_DIR}/src/klib/assert.c ${PROJECT_SOURCE_DIR}/mentos/src/klib/assert.c
${PROJECT_SOURCE_DIR}/src/klib/ctype.c ${PROJECT_SOURCE_DIR}/mentos/src/klib/ctype.c
${PROJECT_SOURCE_DIR}/src/klib/mutex.c ${PROJECT_SOURCE_DIR}/mentos/src/klib/mutex.c
${PROJECT_SOURCE_DIR}/src/klib/string.c ${PROJECT_SOURCE_DIR}/mentos/src/klib/string.c
${PROJECT_SOURCE_DIR}/src/klib/vsprintf.c ${PROJECT_SOURCE_DIR}/mentos/src/klib/vsprintf.c
${PROJECT_SOURCE_DIR}/src/klib/vscanf.c ${PROJECT_SOURCE_DIR}/mentos/src/klib/vscanf.c
${PROJECT_SOURCE_DIR}/src/klib/time.c ${PROJECT_SOURCE_DIR}/mentos/src/klib/time.c
${PROJECT_SOURCE_DIR}/src/klib/libgen.c ${PROJECT_SOURCE_DIR}/mentos/src/klib/libgen.c
${PROJECT_SOURCE_DIR}/src/klib/strerror.c ${PROJECT_SOURCE_DIR}/mentos/src/klib/strerror.c
${PROJECT_SOURCE_DIR}/src/klib/math.c ${PROJECT_SOURCE_DIR}/mentos/src/klib/math.c
${PROJECT_SOURCE_DIR}/src/klib/fcvt.c ${PROJECT_SOURCE_DIR}/mentos/src/klib/fcvt.c
${PROJECT_SOURCE_DIR}/src/klib/spinlock.c ${PROJECT_SOURCE_DIR}/mentos/src/klib/spinlock.c
${PROJECT_SOURCE_DIR}/src/klib/stdlib.c ${PROJECT_SOURCE_DIR}/mentos/src/klib/stdlib.c
${PROJECT_SOURCE_DIR}/src/klib/rbtree.c ${PROJECT_SOURCE_DIR}/mentos/src/klib/rbtree.c
${PROJECT_SOURCE_DIR}/src/klib/ndtree.c ${PROJECT_SOURCE_DIR}/mentos/src/klib/ndtree.c
${PROJECT_SOURCE_DIR}/src/klib/hashmap.c ${PROJECT_SOURCE_DIR}/mentos/src/klib/hashmap.c
${PROJECT_SOURCE_DIR}/src/klib/list.c ${PROJECT_SOURCE_DIR}/mentos/src/klib/list.c
${PROJECT_SOURCE_DIR}/src/mem/kheap.c ${PROJECT_SOURCE_DIR}/mentos/src/mem/kheap.c
${PROJECT_SOURCE_DIR}/src/mem/paging.c ${PROJECT_SOURCE_DIR}/mentos/src/mem/paging.c
${PROJECT_SOURCE_DIR}/src/mem/slab.c ${PROJECT_SOURCE_DIR}/mentos/src/mem/slab.c
${PROJECT_SOURCE_DIR}/src/mem/vmem_map.c ${PROJECT_SOURCE_DIR}/mentos/src/mem/vmem_map.c
${PROJECT_SOURCE_DIR}/src/mem/zone_allocator.c ${PROJECT_SOURCE_DIR}/mentos/src/mem/zone_allocator.c
${PROJECT_SOURCE_DIR}/src/elf/elf.c ${PROJECT_SOURCE_DIR}/mentos/src/elf/elf.c
${PROJECT_SOURCE_DIR}/src/descriptor_tables/gdt.c ${PROJECT_SOURCE_DIR}/mentos/src/descriptor_tables/gdt.c
${PROJECT_SOURCE_DIR}/src/descriptor_tables/gdt.S ${PROJECT_SOURCE_DIR}/mentos/src/descriptor_tables/gdt.s
${PROJECT_SOURCE_DIR}/src/descriptor_tables/interrupt.c ${PROJECT_SOURCE_DIR}/mentos/src/descriptor_tables/interrupt.c
${PROJECT_SOURCE_DIR}/src/descriptor_tables/exception.c ${PROJECT_SOURCE_DIR}/mentos/src/descriptor_tables/exception.c
${PROJECT_SOURCE_DIR}/src/descriptor_tables/interrupt.S ${PROJECT_SOURCE_DIR}/mentos/src/descriptor_tables/interrupt.s
${PROJECT_SOURCE_DIR}/src/descriptor_tables/exception.S ${PROJECT_SOURCE_DIR}/mentos/src/descriptor_tables/exception.s
${PROJECT_SOURCE_DIR}/src/descriptor_tables/idt.c ${PROJECT_SOURCE_DIR}/mentos/src/descriptor_tables/idt.c
${PROJECT_SOURCE_DIR}/src/descriptor_tables/idt.S ${PROJECT_SOURCE_DIR}/mentos/src/descriptor_tables/idt.s
${PROJECT_SOURCE_DIR}/src/descriptor_tables/tss.c ${PROJECT_SOURCE_DIR}/mentos/src/descriptor_tables/tss.c
${PROJECT_SOURCE_DIR}/src/descriptor_tables/tss.S ${PROJECT_SOURCE_DIR}/mentos/src/descriptor_tables/tss.s
${PROJECT_SOURCE_DIR}/src/process/scheduler_algorithm.c ${PROJECT_SOURCE_DIR}/mentos/src/process/scheduler_algorithm.c
${PROJECT_SOURCE_DIR}/src/process/scheduler_feedback.c ${PROJECT_SOURCE_DIR}/mentos/src/process/scheduler_feedback.c
${PROJECT_SOURCE_DIR}/src/process/scheduler.c ${PROJECT_SOURCE_DIR}/mentos/src/process/scheduler.c
${PROJECT_SOURCE_DIR}/src/process/process.c ${PROJECT_SOURCE_DIR}/mentos/src/process/process.c
${PROJECT_SOURCE_DIR}/src/process/wait.c ${PROJECT_SOURCE_DIR}/mentos/src/process/wait.c
${PROJECT_SOURCE_DIR}/src/process/user.S ${PROJECT_SOURCE_DIR}/mentos/src/process/user.s
${PROJECT_SOURCE_DIR}/src/sys/utsname.c ${PROJECT_SOURCE_DIR}/mentos/src/sys/utsname.c
${PROJECT_SOURCE_DIR}/src/sys/module.c ${PROJECT_SOURCE_DIR}/mentos/src/sys/module.c
${PROJECT_SOURCE_DIR}/src/system/errno.c ${PROJECT_SOURCE_DIR}/mentos/src/system/errno.c
${PROJECT_SOURCE_DIR}/src/system/panic.c ${PROJECT_SOURCE_DIR}/mentos/src/system/panic.c
${PROJECT_SOURCE_DIR}/src/system/printk.c ${PROJECT_SOURCE_DIR}/mentos/src/system/printk.c
${PROJECT_SOURCE_DIR}/src/system/signal.c ${PROJECT_SOURCE_DIR}/mentos/src/system/signal.c
${PROJECT_SOURCE_DIR}/src/system/syscall.c ${PROJECT_SOURCE_DIR}/mentos/src/system/syscall.c
) )
# ============================================================================= # =============================================================================
# Add kernel library. # Add kernel library.
if(USE_BUDDY_SYSTEM) if(USE_BUDDY_SYSTEM)
# Add the library with `buddysystem.c`. # Add the library with `buddysystem.c`.
add_library(${KERNEL_NAME} ${KERNEL_SOURCES} src/mem/buddysystem.c) add_library(${KERNEL_NAME} ${KERNEL_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/src/mem/buddysystem.c)
else(USE_BUDDY_SYSTEM) else(USE_BUDDY_SYSTEM)
# Add the library without `buddysystem.c`. # Add the library without `buddysystem.c`.
add_library(${KERNEL_NAME} ${KERNEL_SOURCES}) add_library(${KERNEL_NAME} ${KERNEL_SOURCES})
@@ -203,6 +132,17 @@ target_compile_definitions(
${KERNEL_NAME} PUBLIC ${KERNEL_NAME} PUBLIC
__KERNEL__ __KERNEL__
) )
# Link the kernel.
add_custom_target(
${KERNEL_NAME}.bin
COMMAND ${CMAKE_LINKER} -melf_i386 -static --oformat elf32-i386 --output ${KERNEL_NAME}.bin --script ${CMAKE_CURRENT_SOURCE_DIR}/kernel.lds -Map ${KERNEL_NAME}.map -u kmain
$<TARGET_FILE_NAME:${KERNEL_NAME}> ${BUDDY_SYSTEM_FILE}
COMMAND objcopy -I binary -O elf32-i386 -B i386 ${KERNEL_NAME}.bin ${KERNEL_NAME}.bin.o
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/kernel.lds
DEPENDS ${KERNEL_NAME}
BYPRODUCTS ${KERNEL_NAME}.bin ${KERNEL_NAME}.bin.o
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
# ============================================================================= # =============================================================================
# Enables cache tracing. # Enables cache tracing.
@@ -280,8 +220,8 @@ endif()
# Add bootloader library. # Add bootloader library.
add_library( add_library(
${BOOTLOADER_NAME} ${BOOTLOADER_NAME}
src/boot.c ${CMAKE_CURRENT_SOURCE_DIR}/src/boot.c
src/boot.S ${CMAKE_CURRENT_SOURCE_DIR}/src/boot.s
) )
# Add the includes. # Add the includes.
target_include_directories( target_include_directories(
@@ -294,16 +234,21 @@ target_compile_definitions(
${BOOTLOADER_NAME} PUBLIC ${BOOTLOADER_NAME} PUBLIC
__KERNEL__ __KERNEL__
) )
add_dependencies(
# ============================================================================= ${BOOTLOADER_NAME}
# Build the kernel. ${KERNEL_NAME}
add_custom_target( )
kernel-bootloader.bin ALL target_link_libraries(
COMMAND ${CMAKE_LINKER} -melf_i386 -static --oformat elf32-i386 --output kernel.bin --script ${CMAKE_CURRENT_SOURCE_DIR}/kernel.lds -Map kernel.map -u kmain ${BOOTLOADER_NAME} PUBLIC
$<TARGET_FILE_NAME:${KERNEL_NAME}> ${BUDDY_SYSTEM_FILE} ${KERNEL_NAME}
COMMAND objcopy -I binary -O elf32-i386 -B i386 kernel.bin kernel.bin.o )
COMMAND ${CMAKE_LINKER} -melf_i386 -static --oformat elf32-i386 --output kernel-bootloader.bin --script ${CMAKE_CURRENT_SOURCE_DIR}/boot.lds -Map kernel-bootloader.map # Link the bootloader.
kernel.bin.o $<TARGET_FILE_NAME:${BOOTLOADER_NAME}> add_custom_target(
DEPENDS ${KERNEL_NAME} ${BOOTLOADER_NAME}.bin
DEPENDS ${BOOTLOADER_NAME} COMMAND ${CMAKE_LINKER} -melf_i386 -static --output ${BOOTLOADER_NAME}.bin --script ${CMAKE_CURRENT_SOURCE_DIR}/boot.lds -Map ${BOOTLOADER_NAME}.map ${KERNEL_NAME}.bin.o $<TARGET_FILE_NAME:${BOOTLOADER_NAME}>
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/boot.lds
DEPENDS ${BOOTLOADER_NAME}
DEPENDS ${KERNEL_NAME}.bin
BYPRODUCTS ${BOOTLOADER_NAME}.bin
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
) )
+5 -13
View File
@@ -9,45 +9,37 @@ MEMORY {
SECTIONS SECTIONS
{ {
. = 0x00100000; . = 0x00100000;
_bootloader_start = .;
_bootloader_start = .;
.multiboot . : AT(ADDR(.multiboot)) .multiboot . : AT(ADDR(.multiboot))
{ {
. = ALIGN(4); . = ALIGN(4);
_multiboot_header_start = .;
*(.multiboot_header) *(.multiboot_header)
_multiboot_header_end = .;
} > BOOTLOADER_MEM } > BOOTLOADER_MEM
/* Put the .text section. */ /* Put the .text section. */
.text . : AT(ADDR(.text)) .text . : AT(ADDR(.text))
{ {
_text_start = .;
*(.text) *(.text)
_text_end = .;
} > BOOTLOADER_MEM } > BOOTLOADER_MEM
/* Read-only data. */ /* Read-only data. */
.rodata ALIGN(4K) : AT(ADDR(.rodata)) .rodata ALIGN(4K) : AT(ADDR(.rodata))
{ {
_rodata_start = .;
*(.rodata) *(.rodata)
_rodata_end = .;
} > BOOTLOADER_MEM } > BOOTLOADER_MEM
/* Read-write data (initialized) */ /* Read-write data (initialized) */
.data ALIGN(4K) : AT(ADDR(.data)) .data ALIGN(4K) : AT(ADDR(.data))
{ {
_data_start = .;
*(.data) *(.data)
_data_end = .;
} > BOOTLOADER_MEM } > BOOTLOADER_MEM
/* Read-write data (uninitialized) and stack */ /* Read-write data (uninitialized) and stack */
.bss ALIGN(4K) : AT(ADDR(.bss)) .bss ALIGN(4K) : AT(ADDR(.bss))
{ {
_bss_start = .;
*(.bss*) *(.bss*)
_bss_end = .;
} > BOOTLOADER_MEM } > BOOTLOADER_MEM
/* Put a symbol end here, it tells us where all the kernel code/data ends, /* Put a symbol end here, it tells us where all the kernel code/data ends,
-8
View File
@@ -15,33 +15,25 @@ SECTIONS
/* Put the .text section. */ /* Put the .text section. */
.text . : AT(ADDR(.text)) .text . : AT(ADDR(.text))
{ {
_text_start = .;
EXCLUDE_FILE(*boot.*.o) *(.text) EXCLUDE_FILE(*boot.*.o) *(.text)
_text_end = .;
} > KERNEL_LOWMEM } > KERNEL_LOWMEM
/* Read-only data. */ /* Read-only data. */
.rodata ALIGN(4K) : AT(ADDR(.rodata)) .rodata ALIGN(4K) : AT(ADDR(.rodata))
{ {
_rodata_start = .;
EXCLUDE_FILE(*boot.*.o) *(.rodata) EXCLUDE_FILE(*boot.*.o) *(.rodata)
_rodata_end = .;
} > KERNEL_LOWMEM } > KERNEL_LOWMEM
/* Read-write data (initialized) */ /* Read-write data (initialized) */
.data ALIGN(4K) : AT(ADDR(.data)) .data ALIGN(4K) : AT(ADDR(.data))
{ {
_data_start = .;
EXCLUDE_FILE(*boot.*.o) *(.data) EXCLUDE_FILE(*boot.*.o) *(.data)
_data_end = .;
} > KERNEL_LOWMEM } > KERNEL_LOWMEM
/* Read-write data (uninitialized) and stack */ /* Read-write data (uninitialized) and stack */
.bss ALIGN(4K) : AT(ADDR(.bss)) .bss ALIGN(4K) : AT(ADDR(.bss))
{ {
_bss_start = .;
*(.bss*) *(.bss*)
_bss_end = .;
} > KERNEL_LOWMEM } > KERNEL_LOWMEM
/* Put a symbol end here, it tells us where all the kernel code/data ends, /* Put a symbol end here, it tells us where all the kernel code/data ends,
-103
View File
@@ -1,103 +0,0 @@
; MentOS, The Mentoring Operating system project
; @file boot.asm
; @brief Kernel start location, multiboot header
; @copyright (c) 2014-2021 This file is distributed under the MIT License.
; See LICENSE.md for details.
bits 32 ; All instructions should be 32-bit.
extern boot_main ; The start point of our C code
; The magic field should contain this.
MULTIBOOT_HEADER_MAGIC equ 0x1BADB002
; This should be in %eax.
MULTIBOOT_BOOTLOADER_MAGIC equ 0x2BADB002
; = Specify what GRUB should PROVIDE =========================================
; Align the kernel and kernel modules on i386 page (4KB) boundaries.
MULTIBOOT_PAGE_ALIGN equ 0x00000001
; Provide the kernel with memory information.
MULTIBOOT_MEMORY_INFO equ 0x00000002
; Must pass video information to OS.
MULTIBOOT_VIDEO_MODE equ 0x00000004
; -----------------------------------------------------------------------------
; This is the flag combination that we prepare for Grub
; to read at kernel load time.
MULTIBOOT_HEADER_FLAGS equ (MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO)
; Grub reads this value to make sure it loads a kernel
; and not just garbage.
MULTIBOOT_CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
LOAD_MEMORY_ADDRESS equ 0x00000000
; reserve (1024*1024) for the stack on a doubleword boundary
KERNEL_STACK_SIZE equ 0x100000
; -----------------------------------------------------------------------------
; SECTION (multiboot_header)
; -----------------------------------------------------------------------------
section .multiboot_header
align 4
; This is the GRUB Multiboot header.
multiboot_header:
; magic
dd MULTIBOOT_HEADER_MAGIC
; flags
dd MULTIBOOT_HEADER_FLAGS
; checksum
dd MULTIBOOT_CHECKSUM
; -----------------------------------------------------------------------------
; SECTION (data)
; -----------------------------------------------------------------------------
; section .data nobits
; align 4096
; -----------------------------------------------------------------------------
; SECTION (text)
; -----------------------------------------------------------------------------
section .text
global boot_entry
boot_entry:
; Clear interrupt flag [IF = 0]; 0xFA
cli
; To set up a stack, we simply set the esp register to point to the top of
; our stack (as it grows downwards).
mov esp, stack_top
; pass the initial ESP
push esp
; pass Multiboot info structure
push ebx
; pass Multiboot magic number
push eax
; Call the boot_main() function inside boot.c
call boot_main
; Set interrupt flag [IF = 1]; 0xFA
; Clear interrupts and hang if we return from boot_main
cli
hang:
hlt
jmp hang
global boot_kernel
boot_kernel:
mov edx, [esp + 4] ; stack_pointer
mov ebx, [esp + 8] ; entry
mov eax, [esp + 12] ; boot info
mov esp, edx ; set stack pointer
push eax ; push the boot info
call ebx ; call the kernel main
; -----------------------------------------------------------------------------
; SECTION (bss)
; -----------------------------------------------------------------------------
section .bss
align 16
global stack_bottom
stack_bottom:
resb KERNEL_STACK_SIZE
global stack_top
stack_top:
; the top of the stack is the bottom because the stack counts down
+115
View File
@@ -0,0 +1,115 @@
# MentOS, The Mentoring Operating system project
# @file boot.asm
# @brief Kernel start location, multiboot header
# @copyright (c) 2014-2021 This file is distributed under the MIT License.
# See LICENSE.md for details.
# All instructions should be 32-bit.
.extern boot_main # The start point of our C code
# The magic field should contain this.
.equ MULTIBOOT_HEADER_MAGIC, 0x1BADB002
# This should be in %eax.
.equ MULTIBOOT_BOOTLOADER_MAGIC, 0x2BADB002
# = Specify what GRUB should PROVIDE =========================================
# Align the kernel and kernel modules on i386 page (4KB) boundaries.
.equ MULTIBOOT_PAGE_ALIGN, 0x00000001
# Provide the kernel with memory information.
.equ MULTIBOOT_MEMORY_INFO, 0x00000002
# Must pass video information to OS.
.equ MULTIBOOT_VIDEO_MODE, 0x00000004
# -----------------------------------------------------------------------------
# This is the flag combination that we prepare for Grub
# to read at kernel load time.
.equ MULTIBOOT_HEADER_FLAGS, (MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO)
# Grub reads this value to make sure it loads a kernel
# and not just garbage.
.equ MULTIBOOT_CHECKSUM, -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
.equ LOAD_MEMORY_ADDRESS, 0x00000000
# reserve (1024*1024) for the stack on a doubleword boundary
.equ KERNEL_STACK_SIZE, 0x100000
# -----------------------------------------------------------------------------
# -----------------------------------------------------------------------------
.pushsection .note.name, "a", @note
.align 4
.long 2f - 1f /* namesz */
.long 4f - 3f /* descsz */
.long 18 /* type */
1:.asciz "MentOS" /* name */
2:.align 4
3:.long boot_entry /* desc */
4:.align 4
.popsection
# -----------------------------------------------------------------------------
# SECTION (multiboot_header)
# -----------------------------------------------------------------------------
.globl multiboot_header
.align 4
# This is the GRUB Multiboot header.
multiboot_header:
# magic
.long MULTIBOOT_HEADER_MAGIC
# flags
.long MULTIBOOT_HEADER_FLAGS
# checksum
.long MULTIBOOT_CHECKSUM
# -----------------------------------------------------------------------------
# SECTION (data)
# -----------------------------------------------------------------------------
# section .data nobits
# align 4096
# -----------------------------------------------------------------------------
# SECTION (text)
# -----------------------------------------------------------------------------
.text
.global boot_entry
boot_entry:
# Clear interrupt flag [IF = 0]; 0xFA
cli
# To set up a stack, we simply set the esp register to point to the top of
# our stack (as it grows downwards).
mov $stack_top, %esp
# pass the initial ESP
push %esp
# pass Multiboot info structure
push %ebx
# pass Multiboot magic number
push %eax
# Call the boot_main() function inside boot.c
call boot_main
# Set interrupt flag [IF = 1]; 0xFA
# Clear interrupts and hang if we return from boot_main
cli
hang:
hlt
jmp hang
.global boot_kernel
boot_kernel:
mov 4(%esp),%edx # stack_pointer
mov 8(%esp),%ebx # entry
mov 12(%esp),%eax # boot info
mov %edx,%esp # set stack pointer
push %eax # push the boot info
call *%ebx # call the kernel main
# -----------------------------------------------------------------------------
# SECTION (bss)
# -----------------------------------------------------------------------------
.global stack_bottom
.global stack_top
.bss
.align 16
stack_bottom:
.skip KERNEL_STACK_SIZE
stack_top:
# the top of the stack is the bottom because the stack counts down
-116
View File
@@ -1,116 +0,0 @@
; MentOS, The Mentoring Operating system project
; @file exception.asm
; @brief
; @copyright (c) 2014-2021 This file is distributed under the MIT License.
; See LICENSE.md for details.
extern isr_handler
; Macro used to define a ISR which does not push an error code.
%macro ISR_NOERR 1
global INT_%1
INT_%1:
cli
; A normal ISR stub that pops a dummy error code to keep a
; uniform stack frame
push 0
push %1
jmp isr_common
%endmacro
; Macro used to define a ISR which pushes an error code.
%macro ISR_ERR 1
global INT_%1
INT_%1:
cli
push %1
jmp isr_common
%endmacro
; -----------------------------------------------------------------------------
; SECTION (text)
; -----------------------------------------------------------------------------
section .text
; Standard X86 interrupt service routines
ISR_NOERR 0
ISR_NOERR 1
ISR_NOERR 2
ISR_NOERR 3
ISR_NOERR 4
ISR_NOERR 5
ISR_NOERR 6
ISR_NOERR 7
ISR_ERR 8
ISR_NOERR 9
ISR_ERR 10
ISR_ERR 11
ISR_ERR 12
ISR_ERR 13
ISR_ERR 14
ISR_NOERR 15
ISR_NOERR 16
ISR_NOERR 17
ISR_NOERR 18
ISR_NOERR 19
ISR_NOERR 20
ISR_NOERR 21
ISR_NOERR 22
ISR_NOERR 23
ISR_NOERR 24
ISR_NOERR 25
ISR_NOERR 26
ISR_NOERR 27
ISR_NOERR 28
ISR_NOERR 29
ISR_NOERR 30
ISR_NOERR 31
ISR_NOERR 80
isr_common:
; Save all registers (eax, ecx, edx, ebx, esp, ebp, esi, edi)
pusha
; Save segment registers
push ds
push es
push fs
push gs
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
; CLD - Azzera la flag di Direzione
; Questa istruzione forza semplicemente a zero la flag di Direzione.
; Quando la flag di direzione vale 0 tutte le istruzioni per la
; manipolazione delle stringhe agiscono in avanti, cioè dagli indirizzi più
; bassi a quelli più alti.
; L'istruzione agisce dunque sui puntatori SI e DI producendo su essi un
; autoincremento proporzionale alla dimensione degli operandi trattati.
; Le sue caratteristiche sono riassunte nella seguente tabella (leggi le
; istruzioni Legenda della Tabella):
cld
; Call the interrupt handler.
push esp
call isr_handler
add esp, 0x4
; Restore segment registers.
pop gs
pop fs
pop es
pop ds
; Restore all registers (eax, ecx, edx, ebx, esp, ebp, esi, edi).
popa
; Cleanup error code and IRQ #
add esp, 0x8
iret ; pops 5 things at once:
; CS, EIP, EFLAGS, SS, and ESP
+116
View File
@@ -0,0 +1,116 @@
# MentOS, The Mentoring Operating system project
# @file exception.asm
# @brief
# @copyright (c) 2014-2021 This file is distributed under the MIT License.
# See LICENSE.md for details.
.extern isr_handler
# Macro used to define a ISR which does not push an error code.
.macro ISR_NOERR ARG1
.globl INT_&ARG1
INT_&ARG1:
cli
# A normal ISR stub that pops a dummy error code to keep a
# uniform stack frame
push $0
push &ARG1
jmp isr_common
.endm
# Macro used to define a ISR which pushes an error code.
.macro ISR_ERR ARG1
.globl INT_&ARG1
INT_&ARG1:
cli
push &ARG1
jmp isr_common
.endm
# -----------------------------------------------------------------------------
# SECTION (text)
# -----------------------------------------------------------------------------
.text
# Standard X86 interrupt service routines
ISR_NOERR 0
ISR_NOERR 1
ISR_NOERR 2
ISR_NOERR 3
ISR_NOERR 4
ISR_NOERR 5
ISR_NOERR 6
ISR_NOERR 7
ISR_ERR 8
ISR_NOERR 9
ISR_ERR 10
ISR_ERR 11
ISR_ERR 12
ISR_ERR 13
ISR_ERR 14
ISR_NOERR 15
ISR_NOERR 16
ISR_NOERR 17
ISR_NOERR 18
ISR_NOERR 19
ISR_NOERR 20
ISR_NOERR 21
ISR_NOERR 22
ISR_NOERR 23
ISR_NOERR 24
ISR_NOERR 25
ISR_NOERR 26
ISR_NOERR 27
ISR_NOERR 28
ISR_NOERR 29
ISR_NOERR 30
ISR_NOERR 31
ISR_NOERR 80
isr_common:
# Save all registers (eax, ecx, edx, ebx, esp, ebp, esi, edi)
pusha
# Save segment registers
push %ds
push %es
push %fs
push %gs
mov $0x10,%ax
mov %ax,%ds
mov %ax,%es
mov %ax,%fs
mov %ax,%gs
# CLD - Azzera la flag di Direzione
# Questa istruzione forza semplicemente a zero la flag di Direzione.
# Quando la flag di direzione vale 0 tutte le istruzioni per la
# manipolazione delle stringhe agiscono in avanti, cioè dagli indirizzi più
# bassi a quelli più alti.
# L'istruzione agisce dunque sui puntatori SI e DI producendo su essi un
# autoincremento proporzionale alla dimensione degli operandi trattati.
# Le sue caratteristiche sono riassunte nella seguente tabella (leggi le
# istruzioni Legenda della Tabella):
cld
# Call the interrupt handler.
push %esp
call isr_handler
add $0x4,%esp
# Restore segment registers.
pop %gs
pop %fs
pop %es
pop %ds
# Restore all registers (eax, ecx, edx, ebx, esp, ebp, esi, edi).
popa
# Cleanup error code and IRQ #
add $0x8,%esp
iret # pops 5 things at once:
# CS, EIP, EFLAGS, SS, and ESP
-30
View File
@@ -1,30 +0,0 @@
; MentOS, The Mentoring Operating system project
; @file gdt.asm
; @brief
; @copyright (c) 2014-2021 This file is distributed under the MIT License.
; See LICENSE.md for details.
global gdt_flush ; Allows the C code to call gdt_flush().
; -----------------------------------------------------------------------------
; SECTION (text)
; -----------------------------------------------------------------------------
section .text
gdt_flush:
mov eax, [esp+4] ; Get the pointer to the GDT, passed as a parameter.
lgdt [eax] ; Load the new GDT pointer
; The data segments selectors (registers), can be easily modified using
; simple mov instruction, but the cs can't be used with mov, so you use:
jmp 0x08:flush
; to load the segment configurations into the the code segment selector.
flush:
mov ax, 0x10 ; 0x10 is the offset in the GDT to our data segment
mov ds, ax ; Load all data segment selectors
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
ret
+28
View File
@@ -0,0 +1,28 @@
# MentOS, The Mentoring Operating system project
# @file gdt.asm
# @brief
# @copyright (c) 2014-2021 This file is distributed under the MIT License.
# See LICENSE.md for details.
.global gdt_flush # Allows the C code to call gdt_flush().
# -----------------------------------------------------------------------------
# SECTION (text)
# -----------------------------------------------------------------------------
.text
gdt_flush:
mov 4(%esp),%eax # Get the pointer to the GDT, passed as a parameter.
lgdt (%eax)
# The data segments selectors (registers), can be easily modified using
# simple mov instruction, but the cs can't be used with mov, so you use:
mov $0x10,%ax # 0x10 is the offset in the GDT to our data segment
mov %ax,%ds # Load all data segment selectors
mov %ax,%es
mov %ax,%fs
mov %ax,%gs
mov %ax,%ss
# to load the segment configurations into the the code segment selector.
ret
-17
View File
@@ -1,17 +0,0 @@
; MentOS, The Mentoring Operating system project
; @file idt.asm
; @brief
; @copyright (c) 2014-2021 This file is distributed under the MIT License.
; See LICENSE.md for details.
global idt_flush ; Allows the C code to call idt_flush().
; -----------------------------------------------------------------------------
; SECTION (text)
; -----------------------------------------------------------------------------
section .text
idt_flush:
mov eax, [esp+4] ; Get the pointer to the IDT, passed as a parameter.
lidt [eax] ; Load the IDT pointer.
ret
+17
View File
@@ -0,0 +1,17 @@
# MentOS, The Mentoring Operating system project
# @file idt.asm
# @brief
# @copyright (c) 2014-2021 This file is distributed under the MIT License.
# See LICENSE.md for details.
.global idt_flush # Allows the C code to call idt_flush().
# -----------------------------------------------------------------------------
# SECTION (text)
# -----------------------------------------------------------------------------
.text
idt_flush:
mov 4(%esp),%eax # Get the pointer to the IDT, passed as a parameter.
lidt (%eax)
ret
+55 -57
View File
@@ -1,28 +1,26 @@
; MentOS, The Mentoring Operating system project # MentOS, The Mentoring Operating system project
; @file interrupt.asm # @file interrupt.asm
; @brief # @brief
; @copyright (c) 2014-2021 This file is distributed under the MIT License. # @copyright (c) 2014-2021 This file is distributed under the MIT License.
; See LICENSE.md for details. # See LICENSE.md for details.
extern irq_handler .extern irq_handler
%macro IRQ 2 .macro IRQ ARG1, ARG2
global IRQ_%1 .globl IRQ_&ARG1
IRQ_%1: IRQ_&ARG1:
cli ; disable interrupt line cli # disable interrupt line
; A normal ISR stub that pops a dummy error code to keep a push $0
; uniform stack frame push &ARG2
push 0
push %2 ; irq number
jmp irq_common jmp irq_common
%endmacro .endm
; ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
; SECTION (text) # SECTION (text)
; ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
section .text .text
; 32 is the first irq, 47 is the last one. DO NOT CHANGE THESE NUMBERS. # 32 is the first irq, 47 is the last one. DO NOT CHANGE THESE NUMBERS.
IRQ 0, 32 IRQ 0, 32
IRQ 1, 33 IRQ 1, 33
IRQ 2, 34 IRQ 2, 34
@@ -40,52 +38,52 @@ IRQ 13, 45
IRQ 14, 46 IRQ 14, 46
IRQ 15, 47 IRQ 15, 47
irq_common: irq_common:
;==== Save CPU registers =================================================== # ==== Save CPU registers ===================================================
; when an irq occurs, the following registers are already pushed on stack: # when an irq occurs, the following registers are already pushed on stack:
; eip, cs, eflags, useresp, ss # eip, cs, eflags, useresp, ss
; Save registers: eax, ecx, edx, ebx, esp, ebp, esi, edi # Save registers: eax, ecx, edx, ebx, esp, ebp, esi, edi
pusha pusha
; Save segment registers # Save segment registers
push ds push %ds
push es push %es
push fs push %fs
push gs push %gs
;--------------------------------------------------------------------------- # ---------------------------------------------------------------------------
;==== ensure we are using kernel data segment ============================== # ==== ensure we are using kernel data segment ==============================
mov ax, 0x10 mov $0x10,%ax
mov ds, ax mov %ax,%ds
mov es, ax mov %ax,%es
mov fs, ax mov %ax,%fs
mov gs, ax mov %ax,%gs
cld cld
;--------------------------------------------------------------------------- # ---------------------------------------------------------------------------
;==== Call the interrupt handler =========================================== # ==== Call the interrupt handler ===========================================
; The argument passed is a pointer to an Interrupt_State struct, # The argument passed is a pointer to an Interrupt_State struct,
; which describes the stack layout for all interrupts. # which describes the stack layout for all interrupts.
push esp push %esp
call irq_handler call irq_handler
add esp, $4 ; remove esp from stack add $0x04, %esp # remove esp from stack
;--------------------------------------------------------------------------- # ---------------------------------------------------------------------------
;==== Restore registers ==================================================== # ==== Restore registers ====================================================
; restore segment registers # restore segment registers
pop gs pop %gs
pop fs pop %fs
pop es pop %es
pop ds pop %ds
; restore registers: eax, ecx, edx, ebx, esp, ebp, esi, edi # restore registers: eax, ecx, edx, ebx, esp, ebp, esi, edi
popa popa
;--------------------------------------------------------------------------- # ---------------------------------------------------------------------------
; Cleanup error code and IRQ # # Cleanup error code and IRQ #
add esp, $8 add $0x08, %esp
; return to process # return to process
iret ; pops 5 things at once: iret # pops 5 things at once:
; CS, EIP, EFLAGS, SS, and ESP # CS, EIP, EFLAGS, SS, and ESP
+89
View File
@@ -0,0 +1,89 @@
# MentOS, The Mentoring Operating system project
# @file interrupt.asm
# @brief
# @copyright (c) 2014-2021 This file is distributed under the MIT License.
# See LICENSE.md for details.
.extern irq_handler
.macro IRQ ARG1, ARG2
.globl IRQ_&ARG1
IRQ_&ARG1:
cli # disable interrupt line
push $0
push &ARG2
jmp irq_common
.endm
# -----------------------------------------------------------------------------
# SECTION (text)
# -----------------------------------------------------------------------------
.text
# 32 is the first irq, 47 is the last one. DO NOT CHANGE THESE NUMBERS.
IRQ 0, 32
IRQ 1, 33
IRQ 2, 34
IRQ 3, 35
IRQ 4, 36
IRQ 5, 37
IRQ 6, 38
IRQ 7, 39
IRQ 8, 40
IRQ 9, 41
IRQ 10, 42
IRQ 11, 43
IRQ 12, 44
IRQ 13, 45
IRQ 14, 46
IRQ 15, 47
irq_common:
# ==== Save CPU registers ===================================================
# when an irq occurs, the following registers are already pushed on stack:
# eip, cs, eflags, useresp, ss
# Save registers: eax, ecx, edx, ebx, esp, ebp, esi, edi
pusha
# Save segment registers
push %ds
push %es
push %fs
push %gs
# ---------------------------------------------------------------------------
# ==== ensure we are using kernel data segment ==============================
mov $0x10,%ax
mov %ax,%ds
mov %ax,%es
mov %ax,%fs
mov %ax,%gs
cld
# ---------------------------------------------------------------------------
# ==== Call the interrupt handler ===========================================
# The argument passed is a pointer to an Interrupt_State struct,
# which describes the stack layout for all interrupts.
push %esp
call irq_handler
add $0x04, %esp # remove esp from stack
# ---------------------------------------------------------------------------
# ==== Restore registers ====================================================
# restore segment registers
pop %gs
pop %fs
pop %es
pop %ds
# restore registers: eax, ecx, edx, ebx, esp, ebp, esi, edi
popa
# ---------------------------------------------------------------------------
# Cleanup error code and IRQ #
add $0x08, %esp
# return to process
iret # pops 5 things at once:
# CS, EIP, EFLAGS, SS, and ESP
-17
View File
@@ -1,17 +0,0 @@
; MentOS, The Mentoring Operating system project
; @file tss.asm
; @brief
; @copyright (c) 2014-2021 This file is distributed under the MIT License.
; See LICENSE.md for details.
global tss_flush
; -----------------------------------------------------------------------------
; SECTION (text)
; -----------------------------------------------------------------------------
section .text
tss_flush:
mov ax, 0x28
ltr ax
ret
+18
View File
@@ -0,0 +1,18 @@
# MentOS, The Mentoring Operating system project
# @file tss.asm
# @brief
# @copyright (c) 2014-2021 This file is distributed under the MIT License.
# See LICENSE.md for details.
.global tss_flush
# -----------------------------------------------------------------------------
# SECTION (text)
# -----------------------------------------------------------------------------
.text
tss_flush:
mov $0x28,%ax
ltr %ax
ret
+1 -1
View File
@@ -6,7 +6,7 @@
// Setup the logging for this file (do this before any other include). // Setup the logging for this file (do this before any other include).
#include "sys/kernel_levels.h" // Include kernel log levels. #include "sys/kernel_levels.h" // Include kernel log levels.
#define __DEBUG_HEADER__ "[ELF ]" ///< Change header. #define __DEBUG_HEADER__ "[ELF ]" ///< Change header.
#define __DEBUG_LEVEL__ LOGLEVEL_NOTICE ///< Set log level. #define __DEBUG_LEVEL__ LOGLEVEL_DEBUG ///< Set log level.
#include "io/debug.h" // Include debugging functions. #include "io/debug.h" // Include debugging functions.
#include "assert.h" #include "assert.h"
+23 -45
View File
@@ -43,28 +43,6 @@ char *module_start[MAX_MODULES];
/// Describe end address of grub multiboot modules. /// Describe end address of grub multiboot modules.
char *module_end[MAX_MODULES]; char *module_end[MAX_MODULES];
// Everything is defined in kernel.ld.
/// Points at the multiheader grub info, starting address.
extern uint32_t _multiboot_header_start;
/// Points at the multiheader grub info, ending address.
extern uint32_t _multiboot_header_end;
/// Points at the kernel code, starting address.
extern uint32_t _text_start;
/// Points at the kernel code, ending address.
extern uint32_t _text_end;
/// Points at the read-only kernel data, starting address.
extern uint32_t _rodata_start;
/// Points at the read-only kernel data, ending address.
extern uint32_t _rodata_end;
/// Points at the read-write kernel data initialized, starting address.
extern uint32_t _data_start;
/// Points at the read-write kernel data initialized, ending address.
extern uint32_t _data_end;
/// Points at the read-write kernel data uninitialized an kernel stack, starting address.
extern uint32_t _bss_start;
/// Points at the read-write kernel data uninitialized an kernel stack, ending address.
extern uint32_t _bss_end;
/// Points at the top of the kernel stack. /// Points at the top of the kernel stack.
extern uint32_t stack_top; extern uint32_t stack_top;
/// Points at the bottom of the kernel stack. /// Points at the bottom of the kernel stack.
@@ -107,8 +85,8 @@ int kmain(boot_info_t *boot_informations)
boot_info = *boot_informations; boot_info = *boot_informations;
// Am I booted by a Multiboot-compliant boot loader? // Am I booted by a Multiboot-compliant boot loader?
if (boot_info.magic != MULTIBOOT_BOOTLOADER_MAGIC) { if (boot_info.magic != MULTIBOOT_BOOTLOADER_MAGIC) {
printf("Invalid magic number: 0x%x\n", boot_info.magic); pr_emerg("Invalid magic number: 0x%x\n", boot_info.magic);
return 1; while (1) {}
} }
// Set the initial esp. // Set the initial esp.
initial_esp = boot_info.stack_base; initial_esp = boot_info.stack_base;
@@ -131,7 +109,7 @@ int kmain(boot_info_t *boot_informations)
printf("Initialize modules..."); printf("Initialize modules...");
if (!init_modules(boot_info.multiboot_header)) { if (!init_modules(boot_info.multiboot_header)) {
print_fail(); print_fail();
return 1; while (1) {}
} }
print_ok(); print_ok();
@@ -140,7 +118,7 @@ int kmain(boot_info_t *boot_informations)
printf("Initialize physical memory manager..."); printf("Initialize physical memory manager...");
if (!pmmngr_init(&boot_info)) { if (!pmmngr_init(&boot_info)) {
print_fail(); print_fail();
return 1; while (1) {}
} }
print_ok(); print_ok();
@@ -216,7 +194,7 @@ int kmain(boot_info_t *boot_informations)
printf("Initialize ATA devices..."); printf("Initialize ATA devices...");
if (ata_initialize()) { if (ata_initialize()) {
pr_emerg("Failed to initialize ATA devices!\n"); pr_emerg("Failed to initialize ATA devices!\n");
return 1; while (1) {}
} }
print_ok(); print_ok();
@@ -225,7 +203,7 @@ int kmain(boot_info_t *boot_informations)
printf("Initialize EXT2 filesystem..."); printf("Initialize EXT2 filesystem...");
if (ext2_initialize()) { if (ext2_initialize()) {
pr_emerg("Failed to initialize EXT2 filesystem!\n"); pr_emerg("Failed to initialize EXT2 filesystem!\n");
return 1; while (1) {}
} }
print_ok(); print_ok();
@@ -234,7 +212,7 @@ int kmain(boot_info_t *boot_informations)
printf("Mount EXT2 filesystem..."); printf("Mount EXT2 filesystem...");
if (do_mount("ext2", "/", "/dev/hda")) { if (do_mount("ext2", "/", "/dev/hda")) {
pr_emerg("Failed to mount EXT2 filesystem...\n"); pr_emerg("Failed to mount EXT2 filesystem...\n");
return 1; while (1) {}
} }
print_ok(); print_ok();
@@ -244,7 +222,7 @@ int kmain(boot_info_t *boot_informations)
if (procfs_module_init()) { if (procfs_module_init()) {
print_fail(); print_fail();
pr_emerg("Failed to register `procfs`!\n"); pr_emerg("Failed to register `procfs`!\n");
return 1; while (1) {}
} }
print_ok(); print_ok();
@@ -253,7 +231,7 @@ int kmain(boot_info_t *boot_informations)
printf(" Mounting 'procfs'..."); printf(" Mounting 'procfs'...");
if (do_mount("procfs", "/proc", NULL)) { if (do_mount("procfs", "/proc", NULL)) {
pr_emerg("Failed to mount procfs at `/proc`!\n"); pr_emerg("Failed to mount procfs at `/proc`!\n");
return 1; while (1) {}
} }
print_ok(); print_ok();
@@ -263,7 +241,7 @@ int kmain(boot_info_t *boot_informations)
if (procv_module_init()) { if (procv_module_init()) {
print_fail(); print_fail();
pr_emerg("Failed to initialize `/proc/video`!\n"); pr_emerg("Failed to initialize `/proc/video`!\n");
return 1; while (1) {}
} }
print_ok(); print_ok();
@@ -273,7 +251,7 @@ int kmain(boot_info_t *boot_informations)
if (procs_module_init()) { if (procs_module_init()) {
print_fail(); print_fail();
pr_emerg("Failed to initialize proc system entries!\n"); pr_emerg("Failed to initialize proc system entries!\n");
return 1; while (1) {}
} }
print_ok(); print_ok();
@@ -283,7 +261,7 @@ int kmain(boot_info_t *boot_informations)
if (procipc_module_init()) { if (procipc_module_init()) {
print_fail(); print_fail();
pr_emerg("Failed to initialize the IPC information system!\n"); pr_emerg("Failed to initialize the IPC information system!\n");
return 1; while (1) {}
} }
print_ok(); print_ok();
@@ -293,7 +271,7 @@ int kmain(boot_info_t *boot_informations)
if (sem_init()) { if (sem_init()) {
print_fail(); print_fail();
pr_emerg("Failed to initialize the IPC/SEM system!\n"); pr_emerg("Failed to initialize the IPC/SEM system!\n");
return 1; while (1) {}
} }
print_ok(); print_ok();
@@ -303,7 +281,7 @@ int kmain(boot_info_t *boot_informations)
if (msq_init()) { if (msq_init()) {
print_fail(); print_fail();
pr_emerg("Failed to initialize the IPC/MSQ system!\n"); pr_emerg("Failed to initialize the IPC/MSQ system!\n");
return 1; while (1) {}
} }
print_ok(); print_ok();
@@ -313,7 +291,7 @@ int kmain(boot_info_t *boot_informations)
if (shm_init()) { if (shm_init()) {
print_fail(); print_fail();
pr_emerg("Failed to initialize the IPC/SHM system!\n"); pr_emerg("Failed to initialize the IPC/SHM system!\n");
return 1; while (1) {}
} }
print_ok(); print_ok();
@@ -328,7 +306,7 @@ int kmain(boot_info_t *boot_informations)
if (ps2_initialize()) { if (ps2_initialize()) {
print_fail(); print_fail();
pr_emerg("Failed to initialize proc system entries!\n"); pr_emerg("Failed to initialize proc system entries!\n");
return 1; while (1) {}
} }
print_ok(); print_ok();
@@ -365,7 +343,7 @@ int kmain(boot_info_t *boot_informations)
printf("Init process management..."); printf("Init process management...");
if (!init_tasking()) { if (!init_tasking()) {
print_fail(); print_fail();
return 1; while (1) {}
} }
print_ok(); print_ok();
@@ -375,7 +353,7 @@ int kmain(boot_info_t *boot_informations)
printf("Initialize scheduler feedback system..."); printf("Initialize scheduler feedback system...");
if (!scheduler_feedback_init()) { if (!scheduler_feedback_init()) {
print_fail(); print_fail();
return 1; while (1) {}
} }
print_ok(); print_ok();
#endif #endif
@@ -385,7 +363,7 @@ int kmain(boot_info_t *boot_informations)
printf("Initialize scheduler feedback system (2)..."); printf("Initialize scheduler feedback system (2)...");
if (procfb_module_init()) { if (procfb_module_init()) {
print_fail(); print_fail();
return 1; while (1) {}
} }
print_ok(); print_ok();
@@ -395,7 +373,7 @@ int kmain(boot_info_t *boot_informations)
task_struct *init_p = process_create_init("/bin/init"); task_struct *init_p = process_create_init("/bin/init");
if (!init_p) { if (!init_p) {
print_fail(); print_fail();
return 1; while (1) {}
} }
print_ok(); print_ok();
@@ -404,7 +382,7 @@ int kmain(boot_info_t *boot_informations)
printf("Initialize floating point unit..."); printf("Initialize floating point unit...");
if (!fpu_install()) { if (!fpu_install()) {
print_fail(); print_fail();
return 1; while (1) {}
} }
print_ok(); print_ok();
@@ -413,7 +391,7 @@ int kmain(boot_info_t *boot_informations)
printf("Initialize signals..."); printf("Initialize signals...");
if (!signals_init()) { if (!signals_init()) {
print_fail(); print_fail();
return 1; while (1) {}
} }
print_ok(); print_ok();
@@ -432,5 +410,5 @@ int kmain(boot_info_t *boot_informations)
for (;;) {} for (;;) {}
// We should not be here. // We should not be here.
pr_emerg("Dear developer, we have to talk...\n"); pr_emerg("Dear developer, we have to talk...\n");
return 1; while (1) {}
} }
+10 -4
View File
@@ -4,10 +4,10 @@
/// See LICENSE.md for details. /// See LICENSE.md for details.
// Setup the logging for this file (do this before any other include). // Setup the logging for this file (do this before any other include).
#include "sys/kernel_levels.h" // Include kernel log levels. #include "sys/kernel_levels.h" // Include kernel log levels.
#define __DEBUG_HEADER__ "[PROC ]" ///< Change header. #define __DEBUG_HEADER__ "[PROC ]" ///< Change header.
#define __DEBUG_LEVEL__ LOGLEVEL_NOTICE ///< Set log level. #define __DEBUG_LEVEL__ LOGLEVEL_DEBUG ///< Set log level.
#include "io/debug.h" // Include debugging functions. #include "io/debug.h" // Include debugging functions.
#include "assert.h" #include "assert.h"
#include "elf/elf.h" #include "elf/elf.h"
@@ -91,11 +91,15 @@ static int __reset_process(task_struct *task)
return 0; return 0;
} }
pr_debug("Switching to task page directory.\n");
// Save the current page directory. // Save the current page directory.
page_directory_t *crtdir = paging_get_current_directory(); page_directory_t *crtdir = paging_get_current_directory();
// FIXME: Now to clear the stack a pgdir switch is made, it should be a kernel mmapping. // FIXME: Now to clear the stack a pgdir switch is made, it should be a kernel mmapping.
paging_switch_directory_va(task->mm->pgd); paging_switch_directory_va(task->mm->pgd);
pr_debug("Clean stack (%p).\n", task->mm->start_stack);
// Clean stack space. // Clean stack space.
memset((char *)task->mm->start_stack, 0, DEFAULT_STACK_SIZE); memset((char *)task->mm->start_stack, 0, DEFAULT_STACK_SIZE);
// Set the base address of the stack. // Set the base address of the stack.
@@ -105,6 +109,8 @@ static int __reset_process(task_struct *task)
// Enable the interrupts. // Enable the interrupts.
task->thread.regs.eflags = task->thread.regs.eflags | EFLAG_IF; task->thread.regs.eflags = task->thread.regs.eflags | EFLAG_IF;
pr_debug("Switching to previous page directory.\n");
// Restore previous pgdir // Restore previous pgdir
paging_switch_directory(crtdir); paging_switch_directory(crtdir);
-87
View File
@@ -1,87 +0,0 @@
; MentOS, The Mentoring Operating system project
; @file user.asm
; @brief
; @copyright (c) 2014-2021 This file is distributed under the MIT License.
; See LICENSE.md for details.
; Enter userspace (ring3) (from Ring 0, namely Kernel)
; Usage: enter_userspace(uintptr_t location, uintptr_t stack);
; On stack
; | stack | [ebp + 0x0C] ARG1
; | location | [ebp + 0x08] ARG0
; | return address | [ebp + 0x04]
; | EBP | [ebp + 0x00]
; | SS |
; | ESP |
; | EFLAGS |
; | CS |
; | EIP |
; We can use the following macros to access the arguments ONLY AFTER 0x23 is
; pushed onto the stack, in fact, the first argument is after 0x08 because
; we just pushed first `ebp` and then `0x23`.
%define ARG0 [ebp + 0x08] ; Argument 0
%define ARG1 [ebp + 0x0C] ; Argument 1
%define ARG2 [ebp + 0x10] ; Argument 2
%define ARG3 [ebp + 0x14] ; Argument 3
%define ARG4 [ebp + 0x18] ; Argument 4
; -----------------------------------------------------------------------------
; SECTION (text)
; -----------------------------------------------------------------------------
section .text
global enter_userspace ; Allows the C code to call enter_userspace(...).
enter_userspace:
push ebp ; Save current ebp
mov ebp, esp ; open a new stack frame
;==== Segment selector =====================================================
mov ax, 0x23
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
; we don't need to worry about SS. it's handled by iret
;---------------------------------------------------------------------------
; We have to prepare the following stack before executing iret
; SS --> Segment selector
; ESP --> Stack address
; EFLAGS --> CPU state flgas
; CS --> Code segment
; EIP --> Entry point
;
;==== User data segmenet with bottom 2 bits set for ring3 ?=================
push 0x23 ; push SS on Kernel's stack
;---------------------------------------------------------------------------
;==== (ESP) Stack address ==================================================
mov eax, ARG1 ; get uintptr_t stack
push eax ; push process's stack address on Kernel's stack
;---------------------------------------------------------------------------
;==== (EFLAGS) =============================================================
pushf ; push EFLAGS into Kernel's stack
pop eax ; pop EFLAGS into eax
or eax, 0x200 ; enable interrupt
push eax ; push new EFLAGS on Kernel's stack
;---------------------------------------------------------------------------
;==== (CS) Code Segment ====================================================
push 0x1b ;
;---------------------------------------------------------------------------
;==== (EIP) Entry point ====================================================
mov eax, ARG0 ; get uintptr_t location
push eax ; push uintptr_t location on Kernel's stack
;---------------------------------------------------------------------------
iret ; interrupt return
pop ebp
ret
; WE SHOULD NOT STILL BE HERE! :(p
+78
View File
@@ -0,0 +1,78 @@
# MentOS, The Mentoring Operating system project
# @file user.asm
# @brief
# @copyright (c) 2014-2021 This file is distributed under the MIT License.
# See LICENSE.md for details.
# Enter userspace (ring3) (from Ring 0, namely Kernel)
# Usage: enter_userspace(uintptr_t location, uintptr_t stack);
# On stack
# | stack | [ebp + 0x0C] ARG1
# | location | [ebp + 0x08] ARG0
# | return address | [ebp + 0x04]
# | EBP | [ebp + 0x00]
# | SS |
# | ESP |
# | EFLAGS |
# | CS |
# | EIP |
# -----------------------------------------------------------------------------
# SECTION (text)
# -----------------------------------------------------------------------------
.text
.global enter_userspace # Allows the C code to call enter_userspace(...).
enter_userspace:
push %ebp # Save current ebp
mov %esp,%ebp # open a new stack frame
# ==== Segment selector =====================================================
mov $0x23,%ax
mov %ax,%ds
mov %ax,%es
mov %ax,%fs
mov %ax,%gs
# we don't need to worry about SS. it's handled by iret
# ---------------------------------------------------------------------------
# We have to prepare the following stack before executing iret
# SS --> Segment selector
# ESP --> Stack address
# EFLAGS --> CPU state flgas
# CS --> Code segment
# EIP --> Entry point
#
# ==== User data segmenet with bottom 2 bits set for ring3 ?=================
push $0x23 # push SS on Kernel's stack
# ---------------------------------------------------------------------------
# ==== (ESP) Stack address ==================================================
mov 0x0C(%ebp),%eax # get uintptr_t stack
push %eax # push process's stack address on Kernel's stack
# ---------------------------------------------------------------------------
# ==== (EFLAGS) =============================================================
pushf # push EFLAGS into Kernel's stack
pop %eax # pop EFLAGS into eax
or $0x200,%eax # enable interrupt
push %eax # push new EFLAGS on Kernel's stack
# ---------------------------------------------------------------------------
# ==== (CS) Code Segment ====================================================
push $0x1b #
# ---------------------------------------------------------------------------
# ==== (EIP) Entry point ====================================================
mov 0x08(%ebp),%eax # get uintptr_t location
push %eax # push uintptr_t location on Kernel's stack
# ---------------------------------------------------------------------------
iret # interrupt return
pop %ebp
ret
# WE SHOULD NOT STILL BE HERE! :(p
+62 -56
View File
@@ -1,57 +1,3 @@
# =============================================================================
# Author: Enrico Fraccaroli
# =============================================================================
# Set the minimum required version of cmake.
cmake_minimum_required(VERSION 3.1...3.22)
# Initialize the project.
project(programs C)
# =============================================================================
# C WARNINGs
# =============================================================================
# We need to specify the name of the entry function.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -u_start")
# Warning flags.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wpedantic")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pedantic-errors")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wshadow")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99")
# Disable some specific warnings.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-function")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-variable")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unknown-pragmas")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-missing-braces")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-command-line-argument")
# Set the compiler options.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -static")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -nostdlib")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -nostdinc")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-builtin")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-stack-protector")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-pic")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fomit-frame-pointer")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=i686")
if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 10)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fcommon")
endif()
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g3")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ggdb")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0")
elseif(CMAKE_BUILD_TYPE STREQUAL "Release")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3")
endif(CMAKE_BUILD_TYPE STREQUAL "Debug")
# ============================================================================= # =============================================================================
# BUILD # BUILD
# ============================================================================= # =============================================================================
@@ -88,11 +34,44 @@ set(PROGRAMS
) )
# Set the directory where the compiled binaries will be placed. # Set the directory where the compiled binaries will be placed.
set(MENTOS_BIN_DIR ${CMAKE_SOURCE_DIR}/files/bin) set(MENTOS_BIN_DIR ${CMAKE_SOURCE_DIR}/files/bin)
# Create the directory.
execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${MENTOS_BIN_DIR})
# Add the executables (manually).
set(PROGRAMS
init.c
cpuid.c
clear.c
date.c
ls.c
logo.c
nice.c
poweroff.c
rm.c
shell.c
uname.c
cat.c
echo.c
login.c
mkdir.c
pwd.c
rmdir.c
showpid.c
touch.c
env.c
ps.c
kill.c
ipcrm.c
ipcs.c
sleep.c
man.c
edit.c
uptime.c
)
foreach(FILE_NAME ${PROGRAMS}) foreach(FILE_NAME ${PROGRAMS})
# Prepare the program name. # Prepare the program name.
string(REPLACE ".c" "" EXECUTABLE_NAME ${FILE_NAME}) string(REPLACE ".c" "" EXECUTABLE_NAME ${FILE_NAME})
# Set the name of the target. # Set the name of the target.
set(TARGET_NAME prog_${EXECUTABLE_NAME}) set(TARGET_NAME prog_${EXECUTABLE_NAME})
@@ -108,11 +87,28 @@ foreach(FILE_NAME ${PROGRAMS})
string(RANDOM LENGTH 1 ALPHABET 0123456789AB RANDOM_SEED ${RAND_HASH} TEXADDR_FIRST) string(RANDOM LENGTH 1 ALPHABET 0123456789AB RANDOM_SEED ${RAND_HASH} TEXADDR_FIRST)
set(TEXT_ADDR 0x${TEXADDR_FIRST}${TEXADDR_INFIX}0000) set(TEXT_ADDR 0x${TEXADDR_FIRST}${TEXADDR_INFIX}0000)
# =========================================================================
# EXECUTABLE
# =========================================================================
set(TARGET_NAME prog_${EXECUTABLE_NAME})
# =========================================================================
# TEXT ADDRESS
# =========================================================================
# Randomize .text section address so when debugging symbols don't clash.
# The allowed range is from 256MB to 2.75GB
# Minimum allowed address: 0x10000000
# Max allowed address: 0xB0000000
string(MD5 RAND_HASH ${FILE_NAME})
string(SUBSTRING ${RAND_HASH} 1 3 TEXADDR_INFIX)
string(RANDOM LENGTH 1 ALPHABET 0123456789AB RANDOM_SEED ${RAND_HASH} TEXADDR_FIRST)
set(TEXT_ADDR 0x${TEXADDR_FIRST}${TEXADDR_INFIX}0000)
# ========================================================================= # =========================================================================
# EXECUTABLE # EXECUTABLE
# ========================================================================= # =========================================================================
# Create the target. # Create the target.
add_executable(${TARGET_NAME} ${CMAKE_SOURCE_DIR}/programs/${FILE_NAME}) add_executable(${TARGET_NAME} ${FILE_NAME})
# Add the dependency to libc. # Add the dependency to libc.
add_dependencies(${TARGET_NAME} libc) add_dependencies(${TARGET_NAME} libc)
# Add the includes. # Add the includes.
@@ -128,6 +124,16 @@ foreach(FILE_NAME ${PROGRAMS})
# Set the output name. # Set the output name.
set_target_properties(${TARGET_NAME} PROPERTIES OUTPUT_NAME "${EXECUTABLE_NAME}") set_target_properties(${TARGET_NAME} PROPERTIES OUTPUT_NAME "${EXECUTABLE_NAME}")
target_link_libraries(${TARGET_NAME} libc)
# We need to specify the name of the entry function.
target_compile_options(${TARGET_NAME} PRIVATE -u_start)
# Add the linking properties.
set_target_properties(${TARGET_NAME} PROPERTIES LINK_FLAGS "-Wl,-Ttext=${TEXT_ADDR},-e_start,-melf_i386")
# Set the output directory.
set_target_properties(${TARGET_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${MENTOS_BIN_DIR}")
# Set the output name.
set_target_properties(${TARGET_NAME} PROPERTIES OUTPUT_NAME "${EXECUTABLE_NAME}")
# Append the program name to the list of all the executables. # Append the program name to the list of all the executables.
list(APPEND ALL_EXECUTABLES ${TARGET_NAME}) list(APPEND ALL_EXECUTABLES ${TARGET_NAME})
endforeach() endforeach()
+32 -87
View File
@@ -1,95 +1,40 @@
# =============================================================================
# Author: Enrico Fraccaroli
# =============================================================================
# Set the minimum required version of cmake.
cmake_minimum_required(VERSION 3.1...3.22)
# Initialize the project.
project(tests C)
# =============================================================================
# C WARNINGs
# =============================================================================
# We need to specify the name of the entry function.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -u_start")
# Warning flags.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wpedantic")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pedantic-errors")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wshadow")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99")
# Disable some specific warnings.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-function")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-variable")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unknown-pragmas")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-missing-braces")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-command-line-argument")
# Set the compiler options.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -static")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -nostdlib")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -nostdinc")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-builtin")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-stack-protector")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-pic")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fomit-frame-pointer")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=i686")
if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 10)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fcommon")
endif()
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g3")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ggdb")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0")
elseif(CMAKE_BUILD_TYPE STREQUAL "Release")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3")
endif(CMAKE_BUILD_TYPE STREQUAL "Debug")
# ============================================================================= # =============================================================================
# BUILD # BUILD
# ============================================================================= # =============================================================================
# Add your file in this list.
set(TESTS
t_gid.c
t_alarm.c
t_periodic3.c
t_setenv.c
t_itimer.c
t_fork.c
t_semget.c
t_exec.c
t_sleep.c
t_periodic2.c
t_sigfpe.c
t_sigmask.c
t_getenv.c
t_sigusr.c
t_exec_callee.c
t_shmget.c
t_stopcont.c
t_semop.c
t_sigaction.c
t_schedfb.c
t_siginfo.c
t_groups.c
t_semflg.c
t_abort.c
t_msgget.c
t_periodic1.c
t_kill.c
t_shm_write.c
t_mem.c
t_shm_read.c
)
# Set the directory where the compiled binaries will be placed. # Set the directory where the compiled binaries will be placed.
set(MENTOS_TESTS_DIR ${CMAKE_SOURCE_DIR}/files/bin/tests) set(MENTOS_TESTS_DIR ${CMAKE_SOURCE_DIR}/files/bin/tests)
# Create the directory.
execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${MENTOS_TESTS_DIR})
# Add the executables (manually).
set(TESTS
t_mem.c
t_fork.c
# Real-time programs
t_periodic1.c
t_periodic2.c
t_periodic3.c
# Exec
t_exec.c
t_exec_callee.c
# Test environmental variables.
t_setenv.c
t_getenv.c
# Test: signals.
t_stopcont.c
t_sigusr.c
t_abort.c
t_sigfpe.c
t_siginfo.c
t_sleep.c
t_sigaction.c
t_sigmask.c
t_groups.c
t_alarm.c
t_kill.c
t_itimer.c
t_gid.c
)
foreach(FILE_NAME ${TESTS}) foreach(FILE_NAME ${TESTS})
# Prepare the program name. # Prepare the program name.
+3 -2
View File
@@ -16,7 +16,6 @@ void sig_handler(int sig)
{ {
printf("handler(%d) : Starting handler.\n", sig); printf("handler(%d) : Starting handler.\n", sig);
if (sig == SIGABRT) { if (sig == SIGABRT) {
static int counter = 0; static int counter = 0;
counter += 1; counter += 1;
@@ -38,8 +37,10 @@ int main(int argc, char *argv[])
if (sigaction(SIGABRT, &action, NULL) == -1) { if (sigaction(SIGABRT, &action, NULL) == -1) {
printf("Failed to set signal handler (%s).\n", SIGABRT, strerror(errno)); printf("Failed to set signal handler (%s).\n", SIGABRT, strerror(errno));
return 1; return EXIT_FAILURE;
} }
abort(); abort();
return EXIT_SUCCESS;
} }
+3 -4
View File
@@ -39,12 +39,11 @@ int main(int argc, char *argv[])
action.sa_handler = alarm_handler; action.sa_handler = alarm_handler;
if (sigaction(SIGALRM, &action, NULL) == -1) { if (sigaction(SIGALRM, &action, NULL) == -1) {
printf("Failed to set signal handler (%s).\n", SIGALRM, strerror(errno)); printf("Failed to set signal handler (%s).\n", SIGALRM, strerror(errno));
return 1; return EXIT_FAILURE;
} }
alarm(5); alarm(5);
while(1) { } while (1) {}
return 0; return EXIT_SUCCESS;
} }
+5 -5
View File
@@ -22,12 +22,12 @@ int main(int argc, char *argv[])
int status; int status;
if (argc != 2) { if (argc != 2) {
__print_usage(argc, argv); __print_usage(argc, argv);
return 1; return EXIT_FAILURE;
} }
if (setenv("ENV_VAR", "pwd0", 0) == -1) { if (setenv("ENV_VAR", "pwd0", 0) == -1) {
printf("Failed to set env: `ENV_VAR`\n"); printf("Failed to set env: `ENV_VAR`\n");
return 1; return EXIT_FAILURE;
} }
char *file = "echo"; char *file = "echo";
@@ -54,11 +54,11 @@ int main(int argc, char *argv[])
execvpe(file, exec_argv, exec_envp); execvpe(file, exec_argv, exec_envp);
} else { } else {
__print_usage(argc, argv); __print_usage(argc, argv);
return 1; return EXIT_FAILURE;
} }
printf("Exec failed.\n"); printf("Exec failed.\n");
return 1; return EXIT_FAILURE;
} }
wait(&status); wait(&status);
return 0; return EXIT_SUCCESS;
} }
+2 -2
View File
@@ -11,8 +11,8 @@ int main(int argc, char *argv[])
char *ENV_VAR = getenv("ENV_VAR"); char *ENV_VAR = getenv("ENV_VAR");
if (ENV_VAR == NULL) { if (ENV_VAR == NULL) {
printf("Failed to get env: `ENV_VAR`\n"); printf("Failed to get env: `ENV_VAR`\n");
return 1; return EXIT_FAILURE;
} }
printf("ENV_VAR = %s\n", ENV_VAR); printf("ENV_VAR = %s\n", ENV_VAR);
return 0; return EXIT_SUCCESS;
} }
+2 -2
View File
@@ -12,7 +12,7 @@
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
if (argc != 2) { if (argc != 2) {
return 1; return EXIT_FAILURE;
} }
char *ptr; char *ptr;
int N; int N;
@@ -61,5 +61,5 @@ int main(int argc, char *argv[])
break; break;
} }
#endif #endif
return 0; return EXIT_SUCCESS;
} }
+2 -2
View File
@@ -13,8 +13,8 @@ int main(int argc, char *argv[])
char *ENV_VAR = getenv("ENV_VAR"); char *ENV_VAR = getenv("ENV_VAR");
if (ENV_VAR == NULL) { if (ENV_VAR == NULL) {
printf("Failed to get env: `ENV_VAR`\n"); printf("Failed to get env: `ENV_VAR`\n");
return 1; return EXIT_FAILURE;
} }
printf("ENV_VAR = %s\n", ENV_VAR); printf("ENV_VAR = %s\n", ENV_VAR);
return 0; return EXIT_SUCCESS;
} }
+3 -3
View File
@@ -39,14 +39,14 @@ int main(int argc, char **argv)
group_t *root_group = getgrgid(0); group_t *root_group = getgrgid(0);
if (strcmp(root_group->gr_name, "root") != 0) { if (strcmp(root_group->gr_name, "root") != 0) {
printf("Error in getgrgid function."); printf("Error in getgrgid function.");
return 1; return EXIT_FAILURE;
} }
root_group = getgrnam("root"); root_group = getgrnam("root");
if (root_group->gr_gid != 0) { if (root_group->gr_gid != 0) {
printf("Error in getgrnam function."); printf("Error in getgrnam function.");
return 1; return EXIT_FAILURE;
} }
return 0; return EXIT_SUCCESS;
} }
+2 -2
View File
@@ -27,12 +27,12 @@ int main(int argc, char **argv)
printf("%d) pid_child: %d, gid_child: %d, ppid_child: %d, sid_child: %d\n", printf("%d) pid_child: %d, gid_child: %d, ppid_child: %d, sid_child: %d\n",
i, pid_child, gid_child, ppid_child, sid_child); i, pid_child, gid_child, ppid_child, sid_child);
sleep(5); sleep(5);
exit(0); return EXIT_SUCCESS;
} }
} }
//int status; //int status;
//while (wait(&status) > 0) //while (wait(&status) > 0)
// ; // ;
return 0; return EXIT_SUCCESS;
} }
+2 -2
View File
@@ -49,7 +49,7 @@ int main(int argc, char *argv[])
action.sa_handler = alarm_handler; action.sa_handler = alarm_handler;
if (sigaction(SIGALRM, &action, NULL) == -1) { if (sigaction(SIGALRM, &action, NULL) == -1) {
printf("Failed to set signal handler (%s).\n", SIGALRM, strerror(errno)); printf("Failed to set signal handler (%s).\n", SIGALRM, strerror(errno));
return 1; return EXIT_FAILURE;
} }
itimerval interval = { 0 }; itimerval interval = { 0 };
@@ -57,5 +57,5 @@ int main(int argc, char *argv[])
setitimer(ITIMER_REAL, &interval, NULL); setitimer(ITIMER_REAL, &interval, NULL);
while(1) { } while(1) { }
return 0; return EXIT_SUCCESS;
} }
+2 -2
View File
@@ -48,7 +48,7 @@ int main(int argc, char *argv[])
action.sa_handler = child_sigusr1_handler; action.sa_handler = child_sigusr1_handler;
if (sigaction(SIGUSR1, &action, NULL) == -1) { if (sigaction(SIGUSR1, &action, NULL) == -1) {
printf("Failed to set signal handler (%s).\n", SIGUSR1, strerror(errno)); printf("Failed to set signal handler (%s).\n", SIGUSR1, strerror(errno));
return 1; return EXIT_FAILURE;
} }
child_process(); child_process();
} else { } else {
@@ -61,5 +61,5 @@ int main(int argc, char *argv[])
int status; int status;
wait(&status); wait(&status);
printf("main : end (%d)\n", status); printf("main : end (%d)\n", status);
return 0; return EXIT_SUCCESS;
} }
+2 -2
View File
@@ -14,7 +14,7 @@ int main(int argc, char *argv[])
{ {
if (argc != 3) { if (argc != 3) {
printf("%s: You must provide 2 dimensions.\n", argv[0]); printf("%s: You must provide 2 dimensions.\n", argv[0]);
return 1; return EXIT_FAILURE;
} }
char *ptr; char *ptr;
int rows = strtol(argv[1], &ptr, 10); int rows = strtol(argv[1], &ptr, 10);
@@ -48,5 +48,5 @@ int main(int argc, char *argv[])
sleep(5); sleep(5);
pr_warning("Exiting!\n"); pr_warning("Exiting!\n");
return 0; return EXIT_SUCCESS;
} }
+4 -4
View File
@@ -58,7 +58,7 @@ int main(int argc, char *argv[])
key = ftok("/home/user/test7.txt", 5); key = ftok("/home/user/test7.txt", 5);
if (key < 0) { if (key < 0) {
perror("Failed to generate key using ftok"); perror("Failed to generate key using ftok");
return 1; return EXIT_FAILURE;
} }
printf("Generated key using ftok (key = %d)\n", key); printf("Generated key using ftok (key = %d)\n", key);
@@ -67,7 +67,7 @@ int main(int argc, char *argv[])
msqid = msgget(key, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); msqid = msgget(key, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
if (msqid < 0) { if (msqid < 0) {
perror("Failed to create message queue"); perror("Failed to create message queue");
return 1; return EXIT_FAILURE;
} }
printf("Created message queue (id : %d)\n", msqid); printf("Created message queue (id : %d)\n", msqid);
@@ -81,7 +81,7 @@ int main(int argc, char *argv[])
sleep(3); sleep(3);
// Send the message. // Send the message.
__send_message(msqid, 1, &message, "General Kenobi..."); __send_message(msqid, 1, &message, "General Kenobi...");
return 0; return EXIT_SUCCESS;
} }
// Receive the message. // Receive the message.
__receive_message(msqid, 1, &message); __receive_message(msqid, 1, &message);
@@ -106,5 +106,5 @@ int main(int argc, char *argv[])
perror("Failed to remove message queue."); perror("Failed to remove message queue.");
} }
printf("Correctly removed message queue.\n"); printf("Correctly removed message queue.\n");
return 0; return EXIT_SUCCESS;
} }
+4 -3
View File
@@ -3,10 +3,11 @@
/// @copyright (c) 2014-2023 This file is distributed under the MIT License. /// @copyright (c) 2014-2023 This file is distributed under the MIT License.
/// See LICENSE.md for details. /// See LICENSE.md for details.
#include <stdio.h>
#include <sched.h>
#include <sys/unistd.h> #include <sys/unistd.h>
#include <strerror.h> #include <strerror.h>
#include <stdlib.h>
#include <stdio.h>
#include <sched.h>
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
@@ -42,5 +43,5 @@ int main(int argc, char *argv[])
break; break;
} }
} }
return 0; return EXIT_SUCCESS;
} }
+4 -3
View File
@@ -3,10 +3,11 @@
/// @copyright (c) 2014-2023 This file is distributed under the MIT License. /// @copyright (c) 2014-2023 This file is distributed under the MIT License.
/// See LICENSE.md for details. /// See LICENSE.md for details.
#include <stdio.h>
#include <sched.h>
#include <sys/unistd.h> #include <sys/unistd.h>
#include <strerror.h> #include <strerror.h>
#include <stdlib.h>
#include <stdio.h>
#include <sched.h>
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
@@ -30,5 +31,5 @@ int main(int argc, char *argv[])
break; break;
} }
} }
return 0; return EXIT_SUCCESS;
} }
+4 -3
View File
@@ -3,10 +3,11 @@
/// @copyright (c) 2014-2023 This file is distributed under the MIT License. /// @copyright (c) 2014-2023 This file is distributed under the MIT License.
/// See LICENSE.md for details. /// See LICENSE.md for details.
#include <stdio.h>
#include <sched.h>
#include <sys/unistd.h> #include <sys/unistd.h>
#include <strerror.h> #include <strerror.h>
#include <stdlib.h>
#include <stdio.h>
#include <sched.h>
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
@@ -30,5 +31,5 @@ int main(int argc, char *argv[])
break; break;
} }
} }
return 0; return EXIT_SUCCESS;
} }
+3 -2
View File
@@ -5,6 +5,7 @@
#include <sys/unistd.h> #include <sys/unistd.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <stdlib.h>
#include <stdio.h> #include <stdio.h>
int main(int argc, char *argv[]) int main(int argc, char *argv[])
@@ -14,9 +15,9 @@ int main(int argc, char *argv[])
for (int i = 0; i < 10; ++i) { for (int i = 0; i < 10; ++i) {
if ((cpid = fork()) == 0) { if ((cpid = fork()) == 0) {
execl("/bin/tests/t_alarm", "t_alarm", NULL); execl("/bin/tests/t_alarm", "t_alarm", NULL);
return 0; return EXIT_SUCCESS;
} }
} }
while (wait(NULL) != -1) continue; while (wait(NULL) != -1) continue;
return 0; return EXIT_SUCCESS;
} }
+9 -9
View File
@@ -26,7 +26,7 @@ int main(int argc, char *argv[])
semid = semget(IPC_PRIVATE, 1, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); semid = semget(IPC_PRIVATE, 1, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
if (semid < 0) { if (semid < 0) {
perror("Failed to create semaphore set"); perror("Failed to create semaphore set");
return 1; return EXIT_FAILURE;
} }
printf("[father] Created semaphore set (semid : %d)\n", semid); printf("[father] Created semaphore set (semid : %d)\n", semid);
@@ -37,7 +37,7 @@ int main(int argc, char *argv[])
ret = semctl(semid, 0, SETVAL, &arg); ret = semctl(semid, 0, SETVAL, &arg);
if (ret < 0) { if (ret < 0) {
perror("Failed to set value of semaphore"); perror("Failed to set value of semaphore");
return 1; return EXIT_FAILURE;
} }
printf("[father] Set semaphore value (id : %d, value : %d == 1)\n", semid, arg.val); printf("[father] Set semaphore value (id : %d, value : %d == 1)\n", semid, arg.val);
@@ -46,7 +46,7 @@ int main(int argc, char *argv[])
ret = semctl(semid, 0, GETVAL, NULL); ret = semctl(semid, 0, GETVAL, NULL);
if (ret < 0) { if (ret < 0) {
perror("Failed to get the value of semaphore set"); perror("Failed to get the value of semaphore set");
return 1; return EXIT_FAILURE;
} }
printf("[father] Get semaphore value (id : %d, value : %d == 1)\n", semid, ret); printf("[father] Get semaphore value (id : %d, value : %d == 1)\n", semid, ret);
@@ -65,7 +65,7 @@ int main(int argc, char *argv[])
// Increment semaphore value. // Increment semaphore value.
if (semop(semid, &op_child, 1) < 0) { if (semop(semid, &op_child, 1) < 0) {
perror("Failed to perform first child operation"); perror("Failed to perform first child operation");
return 1; return EXIT_FAILURE;
} }
printf("[child] Succesfully performed opeation (id : %d)\n", semid); printf("[child] Succesfully performed opeation (id : %d)\n", semid);
@@ -74,7 +74,7 @@ int main(int argc, char *argv[])
ret = semctl(semid, 0, GETVAL, NULL); ret = semctl(semid, 0, GETVAL, NULL);
if (ret < 0) { if (ret < 0) {
perror("Failed to get the value of semaphore set"); perror("Failed to get the value of semaphore set");
return 1; return EXIT_FAILURE;
} }
printf("[child] Get semaphore value (id : %d, value : %d == 1)\n", semid, ret); printf("[child] Get semaphore value (id : %d, value : %d == 1)\n", semid, ret);
printf("[child] Exit, now.\n", semid, ret); printf("[child] Exit, now.\n", semid, ret);
@@ -87,14 +87,14 @@ int main(int argc, char *argv[])
} }
printf("[child] Correctly removed semaphore set.\n"); printf("[child] Correctly removed semaphore set.\n");
return 0; return EXIT_SUCCESS;
} }
// ======================================================================== // ========================================================================
// Perform the operations. // Perform the operations.
if (semop(semid, op, 2) < 0) { if (semop(semid, op, 2) < 0) {
perror("Failed to perform operation"); perror("Failed to perform operation");
return 1; return EXIT_FAILURE;
} }
printf("[father] Performed semaphore operations (id : %d)\n", semid); printf("[father] Performed semaphore operations (id : %d)\n", semid);
@@ -103,7 +103,7 @@ int main(int argc, char *argv[])
ret = semctl(semid, 0, GETVAL, NULL); ret = semctl(semid, 0, GETVAL, NULL);
if (ret < 0) { if (ret < 0) {
perror("Failed to get the value of semaphore set"); perror("Failed to get the value of semaphore set");
return 1; return EXIT_FAILURE;
} }
printf("[father] Get semaphore value (id : %d, value : %d == 1)\n", semid, ret); printf("[father] Get semaphore value (id : %d, value : %d == 1)\n", semid, ret);
@@ -115,5 +115,5 @@ int main(int argc, char *argv[])
} }
printf("[father] Correctly removed semaphore set.\n"); printf("[father] Correctly removed semaphore set.\n");
return 0; return EXIT_SUCCESS;
} }
+12 -12
View File
@@ -26,7 +26,7 @@ int main(int argc, char *argv[])
key = ftok("/home/user/test7.txt", 5); key = ftok("/home/user/test7.txt", 5);
if (key < 0) { if (key < 0) {
perror("Failed to generate key using ftok."); perror("Failed to generate key using ftok.");
return 1; return EXIT_FAILURE;
} }
printf("Generated key using ftok (key = %d)\n", key); printf("Generated key using ftok (key = %d)\n", key);
@@ -35,7 +35,7 @@ int main(int argc, char *argv[])
semid = semget(key, 1, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); semid = semget(key, 1, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
if (semid < 0) { if (semid < 0) {
perror("Failed to create semaphore set."); perror("Failed to create semaphore set.");
return 1; return EXIT_FAILURE;
} }
printf("[father] Created semaphore set (id : %d)\n", semid); printf("[father] Created semaphore set (id : %d)\n", semid);
@@ -46,7 +46,7 @@ int main(int argc, char *argv[])
ret = semctl(semid, 0, SETVAL, &arg); ret = semctl(semid, 0, SETVAL, &arg);
if (ret < 0) { if (ret < 0) {
perror("Failed to set value of semaphore."); perror("Failed to set value of semaphore.");
return 1; return EXIT_FAILURE;
} }
printf("[father] Set semaphore value (id : %d, value : %d == 1)\n", semid, arg.val); printf("[father] Set semaphore value (id : %d, value : %d == 1)\n", semid, arg.val);
@@ -55,7 +55,7 @@ int main(int argc, char *argv[])
ret = semctl(semid, 0, GETVAL, NULL); ret = semctl(semid, 0, GETVAL, NULL);
if (ret < 0) { if (ret < 0) {
perror("Failed to get the value of semaphore set."); perror("Failed to get the value of semaphore set.");
return 1; return EXIT_FAILURE;
} }
printf("[father] Get semaphore value (id : %d, value : %d == 1)\n", semid, ret); printf("[father] Get semaphore value (id : %d, value : %d == 1)\n", semid, ret);
@@ -71,7 +71,7 @@ int main(int argc, char *argv[])
sleep(3); sleep(3);
if (semop(semid, &op_child, 1) < 0) { if (semop(semid, &op_child, 1) < 0) {
perror("Failed to perform first child operation."); perror("Failed to perform first child operation.");
return 1; return EXIT_FAILURE;
} }
printf("[child] Succesfully performed opeation (id : %d)\n", semid); printf("[child] Succesfully performed opeation (id : %d)\n", semid);
@@ -79,7 +79,7 @@ int main(int argc, char *argv[])
ret = semctl(semid, 0, GETVAL, NULL); ret = semctl(semid, 0, GETVAL, NULL);
if (ret < 0) { if (ret < 0) {
perror("Failed to get the value of semaphore set."); perror("Failed to get the value of semaphore set.");
return 1; return EXIT_FAILURE;
} }
printf("[child] Get semaphore value (id : %d, value : %d == 0)\n", semid, ret); printf("[child] Get semaphore value (id : %d, value : %d == 0)\n", semid, ret);
@@ -87,7 +87,7 @@ int main(int argc, char *argv[])
sleep(3); sleep(3);
if (semop(semid, &op_child, 1) < 0) { if (semop(semid, &op_child, 1) < 0) {
perror("Failed to perform second child operation."); perror("Failed to perform second child operation.");
return 1; return EXIT_FAILURE;
} }
printf("[child] Succesfully performed opeation (id : %d)\n", semid); printf("[child] Succesfully performed opeation (id : %d)\n", semid);
@@ -95,14 +95,14 @@ int main(int argc, char *argv[])
ret = semctl(semid, 0, GETVAL, NULL); ret = semctl(semid, 0, GETVAL, NULL);
if (ret < 0) { if (ret < 0) {
perror("Failed to get the value of semaphore set."); perror("Failed to get the value of semaphore set.");
return 1; return EXIT_FAILURE;
} }
printf("[child] Get semaphore value (id : %d, value : %d == 0)\n", semid, ret); printf("[child] Get semaphore value (id : %d, value : %d == 0)\n", semid, ret);
printf("[child] Exit, now.\n", semid, ret); printf("[child] Exit, now.\n", semid, ret);
// Exit with the child process. // Exit with the child process.
return 0; return EXIT_SUCCESS;
} }
// ======================================================================== // ========================================================================
@@ -121,7 +121,7 @@ int main(int argc, char *argv[])
// Perform the operations. // Perform the operations.
if (semop(semid, op_father, 3) < 0) { if (semop(semid, op_father, 3) < 0) {
perror("Failed to perform father operation."); perror("Failed to perform father operation.");
return 1; return EXIT_FAILURE;
} }
sleep(2); sleep(2);
@@ -132,7 +132,7 @@ int main(int argc, char *argv[])
ret = semctl(semid, 0, GETVAL, NULL); ret = semctl(semid, 0, GETVAL, NULL);
if (ret < 0) { if (ret < 0) {
perror("Failed to get the value of semaphore set."); perror("Failed to get the value of semaphore set.");
return 1; return EXIT_FAILURE;
} }
printf("[father] Get semaphore value (id : %d, value : %d == 0)\n", semid, ret); printf("[father] Get semaphore value (id : %d, value : %d == 0)\n", semid, ret);
@@ -143,5 +143,5 @@ int main(int argc, char *argv[])
} }
printf("[father] Correctly removed semaphore set.\n"); printf("[father] Correctly removed semaphore set.\n");
return 0; return EXIT_SUCCESS;
} }
+3 -3
View File
@@ -52,7 +52,7 @@ int main(int argc, char *argv[])
if (semctl(semid, 0, SETALL, &arg) == -1) { if (semctl(semid, 0, SETALL, &arg) == -1) {
perror("Failed to set semaphores"); perror("Failed to set semaphores");
return 1; return EXIT_FAILURE;
} }
if (!fork()) { if (!fork()) {
@@ -82,7 +82,7 @@ int main(int argc, char *argv[])
} }
if (semctl(semid, 0, IPC_RMID, 0) == -1) { if (semctl(semid, 0, IPC_RMID, 0) == -1) {
perror("Failed to remove IPC"); perror("Failed to remove IPC");
return 1; return EXIT_FAILURE;
} }
return 0; return EXIT_SUCCESS;
} }
+2 -2
View File
@@ -15,7 +15,7 @@ int main(int argc, char *argv[])
if (setenv("ENV_VAR", "pwd0", 0) == -1) { if (setenv("ENV_VAR", "pwd0", 0) == -1) {
printf("Failed to set env: `PWD`\n"); printf("Failed to set env: `PWD`\n");
return 1; return EXIT_FAILURE;
} }
if (fork() == 0) { if (fork() == 0) {
@@ -24,5 +24,5 @@ int main(int argc, char *argv[])
} }
wait(&status); wait(&status);
return 0; return EXIT_SUCCESS;
} }
+4 -3
View File
@@ -33,7 +33,7 @@ int main(int argc, char *argv[])
action.sa_handler = sigusr1_handler; action.sa_handler = sigusr1_handler;
if (sigaction(SIGUSR1, &action, NULL) == -1) { if (sigaction(SIGUSR1, &action, NULL) == -1) {
printf("Failed to set signal handler (%s).\n", SIGUSR1, strerror(errno)); printf("Failed to set signal handler (%s).\n", SIGUSR1, strerror(errno));
return 1; return EXIT_FAILURE;
} }
printf("main : Calling handler (%d).\n", SIGUSR1); printf("main : Calling handler (%d).\n", SIGUSR1);
@@ -41,8 +41,9 @@ int main(int argc, char *argv[])
int ret = kill(getpid(), SIGUSR1); int ret = kill(getpid(), SIGUSR1);
printf("main : Returning from handler (%d): %d.\n", SIGUSR1, ret); printf("main : Returning from handler (%d): %d.\n", SIGUSR1, ret);
printf("main : value : %d\n", values); printf("main : value : %d\n", values);
for (int i = 0; i < 4; ++i) for (int i = 0; i < 4; ++i) {
printf("values[%d] : `%d`\n", i, values[i]); printf("values[%d] : `%d`\n", i, values[i]);
}
free(values); free(values);
return 0; return EXIT_SUCCESS;
} }
+2 -1
View File
@@ -45,7 +45,7 @@ int main(int argc, char *argv[])
if (sigaction(SIGFPE, &action, NULL) == -1) { if (sigaction(SIGFPE, &action, NULL) == -1) {
printf("Failed to set signal handler (%s).\n", SIGFPE, strerror(errno)); printf("Failed to set signal handler (%s).\n", SIGFPE, strerror(errno));
return 1; return EXIT_FAILURE;
} }
printf("Diving by zero (unrecoverable)...\n"); printf("Diving by zero (unrecoverable)...\n");
@@ -57,4 +57,5 @@ int main(int argc, char *argv[])
d /= e; d /= e;
e -= 1; e -= 1;
printf("d: %d, e: %d\n", d, e); printf("d: %d, e: %d\n", d, e);
return EXIT_SUCCESS;
} }
+2 -1
View File
@@ -36,7 +36,7 @@ int main(int argc, char *argv[])
if (sigaction(SIGFPE, &action, NULL) == -1) { if (sigaction(SIGFPE, &action, NULL) == -1) {
printf("Failed to set signal handler (%s).\n", SIGFPE, strerror(errno)); printf("Failed to set signal handler (%s).\n", SIGFPE, strerror(errno));
return 1; return EXIT_FAILURE;
} }
printf("Diving by zero (unrecoverable)...\n"); printf("Diving by zero (unrecoverable)...\n");
@@ -48,4 +48,5 @@ int main(int argc, char *argv[])
e -= 1; e -= 1;
} }
printf("d: %d, e: %d\n", d, e); printf("d: %d, e: %d\n", d, e);
return EXIT_SUCCESS;
} }
+2 -2
View File
@@ -25,7 +25,7 @@ int main(int argc, char *argv[])
action.sa_handler = sigusr1_handler; action.sa_handler = sigusr1_handler;
if (sigaction(SIGUSR1, &action, NULL) == -1) { if (sigaction(SIGUSR1, &action, NULL) == -1) {
printf("Failed to set signal handler (%d, %s).\n", SIGUSR1, strerror(errno)); printf("Failed to set signal handler (%d, %s).\n", SIGUSR1, strerror(errno));
return 1; return EXIT_FAILURE;
} }
printf("main : Blocking signal (%d).\n", SIGUSR1); printf("main : Blocking signal (%d).\n", SIGUSR1);
@@ -45,5 +45,5 @@ int main(int argc, char *argv[])
ret = kill(getpid(), SIGUSR1); ret = kill(getpid(), SIGUSR1);
printf("main : Returning from handler (%d): %d.\n", SIGUSR1, ret); printf("main : Returning from handler (%d): %d.\n", SIGUSR1, ret);
return 0; return EXIT_SUCCESS;
} }
+4 -3
View File
@@ -38,12 +38,12 @@ int main(int argc, char *argv[])
if (sigaction(SIGUSR1, &action, NULL) == -1) { if (sigaction(SIGUSR1, &action, NULL) == -1) {
printf("Failed to set signal handler (%s).\n", SIGUSR1, strerror(errno)); printf("Failed to set signal handler (%s).\n", SIGUSR1, strerror(errno));
return 1; return EXIT_FAILURE;
} }
if (sigaction(SIGUSR2, &action, NULL) == -1) { if (sigaction(SIGUSR2, &action, NULL) == -1) {
printf("Failed to set signal handler (%s).\n", SIGUSR2, strerror(errno)); printf("Failed to set signal handler (%s).\n", SIGUSR2, strerror(errno));
return 1; return EXIT_FAILURE;
} }
kill(getpid(), SIGUSR1); kill(getpid(), SIGUSR1);
@@ -51,5 +51,6 @@ int main(int argc, char *argv[])
kill(getpid(), SIGUSR2); kill(getpid(), SIGUSR2);
while(1) { }; while(1) { };
return 0;
return EXIT_SUCCESS;
} }
+1 -1
View File
@@ -17,5 +17,5 @@ int main(int argc, char *argv[])
sleep(4); sleep(4);
printf("COMPLETED.\n"); printf("COMPLETED.\n");
return 0; return EXIT_SUCCESS;
} }
+2 -2
View File
@@ -31,7 +31,7 @@ int main(int argc, char *argv[])
action.sa_handler = wait_for_child; action.sa_handler = wait_for_child;
if (sigaction(SIGCHLD, &action, NULL) == -1) { if (sigaction(SIGCHLD, &action, NULL) == -1) {
printf("Failed to set signal handler. %d\n", SIGCHLD); printf("Failed to set signal handler. %d\n", SIGCHLD);
return 1; return EXIT_FAILURE;
} }
child_pid = fork(); child_pid = fork();
@@ -55,5 +55,5 @@ int main(int argc, char *argv[])
} }
} }
return 0; return EXIT_SUCCESS;
} }