diff --git a/ape/ape.S b/ape/ape.S index d9780f2d8..480953974 100644 --- a/ape/ape.S +++ b/ape/ape.S @@ -239,18 +239,17 @@ pc: cld / can have an understanding of physical locality, which deeply / impacts the latency of operations. / -/ - 160KB: 1 head × 40 cylinders × 8 sectors × 512 = 163,840 -/ - 180KB: 1 head × 40 cylinders × 9 sectors × 512 = 184,320 -/ - 320KB: 2 heads × 40 cylinders × 8 sectors × 512 = 327,680 -/ - 360KB: 2 heads × 40 cylinders × 9 sectors × 512 = 368,640 -/ - 720KB: 2 heads × 80 cylinders × 9 sectors × 512 = 737,280 -/ - 1.2MB: 2 heads × 80 cylinders × 15 sectors × 512 = 1,228,800 -/ - 1.44MB: 2 heads × 80 cylinders × 18 sectors × 512 = 1,474,560 +/ - 160KB: 40 cylinders × 1 head × 8 sectors × 512 = 163,840 +/ - 180KB: 40 cylinders × 1 head × 9 sectors × 512 = 184,320 +/ - 320KB: 40 cylinders × 2 heads × 8 sectors × 512 = 327,680 +/ - 360KB: 40 cylinders × 2 heads × 9 sectors × 512 = 368,640 +/ - 720KB: 80 cylinders × 2 heads × 9 sectors × 512 = 737,280 +/ - 1.2MB: 80 cylinders × 2 heads × 15 sectors × 512 = 1,228,800 +/ - 1.44MB: 80 cylinders × 2 heads × 18 sectors × 512 = 1,474,560 / / Terminology / -/ - Cylinder / Tracks should mean the same thing -/ - Heads / Sides / Spindles should mean the same thing +/ - Heads are also known as Tracks / / Disk Base Table / @@ -341,18 +340,18 @@ pcread: push %ax pop %cx pop %ax jc 9f - mov %es,%si + mov %es,%si # addr += 512 add $512>>4,%si mov %si,%es - inc %al + inc %al # ++sector cmp XLM(DRIVE_LAST_SECTOR),%al jbe 2f mov $1,%al - inc %cx - cmp XLM(DRIVE_LAST_CYLINDER),%cx - jbe 2f - xor %cx,%cx - inc %dh + inc %dh # ++head + cmp XLM(DRIVE_LAST_HEAD),%cx + jb 2f + xor %dh,%dh + inc %cx # ++cylinder 2: ret 9: push %ax xor %ax,%ax # try disk reset on error diff --git a/ape/lib/mapimage.c b/ape/lib/mapimage.c index fcbfee2fa..7eea964a7 100644 --- a/ape/lib/mapimage.c +++ b/ape/lib/mapimage.c @@ -30,7 +30,7 @@ textreal static void __map_segment(uint64_t k, uint64_t a, uint64_t b) { textreal void __map_image(void) { __map_segment(PAGE_V | PAGE_U, 0, (uintptr_t)_etext - IMAGE_BASE_VIRTUAL); - __map_segment(PAGE_V | PAGE_U | PAGE_RW | PAGE_XD, + __map_segment(PAGE_V | PAGE_U | PAGE_RW, (uintptr_t)_etext - IMAGE_BASE_VIRTUAL, (uintptr_t)_end - IMAGE_BASE_VIRTUAL); } diff --git a/examples/stat.c b/examples/stat.c index 17815ccb7..29ad42d91 100644 --- a/examples/stat.c +++ b/examples/stat.c @@ -11,6 +11,7 @@ #include "libc/calls/struct/stat.h" #include "libc/errno.h" #include "libc/fmt/fmt.h" +#include "libc/log/check.h" #include "libc/runtime/gc.h" #include "libc/stdio/stdio.h" #include "libc/x/x.h" @@ -23,32 +24,29 @@ void PrintFileMetadata(const char *pathname, struct stat *st) { printf("\n%s:", pathname); - if (stat(pathname, st) != -1) { - printf( - "\n" - "%-32s%,ld\n" - "%-32s%,ld\n" - "%-32s%#lx\n" - "%-32s%#lx\n" - "%-32s%ld\n" - "%-32s%#o\n" - "%-32s%d\n" - "%-32s%d\n" - "%-32s%d\n" - "%-32s%ld\n" - "%-32s%s\n" - "%-32s%s\n" - "%-32s%s\n", - "bytes in file", st->st_size, "physical bytes", st->st_blocks * 512, - "device id w/ file", st->st_dev, "inode", st->st_ino, "hard link count", - st->st_nlink, "mode / permissions", st->st_mode, "owner id", st->st_uid, - "group id", st->st_gid, "device id (if special)", st->st_rdev, - "block size", st->st_blksize, "access time", gc(xiso8601(&st->st_atim)), - "modified time", gc(xiso8601(&st->st_mtim)), "c[omplicated]time", - gc(xiso8601(&st->st_ctim))); - } else { - printf(" %s\n", strerror(errno)); - } + CHECK_NE(-1, stat(pathname, st)); + printf("\n" + "%-32s%,ld\n" + "%-32s%,ld\n" + "%-32s%#lx\n" + "%-32s%#lx\n" + "%-32s%ld\n" + "%-32s%#o\n" + "%-32s%d\n" + "%-32s%d\n" + "%-32s%d\n" + "%-32s%ld\n" + "%-32s%s\n" + "%-32s%s\n" + "%-32s%s\n", + "bytes in file", st->st_size, "physical bytes", st->st_blocks * 512, + "device id w/ file", st->st_dev, "inode", st->st_ino, + "hard link count", st->st_nlink, "mode / permissions", st->st_mode, + "owner id", st->st_uid, "group id", st->st_gid, + "device id (if special)", st->st_rdev, "block size", st->st_blksize, + "access time", gc(xiso8601(&st->st_atim)), "modified time", + gc(xiso8601(&st->st_mtim)), "c[omplicated]time", + gc(xiso8601(&st->st_ctim))); } int main(int argc, char *argv[]) { diff --git a/libc/calls/fstat-metal.c b/libc/calls/fstat-metal.c new file mode 100644 index 000000000..e46dc0d7d --- /dev/null +++ b/libc/calls/fstat-metal.c @@ -0,0 +1,38 @@ +/*-*- 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 2021 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/internal.h" +#include "libc/calls/struct/stat.h" +#include "libc/str/str.h" +#include "libc/sysv/consts/s.h" +#include "libc/sysv/errfuns.h" + +int fstat$metal(int fd, struct stat *st) { + if (fd < 0) return einval(); + if (fd < g_fds.n && g_fds.p[fd].kind == kFdSerial) { + memset(st, 0, sizeof(*st)); + st->st_dev = g_fds.p[fd].handle; + st->st_rdev = g_fds.p[fd].handle; + st->st_nlink = 1; + st->st_mode = S_IFCHR | 0600; + st->st_blksize = 1; + return 0; + } else { + return ebadf(); + } +} diff --git a/libc/calls/fstat-nt.c b/libc/calls/fstat-nt.c index 1cbeba2c6..9d6af9832 100644 --- a/libc/calls/fstat-nt.c +++ b/libc/calls/fstat-nt.c @@ -35,34 +35,47 @@ textwindows int fstat$nt(int64_t handle, struct stat *st) { uint64_t actualsize; struct NtFileCompressionInfo fci; struct NtByHandleFileInformation wst; - if (GetFileInformationByHandle(handle, &wst)) { + if ((filetype = GetFileType(handle))) { memset(st, 0, sizeof(*st)); - filetype = GetFileType(handle); - st->st_mode = - (S_IRUSR | S_IXUSR | - (!(wst.dwFileAttributes & kNtFileAttributeReadonly) ? S_IWUSR : 0) | - ((wst.dwFileAttributes & kNtFileAttributeNormal) ? S_IFREG : 0) | - ((wst.dwFileAttributes & kNtFileFlagOpenReparsePoint) ? S_IFLNK : 0) | - ((wst.dwFileAttributes & kNtFileAttributeDirectory) - ? S_IFDIR - : (((filetype == kNtFileTypeDisk) ? S_IFBLK : 0) | - ((filetype == kNtFileTypeChar) ? S_IFCHR : 0) | - ((filetype == kNtFileTypePipe) ? S_IFIFO : 0)))); - st->st_atim = FileTimeToTimeSpec(wst.ftLastAccessFileTime); - st->st_mtim = FileTimeToTimeSpec(wst.ftLastWriteFileTime); - st->st_ctim = FileTimeToTimeSpec(wst.ftCreationFileTime); - st->st_size = (uint64_t)wst.nFileSizeHigh << 32 | wst.nFileSizeLow; - st->st_blksize = PAGESIZE; - st->st_dev = wst.dwVolumeSerialNumber; - st->st_ino = (uint64_t)wst.nFileIndexHigh << 32 | wst.nFileIndexLow; - st->st_nlink = wst.nNumberOfLinks; - if (GetFileInformationByHandleEx(handle, kNtFileCompressionInfo, &fci, - sizeof(fci))) { - actualsize = fci.CompressedFileSize; - } else { - actualsize = st->st_size; + switch (filetype) { + case kNtFileTypeChar: + st->st_mode = S_IFCHR | 0600; + break; + case kNtFileTypePipe: + st->st_mode = S_IFIFO | 0600; + break; + case kNtFileTypeDisk: + if (GetFileInformationByHandle(handle, &wst)) { + dprintf(1, "handle = %ld\n", handle); + st->st_mode = + (S_IRUSR | S_IXUSR | + (!(wst.dwFileAttributes & kNtFileAttributeReadonly) ? S_IWUSR + : 0) | + ((wst.dwFileAttributes & kNtFileAttributeNormal) ? S_IFREG : 0) | + ((wst.dwFileAttributes & kNtFileFlagOpenReparsePoint) ? S_IFLNK + : 0) | + ((wst.dwFileAttributes & kNtFileAttributeDirectory) ? S_IFDIR + : 0)); + st->st_atim = FileTimeToTimeSpec(wst.ftLastAccessFileTime); + st->st_mtim = FileTimeToTimeSpec(wst.ftLastWriteFileTime); + st->st_ctim = FileTimeToTimeSpec(wst.ftCreationFileTime); + st->st_size = (uint64_t)wst.nFileSizeHigh << 32 | wst.nFileSizeLow; + st->st_blksize = PAGESIZE; + st->st_dev = wst.dwVolumeSerialNumber; + st->st_ino = (uint64_t)wst.nFileIndexHigh << 32 | wst.nFileIndexLow; + st->st_nlink = wst.nNumberOfLinks; + if (GetFileInformationByHandleEx(handle, kNtFileCompressionInfo, &fci, + sizeof(fci))) { + actualsize = fci.CompressedFileSize; + } else { + actualsize = st->st_size; + } + st->st_blocks = roundup(actualsize, PAGESIZE) / 512; + } + break; + default: + break; } - st->st_blocks = roundup(actualsize, PAGESIZE) / 512; return 0; } else { return __winerr(); diff --git a/libc/calls/fstat.c b/libc/calls/fstat.c index e57ed2f08..c82c128e6 100644 --- a/libc/calls/fstat.c +++ b/libc/calls/fstat.c @@ -32,7 +32,11 @@ int fstat(int fd, struct stat *st) { return weaken(__zipos_fstat)( (struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, st); } else if (!IsWindows()) { - return fstat$sysv(fd, st); + if (!IsMetal()) { + return fstat$sysv(fd, st); + } else { + return fstat$metal(fd, st); + } } else { if (!__isfdkind(fd, kFdFile)) return ebadf(); return fstat$nt(g_fds.p[fd].handle, st); diff --git a/libc/calls/internal.h b/libc/calls/internal.h index a30cce281..90b3707f2 100644 --- a/libc/calls/internal.h +++ b/libc/calls/internal.h @@ -267,6 +267,12 @@ int64_t __winerr(void) nocallback privileged; int __mkntpath(const char *, char16_t[hasatleast PATH_MAX - 16]) hidden; int __mkntpath2(const char *, char16_t[hasatleast PATH_MAX - 16], int) hidden; +/*───────────────────────────────────────────────────────────────────────────│─╗ +│ cosmopolitan § syscalls » metal ─╬─│┼ +╚────────────────────────────────────────────────────────────────────────────│*/ + +int fstat$metal(int, struct stat *); + /*───────────────────────────────────────────────────────────────────────────│─╗ │ cosmopolitan § syscalls » drivers ─╬─│┼ ╚────────────────────────────────────────────────────────────────────────────│*/ diff --git a/libc/calls/ischardev.c b/libc/calls/ischardev.c index e10a04525..cc1d6df3e 100644 --- a/libc/calls/ischardev.c +++ b/libc/calls/ischardev.c @@ -30,16 +30,11 @@ textstartup bool32 ischardev(int fd) { int olderr; struct stat st; - if (!IsWindows()) { - olderr = errno; - if (fstat$sysv(fd, &st) != -1) { - return S_ISCHR(st.st_mode); - } else { - errno = olderr; - return false; - } + olderr = errno; + if (fstat(fd, &st) != -1) { + return S_ISCHR(st.st_mode); } else { - return __isfdkind(fd, kFdFile) && - GetFileType(g_fds.p[fd].handle) == kNtFileTypeChar; + errno = olderr; + return false; } } diff --git a/libc/calls/madvise-nt.c b/libc/calls/madvise-nt.c index 6d07e8f86..9d8005d1e 100644 --- a/libc/calls/madvise-nt.c +++ b/libc/calls/madvise-nt.c @@ -31,7 +31,7 @@ forceinline typeof(PrefetchVirtualMemory) *GetPrefetchVirtualMemory(void) { if (!once) { once = true; PrefetchVirtualMemory_ = /* win8.1+ */ - GetProcAddressModule("KernelBase.dll", "PrefetchVirtualMemory"); + GetProcAddressModule("Kernel32.dll", "PrefetchVirtualMemory"); } return PrefetchVirtualMemory_; } @@ -42,7 +42,7 @@ forceinline typeof(OfferVirtualMemory) *GetOfferVirtualMemory(void) { if (!once) { once = true; OfferVirtualMemory_ = /* win8.1+ */ - GetProcAddressModule("KernelBase.dll", "OfferVirtualMemory"); + GetProcAddressModule("Kernel32.dll", "OfferVirtualMemory"); } return OfferVirtualMemory_; } diff --git a/libc/calls/nanosleep.c b/libc/calls/nanosleep.c index 4482aee76..9232381e2 100644 --- a/libc/calls/nanosleep.c +++ b/libc/calls/nanosleep.c @@ -27,10 +27,14 @@ int nanosleep(const struct timespec *req, struct timespec *rem) { if (!req) return efault(); if (!IsWindows()) { - if (!IsXnu()) { - return nanosleep$sysv(req, rem); + if (!IsMetal()) { + if (!IsXnu()) { + return nanosleep$sysv(req, rem); + } else { + return nanosleep$xnu(req, rem); + } } else { - return nanosleep$xnu(req, rem); + return enosys(); /* TODO: Sleep on Metal */ } } else { return nanosleep$nt(req, rem); diff --git a/libc/calls/sigaction.c b/libc/calls/sigaction.c index 9b177397c..d134aba8d 100644 --- a/libc/calls/sigaction.c +++ b/libc/calls/sigaction.c @@ -141,32 +141,36 @@ int(sigaction)(int sig, const struct sigaction *act, struct sigaction *oldact) { return efault(); } if (!IsWindows()) { - if (act) { - memcpy(©, act, sizeof(copy)); - ap = © - if (IsXnu()) { - ap->sa_restorer = (void *)&xnutrampoline; - ap->sa_handler = (void *)&xnutrampoline; - } else { - if (IsLinux()) { - if (!(ap->sa_flags & SA_RESTORER)) { - ap->sa_flags |= SA_RESTORER; - ap->sa_restorer = &__restore_rt; + if (!IsMetal()) { + if (act) { + memcpy(©, act, sizeof(copy)); + ap = © + if (IsXnu()) { + ap->sa_restorer = (void *)&xnutrampoline; + ap->sa_handler = (void *)&xnutrampoline; + } else { + if (IsLinux()) { + if (!(ap->sa_flags & SA_RESTORER)) { + ap->sa_flags |= SA_RESTORER; + ap->sa_restorer = &__restore_rt; + } + } + if (rva >= kSigactionMinRva) { + ap->sa_sigaction = (sigaction_f)__sigenter; } } - if (rva >= kSigactionMinRva) { - ap->sa_sigaction = (sigaction_f)__sigenter; - } + sigaction$cosmo2native((union metasigaction *)ap); + } else { + ap = NULL; } - sigaction$cosmo2native((union metasigaction *)ap); + rc = sigaction$sysv( + sig, ap, oldact, + (!IsXnu() ? 8 /* or linux whines */ + : (int64_t)(intptr_t)oldact /* from go code */)); + if (rc != -1) sigaction$native2cosmo((union metasigaction *)oldact); } else { - ap = NULL; + return enosys(); /* TODO: Signals on Metal */ } - rc = sigaction$sysv( - sig, ap, oldact, - (!IsXnu() ? 8 /* or linux whines */ - : (int64_t)(intptr_t)oldact /* from go code */)); - if (rc != -1) sigaction$native2cosmo((union metasigaction *)oldact); } else { if (oldact) { memset(oldact, 0, sizeof(*oldact)); diff --git a/libc/runtime/program_invocation_short_name.S b/libc/runtime/program_invocation_short_name.S index 870491be3..d7825c7c0 100644 --- a/libc/runtime/program_invocation_short_name.S +++ b/libc/runtime/program_invocation_short_name.S @@ -28,7 +28,10 @@ program_invocation_short_name: .init.start 400,_init_program_invocation_short_name push %rsi - mov (%r13),%rsi + xor %eax,%eax + test %r12d,%r12d # argc + jz 2f + mov (%r13),%rsi # argv[0] mov %rsi,%rcx 1: lodsb cmp $'/,%al @@ -39,5 +42,5 @@ program_invocation_short_name: jnz 1b xchg %rcx,%rax pop %rsi - stosq +2: stosq .init.end 400,_init_program_invocation_short_name diff --git a/tool/build/blinkenlights.c b/tool/build/blinkenlights.c index 253f10ba6..c79df3e70 100644 --- a/tool/build/blinkenlights.c +++ b/tool/build/blinkenlights.c @@ -1789,14 +1789,14 @@ static void OnDiskServiceBadCommand(void) { } static void OnDiskServiceGetParams(void) { - size_t lastsector, lasttrack, lasthead; - lasthead = GetLastIndex(elf->mapsize, 512 * 63 * 1024, 0, 255); - lasttrack = GetLastIndex(elf->mapsize, 512 * 63, 0, 1023); + size_t lastsector, lastcylinder, lasthead; + lastcylinder = GetLastIndex(elf->mapsize, 512 * 63 * 255, 0, 1023); + lasthead = GetLastIndex(elf->mapsize, 512 * 63, 0, 255); lastsector = GetLastIndex(elf->mapsize, 512, 1, 63); m->dx[0] = 1; m->dx[1] = lasthead; - m->cx[0] = lasttrack >> 8 << 6 | lastsector; - m->cx[1] = lasttrack; + m->cx[0] = lastcylinder >> 8 << 6 | lastsector; + m->cx[1] = lastcylinder; m->ax[1] = 0; Write64(m->es, 0); Write16(m->di, 0); @@ -1806,18 +1806,17 @@ static void OnDiskServiceGetParams(void) { static void OnDiskServiceReadSectors(void) { static int x; uint64_t addr, size; - int64_t sectors, drive, head, track, sector, offset; + int64_t sectors, drive, head, cylinder, sector, offset; sectors = m->ax[0]; drive = m->dx[0]; head = m->dx[1]; - track = (m->cx[0] & 0b11000000) << 2 | m->cx[1]; + cylinder = (m->cx[0] & 0b11000000) << 2 | m->cx[1]; sector = (m->cx[0] & 0b00111111) - 1; - offset = head * track * sector * 512; size = sectors * 512; - offset = sector * 512 + track * 512 * 63 + head * 512 * 63 * 1024; + offset = sector * 512 + head * 512 * 63 + cylinder * 512 * 63 * 255; VERBOSEF("bios read sectors %d " - "@ sector %ld track %ld head %ld drive %ld offset %#lx", - sectors, sector, track, head, drive, offset); + "@ sector %ld cylinder %ld head %ld drive %ld offset %#lx", + sectors, sector, cylinder, head, drive, offset); if (0 <= sector && offset + size <= elf->mapsize) { addr = Read64(m->es) + Read16(m->bx); if (addr + size <= m->real.n) {