Giter Site home page Giter Site logo

uefi-musl's Introduction

Musl libc for UEFI

Introduction

This project is a an alpha version of a libc for UEFI.

The aim of this project is to have a small libc with the most important features, such as file management and memory management. It's not designed to be very powerful nor optimised. This library doesn't provide any driver (for storage for example), it simply uses (U)EFI protocols.

Compiling this project

To compile this project, you need EDK II, follow the instructions given on their official documentation page which can be find here: https://github.com/tianocore/tianocore.github.io/wiki/Getting-Started-with-EDK-II

Launching the example

The file main.c contains a simple example of how to use the musl libc. You simply need to include the headers files required, as you would do in a regular Linux C program, and call the functions a regular libc.

After compiling this program, rename the generated MuslLibC.efi to BOOTX64.EFI and put it on a FAT16 or FAT32 USB key in:

/EFI/BOOT/BOOTX64.EFI

How the port was made

Low level functions in the musl libc uses the assembly syscall instruction to tell the Linux kernel to do an operation.

To do so, we can find MACROS __syscallN(...) (where 0 ≤ N ≤ 7) defined in the file src/internal/syscall.h. Those MACROS will be replaced by a assembly routine call called __syscall defined in src/internal/x86_64/syscall.s.

Thereby, to port this library, we only need to replace the call of assembly syscall instruction (contained in __syscall subroutine) by another function call that will reproduce the behaviour of this instruction depending on the registers value. That's why our port provides the C function UefiSyscall(...) in Syscall/syscall.c. The arguments of this function are respectively the values of registers: rax, rdi, rsi, rdx, r10, r8, r9. The first argument, rax, determines the operation to reproduce. The whole Linux x64 syscall table can be found here: http://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/

The source folder Syscall contains code that will reproduce the syscalls. For example, the file Syscall/File.c implements syscalls related to file management, such as open, close, read, write, etc... (Check header file to see the exhaustive list)

How to continue implementing syscalls

To add syscall implementation, you only need to create a new .c and .h file in the Syscall folder, write your code. Add a call to your function inside the UefiSyscall() matching its id (rax value). Then add your file to the build configuration file, MuslLibC.inf, and that's it !

Why this method of porting ?

Reimplementing syscalls lets us modify the least possible the original library, so updating it won't be a difficult task. Moreover, it will also simplify the portage of any other Linux library, as they also use syscalls for low-level functions call.

What has been done

Memory and file management has been done on this project which means that you can use the following syscalls (not exhaustive):

Memory management

  • mmap
  • munmap
  • brk
  • malloc (not a syscall but depends on brk)

File management

  • read
  • write
  • open
  • close
  • stat
  • fstat
  • writev
  • readv
  • dup
  • dup2
  • lseek
  • rename
  • unlink
  • ftruncate
  • truncate
  • creat
  • pread64
  • pwrite64

Functions in stdlib are also functionnal as they don't depend on an syscall. Functions in stdio that works (not exhaustive):

  • sprintf
  • printf
  • fprintf
  • putchar
  • puts
  • fopen
  • fclose
  • fwrite
  • fread
  • fgets
  • fflush

Known issues

Setting or reading errno can provoke a Segmentation Fault on real hardware (in UEFI, it will freeze the computer).

However, in Qemu with OVMF, this problem doesn't exist. A workaround consists in overriding the definition of errno for our syscalls implementations. In that case, errno is a simple MACRO dereferencing an empty space in the memory (see Syscall/File.h). By default, the workaround is used for compiling. Adding the building MACRO -D QEMU in MuslLibC.inf lets us switch back to the original libc errno implementation.

IMPORTANT NOTE:

  • For the moment, this library is ONLY compatible with x86_64 architecture (it contains assembly code)

  • This library also provides a function that MUST be called before exiting the program: LibExit() This function will free the memory allocated by the library itself but also flush and close the opened file descriptors

uefi-musl's People

Contributors

o-marshmallow avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.