Compare commits
83 Commits
3a06c18e10
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| af3dd454b0 | |||
| 2a587942ac | |||
| bf5052fd3d | |||
| d4d3ab13f4 | |||
| 98dbaa05ac | |||
| 1e3e38b0e2 | |||
| c1e10e8b70 | |||
| 7b89a038a2 | |||
| a792bbe5db | |||
| dd46a378b3 | |||
| 33888e364b | |||
| a535c588f1 | |||
| 9f4c4cbc9d | |||
| 3e0fdb616c | |||
| 44cd6c551a | |||
| 60e1ca951c | |||
| 119a86b8e6 | |||
| ac8f669e6b | |||
| 7d6af0344c | |||
| 1e52036585 | |||
| 24fc8ecb97 | |||
| cc15bb54f3 | |||
| ed138d581e | |||
| eaf5e02ad4 | |||
| 88f8d4f18a | |||
| 5d9a3fa54d | |||
| 8236f99aef | |||
| 81b9e7777a | |||
| aa155824d3 | |||
| af424d85d8 | |||
| a37a07d708 | |||
| 2fab6687b0 | |||
| d1a9c5cd45 | |||
| 3bf995cdf6 | |||
| 8c09909d07 | |||
| a041bc55db | |||
| 32d0606d16 | |||
| 3bc331b9c5 | |||
| c2b59ed494 | |||
| c340f927bb | |||
| 7a00de28a1 | |||
| 9148349f44 | |||
| 766411d983 | |||
| 555989e74a | |||
| ffc2ed735e | |||
| 68ae449731 | |||
| 08a9627548 | |||
| 844f6d50eb | |||
| 863be171c1 | |||
| 0471838f30 | |||
| cf70352caa | |||
| 342b588b38 | |||
| cdf828be2d | |||
| c11d55d675 | |||
| a5cf0b050d | |||
| bd39cb11aa | |||
| a01b5ddb11 | |||
| 1e9fe24b39 | |||
| 9044281d1b | |||
| 5dd99bb0a6 | |||
| d03c750e4a | |||
| c66c7f3f3f | |||
| 29acfcee69 | |||
| fea89d675e | |||
| eb8d9c3512 | |||
| 0c56c645ac | |||
| 68b7783f32 | |||
| ea2b0d3986 | |||
| c9ccebacfc | |||
| 5ad5f57a76 | |||
| f441d633b2 | |||
| 9ea3441fcc | |||
| 86ca343cf0 | |||
| b680ffdd5b | |||
| 14799e0d58 | |||
| b7452a449b | |||
| ea6ec785a9 | |||
| 6d88cf4bf3 | |||
| aef0163017 | |||
| b0fda122e0 | |||
| 79af171384 | |||
| 5931642cc2 | |||
| 26a49162e6 |
@@ -1,6 +1,9 @@
|
|||||||
cmake_minimum_required(VERSION 3.14)
|
cmake_minimum_required(VERSION 4.0)
|
||||||
project(Rosetta C CXX ASM)
|
project(Rosetta C CXX ASM)
|
||||||
|
|
||||||
|
include(CheckPIESupported)
|
||||||
|
check_pie_supported()
|
||||||
|
|
||||||
set(sys_dir ${CMAKE_CURRENT_BINARY_DIR}/sys)
|
set(sys_dir ${CMAKE_CURRENT_BINARY_DIR}/sys)
|
||||||
|
|
||||||
set(kernel_name mango_kernel)
|
set(kernel_name mango_kernel)
|
||||||
@@ -25,6 +28,7 @@ add_subdirectory(interface)
|
|||||||
add_subdirectory(sys)
|
add_subdirectory(sys)
|
||||||
add_subdirectory(lib)
|
add_subdirectory(lib)
|
||||||
add_subdirectory(services)
|
add_subdirectory(services)
|
||||||
|
add_subdirectory(runlevel)
|
||||||
add_subdirectory(programs)
|
add_subdirectory(programs)
|
||||||
|
|
||||||
sysroot_add_program(NAME ${kernel_name} BIN_DIR /boot)
|
sysroot_add_program(NAME ${kernel_name} BIN_DIR /boot)
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
include(System-Disk)
|
include(System-Disk)
|
||||||
include(QEMU)
|
include(QEMU)
|
||||||
include(Bochs)
|
include(Bochs)
|
||||||
|
include(Test)
|
||||||
|
|||||||
@@ -5,17 +5,23 @@ set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")
|
|||||||
|
|
||||||
find_program(C_COMPILER x86_64-elf-gcc REQUIRED)
|
find_program(C_COMPILER x86_64-elf-gcc REQUIRED)
|
||||||
find_program(CXX_COMPILER x86_64-elf-g++ REQUIRED)
|
find_program(CXX_COMPILER x86_64-elf-g++ REQUIRED)
|
||||||
find_program(ASM_COMPILER x86_64-elf-as REQUIRED)
|
#find_program(ASM_COMPILER x86_64-elf-as REQUIRED)
|
||||||
|
|
||||||
add_compile_definitions(__mango__=1)
|
add_compile_definitions(__mango__=1)
|
||||||
|
|
||||||
set(CMAKE_C_COMPILER ${C_COMPILER})
|
set(CMAKE_C_COMPILER ${C_COMPILER})
|
||||||
set(CMAKE_CXX_COMPILER ${CXX_COMPILER})
|
set(CMAKE_CXX_COMPILER ${CXX_COMPILER})
|
||||||
set(CMAKE_ASM_COMPILER ${ASM_COMPILER})
|
#set(CMAKE_ASM_COMPILER ${ASM_COMPILER})
|
||||||
|
|
||||||
SET(CMAKE_C_FLAGS "-ffreestanding -nostdlib -z max-page-size=0x1000 -m64 -mcmodel=large -mno-red-zone -mno-mmx -mno-sse -mno-sse2 -D_64BIT -DBYTE_ORDER=1234" CACHE STRING "" FORCE)
|
SET(CMAKE_C_FLAGS "-ffreestanding -nostdlib -z max-page-size=0x1000 -m64 -mcmodel=large -mno-red-zone -mno-mmx -mno-sse -mno-sse2 -D_64BIT -DBYTE_ORDER=1234" CACHE STRING "" FORCE)
|
||||||
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,-shared" CACHE STRING "" FORCE)
|
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,-shared" CACHE STRING "" FORCE)
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "-Wl,--unresolved-symbols=report-all,--dynamic-linker=/lib/ld64.so" CACHE STRING "" FORCE)
|
set(CMAKE_EXE_LINKER_FLAGS "-Wl,--unresolved-symbols=report-all,--dynamic-linker=/lib/ld64.so" CACHE STRING "" FORCE)
|
||||||
|
set(CMAKE_C_LINK_OPTIONS_PIE "-pie")
|
||||||
|
set(CMAKE_C_LINK_PIE_SUPPORTED TRUE)
|
||||||
|
set(CMAKE_C_LINK_NO_PIE_SUPPORTED TRUE)
|
||||||
|
SET(CMAKE_ASM_FLAGS "${CFLAGS} -x assembler-with-cpp")
|
||||||
|
|
||||||
set(CMAKE_C_OUTPUT_EXTENSION .o)
|
set(CMAKE_C_OUTPUT_EXTENSION .o)
|
||||||
set(CMAKE_CXX_OUTPUT_EXTENSION .o)
|
set(CMAKE_CXX_OUTPUT_EXTENSION .o)
|
||||||
|
|
||||||
|
set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
|
||||||
|
|||||||
@@ -8,7 +8,8 @@ find_program(LLDB lldb)
|
|||||||
find_program(GDB gdb)
|
find_program(GDB gdb)
|
||||||
|
|
||||||
set(patched_kernel ${CMAKE_CURRENT_BINARY_DIR}/kernel/${kernel_name}.elf32)
|
set(patched_kernel ${CMAKE_CURRENT_BINARY_DIR}/kernel/${kernel_name}.elf32)
|
||||||
set(generic_flags -m 1G)
|
set(generic_flags -m 128M -cpu qemu64,+rdrand)
|
||||||
|
|
||||||
set(no_debug_flags)
|
set(no_debug_flags)
|
||||||
|
|
||||||
if (${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Linux")
|
if (${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Linux")
|
||||||
|
|||||||
35
arch/x86_64/Test.cmake
Normal file
35
arch/x86_64/Test.cmake
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
find_package(Python COMPONENTS Interpreter)
|
||||||
|
if (NOT Python_EXECUTABLE)
|
||||||
|
message(STATUS "QEMU: Cannot find python. Direct-kernel boot testing unavailable")
|
||||||
|
return()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
find_program(QEMU qemu-system-${TARGET_ARCH} REQUIRED)
|
||||||
|
if (NOT QEMU)
|
||||||
|
message(STATUS "QEMU: Cannot find qemu-system-${TARGET_ARCH}. Direct-kernel boot testing unavailable")
|
||||||
|
return()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
set(patched_kernel ${CMAKE_CURRENT_BINARY_DIR}/kernel/${kernel_name}.elf32)
|
||||||
|
set(generic_flags -m 1G -cpu qemu64,+rdrand)
|
||||||
|
set(this_dir ${CMAKE_SOURCE_DIR}/arch/${CMAKE_SYSTEM_PROCESSOR})
|
||||||
|
set(no_debug_flags)
|
||||||
|
|
||||||
|
if (${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Linux")
|
||||||
|
message(STATUS "QEMU: Enabling KVM acceleration")
|
||||||
|
set(no_debug_flags ${no_debug_flags} -enable-kvm)
|
||||||
|
else ()
|
||||||
|
message(STATUS "QEMU: Host system is not Linux. KVM acceleration unavailable")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
message(STATUS "Test: Enable direct-kernel boot testing with QEMU")
|
||||||
|
add_custom_target(test-successful-boot
|
||||||
|
COMMAND
|
||||||
|
${this_dir}/test/successful-boot
|
||||||
|
${Python_EXECUTABLE}
|
||||||
|
${this_dir}/test/check-results
|
||||||
|
${QEMU}
|
||||||
|
${patched_kernel}
|
||||||
|
${sys_dir}/${bsp_name}
|
||||||
|
USES_TERMINAL
|
||||||
|
DEPENDS ${patched_kernel} bsp)
|
||||||
52
arch/x86_64/test/check-results
Normal file
52
arch/x86_64/test/check-results
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# vim: ft=python
|
||||||
|
import sys
|
||||||
|
|
||||||
|
def log(f, msg):
|
||||||
|
print(msg)
|
||||||
|
f.write(msg)
|
||||||
|
f.write('\n')
|
||||||
|
|
||||||
|
def successful_boot(boot_log, out):
|
||||||
|
nr_panic = boot_log.count("---[ kernel panic")
|
||||||
|
if nr_panic == 1:
|
||||||
|
log(out, "Kernel panic!")
|
||||||
|
return 1
|
||||||
|
if nr_panic > 1:
|
||||||
|
log(out, "Multiple kernel panics!")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
nr_boots = boot_log.count('Mango kernel version')
|
||||||
|
if nr_boots == 0:
|
||||||
|
log(out, "Kernel didn't start!")
|
||||||
|
return 1
|
||||||
|
if nr_boots > 1:
|
||||||
|
log(out, "Kernel rebooted during test!")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
nr_finish = boot_log.count("ld finished")
|
||||||
|
if nr_finish == 0:
|
||||||
|
log(out, "Didn't reach end of boot sequence!")
|
||||||
|
return 1
|
||||||
|
if nr_finish > 1:
|
||||||
|
log(out, "Boot sequence performed multiple times!")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
tests = {
|
||||||
|
'successful-boot': successful_boot,
|
||||||
|
}
|
||||||
|
|
||||||
|
test_name = sys.argv[1]
|
||||||
|
boot_log_path = sys.argv[2]
|
||||||
|
out_path = sys.argv[3]
|
||||||
|
|
||||||
|
boot_log_file = open(boot_log_path, 'r')
|
||||||
|
boot_log = boot_log_file.read()
|
||||||
|
boot_log_file.close()
|
||||||
|
|
||||||
|
out_file = open(out_path, 'a')
|
||||||
|
|
||||||
|
exit(tests[test_name](boot_log, out_file))
|
||||||
69
arch/x86_64/test/successful-boot
Executable file
69
arch/x86_64/test/successful-boot
Executable file
@@ -0,0 +1,69 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# vim: ft=bash
|
||||||
|
|
||||||
|
|
||||||
|
log_dir="test-results/successful-boot"
|
||||||
|
rm -rf $log_dir
|
||||||
|
mkdir -p $log_dir
|
||||||
|
|
||||||
|
logfile="$log_dir/main.log"
|
||||||
|
|
||||||
|
log() {
|
||||||
|
if [ -n "$logfile" ]; then
|
||||||
|
printf '%s\n' "$@" >> "$logfile"
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf '%s\n' "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
log "Running boot test. Press Ctrl+\\ to stop."
|
||||||
|
|
||||||
|
declare -i result
|
||||||
|
declare -i count
|
||||||
|
declare -i pass
|
||||||
|
declare -i fail
|
||||||
|
count=0
|
||||||
|
pass=0
|
||||||
|
fail=0
|
||||||
|
python=$1
|
||||||
|
validation_script=$2
|
||||||
|
qemu=$3
|
||||||
|
kernel=$4
|
||||||
|
initrd=$5
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
log "Test $count"
|
||||||
|
result_file="$log_dir/$count.log"
|
||||||
|
$qemu \
|
||||||
|
-kernel $kernel \
|
||||||
|
-initrd $initrd \
|
||||||
|
-serial file:$result_file \
|
||||||
|
-cpu qemu64,+rdrand \
|
||||||
|
--append kernel.early-console=ttyS0 -s > /dev/null &
|
||||||
|
qemu_id=$!
|
||||||
|
|
||||||
|
sleep 1.2
|
||||||
|
|
||||||
|
$python $validation_script successful-boot $result_file $logfile
|
||||||
|
result=$?
|
||||||
|
|
||||||
|
count=$count+1
|
||||||
|
|
||||||
|
if [ $result -eq 0 ]; then
|
||||||
|
pass=$pass+1
|
||||||
|
else
|
||||||
|
mv $result_file "$result_file.FAIL"
|
||||||
|
fail=$fail+1
|
||||||
|
lldb \
|
||||||
|
-o "file kernel/mango_kernel.debug" \
|
||||||
|
-o "gdb-remote localhost:1234"
|
||||||
|
fi
|
||||||
|
|
||||||
|
kill -INT $qemu_id
|
||||||
|
|
||||||
|
log "---------------"
|
||||||
|
log "Total tests: $count"
|
||||||
|
log "Pass: $pass"
|
||||||
|
log "Fail: $fail"
|
||||||
|
log "---------------"
|
||||||
|
done
|
||||||
@@ -9,6 +9,36 @@ function(bsp_reset)
|
|||||||
COMMAND_ERROR_IS_FATAL ANY)
|
COMMAND_ERROR_IS_FATAL ANY)
|
||||||
endfunction(bsp_reset)
|
endfunction(bsp_reset)
|
||||||
|
|
||||||
|
function(bsp_add_file)
|
||||||
|
set(options)
|
||||||
|
set(one_value_args ID SRC_PATH DEST_DIR)
|
||||||
|
set(multi_value_args)
|
||||||
|
|
||||||
|
cmake_parse_arguments(PARSE_ARGV 0 arg
|
||||||
|
"${options}"
|
||||||
|
"${one_value_args}"
|
||||||
|
"${multi_value_args}")
|
||||||
|
|
||||||
|
set(target_name ${arg_ID})
|
||||||
|
set(bsp_target_name _bsp-${target_name})
|
||||||
|
|
||||||
|
get_property(bsp_targets GLOBAL PROPERTY bsp_target_list)
|
||||||
|
list(LENGTH bsp_targets nr_bsp_targets)
|
||||||
|
if (${nr_bsp_targets} GREATER 0)
|
||||||
|
math(EXPR serialiser_index "${nr_bsp_targets}-1")
|
||||||
|
list(GET bsp_targets ${serialiser_index} serialiser)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
add_custom_target(${bsp_target_name}
|
||||||
|
COMMAND ${Python_EXECUTABLE} ${bsp_tool}
|
||||||
|
add-binary ${bsp_manifest} ${target_name}
|
||||||
|
${arg_DEST_DIR} ${arg_SRC_PATH}
|
||||||
|
COMMENT "Preparing bsp component: ${target_name}"
|
||||||
|
DEPENDS ${arg_SRC_PATH} ${serialiser})
|
||||||
|
|
||||||
|
set_property(GLOBAL PROPERTY bsp_target_list ${bsp_targets} ${bsp_target_name})
|
||||||
|
endfunction(bsp_add_file)
|
||||||
|
|
||||||
function(bsp_add_library)
|
function(bsp_add_library)
|
||||||
set(options)
|
set(options)
|
||||||
set(one_value_args NAME HEADER_DIR LIB_DIR)
|
set(one_value_args NAME HEADER_DIR LIB_DIR)
|
||||||
@@ -70,6 +100,40 @@ function(bsp_add_program)
|
|||||||
set_property(GLOBAL PROPERTY bsp_target_list ${bsp_targets} ${bsp_target_name})
|
set_property(GLOBAL PROPERTY bsp_target_list ${bsp_targets} ${bsp_target_name})
|
||||||
endfunction(bsp_add_program)
|
endfunction(bsp_add_program)
|
||||||
|
|
||||||
|
function(bsp_add_service)
|
||||||
|
set(options)
|
||||||
|
set(one_value_args NAME BIN_DIR SVC_DIR)
|
||||||
|
set(multi_value_args)
|
||||||
|
|
||||||
|
cmake_parse_arguments(PARSE_ARGV 0 arg
|
||||||
|
"${options}"
|
||||||
|
"${one_value_args}"
|
||||||
|
"${multi_value_args}")
|
||||||
|
|
||||||
|
set(target_name ${arg_NAME})
|
||||||
|
set(bsp_target_name _bsp-${target_name})
|
||||||
|
|
||||||
|
get_property(bsp_targets GLOBAL PROPERTY bsp_target_list)
|
||||||
|
get_property(cfg_file TARGET ${arg_NAME} PROPERTY service_cfg_path)
|
||||||
|
list(LENGTH bsp_targets nr_bsp_targets)
|
||||||
|
if (${nr_bsp_targets} GREATER 0)
|
||||||
|
math(EXPR serialiser_index "${nr_bsp_targets}-1")
|
||||||
|
list(GET bsp_targets ${serialiser_index} serialiser)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
add_custom_target(${bsp_target_name}
|
||||||
|
COMMAND ${Python_EXECUTABLE} ${bsp_tool}
|
||||||
|
add-binary ${bsp_manifest} ${target_name}
|
||||||
|
${arg_BIN_DIR} $<TARGET_FILE:${target_name}>
|
||||||
|
COMMAND ${Python_EXECUTABLE} ${bsp_tool}
|
||||||
|
add-binary ${bsp_manifest} ${target_name}-cfg
|
||||||
|
${arg_SVC_DIR} ${cfg_file}
|
||||||
|
COMMENT "Preparing bsp component: ${target_name}"
|
||||||
|
DEPENDS ${target_name} ${serialiser})
|
||||||
|
|
||||||
|
set_property(GLOBAL PROPERTY bsp_target_list ${bsp_targets} ${bsp_target_name})
|
||||||
|
endfunction(bsp_add_service)
|
||||||
|
|
||||||
function(bsp_finalise)
|
function(bsp_finalise)
|
||||||
set(options)
|
set(options)
|
||||||
set(one_value_args BOOTSTRAP_PROGRAM DEST_DIR BSP_NAME)
|
set(one_value_args BOOTSTRAP_PROGRAM DEST_DIR BSP_NAME)
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
find_program(IFC
|
find_program(XPCG
|
||||||
NAMES ifc
|
NAMES xpcg
|
||||||
REQUIRED
|
REQUIRED
|
||||||
HINTS ${BUILD_TOOLS_DIR})
|
HINTS ${BUILD_TOOLS_DIR})
|
||||||
message(STATUS "Found interface compiler: ${IFC}")
|
message(STATUS "Found interface generator: ${XPCG}")
|
||||||
|
|
||||||
function(add_interface)
|
function(add_interface)
|
||||||
set(options)
|
set(options)
|
||||||
@@ -20,9 +20,10 @@ function(add_interface)
|
|||||||
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT ${header_path}
|
OUTPUT ${header_path}
|
||||||
COMMAND ${IFC} ${arg_PATH}
|
COMMAND ${XPCG} ${arg_PATH}
|
||||||
|
DEPENDS ${arg_PATH}
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${arg_PARENT_DIR}
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${arg_PARENT_DIR}
|
||||||
COMMENT "Compiling interface: ${arg_NAME}")
|
COMMENT "Generating interface: ${arg_NAME}")
|
||||||
|
|
||||||
add_custom_target(ifgen-${arg_NAME} ALL
|
add_custom_target(ifgen-${arg_NAME} ALL
|
||||||
DEPENDS ${header_path})
|
DEPENDS ${header_path})
|
||||||
|
|||||||
@@ -155,6 +155,40 @@ function(sysroot_add_program)
|
|||||||
set_property(GLOBAL PROPERTY sysroot_target_list ${sysroot_targets} ${sysroot_target_name})
|
set_property(GLOBAL PROPERTY sysroot_target_list ${sysroot_targets} ${sysroot_target_name})
|
||||||
endfunction(sysroot_add_program)
|
endfunction(sysroot_add_program)
|
||||||
|
|
||||||
|
function(sysroot_add_service)
|
||||||
|
set(options)
|
||||||
|
set(one_value_args NAME BIN_DIR SVC_DIR)
|
||||||
|
set(multi_value_args)
|
||||||
|
|
||||||
|
cmake_parse_arguments(PARSE_ARGV 0 arg
|
||||||
|
"${options}"
|
||||||
|
"${one_value_args}"
|
||||||
|
"${multi_value_args}")
|
||||||
|
|
||||||
|
set(target_name ${arg_NAME})
|
||||||
|
set(sysroot_target_name _sysroot-${target_name})
|
||||||
|
|
||||||
|
get_property(sysroot_targets GLOBAL PROPERTY sysroot_target_list)
|
||||||
|
get_property(cfg_file TARGET ${arg_NAME} PROPERTY service_cfg_path)
|
||||||
|
list(LENGTH sysroot_targets nr_sysroot_targets)
|
||||||
|
if (${nr_sysroot_targets} GREATER 0)
|
||||||
|
math(EXPR serialiser_index "${nr_sysroot_targets}-1")
|
||||||
|
list(GET sysroot_targets ${serialiser_index} serialiser)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
add_custom_target(${sysroot_target_name}
|
||||||
|
COMMAND ${Python_EXECUTABLE} ${sysroot_tool}
|
||||||
|
add-binary ${sysroot_manifest} ${target_name}
|
||||||
|
${arg_BIN_DIR} $<TARGET_FILE:${target_name}>
|
||||||
|
COMMAND ${Python_EXECUTABLE} ${sysroot_tool}
|
||||||
|
add-binary ${sysroot_manifest} ${target_name}-cfg
|
||||||
|
${arg_SVC_DIR} ${cfg_file}
|
||||||
|
COMMENT "Preparing sysroot component: ${target_name}"
|
||||||
|
DEPENDS ${target_name} ${serialiser})
|
||||||
|
|
||||||
|
set_property(GLOBAL PROPERTY sysroot_target_list ${sysroot_targets} ${sysroot_target_name})
|
||||||
|
endfunction(sysroot_add_service)
|
||||||
|
|
||||||
function(sysroot_add_file)
|
function(sysroot_add_file)
|
||||||
set(options)
|
set(options)
|
||||||
set(one_value_args ID SRC_PATH DEST_DIR)
|
set(one_value_args ID SRC_PATH DEST_DIR)
|
||||||
|
|||||||
@@ -32,6 +32,29 @@ function(rosetta_add_executable)
|
|||||||
DESTINATION ${arg_SYSROOT_PATH})
|
DESTINATION ${arg_SYSROOT_PATH})
|
||||||
endfunction(rosetta_add_executable)
|
endfunction(rosetta_add_executable)
|
||||||
|
|
||||||
|
function(rosetta_add_service)
|
||||||
|
set(options)
|
||||||
|
set(one_value_args NAME CFG_FILE)
|
||||||
|
set(multi_value_args SOURCES)
|
||||||
|
cmake_parse_arguments(PARSE_ARGV 0 arg
|
||||||
|
"${options}"
|
||||||
|
"${one_value_args}"
|
||||||
|
"${multi_value_args}")
|
||||||
|
|
||||||
|
set(exec_name ${arg_NAME})
|
||||||
|
get_property(programs GLOBAL PROPERTY rosetta_program_list)
|
||||||
|
set_property(GLOBAL PROPERTY rosetta_program_list ${programs} ${exec_name})
|
||||||
|
|
||||||
|
message(STATUS "Building service ${exec_name}")
|
||||||
|
add_executable(${exec_name} ${arg_SOURCES})
|
||||||
|
|
||||||
|
set_target_properties(${exec_name} PROPERTIES
|
||||||
|
POSITION_INDEPENDENT_CODE ON
|
||||||
|
service_cfg_path ${arg_CFG_FILE})
|
||||||
|
install(TARGETS ${exec_name}
|
||||||
|
DESTINATION ${arg_SYSROOT_PATH})
|
||||||
|
endfunction(rosetta_add_service)
|
||||||
|
|
||||||
function(rosetta_add_library)
|
function(rosetta_add_library)
|
||||||
set(options STATIC SHARED)
|
set(options STATIC SHARED)
|
||||||
set(one_value_args NAME)
|
set(one_value_args NAME)
|
||||||
@@ -64,6 +87,8 @@ function(rosetta_add_library)
|
|||||||
${arg_SOURCES}
|
${arg_SOURCES}
|
||||||
${arg_HEADERS})
|
${arg_HEADERS})
|
||||||
set_target_properties(${static_lib_name} PROPERTIES OUTPUT_NAME "${lib_name}")
|
set_target_properties(${static_lib_name} PROPERTIES OUTPUT_NAME "${lib_name}")
|
||||||
|
target_compile_definitions(${static_lib_name} PRIVATE
|
||||||
|
BUILD_STATIC=1)
|
||||||
set(targets ${targets} ${static_lib_name})
|
set(targets ${targets} ${static_lib_name})
|
||||||
|
|
||||||
if (arg_PUBLIC_INCLUDE_DIRS)
|
if (arg_PUBLIC_INCLUDE_DIRS)
|
||||||
@@ -86,6 +111,8 @@ function(rosetta_add_library)
|
|||||||
PATH ${arg_PUBLIC_INCLUDE_DIRS})
|
PATH ${arg_PUBLIC_INCLUDE_DIRS})
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
target_compile_definitions(${shared_lib_name} PRIVATE
|
||||||
|
BUILD_SHARED=1)
|
||||||
set_target_properties(${shared_lib_name} PROPERTIES
|
set_target_properties(${shared_lib_name} PROPERTIES
|
||||||
SOVERSION 1)
|
SOVERSION 1)
|
||||||
target_link_options(${shared_lib_name} PRIVATE -Wl,--soname,${soname})
|
target_link_options(${shared_lib_name} PRIVATE -Wl,--soname,${soname})
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
file(GLOB if_files *.if)
|
file(GLOB if_files *.xpc)
|
||||||
|
|
||||||
foreach (file ${if_files})
|
foreach (file ${if_files})
|
||||||
get_filename_component(name ${file} NAME_WLE)
|
get_filename_component(name ${file} NAME_WLE)
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
interface fs {
|
|
||||||
msg open(string path, int flags) -> (int err);
|
|
||||||
}
|
|
||||||
11
interface/fs.xpc
Normal file
11
interface/fs.xpc
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
interface fs 6400;
|
||||||
|
|
||||||
|
func open[0](path: string, flags: int) -> (err: int);
|
||||||
|
func close[1]() -> (err: int);
|
||||||
|
|
||||||
|
func read[2](count: size) -> (err: int, nr_read: size, data: buffer);
|
||||||
|
func write[3](data: buffer) -> (err: int, nr_written: size);
|
||||||
|
|
||||||
|
func seek[4](offset: offset, origin: int) -> (err: int, new_pos: offset);
|
||||||
|
|
||||||
|
func map[5](prot: int, flags: int) -> (err: int, vmo: handle);
|
||||||
2
kernel
2
kernel
Submodule kernel updated: 1d4cb882a8...110f625f04
@@ -1,4 +1,4 @@
|
|||||||
set(source_dirs core malloc)
|
set(source_dirs core malloc io)
|
||||||
|
|
||||||
set(public_include_dirs
|
set(public_include_dirs
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
@@ -26,5 +26,7 @@ bsp_add_library(
|
|||||||
NAME libc
|
NAME libc
|
||||||
LIB_DIR /usr/lib)
|
LIB_DIR /usr/lib)
|
||||||
|
|
||||||
target_link_libraries(libc libmango)
|
target_link_libraries(libc PRIVATE libmango librosetta libxpc-static interface::fs)
|
||||||
target_compile_definitions(libc PRIVATE ENABLE_GLOBAL_HEAP=1)
|
target_compile_definitions(libc PRIVATE ENABLE_GLOBAL_HEAP=1)
|
||||||
|
|
||||||
|
add_subdirectory(pthread)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
set(source_dirs stdio string)
|
set(source_dirs stdio string errno)
|
||||||
|
|
||||||
foreach (dir ${source_dirs})
|
foreach (dir ${source_dirs})
|
||||||
file(GLOB dir_sources ${CMAKE_CURRENT_SOURCE_DIR}/${dir}/*.c)
|
file(GLOB dir_sources ${CMAKE_CURRENT_SOURCE_DIR}/${dir}/*.c)
|
||||||
@@ -8,16 +8,22 @@ foreach (dir ${source_dirs})
|
|||||||
set(headers ${headers} ${dir_headers})
|
set(headers ${headers} ${dir_headers})
|
||||||
endforeach (dir)
|
endforeach (dir)
|
||||||
|
|
||||||
set(component_sources ${sources} PARENT_SCOPE)
|
file(GLOB sys_sources
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/sys/${CMAKE_SYSTEM_PROCESSOR}/*.c
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/sys/${CMAKE_SYSTEM_PROCESSOR}/*.S)
|
||||||
|
|
||||||
|
set(component_sources ${sources} ${sys_sources} PARENT_SCOPE)
|
||||||
set(component_headers ${headers} PARENT_SCOPE)
|
set(component_headers ${headers} PARENT_SCOPE)
|
||||||
|
|
||||||
rosetta_add_library(STATIC
|
rosetta_add_library(STATIC
|
||||||
NAME libc-core
|
NAME libc-core
|
||||||
PUBLIC_INCLUDE_DIRS ${public_include_dirs}
|
PUBLIC_INCLUDE_DIRS ${public_include_dirs}
|
||||||
SOURCES ${sources}
|
SOURCES ${sources} ${sys_sources}
|
||||||
HEADERS ${headers})
|
HEADERS ${headers})
|
||||||
|
|
||||||
sysroot_add_library(
|
sysroot_add_library(
|
||||||
NAME libc-core
|
NAME libc-core
|
||||||
HEADER_DIR /usr/include
|
HEADER_DIR /usr/include
|
||||||
LIB_DIR /usr/lib)
|
LIB_DIR /usr/lib)
|
||||||
|
|
||||||
|
target_link_libraries(libc-core PRIVATE libmango librosetta)
|
||||||
|
|||||||
64
lib/libc/core/errno/errno.c
Normal file
64
lib/libc/core/errno/errno.c
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
#include <errno.h>
|
||||||
|
#include <mango/log.h>
|
||||||
|
#include <mango/status.h>
|
||||||
|
|
||||||
|
static int __errno = 32;
|
||||||
|
|
||||||
|
int __attribute__((weak)) * __errno_location(void)
|
||||||
|
{
|
||||||
|
kern_log("using builtin errno");
|
||||||
|
return &__errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(BUILD_STATIC)
|
||||||
|
int __set_errno(int err)
|
||||||
|
{
|
||||||
|
return -err;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(BUILD_SHARED)
|
||||||
|
int __set_errno(int err)
|
||||||
|
{
|
||||||
|
/* TODO */
|
||||||
|
*__errno_location() = err;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int __errno_from_kern_status(unsigned int err)
|
||||||
|
{
|
||||||
|
switch (err) {
|
||||||
|
case KERN_OK:
|
||||||
|
return SUCCESS;
|
||||||
|
case KERN_UNIMPLEMENTED:
|
||||||
|
return ENOSYS;
|
||||||
|
case KERN_NAME_EXISTS:
|
||||||
|
return EEXIST;
|
||||||
|
case KERN_INVALID_ARGUMENT:
|
||||||
|
return EINVAL;
|
||||||
|
case KERN_UNSUPPORTED:
|
||||||
|
return ENOTSUP;
|
||||||
|
case KERN_NO_MEMORY:
|
||||||
|
return ENOMEM;
|
||||||
|
case KERN_NO_ENTRY:
|
||||||
|
return ENOENT;
|
||||||
|
case KERN_WOULD_BLOCK:
|
||||||
|
return EWOULDBLOCK;
|
||||||
|
case KERN_NO_DEVICE:
|
||||||
|
return ENODEV;
|
||||||
|
case KERN_DEVICE_STUCK:
|
||||||
|
case KERN_IO_ERROR:
|
||||||
|
return EIO;
|
||||||
|
case KERN_FATAL_ERROR:
|
||||||
|
return ENXIO;
|
||||||
|
case KERN_BAD_STATE:
|
||||||
|
return EPERM;
|
||||||
|
case KERN_MEMORY_FAULT:
|
||||||
|
return EFAULT;
|
||||||
|
case KERN_ACCESS_DENIED:
|
||||||
|
return EACCES;
|
||||||
|
default:
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
26
lib/libc/core/string/strcpy.c
Normal file
26
lib/libc/core/string/strcpy.c
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
char *strcpy(char *output, const char *input)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
for (i = 0; input[i] != 0; i++) {
|
||||||
|
output[i] = input[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
output[i] = '\0';
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *strncpy(char *output, const char *input, unsigned int count)
|
||||||
|
{
|
||||||
|
unsigned int size = count;
|
||||||
|
unsigned int i;
|
||||||
|
for (i = 0; i < size; i++) {
|
||||||
|
output[i] = input[i];
|
||||||
|
|
||||||
|
if (input[i] == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output[i] = '\0';
|
||||||
|
return output;
|
||||||
|
}
|
||||||
18
lib/libc/core/sys/x86_64/init.c
Normal file
18
lib/libc/core/sys/x86_64/init.c
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#include <mango/log.h>
|
||||||
|
#include <rosetta/bootstrap.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
extern int main(int, const char **, const char **);
|
||||||
|
|
||||||
|
void *__attribute__((weak)) pthread_self(void)
|
||||||
|
{
|
||||||
|
/* Nothing */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int __libc_init(const struct rosetta_bootstrap *bsinfo)
|
||||||
|
{
|
||||||
|
(volatile void)pthread_self();
|
||||||
|
kern_logf("bsinfo = %p", bsinfo);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
#ifndef ERRNO_H_
|
#ifndef ERRNO_H_
|
||||||
#define ERRNO_H_
|
#define ERRNO_H_
|
||||||
|
|
||||||
|
#define errno (*__errno_location())
|
||||||
|
|
||||||
#define SUCCESS 0 /* Success */
|
#define SUCCESS 0 /* Success */
|
||||||
#define EPERM 1 /* Operation not permitted */
|
#define EPERM 1 /* Operation not permitted */
|
||||||
#define ENOENT 2 /* No such file or directory */
|
#define ENOENT 2 /* No such file or directory */
|
||||||
@@ -139,4 +141,9 @@
|
|||||||
#define EQFULL 106 /* Interface output queue is full */
|
#define EQFULL 106 /* Interface output queue is full */
|
||||||
#define ELAST 106 /* Must be equal largest errno */
|
#define ELAST 106 /* Must be equal largest errno */
|
||||||
|
|
||||||
|
extern int __set_errno(int err);
|
||||||
|
extern int __errno_from_kern_status(unsigned int err);
|
||||||
|
|
||||||
|
extern int __attribute__((weak)) * __errno_location(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
53
lib/libc/include/fcntl.h
Normal file
53
lib/libc/include/fcntl.h
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
#ifndef FCNTL_H_
|
||||||
|
#define FCNTL_H_
|
||||||
|
|
||||||
|
#define O_RDONLY 0x0000 /* open for reading only */
|
||||||
|
#define O_WRONLY 0x0001 /* open for writing only */
|
||||||
|
#define O_RDWR 0x0002 /* open for reading and writing */
|
||||||
|
#define O_ACCMODE 0x0003 /* mask for above modes */
|
||||||
|
|
||||||
|
#define O_NONBLOCK 0x00000004 /* no delay */
|
||||||
|
#define O_APPEND 0x00000008 /* set append mode */
|
||||||
|
|
||||||
|
#define O_SHLOCK 0x00000010 /* open with shared file lock */
|
||||||
|
#define O_EXLOCK 0x00000020 /* open with exclusive file lock */
|
||||||
|
#define O_ASYNC 0x00000040 /* signal pgrp when data ready */
|
||||||
|
#define O_FSYNC O_SYNC /* source compatibility: do not use */
|
||||||
|
#define O_NOFOLLOW 0x00000100 /* don't follow symlinks */
|
||||||
|
#define O_CREAT 0x00000200 /* create if nonexistant */
|
||||||
|
#define O_TRUNC 0x00000400 /* truncate to zero length */
|
||||||
|
#define O_EXCL 0x00000800 /* error if already exists */
|
||||||
|
#define O_RESOLVE_BENEATH \
|
||||||
|
0x00001000 /* only for open(2), same value as FMARK \
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define O_EVTONLY \
|
||||||
|
0x00008000 /* descriptor requested for event notifications only */
|
||||||
|
|
||||||
|
#define O_NOCTTY 0x00020000 /* don't assign controlling terminal */
|
||||||
|
|
||||||
|
#define O_DIRECTORY 0x00100000
|
||||||
|
#define O_SYMLINK 0x00200000 /* allow open of a symlink */
|
||||||
|
|
||||||
|
#define O_CLOEXEC 0x01000000 /* implicitly set FD_CLOEXEC */
|
||||||
|
|
||||||
|
#define O_NOFOLLOW_ANY 0x20000000 /* no symlinks allowed in path */
|
||||||
|
|
||||||
|
#define O_EXEC 0x40000000 /* open file for execute only */
|
||||||
|
#define O_SEARCH (O_EXEC | O_DIRECTORY) /* open directory for search only */
|
||||||
|
|
||||||
|
#define AT_FDCWD -2
|
||||||
|
|
||||||
|
#define AT_EACCESS 0x0010 /* Use effective ids in access check */
|
||||||
|
#define AT_SYMLINK_NOFOLLOW \
|
||||||
|
0x0020 /* Act on the symlink itself not the target */
|
||||||
|
#define AT_SYMLINK_FOLLOW 0x0040 /* Act on target of symlink */
|
||||||
|
#define AT_REMOVEDIR 0x0080 /* Path refers to directory */
|
||||||
|
#define AT_REALDEV \
|
||||||
|
0x0200 /* Return real device inodes resides on for fstatat(2) */
|
||||||
|
#define AT_FDONLY \
|
||||||
|
0x0400 /* Use only the fd and Ignore the path for fstatat(2) */
|
||||||
|
#define AT_SYMLINK_NOFOLLOW_ANY \
|
||||||
|
0x0800 /* Path should not contain any symlinks */
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -11,7 +11,12 @@ extern size_t strlen(const char *s);
|
|||||||
extern int strcmp(const char *s1, const char *s2);
|
extern int strcmp(const char *s1, const char *s2);
|
||||||
extern int strncmp(const char *s1, const char *s2, unsigned long n);
|
extern int strncmp(const char *s1, const char *s2, unsigned long n);
|
||||||
|
|
||||||
|
extern int strcpy(const char *s1, const char *s2);
|
||||||
|
extern int strncpy(const char *s1, const char *s2, unsigned long n);
|
||||||
|
|
||||||
extern void *memset(void *str, int c, size_t n);
|
extern void *memset(void *str, int c, size_t n);
|
||||||
extern void *memcpy(void *dst, const void *src, size_t len);
|
extern void *memcpy(void *dst, const void *src, size_t len);
|
||||||
|
|
||||||
|
extern char *strdup(char *s);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
46
lib/libc/include/sys/mman.h
Normal file
46
lib/libc/include/sys/mman.h
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
#ifndef SYS_MMAN_H_
|
||||||
|
#define SYS_MMAN_H_
|
||||||
|
|
||||||
|
#include <mango/types.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#define PROT_NONE 0x00u
|
||||||
|
#define PROT_EXEC 0x01u
|
||||||
|
#define PROT_READ 0x02u
|
||||||
|
#define PROT_WRITE 0x04u
|
||||||
|
|
||||||
|
#define MAP_FAILED ((void *)-1)
|
||||||
|
|
||||||
|
#define MAP_SHARED 0x01u
|
||||||
|
#define MAP_SHARED_VALIDATE 0x02u
|
||||||
|
#define MAP_PRIVATE 0x04u
|
||||||
|
#define MAP_32BIT 0x08u
|
||||||
|
#define MAP_ANON MAP_ANONYMOUS
|
||||||
|
#define MAP_ANONYMOUS 0x10u
|
||||||
|
#define MAP_DENYWRITE 0x20u
|
||||||
|
#define MAP_EXECUTABLE 0x40u
|
||||||
|
#define MAP_FILE 0x80u
|
||||||
|
#define MAP_FIXED 0x100u
|
||||||
|
#define MAP_FIXED_NOREPLACE 0x300u
|
||||||
|
#define MAP_GROWSDOWN 0x400u
|
||||||
|
#define MAP_HUGETLB 0x800u
|
||||||
|
#define MAP_HUGE_2MB 0x1000u
|
||||||
|
#define MAP_HUGE_1GB 0x2000u
|
||||||
|
#define MAP_LOCKED 0x4000u
|
||||||
|
#define MAP_NONBLOCK 0x8000u
|
||||||
|
#define MAP_NORESERVE 0x10000u
|
||||||
|
#define MAP_POPULATE 0x20000u
|
||||||
|
#define MAP_STACK 0x40000u
|
||||||
|
#define MAP_SYNC 0x80000u
|
||||||
|
#define MAP_UNINITIALIZED 0x100000u
|
||||||
|
|
||||||
|
extern void *mmap(
|
||||||
|
void *addr,
|
||||||
|
size_t length,
|
||||||
|
int prot,
|
||||||
|
int flags,
|
||||||
|
int fd,
|
||||||
|
off_t offset);
|
||||||
|
extern int munmap(void *addr, size_t length);
|
||||||
|
|
||||||
|
#endif
|
||||||
18
lib/libc/include/sys/remote.h
Normal file
18
lib/libc/include/sys/remote.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#ifndef SYS_REMOTE_H_
|
||||||
|
#define SYS_REMOTE_H_
|
||||||
|
|
||||||
|
#include <mango/types.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
enum sys_remote_id {
|
||||||
|
SYS_REMOTE_NONE,
|
||||||
|
SYS_REMOTE_NSD,
|
||||||
|
};
|
||||||
|
|
||||||
|
extern bool sys_remote_get(
|
||||||
|
enum sys_remote_id id,
|
||||||
|
tid_t *out_tid,
|
||||||
|
unsigned int *out_chid);
|
||||||
|
extern void sys_remote_set(enum sys_remote_id id, tid_t tid, unsigned int chid);
|
||||||
|
|
||||||
|
#endif
|
||||||
10
lib/libc/include/sys/types.h
Normal file
10
lib/libc/include/sys/types.h
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#ifndef SYS_TYPES_H_
|
||||||
|
#define SYS_TYPES_H_
|
||||||
|
|
||||||
|
#include <mango/types.h>
|
||||||
|
|
||||||
|
#define SEEK_SET 0
|
||||||
|
#define SEEK_CUR 1
|
||||||
|
#define SEEK_END 2
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,9 +1,15 @@
|
|||||||
#ifndef UNISTD_H_
|
#ifndef UNISTD_H_
|
||||||
#define UNISTD_H_
|
#define UNISTD_H_
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stddef.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
extern int open(const char *path, int flags);
|
extern int open(const char *path, int flags);
|
||||||
extern int close(int fd);
|
extern int close(int fd);
|
||||||
|
|
||||||
|
extern int read(int fd, void *buf, size_t count);
|
||||||
|
extern int write(int fd, const void *buf, size_t count);
|
||||||
|
|
||||||
|
extern off_t lseek(int fd, off_t offset, int whence);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
33
lib/libc/io/CMakeLists.txt
Normal file
33
lib/libc/io/CMakeLists.txt
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
set(source_dirs unistd stdio)
|
||||||
|
|
||||||
|
file(GLOB sources *.c *.h)
|
||||||
|
|
||||||
|
foreach (dir ${source_dirs})
|
||||||
|
file(GLOB dir_sources ${CMAKE_CURRENT_SOURCE_DIR}/${dir}/*.c)
|
||||||
|
file(GLOB dir_headers ${CMAKE_CURRENT_SOURCE_DIR}/${dir}/*.h)
|
||||||
|
|
||||||
|
set(sources ${sources} ${dir_sources})
|
||||||
|
set(headers ${headers} ${dir_headers})
|
||||||
|
endforeach (dir)
|
||||||
|
|
||||||
|
file(GLOB_RECURSE sub_headers ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h)
|
||||||
|
set(headers ${headers} ${sub_headers})
|
||||||
|
|
||||||
|
set(component_sources ${sources} PARENT_SCOPE)
|
||||||
|
set(component_headers ${headers} PARENT_SCOPE)
|
||||||
|
set(component_public_include_dirs ${CMAKE_CURRENT_SOURCE_DIR}/include PARENT_SCOPE)
|
||||||
|
|
||||||
|
rosetta_add_library(STATIC
|
||||||
|
NAME libc-io
|
||||||
|
PUBLIC_INCLUDE_DIRS
|
||||||
|
${public_include_dirs}
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||||
|
SOURCES ${sources}
|
||||||
|
HEADERS ${headers})
|
||||||
|
|
||||||
|
sysroot_add_library(
|
||||||
|
NAME libc-io
|
||||||
|
HEADER_DIR /usr/include
|
||||||
|
LIB_DIR /usr/lib)
|
||||||
|
|
||||||
|
target_link_libraries(libc-io libc-core interface::fs libxpc-static libmango)
|
||||||
2
lib/libc/io/fs.c
Normal file
2
lib/libc/io/fs.c
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#define MSG_IMPLEMENTATION
|
||||||
|
#include <rosetta/fs.h>
|
||||||
45
lib/libc/io/remote.c
Normal file
45
lib/libc/io/remote.c
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
#include <sys/remote.h>
|
||||||
|
|
||||||
|
#define TID_INVALID ((tid_t) - 1)
|
||||||
|
#define CHID_INVALID ((unsigned int)-1)
|
||||||
|
|
||||||
|
struct remote {
|
||||||
|
tid_t tid;
|
||||||
|
unsigned int chid;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct remote remotes[] = {
|
||||||
|
[SYS_REMOTE_NONE] = {.tid = TID_INVALID, .chid = CHID_INVALID},
|
||||||
|
[SYS_REMOTE_NSD] = {.tid = TID_INVALID, .chid = CHID_INVALID},
|
||||||
|
};
|
||||||
|
static const size_t nr_remotes = sizeof remotes / sizeof remotes[0];
|
||||||
|
|
||||||
|
bool sys_remote_get(
|
||||||
|
enum sys_remote_id id,
|
||||||
|
tid_t *out_tid,
|
||||||
|
unsigned int *out_chid)
|
||||||
|
{
|
||||||
|
if (id < 0 || id >= nr_remotes) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct remote *remote = &remotes[id];
|
||||||
|
if (remote->tid == TID_INVALID || remote->chid == CHID_INVALID) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_tid = remote->tid;
|
||||||
|
*out_chid = remote->chid;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sys_remote_set(enum sys_remote_id id, tid_t tid, unsigned int chid)
|
||||||
|
{
|
||||||
|
if (id < 0 || id >= nr_remotes) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct remote *remote = &remotes[id];
|
||||||
|
remote->tid = tid;
|
||||||
|
remote->chid = chid;
|
||||||
|
}
|
||||||
11
lib/libc/io/unistd/close.c
Normal file
11
lib/libc/io/unistd/close.c
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#include <errno.h>
|
||||||
|
#include <mango/handle.h>
|
||||||
|
#include <mango/msg.h>
|
||||||
|
#include <rosetta/fs.h>
|
||||||
|
#include <sys/remote.h>
|
||||||
|
|
||||||
|
int close(int fd)
|
||||||
|
{
|
||||||
|
kern_handle_close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
22
lib/libc/io/unistd/lseek.c
Normal file
22
lib/libc/io/unistd/lseek.c
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#include <errno.h>
|
||||||
|
#include <mango/handle.h>
|
||||||
|
#include <mango/msg.h>
|
||||||
|
#include <rosetta/fs.h>
|
||||||
|
#include <sys/remote.h>
|
||||||
|
|
||||||
|
off_t lseek(int fd, off_t offset, int whence)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
off_t new_offset;
|
||||||
|
|
||||||
|
kern_status_t status = fs_seek(fd, offset, whence, &err, &new_offset);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
return __set_errno(__errno_from_kern_status(status));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err != SUCCESS) {
|
||||||
|
return __set_errno(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new_offset;
|
||||||
|
}
|
||||||
170
lib/libc/io/unistd/mmap.c
Normal file
170
lib/libc/io/unistd/mmap.c
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
#include <errno.h>
|
||||||
|
#include <mango/handle.h>
|
||||||
|
#include <mango/task.h>
|
||||||
|
#include <mango/vm.h>
|
||||||
|
#include <rosetta/fs.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
static vm_prot_t vm_prot_from_mmap_prot(int prot)
|
||||||
|
{
|
||||||
|
vm_prot_t vm_prot = VM_PROT_USER;
|
||||||
|
|
||||||
|
if (prot & PROT_READ) {
|
||||||
|
vm_prot |= VM_PROT_READ;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prot & PROT_WRITE) {
|
||||||
|
vm_prot |= VM_PROT_WRITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prot & PROT_EXEC) {
|
||||||
|
vm_prot |= VM_PROT_EXEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
return vm_prot;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_vmo_anon(
|
||||||
|
int fd,
|
||||||
|
int prot,
|
||||||
|
int flags,
|
||||||
|
size_t length,
|
||||||
|
kern_handle_t *out)
|
||||||
|
{
|
||||||
|
vm_prot_t vm_prot = vm_prot_from_mmap_prot(prot);
|
||||||
|
kern_status_t status = vm_object_create(NULL, 0, length, vm_prot, out);
|
||||||
|
return __errno_from_kern_status(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_vmo(
|
||||||
|
int fd,
|
||||||
|
int prot,
|
||||||
|
int flags,
|
||||||
|
size_t length,
|
||||||
|
kern_handle_t *out)
|
||||||
|
{
|
||||||
|
if (fd == -1) {
|
||||||
|
return get_vmo_anon(fd, prot, flags, length, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
int err = 0;
|
||||||
|
kern_status_t status = fs_map(fd, prot, flags, &err, out);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
return __errno_from_kern_status(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *mreserve(kern_handle_t address_space, void *addr, size_t length)
|
||||||
|
{
|
||||||
|
virt_addr_t base = (virt_addr_t)addr;
|
||||||
|
if (!base) {
|
||||||
|
base = MAP_ADDRESS_ANY;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t status
|
||||||
|
= address_space_reserve(address_space, base, length, &base);
|
||||||
|
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
__set_errno(__errno_from_kern_status(status));
|
||||||
|
return MAP_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (void *)base;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset)
|
||||||
|
{
|
||||||
|
int tmp = 0;
|
||||||
|
|
||||||
|
if (flags & MAP_SHARED) {
|
||||||
|
tmp++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & MAP_SHARED_VALIDATE) {
|
||||||
|
tmp++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & MAP_PRIVATE) {
|
||||||
|
tmp++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tmp != 1) {
|
||||||
|
__set_errno(EINVAL);
|
||||||
|
return MAP_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flags & MAP_ANONYMOUS) && fd != -1) {
|
||||||
|
__set_errno(EINVAL);
|
||||||
|
return MAP_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(flags & MAP_ANONYMOUS) && fd == -1) {
|
||||||
|
__set_errno(EINVAL);
|
||||||
|
return MAP_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t status = KERN_OK;
|
||||||
|
kern_handle_t self = KERN_HANDLE_INVALID,
|
||||||
|
address_space = KERN_HANDLE_INVALID;
|
||||||
|
|
||||||
|
status = task_self(&self);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
__set_errno(__errno_from_kern_status(status));
|
||||||
|
return MAP_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = task_get_address_space(self, &address_space);
|
||||||
|
kern_handle_close(self);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
__set_errno(__errno_from_kern_status(status));
|
||||||
|
return MAP_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flags & (MAP_ANONYMOUS | MAP_PRIVATE)) && (prot == PROT_NONE)) {
|
||||||
|
void *ret = mreserve(address_space, addr, length);
|
||||||
|
kern_handle_close(address_space);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_handle_t vmo = KERN_HANDLE_INVALID;
|
||||||
|
int err = get_vmo(fd, prot, flags, length, &vmo);
|
||||||
|
if (err != SUCCESS) {
|
||||||
|
kern_handle_close(address_space);
|
||||||
|
__set_errno(err);
|
||||||
|
return MAP_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
virt_addr_t map_address = 0;
|
||||||
|
vm_prot_t vm_prot = vm_prot_from_mmap_prot(prot);
|
||||||
|
if (addr && (flags & MAP_FIXED)) {
|
||||||
|
status = address_space_map(
|
||||||
|
address_space,
|
||||||
|
(virt_addr_t)addr,
|
||||||
|
vmo,
|
||||||
|
offset,
|
||||||
|
length,
|
||||||
|
vm_prot,
|
||||||
|
&map_address);
|
||||||
|
} else {
|
||||||
|
status = address_space_map(
|
||||||
|
address_space,
|
||||||
|
MAP_ADDRESS_ANY,
|
||||||
|
vmo,
|
||||||
|
offset,
|
||||||
|
length,
|
||||||
|
vm_prot,
|
||||||
|
&map_address);
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_handle_close(vmo);
|
||||||
|
kern_handle_close(address_space);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
__set_errno(__errno_from_kern_status(status));
|
||||||
|
return MAP_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (void *)map_address;
|
||||||
|
}
|
||||||
44
lib/libc/io/unistd/munmap.c
Normal file
44
lib/libc/io/unistd/munmap.c
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
#include <errno.h>
|
||||||
|
#include <mango/handle.h>
|
||||||
|
#include <mango/task.h>
|
||||||
|
#include <mango/vm.h>
|
||||||
|
#include <rosetta/fs.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
int munmap(void *addr, size_t length)
|
||||||
|
{
|
||||||
|
kern_status_t status = KERN_OK;
|
||||||
|
kern_handle_t self = KERN_HANDLE_INVALID,
|
||||||
|
address_space = KERN_HANDLE_INVALID;
|
||||||
|
|
||||||
|
status = task_self(&self);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
return __set_errno(EPERM);
|
||||||
|
}
|
||||||
|
|
||||||
|
status = task_get_address_space(self, &address_space);
|
||||||
|
kern_handle_close(self);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
return __set_errno(EPERM);
|
||||||
|
}
|
||||||
|
|
||||||
|
status = address_space_unmap(address_space, (virt_addr_t)addr, length);
|
||||||
|
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
kern_handle_close(address_space);
|
||||||
|
return __set_errno(__errno_from_kern_status(status));
|
||||||
|
}
|
||||||
|
|
||||||
|
status = address_space_release(
|
||||||
|
address_space,
|
||||||
|
(virt_addr_t)addr,
|
||||||
|
length);
|
||||||
|
kern_handle_close(address_space);
|
||||||
|
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
return __set_errno(__errno_from_kern_status(status));
|
||||||
|
}
|
||||||
|
|
||||||
|
return __set_errno(SUCCESS);
|
||||||
|
}
|
||||||
40
lib/libc/io/unistd/open.c
Normal file
40
lib/libc/io/unistd/open.c
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#include <errno.h>
|
||||||
|
#include <mango/handle.h>
|
||||||
|
#include <mango/msg.h>
|
||||||
|
#include <rosetta/fs.h>
|
||||||
|
#include <sys/remote.h>
|
||||||
|
|
||||||
|
int open(const char *path, int flags)
|
||||||
|
{
|
||||||
|
tid_t remote_tid;
|
||||||
|
unsigned int remote_chid;
|
||||||
|
if (!sys_remote_get(SYS_REMOTE_NSD, &remote_tid, &remote_chid)) {
|
||||||
|
return __set_errno(ENXIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_handle_t port;
|
||||||
|
kern_status_t status = port_create(&port);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
return __set_errno(__errno_from_kern_status(status));
|
||||||
|
}
|
||||||
|
|
||||||
|
status = port_connect(port, remote_tid, remote_chid);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
kern_handle_close(port);
|
||||||
|
return __set_errno(__errno_from_kern_status(status));
|
||||||
|
}
|
||||||
|
|
||||||
|
int err = SUCCESS;
|
||||||
|
status = fs_open(port, path, flags, &err);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
kern_handle_close(port);
|
||||||
|
return __set_errno(__errno_from_kern_status(status));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err != SUCCESS) {
|
||||||
|
kern_handle_close(port);
|
||||||
|
return __set_errno(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int)port;
|
||||||
|
}
|
||||||
21
lib/libc/io/unistd/read.c
Normal file
21
lib/libc/io/unistd/read.c
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#include <errno.h>
|
||||||
|
#include <mango/handle.h>
|
||||||
|
#include <mango/msg.h>
|
||||||
|
#include <rosetta/fs.h>
|
||||||
|
#include <sys/remote.h>
|
||||||
|
|
||||||
|
int read(int fd, void *buf, size_t count)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
size_t nr_read;
|
||||||
|
kern_status_t status = fs_read(fd, count, &err, &nr_read, buf, count);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
return __set_errno(__errno_from_kern_status(status));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err != SUCCESS) {
|
||||||
|
return __set_errno(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nr_read;
|
||||||
|
}
|
||||||
0
lib/libc/io/unistd/write.c
Normal file
0
lib/libc/io/unistd/write.c
Normal file
@@ -1,4 +1,4 @@
|
|||||||
set(source_dirs stdlib)
|
set(source_dirs stdlib string)
|
||||||
|
|
||||||
file(GLOB sources *.c *.h)
|
file(GLOB sources *.c *.h)
|
||||||
|
|
||||||
@@ -30,4 +30,5 @@ sysroot_add_library(
|
|||||||
HEADER_DIR /usr/include
|
HEADER_DIR /usr/include
|
||||||
LIB_DIR /usr/lib)
|
LIB_DIR /usr/lib)
|
||||||
|
|
||||||
|
target_compile_definitions(libc-malloc PRIVATE ENABLE_GLOBAL_HEAP=1)
|
||||||
target_link_libraries(libc-malloc libc-core libmango)
|
target_link_libraries(libc-malloc libc-core libmango)
|
||||||
|
|||||||
@@ -38,14 +38,10 @@ static kern_status_t init_heap_region(heap_t *heap)
|
|||||||
task_get_address_space(self, &address_space);
|
task_get_address_space(self, &address_space);
|
||||||
kern_handle_close(self);
|
kern_handle_close(self);
|
||||||
|
|
||||||
kern_status_t status = vm_region_create(
|
kern_status_t status = address_space_reserve(
|
||||||
address_space,
|
address_space,
|
||||||
"libc-heap",
|
MAP_ADDRESS_ANY,
|
||||||
9,
|
|
||||||
VM_REGION_ANY_OFFSET,
|
|
||||||
HEAP_REGION_SIZE,
|
HEAP_REGION_SIZE,
|
||||||
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_USER,
|
|
||||||
&heap->heap_region,
|
|
||||||
&heap->heap_base);
|
&heap->heap_base);
|
||||||
|
|
||||||
kern_handle_close(address_space);
|
kern_handle_close(address_space);
|
||||||
@@ -72,9 +68,14 @@ static kern_status_t expand_heap(heap_t *heap)
|
|||||||
|
|
||||||
virt_addr_t base = 0;
|
virt_addr_t base = 0;
|
||||||
|
|
||||||
status = vm_region_map_relative(
|
kern_handle_t self, address_space;
|
||||||
heap->heap_region,
|
task_self(&self);
|
||||||
heap->heap_sys_alloc,
|
task_get_address_space(self, &address_space);
|
||||||
|
kern_handle_close(self);
|
||||||
|
|
||||||
|
status = address_space_map(
|
||||||
|
address_space,
|
||||||
|
heap->heap_base + heap->heap_sys_alloc,
|
||||||
vmo,
|
vmo,
|
||||||
0,
|
0,
|
||||||
HEAP_EXPAND_INCREMENT,
|
HEAP_EXPAND_INCREMENT,
|
||||||
@@ -90,7 +91,7 @@ static kern_status_t expand_heap(heap_t *heap)
|
|||||||
void *heap_expand(heap_t *heap, size_t size)
|
void *heap_expand(heap_t *heap, size_t size)
|
||||||
{
|
{
|
||||||
kern_status_t status = KERN_OK;
|
kern_status_t status = KERN_OK;
|
||||||
if (heap->heap_region == KERN_HANDLE_INVALID) {
|
if (!heap->heap_base) {
|
||||||
status = init_heap_region(heap);
|
status = init_heap_region(heap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ struct liballoc_minor;
|
|||||||
|
|
||||||
#define HEAP_INIT \
|
#define HEAP_INIT \
|
||||||
{ \
|
{ \
|
||||||
.heap_region = KERN_HANDLE_INVALID, \
|
|
||||||
.heap_liballoc = { \
|
.heap_liballoc = { \
|
||||||
.l_pageSize = 4096, \
|
.l_pageSize = 4096, \
|
||||||
.l_pageCount = 16, \
|
.l_pageCount = 16, \
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ typedef enum heap_result {
|
|||||||
} heap_result_t;
|
} heap_result_t;
|
||||||
|
|
||||||
typedef struct heap {
|
typedef struct heap {
|
||||||
kern_handle_t heap_region;
|
|
||||||
/* amount of space requested from the heap by the user */
|
/* amount of space requested from the heap by the user */
|
||||||
size_t heap_req_alloc;
|
size_t heap_req_alloc;
|
||||||
/* amount of space requested from the system by the heap */
|
/* amount of space requested from the system by the heap */
|
||||||
|
|||||||
14
lib/libc/malloc/string/strdup.c
Normal file
14
lib/libc/malloc/string/strdup.c
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
char *strdup(char *s)
|
||||||
|
{
|
||||||
|
size_t len = strlen(s);
|
||||||
|
char *out = malloc(len + 1);
|
||||||
|
if (!out) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(out, s, len + 1);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
46
lib/libc/pthread/CMakeLists.txt
Normal file
46
lib/libc/pthread/CMakeLists.txt
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
set(pthread_source_dirs thread)
|
||||||
|
|
||||||
|
foreach (dir ${pthread_source_dirs})
|
||||||
|
file(GLOB dir_sources ${CMAKE_CURRENT_SOURCE_DIR}/${dir}/*.c)
|
||||||
|
file(GLOB dir_headers ${CMAKE_CURRENT_SOURCE_DIR}/${dir}/*.h)
|
||||||
|
|
||||||
|
set(pthread_sources ${pthread_sources} ${dir_sources})
|
||||||
|
set(pthread_headers ${pthread_headers} ${dir_headers})
|
||||||
|
endforeach (dir)
|
||||||
|
|
||||||
|
file(GLOB pthread_sys_sources
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/sys/${CMAKE_SYSTEM_PROCESSOR}/*.c
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/sys/${CMAKE_SYSTEM_PROCESSOR}/*.S)
|
||||||
|
|
||||||
|
set(pthread_sources ${pthread_sources} ${pthread_sys_sources})
|
||||||
|
|
||||||
|
set(pthread_headers ${pthread_headers} ${CMAKE_CURRENT_SOURCE_DIR}/include/pthread.h)
|
||||||
|
set(pthread_public_include_dir ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
|
|
||||||
|
rosetta_add_library(STATIC
|
||||||
|
NAME libc-pthread
|
||||||
|
PUBLIC_INCLUDE_DIRS ${pthread_public_include_dir}
|
||||||
|
SOURCES ${pthread_sources}
|
||||||
|
HEADERS ${pthread_headers})
|
||||||
|
rosetta_add_library(SHARED
|
||||||
|
NAME libpthread
|
||||||
|
PUBLIC_INCLUDE_DIRS ${pthread_public_include_dir}
|
||||||
|
SOURCES ${pthread_sources}
|
||||||
|
HEADERS ${pthread_headers})
|
||||||
|
|
||||||
|
sysroot_add_library(
|
||||||
|
NAME libc-pthread
|
||||||
|
HEADER_DIR /usr/include
|
||||||
|
LIB_DIR /usr/lib)
|
||||||
|
sysroot_add_library(
|
||||||
|
NAME libpthread
|
||||||
|
HEADER_DIR /usr/include
|
||||||
|
LIB_DIR /usr/lib)
|
||||||
|
|
||||||
|
bsp_add_library(
|
||||||
|
NAME libpthread
|
||||||
|
LIB_DIR /usr/lib)
|
||||||
|
|
||||||
|
target_link_libraries(libc-pthread PRIVATE libc-io libmango)
|
||||||
|
target_link_libraries(libpthread PRIVATE libmango)
|
||||||
|
target_link_libraries(libpthread PUBLIC libc)
|
||||||
25
lib/libc/pthread/include/pthread.h
Normal file
25
lib/libc/pthread/include/pthread.h
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#ifndef PTHREAD_H_
|
||||||
|
#define PTHREAD_H_
|
||||||
|
|
||||||
|
#define __PTHREAD_ATTR_SIZE__ 32
|
||||||
|
|
||||||
|
typedef struct __pthread *pthread_t;
|
||||||
|
|
||||||
|
typedef struct __pthread_attr {
|
||||||
|
long __sig;
|
||||||
|
char __opaque[__PTHREAD_ATTR_SIZE__];
|
||||||
|
} pthread_attr_t;
|
||||||
|
|
||||||
|
extern int __pthread_init(void);
|
||||||
|
|
||||||
|
extern int pthread_create(
|
||||||
|
pthread_t *thread,
|
||||||
|
const pthread_attr_t *attr,
|
||||||
|
void *(*start_func)(void *),
|
||||||
|
void *arg);
|
||||||
|
extern pthread_t pthread_self(void);
|
||||||
|
extern int pthread_join(pthread_t thread, void **retval);
|
||||||
|
extern int pthread_detach(pthread_t thread);
|
||||||
|
extern void pthread_exit(void *retval);
|
||||||
|
|
||||||
|
#endif
|
||||||
0
lib/libc/pthread/init.c
Normal file
0
lib/libc/pthread/init.c
Normal file
13
lib/libc/pthread/sys/x86_64/pthread_self.S
Normal file
13
lib/libc/pthread/sys/x86_64/pthread_self.S
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
.code64
|
||||||
|
|
||||||
|
.global __pthread_self
|
||||||
|
.type __pthread_self, @function
|
||||||
|
|
||||||
|
__pthread_self:
|
||||||
|
push %rbp
|
||||||
|
mov %rsp, %rbp
|
||||||
|
|
||||||
|
mov %gs:0, %rax
|
||||||
|
|
||||||
|
pop %rbp
|
||||||
|
ret
|
||||||
35
lib/libc/pthread/sys/x86_64/pthread_unmap_exit.S
Normal file
35
lib/libc/pthread/sys/x86_64/pthread_unmap_exit.S
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
.code64
|
||||||
|
|
||||||
|
#include "mango/syscall.h"
|
||||||
|
|
||||||
|
.global __pthread_unmap_exit
|
||||||
|
.type __pthread_unmap_exit, @function
|
||||||
|
|
||||||
|
/*
|
||||||
|
%rdi = (kern_handle_t)address_space
|
||||||
|
%rsi = (void *)unmap_base
|
||||||
|
%rdx = (size_t)unmap_length
|
||||||
|
*/
|
||||||
|
__pthread_unmap_exit:
|
||||||
|
push %rbp
|
||||||
|
mov %rsp, %rbp
|
||||||
|
|
||||||
|
/* save the address space handle for later */
|
||||||
|
mov %rdi, %rbx
|
||||||
|
|
||||||
|
/* first, unmap the specified region */
|
||||||
|
mov $SYS_ADDRESS_SPACE_UNMAP, %rax
|
||||||
|
/* args are already in the correct registers */
|
||||||
|
syscall
|
||||||
|
|
||||||
|
/* next, close the handle to the address space */
|
||||||
|
mov $SYS_THREAD_EXIT, %rax
|
||||||
|
mov %rbx, %rdi
|
||||||
|
syscall
|
||||||
|
|
||||||
|
/* finally, stop the current thread */
|
||||||
|
mov $SYS_THREAD_EXIT, %rax
|
||||||
|
syscall
|
||||||
|
|
||||||
|
/* unreachable */
|
||||||
|
ret
|
||||||
12
lib/libc/pthread/thread/errno.c
Normal file
12
lib/libc/pthread/thread/errno.c
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#include "pthread.h"
|
||||||
|
|
||||||
|
#include <mango/log.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int *__errno_location(void)
|
||||||
|
{
|
||||||
|
struct __pthread *self = pthread_self();
|
||||||
|
kern_logf("using pthread errno %p", &self->thr_errno);
|
||||||
|
return &self->thr_errno;
|
||||||
|
}
|
||||||
26
lib/libc/pthread/thread/pthread.h
Normal file
26
lib/libc/pthread/thread/pthread.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef _THREAD_PTHREAD_H_
|
||||||
|
#define _THREAD_PTHREAD_H_
|
||||||
|
|
||||||
|
#include <mango/types.h>
|
||||||
|
|
||||||
|
enum pthread_flags {
|
||||||
|
THREAD_DETACHED = 0x01u,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct __pthread {
|
||||||
|
struct __pthread *thr_self;
|
||||||
|
int thr_errno;
|
||||||
|
enum pthread_flags thr_flags;
|
||||||
|
kern_handle_t thr_handle;
|
||||||
|
void *thr_map_base;
|
||||||
|
size_t thr_map_size;
|
||||||
|
void *thr_result;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct __pthread *__pthread_self(void);
|
||||||
|
extern void __pthread_unmap_exit(
|
||||||
|
kern_handle_t address_space,
|
||||||
|
void *unmap_base,
|
||||||
|
size_t unmap_length);
|
||||||
|
|
||||||
|
#endif
|
||||||
0
lib/libc/pthread/thread/pthread_attr.h
Normal file
0
lib/libc/pthread/thread/pthread_attr.h
Normal file
89
lib/libc/pthread/thread/pthread_create.c
Normal file
89
lib/libc/pthread/thread/pthread_create.c
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
#include "pthread.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <mango/status.h>
|
||||||
|
#include <mango/task.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
#define DEFAULT_STACK_SIZE 0x40000
|
||||||
|
|
||||||
|
static void thread_launchpad(uintptr_t thread, uintptr_t func, uintptr_t arg)
|
||||||
|
{
|
||||||
|
struct __pthread *self = (struct __pthread *)thread;
|
||||||
|
void *(*start_func)(void *) = (void *(*)(void *))func;
|
||||||
|
|
||||||
|
void *result = start_func((void *)arg);
|
||||||
|
|
||||||
|
pthread_exit(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_create(
|
||||||
|
pthread_t *thread,
|
||||||
|
const pthread_attr_t *attr,
|
||||||
|
void *(*start_func)(void *),
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
kern_status_t status = KERN_OK;
|
||||||
|
kern_handle_t task;
|
||||||
|
|
||||||
|
status = task_self(&task);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
return __set_errno(EPERM);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t stack_size = DEFAULT_STACK_SIZE;
|
||||||
|
|
||||||
|
void *base
|
||||||
|
= mmap(NULL,
|
||||||
|
stack_size,
|
||||||
|
PROT_READ | PROT_WRITE,
|
||||||
|
MAP_PRIVATE | MAP_ANONYMOUS,
|
||||||
|
-1,
|
||||||
|
0);
|
||||||
|
|
||||||
|
if (!base) {
|
||||||
|
return __set_errno(ENOMEM);
|
||||||
|
}
|
||||||
|
|
||||||
|
virt_addr_t sp = (virt_addr_t)base + DEFAULT_STACK_SIZE;
|
||||||
|
|
||||||
|
sp -= sizeof(struct __pthread);
|
||||||
|
struct __pthread *new = (struct __pthread *)sp;
|
||||||
|
sp &= ~(virt_addr_t)0x10;
|
||||||
|
|
||||||
|
memset(new, 0x0, sizeof *new);
|
||||||
|
new->thr_self = new;
|
||||||
|
new->thr_map_base = base;
|
||||||
|
new->thr_map_size = stack_size;
|
||||||
|
|
||||||
|
uintptr_t args[] = {
|
||||||
|
(uintptr_t)new,
|
||||||
|
(uintptr_t)start_func,
|
||||||
|
(uintptr_t)arg,
|
||||||
|
};
|
||||||
|
size_t nr_args = sizeof args / sizeof args[0];
|
||||||
|
|
||||||
|
status = task_create_thread(
|
||||||
|
task,
|
||||||
|
(virt_addr_t)thread_launchpad,
|
||||||
|
sp,
|
||||||
|
args,
|
||||||
|
nr_args,
|
||||||
|
&new->thr_handle);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
munmap(base, stack_size);
|
||||||
|
return __set_errno(__errno_from_kern_status(status));
|
||||||
|
}
|
||||||
|
|
||||||
|
thread_config_set(
|
||||||
|
new->thr_handle,
|
||||||
|
THREAD_CFG_GSBASE,
|
||||||
|
&new,
|
||||||
|
sizeof(void *));
|
||||||
|
thread_start(new->thr_handle);
|
||||||
|
|
||||||
|
*thread = new;
|
||||||
|
return __set_errno(SUCCESS);
|
||||||
|
}
|
||||||
17
lib/libc/pthread/thread/pthread_detach.c
Normal file
17
lib/libc/pthread/thread/pthread_detach.c
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#include "pthread.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <mango/handle.h>
|
||||||
|
#include <mango/object.h>
|
||||||
|
#include <mango/signal.h>
|
||||||
|
#include <mango/task.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
int pthread_detach(struct __pthread *thread)
|
||||||
|
{
|
||||||
|
thread->thr_flags |= THREAD_DETACHED;
|
||||||
|
kern_handle_close(thread->thr_handle);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
31
lib/libc/pthread/thread/pthread_exit.c
Normal file
31
lib/libc/pthread/thread/pthread_exit.c
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#include "pthread.h"
|
||||||
|
|
||||||
|
#include <mango/handle.h>
|
||||||
|
#include <mango/task.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
extern void pthread_exit(void *retval)
|
||||||
|
{
|
||||||
|
struct __pthread *self = pthread_self();
|
||||||
|
if (!self) {
|
||||||
|
/* TODO: abort(); */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self->thr_flags & THREAD_DETACHED) {
|
||||||
|
kern_handle_t task;
|
||||||
|
kern_handle_t address_space;
|
||||||
|
task_self(&task);
|
||||||
|
task_get_address_space(task, &address_space);
|
||||||
|
kern_handle_close(task);
|
||||||
|
|
||||||
|
__pthread_unmap_exit(
|
||||||
|
address_space,
|
||||||
|
self->thr_map_base,
|
||||||
|
self->thr_map_size);
|
||||||
|
} else {
|
||||||
|
self->thr_result = retval;
|
||||||
|
thread_exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
31
lib/libc/pthread/thread/pthread_join.c
Normal file
31
lib/libc/pthread/thread/pthread_join.c
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#include "pthread.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <mango/handle.h>
|
||||||
|
#include <mango/object.h>
|
||||||
|
#include <mango/signal.h>
|
||||||
|
#include <mango/task.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
int pthread_join(struct __pthread *thread, void **retval)
|
||||||
|
{
|
||||||
|
kern_wait_item_t wait;
|
||||||
|
wait.w_handle = thread->thr_handle;
|
||||||
|
wait.w_waitfor = THREAD_SIGNAL_STOPPED;
|
||||||
|
wait.w_observed = 0;
|
||||||
|
|
||||||
|
kern_status_t status = kern_object_wait(&wait, 1);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
return __set_errno(EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retval) {
|
||||||
|
*retval = thread->thr_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_handle_close(thread->thr_handle);
|
||||||
|
munmap(thread->thr_map_base, thread->thr_map_size);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
36
lib/libc/pthread/thread/pthread_self.c
Normal file
36
lib/libc/pthread/thread/pthread_self.c
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#include "pthread.h"
|
||||||
|
|
||||||
|
#include <mango/task.h>
|
||||||
|
#include <mango/types.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
static struct __pthread main_thread = {0};
|
||||||
|
|
||||||
|
struct __pthread *pthread_self(void)
|
||||||
|
{
|
||||||
|
static int init = 0;
|
||||||
|
if (!init) {
|
||||||
|
kern_handle_t self_handle = KERN_HANDLE_INVALID;
|
||||||
|
kern_status_t status = thread_self(&self_handle);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
/* TODO set an errno value in a way that doesn't result
|
||||||
|
* in a recursive call to pthread_self */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
struct __pthread *self = &main_thread;
|
||||||
|
self->thr_self = self;
|
||||||
|
self->thr_handle = self_handle;
|
||||||
|
self->thr_map_base = self;
|
||||||
|
self->thr_map_size = sizeof *self;
|
||||||
|
thread_config_set(
|
||||||
|
self_handle,
|
||||||
|
THREAD_CFG_GSBASE,
|
||||||
|
&self,
|
||||||
|
sizeof(void *));
|
||||||
|
init = 1;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
return __pthread_self();
|
||||||
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
file(GLOB runtime_sources
|
file(GLOB runtime_sources
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/${CMAKE_SYSTEM_PROCESSOR}/*.s)
|
${CMAKE_CURRENT_SOURCE_DIR}/${CMAKE_SYSTEM_PROCESSOR}/*.s)
|
||||||
set_property(SOURCE ${runtime_sources} PROPERTY LANGUAGE C)
|
|
||||||
|
|
||||||
rosetta_add_object_library(
|
rosetta_add_object_library(
|
||||||
NAME libc-runtime STATIC
|
NAME libc-runtime STATIC
|
||||||
|
|||||||
@@ -3,14 +3,22 @@
|
|||||||
.global _start
|
.global _start
|
||||||
.type _start, @function
|
.type _start, @function
|
||||||
|
|
||||||
.extern main
|
.extern __libc_init
|
||||||
.type main, @function
|
.type __libc_init, @function
|
||||||
|
|
||||||
|
.extern task_exit
|
||||||
|
.type task_exit, @function
|
||||||
|
|
||||||
_start:
|
_start:
|
||||||
# Args (as provided by the ABI)
|
# %rdi: (struct rosetta_bootstrap *)bs_info
|
||||||
# %rdi: int argc
|
mov %rdi, %rbx
|
||||||
# %rsi: const char **argv
|
call __libc_init
|
||||||
# %rdx: kern_handle_t task
|
|
||||||
# %rcx: kern_handle_t address_space
|
mov 0(%rbx), %rdi # argc
|
||||||
|
mov 8(%rbx), %rsi # argv
|
||||||
|
mov 24(%rbx), %rdx # envp
|
||||||
call main
|
call main
|
||||||
|
|
||||||
|
mov %rax, %rdi
|
||||||
|
call task_exit
|
||||||
1: jmp 1b
|
1: jmp 1b
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ sysroot_add_library(
|
|||||||
HEADER_DIR /usr/include
|
HEADER_DIR /usr/include
|
||||||
LIB_DIR /usr/lib)
|
LIB_DIR /usr/lib)
|
||||||
|
|
||||||
target_link_libraries(libfs libmango interface::fs libc)
|
target_link_libraries(libfs libmango interface::fs libc libxpc)
|
||||||
target_link_libraries(libfs-static libmango interface::fs libc-core)
|
target_link_libraries(libfs-static libmango interface::fs libc-core libxpc-static)
|
||||||
|
|
||||||
set_target_properties(libfs-static PROPERTIES POSITION_INDEPENDENT_CODE FALSE)
|
set_target_properties(libfs-static PROPERTIES POSITION_INDEPENDENT_CODE FALSE)
|
||||||
|
|||||||
@@ -1,9 +1,23 @@
|
|||||||
#include "btree.h"
|
#include "btree.h"
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "interface.h"
|
#include "interface.h"
|
||||||
|
#include "mapping.h"
|
||||||
|
|
||||||
#include <fs/allocator.h>
|
#include <fs/allocator.h>
|
||||||
#include <fs/context.h>
|
#include <fs/context.h>
|
||||||
|
#include <fs/dentry.h>
|
||||||
|
#include <fs/inode.h>
|
||||||
|
#include <fs/status.h>
|
||||||
|
#include <fs/superblock.h>
|
||||||
|
#include <mango/handle.h>
|
||||||
|
#include <mango/log.h>
|
||||||
|
#include <mango/object.h>
|
||||||
|
#include <mango/signal.h>
|
||||||
|
#include <mango/task.h>
|
||||||
|
#include <mango/vm.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define TEMP_OBJECT_SIZE 0x10000
|
||||||
|
|
||||||
BTREE_DEFINE_SIMPLE_GET(struct fs_file, unsigned long, f_node, f_id, get_file);
|
BTREE_DEFINE_SIMPLE_GET(struct fs_file, unsigned long, f_node, f_id, get_file);
|
||||||
BTREE_DEFINE_SIMPLE_INSERT(struct fs_file, f_node, f_id, put_file);
|
BTREE_DEFINE_SIMPLE_INSERT(struct fs_file, f_node, f_id, put_file);
|
||||||
@@ -12,14 +26,21 @@ struct fs_context {
|
|||||||
struct fs_superblock *ctx_sb;
|
struct fs_superblock *ctx_sb;
|
||||||
struct fs_allocator *ctx_alloc;
|
struct fs_allocator *ctx_alloc;
|
||||||
struct btree ctx_filelist;
|
struct btree ctx_filelist;
|
||||||
|
kern_handle_t ctx_vm_controller;
|
||||||
|
kern_handle_t ctx_channel;
|
||||||
|
kern_handle_t ctx_temp_object;
|
||||||
|
void *ctx_temp_object_buf;
|
||||||
|
|
||||||
struct fs_vtable ctx_vtable;
|
struct fs_vtable ctx_vtable;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fs_context *fs_context_create(
|
struct fs_context *fs_context_create(struct fs_allocator *alloc)
|
||||||
struct fs_allocator *alloc,
|
|
||||||
struct fs_superblock *sb)
|
|
||||||
{
|
{
|
||||||
|
kern_handle_t self, address_space;
|
||||||
|
task_self(&self);
|
||||||
|
task_get_address_space(self, &address_space);
|
||||||
|
kern_handle_close(self);
|
||||||
|
|
||||||
struct fs_context *ctx = fs_alloc(alloc, sizeof *ctx);
|
struct fs_context *ctx = fs_alloc(alloc, sizeof *ctx);
|
||||||
if (!ctx) {
|
if (!ctx) {
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -27,10 +48,50 @@ struct fs_context *fs_context_create(
|
|||||||
|
|
||||||
memset(ctx, 0x0, sizeof *ctx);
|
memset(ctx, 0x0, sizeof *ctx);
|
||||||
|
|
||||||
ctx->ctx_sb = sb;
|
kern_status_t status = vm_controller_create(&ctx->ctx_vm_controller);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
fs_free(alloc, ctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = vm_object_create(
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
TEMP_OBJECT_SIZE,
|
||||||
|
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_USER,
|
||||||
|
&ctx->ctx_temp_object);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
kern_handle_close(ctx->ctx_vm_controller);
|
||||||
|
fs_free(alloc, ctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
virt_addr_t temp_buffer;
|
||||||
|
status = address_space_map(
|
||||||
|
address_space,
|
||||||
|
MAP_ADDRESS_ANY,
|
||||||
|
ctx->ctx_temp_object,
|
||||||
|
0,
|
||||||
|
TEMP_OBJECT_SIZE,
|
||||||
|
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_USER,
|
||||||
|
&temp_buffer);
|
||||||
|
kern_handle_close(address_space);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
kern_handle_close(ctx->ctx_temp_object);
|
||||||
|
kern_handle_close(ctx->ctx_vm_controller);
|
||||||
|
fs_free(alloc, ctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->ctx_temp_object_buf = (void *)temp_buffer;
|
||||||
ctx->ctx_alloc = alloc;
|
ctx->ctx_alloc = alloc;
|
||||||
|
|
||||||
ctx->ctx_vtable.open = fs_msg_open;
|
ctx->ctx_vtable.open = fs_msg_open;
|
||||||
|
ctx->ctx_vtable.close = fs_msg_close;
|
||||||
|
ctx->ctx_vtable.read = fs_msg_read;
|
||||||
|
ctx->ctx_vtable.write = fs_msg_write;
|
||||||
|
ctx->ctx_vtable.seek = fs_msg_seek;
|
||||||
|
ctx->ctx_vtable.map = fs_msg_map;
|
||||||
|
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
@@ -40,6 +101,141 @@ void fs_context_destroy(struct fs_context *ctx)
|
|||||||
fs_free(ctx->ctx_alloc, ctx);
|
fs_free(ctx->ctx_alloc, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum fs_status fs_context_mount_filesystem(
|
||||||
|
struct fs_context *ctx,
|
||||||
|
fs_mount_function_t func,
|
||||||
|
void *arg,
|
||||||
|
enum fs_mount_flags flags)
|
||||||
|
{
|
||||||
|
if (!func) {
|
||||||
|
return FS_ERR_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct fs_superblock *sb = NULL;
|
||||||
|
enum fs_status status = func(ctx, arg, flags, &sb);
|
||||||
|
if (status != FS_SUCCESS) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sb) {
|
||||||
|
return FS_ERR_INTERNAL_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->ctx_sb = sb;
|
||||||
|
return FS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum fs_status fs_context_unmount_filesystem(struct fs_context *ctx)
|
||||||
|
{
|
||||||
|
return FS_ERR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fs_context_set_channel(struct fs_context *ctx, kern_handle_t channel)
|
||||||
|
{
|
||||||
|
ctx->ctx_channel = channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_handle_t fs_context_get_vm_controller(const struct fs_context *ctx)
|
||||||
|
{
|
||||||
|
return ctx->ctx_vm_controller;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum fs_status handle_msg(struct fs_context *ctx)
|
||||||
|
{
|
||||||
|
xpc_msg_t msg;
|
||||||
|
kern_status_t status = xpc_msg_recv_nowait(ctx->ctx_channel, &msg);
|
||||||
|
if (status == KERN_NO_ENTRY) {
|
||||||
|
return FS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
kern_tracef("message recv error %d", status);
|
||||||
|
return FS_ERR_INTERNAL_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (msg.msg_header.hdr_interface) {
|
||||||
|
case INTERFACE_FS:
|
||||||
|
status = fs_context_dispatch_msg(ctx, &msg);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
kern_tracef(
|
||||||
|
"unknown message protocol %u",
|
||||||
|
msg.msg_header.hdr_interface);
|
||||||
|
xpc_msg_reply_error(&msg, KERN_UNSUPPORTED);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum fs_status handle_page_request(struct fs_context *ctx)
|
||||||
|
{
|
||||||
|
equeue_packet_page_request_t packet;
|
||||||
|
vm_controller_recv(ctx->ctx_vm_controller, &packet);
|
||||||
|
struct file_mapping *mapping = (struct file_mapping *)packet.req_vmo;
|
||||||
|
kern_tracef(
|
||||||
|
"received page request [%zx-%zx] for file %s",
|
||||||
|
packet.req_offset,
|
||||||
|
packet.req_offset + packet.req_length,
|
||||||
|
mapping->m_file->f_dent->d_name);
|
||||||
|
|
||||||
|
size_t length = packet.req_length;
|
||||||
|
if (length > TEMP_OBJECT_SIZE) {
|
||||||
|
length = TEMP_OBJECT_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *dst = ctx->ctx_temp_object_buf;
|
||||||
|
xpc_buffer_t buf = XPC_LOCAL_BUFFER_OUT(dst, TEMP_OBJECT_SIZE);
|
||||||
|
enum fs_status status = fs_file_read_at(
|
||||||
|
mapping->m_file,
|
||||||
|
&buf,
|
||||||
|
packet.req_offset,
|
||||||
|
length);
|
||||||
|
if (status != FS_SUCCESS) {
|
||||||
|
kern_tracef("map-read failed with code %d", status);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
vm_controller_supply_pages(
|
||||||
|
ctx->ctx_vm_controller,
|
||||||
|
mapping->m_vmo,
|
||||||
|
packet.req_offset,
|
||||||
|
ctx->ctx_temp_object,
|
||||||
|
0,
|
||||||
|
packet.req_length);
|
||||||
|
return FS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum fs_status fs_context_handle_request(struct fs_context *ctx)
|
||||||
|
{
|
||||||
|
kern_wait_item_t waiters[] = {
|
||||||
|
{
|
||||||
|
.w_handle = ctx->ctx_channel,
|
||||||
|
.w_waitfor = CHANNEL_SIGNAL_MSG_RECEIVED,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.w_handle = ctx->ctx_vm_controller,
|
||||||
|
.w_waitfor = VM_CONTROLLER_SIGNAL_REQUEST_RECEIVED,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const size_t nr_waiters = sizeof waiters / sizeof waiters[0];
|
||||||
|
|
||||||
|
kern_status_t kstatus = kern_object_wait(waiters, nr_waiters);
|
||||||
|
if (kstatus != KERN_OK) {
|
||||||
|
return FS_ERR_INTERNAL_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (waiters[0].w_observed & CHANNEL_SIGNAL_MSG_RECEIVED) {
|
||||||
|
return handle_msg(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (waiters[1].w_observed & VM_CONTROLLER_SIGNAL_REQUEST_RECEIVED) {
|
||||||
|
return handle_page_request(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
return FS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
struct fs_file *fs_context_open_file(struct fs_context *ctx, unsigned long id)
|
struct fs_file *fs_context_open_file(struct fs_context *ctx, unsigned long id)
|
||||||
{
|
{
|
||||||
struct fs_file *f = get_file(&ctx->ctx_filelist, id);
|
struct fs_file *f = get_file(&ctx->ctx_filelist, id);
|
||||||
@@ -58,29 +254,104 @@ struct fs_file *fs_context_open_file(struct fs_context *ctx, unsigned long id)
|
|||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct fs_file *fs_context_get_file(struct fs_context *ctx, unsigned long id)
|
||||||
|
{
|
||||||
|
return get_file(&ctx->ctx_filelist, id);
|
||||||
|
}
|
||||||
|
|
||||||
void fs_context_close_file(struct fs_context *ctx, struct fs_file *f)
|
void fs_context_close_file(struct fs_context *ctx, struct fs_file *f)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
struct fs_dentry *fs_context_resolve_path(
|
static size_t get_first_path_component(const char *in, char *out, size_t max)
|
||||||
struct fs_context *ctx,
|
|
||||||
const char *path)
|
|
||||||
{
|
{
|
||||||
return NULL;
|
size_t i = 0;
|
||||||
|
while (i < max - 1) {
|
||||||
|
if (in[i] == '\0' || in[i] == '/') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
out[i] = in[i];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
out[i] = '\0';
|
||||||
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
kern_status_t fs_context_dispatch_msg(
|
extern enum fs_status fs_context_resolve_path(
|
||||||
struct fs_context *ctx,
|
struct fs_context *ctx,
|
||||||
kern_handle_t channel,
|
const char *path,
|
||||||
struct msg_endpoint *sender,
|
struct fs_dentry **out)
|
||||||
struct msg_header *hdr)
|
|
||||||
{
|
{
|
||||||
return fs_dispatch(
|
if (!ctx->ctx_sb || !ctx->ctx_sb->s_root) {
|
||||||
channel,
|
return FS_ERR_NO_ENTRY;
|
||||||
&ctx->ctx_vtable,
|
}
|
||||||
sender,
|
|
||||||
hdr,
|
struct fs_dentry *cur = ctx->ctx_sb->s_root;
|
||||||
NULL,
|
|
||||||
0,
|
char tok[256];
|
||||||
ctx);
|
|
||||||
|
while (*path != '\0') {
|
||||||
|
while (*path == '/') {
|
||||||
|
path++;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t tok_len
|
||||||
|
= get_first_path_component(path, tok, sizeof tok);
|
||||||
|
|
||||||
|
if (!tok_len) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_dir = *(path + tok_len) != '\0';
|
||||||
|
|
||||||
|
if (cur->d_inode->i_mode != FS_INODE_DIR) {
|
||||||
|
return FS_ERR_NOT_DIRECTORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct fs_dentry *next = NULL;
|
||||||
|
enum fs_status status
|
||||||
|
= fs_inode_lookup(cur->d_inode, tok, &next);
|
||||||
|
|
||||||
|
if (status != FS_SUCCESS) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!next) {
|
||||||
|
return FS_ERR_INTERNAL_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur = next;
|
||||||
|
|
||||||
|
path += tok_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out = cur;
|
||||||
|
return FS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t fs_context_dispatch_msg(struct fs_context *ctx, xpc_msg_t *msg)
|
||||||
|
{
|
||||||
|
return fs_dispatch(NULL, msg, &ctx->ctx_vtable, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *fs_context_alloc(struct fs_context *ctx, size_t count)
|
||||||
|
{
|
||||||
|
return fs_alloc(ctx->ctx_alloc, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *fs_context_calloc(struct fs_context *ctx, size_t count, size_t sz)
|
||||||
|
{
|
||||||
|
return fs_calloc(ctx->ctx_alloc, count, sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *fs_context_realloc(struct fs_context *ctx, void *p, size_t count)
|
||||||
|
{
|
||||||
|
return fs_realloc(ctx->ctx_alloc, p, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fs_context_free(struct fs_context *ctx, void *p)
|
||||||
|
{
|
||||||
|
fs_free(ctx->ctx_alloc, p);
|
||||||
}
|
}
|
||||||
|
|||||||
54
lib/libfs/file.c
Normal file
54
lib/libfs/file.c
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
#include "file.h"
|
||||||
|
|
||||||
|
struct fs_inode *fs_file_get_inode(const struct fs_file *f)
|
||||||
|
{
|
||||||
|
return f->f_inode;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t fs_file_get_cursor(const struct fs_file *f)
|
||||||
|
{
|
||||||
|
return f->f_seek;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum fs_status fs_file_read(
|
||||||
|
struct fs_file *f,
|
||||||
|
struct xpc_buffer *buf,
|
||||||
|
size_t count)
|
||||||
|
{
|
||||||
|
if (!f->f_ops || !f->f_ops->f_read) {
|
||||||
|
return FS_ERR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
off_t seek = f->f_seek;
|
||||||
|
enum fs_status status = f->f_ops->f_read(f, buf, count, &seek);
|
||||||
|
f->f_seek = seek;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum fs_status fs_file_read_at(
|
||||||
|
struct fs_file *f,
|
||||||
|
struct xpc_buffer *buf,
|
||||||
|
off_t offset,
|
||||||
|
size_t count)
|
||||||
|
{
|
||||||
|
if (!f->f_ops || !f->f_ops->f_read) {
|
||||||
|
return FS_ERR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return f->f_ops->f_read(f, buf, count, &offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum fs_status fs_file_write(
|
||||||
|
struct fs_file *f,
|
||||||
|
const struct xpc_buffer *buf,
|
||||||
|
size_t count)
|
||||||
|
{
|
||||||
|
if (!f->f_ops || !f->f_ops->f_write) {
|
||||||
|
return FS_ERR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
off_t seek = f->f_seek;
|
||||||
|
enum fs_status status = f->f_ops->f_write(f, buf, count, &seek);
|
||||||
|
f->f_seek = seek;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
@@ -2,8 +2,11 @@
|
|||||||
#define _FS_FILE_H_
|
#define _FS_FILE_H_
|
||||||
|
|
||||||
#include "btree.h"
|
#include "btree.h"
|
||||||
|
#include "queue.h"
|
||||||
|
|
||||||
|
#include <fs/dentry.h>
|
||||||
#include <fs/file.h>
|
#include <fs/file.h>
|
||||||
|
#include <fs/inode.h>
|
||||||
|
|
||||||
struct fs_file {
|
struct fs_file {
|
||||||
/* id of the open file, equal to the koid of the port being used to
|
/* id of the open file, equal to the koid of the port being used to
|
||||||
@@ -12,6 +15,12 @@ struct fs_file {
|
|||||||
struct btree_node f_node;
|
struct btree_node f_node;
|
||||||
|
|
||||||
const struct fs_file_ops *f_ops;
|
const struct fs_file_ops *f_ops;
|
||||||
|
|
||||||
|
off_t f_seek;
|
||||||
|
struct fs_inode *f_inode;
|
||||||
|
struct fs_dentry *f_dent;
|
||||||
|
|
||||||
|
struct queue f_mappings;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -2,30 +2,60 @@
|
|||||||
#define FS_CONTEXT_H_
|
#define FS_CONTEXT_H_
|
||||||
|
|
||||||
#include <rosetta/fs.h>
|
#include <rosetta/fs.h>
|
||||||
|
#include <xpc/msg.h>
|
||||||
|
|
||||||
struct fs_file;
|
struct fs_file;
|
||||||
|
struct fs_dentry;
|
||||||
struct fs_context;
|
struct fs_context;
|
||||||
struct fs_allocator;
|
struct fs_allocator;
|
||||||
struct fs_superblock;
|
struct fs_superblock;
|
||||||
|
|
||||||
extern struct fs_context *fs_context_create(
|
enum fs_mount_flags {
|
||||||
struct fs_allocator *alloc,
|
FS_MOUNT_READONLY = 0x01u,
|
||||||
struct fs_superblock *sb);
|
};
|
||||||
|
|
||||||
|
typedef enum fs_status (*fs_mount_function_t)(
|
||||||
|
struct fs_context *,
|
||||||
|
void *arg,
|
||||||
|
enum fs_mount_flags,
|
||||||
|
struct fs_superblock **);
|
||||||
|
|
||||||
|
extern struct fs_context *fs_context_create(struct fs_allocator *alloc);
|
||||||
extern void fs_context_destroy(struct fs_context *ctx);
|
extern void fs_context_destroy(struct fs_context *ctx);
|
||||||
|
|
||||||
|
extern enum fs_status fs_context_mount_filesystem(
|
||||||
|
struct fs_context *ctx,
|
||||||
|
fs_mount_function_t func,
|
||||||
|
void *arg,
|
||||||
|
enum fs_mount_flags flags);
|
||||||
|
extern enum fs_status fs_context_unmount_filesystem(struct fs_context *ctx);
|
||||||
|
|
||||||
|
extern void fs_context_set_channel(
|
||||||
|
struct fs_context *ctx,
|
||||||
|
kern_handle_t channel);
|
||||||
|
extern kern_handle_t fs_context_get_vm_controller(const struct fs_context *ctx);
|
||||||
|
extern enum fs_status fs_context_handle_request(struct fs_context *ctx);
|
||||||
|
|
||||||
extern struct fs_file *fs_context_open_file(
|
extern struct fs_file *fs_context_open_file(
|
||||||
struct fs_context *ctx,
|
struct fs_context *ctx,
|
||||||
unsigned long id);
|
unsigned long id);
|
||||||
|
extern struct fs_file *fs_context_get_file(
|
||||||
|
struct fs_context *ctx,
|
||||||
|
unsigned long id);
|
||||||
extern void fs_context_close_file(struct fs_context *ctx, struct fs_file *f);
|
extern void fs_context_close_file(struct fs_context *ctx, struct fs_file *f);
|
||||||
|
|
||||||
extern struct fs_dentry *fs_context_resolve_path(
|
extern enum fs_status fs_context_resolve_path(
|
||||||
struct fs_context *ctx,
|
struct fs_context *ctx,
|
||||||
const char *path);
|
const char *path,
|
||||||
|
struct fs_dentry **out);
|
||||||
|
|
||||||
extern kern_status_t fs_context_dispatch_msg(
|
extern kern_status_t fs_context_dispatch_msg(
|
||||||
struct fs_context *ctx,
|
struct fs_context *ctx,
|
||||||
kern_handle_t channel,
|
xpc_msg_t *msg);
|
||||||
struct msg_endpoint *sender,
|
|
||||||
struct msg_header *hdr);
|
extern void *fs_context_alloc(struct fs_context *ctx, size_t count);
|
||||||
|
extern void *fs_context_calloc(struct fs_context *ctx, size_t count, size_t sz);
|
||||||
|
extern void *fs_context_realloc(struct fs_context *ctx, void *p, size_t count);
|
||||||
|
extern void fs_context_free(struct fs_context *ctx, void *p);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ struct fs_dentry {
|
|||||||
struct fs_superblock *d_sb;
|
struct fs_superblock *d_sb;
|
||||||
const struct fs_dentry_ops *d_ops;
|
const struct fs_dentry_ops *d_ops;
|
||||||
void *d_fsdata;
|
void *d_fsdata;
|
||||||
|
char *d_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -5,11 +5,36 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
struct fs_file;
|
struct fs_file;
|
||||||
|
struct xpc_buffer;
|
||||||
|
|
||||||
struct fs_file_ops {
|
struct fs_file_ops {
|
||||||
ssize_t (*f_read)(struct fs_file *, void *, size_t);
|
enum fs_status (*f_read)(
|
||||||
ssize_t (*f_write)(struct fs_file *, const void *, size_t);
|
struct fs_file *,
|
||||||
off_t (*f_seek)(struct fs_file *, off_t, int);
|
struct xpc_buffer *,
|
||||||
|
size_t,
|
||||||
|
off_t *);
|
||||||
|
enum fs_status (*f_write)(
|
||||||
|
struct fs_file *,
|
||||||
|
const struct xpc_buffer *,
|
||||||
|
size_t,
|
||||||
|
off_t *);
|
||||||
|
enum fs_status (*f_seek)(struct fs_file *, off_t, int);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern struct fs_inode *fs_file_get_inode(const struct fs_file *f);
|
||||||
|
extern size_t fs_file_get_cursor(const struct fs_file *f);
|
||||||
|
extern enum fs_status fs_file_read(
|
||||||
|
struct fs_file *f,
|
||||||
|
struct xpc_buffer *buf,
|
||||||
|
size_t count);
|
||||||
|
extern enum fs_status fs_file_read_at(
|
||||||
|
struct fs_file *f,
|
||||||
|
struct xpc_buffer *buf,
|
||||||
|
off_t offset,
|
||||||
|
size_t count);
|
||||||
|
extern enum fs_status fs_file_write(
|
||||||
|
struct fs_file *f,
|
||||||
|
const struct xpc_buffer *buf,
|
||||||
|
size_t count);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,17 +1,40 @@
|
|||||||
#ifndef FS_INODE_H_
|
#ifndef FS_INODE_H_
|
||||||
#define FS_INODE_H_
|
#define FS_INODE_H_
|
||||||
|
|
||||||
|
#include <fs/status.h>
|
||||||
|
#include <mango/types.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
struct fs_inode;
|
struct fs_inode;
|
||||||
struct fs_dentry;
|
struct fs_dentry;
|
||||||
struct fs_superblock;
|
struct fs_superblock;
|
||||||
|
struct fs_file_ops;
|
||||||
|
struct file_mapping;
|
||||||
|
|
||||||
|
enum fs_inode_mode {
|
||||||
|
FS_INODE_REG = 0x01u,
|
||||||
|
FS_INODE_DIR = 0x02u,
|
||||||
|
};
|
||||||
|
|
||||||
struct fs_inode_ops {
|
struct fs_inode_ops {
|
||||||
int (*i_lookup)(struct fs_inode *, struct fs_dentry *);
|
enum fs_status (*i_lookup)(
|
||||||
|
struct fs_inode *,
|
||||||
|
const char *,
|
||||||
|
struct fs_dentry **);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fs_inode {
|
struct fs_inode {
|
||||||
|
enum fs_inode_mode i_mode;
|
||||||
struct fs_superblock *i_sb;
|
struct fs_superblock *i_sb;
|
||||||
const struct fs_inode_ops *i_ops;
|
const struct fs_inode_ops *i_ops;
|
||||||
|
const struct fs_file_ops *i_fops;
|
||||||
|
size_t i_size;
|
||||||
|
struct file_mapping *i_shared_mapping;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern enum fs_status fs_inode_lookup(
|
||||||
|
struct fs_inode *inode,
|
||||||
|
const char *name,
|
||||||
|
struct fs_dentry **out);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
18
lib/libfs/include/fs/status.h
Normal file
18
lib/libfs/include/fs/status.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#ifndef FS_STATUS_H_
|
||||||
|
#define FS_STATUS_H_
|
||||||
|
|
||||||
|
enum fs_status {
|
||||||
|
FS_SUCCESS = 0,
|
||||||
|
FS_ERR_NO_ENTRY,
|
||||||
|
FS_ERR_NO_MEMORY,
|
||||||
|
FS_ERR_INVALID_ARGUMENT,
|
||||||
|
FS_ERR_NOT_IMPLEMENTED,
|
||||||
|
FS_ERR_IS_DIRECTORY,
|
||||||
|
FS_ERR_NOT_DIRECTORY,
|
||||||
|
FS_ERR_BAD_STATE,
|
||||||
|
FS_ERR_INTERNAL_FAILURE,
|
||||||
|
};
|
||||||
|
|
||||||
|
extern int fs_status_to_errno(enum fs_status status);
|
||||||
|
|
||||||
|
#endif
|
||||||
13
lib/libfs/inode.c
Normal file
13
lib/libfs/inode.c
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#include <fs/inode.h>
|
||||||
|
|
||||||
|
enum fs_status fs_inode_lookup(
|
||||||
|
struct fs_inode *inode,
|
||||||
|
const char *name,
|
||||||
|
struct fs_dentry **out)
|
||||||
|
{
|
||||||
|
if (!inode->i_ops || !inode->i_ops->i_lookup) {
|
||||||
|
return FS_ERR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return inode->i_ops->i_lookup(inode, name, out);
|
||||||
|
}
|
||||||
@@ -2,20 +2,57 @@
|
|||||||
#define _FS_INTERFACE_H_
|
#define _FS_INTERFACE_H_
|
||||||
|
|
||||||
#include <mango/types.h>
|
#include <mango/types.h>
|
||||||
|
#include <xpc/buffer.h>
|
||||||
|
#include <xpc/context.h>
|
||||||
|
#include <xpc/endpoint.h>
|
||||||
|
#include <xpc/string.h>
|
||||||
|
|
||||||
struct msg_endpoint;
|
struct msg_endpoint;
|
||||||
|
|
||||||
extern kern_status_t fs_msg_open(
|
extern kern_status_t fs_msg_open(
|
||||||
const struct msg_endpoint *sender,
|
xpc_context_t *ctx,
|
||||||
const char *path,
|
const xpc_endpoint_t *sender,
|
||||||
|
const xpc_string_t *path,
|
||||||
int flags,
|
int flags,
|
||||||
int *out_err,
|
int *out_err,
|
||||||
void *arg);
|
void *arg);
|
||||||
extern kern_status_t fs_msg_close(
|
extern kern_status_t fs_msg_close(
|
||||||
const struct msg_endpoint *sender,
|
xpc_context_t *ctx,
|
||||||
const char *path,
|
const xpc_endpoint_t *sender,
|
||||||
int flags,
|
|
||||||
int *out_err,
|
int *out_err,
|
||||||
void *arg);
|
void *arg);
|
||||||
|
|
||||||
|
extern kern_status_t fs_msg_read(
|
||||||
|
xpc_context_t *ctx,
|
||||||
|
const xpc_endpoint_t *sender,
|
||||||
|
size_t count,
|
||||||
|
int *out_err,
|
||||||
|
size_t *out_nr_read,
|
||||||
|
xpc_buffer_t *out_data,
|
||||||
|
void *arg);
|
||||||
|
extern kern_status_t fs_msg_write(
|
||||||
|
xpc_context_t *ctx,
|
||||||
|
const xpc_endpoint_t *sender,
|
||||||
|
const xpc_buffer_t *data,
|
||||||
|
int *out_err,
|
||||||
|
size_t *out_nr_written,
|
||||||
|
void *arg);
|
||||||
|
|
||||||
|
extern kern_status_t fs_msg_seek(
|
||||||
|
xpc_context_t *ctx,
|
||||||
|
const xpc_endpoint_t *sender,
|
||||||
|
off_t offset,
|
||||||
|
int origin,
|
||||||
|
int *out_err,
|
||||||
|
off_t *out_new_pos,
|
||||||
|
void *arg);
|
||||||
|
extern kern_status_t fs_msg_map(
|
||||||
|
xpc_context_t *ctx,
|
||||||
|
const xpc_endpoint_t *sender,
|
||||||
|
int prot,
|
||||||
|
int flags,
|
||||||
|
int *out_err,
|
||||||
|
kern_handle_t *out_vmo,
|
||||||
|
void *arg);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
14
lib/libfs/interface/close.c
Normal file
14
lib/libfs/interface/close.c
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#include "../interface.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <mango/status.h>
|
||||||
|
|
||||||
|
extern kern_status_t fs_msg_close(
|
||||||
|
xpc_context_t *ctx,
|
||||||
|
const xpc_endpoint_t *sender,
|
||||||
|
int *out_err,
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
*out_err = ENOSYS;
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
112
lib/libfs/interface/map.c
Normal file
112
lib/libfs/interface/map.c
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
#include "../file.h"
|
||||||
|
#include "../mapping.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fs/context.h>
|
||||||
|
#include <fs/file.h>
|
||||||
|
#include <fs/status.h>
|
||||||
|
#include <mango/handle.h>
|
||||||
|
#include <mango/log.h>
|
||||||
|
#include <mango/vm.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
static int create_file_mapping(
|
||||||
|
struct fs_context *ctx,
|
||||||
|
int prot,
|
||||||
|
int flags,
|
||||||
|
struct fs_file *f,
|
||||||
|
struct file_mapping **out)
|
||||||
|
{
|
||||||
|
if ((flags & MAP_SHARED) && f->f_inode->i_shared_mapping) {
|
||||||
|
*out = f->f_inode->i_shared_mapping;
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct file_mapping *mapping = fs_context_alloc(ctx, sizeof *mapping);
|
||||||
|
if (!mapping) {
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(mapping, 0x0, sizeof *mapping);
|
||||||
|
|
||||||
|
vm_prot_t vm_prot = VM_PROT_USER;
|
||||||
|
if (prot & PROT_READ) {
|
||||||
|
vm_prot |= VM_PROT_READ;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prot & PROT_WRITE) {
|
||||||
|
vm_prot |= VM_PROT_WRITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prot & PROT_EXEC) {
|
||||||
|
vm_prot |= VM_PROT_EXEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_handle_t vmo = KERN_HANDLE_INVALID;
|
||||||
|
kern_status_t status = vm_controller_create_object(
|
||||||
|
fs_context_get_vm_controller(ctx),
|
||||||
|
f->f_dent->d_name,
|
||||||
|
strlen(f->f_dent->d_name),
|
||||||
|
(equeue_key_t)mapping,
|
||||||
|
f->f_inode->i_size,
|
||||||
|
vm_prot,
|
||||||
|
&vmo);
|
||||||
|
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
fs_context_free(ctx, mapping);
|
||||||
|
return __errno_from_kern_status(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
mapping->m_file = f;
|
||||||
|
mapping->m_vmo = vmo;
|
||||||
|
|
||||||
|
if (flags & MAP_SHARED) {
|
||||||
|
mapping->m_type = FILE_MAPPING_SHARED;
|
||||||
|
f->f_inode->i_shared_mapping = mapping;
|
||||||
|
} else {
|
||||||
|
mapping->m_type = FILE_MAPPING_PRIVATE;
|
||||||
|
queue_push_back(&f->f_mappings, &mapping->m_entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
*out = mapping;
|
||||||
|
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern kern_status_t fs_msg_map(
|
||||||
|
xpc_context_t *xpc,
|
||||||
|
const xpc_endpoint_t *sender,
|
||||||
|
int prot,
|
||||||
|
int flags,
|
||||||
|
int *out_err,
|
||||||
|
kern_handle_t *out_vmo,
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
struct fs_context *ctx = arg;
|
||||||
|
struct fs_file *f = fs_context_get_file(ctx, sender->e_port);
|
||||||
|
if (!f) {
|
||||||
|
*out_err = EBADF;
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct file_mapping *mapping = NULL;
|
||||||
|
int err = create_file_mapping(ctx, prot, flags, f, &mapping);
|
||||||
|
if (err != SUCCESS) {
|
||||||
|
*out_err = err;
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_tracef(
|
||||||
|
"mapping file %s (%s) using vmo %zx",
|
||||||
|
f->f_dent->d_name,
|
||||||
|
(flags & MAP_SHARED) ? "shared" : "private",
|
||||||
|
mapping->m_vmo);
|
||||||
|
|
||||||
|
kern_handle_t vmo;
|
||||||
|
kern_handle_duplicate(mapping->m_vmo, &vmo);
|
||||||
|
|
||||||
|
*out_err = SUCCESS;
|
||||||
|
*out_vmo = vmo;
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
@@ -1,21 +1,55 @@
|
|||||||
|
#include "../file.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fs/context.h>
|
#include <fs/context.h>
|
||||||
|
#include <fs/file.h>
|
||||||
|
#include <fs/status.h>
|
||||||
|
#include <mango/log.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
extern kern_status_t fs_msg_open(
|
extern kern_status_t fs_msg_open(
|
||||||
const struct msg_endpoint *sender,
|
xpc_context_t *xpc,
|
||||||
const char *path,
|
xpc_endpoint_t *sender,
|
||||||
|
const xpc_string_t *path,
|
||||||
int flags,
|
int flags,
|
||||||
int *out_err,
|
int *out_err,
|
||||||
void *arg)
|
void *arg)
|
||||||
{
|
{
|
||||||
|
char path_buf[4096];
|
||||||
|
size_t path_len = 0;
|
||||||
|
kern_status_t status
|
||||||
|
= xpc_string_read(path, path_buf, sizeof path_buf, &path_len);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
struct fs_context *ctx = arg;
|
struct fs_context *ctx = arg;
|
||||||
|
|
||||||
struct fs_dentry *dent = fs_context_resolve_path(ctx, path);
|
struct fs_file *f = fs_context_open_file(ctx, sender->e_port);
|
||||||
if (!dent) {
|
if (!f) {
|
||||||
*out_err = ENOENT;
|
*out_err = ENOMEM;
|
||||||
return KERN_OK;
|
return KERN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (f->f_inode) {
|
||||||
|
*out_err = EBUSY;
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct fs_dentry *dent = NULL;
|
||||||
|
enum fs_status fs_status
|
||||||
|
= fs_context_resolve_path(ctx, path_buf, &dent);
|
||||||
|
if (fs_status != FS_SUCCESS) {
|
||||||
|
fs_context_close_file(ctx, f);
|
||||||
|
*out_err = fs_status_to_errno(fs_status);
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
f->f_seek = 0;
|
||||||
|
f->f_dent = dent;
|
||||||
|
f->f_inode = dent->d_inode;
|
||||||
|
f->f_ops = dent->d_inode->i_fops;
|
||||||
|
|
||||||
*out_err = SUCCESS;
|
*out_err = SUCCESS;
|
||||||
return KERN_OK;
|
return KERN_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
30
lib/libfs/interface/read.c
Normal file
30
lib/libfs/interface/read.c
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#include <errno.h>
|
||||||
|
#include <fs/context.h>
|
||||||
|
#include <fs/file.h>
|
||||||
|
#include <fs/status.h>
|
||||||
|
|
||||||
|
extern kern_status_t fs_msg_read(
|
||||||
|
xpc_context_t *xpc,
|
||||||
|
xpc_endpoint_t *sender,
|
||||||
|
size_t count,
|
||||||
|
int *out_err,
|
||||||
|
size_t *out_nr_read,
|
||||||
|
xpc_buffer_t *out_data,
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
struct fs_context *ctx = arg;
|
||||||
|
struct fs_file *f = fs_context_get_file(ctx, sender->e_port);
|
||||||
|
if (!f) {
|
||||||
|
*out_err = EBADF;
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t start = fs_file_get_cursor(f);
|
||||||
|
enum fs_status status = fs_file_read(f, out_data, count);
|
||||||
|
size_t end = fs_file_get_cursor(f);
|
||||||
|
|
||||||
|
*out_err = fs_status_to_errno(status);
|
||||||
|
*out_nr_read = end - start;
|
||||||
|
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
52
lib/libfs/interface/seek.c
Normal file
52
lib/libfs/interface/seek.c
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#include "../file.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fs/context.h>
|
||||||
|
#include <fs/file.h>
|
||||||
|
#include <fs/status.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
extern kern_status_t fs_msg_seek(
|
||||||
|
xpc_context_t *xpc,
|
||||||
|
const xpc_endpoint_t *sender,
|
||||||
|
off_t rel_offset,
|
||||||
|
int origin,
|
||||||
|
int *out_err,
|
||||||
|
off_t *out_new_pos,
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
struct fs_context *ctx = arg;
|
||||||
|
struct fs_file *f = fs_context_get_file(ctx, sender->e_port);
|
||||||
|
if (!f) {
|
||||||
|
*out_err = EBADF;
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
off_t new_offset = 0;
|
||||||
|
|
||||||
|
switch (origin) {
|
||||||
|
case SEEK_SET:
|
||||||
|
new_offset = rel_offset;
|
||||||
|
break;
|
||||||
|
case SEEK_CUR:
|
||||||
|
new_offset = f->f_seek + rel_offset;
|
||||||
|
break;
|
||||||
|
case SEEK_END:
|
||||||
|
new_offset = f->f_inode->i_size + rel_offset;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
*out_err = EINVAL;
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_offset > f->f_inode->i_size) {
|
||||||
|
*out_err = EINVAL;
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
f->f_seek = new_offset;
|
||||||
|
*out_err = SUCCESS;
|
||||||
|
*out_new_pos = new_offset;
|
||||||
|
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
29
lib/libfs/interface/write.c
Normal file
29
lib/libfs/interface/write.c
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#include <errno.h>
|
||||||
|
#include <fs/context.h>
|
||||||
|
#include <fs/file.h>
|
||||||
|
#include <fs/status.h>
|
||||||
|
|
||||||
|
extern kern_status_t fs_msg_write(
|
||||||
|
xpc_context_t *xpc,
|
||||||
|
const xpc_endpoint_t *sender,
|
||||||
|
const xpc_buffer_t *data,
|
||||||
|
int *out_err,
|
||||||
|
size_t *out_nr_written,
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
struct fs_context *ctx = arg;
|
||||||
|
struct fs_file *f = fs_context_get_file(ctx, sender->e_port);
|
||||||
|
if (!f) {
|
||||||
|
*out_err = EBADF;
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t start = fs_file_get_cursor(f);
|
||||||
|
enum fs_status status = fs_file_write(f, data, data->buf_len);
|
||||||
|
size_t end = fs_file_get_cursor(f);
|
||||||
|
|
||||||
|
*out_err = fs_status_to_errno(status);
|
||||||
|
*out_nr_written = end - start;
|
||||||
|
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
22
lib/libfs/mapping.h
Normal file
22
lib/libfs/mapping.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#ifndef MAPPING_H_
|
||||||
|
#define MAPPING_H_
|
||||||
|
|
||||||
|
#include "queue.h"
|
||||||
|
|
||||||
|
#include <mango/types.h>
|
||||||
|
|
||||||
|
struct fs_file;
|
||||||
|
|
||||||
|
enum file_mapping_type {
|
||||||
|
FILE_MAPPING_PRIVATE,
|
||||||
|
FILE_MAPPING_SHARED,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct file_mapping {
|
||||||
|
enum file_mapping_type m_type;
|
||||||
|
struct fs_file *m_file;
|
||||||
|
kern_handle_t m_vmo;
|
||||||
|
struct queue_entry m_entry;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
138
lib/libfs/queue.c
Normal file
138
lib/libfs/queue.c
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
#include "queue.h"
|
||||||
|
|
||||||
|
size_t queue_length(struct queue *q)
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
struct queue_entry *x = q->q_first;
|
||||||
|
while (x) {
|
||||||
|
i++;
|
||||||
|
x = x->qe_next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
void queue_insert_before(
|
||||||
|
struct queue *q,
|
||||||
|
struct queue_entry *entry,
|
||||||
|
struct queue_entry *before)
|
||||||
|
{
|
||||||
|
struct queue_entry *x = before->qe_prev;
|
||||||
|
if (x) {
|
||||||
|
x->qe_next = entry;
|
||||||
|
} else {
|
||||||
|
q->q_first = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry->qe_prev = x;
|
||||||
|
|
||||||
|
before->qe_prev = entry;
|
||||||
|
entry->qe_next = before;
|
||||||
|
}
|
||||||
|
|
||||||
|
void queue_insert_after(
|
||||||
|
struct queue *q,
|
||||||
|
struct queue_entry *entry,
|
||||||
|
struct queue_entry *after)
|
||||||
|
{
|
||||||
|
struct queue_entry *x = after->qe_next;
|
||||||
|
if (x) {
|
||||||
|
x->qe_prev = entry;
|
||||||
|
} else {
|
||||||
|
q->q_last = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry->qe_prev = x;
|
||||||
|
|
||||||
|
after->qe_next = entry;
|
||||||
|
entry->qe_prev = after;
|
||||||
|
}
|
||||||
|
|
||||||
|
void queue_push_front(struct queue *q, struct queue_entry *entry)
|
||||||
|
{
|
||||||
|
if (q->q_first) {
|
||||||
|
q->q_first->qe_prev = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry->qe_next = q->q_first;
|
||||||
|
entry->qe_prev = NULL;
|
||||||
|
|
||||||
|
q->q_first = entry;
|
||||||
|
|
||||||
|
if (!q->q_last) {
|
||||||
|
q->q_last = entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void queue_push_back(struct queue *q, struct queue_entry *entry)
|
||||||
|
{
|
||||||
|
if (q->q_last) {
|
||||||
|
q->q_last->qe_next = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry->qe_prev = q->q_last;
|
||||||
|
entry->qe_next = NULL;
|
||||||
|
|
||||||
|
q->q_last = entry;
|
||||||
|
|
||||||
|
if (!q->q_first) {
|
||||||
|
q->q_first = entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct queue_entry *queue_pop_front(struct queue *q)
|
||||||
|
{
|
||||||
|
struct queue_entry *x = q->q_first;
|
||||||
|
if (x) {
|
||||||
|
queue_delete(q, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct queue_entry *queue_pop_back(struct queue *q)
|
||||||
|
{
|
||||||
|
struct queue_entry *x = q->q_last;
|
||||||
|
if (x) {
|
||||||
|
queue_delete(q, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
void queue_delete(struct queue *q, struct queue_entry *entry)
|
||||||
|
{
|
||||||
|
if (!entry) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry == q->q_first) {
|
||||||
|
q->q_first = q->q_first->qe_next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry == q->q_last) {
|
||||||
|
q->q_last = q->q_last->qe_prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry->qe_next) {
|
||||||
|
entry->qe_next->qe_prev = entry->qe_prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry->qe_prev) {
|
||||||
|
entry->qe_prev->qe_next = entry->qe_next;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry->qe_next = entry->qe_prev = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void queue_delete_all(struct queue *q)
|
||||||
|
{
|
||||||
|
struct queue_entry *x = q->q_first;
|
||||||
|
while (x) {
|
||||||
|
struct queue_entry *next = x->qe_next;
|
||||||
|
x->qe_next = x->qe_prev = NULL;
|
||||||
|
x = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
q->q_first = q->q_last = NULL;
|
||||||
|
}
|
||||||
100
lib/libfs/queue.h
Normal file
100
lib/libfs/queue.h
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
#ifndef QUEUE_H_
|
||||||
|
#define QUEUE_H_
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define QUEUE_CONTAINER(t, m, v) \
|
||||||
|
((void *)((v) ? (uintptr_t)(v) - (offsetof(t, m)) : 0))
|
||||||
|
|
||||||
|
#define QUEUE_INIT ((struct queue) {.q_first = NULL, .q_last = NULL})
|
||||||
|
#define QUEUE_ENTRY_INIT \
|
||||||
|
((struct queue_entry) {.qe_next = NULL, .qe_prev = NULL})
|
||||||
|
|
||||||
|
#define queue_foreach(iter_type, iter_name, queue_name, node_member) \
|
||||||
|
for (iter_type *iter_name = (iter_type *)QUEUE_CONTAINER( \
|
||||||
|
iter_type, \
|
||||||
|
node_member, \
|
||||||
|
queue_first(queue_name)); \
|
||||||
|
iter_name; \
|
||||||
|
iter_name = (iter_type *)QUEUE_CONTAINER( \
|
||||||
|
iter_type, \
|
||||||
|
node_member, \
|
||||||
|
queue_next(&((iter_name)->node_member))))
|
||||||
|
|
||||||
|
#define queue_foreach_r(iter_type, iter_name, queue_name, node_member) \
|
||||||
|
for (iter_type *iter_name = (iter_type *)QUEUE_CONTAINER( \
|
||||||
|
iter_type, \
|
||||||
|
node_member, \
|
||||||
|
queue_last(queue_name)); \
|
||||||
|
iter_name; \
|
||||||
|
iter_name = (iter_type *)QUEUE_CONTAINER( \
|
||||||
|
iter_type, \
|
||||||
|
node_member, \
|
||||||
|
queue_prev(&((iter_name)->node_member))))
|
||||||
|
|
||||||
|
struct queue_entry {
|
||||||
|
struct queue_entry *qe_next;
|
||||||
|
struct queue_entry *qe_prev;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct queue {
|
||||||
|
struct queue_entry *q_first;
|
||||||
|
struct queue_entry *q_last;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void queue_init(struct queue *q)
|
||||||
|
{
|
||||||
|
memset(q, 0x00, sizeof *q);
|
||||||
|
}
|
||||||
|
static inline bool queue_empty(struct queue *q)
|
||||||
|
{
|
||||||
|
return q->q_first == NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct queue_entry *queue_first(struct queue *q)
|
||||||
|
{
|
||||||
|
return q->q_first;
|
||||||
|
}
|
||||||
|
static inline struct queue_entry *queue_last(struct queue *q)
|
||||||
|
{
|
||||||
|
return q->q_last;
|
||||||
|
}
|
||||||
|
static inline struct queue_entry *queue_next(struct queue_entry *entry)
|
||||||
|
{
|
||||||
|
return entry->qe_next;
|
||||||
|
}
|
||||||
|
static inline struct queue_entry *queue_prev(struct queue_entry *entry)
|
||||||
|
{
|
||||||
|
return entry->qe_prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern size_t queue_length(struct queue *q);
|
||||||
|
|
||||||
|
extern void queue_insert_before(
|
||||||
|
struct queue *q,
|
||||||
|
struct queue_entry *entry,
|
||||||
|
struct queue_entry *before);
|
||||||
|
extern void queue_insert_after(
|
||||||
|
struct queue *q,
|
||||||
|
struct queue_entry *entry,
|
||||||
|
struct queue_entry *after);
|
||||||
|
|
||||||
|
extern void queue_push_front(struct queue *q, struct queue_entry *entry);
|
||||||
|
extern void queue_push_back(struct queue *q, struct queue_entry *entry);
|
||||||
|
|
||||||
|
extern struct queue_entry *queue_pop_front(struct queue *q);
|
||||||
|
extern struct queue_entry *queue_pop_back(struct queue *q);
|
||||||
|
|
||||||
|
extern void queue_delete(struct queue *q, struct queue_entry *entry);
|
||||||
|
extern void queue_delete_all(struct queue *q);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
25
lib/libfs/status.c
Normal file
25
lib/libfs/status.c
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#include <errno.h>
|
||||||
|
#include <fs/status.h>
|
||||||
|
|
||||||
|
int fs_status_to_errno(enum fs_status status)
|
||||||
|
{
|
||||||
|
switch (status) {
|
||||||
|
case FS_SUCCESS:
|
||||||
|
return SUCCESS;
|
||||||
|
case FS_ERR_NO_ENTRY:
|
||||||
|
return ENOENT;
|
||||||
|
case FS_ERR_NO_MEMORY:
|
||||||
|
return ENOMEM;
|
||||||
|
case FS_ERR_INVALID_ARGUMENT:
|
||||||
|
return EINVAL;
|
||||||
|
case FS_ERR_NOT_IMPLEMENTED:
|
||||||
|
return ENOSYS;
|
||||||
|
case FS_ERR_IS_DIRECTORY:
|
||||||
|
return EISDIR;
|
||||||
|
case FS_ERR_NOT_DIRECTORY:
|
||||||
|
return ENOTDIR;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,4 +18,4 @@ sysroot_add_library(
|
|||||||
HEADER_DIR /usr/include
|
HEADER_DIR /usr/include
|
||||||
LIB_DIR /usr/lib)
|
LIB_DIR /usr/lib)
|
||||||
|
|
||||||
target_link_libraries(liblaunch librosetta libmango libc-core)
|
target_link_libraries(liblaunch PRIVATE librosetta libmango libc-core)
|
||||||
|
|||||||
@@ -160,15 +160,10 @@ static kern_status_t create_exec_regions(struct elf_image *image)
|
|||||||
image->e_total_size);
|
image->e_total_size);
|
||||||
kern_status_t status = KERN_OK;
|
kern_status_t status = KERN_OK;
|
||||||
if (image->e_local_space != KERN_HANDLE_INVALID) {
|
if (image->e_local_space != KERN_HANDLE_INVALID) {
|
||||||
status = vm_region_create(
|
status = address_space_reserve(
|
||||||
image->e_local_space,
|
image->e_local_space,
|
||||||
NULL,
|
MAP_ADDRESS_ANY,
|
||||||
0,
|
|
||||||
VM_REGION_ANY_OFFSET,
|
|
||||||
image->e_total_size,
|
image->e_total_size,
|
||||||
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXEC
|
|
||||||
| VM_PROT_USER,
|
|
||||||
&image->e_local_exec,
|
|
||||||
&image->e_local_base);
|
&image->e_local_base);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,22 +172,18 @@ static kern_status_t create_exec_regions(struct elf_image *image)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (image->e_remote_space != KERN_HANDLE_INVALID) {
|
if (image->e_remote_space != KERN_HANDLE_INVALID) {
|
||||||
status = vm_region_create(
|
status = address_space_reserve(
|
||||||
image->e_remote_space,
|
image->e_remote_space,
|
||||||
NULL,
|
MAP_ADDRESS_ANY,
|
||||||
0,
|
|
||||||
VM_REGION_ANY_OFFSET,
|
|
||||||
image->e_total_size,
|
image->e_total_size,
|
||||||
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXEC
|
|
||||||
| VM_PROT_USER,
|
|
||||||
&image->e_remote_exec,
|
|
||||||
&image->e_remote_base);
|
&image->e_remote_base);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status != KERN_OK) {
|
if (status != KERN_OK) {
|
||||||
vm_region_kill(image->e_local_exec);
|
address_space_release(
|
||||||
kern_handle_close(image->e_local_exec);
|
image->e_local_space,
|
||||||
image->e_local_exec = KERN_HANDLE_INVALID;
|
image->e_local_base,
|
||||||
|
image->e_total_size);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@@ -200,6 +191,19 @@ static kern_status_t create_exec_regions(struct elf_image *image)
|
|||||||
return KERN_OK;
|
return KERN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static kern_status_t release_exec_regions(struct elf_image *image)
|
||||||
|
{
|
||||||
|
address_space_release(
|
||||||
|
image->e_local_space,
|
||||||
|
image->e_local_base,
|
||||||
|
image->e_total_size);
|
||||||
|
address_space_release(
|
||||||
|
image->e_remote_space,
|
||||||
|
image->e_remote_base,
|
||||||
|
image->e_total_size);
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static enum launch_status map_executable(struct elf_image *image)
|
static enum launch_status map_executable(struct elf_image *image)
|
||||||
{
|
{
|
||||||
elf_phdr_t phdr;
|
elf_phdr_t phdr;
|
||||||
@@ -256,10 +260,10 @@ static enum launch_status map_executable(struct elf_image *image)
|
|||||||
return LAUNCH_ERR_IMAGE_DATA_LOAD_FAILED;
|
return LAUNCH_ERR_IMAGE_DATA_LOAD_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (image->e_local_exec != KERN_HANDLE_INVALID) {
|
if (image->e_local_space != KERN_HANDLE_INVALID) {
|
||||||
status = vm_region_map_relative(
|
status = address_space_map(
|
||||||
image->e_local_exec,
|
image->e_local_space,
|
||||||
phdr.p_vaddr,
|
image->e_local_base + phdr.p_vaddr,
|
||||||
vmo,
|
vmo,
|
||||||
offset,
|
offset,
|
||||||
phdr.p_memsz,
|
phdr.p_memsz,
|
||||||
@@ -271,10 +275,10 @@ static enum launch_status map_executable(struct elf_image *image)
|
|||||||
return LAUNCH_ERR_MEMORY_MAP_FAILED;
|
return LAUNCH_ERR_MEMORY_MAP_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (image->e_remote_exec != KERN_HANDLE_INVALID) {
|
if (image->e_remote_space != KERN_HANDLE_INVALID) {
|
||||||
status = vm_region_map_relative(
|
status = address_space_map(
|
||||||
image->e_remote_exec,
|
image->e_remote_space,
|
||||||
phdr.p_vaddr,
|
image->e_remote_base + phdr.p_vaddr,
|
||||||
vmo,
|
vmo,
|
||||||
offset,
|
offset,
|
||||||
phdr.p_memsz,
|
phdr.p_memsz,
|
||||||
@@ -330,6 +334,28 @@ static enum launch_status do_rela(struct elf_image *image, elf_rela_t *rela)
|
|||||||
ELF64_R_SYM(rela->r_info),
|
ELF64_R_SYM(rela->r_info),
|
||||||
rela->r_addend);
|
rela->r_addend);
|
||||||
break;
|
break;
|
||||||
|
case R_X86_64_GLOB_DAT:
|
||||||
|
sym = get_dynsym(image, ELF64_R_SYM(rela->r_info));
|
||||||
|
if (!sym) {
|
||||||
|
return LAUNCH_ERR_MISSING_SYMBOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(uint64_t *)(image->e_local_base + rela->r_offset)
|
||||||
|
= image->e_remote_base + sym->st_value + rela->r_addend;
|
||||||
|
kern_tracef(
|
||||||
|
"GLOB_DAT: offset=%zx, symbol=%zu, addend=%zx",
|
||||||
|
rela->r_offset,
|
||||||
|
ELF64_R_SYM(rela->r_info),
|
||||||
|
rela->r_addend);
|
||||||
|
break;
|
||||||
|
case R_X86_64_RELATIVE:
|
||||||
|
*(uint64_t *)(image->e_local_base + rela->r_offset)
|
||||||
|
= image->e_remote_base + rela->r_addend;
|
||||||
|
kern_tracef(
|
||||||
|
"RELATIVE: offset=%zx, addend=%zx",
|
||||||
|
rela->r_offset,
|
||||||
|
rela->r_addend);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
kern_trace("Unknown relocation type");
|
kern_trace("Unknown relocation type");
|
||||||
return LAUNCH_ERR_UNSUPPORTED_EXECUTABLE;
|
return LAUNCH_ERR_UNSUPPORTED_EXECUTABLE;
|
||||||
@@ -499,8 +525,6 @@ void elf_image_init(struct elf_image *out)
|
|||||||
out->e_data = KERN_HANDLE_INVALID;
|
out->e_data = KERN_HANDLE_INVALID;
|
||||||
out->e_local_space = KERN_HANDLE_INVALID;
|
out->e_local_space = KERN_HANDLE_INVALID;
|
||||||
out->e_remote_space = KERN_HANDLE_INVALID;
|
out->e_remote_space = KERN_HANDLE_INVALID;
|
||||||
out->e_local_exec = KERN_HANDLE_INVALID;
|
|
||||||
out->e_remote_exec = KERN_HANDLE_INVALID;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum launch_status elf_image_load(
|
enum launch_status elf_image_load(
|
||||||
@@ -547,6 +571,11 @@ enum launch_status elf_image_load(
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status = release_exec_regions(image);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
status = relocate(image);
|
status = relocate(image);
|
||||||
if (status != LAUNCH_OK) {
|
if (status != LAUNCH_OK) {
|
||||||
return status;
|
return status;
|
||||||
@@ -557,9 +586,9 @@ enum launch_status elf_image_load(
|
|||||||
|
|
||||||
void elf_image_cleanup(struct elf_image *image)
|
void elf_image_cleanup(struct elf_image *image)
|
||||||
{
|
{
|
||||||
vm_region_unmap_relative(image->e_local_exec, 0, image->e_total_size);
|
address_space_unmap(
|
||||||
|
image->e_local_space,
|
||||||
|
image->e_local_base,
|
||||||
|
image->e_total_size);
|
||||||
kern_handle_close(image->e_data);
|
kern_handle_close(image->e_data);
|
||||||
vm_region_kill(image->e_local_exec);
|
|
||||||
kern_handle_close(image->e_local_exec);
|
|
||||||
kern_handle_close(image->e_remote_exec);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -292,7 +292,6 @@ struct elf_image {
|
|||||||
size_t e_page_size;
|
size_t e_page_size;
|
||||||
kern_handle_t e_image, e_data;
|
kern_handle_t e_image, e_data;
|
||||||
kern_handle_t e_local_space, e_remote_space;
|
kern_handle_t e_local_space, e_remote_space;
|
||||||
kern_handle_t e_local_exec, e_remote_exec;
|
|
||||||
virt_addr_t e_local_base, e_remote_base;
|
virt_addr_t e_local_base, e_remote_base;
|
||||||
elf_ehdr_t e_hdr;
|
elf_ehdr_t e_hdr;
|
||||||
elf_phdr_t e_dynamic;
|
elf_phdr_t e_dynamic;
|
||||||
|
|||||||
@@ -45,7 +45,9 @@ struct launch_ctx {
|
|||||||
struct launch_parameters {
|
struct launch_parameters {
|
||||||
kern_handle_t p_parent_task;
|
kern_handle_t p_parent_task;
|
||||||
kern_handle_t p_local_address_space;
|
kern_handle_t p_local_address_space;
|
||||||
kern_handle_t p_executable;
|
|
||||||
|
const char *p_exec_path;
|
||||||
|
kern_handle_t p_exec_image;
|
||||||
|
|
||||||
const char *p_task_name;
|
const char *p_task_name;
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ static kern_handle_t get_library(
|
|||||||
|
|
||||||
static virt_addr_t write_bootstrap_data(
|
static virt_addr_t write_bootstrap_data(
|
||||||
struct stack_writer *stack,
|
struct stack_writer *stack,
|
||||||
|
const char *interpreter,
|
||||||
const struct launch_parameters *params)
|
const struct launch_parameters *params)
|
||||||
{
|
{
|
||||||
virt_addr_t bs_remote;
|
virt_addr_t bs_remote;
|
||||||
@@ -51,9 +52,15 @@ static virt_addr_t write_bootstrap_data(
|
|||||||
bs->bs_handles_count = params->p_handle_count;
|
bs->bs_handles_count = params->p_handle_count;
|
||||||
bs->bs_channels_count = params->p_channel_count;
|
bs->bs_channels_count = params->p_channel_count;
|
||||||
|
|
||||||
|
if (interpreter) {
|
||||||
|
/* two extra args: interpreter path and path to executable */
|
||||||
|
bs->bs_argc += 2;
|
||||||
|
}
|
||||||
|
|
||||||
const char **argv, **envp;
|
const char **argv, **envp;
|
||||||
|
|
||||||
if (bs->bs_argc > 0) {
|
if (bs->bs_argc > 0) {
|
||||||
|
int argc = bs->bs_argc;
|
||||||
virt_addr_t remote_argv;
|
virt_addr_t remote_argv;
|
||||||
argv = stack_writer_put(
|
argv = stack_writer_put(
|
||||||
stack,
|
stack,
|
||||||
@@ -63,27 +70,36 @@ static virt_addr_t write_bootstrap_data(
|
|||||||
bs->bs_argv = (const char **)remote_argv;
|
bs->bs_argv = (const char **)remote_argv;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bs->bs_envc > 0) {
|
/* envc+1 so there is space for a null terminator */
|
||||||
virt_addr_t remote_envp;
|
virt_addr_t remote_envp;
|
||||||
envp = stack_writer_put(
|
envp = stack_writer_put(
|
||||||
stack,
|
stack,
|
||||||
NULL,
|
NULL,
|
||||||
bs->bs_envc * sizeof(char *),
|
(bs->bs_envc + 1) * sizeof(char *),
|
||||||
&remote_envp);
|
&remote_envp);
|
||||||
bs->bs_envp = (const char **)remote_envp;
|
bs->bs_envp = (const char **)remote_envp;
|
||||||
|
|
||||||
|
size_t i = 0, j = 0;
|
||||||
|
if (interpreter) {
|
||||||
|
virt_addr_t arg_ptr;
|
||||||
|
stack_writer_put_string(stack, interpreter, &arg_ptr);
|
||||||
|
argv[i++] = (const char *)arg_ptr;
|
||||||
|
stack_writer_put_string(stack, params->p_exec_path, &arg_ptr);
|
||||||
|
argv[i++] = (const char *)arg_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < params->p_argc; i++) {
|
for (; i < bs->bs_argc; i++, j++) {
|
||||||
virt_addr_t arg_ptr;
|
virt_addr_t arg_ptr;
|
||||||
stack_writer_put_string(stack, params->p_argv[i], &arg_ptr);
|
stack_writer_put_string(stack, params->p_argv[j], &arg_ptr);
|
||||||
argv[i] = (const char *)arg_ptr;
|
argv[i] = (const char *)arg_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < params->p_envc; i++) {
|
virt_addr_t env_ptr;
|
||||||
virt_addr_t env_ptr;
|
for (i = 0; i < bs->bs_envc; i++) {
|
||||||
stack_writer_put_string(stack, params->p_envp[i], &env_ptr);
|
stack_writer_put_string(stack, params->p_envp[i], &env_ptr);
|
||||||
envp[i] = (const char *)env_ptr;
|
envp[i] = (const char *)env_ptr;
|
||||||
}
|
}
|
||||||
|
envp[i] = NULL;
|
||||||
|
|
||||||
return bs_remote;
|
return bs_remote;
|
||||||
}
|
}
|
||||||
@@ -118,16 +134,20 @@ enum launch_status launch_ctx_execute(
|
|||||||
return LAUNCH_ERR_TASK_CREATION_FAILED;
|
return LAUNCH_ERR_TASK_CREATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char interp_path[4096];
|
||||||
|
interp_path[0] = 0;
|
||||||
|
|
||||||
struct elf_image image;
|
struct elf_image image;
|
||||||
elf_image_init(&image);
|
elf_image_init(&image);
|
||||||
|
|
||||||
enum launch_status status = elf_image_load(
|
enum launch_status status = elf_image_load(
|
||||||
&image,
|
&image,
|
||||||
params->p_executable,
|
params->p_exec_image,
|
||||||
params->p_local_address_space,
|
params->p_local_address_space,
|
||||||
remote_address_space);
|
remote_address_space);
|
||||||
|
|
||||||
if (status == LAUNCH_ERR_INTERPRETER_REQUIRED) {
|
if (status == LAUNCH_ERR_INTERPRETER_REQUIRED) {
|
||||||
|
snprintf(interp_path, sizeof interp_path, "%s", image.e_interp);
|
||||||
kern_handle_t interp = get_library(
|
kern_handle_t interp = get_library(
|
||||||
ctx,
|
ctx,
|
||||||
image.e_interp,
|
image.e_interp,
|
||||||
@@ -157,17 +177,17 @@ enum launch_status launch_ctx_execute(
|
|||||||
}
|
}
|
||||||
|
|
||||||
virt_addr_t remote_stack_buf, local_stack_buf;
|
virt_addr_t remote_stack_buf, local_stack_buf;
|
||||||
kstatus = vm_region_map_relative(
|
kstatus = address_space_map(
|
||||||
remote_address_space,
|
remote_address_space,
|
||||||
VM_REGION_ANY_OFFSET,
|
MAP_ADDRESS_ANY,
|
||||||
stack_vmo,
|
stack_vmo,
|
||||||
0,
|
0,
|
||||||
STACK_SIZE,
|
STACK_SIZE,
|
||||||
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_USER,
|
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_USER,
|
||||||
&remote_stack_buf);
|
&remote_stack_buf);
|
||||||
kstatus = vm_region_map_relative(
|
kstatus = address_space_map(
|
||||||
params->p_local_address_space,
|
params->p_local_address_space,
|
||||||
VM_REGION_ANY_OFFSET,
|
MAP_ADDRESS_ANY,
|
||||||
stack_vmo,
|
stack_vmo,
|
||||||
0,
|
0,
|
||||||
STACK_SIZE,
|
STACK_SIZE,
|
||||||
@@ -187,7 +207,7 @@ enum launch_status launch_ctx_execute(
|
|||||||
&stack,
|
&stack,
|
||||||
local_stack_buf + STACK_SIZE,
|
local_stack_buf + STACK_SIZE,
|
||||||
remote_stack_buf + STACK_SIZE);
|
remote_stack_buf + STACK_SIZE);
|
||||||
virt_addr_t bsdata = write_bootstrap_data(&stack, params);
|
virt_addr_t bsdata = write_bootstrap_data(&stack, interp_path, params);
|
||||||
|
|
||||||
virt_addr_t ip = image.e_hdr.e_entry + image.e_remote_base;
|
virt_addr_t ip = image.e_hdr.e_entry + image.e_remote_base;
|
||||||
|
|
||||||
@@ -208,7 +228,10 @@ enum launch_status launch_ctx_execute(
|
|||||||
|
|
||||||
thread_start(thread);
|
thread_start(thread);
|
||||||
|
|
||||||
kern_handle_close(thread);
|
result->r_task = remote_task;
|
||||||
|
result->r_thread = thread;
|
||||||
|
result->r_address_space = remote_address_space;
|
||||||
|
|
||||||
elf_image_cleanup(&image);
|
elf_image_cleanup(&image);
|
||||||
|
|
||||||
return LAUNCH_OK;
|
return LAUNCH_OK;
|
||||||
|
|||||||
@@ -12,4 +12,4 @@ sysroot_add_library(
|
|||||||
HEADER_DIR /usr/include
|
HEADER_DIR /usr/include
|
||||||
LIB_DIR /usr/lib)
|
LIB_DIR /usr/lib)
|
||||||
|
|
||||||
target_link_libraries(librosetta libmango)
|
target_link_libraries(librosetta PRIVATE libmango)
|
||||||
|
|||||||
@@ -26,17 +26,17 @@ struct rosetta_bootstrap_channel {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct rosetta_bootstrap {
|
struct rosetta_bootstrap {
|
||||||
int bs_argc;
|
uintptr_t bs_argc;
|
||||||
const char **bs_argv;
|
const char **bs_argv;
|
||||||
|
|
||||||
int bs_envc;
|
uintptr_t bs_envc;
|
||||||
const char **bs_envp;
|
const char **bs_envp;
|
||||||
|
|
||||||
const struct rosetta_bootstrap_handle *bs_handles;
|
const struct rosetta_bootstrap_handle *bs_handles;
|
||||||
size_t bs_handles_count;
|
uintptr_t bs_handles_count;
|
||||||
|
|
||||||
const struct rosetta_bootstrap_channel *bs_channels;
|
const struct rosetta_bootstrap_channel *bs_channels;
|
||||||
size_t bs_channels_count;
|
uintptr_t bs_channels_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const struct rosetta_bootstrap_channel *rosetta_bootstrap_get_channel(
|
extern const struct rosetta_bootstrap_channel *rosetta_bootstrap_get_channel(
|
||||||
|
|||||||
28
lib/libxpc/CMakeLists.txt
Normal file
28
lib/libxpc/CMakeLists.txt
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
file(GLOB sources
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/*.c)
|
||||||
|
file(GLOB headers
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/*.h
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/include/xpc/*.h)
|
||||||
|
|
||||||
|
set(public_include_dirs
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
|
|
||||||
|
rosetta_add_library(
|
||||||
|
NAME libxpc SHARED STATIC
|
||||||
|
PUBLIC_INCLUDE_DIRS ${public_include_dirs}
|
||||||
|
SOURCES ${sources}
|
||||||
|
HEADERS ${headers})
|
||||||
|
|
||||||
|
sysroot_add_library(
|
||||||
|
NAME libxpc
|
||||||
|
HEADER_DIR /usr/include
|
||||||
|
LIB_DIR /usr/lib)
|
||||||
|
sysroot_add_library(
|
||||||
|
NAME libxpc-static
|
||||||
|
HEADER_DIR /usr/include
|
||||||
|
LIB_DIR /usr/lib)
|
||||||
|
|
||||||
|
target_link_libraries(libxpc libmango libc)
|
||||||
|
target_link_libraries(libxpc-static libmango libc-core)
|
||||||
|
|
||||||
|
#set_target_properties(libxpc-static PROPERTIES POSITION_INDEPENDENT_CODE FALSE)
|
||||||
61
lib/libxpc/buffer.c
Normal file
61
lib/libxpc/buffer.c
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
#include <mango/status.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <xpc/buffer.h>
|
||||||
|
#include <xpc/msg.h>
|
||||||
|
|
||||||
|
kern_status_t xpc_buffer_read(
|
||||||
|
const xpc_buffer_t *buf,
|
||||||
|
void *out,
|
||||||
|
size_t max,
|
||||||
|
size_t *nr_read)
|
||||||
|
{
|
||||||
|
if ((buf->buf_flags & (XPC_BUFFER_F_IN | XPC_BUFFER_F_REMOTE))
|
||||||
|
!= (XPC_BUFFER_F_IN | XPC_BUFFER_F_REMOTE)) {
|
||||||
|
return KERN_BAD_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t to_read = max;
|
||||||
|
if (to_read > buf->buf_len) {
|
||||||
|
to_read = buf->buf_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t status
|
||||||
|
= xpc_msg_read(buf->buf_origin, buf->buf_offset, out, to_read);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO */
|
||||||
|
*nr_read = to_read;
|
||||||
|
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t xpc_buffer_write(
|
||||||
|
xpc_buffer_t *buf,
|
||||||
|
const void *in,
|
||||||
|
size_t len,
|
||||||
|
size_t *nr_written)
|
||||||
|
{
|
||||||
|
if (!(buf->buf_flags & XPC_BUFFER_F_OUT)) {
|
||||||
|
return KERN_BAD_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t to_write = len;
|
||||||
|
if (to_write > buf->buf_max) {
|
||||||
|
to_write = buf->buf_max;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(buf->buf_flags & XPC_BUFFER_F_REMOTE)) {
|
||||||
|
memcpy(buf->buf_ptr, in, to_write);
|
||||||
|
*nr_written = to_write;
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return xpc_msg_write(
|
||||||
|
buf->buf_origin,
|
||||||
|
buf->buf_offset,
|
||||||
|
in,
|
||||||
|
to_write,
|
||||||
|
nr_written);
|
||||||
|
}
|
||||||
83
lib/libxpc/include/xpc/buffer.h
Normal file
83
lib/libxpc/include/xpc/buffer.h
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
#ifndef XPC_BUFFER_H_
|
||||||
|
#define XPC_BUFFER_H_
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <xpc/status.h>
|
||||||
|
|
||||||
|
#define XPC_BUFFER_IN(msg, offset, size) \
|
||||||
|
{ \
|
||||||
|
.buf_flags = XPC_BUFFER_F_IN | XPC_BUFFER_F_REMOTE, \
|
||||||
|
.buf_origin = (msg), \
|
||||||
|
.buf_offset = (offset), \
|
||||||
|
.buf_len = (size), \
|
||||||
|
}
|
||||||
|
#define XPC_BUFFER_OUT(msg, offset, size) \
|
||||||
|
{ \
|
||||||
|
.buf_flags = XPC_BUFFER_F_OUT | XPC_BUFFER_F_REMOTE, \
|
||||||
|
.buf_origin = (msg), \
|
||||||
|
.buf_offset = (offset), \
|
||||||
|
.buf_max = (size), \
|
||||||
|
}
|
||||||
|
#define XPC_LOCAL_BUFFER_OUT(ptr, size) \
|
||||||
|
{ \
|
||||||
|
.buf_flags = XPC_BUFFER_F_OUT, \
|
||||||
|
.buf_ptr = (ptr), \
|
||||||
|
.buf_max = (size), \
|
||||||
|
}
|
||||||
|
|
||||||
|
struct xpc_msg;
|
||||||
|
|
||||||
|
typedef enum xpc_buffer_flags {
|
||||||
|
/* the buffer can be read from */
|
||||||
|
XPC_BUFFER_F_IN = 0x01u,
|
||||||
|
/* the buffer can be written to */
|
||||||
|
XPC_BUFFER_F_OUT = 0x02u,
|
||||||
|
/* the buffer is backed by a buffer located in another address space.
|
||||||
|
* the buffer can only be accessed via xpc_buffer_read and/or
|
||||||
|
* xpc_buffer_write */
|
||||||
|
XPC_BUFFER_F_REMOTE = 0x04u,
|
||||||
|
/* free the buffer backing this buffer when the buffer is discarded.
|
||||||
|
* this is only used for out-buffers. the buffer must have been
|
||||||
|
* allocated using xpc_context_alloc, as it will be freed via a call
|
||||||
|
* to xpc_context_free */
|
||||||
|
XPC_BUFFER_F_FREE_ON_DISCARD = 0x08u,
|
||||||
|
} xpc_buffer_flags_t;
|
||||||
|
|
||||||
|
typedef struct xpc_buffer {
|
||||||
|
xpc_buffer_flags_t buf_flags;
|
||||||
|
/* only valid if F_OUT is set. specifies the maximum
|
||||||
|
* number of chars that can be written to buf_buf,
|
||||||
|
* including the null terminator. */
|
||||||
|
size_t buf_max;
|
||||||
|
/* only valid if F_OUT is set.
|
||||||
|
* if F_FREE_ON_DISCARD is set, must be either NULL or
|
||||||
|
* allocated via xpc_context_alloc */
|
||||||
|
void *buf_ptr;
|
||||||
|
/* valid for F_IN and F_OUT. offset of the buffer data
|
||||||
|
* within the associated message. used when reading
|
||||||
|
* buffer data from a message. */
|
||||||
|
size_t buf_offset;
|
||||||
|
|
||||||
|
/* only valid if F_REMOTE is set.
|
||||||
|
* used to read/write buffer data from/to the sender's address
|
||||||
|
* space. */
|
||||||
|
const struct xpc_msg *buf_origin;
|
||||||
|
|
||||||
|
/* valid for both F_IN and F_OUT buffers.
|
||||||
|
* F_IN: specifies the length of the incoming buffer data.
|
||||||
|
* F_OUT: specifies how many bytes from buf_ptr to send. */
|
||||||
|
size_t buf_len;
|
||||||
|
} xpc_buffer_t;
|
||||||
|
|
||||||
|
extern xpc_status_t xpc_buffer_read(
|
||||||
|
const xpc_buffer_t *s,
|
||||||
|
void *out,
|
||||||
|
size_t max,
|
||||||
|
size_t *nr_read);
|
||||||
|
extern xpc_status_t xpc_buffer_write(
|
||||||
|
xpc_buffer_t *s,
|
||||||
|
const void *in,
|
||||||
|
size_t len,
|
||||||
|
size_t *nr_written);
|
||||||
|
|
||||||
|
#endif
|
||||||
8
lib/libxpc/include/xpc/context.h
Normal file
8
lib/libxpc/include/xpc/context.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#ifndef XPC_CONTEXT_H_
|
||||||
|
#define XPC_CONTEXT_H_
|
||||||
|
|
||||||
|
typedef struct xpc_context {
|
||||||
|
|
||||||
|
} xpc_context_t;
|
||||||
|
|
||||||
|
#endif
|
||||||
13
lib/libxpc/include/xpc/endpoint.h
Normal file
13
lib/libxpc/include/xpc/endpoint.h
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#ifndef XPC_ENDPOINT_H_
|
||||||
|
#define XPC_ENDPOINT_H_
|
||||||
|
|
||||||
|
#include <mango/types.h>
|
||||||
|
|
||||||
|
typedef struct xpc_endpoint {
|
||||||
|
kern_handle_t e_channel;
|
||||||
|
tid_t e_task;
|
||||||
|
koid_t e_port;
|
||||||
|
msgid_t e_msg;
|
||||||
|
} xpc_endpoint_t;
|
||||||
|
|
||||||
|
#endif
|
||||||
55
lib/libxpc/include/xpc/msg.h
Normal file
55
lib/libxpc/include/xpc/msg.h
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
#ifndef XPC_MSG_H_
|
||||||
|
#define XPC_MSG_H_
|
||||||
|
|
||||||
|
#include <mango/types.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <xpc/endpoint.h>
|
||||||
|
|
||||||
|
#define XPC_MSG_MAGIC 0x5850434D
|
||||||
|
|
||||||
|
typedef struct xpc_msg_header {
|
||||||
|
uint32_t hdr_magic;
|
||||||
|
uint32_t hdr_interface;
|
||||||
|
uint16_t hdr_func;
|
||||||
|
uint16_t hdr_status;
|
||||||
|
} xpc_msg_header_t;
|
||||||
|
|
||||||
|
typedef struct xpc_msg {
|
||||||
|
xpc_endpoint_t msg_sender;
|
||||||
|
xpc_msg_header_t msg_header;
|
||||||
|
size_t msg_handles_count;
|
||||||
|
|
||||||
|
kern_msg_handle_t msg_handles[KERN_MSG_MAX_HANDLES];
|
||||||
|
} xpc_msg_t;
|
||||||
|
|
||||||
|
extern void xpc_msg_header_init(
|
||||||
|
xpc_msg_header_t *msg,
|
||||||
|
unsigned long interface,
|
||||||
|
unsigned short func);
|
||||||
|
extern bool xpc_msg_header_validate(const xpc_msg_header_t *msg);
|
||||||
|
extern kern_status_t xpc_msg_recv(kern_handle_t channel, xpc_msg_t *out);
|
||||||
|
extern kern_status_t xpc_msg_recv_nowait(kern_handle_t channel, xpc_msg_t *out);
|
||||||
|
extern kern_status_t xpc_msg_read(
|
||||||
|
const xpc_msg_t *msg,
|
||||||
|
size_t offset,
|
||||||
|
void *p,
|
||||||
|
size_t count);
|
||||||
|
extern kern_status_t xpc_msg_write(
|
||||||
|
const xpc_msg_t *msg,
|
||||||
|
size_t offset,
|
||||||
|
const void *p,
|
||||||
|
size_t count,
|
||||||
|
size_t *nr_written);
|
||||||
|
|
||||||
|
extern kern_status_t xpc_msg_reply(
|
||||||
|
const xpc_msg_t *msg,
|
||||||
|
kern_iovec_t *iov,
|
||||||
|
size_t iov_count,
|
||||||
|
kern_msg_handle_t *handles,
|
||||||
|
size_t handle_count);
|
||||||
|
extern kern_status_t xpc_msg_reply_error(
|
||||||
|
const xpc_msg_t *msg,
|
||||||
|
unsigned short code);
|
||||||
|
|
||||||
|
#endif
|
||||||
12
lib/libxpc/include/xpc/status.h
Normal file
12
lib/libxpc/include/xpc/status.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#ifndef XPC_STATUS_H_
|
||||||
|
#define XPC_STATUS_H_
|
||||||
|
|
||||||
|
typedef enum xpc_status {
|
||||||
|
XPC_SUCCESS = 0,
|
||||||
|
XPC_ERR_BAD_STATE,
|
||||||
|
XPC_ERR_INVALID_ARGUMENT,
|
||||||
|
XPC_ERR_NO_MEMORY,
|
||||||
|
XPC_ERR_MEMORY_FAULT,
|
||||||
|
} xpc_status_t;
|
||||||
|
|
||||||
|
#endif
|
||||||
79
lib/libxpc/include/xpc/string.h
Normal file
79
lib/libxpc/include/xpc/string.h
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
#ifndef XPC_STRING_H_
|
||||||
|
#define XPC_STRING_H_
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <xpc/status.h>
|
||||||
|
|
||||||
|
#define XPC_STRING_NPOS ((size_t)-1)
|
||||||
|
|
||||||
|
#define XPC_STRING_IN(msg, offset, size) \
|
||||||
|
{ \
|
||||||
|
.s_flags = XPC_STRING_F_IN | XPC_STRING_F_REMOTE, \
|
||||||
|
.s_origin = (msg), \
|
||||||
|
.s_offset = (offset), \
|
||||||
|
.s_len = (size), \
|
||||||
|
}
|
||||||
|
#define XPC_STRING_OUT(msg, offset, size) \
|
||||||
|
{ \
|
||||||
|
.s_flags = XPC_STRING_F_OUT | XPC_STRING_F_REMOTE, \
|
||||||
|
.s_origin = (msg), \
|
||||||
|
.s_offset = (offset), \
|
||||||
|
.s_max = (size), \
|
||||||
|
}
|
||||||
|
|
||||||
|
struct xpc_msg;
|
||||||
|
|
||||||
|
typedef enum xpc_string_flags {
|
||||||
|
/* the string can be read from */
|
||||||
|
XPC_STRING_F_IN = 0x01u,
|
||||||
|
/* the string can be written to */
|
||||||
|
XPC_STRING_F_OUT = 0x02u,
|
||||||
|
/* the string is backed by a buffer located in another address space.
|
||||||
|
* the string can only be accessed via xpc_string_read and/or
|
||||||
|
* xpc_string_write */
|
||||||
|
XPC_STRING_F_REMOTE = 0x04u,
|
||||||
|
/* free the buffer backing this string when the string is discarded.
|
||||||
|
* this is only used for out-strings. the buffer must have been
|
||||||
|
* allocated using xpc_context_alloc, as it will be freed via a call
|
||||||
|
* to xpc_context_free */
|
||||||
|
XPC_STRING_F_FREE_ON_DISCARD = 0x08u,
|
||||||
|
} xpc_string_flags_t;
|
||||||
|
|
||||||
|
typedef struct xpc_string {
|
||||||
|
xpc_string_flags_t s_flags;
|
||||||
|
/* only valid if F_OUT is set. specifies the maximum
|
||||||
|
* number of chars that can be written to s_buf,
|
||||||
|
* including the null terminator. */
|
||||||
|
size_t s_max;
|
||||||
|
/* only valid if F_OUT is set.
|
||||||
|
* if F_FREE_ON_DISCARD is set, must be either NULL or
|
||||||
|
* allocated via xpc_context_alloc */
|
||||||
|
const char *s_buf;
|
||||||
|
|
||||||
|
/* valid for F_IN and F_OUT. offset of the string data
|
||||||
|
* within the associated message. used when reading
|
||||||
|
* string data from a message. */
|
||||||
|
size_t s_offset;
|
||||||
|
|
||||||
|
/* only valid if F_REMOTE is set.
|
||||||
|
* used to read/write string data from/to the sender's address space. */
|
||||||
|
const struct xpc_msg *s_origin;
|
||||||
|
|
||||||
|
/* valid for both F_IN and F_OUT strings.
|
||||||
|
* F_IN: specifies the length of the incoming string data.
|
||||||
|
* F_OUT: specifies how many characters from s_buf to send. */
|
||||||
|
size_t s_len;
|
||||||
|
} xpc_string_t;
|
||||||
|
|
||||||
|
extern xpc_status_t xpc_string_read(
|
||||||
|
const xpc_string_t *s,
|
||||||
|
char *out,
|
||||||
|
size_t max,
|
||||||
|
size_t *nr_read);
|
||||||
|
extern xpc_status_t xpc_string_write(
|
||||||
|
xpc_string_t *s,
|
||||||
|
const char *in,
|
||||||
|
size_t len,
|
||||||
|
size_t *nr_written);
|
||||||
|
|
||||||
|
#endif
|
||||||
151
lib/libxpc/msg.c
Normal file
151
lib/libxpc/msg.c
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
#include <mango/msg.h>
|
||||||
|
#include <mango/object.h>
|
||||||
|
#include <mango/signal.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <xpc/msg.h>
|
||||||
|
|
||||||
|
void xpc_msg_header_init(
|
||||||
|
xpc_msg_header_t *msg,
|
||||||
|
unsigned long interface,
|
||||||
|
unsigned short func)
|
||||||
|
{
|
||||||
|
memset(msg, 0x0, sizeof *msg);
|
||||||
|
|
||||||
|
msg->hdr_magic = XPC_MSG_MAGIC;
|
||||||
|
msg->hdr_interface = interface;
|
||||||
|
msg->hdr_func = func;
|
||||||
|
msg->hdr_status = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool xpc_msg_header_validate(const xpc_msg_header_t *msg)
|
||||||
|
{
|
||||||
|
return msg->hdr_magic == XPC_MSG_MAGIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
static kern_status_t __msg_recv(
|
||||||
|
kern_handle_t channel,
|
||||||
|
xpc_msg_t *out,
|
||||||
|
bool nowait)
|
||||||
|
{
|
||||||
|
kern_status_t status = KERN_OK;
|
||||||
|
|
||||||
|
if (!nowait) {
|
||||||
|
kern_wait_item_t wait = {
|
||||||
|
.w_handle = channel,
|
||||||
|
.w_waitfor = CHANNEL_SIGNAL_MSG_RECEIVED,
|
||||||
|
};
|
||||||
|
|
||||||
|
status = kern_object_wait(&wait, 1);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_iovec_t iov = IOVEC(&out->msg_header, sizeof out->msg_header);
|
||||||
|
kern_msg_t msg = {
|
||||||
|
.msg_data = &iov,
|
||||||
|
.msg_data_count = 1,
|
||||||
|
.msg_handles = out->msg_handles,
|
||||||
|
.msg_handles_count = KERN_MSG_MAX_HANDLES,
|
||||||
|
};
|
||||||
|
|
||||||
|
status = msg_recv(channel, &msg);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!xpc_msg_header_validate(&out->msg_header)) {
|
||||||
|
return KERN_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
out->msg_sender.e_channel = channel;
|
||||||
|
out->msg_sender.e_task = msg.msg_sender;
|
||||||
|
out->msg_sender.e_port = msg.msg_endpoint;
|
||||||
|
out->msg_sender.e_msg = msg.msg_id;
|
||||||
|
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t xpc_msg_recv(kern_handle_t channel, xpc_msg_t *out)
|
||||||
|
{
|
||||||
|
kern_status_t status = KERN_OK;
|
||||||
|
while (1) {
|
||||||
|
status = __msg_recv(channel, out, false);
|
||||||
|
|
||||||
|
if (status != KERN_NO_ENTRY) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t xpc_msg_recv_nowait(kern_handle_t channel, xpc_msg_t *out)
|
||||||
|
{
|
||||||
|
return __msg_recv(channel, out, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t xpc_msg_read(
|
||||||
|
const xpc_msg_t *msg,
|
||||||
|
size_t offset,
|
||||||
|
void *p,
|
||||||
|
size_t count)
|
||||||
|
{
|
||||||
|
kern_iovec_t iov = IOVEC(p, count);
|
||||||
|
size_t r = 0;
|
||||||
|
return msg_read(
|
||||||
|
msg->msg_sender.e_channel,
|
||||||
|
msg->msg_sender.e_msg,
|
||||||
|
offset,
|
||||||
|
&iov,
|
||||||
|
1,
|
||||||
|
&r);
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t xpc_msg_write(
|
||||||
|
const xpc_msg_t *msg,
|
||||||
|
size_t offset,
|
||||||
|
const void *p,
|
||||||
|
size_t count,
|
||||||
|
size_t *nr_written)
|
||||||
|
{
|
||||||
|
kern_iovec_t iov = IOVEC(p, count);
|
||||||
|
return msg_write(
|
||||||
|
msg->msg_sender.e_channel,
|
||||||
|
msg->msg_sender.e_msg,
|
||||||
|
offset,
|
||||||
|
&iov,
|
||||||
|
1,
|
||||||
|
nr_written);
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t xpc_msg_reply(
|
||||||
|
const xpc_msg_t *msg,
|
||||||
|
kern_iovec_t *iov,
|
||||||
|
size_t iov_count,
|
||||||
|
kern_msg_handle_t *handles,
|
||||||
|
size_t handle_count)
|
||||||
|
{
|
||||||
|
kern_msg_t reply = MSG(iov, iov_count, handles, handle_count);
|
||||||
|
return msg_reply(
|
||||||
|
msg->msg_sender.e_channel,
|
||||||
|
msg->msg_sender.e_msg,
|
||||||
|
&reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t xpc_msg_reply_error(const xpc_msg_t *msg, unsigned short code)
|
||||||
|
{
|
||||||
|
xpc_msg_header_t reply_data = {
|
||||||
|
.hdr_magic = XPC_MSG_MAGIC,
|
||||||
|
.hdr_interface = msg->msg_header.hdr_interface,
|
||||||
|
.hdr_func = msg->msg_header.hdr_func,
|
||||||
|
.hdr_status = code,
|
||||||
|
};
|
||||||
|
|
||||||
|
kern_iovec_t iov = IOVEC(&reply_data, sizeof reply_data);
|
||||||
|
kern_msg_t reply = MSG(&iov, 1, NULL, 0);
|
||||||
|
return msg_reply(
|
||||||
|
msg->msg_sender.e_channel,
|
||||||
|
msg->msg_sender.e_msg,
|
||||||
|
&reply);
|
||||||
|
}
|
||||||
56
lib/libxpc/string.c
Normal file
56
lib/libxpc/string.c
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
#include <mango/status.h>
|
||||||
|
#include <xpc/msg.h>
|
||||||
|
#include <xpc/string.h>
|
||||||
|
|
||||||
|
xpc_status_t xpc_string_read(
|
||||||
|
const xpc_string_t *s,
|
||||||
|
char *out,
|
||||||
|
size_t max,
|
||||||
|
size_t *nr_read)
|
||||||
|
{
|
||||||
|
if ((s->s_flags & (XPC_STRING_F_IN | XPC_STRING_F_REMOTE))
|
||||||
|
!= (XPC_STRING_F_IN | XPC_STRING_F_REMOTE)) {
|
||||||
|
return KERN_BAD_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t to_read = max - 1;
|
||||||
|
if (to_read > s->s_len) {
|
||||||
|
to_read = s->s_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t status
|
||||||
|
= xpc_msg_read(s->s_origin, s->s_offset, out, to_read);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
out[to_read] = '\0';
|
||||||
|
/* TODO */
|
||||||
|
*nr_read = to_read;
|
||||||
|
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
xpc_status_t xpc_string_write(
|
||||||
|
xpc_string_t *s,
|
||||||
|
const char *in,
|
||||||
|
size_t len,
|
||||||
|
size_t *nr_written)
|
||||||
|
{
|
||||||
|
if ((s->s_flags & (XPC_STRING_F_OUT | XPC_STRING_F_REMOTE))
|
||||||
|
!= (XPC_STRING_F_IN | XPC_STRING_F_REMOTE)) {
|
||||||
|
return KERN_BAD_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t to_write = len;
|
||||||
|
if (to_write > s->s_max - 1) {
|
||||||
|
to_write = s->s_max - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return xpc_msg_write(
|
||||||
|
s->s_origin,
|
||||||
|
s->s_offset,
|
||||||
|
in,
|
||||||
|
to_write,
|
||||||
|
nr_written);
|
||||||
|
}
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
file(GLOB sources *.c)
|
|
||||||
add_executable(systemd ${sources})
|
|
||||||
target_link_libraries(systemd libc libc-runtime liblaunch libmango)
|
|
||||||
|
|
||||||
sysroot_add_program(
|
|
||||||
NAME systemd
|
|
||||||
BIN_DIR /usr/bin)
|
|
||||||
bsp_add_program(
|
|
||||||
NAME systemd
|
|
||||||
BIN_DIR /usr/bin)
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
add_executable(test test.c)
|
|
||||||
target_link_libraries(test libc libc-runtime liblaunch)
|
|
||||||
|
|
||||||
sysroot_add_program(
|
|
||||||
NAME test
|
|
||||||
BIN_DIR /usr/bin)
|
|
||||||
bsp_add_program(
|
|
||||||
NAME test
|
|
||||||
BIN_DIR /usr/bin)
|
|
||||||
@@ -1,157 +0,0 @@
|
|||||||
#include <string.h>
|
|
||||||
|
|
||||||
const char *s
|
|
||||||
= "RHZVNYYFPCGZIKWYLOZAKKLZGKWXDPXSTWNSWDBVDCPUMTAZCRNGNHGQPAGEWVAOCJST"
|
|
||||||
"PBXVWPKXQAHGETDTDETVYAEQGNBLEQIPHGGWKEDJAULOVMZKNABLUUXOTMHJNAVLSGCZ"
|
|
||||||
"QIFHIUCBCIRZIOFVHBPSGVBBZSRAQZYRPMYBNJDFTWSUUZVBQZTBUFUDJDYKUXWHDMXD"
|
|
||||||
"JKBSNWLFPUDGRMQPBCWVJZHOTJBTMGUSXQUZVXLDKWIKINXRFJKSYJEKDAPRQPMQMJPS"
|
|
||||||
"ICCTMELLKDFFJXOXISIXNVANFHLRPYMNPYCMUOYSPAYCKYJKRBZENHXYRJWRYXZGETMJ"
|
|
||||||
"XBFTCMSIHZQSCMLESDFKGTTNMCZSXEFMGXZYPWVPODMYTLDUOKGPMTMFBTQQHPBHMNCM"
|
|
||||||
"LYRGGUAIRSFFBRSKXOLJBWEMEODRQLXZJDRSTXBJOKOMUQKCJVKFHDYXCUUDHDEITHNH"
|
|
||||||
"VQLJJQMLYWGIDVLYCEJTJFJQLTKSAPZGEEZKVLQPHIVJNJVTXJUGPZODIFXTQNLBSFLG"
|
|
||||||
"NSPMGLUSEBOFJWXFFRBHIHYGGTILVVOJRPOFOIGDFCHLAZXLSOUCPCLZCBVWGZVKGDON"
|
|
||||||
"RPYOTSRWUNAGQSPHSGEQHOLUSOZCQQGJBLPKQNGKOPCVKLACDBPAPXDMGKLFPUOFQDWY"
|
|
||||||
"INIKZPLVFSZZZZHAYKXTETJDPMBHKNRCRLXZHFENZCABDTZULCRHCCVZFETBEBEJFVKJ"
|
|
||||||
"ADWFSHKKSMMKGTIHPAIAMWXTRJILBMWMBDZGRPZXHMJVCWPKSNPYPPNSAVQDSMANBFZO"
|
|
||||||
"LJBYKDOZNAPZRWEQDIIZRPNGZGHQWPIONPSAMBNNZERYMIQOVHRGZFXWVUARJMFWNPQP"
|
|
||||||
"GHDCZABLOYHCBCXAIDSPMDKZVBBOKHAHGTEPRQAIBVWTFBQDGDJPQGMVAGQQVMULVPMG"
|
|
||||||
"UPGEJUIZZXQRQKRJUCKDDZFTAHAAHMJLSISGFFOXOYNMJCAPPQXAVFSAFFRPRTEQLNCX"
|
|
||||||
"JVKTHBPZLAEXSIGVJASAERWDGDQDXASXHRSSCNAUMRWSQDZTOJHJGJLLXMJSTXBHOYPH"
|
|
||||||
"ELYKSXNJSPWPMFAKOOTXXTOEBLYFSOIJDWAOCTHDFOEBEEXVUBXOJDUCJWQOUUDOJNZG"
|
|
||||||
"PULPYTAOQEXMHSGOOUXHAJOKRHOOMZYMBHQNTQDWZPCXATDEKTYLNBKNUEIINHQTEGTR"
|
|
||||||
"ZKLMAKIIHHZBQIPXLAGADCFDYWEOJVHFPEMRDIOJYAMWSWEUOPJFEDGRGJOQNTSHRIJY"
|
|
||||||
"JPTOSWYZXJCGXLYVOWKAFGULLNCKIUZDWUXTHNYSWMMCJGTFVVVPJHEKYQVFRWLIZBBK"
|
|
||||||
"CNCRITFZYTQZZGZHXELBEYXSVVYRFBGRFPRDROUXKUMAGFYOJRMCLLHJVMQFYOBCXSEL"
|
|
||||||
"OQAQTRMLSGDAXWMBRSQHCIYYMBQQHMUQOKIANZCBGKHLCPUVUEZVKDTTSOWKKWIUBAIW"
|
|
||||||
"SOCJAUALJFEQQXJBHRRZBFMJZZMIWTFKQDPOBFIGABJTHFLLSZPWWGGLHLYXKBODKBIV"
|
|
||||||
"GAYGIKHNMTMJHCPRBQYAACGSFZPJWXUTRZFCGTLFQBVHZBKYBRMYTTCGIDKYWVRPJDTX"
|
|
||||||
"RKXGOPOQLNSEIGHTSAXGPBROFHQACSIVSLCXTEDUOEPRMGJDYWTKEHCXWINUDCAZWAEY"
|
|
||||||
"RQDKZRZXKWGHVWJDYHGFLCGKCLYCVHZTWWXPDBKTMBKBASERMURDREKNYVOCPHFSEGBQ"
|
|
||||||
"LAUHDDCAPPGOAFZYJYXPPAQLUQVKSDEHPPDXMNWAAYLHXBFEFXRLSMQNIYDECYVVPHEE"
|
|
||||||
"WXFFPEYLSHBXLYJWRABFKJYMJNWAUMVYJKZRDMPUQJKWVNTPRMHTAQGNSDLFTXVNIAIJ"
|
|
||||||
"HOIISROAJCWEOAIHYMDGWEOABPGIMBTTGWYVJDZOOMUSHYDPCMKWDIXDGJCGTQVXWBKP"
|
|
||||||
"DBCVJJDYIAPXKINQXACEMTJRCIAENGTTMWXVSQCCXRDVNZZNQDZTTYJHQGXZIJIIKPAU"
|
|
||||||
"TQJDDQQEPGYZNKCKNMVFCRHUECPVFZYVUWVMSCIQZBVLSTNFAHDDEQRKDOUAQVRVQAVB"
|
|
||||||
"ZCEMAJRJBVWKVBNEIQWWQSJPUVUKMBJIISCWXGGMWANYYLPCXHCBARMFTFMDXWSMKXPW"
|
|
||||||
"DZUGFBSGGWXLOFGYJVIDWNTSGODTHQNCKPWRJENDZNSCEYZRLEPNNYVBNUZMXAUWNAJD"
|
|
||||||
"XGTOLUAAIAHMDJERSESVFSMMHJKHIVIBWZLEAXUKRSWJOTFODRBZIJBRJQTFBVRQHITD"
|
|
||||||
"TDBAJZCZUKSIZJYDXWTSRPLXULXHGEKMWMICUYVAGNGEICEMMVWLLYWTAKWNGLRYOCIG"
|
|
||||||
"BEYTLVAZFHBYIJPUAQHITKHPWAQNEBQVAYZEINLRCKUZILAQPAGBJDWWLGCPQZOZVDQP"
|
|
||||||
"MWTIOAFMEMFKLGVGGHTTKNERTLPPQFALZMCWSOMJQQZMRABNKBCYPFJOWQCXJKXTNOMJ"
|
|
||||||
"MXAWMPFBJHOYHVOBDNWTKHYTISUQMFSNVBGUHDQFYCSZLZAFABKYQSZRQGKXOXORQPSJ"
|
|
||||||
"NKRVVAXMMVVPBSWMTHUNXBLSVIOOQPLRPROIBBQGNQVOXQXRNNMSFGUZEIGIYMLMLYYL"
|
|
||||||
"VINTZYXYXHUFMTQFPDGSFFDVCDMEZXSGQMMGJWMWANFSZNHDIIHVJFOZGMHAOVRUWWVX"
|
|
||||||
"RCOJJKZLTMAOGSRWNNXPYDCQWSSOFWUKFPKQGYLFSMZBZBKWSBMMZMFPOYYMLVYHQQQF"
|
|
||||||
"HORVESQYIKEBBKSEUYXUFRNNXZPUYESZWAKQQPAWZUHYJLXRXBFPRFSCHIHHDVAIKYDZ"
|
|
||||||
"IDLVQBCSGOSGFOUKVMKTODAHQVTACKAONRDYENPGSQFKGKYQROFOEKMJXKFIAEKWNRJH"
|
|
||||||
"RZCCSMNSSHZNSRTBGFJJDWAPVIOBDCQKMDEMUIWGMETBUTCGMMGXLHWWTXXQYAPMQQGU"
|
|
||||||
"CHECLYRWNFKHGRWYZISFYKSGTJXKTKIMJKTUWOQFHXUVTOBYUCOZKLCQCUIURHSIGUAU"
|
|
||||||
"FFSNEHFLHNGBNVTGPKCVCQLHEHLJRWPGSWHKFMMXSSCVTCUOEEZOFOPTDRUPPCYTRSKI"
|
|
||||||
"NJBPLOHMHQLWKMVBSZLZVDZEKXKSCNWPZTGZUXRYJEPENAYFCEKCAMWQLNYDHCSUUSTJ"
|
|
||||||
"GFZCTKDQYPEZKOOJQTYMWHZDDTCMYUXCAKFXISWQZDVETOAYIANBRSXLYKOGGHEEEGAX"
|
|
||||||
"SRIASWZBXTFCHLKMXQDYNLZICZZANCBUVGWFWFHYAWVLQXTQPGPQGRGBEZVIIGZJUVQU"
|
|
||||||
"PNXEMZDIFXAKSHTCCBQSAXWFBNLRYQKXKXQHAFZTUICFQVYOXQEHASXNSVUTYKSVYTMH"
|
|
||||||
"UTPBEVILWSKGQXPAEEOPUSMGQVPWFMRZRIMJZRRQRIZBTTRROUWENBHUYVMOMVPFDLZH"
|
|
||||||
"XMXYRNASODBTLCNRDSLGPTZBZHKTSMHIVNFJOMOFPHDANVSVOYZSTKOQJLDPKLOMAYUU"
|
|
||||||
"CKWTOTDONTXKCEGVXKZNNFIUXHLJPFFNVMWSFPXZKROEIGQNGXWDRFJWDCUEGJCUJGVG"
|
|
||||||
"PHYKQEWVOHHPURHBBIEZCKQCFUFFBDXYRNOHAVJISOQYXMRXIEFEISFEZHLNTJXYEAKM"
|
|
||||||
"EKZPJQVQBKPXPFSOANBBJBAFJQEMPIELYUHYCHUTADTCLFXUQLXWTJEFLJXVBRQXYSIR"
|
|
||||||
"RPMTNMFMUCHQJEVXUSFYUUYJHLEQBHUQOTVADYQGRXVLUPQXVXEDIGNSCYNMKPWLFLHZ"
|
|
||||||
"LMQGPTMBDVUJOBSXDFHKSIEXJJQTURPNZVQDLUEJHQZOQSBMPMBEQOCOSEKVXIVSQIQL"
|
|
||||||
"GSQAUMIAHHLQCBCQWFJWHSYNRFFTBKORISDYNRSMPVERKRJBWGYJRXMKHJDAKRANHFDH"
|
|
||||||
"WTZOHYRVCTTUXCRAFNOLYPRGDYTXNSOTCDNFVVURJILWVDWOCGPQOZIGGNOEAHCBYGMC"
|
|
||||||
"XGXAADYMYDAUXPDFADTVEQTHZRGYASPJRDIKJUFIRXGMFSCIURDNFIDUUDEKPFGWECZC"
|
|
||||||
"OOFZWESHSPSOOBWZKIGODSLXCALULNOLQLCMMLSQDWJDTEOIYXFCLSLKJKGCGURXEEIN"
|
|
||||||
"SCUQTRDGMYXFZEFBATVSYVAJISCBVDBZAJAPKBBQTQNNRZYBLGWPCIORYJJEKIZXRRCG"
|
|
||||||
"ZHGQNMGWVNIANJXYJMWRCGDGDFFQISSZOWTQOKWRGXSGRUSJOHABJUEUIHNTLCXJQPNF"
|
|
||||||
"YUKTQCGRFGZOQWYLJOGOGSRDXESAOTHZVHBEOOYJZYTMOSUUXDQNKTQBVUMRBPJEJIBU"
|
|
||||||
"TOVXSGYSTADWQKFUEFWJDCAYTEYVZYDCQTHXJWYUESZSLRBKRAMLVVVBMEYSYFNBLKTY"
|
|
||||||
"UJRQBOKJQTYXTOFPWGWEEANVFYMAVRKMNJARUOKTZTMMJKNVFEVSECABUZGGUEHRJIHO"
|
|
||||||
"JODXJOOGFZWNURNEXBUCCUHUDYXBZTNJZSQGHAGYLJQSSJERWEGUFAJXGNBXDWVFSCEG"
|
|
||||||
"SUCLQLHHTRQADZIBKFCBBEXUDLPCFUDONSHUUCREKHDUBQBKMECPPOGFYIUZNUDKTILB"
|
|
||||||
"IHMYNAMJIDTJEQTVPFZDNONMWFIJEAUOLPWOZVKEFTXRCXNWHWPYDHLWNSWTMUEIBMSK"
|
|
||||||
"FWROAFBMEOJAVLMNCNWEMGRUDKRPENXCJQQGLPCODNOTGPOQFZTOBEBJIDAMMZARXTMC"
|
|
||||||
"EAHKYNTYZKWCUFYOSCOPICKIDAUSZHWNTVRRSTIMHFBUALQECIZKYFUYJHDTFDODXXNJ"
|
|
||||||
"AKZNUMYZSHIGZQQXBTORWFCGQFKFURMZYWBAQSHAJEASIYAFQZDOUHBJXODDUAWNKWVB"
|
|
||||||
"NABZSUNRULZDXKBRGVCKUIYVRVRMTDFSWCTCDYKBZDELJBDIHLOALYEKHNMECBWRZQBK"
|
|
||||||
"XLWFYJYECKOJOGXJYBKFSUQZKEUWBHEWNHSZKJPRQRMLRFLJWBDZEJQVYRAFQGEOGUBU"
|
|
||||||
"SVVWUGKXHSXHRXWCZKASIYPZZDLRUVBNBUQEEPZPHMSNUETUKMYWNJLEZWVOLZBQMLWE"
|
|
||||||
"YPPVBOTADNFNJWUZKDWRXCJCMDQPGPBIVAVQJVTHEPLXEKPSPJQFNGILKTUETORGMHGH"
|
|
||||||
"HHXTZIXUXPDLKNYGHNNTKAZFCGCUONFANKRXHGPQLPDJACZDMSSFPJHRPPGGSVEYKQHF"
|
|
||||||
"JKASAYIFKXXVEYRCLIMLDEUQWIHZXPLKDCHUFYAHLOQUJMJCXTHFAOSOEYWOMFAZHGPE"
|
|
||||||
"UNYKWLFYQPMRYXDVGWWMOLXHCHQADSYAAQMLBGGNQELFWMYHPWNIDOIFLGHGQUPCVPHS"
|
|
||||||
"WDGERQMWOZBWFHTOSINKTPXQLFGHLVALHCYSPKFBWSYTUHMZQNZSDAQTAZLPHSYZKROA"
|
|
||||||
"PSKJEWCRABAGYIIAYAUOVMTYIQOWYWHLLEXOOVZNLXOIPFNRYHDJYVTJLOHODYRBBBSB"
|
|
||||||
"NPQCNUZHYTWDAQSEBEMDSEDTKORHUCILESZYYYLJNRCFHAWNUMQHDQKXGCJIZOGBDVTU"
|
|
||||||
"PWNKAHKIRBHINKVRRBOPVAWCSPVMTNQQYDYLCKHPKRFYCAYUPGAOQLJSTHGMCXUUQIVI"
|
|
||||||
"MNPISKLETFEWNDDTDHLCQXNGRJJZHGJYYWNXKQIWXENKWQAGAXTCTLGWNVXDMMPHYPBQ"
|
|
||||||
"GWWNCWJWYVBVYOWOEJJPZAZGKJEQHPDBYUQBMOLOIMZXYXFOBNNPMGDCTXLCHBEBHCOS"
|
|
||||||
"HGKAEBGPLANNUHMOHWHAQEWFJSWPIFTWZNKWHKZYDXDAJODTHPXPIGVFYVDNWEQFKKIC"
|
|
||||||
"EBMGPSBVTPXODJVAYJAURNSFOCUNJROYEMOELHMIGLFDMJQFVEOSINHIWDUUIPNSBHEC"
|
|
||||||
"TKUFRERFNYCWSSGCYQWMXOQFCZPCSAVRBMSFZEYDBSWWHYLHIGGIDQJRTLNJOMWQVKES"
|
|
||||||
"KTFWQIRKJEMAZSMFQQSSTCXKOUZLJJWNYJJKSHPAOTEWEKKABTJDOFRGKVBMJFKFFVSP"
|
|
||||||
"GPMUCDWAFPHLKKZGEYTQNFJBGJTSATHNVDWRKSMLAJAPHYEJXYEKCTKDFGDILOIRDWLV"
|
|
||||||
"LAMTOCSMRMXYYHPHYBMKAVDRWYSXVPLZUBPAVUUQDNRCNYPKUSWBTCHJMIHQJNXXXXQX"
|
|
||||||
"LIUZQDFCTJBHELXALVTAJDFIPIFAKJKCPPPPXAVPTOUTLTIGMBUWOIERHBYOIMWTTXOY"
|
|
||||||
"KCZKDVRSARRBMSQFZGGSVPVBHKBYXZBITZDBQDBZLQNPVEQTXECOHOJKEXUUIBXSORPF"
|
|
||||||
"THLTMDDDOYSQZBGMBGZFYAJMHWZOLRUUJAIHOLSCIYGHMRAEIKFLFNLEMHOPKVRTJCMJ"
|
|
||||||
"DKBKJCMDBPGUGPPZBCXYRLHZUYPMIQOXYOCGKBEHZFHGAAKQINMHUNTSJHPPZGNKFREX"
|
|
||||||
"HGGFEFDAWMCMIXEDLUPDAXNCTHFDMHJPZOGJILKJXRUQBGXKDXTBZXSPZLZUCNCZZYRU"
|
|
||||||
"DRUEVXRELACIWMGUIBKEXSYTBIJTJPJJLCIQQBVJGXHPCTSHPASIIAMPATSDCTXZAPCJ"
|
|
||||||
"ESVMBOTOLKGHVRZSBVOBSAAKRPSAFYNPIDVFUMNMJRGKWOANKHZYCABHWIWUJFLDPSFY"
|
|
||||||
"SPBXQEFLNEEMIGMWWXYTXNTHRXUZQKXCMBLEHGRBFPSUMGMBJFFWTAEFCLDBOHMNAICE"
|
|
||||||
"YAZCTBCHKXEIBYUTQEAOVDJVOLTYDJJUCPSXUEPTFZPSJOMQDSSKBAHRIVYHQJFVUQJH"
|
|
||||||
"HRAQYZLYTOAWWIIPEUPQEBYSKTRETZEDWVALVPISUBTOWJZQLVRWKLLLMWEAZZIGMTRV"
|
|
||||||
"DXJHBFOTBFYSKQYJSNVKINMYRAMBFMBZUVHEEUWRRCMLAPOKKIODTFIIVTIPTBMVMZIP"
|
|
||||||
"HKDIQRFOKYTVDLAPPUMYNZBJMZMDDQDTXZWOMAJSJETWLGSAJDNNCODMAMCGADNXJGPP"
|
|
||||||
"GMPQXTZYICNPVATOCYCCGVSAKGCSGCPVUFGNGJPCRVZQXIDIZYCEBNMLMYHUMJZNHGCZ"
|
|
||||||
"TIYTNXTCGMGSBGLIDHYABMLEBGAHLOEYVOAMROXQAFDNEIZAOFWDETNEZWJFHTYOEVDH"
|
|
||||||
"RZDIZNSNBDCERUYZRLFWAANFAETBEWWPNNMUYXVBVDKMWPJUZLEPXOJAZOAYNKZDTBJO"
|
|
||||||
"MKXEMIAGHIQIHXPZGWDEQJKBNTDIWPLDANSOQJTGVPPSROOXGEBBWKLXMUEKZBKTTQTN"
|
|
||||||
"HILWSXGGYZZFYPGDVMNGLGGBSZJYWXGVHAACMVKQLPYXWWJMOQJJCXQOUIRCXPYCITBW"
|
|
||||||
"WCOKSSDXXWHHSOPANMWVIKJFLYNBPQAUHWKZEQBDVWDDULWFVBXUBJVOMHNAELALFGZT"
|
|
||||||
"FHSVLXJTMSOAKGBXKHKDEKVVFRZPKLTRRKCREVPXQYEVGIHAUNEJDLWERMKWJJBONLPW"
|
|
||||||
"BNTDWFILGFYOOAPNXVBDGGYDCZWUSJLPLZRVYAVSQFEXRZACHLLGGDEJGURDPYFCQUCX"
|
|
||||||
"OTNJJUJMMBEYSKJPKBGMQAAWOSPYAWDPJEQRLDJVZMRCYSKBAOQYWTJXSRRRMSFGNFRX"
|
|
||||||
"VEWFGPXVPZQXGRGOLKIYCCAOAGCZSHGPEGVMWETUWVZXZKCJVGQNEJBICWINFFHIUSUE"
|
|
||||||
"SVKYPVAOKBQEMQNKAXHFDETVNNFPQAXQXFJSKJCFLAHNRQUQPXYELGDYJDEETNEYGTMQ"
|
|
||||||
"MYIGQUDGOUMZDQORHNVDXBCJYBFTCDEMATBUCGAEKONTAIRCOHHKJFORZVDQSOWKDLKU"
|
|
||||||
"UOTTLLKQHVKVYOLJWNRRWXEOJMDZIKPMZFBBJCQSVTMCFFZDCWLRQDKAOKEXFVDZCPHE"
|
|
||||||
"UGNBVSILDBRPBJKNZXIWTNOZEDDESKOGYFOWPZJBQIQXKQERGWTJCUXGTOHLAOWDLGPF"
|
|
||||||
"RHVNLXVTKDDCWWZUAXKJZKPMOZCZCYVOIRCJNIJAMFRPAWNKFYAGKHNEPKPFTTRXXGTN"
|
|
||||||
"XFHFJXQWMKDSODYMNWJIFQZJOCYHUKYNYKXSLJNMBKCUXETKQTSZAXZUEERRGNBFDXJW"
|
|
||||||
"IKSVAVDNXLHJXVNDGLFZNZYTMJPDDXCOPGEROKJOGHXLDZJTSWOXIVCJKLYYTKANVFIF"
|
|
||||||
"KRVVEXSZXREAOBPVQRZUQKIWNMPTFUWARTQJCDTPEOVDHTDCWAWTTMNLRTOPYGPBROQA"
|
|
||||||
"QSMTGDCATMYQDJZQAUBQPOZLXDIJCKEVXDTPDNCHNJXMHNRVLWLKSAUYTHVOIYAAHUCY"
|
|
||||||
"XUWPHXMFXBDNBSNZIVKZANBYCHTUDOLHVVXGFDRDOIRCCRTZRNPWFTHSQRYTLGETDTGZ"
|
|
||||||
"KQWQPZYUTFFVFRQCAJAFDJAUMHPRXGUTLMFKOGXQHGOACGELSACTSNJTSOGNJAODFCIB"
|
|
||||||
"EQGGZETTRWOLAPRYJIGCYSUIMDCRHRGBKJFPDXVGPSPGDMBOLAVARRJSNDMZIOPKTAMA"
|
|
||||||
"NRZOSWGMPBPDBPCUADFMIEWOEBNNDFHUJCFMWXAFDKSWUTMMSQZSFBOGSSKOITDUGLLA"
|
|
||||||
"NFCZSGCDFDWUDTBPFKMHROQMIQRLCNGGCSFTNCVXSJJGPUZQREUASWLVOFVHRZPQUYGE"
|
|
||||||
"TBCJUSBKOJVBDWDEGXWBJPFTBFEALLVFFREQSGIONNYQFBFNKENZKSWLEWGEJJPZLRPV"
|
|
||||||
"RLDHLELHFXXIEXDJOSAUGITKSWYCPMEBLWOLAEJXXARMXQCBEFKLOOIYRBYVWLNZKNCA"
|
|
||||||
"ISOZEWVWPUDRGLYYKWWTNCWPZLYYDBKARCATEJHLYYQFNYATGYJIUNMVLEGUYBJVEVVM"
|
|
||||||
"WBVJYQEGPZUOJYLWNEMODVPHTWTLURFETDHELDHPGEQWLRKZRFCEORRGYSBIJHPVNSNZ"
|
|
||||||
"CAVXFCESMJIXGJPGLKDREKYGBPQSACESXAAHVQYFBSYWDPHDNTOZTEGSCISTBUMLDOQP"
|
|
||||||
"WNQCSJUAENKYFCYIYENHTIAARBRTOCYDVMHPCPRGWQVDIFLHWMZWRGCWQTAIKCAJAMLG"
|
|
||||||
"OKGURQTGNNUSCBKTPUXIGKDUWUGMTLCAOTKMXVTAEYWNWBTIQMLVDIEVBAGJMCWMMGZI"
|
|
||||||
"USESSUIHYSYOXHFLNZVTCVATIUVWGDETJUEHTVQBJDGHIIDFYHTFDIDPLNGXLIBMKAYG"
|
|
||||||
"DOZLOFKQXVWSQPRYUKAMGEICLKOMYNLWEMKLWDOPEEZGTXVDQWMULORFGNLKNVVCGQXQ"
|
|
||||||
"CUIYKIAMJSJVQJKRBNBIEELCZLMPQILCEBLZZTKCPBOQLTMZRGTNWHPIUYWMBCNGIABH"
|
|
||||||
"WIAILEDQVNWKJGYWMZYWOZGRHQOUFGCAETYUTLYZBCHKANZYPXTLMVREDIWBPAISSWKP"
|
|
||||||
"IJIBRLWPFXQOLOFIXLUGDVMXNPJWBMMZYJUKUZPPTGVCRIMITUTPYLJOIDQGOMYUFSJB"
|
|
||||||
"MRAZFVZSFZUSNJYDWBUDMFTFDBRCZCZZERWZSOXVAZISSEOMPKHESJRLUMZBBLBIXPZR"
|
|
||||||
"UYRFMLZQMMZWMNXULVXZQPOUKPMXISKOPTEDXASVPAIENMUWMBNGIVWVOQQXKGYEAMAT"
|
|
||||||
"YLDPYAASJSACUYILVJBXLHEMYKRKXEIVCDWKPQUBHACBNBGVTQLFDFPLAGUWUPBNBSIT"
|
|
||||||
"UEENOTZFWDWNNYZTHJIBDYMCERWQNSDKDDUPPXPJTGDYQTFNSRQZZSZBYGSQHRRGSVAQ"
|
|
||||||
"QEICLCSLMWQYXGGJEPJWZXKJUCFHJRACHRHLCRQWKXSUFJNBOMGWAIBKNWUDBJTFWVBW"
|
|
||||||
"UPIUAKBMXXDVVKBEUAEHMOELYCJVEFJEDFBTITDNTEGRAIOACOHFCVERCTRMUZHPRNPQ"
|
|
||||||
"YCFDKGTRGWFEJAXVTTBMIAYLJZEJAAEOBCTIXHYNDWPXIWOVGXSOLTXIBPBLHYKHIDGX"
|
|
||||||
"HHXNVRCMUXBZGFIEDZDBZOKSMKRNYTWJGJBIMQIOZQRFROWMLNYPDDKTRESDVHHJNRMN"
|
|
||||||
"GASH";
|
|
||||||
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
const char *s = "Hello, world!";
|
|
||||||
return strlen(s);
|
|
||||||
}
|
|
||||||
12
runlevel/CMakeLists.txt
Normal file
12
runlevel/CMakeLists.txt
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
file(GLOB runlevels *.runlevel)
|
||||||
|
foreach (f ${runlevels})
|
||||||
|
get_filename_component(name ${f} NAME_WLE)
|
||||||
|
bsp_add_file(
|
||||||
|
ID runlevel-${name}
|
||||||
|
SRC_PATH ${f}
|
||||||
|
DEST_DIR /etc/herdd/runlevels)
|
||||||
|
sysroot_add_file(
|
||||||
|
ID runlevel-${name}
|
||||||
|
SRC_PATH ${f}
|
||||||
|
DEST_DIR /etc/herdd/runlevels)
|
||||||
|
endforeach (f)
|
||||||
3
runlevel/minimal.runlevel
Normal file
3
runlevel/minimal.runlevel
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[Runlevel]
|
||||||
|
Description=Minimal
|
||||||
|
Requires=nsd
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user