Compare commits
8
Commits
b9a6e92816
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ae7af6e6cf | ||
|
|
532d8e757b | ||
|
|
b5215d5327 | ||
|
|
dccb93fb82 | ||
|
|
b78ef69da8 | ||
|
|
d72169473f | ||
|
|
c58605b56d | ||
|
|
63c1720e60 |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 949 KiB |
@@ -18,19 +18,19 @@ meson compile -v -C build
|
||||
sector_size=512
|
||||
partition_offset=2048
|
||||
|
||||
dd if=/dev/zero of=build/os.img bs="${sector_size}" count="$((partition_offset + 20480))"
|
||||
dd if=build/mbr.bin of=build/os.img bs="${sector_size}" count=1 conv=notrunc
|
||||
dd if=build/bootloader.bin of=build/os.img bs="${sector_size}" seek=1 count="$((partition_offset - 1))" conv=notrunc
|
||||
mkfs.fat -F 16 --offset "${partition_offset}" build/os.img
|
||||
mcopy -i build/os.img@@"$((partition_offset * sector_size))" -s src ::src
|
||||
mcopy -i build/os.img@@"$((partition_offset * sector_size))" build/kernel.bin ::kernel.bin
|
||||
mmd -i build/os.img@@"$((partition_offset * sector_size))" ::bin
|
||||
mcopy -i build/os.img@@"$((partition_offset * sector_size))" build/terminal ::bin/terminal
|
||||
mcopy -i build/os.img@@"$((partition_offset * sector_size))" build/shell ::bin/shell
|
||||
mcopy -i build/os.img@@"$((partition_offset * sector_size))" build/echo ::bin/echo
|
||||
mcopy -i build/os.img@@"$((partition_offset * sector_size))" build/ls ::bin/ls
|
||||
mcopy -i build/os.img@@"$((partition_offset * sector_size))" build/cat ::bin/cat
|
||||
mcopy -i build/os.img@@"$((partition_offset * sector_size))" build/cp ::bin/cp
|
||||
mcopy -i build/os.img@@"$((partition_offset * sector_size))" build/mkdir ::bin/mkdir
|
||||
mcopy -i build/os.img@@"$((partition_offset * sector_size))" build/rm ::bin/rm
|
||||
mcopy -i build/os.img@@"$((partition_offset * sector_size))" build/wc ::bin/wc
|
||||
dd if=/dev/zero of=build/os.raw bs="${sector_size}" count="$((partition_offset + 20480))"
|
||||
dd if=build/mbr.bin of=build/os.raw bs="${sector_size}" count=1 conv=notrunc
|
||||
dd if=build/bootloader.bin of=build/os.raw bs="${sector_size}" seek=1 count="$((partition_offset - 1))" conv=notrunc
|
||||
mkfs.fat -F 16 --offset "${partition_offset}" build/os.raw
|
||||
mcopy -i build/os.raw@@"$((partition_offset * sector_size))" -s src ::src
|
||||
mcopy -i build/os.raw@@"$((partition_offset * sector_size))" build/kernel.bin ::kernel.bin
|
||||
mmd -i build/os.raw@@"$((partition_offset * sector_size))" ::bin
|
||||
mcopy -i build/os.raw@@"$((partition_offset * sector_size))" build/terminal ::bin/terminal
|
||||
mcopy -i build/os.raw@@"$((partition_offset * sector_size))" build/shell ::bin/shell
|
||||
mcopy -i build/os.raw@@"$((partition_offset * sector_size))" build/echo ::bin/echo
|
||||
mcopy -i build/os.raw@@"$((partition_offset * sector_size))" build/ls ::bin/ls
|
||||
mcopy -i build/os.raw@@"$((partition_offset * sector_size))" build/cat ::bin/cat
|
||||
mcopy -i build/os.raw@@"$((partition_offset * sector_size))" build/cp ::bin/cp
|
||||
mcopy -i build/os.raw@@"$((partition_offset * sector_size))" build/mkdir ::bin/mkdir
|
||||
mcopy -i build/os.raw@@"$((partition_offset * sector_size))" build/rm ::bin/rm
|
||||
mcopy -i build/os.raw@@"$((partition_offset * sector_size))" build/wc ::bin/wc
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
device=${1:-}
|
||||
if [[ ! -b ${device} ]]; then
|
||||
echo "ERROR: \"${device}\" is not a block device" >&2
|
||||
fi
|
||||
|
||||
if [[ ! -f build/os.raw ]]; then
|
||||
echo "ERROR: \"build/os.raw\" does not appear to be built, run \"build.sh\"" >&2
|
||||
fi
|
||||
|
||||
echo 'Copying the image...' >&2
|
||||
mnt=$(mktemp --directory)
|
||||
mount "${device}2" "${mnt}"
|
||||
cp --update "build/os.raw" "${mnt}"
|
||||
umount "${mnt}"
|
||||
rm -rf "${mnt}"
|
||||
echo 'Done.' >&2
|
||||
+38
-338
@@ -92,20 +92,25 @@ kernel_sources = files([
|
||||
'src/kernel/xhci.c',
|
||||
])
|
||||
|
||||
kernel_elf = executable(
|
||||
'kernel.elf',
|
||||
sources: [kernel_entry_o, timer_o, process_o, syscall_o, lib_sources, kernel_sources],
|
||||
c_args: [
|
||||
c_args = [
|
||||
'-ffreestanding',
|
||||
'-nostdlib',
|
||||
'-nostartfiles',
|
||||
'-mno-red-zone',
|
||||
'-mgeneral-regs-only',
|
||||
'-fno-stack-protector',
|
||||
'-DVERSION="' + meson.project_version() + '"',
|
||||
]
|
||||
|
||||
kernel_elf = executable(
|
||||
'kernel.elf',
|
||||
sources: [kernel_entry_o, timer_o, process_o, syscall_o, lib_sources, kernel_sources],
|
||||
c_args: [
|
||||
c_args,
|
||||
'-mcmodel=kernel',
|
||||
'-Wno-unused-command-line-argument',
|
||||
'-Wconversion',
|
||||
'-DKERNEL="yes"',
|
||||
'-DVERSION="' + meson.project_version() + '"',
|
||||
],
|
||||
link_args: [
|
||||
'-T', meson.project_source_root() / 'src/kernel/linker.ld',
|
||||
@@ -122,353 +127,48 @@ custom_target(
|
||||
build_by_default: true,
|
||||
)
|
||||
|
||||
terminal_start = custom_target(
|
||||
'terminal_start',
|
||||
foreach app : ['terminal', 'shell', 'echo', 'ls', 'cat', 'cp', 'mkdir', 'rm', 'wc']
|
||||
start = custom_target(
|
||||
f'@app@_start',
|
||||
input: 'src/user/start.asm',
|
||||
output: 'terminal_start.o',
|
||||
output: f'@app@_start.o',
|
||||
command: [nasm, '-f', 'elf64', '-o', '@OUTPUT@', '@INPUT@'],
|
||||
)
|
||||
)
|
||||
|
||||
terminal_syscall = custom_target(
|
||||
'terminal_syscall',
|
||||
syscall = custom_target(
|
||||
f'@app@_syscall',
|
||||
input: 'src/user/syscall.asm',
|
||||
output: 'terminal_syscall.o',
|
||||
output: f'@app@_syscall.o',
|
||||
command: [nasm, '-f', 'elf64', '-o', '@OUTPUT@', '@INPUT@'],
|
||||
)
|
||||
)
|
||||
|
||||
terminal_elf = executable(
|
||||
'terminal.elf',
|
||||
sources: [terminal_start, terminal_syscall, lib_sources, 'src/user/app/terminal/terminal.c'],
|
||||
elf = executable(
|
||||
f'@app@.elf',
|
||||
sources: [start, syscall, lib_sources, f'src/user/app/@app@/@app@.c'],
|
||||
c_args: [
|
||||
'-ffreestanding',
|
||||
'-nostdlib',
|
||||
'-fno-stack-protector',
|
||||
c_args,
|
||||
'-mcmodel=large',
|
||||
'-DVERSION="' + meson.project_version() + '"',
|
||||
],
|
||||
link_args: [
|
||||
'-T', meson.project_source_root() / 'src/user/linker.ld',
|
||||
'-nostdlib',
|
||||
],
|
||||
link_depends: 'src/user/linker.ld',
|
||||
)
|
||||
)
|
||||
|
||||
custom_target(
|
||||
'terminal',
|
||||
input: terminal_elf,
|
||||
output: 'terminal',
|
||||
elf_data = custom_target(
|
||||
f'@app@_data.elf',
|
||||
input: elf,
|
||||
output: f'@app@_data.elf',
|
||||
command: ['objcopy', '--set-section-flags', '.data=alloc,load,contents', '@INPUT@', '@OUTPUT@'],
|
||||
build_by_default: true,
|
||||
)
|
||||
|
||||
custom_target(
|
||||
app,
|
||||
input: elf_data,
|
||||
output: app,
|
||||
command: ['objcopy', '-O', 'binary', '@INPUT@', '@OUTPUT@'],
|
||||
build_by_default: true,
|
||||
)
|
||||
|
||||
shell_start = custom_target(
|
||||
'shell_start',
|
||||
input: 'src/user/start.asm',
|
||||
output: 'shell_start.o',
|
||||
command: [nasm, '-f', 'elf64', '-o', '@OUTPUT@', '@INPUT@'],
|
||||
)
|
||||
|
||||
shell_syscall = custom_target(
|
||||
'shell_syscall',
|
||||
input: 'src/user/syscall.asm',
|
||||
output: 'shell_syscall.o',
|
||||
command: [nasm, '-f', 'elf64', '-o', '@OUTPUT@', '@INPUT@'],
|
||||
)
|
||||
|
||||
shell_elf = executable(
|
||||
'shell.elf',
|
||||
sources: [shell_start, shell_syscall, lib_sources, 'src/user/app/shell/shell.c'],
|
||||
c_args: [
|
||||
'-ffreestanding',
|
||||
'-nostdlib',
|
||||
'-fno-stack-protector',
|
||||
'-mcmodel=large',
|
||||
'-DVERSION="' + meson.project_version() + '"',
|
||||
],
|
||||
link_args: [
|
||||
'-T', meson.project_source_root() / 'src/user/linker.ld',
|
||||
'-nostdlib',
|
||||
],
|
||||
link_depends: 'src/user/linker.ld',
|
||||
)
|
||||
|
||||
custom_target(
|
||||
'shell',
|
||||
input: shell_elf,
|
||||
output: 'shell',
|
||||
command: ['objcopy', '-O', 'binary', '@INPUT@', '@OUTPUT@'],
|
||||
build_by_default: true,
|
||||
)
|
||||
|
||||
echo_start = custom_target(
|
||||
'echo_start',
|
||||
input: 'src/user/start.asm',
|
||||
output: 'echo_start.o',
|
||||
command: [nasm, '-f', 'elf64', '-o', '@OUTPUT@', '@INPUT@'],
|
||||
)
|
||||
|
||||
echo_syscall = custom_target(
|
||||
'echo_syscall',
|
||||
input: 'src/user/syscall.asm',
|
||||
output: 'echo_syscall.o',
|
||||
command: [nasm, '-f', 'elf64', '-o', '@OUTPUT@', '@INPUT@'],
|
||||
)
|
||||
|
||||
echo_elf = executable(
|
||||
'echo.elf',
|
||||
sources: [echo_start, echo_syscall, lib_sources, 'src/user/app/echo/echo.c'],
|
||||
c_args: [
|
||||
'-ffreestanding',
|
||||
'-nostdlib',
|
||||
'-fno-stack-protector',
|
||||
'-mcmodel=large',
|
||||
'-DVERSION="' + meson.project_version() + '"',
|
||||
],
|
||||
link_args: [
|
||||
'-T', meson.project_source_root() / 'src/user/linker.ld',
|
||||
'-nostdlib',
|
||||
],
|
||||
link_depends: 'src/user/linker.ld',
|
||||
)
|
||||
|
||||
custom_target(
|
||||
'echo',
|
||||
input: echo_elf,
|
||||
output: 'echo',
|
||||
command: ['objcopy', '-O', 'binary', '@INPUT@', '@OUTPUT@'],
|
||||
build_by_default: true,
|
||||
)
|
||||
|
||||
ls_start = custom_target(
|
||||
'ls_start',
|
||||
input: 'src/user/start.asm',
|
||||
output: 'ls_start.o',
|
||||
command: [nasm, '-f', 'elf64', '-o', '@OUTPUT@', '@INPUT@'],
|
||||
)
|
||||
|
||||
ls_syscall = custom_target(
|
||||
'ls_syscall',
|
||||
input: 'src/user/syscall.asm',
|
||||
output: 'ls_syscall.o',
|
||||
command: [nasm, '-f', 'elf64', '-o', '@OUTPUT@', '@INPUT@'],
|
||||
)
|
||||
|
||||
ls_elf = executable(
|
||||
'ls.elf',
|
||||
sources: [ls_start, ls_syscall, lib_sources, 'src/user/app/ls/ls.c'],
|
||||
c_args: [
|
||||
'-ffreestanding',
|
||||
'-nostdlib',
|
||||
'-fno-stack-protector',
|
||||
'-mcmodel=large',
|
||||
'-DVERSION="' + meson.project_version() + '"',
|
||||
],
|
||||
link_args: [
|
||||
'-T', meson.project_source_root() / 'src/user/linker.ld',
|
||||
'-nostdlib',
|
||||
],
|
||||
link_depends: 'src/user/linker.ld',
|
||||
)
|
||||
|
||||
custom_target(
|
||||
'ls',
|
||||
input: ls_elf,
|
||||
output: 'ls',
|
||||
command: ['objcopy', '-O', 'binary', '@INPUT@', '@OUTPUT@'],
|
||||
build_by_default: true,
|
||||
)
|
||||
|
||||
cat_start = custom_target(
|
||||
'cat_start',
|
||||
input: 'src/user/start.asm',
|
||||
output: 'cat_start.o',
|
||||
command: [nasm, '-f', 'elf64', '-o', '@OUTPUT@', '@INPUT@'],
|
||||
)
|
||||
|
||||
cat_syscall = custom_target(
|
||||
'cat_syscall',
|
||||
input: 'src/user/syscall.asm',
|
||||
output: 'cat_syscall.o',
|
||||
command: [nasm, '-f', 'elf64', '-o', '@OUTPUT@', '@INPUT@'],
|
||||
)
|
||||
|
||||
cat_elf = executable(
|
||||
'cat.elf',
|
||||
sources: [cat_start, cat_syscall, lib_sources, 'src/user/app/cat/cat.c'],
|
||||
c_args: [
|
||||
'-ffreestanding',
|
||||
'-nostdlib',
|
||||
'-fno-stack-protector',
|
||||
'-mcmodel=large',
|
||||
'-DVERSION="' + meson.project_version() + '"',
|
||||
],
|
||||
link_args: [
|
||||
'-T', meson.project_source_root() / 'src/user/linker.ld',
|
||||
'-nostdlib',
|
||||
],
|
||||
link_depends: 'src/user/linker.ld',
|
||||
)
|
||||
|
||||
custom_target(
|
||||
'cat',
|
||||
input: cat_elf,
|
||||
output: 'cat',
|
||||
command: ['objcopy', '-O', 'binary', '@INPUT@', '@OUTPUT@'],
|
||||
build_by_default: true,
|
||||
)
|
||||
|
||||
cp_start = custom_target(
|
||||
'cp_start',
|
||||
input: 'src/user/start.asm',
|
||||
output: 'cp_start.o',
|
||||
command: [nasm, '-f', 'elf64', '-o', '@OUTPUT@', '@INPUT@'],
|
||||
)
|
||||
|
||||
cp_syscall = custom_target(
|
||||
'cp_syscall',
|
||||
input: 'src/user/syscall.asm',
|
||||
output: 'cp_syscall.o',
|
||||
command: [nasm, '-f', 'elf64', '-o', '@OUTPUT@', '@INPUT@'],
|
||||
)
|
||||
|
||||
cp_elf = executable(
|
||||
'cp.elf',
|
||||
sources: [cp_start, cp_syscall, lib_sources, 'src/user/app/cp/cp.c'],
|
||||
c_args: [
|
||||
'-ffreestanding',
|
||||
'-nostdlib',
|
||||
'-fno-stack-protector',
|
||||
'-mcmodel=large',
|
||||
'-DVERSION="' + meson.project_version() + '"',
|
||||
],
|
||||
link_args: [
|
||||
'-T', meson.project_source_root() / 'src/user/linker.ld',
|
||||
'-nostdlib',
|
||||
],
|
||||
link_depends: 'src/user/linker.ld',
|
||||
)
|
||||
|
||||
custom_target(
|
||||
'cp',
|
||||
input: cp_elf,
|
||||
output: 'cp',
|
||||
command: ['objcopy', '-O', 'binary', '@INPUT@', '@OUTPUT@'],
|
||||
build_by_default: true,
|
||||
)
|
||||
|
||||
mkdir_start = custom_target(
|
||||
'mkdir_start',
|
||||
input: 'src/user/start.asm',
|
||||
output: 'mkdir_start.o',
|
||||
command: [nasm, '-f', 'elf64', '-o', '@OUTPUT@', '@INPUT@'],
|
||||
)
|
||||
|
||||
mkdir_syscall = custom_target(
|
||||
'mkdir_syscall',
|
||||
input: 'src/user/syscall.asm',
|
||||
output: 'mkdir_syscall.o',
|
||||
command: [nasm, '-f', 'elf64', '-o', '@OUTPUT@', '@INPUT@'],
|
||||
)
|
||||
|
||||
mkdir_elf = executable(
|
||||
'mkdir.elf',
|
||||
sources: [mkdir_start, mkdir_syscall, lib_sources, 'src/user/app/mkdir/mkdir.c'],
|
||||
c_args: [
|
||||
'-ffreestanding',
|
||||
'-nostdlib',
|
||||
'-fno-stack-protector',
|
||||
'-mcmodel=large',
|
||||
'-DVERSION="' + meson.project_version() + '"',
|
||||
],
|
||||
link_args: [
|
||||
'-T', meson.project_source_root() / 'src/user/linker.ld',
|
||||
'-nostdlib',
|
||||
],
|
||||
link_depends: 'src/user/linker.ld',
|
||||
)
|
||||
|
||||
custom_target(
|
||||
'mkdir',
|
||||
input: mkdir_elf,
|
||||
output: 'mkdir',
|
||||
command: ['objcopy', '-O', 'binary', '@INPUT@', '@OUTPUT@'],
|
||||
build_by_default: true,
|
||||
)
|
||||
|
||||
rm_start = custom_target(
|
||||
'rm_start',
|
||||
input: 'src/user/start.asm',
|
||||
output: 'rm_start.o',
|
||||
command: [nasm, '-f', 'elf64', '-o', '@OUTPUT@', '@INPUT@'],
|
||||
)
|
||||
|
||||
rm_syscall = custom_target(
|
||||
'rm_syscall',
|
||||
input: 'src/user/syscall.asm',
|
||||
output: 'rm_syscall.o',
|
||||
command: [nasm, '-f', 'elf64', '-o', '@OUTPUT@', '@INPUT@'],
|
||||
)
|
||||
|
||||
rm_elf = executable(
|
||||
'rm.elf',
|
||||
sources: [rm_start, rm_syscall, lib_sources, 'src/user/app/rm/rm.c'],
|
||||
c_args: [
|
||||
'-ffreestanding',
|
||||
'-nostdlib',
|
||||
'-fno-stack-protector',
|
||||
'-mcmodel=large',
|
||||
'-DVERSION="' + meson.project_version() + '"',
|
||||
],
|
||||
link_args: [
|
||||
'-T', meson.project_source_root() / 'src/user/linker.ld',
|
||||
'-nostdlib',
|
||||
],
|
||||
link_depends: 'src/user/linker.ld',
|
||||
)
|
||||
|
||||
custom_target(
|
||||
'rm',
|
||||
input: rm_elf,
|
||||
output: 'rm',
|
||||
command: ['objcopy', '-O', 'binary', '@INPUT@', '@OUTPUT@'],
|
||||
build_by_default: true,
|
||||
)
|
||||
|
||||
wc_start = custom_target(
|
||||
'wc_start',
|
||||
input: 'src/user/start.asm',
|
||||
output: 'wc_start.o',
|
||||
command: [nasm, '-f', 'elf64', '-o', '@OUTPUT@', '@INPUT@'],
|
||||
)
|
||||
|
||||
wc_syscall = custom_target(
|
||||
'wc_syscall',
|
||||
input: 'src/user/syscall.asm',
|
||||
output: 'wc_syscall.o',
|
||||
command: [nasm, '-f', 'elf64', '-o', '@OUTPUT@', '@INPUT@'],
|
||||
)
|
||||
|
||||
wc_elf = executable(
|
||||
'wc.elf',
|
||||
sources: [wc_start, wc_syscall, lib_sources, 'src/user/app/wc/wc.c'],
|
||||
c_args: [
|
||||
'-ffreestanding',
|
||||
'-nostdlib',
|
||||
'-fno-stack-protector',
|
||||
'-mcmodel=large',
|
||||
'-DVERSION="' + meson.project_version() + '"',
|
||||
],
|
||||
link_args: [
|
||||
'-T', meson.project_source_root() / 'src/user/linker.ld',
|
||||
'-nostdlib',
|
||||
],
|
||||
link_depends: 'src/user/linker.ld',
|
||||
)
|
||||
|
||||
custom_target(
|
||||
'wc',
|
||||
input: wc_elf,
|
||||
output: 'wc',
|
||||
command: ['objcopy', '-O', 'binary', '@INPUT@', '@OUTPUT@'],
|
||||
build_by_default: true,
|
||||
)
|
||||
)
|
||||
endforeach
|
||||
|
||||
+4
-2
@@ -10,7 +10,6 @@ mov sp, 0x7000
|
||||
FIRST_PARTITION_SECTOR equ 2048 ; TODO Read MBR.
|
||||
STAGE_BUFFER_SEGMENT equ 0x0900
|
||||
STAGE_BUFFER_OFFSET equ 0x0000
|
||||
KERNEL_BUFFER_SEGMENT equ 0x2000
|
||||
|
||||
jmp prepare_kernel
|
||||
|
||||
@@ -41,6 +40,7 @@ data_start: dw 0
|
||||
|
||||
kernel_filename: db 'KERNEL BIN'
|
||||
kernel_cluster: dw 0
|
||||
kernel_buffer_segment: dw 0x2000
|
||||
kernel_buffer_offset: dw 0
|
||||
|
||||
read_sectors:
|
||||
@@ -192,7 +192,7 @@ load_kernel_cluster:
|
||||
add ax, [data_start]
|
||||
xor cx, cx
|
||||
mov cl, [bpb.sectors_per_cluster]
|
||||
mov bx, KERNEL_BUFFER_SEGMENT
|
||||
mov bx, [kernel_buffer_segment]
|
||||
mov es, bx
|
||||
mov di, [kernel_buffer_offset]
|
||||
call read_sectors
|
||||
@@ -201,6 +201,8 @@ load_kernel_cluster:
|
||||
shl ax, 9 ; * 512
|
||||
add ax, [kernel_buffer_offset]
|
||||
mov [kernel_buffer_offset], ax
|
||||
jnc find_next_kernel_cluster
|
||||
add word [kernel_buffer_segment], 0x1000
|
||||
|
||||
find_next_kernel_cluster:
|
||||
xor bx, bx
|
||||
|
||||
+1
-1
@@ -357,7 +357,7 @@ fs_node_t *fat16_open_at(const fs_node_t *directory, uint16_t index, uint64_t fl
|
||||
ei++;
|
||||
}
|
||||
|
||||
fs_node_t *result = open_entry(dir_cluster, entries, ei);
|
||||
fs_node_t *result = ei < entries_count ? open_entry(dir_cluster, entries, ei) : NUL;
|
||||
|
||||
memory_free(entries);
|
||||
|
||||
|
||||
@@ -170,6 +170,7 @@ static uint64_t stream_read(__attribute__((unused)) stream_t *self, uint64_t max
|
||||
}
|
||||
buffer_length -= size;
|
||||
buffer_offset = (buffer_offset + size) % BUFFER_SIZE;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
+32
-44
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "src/kernel/stream.h"
|
||||
#include "src/lib/memory.h"
|
||||
#include "src/lib/string.h"
|
||||
|
||||
extern stream_t *kernel_log;
|
||||
@@ -15,58 +14,47 @@ extern stream_t *kernel_log;
|
||||
#define LOG_LEVEL_DATA 3
|
||||
#define LOG_LEVEL_TRACE 4
|
||||
|
||||
static uint64_t print_size;
|
||||
static char print_buffer[512];
|
||||
|
||||
#define PRINT(stream, fmt, ...) \
|
||||
do { \
|
||||
uint64_t _size = string_length(fmt) * 10; \
|
||||
char *_string = memory_allocate(_size); \
|
||||
_size = string_format(fmt, _size, _string, ##__VA_ARGS__); \
|
||||
stream->write(stream, _string, _size); \
|
||||
memory_free(_string); \
|
||||
} while (0);
|
||||
print_size = string_format(fmt, sizeof(print_buffer) - 1, print_buffer, ##__VA_ARGS__); \
|
||||
stream->write(stream, print_buffer, print_size);
|
||||
|
||||
#define PRINT_LN(stream, fmt, ...) \
|
||||
do { \
|
||||
uint64_t _size = string_length(fmt) * 10; \
|
||||
char *_string = memory_allocate(_size); \
|
||||
_size = string_format(fmt, _size, _string, ##__VA_ARGS__); \
|
||||
print_size = string_format(fmt, sizeof(print_buffer) - 1, print_buffer, ##__VA_ARGS__); \
|
||||
stream->write(stream, __func__, string_length(__func__)); \
|
||||
stream->write(stream, ": ", 2); \
|
||||
stream->write(stream, _string, _size); \
|
||||
stream->write(stream, "\n", 1); \
|
||||
memory_free(_string); \
|
||||
} while (0);
|
||||
stream->write(stream, print_buffer, print_size); \
|
||||
stream->write(stream, "\n", 1);
|
||||
|
||||
#define PRINT_VAL(stream, v, f) PRINT_LN(#v = f, v)
|
||||
|
||||
#define LOG_INFO(fmt, ...) \
|
||||
if (LOG_LEVEL >= LOG_LEVEL_INFO) \
|
||||
PRINT(kernel_log, fmt, ##__VA_ARGS__)
|
||||
#define LOG_STEP(fmt, ...) \
|
||||
if (LOG_LEVEL >= LOG_LEVEL_STEP) \
|
||||
PRINT(kernel_log, fmt, ##__VA_ARGS__)
|
||||
#define LOG_DATA(fmt, ...) \
|
||||
if (LOG_LEVEL >= LOG_LEVEL_DATA) \
|
||||
PRINT(kernel_log, fmt, ##__VA_ARGS__)
|
||||
#define LOG_TRACE(fmt, ...) \
|
||||
if (LOG_LEVEL >= LOG_LEVEL_TRACE) \
|
||||
PRINT(kernel_log, fmt, ##__VA_ARGS__)
|
||||
#define LOG(level, fmt, ...) \
|
||||
if (LOG_LEVEL >= level) { \
|
||||
PRINT(kernel_log, fmt, ##__VA_ARGS__) \
|
||||
}
|
||||
|
||||
#define LOG_LN_INFO(fmt, ...) \
|
||||
if (LOG_LEVEL >= LOG_LEVEL_INFO) \
|
||||
PRINT_LN(kernel_log, fmt, ##__VA_ARGS__)
|
||||
#define LOG_LN_STEP(fmt, ...) \
|
||||
if (LOG_LEVEL >= LOG_LEVEL_STEP) \
|
||||
PRINT_LN(kernel_log, fmt, ##__VA_ARGS__)
|
||||
#define LOG_LN_DATA(fmt, ...) \
|
||||
if (LOG_LEVEL >= LOG_LEVEL_DATA) \
|
||||
PRINT_LN(kernel_log, fmt, ##__VA_ARGS__)
|
||||
#define LOG_LN_TRACE(fmt, ...) \
|
||||
if (LOG_LEVEL >= LOG_LEVEL_TRACE) \
|
||||
PRINT_LN(kernel_log, fmt, ##__VA_ARGS__)
|
||||
#define LOG_LN(level, fmt, ...) \
|
||||
if (LOG_LEVEL >= level) { \
|
||||
PRINT_LN(kernel_log, fmt, ##__VA_ARGS__) \
|
||||
}
|
||||
|
||||
#define LOG_VAL_INFO(v, f) LOG_LN_INFO(#v "=" f, v)
|
||||
#define LOG_VAL_STEP(v, f) LOG_LN_STEP(#v "=" f, v)
|
||||
#define LOG_VAL_DATA(v, f) LOG_LN_DATA(#v "=" f, v)
|
||||
#define LOG_VAL_TRACE(v, f) LOG_LN_TRACE(#v "=" f, v)
|
||||
#define LOG_VAL(level, v, f) LOG_LN(level, #v "=" f, v)
|
||||
|
||||
#define LOG_INFO(fmt, ...) LOG(LOG_LEVEL_INFO, fmt, ##__VA_ARGS__)
|
||||
#define LOG_STEP(fmt, ...) LOG(LOG_LEVEL_STEP, fmt, ##__VA_ARGS__)
|
||||
#define LOG_DATA(fmt, ...) LOG(LOG_LEVEL_DATA, fmt, ##__VA_ARGS__)
|
||||
#define LOG_TRACE(fmt, ...) LOG(LOG_LEVEL_TRACE, fmt, ##__VA_ARGS__)
|
||||
|
||||
#define LOG_LN_INFO(fmt, ...) LOG_LN(LOG_LEVEL_INFO, fmt, ##__VA_ARGS__)
|
||||
#define LOG_LN_STEP(fmt, ...) LOG_LN(LOG_LEVEL_STEP, fmt, ##__VA_ARGS__)
|
||||
#define LOG_LN_DATA(fmt, ...) LOG_LN(LOG_LEVEL_DATA, fmt, ##__VA_ARGS__)
|
||||
#define LOG_LN_TRACE(fmt, ...) LOG_LN(LOG_LEVEL_TRACE, fmt, ##__VA_ARGS__)
|
||||
|
||||
#define LOG_VAL_INFO(v, f) LOG_VAL(LOG_LEVEL_INFO, v, f)
|
||||
#define LOG_VAL_STEP(v, f) LOG_VAL(LOG_LEVEL_STEP, v, f)
|
||||
#define LOG_VAL_DATA(v, f) LOG_VAL(LOG_LEVEL_DATA, v, f)
|
||||
#define LOG_VAL_TRACE(v, f) LOG_VAL(LOG_LEVEL_TRACE, v, f)
|
||||
|
||||
void log_init(stream_t *log);
|
||||
|
||||
+18
-8
@@ -35,6 +35,8 @@ typedef struct __attribute__((packed)) {
|
||||
#define USB_SETUP_RECIPIENT_OTHER 3
|
||||
|
||||
#define USB_SETUP_GET_DESCRIPTOR 0x06
|
||||
#define USB_SETUP_SET_CONFIGURATION 0x09
|
||||
#define USB_SETUP_SET_IDLE 0x0A
|
||||
#define USB_SETUP_SET_PROTOCOL 0x0B
|
||||
|
||||
#define USB_SETUP_DESCRIPTOR_TYPE_R(s) BITS_R((s)->w_value, 15, 8)
|
||||
@@ -52,11 +54,6 @@ typedef struct __attribute__((packed)) {
|
||||
#define USB_DESCRIPTOR_TYPE_CONFIGURATION 0x02
|
||||
#define USB_DESCRIPTOR_TYPE_INTERFACE 0x04
|
||||
#define USB_DESCRIPTOR_TYPE_ENDPOINT 0x05
|
||||
#define USB_DESCRIPTOR_TYPE_HID 0x21
|
||||
|
||||
#define USB_INTERFACE_HID_KEYBOARD_CLASS 0x3
|
||||
#define USB_INTERFACE_HID_KEYBOARD_SUBCLASS 0x1
|
||||
#define USB_INTERFACE_HID_KEYBOARD_PROTOCOL 0x1
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
usb_descriptor_base_t base;
|
||||
@@ -176,7 +173,6 @@ void usb_enumerate(stream_t *out) {
|
||||
}
|
||||
|
||||
xhci_slot_t slot = xhci_attach(port);
|
||||
|
||||
if (slot == (xhci_slot_t)-1) {
|
||||
continue;
|
||||
}
|
||||
@@ -206,7 +202,6 @@ xhci_port_t usb_find_by_interface(uint8_t class, uint8_t subclass, uint8_t proto
|
||||
}
|
||||
|
||||
xhci_slot_t slot = xhci_attach(port);
|
||||
|
||||
if (slot == (xhci_slot_t)-1) {
|
||||
continue;
|
||||
}
|
||||
@@ -239,6 +234,14 @@ xhci_endpoint_t usb_open_endpoint(xhci_slot_t slot, uint8_t type, uint16_t max_p
|
||||
scan_device(slot, &device, &configuration, &interface, &endpoint);
|
||||
|
||||
usb_setup_t setup;
|
||||
memory_set(0, sizeof(setup), &setup);
|
||||
USB_SETUP_DIRECTION_W(&setup, USB_SETUP_DIRECTION_H2D);
|
||||
USB_SETUP_TYPE_W(&setup, USB_SETUP_TYPE_STANDARD);
|
||||
USB_SETUP_RECIPIENT_W(&setup, USB_SETUP_RECIPIENT_DEVICE);
|
||||
setup.b_request = USB_SETUP_SET_CONFIGURATION;
|
||||
setup.w_value = configuration.configuration_value;
|
||||
xhci_control_transfer(slot, *(uint64_t *)&setup, NUL, 0);
|
||||
|
||||
memory_set(0, sizeof(setup), &setup);
|
||||
USB_SETUP_DIRECTION_W(&setup, USB_SETUP_DIRECTION_H2D);
|
||||
USB_SETUP_TYPE_W(&setup, USB_SETUP_TYPE_CLASS);
|
||||
@@ -246,9 +249,16 @@ xhci_endpoint_t usb_open_endpoint(xhci_slot_t slot, uint8_t type, uint16_t max_p
|
||||
setup.b_request = USB_SETUP_SET_PROTOCOL;
|
||||
xhci_control_transfer(slot, *(uint64_t *)&setup, NUL, 0);
|
||||
|
||||
memory_set(0, sizeof(setup), &setup);
|
||||
USB_SETUP_DIRECTION_W(&setup, USB_SETUP_DIRECTION_H2D);
|
||||
USB_SETUP_TYPE_W(&setup, USB_SETUP_TYPE_CLASS);
|
||||
USB_SETUP_RECIPIENT_W(&setup, USB_SETUP_RECIPIENT_INTERFACE);
|
||||
setup.b_request = USB_SETUP_SET_IDLE;
|
||||
xhci_control_transfer(slot, *(uint64_t *)&setup, NUL, 0);
|
||||
|
||||
ASSERT(endpoint.max_packet_size == max_packet_size, "usb_open_endpoint: Unexpected max packet size.");
|
||||
|
||||
return xhci_open_endpoint(slot, endpoint.endpoint_address, type, endpoint.max_packet_size, endpoint.interval);
|
||||
return xhci_open_endpoint(slot, endpoint.endpoint_address, type, endpoint.max_packet_size, 7);
|
||||
}
|
||||
|
||||
uint16_t usb_read_endpoint(xhci_slot_t slot, xhci_endpoint_t endpoint, uint16_t max, void *to) {
|
||||
|
||||
+38
-8
@@ -1,12 +1,12 @@
|
||||
#include "src/kernel/xhci.h"
|
||||
#include "src/kernel/log.h"
|
||||
#include "src/kernel/memory.h"
|
||||
#include "src/kernel/panic.h"
|
||||
#include "src/kernel/pci.h"
|
||||
#include "src/kernel/stream.h"
|
||||
#include "src/lib/layout.h"
|
||||
#include "src/lib/memory.h"
|
||||
#include "src/lib/util.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#define XHCI_PCI_CLASS 0x0C
|
||||
#define XHCI_PCI_SUBCLASS 0x03
|
||||
@@ -29,6 +29,7 @@ typedef volatile struct __attribute__((packed)) {
|
||||
#define XHCI_CAP_REGS_MAX_INTRS(c) BITS_R((c)->hcsparams1, 18, 8)
|
||||
#define XHCI_CAP_REGS_MAX_PORTS(c) BITS_R((c)->hcsparams1, 31, 24)
|
||||
#define XHCI_CAP_REGS_MAX_ERSTS(c) BITS_R((c)->hcsparams2, 7, 4)
|
||||
#define XHCI_CAP_REGS_MAX_SCRATCHPAD_BUFFERS(c) (BITS_R((c)->hcsparams2, 31, 27) << 5 | BITS_R((c)->hcsparams2, 4, 0))
|
||||
|
||||
typedef volatile struct __attribute__((packed)) {
|
||||
uint32_t usbcmd;
|
||||
@@ -96,6 +97,8 @@ static xhci_db_regs *db_regs;
|
||||
|
||||
#define MAX_SLOTS 32
|
||||
|
||||
static void *scratchpads[32];
|
||||
|
||||
static void *dcbaa[MAX_SLOTS + 1] __attribute__((aligned(PAGE_SIZE)));
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
@@ -408,6 +411,13 @@ void xhci_init() {
|
||||
RING_WRAP(cmd);
|
||||
XHCI_TRB_CYCLE_W(&cmd_r[RING_LENGTH], cmd_r_cycle);
|
||||
|
||||
LOG_LN_INFO("Setting up scratchpad buffers...");
|
||||
ASSERT(XHCI_CAP_REGS_MAX_SCRATCHPAD_BUFFERS(cap_regs) <= sizeof(scratchpads), "Too many scratchpad buffers expected.");
|
||||
for (uint32_t i = 0; i < XHCI_CAP_REGS_MAX_SCRATCHPAD_BUFFERS(cap_regs); i++) {
|
||||
scratchpads[i] = memory_page_allocate();
|
||||
}
|
||||
dcbaa[0] = VIRT_TO_PHYS(scratchpads);
|
||||
|
||||
LOG_LN_INFO("Configuring controller...");
|
||||
XHCI_OP_REGS_MAX_SLOTS_EN_W(op_regs, MAX_SLOTS);
|
||||
op_regs->dcbaap = (uint64_t)VIRT_TO_PHYS(dcbaa);
|
||||
@@ -475,13 +485,17 @@ xhci_slot_t xhci_attach(xhci_port_t port) {
|
||||
RING_WRAP(tsf);
|
||||
|
||||
LOG_LN_STEP("Resetting device...");
|
||||
LOG_VAL_TRACE(port_regs[port].portsc, "%x");
|
||||
port_regs[port].portsc = (port_regs[port].portsc & ~(uint32_t)0x00FE0000) | 0x00FE0000;
|
||||
LOG_VAL_TRACE(port_regs[port].portsc, "%x");
|
||||
port_regs[port].portsc = (port_regs[port].portsc & ~(uint32_t)0x00FE0000) | (1 << 4);
|
||||
LOG_VAL_TRACE(port_regs[port].portsc, "%x");
|
||||
while (XHCI_PORT_REGS_PR_R(&port_regs[port]))
|
||||
;
|
||||
LOG_VAL_TRACE(&port_regs[port].portsc, "%x");
|
||||
LOG_VAL_TRACE(port_regs[port].portsc, "%x");
|
||||
while (!XHCI_PORT_REGS_PED(&port_regs[port]) && XHCI_PORT_REGS_PLL(&port_regs[port]) != 0)
|
||||
;
|
||||
LOG_VAL_TRACE(&port_regs[port].portsc, "%x");
|
||||
LOG_VAL_TRACE(port_regs[port].portsc, "%x");
|
||||
|
||||
LOG_LN_STEP("Enabling a slot...");
|
||||
xhci_trb_t cmd_es;
|
||||
@@ -524,7 +538,7 @@ uint64_t xhci_control_transfer(xhci_slot_t slot, uint64_t setup, void *data, uin
|
||||
}
|
||||
|
||||
xhci_endpoint_t xhci_open_endpoint(xhci_slot_t slot, uint8_t address, uint8_t type, uint16_t max_packet_size, uint8_t interval) {
|
||||
LOG_LN_INFO("Opening endpoint slot %d address %hhx...", slot, address);
|
||||
LOG_LN_STEP("Opening endpoint slot %d address %hhx...", slot, address);
|
||||
|
||||
ASSERT(slot < MAX_SLOTS, "xhci_control_transfer: Slot does not exist.");
|
||||
ASSERT(tsf_r_attached_slot == slot, "xhci_open_endpoint: Slot is not attached.");
|
||||
@@ -535,11 +549,11 @@ xhci_endpoint_t xhci_open_endpoint(xhci_slot_t slot, uint8_t address, uint8_t ty
|
||||
uint8_t ep_dir = (address >> 7) & 1;
|
||||
uint8_t dci = ep_num * 2 + ep_dir;
|
||||
|
||||
LOG_LN_INFO("Setting up endpoint ring...");
|
||||
LOG_LN_STEP("Setting up endpoint ring...");
|
||||
RING_WRAP(ep);
|
||||
XHCI_TRB_CYCLE_W(&ep_r[RING_LENGTH], ep_r_cycle);
|
||||
|
||||
LOG_LN_INFO("Configuring endpoint...");
|
||||
LOG_LN_STEP("Configuring endpoint...");
|
||||
memory_set(0, sizeof(xhci_input_ctx_t), &input_ctx);
|
||||
input_ctx.slot = device_ctx.slot;
|
||||
input_ctx.control.add_flags = (1 << 0) | (1 << dci);
|
||||
@@ -583,9 +597,10 @@ uint16_t xhci_read_endpoint(xhci_slot_t slot, xhci_endpoint_t endpoint, uint16_t
|
||||
XHCI_TRB_TRB_TYPE_W(ere, XHCI_TRB_TYPE_TRANSFER_NORMAL);
|
||||
XHCI_TRB_IOC_W(ere, 1);
|
||||
XHCI_TRB_CYCLE_W(ere, ep_r_cycle);
|
||||
RING_ADVANCE(ep);
|
||||
}
|
||||
|
||||
ep_r_cycle ^= 1;
|
||||
|
||||
db_regs[tsf_r_attached_slot] = ep_r_attached_endpoint;
|
||||
|
||||
return 0;
|
||||
@@ -593,6 +608,14 @@ uint16_t xhci_read_endpoint(xhci_slot_t slot, xhci_endpoint_t endpoint, uint16_t
|
||||
|
||||
uint16_t transferred = 0;
|
||||
while (XHCI_TRB_CYCLE_R(&evt_r[evt_r_i]) == evt_r_cycle && !transferred) {
|
||||
if (ep_processed_events == 0) {
|
||||
// A bit of a hack: flip link TRB cycle only after the first event is processed. There is some delay between controller
|
||||
// posting the last success event of the batch, and consuming the link TRB. Flipping the link cycle together with the batch
|
||||
// might happen before the controller got a chance to check the link cycle, and stall the consumption. If we received the
|
||||
// first event of the next batch, we're certain the link TRB has just been processed, and there's plenty of time before the next loop.
|
||||
XHCI_TRB_CYCLE_W(&ep_r[RING_LENGTH], !ep_r_cycle);
|
||||
}
|
||||
|
||||
xhci_trb_t *cmp = &evt_r[evt_r_i];
|
||||
|
||||
if (XHCI_TRB_TRB_TYPE_R(cmp) != XHCI_TRB_TYPE_EVENT_TRANSFER_COMPLETION) {
|
||||
@@ -612,10 +635,17 @@ uint16_t xhci_read_endpoint(xhci_slot_t slot, xhci_endpoint_t endpoint, uint16_t
|
||||
LOG_LN_STEP("Received transfer event, returning...");
|
||||
ep_processed_events++;
|
||||
|
||||
LOG_VAL_TRACE(cmp->parameter, "%lx");
|
||||
LOG_VAL_TRACE(cmp->status, "%x");
|
||||
LOG_VAL_TRACE(cmp->control, "%x");
|
||||
|
||||
xhci_trb_t *cmd = PHYS_TO_VIRT(cmp->parameter);
|
||||
uint16_t size = max < cmd->status ? max : (uint16_t)cmd->status;
|
||||
memory_copy(PHYS_TO_VIRT(cmd->parameter), size, to);
|
||||
|
||||
LOG_VAL_TRACE(size, "%d");
|
||||
LOG_VAL_TRACE(*(uint64_t *)to, "%lx");
|
||||
|
||||
transferred = size;
|
||||
}
|
||||
|
||||
@@ -627,7 +657,7 @@ uint16_t xhci_read_endpoint(xhci_slot_t slot, xhci_endpoint_t endpoint, uint16_t
|
||||
}
|
||||
|
||||
void xhci_close_endpoint(xhci_slot_t slot, xhci_endpoint_t endpoint) {
|
||||
LOG_LN_INFO("Closing endpoind %hhx...", endpoint);
|
||||
LOG_LN_STEP("Closing endpoind %hhx...", endpoint);
|
||||
|
||||
ASSERT(slot < MAX_SLOTS, "xhci_control_transfer: Slot does not exist.");
|
||||
ASSERT(tsf_r_attached_slot == slot, "xhci_close_endpoint: Slot is not attached.");
|
||||
|
||||
@@ -10,8 +10,7 @@ exit_code_t main(uint64_t argc, const char **argv) {
|
||||
|
||||
uint64_t code = EXIT_CODE_OK;
|
||||
for (uint64_t i = 1; i < argc; i++) {
|
||||
uint64_t removed = remove(argv[i]);
|
||||
if (removed == (uint64_t)-1) {
|
||||
if (remove(argv[i]) == (uint64_t)-1) {
|
||||
ERR_S("rm: could not remove file\n");
|
||||
code = EXIT_CODE_GENERAL_FAILURE;
|
||||
}
|
||||
|
||||
@@ -96,7 +96,12 @@ static void execute(char *command) {
|
||||
uint8_t pids_count = 0;
|
||||
|
||||
for (uint8_t i = 0; i < subcommands_count; i++) {
|
||||
string_trim(subcommands[i], ' ', &subcommands[i]);
|
||||
if (!string_trim(subcommands[i], ' ', &subcommands[i])) {
|
||||
if (subcommands_count > 1) {
|
||||
ERR_S("Syntax error.\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
char *argv[16];
|
||||
uint8_t argc = (uint8_t)string_split(subcommands[i], ' ', 16, argv);
|
||||
@@ -166,7 +171,7 @@ exit_code_t main() {
|
||||
print_prompt();
|
||||
|
||||
char line[256];
|
||||
uint64_t offset;
|
||||
uint64_t offset = 0;
|
||||
|
||||
char chunk[64];
|
||||
uint64_t received;
|
||||
|
||||
+3
-4
@@ -3,8 +3,7 @@ ENTRY(_start)
|
||||
SECTIONS {
|
||||
. = 0x0000000000400000;
|
||||
|
||||
.text : { *(.text) }
|
||||
.rodata : { *(.rodata) }
|
||||
.data : { *(.data) }
|
||||
.bss : { *(.bss) }
|
||||
.text : { *(.text*) }
|
||||
.rodata : { *(.rodata*) *(.lrodata*) }
|
||||
.data : { *(.data*) *(.ldata*) *(.bss*) *(.lbss*) }
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ fi
|
||||
qemu-system-x86_64 \
|
||||
"${debug_flags[@]}" \
|
||||
-monitor stdio \
|
||||
-drive file=build/os.img,format=raw,if=none,id=nvme0 \
|
||||
-drive file=build/os.raw,format=raw,if=none,id=nvme0 \
|
||||
-device nvme,drive=nvme0,serial=foo \
|
||||
-device qemu-xhci,id=xhci,msi=off,msix=off \
|
||||
-device usb-kbd,bus=xhci.0 \
|
||||
|
||||
Reference in New Issue
Block a user