195 Commits

Author SHA1 Message Date
Justin C. Miller
2be70976ca Merge branch 'real-hardware' into fb-driver 2021-01-18 13:38:51 -08:00
Justin C. Miller
699fc57e0a [boot] Log address of new table pages
Since it's often needed when debugging between the bootloader and
kernel, log the address of the table pages the bootloader allocated.
2021-01-18 13:36:05 -08:00
Justin C. Miller
f3bb2e5259 [boot] Save commented-out mem map dumping code
This is often needed, so I'm commiting it commented out.
2021-01-18 13:35:01 -08:00
Justin C. Miller
34120fc4c1 [cpu] Split cpuid validation into separate lib
In order to allow the bootloader to do preliminary CPUID validation
while UEFI is still handling displaying information to the user, split
most of the kernel's CPUID handling into a library to be used by both
kernel and boot.
2021-01-18 13:26:45 -08:00
Justin C. Miller
e52fd8eacf [libc] Attempt to speed up memcpy for aligned mem
Copy long-by-long instead of byte-by-byte if both pointers are similarly
aligned.
2021-01-17 20:54:38 -08:00
Justin C. Miller
a97073848c [fb] Use double-buffering in fb driver
Allocate and use a back buffer, so that draws to the screen are always a
single memcpy()
2021-01-17 20:53:41 -08:00
Justin C. Miller
03b2d0dac7 [kernel] Set framebuffer to write-combining
Several changes were needed to make this work:

- Update the page_table::flags to understand memory caching types
- Set up the PAT MSR to add the WC option
- Make page-offset area mapped as WT
- Add all the MTRR and PAT MSRs, and log the MTRRs for verification
- Add a vm_area flag for write_combining
2021-01-17 20:49:47 -08:00
Justin C. Miller
cfeeba4400 [kenrel] Ensure page tables are zeroed before use
I forgot to zero out pages used for page tables, which didn't come back
to bite me until testing on physical hardware..
2021-01-17 10:35:19 -08:00
Justin C. Miller
45b52633bb [boot] Add scanline size to fb boot message
Scanline size can differ from horizontal resolution in some
framebuffers. This isn't currently handled, but at least log it so
it's visible if this lack of handling is a potential error.
2021-01-17 10:28:54 -08:00
Justin C. Miller
b9af081a44 [boot] Don't use custom UEFI memory types
The UEFI spec specifically calls out memory types with the high bit set
as being available for OS loaders' custom use. However, it seems many
UEFI firmware implementations don't handle this well. (Virtualbox, and
the firmware on my Intel NUC and Dell XPS laptop to name a few.)

So sadly since we can't rely on this feature of UEFI in all cases, we
can't use it at all. Instead, treat _all_ memory tagged as EfiLoaderData
as possibly containing data that's been passed to the OS by the
bootloader and don't free it yet.

This will need to be followed up with a change that copies anything we
need to save and frees this memory.

See: https://github.com/kiznit/rainbow-os/blob/master/boot/machine/efi/README.md
2021-01-17 10:26:24 -08:00
Justin C. Miller
d75b9c22d4 [boot] Don't use custom UEFI memory types
The UEFI spec specifically calls out memory types with the high bit set
as being available for OS loaders' custom use. However, it seems many
UEFI firmware implementations don't handle this well. (Virtualbox, and
the firmware on my Intel NUC and Dell XPS laptop to name a few.)

So sadly since we can't rely on this feature of UEFI in all cases, we
can't use it at all. Instead, treat _all_ memory tagged as EfiLoaderData
as possibly containing data that's been passed to the OS by the
bootloader and don't free it yet.

This will need to be followed up with a change that copies anything we
need to save and frees this memory.

See: https://github.com/kiznit/rainbow-os/blob/master/boot/machine/efi/README.md
2021-01-08 22:40:30 -08:00
Justin C. Miller
e20c53f193 [boot] Add framebuffer progress bar
After exiting UEFI, the bootloader had no way of displaying status to
the user. Now it will display a series of small boxes as a progress bar
along the bottom of the screen if a framebuffer exists. Errors or
warnings during a step will cause that step's box to turn red or orange,
and display bars above it to signal the error code.

This caused the simplification of the error handling system (which was
mostly just calling status_line::fail) and added different types of
status objects.
2021-01-08 22:25:37 -08:00
Justin C. Miller
6d4a32b6e8 [boot] List the detected framebuffer in boot log
List information about the detected framebuffer device (or lack thereof)
in the bootloader log messages.
2021-01-06 23:29:31 -08:00
Justin C. Miller
63a5c2da00 Merge branch 'fb-driver' of github.com:justinian/jsix into fb-driver 2021-01-06 23:26:26 -08:00
Justin C. Miller
bdcd0c2fda [kernel] Clean up process::exit
Make process::exit slightly more resilient to being called again.
2021-01-06 23:25:48 -08:00
Justin C. Miller
1be929b9d5 [fb] Simplify scrollback line counting
Using a start and a count was redundant when we know how many lines are
in the buffer already.
2021-01-06 23:20:29 -08:00
Justin C. Miller
d11dd0c3f9 [kernel] Fix memory clobbering from endpoint
The endpoint receive syscalls can block and then write to userspace
memory. Since the current address space may be different after blocking,
make sure to only actually write to the user memory after returning to
the syscall handler - pass values that are on the syscall handler stack
deeper into the kernel.
2021-01-06 23:16:16 -08:00
Justin C. Miller
e08e00790f [kernel] Give processes and threads self handles
It was not consistent how processes got handles to themselves or their
threads, ending up with double entries. Now make such handles automatic
and expose them with new self_handle() methods.
2021-01-06 23:14:39 -08:00
Justin C. Miller
8b3356e9d8 [kutil] Remove uint64_t hash_node specialization
Using a hash of zero to signal an empty slot doesn't play nice with the
hash_node specialization that uses the key for the hash, when 0 is a
common key.

I thought it would be ok, that it'd just be something to remember. But
then I used 0 as a key anyway, so clearly it was a bad idea.
2021-01-06 23:09:50 -08:00
Justin C. Miller
cd30126f17 [boot] Reduce loader spam
Now that the ELF loader is known to be working correctly, remove its
extra print statements about section loading to keep the bootloader
output to one screen.
2021-01-06 11:34:34 -08:00
Justin C. Miller
2c444dccd6 [build] Remove fake terminal.elf
A fake terminal.elf (copy of nulldrv.elf) was added to test the loader.
Now that there actually are multiple programs to load, remove the fake
one.
2021-01-06 11:32:45 -08:00
Justin C. Miller
bd490c4c7b [scripts] Ignore demangle errors building sym table
For some reason, cxxfilt fails to demangle some names on some systems.
Instead of failing the build process, just skip those symbols.
2021-01-06 11:30:40 -08:00
Justin C. Miller
3a67e461de [scripts] Allow qemu.sh to not remove VGA device
Added --vga option to qemu.sh to stop it from passing "-vga none" to
qemu. This allows the console version to act like it has a video device.
2021-01-04 01:00:03 -08:00
Justin C. Miller
972ef39295 [fb] Output klog to fb if video exists
If there's no video, do as we did before, otherwise route logs to the fb
driver instead. (Need to clean this up to just have a log consumer
general interface?) Also added a "scrollback" class to fb driver and
updated the system_get_log syscall.
2021-01-03 18:13:41 -08:00
Justin C. Miller
4c41205e73 [fb] Change to embedding PSF file
Moved old PSF parsing code from kernel, and switched to embedding whole
PSF instead of just glyph data to make font class the same code paths
for both cases.
2021-01-03 00:08:20 -08:00
Justin C. Miller
f6b4a4a103 [fb] Add default hard-coded font
For the fb driver to have a font before loading from disk is available,
create a hard-coded font as a byte array.

To create this, added a new scripts/psf_to_cpp.py which also refactored
out much of scripts/parse_font.py into a new shared module
scripts/fontpsf.py.
2021-01-02 15:52:26 -08:00
327cd93c04 [kernel] Fix vm_space extra deletion
vm_space::clear() was freeing pages on process exit even when free was
false, and potentially double-freeing some pages.
2020-12-31 00:59:48 -08:00
0e6b27e741 [kernel] Improve process init
Move process init from each process needing a main.s with _start to
crt0.s in libc. Also change to a sysv-like initial stack with a
j6-specific array of initialization values after the program arguments.
2020-12-31 00:57:51 -08:00
db8a14720b [kernel] Rename kernel entrypoint
The kernel entrypoint being named _start conflicts with userspace
program entrypoints and makes debugging more difficult. Rename it to
_kernel_start.
2020-12-30 17:56:37 -08:00
87a7293ac1 [tools] Improve j6stack GDB command
Improve the j6stack command in two ways: first, swap the order of the
arguments, as depth is much more likely to be changed. Second, on any
exception accessing memory in the stack, print the exception and
continue instead of failing the whole command.
2020-12-30 17:49:27 -08:00
5787aff866 [fb] Create fb driver
Create a new framebuffer driver. Also hackily passing frame buffer size
in the list of init handles to all processes and mapping the framebuffer
into all processes. Changed bootloader passing frame buffer as a module
to its own struct.
2020-12-27 18:49:38 -08:00
7bdde2d359 [kernel] Fix console line endings
The console's putc() was looking for CRs and if it saw one, appending an
LF. The output was only writing LFs, though, so instead what's needed is
to look for LFs, and if it sees one, insert a CR first.
2020-12-23 12:36:43 -08:00
2e3d7b1656 [kernel] Minor cleanups that have been sitting
Removal of an unused header and fixing a lint warning that a define
could be unset.
2020-11-10 01:17:58 -08:00
bf600a7608 [kutil] Add djb hash as 32 bit constexpr hash
This didn't end up getting used, but I'm adding it for later use.
2020-11-10 01:15:37 -08:00
6b00805d04 [kutil] Make vector size type templateable
Previously kutil::vector used size_t as its size type. Since most uses
in the kernel will never approach 4 billion items, default the size type
to uint32_t but make it an optional template argument. This saves 8
bytes per vector, which can be non-trivial with lots of vectors.
2020-10-18 20:50:31 -07:00
82b7082fc5 [kernel] Make koid generation per-type
Previously koids were a single global counter tagged with the type in
the top bits. Now there are per-type counters that each increment
separately.
2020-10-18 20:48:09 -07:00
8bb9e22218 [kernel] Move bind_irq syscall to new system object
In order to implement capabilities on system resources like IRQs so that
they may be restricted to drivers only, add a new 'system' kobject type,
and move the bind_irq functionality from endpoint to system.

Also fix some stack bugs passing the initial handles to a program.
2020-10-18 20:45:06 -07:00
2ad90dcb5c [kernel] Remove old unused crti/crtn
These were never used because clang generates .ctors and .dtors instead
of .init and .fini
2020-10-07 20:18:49 -07:00
97ea77bd27 [kernel] Consolodate koid and close syscalls
A number of object types had _close or _koid syscalls. Moved those to be
generic for kobject.
2020-10-05 21:51:42 -07:00
1904e240cf [kernel] Let endpoints get interrupt notifications
- Add a tag field to all endpoint messages, which doubles as a
  notification field
- Add a endpoint_bind_irq syscall to enable an endpoint to listen for
  interrupt notifications. This mechanism needs to change.
- Add a temporary copy of the serial port code to nulldrv, and let it
  take responsibility for COM2
2020-10-05 01:06:49 -07:00
4ccaa2dfea [boot] Load programs in boot, not kernel
Remove ELF and initrd loading from the kernel. The bootloader now loads
the initial programs, as it does with the kernel. Other files that were
in the initrd are now on the ESP, and non-program files are just passed
as modules.
2020-10-04 17:11:03 -07:00
da38006f44 [kernel] Remove obsolete 'mappings' list from VMAs
The vm_area_shared type of VMA used to track mappings in a separate
array, which doubled information and wasted space. This was no longer
used, and is now removed.
2020-09-27 21:47:35 -07:00
87b0a93d32 [kernel] Have thread call scheduler on blocking
Instead of making every callsite that may make a thread do a blocking
operation also invoke the scheduler, move that logic into thread
implementation - if the thread is blocking and is the current thread,
call schedule().

Related changes in this commit:

- Also make exiting threads and processes call the scheduler when
  blocking.
- Threads start blocked, and get automatically added to the scheduler's
  blocked list.
2020-09-27 21:35:15 -07:00
ff78c951f0 [libc] Implement sbrk to allow malloc() to work
Userspace can now allocte via malloc. This is slightly janky because it
relies on a single static handle in the library code.
2020-09-27 17:31:23 -07:00
2d44e8112b [kernel] Remove 'allowed' page table flag
The allowed flag was janky and easy to get lost when doing page table
manipulation. All allocation goes throug vm_area now, so 'allowed' can
be dropped.
2020-09-27 16:06:25 -07:00
f7f8bb3f45 [kernel] Replace buffer_cache with vm_area_buffers
In order to reduce the amount of tracked state, now use the
vm_area_buffers instead of a VMA with buffer_cache on top.
2020-09-27 15:34:24 -07:00
67ebc58812 [kernel] Allow for more than three syscall args
The rcx register is used by the function call ABI for the 4th argument,
but is also clobbered by SYSCALL to hold the IP. The r10 register is
caller-saved but not part of the ABI, so stash rcx there when crossing
the syscall boundary.
2020-09-26 22:01:21 -07:00
13aee1755e [kernel] Spit out vm_area types
The vm_space allow() functionality was a bit janky; using VMAs for all
regions would be a lot cleaner. To that end, this change:

- Adds a "static array" ctor to kutil::vector for setting the kernel
  address space's VMA list. This way a kernel heap VMA can be created
  without the heap already existing.
- Splits vm_area into different subclasses depending on desired behavior
- Splits out the concept of vm_mapper which maps vm_areas to vm_spaces,
  so that some kinds of VMA can be inherently single-space
- Implements VMA resizing so that userspace can grow allocations.
- Obsolete page_table_indices is removed

Also, the following bugs were fixed:

- kutil::map iterators on empty maps no longer break
- memory::page_count was doing page-align, not page-count

See: Github bug #242
See: [frobozz blog post](https://jsix.dev/posts/frobozz/)

Tags:
2020-09-26 21:47:15 -07:00
0e0975e5f6 [kernel] Add VMA interface
Finished the VMA kobject and added the related syscalls. Processes can
now allocate memory! Other changes in this commit:

- stop using g_frame_allocator and add frame_allocator::get()
- make sure to release all handles in the process dtor
- fix kutil::map::iterator never comparing to end()
2020-09-23 00:29:05 -07:00
d4283731e4 [kernel] Add syscall helpers
Added the syscalls/helpers.h file to templatize common kobject syscall
operations. Also moved most syscall implementations to using
process::current() and thread::current() instead of asking the
scheduler.
2020-09-23 00:22:15 -07:00
6780ab1b67 [abi] Add j6_err_exists
This error was used by code that didn't end up getting used, but it's a
useful error to keep around.
2020-09-23 00:18:06 -07:00
41eac2764a [kernel] Fix threads and procs never deleting
A check was added in scheduler::prune() which defers deleting threads
and processes if they're the current ones. However, they were still
getting removed from the block list, so they were being leaked.
2020-09-23 00:15:23 -07:00
113d14c440 [kernel] Get rid of page_manager
page_manager is dead - final uses replaced in vm_space (page_in and
clear). Removed the header and cpp, and other lingering references.
2020-09-20 16:16:23 -07:00
abe523be77 [kernel] Remove page_manager::map_pages
The last use of page_manager::map_pages was during loading of ELF
binaries. Switched to vm_space::allow instead.
2020-09-20 14:06:06 -07:00
1b392a0551 [kernel] Move page mapping into vm_space
vm_space no longer relies on page_manager to map pages during a page
fault. Other changes that come with this commit:

- C++ standard has been changed to C++17
- enum bitfield operators became constexpr
- enum bifrield operators can take a mix of ints and enum arguments
- added page table flags enum instead of relying on ints
- remove page_table::unmap_table and page_table::unmap_pages
2020-09-20 10:52:57 -07:00
deb2fa0a09 [kernel] Use kernel proc space as kernel space
As mentioned in the last commit, with processes owning spaces, there was
a weird extra space in the "kernel" process that owns the kernel
threads. Now we use that space as the global kernel space, and don't
create a separate one.
2020-09-18 01:58:46 -07:00
671a0ce0fb [kernel] Move pml4 create/delete into vm_space
vm_space and page_table continue to take over duties from
page_manager:

- creation and deletion of address spaces / pml4s
- cross-address-space copies for endpoints
- taking over pml4 ownership from process

Also fixed the bug where the wrong process was being set in the cpu
data.

To solve: now the kernel process has its own vm_space which is not
g_kernel_space.
2020-09-18 01:22:49 -07:00
ac67111b83 [kernel] Move the page table cache into page_table
Further chipping away at page_manager: the cache of pages to be used as
page tables gets moved to a static in page_table.
2020-09-17 21:30:05 -07:00
09575370ce [kernel] Remove unecessary functions from page manager
In preparation for removing more from page manager, removed several
unecessary functions and all their callsites.
2020-09-17 01:33:10 -07:00
9aa08a70cf [kernel] Begin replacing page_manager with vm_space
This is the first commit of several reworking the VM system. The main
focus is replacing page_manager's global functionality with objects
representing individual VM spaces. The main changes in this commit were:

- Adding the (as yet unused) vm_area object, which will be the main
  point of control for programs to allocate or share memory.
- Replace the old vm_space with a new one based on state in its page
  tables. They will also be containers for vm_areas.
- vm_space takes over from page_manager as the page fault handler
- Commented out the page walking in memory_bootstrap; I'll probably need
  to recreate this functionality, but it was broken as it was.
- Split out the page_table.h implementations from page_manager.cpp into
  the new page_table.cpp, updated it, and added page_table::iterator as
  well.
2020-09-17 00:48:17 -07:00
ca7f78565d [tools] Add the j6bt command to gdb functions
Added the command j6bt (and renamed popc_stack to j6stack) to make
tracking kernel callstacks across interrupts easier.
2020-09-16 23:58:28 -07:00
dcb4d1823f [kutil] Update map iteration
Add an iterator type to kutil::map, and allow for each loops. Also
unify the compare() signature expected by sorting containers, and fixes
to adding and sorting in kutil::vector.
2020-09-15 00:21:28 -07:00
e8564c755b [kernel] Move vm_space into kernel
The vm_space code should not have been in kutil, moving it to kernel.
2020-09-13 16:11:24 -07:00
9dee5e4138 [kernel] Use map for process handles
Replace linearly-indexed vector of handles with new kutil::map. Also
provide thread::current() and process::current() accessors so that every
syscall doesn't need to include the scheduler to deduce the current
process.
2020-09-13 15:54:47 -07:00
245f260d67 [kutil] Allow for specialization in kutil::map
Restructure kutil::map to allow specialization to alter storage as well
as the public API.
2020-09-13 15:53:28 -07:00
5f27727e52 [tests] Upgrade Catch2 to version 2.13.1 2020-09-13 02:19:57 -07:00
1238608430 [kutil] Add kutil::map hash map
Added the kutil::map collection, an open addressing, robinhood hash map
with backwards shift deletes. Also added hash.h with templated
implementations of the FNV-1a 64 bit hash function, and pulled the log2
function out of the heap_allocator code into the new util.h.
2020-09-12 00:31:38 -07:00
71cd7af17b [kutil] Add sorted insert to kutil::vector
Added a sorted insert to vector, as well as cleaning up and extending
the removal functions.
2020-09-07 16:59:21 -07:00
8490472581 [kutil] Fix failing heap allocator tests
The tests clearly haven't even been built in a while. I've added a
helper script to the project root. Also added a kassert() handler that
will allow tests to catch or fail on asserts.
2020-09-07 16:56:07 -07:00
8534d8d3c5 [kernel] Add endpoint object and related syscalls
The endpoint object adds synchronous IPC. Also added the wait-type of
'object' to threads.
2020-09-07 01:09:56 -07:00
53d260cc6e [kernel] Allow unmapping non-fully-mapped areas
The buffer cache will try to clean up a returned buffer by unmapping it,
but it may have only been committed without ever getting mapped. Allow
for page_out to handle non-fully mapped regions.
2020-09-06 16:31:02 -07:00
53a4682418 [kernel] Fix current thread deletion bug
Defer from calling process::thread_exited() in scheduler::prune() if the
thread in question is the currently-executing thread, so that we don't
blow away the stack we're executing on. The next call to prune will pick
up the exited thread.
2020-09-06 15:01:24 -07:00
42455873ff [kernel] Make stdout channel available to processes
The "fake" stdout channel is now being passed in the new j6_process_init
structure to processes, and nulldrv now uses it to print a message to
the console.
2020-08-30 18:47:14 -07:00
724b846ee4 [kernel] Make channels stream based
Multiple changes regarding channels. Mainly channels are now stream
based and can handle partial reads or writes. Channels now use the
kernel buffers area with the related buffer_cache. Added a fake stdout
stream channel and kernel task to read its contents to the screen in
preparation for handing channels as stdin/stdout to processes.
2020-08-30 18:04:19 -07:00
f27b133089 [kernel] Rename stack_cache to buffer_cache
Renamed and genericized the stack_cache class to manage any address
range area of buffers or memory regions. Removed singleton and created
some globals that map to different address regions (kernel stacks,
kernel buffers).

Tags: vmem virtual memeory
2020-08-30 17:59:13 -07:00
773617cbf3 [libc] Created syscall trampolines in libc
Using syscalls.inc (moved to src/include) generate trampoline functions
for directly calling syscalls with libc functions.
2020-08-23 18:14:45 -07:00
44e29b3c4a [build] Fix dump_cc_run not creating bash scripts
It was the difference between > and >>
2020-08-23 17:43:18 -07:00
95a35cd0bf [libc] Bring libc in-tree
Moving libc from its separate repo into this one, minor resulting build
fixes, and a hacky way to add -I for libc headers in builds.
2020-08-23 17:21:08 -07:00
28b800a497 [kernel] Initialize logger task after symbols init
In case something blows up when initializing kernel tasks, make sure
symbol table init is done beforehand.
2020-08-23 17:18:45 -07:00
838776d7df [kernel] Fix bug in vmem commit
When committing an area of vmem and splitting from a larger block, the
block that is returned was set to the unknown state, and the leading
block was incorrectly set to the desired state.

Also remove extra unused thread ctor.
2020-08-23 17:11:46 -07:00
e19fa377d7 [kernel] Remove old unused process.*
These files are not included in the build, but had not been removed.
2020-08-23 17:10:14 -07:00
d63a30728c [kernel] Add get_caller function
Added a function to get the callsite of the current function invocation.
2020-08-22 16:34:58 -07:00
4819920b4e [kutil] Add unreserve/uncommit to vm_space
Added the functionality for unreseve and uncommit to vm_space. Also
added the documented but not implemented ability to pass a 0 address to
get any address region with the given size.
2020-08-16 17:19:17 -07:00
bbb9aae198 [kernel] Use symbol table in stack traces
Now using the symbol table built by build_symbol_table.py in the kernel
when printing stack traces.
2020-08-09 17:27:51 -07:00
0d94776c46 [build] Remove makest from build script
Removing the outdated reference to makest from the build scripts, which
should have been removed as part of the build_symbol_table.py change.
2020-08-09 17:23:14 -07:00
565a5ee960 [makerd] Fix argc bug
Makerd was improperly checking argc for its usage.
2020-08-06 21:12:36 -07:00
e7f9d8f1d7 [scripts] Add symbol table building script
Create a script that builds a simple-to-read symbol table from the
output of `nm`. Include running that script over the kernel in the
build, and including that output in the initrd.

Tags: callstack debugging
2020-08-06 21:11:19 -07:00
55bc49598e [kernel] Assert all PDs exist in kernel space
The bootloader now creates all PD tables in kernel space, so remove
memory_bootstrap.cpp code that dealt with cases where there was no PD
for a given range, and kassert that all PDs exist.

Also deal with the case where the final PD exists, which never committed
the last address range.
2020-08-06 19:07:51 -07:00
579eaaf4a0 [kernel] Move kernel stacks out of the heap
We were previously allocating kernel stacks as large objects on the
heap. Now keep track of areas of the kernel stack area that are in use,
and allocate them from there. Also required actually implementing
vm_space::commit(). This still needs more work.
2020-08-02 18:15:28 -07:00
b98334db28 [kernel] Don't keep creating new processes for kernel tasks
The scheduler was making new process objects every time it made kernel
task threads. Don't do that.
2020-08-02 18:13:09 -07:00
e1b1b5d357 [kernel] Don't double-construct the scheduler
The scheduler singleton was getting constructed twice, once at static
time and then again in main(). Make the singleton a pointer so we only
construct it once.
2020-08-02 18:11:09 -07:00
cf582c4ce4 [boot] Add PD tables for all kernel PML4 entries
Process PML4s all point their high (kernelspace) entries at the same set
of PDs, but that copying only happens on process creation. New PDs added
to the kernel PML4 won't get shared among other PML4s. This change
instantiates empty PDs for all PML4 entries in the higher half to make
sure this can't happen.
2020-08-02 18:06:41 -07:00
911b4c0b10 [kutil] Fix a bug with order ignoring header size
When moving heap allocation order calculation to use __builtin_clz, we
based that calculation off of the length requested, not the totla length
including the memory header size.
2020-08-02 16:54:06 -07:00
94c1f0d3fc [kutil] Calculate block-size order with clz
Previously we were using a less efficient loop method of finding the
appropriate block size order, now we use __builtin_clz, which should use
the CPU's clz instruction if it's available.
2020-07-30 19:54:25 -07:00
73221dfe34 [kutil] Rename 'size' to 'order' when meaning 2^N
Heap allocator is a buddy allocator that deals with power-of-two block
sizes. Previously it referred to both a number of bytes and an order of
magnitude as a 'size'. Rename functions and variables referring to
orders of magnitude to 'order'.

Tags: pedantry
2020-07-30 19:41:41 -07:00
4ffd4949ca [kernel] Clean up threads' kernel stacks on exit
Add a destructor to threads in order to deallocate their kernel stacks.
2020-07-30 19:32:31 -07:00
3f137805bc [kutil] Tracks allocated size in heap allocator
Add a member that keeps track of allocated size to the heap allocator.
This isn't exposed, but is handy for debugging.
2020-07-30 19:30:53 -07:00
6a00057817 [kernel] Remove process startup_bonus to timeslice
Previously we added startup_bonus to work around a segfault happening
when we preemted a newly created process instead of letting it give up
the CPU. Bug is not longer occuring, though that makes me nervous.
2020-07-30 19:11:51 -07:00
58bc5acb1e [kernel] Add object_signal system call
Add a system call to assert signals on a given object, only within the
range of user-settable signals. Also made object_wait return
immediately if any of the given signals are already set.
2020-07-26 18:03:30 -07:00
d3e9d92466 [kernel] Add channel objects
Add the channel object for sending messages between threads. Currently
no good of passing channels to other threads, but global variables in a
single process work. Currently channels are slow and do double copies,
need to refine more.

Tags: ipc
2020-07-26 17:29:11 -07:00
ae3290c53d [kernel] Add userspace threading
Implement the syscalls necessary for threads to create other threads in
their same process. This involved rearranging a number of syscalls, as
well as implementing object_wait and a basic implementation of a
process' list of handles.
2020-07-26 16:02:38 -07:00
4cf222a5bb [kernel] Remove getpid and fork system calls
The getpid and fork system calls were stubbed out previously, this
commit removes them and adds process_koid as a getpid replacement.
2020-07-19 17:15:36 -07:00
c3abe035c8 [kernel] Remove thread_data pointer from TCB
The TCB is always stored at a constant offset within the thread object.
So instead of carrying an extra pointer, just implement thread::from_tcb
to get the thread.
2020-07-19 17:01:15 -07:00
ef5c333030 [kernel] Create process kernel object
Re-implent the concept of processes as separate from threads, and as a
kobject API object. Also improve scheduler::prune which was doing some
unnecessary iterations.
2020-07-19 16:47:18 -07:00
f4cbb9498f [kernel] Fix clock period vs frequency error
Calling `spinwait()` was hanging due to improper computation of the
clock rate because justin did a dumb at math. Also the period can be
greater than 1ns, so the clock's units were updated to microseconds.
2020-07-12 17:43:37 -07:00
794c86f9b4 [kernel] Add thead kobject class
Add the thread kernel API object and move the scheduler to use threads
instead of processes for scheduling and task switching.
2020-07-12 16:07:20 -07:00
Justin C. Miller
8687fe3786 [boot] Zero extra memory in loaded sections
When loading ELF headers (as opposed to sections), the `file_size` of
the data may be smaller than the `mem_size` of the section to be loaded
in memory. Don't blindly copy `mem_size` bytes from the ELF file, but
instead only `file_size`, then zero the rest.

Tags: elf loader
2020-07-04 18:20:49 -07:00
Justin C. Miller
0a28d2db07 [kernel] Update scheduler policies
A few updates to scheduler policies:
* Grant processes a startup timeslice bonus for time spent loading the
  process
* Grant processes a small fraction of a timeslice for yielding the CPU
  with time left
2020-07-03 15:21:03 -07:00
Justin C. Miller
6c468a134b [kernel] Add HPET support, create clock class
Create a clock class which can be queried for current timestamp in
nanoseconds. Also implements a simple HPET class as one possible clock
source.

Tags: time
2020-06-28 17:49:31 -07:00
Justin C. Miller
9b67f87062 [kernel] Add external/ to kernel includes
In order to support future changes, the kernel should also be able to
include from the external/ tree.
2020-06-28 11:51:51 -07:00
Justin C. Miller
b4adc29d7f [kernel] Give scheduler better history tracking
The scheduler again tracks remaining timeslice. Timeslices are bigger,
but once a process uses all of its timeslice, it's demoted and
replenished at the next priority. The scheduler also tracks the last
time a process ran, and promotes it if it's been starved for twice its
full timeslice.

TODO: replenish a small amount of timeslice each time a process is run,
so that more interactive processes keep their priorities.
2020-06-05 00:15:03 -07:00
Justin C. Miller
a10aca573d [kernel] Change to one-shot timer scheduler
Instead of many timer interrupts and decrementing a process' remaining
quanta, change to setting a single timer for when a process should be
preempted. If it uses its whole timeslice, demote it. If it uses less
than half before blocking, promote it. Determine timeslice based on
priority as well.

This change also required changing the apic timer interface to be purely
interval (in microseconds) based instead of its previous interval/tick
hybrid.
2020-06-03 20:56:59 -07:00
Justin C. Miller
ea1224e213 [kernel] Fix scheduler clock bug
The fake clock in the scheduler wasn't getting initialized, so sleeps in
the test userspace programs were returning immediately.
2020-06-02 23:46:03 -07:00
Justin C. Miller
64ad65fa1b [kernel] Fix logger task's bip buffer
The bip buffer implementation was not initializing it's write-state
member, which was causing logs to always fail when the logger was not in
immediate mode.
2020-06-02 20:30:07 -07:00
Justin C. Miller
b881b2639d [kernel] Remove last of old allocator interface
Removing the `allocator.h` file defining the `kutil::allocator`
interface, now that explicit allocators are not being passed around.
Also removed the unused `frame_allocator::raw_allocator` class and
`kutil::invalid_allocator` object.

Tags: memory
2020-06-01 23:40:19 -07:00
Justin C. Miller
a5f72edf82 [kernel] Add in_hv cpu "feature" flag
Reformat the cpu_features.inc file and add the `in_hv` feature that is
supposedly set by hypervisors when running in emulation. QEMU does not
set it.

Tags: cpuid
2020-06-01 23:33:30 -07:00
Justin C. Miller
ea2a3e6f16 [kutil] Remove ctor workaround in slab_allocated
Before global constructors were working, I had added a hack to zero out
the static vector member of in `slab_allocated`. Now that they are
working, this can be removed.
2020-06-01 00:36:34 -07:00
Justin C. Miller
2125f043b6 [kernel] Remove global constructor test class
Removing a test class that wasn't meant to be checked in.
2020-06-01 00:34:37 -07:00
Justin C. Miller
655b5c88d4 [kernel] Remove obsolete 1MiB offset
Back when the bootloader could only mirror higher half memory linearly
to the lower half, the kernel couldn't be loaded at the beginning of
kernel space because it was unlikely to find enough pages there, so it
was loaded at +1MiB in kernel space. Now the bootloader can map any
pages to the necessary locations, the offset can be removed.

Tags: elf linker virtual memory
2020-06-01 00:01:07 -07:00
Justin C. Miller
88b090fe94 [kernel] Run global constructors
Look up the global constructor list that the linker outputs, and run
them all. Required creation of the `kutil::no_construct` template for
objects that are constructed before the global constructors are run.

Also split the `memory_initialize` function into two - one for just
those objects that need to happen before the global ctors, and one
after.

Tags: memory c++
2020-05-31 23:58:01 -07:00
Justin C. Miller
c6c3a556b3 [kernel] Remove explicit allocator passing
Many kernel objects had to keep a hold of refrences to allocators in
order to pass them on down the call chain. Remove those explicit
refrences and use `operator new`, `operator delete`, and define new
`kalloc` and `kfree`.

Also remove `slab_allocator` and replace it with a new mixin for slab
allocation, `slab_allocated`, that overrides `operator new` and
`operator free` for its subclass.

Remove some no longer used related headers, `buddy_allocator.h` and
`address_manager.h`

Tags: memory
2020-05-31 18:22:23 -07:00
Justin C. Miller
67b5f33d46 [general] Remove the last bits of gnu-efi
With the new bootloader changes that use clang to directly build an EFI
application, the last piece of GNU-EFI that was used (the linker script)
is no longer necessary.

Thanks for being a great starting point, GNU-EFI!
2020-05-29 00:24:24 -07:00
Justin C. Miller
b675dfd014 [boot] Fix header include path for uefi headers
After the previous commit, the header path was different. This updates
the build scripts to point to the right location.
2020-05-29 00:21:42 -07:00
Justin C. Miller
fc2b884af9 [build] Copy uefi headers into project
Eventually the UEFI headers should be brought in from their own project,
but for now, like the other projects under external/, these are being
copied into this repository.

Tags: boot uefi
2020-05-25 02:40:51 -07:00
Justin C. Miller
cbd19fa070 [kernel] Don't use deferred logging for now
The last bug getting back to par with master - looks like there might be
threading issues with the logger task at the moment. Turning it off for
now.

Tags: log bug todo
2020-05-24 22:11:54 -07:00
Justin C. Miller
83b330bf2b [kernel] Use constants for known pml4e indices
There were a few lingering bugs due to places where 510/511 were
hard-coded as the kernel-space PML4 entries. These are now constants
defined in kernel_memory.h instead.

Tags: boot memory paging
2020-05-24 22:06:24 -07:00
Justin C. Miller
cc9cde9bfe [tooling] Remove old GDB workarounds
GDB works far better now with QEMU's `-S` flag. No longer does it
complain about changing the target from 32 to 64 bits. Get rid of the
old `waiting` loop and `sleep` call in the GDB config for the kernel.

Tags: debugging
2020-05-24 19:50:45 -07:00
Justin C. Miller
774f6fc334 [kutil] Don't use delete on non-new pointers
`kutil::vector` was calling `operator delete []` on memory that had not
been allocated with `operator new []`, and so was deleting the wrong
pointer.

Tags: bug memory allocator
2020-05-24 19:48:03 -07:00
Justin C. Miller
bfd13e7a9b [kernel] Re-enable most of kernel_main
The `kernel_main()` had a lot change out from under it with the
bootloader changes. This change brings most of it back in line with the
new kernel arguments.

Tags: pml4 paging boot
2020-05-24 17:58:45 -07:00
Justin C. Miller
35b1d37df0 [memory] Rework memory_initialize for new loader
Created a new `memory_initialize()` function that uses the new-style
kernel args structure from the new bootloader.

Additionally:
* Fixed a hard-coded interrupt EOI address that didn't work with new
  memory locations
* Make the `page_manager::fault_handler()` automatically grant pages
  in the kernel heap

Tags: boot page fault
2020-05-24 16:43:36 -07:00
Justin C. Miller
fc3d919f25 [kernel] Fix initial kernel_main triple-fault
At some point, `init_console()` ended up not being before the first
usage of some `log::` functions, which were jumping off into garbage.

Tags: initialization boot
2020-05-23 12:40:47 -07:00
Justin C. Miller
75641a4394 [boot] Add explicit memory map pointer to args
The bootloader was previously just passing the memory map as a module,
but the memory map is important enough to want a direct pointer, instead
of having to search the modules.
2020-05-23 12:39:24 -07:00
Justin C. Miller
ce0bcbd3b6 [boot] Set up CR4 in bootloader
Moving the initial CR4 settings from the kernel's `memory_initialize`
(where it doesn't really fit anyway) to the bootloader's `hardware.cpp`.
2020-05-23 12:35:59 -07:00
Justin C. Miller
3194b460cc [memory] Update kernel_memory to current layout
The `kernel_offset` and `page_offset` had already been updated with
previous bootloader changes, but `kernel_max_heap` had not. Also, make
all the constants `constexpr` instead of `static const` that would live
in multiple TUs.
2020-05-23 12:33:28 -07:00
Justin C. Miller
e1d148a34d [boot] Fix a bug with address-index translation
When `page_entry_iterator` became a template and changed its static shifts
translating virtual address to table indices into a for loop, that loop
was getting the indices backwards (ie, PML4E index was really the PTE
index, and so on).

Tags: paging
2020-05-22 00:32:04 -07:00
Justin C. Miller
b491a09686 [boot] Virtualize memory in the bootloader
Finish updating the page tables, call UEFI's `set_virtual_address_map`
and jump to the kernel!
2020-05-21 23:49:49 -07:00
Justin C. Miller
6a538ad4f3 [boot] Fix several errors getting to kernel
* When using the non-allocating version of `get_uefi_mappings` the
  length was not getting set. Reworked this function.
* Having `build_kernel_mem_map` from `bootloader_main_uefi` caused it to
  get an out of date map key. Moved this function into `efi_main` right
  before exiting boot services.
2020-05-21 23:00:32 -07:00
Justin C. Miller
6ccc172f33 [boot] Centralize where to hlt on error
Searching for `hlt` in disassembly is an easy way to find the error
handler. This change centralizes it to just one, to better match
disassembly with code.
2020-05-21 22:41:33 -07:00
Justin C. Miller
66ca3a3f9b [boot] Consolidate mapping code into iterator obj
The page table code had been copied mostly verbatim from the kernel, and
was a dense mess. I abstraced the `page_table_indices` class and the old
loop behavior of `map_in` into a new `page_entry_iterator` class, making
both `map_pages` and the initial offset mapping code much cleaner.

Tags: vmem paging
2020-05-20 01:02:15 -07:00
Justin C. Miller
4f4a35a7be [boot] Set up initial page tables
Set up initial page tables for both the offset-mapped area and the
loaded kernel code and data.

* Got rid of the `loaded_elf` struct - the loader now runs after the
  initial PML4 is created and maps the ELF sections itself.
* Copied in the `page_table` and `page_table_indices` from the kernel,
  still need to clean this up and extract it into shared code.
* Added `page_table_cache` to the kernel args to pass along free pages
  that can be used for initial page tables.

Tags: paging
2020-05-17 22:03:44 -07:00
Justin C. Miller
c9722a07f3 [boot] Provide memset implementation
Clang needs memset, memcpy, etc to exist even in freestanding situations
because it will emit calls to those functions. This commit adds a simple
weak-linked memset implementation.
2020-05-17 22:00:50 -07:00
Justin C. Miller
42dfa6ccfe [boot] Only allocate memory map once
The `build_kernel_mem_map` function now calls `get_uefi_mappings`
itself, instead of having the efi map passed in. `get_uefi_mappings`
also now takes a `bool allocate` to direct it to actually allocate
the map or not. If it doesn't, it instead just returns the size of
the map and the metadata - which `build_kernel_mem_map`	uses to decide
how much space to first allocate for the kernel's map.
2020-05-16 18:48:28 -07:00
Justin C. Miller
2adef874ee [boot] Make sure the kernel entrypoint abi is sysv
Adding this now because I'm sure I'll forget later. Make sure to
annotate the entrypoint function pointer as `__attribute__((sysv_abi))`
so that it's not called via ms abi like the rest of the loader.
2020-05-16 18:44:35 -07:00
Justin C. Miller
a6e4995963 [boot] Fix call to exit_boot_services
Exiting boot services can't actually be done from inside
`bootloader_uefi_main`, because there are objects in that scope that run
code requiring boot services in their destructors.

Also added `support.cpp` with `memcpy` because clang will emit
references to `memcpy` even in freestanding mode.

Added a `debug_break` function to allow for faking breakpoints when
connecting to the bootloader with GDB.

Tags: debug
2020-05-13 02:08:47 -07:00
Justin C. Miller
2bd91c2d94 [boot] Split get_uefi_mappings and module creation
The `get_mappings()` function was getting too large, and some of its
output is needed by more than just the building of the kernel map. Split
it out into two.

Tags: boot memory
2020-05-10 16:43:18 -07:00
Justin C. Miller
c713f4ff6f [boot] Build the kernel mem map from the UEFI one
Created kernel args memory map structure, looping through UEFI's memory
map to copy and condense.

Tags: boot memory
2020-05-10 16:26:17 -07:00
Justin C. Miller
21b0b08908 [general] Add a git commit template
I've been pretty lax with my commit messages despite attempts to
standardize them. Trying out setting a template. This template can be
applied with:

`git config commit.template .git-commit-template`

See: [another template](https://github.com/joelparkerhenderson/git_commit_template)
See: [another template](https://gist.github.com/adeekshith/cd4c95a064977cdc6c50)

Tags: git
2020-05-10 11:19:33 -07:00
Justin C. Miller
88ace0a99f Fix a bug in print_long_hex()
Because of order of shifting operations and a literal that defaulted
to int, the high 32 bits were printed incorrectly.
2020-05-10 02:31:53 -07:00
Justin C. Miller
10c8f6e4b5 Clean and document header files.
- Add missing doc comments to header files
- Move allocate_kernel_args to main.cpp
- Split functions out into pointer_manipulation.h
2020-05-10 01:42:22 -07:00
Justin C. Miller
9aa749e877 Parse ELF and load kernel, specify mem types
* Very bare-bones ELF parsing to load the kernel
* Custom memory type values for allocated memory
2020-05-09 21:25:45 -07:00
Justin C. Miller
f78a99927a [boot] Add initial stubs for loading kernel ELF 2020-05-02 23:58:41 -07:00
Justin C. Miller
ec794f4f99 Move module loading in main into helper function 2020-03-02 19:43:44 -08:00
Justin C. Miller
884182217c Fix file loading size bug 2020-03-02 19:31:40 -08:00
Justin C. Miller
d94907ae79 Loading files 2020-02-25 22:22:12 -08:00
Justin C. Miller
4accfd136e Add file functionality in fs.cpp 2020-02-24 02:19:15 -08:00
Justin C. Miller
1a223d6ef5 Move args structure allocation to a function in memory.cpp 2020-02-24 02:18:14 -08:00
Justin C. Miller
36b3ad8154 Add an optional context string for status line messges 2020-02-24 02:15:45 -08:00
Justin C. Miller
460973954e Remove utility.* 2020-02-23 18:32:10 -08:00
Justin C. Miller
303a78065e Move find_acpi_table to new hardware.cpp 2020-02-23 18:28:20 -08:00
Justin C. Miller
93f0b70eba Move to RAII-style status_line objects for console status 2020-02-23 17:55:53 -08:00
Justin C. Miller
6f5a2a3d3f Update kernel args to be module-based
- The old kernel_args structure is now mostly represented as a series of
  'modules' or memory ranges, tagged with a type. An arbitrary number
  can be passed to the kernel
- Update bootloader to allocate space for the args header and 10 module
  descriptors
2020-02-23 00:07:50 -08:00
Justin C. Miller
ec563ea8e4 Allow multiple calls to console::status_* functions 2020-02-22 17:52:51 -08:00
Justin C. Miller
570638bba6 Don't require system_table in console 2020-02-22 15:47:07 -08:00
Justin C. Miller
f627ea7de0 Re-add functionality to boot with new UEFI headers
- Pointer fixup event
- ACPI searching
- Move CHECK_* to using try_or_raise()
2020-02-22 14:57:28 -08:00
Justin C. Miller
521c132801 Back to a basic UEFI stub 2020-02-22 01:54:00 -08:00
Justin C. Miller
bc5115b9ea Removed old UEFI headers 2020-02-22 01:52:49 -08:00
Justin C. Miller
6963304c01 Changing jsix license
jsix is now licensed under the MPL2.
2019-10-06 01:37:46 -07:00
Justin C. Miller
ae651a4fcd Move cpptoml.h to external directory 2019-10-06 00:46:30 -07:00
Justin C. Miller
17c2fe6e4e Add debig-exit device to qemu.sh for future tests 2019-10-06 00:29:10 -07:00
Justin C. Miller
f066ac3ffd Move catch.hpp to external directory 2019-10-06 00:01:27 -07:00
Justin C. Miller
edcf633e84 Remove cargo-culted znocombreloc ld flag 2019-08-10 13:49:57 -07:00
Justin C. Miller
d09a454b8b Normalize bootloader's con_debug line endings 2019-07-21 22:29:19 -07:00
Justin C. Miller
d6329ea9bf Update to bonnibel 2.1 2019-07-21 21:10:43 -07:00
Justin C. Miller
83897048ab Update for bonnibel 2.0 2019-07-20 23:19:21 -07:00
Justin C. Miller
7cc59770b8 Update libc for new sysall values via peru 2019-07-07 10:07:00 -07:00
Justin C. Miller
b056d95920 Organize system calls
* syscalls should all return j6_status_t now
* syscalls are grouped by category in name as well as in files
2019-07-07 09:54:29 -07:00
Justin C. Miller
19cd01ef8d Add initial pass of syscall API kobjects 2019-07-07 09:54:29 -07:00
Justin C. Miller
b3f88bbe02 Further refine sysroot.
* remove need for NASM from sysroot
* have peru sync libc separately
2019-07-07 09:52:06 -07:00
Justin C. Miller
f57f38edbd Remove old ident_page_flags 2019-07-05 20:52:04 -07:00
Justin C. Miller
12377ae730 Ignore .peru 2019-07-05 17:29:56 -07:00
Justin C. Miller
bb93dcef44 Remove sysroot binutils dependency
* Link host-targeted binaries with lld
 * Add peru script for getting prebuilt sysroot
 * Add readme for prebuilt sysroots
 * Remove non-working build_sysroot_gcc.sh, rename clang version to just
   build_sysroot.sh
2019-07-05 17:26:24 -07:00
Justin C. Miller
678a12dc90 Ignore .gdb_history 2019-07-04 17:43:42 -07:00
Justin C. Miller
c3dacb2906 Fix mis-flagged page table entries 2019-07-04 17:43:08 -07:00
Justin C. Miller
3a68ec439d Add CPU feature checking.
Introduces the cpu_features.inc table to enumerate the CPU features that
j6 cares about. Features in this table marked CPU_FEATURE_REQ are
considered required, and the boot process will log an error and halt
when any of these features are not supported. This should save me from
banging my head against the wall like I did last night with the missing
pdpe1gb feature.
2019-07-04 16:41:25 -07:00
Justin C. Miller
7ce418aabc Fix KVM page faults from lack of 1GB page support 2019-07-04 02:51:50 -07:00
Justin C. Miller
8ee5091f41 update gitignore 2019-07-03 21:55:23 -07:00
Justin C. Miller
6285517ef7 Rename Popcorn to jsix.
See README.md for more information.
2019-05-27 14:07:29 -07:00
Justin C. Miller
2b0cd6f2f2 Make qemu.sh work with i3 as well 2019-05-26 10:35:22 -07:00
Justin C. Miller
a653c55941 Use 0 instead of syscall_invalid in syscall jump list 2019-05-18 18:11:08 -07:00
Justin C. Miller
ce035d2a43 Finish address_manager to vm_space transition 2019-05-18 18:06:57 -07:00
Justin C. Miller
2d54eb5143 Add vmem log area 2019-05-11 11:32:22 -07:00
Justin C. Miller
b9c8edb657 Allow clang to colorize output in ninja 2019-04-18 00:28:23 -07:00
Justin C. Miller
88315c25a5 Allow vm_space to merge ranges 2019-04-18 00:22:01 -07:00
Justin C. Miller
806bfd1fbf First pass at vm_space (address_manager replacement) 2019-04-17 19:16:54 -07:00
Justin C. Miller
910b5116f4 Fix stack overruns 2019-04-16 23:39:52 -07:00
475 changed files with 39003 additions and 20257 deletions

11
.git-commit-template Normal file
View File

@@ -0,0 +1,11 @@
[section] Imperative-voiced title in less than 50
# Body describes what was done, and why. New obviously-needed features
# don't necessarily require a why.
# Links to relevant bugs or web pages
See: Github bug #242
See: [frobozz blog post](https://jsix.dev/posts/frobozz/)
# Tags and keywords useful for searching
Tags:

4
.gitignore vendored
View File

@@ -2,7 +2,9 @@
/build* /build*
*.bak *.bak
tags tags
popcorn.log jsix.log
*.o *.o
*.a *.a
sysroot sysroot
.gdb_history
.peru

View File

@@ -1,150 +1,354 @@
# Popcorn # License
Popcorn itself is released under the terms of the MIT license: jsix is (c) 2017-2019 Justin C Miller, and distributed under the terms of the
Mozilla Public License 2.0.
> Copyright © 2018 Justin C. Miller, https://devjustinian.com ---
> <justin@devjustinian.com>
>
> Permission is hereby granted, free of charge, to any person obtaining a copy
> of this software and associated documentation files (the “Software”), to deal
> in the Software without restriction, including without limitation the rights
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> copies of the Software, and to permit persons to whom the Software is
> furnished to do so, subject to the following conditions:
>
> The above copyright notice and this permission notice shall be included in
> all copies or substantial portions of the Software.
>
> THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> SOFTWARE.
# Included works ## Mozilla Public License Version 2.0
Popcorn includes and/or is derived from a number of other works, listed here. ### 1. Definitions
## Catch2 #### 1.1. "Contributor"
Popcorn uses [Catch2](https://github.com/catchorg/Catch2) for testing. Catch2 is means each individual or legal entity that creates, contributes to the creation
released under the terms of the Boost Software license: of, or owns Covered Software.
> Boost Software License - Version 1.0 - August 17th, 2003 #### 1.2. "Contributor Version"
>
> Permission is hereby granted, free of charge, to any person or organization
> obtaining a copy of the software and accompanying documentation covered by
> this license (the "Software") to use, reproduce, display, distribute,
> execute, and transmit the Software, and to prepare derivative works of the
> Software, and to permit third-parties to whom the Software is furnished to
> do so, all subject to the following:
>
> The copyright notices in the Software and this entire statement, including
> the above license grant, this restriction and the following disclaimer,
> must be included in all copies of the Software, in whole or in part, and
> all derivative works of the Software, unless such copies or derivative
> works are solely in the form of machine-executable object code generated by
> a source language processor.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
> SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
> FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
> ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> DEALINGS IN THE SOFTWARE.
## cpptoml means the combination of the Contributions of others (if any) used by a
Contributor and that particular Contributor's Contribution.
Popcorn uses the [cpptoml](https://github.com/skystrife/cpptoml) library for #### 1.3. "Contribution
parsing TOML configuration files. cpptoml is released under the terms of the
MIT license:
> Copyright (c) 2014 Chase Geigle means Covered Software of a particular Contributor.
>
> Permission is hereby granted, free of charge, to any person obtaining a copy of
> this software and associated documentation files (the "Software"), to deal in
> the Software without restriction, including without limitation the rights to
> use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
> the Software, and to permit persons to whom the Software is furnished to do so,
> subject to the following conditions:
>
> The above copyright notice and this permission notice shall be included in all
> copies or substantial portions of the Software.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
> FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
> COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
> IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
> CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
## printf #### 1.4. "Covered Software"
Popcorn uses 's tiny [printf](https://github.com/mpaland/printf) library for its means Source Code Form to which the initial Contributor has attached the notice
`*printf()` functions, which is also released under the terms of the MIT license: in Exhibit A, the Executable Form of such Source Code Form, and Modifications
of such Source Code Form, in each case including portions thereof.
> The MIT License (MIT) #### 1.5. "Incompatible With Secondary Licenses"
>
> Copyright (c) 2014 Marco Paland
>
> Permission is hereby granted, free of charge, to any person obtaining a copy
> of this software and associated documentation files (the "Software"), to deal
> in the Software without restriction, including without limitation the rights
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> copies of the Software, and to permit persons to whom the Software is
> furnished to do so, subject to the following conditions:
>
> The above copyright notice and this permission notice shall be included in all
> copies or substantial portions of the Software.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> SOFTWARE.
## GNU-EFI means
Popcorn's UEFI bootloader initially used * **(a)** that the initial Contributor has attached the notice described in
[GNU-EFI](https://gnu-efi.sourceforge.net), and still uses one file (the linker Exhibit B to the Covered Software; or
script for the bootloader) from that project. GNU-EFI claims to be released * **(b)** that the Covered Software was made available under the terms of
under the BSD license. Again, I could not find its specific license file, so I version 1.1 or earlier of the License, but not also under the terms of a
am reproducing a generic 3-clause BSD license (the most restrictive, so as not Secondary License.
to assume any extra rights that may not actually be granted) for it here:
> Copyright © Nigel Croxon #### 1.6. "Executable Form"
>
> Redistribution and use in source and binary forms, with or without
> modification, are permitted provided that the following conditions are met:
>
> 1. Redistributions of source code must retain the above copyright notice, this
> list of conditions and the following disclaimer.
>
> 2. Redistributions in binary form must reproduce the above copyright notice,
> this list of conditions and the following disclaimer in the documentation
> and/or other materials provided with the distribution.
>
> 3. Neither the name of the copyright holder nor the names of its contributors
> may be used to endorse or promote products derived from this software
> without specific prior written permission.
>
> THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
> ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
> WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
> DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
> FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
> SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
> CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
> OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
## Intel EFI Application Toolkit means any form of the work other than Source Code Form.
#### 1.7. "Larger Work"
means a work that combines Covered Software with other material, in a separate
file or files, that is not Covered Software.
#### 1.8. "License"
means this document.
#### 1.9. "Licensable"
means having the right to grant, to the maximum extent possible, whether at the
time of the initial grant or subsequently, any and all of the rights conveyed
by this License.
#### 1.10. "Modifications"
means any of the following:
* **(a)** any file in Source Code Form that results from an addition to,
deletion from, or modification of the contents of Covered Software; or
* **(b)** any new file in Source Code Form that contains any Covered Software.
#### 1.11. "Patent Claims" of a Contributor
means any patent claim(s), including without limitation, method, process, and
apparatus claims, in any patent Licensable by such Contributor that would be
infringed, but for the grant of the License, by the making, using, selling,
offering for sale, having made, import, or transfer of either its Contributions
or its Contributor Version.
#### 1.12. "Secondary License"
means either the GNU General Public License, Version 2.0, the GNU Lesser
General Public License, Version 2.1, the GNU Affero General Public License,
Version 3.0, or any later versions of those licenses.
#### 1.13. "Source Code Form"
means the form of the work preferred for making modifications.
#### 1.14. "You" (or "Your")
means an individual or a legal entity exercising rights under this License. For
legal entities, "You" includes any entity that controls, is controlled by, or
is under common control with You. For purposes of this definition, "control"
means **(a)** the power, direct or indirect, to cause the direction or
management of such entity, whether by contract or otherwise, or **(b)**
ownership of more than fifty percent (50%) of the outstanding shares or
beneficial ownership of such entity.
### 2. License Grants and Conditions
#### 2.1. Grants
Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive
license:
* **(a)** under intellectual property rights (other than patent or trademark)
Licensable by such Contributor to use, reproduce, make available, modify,
display, perform, distribute, and otherwise exploit its Contributions, either
on an unmodified basis, with Modifications, or as part of a Larger Work; and
* **(b)** under Patent Claims of such Contributor to make, use, sell, offer for
sale, have made, import, and otherwise transfer either its Contributions or
its Contributor Version.
#### 2.2. Effective Date
The licenses granted in Section 2.1 with respect to any Contribution become
effective for each Contribution on the date the Contributor first distributes
such Contribution.
#### 2.3. Limitations on Grant Scope
The licenses granted in this Section 2 are the only rights granted under this
License. No additional rights or licenses will be implied from the distribution
or licensing of Covered Software under this License. Notwithstanding Section
2.1(b) above, no patent license is granted by a Contributor:
* **(a)** for any code that a Contributor has removed from Covered Software; or
* **(b)** for infringements caused by: **(i)** Your and any other third party's
modifications of Covered Software, or **(ii)** the combination of its
Contributions with other software (except as part of its Contributor
Version); or
* **(c)** under Patent Claims infringed by Covered Software in the absence of
its Contributions.
This License does not grant any rights in the trademarks, service marks, or
logos of any Contributor (except as may be necessary to comply with the notice
requirements in Section 3.4).
#### 2.4. Subsequent Licenses
No Contributor makes additional grants as a result of Your choice to distribute
the Covered Software under a subsequent version of this License (see Section
10.2) or under the terms of a Secondary License (if permitted under the terms
of Section 3.3).
#### 2.5. Representation
Each Contributor represents that the Contributor believes its Contributions are
its original creation(s) or it has sufficient rights to grant the rights to its
Contributions conveyed by this License.
#### 2.6. Fair Use
This License is not intended to limit any rights You have under applicable
copyright doctrines of fair use, fair dealing, or other equivalents.
#### 2.7. Conditions
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
Section 2.1.
### 3. Responsibilities
#### 3.1. Distribution of Source Form
All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under the
terms of this License. You must inform recipients that the Source Code Form of
the Covered Software is governed by the terms of this License, and how they can
obtain a copy of this License. You may not attempt to alter or restrict the
recipients' rights in the Source Code Form.
#### 3.2. Distribution of Executable Form
If You distribute Covered Software in Executable Form then:
* **(a)** such Covered Software must also be made available in Source Code
Form, as described in Section 3.1, and You must inform recipients of the
Executable Form how they can obtain a copy of such Source Code Form by
reasonable means in a timely manner, at a charge no more than the cost of
distribution to the recipient; and
* **(b)** You may distribute such Executable Form under the terms of this
License, or sublicense it under different terms, provided that the license
for the Executable Form does not attempt to limit or alter the recipients'
rights in the Source Code Form under this License.
#### 3.3. Distribution of a Larger Work
You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for the
Covered Software. If the Larger Work is a combination of Covered Software with
a work governed by one or more Secondary Licenses, and the Covered Software is
not Incompatible With Secondary Licenses, this License permits You to
additionally distribute such Covered Software under the terms of such Secondary
License(s), so that the recipient of the Larger Work may, at their option,
further distribute the Covered Software under the terms of either this License
or such Secondary License(s).
#### 3.4. Notices
You may not remove or alter the substance of any license notices (including
copyright notices, patent notices, disclaimers of warranty, or limitations of
liability) contained within the Source Code Form of the Covered Software,
except that You may alter any license notices to the extent required to remedy
known factual inaccuracies.
#### 3.5. Application of Additional Terms
You may choose to offer, and to charge a fee for, warranty, support, indemnity
or liability obligations to one or more recipients of Covered Software.
However, You may do so only on Your own behalf, and not on behalf of any
Contributor. You must make it absolutely clear that any such warranty, support,
indemnity, or liability obligation is offered by You alone, and You hereby
agree to indemnify every Contributor for any liability incurred by such
Contributor as a result of warranty, support, indemnity or liability terms You
offer. You may include additional disclaimers of warranty and limitations of
liability specific to any jurisdiction.
### 4. Inability to Comply Due to Statute or Regulation
If it is impossible for You to comply with any of the terms of this License
with respect to some or all of the Covered Software due to statute, judicial
order, or regulation then You must: **(a)** comply with the terms of this
License to the maximum extent possible; and **(b)** describe the limitations
and the code they affect. Such description must be placed in a text file
included with all distributions of the Covered Software under this License.
Except to the extent prohibited by statute or regulation, such description must
be sufficiently detailed for a recipient of ordinary skill to be able to
understand it.
### 5. Termination
**5.1.** The rights granted under this License will terminate automatically if
You fail to comply with any of its terms. However, if You become compliant,
then the rights granted under this License from a particular Contributor are
reinstated **(a)** provisionally, unless and until such Contributor explicitly
and finally terminates Your grants, and **(b)** on an ongoing basis, if such
Contributor fails to notify You of the non-compliance by some reasonable means
prior to 60 days after You have come back into compliance. Moreover, Your
grants from a particular Contributor are reinstated on an ongoing basis if such
Contributor notifies You of the non-compliance by some reasonable means, this
is the first time You have received notice of non-compliance with this License
from such Contributor, and You become compliant prior to 30 days after Your
receipt of the notice.
**5.2.** If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions, counter-claims, and
cross-claims) alleging that a Contributor Version directly or indirectly
infringes any patent, then the rights granted to You by any and all
Contributors for the Covered Software under Section 2.1 of this License shall
terminate.
**5.3.** In the event of termination under Sections 5.1 or 5.2 above, all end
user license agreements (excluding distributors and resellers) which have been
validly granted by You or Your distributors under this License prior to
termination shall survive termination.
### 6. Disclaimer of Warranty
> Covered Software is provided under this License on an "as is" basis, without
> warranty of any kind, either expressed, implied, or statutory, including,
> without limitation, warranties that the Covered Software is free of defects,
> merchantable, fit for a particular purpose or non-infringing. The entire risk
> as to the quality and performance of the Covered Software is with You.
> Should any Covered Software prove defective in any respect, You (not any
> Contributor) assume the cost of any necessary servicing, repair, or
> correction. This disclaimer of warranty constitutes an essential part of this
> License. No use of any Covered Software is authorized under this License
> except under this disclaimer.
### 7. Limitation of Liability
> Under no circumstances and under no legal theory, whether tort (including
> negligence), contract, or otherwise, shall any Contributor, or anyone who
> distributes Covered Software as permitted above, be liable to You for any
> direct, indirect, special, incidental, or consequential damages of any
> character including, without limitation, damages for lost profits, loss of
> goodwill, work stoppage, computer failure or malfunction, or any and all
> other commercial damages or losses, even if such party shall have been
> informed of the possibility of such damages. This limitation of liability
> shall not apply to liability for death or personal injury resulting from such
> party's negligence to the extent applicable law prohibits such limitation.
> Some jurisdictions do not allow the exclusion or limitation of incidental or
> consequential damages, so this exclusion and limitation may not apply to You.
### 8. Litigation
Any litigation relating to this License may be brought only in the courts of a
jurisdiction where the defendant maintains its principal place of business and
such litigation shall be governed by laws of that jurisdiction, without
reference to its conflict-of-law provisions. Nothing in this Section shall
prevent a party's ability to bring cross-claims or counter-claims.
### 9. Miscellaneous
This License represents the complete agreement concerning the subject matter
hereof. If any provision of this License is held to be unenforceable, such
provision shall be reformed only to the extent necessary to make it
enforceable. Any law or regulation which provides that the language of a
contract shall be construed against the drafter shall not be used to construe
this License against a Contributor.
### 10. Versions of the License
#### 10.1. New Versions
Mozilla Foundation is the license steward. Except as provided in Section 10.3,
no one other than the license steward has the right to modify or publish new
versions of this License. Each version will be given a distinguishing version
number.
#### 10.2. Effect of New Versions
You may distribute the Covered Software under the terms of the version of the
License under which You originally received the Covered Software, or under the
terms of any subsequent version published by the license steward.
#### 10.3. Modified Versions
If you create software not governed by this License, and you want to create a
new license for such software, you may create and use a modified version of
this License if you rename the license and remove any references to the name of
the license steward (except to note that such modified license differs from
this License).
#### 10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses
If You choose to distribute Source Code Form that is Incompatible With
Secondary Licenses under the terms of this version of the License, the notice
described in Exhibit B of this License must be attached.
### Exhibit A - Source Code Form License Notice
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this file,
You can obtain one at http://mozilla.org/MPL/2.0/.
If it is not possible or desirable to put the notice in a particular file, then
You may include the notice in a location (such as a LICENSE file in a relevant
directory) where a recipient would be likely to look for such a notice.
You may add additional accurate notices of copyright ownership.
### Exhibit B - "Incompatible With Secondary Licenses" Notice
This Source Code Form is "Incompatible With Secondary Licenses", as defined
by the Mozilla Public License, v. 2.0.
Popcorn's UEFI loader uses code from Intel's EFI Application toolkit. Relevant
code includes license statements at the top of each file.

View File

@@ -1,6 +1,6 @@
# popcorn: A toy OS kernel # jsix: A toy OS kernel
**popcorn** is the kernel for the hobby OS that I am currently building. It's **jsix** is the kernel for the hobby OS that I am currently building. It's
far from finished, or even being usable. Instead, it's a sandbox for me to play far from finished, or even being usable. Instead, it's a sandbox for me to play
with kernel-level code and explore architectures. with kernel-level code and explore architectures.
@@ -25,47 +25,54 @@ The design goals of the project are:
temporarily) in some places to allow me to play around with the related temporarily) in some places to allow me to play around with the related
hardware. hardware.
A note on the name: This kernel was originally named Popcorn, but I have since
discovered that the Popcorn Linux project is also developing a kernel with that
name, started around the same time as this project. So I've renamed this kernel
jsix (Always styled _jsix_ or `j6`, never capitalized) as an homage to L4, xv6,
and my wonderful wife.
## Building ## Building
Popcorn uses the [Ninja][] build tool, and generates the build files for it jsix uses the [Ninja][] build tool, and generates the build files for it with a
with a custom tool called [Bonnibel][]. Bonnibel requires [Python 3][] and can custom tool called [Bonnibel][]. Bonnibel can be installed with [Cargo][], or
be downloaded with `pip`: downloaded as a prebuilt binary from its Github repository.
```
pip3 install bonnibel
```
[Ninja]: https://ninja-build.org [Ninja]: https://ninja-build.org
[Bonnibel]: https://github.com/justinian/bonnibel [Bonnibel]: https://github.com/justinian/bonnibel
[Python 3]: https://python.org [Cargo]: https://crates.io/crates/bonnibel
Requrirements: Requrirements:
* python 3 (for installing and running Bonnibel) * bonnibel
* clang
* mtools
* ninja * ninja
* clang
* nasm
* mtools
* curl for downloading the toolchain * curl for downloading the toolchain
### Setting up the cross toolchain ### Setting up the cross toolchain
If you have `clang` and `curl` installed, runing the `scripts/build_sysroot_clang.sh` Running `pb sync` will download and unpack the toolchain into `sysroot`.
script will download and build a nasm/binutils/LLVM toolchain configured for building
Popcorn host binaries.
### Building and running Popcorn #### Compiling the toolchain yourself
Once the toolchain has been set up, running Bonnibel's `pb` command will set up the If you have `clang` and `curl` installed, runing the `scripts/build_sysroot.sh`
build configuration, and `ninja -C build` will actually run the build. If you script will download and build a LLVM toolchain configured for building jsix
have `qemu-system-x86_64` installed, the `qemu.sh` script will to run Popcorn host binaries.
### Building and running jsix
Once the toolchain has been set up, running Bonnibel's `pb init` command will
set up the build configuration, and `pb build` will actually run the build. If
you have `qemu-system-x86_64` installed, the `qemu.sh` script will to run jsix
in QEMU `-nographic` mode. in QEMU `-nographic` mode.
I personally run this either from a real debian amd64 testing/buster machine or I personally run this either from a real debian amd64 testing/buster machine or
a windows WSL debian testing/buster installation. The following should be a windows WSL debian testing/buster installation. The following should be
enough to set up such a system to build the kernel: enough to set up such a system to build the kernel:
sudo apt install qemu-system-x86 nasm clang-6.0 mtools python3-pip curl sudo apt install qemu-system-x86 nasm clang-6.0 mtools curl
sudo update-alternatives /usr/bin/clang clang /usr/bin/clang-6.0 1000 sudo update-alternatives /usr/bin/clang clang /usr/bin/clang-6.0 1000
sudo update-alternatives /usr/bin/clang++ clang++ /usr/bin/clang++-6.0 1000 sudo update-alternatives /usr/bin/clang++ clang++ /usr/bin/clang++-6.0 1000
sudo pip3 install bonnibel curl -L -o pb https://github.com/justinian/bonnibel/releases/download/2.0.0/pb_linux_amd64 && chmod a+x pb

View File

@@ -0,0 +1,63 @@
import gdb
class PrintStackCommand(gdb.Command):
def __init__(self):
super().__init__("j6stack", gdb.COMMAND_DATA)
def invoke(self, arg, from_tty):
args = gdb.string_to_argv(arg)
base = "$rsp"
if len(args) > 0:
base = args[0]
depth = 22
if len(args) > 1:
depth = int(args[1])
for i in range(depth-1, -1, -1):
try:
offset = i * 8
base_addr = gdb.parse_and_eval(base)
value = gdb.parse_and_eval(f"*(uint64_t*)({base} + {offset})")
print("{:016x} (+{:04x}): {:016x}".format(int(base_addr) + offset, offset, int(value)))
except Exception as e:
print(e)
continue
class PrintBacktraceCommand(gdb.Command):
def __init__(self):
super().__init__("j6bt", gdb.COMMAND_DATA)
def invoke(self, arg, from_tty):
args = gdb.string_to_argv(arg)
depth = 30
if len(args) > 0:
depth = int(args[0])
frame = "$rbp"
if len(args) > 1:
frame = args[1]
for i in range(depth-1, -1, -1):
ret = gdb.parse_and_eval(f"*(uint64_t*)({frame} + 8)")
frame = gdb.parse_and_eval(f"*(uint64_t*)({frame})")
name = ""
block = gdb.block_for_pc(int(ret))
if block:
name = block.function or ""
print("{:016x} {}".format(int(ret), name))
if frame == 0 or ret == 0:
return
PrintStackCommand()
PrintBacktraceCommand()
gdb.execute("target remote :1234")
gdb.execute("display/i $rip")

View File

@@ -1,31 +0,0 @@
import gdb
class PrintStackCommand(gdb.Command):
def __init__(self):
super().__init__("popc_stack", gdb.COMMAND_DATA)
def invoke(self, arg, from_tty):
args = gdb.string_to_argv(arg)
base = "$rsp"
if len(args) > 0:
base = args[0]
depth = 22
if len(args) > 1:
depth = int(args[1])
for i in range(depth-1, -1, -1):
offset = i * 8
base_addr = gdb.parse_and_eval(base)
value = gdb.parse_and_eval(f"*(uint64_t*)({base} + {offset})")
print("{:016x} (+{:04x}): {:016x}".format(int(base_addr) + offset, offset, int(value)))
PrintStackCommand()
import time
time.sleep(3.5)
gdb.execute("target remote :1234")
gdb.execute("set waiting = false")
gdb.execute("display/i $rip")

View File

@@ -12,6 +12,11 @@
dest = "screenfont.psf" dest = "screenfont.psf"
source = "../assets/fonts/tamsyn8x16r.psf" source = "../assets/fonts/tamsyn8x16r.psf"
[[files]]
dest = "symbol_table.dat"
source = "symbol_table.dat"
symbols = true
[[files]] [[files]]
dest = "nulldrv1" dest = "nulldrv1"
source = "user/nulldrv" source = "user/nulldrv"

File diff suppressed because it is too large Load Diff

101
external/uefi/boot_services.h vendored Normal file
View File

@@ -0,0 +1,101 @@
#pragma once
#ifndef _uefi_boot_services_h_
#define _uefi_boot_services_h_
// This Source Code Form is part of the j6-uefi-headers project and is subject
// to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was
// not distributed with this file, You can obtain one at
// http://mozilla.org/MPL/2.0/.
#include <stdint.h>
#include <uefi/tables.h>
#include <uefi/types.h>
namespace uefi {
namespace bs_impl {
using allocate_pages = status (*)(allocate_type, memory_type, size_t, void**);
using get_memory_map = status (*)(size_t*, memory_descriptor*, size_t*, size_t*, uint32_t*);
using allocate_pool = status (*)(memory_type, uint64_t, void**);
using handle_protocol = status (*)(handle, const guid*, void**);
using create_event = status (*)(evt, tpl, event_notify, void*, event*);
using exit_boot_services = status (*)(handle, size_t);
using locate_protocol = status (*)(const guid*, void*, void**);
using copy_mem = void (*)(void*, void*, size_t);
using set_mem = void (*)(void*, uint64_t, uint8_t);
}
struct boot_services {
static constexpr uint64_t signature = 0x56524553544f4f42ull;
table_header header;
// Task Priority Level management
void *raise_tpl;
void *restore_tpl;
// Memory Services
bs_impl::allocate_pages allocate_pages;
void *free_pages;
bs_impl::get_memory_map get_memory_map;
bs_impl::allocate_pool allocate_pool;
void *free_pool;
// Event & Timer Services
bs_impl::create_event create_event;
void *set_timer;
void *wait_for_event;
void *signal_event;
void *close_event;
void *check_event;
// Protocol Handler Services
void *install_protocol_interface;
void *reinstall_protocol_interface;
void *uninstall_protocol_interface;
bs_impl::handle_protocol handle_protocol;
void *_reserved;
void *register_protocol_notify;
void *locate_handle;
void *locate_device_path;
void *install_configuration_table;
// Image Services
void *load_image;
void *start_image;
void *exit;
void *unload_image;
bs_impl::exit_boot_services exit_boot_services;
// Miscellaneous Services
void *get_next_monotonic_count;
void *stall;
void *set_watchdog_timer;
// DriverSupport Services
void *connect_controller;
void *disconnect_controller;
// Open and Close Protocol Services
void *open_protocol;
void *close_protocol;
void *open_protocol_information;
// Library Services
void *protocols_per_handle;
void *locate_handle_buffer;
bs_impl::locate_protocol locate_protocol;
void *install_multiple_protocol_interfaces;
void *uninstall_multiple_protocol_interfaces;
// 32-bit CRC Services
void *calculate_crc32;
// Miscellaneous Services
bs_impl::copy_mem copy_mem;
bs_impl::set_mem set_mem;
void *create_event_ex;
};
} // namespace uefi
#endif

39
external/uefi/errors.inc vendored Normal file
View File

@@ -0,0 +1,39 @@
STATUS_WARNING( warn_unknown_glyph, 1)
STATUS_WARNING( warn_delete_failure, 2)
STATUS_WARNING( warn_write_failure, 3)
STATUS_WARNING( warn_buffer_too_small,4)
STATUS_WARNING( warn_stale_data, 5)
STATUS_WARNING( warn_file_system, 6)
STATUS_ERROR( load_error, 1)
STATUS_ERROR( invalid_parameter, 2)
STATUS_ERROR( unsupported, 3)
STATUS_ERROR( bad_buffer_size, 4)
STATUS_ERROR( buffer_too_small, 5)
STATUS_ERROR( not_ready, 6)
STATUS_ERROR( device_error, 7)
STATUS_ERROR( write_protected, 8)
STATUS_ERROR( out_of_resources, 9)
STATUS_ERROR( volume_corrupted, 10)
STATUS_ERROR( volume_full, 11)
STATUS_ERROR( no_media, 12)
STATUS_ERROR( media_changed, 13)
STATUS_ERROR( not_found, 14)
STATUS_ERROR( access_denied, 15)
STATUS_ERROR( no_response, 16)
STATUS_ERROR( no_mapping, 17)
STATUS_ERROR( timeout, 18)
STATUS_ERROR( not_started, 19)
STATUS_ERROR( already_started, 20)
STATUS_ERROR( aborted, 21)
STATUS_ERROR( icmp_error, 22)
STATUS_ERROR( tftp_error, 23)
STATUS_ERROR( protocol_error, 24)
STATUS_ERROR( incompatible_version, 25)
STATUS_ERROR( security_violation, 26)
STATUS_ERROR( crc_error, 27)
STATUS_ERROR( end_of_media, 28)
STATUS_ERROR( end_of_file, 31)
STATUS_ERROR( invalid_language, 32)
STATUS_ERROR( compromised_data, 33)
STATUS_ERROR( http_error, 35)

92
external/uefi/graphics.h vendored Normal file
View File

@@ -0,0 +1,92 @@
#pragma once
#ifndef _uefi_graphics_h_
#define _uefi_graphics_h_
// This Source Code Form is part of the j6-uefi-headers project and is subject
// to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was
// not distributed with this file, You can obtain one at
// http://mozilla.org/MPL/2.0/.
#include <stdint.h>
#include <uefi/types.h>
namespace uefi {
struct text_output_mode
{
int32_t max_mode;
int32_t mode;
int32_t attribute;
int32_t cursor_column;
int32_t cursor_row;
bool cursor_visible;
};
struct pixel_bitmask
{
uint32_t red_mask;
uint32_t green_mask;
uint32_t blue_mask;
uint32_t reserved_mask;
};
enum class pixel_format
{
rgb8,
bgr8,
bitmask,
blt_only
};
struct graphics_output_mode_info
{
uint32_t version;
uint32_t horizontal_resolution;
uint32_t vertical_resolution;
pixel_format pixel_format;
pixel_bitmask pixel_information;
uint32_t pixels_per_scanline;
};
struct graphics_output_mode
{
uint32_t max_mode;
uint32_t mode;
graphics_output_mode_info *info;
uint64_t size_of_info;
uintptr_t frame_buffer_base;
uint64_t frame_buffer_size;
};
enum class attribute : uint64_t
{
black,
blue,
green,
cyan,
red,
magenta,
brown,
light_gray,
dark_gray,
light_blue,
light_green,
light_cyan,
light_red,
light_magenta,
yellow,
white,
background_black = 0x00,
background_blue = 0x10,
background_green = 0x20,
background_cyan = 0x30,
background_red = 0x40,
background_magenta = 0x50,
background_brown = 0x60,
background_light_gray = 0x70,
};
} // namespace uefi
#endif

29
external/uefi/guid.h vendored Normal file
View File

@@ -0,0 +1,29 @@
#pragma once
#ifndef _uefi_guid_h_
#define _uefi_guid_h_
// This Source Code Form is part of the j6-uefi-headers project and is subject
// to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was
// not distributed with this file, You can obtain one at
// http://mozilla.org/MPL/2.0/.
#include <stdint.h>
namespace uefi {
struct guid
{
uint32_t data1;
uint16_t data2;
uint16_t data3;
uint8_t data4[8];
inline bool operator==(const guid &other) const {
return reinterpret_cast<const uint64_t*>(this)[0] == reinterpret_cast<const uint64_t*>(&other)[0]
&& reinterpret_cast<const uint64_t*>(this)[1] == reinterpret_cast<const uint64_t*>(&other)[1];
}
};
} // namespace uefi
#endif

30
external/uefi/protos/device_path.h vendored Normal file
View File

@@ -0,0 +1,30 @@
#pragma once
#ifndef _uefi_protos_device_path_h_
#define _uefi_protos_device_path_h_
// This file was auto generated by the j6-uefi-headers project. Please see
// https://github.com/justinian/j6-uefi-headers for more information.
#include <uefi/guid.h>
#include <uefi/types.h>
namespace uefi {
namespace protos {
struct device_path;
struct device_path
{
static constexpr uefi::guid guid{ 0x09576e91,0x6d3f,0x11d2,{0x8e,0x39,0x00,0xa0,0xc9,0x69,0x72,0x3b} };
uint8_t type;
uint8_t sub_type;
uint16_t length;
protected:
public:
};
} // namespace protos
} // namespace uefi
#endif // _uefi_protos_device_path_h_

126
external/uefi/protos/file.h vendored Normal file
View File

@@ -0,0 +1,126 @@
#pragma once
#ifndef _uefi_protos_file_h_
#define _uefi_protos_file_h_
// This file was auto generated by the j6-uefi-headers project. Please see
// https://github.com/justinian/j6-uefi-headers for more information.
#include <uefi/guid.h>
#include <uefi/types.h>
namespace uefi {
namespace protos {
struct file;
struct file
{
inline uefi::status open(file ** new_handle, const wchar_t * file_name, file_mode open_mode, file_attr attributes) {
return _open(this, new_handle, file_name, open_mode, attributes);
}
inline uefi::status close() {
return _close(this);
}
inline uefi::status delete_file() {
return _delete_file(this);
}
inline uefi::status read(uint64_t * buffer_size, void * buffer) {
return _read(this, buffer_size, buffer);
}
inline uefi::status write(uint64_t * buffer_size, void * buffer) {
return _write(this, buffer_size, buffer);
}
inline uefi::status get_position(uint64_t * position) {
return _get_position(this, position);
}
inline uefi::status set_position(uint64_t position) {
return _set_position(this, position);
}
inline uefi::status get_info(const guid * info_type, uint64_t * buffer_size, void * buffer) {
return _get_info(this, info_type, buffer_size, buffer);
}
inline uefi::status set_info(const guid * info_type, uint64_t buffer_size, void * buffer) {
return _set_info(this, info_type, buffer_size, buffer);
}
inline uefi::status flush() {
return _flush(this);
}
inline uefi::status open_ex(file ** new_handle, const wchar_t * file_name, uint64_t open_mode, uint64_t attributes, file_io_token * token) {
return _open_ex(this, new_handle, file_name, open_mode, attributes, token);
}
inline uefi::status read_ex(file_io_token * token) {
return _read_ex(this, token);
}
inline uefi::status write_ex(file_io_token * token) {
return _write_ex(this, token);
}
inline uefi::status flush_ex(file_io_token * token) {
return _flush_ex(this, token);
}
uint64_t revision;
protected:
using _open_def = uefi::status (*)(uefi::protos::file *, file **, const wchar_t *, file_mode, file_attr);
_open_def _open;
using _close_def = uefi::status (*)(uefi::protos::file *);
_close_def _close;
using _delete_file_def = uefi::status (*)(uefi::protos::file *);
_delete_file_def _delete_file;
using _read_def = uefi::status (*)(uefi::protos::file *, uint64_t *, void *);
_read_def _read;
using _write_def = uefi::status (*)(uefi::protos::file *, uint64_t *, void *);
_write_def _write;
using _get_position_def = uefi::status (*)(uefi::protos::file *, uint64_t *);
_get_position_def _get_position;
using _set_position_def = uefi::status (*)(uefi::protos::file *, uint64_t);
_set_position_def _set_position;
using _get_info_def = uefi::status (*)(uefi::protos::file *, const guid *, uint64_t *, void *);
_get_info_def _get_info;
using _set_info_def = uefi::status (*)(uefi::protos::file *, const guid *, uint64_t, void *);
_set_info_def _set_info;
using _flush_def = uefi::status (*)(uefi::protos::file *);
_flush_def _flush;
using _open_ex_def = uefi::status (*)(uefi::protos::file *, file **, const wchar_t *, uint64_t, uint64_t, file_io_token *);
_open_ex_def _open_ex;
using _read_ex_def = uefi::status (*)(uefi::protos::file *, file_io_token *);
_read_ex_def _read_ex;
using _write_ex_def = uefi::status (*)(uefi::protos::file *, file_io_token *);
_write_ex_def _write_ex;
using _flush_ex_def = uefi::status (*)(uefi::protos::file *, file_io_token *);
_flush_ex_def _flush_ex;
public:
};
} // namespace protos
} // namespace uefi
#endif // _uefi_protos_file_h_

35
external/uefi/protos/file_info.h vendored Normal file
View File

@@ -0,0 +1,35 @@
#pragma once
#ifndef _uefi_protos_file_info_h_
#define _uefi_protos_file_info_h_
// This file was auto generated by the j6-uefi-headers project. Please see
// https://github.com/justinian/j6-uefi-headers for more information.
#include <uefi/guid.h>
#include <uefi/types.h>
namespace uefi {
namespace protos {
struct file_info;
struct file_info
{
static constexpr uefi::guid guid{ 0x09576e92,0x6d3f,0x11d2,{0x8e,0x39,0x00,0xa0,0xc9,0x69,0x72,0x3b} };
uint64_t size;
uint64_t file_size;
uint64_t physical_size;
time create_time;
time last_access_time;
time modification_time;
uint64_t attribute;
wchar_t file_name[];
protected:
public:
};
} // namespace protos
} // namespace uefi
#endif // _uefi_protos_file_info_h_

50
external/uefi/protos/graphics_output.h vendored Normal file
View File

@@ -0,0 +1,50 @@
#pragma once
#ifndef _uefi_protos_graphics_output_h_
#define _uefi_protos_graphics_output_h_
// This file was auto generated by the j6-uefi-headers project. Please see
// https://github.com/justinian/j6-uefi-headers for more information.
#include <uefi/guid.h>
#include <uefi/types.h>
#include <uefi/graphics.h>
namespace uefi {
namespace protos {
struct graphics_output;
struct graphics_output
{
static constexpr uefi::guid guid{ 0x9042a9de,0x23dc,0x4a38,{0x96,0xfb,0x7a,0xde,0xd0,0x80,0x51,0x6a} };
inline uefi::status query_mode(uint32_t mode_number, uint64_t * size_of_info, uefi::graphics_output_mode_info ** info) {
return _query_mode(this, mode_number, size_of_info, info);
}
inline uefi::status set_mode(uint32_t mode_number) {
return _set_mode(this, mode_number);
}
inline uefi::status blt() {
return _blt(this);
}
protected:
using _query_mode_def = uefi::status (*)(uefi::protos::graphics_output *, uint32_t, uint64_t *, uefi::graphics_output_mode_info **);
_query_mode_def _query_mode;
using _set_mode_def = uefi::status (*)(uefi::protos::graphics_output *, uint32_t);
_set_mode_def _set_mode;
using _blt_def = uefi::status (*)(uefi::protos::graphics_output *);
_blt_def _blt;
public:
uefi::graphics_output_mode * mode;
};
} // namespace protos
} // namespace uefi
#endif // _uefi_protos_graphics_output_h_

48
external/uefi/protos/loaded_image.h vendored Normal file
View File

@@ -0,0 +1,48 @@
#pragma once
#ifndef _uefi_protos_loaded_image_h_
#define _uefi_protos_loaded_image_h_
// This file was auto generated by the j6-uefi-headers project. Please see
// https://github.com/justinian/j6-uefi-headers for more information.
#include <uefi/guid.h>
#include <uefi/types.h>
#include <uefi/tables.h>
#include <uefi/protos/device_path.h>
namespace uefi {
namespace protos {
struct loaded_image;
struct loaded_image
{
static constexpr uefi::guid guid{ 0x5b1b31a1,0x9562,0x11d2,{0x8e,0x3f,0x00,0xa0,0xc9,0x69,0x72,0x3b} };
inline uefi::status unload(uefi::handle image_handle) {
return _unload(image_handle);
}
uint32_t revision;
uefi::handle parent_handle;
uefi::system_table * system_table;
uefi::handle device_handle;
uefi::protos::device_path * file_path;
void * reserved;
uint32_t load_options_size;
void * load_options;
void * image_base;
uint64_t image_size;
uefi::memory_type image_code_type;
uefi::memory_type image_data_type;
protected:
using _unload_def = uefi::status (*)(uefi::handle);
_unload_def _unload;
public:
};
} // namespace protos
} // namespace uefi
#endif // _uefi_protos_loaded_image_h_

View File

@@ -0,0 +1,36 @@
#pragma once
#ifndef _uefi_protos_simple_file_system_h_
#define _uefi_protos_simple_file_system_h_
// This file was auto generated by the j6-uefi-headers project. Please see
// https://github.com/justinian/j6-uefi-headers for more information.
#include <uefi/guid.h>
#include <uefi/types.h>
#include <uefi/protos/file.h>
namespace uefi {
namespace protos {
struct simple_file_system;
struct simple_file_system
{
static constexpr uefi::guid guid{ 0x0964e5b22,0x6459,0x11d2,{0x8e,0x39,0x00,0xa0,0xc9,0x69,0x72,0x3b} };
inline uefi::status open_volume(uefi::protos::file ** root) {
return _open_volume(this, root);
}
uint64_t revision;
protected:
using _open_volume_def = uefi::status (*)(uefi::protos::simple_file_system *, uefi::protos::file **);
_open_volume_def _open_volume;
public:
};
} // namespace protos
} // namespace uefi
#endif // _uefi_protos_simple_file_system_h_

View File

@@ -0,0 +1,92 @@
#pragma once
#ifndef _uefi_protos_simple_text_output_h_
#define _uefi_protos_simple_text_output_h_
// This file was auto generated by the j6-uefi-headers project. Please see
// https://github.com/justinian/j6-uefi-headers for more information.
#include <uefi/guid.h>
#include <uefi/types.h>
#include <uefi/graphics.h>
namespace uefi {
namespace protos {
struct simple_text_output;
struct simple_text_output
{
static constexpr uefi::guid guid{ 0x387477c2,0x69c7,0x11d2,{0x8e,0x39,0x00,0xa0,0xc9,0x69,0x72,0x3b} };
inline uefi::status reset(bool extended_verification) {
return _reset(this, extended_verification);
}
inline uefi::status output_string(const wchar_t * string) {
return _output_string(this, string);
}
inline uefi::status test_string(const wchar_t * string) {
return _test_string(this, string);
}
inline uefi::status query_mode(uint64_t mode_number, uint64_t * columns, uint64_t * rows) {
return _query_mode(this, mode_number, columns, rows);
}
inline uefi::status set_mode(uint64_t mode_number) {
return _set_mode(this, mode_number);
}
inline uefi::status set_attribute(uefi::attribute attribute) {
return _set_attribute(this, attribute);
}
inline uefi::status clear_screen() {
return _clear_screen(this);
}
inline uefi::status set_cursor_position(uint64_t column, uint64_t row) {
return _set_cursor_position(this, column, row);
}
inline uefi::status enable_cursor(bool visible) {
return _enable_cursor(this, visible);
}
protected:
using _reset_def = uefi::status (*)(uefi::protos::simple_text_output *, bool);
_reset_def _reset;
using _output_string_def = uefi::status (*)(uefi::protos::simple_text_output *, const wchar_t *);
_output_string_def _output_string;
using _test_string_def = uefi::status (*)(uefi::protos::simple_text_output *, const wchar_t *);
_test_string_def _test_string;
using _query_mode_def = uefi::status (*)(uefi::protos::simple_text_output *, uint64_t, uint64_t *, uint64_t *);
_query_mode_def _query_mode;
using _set_mode_def = uefi::status (*)(uefi::protos::simple_text_output *, uint64_t);
_set_mode_def _set_mode;
using _set_attribute_def = uefi::status (*)(uefi::protos::simple_text_output *, uefi::attribute);
_set_attribute_def _set_attribute;
using _clear_screen_def = uefi::status (*)(uefi::protos::simple_text_output *);
_clear_screen_def _clear_screen;
using _set_cursor_position_def = uefi::status (*)(uefi::protos::simple_text_output *, uint64_t, uint64_t);
_set_cursor_position_def _set_cursor_position;
using _enable_cursor_def = uefi::status (*)(uefi::protos::simple_text_output *, bool);
_enable_cursor_def _enable_cursor;
public:
uefi::text_output_mode * mode;
};
} // namespace protos
} // namespace uefi
#endif // _uefi_protos_simple_text_output_h_

52
external/uefi/runtime_services.h vendored Normal file
View File

@@ -0,0 +1,52 @@
#pragma once
#ifndef _uefi_runtime_services_h_
#define _uefi_runtime_services_h_
// This Source Code Form is part of the j6-uefi-headers project and is subject
// to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was
// not distributed with this file, You can obtain one at
// http://mozilla.org/MPL/2.0/.
#include <stdint.h>
#include <uefi/tables.h>
namespace uefi {
namespace rs_impl {
using convert_pointer = uefi::status (*)(uint64_t, void **);
using set_virtual_address_map = uefi::status (*)(size_t, size_t, uint32_t, memory_descriptor *);
}
struct runtime_services {
static constexpr uint64_t signature = 0x56524553544e5552ull;
table_header header;
// Time Services
void *get_time;
void *set_time;
void *get_wakeup_time;
void *set_wakeup_time;
// Virtual Memory Services
rs_impl::set_virtual_address_map set_virtual_address_map;
rs_impl::convert_pointer convert_pointer;
// Variable Services
void *get_variable;
void *get_next_variable_name;
void *set_variable;
// Miscellaneous Services
void *get_next_high_monotonic_count;
void *reset_system;
// UEFI 2.0 Capsule Services
void *update_capsule;
void *query_capsule_capabilities;
// Miscellaneous UEFI 2.0 Service
void *query_variable_info;
};
} // namespace uefi
#endif

73
external/uefi/tables.h vendored Normal file
View File

@@ -0,0 +1,73 @@
#pragma once
#ifndef _uefi_tables_h_
#define _uefi_tables_h_
// This Source Code Form is part of the j6-uefi-headers project and is subject
// to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was
// not distributed with this file, You can obtain one at
// http://mozilla.org/MPL/2.0/.
#include <stdint.h>
#include <uefi/guid.h>
#include <uefi/types.h>
namespace uefi {
struct runtime_services;
struct boot_services;
namespace protos {
struct simple_text_input;
struct simple_text_output;
}
struct table_header
{
uint64_t signature;
uint32_t revision;
uint32_t header_size;
uint32_t crc32;
uint32_t reserved;
};
struct configuration_table
{
guid vendor_guid;
void *vendor_table;
};
struct system_table
{
table_header header;
char16_t *firmware_vendor;
uint32_t firmware_revision;
handle console_in_handle;
protos::simple_text_input *con_in;
handle console_out_handle;
protos::simple_text_output *con_out;
handle standard_error_handle;
protos::simple_text_output *std_err;
runtime_services *runtime_services;
boot_services *boot_services;
unsigned int number_of_table_entries;
configuration_table *configuration_table;
};
constexpr uint32_t make_system_table_revision(int major, int minor) {
return (major << 16) | minor;
}
constexpr uint64_t system_table_signature = 0x5453595320494249ull;
constexpr uint32_t system_table_revision = make_system_table_revision(2, 70);
constexpr uint32_t specification_revision = system_table_revision;
namespace vendor_guids {
constexpr guid acpi1{ 0xeb9d2d30,0x2d88,0x11d3,{0x9a,0x16,0x00,0x90,0x27,0x3f,0xc1,0x4d} };
constexpr guid acpi2{ 0x8868e871,0xe4f1,0x11d3,{0xbc,0x22,0x00,0x80,0xc7,0x3c,0x88,0x81} };
} // namespace vendor_guids
} // namespace uefi
#endif

157
external/uefi/types.h vendored Normal file
View File

@@ -0,0 +1,157 @@
#pragma once
#ifndef _uefi_types_h_
#define _uefi_types_h_
// This Source Code Form is part of the j6-uefi-headers project and is subject
// to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was
// not distributed with this file, You can obtain one at
// http://mozilla.org/MPL/2.0/.
#include <stdint.h>
namespace uefi {
using handle = void *;
//
// Error and status code definitions
//
constexpr uint64_t error_bit = 0x8000000000000000ull;
constexpr uint64_t make_error(uint64_t e) { return e|error_bit; }
enum class status : uint64_t
{
success = 0,
#define STATUS_WARNING(name, num) name = num,
#define STATUS_ERROR(name, num) name = make_error(num),
#include "uefi/errors.inc"
#undef STATUS_WARNING
#undef STATUS_ERROR
};
inline bool is_error(status s) { return static_cast<uint64_t>(s) & error_bit; }
inline bool is_warning(status s) { return !is_error(s) && s != status::success; }
//
// Time defitions
//
struct time
{
uint16_t year;
uint8_t month;
uint8_t day;
uint8_t hour;
uint8_t minute;
uint8_t second;
uint8_t _pad0;
uint32_t nanosecond;
int16_t time_zone;
uint8_t daylight;
uint8_t _pad1;
};
//
// Memory and allocation defitions
//
enum class memory_type : uint32_t
{
reserved,
loader_code,
loader_data,
boot_services_code,
boot_services_data,
runtime_services_code,
runtime_services_data,
conventional_memory,
unusable_memory,
acpi_reclaim_memory,
acpi_memory_nvs,
memory_mapped_io,
memory_mapped_io_port_space,
pal_code,
persistent_memory,
max_memory_type
};
enum class allocate_type : uint32_t
{
any_pages,
max_address,
address
};
struct memory_descriptor
{
memory_type type;
uintptr_t physical_start;
uintptr_t virtual_start;
uint64_t number_of_pages;
uint64_t attribute;
};
//
// Event handling defitions
//
using event = void *;
enum class evt : uint32_t
{
notify_wait = 0x00000100,
notify_signal = 0x00000200,
signal_exit_boot_services = 0x00000201,
signal_virtual_address_change = 0x60000202,
runtime = 0x40000000,
timer = 0x80000000
};
enum class tpl : uint64_t
{
application = 4,
callback = 8,
notify = 16,
high_level = 31
};
using event_notify = void (*)(event, void*);
//
// File IO defitions
//
struct file_io_token
{
event event;
status status;
uint64_t buffer_size;
void *buffer;
};
enum class file_mode : uint64_t
{
read = 0x0000000000000001ull,
write = 0x0000000000000002ull,
create = 0x8000000000000000ull
};
enum class file_attr : uint64_t
{
none = 0,
read_only = 0x0000000000000001ull,
hidden = 0x0000000000000002ull,
system = 0x0000000000000004ull,
reserved = 0x0000000000000008ull,
directory = 0x0000000000000010ull,
archive = 0x0000000000000020ull
};
} // namespace uefi
#endif

View File

@@ -1,31 +1,31 @@
name: Popcorn name: jsix
templates: scripts/templates templates: scripts/templates
modules: modules:
kernel: kernel:
output: popcorn.elf kind: exe
output: jsix.elf
target: host target: host
deps: deps:
- elf - cpu
- initrd
- kutil - kutil
includes: includes:
- src/kernel - src/kernel
source: source:
- src/kernel/crti.s
- src/kernel/apic.cpp - src/kernel/apic.cpp
- src/kernel/assert.cpp - src/kernel/assert.cpp
- src/kernel/boot.s - src/kernel/boot.s
- src/kernel/clock.cpp
- src/kernel/console.cpp - src/kernel/console.cpp
- src/kernel/cpprt.cpp - src/kernel/cpprt.cpp
- src/kernel/cpu.cpp - src/kernel/cpu.cpp
- src/kernel/debug.cpp - src/kernel/debug.cpp
- src/kernel/debug.s - src/kernel/debug.s
- src/kernel/device_manager.cpp - src/kernel/device_manager.cpp
- src/kernel/font.cpp
- src/kernel/frame_allocator.cpp - src/kernel/frame_allocator.cpp
- src/kernel/fs/gpt.cpp - src/kernel/fs/gpt.cpp
- src/kernel/gdt.cpp - src/kernel/gdt.cpp
- src/kernel/gdt.s - src/kernel/gdt.s
- src/kernel/hpet.cpp
- src/kernel/interrupts.cpp - src/kernel/interrupts.cpp
- src/kernel/interrupts.s - src/kernel/interrupts.s
- src/kernel/io.cpp - src/kernel/io.cpp
@@ -34,65 +34,71 @@ modules:
- src/kernel/main.cpp - src/kernel/main.cpp
- src/kernel/memory_bootstrap.cpp - src/kernel/memory_bootstrap.cpp
- src/kernel/msr.cpp - src/kernel/msr.cpp
- src/kernel/page_manager.cpp - src/kernel/objects/channel.cpp
- src/kernel/objects/endpoint.cpp
- src/kernel/objects/kobject.cpp
- src/kernel/objects/thread.cpp
- src/kernel/objects/process.cpp
- src/kernel/objects/system.cpp
- src/kernel/objects/vm_area.cpp
- src/kernel/page_table.cpp
- src/kernel/pci.cpp - src/kernel/pci.cpp
- src/kernel/process.cpp
- src/kernel/scheduler.cpp - src/kernel/scheduler.cpp
- src/kernel/screen.cpp
- src/kernel/serial.cpp - src/kernel/serial.cpp
- src/kernel/symbol_table.cpp
- src/kernel/syscall.cpp - src/kernel/syscall.cpp
- src/kernel/syscall.s - src/kernel/syscall.s
- src/kernel/syscalls/exit.cpp - src/kernel/syscalls/channel.cpp
- src/kernel/syscalls/fork.cpp - src/kernel/syscalls/endpoint.cpp
- src/kernel/syscalls/getpid.cpp - src/kernel/syscalls/object.cpp
- src/kernel/syscalls/message.cpp - src/kernel/syscalls/process.cpp
- src/kernel/syscalls/noop.cpp - src/kernel/syscalls/system.cpp
- src/kernel/syscalls/pause.cpp - src/kernel/syscalls/thread.cpp
- src/kernel/syscalls/sleep.cpp - src/kernel/syscalls/vm_area.cpp
- src/kernel/task.s - src/kernel/task.s
- src/kernel/crtn.s - src/kernel/vm_mapper.cpp
- src/kernel/vm_space.cpp
boot: boot:
kind: exe kind: exe
target: boot target: boot
output: boot.elf output: boot.efi
deps:
- cpu
source: source:
- src/boot/crt0.s
- src/boot/console.cpp
- src/boot/guids.cpp
- src/boot/loader.cpp
- src/boot/main.cpp - src/boot/main.cpp
- src/boot/console.cpp
- src/boot/error.cpp
- src/boot/fs.cpp
- src/boot/hardware.cpp
- src/boot/loader.cpp
- src/boot/memory.cpp - src/boot/memory.cpp
- src/boot/reloc.cpp - src/boot/paging.cpp
- src/boot/utility.cpp - src/boot/status.cpp
- src/boot/support.cpp
nulldrv: nulldrv:
kind: exe kind: exe
target: user target: user
output: nulldrv output: nulldrv.elf
deps:
- libc
source: source:
- src/drivers/nulldrv/io.cpp
- src/drivers/nulldrv/main.cpp - src/drivers/nulldrv/main.cpp
- src/drivers/nulldrv/main.s - src/drivers/nulldrv/serial.cpp
elf: fb:
kind: lib kind: exe
output: libelf.a target: user
output: fb.elf
deps: deps:
- kutil - libc
includes:
- src/libraries/elf/include
source: source:
- src/libraries/elf/elf.cpp - src/drivers/fb/font.cpp
- src/drivers/fb/main.cpp
initrd: - src/drivers/fb/screen.cpp
kind: lib - src/drivers/fb/scrollback.cpp
output: libinitrd.a
deps:
- kutil
includes:
- src/libraries/initrd/include
source:
- src/libraries/initrd/initrd.cpp
kutil: kutil:
kind: lib kind: lib
@@ -107,15 +113,192 @@ modules:
- src/libraries/kutil/memory.cpp - src/libraries/kutil/memory.cpp
- src/libraries/kutil/printf.c - src/libraries/kutil/printf.c
makerd: cpu:
kind: exe kind: lib
target: native output: libcpu.a
output: makerd includes:
deps: - src/libraries/cpu/include
- initrd
source: source:
- src/tools/makerd/entry.cpp - src/libraries/cpu/cpu.cpp
- src/tools/makerd/main.cpp
libc:
kind: lib
output: libc.a
includes:
- src/libraries/libc/include
target: user
defines:
- DISABLE_SSE
- LACKS_UNISTD_H
- LACKS_FCNTL_H
- LACKS_SYS_PARAM_H
- LACKS_SYS_MMAN_H
- LACKS_SCHED_H
- LACKS_STRINGS_H
- HAVE_MMAP=0
#- LACKS_STRING_H
#- LACKS_ERRNO_H
#- LACKS_STDLIB_H
#- LACKS_TIME_H
source:
- src/libraries/libc/arch/x86_64/_Exit.s
- src/libraries/libc/arch/x86_64/crt0.s
- src/libraries/libc/arch/x86_64/init_libc.c
- src/libraries/libc/arch/x86_64/syscalls.s
- src/libraries/libc/ctype/isalnum.c
- src/libraries/libc/ctype/isalpha.c
- src/libraries/libc/ctype/isblank.c
- src/libraries/libc/ctype/iscntrl.c
- src/libraries/libc/ctype/isdigit.c
- src/libraries/libc/ctype/isgraph.c
- src/libraries/libc/ctype/islower.c
- src/libraries/libc/ctype/isprint.c
- src/libraries/libc/ctype/ispunct.c
- src/libraries/libc/ctype/isspace.c
- src/libraries/libc/ctype/isupper.c
- src/libraries/libc/ctype/isxdigit.c
- src/libraries/libc/ctype/tolower.c
- src/libraries/libc/ctype/toupper.c
- src/libraries/libc/inttypes/imaxabs.c
- src/libraries/libc/inttypes/imaxdiv.c
- src/libraries/libc/inttypes/strtoimax.c
- src/libraries/libc/inttypes/strtoumax.c
- src/libraries/libc/locale/localeconv.c
- src/libraries/libc/locale/setlocale.c
- src/libraries/libc/j6libc/assert.c
- src/libraries/libc/j6libc/errno.c
- src/libraries/libc/j6libc/allocpages.c
- src/libraries/libc/j6libc/atomax.c
- src/libraries/libc/j6libc/closeall.c
- src/libraries/libc/j6libc/close.c
- src/libraries/libc/j6libc/digits.c
- src/libraries/libc/j6libc/filemode.c
- src/libraries/libc/j6libc/fillbuffer.c
- src/libraries/libc/j6libc/flushbuffer.c
- src/libraries/libc/j6libc/is_leap.c
- src/libraries/libc/j6libc/load_lc_collate.c
- src/libraries/libc/j6libc/load_lc_ctype.c
- src/libraries/libc/j6libc/load_lc_messages.c
- src/libraries/libc/j6libc/load_lc_monetary.c
- src/libraries/libc/j6libc/load_lc_numeric.c
- src/libraries/libc/j6libc/load_lc_time.c
- src/libraries/libc/j6libc/load_lines.c
- src/libraries/libc/j6libc/open.c
- src/libraries/libc/j6libc/prepread.c
- src/libraries/libc/j6libc/prepwrite.c
- src/libraries/libc/j6libc/print.c
- src/libraries/libc/j6libc/rename.c
- src/libraries/libc/j6libc/scan.c
- src/libraries/libc/j6libc/seed.c
- src/libraries/libc/j6libc/seek.c
- src/libraries/libc/j6libc/stdinit.c
- src/libraries/libc/j6libc/strtox_main.c
- src/libraries/libc/j6libc/strtox_prelim.c
- src/libraries/libc/j6libc/sbrk.c
- src/libraries/libc/signal/raise.c
- src/libraries/libc/signal/signal.c
- src/libraries/libc/stdio/clearerr.c
- src/libraries/libc/stdio/fclose.c
- src/libraries/libc/stdio/feof.c
- src/libraries/libc/stdio/ferror.c
- src/libraries/libc/stdio/fflush.c
- src/libraries/libc/stdio/fgetc.c
- src/libraries/libc/stdio/fgetpos.c
- src/libraries/libc/stdio/fgets.c
- src/libraries/libc/stdio/fopen.c
- src/libraries/libc/stdio/fprintf.c
- src/libraries/libc/stdio/fputc.c
- src/libraries/libc/stdio/fputs.c
- src/libraries/libc/stdio/fread.c
- src/libraries/libc/stdio/freopen.c
- src/libraries/libc/stdio/fscanf.c
- src/libraries/libc/stdio/fseek.c
- src/libraries/libc/stdio/fsetpos.c
- src/libraries/libc/stdio/ftell.c
- src/libraries/libc/stdio/fwrite.c
- src/libraries/libc/stdio/getc.c
- src/libraries/libc/stdio/getchar.c
- src/libraries/libc/stdio/perror.c
- src/libraries/libc/stdio/printf.c
- src/libraries/libc/stdio/putc.c
- src/libraries/libc/stdio/putchar.c
- src/libraries/libc/stdio/puts.c
- src/libraries/libc/stdio/remove.c
- src/libraries/libc/stdio/rename.c
- src/libraries/libc/stdio/rewind.c
- src/libraries/libc/stdio/scanf.c
- src/libraries/libc/stdio/setbuf.c
- src/libraries/libc/stdio/setvbuf.c
- src/libraries/libc/stdio/snprintf.c
- src/libraries/libc/stdio/sprintf.c
- src/libraries/libc/stdio/sscanf.c
- src/libraries/libc/stdio/tmpfile.c
- src/libraries/libc/stdio/tmpnam.c
- src/libraries/libc/stdio/ungetc.c
- src/libraries/libc/stdio/vfprintf.c
- src/libraries/libc/stdio/vfscanf.c
- src/libraries/libc/stdio/vprintf.c
- src/libraries/libc/stdio/vscanf.c
- src/libraries/libc/stdio/vsnprintf.c
- src/libraries/libc/stdio/vsprintf.c
- src/libraries/libc/stdio/vsscanf.c
- src/libraries/libc/stdlib/abort.c
- src/libraries/libc/stdlib/abs.c
- src/libraries/libc/stdlib/atexit.c
- src/libraries/libc/stdlib/atoi.c
- src/libraries/libc/stdlib/atol.c
- src/libraries/libc/stdlib/atoll.c
- src/libraries/libc/stdlib/bsearch.c
- src/libraries/libc/stdlib/div.c
- src/libraries/libc/stdlib/exit.c
- src/libraries/libc/stdlib/_Exit.c
- src/libraries/libc/stdlib/getenv.c
- src/libraries/libc/stdlib/labs.c
- src/libraries/libc/stdlib/ldiv.c
- src/libraries/libc/stdlib/llabs.c
- src/libraries/libc/stdlib/lldiv.c
- src/libraries/libc/stdlib/malloc.c
- src/libraries/libc/stdlib/qsort.c
- src/libraries/libc/stdlib/rand.c
- src/libraries/libc/stdlib/srand.c
- src/libraries/libc/stdlib/strtol.c
- src/libraries/libc/stdlib/strtoll.c
- src/libraries/libc/stdlib/strtoul.c
- src/libraries/libc/stdlib/strtoull.c
- src/libraries/libc/stdlib/system.c
- src/libraries/libc/string/memchr.c
- src/libraries/libc/string/memcmp.c
- src/libraries/libc/string/memcpy.c
- src/libraries/libc/string/memmove.c
- src/libraries/libc/string/memset.c
- src/libraries/libc/string/strcat.c
- src/libraries/libc/string/strchr.c
- src/libraries/libc/string/strcmp.c
- src/libraries/libc/string/strcoll.c
- src/libraries/libc/string/strcpy.c
- src/libraries/libc/string/strcspn.c
- src/libraries/libc/string/strerror.c
- src/libraries/libc/string/strlen.c
- src/libraries/libc/string/strncat.c
- src/libraries/libc/string/strncmp.c
- src/libraries/libc/string/strncpy.c
- src/libraries/libc/string/strpbrk.c
- src/libraries/libc/string/strrchr.c
- src/libraries/libc/string/strspn.c
- src/libraries/libc/string/strstr.c
- src/libraries/libc/string/strtok.c
- src/libraries/libc/string/strxfrm.c
- src/libraries/libc/time/asctime.c
- src/libraries/libc/time/clock.c
- src/libraries/libc/time/ctime.c
- src/libraries/libc/time/difftime.c
- src/libraries/libc/time/gmtime.c
- src/libraries/libc/time/localtime.c
- src/libraries/libc/time/mktime.c
- src/libraries/libc/time/strftime.c
- src/libraries/libc/time/time.c
- src/libraries/libc/time/timespec_get.c
tests: tests:
kind: exe kind: exe
@@ -124,9 +307,15 @@ modules:
deps: deps:
- kutil - kutil
source: source:
- src/tests/address_manager.cpp
- src/tests/constexpr_hash.cpp - src/tests/constexpr_hash.cpp
- src/tests/linked_list.cpp - src/tests/linked_list.cpp
- src/tests/logger.cpp - src/tests/logger.cpp
- src/tests/heap_allocator.cpp - src/tests/heap_allocator.cpp
- src/tests/main.cpp - src/tests/main.cpp
- src/tests/map.cpp
- src/tests/vector.cpp
overlays:
- url: https://f000.backblazeb2.com/file/jsix-os/sysroot-llvm8-20190706.tar.bz2
path: sysroot
- url: https://f000.backblazeb2.com/file/jsix-os/sysroot-j6libc-8cb8ce7.tar.bz2
path: sysroot

89
other_software.md Normal file
View File

@@ -0,0 +1,89 @@
# Included works
jsix includes and/or is derived from a number of other works, listed here.
## Catch2
jsix uses [Catch2][] for testing. Catch2 is released under the terms of the
Boost Software license:
[Catch2]: https://github.com/catchorg/Catch2
> Boost Software License - Version 1.0 - August 17th, 2003
>
> Permission is hereby granted, free of charge, to any person or organization
> obtaining a copy of the software and accompanying documentation covered by
> this license (the "Software") to use, reproduce, display, distribute,
> execute, and transmit the Software, and to prepare derivative works of the
> Software, and to permit third-parties to whom the Software is furnished to
> do so, all subject to the following:
>
> The copyright notices in the Software and this entire statement, including
> the above license grant, this restriction and the following disclaimer,
> must be included in all copies of the Software, in whole or in part, and
> all derivative works of the Software, unless such copies or derivative
> works are solely in the form of machine-executable object code generated by
> a source language processor.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
> SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
> FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
> ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> DEALINGS IN THE SOFTWARE.
## cpptoml
jsix uses the [cpptoml][] library for parsing TOML configuration files. cpptoml
is released under the terms of the MIT license:
[cpptoml]: https://github.com/skystrife/cpptoml
> Copyright (c) 2014 Chase Geigle
>
> Permission is hereby granted, free of charge, to any person obtaining a copy of
> this software and associated documentation files (the "Software"), to deal in
> the Software without restriction, including without limitation the rights to
> use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
> the Software, and to permit persons to whom the Software is furnished to do so,
> subject to the following conditions:
>
> The above copyright notice and this permission notice shall be included in all
> copies or substantial portions of the Software.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
> FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
> COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
> IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
> CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
## printf
jsix uses Marco Paland's tiny [printf][] library for its `*printf()` functions,
which is also released under the terms of the MIT license:
[printf]: https://github.com/mpaland/printf
> The MIT License (MIT)
>
> Copyright (c) 2014 Marco Paland
>
> Permission is hereby granted, free of charge, to any person obtaining a copy
> of this software and associated documentation files (the "Software"), to deal
> in the Software without restriction, including without limitation the rights
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> copies of the Software, and to permit persons to whom the Software is
> furnished to do so, subject to the following conditions:
>
> The above copyright notice and this permission notice shall be included in all
> copies or substantial portions of the Software.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> SOFTWARE.

36
qemu.sh
View File

@@ -3,21 +3,34 @@
build="$(dirname $0)/build" build="$(dirname $0)/build"
assets="$(dirname $0)/assets" assets="$(dirname $0)/assets"
debug="" debug=""
debugtarget="${build}/jsix.elf"
flash_name="ovmf_vars" flash_name="ovmf_vars"
gfx="-nographic" gfx="-nographic"
vga="-vga none"
kvm="" kvm=""
cpu="Broadwell,+pdpe1gb"
for arg in $@; do for arg in $@; do
case "${arg}" in case "${arg}" in
--debugboot)
debug="-s -S"
debugtarget="${build}/boot/boot.efi"
flash_name="ovmf_vars_d"
;;
--debug) --debug)
debug="-s" debug="-s -S"
flash_name="ovmf_vars_d" flash_name="ovmf_vars_d"
;; ;;
--gfx) --gfx)
gfx="" gfx=""
vga=""
;;
--vga)
vga=""
;; ;;
--kvm) --kvm)
kvm="-enable-kvm" kvm="-enable-kvm"
cpu="host"
;; ;;
*) *)
build="${arg}" build="${arg}"
@@ -35,22 +48,33 @@ fi
if [[ -n $TMUX ]]; then if [[ -n $TMUX ]]; then
if [[ -n $debug ]]; then if [[ -n $debug ]]; then
tmux split-window "gdb ${build}/popcorn.elf" & tmux split-window -h "gdb ${debugtarget}" &
else else
tmux split-window -h -l 80 "sleep 1; telnet localhost 45455" &
tmux last-pane
tmux split-window -l 10 "sleep 1; telnet localhost 45454" & tmux split-window -l 10 "sleep 1; telnet localhost 45454" &
fi fi
elif [[ $DESKTOP_SESSION = "i3" ]]; then
if [[ -n $debug ]]; then
i3-msg exec i3-sensible-terminal -- -e "gdb ${PWD}/${build}/jsix.elf" &
else
i3-msg exec i3-sensible-terminal -- -e 'telnet localhost 45454' &
fi
fi fi
exec qemu-system-x86_64 \ exec qemu-system-x86_64 \
-drive "if=pflash,format=raw,readonly,file=${assets}/ovmf/x64/ovmf_code.fd" \ -drive "if=pflash,format=raw,readonly,file=${assets}/ovmf/x64/ovmf_code.fd" \
-drive "if=pflash,format=raw,file=${build}/${flash_name}.fd" \ -drive "if=pflash,format=raw,file=${build}/${flash_name}.fd" \
-drive "format=raw,file=${build}/popcorn.img" \ -drive "format=raw,file=${build}/jsix.img" \
-device "isa-debug-exit,iobase=0xf4,iosize=0x04" \
-monitor telnet:localhost:45454,server,nowait \ -monitor telnet:localhost:45454,server,nowait \
-serial stdio \
-serial telnet:localhost:45455,server,nowait \
-smp 4 \ -smp 4 \
-m 512 \ -m 512 \
-d mmu,int,guest_errors \ -d mmu,int,guest_errors \
-D popcorn.log \ -D jsix.log \
-cpu Broadwell \ -cpu "${cpu}" \
-M q35 \ -M q35 \
-no-reboot \ -no-reboot \
$gfx $kvm $debug $gfx $vga $kvm $debug

75
scripts/build_symbol_table.py Executable file
View File

@@ -0,0 +1,75 @@
#!/usr/bin/env python3
#
# Generate the jsix style symbol table. The format in memory of this table
# is as follows:
#
# <num_entires> : 8 bytes
# <index> : 16 * N bytes
# <name data> : variable
#
# Each index entry has the format
# <symbol address> : 8 bytes
# <offset of name> : 8 bytes
#
# Name offsets are from the start of the symbol table as a whole. (ie,
# where <num_entries> is located.)
def parse_syms(infile):
"""Take the output of the `nm` command, and parse it into a tuple
representing the symbols in the text segment of the binary. Returns
a list of (address, symbol_name)."""
from cxxfilt import demangle, InvalidName
syms = []
for line in sys.stdin:
addr, t, mangled = line.split()
if t not in "tTvVwW": continue
try:
name = demangle(mangled)
except InvalidName:
continue
addr = int(addr, base=16)
syms.append((addr, name))
return sorted(syms)
def write_table(syms, outfile):
"""Write the given symbol table as generated by parse_syms()
to the outfile, index first, and then name character data."""
import struct
outfile.write(struct.pack("@Q", len(syms)))
index_pos = outfile.tell()
outfile.seek(struct.calcsize("@QQ") * len(syms), 1)
nul = b'\0'
positions = {}
for s in syms:
addr, name = s
positions[addr] = outfile.tell()
data = name.encode('utf-8')
outfile.write(name.encode('utf-8'))
outfile.write(nul)
outfile.seek(index_pos)
for s in syms:
addr = s[0]
pos = positions[addr]
outfile.write(struct.pack("@QQ", addr, pos))
if __name__ == "__main__":
import sys
if len(sys.argv) != 2:
print(f"Usage: {sys.argv[0]} <output>")
sys.exit(1)
outfile = open(sys.argv[1], "wb")
write_table(parse_syms(sys.stdin), outfile)

131
scripts/build_sysroot.sh Executable file
View File

@@ -0,0 +1,131 @@
#!/usr/bin/env bash
TARGET="x86_64-elf"
LLVM_BRANCH="release_80"
TOOLS="clang lld" # lld libunwind libcxxabi libcxx"
PROJECTS="compiler-rt libcxxabi libcxx libunwind"
#RUNTIMES="compiler-rt libcxxabi libcxx libunwind"
set -e
README=$(realpath "$(dirname $0)/readme_for_prebuilt_sysroots.md")
SYSROOT=$(realpath "$(dirname $0)/../sysroot")
WORK=$(realpath "$(dirname $0)/sysroot")
mkdir -p "${SYSROOT}"
mkdir -p "${WORK}"
export CC=clang
export CXX=clang++
if [[ ! -d "${WORK}/llvm" ]]; then
echo "Downloading LLVM..."
git clone -q \
--branch "${LLVM_BRANCH}" \
--depth 1 \
"https://git.llvm.org/git/llvm.git" "${WORK}/llvm"
fi
for tool in ${TOOLS}; do
if [[ ! -d "${WORK}/llvm/tools/${tool}" ]]; then
echo "Downloading ${tool}..."
git clone -q \
--branch "${LLVM_BRANCH}" \
--depth 1 \
"https://git.llvm.org/git/${tool}.git" "${WORK}/llvm/tools/${tool}"
fi
done
if [[ ! -d "${WORK}/llvm/tools/clang/tools/extra" ]]; then
echo "Downloading clang-tools-extra..."
git clone -q \
--branch "${LLVM_BRANCH}" \
--depth 1 \
"https://git.llvm.org/git/clang-tools-extra.git" "${WORK}/llvm/tools/clang/tools/extra"
fi
for proj in ${PROJECTS}; do
if [[ ! -d "${WORK}/llvm/projects/${proj}" ]]; then
echo "Downloading ${proj}..."
git clone -q \
--branch "${LLVM_BRANCH}" \
--depth 1 \
"https://git.llvm.org/git/${proj}.git" "${WORK}/llvm/projects/${proj}"
fi
done
for proj in ${RUNTIMES}; do
if [[ ! -d "${WORK}/llvm/runtimes/${proj}" ]]; then
echo "Downloading ${proj}..."
git clone -q \
--branch "${LLVM_BRANCH}" \
--depth 1 \
"https://git.llvm.org/git/${proj}.git" "${WORK}/llvm/runtime/${proj}"
fi
done
mkdir -p "${WORK}/build/llvm"
pushd "${WORK}/build/llvm"
echo "Configuring LLVM..."
cmake -G Ninja \
-DCLANG_DEFAULT_RTLIB=compiler-rt \
-DCLANG_DEFAULT_STD_C=c11 \
-DCLANG_DEFAULT_STD_CXX=cxx14 \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_C_COMPILER="clang" \
-DCMAKE_CXX_COMPILER="clang++" \
-DCMAKE_CXX_FLAGS="-Wno-unused-parameter -D_LIBCPP_HAS_NO_ALIGNED_ALLOCATION -D_LIBUNWIND_IS_BAREMETAL=1 -U_LIBUNWIND_SUPPORT_DWARF_UNWIND" \
-DCMAKE_INSTALL_PREFIX="${SYSROOT}" \
-DCMAKE_MAKE_PROGRAM=`which ninja` \
-DDEFAULT_SYSROOT="${SYSROOT}" \
-DLIBCXX_CXX_ABI=libcxxabi \
-DLIBCXX_CXX_ABI_INCLUDE_PATHS="${WORK}/llvm/projects/libcxxabi/include" \
-DLIBCXX_CXX_ABI_LIBRARY_PATH=lib \
-DLIBCXX_ENABLE_EXPERIMENTAL_LIBRARY=OFF \
-DLIBCXX_ENABLE_NEW_DELETE_DEFINITIONS=ON \
-DLIBCXX_ENABLE_SHARED=OFF \
-DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON \
-DLIBCXX_ENABLE_THREADS=OFF \
-DLIBCXX_INCLUDE_BENCHMARKS=OFF \
-DLIBCXX_USE_COMPILER_RT=ON \
-DLIBCXXABI_ENABLE_NEW_DELETE_DEFINITIONS=OFF \
-DLIBCXXABI_ENABLE_SHARED=OFF \
-DLIBCXXABI_ENABLE_STATIC_UNWINDER=ON \
-DLIBCXXABI_ENABLE_THREADS=OFF \
-DLIBCXXABI_LIBCXX_PATH="${WORK}/llvm/projects/libcxx" \
-DLIBCXXABI_USE_COMPILER_RT=ON \
-DLIBCXXABI_USE_LLVM_UNWINDER=ON \
-DLIBUNWIND_ENABLE_SHARED=OFF \
-DLIBUNWIND_ENABLE_THREADS=OFF \
-DLIBUNWIND_USE_COMPILER_RT=ON \
-DLLVM_CONFIG_PATH="${SYSROOT}/bin/llvm-config" \
-DLLVM_DEFAULT_TARGET_TRIPLE="x86_64-unknown-elf" \
-DLLVM_ENABLE_LIBCXX=ON \
-DLLVM_ENABLE_LLD=ON \
-DLLVM_ENABLE_PIC=OFF \
-DLLVM_ENABLE_THREADS=OFF \
-DLLVM_INSTALL_BINUTILS_SYMLINKS=ON \
-DLLVM_TARGETS_TO_BUILD="X86" \
${WORK}/llvm > cmake_configure.log
# -DCMAKE_ASM_COMPILER=nasm \
# -DCMAKE_LINKER="${SYSROOT}/bin/ld.lld" \
# -DCOMPILER_RT_ENABLE_LLD=ON \
# -DLIBCXX_ENABLE_LLD=ON \
# -DLIBCXX_ENABLE_STATIC_UNWINDER=ON \
# -DLIBCXXABI_ENABLE_LLD=ON \
# -DLIBUNWIND_ENABLE_LLD=ON \
# -DLLVM_ENABLE_PROJECTS="libcxx;libcxxabi;libunwind;compiler-rt" \
# -DCOMPILER_RT_BAREMETAL_BUILD=ON \
# -DLIBCXXABI_BAREMETAL=ON \
echo "Building LLVM..."
ninja && ninja install
ninja cxx cxxabi compiler-rt
ninja install-compiler-rt install-cxx install-cxxabi
popd
cp "${README}" "${SYSROOT}/README.md"

View File

@@ -1,221 +0,0 @@
#!/usr/bin/env bash
TARGET="x86_64-elf"
NASM_VERSION="2.13.03"
BINUTILS_VERSION="2.31.1"
LLVM_BRANCH="release_80"
TOOLS="clang" # lld libunwind libcxxabi libcxx"
PROJECTS="compiler-rt libcxxabi libcxx libunwind"
#RUNTIMES="compiler-rt libcxxabi libcxx libunwind"
set -e
SYSROOT=$(realpath "$(dirname $0)/../sysroot")
WORK=$(realpath "$(dirname $0)/sysroot")
mkdir -p "${SYSROOT}"
mkdir -p "${WORK}"
export CC=clang
export CXX=clang++
function build_nasm() {
if [[ ! -d "${WORK}/nasm-${NASM_VERSION}" ]]; then
echo "Downloading NASM..."
tarball="nasm-${NASM_VERSION}.tar.gz"
curl -sSOL "https://www.nasm.us/pub/nasm/releasebuilds/${NASM_VERSION}/${tarball}"
tar xzf "${tarball}" -C "${WORK}" && rm "${tarball}"
fi
mkdir -p "${WORK}/build/nasm"
pushd "${WORK}/build/nasm"
if [[ ! -f "${WORK}/build/nasm/config.cache" ]]; then
echo "Configuring NASM..."
"${WORK}/nasm-${NASM_VERSION}/configure" \
--quiet \
--config-cache \
--disable-werror \
--prefix="${SYSROOT}" \
--srcdir="${WORK}/nasm-${NASM_VERSION}"
fi
echo "Building NASM..."
(make -j && make install) > "${WORK}/build/nasm_build.log"
popd
}
function build_binutils() {
if [[ ! -d "${WORK}/binutils-${BINUTILS_VERSION}" ]]; then
echo "Downloading binutils..."
tarball="binutils-${BINUTILS_VERSION}.tar.gz"
curl -sSOL "https://ftp.gnu.org/gnu/binutils/${tarball}"
tar xzf "${tarball}" -C "${WORK}" && rm "${tarball}"
fi
mkdir -p "${WORK}/build/binutils"
pushd "${WORK}/build/binutils"
if [[ ! -f "${WORK}/build/binutils/config.cache" ]]; then
echo "Configuring binutils..."
"${WORK}/binutils-${BINUTILS_VERSION}/configure" \
--quiet \
--config-cache \
--target="${TARGET}" \
--prefix="${SYSROOT}" \
--with-sysroot="${SYSROOT}" \
--with-lib-path="${SYSROOT}/lib" \
--disable-nls \
--disable-werror
fi
echo "Building binutils..."
(make -j && make install) > "${WORK}/build/binutils_build.log"
popd
}
function build_llvm() {
if [[ ! -d "${WORK}/llvm" ]]; then
echo "Downloading LLVM..."
git clone -q \
--branch "${LLVM_BRANCH}" \
--depth 1 \
"https://git.llvm.org/git/llvm.git" "${WORK}/llvm"
fi
for tool in ${TOOLS}; do
if [[ ! -d "${WORK}/llvm/tools/${tool}" ]]; then
echo "Downloading ${tool}..."
git clone -q \
--branch "${LLVM_BRANCH}" \
--depth 1 \
"https://git.llvm.org/git/${tool}.git" "${WORK}/llvm/tools/${tool}"
fi
done
if [[ ! -d "${WORK}/llvm/tools/clang/tools/extra" ]]; then
echo "Downloading clang-tools-extra..."
git clone -q \
--branch "${LLVM_BRANCH}" \
--depth 1 \
"https://git.llvm.org/git/clang-tools-extra.git" "${WORK}/llvm/tools/clang/tools/extra"
fi
for proj in ${PROJECTS}; do
if [[ ! -d "${WORK}/llvm/projects/${proj}" ]]; then
echo "Downloading ${proj}..."
git clone -q \
--branch "${LLVM_BRANCH}" \
--depth 1 \
"https://git.llvm.org/git/${proj}.git" "${WORK}/llvm/projects/${proj}"
fi
done
for proj in ${RUNTIMES}; do
if [[ ! -d "${WORK}/llvm/runtimes/${proj}" ]]; then
echo "Downloading ${proj}..."
git clone -q \
--branch "${LLVM_BRANCH}" \
--depth 1 \
"https://git.llvm.org/git/${proj}.git" "${WORK}/llvm/runtime/${proj}"
fi
done
mkdir -p "${WORK}/build/llvm"
pushd "${WORK}/build/llvm"
echo "Configuring LLVM..."
cmake -G Ninja \
-DCLANG_DEFAULT_RTLIB=compiler-rt \
-DCLANG_DEFAULT_STD_C=c11 \
-DCLANG_DEFAULT_STD_CXX=cxx14 \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_C_COMPILER="clang" \
-DCMAKE_CXX_COMPILER="clang++" \
-DCMAKE_CXX_FLAGS="-Wno-unused-parameter -D_LIBCPP_HAS_NO_ALIGNED_ALLOCATION -D_LIBUNWIND_IS_BAREMETAL=1 -U_LIBUNWIND_SUPPORT_DWARF_UNWIND" \
-DCMAKE_INSTALL_PREFIX="${SYSROOT}" \
-DCMAKE_MAKE_PROGRAM=`which ninja` \
-DDEFAULT_SYSROOT="${SYSROOT}" \
-DLIBCXX_CXX_ABI=libcxxabi \
-DLIBCXX_CXX_ABI_INCLUDE_PATHS="${WORK}/llvm/projects/libcxxabi/include" \
-DLIBCXX_CXX_ABI_LIBRARY_PATH=lib \
-DLIBCXX_ENABLE_EXPERIMENTAL_LIBRARY=OFF \
-DLIBCXX_ENABLE_NEW_DELETE_DEFINITIONS=ON \
-DLIBCXX_ENABLE_SHARED=OFF \
-DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON \
-DLIBCXX_ENABLE_THREADS=OFF \
-DLIBCXX_INCLUDE_BENCHMARKS=OFF \
-DLIBCXX_USE_COMPILER_RT=ON \
-DLIBCXXABI_ENABLE_NEW_DELETE_DEFINITIONS=OFF \
-DLIBCXXABI_ENABLE_SHARED=OFF \
-DLIBCXXABI_ENABLE_STATIC_UNWINDER=ON \
-DLIBCXXABI_ENABLE_THREADS=OFF \
-DLIBCXXABI_LIBCXX_PATH="${WORK}/llvm/projects/libcxx" \
-DLIBCXXABI_USE_COMPILER_RT=ON \
-DLIBCXXABI_USE_LLVM_UNWINDER=ON \
-DLIBUNWIND_ENABLE_SHARED=OFF \
-DLIBUNWIND_ENABLE_THREADS=OFF \
-DLIBUNWIND_USE_COMPILER_RT=ON \
-DLLVM_CONFIG_PATH="${SYSROOT}/bin/llvm-config" \
-DLLVM_DEFAULT_TARGET_TRIPLE="x86_64-unknown-elf" \
-DLLVM_ENABLE_LIBCXX=ON \
-DLLVM_ENABLE_PIC=OFF \
-DLLVM_ENABLE_THREADS=OFF \
-DLLVM_INSTALL_BINUTILS_SYMLINKS=ON \
-DLLVM_TARGETS_TO_BUILD="X86" \
${WORK}/llvm > cmake_configure.log
# -DCMAKE_ASM_COMPILER=nasm \
# -DCMAKE_LINKER="${SYSROOT}/bin/ld.lld" \
# -DCOMPILER_RT_ENABLE_LLD=ON \
# -DLIBCXX_ENABLE_LLD=ON \
# -DLIBCXX_ENABLE_STATIC_UNWINDER=ON \
# -DLIBCXXABI_ENABLE_LLD=ON \
# -DLIBUNWIND_ENABLE_LLD=ON \
# -DLLVM_ENABLE_LLD=ON \
# -DLLVM_ENABLE_PROJECTS="libcxx;libcxxabi;libunwind;compiler-rt" \
# -DCOMPILER_RT_BAREMETAL_BUILD=ON \
# -DLIBCXXABI_BAREMETAL=ON \
echo "Building LLVM..."
ninja && ninja install
ninja cxx cxxabi compiler-rt
ninja install-compiler-rt install-cxx install-cxxabi
popd
}
function build_libc() {
if [[ ! -d "${WORK}/poplibc" ]]; then
echo "Downloading poplibc..."
git clone \
"https://github.com/justinian/poplibc.git" \
"${WORK}/poplibc"
else
echo "Updating poplibc..."
git -C "${WORK}/poplibc" pull
fi
pushd "${WORK}/poplibc"
echo "Building poplibc..."
make install PREFIX="${SYSROOT}"
popd
}
function update_links() {
for exe in `ls "${SYSROOT}/bin/${TARGET}-"*`; do
base=$(echo "$exe" | sed -e "s/${TARGET}-//")
ln -fs "${exe}" "${base}"
done
}
build_nasm
build_binutils
build_libc
build_llvm
update_links
export CC="${SYSROOT}/bin/clang"
export CXX="${SYSROOT}/bin/clang++"
export LD="${SYSROOT}/bin/ld"
build_libc

View File

@@ -1,186 +0,0 @@
#!/usr/bin/env bash
TARGET="x86_64-elf"
NASM_VERSION="2.14.02"
GCC_VERSION="7.4.0"
BINUTILS_VERSION="2.31.1"
SYSROOT=$(realpath "$(dirname $0)/../sysroot")
WORK=$(realpath "$(dirname $0)/sysroot")
echo "Not currently supported"
exit 1
set -e
mkdir -p "${SYSROOT}"
mkdir -p "${WORK}"
function build_nasm() {
if [[ ! -d "${WORK}/nasm-${NASM_VERSION}" ]]; then
echo "Downloading NASM..."
tarball="nasm-${NASM_VERSION}.tar.gz"
curl -sSOL "https://www.nasm.us/pub/nasm/releasebuilds/${NASM_VERSION}/${tarball}"
tar xzf "${tarball}" -C "${WORK}" && rm "${tarball}"
fi
mkdir -p "${WORK}/build/nasm"
pushd "${WORK}/build/nasm"
if [[ ! -f "${WORK}/build/nasm/config.cache" ]]; then
echo "Configuring NASM..."
"${WORK}/nasm-${NASM_VERSION}/configure" \
--quiet \
--config-cache \
--disable-werror \
--prefix="${SYSROOT}" \
--srcdir="${WORK}/nasm-${NASM_VERSION}"
fi
echo "Building NASM..."
(make -j && make install) > "${WORK}/build/nasm_build.log"
popd
}
function build_binutils() {
if [[ ! -d "${WORK}/binutils-${BINUTILS_VERSION}" ]]; then
echo "Downloading binutils..."
tarball="binutils-${BINUTILS_VERSION}.tar.gz"
curl -sSOL "https://ftp.gnu.org/gnu/binutils/${tarball}"
tar xzf "${tarball}" -C "${WORK}" && rm "${tarball}"
fi
mkdir -p "${WORK}/build/binutils"
pushd "${WORK}/build/binutils"
if [[ ! -f "${WORK}/build/binutils/config.cache" ]]; then
echo "Configuring binutils..."
"${WORK}/binutils-${BINUTILS_VERSION}/configure" \
--quiet \
--config-cache \
--target="${TARGET}" \
--prefix="${SYSROOT}" \
--with-sysroot="${SYSROOT}" \
--with-lib-path="${SYSROOT}/lib" \
--disable-nls \
--disable-werror
fi
echo "Building binutils..."
(make -j && make install) > "${WORK}/build/binutils_build.log"
popd
}
function build_gcc() {
if [[ ! -d "${WORK}/gcc-${GCC_VERSION}" ]]; then
echo "Downloading GCC..."
tarball="gcc-${GCC_VERSION}.tar.gz"
curl -sSOL "https://ftp.gnu.org/gnu/gcc/gcc-${GCC_VERSION}/${tarball}"
tar xzf "${tarball}" -C "${WORK}" && rm "${tarball}"
# no-red-zone support version of libgcc
echo "MULTILIB_OPTIONS += mno-red-zone" > "${WORK}/gcc-${GCC_VERSION}/gcc/config/i386/t-${TARGET}"
echo "MULTILIB_DIRNAMES += no-red-zone" >> "${WORK}/gcc-${GCC_VERSION}/gcc/config/i386/t-${TARGET}"
cat <<EOF >> "${WORK}/gcc-${GCC_VERSION}/gcc/config.gcc"
case \${target} in
${TARGET})
tmake_file="\${tmake_file} i386/t-${TARGET}"
;;
esac
EOF
fi
mkdir -p "${WORK}/build/gcc"
pushd "${WORK}/build/gcc"
if [[ ! -f "${WORK}/build/gcc/config.cache" ]]; then
echo "Configuring GCC..."
"${WORK}/gcc-${GCC_VERSION}/configure" \
--quiet \
--config-cache \
--target="${TARGET}" \
--prefix="${SYSROOT}" \
--with-sysroot="${SYSROOT}" \
--with-native-system-header-dir="${SYSROOT}/include" \
--with-newlib \
--without-headers \
--disable-nls \
--enable-languages=c,c++ \
--disable-shared \
--disable-multilib \
--disable-decimal-float \
--disable-threads \
--disable-libatomic \
--disable-libgomp \
--disable-libmpx \
--disable-libquadmath \
--disable-libssp \
--disable-libvtv \
--disable-libstdcxx
fi
echo "Building GCC..."
(make -j all-gcc && make -j all-target-libgcc && \
make install-gcc && make install-target-libgcc) > "${WORK}/build/gcc_build.log"
popd
}
function build_libstdcxx() {
mkdir -p "${WORK}/build/libstdcxx"
pushd "${WORK}/build/libstdcxx"
if [[ ! -f "${WORK}/build/libstdcxx/config.cache" ]]; then
echo "Configuring libstdc++..."
CFLAGS="-I${SYSROOT}/include" \
CXXFLAGS="-I${SYSROOT}/include" \
"${WORK}/gcc-${GCC_VERSION}/libstdc++-v3/configure" \
--config-cache \
--host="${TARGET}" \
--target="${TARGET}" \
--prefix="${SYSROOT}" \
--disable-nls \
--disable-multilib \
--with-newlib \
--disable-libstdcxx-threads \
--disable-libstdcxx-pch \
--with-gxx-include-dir="${SYSROOT}/include/c++"
fi
echo "Building libstdc++..."
(make -j && make install) > "${WORK}/build/libstdcxx_build.log"
popd
}
function build_libc() {
if [[ ! -d "${WORK}/poplibc" ]]; then
echo "Downloading poplibc..."
git clone \
"https://github.com/justinian/poplibc.git" \
"${WORK}/poplibc"
else
echo "Updating poplibc..."
git -C "${WORK}/poplibc" pull
fi
pushd "${WORK}/poplibc"
echo "Building poplibc..."
make install PREFIX="${SYSROOT}"
popd
}
function update_links() {
for exe in `ls "${SYSROOT}/bin/${TARGET}-"*`; do
base=$(echo "$exe" | sed -e "s/${TARGET}-//")
ln -fs "${exe}" "${base}"
done
}
build_nasm
build_binutils
build_gcc
update_links
export PATH="${SYSROOT}/bin:${PATH}"
build_libc
build_libstdcxx

75
scripts/fontpsf.py Normal file
View File

@@ -0,0 +1,75 @@
_MAGIC = (0x72, 0xb5, 0x4a, 0x86)
_VERSION = 0
class PSF2:
from collections import namedtuple
Header = namedtuple("PSF2Header",
["version", "offset", "flags", "count", "charsize", "height", "width"])
def __init__(self, filename, header, data):
self.__filename = filename
self.__header = header
self.__data = data
data = property(lambda self: self.__data)
header = property(lambda self: self.__header)
count = property(lambda self: self.__header.count)
charsize = property(lambda self: self.__header.charsize)
dimension = property(lambda self: (self.__header.width, self.__header.height))
filename = property(lambda self: self.__filename)
@classmethod
def load(cls, filename):
from os.path import basename
from struct import unpack_from
data = open(filename, 'rb').read()
fmt = "BBBBIIIIIII"
values = unpack_from(fmt, data)
if values[:len(_MAGIC)] != _MAGIC:
raise Exception("Bad magic number in header")
header = PSF2.Header(*values[len(_MAGIC):])
if header.version != _VERSION:
raise Exception(f"Bad version {header.version} in header")
return cls(basename(filename), header, data)
class Glyph:
__slots__ = ['index', 'data']
def __init__(self, i, data):
self.index = i
self.data = data
def __index__(self):
return self.index
def empty(self):
return not bool([b for b in self.data if b != 0])
def description(self):
c = chr(self.index)
if c.isprintable():
return "Glyph {:02x}: '{}'".format(self.index, c)
else:
return "Glyph {:02x}".format(self.index)
def __getitem__(self, i):
c = self.__header.charsize
n = i * c + self.__header.offset
return PSF2.Glyph(i, self.__data[n:n+c])
class __iter:
__slots__ = ['font', 'n']
def __init__(self, font):
self.font = font
self.n = 0
def __next__(self):
if self.n < self.font.count:
glyph = self.font[self.n]
self.n += 1
return glyph
else:
raise StopIteration
def __iter__(self):
return PSF2.__iter(self)

34
scripts/parse_font.py Normal file → Executable file
View File

@@ -1,21 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
MAGIC = (0x72, 0xb5, 0x4a, 0x86) from fontpsf import PSF2
from collections import namedtuple
PSF2 = namedtuple("PSF2", ["version", "offset", "flags", "count", "charsize", "height", "width"])
def read_header(data):
from struct import unpack_from, calcsize
fmt = "BBBBIIIIIII"
values = unpack_from(fmt, data)
if values[:len(MAGIC)] != MAGIC:
raise Exception("Bad magic number in header")
return PSF2(*values[len(MAGIC):])
def print_glyph(header, data): def print_glyph(header, data):
bw = (header.width + 7) // 8 bw = (header.width + 7) // 8
@@ -28,16 +13,15 @@ def print_glyph(header, data):
def display_font(filename): def display_font(filename):
data = open(filename, 'rb').read() font = PSF2.load(filename)
print(font.header)
header = read_header(data) for glyph in font:
print(header) if glyph.empty():
print("{}: BLANK".format(glyph.description()))
c = header.charsize else:
for i in range(0, header.count): print("{}:".format(glyph.description()))
n = i * c + header.offset print_glyph(font.header, glyph.data)
print("Glyph {}:".format(i))
print_glyph(header, data[n:n+c])
if __name__ == "__main__": if __name__ == "__main__":

10
scripts/parse_syms.py Executable file
View File

@@ -0,0 +1,10 @@
#!/usr/bin/env python3
def parse_elf(filename):
import struct
with open(filename, 'rb') as elf:
if __name__ == "__main__":
import sys
for arg in sys.argv[1:]:
parse_elf(arg)

27
scripts/psf_to_cpp.py Executable file
View File

@@ -0,0 +1,27 @@
#!/usr/bin/env python3
from fontpsf import PSF2
def print_header(filename):
font = PSF2.load(filename)
print("#pragma once")
print(f"// This file was autogenerated by psf_to_cpp.py from {font.filename}\n")
print(f"const uint8_t font_glyph_size = {font.charsize};")
print(f"const uint8_t font_glyph_width = {font.dimension[0]};")
print(f"const uint8_t font_glyph_height = {font.dimension[1]};")
print(f"const uint16_t font_glyph_count = {font.count};\n")
print('const uint8_t font_glyph_data[] = {')
for glyph in font:
print(" ", "".join([f"0x{b:02x}," for b in glyph.data]), end="")
print(" // {}".format(glyph.description()))
print("};")
if __name__ == "__main__":
import sys
for filename in sys.argv[1:]:
print_header(filename)

View File

@@ -0,0 +1,14 @@
# jsix OS sysroot
This is a pre-built sysroot for building the jsix operating system kernel,
bootloader, and utilities. This package is provided as a convenience, and
contains software from the following repositories.
## The LLVM toolchain
The LLVM sources as downloaded via git from [llvm.org][llvm] under the terms of
the [Apache License v2.0][apache2], modified [as described here][llvmlic].
[llvm]: https://llvm.org
[apache2]: https://www.apache.org/licenses/LICENSE-2.0
[llvmlic]: https://llvm.org/docs/DeveloperPolicy.html#new-llvm-project-license-framework

View File

@@ -1,17 +1,127 @@
{% extends "build.base.j2" %} ninja_required_version = 1.3
builddir = {{ buildroot }}
srcroot = {{ srcroot }}
modulefile = {{ modulefile }}
{% block variables %} {%- for var, value in vars %}
{{ super() }} {{ var }} = {{ value }}
ccflags = $ccflags $ {%- endfor %}
warnflags = $
-Wformat=2 $
-Winit-self $
-Wfloat-equal $
-Winline $
-Wmissing-format-attribute $
-Wmissing-include-dirs $
-Wswitch $
-Wundef $
-Wdisabled-optimization $
-Wpointer-arith $
-Wno-attributes $
-Wno-sign-compare $
-Wno-multichar $
-Wno-div-by-zero $
-Wno-endif-labels $
-Wno-pragmas $
-Wno-format-extra-args $
-Wno-unused-result $
-Wno-deprecated-declarations $
-Wno-unused-function $
-Wno-address-of-packed-member $
-Werror
ccflags = $
-I${srcroot}/src/include $ -I${srcroot}/src/include $
-I${srcroot}/src/include/x86_64 -I${srcroot}/src/include/x86_64 $
{% endblock %} -fcolor-diagnostics $
-DVERSION_MAJOR={{ version_major }} $
-DVERSION_MINOR={{ version_minor }} $
-DVERSION_PATCH={{ version_patch }} $
-DVERSION_GITSHA=0x0{{ version_sha }} $
-DGIT_VERSION=\"{{ version }}\" $
-DGIT_VERSION_WIDE=L\"{{ version }}\" $
$warnflags
{% block baserules %} asflags = $
{{ super() }} -DVERSION_MAJOR={{ version_major }} $
rule makerd -DVERSION_MINOR={{ version_minor }} $
description = Making init ramdisk -DVERSION_PATCH={{ version_patch }} $
command = $builddir/native/makerd $in $out -DVERSION_GITSHA=0x{{ version_sha }} $
-I${srcroot}/src/include
cflags = -std=c11
cxxflags = -std=c++17
libs =
rule c
deps = gcc
depfile = $out.d
description = Compiling $name
command = $cc -MMD -MF $out.d $ccflags $cflags -o $out -c $in
rule dump_c_defs
description = Dumping C defines for $target
command = echo "" | $cc $ccflags $cflags -dM -E - > $out
rule dump_c_run
description = Dumping C arguments for $target
command = $
echo "#!/bin/bash" > $out; $
echo '$cc $ccflags $cflags $$*' >> $out; $
chmod a+x $out
rule cpp
deps = gcc
depfile = $out.d
description = Compiling $name
command = $cxx -MMD -MF $out.d $cxxflags $ccflags -o $out -c $in
rule dump_cpp_defs
description = Dumping C++ defines for $target
command = echo "" | $cxx -x c++ $cxxflags $ccflags -dM -E - > $out
rule dump_cpp_run
description = Dumping C++ arguments for $target
command = $
echo "#!/bin/bash" > $out; $
echo '$cc $cxxflags $ccflags $$*' >> $out; $
chmod a+x $out
rule s
deps = gcc
depfile = $out.d
description = Assembling $name
command = $nasm -o $out -felf64 -MD $out.d $asflags $in
rule exe
description = Linking $name
command = $ld $ldflags -o $out $in $libs
rule lib
description = Archiving $name
command = $ar qcs $out $in
rule regen
generator = true
description = Regenrating build files
command = $
{{ generator }} $
--file $modulefile $
--dir $builddir $
generate
rule cp
description = Copying $name
command = cp $in $out
rule dump
description = Dumping decompiled $name
command = objdump -DSC -M intel $in > $out
rule makest
description = Making symbol table
command = nm $in | ${srcroot}/scripts/build_symbol_table.py $out
rule makeefi rule makeefi
description = Converting $name description = Converting $name
@@ -40,47 +150,65 @@ rule strip
objcopy --only-keep-debug $out $out.debug; $ objcopy --only-keep-debug $out $out.debug; $
strip -g $out; $ strip -g $out; $
objcopy --add-gnu-debuglink=$out.debug $out objcopy --add-gnu-debuglink=$out.debug $out
{% endblock %}
{% block extra %} {% for target in targets %}
subninja {{ target }}/target.ninja
{% endfor %}
build $
{%- for buildfile in buildfiles %}
{{ buildfile }} $
{%- endfor %}
: regen | $
{%- for template in templates %}
{{ template }} $
{%- endfor %}
$modulefile $
{{ generator }}
build $builddir/ovmf_vars.fd : cp $srcroot/assets/ovmf/x64/ovmf_vars.fd build $builddir/ovmf_vars.fd : cp $srcroot/assets/ovmf/x64/ovmf_vars.fd
name = ovmf_vars.fd name = ovmf_vars.fd
build $builddir/ovmf_vars_d.fd : cp $srcroot/assets/ovmf/x64/ovmf_vars_d.fd build $builddir/ovmf_vars_d.fd : cp $srcroot/assets/ovmf/x64/ovmf_vars_d.fd
name = ovmf_vars_d.fd name = ovmf_vars_d.fd
build $builddir/popcorn.elf | $builddir/popcorn.elf.debug : strip $builddir/host/popcorn.elf build $builddir/jsix.elf | $builddir/jsix.elf.debug : strip $builddir/host/jsix.elf
name = kernel name = kernel
build $builddir/popcorn.dump : dump $builddir/host/popcorn.elf build $builddir/jsix.dump : dump $builddir/host/jsix.elf
name = kernel name = kernel
build $builddir/popcorn.elf-gdb.py : cp ${srcroot}/assets/debugging/popcorn.elf-gdb.py build $builddir/jsix.elf-gdb.py : cp ${srcroot}/assets/debugging/jsix.elf-gdb.py
name = kernel debug python scripts name = kernel debug python scripts
build $builddir/fatroot/popcorn.elf : cp $builddir/popcorn.elf build $builddir/fatroot/jsix.elf : cp $builddir/jsix.elf
name = kernel to FAT image name = kernel to FAT image
build $builddir/fatroot/efi/boot/bootx64.efi : cp $builddir/boot/boot.efi build $builddir/fatroot/efi/boot/bootx64.efi : cp $builddir/boot/boot.efi
name = bootloader to FAT image name = bootloader to FAT image
build $builddir/fatroot/initrd.img : makerd ${srcroot}/assets/initrd.toml | $ build $builddir/fatroot/nulldrv.elf : cp $builddir/user/nulldrv.elf
${builddir}/native/makerd $ name = null driver to FAT image
${builddir}/user/nulldrv
build $builddir/popcorn.img : makefat | $ build $builddir/fatroot/fb.elf : cp $builddir/user/fb.elf
$builddir/fatroot/initrd.img $ name = fb driver to FAT image
$builddir/fatroot/popcorn.elf $
build ${builddir}/fatroot/symbol_table.dat : makest ${builddir}/jsix.elf
build $builddir/jsix.img : makefat | $
$builddir/fatroot/symbol_table.dat $
$builddir/fatroot/nulldrv.elf $
$builddir/fatroot/fb.elf $
$builddir/fatroot/jsix.elf $
$builddir/fatroot/efi/boot/bootx64.efi $builddir/fatroot/efi/boot/bootx64.efi
name = popcorn.img name = jsix.img
default $ default $
$builddir/ovmf_vars.fd $ $builddir/ovmf_vars.fd $
$builddir/ovmf_vars_d.fd $ $builddir/ovmf_vars_d.fd $
$builddir/popcorn.dump $ $builddir/jsix.dump $
$builddir/popcorn.elf-gdb.py $ $builddir/jsix.elf-gdb.py $
$builddir/popcorn.img $builddir/jsix.img
{% endblock %}
# vim: ft=ninja et ts=4 sts=4 sw=4 # vim: ft=ninja et ts=4 sts=4 sw=4

View File

@@ -3,23 +3,10 @@
{{ super() }} {{ super() }}
ccflags = $ccflags $ ccflags = $ccflags $
-DKERNEL_FILENAME=L\"popcorn.elf\" $ -g3 $
-DGNU_EFI_USE_MS_ABI $ -DKERNEL_FILENAME=L\"jsix.elf\" $
-DHAVE_USE_MS_ABI $ -I${srcroot}/external/include $
-DEFI_DEBUG=0 $ -I${srcroot}/external/include/X64
-DEFI_DEBUG_CLEAR_MEMORY=0 $
-DBOOTLOADER_DEBUG
ldflags = $ldflags $
-T ${srcroot}/src/arch/x86_64/boot.ld $
-shared
{% endblock %}
{% block extra %}
build $builddir/boot.efi : makeefi ${builddir}/{{ module.output }}
name = boot.efi
{% endblock %} {% endblock %}

View File

@@ -0,0 +1,8 @@
{% extends "module.base.j2" %}
{% block variables %}
{{ super() }}
{% endblock %}
# vim: ft=ninja et ts=4 sts=4 sw=4

View File

@@ -5,6 +5,7 @@
asflags = $asflags -I${srcroot}/src/kernel/ asflags = $asflags -I${srcroot}/src/kernel/
libs = $libs libs = $libs
ldflags = $ldflags -T ${srcroot}/src/arch/x86_64/kernel.ld ldflags = $ldflags -T ${srcroot}/src/arch/x86_64/kernel.ld
ccflags = $ccflags -I${srcroot}/external
{% endblock %} {% endblock %}

View File

@@ -0,0 +1,10 @@
{% extends "exe.default.j2" %}
{% block variables %}
{{ super() }}
ccflags = $ccflags -I${srcroot}/external/cpptoml
{% endblock %}
# vim: ft=ninja et ts=4 sts=4 sw=4

View File

@@ -2,7 +2,7 @@
{% block variables %} {% block variables %}
{{ super() }} {{ super() }}
ccflags = $ccflags -ggdb ccflags = $ccflags -ggdb -I${srcroot}/external/catch
{% endblock %} {% endblock %}

View File

@@ -0,0 +1,4 @@
{% extends "module.base.j2" %}
# vim: ft=ninja et ts=4 sts=4 sw=4

View File

@@ -0,0 +1,45 @@
moddir = ${builddir}/{{ name }}.dir
{% block variables %}
ccflags = $ccflags $
{%- for dep in depmods %}
{%- for inc in dep.includes %}
-I${srcroot}/{{ inc }} $
{%- endfor %}
{%- endfor %}
{%- for inc in module.includes %}
-I${srcroot}/{{ inc }} $
{%- endfor %}
{%- for define in module.defines %}
-D{{ define }} $
{%- endfor %}
{% endblock %}
{% for source in module.source %}
build ${moddir}/{{ source.output }} : {{ source.action }} ${srcroot}/{{ source.input }} || {{ buildfile }}
name = {{ source.name }}
{% endfor %}
build ${builddir}/{{ module.output }} : {{ module.kind }} $
{%- for source in module.source %}
${moddir}/{{ source.output }} $
{%- endfor -%}
{%- for dep in deplibs %}
${builddir}/{{ dep.output }} $
{%- endfor %}
| $
{%- for dep in depexes %}
${builddir}/{{ dep.output }} $
{%- endfor %}
{{ buildfile }}
name = {{ name }}
{% if module.default %}
default ${builddir}/{{ module.output }}
{% endif %}
{% block extra %}
{% endblock %}
# vim: ft=ninja et ts=4 sts=4 sw=4

View File

@@ -3,7 +3,7 @@
{% block binaries %} {% block binaries %}
cc = clang cc = clang
cxx = clang++ cxx = clang++
ld = ld ld = clang++
ar = ar ar = ar
nasm = nasm nasm = nasm
objcopy = objcopy objcopy = objcopy
@@ -12,28 +12,25 @@ objcopy = objcopy
{% block variables %} {% block variables %}
ccflags = $ccflags $ ccflags = $ccflags $
-ggdb $ -I $srcroot/external $
-nostdlib $ --target=x86_64-unknown-windows $
-ffreestanding $ -ffreestanding $
-nodefaultlibs $
-fno-builtin $
-mno-sse $
-fno-omit-frame-pointer $
-mno-red-zone $ -mno-red-zone $
-fshort-wchar $ -fshort-wchar $
-D__ELF__ $ -fno-omit-frame-pointer $
-fPIC -ggdb
cxxflags = $cxxflags $ cxxflags = $cxxflags $
-fno-exceptions $ -fno-rtti $
-fno-rtti $ -fno-exceptions
ldflags = $ldflags $ ldflags = $ldflags $
-g $ --target=x86_64-unknown-windows $
-nostdlib $ -nostdlib $
-znocombreloc $ -Wl,-entry:efi_main $
-Bsymbolic $ -Wl,-subsystem:efi_application $
-nostartfiles -fuse-ld=lld-link $
-g
{% endblock %} {% endblock %}

View File

@@ -0,0 +1,31 @@
builddir = $builddir/{{ target }}
target = {{ target }}
{% block variables %}
{% endblock %}
{% block binaries %}
cc = clang
cxx = clang++
ld = ld
ar = ar
nasm = nasm
objcopy = objcopy
{% endblock %}
{% for module in modules %}
subninja {{ module }}.ninja
{% endfor %}
build ${builddir}/c.defs : dump_c_defs | {{ buildfile }}
build ${builddir}/cpp.defs : dump_cpp_defs | {{ buildfile }}
build ${builddir}/c.run : dump_c_run | {{ buildfile }}
build ${builddir}/cpp.run : dump_cpp_run | {{ buildfile }}
default ${builddir}/c.defs
default ${builddir}/cpp.defs
default ${builddir}/c.run
default ${builddir}/cpp.run
# vim: ft=ninja et ts=4 sts=4 sw=4

View File

@@ -3,10 +3,10 @@
{% block binaries %} {% block binaries %}
cc = ${srcroot}/sysroot/bin/clang cc = ${srcroot}/sysroot/bin/clang
cxx = ${srcroot}/sysroot/bin/clang++ cxx = ${srcroot}/sysroot/bin/clang++
ld = ${srcroot}/sysroot/bin/x86_64-elf-ld ld = ${srcroot}/sysroot/bin/ld.lld
ar = ${srcroot}/sysroot/bin/x86_64-elf-ar ar = ${srcroot}/sysroot/bin/ar
nasm = ${srcroot}/sysroot/bin/nasm nasm = nasm
objcopy = ${srcroot}/sysroot/bin/x86_64-elf-objcopy objcopy = ${srcroot}/sysroot/bin/objcopy
{% endblock %} {% endblock %}
{% block variables %} {% block variables %}
@@ -22,8 +22,9 @@ ccflags = $ccflags $
-g $ -g $
-mcmodel=large $ -mcmodel=large $
-D__ELF__ $ -D__ELF__ $
-D__POPCORN__ $ -D__JSIX__ $
-isystem${srcroot}/sysroot/include $ -isystem${srcroot}/sysroot/include $
-isystem${srcroot}/src/libraries/libc/include $
--sysroot="${srcroot}/sysroot" --sysroot="${srcroot}/sysroot"
cxxflags = $cxxflags $ cxxflags = $cxxflags $
@@ -34,9 +35,7 @@ cxxflags = $cxxflags $
ldflags = $ldflags $ ldflags = $ldflags $
-g $ -g $
-nostdlib $ -nostdlib $
-znocombreloc $
-Bsymbolic $ -Bsymbolic $
-nostartfiles $
-Bstatic -Bstatic
{% endblock %} {% endblock %}

View File

@@ -3,10 +3,10 @@
{% block binaries %} {% block binaries %}
cc = ${srcroot}/sysroot/bin/clang cc = ${srcroot}/sysroot/bin/clang
cxx = ${srcroot}/sysroot/bin/clang++ cxx = ${srcroot}/sysroot/bin/clang++
ld = ${srcroot}/sysroot/bin/x86_64-elf-ld ld = ${srcroot}/sysroot/bin/ld.lld
ar = ${srcroot}/sysroot/bin/x86_64-elf-ar ar = ${srcroot}/sysroot/bin/ar
nasm = ${srcroot}/sysroot/bin/nasm nasm = nasm
objcopy = ${srcroot}/sysroot/bin/x86_64-elf-objcopy objcopy = ${srcroot}/sysroot/bin/objcopy
{% endblock %} {% endblock %}
{% block variables %} {% block variables %}
@@ -21,8 +21,9 @@ ccflags = $ccflags $
-g $ -g $
-mcmodel=large $ -mcmodel=large $
-D__ELF__ $ -D__ELF__ $
-D__POPCORN__ $ -D__JSIX__ $
-isystem${srcroot}/sysroot/include $ -isystem${srcroot}/sysroot/include $
-isystem${srcroot}/src/libraries/libc/include $
--sysroot="${srcroot}/sysroot" --sysroot="${srcroot}/sysroot"
cxxflags = $cxxflags $ cxxflags = $cxxflags $
@@ -33,16 +34,11 @@ cxxflags = $cxxflags $
ldflags = $ldflags $ ldflags = $ldflags $
-g $ -g $
-nostdlib $ -nostdlib $
-znocombreloc $
-Bsymbolic $ -Bsymbolic $
-nostartfiles $
-Bstatic $ -Bstatic $
--sysroot="${srcroot}/sysroot" $ --sysroot="${srcroot}/sysroot" $
-L "${srcroot}/sysroot/lib" $ -L "${srcroot}/sysroot/lib" $
libs = $libs $
-lc
{% endblock %} {% endblock %}
# vim: ft=ninja et ts=4 sts=4 sw=4 # vim: ft=ninja et ts=4 sts=4 sw=4

View File

@@ -1,79 +0,0 @@
/* Linker script originally from GNU-EFI project
* https://sourceforge.net/p/gnu-efi/
*/
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
OUTPUT_ARCH(i386:x86-64)
ENTRY(_start)
SECTIONS
{
. = 0;
ImageBase = .;
/* .hash and/or .gnu.hash MUST come first! */
.hash : { *(.hash) }
.gnu.hash : { *(.gnu.hash) }
. = ALIGN(4096);
.eh_frame :
{
*(.eh_frame)
}
. = ALIGN(4096);
.text :
{
_text = .;
*(.text)
*(.text.*)
*(.gnu.linkonce.t.*)
. = ALIGN(16);
}
_etext = .;
_text_size = . - _text;
. = ALIGN(4096);
.reloc :
{
*(.reloc)
}
. = ALIGN(4096);
.data :
{
_data = .;
*(.rodata*)
*(.got.plt)
*(.got)
*(.data*)
*(.sdata)
/* the EFI loader doesn't seem to like a .bss section, so we stick
it all into .data: */
*(.sbss)
*(.scommon)
*(.dynbss)
*(.bss)
*(COMMON)
*(.rel.local)
}
.note.gnu.build-id : { *(.note.gnu.build-id) }
_edata = .;
_data_size = . - _etext;
. = ALIGN(4096);
.dynamic : { *(.dynamic) }
. = ALIGN(4096);
.rela :
{
*(.rela.data*)
*(.rela.got)
*(.rela.stab)
}
. = ALIGN(4096);
.dynsym : { *(.dynsym) }
. = ALIGN(4096);
.dynstr : { *(.dynstr) }
. = ALIGN(4096);
.ignored.reloc :
{
*(.rela.reloc)
*(.eh_frame)
*(.note.GNU-stack)
}
.comment 0 : { *(.comment) }
}

View File

@@ -1,8 +1,7 @@
ENTRY(_start) ENTRY(_kernel_start)
SECTIONS SECTIONS
{ {
OFFSET = 0xFFFFFF0000000000; . = 0xFFFF800000000000;
. = OFFSET + 0x100000;
.header : { .header : {
__header_start = .; __header_start = .;
@@ -10,29 +9,32 @@ SECTIONS
__header_end = .; __header_end = .;
} }
.text : { .text ALIGN(4096) : {
*(.text) *(.text)
*(.isrs)
} }
.data : { .data ALIGN(4096) : {
*(.data) *(.data)
*(.rodata) *(.rodata)
} }
.isrs : { .ctors : ALIGN(8) {
*(.isrs) __ctors = .;
KEEP(*(.ctors))
__ctors_end = .;
}
.bss ALIGN(4096) : {
__bss_start = .;
*(.bss)
__bss_end = .;
} }
.note : { .note : {
*(.note.*) *(.note.*)
} }
.bss ALIGN(16) : {
__bss_start = .;
*(.bss)
__bss_end = .;
}
.eh_frame : { .eh_frame : {
__eh_frame_start = .; __eh_frame_start = .;
KEEP(*(.eh_frame)) KEEP(*(.eh_frame))

View File

@@ -1,94 +1,152 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <uefi/types.h>
#include <uefi/graphics.h>
#include <uefi/protos/graphics_output.h>
#include "console.h" #include "console.h"
#include "guids.h" #include "error.h"
#include "utility.h"
#ifndef GIT_VERSION_WIDE
#define GIT_VERSION_WIDE L"no version"
#endif
namespace boot {
size_t ROWS = 0; size_t ROWS = 0;
size_t COLS = 0; size_t COLS = 0;
static EFI_SIMPLE_TEXT_OUT_PROTOCOL *m_out = 0; console *console::s_console = nullptr;
static const wchar_t digits[] = {u'0', u'1', u'2', u'3', u'4', u'5', static const wchar_t digits[] = {u'0', u'1', u'2', u'3', u'4', u'5',
u'6', u'7', u'8', u'9', u'a', u'b', u'c', u'd', u'e', u'f'}; u'6', u'7', u'8', u'9', u'a', u'b', u'c', u'd', u'e', u'f'};
console::console(EFI_SYSTEM_TABLE *system_table) :
m_rows(0), static size_t
m_cols(0), wstrlen(const wchar_t *s)
m_out(nullptr)
{ {
size_t count = 0;
while (s && *s++) count++;
return count;
}
console::console(uefi::boot_services *bs, uefi::protos::simple_text_output *out) :
m_rows {0},
m_cols {0},
m_out {out},
m_fb {0, 0}
{
pick_mode(bs);
try_or_raise(
m_out->query_mode(m_out->mode->mode, &m_cols, &m_rows),
L"Failed to get text output mode.");
try_or_raise(
m_out->clear_screen(),
L"Failed to clear screen");
m_out->set_attribute(uefi::attribute::light_cyan);
m_out->output_string(L"jsix loader ");
m_out->set_attribute(uefi::attribute::light_magenta);
m_out->output_string(GIT_VERSION_WIDE);
m_out->set_attribute(uefi::attribute::light_gray);
m_out->output_string(L" booting...\r\n\n");
if (m_fb.type != kernel::args::fb_type::none) {
wchar_t const * type = nullptr;
switch (m_fb.type) {
case kernel::args::fb_type::rgb8:
type = L"rgb8";
break;
case kernel::args::fb_type::bgr8:
type = L"bgr8";
break;
default:
type = L"unknown";
}
printf(L"Found framebuffer: %dx%d[%d] type %s @0x%x\r\n",
m_fb.horizontal, m_fb.vertical, m_fb.scanline, type, m_fb.phys_addr);
} else {
printf(L"No framebuffer found.\r\n");
}
s_console = this; s_console = this;
m_boot = system_table->BootServices;
m_out = system_table->ConOut;
} }
EFI_STATUS void
console::initialize(const wchar_t *version) console::pick_mode(uefi::boot_services *bs)
{ {
EFI_STATUS status; uefi::status status;
uefi::protos::graphics_output *gfx_out_proto;
uefi::guid guid = uefi::protos::graphics_output::guid;
// Might not find a video device at all, so ignore not found errors m_fb.type = kernel::args::fb_type::none;
status = pick_mode();
if (status != EFI_NOT_FOUND)
CHECK_EFI_STATUS_OR_FAIL(status);
status = m_out->QueryMode(m_out, m_out->Mode->Mode, &m_cols, &m_rows); uefi::status has_gop = bs->locate_protocol(&guid, nullptr,
CHECK_EFI_STATUS_OR_RETURN(status, "QueryMode"); (void **)&gfx_out_proto);
status = m_out->ClearScreen(m_out); if (has_gop != uefi::status::success)
CHECK_EFI_STATUS_OR_RETURN(status, "ClearScreen"); // No video output found, skip it
return;
m_out->SetAttribute(m_out, EFI_LIGHTCYAN); const uint32_t modes = gfx_out_proto->mode->max_mode;
m_out->OutputString(m_out, (wchar_t *)L"Popcorn loader "); uint32_t best = gfx_out_proto->mode->mode;
m_out->SetAttribute(m_out, EFI_LIGHTMAGENTA); uefi::graphics_output_mode_info *info =
m_out->OutputString(m_out, (wchar_t *)version); (uefi::graphics_output_mode_info *)gfx_out_proto->mode;
m_out->SetAttribute(m_out, EFI_LIGHTGRAY); uint32_t res = info->horizontal_resolution * info->vertical_resolution;
m_out->OutputString(m_out, (wchar_t *)L" booting...\r\n\n"); int pixmode = static_cast<int>(info->pixel_format);
return status;
}
EFI_STATUS
console::pick_mode()
{
EFI_STATUS status;
EFI_GRAPHICS_OUTPUT_PROTOCOL *gfx_out_proto;
status = m_boot->LocateProtocol(&guid_gfx_out, NULL, (void **)&gfx_out_proto);
CHECK_EFI_STATUS_OR_RETURN(status, "LocateProtocol gfx");
const uint32_t modes = gfx_out_proto->Mode->MaxMode;
uint32_t best = gfx_out_proto->Mode->Mode;
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info =
(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *)gfx_out_proto->Mode;
uint32_t res = info->HorizontalResolution * info->VerticalResolution;
int is_fb = info->PixelFormat != PixelBltOnly;
for (uint32_t i = 0; i < modes; ++i) { for (uint32_t i = 0; i < modes; ++i) {
size_t size = 0; size_t size = 0;
status = gfx_out_proto->QueryMode(gfx_out_proto, i, &size, &info);
CHECK_EFI_STATUS_OR_RETURN(status, "QueryMode"); try_or_raise(
gfx_out_proto->query_mode(i, &size, &info),
L"Failed to find a graphics mode the driver claimed to support");
#ifdef MAX_HRES #ifdef MAX_HRES
if (info->HorizontalResolution > MAX_HRES) continue; if (info->horizontal_resolution > MAX_HRES) continue;
#endif #endif
const uint32_t new_res = info->HorizontalResolution * info->VerticalResolution; const uint32_t new_res = info->horizontal_resolution * info->vertical_resolution;
const int new_is_fb = info->PixelFormat == PixelBltOnly; int new_pixmode = static_cast<int>(info->pixel_format);
if (new_is_fb > is_fb && new_res >= res) { if (new_pixmode <= pixmode && new_res >= res) {
best = i; best = i;
res = new_res; res = new_res;
pixmode = new_pixmode;
} }
} }
status = gfx_out_proto->SetMode(gfx_out_proto, best); try_or_raise(
CHECK_EFI_STATUS_OR_RETURN(status, "SetMode %d/%d", best, modes); gfx_out_proto->set_mode(best),
return EFI_SUCCESS; L"Failed to set graphics mode");
if (pixmode <= static_cast<int>(uefi::pixel_format::bgr8)) {
m_fb.phys_addr = gfx_out_proto->mode->frame_buffer_base;
m_fb.size = gfx_out_proto->mode->frame_buffer_size;
m_fb.vertical = gfx_out_proto->mode->info->vertical_resolution;
m_fb.horizontal = gfx_out_proto->mode->info->horizontal_resolution;
m_fb.scanline = gfx_out_proto->mode->info->pixels_per_scanline;
switch (gfx_out_proto->mode->info->pixel_format) {
case uefi::pixel_format::rgb8:
m_fb.type = kernel::args::fb_type::rgb8;
break;
case uefi::pixel_format::bgr8:
m_fb.type = kernel::args::fb_type::bgr8;
break;
default:
m_fb.type = kernel::args::fb_type::none;
}
}
} }
size_t size_t
@@ -97,11 +155,11 @@ console::print_hex(uint32_t n) const
wchar_t buffer[9]; wchar_t buffer[9];
wchar_t *p = buffer; wchar_t *p = buffer;
for (int i = 7; i >= 0; --i) { for (int i = 7; i >= 0; --i) {
uint8_t nibble = (n & (0xf << (i*4))) >> (i*4); uint8_t nibble = (n >> (i*4)) & 0xf;
*p++ = digits[nibble]; *p++ = digits[nibble];
} }
*p = 0; *p = 0;
m_out->OutputString(m_out, buffer); m_out->output_string(buffer);
return 8; return 8;
} }
@@ -111,11 +169,11 @@ console::print_long_hex(uint64_t n) const
wchar_t buffer[17]; wchar_t buffer[17];
wchar_t *p = buffer; wchar_t *p = buffer;
for (int i = 15; i >= 0; --i) { for (int i = 15; i >= 0; --i) {
uint8_t nibble = (n & (0xf << (i*4))) >> (i*4); uint8_t nibble = (n >> (i*4)) & 0xf;
*p++ = digits[nibble]; *p++ = digits[nibble];
} }
*p = 0; *p = 0;
m_out->OutputString(m_out, buffer); m_out->output_string(buffer);
return 16; return 16;
} }
@@ -130,7 +188,7 @@ console::print_dec(uint32_t n) const
n /= 10; n /= 10;
} while (n != 0); } while (n != 0);
m_out->OutputString(m_out, ++p); m_out->output_string(++p);
return 10 - (p - buffer); return 10 - (p - buffer);
} }
@@ -145,7 +203,7 @@ console::print_long_dec(uint64_t n) const
n /= 10; n /= 10;
} while (n != 0); } while (n != 0);
m_out->OutputString(m_out, ++p); m_out->output_string(++p);
return 20 - (p - buffer); return 20 - (p - buffer);
} }
@@ -165,14 +223,14 @@ console::vprintf(const wchar_t *fmt, va_list args) const
} }
*w = 0; *w = 0;
m_out->OutputString(m_out, buffer); m_out->output_string(buffer);
w = buffer; w = buffer;
r++; // chomp the % r++; // chomp the %
switch (*r++) { switch (*r++) {
case L'%': case L'%':
m_out->OutputString(m_out, const_cast<wchar_t*>(L"%")); m_out->output_string(const_cast<wchar_t*>(L"%"));
count++; count++;
break; break;
@@ -189,7 +247,7 @@ console::vprintf(const wchar_t *fmt, va_list args) const
{ {
wchar_t *s = va_arg(args, wchar_t*); wchar_t *s = va_arg(args, wchar_t*);
count += wstrlen(s); count += wstrlen(s);
m_out->OutputString(m_out, s); m_out->output_string(s);
} }
break; break;
@@ -215,7 +273,7 @@ console::vprintf(const wchar_t *fmt, va_list args) const
} }
*w = 0; *w = 0;
m_out->OutputString(m_out, buffer); m_out->output_string(buffer);
return count; return count;
} }
@@ -243,91 +301,4 @@ console::print(const wchar_t *fmt, ...)
return result; return result;
} }
void } // namespace boot
console::status_begin(const wchar_t *message) const
{
m_out->SetAttribute(m_out, EFI_LIGHTGRAY);
m_out->OutputString(m_out, (wchar_t *)message);
}
void
console::status_ok() const
{
m_out->SetAttribute(m_out, EFI_LIGHTGRAY);
m_out->OutputString(m_out, (wchar_t *)L"[");
m_out->SetAttribute(m_out, EFI_GREEN);
m_out->OutputString(m_out, (wchar_t *)L" ok ");
m_out->SetAttribute(m_out, EFI_LIGHTGRAY);
m_out->OutputString(m_out, (wchar_t *)L"]\r\n");
}
void
console::status_fail(const wchar_t *error) const
{
m_out->SetAttribute(m_out, EFI_LIGHTGRAY);
m_out->OutputString(m_out, (wchar_t *)L"[");
m_out->SetAttribute(m_out, EFI_LIGHTRED);
m_out->OutputString(m_out, (wchar_t *)L"failed");
m_out->SetAttribute(m_out, EFI_LIGHTGRAY);
m_out->OutputString(m_out, (wchar_t *)L"]\r\n");
m_out->SetAttribute(m_out, EFI_RED);
m_out->OutputString(m_out, (wchar_t *)error);
m_out->SetAttribute(m_out, EFI_LIGHTGRAY);
m_out->OutputString(m_out, (wchar_t *)L"\r\n");
}
EFI_STATUS
con_get_framebuffer(
EFI_BOOT_SERVICES *bootsvc,
void **buffer,
size_t *buffer_size,
uint32_t *hres,
uint32_t *vres,
uint32_t *rmask,
uint32_t *gmask,
uint32_t *bmask)
{
EFI_STATUS status;
EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
status = bootsvc->LocateProtocol(&guid_gfx_out, NULL, (void **)&gop);
if (status != EFI_NOT_FOUND) {
CHECK_EFI_STATUS_OR_RETURN(status, "LocateProtocol gfx");
*buffer = (void *)gop->Mode->FrameBufferBase;
*buffer_size = gop->Mode->FrameBufferSize;
*hres = gop->Mode->Info->HorizontalResolution;
*vres = gop->Mode->Info->VerticalResolution;
switch (gop->Mode->Info->PixelFormat) {
case PixelRedGreenBlueReserved8BitPerColor:
*rmask = 0x0000ff;
*gmask = 0x00ff00;
*bmask = 0xff0000;
return EFI_SUCCESS;
case PixelBlueGreenRedReserved8BitPerColor:
*bmask = 0x0000ff;
*gmask = 0x00ff00;
*rmask = 0xff0000;
return EFI_SUCCESS;
case PixelBitMask:
*rmask = gop->Mode->Info->PixelInformation.RedMask;
*gmask = gop->Mode->Info->PixelInformation.GreenMask;
*bmask = gop->Mode->Info->PixelInformation.BlueMask;
return EFI_SUCCESS;
default:
// Not a framebuffer, fall through to zeroing out
// values below.
break;
}
}
*buffer = NULL;
*buffer_size = *hres = *vres = 0;
*rmask = *gmask = *bmask = 0;
return EFI_SUCCESS;
}

View File

@@ -1,18 +1,22 @@
/// \file console.h
/// Text output handler
#pragma once #pragma once
#include <stdarg.h> #include <stdarg.h>
#include <stddef.h> #include <stddef.h>
#include <efi/efi.h> #include <uefi/boot_services.h>
#include <uefi/protos/simple_text_output.h>
#include "kernel_args.h"
#include "types.h"
namespace boot {
/// Object providing basic output functionality to the UEFI console
class console class console
{ {
public: public:
console(EFI_SYSTEM_TABLE *system_table); using framebuffer = kernel::args::framebuffer;
EFI_STATUS initialize(const wchar_t *version); console(uefi::boot_services *bs, uefi::protos::simple_text_output *out);
void status_begin(const wchar_t *message) const;
void status_fail(const wchar_t *error) const;
void status_ok() const;
size_t print_hex(uint32_t n) const; size_t print_hex(uint32_t n) const;
size_t print_dec(uint32_t n) const; size_t print_dec(uint32_t n) const;
@@ -20,27 +24,22 @@ public:
size_t print_long_dec(uint64_t n) const; size_t print_long_dec(uint64_t n) const;
size_t printf(const wchar_t *fmt, ...) const; size_t printf(const wchar_t *fmt, ...) const;
static const console & get() { return *s_console; } const framebuffer & fb() const { return m_fb; };
static console & get() { return *s_console; }
static size_t print(const wchar_t *fmt, ...); static size_t print(const wchar_t *fmt, ...);
private: private:
EFI_STATUS pick_mode(); friend class status_line;
void pick_mode(uefi::boot_services *bs);
size_t vprintf(const wchar_t *fmt, va_list args) const; size_t vprintf(const wchar_t *fmt, va_list args) const;
size_t m_rows, m_cols; size_t m_rows, m_cols;
EFI_BOOT_SERVICES *m_boot; uefi::protos::simple_text_output *m_out;
EFI_SIMPLE_TEXT_OUT_PROTOCOL *m_out; framebuffer m_fb;
static console *s_console; static console *s_console;
}; };
EFI_STATUS } // namespace boot
con_get_framebuffer(
EFI_BOOT_SERVICES *bootsvc,
void **buffer,
size_t *buffer_size,
uint32_t *hres,
uint32_t *vres,
uint32_t *rmask,
uint32_t *gmask,
uint32_t *bmask);

View File

@@ -1,85 +0,0 @@
; crt0-efi-x86_64.S - x86_64 EFI startup code.
; Copyright (C) 1999 Hewlett-Packard Co.
; Contributed by David Mosberger <davidm@hpl.hp.com>.
; Copyright (C) 2005 Intel Co.
; Contributed by Fenghua Yu <fenghua.yu@intel.com>.
;
; All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions
; are met:
;
; * Redistributions of source code must retain the above copyright
; notice, this list of conditions and the following disclaimer.
; * Redistributions in binary form must reproduce the above
; copyright notice, this list of conditions and the following
; disclaimer in the documentation and/or other materials
; provided with the distribution.
; * Neither the name of Hewlett-Packard Co. nor the names of its
; contributors may be used to endorse or promote products derived
; from this software without specific prior written permission.
;
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
; CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
; INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
; MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
; BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
; OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
; PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
; TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
; THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
; SUCH DAMAGE.
;
; 2018-05-05 Converted to NASM syntax by Justin C. Miller
extern ImageBase
extern _DYNAMIC
extern _relocate
extern efi_main
section .text
align 4
global _start
_start:
sub rsp, 8
push rcx
push rdx
; These are already in RDI/RSI from EFI calling us, right? -justin
;lea rdi, [ImageBase]
;lea rsi, [_DYNAMIC]
pop rcx
pop rdx
push rcx
push rdx
call _relocate
pop rdi
pop rsi
call efi_main
add rsp, 8
.exit:
ret
; hand-craft a dummy .reloc section so EFI knows it's a relocatable executable:
section .data
dummy:
dd 0
%define IMAGE_REL_ABSOLUTE 0
section .reloc
label1:
dd 0 ; Page RVA
dd 10 ; Block Size (2*4+2)
dw (IMAGE_REL_ABSOLUTE<<12) + 0 ; reloc for dummy

View File

@@ -1,46 +1,32 @@
/// \file elf.h
/// Definitions and related constants for ELF64 structures
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
#ifndef ELF_VERSION namespace boot {
#define ELF_VERSION 1 namespace elf {
#endif
#ifndef ELF_WORDSIZE constexpr uint8_t version = 1;
#define ELF_WORDSIZE 2 constexpr uint8_t word_size = 2;
#endif constexpr uint8_t endianness = 1;
constexpr uint8_t os_abi = 0;
constexpr uint16_t machine = 0x3e;
#ifndef ELF_ENDIAN const unsigned PT_LOAD = 1;
#define ELF_ENDIAN 1 const unsigned ST_PROGBITS = 1;
#endif const unsigned ST_NOBITS = 8;
const unsigned long SHF_ALLOC = 0x2;
#ifndef ELF_OSABI struct header
#define ELF_OSABI 0
#endif
#ifndef ELF_MACHINE
#define ELF_MACHINE 0x3e
#endif
const unsigned ELF_PT_LOAD = 1;
const unsigned ELF_ST_PROGBITS = 1;
const unsigned ELF_ST_NOBITS = 8;
const unsigned long ELF_SHF_ALLOC = 0x2;
struct elf_ident
{ {
char magic[4]; char magic[4];
uint8_t word_size; uint8_t word_size;
uint8_t endianness; uint8_t endianness;
uint8_t version; uint8_t header_version;
uint8_t os_abi; uint8_t os_abi;
uint64_t reserved; uint64_t reserved;
} __attribute__ ((packed));
struct elf_header
{
struct elf_ident ident;
uint16_t type; uint16_t type;
uint16_t machine; uint16_t machine;
@@ -64,7 +50,7 @@ struct elf_header
uint16_t sh_str_idx; uint16_t sh_str_idx;
} __attribute__ ((packed)); } __attribute__ ((packed));
struct elf_program_header struct program_header
{ {
uint32_t type; uint32_t type;
uint32_t flags; uint32_t flags;
@@ -79,7 +65,7 @@ struct elf_program_header
uint64_t align; uint64_t align;
} __attribute__ ((packed)); } __attribute__ ((packed));
struct elf_section_header struct section_header
{ {
uint32_t name; uint32_t name;
uint32_t type; uint32_t type;
@@ -92,3 +78,6 @@ struct elf_section_header
uint64_t align; uint64_t align;
uint64_t entry_size; uint64_t entry_size;
} __attribute__ ((packed)); } __attribute__ ((packed));
} // namespace elf
} // namespace boot

69
src/boot/error.cpp Normal file
View File

@@ -0,0 +1,69 @@
#include "error.h"
#include "console.h"
#include "kernel_args.h"
#include "status.h"
namespace boot {
namespace error {
struct error_code_desc {
uefi::status code;
const wchar_t *name;
};
struct error_code_desc error_table[] = {
#define STATUS_ERROR(name, num) { uefi::status::name, L#name },
#define STATUS_WARNING(name, num) { uefi::status::name, L#name },
#include "uefi/errors.inc"
#undef STATUS_ERROR
#undef STATUS_WARNING
{ uefi::status::success, nullptr }
};
const wchar_t *
message(uefi::status status)
{
int32_t i = -1;
while (error_table[++i].name != nullptr) {
if (error_table[i].code == status) return error_table[i].name;
}
if (uefi::is_error(status))
return L"Unknown Error";
else
return L"Unknown Warning";
}
[[ noreturn ]] static void
cpu_assert(uefi::status s, const wchar_t *message)
{
asm volatile (
"movq $0xeeeeeeebadbadbad, %%r8;"
"movq %0, %%r9;"
"movq %1, %%r10;"
"movq $0, %%rdx;"
"divq %%rdx;"
:
: "r"((uint64_t)s), "r"(message)
: "rax", "rdx", "r8", "r9", "r10");
while (1) asm("hlt");
}
[[ noreturn ]] void
raise(uefi::status status, const wchar_t *message)
{
if(status_line::fail(message, status))
while (1) asm("hlt");
else
cpu_assert(status, message);
}
} // namespace error
} // namespace boot
void debug_break()
{
volatile int go = 0;
while (!go);
}

33
src/boot/error.h Normal file
View File

@@ -0,0 +1,33 @@
/// \file error.h
/// Error handling definitions
#pragma once
#include <stddef.h>
#include <uefi/types.h>
namespace boot {
class console;
namespace error {
/// Halt or exit the program with the given error status/message
[[ noreturn ]] void raise(uefi::status status, const wchar_t *message);
const wchar_t * message(uefi::status status);
} // namespace error
} // namespace boot
/// Debugging psuedo-breakpoint.
void debug_break();
/// Helper macro to raise an error if an operation fails.
/// \arg s An expression evaluating to a UEFI status
/// \arg m The error message to use on failure
#define try_or_raise(s, m) \
do { \
uefi::status _s = (s); \
if (uefi::is_error(_s)) ::boot::error::raise(_s, (m)); \
} while(0)

114
src/boot/fs.cpp Normal file
View File

@@ -0,0 +1,114 @@
#include <uefi/types.h>
#include <uefi/protos/file.h>
#include <uefi/protos/file_info.h>
#include <uefi/protos/loaded_image.h>
#include <uefi/protos/simple_file_system.h>
#include "fs.h"
#include "console.h"
#include "error.h"
#include "memory.h"
#include "status.h"
namespace boot {
namespace fs {
file::file(uefi::protos::file *f, uefi::boot_services *bs) :
m_file(f),
m_bs(bs)
{
}
file::file(file &o) :
m_file(o.m_file),
m_bs(o.m_bs)
{
o.m_file = nullptr;
}
file::file(file &&o) :
m_file(o.m_file),
m_bs(o.m_bs)
{
o.m_file = nullptr;
}
file::~file()
{
if (m_file)
m_file->close();
}
file
file::open(const wchar_t *path)
{
uefi::protos::file *fh = nullptr;
try_or_raise(
m_file->open(&fh, path, uefi::file_mode::read, uefi::file_attr::none),
L"Could not open relative path to file");
return file(fh, m_bs);
}
buffer
file::load(uefi::memory_type mem_type)
{
uint8_t info_buf[sizeof(uefi::protos::file_info) + 100];
size_t size = sizeof(info_buf);
uefi::guid info_guid = uefi::protos::file_info::guid;
try_or_raise(
m_file->get_info(&info_guid, &size, &info_buf),
L"Could not get file info");
uefi::protos::file_info *info =
reinterpret_cast<uefi::protos::file_info*>(&info_buf);
size_t pages = memory::bytes_to_pages(info->file_size);
void *data = nullptr;
try_or_raise(
m_bs->allocate_pages(
uefi::allocate_type::any_pages,
mem_type, pages, &data),
L"Could not allocate pages to load file");
size = info->file_size;
try_or_raise(
m_file->read(&size, data),
L"Could not read from file");
return { .data = data, .size = size };
}
file
get_boot_volume(uefi::handle image, uefi::boot_services *bs)
{
status_line status(L"Looking up boot volume");
const uefi::guid le_guid = uefi::protos::loaded_image::guid;
uefi::protos::loaded_image *loaded_image = nullptr;
try_or_raise(
bs->handle_protocol(image, &le_guid,
reinterpret_cast<void**>(&loaded_image)),
L"Could not find currently running UEFI loaded image");
const uefi::guid sfs_guid = uefi::protos::simple_file_system::guid;
uefi::protos::simple_file_system *fs;
try_or_raise(
bs->handle_protocol(loaded_image->device_handle, &sfs_guid,
reinterpret_cast<void**>(&fs)),
L"Could not find filesystem protocol for boot volume");
uefi::protos::file *f;
try_or_raise(
fs->open_volume(&f),
L"Could not open the boot volume");
return file(f, bs);
}
} // namespace fs
} // namespace boot

45
src/boot/fs.h Normal file
View File

@@ -0,0 +1,45 @@
/// \file fs.h
/// Definitions for dealing with UEFI's disk access functions
#pragma once
#include <uefi/types.h>
#include <uefi/boot_services.h>
#include <uefi/protos/file.h>
#include "types.h"
namespace boot {
namespace fs {
/// A file or directory in a filesystem.
class file
{
public:
file(file &&o);
file(file &o);
~file();
/// Open another file or directory, relative to this one.
/// \arg path Relative path to the target file from this one
file open(const wchar_t *path);
/// Load the contents of this file into memory.
/// \arg mem_type The UEFI memory type to use for allocation
/// \returns A buffer describing the loaded memory. The
/// memory will be page-aligned.
buffer load(uefi::memory_type mem_type = uefi::memory_type::loader_data);
private:
friend file get_boot_volume(uefi::handle, uefi::boot_services*);
file(uefi::protos::file *f, uefi::boot_services *bs);
uefi::protos::file *m_file;
uefi::boot_services *m_bs;
};
/// Get the filesystem this loader was loaded from.
/// \returns A `file` object representing the root directory of the volume
file get_boot_volume(uefi::handle image, uefi::boot_services *bs);
} // namespace fs
} // namespace boot

View File

@@ -6,6 +6,6 @@ GUID(0x964e5b22,0x6459,0x11d2,0x8e,0x39,0x00,0xa0,0xc9,0x69,0x72,0x3b, guid_simp
GUID(0x09576e91,0x6d3f,0x11d2,0x8e,0x39,0x00,0xa0,0xc9,0x69,0x72,0x3b, guid_device_path); GUID(0x09576e91,0x6d3f,0x11d2,0x8e,0x39,0x00,0xa0,0xc9,0x69,0x72,0x3b, guid_device_path);
GUID(0x8b843e20,0x8132,0x4852,0x90,0xcc,0x55,0x1a,0x4e,0x4a,0x7f,0x1c, guid_device_path_to_text); GUID(0x8b843e20,0x8132,0x4852,0x90,0xcc,0x55,0x1a,0x4e,0x4a,0x7f,0x1c, guid_device_path_to_text);
GUID(0x10d0669c,0x9ec6,0x4268,0xbc,0x48,0xff,0x74,0x75,0x21,0xfe,0x07, guid_popcorn_vendor); GUID(0x10d0669c,0x9ec6,0x4268,0xbc,0x48,0xff,0x74,0x75,0x21,0xfe,0x07, guid_jsix_vendor);
// vim: ft=c // vim: ft=c

55
src/boot/hardware.cpp Normal file
View File

@@ -0,0 +1,55 @@
#include "hardware.h"
#include "console.h"
#include "error.h"
#include "status.h"
namespace boot {
namespace hw {
void *
find_acpi_table(uefi::system_table *st)
{
status_line status(L"Searching for ACPI table");
// Find ACPI tables. Ignore ACPI 1.0 if a 2.0 table is found.
uintptr_t acpi1_table = 0;
for (size_t i = 0; i < st->number_of_table_entries; ++i) {
uefi::configuration_table *table = &st->configuration_table[i];
// If we find an ACPI 2.0 table, return it immediately
if (table->vendor_guid == uefi::vendor_guids::acpi2)
return table->vendor_table;
if (table->vendor_guid == uefi::vendor_guids::acpi1) {
// Mark a v1 table with the LSB high
acpi1_table = reinterpret_cast<uintptr_t>(table->vendor_table);
acpi1_table |= 1;
}
}
if (!acpi1_table) {
error::raise(uefi::status::not_found, L"Could not find ACPI table");
} else if (acpi1_table & 1) {
status_line::warn(L"Only found ACPI 1.0 table");
}
return reinterpret_cast<void*>(acpi1_table);
}
void
setup_cr4()
{
uint64_t cr4 = 0;
asm volatile ( "mov %%cr4, %0" : "=r" (cr4) );
cr4 |=
0x000080 | // Enable global pages
0x000200 | // Enable FXSAVE/FXRSTOR
0x010000 | // Enable FSGSBASE
0x020000 | // Enable PCIDs
0;
asm volatile ( "mov %0, %%cr4" :: "r" (cr4) );
}
} // namespace hw
} // namespace boot

20
src/boot/hardware.h Normal file
View File

@@ -0,0 +1,20 @@
/// \file hardware.h
/// Functions and definitions for detecting and dealing with hardware
#pragma once
#include <uefi/tables.h>
namespace boot {
namespace hw {
/// Find the ACPI table in the system configuration tables
/// and return a pointer to it. If only an ACPI 1.0 table is
/// available, the returned pointer will have its least
/// significant bit set to 1.
void * find_acpi_table(uefi::system_table *st);
/// Enable CPU options in CR4 for the kernel starting state.
void setup_cr4();
} // namespace hw
} // namespace boot

View File

@@ -1,298 +1,110 @@
#include "elf.h" #include <uefi/boot_services.h>
#include "guids.h" #include <uefi/types.h>
#include "loader.h" #include "loader.h"
#include "console.h"
#include "elf.h"
#include "error.h"
#include "fs.h"
#include "memory.h" #include "memory.h"
#include "utility.h" #include "paging.h"
#include "status.h"
#define PAGE_SIZE 0x1000 namespace args = kernel::args;
static wchar_t kernel_name[] = KERNEL_FILENAME; namespace boot {
static wchar_t initrd_name[] = INITRD_FILENAME; namespace loader {
EFI_STATUS buffer
loader_alloc_aligned( load_file(
EFI_BOOT_SERVICES *bootsvc, fs::file &disk,
EFI_MEMORY_TYPE mem_type, const wchar_t *name,
size_t *length, const wchar_t *path,
void **pages) uefi::memory_type type)
{ {
EFI_STATUS status; status_line status(L"Loading file", name);
EFI_PHYSICAL_ADDRESS addr;
size_t alignment = PAGE_SIZE; fs::file file = disk.open(path);
while (alignment < *length) buffer b = file.load(type);
alignment *= 2;
size_t page_count = alignment / PAGE_SIZE; console::print(L" Loaded at: 0x%lx, %d bytes\r\n", b.data, b.size);
*length = alignment; return b;
con_debug(L"Trying to find %d aligned pages for %x\n", page_count, mem_type);
status = bootsvc->AllocatePages(AllocateAnyPages, mem_type, page_count * 2, &addr);
CHECK_EFI_STATUS_OR_RETURN(status, L"Allocating %d pages for alignment", page_count * 2);
con_debug(L" Found %d pages at %lx\n", page_count * 2, addr);
EFI_PHYSICAL_ADDRESS aligned = addr;
aligned = ((aligned - 1) & ~(alignment - 1)) + alignment;
con_debug(L" Aligning %lx to %lx\n", addr, aligned);
size_t before =
(reinterpret_cast<uint64_t>(aligned) -
reinterpret_cast<uint64_t>(addr)) /
PAGE_SIZE;
if (before) {
con_debug(L" Freeing %d initial pages\n", before);
bootsvc->FreePages(addr, before);
}
size_t after = page_count - before;
if (after) {
EFI_PHYSICAL_ADDRESS end =
reinterpret_cast<EFI_PHYSICAL_ADDRESS>(
reinterpret_cast<uint64_t>(aligned) +
page_count * PAGE_SIZE);
con_debug(L" Freeing %d remaining pages\n", after);
bootsvc->FreePages(end, after);
}
*pages = (void *)aligned;
return EFI_SUCCESS;
}
EFI_STATUS
loader_alloc_pages(
EFI_BOOT_SERVICES *bootsvc,
EFI_MEMORY_TYPE mem_type,
size_t *length,
void **pages)
{
EFI_STATUS status;
size_t page_count = ((*length - 1) / PAGE_SIZE) + 1;
EFI_PHYSICAL_ADDRESS addr = (EFI_PHYSICAL_ADDRESS)*pages;
con_debug(L"Trying to find %d non-aligned pages for %x at %lx\n",
page_count, mem_type, addr);
status = bootsvc->AllocatePages(AllocateAddress, mem_type, page_count, &addr);
CHECK_EFI_STATUS_OR_RETURN(status,
L"Allocating %d kernel pages type %x",
page_count, mem_type);
*length = page_count * PAGE_SIZE;
*pages = (void *)addr;
return EFI_SUCCESS;
}
EFI_STATUS
loader_load_initrd(
EFI_BOOT_SERVICES *bootsvc,
EFI_FILE_PROTOCOL *root,
struct loader_data *data)
{
EFI_STATUS status;
EFI_FILE_PROTOCOL *file = NULL;
status = root->Open(root, &file, (wchar_t *)initrd_name, EFI_FILE_MODE_READ,
EFI_FILE_READ_ONLY | EFI_FILE_HIDDEN | EFI_FILE_SYSTEM);
if (status == EFI_NOT_FOUND)
return status;
CHECK_EFI_STATUS_OR_RETURN(status, L"Opening file %s", initrd_name);
char info[sizeof(EFI_FILE_INFO) + 100];
size_t info_length = sizeof(info);
status = file->GetInfo(file, &guid_file_info, &info_length, info);
CHECK_EFI_STATUS_OR_RETURN(status, L"Getting file info");
data->initrd_length = ((EFI_FILE_INFO *)info)->FileSize;
status = loader_alloc_aligned(
bootsvc,
memtype_initrd,
&data->initrd_length,
&data->initrd);
CHECK_EFI_STATUS_OR_RETURN(status, L"Allocating pages");
status = file->Read(file, &data->initrd_length, data->initrd);
CHECK_EFI_STATUS_OR_RETURN(status, L"Reading file");
status = file->Close(file);
CHECK_EFI_STATUS_OR_RETURN(status, L"Closing file handle");
return EFI_SUCCESS;
} }
EFI_STATUS static bool
loader_load_elf( is_elfheader_valid(const elf::header *header)
EFI_BOOT_SERVICES *bootsvc,
EFI_FILE_PROTOCOL *root,
struct loader_data *data)
{ {
EFI_STATUS status; return
header->magic[0] == 0x7f &&
con_debug(L"Opening kernel file %s\r\n", (wchar_t *)kernel_name); header->magic[1] == 'E' &&
header->magic[2] == 'L' &&
EFI_FILE_PROTOCOL *file = NULL; header->magic[3] == 'F' &&
status = root->Open(root, &file, (wchar_t *)kernel_name, EFI_FILE_MODE_READ, header->word_size == elf::word_size &&
EFI_FILE_READ_ONLY | EFI_FILE_HIDDEN | EFI_FILE_SYSTEM); header->endianness == elf::endianness &&
header->os_abi == elf::os_abi &&
if (status == EFI_NOT_FOUND) header->machine == elf::machine &&
return status; header->header_version == elf::version;
uint64_t length = 0;
data->kernel = 0;
data->kernel_entry = 0;
data->kernel_length = 0;
CHECK_EFI_STATUS_OR_RETURN(status, L"Opening file %s", kernel_name);
struct elf_header header;
length = sizeof(struct elf_header);
status = file->Read(file, &length, &header);
CHECK_EFI_STATUS_OR_RETURN(status, L"Reading ELF header");
con_debug(L"Read %u bytes of ELF header\r\n", length);
if (length < sizeof(struct elf_header))
CHECK_EFI_STATUS_OR_RETURN(EFI_LOAD_ERROR, L"Incomplete read of ELF header");
static const char expected[] = {0x7f, 'E', 'L', 'F'};
for (int i = 0; i < sizeof(expected); ++i) {
if (header.ident.magic[i] != expected[i])
CHECK_EFI_STATUS_OR_RETURN(EFI_LOAD_ERROR, L"Bad ELF magic number");
}
if (header.ident.word_size != ELF_WORDSIZE)
CHECK_EFI_STATUS_OR_RETURN(EFI_LOAD_ERROR, L"ELF load error: 32 bit ELF not supported");
if (header.ph_entsize != sizeof(struct elf_program_header))
CHECK_EFI_STATUS_OR_RETURN(EFI_LOAD_ERROR, L"ELF load error: program header size mismatch");
if (header.ident.version != ELF_VERSION ||
header.version != ELF_VERSION)
CHECK_EFI_STATUS_OR_RETURN(EFI_LOAD_ERROR, L"ELF load error: wrong ELF version");
if (header.ident.endianness != 1 ||
header.ident.os_abi != 0 ||
header.machine != 0x3e)
CHECK_EFI_STATUS_OR_RETURN(EFI_LOAD_ERROR, L"ELF load error: wrong machine architecture");
con_debug(L"ELF is valid, entrypoint %lx\r\n", header.entrypoint);
data->kernel_entry = (void *)header.entrypoint;
struct elf_program_header prog_header;
for (int i = 0; i < header.ph_num; ++i) {
status = file->SetPosition(file, header.ph_offset + i * header.ph_entsize);
CHECK_EFI_STATUS_OR_RETURN(status, L"Setting ELF file position");
length = header.ph_entsize;
status = file->Read(file, &length, &prog_header);
CHECK_EFI_STATUS_OR_RETURN(status, L"Reading ELF program header");
if (prog_header.type != ELF_PT_LOAD) continue;
length = prog_header.mem_size;
void *addr = (void *)(prog_header.vaddr - KERNEL_VIRT_ADDRESS);
status = loader_alloc_pages(bootsvc, memtype_kernel, &length, &addr);
CHECK_EFI_STATUS_OR_RETURN(status, L"Allocating kernel pages");
if (data->kernel == 0)
data->kernel = addr;
data->kernel_length = (uint64_t)addr + length - (uint64_t)data->kernel;
}
con_debug(L"Read %d ELF program headers\r\n", header.ph_num);
struct elf_section_header sec_header;
for (int i = 0; i < header.sh_num; ++i) {
status = file->SetPosition(file, header.sh_offset + i * header.sh_entsize);
CHECK_EFI_STATUS_OR_RETURN(status, L"Setting ELF file position");
length = header.sh_entsize;
status = file->Read(file, &length, &sec_header);
CHECK_EFI_STATUS_OR_RETURN(status, L"Reading ELF section header");
if ((sec_header.flags & ELF_SHF_ALLOC) == 0) {
continue;
}
void *addr = (void *)(sec_header.addr - KERNEL_VIRT_ADDRESS);
if (sec_header.type == ELF_ST_PROGBITS) {
status = file->SetPosition(file, sec_header.offset);
CHECK_EFI_STATUS_OR_RETURN(status, L"Setting ELF file position");
length = sec_header.size;
status = file->Read(file, &length, addr);
CHECK_EFI_STATUS_OR_RETURN(status, L"Reading file");
} else if (sec_header.type == ELF_ST_NOBITS) {
bootsvc->SetMem(addr, sec_header.size, 0);
}
}
con_debug(L"Read %d ELF section headers\r\n", header.ph_num);
status = file->Close(file);
CHECK_EFI_STATUS_OR_RETURN(status, L"Closing file handle");
return EFI_SUCCESS;
} }
void
EFI_STATUS load_program(
loader_load_kernel( args::program &program,
EFI_BOOT_SERVICES *bootsvc, const wchar_t *name,
struct loader_data *data) buffer data,
uefi::boot_services *bs)
{ {
if (data == NULL) status_line status(L"Loading program:", name);
CHECK_EFI_STATUS_OR_RETURN(EFI_INVALID_PARAMETER, L"NULL loader_data"); const elf::header *header = reinterpret_cast<const elf::header*>(data.data);
EFI_STATUS status; if (data.size < sizeof(elf::header) || !is_elfheader_valid(header))
EFI_HANDLE *handles = NULL; error::raise(uefi::status::load_error, L"ELF file not valid");
size_t handleCount = 0;
status = bootsvc->LocateHandleBuffer(ByProtocol, &guid_simple_filesystem, NULL, &handleCount, &handles); uintptr_t prog_base = uintptr_t(-1);
CHECK_EFI_STATUS_OR_RETURN(status, L"LocateHandleBuffer"); uintptr_t prog_end = 0;
for (unsigned i = 0; i < handleCount; ++i) { for (int i = 0; i < header->ph_num; ++i) {
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *fileSystem = NULL; ptrdiff_t offset = header->ph_offset + i * header->ph_entsize;
const elf::program_header *pheader =
offset_ptr<elf::program_header>(data.data, offset);
status = bootsvc->HandleProtocol(handles[i], &guid_simple_filesystem, (void **)&fileSystem); if (pheader->type != elf::PT_LOAD)
CHECK_EFI_STATUS_OR_RETURN(status, L"HandleProtocol");
EFI_FILE_PROTOCOL *root = NULL;
status = fileSystem->OpenVolume(fileSystem, &root);
CHECK_EFI_STATUS_OR_RETURN(status, L"OpenVolume");
status = loader_load_elf(bootsvc, root, data);
if (status == EFI_NOT_FOUND)
continue; continue;
CHECK_EFI_STATUS_OR_RETURN(status, L"loader_load_elf: %s", kernel_name); uintptr_t end = pheader->vaddr + pheader->mem_size;
if (pheader->vaddr < prog_base) prog_base = pheader->vaddr;
data->data = (void *)((uint64_t)data->kernel + data->kernel_length); if (end > prog_end) prog_end = end;
data->data_length += PAGE_SIZE; // extra page for map growth
status = loader_alloc_aligned(
bootsvc,
memtype_data,
&data->data_length,
&data->data);
CHECK_EFI_STATUS_OR_RETURN(status, L"loader_alloc_aligned: kernel data");
data->initrd = (void *)((uint64_t)data->data + data->data_length);
status = loader_load_initrd(bootsvc, root, data);
CHECK_EFI_STATUS_OR_RETURN(status, L"loader_load_file: %s", initrd_name);
return EFI_SUCCESS;
} }
return EFI_NOT_FOUND; size_t total_size = prog_end - prog_base;
size_t num_pages = memory::bytes_to_pages(total_size);
void *pages = nullptr;
try_or_raise(
bs->allocate_pages(uefi::allocate_type::any_pages,
uefi::memory_type::loader_data, num_pages, &pages),
L"Failed allocating space for program");
bs->set_mem(pages, total_size, 0);
for (int i = 0; i < header->ph_num; ++i) {
ptrdiff_t offset = header->ph_offset + i * header->ph_entsize;
const elf::program_header *pheader =
offset_ptr<elf::program_header>(data.data, offset);
if (pheader->type != elf::PT_LOAD)
continue;
void *src_start = offset_ptr<void>(data.data, pheader->offset);
void *dest_start = offset_ptr<void>(pages, pheader->vaddr - prog_base);
bs->copy_mem(dest_start, src_start, pheader->file_size);
}
program.phys_addr = reinterpret_cast<uintptr_t>(pages);
program.size = total_size;
program.virt_addr = prog_base;
program.entrypoint = header->entrypoint;
} }
} // namespace loader
} // namespace boot

View File

@@ -1,35 +1,41 @@
/// \file loader.h
/// Definitions for loading the kernel into memory
#pragma once #pragma once
#include <efi/efi.h>
#include <stddef.h>
#define PAGE_SIZE 0x1000 #include <uefi/boot_services.h>
#ifndef KERNEL_PHYS_ADDRESS #include "kernel_args.h"
#define KERNEL_PHYS_ADDRESS 0x100000 #include "memory.h"
#endif #include "types.h"
#ifndef KERNEL_VIRT_ADDRESS namespace boot {
#define KERNEL_VIRT_ADDRESS 0xFFFFFF0000000000
#endif
#ifndef KERNEL_FILENAME namespace fs { class file; }
#define KERNEL_FILENAME L"kernel.elf"
#endif
#ifndef INITRD_FILENAME namespace loader {
#define INITRD_FILENAME L"initrd.img"
#endif
struct loader_data { /// Load a file from disk into memory.
void *kernel; /// \arg disk The opened UEFI filesystem to load from
void *kernel_entry; /// \arg name Name of the module (informational only)
size_t kernel_length; /// \arg path Path on `disk` of the file to load
/// \arg type Memory type to use for allocation
buffer
load_file(
fs::file &disk,
const wchar_t *name,
const wchar_t *path,
uefi::memory_type type = uefi::memory_type::loader_data);
void *initrd; /// Parse and load an ELF file in memory into a loaded image.
size_t initrd_length; /// \arg program The program structure to fill
/// \arg data Buffer of the ELF file in memory
/// \arg bs Boot services
void
load_program(
kernel::args::program &program,
const wchar_t *name,
buffer data,
uefi::boot_services *bs);
void *data; } // namespace loader
size_t data_length; } // namespace boot
};
EFI_STATUS loader_load_kernel(EFI_BOOT_SERVICES *bootsvc, struct loader_data *data);

View File

@@ -1,227 +1,211 @@
#include <uefi/types.h>
#include <uefi/guid.h>
#include <uefi/tables.h>
#include <uefi/protos/simple_text_output.h>
#include <stdalign.h> #include <stdalign.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h>
#include <efi/efi.h>
#include "console.h" #include "console.h"
#include "guids.h" #include "cpu/cpu.h"
#include "kernel_args.h" #include "error.h"
#include "fs.h"
#include "hardware.h"
#include "loader.h" #include "loader.h"
#include "memory.h" #include "memory.h"
#include "utility.h" #include "paging.h"
#include "status.h"
#ifndef SCRATCH_PAGES #include "kernel_args.h"
#define SCRATCH_PAGES 64
#endif
#ifndef GIT_VERSION_WIDE namespace kernel {
#define GIT_VERSION_WIDE L"no version" #include "kernel_memory.h"
#endif }
#define KERNEL_HEADER_MAGIC 0x600db007 namespace args = kernel::args;
#define KERNEL_HEADER_VERSION 1
#pragma pack(push, 1) namespace boot {
struct kernel_header {
uint32_t magic;
uint16_t version;
uint16_t length;
uint8_t major; constexpr int max_modules = 5; // Max modules to allocate room for
uint8_t minor; constexpr int max_programs = 5; // Max programs to allocate room for
uint16_t patch;
uint32_t gitsha; struct program_desc
{
const wchar_t *name;
const wchar_t *path;
}; };
#pragma pack(pop)
using kernel_entry = void (*)(kernel_args *); const program_desc program_list[] = {
{L"kernel", L"jsix.elf"},
{L"null driver", L"nulldrv.elf"},
{L"fb driver", L"fb.elf"},
};
static void /// Change a pointer to point to the higher-half linear-offset version
type_to_wchar(wchar_t *into, uint32_t type) /// of the address it points to.
template <typename T>
void change_pointer(T *&pointer)
{ {
for (int j=0; j<4; ++j) pointer = offset_ptr<T>(pointer, kernel::memory::page_offset);
into[j] = static_cast<wchar_t>(reinterpret_cast<char *>(&type)[j]);
} }
EFI_STATUS /// Allocate space for kernel args. Allocates enough space from pool
detect_debug_mode(EFI_RUNTIME_SERVICES *run, kernel_args *header) { /// memory for the args header and the module and program headers.
wchar_t var_name[] = L"debug"; args::header *
allocate_args_structure(
uefi::boot_services *bs,
size_t max_modules,
size_t max_programs)
{
status_line status {L"Setting up kernel args memory"};
EFI_STATUS status; args::header *args = nullptr;
uint8_t debug = 0;
UINTN var_size = sizeof(debug);
#ifdef __POPCORN_SET_DEBUG_UEFI_VAR__ size_t args_size =
debug = __POPCORN_SET_DEBUG_UEFI_VAR__; sizeof(args::header) + // The header itself
uint32_t attrs = max_modules * sizeof(args::module) + // The module structures
EFI_VARIABLE_NON_VOLATILE | max_programs * sizeof(args::program); // The program structures
EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS;
status = run->SetVariable(
var_name,
&guid_popcorn_vendor,
attrs,
var_size,
&debug);
CHECK_EFI_STATUS_OR_RETURN(status, "detect_debug_mode::SetVariable");
#endif
status = run->GetVariable( try_or_raise(
var_name, bs->allocate_pool(uefi::memory_type::loader_data, args_size,
&guid_popcorn_vendor, reinterpret_cast<void**>(&args)),
nullptr, L"Could not allocate argument memory");
&var_size,
&debug);
CHECK_EFI_STATUS_OR_RETURN(status, "detect_debug_mode::GetVariable");
if (debug) bs->set_mem(args, args_size, 0);
header->flags |= POPCORN_FLAG_DEBUG;
return EFI_SUCCESS; args->modules =
reinterpret_cast<args::module*>(args + 1);
args->num_modules = 0;
args->programs =
reinterpret_cast<args::program*>(args->modules + max_modules);
args->num_programs = 0;
return args;
} }
extern "C" EFI_STATUS /// Add a module to the kernel args list
efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table) inline void
add_module(args::header *args, args::mod_type type, buffer &data)
{ {
EFI_STATUS status; args::module &m = args->modules[args->num_modules++];
EFI_BOOT_SERVICES *bootsvc = system_table->BootServices; m.type = type;
EFI_RUNTIME_SERVICES *runsvc = system_table->RuntimeServices; m.location = data.data;
m.size = data.size;
}
console con(system_table); /// Check that all required cpu features are supported
void
check_cpu_supported()
{
status_line status {L"Checking CPU features"};
// When checking console initialization, use CHECK_EFI_STATUS_OR_RETURN cpu::cpu_id cpu;
// because we can't be sure if the console was fully set up uint64_t missing = cpu.missing();
status = con.initialize(GIT_VERSION_WIDE); if (missing) {
CHECK_EFI_STATUS_OR_RETURN(status, "console::initialize"); #define CPU_FEATURE_OPT(...)
// From here on out, we can use CHECK_EFI_STATUS_OR_FAIL instead #define CPU_FEATURE_REQ(name, ...) \
if (!cpu.has_feature(cpu::feature::name)) { \
memory_init_pointer_fixup(bootsvc, runsvc, SCRATCH_PAGES); status::fail(L"CPU required feature " L ## #name, uefi::status::unsupported); \
// Find ACPI tables. Ignore ACPI 1.0 if a 2.0 table is found.
//
void *acpi_table = NULL;
for (size_t i=0; i<system_table->NumberOfTableEntries; ++i) {
EFI_CONFIGURATION_TABLE *efi_table = &system_table->ConfigurationTable[i];
if (is_guid(&efi_table->VendorGuid, &guid_acpi2)) {
acpi_table = efi_table->VendorTable;
break;
} else if (is_guid(&efi_table->VendorGuid, &guid_acpi1)) {
// Mark a v1 table with the LSB high
acpi_table = (void *)((intptr_t)efi_table->VendorTable | 0x1);
} }
#include "cpu/features.inc"
#undef CPU_FEATURE_REQ
#undef CPU_FEATURE_OPT
error::raise(uefi::status::unsupported, L"CPU not supported");
} }
// Compute necessary number of data pages
//
size_t data_length = 0;
status = memory_get_map_length(bootsvc, &data_length);
CHECK_EFI_STATUS_OR_FAIL(status);
size_t header_size = sizeof(kernel_args);
const size_t header_align = alignof(kernel_args);
if (header_size % header_align)
header_size += header_align - (header_size % header_align);
data_length += header_size;
// Load the kernel image from disk and check it
//
console::print(L"Loading kernel into memory...\r\n");
struct loader_data load;
load.data_length = data_length;
status = loader_load_kernel(bootsvc, &load);
CHECK_EFI_STATUS_OR_FAIL(status);
console::print(L" %x image bytes at 0x%x\r\n", load.kernel_length, load.kernel);
console::print(L" %x data bytes at 0x%x\r\n", load.data_length, load.data);
console::print(L" %x initrd bytes at 0x%x\r\n", load.initrd_length, load.initrd);
struct kernel_header *version = (struct kernel_header *)load.kernel;
if (version->magic != KERNEL_HEADER_MAGIC) {
console::print(L" bad magic %x\r\n", version->magic);
CHECK_EFI_STATUS_OR_FAIL(EFI_CRC_ERROR);
}
console::print(L" Kernel version %d.%d.%d %x%s\r\n",
version->major, version->minor, version->patch, version->gitsha & 0x0fffffff,
version->gitsha & 0xf0000000 ? L"*" : L"");
console::print(L" Entrypoint 0x%x\r\n", load.kernel_entry);
kernel_entry kernel_main =
reinterpret_cast<kernel_entry>(load.kernel_entry);
memory_mark_pointer_fixup((void **)&kernel_main);
// Set up the kernel data pages to pass to the kernel
//
struct kernel_args *data_header = (struct kernel_args *)load.data;
memory_mark_pointer_fixup((void **)&data_header);
data_header->magic = DATA_HEADER_MAGIC;
data_header->version = DATA_HEADER_VERSION;
data_header->length = sizeof(struct kernel_args);
data_header->scratch_pages = SCRATCH_PAGES;
data_header->flags = 0;
data_header->initrd = load.initrd;
data_header->initrd_length = load.initrd_length;
memory_mark_pointer_fixup((void **)&data_header->initrd);
data_header->data = load.data;
data_header->data_length = load.data_length;
memory_mark_pointer_fixup((void **)&data_header->data);
data_header->memory_map = (EFI_MEMORY_DESCRIPTOR *)(data_header + 1);
memory_mark_pointer_fixup((void **)&data_header->memory_map);
data_header->runtime = runsvc;
memory_mark_pointer_fixup((void **)&data_header->runtime);
data_header->acpi_table = acpi_table;
memory_mark_pointer_fixup((void **)&data_header->acpi_table);
data_header->_reserved0 = 0;
data_header->_reserved1 = 0;
// Figure out the framebuffer (if any) and add that to the data header
//
status = con_get_framebuffer(
bootsvc,
&data_header->frame_buffer,
&data_header->frame_buffer_length,
&data_header->hres,
&data_header->vres,
&data_header->rmask,
&data_header->gmask,
&data_header->bmask);
CHECK_EFI_STATUS_OR_FAIL(status);
memory_mark_pointer_fixup((void **)&data_header->frame_buffer);
// Save the memory map and tell the firmware we're taking control.
//
struct memory_map map;
map.length = (load.data_length - header_size);
map.entries =
reinterpret_cast<EFI_MEMORY_DESCRIPTOR *>(data_header->memory_map);
status = memory_get_map(bootsvc, &map);
CHECK_EFI_STATUS_OR_FAIL(status);
data_header->memory_map_length = map.length;
data_header->memory_map_desc_size = map.size;
detect_debug_mode(runsvc, data_header);
// bootsvc->Stall(5000000);
status = bootsvc->ExitBootServices(image_handle, map.key);
CHECK_EFI_STATUS_OR_ASSERT(status, 0);
memory_virtualize(runsvc, &map);
// Hand control to the kernel
//
kernel_main(data_header);
return EFI_LOAD_ERROR;
} }
/// The main procedure for the portion of the loader that runs while
/// UEFI is still in control of the machine. (ie, while the loader still
/// has access to boot services.
args::header *
uefi_preboot(uefi::handle image, uefi::system_table *st)
{
status_line status {L"Performing UEFI pre-boot"};
uefi::boot_services *bs = st->boot_services;
uefi::runtime_services *rs = st->runtime_services;
memory::init_pointer_fixup(bs, rs);
args::header *args =
allocate_args_structure(bs, max_modules, max_programs);
args->magic = args::magic;
args->version = args::version;
args->runtime_services = rs;
args->acpi_table = hw::find_acpi_table(st);
paging::allocate_tables(args, bs);
memory::mark_pointer_fixup(&args->runtime_services);
fs::file disk = fs::get_boot_volume(image, bs);
buffer symbols = loader::load_file(disk, L"symbol table", L"symbol_table.dat",
uefi::memory_type::loader_data);
add_module(args, args::mod_type::symbol_table, symbols);
for (auto &desc : program_list) {
buffer buf = loader::load_file(disk, desc.name, desc.path);
args::program &program = args->programs[args->num_programs++];
loader::load_program(program, desc.name, buf, bs);
}
for (unsigned i = 0; i < args->num_modules; ++i) {
args::module &mod = args->modules[i];
change_pointer(mod.location);
}
return args;
}
memory::efi_mem_map
uefi_exit(args::header *args, uefi::handle image, uefi::boot_services *bs)
{
status_line status {L"Exiting UEFI"};
memory::efi_mem_map map =
memory::build_kernel_mem_map(args, bs);
try_or_raise(
bs->exit_boot_services(image, map.key),
L"Failed to exit boot services");
return map;
}
} // namespace boot
/// The UEFI entrypoint for the loader.
extern "C" uefi::status
efi_main(uefi::handle image, uefi::system_table *st)
{
using namespace boot;
console con(st->boot_services, st->con_out);
check_cpu_supported();
args::header *args = uefi_preboot(image, st);
memory::efi_mem_map map = uefi_exit(args, image, st->boot_services);
args->video = con.fb();
status_bar status {con.fb()}; // Switch to fb status display
args::program &kernel = args->programs[0];
paging::map_pages(args, kernel.phys_addr, kernel.virt_addr, kernel.size);
kernel::entrypoint kentry =
reinterpret_cast<kernel::entrypoint>(kernel.entrypoint);
status.next();
memory::virtualize(args->pml4, map, st->runtime_services);
status.next();
change_pointer(args->pml4);
hw::setup_cr4();
status.next();
kentry(args);
debug_break();
return uefi::status::unsupported;
}

View File

@@ -1,215 +1,268 @@
#include <stddef.h> #include <stddef.h>
#include <uefi/types.h>
#include "loader.h" #include "kernel_memory.h"
#include "console.h"
#include "error.h"
#include "memory.h" #include "memory.h"
#include "utility.h" #include "paging.h"
#include "status.h"
const EFI_MEMORY_TYPE memtype_kernel = static_cast<EFI_MEMORY_TYPE>(0x80000000); namespace boot {
const EFI_MEMORY_TYPE memtype_data = static_cast<EFI_MEMORY_TYPE>(0x80000001); namespace memory {
const EFI_MEMORY_TYPE memtype_initrd = static_cast<EFI_MEMORY_TYPE>(0x80000002);
const EFI_MEMORY_TYPE memtype_scratch = static_cast<EFI_MEMORY_TYPE>(0x80000003);
#define INCREMENT_DESC(p, b) (EFI_MEMORY_DESCRIPTOR*)(((uint8_t*)(p))+(b)) using mem_entry = kernel::args::mem_entry;
using mem_type = kernel::args::mem_type;
size_t fixup_pointer_index = 0; size_t fixup_pointer_index = 0;
void **fixup_pointers[64]; void **fixup_pointers[64];
uint64_t *new_pml4 = 0;
const wchar_t *memory_type_names[] = { static const wchar_t *memory_type_names[] = {
L"EfiReservedMemoryType", L"reserved memory type",
L"EfiLoaderCode", L"loader code",
L"EfiLoaderData", L"loader data",
L"EfiBootServicesCode", L"boot services code",
L"EfiBootServicesData", L"boot services data",
L"EfiRuntimeServicesCode", L"runtime services code",
L"EfiRuntimeServicesData", L"runtime services data",
L"EfiConventionalMemory", L"conventional memory",
L"EfiUnusableMemory", L"unusable memory",
L"EfiACPIReclaimMemory", L"acpi reclaim memory",
L"EfiACPIMemoryNVS", L"acpi memory nvs",
L"EfiMemoryMappedIO", L"memory mapped io",
L"EfiMemoryMappedIOPortSpace", L"memory mapped io port space",
L"EfiPalCode", L"pal code",
L"EfiPersistentMemory", L"persistent memory"
};
static const wchar_t *kernel_memory_type_names[] = {
L"free",
L"pending",
L"acpi",
L"uefi_runtime",
L"mmio",
L"persistent"
}; };
static const wchar_t * static const wchar_t *
memory_type_name(UINT32 value) memory_type_name(uefi::memory_type t)
{ {
if (value >= (sizeof(memory_type_names) / sizeof(wchar_t *))) { if (t < uefi::memory_type::max_memory_type)
switch (value) { return memory_type_names[static_cast<uint32_t>(t)];
case memtype_kernel: return L"Kernel Data";
case memtype_data: return L"Kernel Data"; return L"Bad Type Value";
case memtype_initrd: return L"Initial Ramdisk";
case memtype_scratch: return L"Kernel Scratch Space";
default: return L"Bad Type Value";
}
}
return memory_type_names[value];
} }
void EFIAPI static const wchar_t *
memory_update_marked_addresses(EFI_EVENT UNUSED *event, void *context) kernel_memory_type_name(kernel::args::mem_type t)
{ {
EFI_RUNTIME_SERVICES *runsvc = (EFI_RUNTIME_SERVICES*)context; return kernel_memory_type_names[static_cast<uint32_t>(t)];
for (size_t i = 0; i < fixup_pointer_index; ++i) {
if (fixup_pointers[i])
runsvc->ConvertPointer(0, fixup_pointers[i]);
}
}
EFI_STATUS
memory_init_pointer_fixup(EFI_BOOT_SERVICES *bootsvc, EFI_RUNTIME_SERVICES *runsvc, unsigned scratch_pages)
{
EFI_STATUS status;
EFI_EVENT event;
status = bootsvc->CreateEvent(
EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,
TPL_CALLBACK,
(EFI_EVENT_NOTIFY)&memory_update_marked_addresses,
runsvc,
&event);
CHECK_EFI_STATUS_OR_RETURN(status, "Failed to initialize pointer update event.");
// Reserve a page for our replacement PML4, plus some pages for the kernel to use
// as page tables while it gets started.
EFI_PHYSICAL_ADDRESS addr = 0;
status = bootsvc->AllocatePages(AllocateAnyPages, memtype_scratch, scratch_pages, &addr);
CHECK_EFI_STATUS_OR_RETURN(status, "Failed to allocate page table pages.");
new_pml4 = (uint64_t *)addr;
return EFI_SUCCESS;
} }
void void
memory_mark_pointer_fixup(void **p) update_marked_addresses(uefi::event, void *context)
{ {
if (fixup_pointer_index == 0) { uefi::runtime_services *rs =
const size_t count = sizeof(fixup_pointers) / sizeof(void*); reinterpret_cast<uefi::runtime_services*>(context);
for (size_t i = 0; i < count; ++i) fixup_pointers[i] = 0;
for (size_t i = 0; i < fixup_pointer_index; ++i) {
if (fixup_pointers[i])
rs->convert_pointer(0, fixup_pointers[i]);
} }
}
void
init_pointer_fixup(uefi::boot_services *bs, uefi::runtime_services *rs)
{
status_line status(L"Initializing pointer virtualization event");
uefi::event event;
bs->set_mem(&fixup_pointers, sizeof(fixup_pointers), 0);
fixup_pointer_index = 0;
try_or_raise(
bs->create_event(
uefi::evt::signal_virtual_address_change,
uefi::tpl::callback,
(uefi::event_notify)&update_marked_addresses,
rs,
&event),
L"Error creating memory virtualization event");
}
void
mark_pointer_fixup(void **p)
{
fixup_pointers[fixup_pointer_index++] = p; fixup_pointers[fixup_pointer_index++] = p;
} }
void bool
copy_desc(EFI_MEMORY_DESCRIPTOR *src, EFI_MEMORY_DESCRIPTOR *dst, size_t len) can_merge(mem_entry &prev, mem_type type, uefi::memory_descriptor *next)
{ {
uint8_t *srcb = (uint8_t *)src; return
uint8_t *dstb = (uint8_t *)dst; prev.type == type &&
uint8_t *endb = srcb + len; prev.start + (page_size * prev.pages) == next->physical_start &&
while (srcb < endb) prev.attr == (next->attribute & 0xffffffff);
*dstb++ = *srcb++;
}
EFI_STATUS
memory_get_map_length(EFI_BOOT_SERVICES *bootsvc, size_t *size)
{
if (size == NULL)
return EFI_INVALID_PARAMETER;
EFI_STATUS status;
size_t key, desc_size;
uint32_t desc_version;
*size = 0;
status = bootsvc->GetMemoryMap(size, 0, &key, &desc_size, &desc_version);
if (status != EFI_BUFFER_TOO_SMALL) {
CHECK_EFI_STATUS_OR_RETURN(status, "Failed to get memory map size");
}
return EFI_SUCCESS;
}
EFI_STATUS
memory_get_map(EFI_BOOT_SERVICES *bootsvc, struct memory_map *map)
{
EFI_STATUS status;
if (map == NULL)
return EFI_INVALID_PARAMETER;
size_t needs_size = 0;
status = memory_get_map_length(bootsvc, &needs_size);
if (EFI_ERROR(status)) return status;
if (map->length < needs_size)
return EFI_BUFFER_TOO_SMALL;
status = bootsvc->GetMemoryMap(&map->length, map->entries, &map->key, &map->size, &map->version);
CHECK_EFI_STATUS_OR_RETURN(status, "Failed to load memory map");
return EFI_SUCCESS;
}
EFI_STATUS
memory_dump_map(struct memory_map *map)
{
if (map == NULL)
return EFI_INVALID_PARAMETER;
const size_t count = map->length / map->size;
console::print(L"Memory map:\n");
console::print(L"\t Descriptor Count: %d (%d bytes)\n", count, map->length);
console::print(L"\t Descriptor Size: %d bytes\n", map->size);
console::print(L"\t Type offset: %d\n\n", offsetof(EFI_MEMORY_DESCRIPTOR, Type));
EFI_MEMORY_DESCRIPTOR *end = INCREMENT_DESC(map->entries, map->length);
EFI_MEMORY_DESCRIPTOR *d = map->entries;
while (d < end) {
int runtime = (d->Attribute & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME;
console::print(L"%s%s ", memory_type_name(d->Type), runtime ? L"*" : L" ");
console::print(L"%lx ", d->PhysicalStart);
console::print(L"%lx ", d->VirtualStart);
console::print(L"[%4d]\n", d->NumberOfPages);
d = INCREMENT_DESC(d, map->size);
}
return EFI_SUCCESS;
} }
void void
memory_virtualize(EFI_RUNTIME_SERVICES *runsvc, struct memory_map *map) get_uefi_mappings(efi_mem_map *map, bool allocate, uefi::boot_services *bs)
{ {
memory_mark_pointer_fixup((void **)&runsvc); size_t length = 0;
memory_mark_pointer_fixup((void **)&map); uefi::status status = bs->get_memory_map(
&length, nullptr, &map->key, &map->size, &map->version);
// Get the pointer to the start of PML4 if (status != uefi::status::buffer_too_small)
uint64_t* cr3 = 0; error::raise(status, L"Error getting memory map size");
__asm__ __volatile__ ( "mov %%cr3, %0" : "=r" (cr3) );
// PML4 is indexed with bits 39:47 of the virtual address map->length = length;
uint64_t offset = (KERNEL_VIRT_ADDRESS >> 39) & 0x1ff;
// Double map the lower half pages that are present into the higher half if (allocate) {
for (unsigned i = 0; i < offset; ++i) { map->length += 10*map->size;
if (cr3[i] & 0x1)
new_pml4[i] = new_pml4[offset+i] = cr3[i]; try_or_raise(
else bs->allocate_pool(
new_pml4[i] = new_pml4[offset+i] = 0; uefi::memory_type::loader_data, map->length,
reinterpret_cast<void**>(&map->entries)),
L"Allocating space for memory map");
try_or_raise(
bs->get_memory_map(&map->length, map->entries, &map->key, &map->size, &map->version),
L"Getting UEFI memory map");
} }
}
// Write our new PML4 pointer back to CR3 efi_mem_map
__asm__ __volatile__ ( "mov %0, %%cr3" :: "r" (new_pml4) ); build_kernel_mem_map(kernel::args::header *args, uefi::boot_services *bs)
{
status_line status {L"Creating kernel memory map"};
EFI_MEMORY_DESCRIPTOR *end = INCREMENT_DESC(map->entries, map->length); efi_mem_map map;
EFI_MEMORY_DESCRIPTOR *d = map->entries; get_uefi_mappings(&map, false, bs);
while (d < end) {
switch (d->Type) {
case memtype_kernel:
case memtype_data:
case memtype_initrd:
case memtype_scratch:
d->Attribute |= EFI_MEMORY_RUNTIME;
d->VirtualStart = d->PhysicalStart + KERNEL_VIRT_ADDRESS;
default: size_t map_size = map.num_entries() * sizeof(mem_entry);
if (d->Attribute & EFI_MEMORY_RUNTIME) {
d->VirtualStart = d->PhysicalStart + KERNEL_VIRT_ADDRESS; kernel::args::mem_entry *kernel_map = nullptr;
} try_or_raise(
bs->allocate_pages(
uefi::allocate_type::any_pages,
uefi::memory_type::loader_data,
bytes_to_pages(map_size),
reinterpret_cast<void**>(&kernel_map)),
L"Error allocating kernel memory map module space");
bs->set_mem(kernel_map, map_size, 0);
get_uefi_mappings(&map, true, bs);
size_t i = 0;
bool first = true;
for (auto desc : map) {
/*
// EFI map dump
console::print(L" Range %lx (%lx) %x(%s) [%lu]\r\n",
desc->physical_start, desc->attribute, desc->type, memory_type_name(desc->type), desc->number_of_pages);
*/
mem_type type;
switch (desc->type) {
case uefi::memory_type::reserved:
case uefi::memory_type::unusable_memory:
case uefi::memory_type::acpi_memory_nvs:
case uefi::memory_type::pal_code:
continue;
case uefi::memory_type::loader_code:
case uefi::memory_type::boot_services_code:
case uefi::memory_type::boot_services_data:
case uefi::memory_type::conventional_memory:
type = mem_type::free;
break;
case uefi::memory_type::loader_data:
type = mem_type::pending;
break;
case uefi::memory_type::runtime_services_code:
case uefi::memory_type::runtime_services_data:
type = mem_type::uefi_runtime;
break;
case uefi::memory_type::acpi_reclaim_memory:
type = mem_type::acpi;
break;
case uefi::memory_type::memory_mapped_io:
case uefi::memory_type::memory_mapped_io_port_space:
type = mem_type::mmio;
break;
case uefi::memory_type::persistent_memory:
type = mem_type::persistent;
break;
default:
error::raise(
uefi::status::invalid_parameter,
L"Got an unexpected memory type from UEFI memory map");
}
// TODO: validate uefi's map is sorted
if (first) {
first = false;
kernel_map[i].start = desc->physical_start;
kernel_map[i].pages = desc->number_of_pages;
kernel_map[i].type = type;
kernel_map[i].attr = (desc->attribute & 0xffffffff);
continue;
}
mem_entry &prev = kernel_map[i];
if (can_merge(prev, type, desc)) {
prev.pages += desc->number_of_pages;
} else {
mem_entry &next = kernel_map[++i];
next.start = desc->physical_start;
next.pages = desc->number_of_pages;
next.type = type;
next.attr = (desc->attribute & 0xffffffff);
} }
d = INCREMENT_DESC(d, map->size);
} }
runsvc->SetVirtualAddressMap(map->length, map->size, map->version, map->entries); // Give just the actually-set entries in the header
args->mem_map = kernel_map;
args->map_count = i;
/*
// kernel map dump
for (unsigned i = 0; i < args->map_count; ++i) {
const kernel::args::mem_entry &e = kernel_map[i];
console::print(L" Range %lx (%lx) %x(%s) [%lu]\r\n",
e.start, e.attr, e.type, kernel_memory_type_name(e.type), e.pages);
}
*/
return map;
} }
void
virtualize(void *pml4, efi_mem_map &map, uefi::runtime_services *rs)
{
paging::add_current_mappings(reinterpret_cast<paging::page_table*>(pml4));
for (auto desc : map)
desc->virtual_start = desc->physical_start + ::memory::page_offset;
// Write our new PML4 pointer to CR3
asm volatile ( "mov %0, %%cr3" :: "r" (pml4) );
__sync_synchronize();
try_or_raise(
rs->set_virtual_address_map(
map.length, map.size, map.version, map.entries),
L"Error setting virtual address map");
}
} // namespace boot
} // namespace memory

View File

@@ -1,27 +1,75 @@
/// \file memory.h
/// Memory-related constants and functions.
#pragma once #pragma once
#include <efi/efi.h> #include <uefi/boot_services.h>
#include <uefi/runtime_services.h>
#include <stdint.h>
#include "kernel_args.h"
#include "pointer_manipulation.h"
extern const EFI_MEMORY_TYPE memtype_kernel; namespace boot {
extern const EFI_MEMORY_TYPE memtype_data; namespace memory {
extern const EFI_MEMORY_TYPE memtype_initrd;
extern const EFI_MEMORY_TYPE memtype_scratch;
struct memory_map { /// UEFI specifies that pages are always 4 KiB.
size_t length; constexpr size_t page_size = 0x1000;
size_t size;
size_t key; /// Get the number of pages needed to hold `bytes` bytes
uint32_t version; inline constexpr size_t bytes_to_pages(size_t bytes) {
EFI_MEMORY_DESCRIPTOR *entries; return ((bytes - 1) / page_size) + 1;
}
/// \defgroup pointer_fixup
/// Memory virtualization pointer fixup functions. Handles changing affected pointers
/// when calling UEFI's `set_virtual_address_map` function to change the location of
/// runtime services in virtual memory.
/// @{
/// Set up the pointer fixup UEFI events. This registers the necessary callbacks for
/// runtime services to call when `set_virtual_address_map` is called.
void init_pointer_fixup(uefi::boot_services *bs, uefi::runtime_services *rs);
/// Mark a given pointer as needing to be updated when doing pointer fixup.
void mark_pointer_fixup(void **p);
/// @}
/// Struct that represents UEFI's memory map. Contains a pointer to the map data
/// as well as the data on how to read it.
struct efi_mem_map
{
using desc = uefi::memory_descriptor;
using iterator = offset_iterator<desc>;
size_t length; ///< Total length of the map data
size_t size; ///< Size of an entry in the array
size_t key; ///< Key for detecting changes
uint32_t version; ///< Version of the `memory_descriptor` struct
desc *entries; ///< The array of UEFI descriptors
efi_mem_map() : length(0), size(0), key(0), version(0), entries(nullptr) {}
/// Get the count of entries in the array
inline size_t num_entries() const { return length / size; }
/// Return an iterator to the beginning of the array
iterator begin() { return iterator(entries, size); }
/// Return an iterator to the end of the array
iterator end() { return offset_ptr<desc>(entries, length); }
}; };
EFI_STATUS memory_init_pointer_fixup( /// Add the kernel's memory map as a module to the kernel args.
EFI_BOOT_SERVICES *bootsvc, /// \returns The uefi memory map used to build the kernel map
EFI_RUNTIME_SERVICES *runsvc, efi_mem_map build_kernel_mem_map(kernel::args::header *args, uefi::boot_services *bs);
unsigned scratch_pages);
void memory_mark_pointer_fixup(void **p);
EFI_STATUS memory_get_map_length(EFI_BOOT_SERVICES *bootsvc, size_t *size); /// Activate the given memory mappings. Sets the given page tables live as well
EFI_STATUS memory_get_map(EFI_BOOT_SERVICES *bootsvc, struct memory_map *map); /// as informs UEFI runtime services of the new mappings.
EFI_STATUS memory_dump_map(struct memory_map *map); /// \arg pml4 The root page table for the new mappings
/// \arg map The UEFI memory map, used to update runtime services
void virtualize(
void *pml4,
efi_mem_map &map,
uefi::runtime_services *rs);
void memory_virtualize(EFI_RUNTIME_SERVICES *runsvc, struct memory_map *map); } // namespace boot
} // namespace memory

253
src/boot/paging.cpp Normal file
View File

@@ -0,0 +1,253 @@
#include "kernel_memory.h"
#include "console.h"
#include "error.h"
#include "loader.h"
#include "memory.h"
#include "paging.h"
#include "pointer_manipulation.h"
#include "status.h"
namespace boot {
namespace paging {
using memory::page_size;
using ::memory::pml4e_kernel;
using ::memory::table_entries;
// Flags: 0 0 0 1 0 0 0 0 0 0 1 1 = 0x0103
// IGN | | | | | | | | +- Present
// | | | | | | | +--- Writeable
// | | | | | | +----- Usermode access (supervisor only)
// | | | | | +------- PWT (determining memory type for page)
// | | | | +---------- PCD (determining memory type for page)
// | | | +------------ Accessed flag (not accessed yet)
// | | +-------------- Dirty (not dirtied yet)
// | +---------------- PAT (determining memory type for page)
// +------------------- Global
/// Page table entry flags for entries pointing at a page
constexpr uint16_t page_flags = 0x103;
// Flags: 0 0 0 0 1 1 0 0 0 1 0 1 1 = 0x018b
// | IGN | | | | | | | | +- Present
// | | | | | | | | +--- Writeable
// | | | | | | | +----- Supervisor only
// | | | | | | +------- PWT (determining memory type for page)
// | | | | | +---------- PCD (determining memory type for page)
// | | | | +------------ Accessed flag (not accessed yet)
// | | | +-------------- Dirty (not dirtied yet)
// | | +---------------- Page size (1GiB page)
// | +------------------- Global
// +---------------------------- PAT (determining memory type for page)
/// Page table entry flags for entries pointing at a huge page
constexpr uint16_t huge_page_flags = 0x183;
// Flags: 0 0 0 0 0 0 0 0 0 0 1 1 = 0x0003
// IGNORED | | | | | | | +- Present
// | | | | | | +--- Writeable
// | | | | | +----- Usermode access (Supervisor only)
// | | | | +------- PWT (determining memory type for pdpt)
// | | | +---------- PCD (determining memory type for pdpt)
// | | +------------ Accessed flag (not accessed yet)
// | +-------------- Ignored
// +---------------- Reserved 0 (Table pointer, not page)
/// Page table entry flags for entries pointing at another table
constexpr uint16_t table_flags = 0x003;
/// Iterator over page table entries.
template <unsigned D = 4>
class page_entry_iterator
{
public:
/// Constructor.
/// \arg virt Virtual address this iterator is starting at
/// \arg pml4 Root of the page tables to iterate
/// \arg page_cache Pointer to pages that can be used for page tables
/// \arg page_count Number of pages pointed to by `page_cache`
page_entry_iterator(
uintptr_t virt,
page_table *pml4,
void *&page_cache,
size_t &cache_count) :
m_page_cache(page_cache),
m_cache_count(cache_count)
{
m_table[0] = pml4;
for (unsigned i = 0; i < D; ++i) {
m_index[i] = static_cast<uint16_t>((virt >> (12 + 9*(3-i))) & 0x1ff);
ensure_table(i);
}
}
uintptr_t vaddress() const {
uintptr_t address = 0;
for (unsigned i = 0; i < D; ++i)
address |= static_cast<uintptr_t>(m_index[i]) << (12 + 9*(3-i));
if (address & (1ull<<47)) // canonicalize the address
address |= (0xffffull<<48);
return address;
}
void increment()
{
for (unsigned i = D - 1; i >= 0; --i) {
if (++m_index[i] <= 511) {
for (unsigned j = i + 1; j < D; ++j)
ensure_table(j);
return;
}
m_index[i] = 0;
}
}
uint64_t & operator*() { return entry(D-1); }
private:
inline uint64_t & entry(unsigned level) { return m_table[level]->entries[m_index[level]]; }
void ensure_table(unsigned level)
{
// We're only dealing with D levels of paging, and
// there must always be a PML4.
if (level < 1 || level >= D)
return;
// Entry in the parent that points to the table we want
uint64_t & parent_ent = entry(level - 1);
if (!(parent_ent & 1)) {
if (!m_cache_count--)
error::raise(uefi::status::out_of_resources, L"Page table cache empty");
page_table *table = reinterpret_cast<page_table*>(m_page_cache);
m_page_cache = offset_ptr<void>(m_page_cache, page_size);
parent_ent = (reinterpret_cast<uintptr_t>(table) & ~0xfffull) | table_flags;
m_table[level] = table;
} else {
m_table[level] = reinterpret_cast<page_table*>(parent_ent & ~0xfffull);
}
}
void *&m_page_cache;
size_t &m_cache_count;
page_table *m_table[D];
uint16_t m_index[D];
};
static void
add_offset_mappings(page_table *pml4, void *&page_cache, size_t &num_pages)
{
uintptr_t phys = 0;
uintptr_t virt = ::memory::page_offset; // Start of offset-mapped area
size_t pages = 64 * 1024; // 64 TiB of 1 GiB pages
constexpr size_t GiB = 0x40000000ull;
page_entry_iterator<2> iterator{
virt, pml4,
page_cache,
num_pages};
while (true) {
*iterator = phys | huge_page_flags;
if (--pages == 0)
break;
iterator.increment();
phys += GiB;
}
}
static void
add_kernel_pds(page_table *pml4, void *&page_cache, size_t &num_pages)
{
for (unsigned i = pml4e_kernel; i < table_entries; ++i) {
pml4->set(i, page_cache, table_flags);
page_cache = offset_ptr<void>(page_cache, page_size);
num_pages--;
}
}
void
add_current_mappings(page_table *new_pml4)
{
// Get the pointer to the current PML4
page_table *old_pml4 = 0;
asm volatile ( "mov %%cr3, %0" : "=r" (old_pml4) );
// Only copy mappings in the lower half
for (int i = 0; i < ::memory::pml4e_kernel; ++i) {
uint64_t entry = old_pml4->entries[i];
if (entry & 1)
new_pml4->entries[i] = entry;
}
}
void
allocate_tables(kernel::args::header *args, uefi::boot_services *bs)
{
status_line status(L"Allocating initial page tables");
static constexpr size_t pd_tables = 256; // number of pages for kernelspace PDs
static constexpr size_t extra_tables = 49; // number of extra pages
// number of pages for kernelspace PDs + PML4
static constexpr size_t kernel_tables = pd_tables + 1;
static constexpr size_t tables_needed = kernel_tables + extra_tables;
void *addr = nullptr;
try_or_raise(
bs->allocate_pages(
uefi::allocate_type::any_pages,
uefi::memory_type::loader_data,
tables_needed,
&addr),
L"Error allocating page table pages.");
bs->set_mem(addr, tables_needed*page_size, 0);
page_table *pml4 = reinterpret_cast<page_table*>(addr);
args->pml4 = pml4;
args->table_count = tables_needed - 1;
args->page_tables = offset_ptr<void>(addr, page_size);
console::print(L" First page (pml4) at: 0x%lx\r\n", pml4);
add_kernel_pds(pml4, args->page_tables, args->table_count);
add_offset_mappings(pml4, args->page_tables, args->table_count);
console::print(L" Set up initial mappings, %d spare tables.\r\n", args->table_count);
}
void
map_pages(
kernel::args::header *args,
uintptr_t phys, uintptr_t virt,
size_t size)
{
paging::page_table *pml4 =
reinterpret_cast<paging::page_table*>(args->pml4);
size_t pages = memory::bytes_to_pages(size);
page_entry_iterator<4> iterator{
virt, pml4,
args->page_tables,
args->table_count};
while (true) {
*iterator = phys | page_flags;
if (--pages == 0)
break;
iterator.increment();
phys += page_size;
}
}
} // namespace paging
} // namespace boot

52
src/boot/paging.h Normal file
View File

@@ -0,0 +1,52 @@
#pragma once
/// \file paging.h
/// Page table structure and related definitions
#include <stdint.h>
#include <uefi/boot_services.h>
#include "kernel_args.h"
namespace boot {
namespace paging {
/// Struct to allow easy accessing of a memory page being used as a page table.
struct page_table
{
uint64_t entries[512];
inline page_table * get(int i, uint16_t *flags = nullptr) const {
uint64_t entry = entries[i];
if ((entry & 1) == 0) return nullptr;
if (flags) *flags = entry & 0xfff;
return reinterpret_cast<page_table *>(entry & ~0xfffull);
}
inline void set(int i, void *p, uint16_t flags) {
entries[i] = reinterpret_cast<uint64_t>(p) | (flags & 0xfff);
}
};
/// Allocate memory to be used for initial page tables. Initial offset-mapped
/// page tables are pre-filled. All pages are saved as a module in kernel args
/// and kernel args' `page_table_cache` and `num_free_tables` are updated with
/// the leftover space.
void allocate_tables(
kernel::args::header *args,
uefi::boot_services *bs);
/// Copy existing page table entries to a new page table. Does not do a deep
/// copy - the new PML4 is updated to point to the existing next-level page
/// tables in the current PML4.
void add_current_mappings(page_table *new_pml4);
/// Map a physical address to a virtual address in the given page tables.
/// \arg args The kernel args header, used for the page table cache and pml4
/// \arg phys The phyiscal address to map in
/// \arg virt The virtual address to map in
/// \arg size The size in bytes of the mapping
void map_pages(
kernel::args::header *args,
uintptr_t phys, uintptr_t virt,
size_t bytes);
} // namespace paging
} // namespace boot

View File

@@ -0,0 +1,41 @@
/// \file pointer_manipulation.h
/// Helper functions and types for doing type-safe byte-wise pointer math.
#pragma once
namespace boot {
/// Return a pointer offset from `input` by `offset` bytes.
/// \tparam T Cast the return value to a pointer to `T`
/// \tparam S The type pointed to by the `input` pointer
template <typename T, typename S>
inline T* offset_ptr(S* input, ptrdiff_t offset) {
return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(input) + offset);
}
/// Iterator for an array of `T` whose size is known at runtime
/// \tparam T Type of the objects in the array, whose size might not be
/// what is returned by sizeof(T).
template <typename T>
class offset_iterator
{
public:
/// Constructor.
/// \arg t Pointer to the first item in the array
/// \arg off Offset applied to reach successive items. Default is 0,
/// which creates an effectively constant iterator.
offset_iterator(T* t, size_t off=0) : m_t(t), m_off(off) {}
T* operator++() { m_t = offset_ptr<T>(m_t, m_off); return m_t; }
T* operator++(int) { T* tmp = m_t; operator++(); return tmp; }
bool operator==(T* p) { return p == m_t; }
T* operator*() const { return m_t; }
operator T*() const { return m_t; }
T* operator->() const { return m_t; }
private:
T* m_t;
size_t m_off;
};
} // namespace boot

View File

@@ -1,97 +0,0 @@
/* reloc_x86_64.c - position independent x86_64 ELF shared object relocator
Copyright (C) 1999 Hewlett-Packard Co.
Contributed by David Mosberger <davidm@hpl.hp.com>.
Copyright (C) 2005 Intel Co.
Contributed by Fenghua Yu <fenghua.yu@intel.com>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
* Neither the name of Hewlett-Packard Co. nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*/
#include <efi/efi.h>
#include <elf.h>
extern "C"
EFI_STATUS _relocate (long ldbase, Elf64_Dyn *dyn,
EFI_HANDLE image EFI_UNUSED,
EFI_SYSTEM_TABLE *systab EFI_UNUSED)
{
long relsz = 0, relent = 0;
Elf64_Rel *rel = 0;
unsigned long *addr;
int i;
for (i = 0; dyn[i].d_tag != DT_NULL; ++i) {
switch (dyn[i].d_tag) {
case DT_RELA:
rel = (Elf64_Rel*)
((unsigned long)dyn[i].d_un.d_ptr
+ ldbase);
break;
case DT_RELASZ:
relsz = dyn[i].d_un.d_val;
break;
case DT_RELAENT:
relent = dyn[i].d_un.d_val;
break;
default:
break;
}
}
if (!rel && relent == 0)
return EFI_SUCCESS;
if (!rel || relent == 0)
return EFI_LOAD_ERROR;
while (relsz > 0) {
/* apply the relocs */
switch (ELF64_R_TYPE (rel->r_info)) {
case R_X86_64_NONE:
break;
case R_X86_64_RELATIVE:
addr = (unsigned long *)
(ldbase + rel->r_offset);
*addr += ldbase;
break;
default:
break;
}
rel = (Elf64_Rel*) ((char *) rel + relent);
relsz -= relent;
}
return EFI_SUCCESS;
}

263
src/boot/status.cpp Normal file
View File

@@ -0,0 +1,263 @@
#include <uefi/types.h>
#include <uefi/graphics.h>
#include "console.h"
#include "error.h"
#include "kernel_args.h"
#include "status.h"
constexpr int num_boxes = 30;
namespace boot {
static constexpr int level_ok = 0;
static constexpr int level_warn = 1;
static constexpr int level_fail = 2;
static const wchar_t *level_tags[] = {
L" ok ",
L" warn ",
L"failed"
};
static const uefi::attribute level_colors[] = {
uefi::attribute::green,
uefi::attribute::brown,
uefi::attribute::light_red
};
status *status::s_current = nullptr;
unsigned status::s_current_type = 0;
unsigned status_bar::s_count = 0;
status_line::status_line(const wchar_t *message, const wchar_t *context) :
m_level(level_ok),
m_depth(0),
m_outer(nullptr)
{
if (status::s_current_type == status_line::type) {
m_outer = static_cast<status_line*>(s_current);
m_depth = (m_outer ? 1 + m_outer->m_depth : 0);
}
s_current = this;
s_current_type = status_line::type;
auto out = console::get().m_out;
m_line = out->mode->cursor_row;
int indent = 2 * m_depth;
out->set_cursor_position(indent, m_line);
out->set_attribute(uefi::attribute::light_gray);
out->output_string(message);
if (context) {
out->output_string(L": ");
out->output_string(context);
}
out->output_string(L"\r\n");
print_status_tag();
}
status_line::~status_line()
{
if (s_current != this)
error::raise(uefi::status::unsupported, L"Destroying non-current status_line");
if (m_outer && m_level > m_outer->m_level) {
m_outer->m_level = m_level;
m_outer->print_status_tag();
}
s_current = m_outer;
}
void
status_line::print_status_tag()
{
auto out = console::get().m_out;
int row = out->mode->cursor_row;
int col = out->mode->cursor_column;
uefi::attribute color = level_colors[m_level];
const wchar_t *tag = level_tags[m_level];
out->set_cursor_position(50, m_line);
out->set_attribute(uefi::attribute::light_gray);
out->output_string(L"[");
out->set_attribute(color);
out->output_string(tag);
out->set_attribute(uefi::attribute::light_gray);
out->output_string(L"]\r\n");
out->set_cursor_position(col, row);
}
void
status_line::do_warn(const wchar_t *message, uefi::status status)
{
auto out = console::get().m_out;
int row = out->mode->cursor_row;
if (m_level < level_warn) {
m_level = level_warn;
print_status_tag();
}
int indent = 2 + 2 * m_depth;
out->set_cursor_position(indent, row);
out->set_attribute(uefi::attribute::yellow);
out->output_string(message);
const wchar_t *error = error::message(status);
if (error) {
out->output_string(L": ");
out->output_string(error);
}
out->set_attribute(uefi::attribute::light_gray);
out->output_string(L"\r\n");
}
void
status_line::do_fail(const wchar_t *message, uefi::status status)
{
auto out = console::get().m_out;
int row = out->mode->cursor_row;
if (m_level < level_fail) {
m_level = level_fail;
print_status_tag();
}
int indent = 2 + 2 * m_depth;
out->set_cursor_position(indent, row);
out->set_attribute(uefi::attribute::red);
out->output_string(message);
const wchar_t *error = error::message(status);
if (error) {
out->output_string(L": ");
out->output_string(error);
}
out->set_attribute(uefi::attribute::light_gray);
out->output_string(L"\r\n");
}
status_bar::status_bar(kernel::args::framebuffer const &fb) :
m_outer(nullptr)
{
m_size = (fb.vertical / num_boxes) - 1;
m_top = fb.vertical - m_size;
m_horiz = fb.horizontal;
m_fb = reinterpret_cast<uint32_t*>(fb.phys_addr);
m_type = static_cast<uint16_t>(fb.type);
next();
if (status::s_current_type == status_bar::type)
m_outer = static_cast<status_bar*>(s_current);
s_current = this;
s_current_type = status_bar::type;
}
status_bar::~status_bar()
{
if (s_current != this)
error::raise(uefi::status::unsupported, L"Destroying non-current status_bar");
draw_box();
s_current = m_outer;
}
void
status_bar::do_warn(const wchar_t *message, uefi::status status)
{
m_status = status;
if (m_level < level_warn) {
m_level = level_warn;
draw_box();
}
}
void
status_bar::do_fail(const wchar_t *message, uefi::status status)
{
m_status = status;
if (m_level < level_fail) {
m_level = level_fail;
draw_box();
}
}
static uint32_t
make_color(uint8_t r, uint8_t g, uint8_t b, uint16_t type)
{
switch (static_cast<kernel::args::fb_type>(type)) {
case kernel::args::fb_type::bgr8:
return
(static_cast<uint32_t>(b) << 0) |
(static_cast<uint32_t>(g) << 8) |
(static_cast<uint32_t>(r) << 16);
case kernel::args::fb_type::rgb8:
return
(static_cast<uint32_t>(r) << 0) |
(static_cast<uint32_t>(g) << 8) |
(static_cast<uint32_t>(b) << 16);
default:
return 0;
}
}
void
status_bar::draw_box()
{
static const uint32_t colors[] = {0x909090, 0xf0f0f0};
constexpr unsigned ncolors = sizeof(colors) / sizeof(uint32_t);
if (m_fb == nullptr)
return;
unsigned x0 = m_current * m_size;
unsigned x1 = x0 + m_size - 3;
unsigned y0 = m_top;
unsigned y1 = m_top + m_size - 3;
uint32_t color = 0;
switch (m_level) {
case level_ok:
color = colors[m_current % ncolors];
break;
case level_warn:
color = make_color(0xff, 0xb2, 0x34, m_type);
break;
case level_fail:
color = make_color(0xfb, 0x0a, 0x1e, m_type);
break;
default:
color = 0;
}
for (unsigned y = y0; y < y1; ++y)
for (unsigned x = x0; x < x1; ++x)
m_fb[y * m_horiz + x] = color;
if (m_level > level_ok) {
unsigned nbars = static_cast<uint64_t>(m_status) & 0xffff;
constexpr unsigned bar_height = 4;
for (unsigned i = 1; i <= nbars; ++i) {
y0 = m_top - 2 * i * bar_height;
y1 = y0 + bar_height;
for (unsigned y = y0; y < y1; ++y)
for (unsigned x = x0; x < x1; ++x)
m_fb[y * m_horiz + x] = color;
}
}
}
} // namespace boot

122
src/boot/status.h Normal file
View File

@@ -0,0 +1,122 @@
/// \file status.h
/// Status message and indicator handling
#pragma once
#include <stdint.h>
#include <uefi/types.h>
namespace kernel {
namespace args {
class framebuffer;
}
}
namespace boot {
// Abstract base class for status reporters.
class status
{
public:
virtual void do_warn(const wchar_t *message, uefi::status status) = 0;
virtual void do_fail(const wchar_t *message, uefi::status status) = 0;
/// Set the state to warning, and print a message. If the state is already at
/// warning or error, the state is unchanged but the message is still printed.
/// \arg message The warning message to print, if text is supported
/// \arg status If set, the error or warning code that should be represented
/// \returns True if there was a status handler to display the warning
inline static bool warn(const wchar_t *message, uefi::status status = uefi::status::success) {
if (!s_current) return false;
s_current->do_warn(message, status);
return true;
}
/// Set the state to error, and print a message. If the state is already at
/// error, the state is unchanged but the message is still printed.
/// \arg message The error message to print, if text is supported
/// \arg status The error or warning code that should be represented
/// \returns True if there was a status handler to display the failure
inline static bool fail(const wchar_t *message, uefi::status status) {
if (!s_current) return false;
s_current->do_fail(message, status);
return true;
}
protected:
static status *s_current;
static unsigned s_current_type;
};
/// Scoped status line reporter. Prints a message and an "OK" if no errors
/// or warnings were reported before destruction, otherwise reports the
/// error or warning.
class status_line :
public status
{
public:
constexpr static unsigned type = 1;
/// Constructor.
/// \arg message Description of the operation in progress
/// \arg context If non-null, printed after `message` and a colon
status_line(const wchar_t *message, const wchar_t *context = nullptr);
~status_line();
virtual void do_warn(const wchar_t *message, uefi::status status) override;
virtual void do_fail(const wchar_t *message, uefi::status status) override;
private:
void print_status_tag();
size_t m_line;
int m_level;
int m_depth;
status_line *m_outer;
};
/// Scoped status bar reporter. Draws a row of boxes along the bottom of
/// the screen, turning one red if there's an error in that step.
class status_bar :
public status
{
public:
constexpr static unsigned type = 2;
using framebuffer = kernel::args::framebuffer;
/// Constructor.
/// \arg fb The framebuffer descriptor to draw to
status_bar(kernel::args::framebuffer const &fb);
~status_bar();
virtual void do_warn(const wchar_t *message, uefi::status status) override;
virtual void do_fail(const wchar_t *message, uefi::status status) override;
inline void next() {
m_current = s_count++;
m_level = 0;
m_status = uefi::status::success;
draw_box();
}
private:
void draw_box();
uint32_t *m_fb;
uint32_t m_size;
uint32_t m_top;
uint32_t m_horiz;
int m_level;
uefi::status m_status;
uint16_t m_type;
uint16_t m_current;
status_bar *m_outer;
static unsigned s_count;
};
} // namespace boot

39
src/boot/support.cpp Normal file
View File

@@ -0,0 +1,39 @@
#include <stdint.h>
#include "error.h"
extern "C" {
/// Basic memcpy() implementation for clang. Clang requires freestanding code
/// implement memcpy(), as it may emit references to it. This basic memcpy is
/// not the most efficient, but will get linked if no other memcpy exists.
__attribute__ ((__weak__))
void *memcpy(void *dest, const void *src, size_t n)
{
uint8_t *cdest = reinterpret_cast<uint8_t*>(dest);
const uint8_t *csrc = reinterpret_cast<const uint8_t*>(src);
for (size_t i = 0; i < n; ++i)
cdest[i] = csrc[i];
return dest;
}
/// Basic memset() implementation for clang. Clang requires freestanding code
/// implement memset(), as it may emit references to it. This basic memset is
/// not the most efficient, but will get linked if no other memcpy exists.
__attribute__ ((__weak__))
void *memset(void *dest, int c, size_t n)
{
uint8_t *cdest = reinterpret_cast<uint8_t*>(dest);
for (size_t i = 0; i < n; ++i)
cdest[i] = static_cast<uint8_t>(c);
return dest;
}
int _purecall()
{
::boot::error::raise(uefi::status::unsupported, L"Pure virtual call");
}
} // extern "C"
void operator delete (void *) {}

13
src/boot/types.h Normal file
View File

@@ -0,0 +1,13 @@
/// \file types.h
/// Definitions of shared types used throughout the bootloader
#pragma once
namespace boot {
struct buffer
{
size_t size;
void *data;
};
} // namespace boot

View File

@@ -1,71 +0,0 @@
#include "utility.h"
struct error_code_desc {
EFI_STATUS code;
const wchar_t *name;
};
// Based off the gnu-efi table
struct error_code_desc error_table[] = {
{ EFI_SUCCESS, L"Success" },
{ EFI_LOAD_ERROR, L"Load Error" },
{ EFI_INVALID_PARAMETER, L"Invalid Parameter" },
{ EFI_UNSUPPORTED, L"Unsupported" },
{ EFI_BAD_BUFFER_SIZE, L"Bad Buffer Size" },
{ EFI_BUFFER_TOO_SMALL, L"Buffer Too Small" },
{ EFI_NOT_READY, L"Not Ready" },
{ EFI_DEVICE_ERROR, L"Device Error" },
{ EFI_WRITE_PROTECTED, L"Write Protected" },
{ EFI_OUT_OF_RESOURCES, L"Out of Resources" },
{ EFI_VOLUME_CORRUPTED, L"Volume Corrupt" },
{ EFI_VOLUME_FULL, L"Volume Full" },
{ EFI_NO_MEDIA, L"No Media" },
{ EFI_MEDIA_CHANGED, L"Media changed" },
{ EFI_NOT_FOUND, L"Not Found" },
{ EFI_ACCESS_DENIED, L"Access Denied" },
{ EFI_NO_RESPONSE, L"No Response" },
{ EFI_NO_MAPPING, L"No mapping" },
{ EFI_TIMEOUT, L"Time out" },
{ EFI_NOT_STARTED, L"Not started" },
{ EFI_ALREADY_STARTED, L"Already started" },
{ EFI_ABORTED, L"Aborted" },
{ EFI_ICMP_ERROR, L"ICMP Error" },
{ EFI_TFTP_ERROR, L"TFTP Error" },
{ EFI_PROTOCOL_ERROR, L"Protocol Error" },
{ EFI_INCOMPATIBLE_VERSION, L"Incompatible Version" },
{ EFI_SECURITY_VIOLATION, L"Security Policy Violation" },
{ EFI_CRC_ERROR, L"CRC Error" },
{ EFI_END_OF_MEDIA, L"End of Media" },
{ EFI_END_OF_FILE, L"End of File" },
{ EFI_INVALID_LANGUAGE, L"Invalid Languages" },
{ EFI_COMPROMISED_DATA, L"Compromised Data" },
{ EFI_WARN_UNKOWN_GLYPH, L"Warning Unknown Glyph" },
{ EFI_WARN_DELETE_FAILURE, L"Warning Delete Failure" },
{ EFI_WARN_WRITE_FAILURE, L"Warning Write Failure" },
{ EFI_WARN_BUFFER_TOO_SMALL, L"Warning Buffer Too Small" },
{ 0, NULL }
};
const wchar_t *
util_error_message(EFI_STATUS status)
{
int32_t i = -1;
while (error_table[++i].name != NULL) {
if (error_table[i].code == status) return error_table[i].name;
}
if (EFI_ERROR(status))
return L"Unknown Error";
else
return L"Unknown Warning";
}
size_t
wstrlen(const wchar_t *s)
{
size_t count = 0;
while (s && *s++) count++;
return count;
}

View File

@@ -1,40 +0,0 @@
#include <stddef.h>
#include <efi/efi.h>
#include "console.h"
#define UNUSED __attribute__((unused))
size_t wstrlen(const wchar_t *s);
const wchar_t *util_error_message(EFI_STATUS status);
#define CHECK_EFI_STATUS_OR_RETURN(s, msg, ...) \
if (EFI_ERROR((s))) { \
console::print(L"ERROR: " msg L": %s\r\n", ##__VA_ARGS__, util_error_message(s)); \
return (s); \
}
#define CHECK_EFI_STATUS_OR_FAIL(s) \
if (EFI_ERROR((s))) { \
console::get().status_fail(util_error_message(s)); \
while (1) __asm__("hlt"); \
}
#define CHECK_EFI_STATUS_OR_ASSERT(s, d) \
if (EFI_ERROR((s))) { \
__asm__ __volatile__( \
"movq %0, %%r8;" \
"movq %1, %%r9;" \
"movq %2, %%r10;" \
"movq $0, %%rdx;" \
"divq %%rdx;" \
: \
: "r"((uint64_t)s), "r"((uint64_t)d), "r"((uint64_t)__LINE__) \
: "rax", "rdx", "r8", "r9", "r10"); \
}
#ifdef BOOTLOADER_DEBUG
#define con_debug(...) console::print(L"DEBUG: " __VA_ARGS__)
#else
#define con_debug(...)
#endif

View File

@@ -0,0 +1,390 @@
0x72, 0xb5, 0x4a, 0x86, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x7e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x7e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xf8,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xf8, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xf8, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c,
0x22, 0x20, 0x20, 0xf8, 0x20, 0x20, 0x72, 0x8c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10,
0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x24, 0x7e, 0x24, 0x24,
0x24, 0x7e, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08,
0x1e, 0x20, 0x20, 0x1c, 0x02, 0x02, 0x3c, 0x08, 0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x30, 0x49, 0x4a, 0x34, 0x08, 0x16, 0x29, 0x49, 0x06,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x48, 0x48, 0x48, 0x30, 0x31,
0x49, 0x46, 0x46, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08,
0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x24, 0x18, 0x7e, 0x18, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x7f, 0x08, 0x08, 0x08, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x18, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08,
0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
0x42, 0x46, 0x4a, 0x52, 0x62, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x08, 0x18, 0x28, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x02, 0x04,
0x08, 0x10, 0x20, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e,
0x04, 0x08, 0x1c, 0x02, 0x02, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x04, 0x0c, 0x14, 0x24, 0x44, 0x7e, 0x04, 0x04, 0x04,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x40, 0x40, 0x7c, 0x02,
0x02, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c,
0x20, 0x40, 0x40, 0x7c, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7e, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x3c,
0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x04, 0x38, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00,
0x00, 0x00, 0x18, 0x18, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x04,
0x08, 0x10, 0x20, 0x40, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02,
0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42,
0x02, 0x04, 0x08, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1c, 0x22, 0x41, 0x4f, 0x51, 0x51, 0x51, 0x53, 0x4d, 0x40,
0x20, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x42,
0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c,
0x42, 0x42, 0x42, 0x7c, 0x42, 0x42, 0x42, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1e, 0x20, 0x40, 0x40, 0x40, 0x40, 0x40, 0x20, 0x1e,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x44, 0x42, 0x42, 0x42,
0x42, 0x42, 0x44, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e,
0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x40,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x20, 0x40, 0x40, 0x46,
0x42, 0x42, 0x22, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42,
0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42,
0x44, 0x48, 0x50, 0x60, 0x50, 0x48, 0x44, 0x42, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7e,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x63, 0x55, 0x49, 0x49,
0x41, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42,
0x62, 0x52, 0x4a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x7c,
0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x04, 0x02, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x7c, 0x48, 0x44, 0x42, 0x42,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x40, 0x40, 0x20, 0x18,
0x04, 0x02, 0x02, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42,
0x24, 0x24, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
0x41, 0x41, 0x41, 0x49, 0x49, 0x49, 0x55, 0x63, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x41, 0x41, 0x22, 0x14, 0x08, 0x14, 0x22, 0x41, 0x41,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x22, 0x14, 0x08,
0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e,
0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x7e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1e, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x20, 0x20, 0x10, 0x10,
0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x78, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x78, 0x00, 0x00,
0x00, 0x00, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x3e,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x7c, 0x42, 0x42,
0x42, 0x42, 0x42, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3c, 0x42, 0x40, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x02, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42,
0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x10,
0x10, 0x7e, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e,
0x02, 0x02, 0x3c, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x7c, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08,
0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x04, 0x04, 0x00, 0x1c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x38, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x44, 0x48, 0x50,
0x70, 0x48, 0x44, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x7c,
0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42,
0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x2e, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x40, 0x20, 0x18, 0x04, 0x02, 0x7c,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x7e, 0x10, 0x10,
0x10, 0x10, 0x10, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x24, 0x24, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x41,
0x49, 0x49, 0x55, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x41, 0x22, 0x14, 0x08, 0x14, 0x22, 0x41, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e,
0x02, 0x02, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x04, 0x08,
0x10, 0x20, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x10, 0x10,
0x10, 0x10, 0x10, 0xe0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0e, 0x00, 0x00,
0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x00, 0x00, 0x00, 0x70, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07,
0x08, 0x08, 0x08, 0x08, 0x08, 0x70, 0x00, 0x00, 0x00, 0x00, 0x31, 0x49,
0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00,
0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x08, 0x08,
0x1c, 0x22, 0x40, 0x40, 0x40, 0x22, 0x1c, 0x08, 0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1c, 0x22, 0x20, 0x20, 0xf8, 0x20, 0x20, 0x72, 0x8c,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x3c, 0x24, 0x24,
0x24, 0x3c, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
0x22, 0x14, 0x08, 0x3e, 0x08, 0x3e, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08,
0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1c, 0x22, 0x41, 0x4d, 0x51, 0x51, 0x4d, 0x41, 0x22,
0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x09, 0x12, 0x24, 0x48, 0x24, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x08, 0x08, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x24, 0x12, 0x09, 0x12, 0x24, 0x48,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00,
0x00, 0x08, 0x10, 0x20, 0x40, 0x42, 0x3c, 0x00, 0x20, 0x10, 0x00, 0x18,
0x18, 0x24, 0x24, 0x24, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
0x04, 0x08, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24, 0x7e, 0x42, 0x42, 0x42,
0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24,
0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, 0x32, 0x4c, 0x00, 0x18,
0x18, 0x24, 0x24, 0x24, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
0x24, 0x24, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24, 0x7e, 0x42, 0x42, 0x42,
0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x24, 0x18, 0x18, 0x24, 0x24, 0x24,
0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f,
0x14, 0x14, 0x24, 0x27, 0x3c, 0x44, 0x44, 0x47, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1e, 0x20, 0x40, 0x40, 0x40, 0x40, 0x40, 0x20, 0x1e,
0x08, 0x08, 0x30, 0x00, 0x20, 0x10, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c,
0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0x7e,
0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00,
0x18, 0x24, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x7e,
0x00, 0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c,
0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x3e,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00,
0x04, 0x08, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e,
0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x00, 0x3e,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3c, 0x22, 0x21, 0x21, 0x79, 0x21, 0x21, 0x22, 0x3c,
0x00, 0x00, 0x00, 0x00, 0x32, 0x4c, 0x00, 0x42, 0x62, 0x52, 0x4a, 0x46,
0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x1c,
0x22, 0x41, 0x41, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00,
0x04, 0x08, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x41, 0x41, 0x22, 0x1c,
0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41,
0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x32, 0x4c, 0x00, 0x1c,
0x22, 0x41, 0x41, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00,
0x24, 0x24, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x41, 0x41, 0x22, 0x1c,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x14,
0x08, 0x14, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x3c,
0x42, 0x46, 0x4a, 0x52, 0x62, 0x42, 0x42, 0x3c, 0x40, 0x00, 0x00, 0x00,
0x20, 0x10, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c,
0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x42,
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x24, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c,
0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0x41, 0x41, 0x22, 0x14, 0x08,
0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
0x40, 0x7c, 0x42, 0x42, 0x42, 0x7c, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3c, 0x42, 0x44, 0x4c, 0x42, 0x42, 0x42, 0x44, 0x58,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0x3c, 0x02, 0x02,
0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08,
0x00, 0x3c, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x18, 0x24, 0x00, 0x00, 0x3c, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x3e,
0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x4c, 0x00, 0x00, 0x3c, 0x02, 0x02,
0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x24,
0x00, 0x3c, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00,
0x18, 0x24, 0x24, 0x18, 0x00, 0x3c, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x3e,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x09, 0x39,
0x4f, 0x48, 0x48, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3c, 0x42, 0x40, 0x40, 0x40, 0x42, 0x3c, 0x08, 0x08, 0x30, 0x00,
0x00, 0x00, 0x20, 0x10, 0x00, 0x3c, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x3e,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0x3c, 0x42, 0x42,
0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x00,
0x00, 0x3c, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x24, 0x24, 0x00, 0x3c, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x3e,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x38, 0x08, 0x08,
0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08,
0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x18, 0x24, 0x00, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x38, 0x08, 0x08,
0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x06, 0x1a,
0x01, 0x1d, 0x23, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x32, 0x4c, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x3c, 0x42, 0x42,
0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08,
0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x18, 0x24, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c,
0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x4c, 0x00, 0x00, 0x3c, 0x42, 0x42,
0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x24,
0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x3c, 0x46, 0x4a,
0x52, 0x62, 0x42, 0x3c, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10,
0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x04, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e,
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x00, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x24,
0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x04, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e,
0x02, 0x02, 0x3c, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x5c, 0x62, 0x41,
0x41, 0x41, 0x62, 0x5c, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x24, 0x24,
0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x3c, 0x00,
0xff, 0xff, 0xe2, 0x96, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc2, 0xb0,
0xff, 0xff, 0xff, 0xff, 0xe2, 0x94, 0x98, 0xff, 0xe2, 0x94, 0x90, 0xff,
0xe2, 0x94, 0x8c, 0xff, 0xe2, 0x94, 0x94, 0xff, 0xe2, 0x94, 0xbc, 0xff,
0xff, 0xff, 0xe2, 0x94, 0x80, 0xff, 0xff, 0xff, 0xe2, 0x94, 0x9c, 0xff,
0xe2, 0x94, 0xa4, 0xff, 0xe2, 0x94, 0xb4, 0xff, 0xe2, 0x94, 0xac, 0xff,
0xe2, 0x94, 0x82, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc2, 0xa3, 0xff, 0xff,
0x20, 0xff, 0x21, 0xff, 0x22, 0xff, 0x23, 0xff, 0x24, 0xff, 0x25, 0xff,
0x26, 0xff, 0x27, 0xff, 0x28, 0xff, 0x29, 0xff, 0x2a, 0xff, 0x2b, 0xff,
0x2c, 0xff, 0x2d, 0xff, 0x2e, 0xff, 0x2f, 0xff, 0x30, 0xff, 0x31, 0xff,
0x32, 0xff, 0x33, 0xff, 0x34, 0xff, 0x35, 0xff, 0x36, 0xff, 0x37, 0xff,
0x38, 0xff, 0x39, 0xff, 0x3a, 0xff, 0x3b, 0xff, 0x3c, 0xff, 0x3d, 0xff,
0x3e, 0xff, 0x3f, 0xff, 0x40, 0xff, 0x41, 0xff, 0x42, 0xff, 0x43, 0xff,
0x44, 0xff, 0x45, 0xff, 0x46, 0xff, 0x47, 0xff, 0x48, 0xff, 0x49, 0xff,
0x4a, 0xff, 0x4b, 0xff, 0x4c, 0xff, 0x4d, 0xff, 0x4e, 0xff, 0x4f, 0xff,
0x50, 0xff, 0x51, 0xff, 0x52, 0xff, 0x53, 0xff, 0x54, 0xff, 0x55, 0xff,
0x56, 0xff, 0x57, 0xff, 0x58, 0xff, 0x59, 0xff, 0x5a, 0xff, 0x5b, 0xff,
0x5c, 0xff, 0x5d, 0xff, 0x5e, 0xff, 0x5f, 0xff, 0x60, 0xff, 0x61, 0xff,
0x62, 0xff, 0x63, 0xff, 0x64, 0xff, 0x65, 0xff, 0x66, 0xff, 0x67, 0xff,
0x68, 0xff, 0x69, 0xff, 0x6a, 0xff, 0x6b, 0xff, 0x6c, 0xff, 0x6d, 0xff,
0x6e, 0xff, 0x6f, 0xff, 0x70, 0xff, 0x71, 0xff, 0x72, 0xff, 0x73, 0xff,
0x74, 0xff, 0x75, 0xff, 0x76, 0xff, 0x77, 0xff, 0x78, 0xff, 0x79, 0xff,
0x7a, 0xff, 0x7b, 0xff, 0x7c, 0xff, 0x7d, 0xff, 0x7e, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc2, 0xa0, 0xff, 0xc2, 0xa1,
0xff, 0xc2, 0xa2, 0xff, 0xc2, 0xa3, 0xff, 0xc2, 0xa4, 0xff, 0xc2, 0xa5,
0xff, 0xc2, 0xa6, 0xff, 0xff, 0xc2, 0xa8, 0xff, 0xc2, 0xa9, 0xff, 0xff,
0xc2, 0xab, 0xff, 0xff, 0xc2, 0xad, 0xff, 0xff, 0xff, 0xc2, 0xb0, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc2, 0xb8, 0xff, 0xff, 0xff,
0xc2, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xc2, 0xbf, 0xff, 0xc3, 0x80, 0xff,
0xc3, 0x81, 0xff, 0xc3, 0x82, 0xff, 0xc3, 0x83, 0xff, 0xc3, 0x84, 0xff,
0xc3, 0x85, 0xff, 0xc3, 0x86, 0xff, 0xc3, 0x87, 0xff, 0xc3, 0x88, 0xff,
0xc3, 0x89, 0xff, 0xc3, 0x8a, 0xff, 0xc3, 0x8b, 0xff, 0xc3, 0x8c, 0xff,
0xc3, 0x8d, 0xff, 0xc3, 0x8e, 0xff, 0xc3, 0x8f, 0xff, 0xc3, 0x90, 0xff,
0xc3, 0x91, 0xff, 0xc3, 0x92, 0xff, 0xc3, 0x93, 0xff, 0xc3, 0x94, 0xff,
0xc3, 0x95, 0xff, 0xc3, 0x96, 0xff, 0xc3, 0x97, 0xff, 0xc3, 0x98, 0xff,
0xc3, 0x99, 0xff, 0xc3, 0x9a, 0xff, 0xc3, 0x9b, 0xff, 0xc3, 0x9c, 0xff,
0xc3, 0x9d, 0xff, 0xc3, 0x9e, 0xff, 0xc3, 0x9f, 0xff, 0xc3, 0xa0, 0xff,
0xc3, 0xa1, 0xff, 0xc3, 0xa2, 0xff, 0xc3, 0xa3, 0xff, 0xc3, 0xa4, 0xff,
0xc3, 0xa5, 0xff, 0xc3, 0xa6, 0xff, 0xc3, 0xa7, 0xff, 0xc3, 0xa8, 0xff,
0xc3, 0xa9, 0xff, 0xc3, 0xaa, 0xff, 0xc3, 0xab, 0xff, 0xc3, 0xac, 0xff,
0xc3, 0xad, 0xff, 0xc3, 0xae, 0xff, 0xc3, 0xaf, 0xff, 0xc3, 0xb0, 0xff,
0xc3, 0xb1, 0xff, 0xc3, 0xb2, 0xff, 0xc3, 0xb3, 0xff, 0xc3, 0xb4, 0xff,
0xc3, 0xb5, 0xff, 0xc3, 0xb6, 0xff, 0xc3, 0xb7, 0xff, 0xc3, 0xb8, 0xff,
0xc3, 0xb9, 0xff, 0xc3, 0xba, 0xff, 0xc3, 0xbb, 0xff, 0xc3, 0xbc, 0xff,
0xc3, 0xbd, 0xff, 0xc3, 0xbe, 0xff, 0xc3, 0xbf, 0xff

View File

@@ -1,6 +1,7 @@
#include "kutil/assert.h" #include <assert.h>
#include "font.h" #include "font.h"
/* PSF2 header format /* PSF2 header format
* Taken from the Linux KBD documentation * Taken from the Linux KBD documentation
* http://www.win.tue.nl/~aeb/linux/kbd/font-formats-1.html * http://www.win.tue.nl/~aeb/linux/kbd/font-formats-1.html
@@ -27,43 +28,51 @@ struct psf2_header {
uint32_t height, width; // max dimensions of glyphs uint32_t height, width; // max dimensions of glyphs
}; };
const uint8_t default_font[] = {
// xxd -i < font_file.psf > default_font.inc
#include "default_font.inc"
};
font::font(void const *data) : font::font(void const *data) :
m_size(0, 0), m_sizex {0},
m_count(0), m_sizey {0},
m_data(nullptr) m_count {0},
m_data {nullptr}
{ {
if (!data)
data = default_font;
psf2_header const *psf2 = static_cast<psf2_header const *>(data); psf2_header const *psf2 = static_cast<psf2_header const *>(data);
for (int i = 0; i < sizeof(magic); ++i) { for (int i = 0; i < sizeof(magic); ++i) {
kassert(psf2->magic[i] == magic[i], "Bad font magic number."); assert(psf2->magic[i] == magic[i] && "Bad font magic number.");
} }
m_data = static_cast<uint8_t const *>(data) + psf2->header_size; m_data = static_cast<uint8_t const *>(data) + psf2->header_size;
m_size.x = psf2->width; m_sizex = psf2->width;
m_size.y = psf2->height; m_sizey = psf2->height;
m_count = psf2->length; m_count = psf2->length;
} }
void void
font::draw_glyph( font::draw_glyph(
screen *s, screen &s,
uint32_t glyph, uint32_t glyph,
screen::pixel_t fg, screen::pixel_t fg,
screen::pixel_t bg, screen::pixel_t bg,
unsigned x, unsigned x,
unsigned y) const unsigned y) const
{ {
unsigned bwidth = (m_size.x+7)/8; unsigned bwidth = (m_sizex+7)/8;
uint8_t const *data = m_data + (glyph * glyph_bytes()); uint8_t const *data = m_data + (glyph * glyph_bytes());
for (int dy = 0; dy < m_size.y; ++dy) { for (int dy = 0; dy < m_sizey; ++dy) {
for (int dx = 0; dx < bwidth; ++dx) { for (int dx = 0; dx < bwidth; ++dx) {
uint8_t byte = data[dy * bwidth + dx]; uint8_t byte = data[dy * bwidth + dx];
for (int i = 0; i < 8; ++i) { for (int i = 0; i < 8; ++i) {
if (dx*8 + i >= m_size.x) continue; if (dx*8 + i >= m_sizex) break;
const uint8_t mask = 1 << (7-i); const uint8_t mask = 1 << (7-i);
uint32_t c = (byte & mask) ? fg : bg; uint32_t c = (byte & mask) ? fg : bg;
s->draw_pixel(x + dx*8 + i, y + dy, c); s.draw_pixel(x + dx*8 + i, y + dy, c);
} }
} }
} }

33
src/drivers/fb/font.h Normal file
View File

@@ -0,0 +1,33 @@
#pragma once
#include <stdint.h>
#include "screen.h"
class font
{
public:
/// Constructor.
/// \arg data The font data to load. If null, will load the default
/// built-in font.
font(void const *data = nullptr);
unsigned glyph_bytes() const { return m_sizey * ((m_sizex + 7) / 8); }
unsigned count() const { return m_count; }
unsigned width() const { return m_sizex; }
unsigned height() const { return m_sizey; }
bool valid() const { return m_count > 0; }
void draw_glyph(
screen &s,
uint32_t glyph,
screen::pixel_t fg,
screen::pixel_t bg,
unsigned x,
unsigned y) const;
private:
unsigned m_sizex, m_sizey;
unsigned m_count;
uint8_t const *m_data;
};

105
src/drivers/fb/main.cpp Normal file
View File

@@ -0,0 +1,105 @@
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include "j6/init.h"
#include "j6/errors.h"
#include "j6/signals.h"
#include "j6/types.h"
#include <j6libc/syscalls.h>
#include "font.h"
#include "screen.h"
#include "scrollback.h"
extern "C" {
int main(int, const char **);
void _get_init(size_t *initc, struct j6_init_value **initv);
}
extern j6_handle_t __handle_sys;
struct entry
{
uint8_t bytes;
uint8_t area;
uint8_t severity;
uint8_t sequence;
char message[0];
};
int
main(int argc, const char **argv)
{
_syscall_system_log("fb driver starting");
size_t initc = 0;
j6_init_value *initv = nullptr;
_get_init(&initc, &initv);
j6_init_framebuffer *fb = nullptr;
for (unsigned i = 0; i < initc; ++i) {
if (initv[i].type == j6_init_desc_framebuffer) {
fb = reinterpret_cast<j6_init_framebuffer*>(initv[i].value);
break;
}
}
if (!fb || fb->addr == nullptr) {
_syscall_system_log("fb driver didn't find a framebuffer, exiting");
return 1;
}
const screen::pixel_order order = (fb->flags & 1) ?
screen::pixel_order::bgr8 : screen::pixel_order::rgb8;
screen scr(fb->addr, fb->horizontal, fb->vertical, order);
font fnt;
screen::pixel_t fg = scr.color(0xb0, 0xb0, 0xb0);
screen::pixel_t bg = scr.color(49, 79, 128);
scr.fill(bg);
scr.update();
constexpr int margin = 2;
const unsigned xstride = (margin + fnt.width());
const unsigned ystride = (margin + fnt.height());
const unsigned rows = (scr.height() - margin) / ystride;
const unsigned cols = (scr.width() - margin) / xstride;
scrollback scroll(rows, cols);
int pending = 0;
constexpr int pending_threshold = 10;
char message_buffer[256];
while (true) {
size_t size = sizeof(message_buffer);
_syscall_system_get_log(__handle_sys, message_buffer, &size);
if (size != 0) {
entry *e = reinterpret_cast<entry*>(&message_buffer);
size_t eom = e->bytes - sizeof(entry);
e->message[eom] = 0;
scroll.add_line(e->message, eom);
if (++pending > pending_threshold) {
scroll.render(scr, fnt);
scr.update();
pending = 0;
}
} else {
if (pending) {
scroll.render(scr, fnt);
scr.update();
pending = 0;
}
}
}
_syscall_system_log("fb driver done, exiting");
return 0;
}

50
src/drivers/fb/screen.cpp Normal file
View File

@@ -0,0 +1,50 @@
#include <stdlib.h>
#include <string.h>
#include "screen.h"
screen::screen(void *addr, unsigned hres, unsigned vres, pixel_order order) :
m_fb(static_cast<pixel_t *>(addr)),
m_order(order),
m_resx(hres),
m_resy(vres)
{
m_back = reinterpret_cast<pixel_t*>(malloc(hres*vres*sizeof(pixel_t)));
}
screen::pixel_t
screen::color(uint8_t r, uint8_t g, uint8_t b) const
{
switch (m_order) {
case pixel_order::bgr8:
return
(static_cast<uint32_t>(b) << 0) |
(static_cast<uint32_t>(g) << 8) |
(static_cast<uint32_t>(r) << 16);
case pixel_order::rgb8:
return
(static_cast<uint32_t>(r) << 0) |
(static_cast<uint32_t>(g) << 8) |
(static_cast<uint32_t>(b) << 16);
}
}
void
screen::fill(pixel_t color)
{
const size_t len = m_resx * m_resy;
for (size_t i = 0; i < len; ++i)
m_back[i] = color;
}
void
screen::draw_pixel(unsigned x, unsigned y, pixel_t color)
{
m_back[x + y * m_resx] = color;
}
void
screen::update()
{
memcpy(m_fb, m_back, m_resx*m_resy*sizeof(pixel_t));
}

30
src/drivers/fb/screen.h Normal file
View File

@@ -0,0 +1,30 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
class screen
{
public:
using pixel_t = uint32_t;
enum class pixel_order : uint8_t { bgr8, rgb8, };
screen(void *addr, unsigned hres, unsigned vres, pixel_order order);
unsigned width() const { return m_resx; }
unsigned height() const { return m_resy; }
pixel_t color(uint8_t r, uint8_t g, uint8_t b) const;
void fill(pixel_t color);
void draw_pixel(unsigned x, unsigned y, pixel_t color);
void update();
private:
pixel_t *m_fb, *m_back;
pixel_order m_order;
unsigned m_resx, m_resy;
screen() = delete;
};

View File

@@ -0,0 +1,56 @@
#include <stdlib.h>
#include <string.h>
#include "font.h"
#include "screen.h"
#include "scrollback.h"
scrollback::scrollback(unsigned lines, unsigned cols, unsigned margin) :
m_rows {lines},
m_cols {cols},
m_count {0},
m_margin {margin}
{
m_data = reinterpret_cast<char*>(malloc(lines*cols));
m_lines = reinterpret_cast<char**>(malloc(lines*sizeof(char*)));
for (unsigned i = 0; i < lines; ++i)
m_lines[i] = &m_data[i*cols];
memset(m_data, ' ', lines*cols);
}
void
scrollback::add_line(const char *line, size_t len)
{
unsigned i = m_count++ % m_rows;
if (len > m_cols)
len = m_cols;
memcpy(m_lines[i], line, len);
if (len < m_cols)
memset(m_lines[i]+len, ' ', m_cols - len);
}
char *
scrollback::get_line(unsigned i)
{
return m_lines[(i+m_count)%m_rows];
}
void
scrollback::render(screen &scr, font &fnt)
{
screen::pixel_t fg = scr.color(0xb0, 0xb0, 0xb0);
screen::pixel_t bg = scr.color(49, 79, 128);
const unsigned xstride = (m_margin + fnt.width());
const unsigned ystride = (m_margin + fnt.height());
for (unsigned y = 0; y < m_rows; ++y) {
char *line = get_line(y);
for (unsigned x = 0; x < m_cols; ++x) {
fnt.draw_glyph(scr, line[x], fg, bg, m_margin+x*xstride, m_margin+y*ystride);
}
}
}

View File

@@ -0,0 +1,26 @@
#pragma once
/// \file scrollback.h
class screen;
class font;
class scrollback
{
public:
scrollback(unsigned lines, unsigned cols, unsigned margin = 2);
void add_line(const char *line, size_t len);
char * get_line(unsigned i);
void render(screen &scr, font &fnt);
private:
char *m_data;
char **m_lines;
unsigned m_rows, m_cols;
unsigned m_start;
unsigned m_count;
unsigned m_margin;
};

View File

@@ -0,0 +1,22 @@
#include "io.h"
uint8_t
inb(uint16_t port)
{
uint8_t val;
__asm__ __volatile__ ( "inb %1, %0" : "=a"(val) : "Nd"(port) );
return val;
}
void
outb(uint16_t port, uint8_t val)
{
__asm__ __volatile__ ( "outb %0, %1" :: "a"(val), "Nd"(port) );
}
void
io_wait(unsigned times)
{
for (unsigned i = 0; i < times; ++i)
outb(0x80, 0);
}

24
src/drivers/nulldrv/io.h Normal file
View File

@@ -0,0 +1,24 @@
#pragma once
#include <stdint.h>
extern "C" {
/// Read a byte from an IO port.
/// \arg port The address of the IO port
/// \returns One byte read from the port
uint8_t inb(uint16_t port);
/// Write a byte to an IO port.
/// \arg port The addres of the IO port
/// \arg val The byte to write
void outb(uint16_t port, uint8_t val);
/// Pause briefly by doing IO to port 0x80
/// \arg times Number of times to delay by writing
void io_wait(unsigned times = 1);
}
constexpr uint16_t COM1 = 0x03f8;
constexpr uint16_t COM2 = 0x02f8;

View File

@@ -1,24 +1,140 @@
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
extern "C" { #include "j6/types.h"
int32_t getpid(); #include "j6/errors.h"
int32_t fork(); #include "j6/signals.h"
void sleep(uint64_t til);
void debug();
void message(const char *msg);
#include <j6libc/syscalls.h>
#include "io.h"
#include "serial.h"
char inbuf[1024];
extern j6_handle_t __handle_sys;
j6_handle_t endp = j6_handle_invalid;
extern "C" {
void _init_libc(j6_process_init *);
int main(int, const char **); int main(int, const char **);
} }
void
thread_proc()
{
_syscall_system_log("sub thread starting");
char buffer[512];
size_t len = sizeof(buffer);
j6_tag_t tag = 0;
j6_status_t result = _syscall_endpoint_receive(endp, &tag, &len, (void*)buffer);
if (result != j6_status_ok)
_syscall_thread_exit(result);
_syscall_system_log("sub thread received message");
for (int i = 0; i < len; ++i)
if (buffer[i] >= 'A' && buffer[i] <= 'Z')
buffer[i] += 0x20;
tag++;
result = _syscall_endpoint_send(endp, tag, len, (void*)buffer);
if (result != j6_status_ok)
_syscall_thread_exit(result);
_syscall_system_log("sub thread sent message");
for (int i = 1; i < 5; ++i)
_syscall_thread_sleep(i*10);
_syscall_system_log("sub thread exiting");
_syscall_thread_exit(0);
}
int int
main(int argc, const char **argv) main(int argc, const char **argv)
{ {
int32_t pid = getpid(); j6_handle_t child = j6_handle_invalid;
int32_t child = fork(); j6_signal_t out = 0;
message("hello from nulldrv!");
for (int i = 1; i < 5; ++i) _syscall_system_log("main thread starting");
sleep(i*10);
for (int i = 0; i < argc; ++i)
_syscall_system_log(argv[i]);
void *base = malloc(0x1000);
if (!base)
return 1;
uint64_t *vma_ptr = reinterpret_cast<uint64_t*>(base);
for (int i = 0; i < 3; ++i)
vma_ptr[i*100] = uint64_t(i);
_syscall_system_log("main thread wrote to memory area");
j6_status_t result = _syscall_endpoint_create(&endp);
if (result != j6_status_ok)
return result;
_syscall_system_log("main thread created endpoint");
result = _syscall_thread_create(reinterpret_cast<void*>(&thread_proc), &child);
if (result != j6_status_ok)
return result;
_syscall_system_log("main thread created sub thread");
char message[] = "MAIN THREAD SUCCESSFULLY CALLED SENDRECV IF THIS IS LOWERCASE";
size_t size = sizeof(message);
j6_tag_t tag = 16;
result = _syscall_endpoint_sendrecv(endp, &tag, &size, (void*)message);
if (result != j6_status_ok)
return result;
if (tag != 17)
_syscall_system_log("GOT WRONG TAG FROM SENDRECV");
result = _syscall_system_bind_irq(__handle_sys, endp, 3);
if (result != j6_status_ok)
return result;
_syscall_system_log(message);
_syscall_system_log("main thread waiting on child");
result = _syscall_object_wait(child, -1ull, &out);
if (result != j6_status_ok)
return result;
_syscall_system_log("main testing irqs");
serial_port com2(COM2);
const char *fgseq = "\x1b[2J";
while (*fgseq)
com2.write(*fgseq++);
for (int i = 0; i < 10; ++i)
com2.write('%');
size_t len = 0;
while (true) {
result = _syscall_endpoint_receive(endp, &tag, &len, nullptr);
if (result != j6_status_ok)
return result;
if (j6_tag_is_irq(tag))
_syscall_system_log("main thread got irq!");
}
_syscall_system_log("main thread closing endpoint");
result = _syscall_object_close(endp);
if (result != j6_status_ok)
return result;
_syscall_system_log("main thread done, exiting");
return 0; return 0;
} }

View File

@@ -1,79 +0,0 @@
section .bss
mymessage:
resq 1024
extern main
extern exit
section .text
global getpid
getpid:
push rbp
mov rbp, rsp
mov rax, 0x02 ; getpid syscall
syscall ; pid is now already in rax, so just return
pop rbp
ret
global debug
debug:
push rbp
mov rbp, rsp
mov rax, 0x00 ; debug syscall
syscall
pop rbp
ret
global sleep
sleep:
push rbp
mov rbp, rsp
mov rax, 0x21 ; sleep syscall
syscall
pop rbp
ret
global fork
fork:
push rbp
mov rbp, rsp
mov rax, 0x03
syscall ; pid left in rax
pop rbp
ret
global message
message:
push rbp
mov rbp, rsp
; message should already be in rdi
mov rax, 0x10
syscall
pop rbp
ret
global _start
_start:
xor rbp, rbp ; Sentinel rbp
push rbp
push rbp
mov rbp, rsp
mov rdi, 0
mov rsi, 0
call main
mov rdi, rax
call exit

View File

@@ -0,0 +1,41 @@
#include "io.h"
#include "serial.h"
serial_port::serial_port() :
m_port(0)
{
}
serial_port::serial_port(uint16_t port) :
m_port(port)
{
outb(port + 1, 0x00); // Disable all interrupts
outb(port + 3, 0x80); // Enable the Divisor Latch Access Bit
outb(port + 0, 0x01); // Divisor low bit: 1 (115200 baud)
outb(port + 1, 0x00); // Divisor high bit
outb(port + 3, 0x03); // 8-N-1
outb(port + 2, 0xe7); // Clear and enable FIFO, enable 64 byte, 56 byte trigger
outb(port + 4, 0x0b); // Data terminal ready, Request to send, aux output 2 (irq enable)
outb(port + 1, 0x03); // Enable interrupts
}
bool serial_port::read_ready() { return (inb(m_port + 5) & 0x01) != 0; }
bool serial_port::write_ready() {
uint8_t lsr = inb(m_port + 5);
return (lsr & 0x20) != 0;
}
char
serial_port::read() {
while (!read_ready());
return inb(m_port);
}
void
serial_port::write(char c) {
while (!write_ready());
outb(m_port, c);
}

View File

@@ -0,0 +1,26 @@
#pragma once
/// \file serial.h
/// Declarations related to serial ports.
#include <stdint.h>
#define serial_port nulldrv_serial_port
class serial_port
{
public:
/// Constructor.
/// \arg port The IO address of the serial port
serial_port(uint16_t port);
serial_port();
void write(char c);
char read();
private:
uint16_t m_port;
bool read_ready();
bool write_ready();
};

View File

@@ -1,62 +0,0 @@
/*++
Copyright (c) 1998 Intel Corporation
Module Name:
efi.h
Abstract:
Public EFI header files
Revision History
--*/
// Add a predefined macro to detect usage of the library
#ifndef _GNU_EFI
#define _GNU_EFI
#endif
//
// Build flags on input
// EFI32
// EFI_DEBUG - Enable debugging code
// EFI_NT_EMULATOR - Building for running under NT
//
#ifndef _EFI_INCLUDE_
#define _EFI_INCLUDE_
#define EFI_FIRMWARE_VENDOR L"INTEL"
#define EFI_FIRMWARE_MAJOR_REVISION 12
#define EFI_FIRMWARE_MINOR_REVISION 33
#define EFI_FIRMWARE_REVISION ((EFI_FIRMWARE_MAJOR_REVISION <<16) | (EFI_FIRMWARE_MINOR_REVISION))
#include <efi/efibind.h>
#include <efi/eficompiler.h>
#include <efi/efidef.h>
#include <efi/efidevp.h>
#include <efi/efipciio.h>
#include <efi/efiprot.h>
#include <efi/eficon.h>
#include <efi/efiser.h>
#include <efi/efi_nii.h>
#include <efi/efipxebc.h>
#include <efi/efinet.h>
#include <efi/efiapi.h>
#include <efi/efifs.h>
#include <efi/efierr.h>
#include <efi/efiui.h>
#include <efi/efiip.h>
#include <efi/efiudp.h>
#include <efi/efitcp.h>
#include <efi/efipoint.h>
#include <efi/efisetjmp.h>
#endif

View File

@@ -1,78 +0,0 @@
#ifndef _EFI_NII_H
#define _EFI_NII_H
/*++
Copyright (c) 2000 Intel Corporation
Module name:
efi_nii.h
Abstract:
Revision history:
2000-Feb-18 M(f)J GUID updated.
Structure order changed for machine word alignment.
Added StringId[4] to structure.
2000-Feb-14 M(f)J Genesis.
--*/
#define EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID \
{ 0xE18541CD, 0xF755, 0x4f73, {0x92, 0x8D, 0x64, 0x3C, 0x8A, 0x79, 0xB2, 0x29} }
#define EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION 0x00010000
#define EFI_NETWORK_INTERFACE_IDENTIFIER_INTERFACE_REVISION EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION
typedef enum {
EfiNetworkInterfaceUndi = 1
} EFI_NETWORK_INTERFACE_TYPE;
typedef struct _EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL {
UINT64 Revision;
// Revision of the network interface identifier protocol interface.
UINT64 ID;
// Address of the first byte of the identifying structure for this
// network interface. This is set to zero if there is no structure.
//
// For PXE/UNDI this is the first byte of the !PXE structure.
UINT64 ImageAddr;
// Address of the UNrelocated driver/ROM image. This is set
// to zero if there is no driver/ROM image.
//
// For 16-bit UNDI, this is the first byte of the option ROM in
// upper memory.
//
// For 32/64-bit S/W UNDI, this is the first byte of the EFI ROM
// image.
//
// For H/W UNDI, this is set to zero.
UINT32 ImageSize;
// Size of the UNrelocated driver/ROM image of this network interface.
// This is set to zero if there is no driver/ROM image.
CHAR8 StringId[4];
// 4 char ASCII string to go in class identifier (option 60) in DHCP
// and Boot Server discover packets.
// For EfiNetworkInterfaceUndi this field is "UNDI".
// For EfiNetworkInterfaceSnp this field is "SNPN".
UINT8 Type;
UINT8 MajorVer;
UINT8 MinorVer;
// Information to be placed into the PXE DHCP and Discover packets.
// This is the network interface type and version number that will
// be placed into DHCP option 94 (client network interface identifier).
BOOLEAN Ipv6Supported;
UINT8 IfNum; // interface number to be used with pxeid structure
} EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL, EFI_NETWORK_INTERFACE_IDENTIFIER_INTERFACE;
// Note: Because it conflicted with the EDK2 struct name, the
// 'EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL' GUID definition,
// from older versions of gnu-efi, is now obsoleted.
// Use 'EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID' instead.
#endif // _EFI_NII_H

File diff suppressed because it is too large Load Diff

View File

@@ -1,967 +0,0 @@
#ifndef _EFI_API_H
#define _EFI_API_H
/*++
Copyright (c) 1998 Intel Corporation
Module Name:
efiapi.h
Abstract:
Global EFI runtime & boot service interfaces
Revision History
--*/
//
// EFI Specification Revision
//
#define EFI_SPECIFICATION_MAJOR_REVISION 1
#define EFI_SPECIFICATION_MINOR_REVISION 02
//
// Declare forward referenced data structures
//
INTERFACE_DECL(_EFI_SYSTEM_TABLE);
//
// EFI Memory
//
typedef
EFI_STATUS
(EFIAPI *EFI_ALLOCATE_PAGES) (
IN EFI_ALLOCATE_TYPE Type,
IN EFI_MEMORY_TYPE MemoryType,
IN UINTN NoPages,
OUT EFI_PHYSICAL_ADDRESS *Memory
);
typedef
EFI_STATUS
(EFIAPI *EFI_FREE_PAGES) (
IN EFI_PHYSICAL_ADDRESS Memory,
IN UINTN NoPages
);
typedef
EFI_STATUS
(EFIAPI *EFI_GET_MEMORY_MAP) (
IN OUT UINTN *MemoryMapSize,
IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
OUT UINTN *MapKey,
OUT UINTN *DescriptorSize,
OUT UINT32 *DescriptorVersion
);
#define NextMemoryDescriptor(Ptr,Size) ((EFI_MEMORY_DESCRIPTOR *) (((UINT8 *) Ptr) + Size))
typedef
EFI_STATUS
(EFIAPI *EFI_ALLOCATE_POOL) (
IN EFI_MEMORY_TYPE PoolType,
IN UINTN Size,
OUT VOID **Buffer
);
typedef
EFI_STATUS
(EFIAPI *EFI_FREE_POOL) (
IN VOID *Buffer
);
typedef
EFI_STATUS
(EFIAPI *EFI_SET_VIRTUAL_ADDRESS_MAP) (
IN UINTN MemoryMapSize,
IN UINTN DescriptorSize,
IN UINT32 DescriptorVersion,
IN EFI_MEMORY_DESCRIPTOR *VirtualMap
);
#define EFI_OPTIONAL_PTR 0x00000001
#define EFI_INTERNAL_FNC 0x00000002 // Pointer to internal runtime fnc
#define EFI_INTERNAL_PTR 0x00000004 // Pointer to internal runtime data
typedef
EFI_STATUS
(EFIAPI *EFI_CONVERT_POINTER) (
IN UINTN DebugDisposition,
IN OUT VOID **Address
);
//
// EFI Events
//
#define EVT_TIMER 0x80000000
#define EVT_RUNTIME 0x40000000
#define EVT_RUNTIME_CONTEXT 0x20000000
#define EVT_NOTIFY_WAIT 0x00000100
#define EVT_NOTIFY_SIGNAL 0x00000200
#define EVT_SIGNAL_EXIT_BOOT_SERVICES 0x00000201
#define EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE 0x60000202
#define EVT_EFI_SIGNAL_MASK 0x000000FF
#define EVT_EFI_SIGNAL_MAX 4
#define EFI_EVENT_TIMER EVT_TIMER
#define EFI_EVENT_RUNTIME EVT_RUNTIME
#define EFI_EVENT_RUNTIME_CONTEXT EVT_RUNTIME_CONTEXT
#define EFI_EVENT_NOTIFY_WAIT EVT_NOTIFY_WAIT
#define EFI_EVENT_NOTIFY_SIGNAL EVT_NOTIFY_SIGNAL
#define EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES EVT_SIGNAL_EXIT_BOOT_SERVICES
#define EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE
#define EFI_EVENT_EFI_SIGNAL_MASK EVT_EFI_SIGNAL_MASK
#define EFI_EVENT_EFI_SIGNAL_MAX EVT_EFI_SIGNAL_MAX
typedef
VOID
(EFIAPI *EFI_EVENT_NOTIFY) (
IN EFI_EVENT Event,
IN VOID *Context
);
typedef
EFI_STATUS
(EFIAPI *EFI_CREATE_EVENT) (
IN UINT32 Type,
IN EFI_TPL NotifyTpl,
IN EFI_EVENT_NOTIFY NotifyFunction,
IN VOID *NotifyContext,
OUT EFI_EVENT *Event
);
typedef enum {
TimerCancel,
TimerPeriodic,
TimerRelative,
TimerTypeMax
} EFI_TIMER_DELAY;
typedef
EFI_STATUS
(EFIAPI *EFI_SET_TIMER) (
IN EFI_EVENT Event,
IN EFI_TIMER_DELAY Type,
IN UINT64 TriggerTime
);
typedef
EFI_STATUS
(EFIAPI *EFI_SIGNAL_EVENT) (
IN EFI_EVENT Event
);
typedef
EFI_STATUS
(EFIAPI *EFI_WAIT_FOR_EVENT) (
IN UINTN NumberOfEvents,
IN EFI_EVENT *Event,
OUT UINTN *Index
);
typedef
EFI_STATUS
(EFIAPI *EFI_CLOSE_EVENT) (
IN EFI_EVENT Event
);
typedef
EFI_STATUS
(EFIAPI *EFI_CHECK_EVENT) (
IN EFI_EVENT Event
);
//
// Task priority level
//
#define TPL_APPLICATION 4
#define TPL_CALLBACK 8
#define TPL_NOTIFY 16
#define TPL_HIGH_LEVEL 31
#define EFI_TPL_APPLICATION TPL_APPLICATION
#define EFI_TPL_CALLBACK TPL_CALLBACK
#define EFI_TPL_NOTIFY TPL_NOTIFY
#define EFI_TPL_HIGH_LEVEL TPL_HIGH_LEVEL
typedef
EFI_TPL
(EFIAPI *EFI_RAISE_TPL) (
IN EFI_TPL NewTpl
);
typedef
VOID
(EFIAPI *EFI_RESTORE_TPL) (
IN EFI_TPL OldTpl
);
//
// EFI platform varibles
//
#define EFI_GLOBAL_VARIABLE \
{ 0x8BE4DF61, 0x93CA, 0x11d2, {0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C} }
// Variable attributes
#define EFI_VARIABLE_NON_VOLATILE 0x00000001
#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002
#define EFI_VARIABLE_RUNTIME_ACCESS 0x00000004
#define EFI_VARIABLE_HARDWARE_ERROR_RECORD 0x00000008
#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x00000010
#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS 0x00000020
#define EFI_VARIABLE_APPEND_WRITE 0x00000040
// Variable size limitation
#define EFI_MAXIMUM_VARIABLE_SIZE 1024
typedef
EFI_STATUS
(EFIAPI *EFI_GET_VARIABLE) (
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
OUT UINT32 *Attributes OPTIONAL,
IN OUT UINTN *DataSize,
OUT VOID *Data
);
typedef
EFI_STATUS
(EFIAPI *EFI_GET_NEXT_VARIABLE_NAME) (
IN OUT UINTN *VariableNameSize,
IN OUT CHAR16 *VariableName,
IN OUT EFI_GUID *VendorGuid
);
typedef
EFI_STATUS
(EFIAPI *EFI_SET_VARIABLE) (
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
IN UINT32 Attributes,
IN UINTN DataSize,
IN VOID *Data
);
//
// EFI Time
//
typedef struct {
UINT32 Resolution; // 1e-6 parts per million
UINT32 Accuracy; // hertz
BOOLEAN SetsToZero; // Set clears sub-second time
} EFI_TIME_CAPABILITIES;
typedef
EFI_STATUS
(EFIAPI *EFI_GET_TIME) (
OUT EFI_TIME *Time,
OUT EFI_TIME_CAPABILITIES *Capabilities OPTIONAL
);
typedef
EFI_STATUS
(EFIAPI *EFI_SET_TIME) (
IN EFI_TIME *Time
);
typedef
EFI_STATUS
(EFIAPI *EFI_GET_WAKEUP_TIME) (
OUT BOOLEAN *Enabled,
OUT BOOLEAN *Pending,
OUT EFI_TIME *Time
);
typedef
EFI_STATUS
(EFIAPI *EFI_SET_WAKEUP_TIME) (
IN BOOLEAN Enable,
IN EFI_TIME *Time OPTIONAL
);
//
// Image functions
//
// PE32+ Subsystem type for EFI images
#if !defined(IMAGE_SUBSYSTEM_EFI_APPLICATION)
#define IMAGE_SUBSYSTEM_EFI_APPLICATION 10
#define IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11
#define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12
#endif
// PE32+ Machine type for EFI images
#if !defined(EFI_IMAGE_MACHINE_IA32)
#define EFI_IMAGE_MACHINE_IA32 0x014c
#endif
#if !defined(EFI_IMAGE_MACHINE_IA64)
#define EFI_IMAGE_MACHINE_IA64 0x0200
#endif
#if !defined(EFI_IMAGE_MACHINE_EBC)
#define EFI_IMAGE_MACHINE_EBC 0x0EBC
#endif
#if !defined(EFI_IMAGE_MACHINE_X64)
#define EFI_IMAGE_MACHINE_X64 0x8664
#endif
#if !defined(EFI_IMAGE_MACHINE_ARMTHUMB_MIXED)
#define EFI_IMAGE_MACHINE_ARMTHUMB_MIXED 0x01C2
#endif
#if !defined(EFI_IMAGE_MACHINE_AARCH64)
#define EFI_IMAGE_MACHINE_AARCH64 0xAA64
#endif
// Image Entry prototype
typedef
EFI_STATUS
(EFIAPI *EFI_IMAGE_ENTRY_POINT) (
IN EFI_HANDLE ImageHandle,
IN struct _EFI_SYSTEM_TABLE *SystemTable
);
typedef
EFI_STATUS
(EFIAPI *EFI_IMAGE_LOAD) (
IN BOOLEAN BootPolicy,
IN EFI_HANDLE ParentImageHandle,
IN EFI_DEVICE_PATH *FilePath,
IN VOID *SourceBuffer OPTIONAL,
IN UINTN SourceSize,
OUT EFI_HANDLE *ImageHandle
);
typedef
EFI_STATUS
(EFIAPI *EFI_IMAGE_START) (
IN EFI_HANDLE ImageHandle,
OUT UINTN *ExitDataSize,
OUT CHAR16 **ExitData OPTIONAL
);
typedef
EFI_STATUS
(EFIAPI *EFI_EXIT) (
IN EFI_HANDLE ImageHandle,
IN EFI_STATUS ExitStatus,
IN UINTN ExitDataSize,
IN CHAR16 *ExitData OPTIONAL
);
// Image handle
/*#define LOADED_IMAGE_PROTOCOL \
{ 0x5B1B31A1, 0x9562, 0x11d2, {0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B} }
#define EFI_IMAGE_INFORMATION_REVISION 0x1000
typedef struct {
UINT32 Revision;
EFI_HANDLE ParentHandle;
struct _EFI_SYSTEM_TABLE *SystemTable;
// Source location of image
EFI_HANDLE DeviceHandle;
EFI_DEVICE_PATH *FilePath;
VOID *Reserved;
// Images load options
UINT32 LoadOptionsSize;
VOID *LoadOptions;
// Location of where image was loaded
VOID *ImageBase;
UINT64 ImageSize;
EFI_MEMORY_TYPE ImageCodeType;
EFI_MEMORY_TYPE ImageDataType;
// If the driver image supports a dynamic unload request
EFI_IMAGE_UNLOAD Unload;
} EFI_LOADED_IMAGE;*/
typedef
EFI_STATUS
(EFIAPI *EFI_EXIT_BOOT_SERVICES) (
IN EFI_HANDLE ImageHandle,
IN UINTN MapKey
);
//
// Misc
//
typedef
EFI_STATUS
(EFIAPI *EFI_STALL) (
IN UINTN Microseconds
);
typedef
EFI_STATUS
(EFIAPI *EFI_SET_WATCHDOG_TIMER) (
IN UINTN Timeout,
IN UINT64 WatchdogCode,
IN UINTN DataSize,
IN CHAR16 *WatchdogData OPTIONAL
);
typedef
EFI_STATUS
(EFIAPI *EFI_CONNECT_CONTROLLER) (
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE *DriverImageHandle OPTIONAL,
IN EFI_DEVICE_PATH *RemainingDevicePath OPTIONAL,
IN BOOLEAN Recursive
);
typedef
EFI_STATUS
(EFIAPI *EFI_DISCONNECT_CONTROLLER) (
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE DriverImageHandle OPTIONAL,
IN EFI_HANDLE ChildHandle OPTIONAL
);
#define EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL 0x00000001
#define EFI_OPEN_PROTOCOL_GET_PROTOCOL 0x00000002
#define EFI_OPEN_PROTOCOL_TEST_PROTOCOL 0x00000004
#define EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 0x00000008
#define EFI_OPEN_PROTOCOL_BY_DRIVER 0x00000010
#define EFI_OPEN_PROTOCOL_EXCLUSIVE 0x00000020
typedef
EFI_STATUS
(EFIAPI *EFI_OPEN_PROTOCOL) (
IN EFI_HANDLE Handle,
IN EFI_GUID *Protocol,
OUT VOID **Interface OPTIONAL,
IN EFI_HANDLE AgentHandle,
IN EFI_HANDLE ControllerHandle,
IN UINT32 Attributes
);
typedef
EFI_STATUS
(EFIAPI *EFI_CLOSE_PROTOCOL) (
IN EFI_HANDLE Handle,
IN EFI_GUID *Protocol,
IN EFI_HANDLE AgentHandle,
IN EFI_HANDLE ControllerHandle
);
typedef struct {
EFI_HANDLE AgentHandle;
EFI_HANDLE ControllerHandle;
UINT32 Attributes;
UINT32 OpenCount;
} EFI_OPEN_PROTOCOL_INFORMATION_ENTRY;
typedef
EFI_STATUS
(EFIAPI *EFI_OPEN_PROTOCOL_INFORMATION) (
IN EFI_HANDLE Handle,
IN EFI_GUID *Protocol,
OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer,
OUT UINTN *EntryCount
);
typedef
EFI_STATUS
(EFIAPI *EFI_PROTOCOLS_PER_HANDLE) (
IN EFI_HANDLE Handle,
OUT EFI_GUID ***ProtocolBuffer,
OUT UINTN *ProtocolBufferCount
);
typedef enum {
AllHandles,
ByRegisterNotify,
ByProtocol
} EFI_LOCATE_SEARCH_TYPE;
typedef
EFI_STATUS
(EFIAPI *EFI_LOCATE_HANDLE_BUFFER) (
IN EFI_LOCATE_SEARCH_TYPE SearchType,
IN EFI_GUID *Protocol OPTIONAL,
IN VOID *SearchKey OPTIONAL,
IN OUT UINTN *NoHandles,
OUT EFI_HANDLE **Buffer
);
typedef
EFI_STATUS
(EFIAPI *EFI_LOCATE_PROTOCOL) (
IN EFI_GUID *Protocol,
IN VOID *Registration OPTIONAL,
OUT VOID **Interface
);
typedef
EFI_STATUS
(EFIAPI *EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES) (
IN OUT EFI_HANDLE *Handle,
...
);
typedef
EFI_STATUS
(EFIAPI *EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES) (
IN OUT EFI_HANDLE Handle,
...
);
typedef
EFI_STATUS
(EFIAPI *EFI_CALCULATE_CRC32) (
IN VOID *Data,
IN UINTN DataSize,
OUT UINT32 *Crc32
);
typedef
VOID
(EFIAPI *EFI_COPY_MEM) (
IN VOID *Destination,
IN VOID *Source,
IN UINTN Length
);
typedef
VOID
(EFIAPI *EFI_SET_MEM) (
IN VOID *Buffer,
IN UINTN Size,
IN UINT8 Value
);
typedef
EFI_STATUS
(EFIAPI *EFI_CREATE_EVENT_EX) (
IN UINT32 Type,
IN EFI_TPL NotifyTpl,
IN EFI_EVENT_NOTIFY NotifyFunction OPTIONAL,
IN const VOID *NotifyContext OPTIONAL,
IN const EFI_GUID EventGroup OPTIONAL,
OUT EFI_EVENT *Event
);
typedef enum {
EfiResetCold,
EfiResetWarm,
EfiResetShutdown
} EFI_RESET_TYPE;
typedef
EFI_STATUS
(EFIAPI *EFI_RESET_SYSTEM) (
IN EFI_RESET_TYPE ResetType,
IN EFI_STATUS ResetStatus,
IN UINTN DataSize,
IN CHAR16 *ResetData OPTIONAL
);
typedef
EFI_STATUS
(EFIAPI *EFI_GET_NEXT_MONOTONIC_COUNT) (
OUT UINT64 *Count
);
typedef
EFI_STATUS
(EFIAPI *EFI_GET_NEXT_HIGH_MONO_COUNT) (
OUT UINT32 *HighCount
);
typedef struct {
UINT64 Length;
union {
EFI_PHYSICAL_ADDRESS DataBlock;
EFI_PHYSICAL_ADDRESS ContinuationPointer;
} Union;
} EFI_CAPSULE_BLOCK_DESCRIPTOR;
typedef struct {
EFI_GUID CapsuleGuid;
UINT32 HeaderSize;
UINT32 Flags;
UINT32 CapsuleImageSize;
} EFI_CAPSULE_HEADER;
#define CAPSULE_FLAGS_PERSIST_ACROSS_RESET 0x00010000
#define CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE 0x00020000
#define CAPSULE_FLAGS_INITIATE_RESET 0x00040000
typedef
EFI_STATUS
(EFIAPI *EFI_UPDATE_CAPSULE) (
IN EFI_CAPSULE_HEADER **CapsuleHeaderArray,
IN UINTN CapsuleCount,
IN EFI_PHYSICAL_ADDRESS ScatterGatherList OPTIONAL
);
typedef
EFI_STATUS
(EFIAPI *EFI_QUERY_CAPSULE_CAPABILITIES) (
IN EFI_CAPSULE_HEADER **CapsuleHeaderArray,
IN UINTN CapsuleCount,
OUT UINT64 *MaximumCapsuleSize,
OUT EFI_RESET_TYPE *ResetType
);
typedef
EFI_STATUS
(EFIAPI *EFI_QUERY_VARIABLE_INFO) (
IN UINT32 Attributes,
OUT UINT64 *MaximumVariableStorageSize,
OUT UINT64 *RemainingVariableStorageSize,
OUT UINT64 *MaximumVariableSize
);
//
// Protocol handler functions
//
typedef enum {
EFI_NATIVE_INTERFACE,
EFI_PCODE_INTERFACE
} EFI_INTERFACE_TYPE;
typedef
EFI_STATUS
(EFIAPI *EFI_INSTALL_PROTOCOL_INTERFACE) (
IN OUT EFI_HANDLE *Handle,
IN EFI_GUID *Protocol,
IN EFI_INTERFACE_TYPE InterfaceType,
IN VOID *Interface
);
typedef
EFI_STATUS
(EFIAPI *EFI_REINSTALL_PROTOCOL_INTERFACE) (
IN EFI_HANDLE Handle,
IN EFI_GUID *Protocol,
IN VOID *OldInterface,
IN VOID *NewInterface
);
typedef
EFI_STATUS
(EFIAPI *EFI_UNINSTALL_PROTOCOL_INTERFACE) (
IN EFI_HANDLE Handle,
IN EFI_GUID *Protocol,
IN VOID *Interface
);
typedef
EFI_STATUS
(EFIAPI *EFI_HANDLE_PROTOCOL) (
IN EFI_HANDLE Handle,
IN EFI_GUID *Protocol,
OUT VOID **Interface
);
typedef
EFI_STATUS
(EFIAPI *EFI_REGISTER_PROTOCOL_NOTIFY) (
IN EFI_GUID *Protocol,
IN EFI_EVENT Event,
OUT VOID **Registration
);
typedef
EFI_STATUS
(EFIAPI *EFI_LOCATE_HANDLE) (
IN EFI_LOCATE_SEARCH_TYPE SearchType,
IN EFI_GUID *Protocol OPTIONAL,
IN VOID *SearchKey OPTIONAL,
IN OUT UINTN *BufferSize,
OUT EFI_HANDLE *Buffer
);
typedef
EFI_STATUS
(EFIAPI *EFI_LOCATE_DEVICE_PATH) (
IN EFI_GUID *Protocol,
IN OUT EFI_DEVICE_PATH **DevicePath,
OUT EFI_HANDLE *Device
);
typedef
EFI_STATUS
(EFIAPI *EFI_INSTALL_CONFIGURATION_TABLE) (
IN EFI_GUID *Guid,
IN VOID *Table
);
typedef
EFI_STATUS
(EFIAPI *EFI_RESERVED_SERVICE) (
);
//
// Standard EFI table header
//
typedef struct _EFI_TABLE_HEADER {
UINT64 Signature;
UINT32 Revision;
UINT32 HeaderSize;
UINT32 CRC32;
UINT32 Reserved;
} EFI_TABLE_HEADER;
//
// EFI Runtime Serivces Table
//
#define EFI_RUNTIME_SERVICES_SIGNATURE 0x56524553544e5552
#define EFI_RUNTIME_SERVICES_REVISION (EFI_SPECIFICATION_MAJOR_REVISION<<16) | (EFI_SPECIFICATION_MINOR_REVISION)
typedef struct {
EFI_TABLE_HEADER Hdr;
//
// Time services
//
EFI_GET_TIME GetTime;
EFI_SET_TIME SetTime;
EFI_GET_WAKEUP_TIME GetWakeupTime;
EFI_SET_WAKEUP_TIME SetWakeupTime;
//
// Virtual memory services
//
EFI_SET_VIRTUAL_ADDRESS_MAP SetVirtualAddressMap;
EFI_CONVERT_POINTER ConvertPointer;
//
// Variable serviers
//
EFI_GET_VARIABLE GetVariable;
EFI_GET_NEXT_VARIABLE_NAME GetNextVariableName;
EFI_SET_VARIABLE SetVariable;
//
// Misc
//
EFI_GET_NEXT_HIGH_MONO_COUNT GetNextHighMonotonicCount;
EFI_RESET_SYSTEM ResetSystem;
EFI_UPDATE_CAPSULE UpdateCapsule;
EFI_QUERY_CAPSULE_CAPABILITIES QueryCapsuleCapabilities;
EFI_QUERY_VARIABLE_INFO QueryVariableInfo;
} EFI_RUNTIME_SERVICES;
//
// EFI Boot Services Table
//
#define EFI_BOOT_SERVICES_SIGNATURE 0x56524553544f4f42
#define EFI_BOOT_SERVICES_REVISION (EFI_SPECIFICATION_MAJOR_REVISION<<16) | (EFI_SPECIFICATION_MINOR_REVISION)
typedef struct _EFI_BOOT_SERVICES {
EFI_TABLE_HEADER Hdr;
//
// Task priority functions
//
EFI_RAISE_TPL RaiseTPL;
EFI_RESTORE_TPL RestoreTPL;
//
// Memory functions
//
EFI_ALLOCATE_PAGES AllocatePages;
EFI_FREE_PAGES FreePages;
EFI_GET_MEMORY_MAP GetMemoryMap;
EFI_ALLOCATE_POOL AllocatePool;
EFI_FREE_POOL FreePool;
//
// Event & timer functions
//
EFI_CREATE_EVENT CreateEvent;
EFI_SET_TIMER SetTimer;
EFI_WAIT_FOR_EVENT WaitForEvent;
EFI_SIGNAL_EVENT SignalEvent;
EFI_CLOSE_EVENT CloseEvent;
EFI_CHECK_EVENT CheckEvent;
//
// Protocol handler functions
//
EFI_INSTALL_PROTOCOL_INTERFACE InstallProtocolInterface;
EFI_REINSTALL_PROTOCOL_INTERFACE ReinstallProtocolInterface;
EFI_UNINSTALL_PROTOCOL_INTERFACE UninstallProtocolInterface;
EFI_HANDLE_PROTOCOL HandleProtocol;
EFI_HANDLE_PROTOCOL PCHandleProtocol;
EFI_REGISTER_PROTOCOL_NOTIFY RegisterProtocolNotify;
EFI_LOCATE_HANDLE LocateHandle;
EFI_LOCATE_DEVICE_PATH LocateDevicePath;
EFI_INSTALL_CONFIGURATION_TABLE InstallConfigurationTable;
//
// Image functions
//
EFI_IMAGE_LOAD LoadImage;
EFI_IMAGE_START StartImage;
EFI_EXIT Exit;
EFI_IMAGE_UNLOAD UnloadImage;
EFI_EXIT_BOOT_SERVICES ExitBootServices;
//
// Misc functions
//
EFI_GET_NEXT_MONOTONIC_COUNT GetNextMonotonicCount;
EFI_STALL Stall;
EFI_SET_WATCHDOG_TIMER SetWatchdogTimer;
//
// DriverSupport Services
//
EFI_CONNECT_CONTROLLER ConnectController;
EFI_DISCONNECT_CONTROLLER DisconnectController;
//
// Open and Close Protocol Services
//
EFI_OPEN_PROTOCOL OpenProtocol;
EFI_CLOSE_PROTOCOL CloseProtocol;
EFI_OPEN_PROTOCOL_INFORMATION OpenProtocolInformation;
//
// Library Services
//
EFI_PROTOCOLS_PER_HANDLE ProtocolsPerHandle;
EFI_LOCATE_HANDLE_BUFFER LocateHandleBuffer;
EFI_LOCATE_PROTOCOL LocateProtocol;
EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES InstallMultipleProtocolInterfaces;
EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES UninstallMultipleProtocolInterfaces;
//
// 32-bit CRC Services
//
EFI_CALCULATE_CRC32 CalculateCrc32;
//
// Misc Services
//
EFI_COPY_MEM CopyMem;
EFI_SET_MEM SetMem;
EFI_CREATE_EVENT_EX CreateEventEx;
} EFI_BOOT_SERVICES;
//
// EFI Configuration Table and GUID definitions
//
#define MPS_TABLE_GUID \
{ 0xeb9d2d2f, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d} }
#define ACPI_TABLE_GUID \
{ 0xeb9d2d30, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d} }
#define ACPI_20_TABLE_GUID \
{ 0x8868e871, 0xe4f1, 0x11d3, {0xbc, 0x22, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81} }
#define SMBIOS_TABLE_GUID \
{ 0xeb9d2d31, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d} }
#define SMBIOS3_TABLE_GUID \
{ 0xf2fd1544, 0x9794, 0x4a2c, {0x99, 0x2e, 0xe5, 0xbb, 0xcf, 0x20, 0xe3, 0x94} }
#define SAL_SYSTEM_TABLE_GUID \
{ 0xeb9d2d32, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d} }
typedef struct _EFI_CONFIGURATION_TABLE {
EFI_GUID VendorGuid;
VOID *VendorTable;
} EFI_CONFIGURATION_TABLE;
//
// EFI System Table
//
#define EFI_SYSTEM_TABLE_SIGNATURE 0x5453595320494249
#define EFI_SYSTEM_TABLE_REVISION (EFI_SPECIFICATION_MAJOR_REVISION<<16) | (EFI_SPECIFICATION_MINOR_REVISION)
typedef struct _EFI_SYSTEM_TABLE {
EFI_TABLE_HEADER Hdr;
CHAR16 *FirmwareVendor;
UINT32 FirmwareRevision;
EFI_HANDLE ConsoleInHandle;
SIMPLE_INPUT_INTERFACE *ConIn;
EFI_HANDLE ConsoleOutHandle;
SIMPLE_TEXT_OUTPUT_INTERFACE *ConOut;
EFI_HANDLE StandardErrorHandle;
SIMPLE_TEXT_OUTPUT_INTERFACE *StdErr;
EFI_RUNTIME_SERVICES *RuntimeServices;
EFI_BOOT_SERVICES *BootServices;
UINTN NumberOfTableEntries;
EFI_CONFIGURATION_TABLE *ConfigurationTable;
} EFI_SYSTEM_TABLE;
#endif

View File

@@ -1,30 +0,0 @@
/*++
Copyright (c) 2016 Pete Batard <pete@akeo.ie>
Module Name:
eficompiler.h
Abstract:
Compiler specific adjustments
--*/
#ifdef _MSC_EXTENSIONS
#define EFI_UNUSED
#else
#define EFI_UNUSED __attribute__((__unused__))
#endif
#ifdef _MSC_EXTENSIONS
#define ALIGN(x) __declspec(align(x))
#else
#define ALIGN(x) __attribute__((__aligned__(x)))
#endif
/* Also add a catch-all on __attribute__() for MS compilers */
#ifdef _MSC_EXTENSIONS
#define __attribute__(x)
#endif

View File

@@ -1,306 +0,0 @@
#ifndef _EFI_CON_H
#define _EFI_CON_H
/*++
Copyright (c) 1998 Intel Corporation
Module Name:
eficon.h
Abstract:
EFI console protocols
Revision History
--*/
//
// Text output protocol
//
#define EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID \
{ 0x387477c2, 0x69c7, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} }
#define SIMPLE_TEXT_OUTPUT_PROTOCOL EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID
INTERFACE_DECL(_SIMPLE_TEXT_OUTPUT_INTERFACE);
typedef
EFI_STATUS
(EFIAPI *EFI_TEXT_RESET) (
IN struct _SIMPLE_TEXT_OUTPUT_INTERFACE *This,
IN BOOLEAN ExtendedVerification
);
typedef
EFI_STATUS
(EFIAPI *EFI_TEXT_OUTPUT_STRING) (
IN struct _SIMPLE_TEXT_OUTPUT_INTERFACE *This,
IN CHAR16 *String
);
typedef
EFI_STATUS
(EFIAPI *EFI_TEXT_TEST_STRING) (
IN struct _SIMPLE_TEXT_OUTPUT_INTERFACE *This,
IN CHAR16 *String
);
typedef
EFI_STATUS
(EFIAPI *EFI_TEXT_QUERY_MODE) (
IN struct _SIMPLE_TEXT_OUTPUT_INTERFACE *This,
IN UINTN ModeNumber,
OUT UINTN *Columns,
OUT UINTN *Rows
);
typedef
EFI_STATUS
(EFIAPI *EFI_TEXT_SET_MODE) (
IN struct _SIMPLE_TEXT_OUTPUT_INTERFACE *This,
IN UINTN ModeNumber
);
typedef
EFI_STATUS
(EFIAPI *EFI_TEXT_SET_ATTRIBUTE) (
IN struct _SIMPLE_TEXT_OUTPUT_INTERFACE *This,
IN UINTN Attribute
);
#define EFI_BLACK 0x00
#define EFI_BLUE 0x01
#define EFI_GREEN 0x02
#define EFI_CYAN (EFI_BLUE | EFI_GREEN)
#define EFI_RED 0x04
#define EFI_MAGENTA (EFI_BLUE | EFI_RED)
#define EFI_BROWN (EFI_GREEN | EFI_RED)
#define EFI_LIGHTGRAY (EFI_BLUE | EFI_GREEN | EFI_RED)
#define EFI_BRIGHT 0x08
#define EFI_DARKGRAY (EFI_BRIGHT)
#define EFI_LIGHTBLUE (EFI_BLUE | EFI_BRIGHT)
#define EFI_LIGHTGREEN (EFI_GREEN | EFI_BRIGHT)
#define EFI_LIGHTCYAN (EFI_CYAN | EFI_BRIGHT)
#define EFI_LIGHTRED (EFI_RED | EFI_BRIGHT)
#define EFI_LIGHTMAGENTA (EFI_MAGENTA | EFI_BRIGHT)
#define EFI_YELLOW (EFI_BROWN | EFI_BRIGHT)
#define EFI_WHITE (EFI_BLUE | EFI_GREEN | EFI_RED | EFI_BRIGHT)
#define EFI_TEXT_ATTR(f,b) ((f) | ((b) << 4))
#define EFI_BACKGROUND_BLACK 0x00
#define EFI_BACKGROUND_BLUE 0x10
#define EFI_BACKGROUND_GREEN 0x20
#define EFI_BACKGROUND_CYAN (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_GREEN)
#define EFI_BACKGROUND_RED 0x40
#define EFI_BACKGROUND_MAGENTA (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_RED)
#define EFI_BACKGROUND_BROWN (EFI_BACKGROUND_GREEN | EFI_BACKGROUND_RED)
#define EFI_BACKGROUND_LIGHTGRAY (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_GREEN | EFI_BACKGROUND_RED)
typedef
EFI_STATUS
(EFIAPI *EFI_TEXT_CLEAR_SCREEN) (
IN struct _SIMPLE_TEXT_OUTPUT_INTERFACE *This
);
typedef
EFI_STATUS
(EFIAPI *EFI_TEXT_SET_CURSOR_POSITION) (
IN struct _SIMPLE_TEXT_OUTPUT_INTERFACE *This,
IN UINTN Column,
IN UINTN Row
);
typedef
EFI_STATUS
(EFIAPI *EFI_TEXT_ENABLE_CURSOR) (
IN struct _SIMPLE_TEXT_OUTPUT_INTERFACE *This,
IN BOOLEAN Enable
);
typedef struct {
INT32 MaxMode;
// current settings
INT32 Mode;
INT32 Attribute;
INT32 CursorColumn;
INT32 CursorRow;
BOOLEAN CursorVisible;
} SIMPLE_TEXT_OUTPUT_MODE;
typedef struct _SIMPLE_TEXT_OUTPUT_INTERFACE {
EFI_TEXT_RESET Reset;
EFI_TEXT_OUTPUT_STRING OutputString;
EFI_TEXT_TEST_STRING TestString;
EFI_TEXT_QUERY_MODE QueryMode;
EFI_TEXT_SET_MODE SetMode;
EFI_TEXT_SET_ATTRIBUTE SetAttribute;
EFI_TEXT_CLEAR_SCREEN ClearScreen;
EFI_TEXT_SET_CURSOR_POSITION SetCursorPosition;
EFI_TEXT_ENABLE_CURSOR EnableCursor;
// Current mode
SIMPLE_TEXT_OUTPUT_MODE *Mode;
} SIMPLE_TEXT_OUTPUT_INTERFACE, EFI_SIMPLE_TEXT_OUT_PROTOCOL;
//
// Define's for required EFI Unicode Box Draw character
//
#define BOXDRAW_HORIZONTAL 0x2500
#define BOXDRAW_VERTICAL 0x2502
#define BOXDRAW_DOWN_RIGHT 0x250c
#define BOXDRAW_DOWN_LEFT 0x2510
#define BOXDRAW_UP_RIGHT 0x2514
#define BOXDRAW_UP_LEFT 0x2518
#define BOXDRAW_VERTICAL_RIGHT 0x251c
#define BOXDRAW_VERTICAL_LEFT 0x2524
#define BOXDRAW_DOWN_HORIZONTAL 0x252c
#define BOXDRAW_UP_HORIZONTAL 0x2534
#define BOXDRAW_VERTICAL_HORIZONTAL 0x253c
#define BOXDRAW_DOUBLE_HORIZONTAL 0x2550
#define BOXDRAW_DOUBLE_VERTICAL 0x2551
#define BOXDRAW_DOWN_RIGHT_DOUBLE 0x2552
#define BOXDRAW_DOWN_DOUBLE_RIGHT 0x2553
#define BOXDRAW_DOUBLE_DOWN_RIGHT 0x2554
#define BOXDRAW_DOWN_LEFT_DOUBLE 0x2555
#define BOXDRAW_DOWN_DOUBLE_LEFT 0x2556
#define BOXDRAW_DOUBLE_DOWN_LEFT 0x2557
#define BOXDRAW_UP_RIGHT_DOUBLE 0x2558
#define BOXDRAW_UP_DOUBLE_RIGHT 0x2559
#define BOXDRAW_DOUBLE_UP_RIGHT 0x255a
#define BOXDRAW_UP_LEFT_DOUBLE 0x255b
#define BOXDRAW_UP_DOUBLE_LEFT 0x255c
#define BOXDRAW_DOUBLE_UP_LEFT 0x255d
#define BOXDRAW_VERTICAL_RIGHT_DOUBLE 0x255e
#define BOXDRAW_VERTICAL_DOUBLE_RIGHT 0x255f
#define BOXDRAW_DOUBLE_VERTICAL_RIGHT 0x2560
#define BOXDRAW_VERTICAL_LEFT_DOUBLE 0x2561
#define BOXDRAW_VERTICAL_DOUBLE_LEFT 0x2562
#define BOXDRAW_DOUBLE_VERTICAL_LEFT 0x2563
#define BOXDRAW_DOWN_HORIZONTAL_DOUBLE 0x2564
#define BOXDRAW_DOWN_DOUBLE_HORIZONTAL 0x2565
#define BOXDRAW_DOUBLE_DOWN_HORIZONTAL 0x2566
#define BOXDRAW_UP_HORIZONTAL_DOUBLE 0x2567
#define BOXDRAW_UP_DOUBLE_HORIZONTAL 0x2568
#define BOXDRAW_DOUBLE_UP_HORIZONTAL 0x2569
#define BOXDRAW_VERTICAL_HORIZONTAL_DOUBLE 0x256a
#define BOXDRAW_VERTICAL_DOUBLE_HORIZONTAL 0x256b
#define BOXDRAW_DOUBLE_VERTICAL_HORIZONTAL 0x256c
//
// EFI Required Block Elements Code Chart
//
#define BLOCKELEMENT_FULL_BLOCK 0x2588
#define BLOCKELEMENT_LIGHT_SHADE 0x2591
//
// EFI Required Geometric Shapes Code Chart
//
#define GEOMETRICSHAPE_UP_TRIANGLE 0x25b2
#define GEOMETRICSHAPE_RIGHT_TRIANGLE 0x25ba
#define GEOMETRICSHAPE_DOWN_TRIANGLE 0x25bc
#define GEOMETRICSHAPE_LEFT_TRIANGLE 0x25c4
//
// EFI Required Arrow shapes
//
#define ARROW_UP 0x2191
#define ARROW_DOWN 0x2193
//
// Text input protocol
//
#define EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID \
{ 0x387477c1, 0x69c7, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} }
#define SIMPLE_TEXT_INPUT_PROTOCOL EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID
INTERFACE_DECL(_SIMPLE_INPUT_INTERFACE);
typedef struct {
UINT16 ScanCode;
CHAR16 UnicodeChar;
} EFI_INPUT_KEY;
//
// Baseline unicode control chars
//
#define CHAR_NULL 0x0000
#define CHAR_BACKSPACE 0x0008
#define CHAR_TAB 0x0009
#define CHAR_LINEFEED 0x000A
#define CHAR_CARRIAGE_RETURN 0x000D
//
// Scan codes for base line keys
//
#define SCAN_NULL 0x0000
#define SCAN_UP 0x0001
#define SCAN_DOWN 0x0002
#define SCAN_RIGHT 0x0003
#define SCAN_LEFT 0x0004
#define SCAN_HOME 0x0005
#define SCAN_END 0x0006
#define SCAN_INSERT 0x0007
#define SCAN_DELETE 0x0008
#define SCAN_PAGE_UP 0x0009
#define SCAN_PAGE_DOWN 0x000A
#define SCAN_F1 0x000B
#define SCAN_F2 0x000C
#define SCAN_F3 0x000D
#define SCAN_F4 0x000E
#define SCAN_F5 0x000F
#define SCAN_F6 0x0010
#define SCAN_F7 0x0011
#define SCAN_F8 0x0012
#define SCAN_F9 0x0013
#define SCAN_F10 0x0014
#define SCAN_F11 0x0015
#define SCAN_F12 0x0016
#define SCAN_ESC 0x0017
typedef
EFI_STATUS
(EFIAPI *EFI_INPUT_RESET) (
IN struct _SIMPLE_INPUT_INTERFACE *This,
IN BOOLEAN ExtendedVerification
);
typedef
EFI_STATUS
(EFIAPI *EFI_INPUT_READ_KEY) (
IN struct _SIMPLE_INPUT_INTERFACE *This,
OUT EFI_INPUT_KEY *Key
);
typedef struct _SIMPLE_INPUT_INTERFACE {
EFI_INPUT_RESET Reset;
EFI_INPUT_READ_KEY ReadKeyStroke;
EFI_EVENT WaitForKey;
} SIMPLE_INPUT_INTERFACE, EFI_SIMPLE_TEXT_IN_PROTOCOL;
#endif

View File

@@ -1,620 +0,0 @@
#ifndef _EFI_DEBUG_H
#define _EFI_DEBUG_H
/*++
Copyright (c) 1998 Intel Corporation
Module Name:
efidebug.h
Abstract:
EFI library debug functions
Revision History
--*/
extern UINTN EFIDebug;
#if EFI_DEBUG
#define DBGASSERT(a) DbgAssert(__FILE__, __LINE__, #a)
#define DEBUG(a) DbgPrint a
#else
#define DBGASSERT(a)
#define DEBUG(a)
#endif
#if EFI_DEBUG_CLEAR_MEMORY
#define DBGSETMEM(a,l) SetMem(a,l,(CHAR8)BAD_POINTER)
#else
#define DBGSETMEM(a,l)
#endif
#define D_INIT 0x00000001 // Initialization style messages
#define D_WARN 0x00000002 // Warnings
#define D_LOAD 0x00000004 // Load events
#define D_FS 0x00000008 // EFI File system
#define D_POOL 0x00000010 // Alloc & Free's
#define D_PAGE 0x00000020 // Alloc & Free's
#define D_INFO 0x00000040 // Verbose
#define D_VAR 0x00000100 // Variable
#define D_PARSE 0x00000200 // Command parsing
#define D_BM 0x00000400 // Boot manager
#define D_BLKIO 0x00001000 // BlkIo Driver
#define D_BLKIO_ULTRA 0x00002000 // BlkIo Driver
#define D_NET 0x00004000 // SNI Driver
#define D_NET_ULTRA 0x00008000 // SNI Driver
#define D_TXTIN 0x00010000 // Simple Input Driver
#define D_TXTOUT 0x00020000 // Simple Text Output Driver
#define D_ERROR_ATA 0x00040000 // ATA error messages
#define D_ERROR 0x80000000 // Error
#define D_RESERVED 0x7fffC880 // Bits not reserved above
//
// Current Debug level of the system, value of EFIDebug
//
//#define EFI_DBUG_MASK (D_ERROR | D_WARN | D_LOAD | D_BLKIO | D_INIT)
#define EFI_DBUG_MASK (D_ERROR)
//
//
//
#if EFI_DEBUG
#define ASSERT(a) if(!(a)) DBGASSERT(a)
#define ASSERT_LOCKED(l) if(!(l)->Lock) DBGASSERT(l not locked)
#define ASSERT_STRUCT(p,t) DBGASSERT(t not structure), p
#else
#define ASSERT(a)
#define ASSERT_LOCKED(l)
#define ASSERT_STRUCT(p,t)
#endif
//
// Prototypes
//
INTN
DbgAssert (
CONST CHAR8 *file,
INTN lineno,
CONST CHAR8 *string
);
INTN
DbgPrint (
INTN mask,
CONST CHAR8 *format,
...
);
//
// Instruction Set Architectures definitions for debuggers
//
typedef INTN EFI_EXCEPTION_TYPE;
// IA32
#define EXCEPT_IA32_DIVIDE_ERROR 0
#define EXCEPT_IA32_DEBUG 1
#define EXCEPT_IA32_NMI 2
#define EXCEPT_IA32_BREAKPOINT 3
#define EXCEPT_IA32_OVERFLOW 4
#define EXCEPT_IA32_BOUND 5
#define EXCEPT_IA32_INVALID_OPCODE 6
#define EXCEPT_IA32_DOUBLE_FAULT 8
#define EXCEPT_IA32_INVALID_TSS 10
#define EXCEPT_IA32_SEG_NOT_PRESENT 11
#define EXCEPT_IA32_STACK_FAULT 12
#define EXCEPT_IA32_GP_FAULT 13
#define EXCEPT_IA32_PAGE_FAULT 14
#define EXCEPT_IA32_FP_ERROR 16
#define EXCEPT_IA32_ALIGNMENT_CHECK 17
#define EXCEPT_IA32_MACHINE_CHECK 18
#define EXCEPT_IA32_SIMD 19
typedef struct {
UINT16 Fcw;
UINT16 Fsw;
UINT16 Ftw;
UINT16 Opcode;
UINT32 Eip;
UINT16 Cs;
UINT16 Reserved1;
UINT32 DataOffset;
UINT16 Ds;
UINT8 Reserved2[10];
UINT8 St0Mm0[10], Reserved3[6];
UINT8 St1Mm1[10], Reserved4[6];
UINT8 St2Mm2[10], Reserved5[6];
UINT8 St3Mm3[10], Reserved6[6];
UINT8 St4Mm4[10], Reserved7[6];
UINT8 St5Mm5[10], Reserved8[6];
UINT8 St6Mm6[10], Reserved9[6];
UINT8 St7Mm7[10], Reserved10[6];
UINT8 Xmm0[16];
UINT8 Xmm1[16];
UINT8 Xmm2[16];
UINT8 Xmm3[16];
UINT8 Xmm4[16];
UINT8 Xmm5[16];
UINT8 Xmm6[16];
UINT8 Xmm7[16];
UINT8 Reserved11[14 * 16];
} EFI_FX_SAVE_STATE_IA32;
typedef struct {
UINT32 ExceptionData;
EFI_FX_SAVE_STATE_IA32 FxSaveState;
UINT32 Dr0;
UINT32 Dr1;
UINT32 Dr2;
UINT32 Dr3;
UINT32 Dr6;
UINT32 Dr7;
UINT32 Cr0;
UINT32 Cr1;
UINT32 Cr2;
UINT32 Cr3;
UINT32 Cr4;
UINT32 Eflags;
UINT32 Ldtr;
UINT32 Tr;
UINT32 Gdtr[2];
UINT32 Idtr[2];
UINT32 Eip;
UINT32 Gs;
UINT32 Fs;
UINT32 Es;
UINT32 Ds;
UINT32 Cs;
UINT32 Ss;
UINT32 Edi;
UINT32 Esi;
UINT32 Ebp;
UINT32 Esp;
UINT32 Ebx;
UINT32 Edx;
UINT32 Ecx;
UINT32 Eax;
} EFI_SYSTEM_CONTEXT_IA32;
// X64
#define EXCEPT_X64_DIVIDE_ERROR 0
#define EXCEPT_X64_DEBUG 1
#define EXCEPT_X64_NMI 2
#define EXCEPT_X64_BREAKPOINT 3
#define EXCEPT_X64_OVERFLOW 4
#define EXCEPT_X64_BOUND 5
#define EXCEPT_X64_INVALID_OPCODE 6
#define EXCEPT_X64_DOUBLE_FAULT 8
#define EXCEPT_X64_INVALID_TSS 10
#define EXCEPT_X64_SEG_NOT_PRESENT 11
#define EXCEPT_X64_STACK_FAULT 12
#define EXCEPT_X64_GP_FAULT 13
#define EXCEPT_X64_PAGE_FAULT 14
#define EXCEPT_X64_FP_ERROR 16
#define EXCEPT_X64_ALIGNMENT_CHECK 17
#define EXCEPT_X64_MACHINE_CHECK 18
#define EXCEPT_X64_SIMD 19
typedef struct {
UINT16 Fcw;
UINT16 Fsw;
UINT16 Ftw;
UINT16 Opcode;
UINT64 Rip;
UINT64 DataOffset;
UINT8 Reserved1[8];
UINT8 St0Mm0[10], Reserved2[6];
UINT8 St1Mm1[10], Reserved3[6];
UINT8 St2Mm2[10], Reserved4[6];
UINT8 St3Mm3[10], Reserved5[6];
UINT8 St4Mm4[10], Reserved6[6];
UINT8 St5Mm5[10], Reserved7[6];
UINT8 St6Mm6[10], Reserved8[6];
UINT8 St7Mm7[10], Reserved9[6];
UINT8 Xmm0[16];
UINT8 Xmm1[16];
UINT8 Xmm2[16];
UINT8 Xmm3[16];
UINT8 Xmm4[16];
UINT8 Xmm5[16];
UINT8 Xmm6[16];
UINT8 Xmm7[16];
UINT8 Reserved11[14 * 16];
} EFI_FX_SAVE_STATE_X64;
typedef struct {
UINT64 ExceptionData;
EFI_FX_SAVE_STATE_X64 FxSaveState;
UINT64 Dr0;
UINT64 Dr1;
UINT64 Dr2;
UINT64 Dr3;
UINT64 Dr6;
UINT64 Dr7;
UINT64 Cr0;
UINT64 Cr1;
UINT64 Cr2;
UINT64 Cr3;
UINT64 Cr4;
UINT64 Cr8;
UINT64 Rflags;
UINT64 Ldtr;
UINT64 Tr;
UINT64 Gdtr[2];
UINT64 Idtr[2];
UINT64 Rip;
UINT64 Gs;
UINT64 Fs;
UINT64 Es;
UINT64 Ds;
UINT64 Cs;
UINT64 Ss;
UINT64 Rdi;
UINT64 Rsi;
UINT64 Rbp;
UINT64 Rsp;
UINT64 Rbx;
UINT64 Rdx;
UINT64 Rcx;
UINT64 Rax;
UINT64 R8;
UINT64 R9;
UINT64 R10;
UINT64 R11;
UINT64 R12;
UINT64 R13;
UINT64 R14;
UINT64 R15;
} EFI_SYSTEM_CONTEXT_X64;
/// IA64
#define EXCEPT_IPF_VHTP_TRANSLATION 0
#define EXCEPT_IPF_INSTRUCTION_TLB 1
#define EXCEPT_IPF_DATA_TLB 2
#define EXCEPT_IPF_ALT_INSTRUCTION_TLB 3
#define EXCEPT_IPF_ALT_DATA_TLB 4
#define EXCEPT_IPF_DATA_NESTED_TLB 5
#define EXCEPT_IPF_INSTRUCTION_KEY_MISSED 6
#define EXCEPT_IPF_DATA_KEY_MISSED 7
#define EXCEPT_IPF_DIRTY_BIT 8
#define EXCEPT_IPF_INSTRUCTION_ACCESS_BIT 9
#define EXCEPT_IPF_DATA_ACCESS_BIT 10
#define EXCEPT_IPF_BREAKPOINT 11
#define EXCEPT_IPF_EXTERNAL_INTERRUPT 12
#define EXCEPT_IPF_PAGE_NOT_PRESENT 20
#define EXCEPT_IPF_KEY_PERMISSION 21
#define EXCEPT_IPF_INSTRUCTION_ACCESS_RIGHTS 22
#define EXCEPT_IPF_DATA_ACCESS_RIGHTS 23
#define EXCEPT_IPF_GENERAL_EXCEPTION 24
#define EXCEPT_IPF_DISABLED_FP_REGISTER 25
#define EXCEPT_IPF_NAT_CONSUMPTION 26
#define EXCEPT_IPF_SPECULATION 27
#define EXCEPT_IPF_DEBUG 29
#define EXCEPT_IPF_UNALIGNED_REFERENCE 30
#define EXCEPT_IPF_UNSUPPORTED_DATA_REFERENCE 31
#define EXCEPT_IPF_FP_FAULT 32
#define EXCEPT_IPF_FP_TRAP 33
#define EXCEPT_IPF_LOWER_PRIVILEGE_TRANSFER_TRAP 34
#define EXCEPT_IPF_TAKEN_BRANCH 35
#define EXCEPT_IPF_SINGLE_STEP 36
#define EXCEPT_IPF_IA32_EXCEPTION 45
#define EXCEPT_IPF_IA32_INTERCEPT 46
#define EXCEPT_IPF_IA32_INTERRUPT 47
typedef struct {
UINT64 Reserved;
UINT64 R1;
UINT64 R2;
UINT64 R3;
UINT64 R4;
UINT64 R5;
UINT64 R6;
UINT64 R7;
UINT64 R8;
UINT64 R9;
UINT64 R10;
UINT64 R11;
UINT64 R12;
UINT64 R13;
UINT64 R14;
UINT64 R15;
UINT64 R16;
UINT64 R17;
UINT64 R18;
UINT64 R19;
UINT64 R20;
UINT64 R21;
UINT64 R22;
UINT64 R23;
UINT64 R24;
UINT64 R25;
UINT64 R26;
UINT64 R27;
UINT64 R28;
UINT64 R29;
UINT64 R30;
UINT64 R31;
UINT64 F2[2];
UINT64 F3[2];
UINT64 F4[2];
UINT64 F5[2];
UINT64 F6[2];
UINT64 F7[2];
UINT64 F8[2];
UINT64 F9[2];
UINT64 F10[2];
UINT64 F11[2];
UINT64 F12[2];
UINT64 F13[2];
UINT64 F14[2];
UINT64 F15[2];
UINT64 F16[2];
UINT64 F17[2];
UINT64 F18[2];
UINT64 F19[2];
UINT64 F20[2];
UINT64 F21[2];
UINT64 F22[2];
UINT64 F23[2];
UINT64 F24[2];
UINT64 F25[2];
UINT64 F26[2];
UINT64 F27[2];
UINT64 F28[2];
UINT64 F29[2];
UINT64 F30[2];
UINT64 F31[2];
UINT64 Pr;
UINT64 B0;
UINT64 B1;
UINT64 B2;
UINT64 B3;
UINT64 B4;
UINT64 B5;
UINT64 B6;
UINT64 B7;
UINT64 ArRsc;
UINT64 ArBsp;
UINT64 ArBspstore;
UINT64 ArRnat;
UINT64 ArFcr;
UINT64 ArEflag;
UINT64 ArCsd;
UINT64 ArSsd;
UINT64 ArCflg;
UINT64 ArFsr;
UINT64 ArFir;
UINT64 ArFdr;
UINT64 ArCcv;
UINT64 ArUnat;
UINT64 ArFpsr;
UINT64 ArPfs;
UINT64 ArLc;
UINT64 ArEc;
UINT64 CrDcr;
UINT64 CrItm;
UINT64 CrIva;
UINT64 CrPta;
UINT64 CrIpsr;
UINT64 CrIsr;
UINT64 CrIip;
UINT64 CrIfa;
UINT64 CrItir;
UINT64 CrIipa;
UINT64 CrIfs;
UINT64 CrIim;
UINT64 CrIha;
UINT64 Dbr0;
UINT64 Dbr1;
UINT64 Dbr2;
UINT64 Dbr3;
UINT64 Dbr4;
UINT64 Dbr5;
UINT64 Dbr6;
UINT64 Dbr7;
UINT64 Ibr0;
UINT64 Ibr1;
UINT64 Ibr2;
UINT64 Ibr3;
UINT64 Ibr4;
UINT64 Ibr5;
UINT64 Ibr6;
UINT64 Ibr7;
UINT64 IntNat;
} EFI_SYSTEM_CONTEXT_IPF;
// EBC
#define EXCEPT_EBC_UNDEFINED 0
#define EXCEPT_EBC_DIVIDE_ERROR 1
#define EXCEPT_EBC_DEBUG 2
#define EXCEPT_EBC_BREAKPOINT 3
#define EXCEPT_EBC_OVERFLOW 4
#define EXCEPT_EBC_INVALID_OPCODE 5
#define EXCEPT_EBC_STACK_FAULT 6
#define EXCEPT_EBC_ALIGNMENT_CHECK 7
#define EXCEPT_EBC_INSTRUCTION_ENCODING 8
#define EXCEPT_EBC_BAD_BREAK 9
#define EXCEPT_EBC_STEP 10
#define MAX_EBC_EXCEPTION EXCEPT_EBC_STEP
typedef struct {
UINT64 R0;
UINT64 R1;
UINT64 R2;
UINT64 R3;
UINT64 R4;
UINT64 R5;
UINT64 R6;
UINT64 R7;
UINT64 Flags;
UINT64 ControlFlags;
UINT64 Ip;
} EFI_SYSTEM_CONTEXT_EBC;
// ARM
#define EXCEPT_ARM_RESET 0
#define EXCEPT_ARM_UNDEFINED_INSTRUCTION 1
#define EXCEPT_ARM_SOFTWARE_INTERRUPT 2
#define EXCEPT_ARM_PREFETCH_ABORT 3
#define EXCEPT_ARM_DATA_ABORT 4
#define EXCEPT_ARM_RESERVED 5
#define EXCEPT_ARM_IRQ 6
#define EXCEPT_ARM_FIQ 7
#define MAX_ARM_EXCEPTION EXCEPT_ARM_FIQ
typedef struct {
UINT32 R0;
UINT32 R1;
UINT32 R2;
UINT32 R3;
UINT32 R4;
UINT32 R5;
UINT32 R6;
UINT32 R7;
UINT32 R8;
UINT32 R9;
UINT32 R10;
UINT32 R11;
UINT32 R12;
UINT32 SP;
UINT32 LR;
UINT32 PC;
UINT32 CPSR;
UINT32 DFSR;
UINT32 DFAR;
UINT32 IFSR;
UINT32 IFAR;
} EFI_SYSTEM_CONTEXT_ARM;
typedef union {
EFI_SYSTEM_CONTEXT_EBC *SystemContextEbc;
EFI_SYSTEM_CONTEXT_IA32 *SystemContextIa32;
EFI_SYSTEM_CONTEXT_X64 *SystemContextX64;
EFI_SYSTEM_CONTEXT_IPF *SystemContextIpf;
EFI_SYSTEM_CONTEXT_ARM *SystemContextArm;
} EFI_SYSTEM_CONTEXT;
typedef
VOID
(EFIAPI *EFI_EXCEPTION_CALLBACK)(
IN EFI_EXCEPTION_TYPE ExceptionType,
IN OUT EFI_SYSTEM_CONTEXT SystemContext);
typedef
VOID
(EFIAPI *EFI_PERIODIC_CALLBACK)(
IN OUT EFI_SYSTEM_CONTEXT SystemContext);
typedef enum {
IsaIa32 = EFI_IMAGE_MACHINE_IA32,
IsaX64 = EFI_IMAGE_MACHINE_X64,
IsaIpf = EFI_IMAGE_MACHINE_IA64,
IsaEbc = EFI_IMAGE_MACHINE_EBC,
IsaArm = EFI_IMAGE_MACHINE_ARMTHUMB_MIXED,
// IsaArm64 = EFI_IMAGE_MACHINE_AARCH64
} EFI_INSTRUCTION_SET_ARCHITECTURE;
//
// DEBUG_IMAGE_INFO
//
#define EFI_DEBUG_IMAGE_INFO_TABLE_GUID \
{ 0x49152e77, 0x1ada, 0x4764, {0xb7, 0xa2, 0x7a, 0xfe, 0xfe, 0xd9, 0x5e, 0x8b} }
#define EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS 0x01
#define EFI_DEBUG_IMAGE_INFO_TABLE_MODIFIED 0x02
#define EFI_DEBUG_IMAGE_INFO_INITIAL_SIZE (EFI_PAGE_SIZE / sizeof (UINTN))
#define EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL 0x01
typedef struct {
UINT64 Signature;
EFI_PHYSICAL_ADDRESS EfiSystemTableBase;
UINT32 Crc32;
} EFI_SYSTEM_TABLE_POINTER;
typedef struct {
UINT32 ImageInfoType;
EFI_LOADED_IMAGE_PROTOCOL *LoadedImageProtocolInstance;
EFI_HANDLE *ImageHandle;
} EFI_DEBUG_IMAGE_INFO_NORMAL;
typedef union {
UINT32 *ImageInfoType;
EFI_DEBUG_IMAGE_INFO_NORMAL *NormalImage;
} EFI_DEBUG_IMAGE_INFO;
typedef struct {
volatile UINT32 UpdateStatus;
UINT32 TableSize;
EFI_DEBUG_IMAGE_INFO *EfiDebugImageInfoTable;
} EFI_DEBUG_IMAGE_INFO_TABLE_HEADER;
//
// EFI_DEBUGGER_PROTOCOL
//
#define EFI_DEBUG_SUPPORT_PROTOCOL_GUID \
{ 0x2755590c, 0x6f3c, 0x42fa, {0x9e, 0xa4, 0xa3, 0xba, 0x54, 0x3c, 0xda, 0x25} }
INTERFACE_DECL(_EFI_DEBUG_SUPPORT_PROTOCOL);
typedef
EFI_STATUS
(EFIAPI *EFI_GET_MAXIMUM_PROCESSOR_INDEX)(
IN struct _EFI_DEBUG_SUPPORT_PROTOCOL *This,
OUT UINTN *MaxProcessorIndex);
typedef
EFI_STATUS
(EFIAPI *EFI_REGISTER_PERIODIC_CALLBACK)(
IN struct _EFI_DEBUG_SUPPORT_PROTOCOL *This,
IN UINTN ProcessorIndex,
IN EFI_PERIODIC_CALLBACK PeriodicCallback);
typedef
EFI_STATUS
(EFIAPI *EFI_REGISTER_EXCEPTION_CALLBACK)(
IN struct _EFI_DEBUG_SUPPORT_PROTOCOL *This,
IN UINTN ProcessorIndex,
IN EFI_EXCEPTION_CALLBACK ExceptionCallback,
IN EFI_EXCEPTION_TYPE ExceptionType);
typedef
EFI_STATUS
(EFIAPI *EFI_INVALIDATE_INSTRUCTION_CACHE)(
IN struct _EFI_DEBUG_SUPPORT_PROTOCOL *This,
IN UINTN ProcessorIndex,
IN VOID *Start,
IN UINT64 Length);
typedef struct _EFI_DEBUG_SUPPORT_PROTOCOL {
EFI_INSTRUCTION_SET_ARCHITECTURE Isa;
EFI_GET_MAXIMUM_PROCESSOR_INDEX GetMaximumProcessorIndex;
EFI_REGISTER_PERIODIC_CALLBACK RegisterPeriodicCallback;
EFI_REGISTER_EXCEPTION_CALLBACK RegisterExceptionCallback;
EFI_INVALIDATE_INSTRUCTION_CACHE InvalidateInstructionCache;
} EFI_DEBUG_SUPPORT_PROTOCOL;
#endif

View File

@@ -1,220 +0,0 @@
#ifndef _EFI_DEF_H
#define _EFI_DEF_H
/*++
Copyright (c) 1998 Intel Corporation
Module Name:
efidef.h
Abstract:
EFI definitions
Revision History
--*/
typedef wchar_t CHAR16;
typedef char CHAR8;
typedef uint8_t BOOLEAN;
#ifndef CONST
#define CONST const
#endif
#ifndef TRUE
#define TRUE ((BOOLEAN) 1)
#define FALSE ((BOOLEAN) 0)
#endif
#ifndef NULL
#define NULL ((VOID *) 0)
#endif
typedef UINTN EFI_STATUS;
typedef UINT64 EFI_LBA;
typedef UINTN EFI_TPL;
typedef VOID *EFI_HANDLE;
typedef VOID *EFI_EVENT;
//
// Prototype argument decoration for EFI parameters to indicate
// their direction
//
// IN - argument is passed into the function
// OUT - argument (pointer) is returned from the function
// OPTIONAL - argument is optional
//
#ifndef IN
#define IN
#define OUT
#define OPTIONAL
#endif
//
// A GUID
//
typedef struct {
UINT32 Data1;
UINT16 Data2;
UINT16 Data3;
UINT8 Data4[8];
} EFI_GUID;
//
// Time
//
typedef struct {
UINT16 Year; // 1998 - 20XX
UINT8 Month; // 1 - 12
UINT8 Day; // 1 - 31
UINT8 Hour; // 0 - 23
UINT8 Minute; // 0 - 59
UINT8 Second; // 0 - 59
UINT8 Pad1;
UINT32 Nanosecond; // 0 - 999,999,999
INT16 TimeZone; // -1440 to 1440 or 2047
UINT8 Daylight;
UINT8 Pad2;
} EFI_TIME;
// Bit definitions for EFI_TIME.Daylight
#define EFI_TIME_ADJUST_DAYLIGHT 0x01
#define EFI_TIME_IN_DAYLIGHT 0x02
// Value definition for EFI_TIME.TimeZone
#define EFI_UNSPECIFIED_TIMEZONE 0x07FF
//
// Networking
//
typedef struct {
UINT8 Addr[4];
} EFI_IPv4_ADDRESS;
typedef struct {
UINT8 Addr[16];
} EFI_IPv6_ADDRESS;
typedef struct {
UINT8 Addr[32];
} EFI_MAC_ADDRESS;
typedef struct {
UINT32 ReceivedQueueTimeoutValue;
UINT32 TransmitQueueTimeoutValue;
UINT16 ProtocolTypeFilter;
BOOLEAN EnableUnicastReceive;
BOOLEAN EnableMulticastReceive;
BOOLEAN EnableBroadcastReceive;
BOOLEAN EnablePromiscuousReceive;
BOOLEAN FlushQueuesOnReset;
BOOLEAN EnableReceiveTimestamps;
BOOLEAN DisableBackgroundPolling;
} EFI_MANAGED_NETWORK_CONFIG_DATA;
//
// Memory
//
typedef UINT64 EFI_PHYSICAL_ADDRESS;
typedef UINT64 EFI_VIRTUAL_ADDRESS;
typedef enum {
AllocateAnyPages,
AllocateMaxAddress,
AllocateAddress,
MaxAllocateType
} EFI_ALLOCATE_TYPE;
//Preseve the attr on any range supplied.
//ConventialMemory must have WB,SR,SW when supplied.
//When allocating from ConventialMemory always make it WB,SR,SW
//When returning to ConventialMemory always make it WB,SR,SW
//When getting the memory map, or on RT for runtime types
typedef enum {
EfiReservedMemoryType,
EfiLoaderCode,
EfiLoaderData,
EfiBootServicesCode,
EfiBootServicesData,
EfiRuntimeServicesCode,
EfiRuntimeServicesData,
EfiConventionalMemory,
EfiUnusableMemory,
EfiACPIReclaimMemory,
EfiACPIMemoryNVS,
EfiMemoryMappedIO,
EfiMemoryMappedIOPortSpace,
EfiPalCode,
EfiMaxMemoryType
} EFI_MEMORY_TYPE;
// possible caching types for the memory range
#define EFI_MEMORY_UC 0x0000000000000001
#define EFI_MEMORY_WC 0x0000000000000002
#define EFI_MEMORY_WT 0x0000000000000004
#define EFI_MEMORY_WB 0x0000000000000008
#define EFI_MEMORY_UCE 0x0000000000000010
// physical memory protection on range
#define EFI_MEMORY_WP 0x0000000000001000
#define EFI_MEMORY_RP 0x0000000000002000
#define EFI_MEMORY_XP 0x0000000000004000
// range requires a runtime mapping
#define EFI_MEMORY_RUNTIME 0x8000000000000000
#define EFI_MEMORY_DESCRIPTOR_VERSION 1
typedef struct {
UINT32 Type; // Field size is 32 bits followed by 32 bit pad
UINT32 Pad;
EFI_PHYSICAL_ADDRESS PhysicalStart; // Field size is 64 bits
EFI_VIRTUAL_ADDRESS VirtualStart; // Field size is 64 bits
UINT64 NumberOfPages; // Field size is 64 bits
UINT64 Attribute; // Field size is 64 bits
} EFI_MEMORY_DESCRIPTOR;
//
// International Language
//
typedef UINT8 ISO_639_2;
#define ISO_639_2_ENTRY_SIZE 3
//
//
//
#define EFI_PAGE_SIZE 4096
#define EFI_PAGE_MASK 0xFFF
#define EFI_PAGE_SHIFT 12
#define EFI_SIZE_TO_PAGES(a) \
( ((a) >> EFI_PAGE_SHIFT) + ((a) & EFI_PAGE_MASK ? 1 : 0) )
#define EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001
#define EFI_OS_INDICATIONS_TIMESTAMP_REVOCATION 0x0000000000000002
#define EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED \
0x0000000000000004
#define EFI_OS_INDICATIONS_FMP_CAPSULE_SUPPORTED \
0x0000000000000008
#define EFI_OS_INDICATIONS_CAPSULE_RESULT_VAR_SUPPORTED \
0x0000000000000010
#endif

View File

@@ -1,582 +0,0 @@
#ifndef _DEVPATH_H
#define _DEVPATH_H
/*++
Copyright (c) 1998 Intel Corporation
Module Name:
devpath.h
Abstract:
Defines for parsing the EFI Device Path structures
Revision History
--*/
//
// Device Path structures - Section C
//
typedef struct _EFI_DEVICE_PATH_PROTOCOL {
UINT8 Type;
UINT8 SubType;
UINT8 Length[2];
} EFI_DEVICE_PATH_PROTOCOL;
typedef struct _EFI_DEVICE_PATH_PROTOCOL _EFI_DEVICE_PATH;
typedef EFI_DEVICE_PATH_PROTOCOL EFI_DEVICE_PATH;
#define EFI_DP_TYPE_MASK 0x7F
#define EFI_DP_TYPE_UNPACKED 0x80
//#define END_DEVICE_PATH_TYPE 0xff
#define END_DEVICE_PATH_TYPE 0x7f
//#define END_DEVICE_PATH_TYPE_UNPACKED 0x7f
#define END_ENTIRE_DEVICE_PATH_SUBTYPE 0xff
#define END_INSTANCE_DEVICE_PATH_SUBTYPE 0x01
#define END_DEVICE_PATH_LENGTH (sizeof(EFI_DEVICE_PATH_PROTOCOL))
#define DP_IS_END_TYPE(a)
#define DP_IS_END_SUBTYPE(a) ( ((a)->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE )
#define DevicePathType(a) ( ((a)->Type) & EFI_DP_TYPE_MASK )
#define DevicePathSubType(a) ( (a)->SubType )
#define DevicePathNodeLength(a) ( ((a)->Length[0]) | ((a)->Length[1] << 8) )
#define NextDevicePathNode(a) ( (EFI_DEVICE_PATH_PROTOCOL *) ( ((UINT8 *) (a)) + DevicePathNodeLength(a)))
//#define IsDevicePathEndType(a) ( DevicePathType(a) == END_DEVICE_PATH_TYPE_UNPACKED )
#define IsDevicePathEndType(a) ( DevicePathType(a) == END_DEVICE_PATH_TYPE )
#define IsDevicePathEndSubType(a) ( (a)->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE )
#define IsDevicePathEnd(a) ( IsDevicePathEndType(a) && IsDevicePathEndSubType(a) )
#define IsDevicePathUnpacked(a) ( (a)->Type & EFI_DP_TYPE_UNPACKED )
#define SetDevicePathNodeLength(a,l) { \
(a)->Length[0] = (UINT8) (l); \
(a)->Length[1] = (UINT8) ((l) >> 8); \
}
#define SetDevicePathEndNode(a) { \
(a)->Type = END_DEVICE_PATH_TYPE; \
(a)->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE; \
(a)->Length[0] = sizeof(EFI_DEVICE_PATH_PROTOCOL); \
(a)->Length[1] = 0; \
}
/*
* Hardware Device Path (UEFI 2.4 specification, version 2.4 § 9.3.2.)
*/
#define HARDWARE_DEVICE_PATH 0x01
#define HW_PCI_DP 0x01
typedef struct _PCI_DEVICE_PATH {
EFI_DEVICE_PATH_PROTOCOL Header;
UINT8 Function;
UINT8 Device;
} PCI_DEVICE_PATH;
#define HW_PCCARD_DP 0x02
typedef struct _PCCARD_DEVICE_PATH {
EFI_DEVICE_PATH_PROTOCOL Header;
UINT8 FunctionNumber ;
} PCCARD_DEVICE_PATH;
#define HW_MEMMAP_DP 0x03
typedef struct _MEMMAP_DEVICE_PATH {
EFI_DEVICE_PATH_PROTOCOL Header;
UINT32 MemoryType;
EFI_PHYSICAL_ADDRESS StartingAddress;
EFI_PHYSICAL_ADDRESS EndingAddress;
} MEMMAP_DEVICE_PATH;
#define HW_VENDOR_DP 0x04
typedef struct _VENDOR_DEVICE_PATH {
EFI_DEVICE_PATH_PROTOCOL Header;
EFI_GUID Guid;
} VENDOR_DEVICE_PATH;
#define UNKNOWN_DEVICE_GUID \
{ 0xcf31fac5, 0xc24e, 0x11d2, {0x85, 0xf3, 0x0, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b} }
typedef struct _UKNOWN_DEVICE_VENDOR_DP {
VENDOR_DEVICE_PATH DevicePath;
UINT8 LegacyDriveLetter;
} UNKNOWN_DEVICE_VENDOR_DEVICE_PATH;
#define HW_CONTROLLER_DP 0x05
typedef struct _CONTROLLER_DEVICE_PATH {
EFI_DEVICE_PATH_PROTOCOL Header;
UINT32 Controller;
} CONTROLLER_DEVICE_PATH;
/*
* ACPI Device Path (UEFI 2.4 specification, version 2.4 § 9.3.3 and 9.3.4.)
*/
#define ACPI_DEVICE_PATH 0x02
#define ACPI_DP 0x01
typedef struct _ACPI_HID_DEVICE_PATH {
EFI_DEVICE_PATH_PROTOCOL Header;
UINT32 HID;
UINT32 UID;
} ACPI_HID_DEVICE_PATH;
#define EXPANDED_ACPI_DP 0x02
typedef struct _EXPANDED_ACPI_HID_DEVICE_PATH {
EFI_DEVICE_PATH_PROTOCOL Header;
UINT32 HID;
UINT32 UID;
UINT32 CID;
UINT8 HidStr[1];
} EXPANDED_ACPI_HID_DEVICE_PATH;
#define ACPI_ADR_DP 3
typedef struct _ACPI_ADR_DEVICE_PATH {
EFI_DEVICE_PATH_PROTOCOL Header ;
UINT32 ADR ;
} ACPI_ADR_DEVICE_PATH ;
//
// EISA ID Macro
// EISA ID Definition 32-bits
// bits[15:0] - three character compressed ASCII EISA ID.
// bits[31:16] - binary number
// Compressed ASCII is 5 bits per character 0b00001 = 'A' 0b11010 = 'Z'
//
#define PNP_EISA_ID_CONST 0x41d0
#define EISA_ID(_Name, _Num) ((UINT32) ((_Name) | (_Num) << 16))
#define EISA_PNP_ID(_PNPId) (EISA_ID(PNP_EISA_ID_CONST, (_PNPId)))
#define PNP_EISA_ID_MASK 0xffff
#define EISA_ID_TO_NUM(_Id) ((_Id) >> 16)
/*
* Messaging Device Path (UEFI 2.4 specification, version 2.4 § 9.3.5.)
*/
#define MESSAGING_DEVICE_PATH 0x03
#define MSG_ATAPI_DP 0x01
typedef struct _ATAPI_DEVICE_PATH {
EFI_DEVICE_PATH_PROTOCOL Header;
UINT8 PrimarySecondary;
UINT8 SlaveMaster;
UINT16 Lun;
} ATAPI_DEVICE_PATH;
#define MSG_SCSI_DP 0x02
typedef struct _SCSI_DEVICE_PATH {
EFI_DEVICE_PATH_PROTOCOL Header;
UINT16 Pun;
UINT16 Lun;
} SCSI_DEVICE_PATH;
#define MSG_FIBRECHANNEL_DP 0x03
typedef struct _FIBRECHANNEL_DEVICE_PATH {
EFI_DEVICE_PATH_PROTOCOL Header;
UINT32 Reserved;
UINT64 WWN;
UINT64 Lun;
} FIBRECHANNEL_DEVICE_PATH;
/**
* Fibre Channel Ex SubType.
* UEFI 2.0 specification version 2.4 § 9.3.5.6.
*/
#define MSG_FIBRECHANNELEX_DP 21
typedef struct _FIBRECHANNELEX_DEVICE_PATH {
EFI_DEVICE_PATH_PROTOCOL Header ;
UINT32 Reserved ;
UINT8 WWN[ 8 ] ; /* World Wide Name */
UINT8 Lun[ 8 ] ; /* Logical unit, T-10 SCSI Architecture Model 4 specification */
} FIBRECHANNELEX_DEVICE_PATH ;
#define MSG_1394_DP 0x04
typedef struct _F1394_DEVICE_PATH {
EFI_DEVICE_PATH_PROTOCOL Header;
UINT32 Reserved;
UINT64 Guid;
} F1394_DEVICE_PATH;
#define MSG_USB_DP 0x05
typedef struct _USB_DEVICE_PATH {
EFI_DEVICE_PATH_PROTOCOL Header;
UINT8 Port;
UINT8 Endpoint;
} USB_DEVICE_PATH;
/**
* SATA Device Path SubType.
* UEFI 2.0 specification version 2.4 § 9.3.5.6.
*/
#define MSG_SATA_DP 18
typedef struct _SATA_DEVICE_PATH {
EFI_DEVICE_PATH_PROTOCOL Header ;
UINT16 HBAPortNumber ;
UINT16 PortMultiplierPortNumber ;
UINT16 Lun ; /* Logical Unit Number */
} SATA_DEVICE_PATH ;
/**
* USB WWID Device Path SubType.
* UEFI 2.0 specification version 2.4 § 9.3.5.7.
*/
#define MSG_USB_WWID_DP 16
typedef struct _USB_WWID_DEVICE_PATH {
EFI_DEVICE_PATH_PROTOCOL Header ;
UINT16 InterfaceNumber ;
UINT16 VendorId ;
UINT16 ProductId ;
CHAR16 SerialNumber[ 1 ] ; /* UTF-16 characters of the USB serial number */
} USB_WWID_DEVICE_PATH ;
/**
* Device Logical Unit SubType.
* UEFI 2.0 specification version 2.4 § 9.3.5.8.
*/
#define MSG_DEVICE_LOGICAL_UNIT_DP 17
typedef struct _DEVICE_LOGICAL_UNIT_DEVICE_PATH {
EFI_DEVICE_PATH_PROTOCOL Header ;
UINT8 Lun ; /* Logical Unit Number */
} DEVICE_LOGICAL_UNIT_DEVICE_PATH ;
#define MSG_USB_CLASS_DP 0x0F
typedef struct _USB_CLASS_DEVICE_PATH {
EFI_DEVICE_PATH_PROTOCOL Header;
UINT16 VendorId;
UINT16 ProductId;
UINT8 DeviceClass;
UINT8 DeviceSubclass;
UINT8 DeviceProtocol;
} USB_CLASS_DEVICE_PATH;
#define MSG_I2O_DP 0x06
typedef struct _I2O_DEVICE_PATH {
EFI_DEVICE_PATH_PROTOCOL Header;
UINT32 Tid;
} I2O_DEVICE_PATH;
#define MSG_MAC_ADDR_DP 0x0b
typedef struct _MAC_ADDR_DEVICE_PATH {
EFI_DEVICE_PATH_PROTOCOL Header;
EFI_MAC_ADDRESS MacAddress;
UINT8 IfType;
} MAC_ADDR_DEVICE_PATH;
#define MSG_IPv4_DP 0x0c
typedef struct _IPv4_DEVICE_PATH {
EFI_DEVICE_PATH_PROTOCOL Header;
EFI_IPv4_ADDRESS LocalIpAddress;
EFI_IPv4_ADDRESS RemoteIpAddress;
UINT16 LocalPort;
UINT16 RemotePort;
UINT16 Protocol;
BOOLEAN StaticIpAddress;
/* new from UEFI version 2, code must check Length field in Header */
EFI_IPv4_ADDRESS GatewayIpAddress ;
EFI_IPv4_ADDRESS SubnetMask ;
} IPv4_DEVICE_PATH;
#define MSG_IPv6_DP 0x0d
typedef struct _IPv6_DEVICE_PATH {
EFI_DEVICE_PATH_PROTOCOL Header;
EFI_IPv6_ADDRESS LocalIpAddress;
EFI_IPv6_ADDRESS RemoteIpAddress;
UINT16 LocalPort;
UINT16 RemotePort;
UINT16 Protocol;
BOOLEAN IPAddressOrigin ;
/* new from UEFI version 2, code must check Length field in Header */
UINT8 PrefixLength ;
EFI_IPv6_ADDRESS GatewayIpAddress ;
} IPv6_DEVICE_PATH;
/**
* Uniform Resource Identifiers SubType.
* UEFI 2.0 specification version 2.4C § 9.3.5.23.
*/
#define MSG_URI_DP 24
typedef struct _URI_DEVICE_PATH {
EFI_DEVICE_PATH_PROTOCOL Header;
CHAR8 Uri[1];
} URI_DEVICE_PATH;
/**
* Device Logical Unit SubType.
* UEFI 2.0 specification version 2.4 § 9.3.5.8.
*/
#define MSG_VLAN_DP 20
typedef struct _VLAN_DEVICE_PATH {
EFI_DEVICE_PATH_PROTOCOL Header ;
UINT16 VlanId ;
} VLAN_DEVICE_PATH;
#define MSG_INFINIBAND_DP 0x09
typedef struct _INFINIBAND_DEVICE_PATH {
EFI_DEVICE_PATH_PROTOCOL Header;
UINT32 ResourceFlags ;
UINT64 PortGid ;
UINT64 ServiceId ;
UINT64 TargetPortId ;
UINT64 DeviceId ;
} INFINIBAND_DEVICE_PATH;
#define MSG_UART_DP 0x0e
typedef struct _UART_DEVICE_PATH {
EFI_DEVICE_PATH_PROTOCOL Header;
UINT32 Reserved;
UINT64 BaudRate;
UINT8 DataBits;
UINT8 Parity;
UINT8 StopBits;
} UART_DEVICE_PATH;
#define MSG_VENDOR_DP 0x0A
/* Use VENDOR_DEVICE_PATH struct */
#define EFI_PC_ANSI_GUID \
{ 0xe0c14753, 0xf9be, 0x11d2, {0x9a, 0x0c, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d} }
#define DEVICE_PATH_MESSAGING_PC_ANSI EFI_PC_ANSI_GUID
#define EFI_VT_100_GUID \
{ 0xdfa66065, 0xb419, 0x11d3, {0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d} }
#define DEVICE_PATH_MESSAGING_VT_100 EFI_VT_100_GUID
#define EFI_VT_100_PLUS_GUID \
{ 0x7baec70b, 0x57e0, 0x4c76, {0x8e, 0x87, 0x2f, 0x9e, 0x28, 0x08, 0x83, 0x43} }
#define DEVICE_PATH_MESSAGING_VT_100_PLUS EFI_VT_100_PLUS_GUID
#define EFI_VT_UTF8_GUID \
{ 0xad15a0d6, 0x8bec, 0x4acf, {0xa0, 0x73, 0xd0, 0x1d, 0xe7, 0x7e, 0x2d, 0x88} }
#define DEVICE_PATH_MESSAGING_VT_UTF8 EFI_VT_UTF8_GUID
/*
* Media Device Path (UEFI 2.4 specification, version 2.4 § 9.3.6.)
*/
#define MEDIA_DEVICE_PATH 0x04
#define MEDIA_HARDDRIVE_DP 0x01
typedef struct _HARDDRIVE_DEVICE_PATH {
EFI_DEVICE_PATH_PROTOCOL Header;
UINT32 PartitionNumber;
UINT64 PartitionStart;
UINT64 PartitionSize;
UINT8 Signature[16];
UINT8 MBRType;
UINT8 SignatureType;
} HARDDRIVE_DEVICE_PATH;
#define MBR_TYPE_PCAT 0x01
#define MBR_TYPE_EFI_PARTITION_TABLE_HEADER 0x02
#define SIGNATURE_TYPE_MBR 0x01
#define SIGNATURE_TYPE_GUID 0x02
#define MEDIA_CDROM_DP 0x02
typedef struct _CDROM_DEVICE_PATH {
EFI_DEVICE_PATH_PROTOCOL Header;
UINT32 BootEntry;
UINT64 PartitionStart;
UINT64 PartitionSize;
} CDROM_DEVICE_PATH;
#define MEDIA_VENDOR_DP 0x03
/* Use VENDOR_DEVICE_PATH struct */
#define MEDIA_FILEPATH_DP 0x04
typedef struct _FILEPATH_DEVICE_PATH {
EFI_DEVICE_PATH_PROTOCOL Header;
CHAR16 PathName[1];
} FILEPATH_DEVICE_PATH;
#define SIZE_OF_FILEPATH_DEVICE_PATH EFI_FIELD_OFFSET(FILEPATH_DEVICE_PATH,PathName)
#define MEDIA_PROTOCOL_DP 0x05
typedef struct _MEDIA_PROTOCOL_DEVICE_PATH {
EFI_DEVICE_PATH_PROTOCOL Header;
EFI_GUID Protocol;
} MEDIA_PROTOCOL_DEVICE_PATH;
/**
* PIWG Firmware File SubType.
* UEFI 2.0 specification version 2.4 § 9.3.6.6.
*/
#define MEDIA_PIWG_FW_FILE_DP 6
typedef struct _MEDIA_FW_VOL_FILEPATH_DEVICE_PATH {
EFI_DEVICE_PATH_PROTOCOL Header ;
EFI_GUID FvFileName ;
} MEDIA_FW_VOL_FILEPATH_DEVICE_PATH ;
/**
* PIWG Firmware Volume Device Path SubType.
* UEFI 2.0 specification version 2.4 § 9.3.6.7.
*/
#define MEDIA_PIWG_FW_VOL_DP 7
typedef struct _MEDIA_FW_VOL_DEVICE_PATH {
EFI_DEVICE_PATH_PROTOCOL Header ;
EFI_GUID FvName ;
} MEDIA_FW_VOL_DEVICE_PATH ;
/**
* Media relative offset range device path.
* UEFI 2.0 specification version 2.4 § 9.3.6.8.
*/
#define MEDIA_RELATIVE_OFFSET_RANGE_DP 8
typedef struct _MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH {
EFI_DEVICE_PATH_PROTOCOL Header ;
UINT32 Reserved ;
UINT64 StartingOffset ;
UINT64 EndingOffset ;
} MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH ;
/*
* BIOS Boot Specification Device Path (UEFI 2.4 specification, version 2.4 § 9.3.7.)
*/
#define BBS_DEVICE_PATH 0x05
#define BBS_BBS_DP 0x01
typedef struct _BBS_BBS_DEVICE_PATH {
EFI_DEVICE_PATH_PROTOCOL Header;
UINT16 DeviceType;
UINT16 StatusFlag;
CHAR8 String[1];
} BBS_BBS_DEVICE_PATH;
/* DeviceType definitions - from BBS specification */
#define BBS_TYPE_FLOPPY 0x01
#define BBS_TYPE_HARDDRIVE 0x02
#define BBS_TYPE_CDROM 0x03
#define BBS_TYPE_PCMCIA 0x04
#define BBS_TYPE_USB 0x05
#define BBS_TYPE_EMBEDDED_NETWORK 0x06
#define BBS_TYPE_DEV 0x80
#define BBS_TYPE_UNKNOWN 0xFF
typedef union {
EFI_DEVICE_PATH_PROTOCOL DevPath;
PCI_DEVICE_PATH Pci;
PCCARD_DEVICE_PATH PcCard;
MEMMAP_DEVICE_PATH MemMap;
VENDOR_DEVICE_PATH Vendor;
UNKNOWN_DEVICE_VENDOR_DEVICE_PATH UnknownVendor;
CONTROLLER_DEVICE_PATH Controller;
ACPI_HID_DEVICE_PATH Acpi;
ATAPI_DEVICE_PATH Atapi;
SCSI_DEVICE_PATH Scsi;
FIBRECHANNEL_DEVICE_PATH FibreChannel;
F1394_DEVICE_PATH F1394;
USB_DEVICE_PATH Usb;
USB_CLASS_DEVICE_PATH UsbClass;
I2O_DEVICE_PATH I2O;
MAC_ADDR_DEVICE_PATH MacAddr;
IPv4_DEVICE_PATH Ipv4;
IPv6_DEVICE_PATH Ipv6;
URI_DEVICE_PATH Uri;
INFINIBAND_DEVICE_PATH InfiniBand;
UART_DEVICE_PATH Uart;
HARDDRIVE_DEVICE_PATH HardDrive;
CDROM_DEVICE_PATH CD;
FILEPATH_DEVICE_PATH FilePath;
MEDIA_PROTOCOL_DEVICE_PATH MediaProtocol;
BBS_BBS_DEVICE_PATH Bbs;
} EFI_DEV_PATH;
typedef union {
EFI_DEVICE_PATH_PROTOCOL *DevPath;
PCI_DEVICE_PATH *Pci;
PCCARD_DEVICE_PATH *PcCard;
MEMMAP_DEVICE_PATH *MemMap;
VENDOR_DEVICE_PATH *Vendor;
UNKNOWN_DEVICE_VENDOR_DEVICE_PATH *UnknownVendor;
CONTROLLER_DEVICE_PATH *Controller;
ACPI_HID_DEVICE_PATH *Acpi;
ATAPI_DEVICE_PATH *Atapi;
SCSI_DEVICE_PATH *Scsi;
FIBRECHANNEL_DEVICE_PATH *FibreChannel;
F1394_DEVICE_PATH *F1394;
USB_DEVICE_PATH *Usb;
USB_CLASS_DEVICE_PATH *UsbClass;
I2O_DEVICE_PATH *I2O;
MAC_ADDR_DEVICE_PATH *MacAddr;
IPv4_DEVICE_PATH *Ipv4;
IPv6_DEVICE_PATH *Ipv6;
URI_DEVICE_PATH *Uri;
INFINIBAND_DEVICE_PATH *InfiniBand;
UART_DEVICE_PATH *Uart;
HARDDRIVE_DEVICE_PATH *HardDrive;
FILEPATH_DEVICE_PATH *FilePath;
MEDIA_PROTOCOL_DEVICE_PATH *MediaProtocol;
CDROM_DEVICE_PATH *CD;
BBS_BBS_DEVICE_PATH *Bbs;
} EFI_DEV_PATH_PTR;
#define EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID \
{ 0x8b843e20, 0x8132, 0x4852, {0x90, 0xcc, 0x55, 0x1a, 0x4e, 0x4a, 0x7f, 0x1c} }
typedef
CHAR16*
(EFIAPI *EFI_DEVICE_PATH_TO_TEXT_NODE) (
IN CONST EFI_DEVICE_PATH_PROTOCOL *DeviceNode,
IN BOOLEAN DisplayOnly,
IN BOOLEAN AllowShortcuts
);
typedef
CHAR16*
(EFIAPI *EFI_DEVICE_PATH_TO_TEXT_PATH) (
IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
IN BOOLEAN DisplayOnly,
IN BOOLEAN AllowShortcuts
);
typedef struct _EFI_DEVICE_PATH_TO_TEXT_PROTOCOL {
EFI_DEVICE_PATH_TO_TEXT_NODE ConvertDeviceNodeToText;
EFI_DEVICE_PATH_TO_TEXT_PATH ConvertDevicePathToText;
} EFI_DEVICE_PATH_TO_TEXT_PROTOCOL;
#define EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL_GUID \
{ 0x5c99a21, 0xc70f, 0x4ad2, {0x8a, 0x5f, 0x35, 0xdf, 0x33, 0x43, 0xf5, 0x1e} }
typedef
EFI_DEVICE_PATH_PROTOCOL*
(EFIAPI *EFI_DEVICE_PATH_FROM_TEXT_NODE) (
IN CONST CHAR16 *TextDeviceNode
);
typedef
EFI_DEVICE_PATH_PROTOCOL*
(EFIAPI *EFI_DEVICE_PATH_FROM_TEXT_PATH) (
IN CONST CHAR16 *TextDevicePath
);
typedef struct {
EFI_DEVICE_PATH_FROM_TEXT_NODE ConvertTextToDeviceNode;
EFI_DEVICE_PATH_FROM_TEXT_PATH ConvertTextToDevicePath;
} EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL;
#endif

View File

@@ -1,67 +0,0 @@
#ifndef _EFI_ERR_H
#define _EFI_ERR_H
/*++
Copyright (c) 1998 Intel Corporation
Module Name:
efierr.h
Abstract:
EFI error codes
Revision History
--*/
#define EFIWARN(a) (a)
#define EFI_ERROR(a) (((INTN) a) < 0)
#define EFI_SUCCESS 0
#define EFI_LOAD_ERROR EFIERR(1)
#define EFI_INVALID_PARAMETER EFIERR(2)
#define EFI_UNSUPPORTED EFIERR(3)
#define EFI_BAD_BUFFER_SIZE EFIERR(4)
#define EFI_BUFFER_TOO_SMALL EFIERR(5)
#define EFI_NOT_READY EFIERR(6)
#define EFI_DEVICE_ERROR EFIERR(7)
#define EFI_WRITE_PROTECTED EFIERR(8)
#define EFI_OUT_OF_RESOURCES EFIERR(9)
#define EFI_VOLUME_CORRUPTED EFIERR(10)
#define EFI_VOLUME_FULL EFIERR(11)
#define EFI_NO_MEDIA EFIERR(12)
#define EFI_MEDIA_CHANGED EFIERR(13)
#define EFI_NOT_FOUND EFIERR(14)
#define EFI_ACCESS_DENIED EFIERR(15)
#define EFI_NO_RESPONSE EFIERR(16)
#define EFI_NO_MAPPING EFIERR(17)
#define EFI_TIMEOUT EFIERR(18)
#define EFI_NOT_STARTED EFIERR(19)
#define EFI_ALREADY_STARTED EFIERR(20)
#define EFI_ABORTED EFIERR(21)
#define EFI_ICMP_ERROR EFIERR(22)
#define EFI_TFTP_ERROR EFIERR(23)
#define EFI_PROTOCOL_ERROR EFIERR(24)
#define EFI_INCOMPATIBLE_VERSION EFIERR(25)
#define EFI_SECURITY_VIOLATION EFIERR(26)
#define EFI_CRC_ERROR EFIERR(27)
#define EFI_END_OF_MEDIA EFIERR(28)
#define EFI_END_OF_FILE EFIERR(31)
#define EFI_INVALID_LANGUAGE EFIERR(32)
#define EFI_COMPROMISED_DATA EFIERR(33)
#define EFI_WARN_UNKOWN_GLYPH EFIWARN(1)
#define EFI_WARN_DELETE_FAILURE EFIWARN(2)
#define EFI_WARN_WRITE_FAILURE EFIWARN(3)
#define EFI_WARN_BUFFER_TOO_SMALL EFIWARN(4)
#endif

View File

@@ -1,116 +0,0 @@
#ifndef _EFI_FS_H
#define _EFI_FS_H
/*++
Copyright (c) 1998 Intel Corporation
Module Name:
efifs.h
Abstract:
EFI File System structures
Revision History
--*/
//
// EFI Partition header (normaly starts in LBA 1)
//
#define EFI_PARTITION_SIGNATURE 0x5053595320494249
#define EFI_PARTITION_REVISION 0x00010001
#define MIN_EFI_PARTITION_BLOCK_SIZE 512
#define EFI_PARTITION_LBA 1
typedef struct _EFI_PARTITION_HEADER {
EFI_TABLE_HEADER Hdr;
UINT32 DirectoryAllocationNumber;
UINT32 BlockSize;
EFI_LBA FirstUsableLba;
EFI_LBA LastUsableLba;
EFI_LBA UnusableSpace;
EFI_LBA FreeSpace;
EFI_LBA RootFile;
EFI_LBA SecutiryFile;
} EFI_PARTITION_HEADER;
//
// File header
//
#define EFI_FILE_HEADER_SIGNATURE 0x454c494620494249
#define EFI_FILE_HEADER_REVISION 0x00010000
#define EFI_FILE_STRING_SIZE 260
typedef struct _EFI_FILE_HEADER {
EFI_TABLE_HEADER Hdr;
UINT32 Class;
UINT32 LBALOffset;
EFI_LBA Parent;
UINT64 FileSize;
UINT64 FileAttributes;
EFI_TIME FileCreateTime;
EFI_TIME FileModificationTime;
EFI_GUID VendorGuid;
CHAR16 FileString[EFI_FILE_STRING_SIZE];
} EFI_FILE_HEADER;
//
// Return the file's first LBAL which is in the same
// logical block as the file header
//
#define EFI_FILE_LBAL(a) ((EFI_LBAL *) (((CHAR8 *) (a)) + (a)->LBALOffset))
#define EFI_FILE_CLASS_FREE_SPACE 1
#define EFI_FILE_CLASS_EMPTY 2
#define EFI_FILE_CLASS_NORMAL 3
//
// Logical Block Address List - the fundemental block
// description structure
//
#define EFI_LBAL_SIGNATURE 0x4c41424c20494249
#define EFI_LBAL_REVISION 0x00010000
typedef struct _EFI_LBAL {
EFI_TABLE_HEADER Hdr;
UINT32 Class;
EFI_LBA Parent;
EFI_LBA Next;
UINT32 ArraySize;
UINT32 ArrayCount;
} EFI_LBAL;
// Array size
#define EFI_LBAL_ARRAY_SIZE(lbal,offs,blks) \
(((blks) - (offs) - (lbal)->Hdr.HeaderSize) / sizeof(EFI_RL))
//
// Logical Block run-length
//
typedef struct {
EFI_LBA Start;
UINT64 Length;
} EFI_RL;
//
// Return the run-length structure from an LBAL header
//
#define EFI_LBAL_RL(a) ((EFI_RL*) (((CHAR8 *) (a)) + (a)->Hdr.HeaderSize))
#endif

Some files were not shown because too many files have changed in this diff Show More