mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-01 00:38:31 +00:00
Initial import
This commit is contained in:
commit
c91b3c5006
14915 changed files with 590219 additions and 0 deletions
660
ape/ape.lds
Normal file
660
ape/ape.lds
Normal file
|
@ -0,0 +1,660 @@
|
|||
/*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│
|
||||
│vi: set et sts=2 tw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╠──────────────────────────────────────────────────────────────────────────────╣
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█▀█░▀█▀░█░█░█▀█░█░░░█░░░█░█░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█░▄░░█░░█░█░█▀█░█░░░█░░░▀█▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░▀░▀░▀▀▀░░▀░░▀▀▀░▀░▀░▀▀▀░▀▀▀░░▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█▀█░█▀█░▀█▀░█▀█░█▀█░█░░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀▀░█ █░██▀░░█░░█▀█░█▀█░█░░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░▀░░░▀▀▀░▀░▀░░▀░░▀░▀░▀▀▀░▀▀▀░▀▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀▀░█░█░█▀▀░█▀█░█░█░▀█▀░█▀█░█▀█░█░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░▄▄░░░▐█░░│
|
||||
│░░░░░░░█▀▀░▄▀▄░█▀▀░█░▄░█░█░░█░░█▀█░█▀█░█░░█▀▀░░░░░░░░░░░░▄▄▄░░░▄██▄░░█▀░░░█░▄░│
|
||||
│░░░░░░░▀▀▀░▀░▀░▀▀▀░▀▀▀░▀▀▀░░▀░░▀░▀░▀▀▀░▀▀░▀▀▀░░░░░░░░░░▄██▀█▌░██▄▄░░▐█▀▄░▐█▀░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▐█▀▀▌░░░▄▀▌░▌░█░▌░░▌░▌░░│
|
||||
╠──────────────────────────────────────────────────────▌▀▄─▐──▀▄─▐▄─▐▄▐▄─▐▄─▐▄─│
|
||||
│ αcτµαlly pδrταblε εxεcµταblε § linker │
|
||||
╚──────────────────────────────────────────────────────────────────────────────╝
|
||||
Having an executable run natively on stock Windows / Mac / Linux / BSD
|
||||
entails two steps: (1) create a .com.dbg binary w/ Linux toolchain and
|
||||
then (2) unwrap the .com binary embedded within:
|
||||
|
||||
objcopy -SO binary input.com.dbg output.com
|
||||
|
||||
Both executables will work fine, but only the .com format is portable.
|
||||
|
||||
───BUILDING─────────────────────────────────────────────────────────────
|
||||
|
||||
LC_ALL=C ld -T ape/ape.lds ...
|
||||
|
||||
───RUNNING──────────────────────────────────────────────────────────────
|
||||
|
||||
./foo.com.dbg # works on host machine
|
||||
./foo.com # works on any os / arch
|
||||
qemu-system-x86_64 -s foo.com # works on any os / arch
|
||||
|
||||
───BACKGROUND───────────────────────────────────────────────────────────
|
||||
|
||||
The purpose of this software is to help native programs have the same
|
||||
level of consistency, in terms of user experience, that we enjoy with
|
||||
web applications. It's basically like MeteorJS, except primarily CLI,
|
||||
bootable, and more on the order of a few kilobytes than hundred megs.
|
||||
|
||||
Rather than Isomorphic JavaScript it's built using Isomorphic Binary,
|
||||
since it grants the fastest possible performance and can be trivially
|
||||
emulated in the browser. System resource utilization is also a few kb
|
||||
and GUIs are possible too since Cosmopolitan exports the Windows API,
|
||||
but we recommend doing it with a CLI web server instead and embedding
|
||||
files in your αcτµαlly pδrταblε εxεcµταblε as it's isomorphic to zip.
|
||||
|
||||
Isomorphic Binary principles state that most platform differences are
|
||||
just numbers, which we integrate easily into a unified business logic
|
||||
through the use of a sufficiently powerful linker. System numbers are
|
||||
otherwise known as ABIs and they're usually the most stable canonical
|
||||
interfaces that platforms provide. This is how we are able to support
|
||||
more versions of Linux than most Linux-only software, e.g. glibc FTMP
|
||||
|
||||
───DEBUGGING────────────────────────────────────────────────────────────
|
||||
|
||||
Can be done in a few ways:
|
||||
|
||||
gdb --tui foo.com.dbg
|
||||
gdb --tui foo.com -ex 'add-symbol-file foo.com.dbg 0x200000'
|
||||
gdb --tui -ex 'add-symbol-file foo.com.dbg 0x7c00' \
|
||||
-ex 'add-symbol-file foo.com.dbg 0x200000' \
|
||||
-ex -target remote localhost:1234'
|
||||
|
||||
───TRANSPARENCY─────────────────────────────────────────────────────────
|
||||
|
||||
αcτµαlly pδrταblε εxεcµταblε is designed to facilitate maximum
|
||||
transparency to engender trust in this linker process.
|
||||
|
||||
The headers and symbols can be viewed using readelf or objdump:
|
||||
|
||||
readelf -Wa input.com.dbg # maximum transparency
|
||||
objdump -wxd input.com.dbg # maximum transparency
|
||||
|
||||
The disassembly can be viewed using objdump:
|
||||
|
||||
readelf -Wa input.com.dbg # maximum transparency
|
||||
objdump -d input.com.dbg # maximum transparency
|
||||
objdump -dj.text input.com.dbg # skip αpε boilerplate
|
||||
objdump -j.load -dMi8086 input.com.dbg # fixes real mode code
|
||||
|
||||
Some commands for controlling the verbosity of binaries:
|
||||
|
||||
strip -X input.com.dbg # remove ".L" symbols
|
||||
strip input.com.dbg # remove all symbols
|
||||
strip -S input.com.dbg # remove debug info only
|
||||
make CPPFLAGS=-DNDEBUG # remove asserts (prod)
|
||||
make CPPFLAGS=-DIM_FEELING_NAUGHTY # remove legal notices
|
||||
|
||||
The Makefile build is also configured to always produce a .map file
|
||||
when building each program, which provides further details.
|
||||
|
||||
───HACKABILITY──────────────────────────────────────────────────────────
|
||||
|
||||
Your linker and assemblies were designed provide extensibility through
|
||||
the use of link-time data structures we call "decentralized sections".
|
||||
They allow functions like _init() to be comprised of many small pieces
|
||||
defined throughout the codebase. The same applies to ELF / PE headers.
|
||||
|
||||
Extending that content usually entails writing a .S file. The process
|
||||
has more in common with JavaScript programming than contemporary C++
|
||||
development practices. It's the reason Cosmopolitan is able to build
|
||||
the fast tiny multiplatform autonomous binaries that indie developers
|
||||
love using a scalable development model that big businesses respect.
|
||||
|
||||
───SECURITY─────────────────────────────────────────────────────────────
|
||||
|
||||
αcτµαlly pδrταblε εxεcµταblε is designed to be secure in untrustworthy
|
||||
computing environments. Code and data are separated. Data structures
|
||||
initialized at startup are automatically memory protected afterwards.
|
||||
Code intended for platforms you don't use is automatically unmapped
|
||||
too, minimizing any possible chance of impacting your system, while
|
||||
still being there in case you ever need it.
|
||||
|
||||
───CONFIDENTIALITY──────────────────────────────────────────────────────
|
||||
|
||||
αcτµαlly pδrταblε εxεcµταblε is also designed to not leak confidential
|
||||
information by default. Details relating to the host build environment
|
||||
such as system/library versions, user ids, home folder locations, etc.
|
||||
are not taken into consideration at build time since it's hermetic. We
|
||||
can't make speak for debug information, which is why it's put in other
|
||||
files. We also provide the bing and fold programs for auditing binary.
|
||||
|
||||
───DESIGN─DETAILS───────────────────────────────────────────────────────
|
||||
|
||||
αcτµαlly pδrταblε εxεcµταblε is a non-reflective (a.k.a. flat) binary
|
||||
format that includes ELF, PE, and Macho-O headers only to respect the
|
||||
initialization rituals that supported platforms require.
|
||||
|
||||
Binaries are sparse because Intel's six thousand page manual says:
|
||||
|
||||
“Always put code and data on separate pages. [...] If code is
|
||||
to be modified, try to do it all at once and make sure the
|
||||
code that performs the modifications and the code being
|
||||
modified are on separate 4KByte pages or on separate aligned
|
||||
1-KByte subpages. [...] If (hopefully read-only) data must
|
||||
occur on the same page as code, avoid placing it immediately
|
||||
after an indirect jump [...] or inserting an illegal opcode
|
||||
[...] after the indirect branch [which] may degrade perf in
|
||||
some circumstances.” ──Intel V.O §3.6.9
|
||||
|
||||
Support for linking dynamic shared objects is only implemented on
|
||||
Windows NT for the reasons described by Ulrich Drepper in his DSO
|
||||
tutorial. We've implemented this independently of the ld codebase
|
||||
because authentic GNU tooling is powerful enough to generalize to
|
||||
arbitrary formats without needing to add features to its codebase.
|
||||
|
||||
Cosmopolitan core library functions may be converted to the COFF or
|
||||
Mach-O object formats using objconv. That gives you some freedom to
|
||||
choose to use the Microsoft or Apple linker instead of this one. We
|
||||
otherwise can't use those formats, due to how they heavily restrict
|
||||
naming, which basically makes everything we're doing impossible. In
|
||||
the future an authentic GNU toolchain will be made available on the
|
||||
Windows and Apple platforms, using canonical formats and behaviors.
|
||||
Until then, we can build for those platforms using Linux or WSL. */
|
||||
|
||||
#ifdef __LINKER__
|
||||
#include "ape/macros.h"
|
||||
#include "ape/config.h"
|
||||
#include "libc/nt/pedef.h"
|
||||
#include "libc/zip.h"
|
||||
|
||||
ENTRY(_start)
|
||||
|
||||
/* Plans real memory solution at linktime. */
|
||||
MEMORY {
|
||||
PageZero : org = 0x0000000000000000, len = 0x0000000000001000
|
||||
RealBss : org = XLM_BASE_REAL, len = XLM_SIZE
|
||||
RealProgram : org = IMAGE_BASE_REAL, len = 0x0000000000010000 - IMAGE_BASE_REAL
|
||||
RealScratch : org = REAL_SCRATCH_AREA, len = REAL_STACK_FRAME - REAL_SCRATCH_AREA
|
||||
RealStack : org = REAL_STACK_FRAME, len = 0x0000000000010000
|
||||
EbdaMemory : org = 0x0000000000080000, len = 0x0000000000020000
|
||||
VideoMemory : org = 0x00000000000a0000, len = 0x0000000000020000
|
||||
Romz : org = 0x00000000000c0000, len = 0x0000000000030000
|
||||
BiosMemory : org = 0x00000000000f0000, len = 0x0000000000010000
|
||||
SmallCode : org = IMAGE_BASE_PHYSICAL, len = 0x0000000040000000 - IMAGE_BASE_PHYSICAL
|
||||
ZipData : org = 0x0000000040000000, len = 0x0000000040000000
|
||||
}
|
||||
|
||||
PHDRS {
|
||||
Head PT_LOAD FLAGS(5);
|
||||
Rom PT_LOAD FLAGS(5);
|
||||
Ram PT_LOAD FLAGS(6);
|
||||
stack PT_GNU_STACK FLAGS(6);
|
||||
}
|
||||
|
||||
SECTIONS {
|
||||
|
||||
/*BEGIN: realmode addressability guarantee */
|
||||
/*BEGIN: xnu addressability guarantee */
|
||||
/*BEGIN: linux addressability guarantee */
|
||||
/*BEGIN: bsd addressability guarantee */
|
||||
|
||||
.head SEGMENT_START("text-segment", IMAGE_BASE_VIRTUAL) : {
|
||||
HIDDEN(_base = .);
|
||||
|
||||
/* Real Mode */
|
||||
KEEP(*(.head))
|
||||
. += 1;
|
||||
|
||||
/* Executable & Linkable Format */
|
||||
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 1);
|
||||
KEEP(*(.elf.phdrs))
|
||||
HIDDEN(.Lape.phdrs.end = .);
|
||||
. += 1;
|
||||
|
||||
/* OpenBSD */
|
||||
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 1);
|
||||
HIDDEN(.Lape.note = .);
|
||||
KEEP(*(.note.openbsd.ident))
|
||||
HIDDEN(.Lape.note.end = .);
|
||||
. += 1;
|
||||
|
||||
/* Portable Executable */
|
||||
KEEP(*(.pe.header))
|
||||
HIDDEN(.Lape.pe.sections = .);
|
||||
KEEP(*(.pe.sections))
|
||||
HIDDEN(.Lape.pe.sections_end = .);
|
||||
. += 1;
|
||||
|
||||
/* Mach-O */
|
||||
KEEP(*(.macho))
|
||||
. = ALIGN(__SIZEOF_POINTER__);
|
||||
HIDDEN(.Lape.macho.end = .);
|
||||
. += 1;
|
||||
|
||||
KEEP(*(.ape.pad.head))
|
||||
. = ALIGN(4096); /* alignments only mandatory when impossible otherwise */
|
||||
HIDDEN(_ehead = .);
|
||||
} AT>SmallCode :Head
|
||||
|
||||
/*BEGIN: nt addressability guarantee */
|
||||
|
||||
.text . : {
|
||||
/* Code that needs to be addressable in Real Mode */
|
||||
*(.text.real)
|
||||
KEEP(*(SORT_BY_NAME(.sort.text.real.*)))
|
||||
*(.rodata.real)
|
||||
KEEP(*(SORT_BY_NAME(.sort.rodata.real.*)))
|
||||
HIDDEN(_ereal = .);
|
||||
|
||||
/*END: realmode addressability guarantee */
|
||||
|
||||
/* Normal Code */
|
||||
*(.start)
|
||||
KEEP(*(.initprologue))
|
||||
KEEP(*(SORT_BY_NAME(.init.*)))
|
||||
KEEP(*(SORT_NONE(.init)))
|
||||
KEEP(*(.initepilogue))
|
||||
KEEP(*(.pltprologue))
|
||||
*(.plt)
|
||||
KEEP(*(.pltepilogue))
|
||||
KEEP(*(.pltgotprologue))
|
||||
*(.plt.got)
|
||||
KEEP(*(.pltgotepilogue))
|
||||
*(.text.startup .text.startup.*)
|
||||
*(.text.exit .text.exit.*)
|
||||
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
|
||||
*(SORT_BY_ALIGNMENT(.text.antiquity))
|
||||
*(SORT_BY_ALIGNMENT(.text.antiquity.*))
|
||||
KEEP(*(.textwindowsprologue))
|
||||
*(.text.windows)
|
||||
KEEP(*(.textwindowsepilogue))
|
||||
*(SORT_BY_ALIGNMENT(.text.modernity))
|
||||
*(SORT_BY_ALIGNMENT(.text.modernity.*))
|
||||
*(SORT_BY_ALIGNMENT(.text.hot))
|
||||
*(SORT_BY_ALIGNMENT(.text.hot.*))
|
||||
KEEP(*(.keep.text))
|
||||
*(.text .stub .text.*)
|
||||
KEEP(*(SORT_BY_NAME(.sort.text.*)))
|
||||
|
||||
/* Won't support NX bit DRM for tiny executables */
|
||||
HIDDEN(.Lape.piro.align = ABSOLUTE(. > APE_PIRO_THRESHOLD ? 0x1000 : 8));
|
||||
|
||||
/* Code that musn't be mapped in production */
|
||||
KEEP(*(.ape.pad.test));
|
||||
. = ALIGN(.Lape.piro.align);
|
||||
HIDDEN(__test_start = .);
|
||||
*(.test.unlikely)
|
||||
*(.test .test.*)
|
||||
|
||||
/* Privileged code invulnerable to magic */
|
||||
KEEP(*(.ape.pad.privileged));
|
||||
. = ALIGN(.Lape.piro.align);
|
||||
HIDDEN(__privileged_start = .);
|
||||
HIDDEN(__test_end = .);
|
||||
. += 1;
|
||||
*(.privileged)
|
||||
|
||||
/*BEGIN: Read Only Data */
|
||||
|
||||
KEEP(*(.ape.pad.rodata));
|
||||
. = ALIGN(.Lape.piro.align);
|
||||
. += 1;
|
||||
|
||||
/* Nonspecific Read-Only Data */
|
||||
*(.rodata .rodata.*)
|
||||
. += 1;
|
||||
|
||||
/* Undefined Behavior Sanitizer Types */
|
||||
HIDDEN(__ubsan_types_start = .);
|
||||
*(.ubsan.types)
|
||||
HIDDEN(__ubsan_types_end = .);
|
||||
. += 1;
|
||||
|
||||
/* Undefined Behavior Sanitizer Data */
|
||||
HIDDEN(__ubsan_data_start = .);
|
||||
*(.ubsan.data)
|
||||
HIDDEN(__ubsan_data_end = .);
|
||||
|
||||
/* Unit Test & Fixture Registry */
|
||||
|
||||
/*BEGIN: Read only data that needn't be mapped after initialization */
|
||||
|
||||
/* Legal Notices */
|
||||
KEEP(*(.commentprologue))
|
||||
KEEP(*(.comment))
|
||||
KEEP(*(.commentepilogue))
|
||||
|
||||
/* Windows DLL Import Directory */
|
||||
KEEP(*(.idata.ro));
|
||||
KEEP(*(SORT_BY_NAME(.idata.ro.*)))
|
||||
. += 1;
|
||||
|
||||
/* Encoded Data Structures w/ Linear Initialization Order */
|
||||
KEEP(*(.initroprologue))
|
||||
KEEP(*(SORT_BY_NAME(.initro.*)))
|
||||
KEEP(*(.initroepilogue))
|
||||
KEEP(*(SORT_BY_NAME(.sort.rodata.*)))
|
||||
|
||||
KEEP(*(.ape.pad.text))
|
||||
HIDDEN(.Lape.data.align = ABSOLUTE(PAGESIZE));
|
||||
. = ALIGN(.Lape.data.align);
|
||||
HIDDEN(_etext = .);
|
||||
PROVIDE_HIDDEN(etext = .);
|
||||
/*END: Read Only Data (only needed for initialization) */
|
||||
/*END: Read Only Data */
|
||||
} AT>SmallCode :Rom
|
||||
|
||||
.data . : {
|
||||
/*BEGIN: Read/Write Data */
|
||||
KEEP(*(.dataprologue))
|
||||
*(.data .data.*)
|
||||
KEEP(*(SORT_BY_NAME(.sort.data.*)))
|
||||
. += . > 0 ? 1 : 0;
|
||||
|
||||
KEEP(*(.gotprologue))
|
||||
*(.got)
|
||||
KEEP(*(.gotepilogue))
|
||||
|
||||
KEEP(*(.gotpltprologue))
|
||||
*(.got.plt)
|
||||
KEEP(*(.gotpltepilogue))
|
||||
|
||||
/*BEGIN: Post-Initialization Read-Only */
|
||||
. = ALIGN(.Lape.piro.align);
|
||||
HIDDEN(__piro_start = .);
|
||||
|
||||
QUAD(IMAGE_BASE_VIRTUAL);
|
||||
|
||||
PROVIDE_HIDDEN(__init_array_start = .);
|
||||
KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*)
|
||||
SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||
KEEP(*(SORT_NONE(.ctors)))
|
||||
KEEP(*(SORT_NONE(.init_array)))
|
||||
KEEP(*(SORT_NONE(.preinit_array)))
|
||||
PROVIDE_HIDDEN(__init_array_end = .);
|
||||
|
||||
. += 1;
|
||||
. = ALIGN(__SIZEOF_POINTER__);
|
||||
PROVIDE_HIDDEN(__fini_array_start = .);
|
||||
KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*)
|
||||
SORT_BY_INIT_PRIORITY(.dtors.*)))
|
||||
KEEP(*(SORT_NONE(.dtors)))
|
||||
PROVIDE_HIDDEN(__fini_array_end = .);
|
||||
|
||||
KEEP(*(SORT_BY_NAME(.piro.relo.sort.*)))
|
||||
PROVIDE_HIDDEN(__relo_end = .);
|
||||
KEEP(*(SORT_BY_NAME(.piro.data.sort.*)))
|
||||
KEEP(*(.piro.pad.data))
|
||||
. = ALIGN(.Lape.data.align);
|
||||
HIDDEN(_edata = .);
|
||||
PROVIDE_HIDDEN(edata = .);
|
||||
} AT>SmallCode :Ram
|
||||
|
||||
.bss . : {
|
||||
KEEP(*(SORT_BY_NAME(.piro.bss.init.*)))
|
||||
*(.piro.bss)
|
||||
KEEP(*(SORT_BY_NAME(.piro.bss.sort.*)))
|
||||
. += 1;
|
||||
. = ALIGN(.Lape.piro.align);
|
||||
HIDDEN(__piro_end = .);
|
||||
/*END: Post-Initialization Read-Only */
|
||||
|
||||
/* Statically Allocated Empty Space */
|
||||
*(SORT_BY_ALIGNMENT(.bss))
|
||||
*(SORT_BY_ALIGNMENT(.bss.*))
|
||||
*(COMMON)
|
||||
|
||||
KEEP(*(SORT_BY_NAME(.sort.bss.*)))
|
||||
|
||||
/* eXtreme Low Memory w/ Userspace Remapping */
|
||||
. = ALIGN(0x1000);
|
||||
*(.xlm)
|
||||
. = ALIGN(0x1000);
|
||||
|
||||
HIDDEN(_end = .);
|
||||
PROVIDE_HIDDEN(end = .);
|
||||
} AT>SmallCode :Ram
|
||||
|
||||
/*END: nt addressability guarantee */
|
||||
/*END: bsd addressability guarantee */
|
||||
/*END: linux addressability guarantee */
|
||||
/*END: xnu addressability guarantee */
|
||||
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
.stab.excl 0 : { *(.stab.excl) }
|
||||
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||
.stab.index 0 : { *(.stab.index) }
|
||||
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||
.comment 0 : { *(.comment) }
|
||||
.debug 0 : { *(.debug) }
|
||||
.line 0 : { *(.line) }
|
||||
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||
.debug_aranges 0 : { *(.debug_aranges) }
|
||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
|
||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) }
|
||||
.debug_frame 0 : { *(.debug_frame) }
|
||||
.debug_str 0 : { *(.debug_str) }
|
||||
.debug_loc 0 : { *(.debug_loc) }
|
||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||
.debug_typenames 0 : { *(.debug_typenames) }
|
||||
.debug_varnames 0 : { *(.debug_varnames) }
|
||||
.debug_pubtypes 0 : { *(.debug_pubtypes) }
|
||||
.debug_ranges 0 : { *(.debug_ranges) }
|
||||
.debug_macro 0 : { *(.debug_macro) }
|
||||
.debug_addr 0 : { *(.debug_addr) }
|
||||
.gnu.attributes 0 : { KEEP(*(.gnu.attributes)) }
|
||||
.GCC.command.line 0 : { *(.GCC.command.line) }
|
||||
|
||||
/DISCARD/ : {
|
||||
*(.discard)
|
||||
*(.yoink)
|
||||
*(.*)
|
||||
}
|
||||
}
|
||||
|
||||
PFSTUB8(.Lape.elf.entry, _start);
|
||||
PFSTUB8(.Lape.elf.phoff, RVA(ape.phdrs));
|
||||
PFSTUB8(.Lape.elf.shoff, 0);
|
||||
PFSTUB4(.Lape.elf.phnum, (.Lape.phdrs.end - ape.phdrs) / 56);
|
||||
PFSTUB4(.Lape.elf.shnum, 0);
|
||||
PFSTUB4(.Lape.elf.shstrndx, 0);
|
||||
SHSTUB2(.Lape.macho.dd.skip, RVA(ape.macho) / 8);
|
||||
SHSTUB2(.Lape.macho.dd.count, (.Lape.macho.end - ape.macho) / 8);
|
||||
PFSTUB4(.Lape.pe.offset, ape.pe - ape.mz);
|
||||
|
||||
HIDDEN(.Lape.pe.optsz = .Lape.pe.sections - (ape.pe + 24));
|
||||
HIDDEN(.Lape.pe.shnum = (.Lape.pe.sections_end - .Lape.pe.sections) / 40);
|
||||
HIDDEN(.Lidata.idtsize = idata.idtend - idata.idt);
|
||||
HIDDEN(.Lidata.iatsize = idata.iatend - idata.iat);
|
||||
|
||||
HIDDEN(.Lape.rom.offset = 0);
|
||||
HIDDEN(.Lape.rom.vaddr = ADDR(.head));
|
||||
HIDDEN(.Lape.rom.paddr = LOADADDR(.head));
|
||||
HIDDEN(.Lape.rom.filesz = LOADADDR(.data) - .Lape.rom.paddr);
|
||||
HIDDEN(.Lape.rom.memsz = ADDR(.data) - ADDR(.head));
|
||||
HIDDEN(.Lape.rom.align = 0x1000);
|
||||
HIDDEN(.Lape.rom.rva = RVA(.Lape.rom.vaddr));
|
||||
|
||||
HIDDEN(.Lape.ram.offset = .Lape.rom.offset + .Lape.rom.filesz);
|
||||
HIDDEN(.Lape.ram.vaddr = ADDR(.data));
|
||||
HIDDEN(.Lape.ram.paddr = LOADADDR(.data));
|
||||
HIDDEN(.Lape.ram.filesz = LOADADDR(.bss) - LOADADDR(.data));
|
||||
HIDDEN(.Lape.ram.memsz = ADDR(.bss) + SIZEOF(.bss) - .Lape.ram.vaddr);
|
||||
HIDDEN(.Lape.ram.align = 0x1000);
|
||||
HIDDEN(.Lape.ram.rva = RVA(.Lape.ram.vaddr));
|
||||
|
||||
HIDDEN(.Lape.note.offset = .Lape.rom.offset + (.Lape.note - .Lape.rom.vaddr));
|
||||
HIDDEN(.Lape.note.vaddr = .Lape.note);
|
||||
HIDDEN(.Lape.note.paddr = .Lape.rom.paddr + .Lape.note.offset);
|
||||
HIDDEN(.Lape.note.filesz = .Lape.note.end - .Lape.note);
|
||||
HIDDEN(.Lape.note.memsz = .Lape.note.filesz);
|
||||
HIDDEN(.Lape.note.align = __SIZEOF_POINTER__);
|
||||
|
||||
HIDDEN(.Lape.text.offset = .Lape.rom.offset + LOADADDR(.text) - .Lape.rom.paddr);
|
||||
HIDDEN(.Lape.text.paddr = LOADADDR(.text));
|
||||
HIDDEN(.Lape.text.vaddr = ADDR(.text));
|
||||
HIDDEN(.Lape.text.filesz = SIZEOF(.text));
|
||||
HIDDEN(.Lape.text.memsz = SIZEOF(.text));
|
||||
HIDDEN(.Lape.text.align = 4096);
|
||||
HIDDEN(.Lape.text.rva = RVA(.Lape.text.vaddr));
|
||||
|
||||
HIDDEN(.Lape.data.offset = .Lape.ram.offset + LOADADDR(.data) - .Lape.ram.paddr);
|
||||
HIDDEN(.Lape.data.paddr = LOADADDR(.data));
|
||||
HIDDEN(.Lape.data.vaddr = ADDR(.data));
|
||||
HIDDEN(.Lape.data.filesz = SIZEOF(.data));
|
||||
HIDDEN(.Lape.data.memsz = SIZEOF(.data));
|
||||
HIDDEN(.Lape.data.align = 0x1000);
|
||||
HIDDEN(.Lape.data.rva = RVA(.Lape.data.vaddr));
|
||||
|
||||
HIDDEN(.Lape.bss.offset = .Lape.ram.offset + LOADADDR(.bss) - .Lape.ram.paddr);
|
||||
HIDDEN(.Lape.bss.paddr = LOADADDR(.bss));
|
||||
HIDDEN(.Lape.bss.vaddr = ADDR(.bss));
|
||||
HIDDEN(.Lape.bss.filesz = 0);
|
||||
HIDDEN(.Lape.bss.memsz = SIZEOF(.bss));
|
||||
HIDDEN(.Lape.bss.align = .Lape.data.align);
|
||||
|
||||
/* Program Loader Auto-Tune */
|
||||
HIDDEN(v_ape_realsectors =
|
||||
MIN(REAL_SCRATCH_AREA - IMAGE_BASE_REAL,
|
||||
ROUNDUP(RVA(_edata), 512)) / 512);
|
||||
HIDDEN(v_ape_highsectors =
|
||||
(ROUNDUP(RVA(_edata), 512) / 512) - v_ape_realsectors);
|
||||
|
||||
/* Windows NT Auto-Subsystem Embedding */
|
||||
HIDDEN(v_ntsubsystem = (DEFINED(GetMessage)
|
||||
? kNtImageSubsystemWindowsGui
|
||||
: kNtImageSubsystemWindowsCui));
|
||||
|
||||
/* ZIP End of Central Directory header */
|
||||
#define ZIPCONST(NAME, VAL) HIDDEN(NAME = DEFINED(__zip_start) ? VAL : 0);
|
||||
ZIPCONST(v_zip_cdoffset, __zip_start - IMAGE_BASE_VIRTUAL);
|
||||
ZIPCONST(v_zip_cdirsize, __zip_end - __zip_start);
|
||||
ZIPCONST(v_zip_records, v_zip_cdirsize / kZipCdirHdrLinkableSize);
|
||||
ZIPCONST(v_zip_commentsize, _edata - __zip_end - kZipCdirHdrMinSize);
|
||||
|
||||
/* Generates deterministic ID for Mach-O. */
|
||||
#define PHI 0x9e3779b9925d4c17
|
||||
#define XOR(X,Y) ((X | Y) - (X & Y))
|
||||
#define XORSHIFT(X,Y) \
|
||||
X = XOR(X, (Y >> 12)); \
|
||||
X = XOR(X, (Y << 25)); \
|
||||
X = XOR(X, (Y >> 27))
|
||||
#define KMH(X,Y) \
|
||||
X = (X + (Y >> 000) & 0xFF) * PHI; \
|
||||
X = (X + (Y >> 010) & 0xFF) * PHI; \
|
||||
X = (X + (Y >> 020) & 0xFF) * PHI; \
|
||||
X = (X + (Y >> 030) & 0xFF) * PHI
|
||||
#define BOOP(X) \
|
||||
XORSHIFT(uuid1_, X); \
|
||||
KMH(uuid1_, X); \
|
||||
XORSHIFT(uuid2_, X); \
|
||||
KMH(uuid2_, X)
|
||||
|
||||
HIDDEN(uuid1_ = 88172645463325252);
|
||||
HIDDEN(uuid2_ = 88172645463325252);
|
||||
|
||||
BOOP(.Lape.bss.align);
|
||||
BOOP(.Lape.bss.filesz);
|
||||
BOOP(.Lape.bss.memsz);
|
||||
BOOP(.Lape.bss.offset);
|
||||
BOOP(.Lape.bss.paddr);
|
||||
BOOP(.Lape.data.align);
|
||||
BOOP(.Lape.data.filesz);
|
||||
BOOP(.Lape.data.memsz);
|
||||
BOOP(.Lape.data.offset);
|
||||
BOOP(.Lape.data.paddr);
|
||||
BOOP(.Lape.data.rva);
|
||||
BOOP(.Lape.data.vaddr);
|
||||
BOOP(.Lape.elf.entry);
|
||||
BOOP(.Lape.elf.phnum);
|
||||
BOOP(.Lape.elf.phoff);
|
||||
BOOP(.Lape.elf.shnum);
|
||||
BOOP(.Lape.elf.shoff);
|
||||
BOOP(.Lape.elf.shstrndx);
|
||||
BOOP(.Lape.macho.end);
|
||||
BOOP(.Lape.note);
|
||||
BOOP(.Lape.note.align);
|
||||
BOOP(.Lape.note.end);
|
||||
BOOP(.Lape.note.filesz);
|
||||
BOOP(.Lape.note.memsz);
|
||||
BOOP(.Lape.note.offset);
|
||||
BOOP(.Lape.note.paddr);
|
||||
BOOP(.Lape.note.vaddr);
|
||||
BOOP(.Lape.pe.offset);
|
||||
BOOP(.Lape.pe.optsz);
|
||||
BOOP(.Lape.pe.sections);
|
||||
BOOP(.Lape.pe.sections_end);
|
||||
BOOP(.Lape.pe.shnum);
|
||||
BOOP(.Lape.phdrs.end);
|
||||
BOOP(.Lape.ram.align);
|
||||
BOOP(.Lape.ram.filesz);
|
||||
BOOP(.Lape.ram.memsz);
|
||||
BOOP(.Lape.ram.offset);
|
||||
BOOP(.Lape.ram.paddr);
|
||||
BOOP(.Lape.ram.rva);
|
||||
BOOP(.Lape.ram.vaddr);
|
||||
BOOP(.Lape.rom.align);
|
||||
BOOP(.Lape.rom.filesz);
|
||||
BOOP(.Lape.rom.memsz);
|
||||
BOOP(.Lape.rom.offset);
|
||||
BOOP(.Lape.rom.paddr);
|
||||
BOOP(.Lape.rom.rva);
|
||||
BOOP(.Lape.rom.vaddr);
|
||||
BOOP(.Lape.text.align);
|
||||
BOOP(.Lape.text.filesz);
|
||||
BOOP(.Lape.text.memsz);
|
||||
BOOP(.Lape.text.offset);
|
||||
BOOP(.Lape.text.paddr);
|
||||
BOOP(.Lape.text.rva);
|
||||
BOOP(.Lape.text.vaddr);
|
||||
BOOP(ADDR(.bss));
|
||||
BOOP(WinMain);
|
||||
BOOP(_start);
|
||||
BOOP(ape.macho);
|
||||
BOOP(ape.mz);
|
||||
BOOP(ape.pe);
|
||||
BOOP(ape.phdrs);
|
||||
BOOP(v_ape_realsectors);
|
||||
|
||||
ASSERT(ape.mz == IMAGE_BASE_VIRTUAL, "linker panic");
|
||||
ASSERT((DEFINED(__init_bss_end) ? __init_bss_end : 0) % __SIZEOF_POINTER__ == 0,
|
||||
"__init_bss misalign");
|
||||
ASSERT(((DEFINED(__init_rodata_end) ? __init_rodata_end : 0) %
|
||||
__SIZEOF_POINTER__ == 0),
|
||||
"__init_rodata misalign");
|
||||
|
||||
ASSERT((!DEFINED(ape.grub) ? 1 : RVA(ape.grub) < 8192),
|
||||
"grub stub needs to be in first 8kb of image");
|
||||
|
||||
ASSERT(DEFINED(_start) || DEFINED(_start16),
|
||||
"please link a _start() or _start16() entrypoint");
|
||||
|
||||
ASSERT(!DEFINED(_start16) || REAL(_end) < 65536,
|
||||
"ape won't support non-tiny real mode programs");
|
||||
|
||||
/* Let's not be like Knight Capital. */
|
||||
/* NOCROSSREFS_TO(.test .text) */
|
||||
|
||||
/* ASSERT(ape_sysv_start == .Lape.text.vaddr, */
|
||||
/* "ape_sysv_start() must be first in .text"); */
|
||||
|
||||
#endif /* __LINKER__ */
|
57
ape/ape.mk
Normal file
57
ape/ape.mk
Normal file
|
@ -0,0 +1,57 @@
|
|||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||
#
|
||||
# OVERVIEW
|
||||
#
|
||||
# αcτµαlly pδrταblε εxεcµταblε
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# This file defines the libraries, runtimes, and build rules needed to
|
||||
# create executables from your Linux workstation that'll run anywhere.
|
||||
# Loading this package will make certain systemic modifications to the
|
||||
# build like turning off the System V "Red Zone" optimization, because
|
||||
# αcτµαlly pδrταblε εxεcµταblεs need to be able to run in kernelspace.
|
||||
|
||||
PKGS += APE
|
||||
|
||||
DEFAULT_COPTS += -mno-red-zone
|
||||
DEFAULT_LDFLAGS += -z max-page-size=0x1000
|
||||
|
||||
APELINK = ACTION=LINK.ape $(LINK) $(LINKARGS) $(OUTPUT_OPTION) && $(STRIP) -X $@ && $(GZ) $(ZFLAGS) -f $@.map
|
||||
|
||||
APE = $(APE_DEPS) \
|
||||
$(APE_OBJS) \
|
||||
o/$(MODE)/ape/ape.lds
|
||||
|
||||
APE_FILES := \
|
||||
$(wildcard ape/*.*)
|
||||
|
||||
APE_HDRS = \
|
||||
$(filter %.h,$(APE_FILES))
|
||||
|
||||
APE_SRCS = \
|
||||
$(filter %.S,$(APE_FILES))
|
||||
|
||||
APE_OBJS = \
|
||||
$(APE_SRCS:%=o/$(MODE)/%.zip.o) \
|
||||
$(APE_SRCS:%.S=o/$(MODE)/%.o)
|
||||
|
||||
APE_DEPS = \
|
||||
$(APE_LIB)
|
||||
|
||||
APE_CHECKS = \
|
||||
$(APE_HDRS:%=o/%.ok)
|
||||
|
||||
o/%.com: o/%.com.dbg
|
||||
@ACTION=OBJCOPY.ape TARGET=$@ build/do $(OBJCOPY) -SO binary $< $@
|
||||
|
||||
o/ape/idata.inc: ape/idata.h ape/relocations.h
|
||||
|
||||
$(APE_OBJS): $(BUILD_FILES) \
|
||||
ape/ape.mk
|
||||
|
||||
.PHONY: o/$(MODE)/ape
|
||||
o/$(MODE)/ape: $(APE) \
|
||||
$(APE_CHECKS) \
|
||||
o/$(MODE)/ape/lib
|
137
ape/config.h
Normal file
137
ape/config.h
Normal file
|
@ -0,0 +1,137 @@
|
|||
#ifndef APE_CONFIG_H_
|
||||
#define APE_CONFIG_H_
|
||||
#include "ape/relocations.h"
|
||||
#include "libc/macros.h"
|
||||
|
||||
/**
|
||||
* @fileverview αcτµαlly pδrταblε εxεcµταblε configuration.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Post-Initialization Read-Only Code Size Threshold.
|
||||
*
|
||||
* An executable needs to have at least this much code, before the
|
||||
* linker adds non-mandatory 4kb alignments. The benefit is better
|
||||
* memory protection. The tradeoff is sparser binaries.
|
||||
*/
|
||||
#ifndef APE_PIRO_THRESHOLD
|
||||
#ifdef CONFIG_DBG
|
||||
#define APE_PIRO_THRESHOLD 0x1000
|
||||
#else
|
||||
#define APE_PIRO_THRESHOLD 0x10000
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* PC Standard I/O Configuration.
|
||||
*/
|
||||
#ifndef METAL_STDIN
|
||||
#define METAL_STDIN COM1
|
||||
#endif
|
||||
#ifndef METAL_STDOUT
|
||||
#define METAL_STDOUT COM1
|
||||
#endif
|
||||
#ifndef METAL_STDERR
|
||||
#define METAL_STDERR COM2 /* will fallback to stdout if COM2 not present */
|
||||
#endif
|
||||
|
||||
/**
|
||||
* PC Display Configuration (MDA/CGA)
|
||||
* @see www.lammertbies.nl/comm/info/serial-uart.html
|
||||
* @see ape/lib/vidya.h
|
||||
*/
|
||||
#ifndef VIDYA_MODE
|
||||
#define VIDYA_MODE VIDYA_MODE_MDA
|
||||
#endif
|
||||
|
||||
/* FPU Control Word (x87) Exception Masks
|
||||
@see Intel Manual V1 §8.1.5
|
||||
|
||||
IM: Invalid Operation ───────────────┐
|
||||
DM: Denormal Operand ───────────────┐│
|
||||
ZM: Zero Divide ───────────────────┐││
|
||||
OM: Overflow ─────────────────────┐│││
|
||||
UM: Underflow ───────────────────┐││││
|
||||
PM: Precision ──────────────────┐│││││
|
||||
PC: Precision Control ────────┐ ││││││
|
||||
{float,∅,double,long double} │ ││││││
|
||||
RC: Rounding Control ───────┐ │ ││││││
|
||||
{even, →-∞, →+∞, →0} │┌┤ ││││││
|
||||
┌┤││ ││││││
|
||||
d││││rr││││││*/
|
||||
#define X87_NORMAL 0b000000000001101111111
|
||||
#define X87_DTOA 0b000000000001000000000
|
||||
#define X87_DTOA_MASK 0b000000000001100000000
|
||||
#ifndef X87_DEFAULT
|
||||
#define X87_DEFAULT X87_NORMAL
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Serial Line Configuration (8250 UART 16550)
|
||||
* @see ape/lib/uart.h
|
||||
*/
|
||||
#ifndef UART_BAUD_RATE
|
||||
#define UART_BAUD_RATE 9600 /* bits per second ∈ [50,115200] */
|
||||
#endif
|
||||
#define UART_CONF_DLR (1843200 /*hz*/ / 16 /*wut*/ / (UART_BAUD_RATE))
|
||||
#ifndef UART_CONF_IIR
|
||||
/* ┌interrupt trigger level {1,4,8,14}
|
||||
│ ┌enable 64 byte fifo (UART 16750+)
|
||||
│ │ ┌select dma mode
|
||||
│ │ │┌clear transmit fifo
|
||||
│ │ ││┌clear receive fifo
|
||||
├┐│ │││┌enable fifos*/
|
||||
#define UART_CONF_IIR 0b00000000
|
||||
#endif
|
||||
#ifndef UART_CONF_LCR
|
||||
/* ┌dlab: flips configuration mode state
|
||||
│┌enable break signal
|
||||
││ ┌parity {none,odd,even,high,low}
|
||||
││ │ ┌extra stop bit
|
||||
││ │ │┌data word length (bits+5)
|
||||
││┌┴┐│├┐*/
|
||||
#define UART_CONF_LCR 0b01000011
|
||||
#endif
|
||||
|
||||
/**
|
||||
* eXtreme Low Memory.
|
||||
*/
|
||||
#define XLM(VAR) (XLM_BASE_REAL + XLM_##VAR)
|
||||
#define XLMV(VAR) (__xlm + XLM_##VAR)
|
||||
#define XLM_BASE_REAL 0x1000
|
||||
#define XLM_E820 0
|
||||
#define XLM_E820_SIZE 0x2000
|
||||
#define XLM_BIOS_DATA_AREA 0x2000
|
||||
#define XLM_BIOS_DATA_AREA_SIZE 256
|
||||
#define XLM_DRIVE_BASE_TABLE 0x2200 /* drive values are contiguous */
|
||||
#define XLM_DRIVE_BASE_TABLE_SIZE 11
|
||||
#define XLM_DRIVE_TYPE 0x220b
|
||||
#define XLM_DRIVE_TYPE_SIZE 1
|
||||
#define XLM_DRIVE_LAST_SECTOR 0x220c /* 1-based inclusive, e.g. 18 */
|
||||
#define XLM_DRIVE_LAST_SECTOR_SIZE 1
|
||||
#define XLM_DRIVE_LAST_CYLINDER 0x220d /* 0-based incl, e.g. 79 */
|
||||
#define XLM_DRIVE_LAST_CYLINDER_SIZE 2
|
||||
#define XLM_DRIVE_ATTACHED 0x220f
|
||||
#define XLM_DRIVE_ATTACHED_SIZE 1
|
||||
#define XLM_DRIVE_LAST_HEAD 0x2210 /* 0-based inclusive, e.g. 1 */
|
||||
#define XLM_DRIVE_LAST_HEAD_SIZE 1
|
||||
#define XLM_DRIVE 0x2211
|
||||
#define XLM_DRIVE_SIZE 1
|
||||
#define XLM_HAVEEXTMEMKB 0x2212
|
||||
#define XLM_HAVEEXTMEMKB_SIZE 4
|
||||
#define XLM_VIDEO_POSITION_FAR_POINTER 0x2216 /* video cursor far pointer */
|
||||
#define XLM_VIDEO_POSITION_FAR_POINTER_SIZE 4
|
||||
#define XLM_PAGE_TABLE_STACK_POINTER 0x2220
|
||||
#define XLM_PAGE_TABLE_STACK_POINTER_SIZE 8
|
||||
#define XLM_BADIDT 0x2230
|
||||
#define XLM_BADIDT_SIZE 6
|
||||
#define XLM_LOADSTATE 0x2240
|
||||
#define XLM_LOADSTATE_SIZE 4
|
||||
#define XLM_SIZE ROUNDUP(XLM_LOADSTATE + XLM_LOADSTATE_SIZE, 0x1000)
|
||||
#define IMAGE_BASE_REAL (XLM_BASE_REAL + XLM_SIZE)
|
||||
|
||||
#if !defined(__LINKER__) && !defined(__ASSEMBLER__)
|
||||
extern char __xlm[XLM_SIZE];
|
||||
#endif /* !defined(__LINKER__) && !defined(__ASSEMBLER__) */
|
||||
|
||||
#endif /* APE_CONFIG_H_ */
|
1279
ape/etc/bochsrc.dbg
Normal file
1279
ape/etc/bochsrc.dbg
Normal file
File diff suppressed because it is too large
Load diff
1294
ape/etc/bochsrc.ffs
Normal file
1294
ape/etc/bochsrc.ffs
Normal file
File diff suppressed because it is too large
Load diff
119
ape/idata.h
Normal file
119
ape/idata.h
Normal file
|
@ -0,0 +1,119 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#ifndef APE_IDATA_H_
|
||||
#define APE_IDATA_H_
|
||||
#ifdef __ASSEMBLER__
|
||||
#include "ape/relocations.h"
|
||||
/* clang-format off */
|
||||
|
||||
/ Links function from external DLL.
|
||||
/
|
||||
/ This embeds a function pointer in the binary. The NT Executive
|
||||
/ fills its value before control is handed off to the program.
|
||||
/
|
||||
/ @note only ELF toolchains are powerful enough to use this
|
||||
/ @see libc/nt/master.sh
|
||||
/ @see ape/ape.lds
|
||||
/ @see winimp
|
||||
.macro .imp dll:req fn:req actual hint
|
||||
.dll \dll
|
||||
.section .piro.data.sort.iat.2.\dll\().2.\fn,"aw",@progbits
|
||||
.type \fn,@object
|
||||
.align __SIZEOF_POINTER__
|
||||
\fn: .quad RVA((.L\dll\().\fn))
|
||||
.size \fn,.-\fn
|
||||
.globl \fn
|
||||
.hidden \fn
|
||||
.previous
|
||||
.section .idata.ro.ilt.\dll\().2.\fn,"a",@progbits
|
||||
.Lidata.ilt.\dll\().\fn:
|
||||
.quad RVA((.L\dll\().\fn))
|
||||
.type .Lidata.ilt..L\dll\().\fn,@object
|
||||
.size .Lidata.ilt..L\dll\().\fn,.-.Lidata.ilt.\dll\().\fn
|
||||
.previous
|
||||
.section .idata.ro.hnt.\dll\().2.\fn,"a",@progbits
|
||||
.L\dll\().\fn:
|
||||
.ifnb \hint # hint i.e. guess function ordinal
|
||||
.short \hint
|
||||
.else
|
||||
.short 0
|
||||
.endif
|
||||
.ifnb \actual # name
|
||||
.asciz "\actual"
|
||||
.else
|
||||
.asciz "\fn"
|
||||
.endif
|
||||
.align 2 # documented requirement
|
||||
/ .globl .L\dll\().\fn
|
||||
/ .hidden .L\dll\().\fn
|
||||
.type .L\dll\().\fn,@object
|
||||
.size .L\dll\().\fn,.-.L\dll\().\fn
|
||||
.previous
|
||||
.endm
|
||||
|
||||
/ Defines DLL import.
|
||||
/ @note this is an implementation detail of .imp
|
||||
.macro .dll name:req
|
||||
.section .idata.ro.idt.2.\name,"aG",\name,comdat
|
||||
.equ .Lidata.idt.\name,.
|
||||
.long RVA(idata.ilt.\name) # ImportLookupTable
|
||||
.long 0 # TimeDateStamp
|
||||
.long 0 # ForwarderChain
|
||||
.long RVA(.Lidata.str.\name) # DllNameRva
|
||||
.long RVA(idata.iat.\name) # ImportAddressTable
|
||||
.type .Lidata.idt.\name,@object
|
||||
.size .Lidata.idt.\name,.-.Lidata.idt.\name
|
||||
.previous
|
||||
.section .idata.ro.ilt.\name\().1,"aG",\name,comdat
|
||||
.align __SIZEOF_POINTER__
|
||||
.type idata.ilt.\name,@object
|
||||
idata.ilt.\name:
|
||||
.previous/*
|
||||
...
|
||||
decentralized content
|
||||
...
|
||||
*/.section .idata.ro.ilt.\name\().3,"aG",\name,comdat
|
||||
.quad 0
|
||||
.previous
|
||||
.section .idata.ro.hnt.\name\().1,"aG",\name,comdat
|
||||
.align __SIZEOF_POINTER__
|
||||
.type idata.hnt.\name,@object
|
||||
.equ idata.hnt.\name,.
|
||||
.previous
|
||||
.section .piro.data.sort.iat.2.\name\().1,"awG",\name,comdat
|
||||
.align __SIZEOF_POINTER__
|
||||
.type idata.iat.\name,@object
|
||||
idata.iat.\name:
|
||||
.previous/*
|
||||
...
|
||||
decentralized content
|
||||
...
|
||||
*/.section .piro.data.sort.iat.2.\name\().3,"awG",\name,comdat
|
||||
.quad 0
|
||||
.previous
|
||||
.pushsection .rodata.str1.1,"aSM",@progbits,1
|
||||
.Lidata.str.\name:
|
||||
.asciz "\name\().dll"
|
||||
.popsection
|
||||
.endm
|
||||
|
||||
/* clang-format on */
|
||||
#endif /* __ASSEMBLER__ */
|
||||
#endif /* APE_IDATA_H_ */
|
42
ape/lib/apelib.mk
Normal file
42
ape/lib/apelib.mk
Normal file
|
@ -0,0 +1,42 @@
|
|||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||
|
||||
PKGS += APE_LIB
|
||||
|
||||
APE_LIB_ARTIFACTS += APE_LIB_A
|
||||
APE_LIB = $(APE_LIB_A_DEPS) $(APE_LIB_A)
|
||||
APE_LIB_A = o/$(MODE)/ape/lib/apelib.a
|
||||
APE_LIB_A_FILES := $(wildcard ape/lib/*)
|
||||
APE_LIB_A_HDRS = $(filter %.h,$(APE_LIB_A_FILES))
|
||||
APE_LIB_A_SRCS_S = $(filter %.S,$(APE_LIB_A_FILES))
|
||||
APE_LIB_A_SRCS_C = $(filter %.c,$(APE_LIB_A_FILES))
|
||||
|
||||
APE_LIB_A_SRCS = \
|
||||
$(APE_LIB_A_SRCS_S) \
|
||||
$(APE_LIB_A_SRCS_C)
|
||||
|
||||
APE_LIB_A_OBJS = \
|
||||
$(APE_LIB_A_SRCS_S:%.S=o/$(MODE)/%.o) \
|
||||
$(APE_LIB_A_SRCS_C:%.c=o/$(MODE)/%.o) \
|
||||
$(APE_LIB_A_SRCS:%=o/$(MODE)/%.zip.o) \
|
||||
o/$(MODE)/NOTICE.zip.o
|
||||
|
||||
APE_LIB_A_CHECKS = $(APE_LIB_A_HDRS:%=o/$(MODE)/%.ok)
|
||||
APE_LIB_A_DIRECTDEPS = LIBC_STR LIBC_STUBS
|
||||
APE_LIB_A_DEPS = $(call uniq,$(foreach x,$(APE_LIB_A_DIRECTDEPS),$($(x))))
|
||||
|
||||
$(APE_LIB_A): ape/lib/ $(APE_LIB_A).pkg $(APE_LIB_A_OBJS)
|
||||
$(APE_LIB_A).pkg: $(APE_LIB_A_OBJS) $(foreach x,$(APE_LIB_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
APE_LIB_LIBS = $(foreach x,$(APE_LIB_ARTIFACTS),$($(x)))
|
||||
APE_LIB_SRCS = $(foreach x,$(APE_LIB_ARTIFACTS),$($(x)_SRCS))
|
||||
APE_LIB_HDRS = $(foreach x,$(APE_LIB_ARTIFACTS),$($(x)_HDRS))
|
||||
APE_LIB_BINS = $(foreach x,$(APE_LIB_ARTIFACTS),$($(x)_BINS))
|
||||
APE_LIB_CHECKS = $(foreach x,$(APE_LIB_ARTIFACTS),$($(x)_CHECKS))
|
||||
APE_LIB_OBJS = $(foreach x,$(APE_LIB_ARTIFACTS),$($(x)_OBJS))
|
||||
$(APE_LIB_OBJS): $(BUILD_FILES) libc/str/str.mk
|
||||
|
||||
.PHONY: o/$(MODE)/ape/lib
|
||||
o/$(MODE)/ape/lib: \
|
||||
$(APE_LIB_CHECKS) \
|
||||
$(APE_LIB_A)
|
59
ape/lib/apm.h
Normal file
59
ape/lib/apm.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╠──────────────────────────────────────────────────────────────────────────────╣
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█▀█░▀█▀░█░█░█▀█░█░░░█░░░█░█░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█░▄░░█░░█░█░█▀█░█░░░█░░░▀█▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░▀░▀░▀▀▀░░▀░░▀▀▀░▀░▀░▀▀▀░▀▀▀░░▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█▀█░█▀█░▀█▀░█▀█░█▀█░█░░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀▀░█ █░██▀░░█░░█▀█░█▀█░█░░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░▀░░░▀▀▀░▀░▀░░▀░░▀░▀░▀▀▀░▀▀▀░▀▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀▀░█░█░█▀▀░█▀█░█░█░▀█▀░█▀█░█▀█░█░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░▄▄░░░▐█░░│
|
||||
│░░░░░░░█▀▀░▄▀▄░█▀▀░█░▄░█░█░░█░░█▀█░█▀█░█░░█▀▀░░░░░░░░░░░░▄▄▄░░░▄██▄░░█▀░░░█░▄░│
|
||||
│░░░░░░░▀▀▀░▀░▀░▀▀▀░▀▀▀░▀▀▀░░▀░░▀░▀░▀▀▀░▀▀░▀▀▀░░░░░░░░░░▄██▀█▌░██▄▄░░▐█▀▄░▐█▀░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▐█▀▀▌░░░▄▀▌░▌░█░▌░░▌░▌░░│
|
||||
╠──────────────────────────────────────────────────────▌▀▄─▐──▀▄─▐▄─▐▄▐▄─▐▄─▐▄─│
|
||||
│ αcτµαlly pδrταblε εxεcµταblε § green energy │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#ifndef APE_LIB_APM_H_
|
||||
#define APE_LIB_APM_H_
|
||||
|
||||
/**
|
||||
* @fileoverview Advanced Power Management.
|
||||
*
|
||||
* <p>APM is useful for exiting programs, without needing to ask the
|
||||
* human to flip a physical switch or pass QEMU's -no-reboot flag.
|
||||
*
|
||||
* <p><b>Implementation Detail:</b> Supporting ACPI would literally
|
||||
* require implementing a programming language.
|
||||
*
|
||||
* @see APM BIOS Interface Specification v1.2
|
||||
* @since IBM PC/AT
|
||||
*/
|
||||
|
||||
#define APM_SERVICE 0x15
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
void apmoff(void) noreturn;
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* APE_LIB_APM_H_ */
|
36
ape/lib/bootdr.S
Normal file
36
ape/lib/bootdr.S
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 sw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/macros.h"
|
||||
#include "ape/notice.inc"
|
||||
.section .real,"ax",@progbits
|
||||
.yoink __FILE__
|
||||
.code16
|
||||
|
||||
/ Resets personal computer.
|
||||
/
|
||||
/ @param di drive number, e.g. A:\ is 0x00, C:\ is 0x80
|
||||
/ @mode real
|
||||
/ @noreturn
|
||||
bootdr: push %bp
|
||||
mov %sp,%bp
|
||||
mov %di,%dx
|
||||
int $0x19
|
||||
ljmp $0xf000,$0xfff0
|
||||
.endfn bootdr,globl
|
38
ape/lib/e820map.S
Normal file
38
ape/lib/e820map.S
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/lib/pc.h"
|
||||
#include "ape/config.h"
|
||||
#include "ape/macros.h"
|
||||
#include "ape/notice.inc"
|
||||
.section .real,"ax",@progbits
|
||||
.yoink __FILE__
|
||||
.code16
|
||||
|
||||
.globl e820map
|
||||
.hidden e820map
|
||||
.type e820map,@object
|
||||
.size e820map,XLM_E820_SIZE
|
||||
e820map = ape.xlm + XLM_E820
|
||||
|
||||
.globl e820map_xlm
|
||||
.hidden e820map_xlm
|
||||
.type e820map_xlm,@object
|
||||
.size e820map_xlm,XLM_E820_SIZE
|
||||
e820map_xlm = XLM(E820)
|
59
ape/lib/flattenhighmemory.c
Normal file
59
ape/lib/flattenhighmemory.c
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/config.h"
|
||||
#include "ape/lib/pc.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/safemacros.h"
|
||||
|
||||
/**
|
||||
* Virtualizes physical memory.
|
||||
*
|
||||
* This function removes memory holes (discovered by e820() earlier) and
|
||||
* creates the illusion of flat contiguous memory for as much RAM as the
|
||||
* BIOS reports usable. Memory is safe to use and remap afterwards.
|
||||
*
|
||||
* @see ape/ape.S
|
||||
*/
|
||||
textreal void flattenhighmemory(struct SmapEntry *e820, struct PageTable *pml4t,
|
||||
uint64_t *ptsp) {
|
||||
struct SmapEntry *smap = e820;
|
||||
struct SmapEntry *hole = e820;
|
||||
uint64_t paddr = IMAGE_BASE_PHYSICAL;
|
||||
uint64_t vaddr = IMAGE_BASE_VIRTUAL;
|
||||
while (smap->size) {
|
||||
while (smap->size && smap->type != kMemoryUsable) smap++;
|
||||
paddr = roundup(max(paddr, smap->addr), PAGESIZE);
|
||||
while (paddr < rounddown(smap->addr + smap->size, PAGESIZE)) {
|
||||
while (hole->size &&
|
||||
(hole->type == kMemoryUsable || hole->addr + hole->size < paddr)) {
|
||||
hole++;
|
||||
}
|
||||
if (paddr >= hole->addr && paddr < hole->addr + hole->size) {
|
||||
paddr = roundup(hole->addr + hole->size, PAGESIZE);
|
||||
} else {
|
||||
uint64_t *entry = getpagetableentry(vaddr, 3, pml4t, ptsp);
|
||||
*entry = paddr | PAGE_V | PAGE_RW;
|
||||
vaddr += 0x1000;
|
||||
paddr += 0x1000;
|
||||
}
|
||||
}
|
||||
smap++;
|
||||
}
|
||||
}
|
32
ape/lib/g_pml4t.S
Normal file
32
ape/lib/g_pml4t.S
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/lib/pc.h"
|
||||
#include "ape/config.h"
|
||||
#include "ape/macros.h"
|
||||
#include "ape/notice.inc"
|
||||
.section .real,"ax",@progbits
|
||||
.yoink __FILE__
|
||||
.code16
|
||||
|
||||
.globl g_pml4t
|
||||
.hidden g_pml4t
|
||||
.type g_pml4t,@object
|
||||
.size g_pml4t,0x1000
|
||||
g_pml4t = REAL_STACK_FRAME - 0x1000
|
38
ape/lib/g_ptsp.S
Normal file
38
ape/lib/g_ptsp.S
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/lib/pc.h"
|
||||
#include "ape/config.h"
|
||||
#include "ape/macros.h"
|
||||
#include "ape/notice.inc"
|
||||
.section .real,"ax",@progbits
|
||||
.yoink __FILE__
|
||||
.code16
|
||||
|
||||
.globl g_ptsp
|
||||
.hidden g_ptsp
|
||||
.type g_ptsp,@object
|
||||
.size g_ptsp,XLM_PAGE_TABLE_STACK_POINTER_SIZE
|
||||
g_ptsp = ape.xlm + XLM_PAGE_TABLE_STACK_POINTER
|
||||
|
||||
.globl g_ptsp_xlm
|
||||
.hidden g_ptsp_xlm
|
||||
.type g_ptsp_xlm,@object
|
||||
.size g_ptsp_xlm,XLM_PAGE_TABLE_STACK_POINTER_SIZE
|
||||
g_ptsp_xlm = XLM(PAGE_TABLE_STACK_POINTER)
|
40
ape/lib/getpagetableentry.c
Normal file
40
ape/lib/getpagetableentry.c
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/lib/pc.h"
|
||||
#include "libc/assert.h"
|
||||
|
||||
textreal static uint64_t pushpagetable(uint64_t *ptsp) {
|
||||
return (*ptsp -= PAGESIZE) | PAGE_V | PAGE_RW;
|
||||
}
|
||||
|
||||
textreal uint64_t *getpagetableentry(uint64_t vaddr, unsigned depth,
|
||||
struct PageTable *pml4t, uint64_t *ptsp) {
|
||||
assert(depth <= 3);
|
||||
assert(*ptsp % PAGESIZE == 0);
|
||||
assert((intptr_t)pml4t % PAGESIZE == 0);
|
||||
unsigned char shift = 39;
|
||||
for (;;) {
|
||||
uint64_t *entry = &pml4t->p[(vaddr >> shift) & 511];
|
||||
if (!depth--) return entry;
|
||||
shift -= 9;
|
||||
if (!*entry) *entry = pushpagetable(ptsp);
|
||||
pml4t = (void *)(*entry & PAGE_TA);
|
||||
}
|
||||
}
|
46
ape/lib/kbiosdataarea.S
Normal file
46
ape/lib/kbiosdataarea.S
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/lib/pc.h"
|
||||
#include "ape/config.h"
|
||||
#include "ape/macros.h"
|
||||
#include "ape/notice.inc"
|
||||
.section .real,"ax",@progbits
|
||||
.yoink __FILE__
|
||||
.code16
|
||||
|
||||
.globl kBiosDataArea
|
||||
.hidden kBiosDataArea
|
||||
.type kBiosDataArea,@object
|
||||
.size kBiosDataArea,XLM_BIOS_DATA_AREA_SIZE
|
||||
kBiosDataArea = ape.xlm + XLM_BIOS_DATA_AREA
|
||||
|
||||
.globl kBiosDataAreaXlm
|
||||
.hidden kBiosDataAreaXlm
|
||||
.type kBiosDataAreaXlm,@object
|
||||
.size kBiosDataAreaXlm,XLM_BIOS_DATA_AREA_SIZE
|
||||
kBiosDataAreaXlm = XLM(BIOS_DATA_AREA)
|
||||
|
||||
.section .sort.real.init.2.kBiosDataArea,"ax",@progbits
|
||||
movpp %ds,%es # copy bios data to valid page
|
||||
mov $PC_BIOS_DATA_AREA,%si
|
||||
mov $XLM(BIOS_DATA_AREA),%di
|
||||
mov $XLM_BIOS_DATA_AREA_SIZE,%cx
|
||||
rep movsb
|
||||
.previous
|
27
ape/lib/pageunmap.c
Normal file
27
ape/lib/pageunmap.c
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/lib/pc.h"
|
||||
#include "libc/bits/bits.h"
|
||||
|
||||
textreal void pageunmap(uint64_t vaddr) {
|
||||
uint64_t *entry = getpagetableentry(vaddr, 3, &g_pml4t, &g_ptsp_xlm);
|
||||
*entry &= ~PAGE_V;
|
||||
invlpg(vaddr);
|
||||
}
|
239
ape/lib/pc.h
Normal file
239
ape/lib/pc.h
Normal file
|
@ -0,0 +1,239 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╠──────────────────────────────────────────────────────────────────────────────╣
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█▀█░▀█▀░█░█░█▀█░█░░░█░░░█░█░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█░▄░░█░░█░█░█▀█░█░░░█░░░▀█▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░▀░▀░▀▀▀░░▀░░▀▀▀░▀░▀░▀▀▀░▀▀▀░░▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█▀█░█▀█░▀█▀░█▀█░█▀█░█░░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀▀░█ █░██▀░░█░░█▀█░█▀█░█░░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░▀░░░▀▀▀░▀░▀░░▀░░▀░▀░▀▀▀░▀▀▀░▀▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀▀░█░█░█▀▀░█▀█░█░█░▀█▀░█▀█░█▀█░█░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░▄▄░░░▐█░░│
|
||||
│░░░░░░░█▀▀░▄▀▄░█▀▀░█░▄░█░█░░█░░█▀█░█▀█░█░░█▀▀░░░░░░░░░░░░▄▄▄░░░▄██▄░░█▀░░░█░▄░│
|
||||
│░░░░░░░▀▀▀░▀░▀░▀▀▀░▀▀▀░▀▀▀░░▀░░▀░▀░▀▀▀░▀▀░▀▀▀░░░░░░░░░░▄██▀█▌░██▄▄░░▐█▀▄░▐█▀░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▐█▀▀▌░░░▄▀▌░▌░█░▌░░▌░▌░░│
|
||||
╠──────────────────────────────────────────────────────▌▀▄─▐──▀▄─▐▄─▐▄▐▄─▐▄─▐▄─│
|
||||
│ αcτµαlly pδrταblε εxεcµταblε § ibm personal computer │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#ifndef APE_LIB_PC_H_
|
||||
#define APE_LIB_PC_H_
|
||||
|
||||
#define BOOTSIG 0xaa55 /* master boot record signature */
|
||||
#define PC_BIOS_DATA_AREA 0x400
|
||||
|
||||
#define kInterruptFlag (1u << 9)
|
||||
|
||||
/* FPU Status Word (x87)
|
||||
@see Intel Manual V1 §8.1.3
|
||||
IE: Invalid Operation ────────────────┐
|
||||
DE: Denormalized Operand ────────────┐│
|
||||
ZE: Zero Divide ────────────────────┐││
|
||||
OE: Overflow Flag ─────────────────┐│││
|
||||
UE: Underflow Flag ───────────────┐││││
|
||||
PE: Precision Flag ──────────────┐│││││
|
||||
SF: Stack Fault ────────────────┐││││││
|
||||
ES: Exception Summary Status ──┐│││││││
|
||||
C0-3: Condition Codes ──┬────┐ ││││││││
|
||||
Top of Stack Pointer ─────┐ │ ││││││││
|
||||
B: FPU Busy ───────────┐│ │ │ ││││││││
|
||||
││┌┴┐┌┼┐││││││││
|
||||
│↓│ │↓↓↓││││││││*/
|
||||
#define FPU_ZE 0b0000000000100000000000100
|
||||
#define FPU_C0 0b0000000000000000100000000
|
||||
#define FPU_C1 0b0000000000000001000000000
|
||||
#define FPU_C2 0b0000000000000010000000000
|
||||
#define FPU_C3 0b0000000000100000000000000
|
||||
|
||||
#define CR0_PE (1u << 0) /* protected mode enabled */
|
||||
#define CR0_MP (1u << 1) /* monitor coprocessor */
|
||||
#define CR0_EM (1u << 2) /* no x87 fpu present if set */
|
||||
#define CR0_TS (1u << 3) /* task switched x87 */
|
||||
#define CR0_ET (1u << 4) /* extension type 287 or 387 */
|
||||
#define CR0_NE (1u << 5) /* enable x87 error reporting */
|
||||
#define CR0_WP (1u << 16) /* write protect read-only pages @pl0 */
|
||||
#define CR0_AM (1u << 18) /* alignment mask */
|
||||
#define CR0_NW (1u << 29) /* global write-through cache disable */
|
||||
#define CR0_CD (1u << 30) /* global cache disable */
|
||||
#define CR0_PG (1u << 31) /* paging enabled */
|
||||
|
||||
#define CR4_VME (1u << 0) /* virtual 8086 mode extension */
|
||||
#define CR4_PVI (1u << 1) /* protected mode virtual interrupts */
|
||||
#define CR4_TSD (1u << 2) /* time stamp disable (rdtsc) */
|
||||
#define CR4_DE (1u << 3) /* debugging extensions */
|
||||
#define CR4_PSE (1u << 4) /* page size extension */
|
||||
#define CR4_PAE (1u << 5) /* physical address extension */
|
||||
#define CR4_MCE (1u << 6) /* machine check exception */
|
||||
#define CR4_PGE (1u << 7) /* page global enabled */
|
||||
#define CR4_OSFXSR (1u << 9) /* enable SSE and fxsave/fxrestor */
|
||||
#define CR4_OSXMMEXCPT (1u << 10) /* enable unmasked SSE exceptions */
|
||||
#define CR4_LA57 (1u << 12) /* enable level-5 paging */
|
||||
#define CR4_VMXE (1u << 13) /* enable VMX operations */
|
||||
#define CR4_SMXE (1u << 14) /* enable SMX operations */
|
||||
#define CR4_FSGSBASE (1u << 16) /* enable *FSBASE and *GSBASE instructions */
|
||||
#define CR4_PCIDE (1u << 17) /* enable process-context identifiers */
|
||||
#define CR4_OSXSAVE (1u << 18) /* enable XSAVE */
|
||||
|
||||
#define XCR0_X87 (1u << 0)
|
||||
#define XCR0_SSE (1u << 1)
|
||||
#define XCR0_AVX (1u << 2)
|
||||
#define XCR0_BNDREG (1u << 3)
|
||||
#define XCR0_BNDCSR (1u << 4)
|
||||
#define XCR0_OPMASK (1u << 5)
|
||||
#define XCR0_ZMM_HI256 (1u << 6)
|
||||
#define XCR0_HI16_ZMM (1u << 7)
|
||||
|
||||
#define EFER 0xC0000080 /* extended feature enable register */
|
||||
#define EFER_SCE (1u << 0) /* system call extensions */
|
||||
#define EFER_LME (1u << 8) /* long mode enable */
|
||||
#define EFER_LMA (1u << 10) /* long mode active */
|
||||
#define EFER_NXE (1u << 11) /* no-execute enable */
|
||||
|
||||
#define GDT_REAL_CODE 8
|
||||
#define GDT_REAL_DATA 16
|
||||
#define GDT_LEGACY_CODE 24
|
||||
#define GDT_LEGACY_DATA 32
|
||||
#define GDT_LONG_CODE 40
|
||||
#define GDT_LONG_DATA 48
|
||||
|
||||
#define PIC1 0x20 /* IO base address for master PIC */
|
||||
#define PIC2 0xA0 /* IO base address for slave PIC */
|
||||
#define PIC1_CMD PIC1
|
||||
#define PIC1_DATA (PIC1 + 1)
|
||||
#define PIC2_CMD PIC2
|
||||
#define PIC2_DATA (PIC2 + 1)
|
||||
#define PIC_EOI 0x20 /* End-of-interrupt command code */
|
||||
#define PIC_READ_IRR 0x0a /* OCW3 irq ready next CMD read */
|
||||
#define PIC_READ_ISR 0x0b /* OCW3 irq service next CMD read */
|
||||
|
||||
/* Long Mode Paging
|
||||
@see Intel Manual V.3A §4.1 §4.5
|
||||
IsValid (ignored on CR3) V┐
|
||||
┌Block Instr. Fetches (if NXE) IsWritable (ignored on CR3) RW┐│
|
||||
│ Permit User-Mode Access - u┐││
|
||||
│ Page-level Write-Through - PWT┐│││
|
||||
│ Page-level Cache Disable - PCD┐││││
|
||||
│ Set if has been read - Accessed┐│││││
|
||||
│ Set if has been written - Dirty┐││││││
|
||||
│ IsPage (if PDPTE/PDE) or PAT (if PT)┐│││││││
|
||||
│ (If this maps 2MB/1GB page and CR4.PGE) Global┐││││││││
|
||||
│ (If IsPage 2MB/1GB, see Intel V3A § 11.12) PAT │││││││││
|
||||
│ │ │││││││││
|
||||
│ ┌────────────────────────────────────┤ │││││││││
|
||||
│ Must Be 0┐│ Next Page Table Address (!IsPage) │ │││││││││
|
||||
│ │├────────────────────────────────────┤ │││││││││
|
||||
│ ││ Physical Address 4KB │ │││││││││
|
||||
│┌───┐┌─────┐│├───────────────────────────┐ │ign│││││││││
|
||||
││PKE││ ign │││ Physical Address 2MB │ │┌┴┐│││││││││
|
||||
││ ││ ││├──────────────────┐ │ ││ ││││││││││
|
||||
││ ││ │││ Phys. Addr. 1GB │ │ ││ ││││││││││
|
||||
││ ││ │││ │ │ ││ ││││││││││
|
||||
0b00000000000011111111111111111111111111111111111111000000000000
|
||||
6666555555555544444444443333333333222222222211111111110000000000
|
||||
3210987654321098765432109876543210987654321098765432109876543210*/
|
||||
#define PAGE_V /* */ 0b000000001
|
||||
#define PAGE_RW /* */ 0b000000010
|
||||
#define PAGE_U /* */ 0b000000100
|
||||
#define PAGE_2MB /* */ 0b110000000
|
||||
#define PAGE_1GB /* */ 0b110000000
|
||||
#define PAGE_TA 0b011111111111111111111111111111111111111000000000000
|
||||
#define PAGE_PA2 0b11111111111111111111111111111000000000000000000000
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
#include "ape/config.h"
|
||||
|
||||
struct thatispacked GlobalDescriptorTable {
|
||||
uint16_t size;
|
||||
uint64_t *entries;
|
||||
};
|
||||
|
||||
/**
|
||||
* Memory hole map.
|
||||
* @see wiki.osdev.org/Detecting_Memory_(x86)
|
||||
* @since 2002
|
||||
*/
|
||||
struct SmapEntry {
|
||||
uint64_t addr;
|
||||
uint64_t size;
|
||||
enum {
|
||||
kMemoryUsable = 1,
|
||||
kMemoryUnusable = 2,
|
||||
kMemoryAcpiReclaimable = 3,
|
||||
kMemoryAcpiNvs = 4,
|
||||
kMemoryBad = 5
|
||||
} type;
|
||||
uint32_t __acpi3; /* is abstracted */
|
||||
};
|
||||
|
||||
struct IdtDescriptor {
|
||||
uint16_t offset_1; /* offset bits 0..15 */
|
||||
uint16_t selector; /* a code segment selector in GDT or LDT */
|
||||
uint8_t ist; /* bits 0..2 hold stack table offset, rest are zero */
|
||||
uint8_t type_attr; /* type and attributes */
|
||||
uint16_t offset_2; /* offset bits 16..31 */
|
||||
uint32_t offset_3; /* offset bits 32..63 */
|
||||
uint32_t zero; /* reserved */
|
||||
};
|
||||
|
||||
struct thatispacked PageTable {
|
||||
uint64_t p[512];
|
||||
} aligned(PAGESIZE);
|
||||
|
||||
extern struct PageTable g_pml4t;
|
||||
extern struct GlobalDescriptorTable gdt;
|
||||
|
||||
extern const unsigned char kBiosDataArea[256];
|
||||
extern const unsigned char kBiosDataAreaXlm[256];
|
||||
|
||||
extern struct SmapEntry e820map[XLM_E820_SIZE / sizeof(struct SmapEntry)];
|
||||
extern struct SmapEntry e820map_xlm[XLM_E820_SIZE / sizeof(struct SmapEntry)];
|
||||
|
||||
extern uint64_t g_ptsp;
|
||||
extern uint64_t g_ptsp_xlm;
|
||||
|
||||
void bootdr(char drive) noreturn;
|
||||
|
||||
void smapsort(struct SmapEntry *);
|
||||
uint64_t *getpagetableentry(uint64_t, unsigned, struct PageTable *, uint64_t *);
|
||||
void flattenhighmemory(struct SmapEntry *, struct PageTable *, uint64_t *);
|
||||
void pageunmap(uint64_t);
|
||||
|
||||
forceinline unsigned long eflags(void) {
|
||||
unsigned long res;
|
||||
asm("pushf\n\t"
|
||||
"pop\t%0"
|
||||
: "=rm"(res));
|
||||
return res;
|
||||
}
|
||||
|
||||
forceinline unsigned char inb(unsigned short port) {
|
||||
unsigned char al;
|
||||
asm volatile("inb\t%1,%0" : "=a"(al) : "dN"(port));
|
||||
return al;
|
||||
}
|
||||
|
||||
forceinline void outb(unsigned short port, unsigned char byte) {
|
||||
asm volatile("outb\t%0,%1"
|
||||
: /* no inputs */
|
||||
: "a"(byte), "dN"(port));
|
||||
}
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* APE_LIB_PC_H_ */
|
140
ape/lib/pic.c
Normal file
140
ape/lib/pic.c
Normal file
|
@ -0,0 +1,140 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/lib/pc.h"
|
||||
|
||||
#define ICW1_ICW4 0x01 /* ICW4 (not) needed */
|
||||
#define ICW1_SINGLE 0x02 /* Single (cascade) mode */
|
||||
#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */
|
||||
#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */
|
||||
#define ICW1_INIT 0x10 /* Initialization - required! */
|
||||
|
||||
#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */
|
||||
#define ICW4_AUTO 0x02 /* Auto (normal) EOI */
|
||||
#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */
|
||||
#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */
|
||||
#define ICW4_SFNM 0x10 /* Special fully nested (not) */
|
||||
|
||||
static inline void io_wait(void) {
|
||||
/* Magic technique from Linux, according to:
|
||||
* wiki.osdev.org/index.php?title=Inline_Assembly/Examples&oldid=23541
|
||||
*/
|
||||
outb(0x80, 0);
|
||||
}
|
||||
|
||||
void PIC_sendEOI(unsigned char irq) {
|
||||
if (irq >= 8) outb(PIC2_CMD, PIC_EOI);
|
||||
outb(PIC1_CMD, PIC_EOI);
|
||||
}
|
||||
|
||||
bool AreInterruptsEnabled() {
|
||||
return (eflags() & kInterruptFlag) == kInterruptFlag;
|
||||
}
|
||||
|
||||
nodiscard forceinline unsigned long irqdisable(void) {
|
||||
unsigned long eflags;
|
||||
asm("pushf\n\t"
|
||||
"cli\n\t"
|
||||
"pop\t%0"
|
||||
: "=r"(eflags)
|
||||
: /* no inputs */
|
||||
: "cc");
|
||||
return eflags;
|
||||
}
|
||||
|
||||
forceinline void irqrestore(unsigned long eflags) {
|
||||
asm volatile(
|
||||
"push\t%0\n\t"
|
||||
"popf"
|
||||
: /* no outputs */
|
||||
: "rm"(eflags)
|
||||
: "cc");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param offset1 is vector offset for master PIC
|
||||
* vectors on the master become offset1..offset1+7
|
||||
* @param offset2 is same for slave PIC: offset2..offset2+7
|
||||
**/
|
||||
void PIC_remap(int offset1, int offset2) {
|
||||
unsigned char a1, a2;
|
||||
a1 = inb(PIC1_DATA); // save masks
|
||||
a2 = inb(PIC2_DATA);
|
||||
outb(PIC1_CMD,
|
||||
ICW1_INIT |
|
||||
ICW1_ICW4); // starts the initialization sequence (in cascade mode)
|
||||
io_wait();
|
||||
outb(PIC2_CMD, ICW1_INIT | ICW1_ICW4);
|
||||
io_wait();
|
||||
outb(PIC1_DATA, offset1); // ICW2: Master PIC vector offset
|
||||
io_wait();
|
||||
outb(PIC2_DATA, offset2); // ICW2: Slave PIC vector offset
|
||||
io_wait();
|
||||
outb(PIC1_DATA, 4); // ICW3: tell Master PIC that there is a slave PIC at
|
||||
// IRQ2 (0000 0100)
|
||||
io_wait();
|
||||
outb(PIC2_DATA, 2); // ICW3: tell Slave PIC its cascade identity (0000 0010)
|
||||
io_wait();
|
||||
outb(PIC1_DATA, ICW4_8086);
|
||||
io_wait();
|
||||
outb(PIC2_DATA, ICW4_8086);
|
||||
io_wait();
|
||||
outb(PIC1_DATA, a1); // restore saved masks.
|
||||
outb(PIC2_DATA, a2);
|
||||
}
|
||||
|
||||
void IRQ_set_mask(unsigned char IRQline) {
|
||||
uint16_t port;
|
||||
uint8_t value;
|
||||
if (IRQline < 8) {
|
||||
port = PIC1_DATA;
|
||||
} else {
|
||||
port = PIC2_DATA;
|
||||
IRQline -= 8;
|
||||
}
|
||||
value = inb(port) | (1 << IRQline);
|
||||
outb(port, value);
|
||||
}
|
||||
|
||||
void IRQ_clear_mask(unsigned char IRQline) {
|
||||
uint16_t port;
|
||||
uint8_t value;
|
||||
if (IRQline < 8) {
|
||||
port = PIC1_DATA;
|
||||
} else {
|
||||
port = PIC2_DATA;
|
||||
IRQline -= 8;
|
||||
}
|
||||
value = inb(port) & ~(1 << IRQline);
|
||||
outb(port, value);
|
||||
}
|
||||
|
||||
static uint16_t __pic_get_irq_reg(int ocw3) {
|
||||
/* OCW3 to PIC CMD to get the register values. PIC2 is chained, and
|
||||
* represents IRQs 8-15. PIC1 is IRQs 0-7, with 2 being the chain */
|
||||
outb(PIC1_CMD, ocw3);
|
||||
outb(PIC2_CMD, ocw3);
|
||||
return (inb(PIC2_CMD) << 8) | inb(PIC1_CMD);
|
||||
}
|
||||
|
||||
/* Returns the combined value of the cascaded PICs irq request register */
|
||||
uint16_t pic_get_irr(void) { return __pic_get_irq_reg(PIC_READ_IRR); }
|
||||
|
||||
/* Returns the combined value of the cascaded PICs in-service register */
|
||||
uint16_t pic_get_isr(void) { return __pic_get_irq_reg(PIC_READ_ISR); }
|
47
ape/lib/smapsort.c
Normal file
47
ape/lib/smapsort.c
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/lib/pc.h"
|
||||
|
||||
textreal static unsigned smapcount(const struct SmapEntry *se) {
|
||||
unsigned i = 0;
|
||||
while (se[i].size) ++i;
|
||||
return i;
|
||||
}
|
||||
|
||||
textreal static void smapsorter(size_t n, struct SmapEntry a[n]) {
|
||||
struct SmapEntry t;
|
||||
unsigned i, j;
|
||||
for (i = 1; i < n; ++i) {
|
||||
j = i;
|
||||
t = a[i];
|
||||
while (j > 0 && (intptr_t)t.addr - (intptr_t)a[j - 1].addr) {
|
||||
a[j] = a[j - 1];
|
||||
--j;
|
||||
}
|
||||
a[j] = t;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts BIOS e820 memory map.
|
||||
*/
|
||||
textreal void smapsort(struct SmapEntry *smap) {
|
||||
smapsorter(smapcount(smap), smap);
|
||||
}
|
281
ape/macros.h
Normal file
281
ape/macros.h
Normal file
|
@ -0,0 +1,281 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╠──────────────────────────────────────────────────────────────────────────────╣
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█▀█░▀█▀░█░█░█▀█░█░░░█░░░█░█░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█░▄░░█░░█░█░█▀█░█░░░█░░░▀█▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░▀░▀░▀▀▀░░▀░░▀▀▀░▀░▀░▀▀▀░▀▀▀░░▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█▀█░█▀█░▀█▀░█▀█░█▀█░█░░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀▀░█ █░██▀░░█░░█▀█░█▀█░█░░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░▀░░░▀▀▀░▀░▀░░▀░░▀░▀░▀▀▀░▀▀▀░▀▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀▀░█░█░█▀▀░█▀█░█░█░▀█▀░█▀█░█▀█░█░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░▄▄░░░▐█░░│
|
||||
│░░░░░░░█▀▀░▄▀▄░█▀▀░█░▄░█░█░░█░░█▀█░█▀█░█░░█▀▀░░░░░░░░░░░░▄▄▄░░░▄██▄░░█▀░░░█░▄░│
|
||||
│░░░░░░░▀▀▀░▀░▀░▀▀▀░▀▀▀░▀▀▀░░▀░░▀░▀░▀▀▀░▀▀░▀▀▀░░░░░░░░░░▄██▀█▌░██▄▄░░▐█▀▄░▐█▀░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▐█▀▀▌░░░▄▀▌░▌░█░▌░░▌░▌░░│
|
||||
╠──────────────────────────────────────────────────────▌▀▄─▐──▀▄─▐▄─▐▄▐▄─▐▄─▐▄─│
|
||||
│ αcτµαlly pδrταblε εxεcµταblε § macros │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#ifndef APE_MACROS_H_
|
||||
#define APE_MACROS_H_
|
||||
#include "libc/macros.h"
|
||||
#ifdef __ASSEMBLER__
|
||||
/* clang-format off */
|
||||
|
||||
/**
|
||||
* @fileoverview Macros relevant to αcτµαlly pδrταblε εxεcµταblε.
|
||||
*/
|
||||
|
||||
/ Calls near (i.e. pc+pcrel<64kB) FUNCTION.
|
||||
/ @mode long,legacy,real
|
||||
/ @cost 9 bytes overhead
|
||||
.macro rlcall function:req
|
||||
.byte 0x50 # push %[er]ax
|
||||
.byte 0xb8,0,0 # mov $?,%[e]ax
|
||||
jmp 911f
|
||||
.byte 0x58 # pop %[er]ax
|
||||
.byte 0xe8 # call Jvds
|
||||
.long \function\()-.-4
|
||||
jmp 912f
|
||||
911: .byte 0x58 # pop %[er]ax
|
||||
.byte 0xe8 # call Jvds
|
||||
.short \function\()-.-2
|
||||
912:
|
||||
.endm
|
||||
|
||||
/ Loads far (i.e. <1mb) abs constexpr ADDRESS into ES:DI+EDX+RDX.
|
||||
/ @mode long,legacy,real
|
||||
.macro movesdi address:req
|
||||
.byte 0xbf # mov $0x????xxxx,%[e]di
|
||||
.short \address>>4
|
||||
.byte 0x8e,0xc7 # mov %di,%es
|
||||
.byte 0xbf # mov $0x????xxxx,%[e]di
|
||||
.short \address&0xf
|
||||
jmp 297f
|
||||
.byte 0xbf # mov $0x????xxxx,%edi
|
||||
.long \address
|
||||
297:
|
||||
.endm
|
||||
|
||||
/ Loads 16-bit CONSTEXPR into Qw-register w/ optional zero-extend.
|
||||
/ @mode long,legacy,real
|
||||
.macro bbmov constexpr:req abcd abcd.hi:req abcd.lo:req
|
||||
.ifnb \abcd
|
||||
.if (\constexpr)<128 && (\constexpr)>=0
|
||||
pushpop \constexpr,\abcd
|
||||
.exitm
|
||||
.endif
|
||||
.endif
|
||||
movb $(\constexpr)>>8&0xff,\abcd.hi
|
||||
movb $(\constexpr)&0xff,\abcd.lo
|
||||
.endm
|
||||
|
||||
/ Compares 16-bit CONSTEXPR with Qw-register.
|
||||
/ @mode long,legacy,real
|
||||
.macro bbcmp constexpr:req abcd.hi:req abcd.lo:req
|
||||
cmpb $(\constexpr)>>8&0xff,\abcd.hi
|
||||
jnz 387f
|
||||
cmpb $(\constexpr)&0xff,\abcd.lo
|
||||
387:
|
||||
.endm
|
||||
|
||||
/ Adds 16-bit CONSTEXPR to Qw-register.
|
||||
/ @mode long,legacy,real
|
||||
.macro bbadd constexpr:req abcd.hi:req abcd.lo:req
|
||||
addb $(\constexpr)&0xff,\abcd.lo
|
||||
.if (\constexpr) != 0
|
||||
adcb $(\constexpr)>>8&0xff,\abcd.hi
|
||||
.endif
|
||||
.endm
|
||||
|
||||
/ Subtracts 16-bit CONSTEXPR from Qw-register.
|
||||
/ @mode long,legacy,real
|
||||
.macro bbsub constexpr:req abcd.hi:req abcd.lo:req
|
||||
subb $(\constexpr)&0xff,\abcd.lo
|
||||
.if (\constexpr) != 0
|
||||
sbbb $(\constexpr)>>8&0xff,\abcd.hi
|
||||
.endif
|
||||
.endm
|
||||
|
||||
/ Ands Qw-register with 16-bit CONSTEXPR.
|
||||
/ @mode long,legacy,real
|
||||
.macro bband constexpr:req abcd.hi:req abcd.lo:req
|
||||
.if ((\constexpr)&0xff) != 0xff || ((\constexpr)>>8&0xff) == 0xff
|
||||
andb $(\constexpr)&0xff,\abcd.lo
|
||||
.endif
|
||||
.if ((\constexpr)>>8&0xff) != 0xff
|
||||
andb $(\constexpr)>>8&0xff,\abcd.hi
|
||||
.endif
|
||||
.endm
|
||||
|
||||
/ Ors Qw-register with 16-bit CONSTEXPR.
|
||||
/ @mode long,legacy,real
|
||||
.macro bbor constexpr:req abcd.hi:req abcd.lo:req
|
||||
.if ((\constexpr)&0xff) != 0 || ((\constexpr)>>8&0xff) != 0
|
||||
orb $(\constexpr)&0xff,\abcd.lo
|
||||
.endif
|
||||
.if ((\constexpr)>>8&0xff) != 0
|
||||
orb $(\constexpr)>>8&0xff,\abcd.hi
|
||||
.endif
|
||||
.endm
|
||||
|
||||
/ Performs ACTION only if in real mode.
|
||||
/ @mode long,legacy,real
|
||||
.macro rlo clobber:req action:vararg
|
||||
990: mov $0,\clobber
|
||||
.if .-990b!=3
|
||||
.error "bad clobber or assembler mode"
|
||||
.endif
|
||||
991: \action
|
||||
.rept 2-(.-991b)
|
||||
nop
|
||||
.endr
|
||||
.if .-991b!=2
|
||||
.error "ACTION must be 1-2 bytes"
|
||||
.endif
|
||||
.endm
|
||||
|
||||
/ Initializes real mode stack.
|
||||
/ The most holiest of holy code.
|
||||
/ @mode real
|
||||
/ @see www.pcjs.org/pubs/pc/reference/intel/8086/
|
||||
.macro rlstack seg:req addr:req
|
||||
cli
|
||||
mov \seg,%ss
|
||||
mov \addr,%sp
|
||||
sti
|
||||
.endm
|
||||
|
||||
/ Symbolic Linker-Defined Binary Content.
|
||||
.macro .stub name:req kind:req default type=@object
|
||||
.ifnb \default
|
||||
.equ \name,\default
|
||||
.endif
|
||||
.\kind \name
|
||||
.type \name,\type
|
||||
.weak \name
|
||||
.hidden \name
|
||||
.endm
|
||||
|
||||
/ Symbolic Linker-Defined Binary-Encoded-Bourne Content.
|
||||
/ @param units is the number of encoded 32-bit values to insert,
|
||||
/ e.g. \000 can be encoded as 0x3030305c.
|
||||
.macro .shstub name:req units:req
|
||||
ss \name,0
|
||||
.if \units>1
|
||||
ss \name,1
|
||||
.if \units>2
|
||||
ss \name,2
|
||||
ss \name,3
|
||||
.if \units>4
|
||||
ss \name,4
|
||||
ss \name,5
|
||||
ss \name,6
|
||||
ss \name,7
|
||||
.endif
|
||||
.endif
|
||||
.endif
|
||||
.endm
|
||||
.macro ss name n
|
||||
.stub \name\()_bcs\n,long
|
||||
.endm
|
||||
|
||||
/* clang-format on */
|
||||
#elif defined(__LINKER__)
|
||||
|
||||
#define BCX_NIBBLE(X) ((((X)&0xf) > 0x9) ? ((X)&0xf) + 0x37 : ((X)&0xf) + 0x30)
|
||||
#define BCX_OCTET(X) ((BCX_NIBBLE((X) >> 4) << 8) | (BCX_NIBBLE((X) >> 0) << 0))
|
||||
#define BCX_INT16(X) ((BCX_OCTET((X) >> 8) << 16) | (BCX_OCTET((X) >> 0) << 0))
|
||||
#define BCXSTUB(SYM, X) \
|
||||
HIDDEN(SYM##_bcx0 = BCX_INT16((X) >> 48)); \
|
||||
HIDDEN(SYM##_bcx1 = BCX_INT16((X) >> 32)); \
|
||||
HIDDEN(SYM##_bcx2 = BCX_INT16((X) >> 16)); \
|
||||
HIDDEN(SYM##_bcx3 = BCX_INT16((X) >> 0))
|
||||
|
||||
/**
|
||||
* Binary coded backslash octet support.
|
||||
*
|
||||
* <p>This allows linker scripts to generate printf commands.
|
||||
*/
|
||||
#define BCO_OCTET(X) (((X)&0x7) + 0x30)
|
||||
#define BCOB_UNIT(X) \
|
||||
((BCO_OCTET((X) >> 0) << 24) | (BCO_OCTET((X) >> 3) << 16) | \
|
||||
(BCO_OCTET(((X)&0xff) >> 6) << 8) | 0x5c)
|
||||
|
||||
#define PFBYTE(SYM, X, I) HIDDEN(SYM##_bcs##I = BCOB_UNIT((X) >> ((I)*8)))
|
||||
#define PFSTUB2(SYM, X) \
|
||||
HIDDEN(SYM = (X)); \
|
||||
PFBYTE(SYM, X, 0); \
|
||||
PFBYTE(SYM, X, 1)
|
||||
#define PFSTUB4(SYM, X) \
|
||||
PFSTUB2(SYM, X); \
|
||||
PFBYTE(SYM, X, 2); \
|
||||
PFBYTE(SYM, X, 3)
|
||||
#define PFSTUB8(SYM, X) \
|
||||
PFSTUB4(SYM, X); \
|
||||
PFBYTE(SYM, X, 4); \
|
||||
PFBYTE(SYM, X, 5); \
|
||||
PFBYTE(SYM, X, 6); \
|
||||
PFBYTE(SYM, X, 7)
|
||||
|
||||
/**
|
||||
* Binary coded decimal support.
|
||||
*
|
||||
* <p>This allows linker scripts to generate dd commands. Leading spaces
|
||||
* need to be inserted so Mac doesn't consider them octal; therefore,
|
||||
* parameters must be quoted; and eight digits should be good enough.
|
||||
*/
|
||||
#define SHSTUB2(SYM, X) \
|
||||
HIDDEN(SYM##_bcs0 = BCD10K(X)); \
|
||||
HIDDEN(SYM##_bcs1 = BCD(X))
|
||||
#define BCD(X) \
|
||||
((X) == 0 \
|
||||
? 0x20202030 \
|
||||
: (X) < 10 ? 0x30202020 + (((X) % 10) << 24) \
|
||||
: (X) < 100 ? 0x30302020 + (((X) % 10) << 24) + \
|
||||
(((X) / 10 % 10) << 16) \
|
||||
: (X) < 1000 ? 0x30303020 + (((X) % 10) << 24) + \
|
||||
(((X) / 10 % 10) << 16) + \
|
||||
(((X) / 100 % 10) << 8) \
|
||||
: 0x30303030 + (((X) % 10) << 24) + \
|
||||
(((X) / 10 % 10) << 16) + \
|
||||
(((X) / 100 % 10) << 8) + \
|
||||
(((X) / 1000 % 10) << 0))
|
||||
#define BCD10K(X) \
|
||||
((X) < 10000 \
|
||||
? 0x20202020 \
|
||||
: (X) < 100000 \
|
||||
? 0x30202020 + (((X) / 10000 % 10) << 24) \
|
||||
: (X) < 1000000 \
|
||||
? 0x30302020 + (((X) / 10000 % 10) << 24) + \
|
||||
(((X) / 100000 % 10) << 16) \
|
||||
: (X) < 10000000 \
|
||||
? 0x30303020 + (((X) / 10000 % 10) << 24) + \
|
||||
(((X) / 100000 % 10) << 16) + \
|
||||
(((X) / 1000000 % 10) << 8) \
|
||||
: (X) < 100000000 \
|
||||
? 0x30303030 + (((X) / 10000 % 10) << 24) + \
|
||||
(((X) / 100000 % 10) << 16) + \
|
||||
(((X) / 1000000 % 10) << 8) + \
|
||||
(((X) / 10000000 % 10) << 0) \
|
||||
: 0xffffffffffffffff)
|
||||
|
||||
#endif /* __ASSEMBLER__ */
|
||||
#endif /* APE_MACROS_H_ */
|
41
ape/mtime.h
Normal file
41
ape/mtime.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
#ifndef COSMOPOLITAN_APE_MTIME_H_
|
||||
#define COSMOPOLITAN_APE_MTIME_H_
|
||||
#include "libc/dos.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Deterministic last modified timestamp embedding.
|
||||
*/
|
||||
|
||||
#ifndef MTIME_YEAR
|
||||
#define MTIME_YEAR 2019
|
||||
#endif
|
||||
|
||||
#ifndef MTIME_MONTH
|
||||
#define MTIME_MONTH 1
|
||||
#endif
|
||||
|
||||
#ifndef MTIME_DAY
|
||||
#define MTIME_DAY 1
|
||||
#endif
|
||||
|
||||
#ifndef MTIME_HOUR
|
||||
#define MTIME_HOUR 0
|
||||
#endif
|
||||
|
||||
#ifndef MTIME_MINUTES
|
||||
#define MTIME_MINUTES 0
|
||||
#endif
|
||||
|
||||
#ifndef MTIME_SECONDS
|
||||
#define MTIME_SECONDS 0
|
||||
#endif
|
||||
|
||||
#ifndef ZIP_MTIME_DATE
|
||||
#define ZIP_MTIME_DATE DOS_DATE(MTIME_YEAR, MTIME_MONTH, MTIME_DAY)
|
||||
#endif
|
||||
|
||||
#ifndef ZIP_MTIME_TIME
|
||||
#define ZIP_MTIME_TIME DOS_TIME(MTIME_HOUR, MTIME_MINUTES, MTIME_SECONDS)
|
||||
#endif
|
||||
|
||||
#endif /* COSMOPOLITAN_APE_MTIME_H_ */
|
69
ape/mz.ansi
Normal file
69
ape/mz.ansi
Normal file
|
@ -0,0 +1,69 @@
|
|||
ProTip: cat ape/mz.ansi
|
||||
|
||||
[38;5;150;48;5;150m▀[38;5;186m▀[38;5;150m▀▀[38;5;144m▀[48;5;144m▀[38;5;143m▀[38;5;107;48;5;107m▀[38;5;101;48;5;101m▀▀[38;5;65;48;5;65m▀[38;5;241;48;5;241m▀[38;5;240;48;5;59m▀[48;5;240m▀▀[38;5;239m▀[38;5;240m▀[38;5;239m▀[48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;238m▀▀▀[48;5;238m▀▀▀▀▀[0m
|
||||
[38;5;150;48;5;150m▀▀▀▀[48;5;144m▀[38;5;144;48;5;143m▀[38;5;143m▀[38;5;107;48;5;107m▀[38;5;101;48;5;101m▀▀[38;5;65;48;5;65m▀[38;5;241m▀[38;5;59;48;5;59m▀[38;5;240;48;5;240m▀▀▀▀▀▀▀[38;5;239;48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;238;48;5;238m▀▀▀▀[0m
|
||||
[38;5;150;48;5;150m▀▀▀▀[38;5;144;48;5;144m▀[38;5;143;48;5;143m▀[38;5;107;48;5;107m▀▀[38;5;101;48;5;101m▀▀[38;5;65;48;5;65m▀▀[38;5;59;48;5;59m▀[38;5;240;48;5;240m▀▀▀▀▀▀▀▀▀[38;5;239m▀▀[38;5;240m▀▀[38;5;239m▀▀[48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;238m▀[48;5;238m▀▀▀▀[0m
|
||||
[38;5;144;48;5;144m▀▀▀[48;5;143m▀[38;5;143m▀[48;5;107m▀[38;5;107;48;5;101m▀[38;5;101m▀▀[48;5;65m▀[38;5;65m▀▀[38;5;59;48;5;59m▀▀[38;5;240;48;5;240m▀▀[48;5;59m▀▀[48;5;240m▀▀▀▀▀▀▀▀▀▀▀[38;5;239m▀▀[48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;238;48;5;238m▀[48;5;239m▀[48;5;238m▀▀[0m
|
||||
[38;5;143;48;5;107m▀▀[48;5;143m▀▀[38;5;107;48;5;107m▀[48;5;101m▀[38;5;101;48;5;65m▀[38;5;65m▀▀▀▀▀[38;5;59m▀▀[38;5;241m▀[38;5;65;48;5;101m▀▀[48;5;107m▀▀▀▀▀▀▀▀[38;5;242m▀[38;5;241;48;5;101m▀[38;5;59m▀▀[38;5;240;48;5;65m▀[48;5;241m▀[48;5;59m▀[38;5;239;48;5;240m▀▀[48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;238;48;5;238m▀▀[48;5;239m▀[0m
|
||||
[38;5;107;48;5;107m▀▀▀▀[48;5;101m▀[38;5;101;48;5;65m▀[38;5;65m▀▀▀▀▀▀[48;5;101m▀[38;5;101m▀[48;5;107m▀[38;5;107m▀[48;5;143m▀[38;5;143m▀▀[48;5;150m▀[48;5;144m▀▀▀[38;5;144m▀▀▀[38;5;143;48;5;143m▀▀[38;5;107m▀[38;5;101;48;5;101m▀▀[38;5;65;48;5;65m▀[38;5;240;48;5;59m▀[48;5;240m▀[38;5;239m▀[48;5;239m▀[48;5;238m▀▀[38;5;240;48;5;239m▀[48;5;238m▀[38;5;239m▀[48;5;237m▀▀▀▀[48;5;238m▀[48;5;237m▀[48;5;238m▀[48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;107;48;5;144m▀▀[48;5;107m▀[38;5;101;48;5;101m▀[38;5;65;48;5;65m▀[48;5;59m▀▀▀▀▀[48;5;65m▀[38;5;101;48;5;101m▀[48;5;107m▀[38;5;107m▀[48;5;143m▀[38;5;143m▀▀[48;5;186m▀[38;5;186m▀▀▀▀▀▀▀[38;5;144;48;5;144m▀▀[38;5;143;48;5;143m▀▀[38;5;101;48;5;101m▀[48;5;59m▀[38;5;242;48;5;239m▀[38;5;239;48;5;238m▀[38;5;238;48;5;237m▀▀▀▀[38;5;237;48;5;236m▀▀[48;5;235m▀[38;5;236m▀[38;5;235m▀[38;5;236;48;5;234m▀[38;5;237;48;5;235m▀[38;5;236m▀[38;5;237m▀[38;5;236m▀[38;5;237;48;5;234m▀[38;5;236;48;5;235m▀[38;5;237m▀[38;5;239;48;5;236m▀[48;5;238m▀[48;5;239m▀[48;5;240m▀[48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;238;48;5;238m▀▀[0m
|
||||
[38;5;144;48;5;144m▀▀▀[38;5;107;48;5;108m▀[38;5;65;48;5;101m▀[48;5;65m▀[38;5;59m▀[48;5;59m▀▀▀[38;5;65;48;5;65m▀[38;5;101;48;5;101m▀[38;5;107;48;5;107m▀[48;5;143m▀[38;5;143m▀[48;5;150m▀[38;5;150;48;5;186m▀[38;5;186m▀▀[48;5;187m▀▀[48;5;186m▀▀▀▀[38;5;150;48;5;180m▀[38;5;144;48;5;144m▀[38;5;143;48;5;143m▀[38;5;107;48;5;101m▀[38;5;101;48;5;240m▀[38;5;240m▀[38;5;239;48;5;238m▀[38;5;238;48;5;237m▀▀[38;5;237;48;5;239m▀[48;5;236m▀[38;5;236;48;5;237m▀[48;5;235m▀[38;5;235m▀[38;5;234m▀[38;5;235m▀▀▀[48;5;234m▀[38;5;234m▀[38;5;235;48;5;233m▀▀[38;5;234m▀[38;5;235m▀[38;5;234;48;5;234m▀▀[38;5;235m▀▀[38;5;237;48;5;235m▀[38;5;239m▀[48;5;237m▀[48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[48;5;238m▀[38;5;238m▀[0m
|
||||
[38;5;150;48;5;150m▀[38;5;144;48;5;144m▀▀▀[38;5;107;48;5;107m▀[38;5;65;48;5;101m▀[48;5;65m▀[38;5;59;48;5;59m▀▀[48;5;65m▀[38;5;65m▀▀[38;5;101;48;5;101m▀[38;5;143;48;5;144m▀[38;5;144;48;5;150m▀[38;5;186;48;5;186m▀▀[38;5;187;48;5;187m▀▀▀▀▀[38;5;186;48;5;186m▀▀[48;5;144m▀[38;5;144;48;5;101m▀[38;5;137;48;5;95m▀[38;5;95m▀[38;5;59;48;5;101m▀[48;5;239m▀[38;5;238;48;5;238m▀[38;5;237m▀▀[38;5;236;48;5;236m▀[38;5;238m▀[38;5;237m▀[38;5;235m▀▀[48;5;235m▀▀[48;5;234m▀▀[38;5;234;48;5;235m▀▀[48;5;234m▀▀[38;5;233m▀[48;5;233m▀[38;5;234m▀[48;5;234m▀▀▀▀[38;5;235m▀▀▀[38;5;236;48;5;235m▀[38;5;239m▀[48;5;238m▀[48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[48;5;238m▀[38;5;238m▀▀▀[0m
|
||||
[38;5;186;48;5;186m▀[38;5;144;48;5;150m▀[48;5;144m▀[48;5;108m▀[38;5;107;48;5;107m▀[38;5;101;48;5;101m▀[38;5;65;48;5;65m▀[38;5;241;48;5;241m▀[38;5;59;48;5;65m▀[38;5;65m▀[48;5;101m▀[38;5;101m▀[38;5;107;48;5;107m▀[38;5;144;48;5;144m▀[38;5;150;48;5;150m▀[38;5;186;48;5;186m▀[38;5;187m▀[48;5;187m▀▀▀▀▀[38;5;186;48;5;144m▀[38;5;144;48;5;101m▀[38;5;101;48;5;95m▀[38;5;240;48;5;238m▀[38;5;59;48;5;240m▀[38;5;101;48;5;95m▀[38;5;239;48;5;239m▀[38;5;237m▀[38;5;238m▀[48;5;238m▀[38;5;235;48;5;237m▀[48;5;236m▀▀[38;5;234;48;5;235m▀[48;5;234m▀[38;5;235m▀▀[38;5;234;48;5;235m▀[48;5;234m▀▀[38;5;235m▀▀▀[38;5;234m▀▀▀[38;5;233m▀[38;5;234;48;5;233m▀▀▀▀▀[48;5;234m▀▀▀▀[38;5;235;48;5;235m▀[38;5;238;48;5;236m▀[38;5;239;48;5;238m▀[48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;238;48;5;238m▀▀▀▀[0m
|
||||
[38;5;186;48;5;150m▀[38;5;150;48;5;144m▀[38;5;144;48;5;143m▀[38;5;107;48;5;107m▀[38;5;101;48;5;101m▀[38;5;65;48;5;65m▀[48;5;241m▀[38;5;241m▀[38;5;65;48;5;65m▀[48;5;101m▀[38;5;101m▀[48;5;107m▀[38;5;144;48;5;144m▀▀[48;5;150m▀[38;5;186;48;5;186m▀[38;5;187m▀[48;5;187m▀▀▀▀[48;5;137m▀[38;5;101;48;5;101m▀[48;5;95m▀[38;5;239;48;5;240m▀[38;5;238;48;5;239m▀[38;5;59;48;5;95m▀[38;5;95;48;5;240m▀[38;5;59m▀[38;5;239;48;5;239m▀[38;5;238;48;5;240m▀[48;5;238m▀[38;5;237m▀[48;5;236m▀[48;5;235m▀[38;5;236m▀[38;5;235m▀▀[38;5;234m▀[48;5;234m▀▀[38;5;235;48;5;235m▀[38;5;234;48;5;234m▀▀▀▀▀[48;5;233m▀[38;5;233m▀▀▀▀[48;5;234m▀[48;5;233m▀[48;5;234m▀▀[48;5;233m▀[38;5;234;48;5;234m▀[38;5;235;48;5;235m▀[38;5;236;48;5;236m▀[38;5;237;48;5;237m▀[38;5;238;48;5;238m▀[38;5;239;48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;238m▀[48;5;238m▀▀▀[0m
|
||||
[38;5;150;48;5;143m▀[38;5;143;48;5;107m▀[38;5;107;48;5;65m▀[38;5;101m▀[38;5;65;48;5;59m▀▀[38;5;59m▀[48;5;65m▀[38;5;65m▀▀[38;5;101;48;5;101m▀[38;5;107;48;5;108m▀[38;5;144;48;5;144m▀▀[38;5;186;48;5;186m▀[38;5;187m▀[48;5;187m▀▀▀[48;5;186m▀[38;5;144;48;5;101m▀[38;5;101m▀▀[38;5;95;48;5;240m▀[38;5;59m▀▀▀[38;5;240;48;5;95m▀[48;5;101m▀[38;5;101;48;5;144m▀[38;5;138;48;5;101m▀[38;5;240;48;5;95m▀[38;5;237;48;5;239m▀[48;5;237m▀[38;5;236;48;5;236m▀[48;5;235m▀▀[38;5;235;48;5;236m▀▀▀[48;5;235m▀[38;5;234m▀▀[38;5;235m▀[38;5;234;48;5;234m▀▀▀[48;5;233m▀[38;5;233;48;5;234m▀▀▀[38;5;234;48;5;236m▀[48;5;237m▀[38;5;235;48;5;238m▀▀[38;5;234;48;5;236m▀[48;5;234m▀[48;5;233m▀[38;5;235;48;5;234m▀[48;5;235m▀[38;5;237m▀[48;5;237m▀[38;5;238m▀[38;5;239;48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;238m▀[38;5;239m▀[0m
|
||||
[38;5;107;48;5;107m▀[38;5;65;48;5;65m▀▀[38;5;59;48;5;59m▀▀[48;5;241m▀[38;5;65;48;5;65m▀▀[48;5;101m▀[38;5;101;48;5;107m▀[38;5;107;48;5;144m▀[38;5;108m▀[38;5;144m▀[38;5;150;48;5;150m▀[48;5;186m▀[38;5;186m▀▀[48;5;150m▀[48;5;144m▀[38;5;144m▀[38;5;101;48;5;95m▀[48;5;101m▀[38;5;95;48;5;241m▀[38;5;59;48;5;59m▀[48;5;95m▀[38;5;240;48;5;239m▀[48;5;95m▀[38;5;101;48;5;181m▀[38;5;253;48;5;255m▀[38;5;255;48;5;224m▀[38;5;188;48;5;187m▀[38;5;180;48;5;181m▀[38;5;101;48;5;180m▀[38;5;239;48;5;137m▀[38;5;236;48;5;95m▀▀▀[38;5;235m▀▀▀[38;5;236;48;5;238m▀[38;5;235;48;5;237m▀[48;5;236m▀[38;5;234;48;5;235m▀[48;5;234m▀▀▀[48;5;235m▀▀[38;5;235;48;5;237m▀[38;5;236;48;5;239m▀[38;5;237;48;5;240m▀[38;5;239;48;5;95m▀▀[38;5;240m▀[38;5;239;48;5;240m▀[38;5;235;48;5;236m▀[38;5;233;48;5;234m▀[38;5;235m▀[48;5;235m▀[38;5;236;48;5;236m▀▀[38;5;237;48;5;237m▀[38;5;239;48;5;238m▀[48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;101;48;5;65m▀[38;5;65m▀[38;5;241;48;5;59m▀[38;5;240m▀[38;5;241;48;5;65m▀[38;5;65m▀[48;5;101m▀[38;5;101;48;5;107m▀[38;5;107;48;5;144m▀[38;5;108m▀[38;5;144;48;5;150m▀[38;5;150m▀▀▀[38;5;186m▀▀[48;5;186m▀[38;5;150;48;5;150m▀[38;5;144;48;5;144m▀[38;5;101;48;5;101m▀▀[38;5;95;48;5;95m▀[38;5;59m▀[38;5;95;48;5;239m▀[38;5;238;48;5;237m▀[38;5;240;48;5;95m▀[38;5;144;48;5;224m▀[38;5;224;48;5;255m▀[38;5;254;48;5;224m▀[38;5;253;48;5;223m▀[38;5;187;48;5;187m▀[38;5;181;48;5;181m▀[38;5;180;48;5;180m▀[38;5;138;48;5;137m▀[38;5;137m▀▀[38;5;131m▀[38;5;95m▀▀[38;5;137m▀▀▀[38;5;101m▀[38;5;95m▀▀[38;5;240;48;5;95m▀[38;5;238m▀▀[38;5;239m▀[38;5;95m▀▀▀▀▀▀▀[38;5;237;48;5;239m▀[38;5;235;48;5;235m▀[48;5;234m▀▀[48;5;235m▀[38;5;236m▀▀[38;5;238;48;5;238m▀[38;5;239;48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;65;48;5;65m▀▀[38;5;59;48;5;241m▀[38;5;241;48;5;65m▀[38;5;65;48;5;101m▀[38;5;101;48;5;107m▀[38;5;107;48;5;144m▀[38;5;144m▀[38;5;150;48;5;150m▀▀[48;5;186m▀▀▀[38;5;186m▀[38;5;150;48;5;150m▀▀[48;5;144m▀[38;5;144m▀▀[38;5;101;48;5;137m▀[48;5;95m▀[38;5;239;48;5;59m▀[38;5;240;48;5;238m▀[38;5;236m▀[38;5;238m▀[38;5;137;48;5;180m▀[38;5;224;48;5;224m▀[38;5;255m▀[38;5;187;48;5;187m▀[48;5;181m▀[38;5;181;48;5;180m▀[38;5;180;48;5;144m▀[38;5;138;48;5;138m▀[38;5;137;48;5;137m▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;95m▀[38;5;137m▀▀[38;5;95;48;5;95m▀▀▀▀▀▀▀▀[38;5;235;48;5;237m▀[38;5;233;48;5;233m▀▀[38;5;235;48;5;234m▀▀[48;5;235m▀[38;5;237;48;5;237m▀[38;5;239;48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;65;48;5;101m▀[48;5;65m▀▀▀[38;5;107;48;5;107m▀[48;5;144m▀[38;5;144m▀▀[38;5;150;48;5;150m▀▀[38;5;186m▀[48;5;186m▀▀[48;5;150m▀[38;5;150m▀▀[38;5;144;48;5;144m▀▀[38;5;101;48;5;101m▀▀[38;5;240;48;5;239m▀[38;5;239;48;5;237m▀[38;5;237;48;5;238m▀[38;5;239;48;5;239m▀[48;5;95m▀[38;5;187;48;5;187m▀[38;5;224m▀▀[38;5;181;48;5;180m▀[38;5;180m▀▀[38;5;138m▀[48;5;144m▀[38;5;137;48;5;137m▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;131;48;5;131m▀[38;5;137m▀[38;5;131;48;5;95m▀[38;5;95m▀▀▀▀▀▀▀[38;5;238;48;5;239m▀[38;5;234;48;5;235m▀[38;5;233;48;5;234m▀▀[48;5;233m▀[38;5;234;48;5;234m▀[38;5;236;48;5;236m▀[38;5;239;48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;101;48;5;107m▀▀▀[38;5;107m▀[38;5;144;48;5;144m▀▀[38;5;150;48;5;150m▀▀▀▀▀▀▀[48;5;144m▀[38;5;144;48;5;143m▀[48;5;107m▀[38;5;143m▀[38;5;107m▀[38;5;101;48;5;101m▀[38;5;59;48;5;238m▀[38;5;236;48;5;235m▀[38;5;238;48;5;238m▀[38;5;241;48;5;241m▀[38;5;240m▀[38;5;95;48;5;101m▀[38;5;180;48;5;180m▀[38;5;187;48;5;181m▀[38;5;181;48;5;180m▀▀[38;5;180m▀▀▀[38;5;138m▀[38;5;137;48;5;137m▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;131m▀[38;5;95;48;5;131m▀[48;5;95m▀▀▀▀▀▀▀▀[38;5;239;48;5;239m▀[38;5;235;48;5;235m▀[38;5;234m▀[48;5;234m▀▀[38;5;235;48;5;235m▀[38;5;237;48;5;237m▀[38;5;239;48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;144;48;5;144m▀[38;5;108m▀▀[38;5;144m▀▀▀▀[38;5;150m▀▀[38;5;144m▀[48;5;143m▀[48;5;107m▀[38;5;143m▀[38;5;107;48;5;101m▀[48;5;65m▀▀[38;5;101m▀[48;5;101m▀[38;5;59;48;5;239m▀[38;5;237;48;5;237m▀[38;5;236;48;5;236m▀[38;5;238;48;5;239m▀[38;5;241m▀[38;5;240;48;5;59m▀[38;5;101;48;5;95m▀[38;5;180;48;5;180m▀▀[48;5;187m▀[48;5;181m▀▀[38;5;181m▀▀[38;5;180;48;5;180m▀[38;5;138;48;5;137m▀[38;5;137m▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;131m▀[38;5;137m▀[38;5;95;48;5;95m▀▀▀▀▀▀▀[48;5;240m▀[38;5;238;48;5;238m▀[38;5;235;48;5;234m▀[38;5;234m▀▀▀▀[38;5;237;48;5;236m▀[38;5;239;48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;144;48;5;150m▀[48;5;144m▀▀▀▀▀▀▀▀[48;5;107m▀[38;5;143m▀[38;5;107;48;5;101m▀[38;5;101;48;5;65m▀[38;5;65m▀▀[48;5;241m▀[38;5;59m▀[38;5;241;48;5;59m▀[38;5;238;48;5;238m▀[38;5;235;48;5;236m▀[38;5;236;48;5;237m▀[38;5;237;48;5;238m▀[38;5;240;48;5;237m▀[38;5;239;48;5;238m▀[38;5;95;48;5;137m▀[38;5;180;48;5;180m▀[38;5;181;48;5;223m▀[38;5;187;48;5;187m▀▀[48;5;138m▀[38;5;180;48;5;95m▀[38;5;144m▀[38;5;137;48;5;240m▀▀[48;5;95m▀▀[48;5;101m▀[48;5;137m▀[48;5;131m▀[48;5;137m▀▀▀▀▀▀▀▀[48;5;95m▀[38;5;95m▀[38;5;131m▀[38;5;95m▀▀▀▀▀▀[38;5;240m▀[38;5;238;48;5;238m▀[38;5;234;48;5;234m▀[38;5;233;48;5;233m▀[38;5;234;48;5;234m▀▀▀[38;5;237;48;5;236m▀[38;5;239;48;5;239m▀[48;5;240m▀[48;5;239m▀[48;5;240m▀▀▀[48;5;239m▀▀▀[48;5;240m▀▀▀▀▀▀[48;5;239m▀[0m
|
||||
[38;5;150;48;5;150m▀[38;5;144;48;5;144m▀▀▀[38;5;107;48;5;107m▀[38;5;108;48;5;108m▀[48;5;107m▀[38;5;107m▀▀[48;5;101m▀[38;5;101;48;5;65m▀[38;5;65m▀▀▀▀[38;5;241m▀[38;5;59;48;5;59m▀[38;5;238;48;5;238m▀[38;5;236;48;5;236m▀[48;5;237m▀[38;5;237;48;5;239m▀[48;5;237m▀[48;5;236m▀[38;5;239;48;5;95m▀[38;5;144;48;5;187m▀[38;5;181;48;5;223m▀[38;5;187;48;5;180m▀[38;5;181;48;5;137m▀[38;5;137;48;5;101m▀[38;5;95;48;5;95m▀[48;5;101m▀[38;5;240m▀[48;5;95m▀[38;5;239m▀▀[38;5;240m▀[38;5;95m▀▀▀▀[38;5;131m▀[38;5;137m▀▀▀[38;5;95;48;5;101m▀[48;5;95m▀[48;5;240m▀▀[38;5;239m▀[48;5;239m▀▀[38;5;240;48;5;240m▀[38;5;239m▀▀[38;5;95;48;5;239m▀[48;5;95m▀▀[38;5;239;48;5;240m▀[38;5;235;48;5;236m▀[38;5;233;48;5;233m▀[38;5;234;48;5;234m▀▀▀[38;5;236;48;5;236m▀[38;5;239;48;5;239m▀[38;5;240;48;5;240m▀▀▀▀[48;5;239m▀[38;5;239m▀[48;5;240m▀[38;5;240m▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;150;48;5;144m▀[38;5;144;48;5;143m▀▀[48;5;107m▀[38;5;107m▀▀▀[48;5;101m▀[38;5;101;48;5;65m▀[38;5;65m▀▀▀▀▀▀[48;5;59m▀[38;5;241;48;5;65m▀[38;5;239;48;5;138m▀[38;5;237;48;5;238m▀[38;5;238m▀[48;5;237m▀[38;5;236;48;5;236m▀[38;5;237;48;5;238m▀[38;5;137;48;5;180m▀[38;5;224;48;5;253m▀[38;5;187;48;5;187m▀[38;5;144;48;5;181m▀▀[38;5;138;48;5;137m▀[38;5;137m▀[48;5;95m▀[48;5;236m▀[38;5;138;48;5;235m▀[38;5;137;48;5;236m▀[38;5;101;48;5;238m▀[38;5;95;48;5;240m▀[48;5;95m▀▀▀▀▀[38;5;137;48;5;137m▀[38;5;95m▀[48;5;95m▀▀[48;5;240m▀[48;5;239m▀[38;5;239;48;5;240m▀[38;5;240;48;5;239m▀[38;5;95m▀[38;5;101;48;5;95m▀[48;5;101m▀[38;5;95;48;5;95m▀▀▀[38;5;239;48;5;239m▀[38;5;95;48;5;240m▀[38;5;240;48;5;95m▀[38;5;237;48;5;237m▀[38;5;233;48;5;233m▀[38;5;235;48;5;234m▀[38;5;234m▀[38;5;235;48;5;235m▀▀[38;5;237;48;5;237m▀[38;5;239;48;5;239m▀[38;5;240m▀▀[38;5;239m▀▀▀[38;5;240;48;5;240m▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;143;48;5;107m▀[38;5;107m▀▀[48;5;101m▀▀[38;5;101;48;5;65m▀[38;5;65m▀▀▀▀▀▀▀▀▀[38;5;59;48;5;241m▀[38;5;180;48;5;173m▀[38;5;137;48;5;131m▀[38;5;240;48;5;240m▀[38;5;238m▀[38;5;236;48;5;238m▀[38;5;238;48;5;240m▀[38;5;239;48;5;101m▀[38;5;181;48;5;187m▀[38;5;188m▀[38;5;181;48;5;144m▀[38;5;187;48;5;137m▀[38;5;137;48;5;240m▀[38;5;239;48;5;239m▀[38;5;236;48;5;95m▀[38;5;239m▀[38;5;236;48;5;240m▀▀[38;5;238;48;5;239m▀[38;5;240m▀[38;5;238m▀▀[38;5;239;48;5;238m▀[38;5;95;48;5;95m▀[38;5;131;48;5;131m▀[38;5;95m▀[38;5;137m▀[38;5;95;48;5;95m▀▀[38;5;240;48;5;239m▀[38;5;238m▀[48;5;238m▀▀[38;5;237;48;5;240m▀[38;5;235;48;5;236m▀[48;5;235m▀[38;5;234;48;5;237m▀[38;5;237m▀[38;5;95;48;5;234m▀[48;5;238m▀[48;5;95m▀[38;5;240m▀[38;5;95m▀[38;5;238;48;5;239m▀[38;5;234;48;5;235m▀[38;5;233;48;5;234m▀[38;5;234m▀[38;5;235;48;5;235m▀[38;5;238;48;5;239m▀[38;5;240m▀[38;5;239m▀▀▀▀▀▀[38;5;240;48;5;240m▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;107;48;5;107m▀[48;5;101m▀[38;5;101m▀[48;5;65m▀[38;5;65m▀▀▀▀▀▀▀▀▀[48;5;241m▀[38;5;241m▀[38;5;59;48;5;59m▀[38;5;167;48;5;131m▀[38;5;131;48;5;95m▀[38;5;101;48;5;180m▀[38;5;95;48;5;95m▀[38;5;238;48;5;239m▀[38;5;242;48;5;95m▀[38;5;138;48;5;187m▀[38;5;187m▀[38;5;180;48;5;144m▀[38;5;181;48;5;180m▀[38;5;137m▀[48;5;137m▀[48;5;95m▀▀▀▀▀[38;5;131m▀[38;5;95m▀▀▀[38;5;239m▀[38;5;240m▀[38;5;137;48;5;138m▀[38;5;131;48;5;137m▀▀[38;5;95;48;5;95m▀▀▀[38;5;240m▀[38;5;95m▀[38;5;240m▀▀[38;5;95m▀[38;5;241;48;5;101m▀[38;5;95;48;5;95m▀▀[38;5;239m▀[38;5;240m▀[38;5;239m▀[38;5;95m▀▀[38;5;240m▀[38;5;235;48;5;235m▀▀[48;5;236m▀[38;5;237;48;5;239m▀[38;5;95;48;5;95m▀[38;5;239;48;5;239m▀▀▀▀▀▀▀▀[38;5;240m▀[48;5;240m▀▀▀▀▀▀▀[0m
|
||||
[38;5;107;48;5;101m▀[38;5;101;48;5;65m▀[38;5;65m▀▀▀▀▀▀▀▀▀▀[48;5;241m▀[38;5;241m▀[38;5;59;48;5;59m▀[48;5;240m▀[38;5;173;48;5;173m▀[38;5;137;48;5;180m▀[38;5;181;48;5;137m▀[38;5;137m▀[38;5;239;48;5;95m▀[38;5;137;48;5;180m▀[38;5;187;48;5;187m▀[38;5;223;48;5;181m▀[38;5;181;48;5;180m▀[38;5;138;48;5;137m▀[38;5;137;48;5;144m▀[38;5;95;48;5;137m▀▀▀[48;5;95m▀▀▀▀▀▀[48;5;137m▀▀[38;5;137;48;5;180m▀[38;5;180m▀[38;5;137;48;5;137m▀▀[38;5;95;48;5;95m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;236;48;5;237m▀▀[38;5;238;48;5;95m▀[38;5;95m▀▀[38;5;239;48;5;239m▀▀▀▀▀▀▀▀▀▀▀[38;5;240m▀▀▀▀▀[0m
|
||||
[38;5;101;48;5;65m▀[38;5;65m▀▀▀▀▀▀▀▀▀▀▀[38;5;241;48;5;241m▀[38;5;59m▀▀[48;5;59m▀[38;5;174;48;5;137m▀[38;5;180;48;5;180m▀[38;5;95;48;5;95m▀▀[48;5;186m▀[38;5;180;48;5;180m▀▀[38;5;181m▀[38;5;180m▀[48;5;187m▀[38;5;187m▀[38;5;180;48;5;180m▀[38;5;137;48;5;137m▀▀▀▀[48;5;131m▀▀[48;5;137m▀▀▀[38;5;138;48;5;180m▀[38;5;180;48;5;181m▀[38;5;181;48;5;187m▀[38;5;137;48;5;137m▀[38;5;131;48;5;131m▀[38;5;95;48;5;95m▀▀▀▀▀▀▀[48;5;131m▀[38;5;131;48;5;137m▀▀[38;5;95m▀▀[48;5;131m▀[48;5;95m▀▀▀▀[38;5;242;48;5;101m▀[38;5;237;48;5;95m▀[38;5;95m▀▀[48;5;241m▀[38;5;239;48;5;239m▀▀▀▀▀▀[48;5;238m▀[48;5;239m▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;65;48;5;65m▀▀▀▀▀▀▀▀▀▀▀▀▀[48;5;241m▀[38;5;241m▀[38;5;59m▀[38;5;101;48;5;240m▀[38;5;174;48;5;180m▀[38;5;95;48;5;95m▀[38;5;131;48;5;137m▀[38;5;137;48;5;131m▀[38;5;180;48;5;180m▀▀▀[38;5;181;48;5;187m▀[38;5;224m▀[38;5;181;48;5;180m▀[38;5;138;48;5;137m▀[38;5;137m▀▀▀▀[38;5;131;48;5;131m▀[38;5;137m▀▀[48;5;180m▀[38;5;138m▀[38;5;180m▀[38;5;181;48;5;187m▀[38;5;187;48;5;180m▀[38;5;137;48;5;137m▀▀[38;5;131;48;5;131m▀[38;5;95;48;5;95m▀▀▀▀▀[38;5;131m▀[38;5;137;48;5;131m▀[48;5;137m▀▀▀[38;5;131m▀[48;5;131m▀[48;5;95m▀[38;5;95m▀▀▀[38;5;101m▀[38;5;95;48;5;101m▀[48;5;95m▀▀[38;5;239;48;5;239m▀▀▀▀▀▀[38;5;238;48;5;238m▀▀[38;5;239;48;5;239m▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;65;48;5;65m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;241;48;5;241m▀[38;5;59;48;5;65m▀[38;5;181;48;5;101m▀[38;5;223;48;5;180m▀[38;5;137;48;5;137m▀[48;5;173m▀[38;5;180;48;5;180m▀▀▀▀[48;5;137m▀[38;5;137m▀[48;5;131m▀[38;5;131m▀[38;5;137;48;5;95m▀[38;5;131m▀[38;5;95m▀▀▀▀[38;5;180;48;5;144m▀[38;5;181;48;5;180m▀▀[38;5;187m▀[38;5;180;48;5;137m▀[38;5;137;48;5;131m▀[48;5;137m▀[38;5;131m▀[38;5;95;48;5;95m▀▀▀▀▀▀[48;5;240m▀▀[38;5;131;48;5;95m▀[38;5;137m▀[38;5;131m▀▀[38;5;95m▀▀▀▀▀▀▀[48;5;59m▀[38;5;239;48;5;239m▀▀▀▀▀▀▀[38;5;238m▀[38;5;239m▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;65;48;5;65m▀▀▀[38;5;241;48;5;59m▀[38;5;65;48;5;241m▀[48;5;65m▀▀▀▀▀▀▀▀▀▀▀[38;5;241;48;5;241m▀[38;5;65m▀[38;5;180;48;5;245m▀[38;5;173;48;5;180m▀[38;5;180;48;5;137m▀[48;5;180m▀▀▀[38;5;137;48;5;131m▀[48;5;137m▀[38;5;95;48;5;95m▀▀▀[48;5;238m▀[38;5;240;48;5;239m▀[48;5;238m▀[38;5;95;48;5;240m▀[48;5;239m▀▀[48;5;95m▀[48;5;240m▀[38;5;137;48;5;238m▀[48;5;237m▀[38;5;131;48;5;95m▀[38;5;95m▀▀▀▀[48;5;238m▀[48;5;239m▀[38;5;240m▀[38;5;95m▀▀[48;5;240m▀[38;5;240m▀[38;5;239;48;5;238m▀[38;5;95;48;5;237m▀[48;5;95m▀▀▀▀▀▀▀▀[38;5;101;48;5;101m▀[38;5;240;48;5;239m▀[38;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;65;48;5;65m▀▀▀[38;5;59;48;5;59m▀[38;5;241;48;5;241m▀[38;5;65;48;5;65m▀▀▀[48;5;241m▀[48;5;65m▀▀▀▀▀▀▀▀[38;5;241;48;5;59m▀[38;5;65m▀[38;5;180;48;5;65m▀[38;5;181;48;5;137m▀[38;5;180m▀[48;5;180m▀[38;5;137;48;5;137m▀[38;5;95;48;5;95m▀[38;5;137;48;5;137m▀[38;5;95;48;5;95m▀[38;5;240;48;5;236m▀[38;5;235m▀[38;5;238;48;5;237m▀[38;5;237m▀[38;5;240m▀[38;5;238;48;5;239m▀[48;5;238m▀[38;5;239;48;5;239m▀[38;5;238m▀[38;5;239;48;5;238m▀[38;5;238;48;5;239m▀[48;5;238m▀[38;5;236;48;5;236m▀[38;5;238;48;5;239m▀[38;5;239m▀[48;5;238m▀[38;5;240;48;5;239m▀[38;5;236;48;5;237m▀[38;5;238m▀[38;5;237;48;5;238m▀▀[38;5;238;48;5;237m▀[38;5;239;48;5;238m▀[38;5;238;48;5;237m▀▀[38;5;236m▀[48;5;235m▀[38;5;95;48;5;238m▀[48;5;240m▀▀[48;5;95m▀▀▀▀[38;5;240;48;5;239m▀[38;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;65;48;5;65m▀▀[38;5;241;48;5;241m▀[38;5;59;48;5;59m▀▀[38;5;241;48;5;241m▀▀▀▀▀[38;5;65m▀[48;5;65m▀▀▀[48;5;241m▀[38;5;241;48;5;59m▀▀▀[38;5;59m▀▀[38;5;240;48;5;240m▀[38;5;242m▀[38;5;180;48;5;180m▀[38;5;137;48;5;137m▀[38;5;95;48;5;95m▀[38;5;137;48;5;137m▀[38;5;95;48;5;95m▀[38;5;236;48;5;239m▀▀[48;5;238m▀[38;5;237;48;5;236m▀▀[48;5;238m▀[38;5;239;48;5;239m▀▀[38;5;238;48;5;238m▀[38;5;237m▀[38;5;239;48;5;237m▀[38;5;237;48;5;236m▀[38;5;236m▀▀[38;5;237;48;5;237m▀[48;5;235m▀[38;5;238;48;5;236m▀[38;5;237;48;5;237m▀[48;5;238m▀[48;5;236m▀[38;5;239;48;5;237m▀[38;5;237;48;5;235m▀[48;5;238m▀[48;5;237m▀[48;5;235m▀[48;5;236m▀[38;5;234m▀[38;5;239;48;5;239m▀[38;5;240;48;5;240m▀▀[38;5;95m▀[38;5;241m▀[38;5;240;48;5;239m▀[38;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;65;48;5;65m▀▀[38;5;59;48;5;241m▀[48;5;59m▀▀▀[38;5;241;48;5;241m▀▀[48;5;59m▀[48;5;241m▀▀▀[38;5;65;48;5;65m▀▀[48;5;241m▀[38;5;241m▀▀[38;5;59;48;5;59m▀▀[38;5;240;48;5;240m▀▀▀[38;5;180;48;5;143m▀[38;5;137;48;5;137m▀[38;5;95;48;5;95m▀[48;5;240m▀[48;5;95m▀▀[38;5;240m▀[38;5;95m▀[38;5;240m▀[38;5;237;48;5;240m▀[38;5;236;48;5;239m▀[38;5;235;48;5;237m▀[38;5;240;48;5;242m▀[38;5;239;48;5;101m▀[38;5;237;48;5;138m▀[38;5;238m▀[38;5;236;48;5;101m▀[38;5;234m▀[38;5;238;48;5;95m▀[38;5;236;48;5;240m▀[38;5;237;48;5;59m▀[38;5;235;48;5;95m▀▀[38;5;237;48;5;101m▀[38;5;235;48;5;241m▀[38;5;236;48;5;238m▀[38;5;234m▀[38;5;236m▀[38;5;237;48;5;239m▀[38;5;239;48;5;240m▀[38;5;240;48;5;59m▀[48;5;95m▀[38;5;95m▀[38;5;240;48;5;240m▀[48;5;239m▀[48;5;240m▀[38;5;239;48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;65;48;5;241m▀[38;5;241m▀[38;5;59;48;5;59m▀▀[48;5;65m▀[38;5;241m▀[38;5;65m▀▀▀▀[38;5;241m▀[38;5;65m▀[38;5;241m▀[38;5;65m▀[38;5;241m▀[48;5;241m▀▀[38;5;59;48;5;59m▀[48;5;240m▀[38;5;240m▀▀▀[38;5;137;48;5;101m▀[48;5;137m▀▀[38;5;95;48;5;95m▀▀▀▀▀▀▀▀[38;5;239m▀[38;5;236;48;5;239m▀[38;5;59;48;5;238m▀[38;5;144;48;5;102m▀[38;5;245;48;5;95m▀[38;5;248;48;5;239m▀[38;5;249;48;5;240m▀[48;5;238m▀[38;5;248;48;5;237m▀[48;5;238m▀[38;5;247;48;5;239m▀[38;5;243;48;5;238m▀[38;5;246;48;5;241m▀[38;5;239;48;5;239m▀[38;5;235m▀[38;5;238m▀[38;5;239;48;5;95m▀[38;5;95m▀▀[48;5;240m▀▀[38;5;240;48;5;239m▀[38;5;239m▀[48;5;240m▀[38;5;240;48;5;239m▀[38;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[48;5;240m▀[48;5;239m▀▀[38;5;240;48;5;240m▀▀[0m
|
||||
[38;5;65;48;5;241m▀[38;5;241m▀[38;5;59;48;5;65m▀[38;5;65m▀▀▀▀[48;5;101m▀▀▀▀▀[48;5;65m▀[48;5;242m▀▀[38;5;241;48;5;65m▀[48;5;59m▀[38;5;59;48;5;241m▀[38;5;240;48;5;59m▀[48;5;240m▀▀[48;5;239m▀[38;5;101;48;5;101m▀[38;5;143;48;5;180m▀[38;5;137;48;5;137m▀[38;5;95m▀[48;5;95m▀▀▀▀▀▀[48;5;101m▀[48;5;137m▀▀[48;5;131m▀[38;5;240;48;5;95m▀[38;5;246m▀[38;5;247m▀[38;5;248m▀[38;5;245m▀[38;5;248m▀[38;5;247m▀[38;5;243m▀[38;5;239m▀▀▀▀[38;5;95m▀▀▀▀[38;5;240m▀[48;5;240m▀[48;5;239m▀[48;5;240m▀[48;5;239m▀[38;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;240m▀▀▀[48;5;240m▀[0m
|
||||
[38;5;241;48;5;241m▀[48;5;65m▀[38;5;65m▀▀▀▀[38;5;101;48;5;101m▀▀▀▀▀▀▀[38;5;243m▀[38;5;65;48;5;242m▀[38;5;242m▀[38;5;241m▀[48;5;243m▀[38;5;59;48;5;245m▀[38;5;240;48;5;247m▀[48;5;246m▀[38;5;239m▀[38;5;245;48;5;181m▀[38;5;180;48;5;180m▀[38;5;137m▀[48;5;137m▀[38;5;95m▀[48;5;95m▀▀▀▀[48;5;101m▀▀[38;5;101;48;5;137m▀[38;5;137m▀[48;5;101m▀[38;5;131;48;5;95m▀[38;5;95m▀▀▀[38;5;101;48;5;240m▀[38;5;95;48;5;95m▀▀▀▀▀▀▀▀▀▀▀[38;5;59;48;5;59m▀[38;5;240;48;5;240m▀[48;5;239m▀[38;5;239;48;5;240m▀[48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;65;48;5;101m▀▀▀▀▀▀[38;5;101m▀▀▀▀▀▀▀▀[38;5;65m▀[48;5;65m▀[38;5;241;48;5;145m▀[38;5;255;48;5;231m▀[38;5;174;48;5;180m▀[38;5;131;48;5;131m▀▀▀[38;5;180;48;5;223m▀[48;5;180m▀▀[38;5;137m▀[48;5;137m▀[38;5;95m▀[38;5;101;48;5;95m▀[38;5;137;48;5;137m▀▀[38;5;95m▀[38;5;137m▀[38;5;101m▀[48;5;95m▀[38;5;131;48;5;131m▀[38;5;95;48;5;95m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[48;5;59m▀[38;5;240;48;5;240m▀[48;5;239m▀[38;5;239;48;5;240m▀[38;5;240m▀[38;5;239;48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;107;48;5;107m▀[38;5;101m▀▀[48;5;101m▀▀▀[48;5;107m▀[48;5;108m▀▀[38;5;107m▀[38;5;245m▀[38;5;101;48;5;101m▀▀▀▀[38;5;242;48;5;249m▀[38;5;231;48;5;231m▀▀[38;5;181;48;5;255m▀[38;5;131;48;5;131m▀[38;5;95;48;5;95m▀[48;5;131m▀[38;5;223;48;5;223m▀[38;5;180;48;5;180m▀▀▀[38;5;137;48;5;137m▀▀[38;5;95m▀[38;5;101;48;5;101m▀[38;5;137;48;5;137m▀▀▀▀▀[38;5;95m▀▀▀[48;5;95m▀▀▀▀▀▀▀▀▀▀▀▀[48;5;59m▀[38;5;240;48;5;240m▀[38;5;239m▀[38;5;240m▀[38;5;95;48;5;95m▀[38;5;240;48;5;239m▀[38;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;143;48;5;144m▀[38;5;107;48;5;143m▀[48;5;107m▀▀[38;5;101;48;5;101m▀[38;5;107;48;5;107m▀[38;5;108m▀[48;5;108m▀▀[48;5;107m▀[38;5;107m▀[38;5;101;48;5;101m▀▀▀[48;5;145m▀[38;5;255;48;5;231m▀[38;5;231m▀▀▀[38;5;131;48;5;174m▀[48;5;95m▀[38;5;174;48;5;223m▀[38;5;223;48;5;187m▀[38;5;180;48;5;180m▀▀▀[38;5;179;48;5;179m▀[38;5;137;48;5;137m▀▀▀[48;5;95m▀[48;5;137m▀▀▀▀▀[38;5;95;48;5;95m▀[38;5;131m▀[38;5;95m▀▀▀[48;5;101m▀[38;5;137m▀[38;5;95;48;5;95m▀▀▀▀▀▀[48;5;240m▀[38;5;240;48;5;239m▀[38;5;239;48;5;240m▀[38;5;240m▀[38;5;95m▀[48;5;95m▀[38;5;239;48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[48;5;240m▀[48;5;239m▀▀▀▀▀▀[0m
|
||||
[38;5;144;48;5;144m▀[38;5;143m▀[48;5;143m▀[38;5;107;48;5;107m▀[38;5;101m▀[38;5;107m▀▀[38;5;108m▀▀[48;5;108m▀▀[38;5;107;48;5;107m▀[48;5;108m▀[38;5;101;48;5;144m▀[38;5;255;48;5;231m▀[38;5;231m▀▀▀▀[38;5;224m▀[38;5;94;48;5;95m▀[38;5;223;48;5;223m▀[38;5;181;48;5;180m▀[38;5;180m▀[48;5;179m▀[38;5;179;48;5;173m▀▀[38;5;137;48;5;137m▀▀▀[38;5;95;48;5;95m▀▀[38;5;137m▀▀▀[38;5;95m▀▀▀▀▀▀▀▀▀▀▀▀[38;5;240;48;5;240m▀[48;5;239m▀[38;5;239m▀▀[38;5;240;48;5;240m▀▀[38;5;95;48;5;95m▀[48;5;101m▀[38;5;239;48;5;240m▀[48;5;239m▀▀▀▀▀▀▀▀▀▀▀▀[38;5;240;48;5;240m▀▀▀▀▀▀▀▀▀[38;5;239m▀▀▀[0m
|
||||
[38;5;150;48;5;186m▀[38;5;144;48;5;144m▀[38;5;143;48;5;143m▀[38;5;107;48;5;107m▀▀▀[48;5;143m▀▀[38;5;143m▀[38;5;107m▀▀▀[48;5;108m▀[38;5;252;48;5;231m▀[38;5;231m▀▀▀▀▀[38;5;255;48;5;224m▀[38;5;138m▀[38;5;223;48;5;180m▀[38;5;180m▀▀[38;5;179;48;5;173m▀[38;5;173m▀[48;5;137m▀[38;5;137m▀▀[48;5;131m▀[38;5;95;48;5;95m▀▀▀▀[48;5;240m▀[48;5;239m▀▀▀▀[48;5;240m▀[38;5;240;48;5;239m▀▀▀▀▀[48;5;238m▀▀[38;5;239;48;5;239m▀▀▀[48;5;240m▀[38;5;240m▀[48;5;95m▀[38;5;95m▀[38;5;138;48;5;144m▀[38;5;243;48;5;247m▀[38;5;239;48;5;239m▀▀▀▀▀▀▀▀▀▀[38;5;240;48;5;240m▀▀▀▀▀▀▀▀▀[48;5;59m▀[48;5;240m▀[48;5;59m▀[48;5;241m▀▀[0m
|
||||
[38;5;150;48;5;150m▀[38;5;144;48;5;144m▀[38;5;143;48;5;143m▀[38;5;107m▀[48;5;107m▀▀[38;5;143;48;5;143m▀▀▀[48;5;151m▀[48;5;255m▀[38;5;144;48;5;231m▀[38;5;188m▀[38;5;231m▀▀▀▀▀▀▀[48;5;255m▀[38;5;144;48;5;224m▀[38;5;180;48;5;95m▀[48;5;180m▀[38;5;173;48;5;173m▀[38;5;137;48;5;137m▀▀▀[38;5;131;48;5;95m▀[38;5;95m▀▀▀▀▀[38;5;240m▀[38;5;239;48;5;239m▀▀▀[38;5;238m▀▀▀▀[48;5;238m▀▀▀[48;5;239m▀[38;5;239;48;5;238m▀▀[48;5;239m▀[48;5;240m▀[38;5;240m▀[38;5;95m▀[38;5;240;48;5;95m▀[38;5;95m▀[38;5;138;48;5;138m▀[38;5;181;48;5;251m▀[38;5;239;48;5;240m▀[48;5;239m▀▀▀▀▀▀▀▀[38;5;240;48;5;240m▀▀▀▀▀▀▀[48;5;59m▀▀[38;5;59m▀▀[48;5;241m▀[38;5;241;48;5;65m▀[38;5;65m▀▀[0m
|
||||
[38;5;150;48;5;150m▀[38;5;144;48;5;149m▀[38;5;143;48;5;143m▀[48;5;144m▀[48;5;187m▀[48;5;255m▀[38;5;144;48;5;231m▀[38;5;252m▀[38;5;231;48;5;255m▀[48;5;231m▀[38;5;255;48;5;224m▀[38;5;224;48;5;182m▀[38;5;231;48;5;231m▀▀▀▀▀▀▀▀▀[38;5;255;48;5;224m▀[38;5;138;48;5;252m▀[38;5;137;48;5;95m▀[48;5;131m▀[48;5;137m▀▀▀[38;5;131;48;5;131m▀[48;5;95m▀[38;5;95m▀▀▀▀[48;5;240m▀[38;5;239;48;5;239m▀▀▀▀▀▀▀[48;5;238m▀▀[38;5;238m▀▀[48;5;239m▀[38;5;239m▀▀[38;5;95;48;5;95m▀▀▀▀[48;5;239m▀[38;5;138;48;5;138m▀[38;5;181;48;5;181m▀[38;5;244;48;5;247m▀[38;5;240;48;5;240m▀[38;5;239m▀[38;5;240m▀[38;5;239m▀▀▀▀[38;5;240m▀▀▀▀[48;5;59m▀▀▀▀▀[38;5;59m▀[38;5;240m▀[38;5;59m▀[38;5;241;48;5;241m▀[38;5;65;48;5;65m▀▀[38;5;101;48;5;101m▀[0m
|
||||
[38;5;150;48;5;231m▀[38;5;187m▀[38;5;255;48;5;255m▀[38;5;231m▀[48;5;224m▀[38;5;255m▀[38;5;231;48;5;231m▀[38;5;255;48;5;255m▀[38;5;231;48;5;254m▀[38;5;254;48;5;224m▀[38;5;224m▀[38;5;181;48;5;252m▀[38;5;231;48;5;255m▀[48;5;231m▀▀▀▀▀▀▀[38;5;255;48;5;255m▀[38;5;254m▀[38;5;224;48;5;254m▀[38;5;181;48;5;253m▀[38;5;239;48;5;138m▀[38;5;95;48;5;95m▀[38;5;131m▀▀▀[38;5;95m▀▀▀▀▀▀▀[38;5;240;48;5;240m▀[38;5;239;48;5;239m▀▀▀▀▀[38;5;238m▀▀[38;5;239m▀[38;5;238m▀[38;5;239;48;5;240m▀[48;5;95m▀[38;5;95m▀▀[48;5;240m▀[48;5;239m▀[38;5;239;48;5;238m▀[38;5;237;48;5;95m▀[38;5;248;48;5;181m▀[38;5;181;48;5;251m▀[38;5;249m▀[38;5;59;48;5;247m▀[48;5;242m▀[38;5;240;48;5;241m▀▀[48;5;59m▀▀▀[48;5;241m▀[38;5;59;48;5;242m▀▀[38;5;241m▀[48;5;65m▀▀▀▀[38;5;59;48;5;241m▀▀[48;5;59m▀▀[38;5;241;48;5;241m▀[38;5;65;48;5;65m▀▀[38;5;101;48;5;101m▀[0m
|
||||
[38;5;255;48;5;253m▀[38;5;224;48;5;252m▀[48;5;188m▀[38;5;188m▀[48;5;253m▀[38;5;255;48;5;231m▀[38;5;231m▀[38;5;255;48;5;224m▀[38;5;224m▀▀[38;5;252;48;5;252m▀▀[38;5;254;48;5;253m▀[38;5;231;48;5;231m▀▀▀▀▀▀▀[38;5;255m▀[48;5;255m▀▀[38;5;254;48;5;254m▀[38;5;224m▀[38;5;95;48;5;181m▀[48;5;95m▀▀▀▀▀▀▀▀▀▀▀▀[38;5;239m▀[38;5;240m▀[38;5;239m▀▀[38;5;240m▀[38;5;239;48;5;239m▀▀[38;5;240m▀[48;5;95m▀[38;5;95;48;5;239m▀[38;5;240;48;5;240m▀[48;5;239m▀[38;5;239m▀[38;5;238;48;5;238m▀[48;5;138m▀[38;5;181;48;5;181m▀[48;5;251m▀[48;5;181m▀[38;5;251;48;5;251m▀[38;5;252;48;5;252m▀[38;5;188;48;5;224m▀[38;5;246m▀[38;5;243;48;5;181m▀[48;5;246m▀[38;5;244;48;5;108m▀▀[38;5;102;48;5;247m▀▀[38;5;244;48;5;108m▀▀▀[48;5;245m▀[38;5;243;48;5;244m▀[38;5;65m▀[48;5;243m▀[38;5;241;48;5;65m▀[38;5;59;48;5;241m▀[48;5;59m▀[38;5;241m▀▀[38;5;65;48;5;65m▀[38;5;101m▀[0m
|
||||
[38;5;252;48;5;252m▀▀[38;5;188;48;5;188m▀[48;5;254m▀[38;5;255;48;5;231m▀[38;5;231m▀[38;5;255;48;5;224m▀[38;5;224m▀▀[48;5;188m▀[38;5;252;48;5;252m▀▀[38;5;224;48;5;254m▀[38;5;231;48;5;255m▀[48;5;231m▀▀▀▀▀▀[48;5;255m▀[38;5;255m▀▀▀[38;5;224;48;5;254m▀[38;5;253;48;5;188m▀[38;5;181;48;5;138m▀[38;5;240;48;5;95m▀[38;5;95m▀▀▀[48;5;240m▀[48;5;95m▀▀▀▀▀▀▀▀▀▀▀[38;5;239;48;5;239m▀▀[38;5;240;48;5;95m▀[38;5;95m▀[48;5;240m▀[38;5;239;48;5;239m▀▀[38;5;238;48;5;238m▀[48;5;95m▀[38;5;181;48;5;138m▀[48;5;251m▀[38;5;251m▀[38;5;181m▀[38;5;251m▀[38;5;252m▀▀[48;5;181m▀▀[38;5;250;48;5;252m▀[38;5;247;48;5;250m▀[48;5;248m▀[38;5;248;48;5;145m▀▀▀[38;5;247;48;5;248m▀[38;5;108m▀[48;5;247m▀[38;5;245;48;5;108m▀[38;5;102m▀[38;5;244;48;5;102m▀[38;5;243;48;5;101m▀[38;5;65;48;5;65m▀[38;5;241m▀[38;5;240;48;5;241m▀[48;5;240m▀▀[38;5;65m▀[0m
|
||||
[38;5;252;48;5;252m▀▀[38;5;188;48;5;253m▀[38;5;255;48;5;255m▀[38;5;231;48;5;231m▀[38;5;255;48;5;224m▀[38;5;224;48;5;188m▀▀▀[38;5;188;48;5;252m▀[38;5;252m▀[38;5;188;48;5;253m▀[38;5;253;48;5;224m▀[38;5;255;48;5;254m▀[38;5;231;48;5;231m▀▀▀▀▀▀▀[38;5;255m▀▀[38;5;231;48;5;182m▀[38;5;181;48;5;181m▀▀▀[38;5;95m▀[48;5;95m▀▀[38;5;240m▀[38;5;239;48;5;239m▀▀▀▀[38;5;95;48;5;240m▀[48;5;95m▀▀▀▀▀[38;5;240m▀[48;5;240m▀[38;5;239m▀[38;5;95;48;5;95m▀▀[48;5;240m▀[38;5;239;48;5;239m▀▀▀[38;5;237;48;5;236m▀[38;5;138;48;5;95m▀[38;5;181;48;5;248m▀[38;5;239m▀[38;5;181;48;5;95m▀[38;5;251;48;5;251m▀[48;5;181m▀[48;5;251m▀▀[38;5;181;48;5;181m▀▀▀[38;5;251m▀[38;5;252;48;5;252m▀[38;5;250m▀[38;5;249m▀[48;5;251m▀[48;5;249m▀[38;5;145m▀[38;5;144;48;5;248m▀[38;5;108;48;5;144m▀▀▀[48;5;108m▀▀[38;5;245m▀[38;5;244;48;5;102m▀[38;5;243;48;5;101m▀[38;5;65m▀▀[0m
|
||||
[38;5;252;48;5;252m▀[48;5;188m▀[38;5;254;48;5;254m▀[38;5;231;48;5;231m▀[48;5;255m▀[38;5;253;48;5;188m▀[38;5;188m▀[48;5;252m▀[38;5;252m▀▀▀[38;5;253;48;5;253m▀[48;5;254m▀[48;5;253m▀[38;5;255;48;5;255m▀[38;5;231;48;5;231m▀▀▀▀▀▀[48;5;254m▀[38;5;188;48;5;175m▀[38;5;181;48;5;181m▀[48;5;138m▀[48;5;181m▀▀[38;5;252;48;5;252m▀[38;5;188;48;5;224m▀[38;5;95;48;5;138m▀[48;5;95m▀▀[38;5;240m▀[38;5;239;48;5;239m▀[48;5;240m▀[48;5;239m▀▀[38;5;95m▀[38;5;240m▀[48;5;95m▀▀▀▀[38;5;95m▀▀▀[38;5;239m▀[48;5;239m▀▀▀[38;5;236;48;5;236m▀[38;5;95;48;5;95m▀[38;5;145;48;5;145m▀[38;5;181;48;5;181m▀[38;5;95;48;5;95m▀[38;5;181;48;5;248m▀[38;5;250;48;5;181m▀[38;5;251m▀[48;5;251m▀[38;5;181;48;5;181m▀▀▀▀▀[38;5;252;48;5;251m▀▀[48;5;252m▀▀[38;5;251;48;5;188m▀[38;5;145;48;5;252m▀[38;5;144;48;5;250m▀[48;5;248m▀[48;5;144m▀[48;5;108m▀[38;5;108m▀▀▀[48;5;144m▀▀▀[0m
|
||||
[38;5;252;48;5;252m▀[38;5;188;48;5;188m▀[38;5;255;48;5;255m▀[38;5;231;48;5;231m▀[38;5;254;48;5;188m▀[38;5;188;48;5;252m▀▀[38;5;252m▀▀▀[48;5;188m▀[38;5;254;48;5;254m▀[38;5;253;48;5;253m▀▀[38;5;255;48;5;254m▀[48;5;255m▀▀[38;5;231;48;5;231m▀▀▀▀[38;5;252;48;5;175m▀[38;5;181;48;5;181m▀▀▀▀[48;5;252m▀[38;5;224;48;5;188m▀[38;5;181;48;5;138m▀[38;5;95;48;5;95m▀▀▀[38;5;239m▀▀[48;5;240m▀[48;5;239m▀▀[48;5;240m▀[38;5;95;48;5;95m▀▀▀▀▀▀▀▀▀▀[48;5;240m▀[38;5;239;48;5;239m▀[38;5;235;48;5;95m▀[38;5;95;48;5;137m▀[38;5;181;48;5;181m▀[48;5;251m▀[38;5;95;48;5;131m▀[38;5;138;48;5;248m▀[38;5;181;48;5;251m▀▀▀▀[48;5;181m▀▀▀▀▀[38;5;251m▀[38;5;181m▀[38;5;252m▀▀[48;5;251m▀[38;5;188;48;5;252m▀[38;5;252m▀[38;5;250;48;5;188m▀[38;5;144;48;5;187m▀[48;5;249m▀[48;5;144m▀▀▀▀[48;5;150m▀[0m
|
||||
[38;5;252;48;5;252m▀[38;5;188;48;5;253m▀[38;5;255;48;5;231m▀[48;5;224m▀[38;5;252;48;5;252m▀▀[48;5;251m▀[38;5;251m▀▀[38;5;252;48;5;252m▀[38;5;188;48;5;188m▀[38;5;254;48;5;253m▀[38;5;253;48;5;188m▀[38;5;254;48;5;254m▀▀[38;5;255;48;5;255m▀▀▀[38;5;231m▀[48;5;231m▀[38;5;255;48;5;255m▀[38;5;132;48;5;138m▀[38;5;181;48;5;181m▀▀▀▀[38;5;188;48;5;252m▀[38;5;138;48;5;95m▀[38;5;95m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[48;5;138m▀[38;5;138m▀[38;5;137m▀[38;5;248;48;5;181m▀[38;5;181;48;5;95m▀[38;5;132;48;5;132m▀[38;5;181;48;5;181m▀[38;5;251m▀[48;5;251m▀[38;5;181m▀[38;5;251m▀[38;5;181;48;5;181m▀▀▀▀▀▀▀▀▀▀▀[38;5;251m▀[38;5;252m▀[48;5;251m▀▀[38;5;187;48;5;252m▀▀[38;5;144;48;5;187m▀[38;5;150m▀▀[0m
|
||||
[38;5;252;48;5;252m▀[38;5;254;48;5;254m▀[38;5;255;48;5;255m▀[38;5;252;48;5;252m▀▀[48;5;251m▀[38;5;251m▀[38;5;181;48;5;181m▀[38;5;251m▀[48;5;251m▀[38;5;188;48;5;252m▀[38;5;253;48;5;188m▀[38;5;252;48;5;252m▀[38;5;253;48;5;188m▀[38;5;254;48;5;253m▀[38;5;253;48;5;188m▀[38;5;255;48;5;255m▀▀▀[38;5;231;48;5;231m▀[38;5;224;48;5;252m▀[38;5;175;48;5;181m▀[38;5;174;48;5;132m▀[38;5;181;48;5;181m▀[38;5;252;48;5;188m▀[48;5;224m▀[38;5;224;48;5;138m▀[38;5;95;48;5;95m▀▀▀▀▀▀▀[48;5;131m▀[48;5;95m▀▀▀▀▀▀[38;5;131m▀[48;5;131m▀[38;5;95;48;5;95m▀▀▀▀▀[38;5;239m▀[38;5;181;48;5;181m▀[38;5;138m▀[48;5;138m▀[48;5;145m▀[48;5;138m▀[48;5;181m▀[38;5;181m▀▀▀[38;5;251m▀[38;5;181m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;251;48;5;251m▀[38;5;252;48;5;252m▀▀[38;5;251;48;5;251m▀[38;5;181;48;5;181m▀[38;5;187m▀[0m
|
||||
[38;5;252;48;5;252m▀[38;5;255;48;5;255m▀[38;5;254;48;5;188m▀[38;5;181;48;5;181m▀▀[38;5;251m▀▀[38;5;181m▀▀▀[38;5;252;48;5;252m▀▀▀▀[38;5;253;48;5;188m▀[38;5;188m▀[38;5;224;48;5;252m▀[48;5;254m▀[38;5;255;48;5;231m▀[38;5;231;48;5;255m▀[38;5;251;48;5;181m▀[38;5;181m▀[38;5;138m▀[38;5;181;48;5;138m▀[38;5;255;48;5;255m▀[38;5;188;48;5;181m▀[38;5;95;48;5;138m▀[48;5;95m▀▀▀▀▀▀▀▀[38;5;137m▀[48;5;137m▀▀[38;5;95;48;5;95m▀▀[48;5;131m▀[38;5;137m▀[38;5;131;48;5;95m▀[38;5;95m▀▀▀▀▀[38;5;181;48;5;181m▀▀[48;5;138m▀[38;5;138;48;5;181m▀[38;5;181;48;5;138m▀[38;5;138;48;5;181m▀[38;5;181;48;5;251m▀[48;5;181m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;188;48;5;254m▀[38;5;255;48;5;253m▀[38;5;251;48;5;181m▀[38;5;181m▀▀▀▀▀▀[38;5;251m▀[38;5;252;48;5;251m▀[48;5;252m▀[48;5;251m▀▀[48;5;252m▀▀[38;5;251m▀[38;5;255;48;5;254m▀[38;5;231;48;5;255m▀[38;5;188;48;5;182m▀[38;5;181m▀[48;5;251m▀▀[38;5;138;48;5;181m▀[38;5;224;48;5;95m▀[38;5;181;48;5;181m▀▀[38;5;95m▀[48;5;95m▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;131m▀▀[38;5;95m▀▀▀▀[38;5;137;48;5;180m▀[38;5;181;48;5;181m▀▀▀[38;5;145m▀[38;5;132;48;5;138m▀[38;5;181;48;5;251m▀[48;5;181m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[0m
|
||||
[38;5;254;48;5;224m▀[38;5;252;48;5;181m▀[38;5;181m▀▀▀▀▀▀[48;5;251m▀▀[38;5;251m▀[38;5;252;48;5;252m▀[38;5;251;48;5;251m▀▀[38;5;252m▀[48;5;252m▀[48;5;251m▀[48;5;181m▀▀[38;5;181m▀[38;5;251;48;5;251m▀▀▀[38;5;181m▀[38;5;138;48;5;181m▀[48;5;138m▀[38;5;181m▀[48;5;181m▀▀[38;5;137m▀[38;5;95;48;5;138m▀[48;5;95m▀▀▀▀▀▀▀▀▀▀▀▀▀▀[48;5;138m▀[38;5;180;48;5;181m▀[38;5;181;48;5;95m▀▀[48;5;248m▀[38;5;249;48;5;181m▀[38;5;181m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;145;48;5;248m▀[38;5;181;48;5;181m▀▀[48;5;145m▀[0m
|
||||
[38;5;188;48;5;251m▀[38;5;181;48;5;181m▀▀▀▀▀▀▀▀▀[38;5;251;48;5;251m▀▀▀▀▀[38;5;252;48;5;252m▀[38;5;251;48;5;251m▀▀▀[48;5;252m▀[38;5;252m▀[38;5;181;48;5;251m▀[48;5;181m▀[38;5;251m▀[48;5;251m▀[38;5;181m▀[38;5;138;48;5;181m▀[38;5;95;48;5;138m▀[38;5;181;48;5;131m▀▀[48;5;181m▀[38;5;137m▀[38;5;95;48;5;95m▀▀▀▀▀▀▀▀▀▀▀▀[38;5;131;48;5;181m▀[38;5;181;48;5;248m▀[38;5;138;48;5;181m▀[38;5;96m▀[38;5;248m▀[38;5;181m▀▀▀▀[38;5;249m▀[38;5;181m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;145m▀[38;5;181m▀▀▀[38;5;145m▀[38;5;181m▀[48;5;145m▀[38;5;145;48;5;248m▀[0m
|
||||
[38;5;181;48;5;181m▀▀▀▀▀▀▀▀▀▀[38;5;251;48;5;251m▀▀[48;5;181m▀[38;5;181m▀[38;5;251m▀[48;5;251m▀▀[38;5;181;48;5;181m▀▀[38;5;251;48;5;251m▀[38;5;188;48;5;188m▀[38;5;251;48;5;252m▀[48;5;181m▀[38;5;181m▀[38;5;251m▀[48;5;251m▀[38;5;181m▀[48;5;181m▀▀[48;5;251m▀[38;5;138;48;5;188m▀[38;5;174;48;5;181m▀[38;5;181;48;5;138m▀[38;5;95;48;5;181m▀[48;5;95m▀▀▀▀▀▀▀▀[48;5;138m▀[38;5;138;48;5;248m▀[38;5;181;48;5;181m▀▀▀▀▀▀▀[48;5;249m▀[38;5;145;48;5;181m▀[38;5;181m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[48;5;248m▀[48;5;181m▀▀▀▀▀[48;5;145m▀[48;5;181m▀▀▀[38;5;145;48;5;248m▀▀[0m
|
||||
[38;5;181;48;5;181m▀▀▀▀▀▀▀▀▀▀[38;5;251;48;5;251m▀▀[38;5;181;48;5;181m▀▀▀[48;5;250m▀[48;5;181m▀▀▀▀[38;5;252;48;5;251m▀[48;5;252m▀[38;5;251;48;5;251m▀[38;5;181;48;5;181m▀▀[38;5;251;48;5;251m▀▀▀[38;5;181;48;5;181m▀[38;5;188;48;5;251m▀[38;5;181;48;5;253m▀[48;5;254m▀[38;5;182;48;5;181m▀[38;5;181;48;5;251m▀[48;5;181m▀[38;5;95;48;5;138m▀[48;5;95m▀▀▀▀▀[38;5;138;48;5;181m▀[38;5;248;48;5;249m▀[38;5;181;48;5;181m▀▀▀▀▀▀▀[38;5;249;48;5;249m▀[48;5;181m▀[38;5;181m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;145m▀[38;5;248;48;5;248m▀[38;5;181;48;5;181m▀▀▀▀▀▀▀[38;5;145;48;5;145m▀[38;5;248;48;5;248m▀▀[0m
|
||||
[38;5;181;48;5;249m▀[48;5;181m▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;250;48;5;250m▀[38;5;181;48;5;181m▀▀▀▀[38;5;251;48;5;251m▀[38;5;252m▀[48;5;252m▀[38;5;181;48;5;251m▀[48;5;181m▀▀[38;5;251m▀▀[38;5;181m▀▀[38;5;251;48;5;251m▀[38;5;181m▀[38;5;251;48;5;181m▀[38;5;181m▀[38;5;251;48;5;251m▀[38;5;181m▀[38;5;95;48;5;138m▀[48;5;95m▀▀[48;5;238m▀[38;5;248;48;5;181m▀[48;5;249m▀[38;5;181;48;5;181m▀▀▀▀▀▀▀[38;5;249m▀[48;5;249m▀[38;5;181;48;5;181m▀▀▀▀▀▀▀▀▀▀▀▀[48;5;249m▀[48;5;181m▀▀▀▀▀[38;5;248;48;5;145m▀[48;5;248m▀[38;5;181;48;5;145m▀[48;5;181m▀▀▀▀▀[38;5;248;48;5;145m▀[48;5;248m▀▀[0m
|
||||
[38;5;145;48;5;145m▀▀[38;5;249;48;5;249m▀[38;5;181;48;5;181m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;251m▀[48;5;251m▀▀[38;5;181m▀[48;5;181m▀▀▀▀▀▀▀▀▀▀▀▀▀[38;5;95;48;5;95m▀[38;5;240;48;5;239m▀[38;5;138;48;5;181m▀[38;5;181m▀[38;5;249m▀[38;5;181m▀▀▀▀▀▀▀[38;5;145;48;5;145m▀[38;5;249;48;5;249m▀[38;5;181;48;5;181m▀▀▀[48;5;249m▀[38;5;249;48;5;181m▀▀[38;5;181m▀▀▀▀▀[48;5;249m▀[38;5;249;48;5;145m▀[38;5;181;48;5;181m▀▀▀▀▀[38;5;145m▀[38;5;248;48;5;248m▀▀[38;5;145;48;5;145m▀[38;5;181m▀▀[48;5;181m▀[48;5;145m▀[38;5;145m▀[38;5;248;48;5;248m▀▀[0m
|
||||
[38;5;145;48;5;248m▀[48;5;145m▀[38;5;249;48;5;249m▀[38;5;181;48;5;181m▀▀▀▀▀▀▀▀▀[48;5;249m▀▀[48;5;181m▀▀▀▀▀▀▀▀[38;5;251m▀▀[38;5;181m▀▀▀▀▀▀▀▀▀▀▀▀[38;5;252;48;5;251m▀[38;5;240;48;5;240m▀[38;5;95;48;5;181m▀[38;5;181m▀▀▀▀▀▀▀▀▀[48;5;145m▀[38;5;248m▀[38;5;249;48;5;249m▀[38;5;181;48;5;181m▀▀▀[48;5;249m▀▀[38;5;249m▀[38;5;181;48;5;181m▀▀▀▀▀[48;5;249m▀[38;5;145;48;5;145m▀[38;5;181m▀[48;5;249m▀[48;5;145m▀[48;5;181m▀▀[38;5;249m▀[38;5;248;48;5;248m▀▀▀[38;5;145m▀▀▀▀[38;5;248m▀[38;5;138m▀[38;5;248;48;5;247m▀[0m
|
||||
[38;5;145;48;5;248m▀[48;5;145m▀[38;5;249m▀[48;5;249m▀[38;5;181m▀▀[48;5;181m▀[38;5;249;48;5;249m▀[38;5;181;48;5;181m▀▀▀▀[48;5;249m▀[38;5;249m▀[38;5;181m▀[38;5;249m▀[38;5;181;48;5;181m▀▀[48;5;249m▀[48;5;181m▀[48;5;249m▀[38;5;250;48;5;250m▀[38;5;181;48;5;181m▀▀▀▀[38;5;249;48;5;249m▀[38;5;181;48;5;181m▀▀[38;5;249;48;5;249m▀[38;5;181m▀[48;5;181m▀▀▀▀▀▀[38;5;95m▀[38;5;181m▀▀▀▀▀▀▀[48;5;249m▀[48;5;181m▀[38;5;249;48;5;249m▀[38;5;145;48;5;248m▀[48;5;249m▀[38;5;249m▀[48;5;181m▀[38;5;181m▀[38;5;249;48;5;249m▀[38;5;145;48;5;145m▀▀▀[38;5;181m▀[48;5;249m▀▀▀[38;5;249;48;5;145m▀[38;5;145m▀▀[38;5;181m▀[38;5;249m▀▀[38;5;181m▀▀[38;5;145;48;5;181m▀[48;5;145m▀[38;5;248;48;5;248m▀▀▀▀▀▀▀[48;5;138m▀[38;5;247m▀[0m
|
||||
[38;5;248;48;5;248m▀[38;5;145m▀[48;5;145m▀▀▀[38;5;249m▀[48;5;249m▀▀▀[38;5;181m▀▀[38;5;249m▀[48;5;145m▀▀[48;5;249m▀▀[38;5;181m▀▀[38;5;249m▀[48;5;145m▀[48;5;249m▀[48;5;145m▀[38;5;181;48;5;249m▀▀[48;5;181m▀▀[38;5;249;48;5;249m▀▀[38;5;181m▀[38;5;249m▀▀[38;5;181;48;5;181m▀▀▀▀▀▀▀▀[48;5;145m▀[38;5;145m▀[38;5;181m▀[48;5;181m▀▀▀[38;5;249;48;5;249m▀[38;5;181m▀[38;5;145;48;5;248m▀[38;5;248m▀[38;5;249;48;5;181m▀[48;5;249m▀[38;5;181m▀▀[38;5;145;48;5;145m▀[48;5;248m▀▀[48;5;145m▀[38;5;249m▀▀[48;5;249m▀[38;5;145;48;5;145m▀▀[48;5;248m▀[38;5;248m▀▀▀▀▀[38;5;145m▀[48;5;145m▀▀[38;5;248;48;5;248m▀[48;5;138m▀[48;5;248m▀▀▀[48;5;247m▀▀[48;5;138m▀[38;5;138m▀[0m
|
||||
|
||||
The αcτµαlly pδrταblε εxεcµταblε software is dedicated to:
|
||||
|
||||
Mark "Zibo" Joseph Zbikowski
|
||||
Architect @ Microsoft Corporation & Early Computer Hacker
|
||||
Whose Initials Grace Every Executable
|
||||
|
0
ape/notice.inc
Normal file
0
ape/notice.inc
Normal file
67
ape/relocations.h
Normal file
67
ape/relocations.h
Normal file
|
@ -0,0 +1,67 @@
|
|||
#ifndef COSMOPOLITAN_APE_RELOCATIONS_H_
|
||||
#define COSMOPOLITAN_APE_RELOCATIONS_H_
|
||||
/*─────────────────────────────────────────────────────────────────────────────╗
|
||||
│ αcτµαlly pδrταblε εxεcµταblε § relocations │
|
||||
╚──────────────────────────────────────────────────────────────────────────────╝
|
||||
One of the things αcτµαlly pδrταblε εxεcµταblε does a good job
|
||||
abstracting, is how a program needs to exist at three addresses
|
||||
simultaneously during the early stages of the loading process.
|
||||
|
||||
By default, the linker calculates all symbols using virtual addresses.
|
||||
In some cases it's necessary to use addend macros that change virtual
|
||||
addresses into the other two types: physical and real. */
|
||||
|
||||
#ifndef IMAGE_BASE_VIRTUAL
|
||||
#define IMAGE_BASE_VIRTUAL 0x400000
|
||||
#endif
|
||||
|
||||
#ifndef IMAGE_BASE_PHYSICAL
|
||||
#define IMAGE_BASE_PHYSICAL 0x100000
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Location of anything goes memory for real mode.
|
||||
*
|
||||
* The MBR won't load program content beyond this address, so we have
|
||||
* room for buffers, page tables, etc. before we reach the stack frame.
|
||||
*/
|
||||
#ifndef REAL_SCRATCH_AREA
|
||||
#define REAL_SCRATCH_AREA 0x40000
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Location of real mode 64kb stack frame.
|
||||
*
|
||||
* This address was chosen because memory beyond 0x80000 can't be
|
||||
* accessed safely without consulting e820.
|
||||
*/
|
||||
#ifndef REAL_STACK_FRAME
|
||||
#define REAL_STACK_FRAME 0x70000
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Returns Relative Virtual Address.
|
||||
*/
|
||||
#define RVA(x) ((x) - (IMAGE_BASE_VIRTUAL))
|
||||
|
||||
/**
|
||||
* Adjusts virtual address so it's relative to load address.
|
||||
*/
|
||||
#define PHYSICAL(x) ((x) - (IMAGE_BASE_VIRTUAL - IMAGE_BASE_PHYSICAL))
|
||||
|
||||
/**
|
||||
* Makes high-entropy read-only addresses relocatable in real mode.
|
||||
*/
|
||||
#define REAL(x) ((x) - (IMAGE_BASE_VIRTUAL - IMAGE_BASE_REAL))
|
||||
|
||||
#if IMAGE_BASE_VIRTUAL % 0x200000 != 0
|
||||
#error "IMAGE_BASE_VIRTUAL must be 2mb aligned"
|
||||
#endif
|
||||
#if IMAGE_BASE_PHYSICAL % 0x1000 != 0
|
||||
#error "IMAGE_BASE_PHYSICAL must be 4kb aligned"
|
||||
#endif
|
||||
#if IMAGE_BASE_REAL % 0x1000 != 0
|
||||
#error "IMAGE_BASE_REAL must be 4kb aligned"
|
||||
#endif
|
||||
|
||||
#endif /* COSMOPOLITAN_APE_RELOCATIONS_H_ */
|
Loading…
Add table
Add a link
Reference in a new issue