mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-08-08 10:50:28 +00:00
[metal] Get zipos working again for legacy BIOS boot
examples/hellolua.c now runs again when booted as a legacy BIOS disk image. - output number of sectors to load as a patchable variable; for now the patching is done by tool/build/zipcopy.c - remove references to _ezip - add tweaks to metal mmap() - implement lseek() & fstat() for metal memory files
This commit is contained in:
parent
4c74f09393
commit
44dc43fcb5
13 changed files with 160 additions and 55 deletions
72
ape/ape.S
72
ape/ape.S
|
@ -152,10 +152,13 @@ ape_mz:
|
||||||
.short 0x0800 // MZ: increases cs load lower bound
|
.short 0x0800 // MZ: increases cs load lower bound
|
||||||
.short 0x0040 // MZ: reloc table offset
|
.short 0x0040 // MZ: reloc table offset
|
||||||
.short 0 // MZ: overlay number
|
.short 0 // MZ: overlay number
|
||||||
|
.ascii "'<<'@'\n"
|
||||||
.org 0x24 // MZ: bytes reserved for you
|
.org 0x24 // MZ: bytes reserved for you
|
||||||
.ascii "JT" // MZ: OEM identifier
|
.ascii "JT" // MZ: OEM identifier
|
||||||
.short 0 // MZ: OEM information
|
.short 1 // MZ: OEM information
|
||||||
.ascii "' <<'@'\n"
|
__ape_com_sectors:
|
||||||
|
.short v_ape_allsectors // total number of sectors to load;
|
||||||
|
.endobj __ape_com_sectors,globl // to be patched by Cosmo tools
|
||||||
.org 0x40-4 // MZ: bytes reserved for you
|
.org 0x40-4 // MZ: bytes reserved for you
|
||||||
#if SupportsWindows() || SupportsMetal()
|
#if SupportsWindows() || SupportsMetal()
|
||||||
.long RVA(ape_pe) // PE: the new technology
|
.long RVA(ape_pe) // PE: the new technology
|
||||||
|
@ -220,7 +223,7 @@ stub: mov $0x40,%dl // *literally* dos
|
||||||
nop // system five bootpoint
|
nop // system five bootpoint
|
||||||
.org 0x48,0x90 // note ⌂ELF means JG 47
|
.org 0x48,0x90 // note ⌂ELF means JG 47
|
||||||
jmp 3f // MZ also means pop r10
|
jmp 3f // MZ also means pop r10
|
||||||
2: sub $8,%rsp // a.k.a. dec %ax sub %sp
|
2: push %rax // a.k.a. push %ax
|
||||||
xor %edx,%edx // MZ ate BIOS drive code
|
xor %edx,%edx // MZ ate BIOS drive code
|
||||||
3: .byte 0xbd,0,0 // a.k.a. mov imm,%bp
|
3: .byte 0xbd,0,0 // a.k.a. mov imm,%bp
|
||||||
jmp pc // real mode, is real
|
jmp pc // real mode, is real
|
||||||
|
@ -291,7 +294,11 @@ pc: cld
|
||||||
mov $1,%al // current sector
|
mov $1,%al // current sector
|
||||||
xor %cx,%cx // current cylinder
|
xor %cx,%cx // current cylinder
|
||||||
xor %dh,%dh // current head
|
xor %dh,%dh // current head
|
||||||
mov $v_ape_realsectors,%di // total sectors
|
mov $v_ape_maxrealsectors,%di // no. sectors for base memory
|
||||||
|
mov REAL(__ape_com_sectors),%bp
|
||||||
|
cmp %bp,%di
|
||||||
|
jb 3f
|
||||||
|
mov %bp,%di
|
||||||
3: call pcread
|
3: call pcread
|
||||||
mov %es,%si // addr += 512
|
mov %es,%si // addr += 512
|
||||||
add $512>>4,%si
|
add $512>>4,%si
|
||||||
|
@ -417,13 +424,12 @@ pcread: push %ax
|
||||||
ror %cl
|
ror %cl
|
||||||
or %al,%cl
|
or %al,%cl
|
||||||
xor %bx,%bx // es:bx is destination addr
|
xor %bx,%bx // es:bx is destination addr
|
||||||
mov $1,%al // read only one disk sector
|
mov $0x0201,%ax // read only one disk sector
|
||||||
mov $2,%ah // read disk sectors ordinal
|
|
||||||
int $0x13
|
int $0x13
|
||||||
pop %cx
|
pop %cx
|
||||||
pop %ax
|
pop %ax
|
||||||
jc 9f
|
jc 9f
|
||||||
inc %al // ++sector
|
inc %ax // ++sector
|
||||||
cmp mm+"struct mman::pc_drive_last_sector",%al
|
cmp mm+"struct mman::pc_drive_last_sector",%al
|
||||||
jbe 2f
|
jbe 2f
|
||||||
mov $1,%al
|
mov $1,%al
|
||||||
|
@ -480,7 +486,7 @@ sinit4: mov $4,%cx
|
||||||
jz 1f
|
jz 1f
|
||||||
push %cx
|
push %cx
|
||||||
push %si
|
push %si
|
||||||
xchg %ax,%di
|
xchg %ax,%dx
|
||||||
mov $REAL(sconf),%si
|
mov $REAL(sconf),%si
|
||||||
call sinit
|
call sinit
|
||||||
pop %si
|
pop %si
|
||||||
|
@ -491,18 +497,16 @@ sinit4: mov $4,%cx
|
||||||
|
|
||||||
// Initializes Serial Line Communications 8250 UART 16550A
|
// Initializes Serial Line Communications 8250 UART 16550A
|
||||||
//
|
//
|
||||||
// @param word di tty port
|
// @param word dx tty port
|
||||||
// @param char (*{es:,e,r}si)[4] register initial values
|
// @param char (*{es:,e,r}si)[4] register initial values
|
||||||
|
// @clob dx
|
||||||
// @mode long,legacy,real
|
// @mode long,legacy,real
|
||||||
// @see www.lammertbies.nl/comm/info/serial-uart.html
|
// @see www.lammertbies.nl/comm/info/serial-uart.html
|
||||||
sinit: mov %di,%dx
|
sinit: test %dx,%dx
|
||||||
test %dx,%dx
|
|
||||||
jz 2f
|
jz 2f
|
||||||
push %dx
|
push %dx
|
||||||
push %si
|
push %si
|
||||||
xor %cx,%cx
|
add $UART_LCR,%dx
|
||||||
mov $UART_LCR,%cl
|
|
||||||
add %cx,%dx
|
|
||||||
lodsb %ds:(%si),%al
|
lodsb %ds:(%si),%al
|
||||||
pop %si
|
pop %si
|
||||||
or $UART_DLAB,%al
|
or $UART_DLAB,%al
|
||||||
|
@ -1515,7 +1519,11 @@ cpyhi: push %es
|
||||||
call unreal
|
call unreal
|
||||||
mov $IMAGE_BASE_REAL,%esi
|
mov $IMAGE_BASE_REAL,%esi
|
||||||
mov $IMAGE_BASE_PHYSICAL,%edi
|
mov $IMAGE_BASE_PHYSICAL,%edi
|
||||||
mov $v_ape_realdwords,%ecx
|
mov $v_ape_maxrealsectors,%ecx
|
||||||
|
cmp %bp,%cx
|
||||||
|
jb 1f
|
||||||
|
mov %bp,%cx
|
||||||
|
1: shl $9-2,%ecx // convert sector count to dword count
|
||||||
cld
|
cld
|
||||||
rep movsl %ds:(%esi),%es:(%edi)
|
rep movsl %ds:(%esi),%es:(%edi)
|
||||||
sti
|
sti
|
||||||
|
@ -1545,13 +1553,16 @@ unreal: push %ds
|
||||||
pop %ds
|
pop %ds
|
||||||
ret
|
ret
|
||||||
|
|
||||||
// Reads any remaining program pages into memory which have not yet
|
// Reads any remaining program & data sectors into memory which have not
|
||||||
// been read by the boot sector.
|
// yet been read by the boot sector.
|
||||||
//
|
//
|
||||||
// @clob eax, ecx, dx, esi, edi, bp
|
// @return ebp physical address after end of loaded sectors
|
||||||
loadhi: mov $v_ape_highsectors,%bp
|
// @clob eax, ecx, dx, esi, edi
|
||||||
test %bp,%bp
|
loadhi:
|
||||||
jz 9f
|
#define SEG 0x79000
|
||||||
|
mov $IMAGE_BASE_PHYSICAL+v_ape_maxrealbytes-SEG,%edi
|
||||||
|
sub $v_ape_maxrealsectors,%bp
|
||||||
|
jbe 9f
|
||||||
mov $mm+"struct mman::pc_drive",%si
|
mov $mm+"struct mman::pc_drive",%si
|
||||||
cld
|
cld
|
||||||
lodsb //← pc_drive
|
lodsb //← pc_drive
|
||||||
|
@ -1565,8 +1576,6 @@ loadhi: mov $v_ape_highsectors,%bp
|
||||||
xchg %ax,%cx
|
xchg %ax,%cx
|
||||||
mov (%si),%dh #← pc_drive_next_head
|
mov (%si),%dh #← pc_drive_next_head
|
||||||
push %es
|
push %es
|
||||||
#define SEG 0x79000
|
|
||||||
mov $IMAGE_BASE_PHYSICAL+v_ape_realbytes-SEG,%edi
|
|
||||||
push $SEG>>4
|
push $SEG>>4
|
||||||
pop %es
|
pop %es
|
||||||
0: call pcread
|
0: call pcread
|
||||||
|
@ -1584,7 +1593,8 @@ loadhi: mov $v_ape_highsectors,%bp
|
||||||
dec %bp
|
dec %bp
|
||||||
jnz 0b
|
jnz 0b
|
||||||
pop %es
|
pop %es
|
||||||
9: ret
|
9: lea SEG(%edi),%ebp
|
||||||
|
ret
|
||||||
|
|
||||||
// Initializes long mode paging.
|
// Initializes long mode paging.
|
||||||
pinit: push %ds
|
pinit: push %ds
|
||||||
|
@ -1638,6 +1648,8 @@ golong: cli
|
||||||
.endfn golong
|
.endfn golong
|
||||||
|
|
||||||
// Long mode is long.
|
// Long mode is long.
|
||||||
|
//
|
||||||
|
// @param ebp physical address after end of loaded sectors
|
||||||
.code64
|
.code64
|
||||||
long: movabs $BANE+PHYSICAL(0f),%rax
|
long: movabs $BANE+PHYSICAL(0f),%rax
|
||||||
jmp *%rax
|
jmp *%rax
|
||||||
|
@ -1653,12 +1665,12 @@ long: movabs $BANE+PHYSICAL(0f),%rax
|
||||||
xor %r13d,%r13d
|
xor %r13d,%r13d
|
||||||
xor %r14d,%r14d
|
xor %r14d,%r14d
|
||||||
xor %r15d,%r15d
|
xor %r15d,%r15d
|
||||||
xor %ebx,%ebx
|
|
||||||
xor %ebp,%ebp
|
|
||||||
mov $mm,%rdi
|
mov $mm,%rdi
|
||||||
mov %cr3,%rsi
|
mov %cr3,%rsi
|
||||||
mov $IMAGE_BASE_PHYSICAL,%edx
|
mov $IMAGE_BASE_PHYSICAL,%edx
|
||||||
lea v_ape_allbytes(%rdx),%ecx
|
mov %ebp,%ecx
|
||||||
|
xor %ebx,%ebx
|
||||||
|
xor %ebp,%ebp
|
||||||
call __map_phdrs
|
call __map_phdrs
|
||||||
push $0x037f
|
push $0x037f
|
||||||
fldcw (%rsp)
|
fldcw (%rsp)
|
||||||
|
@ -1792,9 +1804,9 @@ kernel: movabs $ape_stack_vaddr,%rsp
|
||||||
.endm
|
.endm
|
||||||
.ldsvar _end
|
.ldsvar _end
|
||||||
.ldsvar _etext
|
.ldsvar _etext
|
||||||
.ldsvar v_ape_realsectors
|
.ldsvar v_ape_maxrealsectors
|
||||||
.ldsvar v_ape_realbytes
|
.ldsvar v_ape_maxrealbytes
|
||||||
.ldsvar v_ape_highsectors
|
.ldsvar v_ape_allsectors
|
||||||
.ldsvar ape_idata_ro
|
.ldsvar ape_idata_ro
|
||||||
.ldsvar ape_piro
|
.ldsvar ape_piro
|
||||||
.ldsvar ape_piro_end
|
.ldsvar ape_piro_end
|
||||||
|
|
11
ape/ape.lds
11
ape/ape.lds
|
@ -436,7 +436,6 @@ SECTIONS {
|
||||||
/*END: NT FORK COPYING */
|
/*END: NT FORK COPYING */
|
||||||
_edata = .;
|
_edata = .;
|
||||||
PROVIDE(edata = .);
|
PROVIDE(edata = .);
|
||||||
_ezip = .; /* <-- very deprecated */
|
|
||||||
} :Ram
|
} :Ram
|
||||||
|
|
||||||
. = ALIGN(CONSTANT(COMMONPAGESIZE));
|
. = ALIGN(CONSTANT(COMMONPAGESIZE));
|
||||||
|
@ -632,12 +631,10 @@ APE_DECLARE_FIXED_DECIMAL(IDENTITY, blink_xnu_aarch64_size);
|
||||||
#endif /* APE_IS_SHELL_SCRIPT */
|
#endif /* APE_IS_SHELL_SCRIPT */
|
||||||
|
|
||||||
#if SupportsMetal()
|
#if SupportsMetal()
|
||||||
v_ape_realsectors = MIN(0x70000 - IMAGE_BASE_REAL, ROUNDUP(RVA(_ezip), 512)) / 512;
|
v_ape_maxrealbytes = ROUNDUP(0x70000 - IMAGE_BASE_REAL, 512);
|
||||||
v_ape_realbytes = v_ape_realsectors * 512;
|
v_ape_maxrealsectors = v_ape_maxrealbytes / 512;
|
||||||
v_ape_realdwords = v_ape_realsectors * (512 / 4);
|
v_ape_allbytes = ROUNDUP(_edata - __executable_start, 512);
|
||||||
v_ape_allsectors = ROUNDUP(RVA(_ezip), 512) / 512;
|
v_ape_allsectors = v_ape_allbytes / 512;
|
||||||
v_ape_allbytes = v_ape_allsectors * 512;
|
|
||||||
v_ape_highsectors = MIN(0xffff, v_ape_allsectors - v_ape_realsectors);
|
|
||||||
TSSDESCSTUB2(_tss, _tss, _tss_end ? _tss_end - _tss - 1 : 0);
|
TSSDESCSTUB2(_tss, _tss, _tss_end ? _tss_end - _tss - 1 : 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@ extern unsigned char __privileged_start[] __attribute__((__weak__));
|
||||||
extern unsigned char _ehead[] __attribute__((__weak__));
|
extern unsigned char _ehead[] __attribute__((__weak__));
|
||||||
extern unsigned char _etext[] __attribute__((__weak__));
|
extern unsigned char _etext[] __attribute__((__weak__));
|
||||||
extern unsigned char _edata[] __attribute__((__weak__));
|
extern unsigned char _edata[] __attribute__((__weak__));
|
||||||
extern unsigned char _ezip[] __attribute__((__weak__));
|
|
||||||
extern unsigned char _end[] __attribute__((__weak__));
|
extern unsigned char _end[] __attribute__((__weak__));
|
||||||
extern unsigned char _ereal[] __attribute__((__weak__));
|
extern unsigned char _ereal[] __attribute__((__weak__));
|
||||||
extern unsigned char _tdata_start[] __attribute__((__weak__));
|
extern unsigned char _tdata_start[] __attribute__((__weak__));
|
||||||
|
|
Binary file not shown.
|
@ -17,14 +17,17 @@
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/internal.h"
|
#include "libc/calls/internal.h"
|
||||||
|
#include "libc/calls/metalfile.internal.h"
|
||||||
#include "libc/calls/struct/stat.h"
|
#include "libc/calls/struct/stat.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#include "libc/sysv/consts/s.h"
|
#include "libc/sysv/consts/s.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
int sys_fstat_metal(int fd, struct stat *st) {
|
int sys_fstat_metal(int fd, struct stat *st) {
|
||||||
if (fd < 0) return einval();
|
struct MetalFile *file;
|
||||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdSerial) {
|
if (fd < 0 || fd >= g_fds.n) return einval();
|
||||||
|
switch (g_fds.p[fd].kind) {
|
||||||
|
case kFdSerial:
|
||||||
bzero(st, sizeof(*st));
|
bzero(st, sizeof(*st));
|
||||||
st->st_dev = g_fds.p[fd].handle;
|
st->st_dev = g_fds.p[fd].handle;
|
||||||
st->st_rdev = g_fds.p[fd].handle;
|
st->st_rdev = g_fds.p[fd].handle;
|
||||||
|
@ -32,7 +35,15 @@ int sys_fstat_metal(int fd, struct stat *st) {
|
||||||
st->st_mode = S_IFCHR | 0600;
|
st->st_mode = S_IFCHR | 0600;
|
||||||
st->st_blksize = 1;
|
st->st_blksize = 1;
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
case kFdFile:
|
||||||
|
file = (struct MetalFile *)g_fds.p[fd].handle;
|
||||||
|
bzero(st, sizeof(*st));
|
||||||
|
st->st_nlink = 1;
|
||||||
|
st->st_size = file->size;
|
||||||
|
st->st_mode = S_IFREG | 0600;
|
||||||
|
st->st_blksize = 1;
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
return ebadf();
|
return ebadf();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,7 @@ forceinline bool __isfdkind(int fd, int kind) {
|
||||||
int _check_interrupts(int);
|
int _check_interrupts(int);
|
||||||
int sys_close_nt(struct Fd *, int);
|
int sys_close_nt(struct Fd *, int);
|
||||||
int sys_openat_metal(int, const char *, int, unsigned);
|
int sys_openat_metal(int, const char *, int, unsigned);
|
||||||
|
int64_t sys_lseek_metal(struct Fd *, int64_t, int);
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
|
50
libc/calls/lseek-metal.c
Normal file
50
libc/calls/lseek-metal.c
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
/*-*- 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 │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/calls/internal.h"
|
||||||
|
#include "libc/calls/metalfile.internal.h"
|
||||||
|
#include "libc/calls/struct/fd.internal.h"
|
||||||
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
|
int64_t sys_lseek_metal(struct Fd *fd, int64_t offset, int whence) {
|
||||||
|
size_t new_pos;
|
||||||
|
struct MetalFile *file;
|
||||||
|
switch (fd->kind) {
|
||||||
|
case kFdFile:
|
||||||
|
file = (struct MetalFile *)fd->handle;
|
||||||
|
switch (whence) {
|
||||||
|
case SEEK_SET:
|
||||||
|
new_pos = offset;
|
||||||
|
break;
|
||||||
|
case SEEK_CUR:
|
||||||
|
new_pos = file->pos + offset;
|
||||||
|
break;
|
||||||
|
case SEEK_END:
|
||||||
|
new_pos = file->size + offset;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return einval();
|
||||||
|
}
|
||||||
|
if (new_pos > file->size) return einval();
|
||||||
|
file->pos = new_pos;
|
||||||
|
return new_pos;
|
||||||
|
default:
|
||||||
|
return ebadf();
|
||||||
|
}
|
||||||
|
}
|
|
@ -77,9 +77,11 @@
|
||||||
*/
|
*/
|
||||||
int64_t lseek(int fd, int64_t offset, int whence) {
|
int64_t lseek(int fd, int64_t offset, int whence) {
|
||||||
int64_t rc;
|
int64_t rc;
|
||||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
if (fd >= 0 && fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||||
rc = _weaken(__zipos_seek)(
|
rc = _weaken(__zipos_seek)(
|
||||||
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, offset, whence);
|
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, offset, whence);
|
||||||
|
} else if (fd >= 0 && fd < g_fds.n && IsMetal()) {
|
||||||
|
rc = sys_lseek_metal(g_fds.p + fd, offset, whence);
|
||||||
} else if (IsLinux() || IsXnu() || IsFreebsd() || IsOpenbsd()) {
|
} else if (IsLinux() || IsXnu() || IsFreebsd() || IsOpenbsd()) {
|
||||||
rc = sys_lseek(fd, offset, whence, 0);
|
rc = sys_lseek(fd, offset, whence, 0);
|
||||||
} else if (IsNetbsd()) {
|
} else if (IsNetbsd()) {
|
||||||
|
|
|
@ -53,7 +53,7 @@ void *__ape_com_base;
|
||||||
size_t __ape_com_size = 0;
|
size_t __ape_com_size = 0;
|
||||||
|
|
||||||
textstartup dontasan void InitializeMetalFile(void) {
|
textstartup dontasan void InitializeMetalFile(void) {
|
||||||
if (IsMetal()) {
|
if (IsMetal() && _weaken(__ape_com_sectors)) {
|
||||||
/*
|
/*
|
||||||
* Copy out a pristine image of the program — before the program might
|
* Copy out a pristine image of the program — before the program might
|
||||||
* decide to modify its own .data section.
|
* decide to modify its own .data section.
|
||||||
|
@ -63,8 +63,7 @@ textstartup dontasan void InitializeMetalFile(void) {
|
||||||
* The zipos code will automatically arrange to do this. Alternatively,
|
* The zipos code will automatically arrange to do this. Alternatively,
|
||||||
* user code can __static_yoink this symbol.
|
* user code can __static_yoink this symbol.
|
||||||
*/
|
*/
|
||||||
size_t size = ROUNDUP(_ezip - __executable_start, 4096);
|
size_t size = ROUNDUP((size_t)__ape_com_sectors * 512, 4096);
|
||||||
// TODO(jart): Restore support for ZIPOS on metal.
|
|
||||||
void *copied_base;
|
void *copied_base;
|
||||||
struct DirectMap dm;
|
struct DirectMap dm;
|
||||||
dm = sys_mmap_metal(NULL, size, PROT_READ | PROT_WRITE,
|
dm = sys_mmap_metal(NULL, size, PROT_READ | PROT_WRITE,
|
||||||
|
|
|
@ -11,6 +11,7 @@ struct MetalFile {
|
||||||
|
|
||||||
extern void *__ape_com_base;
|
extern void *__ape_com_base;
|
||||||
extern size_t __ape_com_size;
|
extern size_t __ape_com_size;
|
||||||
|
extern uint16_t __ape_com_sectors; // ape/ape.S
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/assert.h"
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/internal.h"
|
#include "libc/calls/internal.h"
|
||||||
#include "libc/calls/metalfile.internal.h"
|
#include "libc/calls/metalfile.internal.h"
|
||||||
|
@ -46,6 +47,10 @@ dontasan struct DirectMap sys_mmap_metal(void *vaddr, size_t size, int prot,
|
||||||
struct mman *mm;
|
struct mman *mm;
|
||||||
struct DirectMap res;
|
struct DirectMap res;
|
||||||
uint64_t addr, faddr = 0, page, e, *pte, *fdpte, *pml4t;
|
uint64_t addr, faddr = 0, page, e, *pte, *fdpte, *pml4t;
|
||||||
|
if ((uintptr_t)BANE + size < (uintptr_t)BANE) {
|
||||||
|
assert(false);
|
||||||
|
return bad_mmap();
|
||||||
|
}
|
||||||
mm = __get_mm();
|
mm = __get_mm();
|
||||||
pml4t = __get_pml4t();
|
pml4t = __get_pml4t();
|
||||||
size = ROUNDUP(size, 4096);
|
size = ROUNDUP(size, 4096);
|
||||||
|
@ -69,11 +74,14 @@ dontasan struct DirectMap sys_mmap_metal(void *vaddr, size_t size, int prot,
|
||||||
} else {
|
} else {
|
||||||
addr = ROUNDUP(addr, 4096);
|
addr = ROUNDUP(addr, 4096);
|
||||||
}
|
}
|
||||||
for (i = 0; i < size; i += 4096) {
|
i = 0;
|
||||||
|
while (i < size) {
|
||||||
pte = __get_virtual(mm, pml4t, addr + i, false);
|
pte = __get_virtual(mm, pml4t, addr + i, false);
|
||||||
if (pte && (*pte & (PAGE_V | PAGE_RSRV))) {
|
if (pte && (*pte & (PAGE_V | PAGE_RSRV))) {
|
||||||
addr = MAX(addr, sys_mmap_metal_break) + i + 4096;
|
addr = MAX(addr, sys_mmap_metal_break) + i + 4096;
|
||||||
i = 0;
|
i = 0;
|
||||||
|
} else {
|
||||||
|
i += 4096;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sys_mmap_metal_break = MAX(addr + size, sys_mmap_metal_break);
|
sys_mmap_metal_break = MAX(addr + size, sys_mmap_metal_break);
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
│ OTHER DEALINGS IN THE SOFTWARE. │
|
│ OTHER DEALINGS IN THE SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
|
#include "libc/intrin/kprintf.h"
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/runtime/pc.internal.h"
|
#include "libc/runtime/pc.internal.h"
|
||||||
|
|
||||||
|
|
|
@ -23,11 +23,15 @@
|
||||||
#include "libc/elf/struct/shdr.h"
|
#include "libc/elf/struct/shdr.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/fmt/magnumstrs.internal.h"
|
#include "libc/fmt/magnumstrs.internal.h"
|
||||||
|
#include "libc/intrin/newbie.h"
|
||||||
#include "libc/limits.h"
|
#include "libc/limits.h"
|
||||||
|
#include "libc/nt/struct/imagedosheader.internal.h"
|
||||||
|
#include "libc/runtime/pc.internal.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/stdio/stdio.h"
|
#include "libc/stdio/stdio.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#include "libc/sysv/consts/map.h"
|
#include "libc/sysv/consts/map.h"
|
||||||
|
#include "libc/sysv/consts/msync.h"
|
||||||
#include "libc/sysv/consts/o.h"
|
#include "libc/sysv/consts/o.h"
|
||||||
#include "libc/sysv/consts/prot.h"
|
#include "libc/sysv/consts/prot.h"
|
||||||
#include "libc/zip.internal.h"
|
#include "libc/zip.internal.h"
|
||||||
|
@ -109,6 +113,25 @@ static void GetOpts(int argc, char *argv[]) {
|
||||||
outpath = argv[optind + 1];
|
outpath = argv[optind + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void BiosZipFix(unsigned long cdest) {
|
||||||
|
struct NtImageDosHeader head;
|
||||||
|
size_t hd_sz = sizeof(head);
|
||||||
|
size_t e_oemid = offsetof(struct NtImageDosHeader, e_oemid);
|
||||||
|
size_t e_oeminfo = offsetof(struct NtImageDosHeader, e_oeminfo);
|
||||||
|
if (outsize < hd_sz) return;
|
||||||
|
if (pread(outfd, &head, hd_sz, 0) != hd_sz) return;
|
||||||
|
if (READ64LE((uint8_t *)&head) != READ64LE("MZqFpD='") &&
|
||||||
|
READ64LE((uint8_t *)&head) != READ64LE("jartsr='")) return;
|
||||||
|
if (le16toh(head.e_oemid) != READ16LE("JT") ||
|
||||||
|
le16toh(head.e_oeminfo) != 1) return;
|
||||||
|
// patch executable head so that it will load the right count of sectors
|
||||||
|
// when run as a legacy BIOS disk image
|
||||||
|
head.e_res2[0] = htole16(ROUNDUP(cdest, 0x200) / 0x200);
|
||||||
|
if (pwrite(outfd, &head, hd_sz, 0) != hd_sz) {
|
||||||
|
SysDie(outpath, "head pwrite");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void CopyZip(void) {
|
static void CopyZip(void) {
|
||||||
char *secstrs;
|
char *secstrs;
|
||||||
int rela, recs;
|
int rela, recs;
|
||||||
|
@ -176,7 +199,7 @@ static void CopyZip(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// write output
|
// write output
|
||||||
if ((outfd = open(outpath, O_WRONLY | O_CREAT, 0644)) == -1) {
|
if ((outfd = open(outpath, O_RDWR | O_CREAT, 0644)) == -1) {
|
||||||
SysDie(outpath, "open");
|
SysDie(outpath, "open");
|
||||||
}
|
}
|
||||||
if ((outsize = lseek(outfd, 0, SEEK_END)) == -1) {
|
if ((outsize = lseek(outfd, 0, SEEK_END)) == -1) {
|
||||||
|
@ -205,6 +228,7 @@ static void CopyZip(void) {
|
||||||
if (pwrite(outfd, eocd, length, cdest) != length) {
|
if (pwrite(outfd, eocd, length, cdest) != length) {
|
||||||
SysDie(outpath, "eocd pwrite");
|
SysDie(outpath, "eocd pwrite");
|
||||||
}
|
}
|
||||||
|
BiosZipFix(cdest);
|
||||||
if (close(outfd)) {
|
if (close(outfd)) {
|
||||||
SysDie(outpath, "close");
|
SysDie(outpath, "close");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue