Index: stable/10/lib/libstand/Makefile =================================================================== --- stable/10/lib/libstand/Makefile (revision 271134) +++ stable/10/lib/libstand/Makefile (revision 271135) @@ -1,190 +1,181 @@ # $FreeBSD$ # Originally from $NetBSD: Makefile,v 1.21 1997/10/26 22:08:38 lukem Exp $ # # Notes: # - We don't use the libc strerror/sys_errlist because the string table is # quite large. # .include MK_SSP= no LIB= stand NO_PROFILE= NO_PIC= INCS= stand.h MAN= libstand.3 WARNS?= 0 CFLAGS+= -ffreestanding -Wformat CFLAGS+= -I${.CURDIR} .if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64" -CFLAGS.gcc+= -mpreferred-stack-boundary=2 CFLAGS+= -mno-mmx -mno-3dnow -mno-sse -mno-sse2 -mno-sse3 -msoft-float .endif +.if ${MACHINE_CPUARCH} == "i386" +CFLAGS.gcc+= -mpreferred-stack-boundary=2 +.endif +.if ${MACHINE_CPUARCH} == "amd64" +CFLAGS+= -fPIC +.endif .if ${MACHINE} == "pc98" CFLAGS+= -Os .endif .if ${MACHINE_CPUARCH} == "powerpc" CFLAGS+= -msoft-float -D_STANDALONE -DNETIF_DEBUG .endif -.if ${MACHINE_ARCH} == "amd64" || ${MACHINE_ARCH} == "powerpc64" -CFLAGS+= -m32 -I. -.endif .if ${MACHINE_CPUARCH} == "arm" CFLAGS+= -msoft-float -D_STANDALONE .endif .if ${MACHINE_CPUARCH} == "mips" CFLAGS+= -G0 -fno-pic -mno-abicalls .endif # standalone components and stuff we have modified locally SRCS+= gzguts.h zutil.h __main.c assert.c bcd.c bswap.c environment.c getopt.c gets.c \ globals.c pager.c printf.c strdup.c strerror.c strtol.c strtoul.c random.c \ sbrk.c twiddle.c zalloc.c zalloc_malloc.c # private (pruned) versions of libc string functions SRCS+= strcasecmp.c .PATH: ${.CURDIR}/../libc/net SRCS+= ntoh.c # string functions from libc .PATH: ${.CURDIR}/../libc/string .if ${MACHINE_CPUARCH} != "ia64" SRCS+= bcmp.c bcopy.c bzero.c ffs.c memccpy.c memchr.c memcmp.c memcpy.c \ memmove.c memset.c qdivrem.c strcat.c strchr.c strcmp.c strcpy.c \ strcspn.c strlen.c strncat.c strncmp.c strncpy.c strpbrk.c \ strrchr.c strsep.c strspn.c strstr.c strtok.c swab.c .endif .if ${MACHINE_CPUARCH} == "arm" .PATH: ${.CURDIR}/../libc/arm/gen .if ${MK_ARM_EABI} == "no" SRCS+= divsi3.S .else # Compiler support functions .PATH: ${.CURDIR}/../../contrib/compiler-rt/lib/ # __clzsi2 and ctzsi2 for various builtin functions SRCS+= clzsi2.c ctzsi2.c # Divide and modulus functions called by the compiler SRCS+= divmoddi4.c divmodsi4.c divdi3.c divsi3.c moddi3.c modsi3.c SRCS+= udivmoddi4.c udivmodsi4.c udivdi3.c udivsi3.c umoddi3.c umodsi3.c .PATH: ${.CURDIR}/../../contrib/compiler-rt/lib/arm/ SRCS+= aeabi_idivmod.S aeabi_ldivmod.S aeabi_uidivmod.S aeabi_uldivmod.S SRCS+= aeabi_memcmp.S aeabi_memcpy.S aeabi_memmove.S aeabi_memset.S .endif .endif .if ${MACHINE_CPUARCH} == "ia64" .PATH: ${.CURDIR}/../libc/ia64/string SRCS+= bcmp.c bcopy.S bzero.S ffs.S memccpy.c memchr.c memcmp.c memcpy.S \ memmove.S memset.c strcat.c strchr.c strcmp.c strcpy.c strcspn.c \ strlen.c strncat.c strncmp.c strncpy.c strpbrk.c strrchr.c strsep.c \ strspn.c strstr.c strtok.c swab.c .PATH: ${.CURDIR}/../libc/ia64/gen SRCS+= __divdi3.S __divsi3.S __moddi3.S __modsi3.S SRCS+= __udivdi3.S __udivsi3.S __umoddi3.S __umodsi3.S .endif .if ${MACHINE_CPUARCH} == "powerpc" .PATH: ${.CURDIR}/../libc/quad SRCS+= ashldi3.c ashrdi3.c .PATH: ${.CURDIR}/../libc/powerpc/gen SRCS+= syncicache.c .endif # uuid functions from libc .PATH: ${.CURDIR}/../libc/uuid SRCS+= uuid_equal.c uuid_is_nil.c # _setjmp/_longjmp -.if ${MACHINE_CPUARCH} == "amd64" -.PATH: ${.CURDIR}/i386 -.elif ${MACHINE_ARCH} == "powerpc64" +.if ${MACHINE_ARCH} == "powerpc64" .PATH: ${.CURDIR}/powerpc .else .PATH: ${.CURDIR}/${MACHINE_CPUARCH} .endif SRCS+= _setjmp.S # decompression functionality from libbz2 # NOTE: to actually test this functionality after libbz2 upgrade compile # loader(8) with LOADER_BZIP2_SUPPORT defined .PATH: ${.CURDIR}/../../contrib/bzip2 CFLAGS+= -DBZ_NO_STDIO -DBZ_NO_COMPRESS SRCS+= libstand_bzlib_private.h .for file in bzlib.c crctable.c decompress.c huffman.c randtable.c SRCS+= _${file} CLEANFILES+= _${file} _${file}: ${file} sed "s|bzlib_private\.h|libstand_bzlib_private.h|" ${.ALLSRC} > ${.TARGET} .endfor CLEANFILES+= libstand_bzlib_private.h libstand_bzlib_private.h: bzlib_private.h sed -e 's||"stand.h"|' \ ${.ALLSRC} > ${.TARGET} # decompression functionality from libz .PATH: ${.CURDIR}/../libz CFLAGS+=-DHAVE_MEMCPY -I${.CURDIR}/../libz SRCS+= adler32.c crc32.c libstand_zutil.h libstand_gzguts.h .for file in infback.c inffast.c inflate.c inftrees.c zutil.c SRCS+= _${file} CLEANFILES+= _${file} _${file}: ${file} sed -e "s|zutil\.h|libstand_zutil.h|" \ -e "s|gzguts\.h|libstand_gzguts.h|" \ ${.ALLSRC} > ${.TARGET} .endfor # depend on stand.h being able to be included multiple times .for file in zutil.h gzguts.h CLEANFILES+= libstand_${file} libstand_${file}: ${file} sed -e 's||"stand.h"|' \ -e 's||"stand.h"|' \ -e 's||"stand.h"|' \ -e 's||"stand.h"|' \ -e 's||"stand.h"|' \ ${.ALLSRC} > ${.TARGET} .endfor # io routines SRCS+= closeall.c dev.c ioctl.c nullfs.c stat.c \ fstat.c close.c lseek.c open.c read.c write.c readdir.c # network routines SRCS+= arp.c ether.c inet_ntoa.c in_cksum.c net.c udp.c netif.c rpc.c # network info services: SRCS+= bootp.c rarp.c bootparam.c # boot filesystems SRCS+= ufs.c nfs.c cd9660.c tftp.c gzipfs.c bzipfs.c SRCS+= dosfs.c ext2fs.c SRCS+= splitfs.c .if ${MK_NAND} != "no" SRCS+= nandfs.c .endif .include -.if ${MACHINE_CPUARCH} == "amd64" -beforedepend ${OBJS}: machine -cleandepend: cleanmachine -cleanmachine: - rm -f machine - -machine: - ln -s ${.CURDIR}/../../sys/i386/include machine -.endif Index: stable/10/sys/boot/ficl64/Makefile =================================================================== --- stable/10/sys/boot/ficl64/Makefile (revision 271134) +++ stable/10/sys/boot/ficl64/Makefile (nonexistent) @@ -1,8 +0,0 @@ -# $FreeBSD$ - -FICL64= -FICLDIR= ${.CURDIR}/../ficl - -.PATH: ${FICLDIR} - -.include "${FICLDIR}/Makefile" Property changes on: stable/10/sys/boot/ficl64/Makefile ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: stable/10/sys/boot/Makefile =================================================================== --- stable/10/sys/boot/Makefile (revision 271134) +++ stable/10/sys/boot/Makefile (revision 271135) @@ -1,17 +1,20 @@ # $FreeBSD$ .include .include .if ${MK_FORTH} != "no" # Build the add-in FORTH interpreter. SUBDIR+= ficl .endif # Pick the machine-dependent subdir based on the target architecture. -ADIR= ${MACHINE:S/amd64/i386/:S/powerpc64/powerpc/} +ADIR= ${MACHINE:S/powerpc64/powerpc/} .if exists(${.CURDIR}/${ADIR}/.) SUBDIR+= ${ADIR} +.endif +.if ${MACHINE} == "amd64" +SUBDIR+= i386 .endif .include Index: stable/10/sys/boot/Makefile.amd64 =================================================================== --- stable/10/sys/boot/Makefile.amd64 (revision 271134) +++ stable/10/sys/boot/Makefile.amd64 (revision 271135) @@ -1,6 +1,10 @@ # $FreeBSD$ SUBDIR+= efi SUBDIR+= libstand32 SUBDIR+= zfs SUBDIR+= userboot + +.if ${MK_FORTH} != "no" +SUBDIR+= ficl32 +.endif Index: stable/10/sys/boot/amd64/Makefile.inc =================================================================== --- stable/10/sys/boot/amd64/Makefile.inc (nonexistent) +++ stable/10/sys/boot/amd64/Makefile.inc (revision 271135) @@ -0,0 +1,12 @@ +# Common defines for all of /sys/boot/amd64/ +# +# $FreeBSD$ + +BINDIR?= /boot + +# See conf/kern.mk for the correct set of these +CFLAGS+= -ffreestanding +CFLAGS+= -mno-mmx -mno-sse -mno-aes -mno-avx -msoft-float +LDFLAGS+= -nostdlib + +.include "../Makefile.inc" Property changes on: stable/10/sys/boot/amd64/Makefile.inc ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/10/sys/boot/amd64/efi/Makefile =================================================================== --- stable/10/sys/boot/amd64/efi/Makefile (nonexistent) +++ stable/10/sys/boot/amd64/efi/Makefile (revision 271135) @@ -0,0 +1,104 @@ +# $FreeBSD$ + +NO_MAN= + +.include + +# In-tree GCC does not support __attribute__((ms_abi)). +.if ${COMPILER_TYPE} != "gcc" + +MK_SSP= no + +PROG= loader.sym +INTERNALPROG= + +# architecture-specific loader code +SRCS= autoload.c \ + bootinfo.c \ + conf.c \ + copy.c \ + devicename.c \ + elf64_freebsd.c \ + framebuffer.c \ + main.c \ + reloc.c \ + vers.c +SRCS+= amd64_tramp.S \ + start.S + +CFLAGS+= -fPIC +CFLAGS+= -I. +CFLAGS+= -I${.CURDIR}/../../efi/include +CFLAGS+= -I${.CURDIR}/../../efi/include/${MACHINE_CPUARCH} +CFLAGS+= -I${.CURDIR}/../../../contrib/dev/acpica/include +CFLAGS+= -I${.CURDIR}/../../.. + +.if ${MK_FORTH} != "no" +BOOT_FORTH= yes +CFLAGS+= -DBOOT_FORTH +CFLAGS+= -I${.CURDIR}/../../ficl +CFLAGS+= -I${.CURDIR}/../../ficl/${MACHINE_CPUARCH} +LIBFICL= ${.OBJDIR}/../../ficl/libficl.a +.endif + +# Include bcache code. +HAVE_BCACHE= yes + +# Always add MI sources +.PATH: ${.CURDIR}/../../common +.include "${.CURDIR}/../../common/Makefile.inc" +CFLAGS+= -I${.CURDIR}/../../common + +FILES= loader.efi +FILESMODE_loader.efi= ${BINMODE} + +LDSCRIPT= ${.CURDIR}/ldscript.${MACHINE_CPUARCH} +LDFLAGS= -Wl,-T${LDSCRIPT} -Wl,-Bsymbolic -shared -Wl,-znocombreloc + +${PROG}: ${LDSCRIPT} + +CLEANFILES= vers.c loader.efi + +NEWVERSWHAT= "EFI loader" ${MACHINE_CPUARCH} + +vers.c: ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version + sh ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version ${NEWVERSWHAT} + +OBJCOPY?= objcopy +OBJDUMP?= objdump + +.if ${MACHINE_CPUARCH} == "amd64" +EFI_TARGET= efi-app-x86_64 +.else +EFI_TARGET= efi-app-ia32 +.endif + +loader.efi: loader.sym + if [ `${OBJDUMP} -t ${.ALLSRC} | fgrep '*UND*' | wc -l` != 0 ]; then \ + ${OBJDUMP} -t ${.ALLSRC} | fgrep '*UND*'; \ + exit 1; \ + fi + ${OBJCOPY} -j .text -j .sdata -j .data \ + -j .dynamic -j .dynsym -j .rel.dyn \ + -j .rela.dyn -j .reloc -j .eh_frame -j set_Xcommand_set \ + --target=${EFI_TARGET} ${.ALLSRC} ${.TARGET} + +LIBEFI= ${.OBJDIR}/../../efi/libefi/libefi.a +CFLAGS+= -I${.CURDIR}/../../common + +DPADD= ${LIBFICL} ${LIBEFI} ${LIBSTAND} +LDADD= ${LIBFICL} ${LIBEFI} ${LIBSTAND} + +.endif # ${COMPILER_TYPE} != "gcc" + +.include + +beforedepend ${OBJS}: machine x86 + +CLEANFILES+= machine x86 + +machine: + ln -sf ${.CURDIR}/../../../amd64/include machine + +x86: + ln -sf ${.CURDIR}/../../../x86/include x86 Property changes on: stable/10/sys/boot/amd64/efi/Makefile ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/10/sys/boot/amd64/efi/copy.c =================================================================== --- stable/10/sys/boot/amd64/efi/copy.c (nonexistent) +++ stable/10/sys/boot/amd64/efi/copy.c (revision 271135) @@ -0,0 +1,102 @@ +/*- + * Copyright (c) 2013 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Benno Rice under sponsorship from + * the FreeBSD Foundation. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include + +#include +#include + +#include +#include + +#define STAGE_PAGES 8192 /* 32MB */ + +EFI_PHYSICAL_ADDRESS staging; +int stage_offset_set = 0; +ssize_t stage_offset; + +int +x86_efi_copy_init(void) +{ + EFI_STATUS status; + + status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData, + STAGE_PAGES, &staging); + if (EFI_ERROR(status)) { + printf("failed to allocate staging area: %lu\n", + (unsigned long)(status & EFI_ERROR_MASK)); + return (status); + } + + return (0); +} + +ssize_t +x86_efi_copyin(const void *src, vm_offset_t dest, const size_t len) +{ + + if (!stage_offset_set) { + stage_offset = (vm_offset_t)staging - dest; + stage_offset_set = 1; + } + + bcopy(src, (void *)(dest + stage_offset), len); + return (len); +} + +ssize_t +x86_efi_copyout(const vm_offset_t src, void *dest, const size_t len) +{ + + bcopy((void *)(src + stage_offset), dest, len); + return (len); +} + + +ssize_t +x86_efi_readin(const int fd, vm_offset_t dest, const size_t len) +{ + + return (read(fd, (void *)(dest + stage_offset), len)); +} + +void +x86_efi_copy_finish(void) +{ + uint64_t *src, *dst, *last; + + src = (uint64_t *)staging; + dst = (uint64_t *)(staging - stage_offset); + last = (uint64_t *)(staging + STAGE_PAGES * EFI_PAGE_SIZE); + + while (src < last) + *dst++ = *src++; +} Property changes on: stable/10/sys/boot/amd64/efi/copy.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/10/sys/boot/amd64/efi/elf64_freebsd.c =================================================================== --- stable/10/sys/boot/amd64/efi/elf64_freebsd.c (nonexistent) +++ stable/10/sys/boot/amd64/efi/elf64_freebsd.c (revision 271135) @@ -0,0 +1,190 @@ +/*- + * Copyright (c) 1998 Michael Smith + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#define __ELF_WORD_SIZE 64 +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "bootstrap.h" + +#include "platform/acfreebsd.h" +#include "acconfig.h" +#define ACPI_SYSTEM_XFACE +#include "actypes.h" +#include "actbl.h" + +#include "x86_efi.h" + +static EFI_GUID acpi_guid = ACPI_TABLE_GUID; +static EFI_GUID acpi20_guid = ACPI_20_TABLE_GUID; + +extern int bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp); + +static int elf64_exec(struct preloaded_file *amp); +static int elf64_obj_exec(struct preloaded_file *amp); + +struct file_format amd64_elf = { elf64_loadfile, elf64_exec }; +struct file_format amd64_elf_obj = { elf64_obj_loadfile, elf64_obj_exec }; + +#define PG_V 0x001 +#define PG_RW 0x002 +#define PG_U 0x004 +#define PG_PS 0x080 + +typedef u_int64_t p4_entry_t; +typedef u_int64_t p3_entry_t; +typedef u_int64_t p2_entry_t; +static p4_entry_t *PT4; +static p3_entry_t *PT3; +static p2_entry_t *PT2; + +static void (*trampoline)(uint64_t stack, void *copy_finish, uint64_t kernend, + uint64_t modulep, p4_entry_t *pagetable, + uint64_t entry); + +extern uintptr_t amd64_tramp; +extern uint32_t amd64_tramp_size; + +/* + * There is an ELF kernel and one or more ELF modules loaded. + * We wish to start executing the kernel image, so make such + * preparations as are required, and do so. + */ +static int +elf64_exec(struct preloaded_file *fp) +{ + struct file_metadata *md; + Elf_Ehdr *ehdr; + vm_offset_t modulep, kernend, trampcode, trampstack; + int err, i; + ACPI_TABLE_RSDP *rsdp; + char buf[24]; + int revision; + EFI_STATUS status; + + rsdp = efi_get_table(&acpi20_guid); + if (rsdp == NULL) { + rsdp = efi_get_table(&acpi_guid); + } + if (rsdp != NULL) { + sprintf(buf, "0x%016llx", (unsigned long long)rsdp); + setenv("hint.acpi.0.rsdp", buf, 1); + revision = rsdp->Revision; + if (revision == 0) + revision = 1; + sprintf(buf, "%d", revision); + setenv("hint.acpi.0.revision", buf, 1); + strncpy(buf, rsdp->OemId, sizeof(rsdp->OemId)); + buf[sizeof(rsdp->OemId)] = '\0'; + setenv("hint.acpi.0.oem", buf, 1); + sprintf(buf, "0x%016x", rsdp->RsdtPhysicalAddress); + setenv("hint.acpi.0.rsdt", buf, 1); + if (revision >= 2) { + /* XXX extended checksum? */ + sprintf(buf, "0x%016llx", + (unsigned long long)rsdp->XsdtPhysicalAddress); + setenv("hint.acpi.0.xsdt", buf, 1); + sprintf(buf, "%d", rsdp->Length); + setenv("hint.acpi.0.xsdt_length", buf, 1); + } + } + + if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) + return(EFTYPE); + ehdr = (Elf_Ehdr *)&(md->md_data); + + trampcode = (vm_offset_t)0x0000000040000000; + err = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData, 1, + (EFI_PHYSICAL_ADDRESS *)&trampcode); + bzero((void *)trampcode, EFI_PAGE_SIZE); + trampstack = trampcode + EFI_PAGE_SIZE - 8; + bcopy((void *)&amd64_tramp, (void *)trampcode, amd64_tramp_size); + trampoline = (void *)trampcode; + + PT4 = (p4_entry_t *)0x0000000040000000; + err = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData, 3, + (EFI_PHYSICAL_ADDRESS *)&PT4); + bzero(PT4, 3 * EFI_PAGE_SIZE); + + PT3 = &PT4[512]; + PT2 = &PT3[512]; + + /* + * This is kinda brutal, but every single 1GB VM memory segment points + * to the same first 1GB of physical memory. But it is more than + * adequate. + */ + for (i = 0; i < 512; i++) { + /* Each slot of the L4 pages points to the same L3 page. */ + PT4[i] = (p4_entry_t)PT3; + PT4[i] |= PG_V | PG_RW | PG_U; + + /* Each slot of the L3 pages points to the same L2 page. */ + PT3[i] = (p3_entry_t)PT2; + PT3[i] |= PG_V | PG_RW | PG_U; + + /* The L2 page slots are mapped with 2MB pages for 1GB. */ + PT2[i] = i * (2 * 1024 * 1024); + PT2[i] |= PG_V | PG_RW | PG_PS | PG_U; + } + + printf("Start @ 0x%lx ...\n", ehdr->e_entry); + + err = bi_load(fp->f_args, &modulep, &kernend); + if (err != 0) + return(err); + + status = BS->ExitBootServices(IH, x86_efi_mapkey); + if (EFI_ERROR(status)) { + printf("%s: ExitBootServices() returned 0x%lx\n", __func__, + (long)status); + return (EINVAL); + } + + dev_cleanup(); + + trampoline(trampstack, x86_efi_copy_finish, kernend, modulep, PT4, + ehdr->e_entry); + + panic("exec returned"); +} + +static int +elf64_obj_exec(struct preloaded_file *fp) +{ + return (EFTYPE); +} Property changes on: stable/10/sys/boot/amd64/efi/elf64_freebsd.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/10/sys/boot/amd64/efi/main.c =================================================================== --- stable/10/sys/boot/amd64/efi/main.c (nonexistent) +++ stable/10/sys/boot/amd64/efi/main.c (revision 271135) @@ -0,0 +1,377 @@ +/*- + * Copyright (c) 2008-2010 Rui Paulo + * Copyright (c) 2006 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include + +#include +#include + +#include +#include "x86_efi.h" + +extern char bootprog_name[]; +extern char bootprog_rev[]; +extern char bootprog_date[]; +extern char bootprog_maker[]; + +struct devdesc currdev; /* our current device */ +struct arch_switch archsw; /* MI/MD interface boundary */ + +EFI_GUID acpi = ACPI_TABLE_GUID; +EFI_GUID acpi20 = ACPI_20_TABLE_GUID; +EFI_GUID devid = DEVICE_PATH_PROTOCOL; +EFI_GUID imgid = LOADED_IMAGE_PROTOCOL; +EFI_GUID mps = MPS_TABLE_GUID; +EFI_GUID netid = EFI_SIMPLE_NETWORK_PROTOCOL; +EFI_GUID smbios = SMBIOS_TABLE_GUID; + +EFI_STATUS +main(int argc, CHAR16 *argv[]) +{ + char vendor[128]; + EFI_LOADED_IMAGE *img; + int i; + + /* + * XXX Chicken-and-egg problem; we want to have console output + * early, but some console attributes may depend on reading from + * eg. the boot device, which we can't do yet. We can use + * printf() etc. once this is done. + */ + cons_probe(); + + if (x86_efi_copy_init()) { + printf("failed to allocate staging area\n"); + return (EFI_BUFFER_TOO_SMALL); + } + + /* + * March through the device switch probing for things. + */ + for (i = 0; devsw[i] != NULL; i++) + if (devsw[i]->dv_init != NULL) + (devsw[i]->dv_init)(); + + /* Get our loaded image protocol interface structure. */ + BS->HandleProtocol(IH, &imgid, (VOID**)&img); + + printf("Image base: 0x%lx\n", (u_long)img->ImageBase); + printf("EFI version: %d.%02d\n", ST->Hdr.Revision >> 16, + ST->Hdr.Revision & 0xffff); + printf("EFI Firmware: "); + /* printf doesn't understand EFI Unicode */ + ST->ConOut->OutputString(ST->ConOut, ST->FirmwareVendor); + printf(" (rev %d.%02d)\n", ST->FirmwareRevision >> 16, + ST->FirmwareRevision & 0xffff); + + printf("\n"); + printf("%s, Revision %s\n", bootprog_name, bootprog_rev); + printf("(%s, %s)\n", bootprog_maker, bootprog_date); + + efi_handle_lookup(img->DeviceHandle, &currdev.d_dev, &currdev.d_unit); + currdev.d_type = currdev.d_dev->dv_type; + + /* + * Disable the watchdog timer. By default the boot manager sets + * the timer to 5 minutes before invoking a boot option. If we + * want to return to the boot manager, we have to disable the + * watchdog timer and since we're an interactive program, we don't + * want to wait until the user types "quit". The timer may have + * fired by then. We don't care if this fails. It does not prevent + * normal functioning in any way... + */ + BS->SetWatchdogTimer(0, 0, 0, NULL); + + env_setenv("currdev", EV_VOLATILE, x86_efi_fmtdev(&currdev), + x86_efi_setcurrdev, env_nounset); + env_setenv("loaddev", EV_VOLATILE, x86_efi_fmtdev(&currdev), env_noset, + env_nounset); + + setenv("LINES", "24", 1); /* optional */ + + archsw.arch_autoload = x86_efi_autoload; + archsw.arch_getdev = x86_efi_getdev; + archsw.arch_copyin = x86_efi_copyin; + archsw.arch_copyout = x86_efi_copyout; + archsw.arch_readin = x86_efi_readin; + + interact(); /* doesn't return */ + + return (EFI_SUCCESS); /* keep compiler happy */ +} + +COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot); + +static int +command_reboot(int argc, char *argv[]) +{ + int i; + + for (i = 0; devsw[i] != NULL; ++i) + if (devsw[i]->dv_cleanup != NULL) + (devsw[i]->dv_cleanup)(); + + RS->ResetSystem(EfiResetCold, EFI_SUCCESS, 23, + (CHAR16 *)"Reboot from the loader"); + + /* NOTREACHED */ + return (CMD_ERROR); +} + +COMMAND_SET(quit, "quit", "exit the loader", command_quit); + +static int +command_quit(int argc, char *argv[]) +{ + exit(0); + return (CMD_OK); +} + +COMMAND_SET(memmap, "memmap", "print memory map", command_memmap); + +static int +command_memmap(int argc, char *argv[]) +{ + UINTN sz; + EFI_MEMORY_DESCRIPTOR *map, *p; + UINTN key, dsz; + UINT32 dver; + EFI_STATUS status; + int i, ndesc; + static char *types[] = { + "Reserved", + "LoaderCode", + "LoaderData", + "BootServicesCode", + "BootServicesData", + "RuntimeServicesCode", + "RuntimeServicesData", + "ConventionalMemory", + "UnusableMemory", + "ACPIReclaimMemory", + "ACPIMemoryNVS", + "MemoryMappedIO", + "MemoryMappedIOPortSpace", + "PalCode" + }; + + sz = 0; + status = BS->GetMemoryMap(&sz, 0, &key, &dsz, &dver); + if (status != EFI_BUFFER_TOO_SMALL) { + printf("Can't determine memory map size\n"); + return CMD_ERROR; + } + map = malloc(sz); + status = BS->GetMemoryMap(&sz, map, &key, &dsz, &dver); + if (EFI_ERROR(status)) { + printf("Can't read memory map\n"); + return CMD_ERROR; + } + + ndesc = sz / dsz; + printf("%23s %12s %12s %8s %4s\n", + "Type", "Physical", "Virtual", "#Pages", "Attr"); + + for (i = 0, p = map; i < ndesc; + i++, p = NextMemoryDescriptor(p, dsz)) { + printf("%23s %012lx %012lx %08lx ", + types[p->Type], + p->PhysicalStart, + p->VirtualStart, + p->NumberOfPages); + if (p->Attribute & EFI_MEMORY_UC) + printf("UC "); + if (p->Attribute & EFI_MEMORY_WC) + printf("WC "); + if (p->Attribute & EFI_MEMORY_WT) + printf("WT "); + if (p->Attribute & EFI_MEMORY_WB) + printf("WB "); + if (p->Attribute & EFI_MEMORY_UCE) + printf("UCE "); + if (p->Attribute & EFI_MEMORY_WP) + printf("WP "); + if (p->Attribute & EFI_MEMORY_RP) + printf("RP "); + if (p->Attribute & EFI_MEMORY_XP) + printf("XP "); + printf("\n"); + } + + return CMD_OK; +} + +COMMAND_SET(configuration, "configuration", + "print configuration tables", command_configuration); + +static const char * +guid_to_string(EFI_GUID *guid) +{ + static char buf[40]; + + sprintf(buf, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + guid->Data1, guid->Data2, guid->Data3, guid->Data4[0], + guid->Data4[1], guid->Data4[2], guid->Data4[3], guid->Data4[4], + guid->Data4[5], guid->Data4[6], guid->Data4[7]); + return (buf); +} + +static int +command_configuration(int argc, char *argv[]) +{ + int i; + + printf("NumberOfTableEntries=%ld\n", ST->NumberOfTableEntries); + for (i = 0; i < ST->NumberOfTableEntries; i++) { + EFI_GUID *guid; + + printf(" "); + guid = &ST->ConfigurationTable[i].VendorGuid; + if (!memcmp(guid, &mps, sizeof(EFI_GUID))) + printf("MPS Table"); + else if (!memcmp(guid, &acpi, sizeof(EFI_GUID))) + printf("ACPI Table"); + else if (!memcmp(guid, &acpi20, sizeof(EFI_GUID))) + printf("ACPI 2.0 Table"); + else if (!memcmp(guid, &smbios, sizeof(EFI_GUID))) + printf("SMBIOS Table"); + else + printf("Unknown Table (%s)", guid_to_string(guid)); + printf(" at %p\n", ST->ConfigurationTable[i].VendorTable); + } + + return CMD_OK; +} + + +COMMAND_SET(mode, "mode", "change or display text modes", command_mode); + +static int +command_mode(int argc, char *argv[]) +{ + UINTN cols, rows; + unsigned int mode; + int i; + char *cp; + char rowenv[8]; + EFI_STATUS status; + SIMPLE_TEXT_OUTPUT_INTERFACE *conout; + + conout = ST->ConOut; + + if (argc > 1) { + mode = strtol(argv[1], &cp, 0); + if (cp[0] != '\0') { + printf("Invalid mode\n"); + return (CMD_ERROR); + } + status = conout->QueryMode(conout, mode, &cols, &rows); + if (EFI_ERROR(status)) { + printf("invalid mode %d\n", mode); + return (CMD_ERROR); + } + status = conout->SetMode(conout, mode); + if (EFI_ERROR(status)) { + printf("couldn't set mode %d\n", mode); + return (CMD_ERROR); + } + sprintf(rowenv, "%u", (unsigned)rows); + setenv("LINES", rowenv, 1); + + return (CMD_OK); + } + + for (i = 0; ; i++) { + status = conout->QueryMode(conout, i, &cols, &rows); + if (EFI_ERROR(status)) + break; + printf("Mode %d: %u columns, %u rows\n", i, (unsigned)cols, + (unsigned)rows); + } + + if (i != 0) + printf("Choose the mode with \"col \"\n"); + + return (CMD_OK); +} + + +COMMAND_SET(nvram, "nvram", "get or set NVRAM variables", command_nvram); + +static int +command_nvram(int argc, char *argv[]) +{ + CHAR16 var[128]; + CHAR16 *data; + EFI_STATUS status; + EFI_GUID varguid = { 0,0,0,{0,0,0,0,0,0,0,0} }; + UINTN varsz, datasz; + SIMPLE_TEXT_OUTPUT_INTERFACE *conout; + int i; + + conout = ST->ConOut; + + /* Initiate the search */ + status = RS->GetNextVariableName(&varsz, NULL, NULL); + + for (; status != EFI_NOT_FOUND; ) { + status = RS->GetNextVariableName(&varsz, var, + &varguid); + //if (EFI_ERROR(status)) + //break; + + conout->OutputString(conout, var); + printf("="); + datasz = 0; + status = RS->GetVariable(var, &varguid, NULL, &datasz, + NULL); + /* XXX: check status */ + data = malloc(datasz); + status = RS->GetVariable(var, &varguid, NULL, &datasz, + data); + if (EFI_ERROR(status)) + printf(""); + else { + for (i = 0; i < datasz; i++) { + if (isalnum(data[i]) || isspace(data[i])) + printf("%c", data[i]); + else + printf("\\x%02x", data[i]); + } + } + /* XXX */ + pager_output("\n"); + free(data); + } + + return (CMD_OK); +} Property changes on: stable/10/sys/boot/amd64/efi/main.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/10/sys/boot/amd64/efi/amd64_tramp.S =================================================================== --- stable/10/sys/boot/amd64/efi/amd64_tramp.S (nonexistent) +++ stable/10/sys/boot/amd64/efi/amd64_tramp.S (revision 271135) @@ -0,0 +1,64 @@ +/*- + * Copyright (c) 2013 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Benno Rice under sponsorship from + * the FreeBSD Foundation. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include + + .text + .globl amd64_tramp + +/* + * void amd64_tramp(uint64_t stack, void *copy_finish, uint64_t kernend, + * uint64_t modulep, uint64_t pagetable, uint64_t entry) + */ +amd64_tramp: + cli /* Make sure we don't get interrupted. */ + movq %rdi,%rsp /* Switch to our temporary stack. */ + + movq %rdx,%r12 /* Stash the kernel values for later. */ + movq %rcx,%r13 + movq %r8,%r14 + movq %r9,%r15 + + callq *%rsi /* Call copy_finish so we're all ready to go. */ + + pushq %r12 /* Push kernend. */ + salq $32,%r13 /* Shift modulep and push it. */ + pushq %r13 + pushq %r15 /* Push the entry address. */ + movq %r14,%cr3 /* Switch page tables. */ + ret /* "Return" to kernel entry. */ + + ALIGN_TEXT +amd64_tramp_end: + + .data + .globl amd64_tramp_size +amd64_tramp_size: + .long amd64_tramp_end-amd64_tramp Property changes on: stable/10/sys/boot/amd64/efi/amd64_tramp.S ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/10/sys/boot/amd64/efi/autoload.c =================================================================== --- stable/10/sys/boot/amd64/efi/autoload.c (nonexistent) +++ stable/10/sys/boot/amd64/efi/autoload.c (revision 271135) @@ -0,0 +1,35 @@ +/*- + * Copyright (c) 2010 Rui Paulo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +int +x86_efi_autoload(void) +{ + + return (0); +} Property changes on: stable/10/sys/boot/amd64/efi/autoload.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/10/sys/boot/amd64/efi/bootinfo.c =================================================================== --- stable/10/sys/boot/amd64/efi/bootinfo.c (nonexistent) +++ stable/10/sys/boot/amd64/efi/bootinfo.c (revision 271135) @@ -0,0 +1,360 @@ +/*- + * Copyright (c) 1998 Michael Smith + * Copyright (c) 2004, 2006 Marcel Moolenaar + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "bootstrap.h" +#include "framebuffer.h" +#include "x86_efi.h" + +UINTN x86_efi_mapkey; + +static const char howto_switches[] = "aCdrgDmphsv"; +static int howto_masks[] = { + RB_ASKNAME, RB_CDROM, RB_KDB, RB_DFLTROOT, RB_GDB, RB_MULTIPLE, + RB_MUTE, RB_PAUSE, RB_SERIAL, RB_SINGLE, RB_VERBOSE +}; + +static int +bi_getboothowto(char *kargs) +{ + const char *sw; + char *opts; + int howto, i; + + howto = 0; + + /* Get the boot options from the environment first. */ + for (i = 0; howto_names[i].ev != NULL; i++) { + if (getenv(howto_names[i].ev) != NULL) + howto |= howto_names[i].mask; + } + + /* Parse kargs */ + if (kargs == NULL) + return (howto); + + opts = strchr(kargs, '-'); + while (opts != NULL) { + while (*(++opts) != '\0') { + sw = strchr(howto_switches, *opts); + if (sw == NULL) + break; + howto |= howto_masks[sw - howto_switches]; + } + opts = strchr(opts, '-'); + } + + return (howto); +} + +/* + * Copy the environment into the load area starting at (addr). + * Each variable is formatted as =, with a single nul + * separating each variable, and a double nul terminating the environment. + */ +static vm_offset_t +bi_copyenv(vm_offset_t start) +{ + struct env_var *ep; + vm_offset_t addr, last; + size_t len; + + addr = last = start; + + /* Traverse the environment. */ + for (ep = environ; ep != NULL; ep = ep->ev_next) { + len = strlen(ep->ev_name); + if (x86_efi_copyin(ep->ev_name, addr, len) != len) + break; + addr += len; + if (x86_efi_copyin("=", addr, 1) != 1) + break; + addr++; + if (ep->ev_value != NULL) { + len = strlen(ep->ev_value); + if (x86_efi_copyin(ep->ev_value, addr, len) != len) + break; + addr += len; + } + if (x86_efi_copyin("", addr, 1) != 1) + break; + last = ++addr; + } + + if (x86_efi_copyin("", last++, 1) != 1) + last = start; + return(last); +} + +/* + * Copy module-related data into the load area, where it can be + * used as a directory for loaded modules. + * + * Module data is presented in a self-describing format. Each datum + * is preceded by a 32-bit identifier and a 32-bit size field. + * + * Currently, the following data are saved: + * + * MOD_NAME (variable) module name (string) + * MOD_TYPE (variable) module type (string) + * MOD_ARGS (variable) module parameters (string) + * MOD_ADDR sizeof(vm_offset_t) module load address + * MOD_SIZE sizeof(size_t) module size + * MOD_METADATA (variable) type-specific metadata + */ +#define COPY32(v, a, c) { \ + uint32_t x = (v); \ + if (c) \ + x86_efi_copyin(&x, a, sizeof(x)); \ + a += sizeof(x); \ +} + +#define MOD_STR(t, a, s, c) { \ + COPY32(t, a, c); \ + COPY32(strlen(s) + 1, a, c); \ + if (c) \ + x86_efi_copyin(s, a, strlen(s) + 1); \ + a += roundup(strlen(s) + 1, sizeof(uint64_t)); \ +} + +#define MOD_NAME(a, s, c) MOD_STR(MODINFO_NAME, a, s, c) +#define MOD_TYPE(a, s, c) MOD_STR(MODINFO_TYPE, a, s, c) +#define MOD_ARGS(a, s, c) MOD_STR(MODINFO_ARGS, a, s, c) + +#define MOD_VAR(t, a, s, c) { \ + COPY32(t, a, c); \ + COPY32(sizeof(s), a, c); \ + if (c) \ + x86_efi_copyin(&s, a, sizeof(s)); \ + a += roundup(sizeof(s), sizeof(uint64_t)); \ +} + +#define MOD_ADDR(a, s, c) MOD_VAR(MODINFO_ADDR, a, s, c) +#define MOD_SIZE(a, s, c) MOD_VAR(MODINFO_SIZE, a, s, c) + +#define MOD_METADATA(a, mm, c) { \ + COPY32(MODINFO_METADATA | mm->md_type, a, c); \ + COPY32(mm->md_size, a, c); \ + if (c) \ + x86_efi_copyin(mm->md_data, a, mm->md_size); \ + a += roundup(mm->md_size, sizeof(uint64_t)); \ +} + +#define MOD_END(a, c) { \ + COPY32(MODINFO_END, a, c); \ + COPY32(0, a, c); \ +} + +static vm_offset_t +bi_copymodules(vm_offset_t addr) +{ + struct preloaded_file *fp; + struct file_metadata *md; + int c; + uint64_t v; + + c = addr != 0; + /* Start with the first module on the list, should be the kernel. */ + for (fp = file_findfile(NULL, NULL); fp != NULL; fp = fp->f_next) { + MOD_NAME(addr, fp->f_name, c); /* This must come first. */ + MOD_TYPE(addr, fp->f_type, c); + if (fp->f_args) + MOD_ARGS(addr, fp->f_args, c); + v = fp->f_addr; + MOD_ADDR(addr, v, c); + v = fp->f_size; + MOD_SIZE(addr, v, c); + for (md = fp->f_metadata; md != NULL; md = md->md_next) + if (!(md->md_type & MODINFOMD_NOCOPY)) + MOD_METADATA(addr, md, c); + } + MOD_END(addr, c); + return(addr); +} + +static int +bi_load_efi_data(struct preloaded_file *kfp) +{ + EFI_MEMORY_DESCRIPTOR *mm; + EFI_PHYSICAL_ADDRESS addr; + EFI_STATUS status; + size_t efisz; + UINTN mmsz, pages, sz; + UINT32 mmver; + struct efi_map_header *efihdr; + struct efi_fb efifb; + + if (efi_find_framebuffer(&efifb) == 0) + file_addmetadata(kfp, MODINFOMD_EFI_FB, sizeof(efifb), &efifb); + + efisz = (sizeof(struct efi_map_header) + 0xf) & ~0xf; + + /* + * Allocate enough pages to hold the bootinfo block and the memory + * map EFI will return to us. The memory map has an unknown size, + * so we have to determine that first. Note that the AllocatePages + * call can itself modify the memory map, so we have to take that + * into account as well. The changes to the memory map are caused + * by splitting a range of free memory into two (AFAICT), so that + * one is marked as being loader data. + */ + sz = 0; + BS->GetMemoryMap(&sz, NULL, &x86_efi_mapkey, &mmsz, &mmver); + sz += mmsz; + sz = (sz + 0xf) & ~0xf; + pages = EFI_SIZE_TO_PAGES(sz + efisz); + status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData, pages, + &addr); + if (EFI_ERROR(status)) { + printf("%s: AllocatePages() returned 0x%lx\n", __func__, + (long)status); + return (ENOMEM); + } + + /* + * Read the memory map and stash it after bootinfo. Align the + * memory map on a 16-byte boundary (the bootinfo block is page + * aligned). + */ + efihdr = (struct efi_map_header *)addr; + mm = (void *)((uint8_t *)efihdr + efisz); + sz = (EFI_PAGE_SIZE * pages) - efisz; + status = BS->GetMemoryMap(&sz, mm, &x86_efi_mapkey, &mmsz, &mmver); + if (EFI_ERROR(status)) { + printf("%s: GetMemoryMap() returned 0x%lx\n", __func__, + (long)status); + return (EINVAL); + } + + efihdr->memory_size = sz; + efihdr->descriptor_size = mmsz; + efihdr->descriptor_version = mmver; + + file_addmetadata(kfp, MODINFOMD_EFI_MAP, efisz + sz, efihdr); + + return (0); +} + +/* + * Load the information expected by an amd64 kernel. + * + * - The 'boothowto' argument is constructed. + * - The 'bootdev' argument is constructed. + * - The 'bootinfo' struct is constructed, and copied into the kernel space. + * - The kernel environment is copied into kernel space. + * - Module metadata are formatted and placed in kernel space. + */ +int +bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp) +{ + struct preloaded_file *xp, *kfp; + struct devdesc *rootdev; + struct file_metadata *md; + vm_offset_t addr; + uint64_t kernend; + uint64_t envp; + vm_offset_t size; + char *rootdevname; + int howto; + + howto = bi_getboothowto(args); + + /* + * Allow the environment variable 'rootdev' to override the supplied + * device. This should perhaps go to MI code and/or have $rootdev + * tested/set by MI code before launching the kernel. + */ + rootdevname = getenv("rootdev"); + x86_efi_getdev((void**)(&rootdev), rootdevname, NULL); + if (rootdev == NULL) { + printf("Can't determine root device.\n"); + return(EINVAL); + } + + /* Try reading the /etc/fstab file to select the root device */ + getrootmount(x86_efi_fmtdev((void *)rootdev)); + + addr = 0; + for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) { + if (addr < (xp->f_addr + xp->f_size)) + addr = xp->f_addr + xp->f_size; + } + + /* Pad to a page boundary. */ + addr = roundup(addr, PAGE_SIZE); + + /* Copy our environment. */ + envp = addr; + addr = bi_copyenv(addr); + + /* Pad to a page boundary. */ + addr = roundup(addr, PAGE_SIZE); + + kfp = file_findfile(NULL, "elf kernel"); + if (kfp == NULL) + kfp = file_findfile(NULL, "elf64 kernel"); + if (kfp == NULL) + panic("can't find kernel file"); + kernend = 0; /* fill it in later */ + file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto); + file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp); + file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend); + + bi_load_efi_data(kfp); + + /* Figure out the size and location of the metadata. */ + *modulep = addr; + size = bi_copymodules(0); + kernend = roundup(addr + size, PAGE_SIZE); + *kernendp = kernend; + + /* patch MODINFOMD_KERNEND */ + md = file_findmetadata(kfp, MODINFOMD_KERNEND); + bcopy(&kernend, md->md_data, sizeof kernend); + + /* Copy module list and metadata. */ + (void)bi_copymodules(addr); + + return (0); +} Property changes on: stable/10/sys/boot/amd64/efi/bootinfo.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/10/sys/boot/amd64/efi/conf.c =================================================================== --- stable/10/sys/boot/amd64/efi/conf.c (nonexistent) +++ stable/10/sys/boot/amd64/efi/conf.c (revision 271135) @@ -0,0 +1,69 @@ +/*- + * Copyright (c) 2006 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +struct devsw *devsw[] = { + &efipart_dev, + &efinet_dev, + NULL +}; + +struct fs_ops *file_system[] = { + &dosfs_fsops, + &ufs_fsops, + &cd9660_fsops, + &nfs_fsops, + &gzipfs_fsops, + NULL +}; + +struct netif_driver *netif_drivers[] = { + &efinetif, + NULL +}; + +extern struct file_format amd64_elf; +extern struct file_format amd64_elf_obj; + +struct file_format *file_formats[] = { + &amd64_elf, + &amd64_elf_obj, + NULL +}; + +extern struct console efi_console; + +struct console *consoles[] = { + &efi_console, + NULL +}; Property changes on: stable/10/sys/boot/amd64/efi/conf.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/10/sys/boot/amd64/efi/devicename.c =================================================================== --- stable/10/sys/boot/amd64/efi/devicename.c (nonexistent) +++ stable/10/sys/boot/amd64/efi/devicename.c (revision 271135) @@ -0,0 +1,169 @@ +/*- + * Copyright (c) 1998 Michael Smith + * Copyright (c) 2006 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include "bootstrap.h" + +#include +#include + +static int x86_efi_parsedev(struct devdesc **, const char *, const char **); + +/* + * Point (dev) at an allocated device specifier for the device matching the + * path in (devspec). If it contains an explicit device specification, + * use that. If not, use the default device. + */ +int +x86_efi_getdev(void **vdev, const char *devspec, const char **path) +{ + struct devdesc **dev = (struct devdesc **)vdev; + int rv; + + /* + * If it looks like this is just a path and no device, then + * use the current device instead. + */ + if (devspec == NULL || *devspec == '/' || !strchr(devspec, ':')) { + rv = x86_efi_parsedev(dev, getenv("currdev"), NULL); + if (rv == 0 && path != NULL) + *path = devspec; + return (rv); + } + + /* Parse the device name off the beginning of the devspec. */ + return (x86_efi_parsedev(dev, devspec, path)); +} + +/* + * Point (dev) at an allocated device specifier matching the string version + * at the beginning of (devspec). Return a pointer to the remaining + * text in (path). + * + * In all cases, the beginning of (devspec) is compared to the names + * of known devices in the device switch, and then any following text + * is parsed according to the rules applied to the device type. + * + * For disk-type devices, the syntax is: + * + * fs: + */ +static int +x86_efi_parsedev(struct devdesc **dev, const char *devspec, const char **path) +{ + struct devdesc *idev; + struct devsw *dv; + char *cp; + const char *np; + int i, err; + + /* minimum length check */ + if (strlen(devspec) < 2) + return (EINVAL); + + /* look for a device that matches */ + for (i = 0; devsw[i] != NULL; i++) { + dv = devsw[i]; + if (!strncmp(devspec, dv->dv_name, strlen(dv->dv_name))) + break; + } + if (devsw[i] == NULL) + return (ENOENT); + + idev = malloc(sizeof(struct devdesc)); + if (idev == NULL) + return (ENOMEM); + + idev->d_dev = dv; + idev->d_type = dv->dv_type; + idev->d_unit = -1; + + err = 0; + np = devspec + strlen(dv->dv_name); + if (*np != '\0' && *np != ':') { + idev->d_unit = strtol(np, &cp, 0); + if (cp == np) { + idev->d_unit = -1; + free(idev); + return (EUNIT); + } + } + if (*cp != '\0' && *cp != ':') { + free(idev); + return (EINVAL); + } + + if (path != NULL) + *path = (*cp == 0) ? cp : cp + 1; + if (dev != NULL) + *dev = idev; + else + free(idev); + return (0); +} + +char * +x86_efi_fmtdev(void *vdev) +{ + struct devdesc *dev = (struct devdesc *)vdev; + static char buf[32]; /* XXX device length constant? */ + + switch(dev->d_type) { + case DEVT_NONE: + strcpy(buf, "(no device)"); + break; + + default: + sprintf(buf, "%s%d:", dev->d_dev->dv_name, dev->d_unit); + break; + } + + return(buf); +} + +/* + * Set currdev to suit the value being supplied in (value) + */ +int +x86_efi_setcurrdev(struct env_var *ev, int flags, const void *value) +{ + struct devdesc *ncurr; + int rv; + + rv = x86_efi_parsedev(&ncurr, value, NULL); + if (rv != 0) + return(rv); + + free(ncurr); + env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL); + return (0); +} Property changes on: stable/10/sys/boot/amd64/efi/devicename.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/10/sys/boot/amd64/efi/framebuffer.c =================================================================== --- stable/10/sys/boot/amd64/efi/framebuffer.c (nonexistent) +++ stable/10/sys/boot/amd64/efi/framebuffer.c (revision 271135) @@ -0,0 +1,85 @@ +/*- + * Copyright (c) 2013 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Benno Rice under sponsorship from + * the FreeBSD Foundation. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include + +#include +#include +#include + +static EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; + +int +efi_find_framebuffer(struct efi_fb *efifb) +{ + EFI_GRAPHICS_OUTPUT *gop; + EFI_STATUS status; + EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *mode; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info; + + status = BS->LocateProtocol(&gop_guid, NULL, (VOID **)&gop); + if (EFI_ERROR(status)) + return (1); + + mode = gop->Mode; + info = gop->Mode->Info; + + efifb->fb_addr = mode->FrameBufferBase; + efifb->fb_size = mode->FrameBufferSize; + efifb->fb_height = info->VerticalResolution; + efifb->fb_width = info->HorizontalResolution; + efifb->fb_stride = info->PixelsPerScanLine; + + switch (info->PixelFormat) { + case PixelRedGreenBlueReserved8BitPerColor: + efifb->fb_mask_red = 0x000000ff; + efifb->fb_mask_green = 0x0000ff00; + efifb->fb_mask_blue = 0x00ff0000; + efifb->fb_mask_reserved = 0xff000000; + break; + case PixelBlueGreenRedReserved8BitPerColor: + efifb->fb_mask_red = 0x00ff0000; + efifb->fb_mask_green = 0x0000ff00; + efifb->fb_mask_blue = 0x000000ff; + efifb->fb_mask_reserved = 0xff000000; + break; + case PixelBitMask: + efifb->fb_mask_red = info->PixelInformation.RedMask; + efifb->fb_mask_green = info->PixelInformation.GreenMask; + efifb->fb_mask_blue = info->PixelInformation.BlueMask; + efifb->fb_mask_reserved = + info->PixelInformation.ReservedMask; + break; + default: + return (1); + } + return (0); +} Property changes on: stable/10/sys/boot/amd64/efi/framebuffer.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/10/sys/boot/amd64/efi/framebuffer.h =================================================================== --- stable/10/sys/boot/amd64/efi/framebuffer.h (nonexistent) +++ stable/10/sys/boot/amd64/efi/framebuffer.h (revision 271135) @@ -0,0 +1,36 @@ +/*- + * Copyright (c) 2013 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Benno Rice under sponsorship from + * the FreeBSD Foundation. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _EFIFB_H_ +#define _EFIFB_H_ + +int efi_find_framebuffer(struct efi_fb *efifb); + +#endif /* _EFIFB_H_ */ Property changes on: stable/10/sys/boot/amd64/efi/framebuffer.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/10/sys/boot/amd64/efi/ldscript.amd64 =================================================================== --- stable/10/sys/boot/amd64/efi/ldscript.amd64 (nonexistent) +++ stable/10/sys/boot/amd64/efi/ldscript.amd64 (revision 271135) @@ -0,0 +1,67 @@ +/* $FreeBSD$ */ +OUTPUT_FORMAT("elf64-x86-64-freebsd", "elf64-x86-64-freebsd", "elf64-x86-64-freebsd") +OUTPUT_ARCH(i386:x86-64) +ENTRY(_start) +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = 0; + ImageBase = .; + .hash : { *(.hash) } /* this MUST come first! */ + . = ALIGN(4096); + .eh_frame : + { + *(.eh_frame) + } + . = ALIGN(4096); + .text : { + *(.text .stub .text.* .gnu.linkonce.t.*) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.plt) + } =0x00300000010070000002000001000400 + . = ALIGN(4096); + .data : { + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + *(.opd) + *(.data .data.* .gnu.linkonce.d.*) + *(.data1) + *(.plabel) + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + } + . = ALIGN(4096); + set_Xcommand_set : { + __start_set_Xcommand_set = .; + *(set_Xcommand_set) + __stop_set_Xcommand_set = .; + } + . = ALIGN(4096); + __gp = .; + .sdata : { + *(.got.plt .got) + *(.sdata .sdata.* .gnu.linkonce.s.*) + *(dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + } + . = ALIGN(4096); + .dynamic : { *(.dynamic) } + . = ALIGN(4096); + .rela.dyn : { + *(.rela.data*) + *(.rela.got) + *(.rela.stab) + *(.relaset_*) + } + . = ALIGN(4096); + .reloc : { *(.reloc) } + . = ALIGN(4096); + .dynsym : { *(.dynsym) } + . = ALIGN(4096); + .dynstr : { *(.dynstr) } +} Property changes on: stable/10/sys/boot/amd64/efi/ldscript.amd64 ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/10/sys/boot/amd64/efi/reloc.c =================================================================== --- stable/10/sys/boot/amd64/efi/reloc.c (nonexistent) +++ stable/10/sys/boot/amd64/efi/reloc.c (revision 271135) @@ -0,0 +1,107 @@ +/*- + * Copyright (c) 2008-2010 Rui Paulo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#ifdef __i386__ +#define ElfW_Rel Elf32_Rel +#define ElfW_Dyn Elf32_Dyn +#define ELFW_R_TYPE ELF32_R_TYPE +#elif __amd64__ +#define ElfW_Rel Elf64_Rel +#define ElfW_Dyn Elf64_Dyn +#define ELFW_R_TYPE ELF64_R_TYPE +#endif + +/* + * A simple relocator for IA32/AMD64 EFI binaries. + */ +EFI_STATUS +_reloc(unsigned long ImageBase, ElfW_Dyn *dynamic, EFI_HANDLE image_handle, + EFI_SYSTEM_TABLE *system_table) +{ + unsigned long relsz, relent; + unsigned long *newaddr; + ElfW_Rel *rel; + ElfW_Dyn *dynp; + + /* + * Find the relocation address, its size and the relocation entry. + */ + relsz = 0; + relent = 0; + for (dynp = dynamic; dynp->d_tag != DT_NULL; dynp++) { + switch (dynp->d_tag) { + case DT_REL: + case DT_RELA: + rel = (ElfW_Rel *) ((unsigned long) dynp->d_un.d_ptr + + ImageBase); + break; + case DT_RELSZ: + case DT_RELASZ: + relsz = dynp->d_un.d_val; + break; + case DT_RELENT: + case DT_RELAENT: + relent = dynp->d_un.d_val; + break; + default: + break; + } + } + + /* + * Perform the actual relocation. + * XXX: We are reusing code for the amd64 version of this, but + * we must make sure the relocation types are the same. + */ + CTASSERT(R_386_NONE == R_X86_64_NONE); + CTASSERT(R_386_RELATIVE == R_X86_64_RELATIVE); + for (; relsz > 0; relsz -= relent) { + switch (ELFW_R_TYPE(rel->r_info)) { + case R_386_NONE: + /* No relocation needs be performed. */ + break; + case R_386_RELATIVE: + /* Address relative to the base address. */ + newaddr = (unsigned long *)(ImageBase + rel->r_offset); + *newaddr += ImageBase; + break; + default: + /* XXX: do we need other relocations ? */ + break; + } + rel = (ElfW_Rel *) ((caddr_t) rel + relent); + } + + return (EFI_SUCCESS); +} Property changes on: stable/10/sys/boot/amd64/efi/reloc.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/10/sys/boot/amd64/efi/start.S =================================================================== --- stable/10/sys/boot/amd64/efi/start.S (nonexistent) +++ stable/10/sys/boot/amd64/efi/start.S (revision 271135) @@ -0,0 +1,76 @@ +/*- + * Copyright (C) 1999 Hewlett-Packard Co. + * Contributed by David Mosberger . + * Copyright (C) 2005 Intel Co. + * Contributed by Fenghua Yu . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hewlett-Packard Co. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * crt0-efi-x86_64.S - x86_64 EFI startup code. + * $FreeBSD$ + */ + + .text + .align 4 + + .globl _start +_start: + subq $8, %rsp + pushq %rcx + pushq %rdx + +0: + lea ImageBase(%rip), %rdi + lea _DYNAMIC(%rip), %rsi + + popq %rcx + popq %rdx + pushq %rcx + pushq %rdx + call _reloc + + popq %rdi + popq %rsi + + call efi_main + addq $8, %rsp + +.exit: + ret + + /* + * hand-craft a dummy .reloc section so EFI knows it's a relocatable + * executable: + */ + + .data + .section .reloc, "a" + .long 0 + .long 10 + .word 0 Property changes on: stable/10/sys/boot/amd64/efi/start.S ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/10/sys/boot/amd64/efi/version =================================================================== --- stable/10/sys/boot/amd64/efi/version (nonexistent) +++ stable/10/sys/boot/amd64/efi/version (revision 271135) @@ -0,0 +1,7 @@ +$FreeBSD$ + +NOTE ANY CHANGES YOU MAKE TO THE BOOTBLOCKS HERE. The format of this +file is important. Make sure the current version number is on line 6. + +1.1: Keep in sync with i386 version. +0.1: Initial i386 version. Derived from ia64. Property changes on: stable/10/sys/boot/amd64/efi/version ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/10/sys/boot/amd64/efi/x86_efi.h =================================================================== --- stable/10/sys/boot/amd64/efi/x86_efi.h (nonexistent) +++ stable/10/sys/boot/amd64/efi/x86_efi.h (revision 271135) @@ -0,0 +1,49 @@ +/*- + * Copyright (c) 2013 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Benno Rice under sponsorship from + * the FreeBSD Foundation. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _X86_EFI_COPY_H_ +#define _X86_EFI_COPY_H_ + +int x86_efi_autoload(void); + +int x86_efi_getdev(void **vdev, const char *devspec, const char **path); +char *x86_efi_fmtdev(void *vdev); +int x86_efi_setcurrdev(struct env_var *ev, int flags, const void *value); + +int x86_efi_copy_init(void); +void x86_efi_copy_finish(void); + +ssize_t x86_efi_copyin(const void *src, vm_offset_t dest, const size_t len); +ssize_t x86_efi_copyout(const vm_offset_t src, void *dest, const size_t len); +ssize_t x86_efi_readin(const int fd, vm_offset_t dest, const size_t len); + +extern UINTN x86_efi_mapkey; + +#endif /* _X86_EFI_COPY_H_ */ Property changes on: stable/10/sys/boot/amd64/efi/x86_efi.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/10/sys/boot/amd64/Makefile =================================================================== --- stable/10/sys/boot/amd64/Makefile (nonexistent) +++ stable/10/sys/boot/amd64/Makefile (revision 271135) @@ -0,0 +1,7 @@ +# $FreeBSD$ + +.include + +SUBDIR= efi + +.include Property changes on: stable/10/sys/boot/amd64/Makefile ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/10/sys/boot/efi/Makefile.inc =================================================================== --- stable/10/sys/boot/efi/Makefile.inc (revision 271134) +++ stable/10/sys/boot/efi/Makefile.inc (revision 271135) @@ -1,20 +1,13 @@ # $FreeBSD$ BINDIR?= /boot -.if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64" +.if ${MACHINE_CPUARCH} == "i386" CFLAGS+= -march=i386 -.endif - -.if ${MACHINE_CPUARCH} == "amd64" -CFLAGS+= -m32 -ACFLAGS+= -m32 -LDFLAGS+= -m elf_i386_fbsd -AFLAGS+= --32 .endif # Options used when building app-specific efi components CFLAGS+= -ffreestanding -fshort-wchar -Wformat LDFLAGS+= -nostdlib .include "../Makefile.inc" Index: stable/10/sys/boot/efi/include/amd64/efibind.h =================================================================== --- stable/10/sys/boot/efi/include/amd64/efibind.h (nonexistent) +++ stable/10/sys/boot/efi/include/amd64/efibind.h (revision 271135) @@ -0,0 +1,267 @@ +/* $FreeBSD$ */ +/*++ + +Copyright (c) 1999 - 2003 Intel Corporation. All rights reserved +This software and associated documentation (if any) is furnished +under a license and may only be used or copied in accordance +with the terms of the license. Except as permitted by such +license, no part of this software or documentation may be +reproduced, stored in a retrieval system, or transmitted in any +form or by any means without the express written consent of +Intel Corporation. + +Module Name: + + efefind.h + +Abstract: + + EFI to compile bindings + + + + +Revision History + +--*/ + +#pragma pack() + + +#ifdef __FreeBSD__ +#include +#else +// +// Basic int types of various widths +// + +#if (__STDC_VERSION__ < 199901L ) + + // No ANSI C 1999/2000 stdint.h integer width declarations + + #if _MSC_EXTENSIONS + + // Use Microsoft C compiler integer width declarations + + typedef unsigned __int64 uint64_t; + typedef __int64 int64_t; + typedef unsigned __int32 uint32_t; + typedef __int32 int32_t; + typedef unsigned short uint16_t; + typedef short int16_t; + typedef unsigned char uint8_t; + typedef char int8_t; + #else + #ifdef UNIX_LP64 + + // Use LP64 programming model from C_FLAGS for integer width declarations + + typedef unsigned long uint64_t; + typedef long int64_t; + typedef unsigned int uint32_t; + typedef int int32_t; + typedef unsigned short uint16_t; + typedef short int16_t; + typedef unsigned char uint8_t; + typedef char int8_t; + #else + + // Assume P64 programming model from C_FLAGS for integer width declarations + + typedef unsigned long long uint64_t; + typedef long long int64_t; + typedef unsigned int uint32_t; + typedef int int32_t; + typedef unsigned short uint16_t; + typedef short int16_t; + typedef unsigned char uint8_t; + typedef char int8_t; + #endif + #endif +#endif +#endif /* __FreeBSD__ */ + +// +// Basic EFI types of various widths +// + +typedef uint64_t UINT64; +typedef int64_t INT64; + +#ifndef _BASETSD_H_ + typedef uint32_t UINT32; + typedef int32_t INT32; +#endif + +typedef uint16_t UINT16; +typedef int16_t INT16; +typedef uint8_t UINT8; +typedef int8_t INT8; + + +#undef VOID +#define VOID void + + +typedef int64_t INTN; +typedef uint64_t UINTN; + +#ifdef EFI_NT_EMULATOR + #define POST_CODE(_Data) +#else + #ifdef EFI_DEBUG +#define POST_CODE(_Data) __asm mov eax,(_Data) __asm out 0x80,al + #else + #define POST_CODE(_Data) + #endif +#endif + +#define EFIERR(a) (0x8000000000000000 | a) +#define EFI_ERROR_MASK 0x8000000000000000 +#define EFIERR_OEM(a) (0xc000000000000000 | a) + + +#define BAD_POINTER 0xFBFBFBFBFBFBFBFB +#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFF + +#define BREAKPOINT() __asm { int 3 } + +// +// Pointers must be aligned to these address to function +// + +#define MIN_ALIGNMENT_SIZE 4 + +#define ALIGN_VARIABLE(Value ,Adjustment) \ + (UINTN)Adjustment = 0; \ + if((UINTN)Value % MIN_ALIGNMENT_SIZE) \ + (UINTN)Adjustment = MIN_ALIGNMENT_SIZE - ((UINTN)Value % MIN_ALIGNMENT_SIZE); \ + Value = (UINTN)Value + (UINTN)Adjustment + + +// +// Define macros to build data structure signatures from characters. +// + +#define EFI_SIGNATURE_16(A,B) ((A) | (B<<8)) +#define EFI_SIGNATURE_32(A,B,C,D) (EFI_SIGNATURE_16(A,B) | (EFI_SIGNATURE_16(C,D) << 16)) +#define EFI_SIGNATURE_64(A,B,C,D,E,F,G,H) (EFI_SIGNATURE_32(A,B,C,D) | ((UINT64)(EFI_SIGNATURE_32(E,F,G,H)) << 32)) + +// +// EFIAPI - prototype calling convention for EFI function pointers +// BOOTSERVICE - prototype for implementation of a boot service interface +// RUNTIMESERVICE - prototype for implementation of a runtime service interface +// RUNTIMEFUNCTION - prototype for implementation of a runtime function that is not a service +// RUNTIME_CODE - pragma macro for declaring runtime code +// + +#ifdef __amd64__ +#define EFIAPI __attribute__((ms_abi)) +#endif + +#ifndef EFIAPI // Forces EFI calling conventions reguardless of compiler options + #if _MSC_EXTENSIONS + #define EFIAPI __cdecl // Force C calling convention for Microsoft C compiler + #else + #define EFIAPI // Substitute expresion to force C calling convention + #endif +#endif + +#define BOOTSERVICE +//#define RUNTIMESERVICE(proto,a) alloc_text("rtcode",a); proto a +//#define RUNTIMEFUNCTION(proto,a) alloc_text("rtcode",a); proto a +#define RUNTIMESERVICE +#define RUNTIMEFUNCTION + + +#define RUNTIME_CODE(a) alloc_text("rtcode", a) +#define BEGIN_RUNTIME_DATA() data_seg("rtdata") +#define END_RUNTIME_DATA() data_seg("") + +#define VOLATILE volatile + +#define MEMORY_FENCE() + +#ifdef EFI_NO_INTERFACE_DECL + #define EFI_FORWARD_DECLARATION(x) + #define EFI_INTERFACE_DECL(x) +#else + #define EFI_FORWARD_DECLARATION(x) typedef struct _##x x + #define EFI_INTERFACE_DECL(x) typedef struct x +#endif + +#ifdef EFI_NT_EMULATOR + +// +// To help ensure proper coding of integrated drivers, they are +// compiled as DLLs. In NT they require a dll init entry pointer. +// The macro puts a stub entry point into the DLL so it will load. +// + +#define EFI_DRIVER_ENTRY_POINT(InitFunction) \ + EFI_STATUS \ + InitFunction ( \ + EFI_HANDLE ImageHandle, \ + EFI_SYSTEM_TABLE *SystemTable \ + ); \ + \ + UINTN \ + __stdcall \ + _DllMainCRTStartup ( \ + UINTN Inst, \ + UINTN reason_for_call, \ + VOID *rserved \ + ) \ + { \ + return 1; \ + } \ + \ + int \ + __declspec( dllexport ) \ + __cdecl \ + InitializeDriver ( \ + void *ImageHandle, \ + void *SystemTable \ + ) \ + { \ + return InitFunction(ImageHandle, SystemTable); \ + } + + + #define LOAD_INTERNAL_DRIVER(_if, type, name, entry) \ + (_if)->LoadInternal(type, name, NULL) + +#else // EFI_NT_EMULATOR + +// +// When build similiar to FW, then link everything together as +// one big module. +// + + #define EFI_DRIVER_ENTRY_POINT(InitFunction) + + #define LOAD_INTERNAL_DRIVER(_if, type, name, entry) \ + (_if)->LoadInternal(type, name, entry) + +#endif // EFI_FW_NT + +#ifdef __FreeBSD__ +#define INTERFACE_DECL(x) struct x +#else +// +// Some compilers don't support the forward reference construct: +// typedef struct XXXXX +// +// The following macro provide a workaround for such cases. +// +#ifdef NO_INTERFACE_DECL +#define INTERFACE_DECL(x) +#else +#define INTERFACE_DECL(x) typedef struct x +#endif +#endif /* __FreeBSD__ */ + +#if _MSC_EXTENSIONS +#pragma warning ( disable : 4731 ) // Suppress warnings about modification of EBP +#endif + Property changes on: stable/10/sys/boot/efi/include/amd64/efibind.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/10/sys/boot/efi/include/amd64/pe.h =================================================================== --- stable/10/sys/boot/efi/include/amd64/pe.h (nonexistent) +++ stable/10/sys/boot/efi/include/amd64/pe.h (revision 271135) @@ -0,0 +1,592 @@ +/* $FreeBSD$ */ +/* + PE32+ header file + */ +#ifndef _PE_H +#define _PE_H + +#define IMAGE_DOS_SIGNATURE 0x5A4D // MZ +#define IMAGE_OS2_SIGNATURE 0x454E // NE +#define IMAGE_OS2_SIGNATURE_LE 0x454C // LE +#define IMAGE_NT_SIGNATURE 0x00004550 // PE00 +#define IMAGE_EDOS_SIGNATURE 0x44454550 // PEED + + +typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header + UINT16 e_magic; // Magic number + UINT16 e_cblp; // Bytes on last page of file + UINT16 e_cp; // Pages in file + UINT16 e_crlc; // Relocations + UINT16 e_cparhdr; // Size of header in paragraphs + UINT16 e_minalloc; // Minimum extra paragraphs needed + UINT16 e_maxalloc; // Maximum extra paragraphs needed + UINT16 e_ss; // Initial (relative) SS value + UINT16 e_sp; // Initial SP value + UINT16 e_csum; // Checksum + UINT16 e_ip; // Initial IP value + UINT16 e_cs; // Initial (relative) CS value + UINT16 e_lfarlc; // File address of relocation table + UINT16 e_ovno; // Overlay number + UINT16 e_res[4]; // Reserved words + UINT16 e_oemid; // OEM identifier (for e_oeminfo) + UINT16 e_oeminfo; // OEM information; e_oemid specific + UINT16 e_res2[10]; // Reserved words + UINT32 e_lfanew; // File address of new exe header + } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; + +typedef struct _IMAGE_OS2_HEADER { // OS/2 .EXE header + UINT16 ne_magic; // Magic number + UINT8 ne_ver; // Version number + UINT8 ne_rev; // Revision number + UINT16 ne_enttab; // Offset of Entry Table + UINT16 ne_cbenttab; // Number of bytes in Entry Table + UINT32 ne_crc; // Checksum of whole file + UINT16 ne_flags; // Flag UINT16 + UINT16 ne_autodata; // Automatic data segment number + UINT16 ne_heap; // Initial heap allocation + UINT16 ne_stack; // Initial stack allocation + UINT32 ne_csip; // Initial CS:IP setting + UINT32 ne_sssp; // Initial SS:SP setting + UINT16 ne_cseg; // Count of file segments + UINT16 ne_cmod; // Entries in Module Reference Table + UINT16 ne_cbnrestab; // Size of non-resident name table + UINT16 ne_segtab; // Offset of Segment Table + UINT16 ne_rsrctab; // Offset of Resource Table + UINT16 ne_restab; // Offset of resident name table + UINT16 ne_modtab; // Offset of Module Reference Table + UINT16 ne_imptab; // Offset of Imported Names Table + UINT32 ne_nrestab; // Offset of Non-resident Names Table + UINT16 ne_cmovent; // Count of movable entries + UINT16 ne_align; // Segment alignment shift count + UINT16 ne_cres; // Count of resource segments + UINT8 ne_exetyp; // Target Operating system + UINT8 ne_flagsothers; // Other .EXE flags + UINT16 ne_pretthunks; // offset to return thunks + UINT16 ne_psegrefbytes; // offset to segment ref. bytes + UINT16 ne_swaparea; // Minimum code swap area size + UINT16 ne_expver; // Expected Windows version number + } IMAGE_OS2_HEADER, *PIMAGE_OS2_HEADER; + +// +// File header format. +// + +typedef struct _IMAGE_FILE_HEADER { + UINT16 Machine; + UINT16 NumberOfSections; + UINT32 TimeDateStamp; + UINT32 PointerToSymbolTable; + UINT32 NumberOfSymbols; + UINT16 SizeOfOptionalHeader; + UINT16 Characteristics; +} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; + +#define IMAGE_SIZEOF_FILE_HEADER 20 + +#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 // Relocation info stripped from file. +#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 // File is executable (i.e. no unresolved externel references). +#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line nunbers stripped from file. +#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 // Local symbols stripped from file. +#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 // Bytes of machine word are reversed. +#define IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine. +#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 // Debugging info stripped from file in .DBG file +#define IMAGE_FILE_SYSTEM 0x1000 // System File. +#define IMAGE_FILE_DLL 0x2000 // File is a DLL. +#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 // Bytes of machine word are reversed. + +#define IMAGE_FILE_MACHINE_UNKNOWN 0 +#define IMAGE_FILE_MACHINE_I386 0x14c // Intel 386. +#define IMAGE_FILE_MACHINE_R3000 0x162 // MIPS little-endian, 0540 big-endian +#define IMAGE_FILE_MACHINE_R4000 0x166 // MIPS little-endian +#define IMAGE_FILE_MACHINE_ALPHA 0x184 // Alpha_AXP +#define IMAGE_FILE_MACHINE_POWERPC 0x1F0 // IBM PowerPC Little-Endian +#define IMAGE_FILE_MACHINE_TAHOE 0x7cc // Intel EM machine +// +// Directory format. +// + +typedef struct _IMAGE_DATA_DIRECTORY { + UINT32 VirtualAddress; + UINT32 Size; +} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; + +#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 + +// +// Optional header format. +// + +typedef struct _IMAGE_OPTIONAL_HEADER { + // + // Standard fields. + // + + UINT16 Magic; + UINT8 MajorLinkerVersion; + UINT8 MinorLinkerVersion; + UINT32 SizeOfCode; + UINT32 SizeOfInitializedData; + UINT32 SizeOfUninitializedData; + UINT32 AddressOfEntryPoint; + UINT32 BaseOfCode; + UINT32 BaseOfData; + + // + // NT additional fields. + // + + UINT32 ImageBase; + UINT32 SectionAlignment; + UINT32 FileAlignment; + UINT16 MajorOperatingSystemVersion; + UINT16 MinorOperatingSystemVersion; + UINT16 MajorImageVersion; + UINT16 MinorImageVersion; + UINT16 MajorSubsystemVersion; + UINT16 MinorSubsystemVersion; + UINT32 Reserved1; + UINT32 SizeOfImage; + UINT32 SizeOfHeaders; + UINT32 CheckSum; + UINT16 Subsystem; + UINT16 DllCharacteristics; + UINT32 SizeOfStackReserve; + UINT32 SizeOfStackCommit; + UINT32 SizeOfHeapReserve; + UINT32 SizeOfHeapCommit; + UINT32 LoaderFlags; + UINT32 NumberOfRvaAndSizes; + IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; +} IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER; + +typedef struct _IMAGE_ROM_OPTIONAL_HEADER { + UINT16 Magic; + UINT8 MajorLinkerVersion; + UINT8 MinorLinkerVersion; + UINT32 SizeOfCode; + UINT32 SizeOfInitializedData; + UINT32 SizeOfUninitializedData; + UINT32 AddressOfEntryPoint; + UINT32 BaseOfCode; + UINT32 BaseOfData; + UINT32 BaseOfBss; + UINT32 GprMask; + UINT32 CprMask[4]; + UINT32 GpValue; +} IMAGE_ROM_OPTIONAL_HEADER, *PIMAGE_ROM_OPTIONAL_HEADER; + +#define IMAGE_SIZEOF_ROM_OPTIONAL_HEADER 56 +#define IMAGE_SIZEOF_STD_OPTIONAL_HEADER 28 +#define IMAGE_SIZEOF_NT_OPTIONAL_HEADER 224 + +#define IMAGE_NT_OPTIONAL_HDR_MAGIC 0x10b +#define IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x107 + +typedef struct _IMAGE_NT_HEADERS { + UINT32 Signature; + IMAGE_FILE_HEADER FileHeader; + IMAGE_OPTIONAL_HEADER OptionalHeader; +} IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS; + +typedef struct _IMAGE_ROM_HEADERS { + IMAGE_FILE_HEADER FileHeader; + IMAGE_ROM_OPTIONAL_HEADER OptionalHeader; +} IMAGE_ROM_HEADERS, *PIMAGE_ROM_HEADERS; + +#define IMAGE_FIRST_SECTION( ntheader ) ((PIMAGE_SECTION_HEADER) \ + ((UINT32)ntheader + \ + FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + \ + ((PIMAGE_NT_HEADERS)(ntheader))->FileHeader.SizeOfOptionalHeader \ + )) + + +// Subsystem Values + +#define IMAGE_SUBSYSTEM_UNKNOWN 0 // Unknown subsystem. +#define IMAGE_SUBSYSTEM_NATIVE 1 // Image doesn't require a subsystem. +#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem. +#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem. +#define IMAGE_SUBSYSTEM_OS2_CUI 5 // image runs in the OS/2 character subsystem. +#define IMAGE_SUBSYSTEM_POSIX_CUI 7 // image run in the Posix character subsystem. + + +// Directory Entries + +#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // Export Directory +#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 // Import Directory +#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 // Resource Directory +#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 // Exception Directory +#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 // Security Directory +#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 // Base Relocation Table +#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 // Debug Directory +#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 // Description String +#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 // Machine Value (MIPS GP) +#define IMAGE_DIRECTORY_ENTRY_TLS 9 // TLS Directory +#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 // Load Configuration Directory + +// +// Section header format. +// + +#define IMAGE_SIZEOF_SHORT_NAME 8 + +typedef struct _IMAGE_SECTION_HEADER { + UINT8 Name[IMAGE_SIZEOF_SHORT_NAME]; + union { + UINT32 PhysicalAddress; + UINT32 VirtualSize; + } Misc; + UINT32 VirtualAddress; + UINT32 SizeOfRawData; + UINT32 PointerToRawData; + UINT32 PointerToRelocations; + UINT32 PointerToLinenumbers; + UINT16 NumberOfRelocations; + UINT16 NumberOfLinenumbers; + UINT32 Characteristics; +} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; + +#define IMAGE_SIZEOF_SECTION_HEADER 40 + +#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 // Reserved. + +#define IMAGE_SCN_CNT_CODE 0x00000020 // Section contains code. +#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 // Section contains initialized data. +#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 // Section contains uninitialized data. + +#define IMAGE_SCN_LNK_OTHER 0x00000100 // Reserved. +#define IMAGE_SCN_LNK_INFO 0x00000200 // Section contains comments or some other type of information. +#define IMAGE_SCN_LNK_REMOVE 0x00000800 // Section contents will not become part of image. +#define IMAGE_SCN_LNK_COMDAT 0x00001000 // Section contents comdat. + +#define IMAGE_SCN_ALIGN_1BYTES 0x00100000 // +#define IMAGE_SCN_ALIGN_2BYTES 0x00200000 // +#define IMAGE_SCN_ALIGN_4BYTES 0x00300000 // +#define IMAGE_SCN_ALIGN_8BYTES 0x00400000 // +#define IMAGE_SCN_ALIGN_16BYTES 0x00500000 // Default alignment if no others are specified. +#define IMAGE_SCN_ALIGN_32BYTES 0x00600000 // +#define IMAGE_SCN_ALIGN_64BYTES 0x00700000 // + +#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 // Section can be discarded. +#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 // Section is not cachable. +#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 // Section is not pageable. +#define IMAGE_SCN_MEM_SHARED 0x10000000 // Section is shareable. +#define IMAGE_SCN_MEM_EXECUTE 0x20000000 // Section is executable. +#define IMAGE_SCN_MEM_READ 0x40000000 // Section is readable. +#define IMAGE_SCN_MEM_WRITE 0x80000000 // Section is writeable. + +// +// Symbol format. +// + + +#define IMAGE_SIZEOF_SYMBOL 18 + +// +// Section values. +// +// Symbols have a section number of the section in which they are +// defined. Otherwise, section numbers have the following meanings: +// + +#define IMAGE_SYM_UNDEFINED (UINT16)0 // Symbol is undefined or is common. +#define IMAGE_SYM_ABSOLUTE (UINT16)-1 // Symbol is an absolute value. +#define IMAGE_SYM_DEBUG (UINT16)-2 // Symbol is a special debug item. + +// +// Type (fundamental) values. +// + +#define IMAGE_SYM_TYPE_NULL 0 // no type. +#define IMAGE_SYM_TYPE_VOID 1 // +#define IMAGE_SYM_TYPE_CHAR 2 // type character. +#define IMAGE_SYM_TYPE_SHORT 3 // type short integer. +#define IMAGE_SYM_TYPE_INT 4 // +#define IMAGE_SYM_TYPE_LONG 5 // +#define IMAGE_SYM_TYPE_FLOAT 6 // +#define IMAGE_SYM_TYPE_DOUBLE 7 // +#define IMAGE_SYM_TYPE_STRUCT 8 // +#define IMAGE_SYM_TYPE_UNION 9 // +#define IMAGE_SYM_TYPE_ENUM 10 // enumeration. +#define IMAGE_SYM_TYPE_MOE 11 // member of enumeration. +#define IMAGE_SYM_TYPE_BYTE 12 // +#define IMAGE_SYM_TYPE_WORD 13 // +#define IMAGE_SYM_TYPE_UINT 14 // +#define IMAGE_SYM_TYPE_DWORD 15 // + +// +// Type (derived) values. +// + +#define IMAGE_SYM_DTYPE_NULL 0 // no derived type. +#define IMAGE_SYM_DTYPE_POINTER 1 // pointer. +#define IMAGE_SYM_DTYPE_FUNCTION 2 // function. +#define IMAGE_SYM_DTYPE_ARRAY 3 // array. + +// +// Storage classes. +// + +#define IMAGE_SYM_CLASS_END_OF_FUNCTION (BYTE )-1 +#define IMAGE_SYM_CLASS_NULL 0 +#define IMAGE_SYM_CLASS_AUTOMATIC 1 +#define IMAGE_SYM_CLASS_EXTERNAL 2 +#define IMAGE_SYM_CLASS_STATIC 3 +#define IMAGE_SYM_CLASS_REGISTER 4 +#define IMAGE_SYM_CLASS_EXTERNAL_DEF 5 +#define IMAGE_SYM_CLASS_LABEL 6 +#define IMAGE_SYM_CLASS_UNDEFINED_LABEL 7 +#define IMAGE_SYM_CLASS_MEMBER_OF_STRUCT 8 +#define IMAGE_SYM_CLASS_ARGUMENT 9 +#define IMAGE_SYM_CLASS_STRUCT_TAG 10 +#define IMAGE_SYM_CLASS_MEMBER_OF_UNION 11 +#define IMAGE_SYM_CLASS_UNION_TAG 12 +#define IMAGE_SYM_CLASS_TYPE_DEFINITION 13 +#define IMAGE_SYM_CLASS_UNDEFINED_STATIC 14 +#define IMAGE_SYM_CLASS_ENUM_TAG 15 +#define IMAGE_SYM_CLASS_MEMBER_OF_ENUM 16 +#define IMAGE_SYM_CLASS_REGISTER_PARAM 17 +#define IMAGE_SYM_CLASS_BIT_FIELD 18 +#define IMAGE_SYM_CLASS_BLOCK 100 +#define IMAGE_SYM_CLASS_FUNCTION 101 +#define IMAGE_SYM_CLASS_END_OF_STRUCT 102 +#define IMAGE_SYM_CLASS_FILE 103 +// new +#define IMAGE_SYM_CLASS_SECTION 104 +#define IMAGE_SYM_CLASS_WEAK_EXTERNAL 105 + +// type packing constants + +#define N_BTMASK 017 +#define N_TMASK 060 +#define N_TMASK1 0300 +#define N_TMASK2 0360 +#define N_BTSHFT 4 +#define N_TSHIFT 2 + +// MACROS + +// +// Communal selection types. +// + +#define IMAGE_COMDAT_SELECT_NODUPLICATES 1 +#define IMAGE_COMDAT_SELECT_ANY 2 +#define IMAGE_COMDAT_SELECT_SAME_SIZE 3 +#define IMAGE_COMDAT_SELECT_EXACT_MATCH 4 +#define IMAGE_COMDAT_SELECT_ASSOCIATIVE 5 + +#define IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY 1 +#define IMAGE_WEAK_EXTERN_SEARCH_LIBRARY 2 +#define IMAGE_WEAK_EXTERN_SEARCH_ALIAS 3 + + +// +// Relocation format. +// + +typedef struct _IMAGE_RELOCATION { + UINT32 VirtualAddress; + UINT32 SymbolTableIndex; + UINT16 Type; +} IMAGE_RELOCATION; + +#define IMAGE_SIZEOF_RELOCATION 10 + +// +// I386 relocation types. +// + +#define IMAGE_REL_I386_ABSOLUTE 0 // Reference is absolute, no relocation is necessary +#define IMAGE_REL_I386_DIR16 01 // Direct 16-bit reference to the symbols virtual address +#define IMAGE_REL_I386_REL16 02 // PC-relative 16-bit reference to the symbols virtual address +#define IMAGE_REL_I386_DIR32 06 // Direct 32-bit reference to the symbols virtual address +#define IMAGE_REL_I386_DIR32NB 07 // Direct 32-bit reference to the symbols virtual address, base not included +#define IMAGE_REL_I386_SEG12 011 // Direct 16-bit reference to the segment-selector bits of a 32-bit virtual address +#define IMAGE_REL_I386_SECTION 012 +#define IMAGE_REL_I386_SECREL 013 +#define IMAGE_REL_I386_REL32 024 // PC-relative 32-bit reference to the symbols virtual address + +// +// MIPS relocation types. +// + +#define IMAGE_REL_MIPS_ABSOLUTE 0 // Reference is absolute, no relocation is necessary +#define IMAGE_REL_MIPS_REFHALF 01 +#define IMAGE_REL_MIPS_REFWORD 02 +#define IMAGE_REL_MIPS_JMPADDR 03 +#define IMAGE_REL_MIPS_REFHI 04 +#define IMAGE_REL_MIPS_REFLO 05 +#define IMAGE_REL_MIPS_GPREL 06 +#define IMAGE_REL_MIPS_LITERAL 07 +#define IMAGE_REL_MIPS_SECTION 012 +#define IMAGE_REL_MIPS_SECREL 013 +#define IMAGE_REL_MIPS_REFWORDNB 042 +#define IMAGE_REL_MIPS_PAIR 045 + +// +// Alpha Relocation types. +// + +#define IMAGE_REL_ALPHA_ABSOLUTE 0x0 +#define IMAGE_REL_ALPHA_REFLONG 0x1 +#define IMAGE_REL_ALPHA_REFQUAD 0x2 +#define IMAGE_REL_ALPHA_GPREL32 0x3 +#define IMAGE_REL_ALPHA_LITERAL 0x4 +#define IMAGE_REL_ALPHA_LITUSE 0x5 +#define IMAGE_REL_ALPHA_GPDISP 0x6 +#define IMAGE_REL_ALPHA_BRADDR 0x7 +#define IMAGE_REL_ALPHA_HINT 0x8 +#define IMAGE_REL_ALPHA_INLINE_REFLONG 0x9 +#define IMAGE_REL_ALPHA_REFHI 0xA +#define IMAGE_REL_ALPHA_REFLO 0xB +#define IMAGE_REL_ALPHA_PAIR 0xC +#define IMAGE_REL_ALPHA_MATCH 0xD +#define IMAGE_REL_ALPHA_SECTION 0xE +#define IMAGE_REL_ALPHA_SECREL 0xF +#define IMAGE_REL_ALPHA_REFLONGNB 0x10 + +// +// IBM PowerPC relocation types. +// + +#define IMAGE_REL_PPC_ABSOLUTE 0x0000 // NOP +#define IMAGE_REL_PPC_ADDR64 0x0001 // 64-bit address +#define IMAGE_REL_PPC_ADDR32 0x0002 // 32-bit address +#define IMAGE_REL_PPC_ADDR24 0x0003 // 26-bit address, shifted left 2 (branch absolute) +#define IMAGE_REL_PPC_ADDR16 0x0004 // 16-bit address +#define IMAGE_REL_PPC_ADDR14 0x0005 // 16-bit address, shifted left 2 (load doubleword) +#define IMAGE_REL_PPC_REL24 0x0006 // 26-bit PC-relative offset, shifted left 2 (branch relative) +#define IMAGE_REL_PPC_REL14 0x0007 // 16-bit PC-relative offset, shifted left 2 (br cond relative) +#define IMAGE_REL_PPC_TOCREL16 0x0008 // 16-bit offset from TOC base +#define IMAGE_REL_PPC_TOCREL14 0x0009 // 16-bit offset from TOC base, shifted left 2 (load doubleword) + +#define IMAGE_REL_PPC_ADDR32NB 0x000A // 32-bit addr w/o image base +#define IMAGE_REL_PPC_SECREL 0x000B // va of containing section (as in an image sectionhdr) +#define IMAGE_REL_PPC_SECTION 0x000C // sectionheader number +#define IMAGE_REL_PPC_IFGLUE 0x000D // substitute TOC restore instruction iff symbol is glue code +#define IMAGE_REL_PPC_IMGLUE 0x000E // symbol is glue code; virtual address is TOC restore instruction + +#define IMAGE_REL_PPC_TYPEMASK 0x00FF // mask to isolate above values in IMAGE_RELOCATION.Type + +// Flag bits in IMAGE_RELOCATION.TYPE + +#define IMAGE_REL_PPC_NEG 0x0100 // subtract reloc value rather than adding it +#define IMAGE_REL_PPC_BRTAKEN 0x0200 // fix branch prediction bit to predict branch taken +#define IMAGE_REL_PPC_BRNTAKEN 0x0400 // fix branch prediction bit to predict branch not taken +#define IMAGE_REL_PPC_TOCDEFN 0x0800 // toc slot defined in file (or, data in toc) + +// +// Based relocation format. +// + +typedef struct _IMAGE_BASE_RELOCATION { + UINT32 VirtualAddress; + UINT32 SizeOfBlock; +// UINT16 TypeOffset[1]; +} IMAGE_BASE_RELOCATION, *PIMAGE_BASE_RELOCATION; + +#define IMAGE_SIZEOF_BASE_RELOCATION 8 + +// +// Based relocation types. +// + +#define IMAGE_REL_BASED_ABSOLUTE 0 +#define IMAGE_REL_BASED_HIGH 1 +#define IMAGE_REL_BASED_LOW 2 +#define IMAGE_REL_BASED_HIGHLOW 3 +#define IMAGE_REL_BASED_HIGHADJ 4 +#define IMAGE_REL_BASED_MIPS_JMPADDR 5 +#define IMAGE_REL_BASED_IA64_IMM64 9 +#define IMAGE_REL_BASED_DIR64 10 + +// +// Line number format. +// + +typedef struct _IMAGE_LINENUMBER { + union { + UINT32 SymbolTableIndex; // Symbol table index of function name if Linenumber is 0. + UINT32 VirtualAddress; // Virtual address of line number. + } Type; + UINT16 Linenumber; // Line number. +} IMAGE_LINENUMBER; + +#define IMAGE_SIZEOF_LINENUMBER 6 + +// +// Archive format. +// + +#define IMAGE_ARCHIVE_START_SIZE 8 +#define IMAGE_ARCHIVE_START "!\n" +#define IMAGE_ARCHIVE_END "`\n" +#define IMAGE_ARCHIVE_PAD "\n" +#define IMAGE_ARCHIVE_LINKER_MEMBER "/ " +#define IMAGE_ARCHIVE_LONGNAMES_MEMBER "// " + +typedef struct _IMAGE_ARCHIVE_MEMBER_HEADER { + UINT8 Name[16]; // File member name - `/' terminated. + UINT8 Date[12]; // File member date - decimal. + UINT8 UserID[6]; // File member user id - decimal. + UINT8 GroupID[6]; // File member group id - decimal. + UINT8 Mode[8]; // File member mode - octal. + UINT8 Size[10]; // File member size - decimal. + UINT8 EndHeader[2]; // String to end header. +} IMAGE_ARCHIVE_MEMBER_HEADER, *PIMAGE_ARCHIVE_MEMBER_HEADER; + +#define IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60 + +// +// DLL support. +// + +// +// Export Format +// + +typedef struct _IMAGE_EXPORT_DIRECTORY { + UINT32 Characteristics; + UINT32 TimeDateStamp; + UINT16 MajorVersion; + UINT16 MinorVersion; + UINT32 Name; + UINT32 Base; + UINT32 NumberOfFunctions; + UINT32 NumberOfNames; + UINT32 *AddressOfFunctions; + UINT32 *AddressOfNames; + UINT32 *AddressOfNameOrdinals; +} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY; + +// +// Import Format +// + +typedef struct _IMAGE_IMPORT_BY_NAME { + UINT16 Hint; + UINT8 Name[1]; +} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME; + +typedef struct _IMAGE_THUNK_DATA { + union { + UINT32 Function; + UINT32 Ordinal; + PIMAGE_IMPORT_BY_NAME AddressOfData; + } u1; +} IMAGE_THUNK_DATA, *PIMAGE_THUNK_DATA; + +#define IMAGE_ORDINAL_FLAG 0x80000000 +#define IMAGE_SNAP_BY_ORDINAL(Ordinal) ((Ordinal & IMAGE_ORDINAL_FLAG) != 0) +#define IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff) + +typedef struct _IMAGE_IMPORT_DESCRIPTOR { + UINT32 Characteristics; + UINT32 TimeDateStamp; + UINT32 ForwarderChain; + UINT32 Name; + PIMAGE_THUNK_DATA FirstThunk; +} IMAGE_IMPORT_DESCRIPTOR, *PIMAGE_IMPORT_DESCRIPTOR; + +#endif Property changes on: stable/10/sys/boot/efi/include/amd64/pe.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/10/sys/boot/efi/include/efi.h =================================================================== --- stable/10/sys/boot/efi/include/efi.h (revision 271134) +++ stable/10/sys/boot/efi/include/efi.h (revision 271135) @@ -1,62 +1,63 @@ /* $FreeBSD$ */ /*++ Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved This software and associated documentation (if any) is furnished under a license and may only be used or copied in accordance with the terms of the license. Except as permitted by such license, no part of this software or documentation may be reproduced, stored in a retrieval system, or transmitted in any form or by any means without the express written consent of Intel Corporation. Module Name: efi.h Abstract: Public EFI header files Revision History --*/ // // Build flags on input // EFI32 // EFI_DEBUG - Enable debugging code // EFI_NT_EMULATOR - Building for running under NT // #ifndef _EFI_INCLUDE_ #define _EFI_INCLUDE_ #define EFI_FIRMWARE_VENDOR L"INTEL" #define EFI_FIRMWARE_MAJOR_REVISION 14 #define EFI_FIRMWARE_MINOR_REVISION 62 #define EFI_FIRMWARE_REVISION ((EFI_FIRMWARE_MAJOR_REVISION <<16) | (EFI_FIRMWARE_MINOR_REVISION)) #include "efibind.h" #include "efidef.h" #include "efidevp.h" #include "efiprot.h" #include "eficon.h" #include "efiser.h" #include "efi_nii.h" #include "efipxebc.h" #include "efinet.h" #include "efiapi.h" #include "efifs.h" #include "efierr.h" +#include "efigop.h" #define EFI_STRINGIZE(a) #a #define EFI_PROTOCOL_DEFINITION(a) EFI_STRINGIZE(Protocol/a/a.h) #define EFI_GUID_DEFINITION(a) EFI_STRINGIZE(Guid/a/a##.h) #define EFI_GUID_STRING(guidpointer, shortstring, longstring) #endif Index: stable/10/sys/boot/efi/include/efigop.h =================================================================== --- stable/10/sys/boot/efi/include/efigop.h (nonexistent) +++ stable/10/sys/boot/efi/include/efigop.h (revision 271135) @@ -0,0 +1,122 @@ +/* $FreeBSD$ */ +/*++ + +Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved +This software and associated documentation (if any) is furnished +under a license and may only be used or copied in accordance +with the terms of the license. Except as permitted by such +license, no part of this software or documentation may be +reproduced, stored in a retrieval system, or transmitted in any +form or by any means without the express written consent of +Intel Corporation. + +Module Name: + + efigop.h + +Abstract: + Info about framebuffers + + + + +Revision History + +--*/ + +#ifndef _EFIGOP_H +#define _EFIGOP_H + +#define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID \ + { 0x9042a9de, 0x23dc, 0x4a38, 0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, \ + 0x51, 0x6a } + +INTERFACE_DECL(_EFI_GRAPHICS_OUTPUT); + +typedef struct { + UINT32 RedMask; + UINT32 GreenMask; + UINT32 BlueMask; + UINT32 ReservedMask; +} EFI_PIXEL_BITMASK; + +typedef enum { + PixelRedGreenBlueReserved8BitPerColor, + PixelBlueGreenRedReserved8BitPerColor, + PixelBitMask, + PixelBltOnly, + PixelFormatMax, +} EFI_GRAPHICS_PIXEL_FORMAT; + +typedef struct { + UINT32 Version; + UINT32 HorizontalResolution; + UINT32 VerticalResolution; + EFI_GRAPHICS_PIXEL_FORMAT PixelFormat; + EFI_PIXEL_BITMASK PixelInformation; + UINT32 PixelsPerScanLine; +} EFI_GRAPHICS_OUTPUT_MODE_INFORMATION; + +typedef struct { + UINT32 MaxMode; + UINT32 Mode; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; + UINTN SizeOfInfo; + EFI_PHYSICAL_ADDRESS FrameBufferBase; + UINTN FrameBufferSize; +} EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE; + +typedef +EFI_STATUS +(EFIAPI *EFI_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE) ( + IN struct _EFI_GRAPHICS_OUTPUT *This, + IN UINT32 ModeNumber, + OUT UINTN *SizeOfInfo, + OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE) ( + IN struct _EFI_GRAPHICS_OUTPUT *This, + IN UINT32 ModeNumber + ); + +typedef struct { + UINT8 Blue; + UINT8 Green; + UINT8 Red; + UINT8 Reserved; +} EFI_GRAPHICS_OUTPUT_BLT_PIXEL; + +typedef enum { + EfiBltVideoFill, + EfiBltVideoToBltBuffer, + EfiBltBufferToVideo, + EfiBltVideoToVideo, + EfiGraphcisOutputBltOperationMax, +} EFI_GRAPHICS_OUTPUT_BLT_OPERATION; + +typedef +EFI_STATUS +(EFIAPI *EFI_GRAPHICS_OUTPUT_PROTOCOL_BLT) ( + IN struct _EFI_GRAPHICS_OUTPUT *This, + IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, + IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta + ); + +typedef struct _EFI_GRAPHICS_OUTPUT { + EFI_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE QueryMode; + EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE SetMode; + EFI_GRAPHICS_OUTPUT_PROTOCOL_BLT Blt; + EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode; +} EFI_GRAPHICS_OUTPUT; + +#endif /* _EFIGOP_H */ Property changes on: stable/10/sys/boot/efi/include/efigop.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/10/sys/boot/efi/include/efilib.h =================================================================== --- stable/10/sys/boot/efi/include/efilib.h (revision 271134) +++ stable/10/sys/boot/efi/include/efilib.h (revision 271135) @@ -1,52 +1,52 @@ /*- * Copyright (c) 2000 Doug Rabson * Copyright (c) 2006 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include extern EFI_HANDLE IH; extern EFI_SYSTEM_TABLE *ST; extern EFI_BOOT_SERVICES *BS; extern EFI_RUNTIME_SERVICES *RS; extern struct devsw efipart_dev; extern struct devsw efinet_dev; extern struct netif_driver efinetif; void *efi_get_table(EFI_GUID *tbl); void efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table); -int efi_register_handles(struct devsw *, EFI_HANDLE *, int); +int efi_register_handles(struct devsw *, EFI_HANDLE *, EFI_HANDLE *, int); EFI_HANDLE efi_find_handle(struct devsw *, int); int efi_handle_lookup(EFI_HANDLE, struct devsw **, int *); int efi_status_to_errno(EFI_STATUS); time_t efi_time(EFI_TIME *); EFI_STATUS main(int argc, CHAR16 *argv[]); void exit(EFI_STATUS status); Index: stable/10/sys/boot/efi/libefi/Makefile =================================================================== --- stable/10/sys/boot/efi/libefi/Makefile (revision 271134) +++ stable/10/sys/boot/efi/libefi/Makefile (revision 271135) @@ -1,16 +1,23 @@ # $FreeBSD$ LIB= efi INTERNALLIB= SRCS= delay.c efi_console.c efinet.c efipart.c errno.c handles.c \ libefi.c time.c +.if ${MACHINE_ARCH} == "amd64" +CFLAGS+= -fPIC +.endif CFLAGS+= -I${.CURDIR}/../include -CFLAGS+= -I${.CURDIR}/../include/${MACHINE_CPUARCH:S/amd64/i386/} +CFLAGS+= -I${.CURDIR}/../include/${MACHINE_CPUARCH} CFLAGS+= -I${.CURDIR}/../../../../lib/libstand # Pick up the bootstrap header for some interface items CFLAGS+= -I${.CURDIR}/../../common + + +# Suppress warning from clang for FreeBSD %b and %D formats +CFLAGS+= -fformat-extensions .include Index: stable/10/sys/boot/efi/libefi/efinet.c =================================================================== --- stable/10/sys/boot/efi/libefi/efinet.c (revision 271134) +++ stable/10/sys/boot/efi/libefi/efinet.c (revision 271135) @@ -1,310 +1,310 @@ /*- * Copyright (c) 2001 Doug Rabson * Copyright (c) 2002, 2006 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include static EFI_GUID sn_guid = EFI_SIMPLE_NETWORK_PROTOCOL; static void efinet_end(struct netif *); static int efinet_get(struct iodesc *, void *, size_t, time_t); static void efinet_init(struct iodesc *, void *); static int efinet_match(struct netif *, void *); static int efinet_probe(struct netif *, void *); static int efinet_put(struct iodesc *, void *, size_t); struct netif_driver efinetif = { .netif_bname = "efinet", .netif_match = efinet_match, .netif_probe = efinet_probe, .netif_init = efinet_init, .netif_get = efinet_get, .netif_put = efinet_put, .netif_end = efinet_end, .netif_ifs = NULL, .netif_nifs = 0 }; #ifdef EFINET_DEBUG static void dump_mode(EFI_SIMPLE_NETWORK_MODE *mode) { int i; printf("State = %x\n", mode->State); printf("HwAddressSize = %u\n", mode->HwAddressSize); printf("MediaHeaderSize = %u\n", mode->MediaHeaderSize); printf("MaxPacketSize = %u\n", mode->MaxPacketSize); printf("NvRamSize = %u\n", mode->NvRamSize); printf("NvRamAccessSize = %u\n", mode->NvRamAccessSize); printf("ReceiveFilterMask = %x\n", mode->ReceiveFilterMask); printf("ReceiveFilterSetting = %u\n", mode->ReceiveFilterSetting); printf("MaxMCastFilterCount = %u\n", mode->MaxMCastFilterCount); printf("MCastFilterCount = %u\n", mode->MCastFilterCount); printf("MCastFilter = {"); for (i = 0; i < mode->MCastFilterCount; i++) printf(" %s", ether_sprintf(mode->MCastFilter[i].Addr)); printf(" }\n"); printf("CurrentAddress = %s\n", ether_sprintf(mode->CurrentAddress.Addr)); printf("BroadcastAddress = %s\n", ether_sprintf(mode->BroadcastAddress.Addr)); printf("PermanentAddress = %s\n", ether_sprintf(mode->PermanentAddress.Addr)); printf("IfType = %u\n", mode->IfType); printf("MacAddressChangeable = %d\n", mode->MacAddressChangeable); printf("MultipleTxSupported = %d\n", mode->MultipleTxSupported); printf("MediaPresentSupported = %d\n", mode->MediaPresentSupported); printf("MediaPresent = %d\n", mode->MediaPresent); } #endif static int efinet_match(struct netif *nif, void *machdep_hint) { return (1); } static int efinet_probe(struct netif *nif, void *machdep_hint) { return (0); } static int efinet_put(struct iodesc *desc, void *pkt, size_t len) { struct netif *nif = desc->io_netif; EFI_SIMPLE_NETWORK *net; EFI_STATUS status; void *buf; net = nif->nif_devdata; status = net->Transmit(net, 0, len, pkt, 0, 0, 0); if (status != EFI_SUCCESS) return (-1); /* Wait for the buffer to be transmitted */ do { buf = 0; /* XXX Is this needed? */ status = net->GetStatus(net, 0, &buf); /* * XXX EFI1.1 and the E1000 card returns a different * address than we gave. Sigh. */ } while (status == EFI_SUCCESS && buf == 0); /* XXX How do we deal with status != EFI_SUCCESS now? */ return ((status == EFI_SUCCESS) ? len : -1); } static int efinet_get(struct iodesc *desc, void *pkt, size_t len, time_t timeout) { struct netif *nif = desc->io_netif; EFI_SIMPLE_NETWORK *net; EFI_STATUS status; UINTN bufsz; time_t t; char buf[2048]; net = nif->nif_devdata; t = time(0); while ((time(0) - t) < timeout) { bufsz = sizeof(buf); status = net->Receive(net, 0, &bufsz, buf, 0, 0, 0); if (status == EFI_SUCCESS) { /* * XXX EFI1.1 and the E1000 card trash our * workspace if we do not do this silly copy. * Either they are not respecting the len * value or do not like the alignment. */ if (bufsz > len) bufsz = len; bcopy(buf, pkt, bufsz); return (bufsz); } if (status != EFI_NOT_READY) return (0); } return (0); } static void efinet_init(struct iodesc *desc, void *machdep_hint) { struct netif *nif = desc->io_netif; EFI_SIMPLE_NETWORK *net; EFI_HANDLE h; EFI_STATUS status; h = nif->nif_driver->netif_ifs[nif->nif_unit].dif_private; status = BS->HandleProtocol(h, &sn_guid, (VOID **)&nif->nif_devdata); if (status != EFI_SUCCESS) { printf("net%d: cannot start interface (status=%ld)\n", nif->nif_unit, (long)status); return; } net = nif->nif_devdata; if (net->Mode->State == EfiSimpleNetworkStopped) { status = net->Start(net); if (status != EFI_SUCCESS) { printf("net%d: cannot start interface (status=%ld)\n", nif->nif_unit, (long)status); return; } } if (net->Mode->State != EfiSimpleNetworkInitialized) { status = net->Initialize(net, 0, 0); if (status != EFI_SUCCESS) { printf("net%d: cannot init. interface (status=%ld)\n", nif->nif_unit, (long)status); return; } } if (net->Mode->ReceiveFilterSetting == 0) { UINT32 mask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST; status = net->ReceiveFilters(net, mask, 0, FALSE, 0, 0); if (status != EFI_SUCCESS) { printf("net%d: cannot set rx. filters (status=%ld)\n", nif->nif_unit, (long)status); return; } } #ifdef EFINET_DEBUG dump_mode(net->Mode); #endif bcopy(net->Mode->CurrentAddress.Addr, desc->myea, 6); desc->xid = 1; } static void efinet_end(struct netif *nif) { EFI_SIMPLE_NETWORK *net = nif->nif_devdata; net->Shutdown(net); } static int efinet_dev_init(void); static void efinet_dev_print(int); struct devsw efinet_dev = { .dv_name = "net", .dv_type = DEVT_NET, .dv_init = efinet_dev_init, .dv_strategy = net_strategy, .dv_open = net_open, .dv_close = net_close, .dv_ioctl = noioctl, .dv_print = efinet_dev_print, .dv_cleanup = NULL }; static int efinet_dev_init() { struct netif_dif *dif; struct netif_stats *stats; EFI_HANDLE *handles; EFI_STATUS status; UINTN sz; int err, i, nifs; sz = 0; handles = NULL; status = BS->LocateHandle(ByProtocol, &sn_guid, 0, &sz, 0); if (status == EFI_BUFFER_TOO_SMALL) { handles = (EFI_HANDLE *)malloc(sz); status = BS->LocateHandle(ByProtocol, &sn_guid, 0, &sz, handles); if (EFI_ERROR(status)) free(handles); } if (EFI_ERROR(status)) return (efi_status_to_errno(status)); nifs = sz / sizeof(EFI_HANDLE); - err = efi_register_handles(&efinet_dev, handles, nifs); + err = efi_register_handles(&efinet_dev, handles, NULL, nifs); free(handles); if (err != 0) return (err); efinetif.netif_nifs = nifs; efinetif.netif_ifs = calloc(nifs, sizeof(struct netif_dif)); stats = calloc(nifs, sizeof(struct netif_stats)); for (i = 0; i < nifs; i++) { dif = &efinetif.netif_ifs[i]; dif->dif_unit = i; dif->dif_nsel = 1; dif->dif_stats = &stats[i]; dif->dif_private = efi_find_handle(&efinet_dev, i); } return (0); } static void efinet_dev_print(int verbose) { char line[80]; EFI_HANDLE h; int unit; for (unit = 0, h = efi_find_handle(&efinet_dev, 0); h != NULL; h = efi_find_handle(&efinet_dev, ++unit)) { sprintf(line, " %s%d:\n", efinet_dev.dv_name, unit); pager_output(line); } } Index: stable/10/sys/boot/efi/libefi/efipart.c =================================================================== --- stable/10/sys/boot/efi/libefi/efipart.c (revision 271134) +++ stable/10/sys/boot/efi/libefi/efipart.c (revision 271135) @@ -1,266 +1,300 @@ /*- * Copyright (c) 2010 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include static EFI_GUID blkio_guid = BLOCK_IO_PROTOCOL; +static EFI_GUID devpath_guid = DEVICE_PATH_PROTOCOL; static int efipart_init(void); static int efipart_strategy(void *, int, daddr_t, size_t, char *, size_t *); static int efipart_open(struct open_file *, ...); static int efipart_close(struct open_file *); static void efipart_print(int); struct devsw efipart_dev = { .dv_name = "part", .dv_type = DEVT_DISK, .dv_init = efipart_init, .dv_strategy = efipart_strategy, .dv_open = efipart_open, .dv_close = efipart_close, .dv_ioctl = noioctl, .dv_print = efipart_print, .dv_cleanup = NULL }; static int efipart_init(void) { EFI_BLOCK_IO *blkio; - EFI_HANDLE *hin, *hout; + EFI_DEVICE_PATH *devpath, *node; + EFI_HANDLE *hin, *hout, *aliases, handle; EFI_STATUS status; UINTN sz; + CHAR16 *path; u_int n, nin, nout; int err; sz = 0; hin = NULL; status = BS->LocateHandle(ByProtocol, &blkio_guid, 0, &sz, 0); if (status == EFI_BUFFER_TOO_SMALL) { - hin = (EFI_HANDLE *)malloc(sz * 2); + hin = (EFI_HANDLE *)malloc(sz * 3); status = BS->LocateHandle(ByProtocol, &blkio_guid, 0, &sz, hin); if (EFI_ERROR(status)) free(hin); } if (EFI_ERROR(status)) return (efi_status_to_errno(status)); /* Filter handles to only include FreeBSD partitions. */ nin = sz / sizeof(EFI_HANDLE); hout = hin + nin; + aliases = hout + nin; nout = 0; + bzero(aliases, nin * sizeof(EFI_HANDLE)); + for (n = 0; n < nin; n++) { - status = BS->HandleProtocol(hin[n], &blkio_guid, &blkio); + status = BS->HandleProtocol(hin[n], &devpath_guid, + (void **)&devpath); + if (EFI_ERROR(status)) { + continue; + } + node = devpath; + while (!IsDevicePathEnd(NextDevicePathNode(node))) + node = NextDevicePathNode(node); + status = BS->HandleProtocol(hin[n], &blkio_guid, + (void**)&blkio); if (EFI_ERROR(status)) continue; if (!blkio->Media->LogicalPartition) continue; - hout[nout] = hin[n]; + + /* + * If we come across a logical partition of subtype CDROM + * it doesn't refer to the CD filesystem itself, but rather + * to any usable El Torito boot image on it. In this case + * we try to find the parent device and add that instead as + * that will be the CD filesystem. + */ + if (DevicePathType(node) == MEDIA_DEVICE_PATH && + DevicePathSubType(node) == MEDIA_CDROM_DP) { + node->Type = END_DEVICE_PATH_TYPE; + node->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE; + status = BS->LocateDevicePath(&blkio_guid, &devpath, + &handle); + if (EFI_ERROR(status)) + continue; + hout[nout] = handle; + aliases[nout] = hin[n]; + } else + hout[nout] = hin[n]; nout++; } - err = efi_register_handles(&efipart_dev, hout, nout); + err = efi_register_handles(&efipart_dev, hout, aliases, nout); free(hin); return (err); } static void efipart_print(int verbose) { char line[80]; EFI_BLOCK_IO *blkio; EFI_HANDLE h; EFI_STATUS status; u_int unit; for (unit = 0, h = efi_find_handle(&efipart_dev, 0); h != NULL; h = efi_find_handle(&efipart_dev, ++unit)) { sprintf(line, " %s%d:", efipart_dev.dv_name, unit); pager_output(line); - status = BS->HandleProtocol(h, &blkio_guid, &blkio); + status = BS->HandleProtocol(h, &blkio_guid, (void **)&blkio); if (!EFI_ERROR(status)) { sprintf(line, " %llu blocks", (unsigned long long)(blkio->Media->LastBlock + 1)); pager_output(line); if (blkio->Media->RemovableMedia) pager_output(" (removable)"); } pager_output("\n"); } } static int efipart_open(struct open_file *f, ...) { va_list args; struct devdesc *dev; EFI_BLOCK_IO *blkio; EFI_HANDLE h; EFI_STATUS status; va_start(args, f); dev = va_arg(args, struct devdesc*); va_end(args); h = efi_find_handle(&efipart_dev, dev->d_unit); if (h == NULL) return (EINVAL); - status = BS->HandleProtocol(h, &blkio_guid, &blkio); + status = BS->HandleProtocol(h, &blkio_guid, (void **)&blkio); if (EFI_ERROR(status)) return (efi_status_to_errno(status)); if (!blkio->Media->MediaPresent) return (EAGAIN); dev->d_opendata = blkio; return (0); } static int efipart_close(struct open_file *f) { struct devdesc *dev; dev = (struct devdesc *)(f->f_devdata); if (dev->d_opendata == NULL) return (EINVAL); dev->d_opendata = NULL; return (0); } /* * efipart_readwrite() * Internal equivalent of efipart_strategy(), which operates on the * media-native block size. This function expects all I/O requests * to be within the media size and returns an error if such is not * the case. */ static int efipart_readwrite(EFI_BLOCK_IO *blkio, int rw, daddr_t blk, daddr_t nblks, char *buf) { EFI_STATUS status; if (blkio == NULL) return (ENXIO); if (blk < 0 || blk > blkio->Media->LastBlock) return (EIO); if ((blk + nblks - 1) > blkio->Media->LastBlock) return (EIO); switch (rw) { case F_READ: status = blkio->ReadBlocks(blkio, blkio->Media->MediaId, blk, nblks * blkio->Media->BlockSize, buf); break; case F_WRITE: if (blkio->Media->ReadOnly) return (EROFS); status = blkio->WriteBlocks(blkio, blkio->Media->MediaId, blk, nblks * blkio->Media->BlockSize, buf); break; default: return (ENOSYS); } if (EFI_ERROR(status)) printf("%s: rw=%d, status=%lu\n", __func__, rw, (u_long)status); return (efi_status_to_errno(status)); } static int efipart_strategy(void *devdata, int rw, daddr_t blk, size_t size, char *buf, size_t *rsize) { struct devdesc *dev = (struct devdesc *)devdata; EFI_BLOCK_IO *blkio; off_t off; char *blkbuf; size_t blkoff, blksz; int error; if (dev == NULL || blk < 0) return (EINVAL); blkio = dev->d_opendata; if (blkio == NULL) return (ENXIO); if (size == 0 || (size % 512) != 0) return (EIO); if (rsize != NULL) *rsize = size; if (blkio->Media->BlockSize == 512) return (efipart_readwrite(blkio, rw, blk, size / 512, buf)); /* * The block size of the media is not 512B per sector. */ blkbuf = malloc(blkio->Media->BlockSize); if (blkbuf == NULL) return (ENOMEM); error = 0; off = blk * 512; blk = off / blkio->Media->BlockSize; blkoff = off % blkio->Media->BlockSize; blksz = blkio->Media->BlockSize - blkoff; while (size > 0) { error = efipart_readwrite(blkio, rw, blk, 1, blkbuf); if (error) break; if (size < blksz) blksz = size; bcopy(blkbuf + blkoff, buf, blksz); buf += blksz; size -= blksz; blk++; blkoff = 0; blksz = blkio->Media->BlockSize; } free(blkbuf); return (error); } Index: stable/10/sys/boot/efi/libefi/handles.c =================================================================== --- stable/10/sys/boot/efi/libefi/handles.c (revision 271134) +++ stable/10/sys/boot/efi/libefi/handles.c (revision 271135) @@ -1,90 +1,96 @@ /*- * Copyright (c) 2006 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include struct entry { EFI_HANDLE handle; + EFI_HANDLE alias; struct devsw *dev; int unit; }; struct entry *entry; int nentries; int -efi_register_handles(struct devsw *sw, EFI_HANDLE *handles, int count) +efi_register_handles(struct devsw *sw, EFI_HANDLE *handles, + EFI_HANDLE *aliases, int count) { size_t sz; int idx, unit; idx = nentries; nentries += count; sz = nentries * sizeof(struct entry); entry = (entry == NULL) ? malloc(sz) : realloc(entry, sz); for (unit = 0; idx < nentries; idx++, unit++) { entry[idx].handle = handles[unit]; + if (aliases != NULL) + entry[idx].alias = aliases[unit]; + else + entry[idx].alias = NULL; entry[idx].dev = sw; entry[idx].unit = unit; } return (0); } EFI_HANDLE efi_find_handle(struct devsw *dev, int unit) { int idx; for (idx = 0; idx < nentries; idx++) { if (entry[idx].dev != dev) continue; if (entry[idx].unit != unit) continue; return (entry[idx].handle); } return (NULL); } int efi_handle_lookup(EFI_HANDLE h, struct devsw **dev, int *unit) { int idx; for (idx = 0; idx < nentries; idx++) { - if (entry[idx].handle != h) + if (entry[idx].handle != h && entry[idx].alias != h) continue; if (dev != NULL) *dev = entry[idx].dev; if (unit != NULL) *unit = entry[idx].unit; return (0); } return (ENOENT); } Index: stable/10/sys/boot/ficl/Makefile =================================================================== --- stable/10/sys/boot/ficl/Makefile (revision 271134) +++ stable/10/sys/boot/ficl/Makefile (revision 271135) @@ -1,77 +1,88 @@ # $FreeBSD$ # FICLDIR?= ${.CURDIR} -.if !defined(FICL64) +.if defined(FICL32) .PATH: ${FICLDIR}/${MACHINE_CPUARCH:S/amd64/i386/} .else .PATH: ${FICLDIR}/${MACHINE_CPUARCH} .endif BASE_SRCS= dict.c ficl.c fileaccess.c float.c loader.c math64.c \ prefix.c search.c stack.c tools.c vm.c words.c SRCS= ${BASE_SRCS} sysdep.c softcore.c CLEANFILES= softcore.c testmain testmain.o CFLAGS+= -ffreestanding -.if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64" -.if !defined(FICL64) +.if ${MACHINE_CPUARCH} == "i386" || \ + (${MACHINE_CPUARCH} == "amd64" && defined(FICL32)) CFLAGS+= -march=i386 CFLAGS.gcc+= -mpreferred-stack-boundary=2 .endif +.if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64" CFLAGS+= -mno-mmx -mno-3dnow -mno-sse -mno-sse2 -mno-sse3 -msoft-float .endif .if ${MACHINE_CPUARCH} == "powerpc" || ${MACHINE_CPUARCH} == "arm" CFLAGS+= -msoft-float .endif .if ${MACHINE} == "pc98" CFLAGS+= -Os -DPC98 .endif .if HAVE_PNP CFLAGS+= -DHAVE_PNP .endif .ifmake testmain CFLAGS+= -DTESTMAIN -D_TESTMAIN SRCS+= testmain.c PROG= testmain .include .else LIB= ficl INTERNALLIB= .include .endif # Standard softwords .PATH: ${FICLDIR}/softwords SOFTWORDS= softcore.fr jhlocal.fr marker.fr freebsd.fr ficllocal.fr \ ifbrack.fr # Optional OO extension softwords #SOFTWORDS+= oo.fr classes.fr -.if ${MACHINE_CPUARCH} == "amd64" && !defined(FICL64) +.if ${MACHINE_CPUARCH} == "amd64" +.if defined(FICL32) CFLAGS+= -m32 -I. +.else +CFLAGS+= -fPIC .endif +.endif .if ${MACHINE_ARCH} == "powerpc64" CFLAGS+= -m32 -mcpu=powerpc -I. .endif -CFLAGS+= -I${FICLDIR} -I${FICLDIR}/${MACHINE_CPUARCH:S/amd64/i386/} \ +.if ${MACHINE_CPUARCH} == "amd64" && defined(FICL32) +FICL_CPUARCH= i386 +.else +FICL_CPUARCH= ${MACHINE_CPUARCH} +.endif + +CFLAGS+= -I${FICLDIR} -I${FICLDIR}/${FICL_CPUARCH} \ -I${FICLDIR}/../common softcore.c: ${SOFTWORDS} softcore.awk (cd ${FICLDIR}/softwords; cat ${SOFTWORDS} \ | awk -f softcore.awk -v datestamp="`LC_ALL=C date`") > ${.TARGET} -.if ${MACHINE_CPUARCH} == "amd64" +.if ${MACHINE_CPUARCH} == "amd64" && defined(FICL32) .if !exists(machine) ${SRCS:M*.c:R:S/$/.o/g}: machine beforedepend ${OBJS}: machine .endif machine: ln -sf ${.CURDIR}/../../i386/include machine CLEANFILES+= machine .endif Index: stable/10/sys/boot/ficl/tools.c =================================================================== --- stable/10/sys/boot/ficl/tools.c (revision 271134) +++ stable/10/sys/boot/ficl/tools.c (revision 271135) @@ -1,918 +1,918 @@ /******************************************************************* ** t o o l s . c ** Forth Inspired Command Language - programming tools ** Author: John Sadler (john_sadler@alum.mit.edu) ** Created: 20 June 2000 ** $Id: tools.c,v 1.11 2001/12/05 07:21:34 jsadler Exp $ *******************************************************************/ /* ** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu) ** All rights reserved. ** ** Get the latest Ficl release at http://ficl.sourceforge.net ** ** I am interested in hearing from anyone who uses ficl. If you have ** a problem, a success story, a defect, an enhancement request, or ** if you would like to contribute to the ficl release, please ** contact me by email at the address above. ** ** L I C E N S E and D I S C L A I M E R ** ** Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions ** are met: ** 1. Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** 2. Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in the ** documentation and/or other materials provided with the distribution. ** ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ** SUCH DAMAGE. */ /* ** NOTES: ** SEE needs information about the addresses of functions that ** are the CFAs of colon definitions, constants, variables, DOES> ** words, and so on. It gets this information from a table and supporting ** functions in words.c. ** colonParen doDoes createParen variableParen userParen constantParen ** ** Step and break debugger for Ficl ** debug ( xt -- ) Start debugging an xt ** Set a breakpoint ** Specify breakpoint default action */ /* $FreeBSD$ */ #ifdef TESTMAIN #include #include /* sprintf */ #include #else #include #endif #include #include "ficl.h" #if 0 /* ** nBREAKPOINTS sizes the breakpoint array. One breakpoint (bp 0) is reserved ** for the STEP command. The rest are user programmable. */ #define nBREAKPOINTS 32 #endif /************************************************************************** v m S e t B r e a k ** Set a breakpoint at the current value of IP by ** storing that address in a BREAKPOINT record **************************************************************************/ static void vmSetBreak(FICL_VM *pVM, FICL_BREAKPOINT *pBP) { FICL_WORD *pStep = ficlLookup(pVM->pSys, "step-break"); assert(pStep); pBP->address = pVM->ip; pBP->origXT = *pVM->ip; *pVM->ip = pStep; } /************************************************************************** ** d e b u g P r o m p t **************************************************************************/ static void debugPrompt(FICL_VM *pVM) { vmTextOut(pVM, "dbg> ", 0); } /************************************************************************** ** i s A F i c l W o r d ** Vet a candidate pointer carefully to make sure ** it's not some chunk o' inline data... ** It has to have a name, and it has to look ** like it's in the dictionary address range. ** NOTE: this excludes :noname words! **************************************************************************/ int isAFiclWord(FICL_DICT *pd, FICL_WORD *pFW) { if (!dictIncludes(pd, pFW)) return 0; if (!dictIncludes(pd, pFW->name)) return 0; if ((pFW->link != NULL) && !dictIncludes(pd, pFW->link)) return 0; if ((pFW->nName <= 0) || (pFW->name[pFW->nName] != '\0')) return 0; if (strlen(pFW->name) != pFW->nName) return 0; return 1; } #if 0 static int isPrimitive(FICL_WORD *pFW) { WORDKIND wk = ficlWordClassify(pFW); return ((wk != COLON) && (wk != DOES)); } #endif /************************************************************************** f i n d E n c l o s i n g W o r d ** Given a pointer to something, check to make sure it's an address in the ** dictionary. If so, search backwards until we find something that looks ** like a dictionary header. If successful, return the address of the ** FICL_WORD found. Otherwise return NULL. ** nSEARCH_CELLS sets the maximum neighborhood this func will search before giving up **************************************************************************/ #define nSEARCH_CELLS 100 static FICL_WORD *findEnclosingWord(FICL_VM *pVM, CELL *cp) { FICL_WORD *pFW; FICL_DICT *pd = vmGetDict(pVM); int i; if (!dictIncludes(pd, (void *)cp)) return NULL; for (i = nSEARCH_CELLS; i > 0; --i, --cp) { pFW = (FICL_WORD *)(cp + 1 - (sizeof (FICL_WORD) / sizeof (CELL))); if (isAFiclWord(pd, pFW)) return pFW; } return NULL; } /************************************************************************** s e e ** TOOLS ( "name" -- ) ** Display a human-readable representation of the named word's definition. ** The source of the representation (object-code decompilation, source ** block, etc.) and the particular form of the display is implementation ** defined. **************************************************************************/ /* ** seeColon (for proctologists only) ** Walks a colon definition, decompiling ** on the fly. Knows about primitive control structures. */ static void seeColon(FICL_VM *pVM, CELL *pc) { char *cp; CELL *param0 = pc; FICL_DICT *pd = vmGetDict(pVM); FICL_WORD *pSemiParen = ficlLookup(pVM->pSys, "(;)"); assert(pSemiParen); for (; pc->p != pSemiParen; pc++) { FICL_WORD *pFW = (FICL_WORD *)(pc->p); cp = pVM->pad; if ((void *)pc == (void *)pVM->ip) *cp++ = '>'; else *cp++ = ' '; - cp += sprintf(cp, "%3d ", pc-param0); + cp += sprintf(cp, "%3d ", (int)(pc-param0)); if (isAFiclWord(pd, pFW)) { WORDKIND kind = ficlWordClassify(pFW); CELL c; switch (kind) { case LITERAL: c = *++pc; if (isAFiclWord(pd, c.p)) { FICL_WORD *pLit = (FICL_WORD *)c.p; sprintf(cp, "%.*s ( %#lx literal )", pLit->nName, pLit->name, (unsigned long)c.u); } else sprintf(cp, "literal %ld (%#lx)", (long)c.i, (unsigned long)c.u); break; case STRINGLIT: { FICL_STRING *sp = (FICL_STRING *)(void *)++pc; pc = (CELL *)alignPtr(sp->text + sp->count + 1) - 1; sprintf(cp, "s\" %.*s\"", sp->count, sp->text); } break; case CSTRINGLIT: { FICL_STRING *sp = (FICL_STRING *)(void *)++pc; pc = (CELL *)alignPtr(sp->text + sp->count + 1) - 1; sprintf(cp, "c\" %.*s\"", sp->count, sp->text); } break; case IF: c = *++pc; if (c.i > 0) - sprintf(cp, "if / while (branch %d)", pc+c.i-param0); + sprintf(cp, "if / while (branch %d)", (int)(pc+c.i-param0)); else - sprintf(cp, "until (branch %d)", pc+c.i-param0); + sprintf(cp, "until (branch %d)", (int)(pc+c.i-param0)); break; case BRANCH: c = *++pc; if (c.i == 0) - sprintf(cp, "repeat (branch %d)", pc+c.i-param0); + sprintf(cp, "repeat (branch %d)", (int)(pc+c.i-param0)); else if (c.i == 1) - sprintf(cp, "else (branch %d)", pc+c.i-param0); + sprintf(cp, "else (branch %d)", (int)(pc+c.i-param0)); else - sprintf(cp, "endof (branch %d)", pc+c.i-param0); + sprintf(cp, "endof (branch %d)", (int)(pc+c.i-param0)); break; case OF: c = *++pc; - sprintf(cp, "of (branch %d)", pc+c.i-param0); + sprintf(cp, "of (branch %d)", (int)(pc+c.i-param0)); break; case QDO: c = *++pc; - sprintf(cp, "?do (leave %d)", (CELL *)c.p-param0); + sprintf(cp, "?do (leave %d)", (int)((CELL *)c.p-param0)); break; case DO: c = *++pc; - sprintf(cp, "do (leave %d)", (CELL *)c.p-param0); + sprintf(cp, "do (leave %d)", (int)((CELL *)c.p-param0)); break; case LOOP: c = *++pc; - sprintf(cp, "loop (branch %d)", pc+c.i-param0); + sprintf(cp, "loop (branch %d)", (int)(pc+c.i-param0)); break; case PLOOP: c = *++pc; - sprintf(cp, "+loop (branch %d)", pc+c.i-param0); + sprintf(cp, "+loop (branch %d)", (int)(pc+c.i-param0)); break; default: sprintf(cp, "%.*s", pFW->nName, pFW->name); break; } } else /* probably not a word - punt and print value */ { sprintf(cp, "%ld ( %#lx )", (long)pc->i, (unsigned long)pc->u); } vmTextOut(pVM, pVM->pad, 1); } vmTextOut(pVM, ";", 1); } /* ** Here's the outer part of the decompiler. It's ** just a big nested conditional that checks the ** CFA of the word to decompile for each kind of ** known word-builder code, and tries to do ** something appropriate. If the CFA is not recognized, ** just indicate that it is a primitive. */ static void seeXT(FICL_VM *pVM) { FICL_WORD *pFW; WORDKIND kind; pFW = (FICL_WORD *)stackPopPtr(pVM->pStack); kind = ficlWordClassify(pFW); switch (kind) { case COLON: sprintf(pVM->pad, ": %.*s", pFW->nName, pFW->name); vmTextOut(pVM, pVM->pad, 1); seeColon(pVM, pFW->param); break; case DOES: vmTextOut(pVM, "does>", 1); seeColon(pVM, (CELL *)pFW->param->p); break; case CREATE: vmTextOut(pVM, "create", 1); break; case VARIABLE: sprintf(pVM->pad, "variable = %ld (%#lx)", (long)pFW->param->i, (unsigned long)pFW->param->u); vmTextOut(pVM, pVM->pad, 1); break; #if FICL_WANT_USER case USER: sprintf(pVM->pad, "user variable %ld (%#lx)", (long)pFW->param->i, (unsigned long)pFW->param->u); vmTextOut(pVM, pVM->pad, 1); break; #endif case CONSTANT: sprintf(pVM->pad, "constant = %ld (%#lx)", (long)pFW->param->i, (unsigned long)pFW->param->u); vmTextOut(pVM, pVM->pad, 1); default: sprintf(pVM->pad, "%.*s is a primitive", pFW->nName, pFW->name); vmTextOut(pVM, pVM->pad, 1); break; } if (pFW->flags & FW_IMMEDIATE) { vmTextOut(pVM, "immediate", 1); } if (pFW->flags & FW_COMPILE) { vmTextOut(pVM, "compile-only", 1); } return; } static void see(FICL_VM *pVM) { ficlTick(pVM); seeXT(pVM); return; } /************************************************************************** f i c l D e b u g X T ** debug ( xt -- ) ** Given an xt of a colon definition or a word defined by DOES>, set the ** VM up to debug the word: push IP, set the xt as the next thing to execute, ** set a breakpoint at its first instruction, and run to the breakpoint. ** Note: the semantics of this word are equivalent to "step in" **************************************************************************/ void ficlDebugXT(FICL_VM *pVM) { FICL_WORD *xt = stackPopPtr(pVM->pStack); WORDKIND wk = ficlWordClassify(xt); stackPushPtr(pVM->pStack, xt); seeXT(pVM); switch (wk) { case COLON: case DOES: /* ** Run the colon code and set a breakpoint at the next instruction */ vmExecute(pVM, xt); vmSetBreak(pVM, &(pVM->pSys->bpStep)); break; default: vmExecute(pVM, xt); break; } return; } /************************************************************************** s t e p I n ** FICL ** Execute the next instruction, stepping into it if it's a colon definition ** or a does> word. This is the easy kind of step. **************************************************************************/ void stepIn(FICL_VM *pVM) { /* ** Do one step of the inner loop */ { M_VM_STEP(pVM) } /* ** Now set a breakpoint at the next instruction */ vmSetBreak(pVM, &(pVM->pSys->bpStep)); return; } /************************************************************************** s t e p O v e r ** FICL ** Execute the next instruction atomically. This requires some insight into ** the memory layout of compiled code. Set a breakpoint at the next instruction ** in this word, and run until we hit it **************************************************************************/ void stepOver(FICL_VM *pVM) { FICL_WORD *pFW; WORDKIND kind; FICL_WORD *pStep = ficlLookup(pVM->pSys, "step-break"); assert(pStep); pFW = *pVM->ip; kind = ficlWordClassify(pFW); switch (kind) { case COLON: case DOES: /* ** assume that the next cell holds an instruction ** set a breakpoint there and return to the inner interp */ pVM->pSys->bpStep.address = pVM->ip + 1; pVM->pSys->bpStep.origXT = pVM->ip[1]; pVM->ip[1] = pStep; break; default: stepIn(pVM); break; } return; } /************************************************************************** s t e p - b r e a k ** FICL ** Handles breakpoints for stepped execution. ** Upon entry, bpStep contains the address and replaced instruction ** of the current breakpoint. ** Clear the breakpoint ** Get a command from the console. ** i (step in) - execute the current instruction and set a new breakpoint ** at the IP ** o (step over) - execute the current instruction to completion and set ** a new breakpoint at the IP ** g (go) - execute the current instruction and exit ** q (quit) - abort current word ** b (toggle breakpoint) **************************************************************************/ void stepBreak(FICL_VM *pVM) { STRINGINFO si; FICL_WORD *pFW; FICL_WORD *pOnStep; if (!pVM->fRestart) { assert(pVM->pSys->bpStep.address); assert(pVM->pSys->bpStep.origXT); /* ** Clear the breakpoint that caused me to run ** Restore the original instruction at the breakpoint, ** and restore the IP */ pVM->ip = (IPTYPE)(pVM->pSys->bpStep.address); *pVM->ip = pVM->pSys->bpStep.origXT; /* ** If there's an onStep, do it */ pOnStep = ficlLookup(pVM->pSys, "on-step"); if (pOnStep) ficlExecXT(pVM, pOnStep); /* ** Print the name of the next instruction */ pFW = pVM->pSys->bpStep.origXT; sprintf(pVM->pad, "next: %.*s", pFW->nName, pFW->name); #if 0 if (isPrimitive(pFW)) { strcat(pVM->pad, " ( primitive )"); } #endif vmTextOut(pVM, pVM->pad, 1); debugPrompt(pVM); } else { pVM->fRestart = 0; } si = vmGetWord(pVM); if (!strincmp(si.cp, "i", si.count)) { stepIn(pVM); } else if (!strincmp(si.cp, "g", si.count)) { return; } else if (!strincmp(si.cp, "l", si.count)) { FICL_WORD *xt; xt = findEnclosingWord(pVM, (CELL *)(pVM->ip)); if (xt) { stackPushPtr(pVM->pStack, xt); seeXT(pVM); } else { vmTextOut(pVM, "sorry - can't do that", 1); } vmThrow(pVM, VM_RESTART); } else if (!strincmp(si.cp, "o", si.count)) { stepOver(pVM); } else if (!strincmp(si.cp, "q", si.count)) { ficlTextOut(pVM, FICL_PROMPT, 0); vmThrow(pVM, VM_ABORT); } else if (!strincmp(si.cp, "x", si.count)) { /* ** Take whatever's left in the TIB and feed it to a subordinate ficlExec */ int ret; char *cp = pVM->tib.cp + pVM->tib.index; int count = pVM->tib.end - cp; FICL_WORD *oldRun = pVM->runningWord; ret = ficlExecC(pVM, cp, count); if (ret == VM_OUTOFTEXT) { ret = VM_RESTART; pVM->runningWord = oldRun; vmTextOut(pVM, "", 1); } vmThrow(pVM, ret); } else { vmTextOut(pVM, "i -- step In", 1); vmTextOut(pVM, "o -- step Over", 1); vmTextOut(pVM, "g -- Go (execute to completion)", 1); vmTextOut(pVM, "l -- List source code", 1); vmTextOut(pVM, "q -- Quit (stop debugging and abort)", 1); vmTextOut(pVM, "x -- eXecute the rest of the line as ficl words", 1); debugPrompt(pVM); vmThrow(pVM, VM_RESTART); } return; } /************************************************************************** b y e ** TOOLS ** Signal the system to shut down - this causes ficlExec to return ** VM_USEREXIT. The rest is up to you. **************************************************************************/ static void bye(FICL_VM *pVM) { vmThrow(pVM, VM_USEREXIT); return; } /************************************************************************** d i s p l a y S t a c k ** TOOLS ** Display the parameter stack (code for ".s") **************************************************************************/ static void displayPStack(FICL_VM *pVM) { FICL_STACK *pStk = pVM->pStack; int d = stackDepth(pStk); int i; CELL *pCell; vmCheckStack(pVM, 0, 0); if (d == 0) vmTextOut(pVM, "(Stack Empty) ", 0); else { pCell = pStk->base; for (i = 0; i < d; i++) { vmTextOut(pVM, ltoa((*pCell++).i, pVM->pad, pVM->base), 0); vmTextOut(pVM, " ", 0); } } return; } static void displayRStack(FICL_VM *pVM) { FICL_STACK *pStk = pVM->rStack; int d = stackDepth(pStk); int i; CELL *pCell; FICL_DICT *dp = vmGetDict(pVM); vmCheckStack(pVM, 0, 0); if (d == 0) vmTextOut(pVM, "(Stack Empty) ", 0); else { pCell = pStk->base; for (i = 0; i < d; i++) { CELL c = *pCell++; /* ** Attempt to find the word that contains the ** stacked address (as if it is part of a colon definition). ** If this works, print the name of the word. Otherwise print ** the value as a number. */ if (dictIncludes(dp, c.p)) { FICL_WORD *pFW = findEnclosingWord(pVM, c.p); if (pFW) { int offset = (CELL *)c.p - &pFW->param[0]; sprintf(pVM->pad, "%s+%d ", pFW->name, offset); vmTextOut(pVM, pVM->pad, 0); continue; /* no need to print the numeric value */ } } vmTextOut(pVM, ltoa(c.i, pVM->pad, pVM->base), 0); vmTextOut(pVM, " ", 0); } } return; } /************************************************************************** f o r g e t - w i d ** **************************************************************************/ static void forgetWid(FICL_VM *pVM) { FICL_DICT *pDict = vmGetDict(pVM); FICL_HASH *pHash; pHash = (FICL_HASH *)stackPopPtr(pVM->pStack); hashForget(pHash, pDict->here); return; } /************************************************************************** f o r g e t ** TOOLS EXT ( "name" -- ) ** Skip leading space delimiters. Parse name delimited by a space. ** Find name, then delete name from the dictionary along with all ** words added to the dictionary after name. An ambiguous ** condition exists if name cannot be found. ** ** If the Search-Order word set is present, FORGET searches the ** compilation word list. An ambiguous condition exists if the ** compilation word list is deleted. **************************************************************************/ static void forget(FICL_VM *pVM) { void *where; FICL_DICT *pDict = vmGetDict(pVM); FICL_HASH *pHash = pDict->pCompile; ficlTick(pVM); where = ((FICL_WORD *)stackPopPtr(pVM->pStack))->name; hashForget(pHash, where); pDict->here = PTRtoCELL where; return; } /************************************************************************** l i s t W o r d s ** **************************************************************************/ #define nCOLWIDTH 8 static void listWords(FICL_VM *pVM) { FICL_DICT *dp = vmGetDict(pVM); FICL_HASH *pHash = dp->pSearch[dp->nLists - 1]; FICL_WORD *wp; int nChars = 0; int len; int y = 0; unsigned i; int nWords = 0; char *cp; char *pPad = pVM->pad; for (i = 0; i < pHash->size; i++) { for (wp = pHash->table[i]; wp != NULL; wp = wp->link, nWords++) { if (wp->nName == 0) /* ignore :noname defs */ continue; cp = wp->name; nChars += sprintf(pPad + nChars, "%s", cp); if (nChars > 70) { pPad[nChars] = '\0'; nChars = 0; y++; if(y>23) { y=0; vmTextOut(pVM, "--- Press Enter to continue ---",0); getchar(); vmTextOut(pVM,"\r",0); } vmTextOut(pVM, pPad, 1); } else { len = nCOLWIDTH - nChars % nCOLWIDTH; while (len-- > 0) pPad[nChars++] = ' '; } if (nChars > 70) { pPad[nChars] = '\0'; nChars = 0; y++; if(y>23) { y=0; vmTextOut(pVM, "--- Press Enter to continue ---",0); getchar(); vmTextOut(pVM,"\r",0); } vmTextOut(pVM, pPad, 1); } } } if (nChars > 0) { pPad[nChars] = '\0'; nChars = 0; vmTextOut(pVM, pPad, 1); } sprintf(pVM->pad, "Dictionary: %d words, %ld cells used of %u total", nWords, (long) (dp->here - dp->dict), dp->size); vmTextOut(pVM, pVM->pad, 1); return; } /************************************************************************** l i s t E n v ** Print symbols defined in the environment **************************************************************************/ static void listEnv(FICL_VM *pVM) { FICL_DICT *dp = pVM->pSys->envp; FICL_HASH *pHash = dp->pForthWords; FICL_WORD *wp; unsigned i; int nWords = 0; for (i = 0; i < pHash->size; i++) { for (wp = pHash->table[i]; wp != NULL; wp = wp->link, nWords++) { vmTextOut(pVM, wp->name, 1); } } sprintf(pVM->pad, "Environment: %d words, %ld cells used of %u total", nWords, (long) (dp->here - dp->dict), dp->size); vmTextOut(pVM, pVM->pad, 1); return; } /************************************************************************** e n v C o n s t a n t ** Ficl interface to ficlSetEnv and ficlSetEnvD - allow ficl code to set ** environment constants... **************************************************************************/ static void envConstant(FICL_VM *pVM) { unsigned value; #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 0); #endif vmGetWordToPad(pVM); value = POPUNS(); ficlSetEnv(pVM->pSys, pVM->pad, (FICL_UNS)value); return; } static void env2Constant(FICL_VM *pVM) { unsigned v1, v2; #if FICL_ROBUST > 1 vmCheckStack(pVM, 2, 0); #endif vmGetWordToPad(pVM); v2 = POPUNS(); v1 = POPUNS(); ficlSetEnvD(pVM->pSys, pVM->pad, v1, v2); return; } /************************************************************************** f i c l C o m p i l e T o o l s ** Builds wordset for debugger and TOOLS optional word set **************************************************************************/ void ficlCompileTools(FICL_SYSTEM *pSys) { FICL_DICT *dp = pSys->dp; assert (dp); /* ** TOOLS and TOOLS EXT */ dictAppendWord(dp, ".s", displayPStack, FW_DEFAULT); dictAppendWord(dp, "bye", bye, FW_DEFAULT); dictAppendWord(dp, "forget", forget, FW_DEFAULT); dictAppendWord(dp, "see", see, FW_DEFAULT); dictAppendWord(dp, "words", listWords, FW_DEFAULT); /* ** Set TOOLS environment query values */ ficlSetEnv(pSys, "tools", FICL_TRUE); ficlSetEnv(pSys, "tools-ext", FICL_FALSE); /* ** Ficl extras */ dictAppendWord(dp, "r.s", displayRStack, FW_DEFAULT); /* guy carver */ dictAppendWord(dp, ".env", listEnv, FW_DEFAULT); dictAppendWord(dp, "env-constant", envConstant, FW_DEFAULT); dictAppendWord(dp, "env-2constant", env2Constant, FW_DEFAULT); dictAppendWord(dp, "debug-xt", ficlDebugXT, FW_DEFAULT); dictAppendWord(dp, "parse-order", ficlListParseSteps, FW_DEFAULT); dictAppendWord(dp, "step-break",stepBreak, FW_DEFAULT); dictAppendWord(dp, "forget-wid",forgetWid, FW_DEFAULT); dictAppendWord(dp, "see-xt", seeXT, FW_DEFAULT); return; } Index: stable/10/sys/boot/ficl/words.c =================================================================== --- stable/10/sys/boot/ficl/words.c (revision 271134) +++ stable/10/sys/boot/ficl/words.c (revision 271135) @@ -1,5209 +1,5209 @@ /******************************************************************* ** w o r d s . c ** Forth Inspired Command Language ** ANS Forth CORE word-set written in C ** Author: John Sadler (john_sadler@alum.mit.edu) ** Created: 19 July 1997 ** $Id: words.c,v 1.17 2001/12/05 07:21:34 jsadler Exp $ *******************************************************************/ /* ** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu) ** All rights reserved. ** ** Get the latest Ficl release at http://ficl.sourceforge.net ** ** I am interested in hearing from anyone who uses ficl. If you have ** a problem, a success story, a defect, an enhancement request, or ** if you would like to contribute to the ficl release, please ** contact me by email at the address above. ** ** L I C E N S E and D I S C L A I M E R ** ** Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions ** are met: ** 1. Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** 2. Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in the ** documentation and/or other materials provided with the distribution. ** ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ** SUCH DAMAGE. */ /* $FreeBSD$ */ #ifdef TESTMAIN #include #include #include #include #else #include #endif #include #include "ficl.h" #include "math64.h" static void colonParen(FICL_VM *pVM); static void literalIm(FICL_VM *pVM); static int ficlParseWord(FICL_VM *pVM, STRINGINFO si); /* ** Control structure building words use these ** strings' addresses as markers on the stack to ** check for structure completion. */ static char doTag[] = "do"; static char colonTag[] = "colon"; static char leaveTag[] = "leave"; static char destTag[] = "target"; static char origTag[] = "origin"; static char caseTag[] = "case"; static char ofTag[] = "of"; static char fallthroughTag[] = "fallthrough"; #if FICL_WANT_LOCALS static void doLocalIm(FICL_VM *pVM); static void do2LocalIm(FICL_VM *pVM); #endif /* ** C O N T R O L S T R U C T U R E B U I L D E R S ** ** Push current dict location for later branch resolution. ** The location may be either a branch target or a patch address... */ static void markBranch(FICL_DICT *dp, FICL_VM *pVM, char *tag) { PUSHPTR(dp->here); PUSHPTR(tag); return; } static void markControlTag(FICL_VM *pVM, char *tag) { PUSHPTR(tag); return; } static void matchControlTag(FICL_VM *pVM, char *tag) { char *cp; #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 0); #endif cp = (char *)stackPopPtr(pVM->pStack); /* ** Changed the code below to compare the pointers first (by popular demand) */ if ( (cp != tag) && strcmp(cp, tag) ) { vmThrowErr(pVM, "Error -- unmatched control structure \"%s\"", tag); } return; } /* ** Expect a branch target address on the param stack, ** compile a literal offset from the current dict location ** to the target address */ static void resolveBackBranch(FICL_DICT *dp, FICL_VM *pVM, char *tag) { FICL_INT offset; CELL *patchAddr; matchControlTag(pVM, tag); #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 0); #endif patchAddr = (CELL *)stackPopPtr(pVM->pStack); offset = patchAddr - dp->here; dictAppendCell(dp, LVALUEtoCELL(offset)); return; } /* ** Expect a branch patch address on the param stack, ** compile a literal offset from the patch location ** to the current dict location */ static void resolveForwardBranch(FICL_DICT *dp, FICL_VM *pVM, char *tag) { FICL_INT offset; CELL *patchAddr; matchControlTag(pVM, tag); #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 0); #endif patchAddr = (CELL *)stackPopPtr(pVM->pStack); offset = dp->here - patchAddr; *patchAddr = LVALUEtoCELL(offset); return; } /* ** Match the tag to the top of the stack. If success, ** sopy "here" address into the cell whose address is next ** on the stack. Used by do..leave..loop. */ static void resolveAbsBranch(FICL_DICT *dp, FICL_VM *pVM, char *tag) { CELL *patchAddr; char *cp; #if FICL_ROBUST > 1 vmCheckStack(pVM, 2, 0); #endif cp = stackPopPtr(pVM->pStack); /* ** Changed the comparison below to compare the pointers first (by popular demand) */ if ((cp != tag) && strcmp(cp, tag)) { vmTextOut(pVM, "Warning -- Unmatched control word: ", 0); vmTextOut(pVM, tag, 1); } patchAddr = (CELL *)stackPopPtr(pVM->pStack); *patchAddr = LVALUEtoCELL(dp->here); return; } /************************************************************************** f i c l P a r s e N u m b e r ** Attempts to convert the NULL terminated string in the VM's pad to ** a number using the VM's current base. If successful, pushes the number ** onto the param stack and returns TRUE. Otherwise, returns FALSE. ** (jws 8/01) Trailing decimal point causes a zero cell to be pushed. (See ** the standard for DOUBLE wordset. **************************************************************************/ int ficlParseNumber(FICL_VM *pVM, STRINGINFO si) { FICL_INT accum = 0; char isNeg = FALSE; char hasDP = FALSE; unsigned base = pVM->base; char *cp = SI_PTR(si); FICL_COUNT count= (FICL_COUNT)SI_COUNT(si); unsigned ch; unsigned digit; if (count > 1) { switch (*cp) { case '-': cp++; count--; isNeg = TRUE; break; case '+': cp++; count--; isNeg = FALSE; break; default: break; } } if ((count > 0) && (cp[count-1] == '.')) /* detect & remove trailing decimal */ { hasDP = TRUE; count--; } if (count == 0) /* detect "+", "-", ".", "+." etc */ return FALSE; while ((count--) && ((ch = *cp++) != '\0')) { if (!isalnum(ch)) return FALSE; digit = ch - '0'; if (digit > 9) digit = tolower(ch) - 'a' + 10; if (digit >= base) return FALSE; accum = accum * base + digit; } if (hasDP) /* simple (required) DOUBLE support */ PUSHINT(0); if (isNeg) accum = -accum; PUSHINT(accum); if (pVM->state == COMPILE) literalIm(pVM); return TRUE; } /************************************************************************** a d d & f r i e n d s ** **************************************************************************/ static void add(FICL_VM *pVM) { FICL_INT i; #if FICL_ROBUST > 1 vmCheckStack(pVM, 2, 1); #endif i = stackPopINT(pVM->pStack); i += stackGetTop(pVM->pStack).i; stackSetTop(pVM->pStack, LVALUEtoCELL(i)); return; } static void sub(FICL_VM *pVM) { FICL_INT i; #if FICL_ROBUST > 1 vmCheckStack(pVM, 2, 1); #endif i = stackPopINT(pVM->pStack); i = stackGetTop(pVM->pStack).i - i; stackSetTop(pVM->pStack, LVALUEtoCELL(i)); return; } static void mul(FICL_VM *pVM) { FICL_INT i; #if FICL_ROBUST > 1 vmCheckStack(pVM, 2, 1); #endif i = stackPopINT(pVM->pStack); i *= stackGetTop(pVM->pStack).i; stackSetTop(pVM->pStack, LVALUEtoCELL(i)); return; } static void negate(FICL_VM *pVM) { FICL_INT i; #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 1); #endif i = -stackPopINT(pVM->pStack); PUSHINT(i); return; } static void ficlDiv(FICL_VM *pVM) { FICL_INT i; #if FICL_ROBUST > 1 vmCheckStack(pVM, 2, 1); #endif i = stackPopINT(pVM->pStack); i = stackGetTop(pVM->pStack).i / i; stackSetTop(pVM->pStack, LVALUEtoCELL(i)); return; } /* ** slash-mod CORE ( n1 n2 -- n3 n4 ) ** Divide n1 by n2, giving the single-cell remainder n3 and the single-cell ** quotient n4. An ambiguous condition exists if n2 is zero. If n1 and n2 ** differ in sign, the implementation-defined result returned will be the ** same as that returned by either the phrase ** >R S>D R> FM/MOD or the phrase >R S>D R> SM/REM . ** NOTE: Ficl complies with the second phrase (symmetric division) */ static void slashMod(FICL_VM *pVM) { DPINT n1; FICL_INT n2; INTQR qr; #if FICL_ROBUST > 1 vmCheckStack(pVM, 2, 2); #endif n2 = stackPopINT(pVM->pStack); n1.lo = stackPopINT(pVM->pStack); i64Extend(n1); qr = m64SymmetricDivI(n1, n2); PUSHINT(qr.rem); PUSHINT(qr.quot); return; } static void onePlus(FICL_VM *pVM) { FICL_INT i; #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 1); #endif i = stackGetTop(pVM->pStack).i; i += 1; stackSetTop(pVM->pStack, LVALUEtoCELL(i)); return; } static void oneMinus(FICL_VM *pVM) { FICL_INT i; #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 1); #endif i = stackGetTop(pVM->pStack).i; i -= 1; stackSetTop(pVM->pStack, LVALUEtoCELL(i)); return; } static void twoMul(FICL_VM *pVM) { FICL_INT i; #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 1); #endif i = stackGetTop(pVM->pStack).i; i *= 2; stackSetTop(pVM->pStack, LVALUEtoCELL(i)); return; } static void twoDiv(FICL_VM *pVM) { FICL_INT i; #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 1); #endif i = stackGetTop(pVM->pStack).i; i >>= 1; stackSetTop(pVM->pStack, LVALUEtoCELL(i)); return; } static void mulDiv(FICL_VM *pVM) { FICL_INT x, y, z; DPINT prod; #if FICL_ROBUST > 1 vmCheckStack(pVM, 3, 1); #endif z = stackPopINT(pVM->pStack); y = stackPopINT(pVM->pStack); x = stackPopINT(pVM->pStack); prod = m64MulI(x,y); x = m64SymmetricDivI(prod, z).quot; PUSHINT(x); return; } static void mulDivRem(FICL_VM *pVM) { FICL_INT x, y, z; DPINT prod; INTQR qr; #if FICL_ROBUST > 1 vmCheckStack(pVM, 3, 2); #endif z = stackPopINT(pVM->pStack); y = stackPopINT(pVM->pStack); x = stackPopINT(pVM->pStack); prod = m64MulI(x,y); qr = m64SymmetricDivI(prod, z); PUSHINT(qr.rem); PUSHINT(qr.quot); return; } /************************************************************************** c o l o n d e f i n i t i o n s ** Code to begin compiling a colon definition ** This function sets the state to COMPILE, then creates a ** new word whose name is the next word in the input stream ** and whose code is colonParen. **************************************************************************/ static void colon(FICL_VM *pVM) { FICL_DICT *dp = vmGetDict(pVM); STRINGINFO si = vmGetWord(pVM); dictCheckThreshold(dp); pVM->state = COMPILE; markControlTag(pVM, colonTag); dictAppendWord2(dp, si, colonParen, FW_DEFAULT | FW_SMUDGE); #if FICL_WANT_LOCALS pVM->pSys->nLocals = 0; #endif return; } /************************************************************************** c o l o n P a r e n ** This is the code that executes a colon definition. It assumes that the ** virtual machine is running a "next" loop (See the vm.c ** for its implementation of member function vmExecute()). The colon ** code simply copies the address of the first word in the list of words ** to interpret into IP after saving its old value. When we return to the ** "next" loop, the virtual machine will call the code for each word in ** turn. ** **************************************************************************/ static void colonParen(FICL_VM *pVM) { IPTYPE tempIP = (IPTYPE) (pVM->runningWord->param); vmPushIP(pVM, tempIP); return; } /************************************************************************** s e m i c o l o n C o I m ** ** IMMEDIATE code for ";". This function sets the state to INTERPRET and ** terminates a word under compilation by appending code for "(;)" to ** the definition. TO DO: checks for leftover branch target tags on the ** return stack and complains if any are found. **************************************************************************/ static void semiParen(FICL_VM *pVM) { vmPopIP(pVM); return; } static void semicolonCoIm(FICL_VM *pVM) { FICL_DICT *dp = vmGetDict(pVM); assert(pVM->pSys->pSemiParen); matchControlTag(pVM, colonTag); #if FICL_WANT_LOCALS assert(pVM->pSys->pUnLinkParen); if (pVM->pSys->nLocals > 0) { FICL_DICT *pLoc = ficlGetLoc(pVM->pSys); dictEmpty(pLoc, pLoc->pForthWords->size); dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pUnLinkParen)); } pVM->pSys->nLocals = 0; #endif dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pSemiParen)); pVM->state = INTERPRET; dictUnsmudge(dp); return; } /************************************************************************** e x i t ** CORE ** This function simply pops the previous instruction ** pointer and returns to the "next" loop. Used for exiting from within ** a definition. Note that exitParen is identical to semiParen - they ** are in two different functions so that "see" can correctly identify ** the end of a colon definition, even if it uses "exit". **************************************************************************/ static void exitParen(FICL_VM *pVM) { vmPopIP(pVM); return; } static void exitCoIm(FICL_VM *pVM) { FICL_DICT *dp = vmGetDict(pVM); assert(pVM->pSys->pExitParen); IGNORE(pVM); #if FICL_WANT_LOCALS if (pVM->pSys->nLocals > 0) { dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pUnLinkParen)); } #endif dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pExitParen)); return; } /************************************************************************** c o n s t a n t P a r e n ** This is the run-time code for "constant". It simply returns the ** contents of its word's first data cell. ** **************************************************************************/ void constantParen(FICL_VM *pVM) { FICL_WORD *pFW = pVM->runningWord; #if FICL_ROBUST > 1 vmCheckStack(pVM, 0, 1); #endif stackPush(pVM->pStack, pFW->param[0]); return; } void twoConstParen(FICL_VM *pVM) { FICL_WORD *pFW = pVM->runningWord; #if FICL_ROBUST > 1 vmCheckStack(pVM, 0, 2); #endif stackPush(pVM->pStack, pFW->param[0]); /* lo */ stackPush(pVM->pStack, pFW->param[1]); /* hi */ return; } /************************************************************************** c o n s t a n t ** IMMEDIATE ** Compiles a constant into the dictionary. Constants return their ** value when invoked. Expects a value on top of the parm stack. **************************************************************************/ static void constant(FICL_VM *pVM) { FICL_DICT *dp = vmGetDict(pVM); STRINGINFO si = vmGetWord(pVM); #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 0); #endif dictAppendWord2(dp, si, constantParen, FW_DEFAULT); dictAppendCell(dp, stackPop(pVM->pStack)); return; } static void twoConstant(FICL_VM *pVM) { FICL_DICT *dp = vmGetDict(pVM); STRINGINFO si = vmGetWord(pVM); CELL c; #if FICL_ROBUST > 1 vmCheckStack(pVM, 2, 0); #endif c = stackPop(pVM->pStack); dictAppendWord2(dp, si, twoConstParen, FW_DEFAULT); dictAppendCell(dp, stackPop(pVM->pStack)); dictAppendCell(dp, c); return; } /************************************************************************** d i s p l a y C e l l ** Drop and print the contents of the cell at the top of the param ** stack **************************************************************************/ static void displayCell(FICL_VM *pVM) { CELL c; #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 0); #endif c = stackPop(pVM->pStack); ltoa((c).i, pVM->pad, pVM->base); strcat(pVM->pad, " "); vmTextOut(pVM, pVM->pad, 0); return; } static void uDot(FICL_VM *pVM) { FICL_UNS u; #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 0); #endif u = stackPopUNS(pVM->pStack); ultoa(u, pVM->pad, pVM->base); strcat(pVM->pad, " "); vmTextOut(pVM, pVM->pad, 0); return; } static void hexDot(FICL_VM *pVM) { FICL_UNS u; #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 0); #endif u = stackPopUNS(pVM->pStack); ultoa(u, pVM->pad, 16); strcat(pVM->pad, " "); vmTextOut(pVM, pVM->pad, 0); return; } /************************************************************************** s t r l e n ** FICL ( c-string -- length ) ** ** Returns the length of a C-style (zero-terminated) string. ** ** --lch **/ static void ficlStrlen(FICL_VM *ficlVM) { char *address = (char *)stackPopPtr(ficlVM->pStack); stackPushINT(ficlVM->pStack, strlen(address)); } /************************************************************************** s p r i n t f ** FICL ( i*x c-addr-fmt u-fmt c-addr-buffer u-buffer -- c-addr-buffer u-written success-flag ) ** Similar to the C sprintf() function. It formats into a buffer based on ** a "format" string. Each character in the format string is copied verbatim ** to the output buffer, until SPRINTF encounters a percent sign ("%"). ** SPRINTF then skips the percent sign, and examines the next character ** (the "format character"). Here are the valid format characters: ** s - read a C-ADDR U-LENGTH string from the stack and copy it to ** the buffer ** d - read a cell from the stack, format it as a string (base-10, ** signed), and copy it to the buffer ** x - same as d, except in base-16 ** u - same as d, but unsigned ** % - output a literal percent-sign to the buffer ** SPRINTF returns the c-addr-buffer argument unchanged, the number of bytes ** written, and a flag indicating whether or not it ran out of space while ** writing to the output buffer (TRUE if it ran out of space). ** ** If SPRINTF runs out of space in the buffer to store the formatted string, ** it still continues parsing, in an effort to preserve your stack (otherwise ** it might leave uneaten arguments behind). ** ** --lch **************************************************************************/ static void ficlSprintf(FICL_VM *pVM) /* */ { int bufferLength = stackPopINT(pVM->pStack); char *buffer = (char *)stackPopPtr(pVM->pStack); char *bufferStart = buffer; int formatLength = stackPopINT(pVM->pStack); char *format = (char *)stackPopPtr(pVM->pStack); char *formatStop = format + formatLength; int base = 10; int unsignedInteger = FALSE; FICL_INT append = FICL_TRUE; while (format < formatStop) { char scratch[64]; char *source; int actualLength; int desiredLength; int leadingZeroes; if (*format != '%') { source = format; actualLength = desiredLength = 1; leadingZeroes = 0; } else { format++; if (format == formatStop) break; leadingZeroes = (*format == '0'); if (leadingZeroes) { format++; if (format == formatStop) break; } desiredLength = isdigit(*format); if (desiredLength) { desiredLength = strtol(format, &format, 10); if (format == formatStop) break; } else if (*format == '*') { desiredLength = stackPopINT(pVM->pStack); format++; if (format == formatStop) break; } switch (*format) { case 's': case 'S': { actualLength = stackPopINT(pVM->pStack); source = (char *)stackPopPtr(pVM->pStack); break; } case 'x': case 'X': base = 16; case 'u': case 'U': unsignedInteger = TRUE; case 'd': case 'D': { int integer = stackPopINT(pVM->pStack); if (unsignedInteger) ultoa(integer, scratch, base); else ltoa(integer, scratch, base); base = 10; unsignedInteger = FALSE; source = scratch; actualLength = strlen(scratch); break; } case '%': source = format; actualLength = 1; default: continue; } } if (append != FICL_FALSE) { if (!desiredLength) desiredLength = actualLength; if (desiredLength > bufferLength) { append = FICL_FALSE; desiredLength = bufferLength; } while (desiredLength > actualLength) { *buffer++ = (char)((leadingZeroes) ? '0' : ' '); bufferLength--; desiredLength--; } memcpy(buffer, source, actualLength); buffer += actualLength; bufferLength -= actualLength; } format++; } stackPushPtr(pVM->pStack, bufferStart); stackPushINT(pVM->pStack, buffer - bufferStart); stackPushINT(pVM->pStack, append); } /************************************************************************** d u p & f r i e n d s ** **************************************************************************/ static void depth(FICL_VM *pVM) { int i; #if FICL_ROBUST > 1 vmCheckStack(pVM, 0, 1); #endif i = stackDepth(pVM->pStack); PUSHINT(i); return; } static void drop(FICL_VM *pVM) { #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 0); #endif stackDrop(pVM->pStack, 1); return; } static void twoDrop(FICL_VM *pVM) { #if FICL_ROBUST > 1 vmCheckStack(pVM, 2, 0); #endif stackDrop(pVM->pStack, 2); return; } static void dup(FICL_VM *pVM) { #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 2); #endif stackPick(pVM->pStack, 0); return; } static void twoDup(FICL_VM *pVM) { #if FICL_ROBUST > 1 vmCheckStack(pVM, 2, 4); #endif stackPick(pVM->pStack, 1); stackPick(pVM->pStack, 1); return; } static void over(FICL_VM *pVM) { #if FICL_ROBUST > 1 vmCheckStack(pVM, 2, 3); #endif stackPick(pVM->pStack, 1); return; } static void twoOver(FICL_VM *pVM) { #if FICL_ROBUST > 1 vmCheckStack(pVM, 4, 6); #endif stackPick(pVM->pStack, 3); stackPick(pVM->pStack, 3); return; } static void pick(FICL_VM *pVM) { CELL c = stackPop(pVM->pStack); #if FICL_ROBUST > 1 vmCheckStack(pVM, c.i+1, c.i+2); #endif stackPick(pVM->pStack, c.i); return; } static void questionDup(FICL_VM *pVM) { CELL c; #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 2); #endif c = stackGetTop(pVM->pStack); if (c.i != 0) stackPick(pVM->pStack, 0); return; } static void roll(FICL_VM *pVM) { int i = stackPop(pVM->pStack).i; i = (i > 0) ? i : 0; #if FICL_ROBUST > 1 vmCheckStack(pVM, i+1, i+1); #endif stackRoll(pVM->pStack, i); return; } static void minusRoll(FICL_VM *pVM) { int i = stackPop(pVM->pStack).i; i = (i > 0) ? i : 0; #if FICL_ROBUST > 1 vmCheckStack(pVM, i+1, i+1); #endif stackRoll(pVM->pStack, -i); return; } static void rot(FICL_VM *pVM) { #if FICL_ROBUST > 1 vmCheckStack(pVM, 3, 3); #endif stackRoll(pVM->pStack, 2); return; } static void swap(FICL_VM *pVM) { #if FICL_ROBUST > 1 vmCheckStack(pVM, 2, 2); #endif stackRoll(pVM->pStack, 1); return; } static void twoSwap(FICL_VM *pVM) { #if FICL_ROBUST > 1 vmCheckStack(pVM, 4, 4); #endif stackRoll(pVM->pStack, 3); stackRoll(pVM->pStack, 3); return; } /************************************************************************** e m i t & f r i e n d s ** **************************************************************************/ static void emit(FICL_VM *pVM) { char *cp = pVM->pad; int i; #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 0); #endif i = stackPopINT(pVM->pStack); cp[0] = (char)i; cp[1] = '\0'; vmTextOut(pVM, cp, 0); return; } static void cr(FICL_VM *pVM) { vmTextOut(pVM, "", 1); return; } static void commentLine(FICL_VM *pVM) { char *cp = vmGetInBuf(pVM); char *pEnd = vmGetInBufEnd(pVM); char ch = *cp; while ((cp != pEnd) && (ch != '\r') && (ch != '\n')) { ch = *++cp; } /* ** Cope with DOS or UNIX-style EOLs - ** Check for /r, /n, /r/n, or /n/r end-of-line sequences, ** and point cp to next char. If EOL is \0, we're done. */ if (cp != pEnd) { cp++; if ( (cp != pEnd) && (ch != *cp) && ((*cp == '\r') || (*cp == '\n')) ) cp++; } vmUpdateTib(pVM, cp); return; } /* ** paren CORE ** Compilation: Perform the execution semantics given below. ** Execution: ( "ccc" -- ) ** Parse ccc delimited by ) (right parenthesis). ( is an immediate word. ** The number of characters in ccc may be zero to the number of characters ** in the parse area. ** */ static void commentHang(FICL_VM *pVM) { vmParseStringEx(pVM, ')', 0); return; } /************************************************************************** F E T C H & S T O R E ** **************************************************************************/ static void fetch(FICL_VM *pVM) { CELL *pCell; #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 1); #endif pCell = (CELL *)stackPopPtr(pVM->pStack); stackPush(pVM->pStack, *pCell); return; } /* ** two-fetch CORE ( a-addr -- x1 x2 ) ** Fetch the cell pair x1 x2 stored at a-addr. x2 is stored at a-addr and ** x1 at the next consecutive cell. It is equivalent to the sequence ** DUP CELL+ @ SWAP @ . */ static void twoFetch(FICL_VM *pVM) { CELL *pCell; #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 2); #endif pCell = (CELL *)stackPopPtr(pVM->pStack); stackPush(pVM->pStack, *pCell++); stackPush(pVM->pStack, *pCell); swap(pVM); return; } /* ** store CORE ( x a-addr -- ) ** Store x at a-addr. */ static void store(FICL_VM *pVM) { CELL *pCell; #if FICL_ROBUST > 1 vmCheckStack(pVM, 2, 0); #endif pCell = (CELL *)stackPopPtr(pVM->pStack); *pCell = stackPop(pVM->pStack); } /* ** two-store CORE ( x1 x2 a-addr -- ) ** Store the cell pair x1 x2 at a-addr, with x2 at a-addr and x1 at the ** next consecutive cell. It is equivalent to the sequence ** SWAP OVER ! CELL+ ! . */ static void twoStore(FICL_VM *pVM) { CELL *pCell; #if FICL_ROBUST > 1 vmCheckStack(pVM, 3, 0); #endif pCell = (CELL *)stackPopPtr(pVM->pStack); *pCell++ = stackPop(pVM->pStack); *pCell = stackPop(pVM->pStack); } static void plusStore(FICL_VM *pVM) { CELL *pCell; #if FICL_ROBUST > 1 vmCheckStack(pVM, 2, 0); #endif pCell = (CELL *)stackPopPtr(pVM->pStack); pCell->i += stackPop(pVM->pStack).i; } static void quadFetch(FICL_VM *pVM) { UNS32 *pw; #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 1); #endif pw = (UNS32 *)stackPopPtr(pVM->pStack); PUSHUNS((FICL_UNS)*pw); return; } static void quadStore(FICL_VM *pVM) { UNS32 *pw; #if FICL_ROBUST > 1 vmCheckStack(pVM, 2, 0); #endif pw = (UNS32 *)stackPopPtr(pVM->pStack); *pw = (UNS32)(stackPop(pVM->pStack).u); } static void wFetch(FICL_VM *pVM) { UNS16 *pw; #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 1); #endif pw = (UNS16 *)stackPopPtr(pVM->pStack); PUSHUNS((FICL_UNS)*pw); return; } static void wStore(FICL_VM *pVM) { UNS16 *pw; #if FICL_ROBUST > 1 vmCheckStack(pVM, 2, 0); #endif pw = (UNS16 *)stackPopPtr(pVM->pStack); *pw = (UNS16)(stackPop(pVM->pStack).u); } static void cFetch(FICL_VM *pVM) { UNS8 *pc; #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 1); #endif pc = (UNS8 *)stackPopPtr(pVM->pStack); PUSHUNS((FICL_UNS)*pc); return; } static void cStore(FICL_VM *pVM) { UNS8 *pc; #if FICL_ROBUST > 1 vmCheckStack(pVM, 2, 0); #endif pc = (UNS8 *)stackPopPtr(pVM->pStack); *pc = (UNS8)(stackPop(pVM->pStack).u); } /************************************************************************** b r a n c h P a r e n ** ** Runtime for "(branch)" -- expects a literal offset in the next ** compilation address, and branches to that location. **************************************************************************/ static void branchParen(FICL_VM *pVM) { vmBranchRelative(pVM, (uintptr_t)*(pVM->ip)); return; } /************************************************************************** b r a n c h 0 ** Runtime code for "(branch0)"; pop a flag from the stack, ** branch if 0. fall through otherwise. The heart of "if" and "until". **************************************************************************/ static void branch0(FICL_VM *pVM) { FICL_UNS flag; #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 0); #endif flag = stackPopUNS(pVM->pStack); if (flag) { /* fall through */ vmBranchRelative(pVM, 1); } else { /* take branch (to else/endif/begin) */ vmBranchRelative(pVM, (uintptr_t)*(pVM->ip)); } return; } /************************************************************************** i f C o I m ** IMMEDIATE COMPILE-ONLY ** Compiles code for a conditional branch into the dictionary ** and pushes the branch patch address on the stack for later ** patching by ELSE or THEN/ENDIF. **************************************************************************/ static void ifCoIm(FICL_VM *pVM) { FICL_DICT *dp = vmGetDict(pVM); assert(pVM->pSys->pBranch0); dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pBranch0)); markBranch(dp, pVM, origTag); dictAppendUNS(dp, 1); return; } /************************************************************************** e l s e C o I m ** ** IMMEDIATE COMPILE-ONLY ** compiles an "else"... ** 1) Compile a branch and a patch address; the address gets patched ** by "endif" to point past the "else" code. ** 2) Pop the "if" patch address ** 3) Patch the "if" branch to point to the current compile address. ** 4) Push the "else" patch address. ("endif" patches this to jump past ** the "else" code. **************************************************************************/ static void elseCoIm(FICL_VM *pVM) { CELL *patchAddr; FICL_INT offset; FICL_DICT *dp = vmGetDict(pVM); assert(pVM->pSys->pBranchParen); /* (1) compile branch runtime */ dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pBranchParen)); matchControlTag(pVM, origTag); patchAddr = (CELL *)stackPopPtr(pVM->pStack); /* (2) pop "if" patch addr */ markBranch(dp, pVM, origTag); /* (4) push "else" patch addr */ dictAppendUNS(dp, 1); /* (1) compile patch placeholder */ offset = dp->here - patchAddr; *patchAddr = LVALUEtoCELL(offset); /* (3) Patch "if" */ return; } /************************************************************************** e n d i f C o I m ** IMMEDIATE COMPILE-ONLY **************************************************************************/ static void endifCoIm(FICL_VM *pVM) { FICL_DICT *dp = vmGetDict(pVM); resolveForwardBranch(dp, pVM, origTag); return; } /************************************************************************** c a s e C o I m ** IMMEDIATE COMPILE-ONLY ** ** ** At compile-time, a CASE-SYS (see DPANS94 6.2.0873) looks like this: ** i*addr i caseTag ** and an OF-SYS (see DPANS94 6.2.1950) looks like this: ** i*addr i caseTag addr ofTag ** The integer under caseTag is the count of fixup addresses that branch ** to ENDCASE. **************************************************************************/ static void caseCoIm(FICL_VM *pVM) { #if FICL_ROBUST > 1 vmCheckStack(pVM, 0, 2); #endif PUSHUNS(0); markControlTag(pVM, caseTag); return; } /************************************************************************** e n d c a s eC o I m ** IMMEDIATE COMPILE-ONLY **************************************************************************/ static void endcaseCoIm(FICL_VM *pVM) { FICL_UNS fixupCount; FICL_DICT *dp; CELL *patchAddr; FICL_INT offset; assert(pVM->pSys->pDrop); /* ** if the last OF ended with FALLTHROUGH, ** just add the FALLTHROUGH fixup to the ** ENDOF fixups */ if (stackGetTop(pVM->pStack).p == fallthroughTag) { matchControlTag(pVM, fallthroughTag); patchAddr = POPPTR(); matchControlTag(pVM, caseTag); fixupCount = POPUNS(); PUSHPTR(patchAddr); PUSHUNS(fixupCount + 1); markControlTag(pVM, caseTag); } matchControlTag(pVM, caseTag); #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 0); #endif fixupCount = POPUNS(); #if FICL_ROBUST > 1 vmCheckStack(pVM, fixupCount, 0); #endif dp = vmGetDict(pVM); dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pDrop)); while (fixupCount--) { patchAddr = (CELL *)stackPopPtr(pVM->pStack); offset = dp->here - patchAddr; *patchAddr = LVALUEtoCELL(offset); } return; } static void ofParen(FICL_VM *pVM) { FICL_UNS a, b; #if FICL_ROBUST > 1 vmCheckStack(pVM, 2, 1); #endif a = POPUNS(); b = stackGetTop(pVM->pStack).u; if (a == b) { /* fall through */ stackDrop(pVM->pStack, 1); vmBranchRelative(pVM, 1); } else { /* take branch to next of or endswitch */ vmBranchRelative(pVM, *(int *)(pVM->ip)); } return; } /************************************************************************** o f C o I m ** IMMEDIATE COMPILE-ONLY **************************************************************************/ static void ofCoIm(FICL_VM *pVM) { FICL_DICT *dp = vmGetDict(pVM); CELL *fallthroughFixup = NULL; assert(pVM->pSys->pBranch0); #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 3); #endif if (stackGetTop(pVM->pStack).p == fallthroughTag) { matchControlTag(pVM, fallthroughTag); fallthroughFixup = POPPTR(); } matchControlTag(pVM, caseTag); markControlTag(pVM, caseTag); dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pOfParen)); markBranch(dp, pVM, ofTag); dictAppendUNS(dp, 2); if (fallthroughFixup != NULL) { FICL_INT offset = dp->here - fallthroughFixup; *fallthroughFixup = LVALUEtoCELL(offset); } return; } /************************************************************************** e n d o f C o I m ** IMMEDIATE COMPILE-ONLY **************************************************************************/ static void endofCoIm(FICL_VM *pVM) { CELL *patchAddr; FICL_UNS fixupCount; FICL_INT offset; FICL_DICT *dp = vmGetDict(pVM); #if FICL_ROBUST > 1 vmCheckStack(pVM, 4, 3); #endif assert(pVM->pSys->pBranchParen); /* ensure we're in an OF, */ matchControlTag(pVM, ofTag); /* grab the address of the branch location after the OF */ patchAddr = (CELL *)stackPopPtr(pVM->pStack); /* ensure we're also in a "case" */ matchControlTag(pVM, caseTag); /* grab the current number of ENDOF fixups */ fixupCount = POPUNS(); /* compile branch runtime */ dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pBranchParen)); /* push a new ENDOF fixup, the updated count of ENDOF fixups, and the caseTag */ PUSHPTR(dp->here); PUSHUNS(fixupCount + 1); markControlTag(pVM, caseTag); /* reserve space for the ENDOF fixup */ dictAppendUNS(dp, 2); /* and patch the original OF */ offset = dp->here - patchAddr; *patchAddr = LVALUEtoCELL(offset); } /************************************************************************** f a l l t h r o u g h C o I m ** IMMEDIATE COMPILE-ONLY **************************************************************************/ static void fallthroughCoIm(FICL_VM *pVM) { CELL *patchAddr; FICL_INT offset; FICL_DICT *dp = vmGetDict(pVM); #if FICL_ROBUST > 1 vmCheckStack(pVM, 4, 3); #endif /* ensure we're in an OF, */ matchControlTag(pVM, ofTag); /* grab the address of the branch location after the OF */ patchAddr = (CELL *)stackPopPtr(pVM->pStack); /* ensure we're also in a "case" */ matchControlTag(pVM, caseTag); /* okay, here we go. put the case tag back. */ markControlTag(pVM, caseTag); /* compile branch runtime */ dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pBranchParen)); /* push a new FALLTHROUGH fixup and the fallthroughTag */ PUSHPTR(dp->here); markControlTag(pVM, fallthroughTag); /* reserve space for the FALLTHROUGH fixup */ dictAppendUNS(dp, 2); /* and patch the original OF */ offset = dp->here - patchAddr; *patchAddr = LVALUEtoCELL(offset); } /************************************************************************** h a s h ** hash ( c-addr u -- code) ** calculates hashcode of specified string and leaves it on the stack **************************************************************************/ static void hash(FICL_VM *pVM) { STRINGINFO si; SI_SETLEN(si, stackPopUNS(pVM->pStack)); SI_SETPTR(si, stackPopPtr(pVM->pStack)); PUSHUNS(hashHashCode(si)); return; } /************************************************************************** i n t e r p r e t ** This is the "user interface" of a Forth. It does the following: ** while there are words in the VM's Text Input Buffer ** Copy next word into the pad (vmGetWord) ** Attempt to find the word in the dictionary (dictLookup) ** If successful, execute the word. ** Otherwise, attempt to convert the word to a number (isNumber) ** If successful, push the number onto the parameter stack. ** Otherwise, print an error message and exit loop... ** End Loop ** ** From the standard, section 3.4 ** Text interpretation (see 6.1.1360 EVALUATE and 6.1.2050 QUIT) shall ** repeat the following steps until either the parse area is empty or an ** ambiguous condition exists: ** a) Skip leading spaces and parse a name (see 3.4.1); **************************************************************************/ static void interpret(FICL_VM *pVM) { STRINGINFO si; int i; FICL_SYSTEM *pSys; assert(pVM); pSys = pVM->pSys; si = vmGetWord0(pVM); /* ** Get next word...if out of text, we're done. */ if (si.count == 0) { vmThrow(pVM, VM_OUTOFTEXT); } /* ** Attempt to find the incoming token in the dictionary. If that fails... ** run the parse chain against the incoming token until somebody eats it. ** Otherwise emit an error message and give up. ** Although ficlParseWord could be part of the parse list, I've hard coded it ** in for robustness. ficlInitSystem adds the other default steps to the list. */ if (ficlParseWord(pVM, si)) return; for (i=0; i < FICL_MAX_PARSE_STEPS; i++) { FICL_WORD *pFW = pSys->parseList[i]; if (pFW == NULL) break; if (pFW->code == parseStepParen) { FICL_PARSE_STEP pStep; pStep = (FICL_PARSE_STEP)(pFW->param->fn); if ((*pStep)(pVM, si)) return; } else { stackPushPtr(pVM->pStack, SI_PTR(si)); stackPushUNS(pVM->pStack, SI_COUNT(si)); ficlExecXT(pVM, pFW); if (stackPopINT(pVM->pStack)) return; } } i = SI_COUNT(si); vmThrowErr(pVM, "%.*s not found", i, SI_PTR(si)); return; /* back to inner interpreter */ } /************************************************************************** f i c l P a r s e W o r d ** From the standard, section 3.4 ** b) Search the dictionary name space (see 3.4.2). If a definition name ** matching the string is found: ** 1.if interpreting, perform the interpretation semantics of the definition ** (see 3.4.3.2), and continue at a); ** 2.if compiling, perform the compilation semantics of the definition ** (see 3.4.3.3), and continue at a). ** ** c) If a definition name matching the string is not found, attempt to ** convert the string to a number (see 3.4.1.3). If successful: ** 1.if interpreting, place the number on the data stack, and continue at a); ** 2.if compiling, compile code that when executed will place the number on ** the stack (see 6.1.1780 LITERAL), and continue at a); ** ** d) If unsuccessful, an ambiguous condition exists (see 3.4.4). ** ** (jws 4/01) Modified to be a FICL_PARSE_STEP **************************************************************************/ static int ficlParseWord(FICL_VM *pVM, STRINGINFO si) { FICL_DICT *dp = vmGetDict(pVM); FICL_WORD *tempFW; #if FICL_ROBUST dictCheck(dp, pVM, 0); vmCheckStack(pVM, 0, 0); #endif #if FICL_WANT_LOCALS if (pVM->pSys->nLocals > 0) { tempFW = ficlLookupLoc(pVM->pSys, si); } else #endif tempFW = dictLookup(dp, si); if (pVM->state == INTERPRET) { if (tempFW != NULL) { if (wordIsCompileOnly(tempFW)) { vmThrowErr(pVM, "Error: Compile only!"); } vmExecute(pVM, tempFW); return (int)FICL_TRUE; } } else /* (pVM->state == COMPILE) */ { if (tempFW != NULL) { if (wordIsImmediate(tempFW)) { vmExecute(pVM, tempFW); } else { dictAppendCell(dp, LVALUEtoCELL(tempFW)); } return (int)FICL_TRUE; } } return FICL_FALSE; } /* ** Surrogate precompiled parse step for ficlParseWord (this step is hard coded in ** INTERPRET) */ static void lookup(FICL_VM *pVM) { STRINGINFO si; SI_SETLEN(si, stackPopUNS(pVM->pStack)); SI_SETPTR(si, stackPopPtr(pVM->pStack)); stackPushINT(pVM->pStack, ficlParseWord(pVM, si)); return; } /************************************************************************** p a r e n P a r s e S t e p ** (parse-step) ( c-addr u -- flag ) ** runtime for a precompiled parse step - pop a counted string off the ** stack, run the parse step against it, and push the result flag (FICL_TRUE ** if success, FICL_FALSE otherwise). **************************************************************************/ void parseStepParen(FICL_VM *pVM) { STRINGINFO si; FICL_WORD *pFW = pVM->runningWord; FICL_PARSE_STEP pStep = (FICL_PARSE_STEP)(pFW->param->fn); SI_SETLEN(si, stackPopINT(pVM->pStack)); SI_SETPTR(si, stackPopPtr(pVM->pStack)); PUSHINT((*pStep)(pVM, si)); return; } static void addParseStep(FICL_VM *pVM) { FICL_WORD *pStep; FICL_DICT *pd = vmGetDict(pVM); #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 0); #endif pStep = (FICL_WORD *)(stackPop(pVM->pStack).p); if ((pStep != NULL) && isAFiclWord(pd, pStep)) ficlAddParseStep(pVM->pSys, pStep); return; } /************************************************************************** l i t e r a l P a r e n ** ** This is the runtime for (literal). It assumes that it is part of a colon ** definition, and that the next CELL contains a value to be pushed on the ** parameter stack at runtime. This code is compiled by "literal". ** **************************************************************************/ static void literalParen(FICL_VM *pVM) { #if FICL_ROBUST > 1 vmCheckStack(pVM, 0, 1); #endif PUSHINT(*(FICL_INT *)(pVM->ip)); vmBranchRelative(pVM, 1); return; } static void twoLitParen(FICL_VM *pVM) { #if FICL_ROBUST > 1 vmCheckStack(pVM, 0, 2); #endif PUSHINT(*((FICL_INT *)(pVM->ip)+1)); PUSHINT(*(FICL_INT *)(pVM->ip)); vmBranchRelative(pVM, 2); return; } /************************************************************************** l i t e r a l I m ** ** IMMEDIATE code for "literal". This function gets a value from the stack ** and compiles it into the dictionary preceded by the code for "(literal)". ** IMMEDIATE **************************************************************************/ static void literalIm(FICL_VM *pVM) { FICL_DICT *dp = vmGetDict(pVM); assert(pVM->pSys->pLitParen); dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pLitParen)); dictAppendCell(dp, stackPop(pVM->pStack)); return; } static void twoLiteralIm(FICL_VM *pVM) { FICL_DICT *dp = vmGetDict(pVM); assert(pVM->pSys->pTwoLitParen); dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pTwoLitParen)); dictAppendCell(dp, stackPop(pVM->pStack)); dictAppendCell(dp, stackPop(pVM->pStack)); return; } /************************************************************************** l o g i c a n d c o m p a r i s o n s ** **************************************************************************/ static void zeroEquals(FICL_VM *pVM) { CELL c; #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 1); #endif c.i = FICL_BOOL(stackPopINT(pVM->pStack) == 0); stackPush(pVM->pStack, c); return; } static void zeroLess(FICL_VM *pVM) { CELL c; #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 1); #endif c.i = FICL_BOOL(stackPopINT(pVM->pStack) < 0); stackPush(pVM->pStack, c); return; } static void zeroGreater(FICL_VM *pVM) { CELL c; #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 1); #endif c.i = FICL_BOOL(stackPopINT(pVM->pStack) > 0); stackPush(pVM->pStack, c); return; } static void isEqual(FICL_VM *pVM) { CELL x, y; #if FICL_ROBUST > 1 vmCheckStack(pVM, 2, 1); #endif x = stackPop(pVM->pStack); y = stackPop(pVM->pStack); PUSHINT(FICL_BOOL(x.i == y.i)); return; } static void isLess(FICL_VM *pVM) { CELL x, y; #if FICL_ROBUST > 1 vmCheckStack(pVM, 2, 1); #endif y = stackPop(pVM->pStack); x = stackPop(pVM->pStack); PUSHINT(FICL_BOOL(x.i < y.i)); return; } static void uIsLess(FICL_VM *pVM) { FICL_UNS u1, u2; #if FICL_ROBUST > 1 vmCheckStack(pVM, 2, 1); #endif u2 = stackPopUNS(pVM->pStack); u1 = stackPopUNS(pVM->pStack); PUSHINT(FICL_BOOL(u1 < u2)); return; } static void isGreater(FICL_VM *pVM) { CELL x, y; #if FICL_ROBUST > 1 vmCheckStack(pVM, 2, 1); #endif y = stackPop(pVM->pStack); x = stackPop(pVM->pStack); PUSHINT(FICL_BOOL(x.i > y.i)); return; } static void bitwiseAnd(FICL_VM *pVM) { CELL x, y; #if FICL_ROBUST > 1 vmCheckStack(pVM, 2, 1); #endif x = stackPop(pVM->pStack); y = stackPop(pVM->pStack); PUSHINT(x.i & y.i); return; } static void bitwiseOr(FICL_VM *pVM) { CELL x, y; #if FICL_ROBUST > 1 vmCheckStack(pVM, 2, 1); #endif x = stackPop(pVM->pStack); y = stackPop(pVM->pStack); PUSHINT(x.i | y.i); return; } static void bitwiseXor(FICL_VM *pVM) { CELL x, y; #if FICL_ROBUST > 1 vmCheckStack(pVM, 2, 1); #endif x = stackPop(pVM->pStack); y = stackPop(pVM->pStack); PUSHINT(x.i ^ y.i); return; } static void bitwiseNot(FICL_VM *pVM) { CELL x; #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 1); #endif x = stackPop(pVM->pStack); PUSHINT(~x.i); return; } /************************************************************************** D o / L o o p ** do -- IMMEDIATE COMPILE ONLY ** Compiles code to initialize a loop: compile (do), ** allot space to hold the "leave" address, push a branch ** target address for the loop. ** (do) -- runtime for "do" ** pops index and limit from the p stack and moves them ** to the r stack, then skips to the loop body. ** loop -- IMMEDIATE COMPILE ONLY ** +loop ** Compiles code for the test part of a loop: ** compile (loop), resolve forward branch from "do", and ** copy "here" address to the "leave" address allotted by "do" ** i,j,k -- COMPILE ONLY ** Runtime: Push loop indices on param stack (i is innermost loop...) ** Note: each loop has three values on the return stack: ** ( R: leave limit index ) ** "leave" is the absolute address of the next cell after the loop ** limit and index are the loop control variables. ** leave -- COMPILE ONLY ** Runtime: pop the loop control variables, then pop the ** "leave" address and jump (absolute) there. **************************************************************************/ static void doCoIm(FICL_VM *pVM) { FICL_DICT *dp = vmGetDict(pVM); assert(pVM->pSys->pDoParen); dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pDoParen)); /* ** Allot space for a pointer to the end ** of the loop - "leave" uses this... */ markBranch(dp, pVM, leaveTag); dictAppendUNS(dp, 0); /* ** Mark location of head of loop... */ markBranch(dp, pVM, doTag); return; } static void doParen(FICL_VM *pVM) { CELL index, limit; #if FICL_ROBUST > 1 vmCheckStack(pVM, 2, 0); #endif index = stackPop(pVM->pStack); limit = stackPop(pVM->pStack); /* copy "leave" target addr to stack */ stackPushPtr(pVM->rStack, *(pVM->ip++)); stackPush(pVM->rStack, limit); stackPush(pVM->rStack, index); return; } static void qDoCoIm(FICL_VM *pVM) { FICL_DICT *dp = vmGetDict(pVM); assert(pVM->pSys->pQDoParen); dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pQDoParen)); /* ** Allot space for a pointer to the end ** of the loop - "leave" uses this... */ markBranch(dp, pVM, leaveTag); dictAppendUNS(dp, 0); /* ** Mark location of head of loop... */ markBranch(dp, pVM, doTag); return; } static void qDoParen(FICL_VM *pVM) { CELL index, limit; #if FICL_ROBUST > 1 vmCheckStack(pVM, 2, 0); #endif index = stackPop(pVM->pStack); limit = stackPop(pVM->pStack); /* copy "leave" target addr to stack */ stackPushPtr(pVM->rStack, *(pVM->ip++)); if (limit.u == index.u) { vmPopIP(pVM); } else { stackPush(pVM->rStack, limit); stackPush(pVM->rStack, index); } return; } /* ** Runtime code to break out of a do..loop construct ** Drop the loop control variables; the branch address ** past "loop" is next on the return stack. */ static void leaveCo(FICL_VM *pVM) { /* almost unloop */ stackDrop(pVM->rStack, 2); /* exit */ vmPopIP(pVM); return; } static void unloopCo(FICL_VM *pVM) { stackDrop(pVM->rStack, 3); return; } static void loopCoIm(FICL_VM *pVM) { FICL_DICT *dp = vmGetDict(pVM); assert(pVM->pSys->pLoopParen); dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pLoopParen)); resolveBackBranch(dp, pVM, doTag); resolveAbsBranch(dp, pVM, leaveTag); return; } static void plusLoopCoIm(FICL_VM *pVM) { FICL_DICT *dp = vmGetDict(pVM); assert(pVM->pSys->pPLoopParen); dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pPLoopParen)); resolveBackBranch(dp, pVM, doTag); resolveAbsBranch(dp, pVM, leaveTag); return; } static void loopParen(FICL_VM *pVM) { FICL_INT index = stackGetTop(pVM->rStack).i; FICL_INT limit = stackFetch(pVM->rStack, 1).i; index++; if (index >= limit) { stackDrop(pVM->rStack, 3); /* nuke the loop indices & "leave" addr */ vmBranchRelative(pVM, 1); /* fall through the loop */ } else { /* update index, branch to loop head */ stackSetTop(pVM->rStack, LVALUEtoCELL(index)); vmBranchRelative(pVM, (uintptr_t)*(pVM->ip)); } return; } static void plusLoopParen(FICL_VM *pVM) { FICL_INT index,limit,increment; int flag; #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 0); #endif index = stackGetTop(pVM->rStack).i; limit = stackFetch(pVM->rStack, 1).i; increment = POP().i; index += increment; if (increment < 0) flag = (index < limit); else flag = (index >= limit); if (flag) { stackDrop(pVM->rStack, 3); /* nuke the loop indices & "leave" addr */ vmBranchRelative(pVM, 1); /* fall through the loop */ } else { /* update index, branch to loop head */ stackSetTop(pVM->rStack, LVALUEtoCELL(index)); vmBranchRelative(pVM, (uintptr_t)*(pVM->ip)); } return; } static void loopICo(FICL_VM *pVM) { CELL index = stackGetTop(pVM->rStack); stackPush(pVM->pStack, index); return; } static void loopJCo(FICL_VM *pVM) { CELL index = stackFetch(pVM->rStack, 3); stackPush(pVM->pStack, index); return; } static void loopKCo(FICL_VM *pVM) { CELL index = stackFetch(pVM->rStack, 6); stackPush(pVM->pStack, index); return; } /************************************************************************** r e t u r n s t a c k ** **************************************************************************/ static void toRStack(FICL_VM *pVM) { #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 0); #endif stackPush(pVM->rStack, POP()); } static void fromRStack(FICL_VM *pVM) { #if FICL_ROBUST > 1 vmCheckStack(pVM, 0, 1); #endif PUSH(stackPop(pVM->rStack)); } static void fetchRStack(FICL_VM *pVM) { #if FICL_ROBUST > 1 vmCheckStack(pVM, 0, 1); #endif PUSH(stackGetTop(pVM->rStack)); } static void twoToR(FICL_VM *pVM) { #if FICL_ROBUST > 1 vmCheckStack(pVM, 2, 0); #endif stackRoll(pVM->pStack, 1); stackPush(pVM->rStack, stackPop(pVM->pStack)); stackPush(pVM->rStack, stackPop(pVM->pStack)); return; } static void twoRFrom(FICL_VM *pVM) { #if FICL_ROBUST > 1 vmCheckStack(pVM, 0, 2); #endif stackPush(pVM->pStack, stackPop(pVM->rStack)); stackPush(pVM->pStack, stackPop(pVM->rStack)); stackRoll(pVM->pStack, 1); return; } static void twoRFetch(FICL_VM *pVM) { #if FICL_ROBUST > 1 vmCheckStack(pVM, 0, 2); #endif stackPush(pVM->pStack, stackFetch(pVM->rStack, 1)); stackPush(pVM->pStack, stackFetch(pVM->rStack, 0)); return; } /************************************************************************** v a r i a b l e ** **************************************************************************/ static void variableParen(FICL_VM *pVM) { FICL_WORD *fw; #if FICL_ROBUST > 1 vmCheckStack(pVM, 0, 1); #endif fw = pVM->runningWord; PUSHPTR(fw->param); } static void variable(FICL_VM *pVM) { FICL_DICT *dp = vmGetDict(pVM); STRINGINFO si = vmGetWord(pVM); dictAppendWord2(dp, si, variableParen, FW_DEFAULT); dictAllotCells(dp, 1); return; } static void twoVariable(FICL_VM *pVM) { FICL_DICT *dp = vmGetDict(pVM); STRINGINFO si = vmGetWord(pVM); dictAppendWord2(dp, si, variableParen, FW_DEFAULT); dictAllotCells(dp, 2); return; } /************************************************************************** b a s e & f r i e n d s ** **************************************************************************/ static void base(FICL_VM *pVM) { CELL *pBase; #if FICL_ROBUST > 1 vmCheckStack(pVM, 0, 1); #endif pBase = (CELL *)(&pVM->base); stackPush(pVM->pStack, LVALUEtoCELL(pBase)); return; } static void decimal(FICL_VM *pVM) { pVM->base = 10; return; } static void hex(FICL_VM *pVM) { pVM->base = 16; return; } /************************************************************************** a l l o t & f r i e n d s ** **************************************************************************/ static void allot(FICL_VM *pVM) { FICL_DICT *dp; FICL_INT i; #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 0); #endif dp = vmGetDict(pVM); i = POPINT(); #if FICL_ROBUST dictCheck(dp, pVM, i); #endif dictAllot(dp, i); return; } static void here(FICL_VM *pVM) { FICL_DICT *dp; #if FICL_ROBUST > 1 vmCheckStack(pVM, 0, 1); #endif dp = vmGetDict(pVM); PUSHPTR(dp->here); return; } static void comma(FICL_VM *pVM) { FICL_DICT *dp; CELL c; #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 0); #endif dp = vmGetDict(pVM); c = POP(); dictAppendCell(dp, c); return; } static void cComma(FICL_VM *pVM) { FICL_DICT *dp; char c; #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 0); #endif dp = vmGetDict(pVM); c = (char)POPINT(); dictAppendChar(dp, c); return; } static void cells(FICL_VM *pVM) { FICL_INT i; #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 1); #endif i = POPINT(); PUSHINT(i * (FICL_INT)sizeof (CELL)); return; } static void cellPlus(FICL_VM *pVM) { char *cp; #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 1); #endif cp = POPPTR(); PUSHPTR(cp + sizeof (CELL)); return; } /************************************************************************** t i c k ** tick CORE ( "name" -- xt ) ** Skip leading space delimiters. Parse name delimited by a space. Find ** name and return xt, the execution token for name. An ambiguous condition ** exists if name is not found. **************************************************************************/ void ficlTick(FICL_VM *pVM) { FICL_WORD *pFW = NULL; STRINGINFO si = vmGetWord(pVM); #if FICL_ROBUST > 1 vmCheckStack(pVM, 0, 1); #endif pFW = dictLookup(vmGetDict(pVM), si); if (!pFW) { int i = SI_COUNT(si); vmThrowErr(pVM, "%.*s not found", i, SI_PTR(si)); } PUSHPTR(pFW); return; } static void bracketTickCoIm(FICL_VM *pVM) { ficlTick(pVM); literalIm(pVM); return; } /************************************************************************** p o s t p o n e ** Lookup the next word in the input stream and compile code to ** insert it into definitions created by the resulting word ** (defers compilation, even of immediate words) **************************************************************************/ static void postponeCoIm(FICL_VM *pVM) { FICL_DICT *dp = vmGetDict(pVM); FICL_WORD *pFW; FICL_WORD *pComma = ficlLookup(pVM->pSys, ","); assert(pComma); ficlTick(pVM); pFW = stackGetTop(pVM->pStack).p; if (wordIsImmediate(pFW)) { dictAppendCell(dp, stackPop(pVM->pStack)); } else { literalIm(pVM); dictAppendCell(dp, LVALUEtoCELL(pComma)); } return; } /************************************************************************** e x e c u t e ** Pop an execution token (pointer to a word) off the stack and ** run it **************************************************************************/ static void execute(FICL_VM *pVM) { FICL_WORD *pFW; #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 0); #endif pFW = stackPopPtr(pVM->pStack); vmExecute(pVM, pFW); return; } /************************************************************************** i m m e d i a t e ** Make the most recently compiled word IMMEDIATE -- it executes even ** in compile state (most often used for control compiling words ** such as IF, THEN, etc) **************************************************************************/ static void immediate(FICL_VM *pVM) { IGNORE(pVM); dictSetImmediate(vmGetDict(pVM)); return; } static void compileOnly(FICL_VM *pVM) { IGNORE(pVM); dictSetFlags(vmGetDict(pVM), FW_COMPILE, 0); return; } static void setObjectFlag(FICL_VM *pVM) { IGNORE(pVM); dictSetFlags(vmGetDict(pVM), FW_ISOBJECT, 0); return; } static void isObject(FICL_VM *pVM) { - int flag; + FICL_INT flag; FICL_WORD *pFW = (FICL_WORD *)stackPopPtr(pVM->pStack); flag = ((pFW != NULL) && (pFW->flags & FW_ISOBJECT)) ? FICL_TRUE : FICL_FALSE; stackPushINT(pVM->pStack, flag); return; } static void cstringLit(FICL_VM *pVM) { FICL_STRING *sp = (FICL_STRING *)(pVM->ip); char *cp = sp->text; cp += sp->count + 1; cp = alignPtr(cp); pVM->ip = (IPTYPE)(void *)cp; stackPushPtr(pVM->pStack, sp); return; } static void cstringQuoteIm(FICL_VM *pVM) { FICL_DICT *dp = vmGetDict(pVM); if (pVM->state == INTERPRET) { FICL_STRING *sp = (FICL_STRING *) dp->here; vmGetString(pVM, sp, '\"'); stackPushPtr(pVM->pStack, sp); /* move HERE past string so it doesn't get overwritten. --lch */ dictAllot(dp, sp->count + sizeof(FICL_COUNT)); } else /* COMPILE state */ { dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pCStringLit)); dp->here = PTRtoCELL vmGetString(pVM, (FICL_STRING *)dp->here, '\"'); dictAlign(dp); } return; } /************************************************************************** d o t Q u o t e ** IMMEDIATE word that compiles a string literal for later display ** Compile stringLit, then copy the bytes of the string from the TIB ** to the dictionary. Backpatch the count byte and align the dictionary. ** ** stringlit: Fetch the count from the dictionary, then push the address ** and count on the stack. Finally, update ip to point to the first ** aligned address after the string text. **************************************************************************/ static void stringLit(FICL_VM *pVM) { FICL_STRING *sp; FICL_COUNT count; char *cp; #if FICL_ROBUST > 1 vmCheckStack(pVM, 0, 2); #endif sp = (FICL_STRING *)(pVM->ip); count = sp->count; cp = sp->text; PUSHPTR(cp); PUSHUNS(count); cp += count + 1; cp = alignPtr(cp); pVM->ip = (IPTYPE)(void *)cp; } static void dotQuoteCoIm(FICL_VM *pVM) { FICL_DICT *dp = vmGetDict(pVM); FICL_WORD *pType = ficlLookup(pVM->pSys, "type"); assert(pType); dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pStringLit)); dp->here = PTRtoCELL vmGetString(pVM, (FICL_STRING *)dp->here, '\"'); dictAlign(dp); dictAppendCell(dp, LVALUEtoCELL(pType)); return; } static void dotParen(FICL_VM *pVM) { char *pSrc = vmGetInBuf(pVM); char *pEnd = vmGetInBufEnd(pVM); char *pDest = pVM->pad; char ch; /* ** Note: the standard does not want leading spaces skipped (apparently) */ for (ch = *pSrc; (pEnd != pSrc) && (ch != ')'); ch = *++pSrc) *pDest++ = ch; *pDest = '\0'; if ((pEnd != pSrc) && (ch == ')')) pSrc++; vmTextOut(pVM, pVM->pad, 0); vmUpdateTib(pVM, pSrc); return; } /************************************************************************** s l i t e r a l ** STRING ** Interpretation: Interpretation semantics for this word are undefined. ** Compilation: ( c-addr1 u -- ) ** Append the run-time semantics given below to the current definition. ** Run-time: ( -- c-addr2 u ) ** Return c-addr2 u describing a string consisting of the characters ** specified by c-addr1 u during compilation. A program shall not alter ** the returned string. **************************************************************************/ static void sLiteralCoIm(FICL_VM *pVM) { FICL_DICT *dp; char *cp, *cpDest; FICL_UNS u; #if FICL_ROBUST > 1 vmCheckStack(pVM, 2, 0); #endif dp = vmGetDict(pVM); u = POPUNS(); cp = POPPTR(); dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pStringLit)); cpDest = (char *) dp->here; *cpDest++ = (char) u; for (; u > 0; --u) { *cpDest++ = *cp++; } *cpDest++ = 0; dp->here = PTRtoCELL alignPtr(cpDest); return; } /************************************************************************** s t a t e ** Return the address of the VM's state member (must be sized the ** same as a CELL for this reason) **************************************************************************/ static void state(FICL_VM *pVM) { #if FICL_ROBUST > 1 vmCheckStack(pVM, 0, 1); #endif PUSHPTR(&pVM->state); return; } /************************************************************************** c r e a t e . . . d o e s > ** Make a new word in the dictionary with the run-time effect of ** a variable (push my address), but with extra space allotted ** for use by does> . **************************************************************************/ static void createParen(FICL_VM *pVM) { CELL *pCell; #if FICL_ROBUST > 1 vmCheckStack(pVM, 0, 1); #endif pCell = pVM->runningWord->param; PUSHPTR(pCell+1); return; } static void create(FICL_VM *pVM) { FICL_DICT *dp = vmGetDict(pVM); STRINGINFO si = vmGetWord(pVM); dictCheckThreshold(dp); dictAppendWord2(dp, si, createParen, FW_DEFAULT); dictAllotCells(dp, 1); return; } static void doDoes(FICL_VM *pVM) { CELL *pCell; IPTYPE tempIP; #if FICL_ROBUST > 1 vmCheckStack(pVM, 0, 1); #endif pCell = pVM->runningWord->param; tempIP = (IPTYPE)((*pCell).p); PUSHPTR(pCell+1); vmPushIP(pVM, tempIP); return; } static void doesParen(FICL_VM *pVM) { FICL_DICT *dp = vmGetDict(pVM); dp->smudge->code = doDoes; dp->smudge->param[0] = LVALUEtoCELL(pVM->ip); vmPopIP(pVM); return; } static void doesCoIm(FICL_VM *pVM) { FICL_DICT *dp = vmGetDict(pVM); #if FICL_WANT_LOCALS assert(pVM->pSys->pUnLinkParen); if (pVM->pSys->nLocals > 0) { FICL_DICT *pLoc = ficlGetLoc(pVM->pSys); dictEmpty(pLoc, pLoc->pForthWords->size); dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pUnLinkParen)); } pVM->pSys->nLocals = 0; #endif IGNORE(pVM); dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pDoesParen)); return; } /************************************************************************** t o b o d y ** to-body CORE ( xt -- a-addr ) ** a-addr is the data-field address corresponding to xt. An ambiguous ** condition exists if xt is not for a word defined via CREATE. **************************************************************************/ static void toBody(FICL_VM *pVM) { FICL_WORD *pFW; /*#$-GUY CHANGE: Added robustness.-$#*/ #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 1); #endif pFW = POPPTR(); PUSHPTR(pFW->param + 1); return; } /* ** from-body ficl ( a-addr -- xt ) ** Reverse effect of >body */ static void fromBody(FICL_VM *pVM) { char *ptr; #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 1); #endif ptr = (char *)POPPTR() - sizeof (FICL_WORD); PUSHPTR(ptr); return; } /* ** >name ficl ( xt -- c-addr u ) ** Push the address and length of a word's name given its address ** xt. */ static void toName(FICL_VM *pVM) { FICL_WORD *pFW; #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 2); #endif pFW = POPPTR(); PUSHPTR(pFW->name); PUSHUNS(pFW->nName); return; } static void getLastWord(FICL_VM *pVM) { FICL_DICT *pDict = vmGetDict(pVM); FICL_WORD *wp = pDict->smudge; assert(wp); vmPush(pVM, LVALUEtoCELL(wp)); return; } /************************************************************************** l b r a c k e t e t c ** **************************************************************************/ static void lbracketCoIm(FICL_VM *pVM) { pVM->state = INTERPRET; return; } static void rbracket(FICL_VM *pVM) { pVM->state = COMPILE; return; } /************************************************************************** p i c t u r e d n u m e r i c w o r d s ** ** less-number-sign CORE ( -- ) ** Initialize the pictured numeric output conversion process. ** (clear the pad) **************************************************************************/ static void lessNumberSign(FICL_VM *pVM) { FICL_STRING *sp = PTRtoSTRING pVM->pad; sp->count = 0; return; } /* ** number-sign CORE ( ud1 -- ud2 ) ** Divide ud1 by the number in BASE giving the quotient ud2 and the remainder ** n. (n is the least-significant digit of ud1.) Convert n to external form ** and add the resulting character to the beginning of the pictured numeric ** output string. An ambiguous condition exists if # executes outside of a ** <# #> delimited number conversion. */ static void numberSign(FICL_VM *pVM) { FICL_STRING *sp; DPUNS u; UNS16 rem; #if FICL_ROBUST > 1 vmCheckStack(pVM, 2, 2); #endif sp = PTRtoSTRING pVM->pad; u = u64Pop(pVM->pStack); rem = m64UMod(&u, (UNS16)(pVM->base)); sp->text[sp->count++] = digit_to_char(rem); u64Push(pVM->pStack, u); return; } /* ** number-sign-greater CORE ( xd -- c-addr u ) ** Drop xd. Make the pictured numeric output string available as a character ** string. c-addr and u specify the resulting character string. A program ** may replace characters within the string. */ static void numberSignGreater(FICL_VM *pVM) { FICL_STRING *sp; #if FICL_ROBUST > 1 vmCheckStack(pVM, 2, 2); #endif sp = PTRtoSTRING pVM->pad; sp->text[sp->count] = 0; strrev(sp->text); DROP(2); PUSHPTR(sp->text); PUSHUNS(sp->count); return; } /* ** number-sign-s CORE ( ud1 -- ud2 ) ** Convert one digit of ud1 according to the rule for #. Continue conversion ** until the quotient is zero. ud2 is zero. An ambiguous condition exists if ** #S executes outside of a <# #> delimited number conversion. ** TO DO: presently does not use ud1 hi cell - use it! */ static void numberSignS(FICL_VM *pVM) { FICL_STRING *sp; DPUNS u; UNS16 rem; #if FICL_ROBUST > 1 vmCheckStack(pVM, 2, 2); #endif sp = PTRtoSTRING pVM->pad; u = u64Pop(pVM->pStack); do { rem = m64UMod(&u, (UNS16)(pVM->base)); sp->text[sp->count++] = digit_to_char(rem); } while (u.hi || u.lo); u64Push(pVM->pStack, u); return; } /* ** HOLD CORE ( char -- ) ** Add char to the beginning of the pictured numeric output string. An ambiguous ** condition exists if HOLD executes outside of a <# #> delimited number conversion. */ static void hold(FICL_VM *pVM) { FICL_STRING *sp; int i; #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 0); #endif sp = PTRtoSTRING pVM->pad; i = POPINT(); sp->text[sp->count++] = (char) i; return; } /* ** SIGN CORE ( n -- ) ** If n is negative, add a minus sign to the beginning of the pictured ** numeric output string. An ambiguous condition exists if SIGN ** executes outside of a <# #> delimited number conversion. */ static void sign(FICL_VM *pVM) { FICL_STRING *sp; int i; #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 0); #endif sp = PTRtoSTRING pVM->pad; i = POPINT(); if (i < 0) sp->text[sp->count++] = '-'; return; } /************************************************************************** t o N u m b e r ** to-number CORE ( ud1 c-addr1 u1 -- ud2 c-addr2 u2 ) ** ud2 is the unsigned result of converting the characters within the ** string specified by c-addr1 u1 into digits, using the number in BASE, ** and adding each into ud1 after multiplying ud1 by the number in BASE. ** Conversion continues left-to-right until a character that is not ** convertible, including any + or -, is encountered or the string is ** entirely converted. c-addr2 is the location of the first unconverted ** character or the first character past the end of the string if the string ** was entirely converted. u2 is the number of unconverted characters in the ** string. An ambiguous condition exists if ud2 overflows during the ** conversion. **************************************************************************/ static void toNumber(FICL_VM *pVM) { FICL_UNS count; char *cp; DPUNS accum; FICL_UNS base = pVM->base; FICL_UNS ch; FICL_UNS digit; #if FICL_ROBUST > 1 vmCheckStack(pVM,4,4); #endif count = POPUNS(); cp = (char *)POPPTR(); accum = u64Pop(pVM->pStack); for (ch = *cp; count > 0; ch = *++cp, count--) { if (ch < '0') break; digit = ch - '0'; if (digit > 9) digit = tolower(ch) - 'a' + 10; /* ** Note: following test also catches chars between 9 and a ** because 'digit' is unsigned! */ if (digit >= base) break; accum = m64Mac(accum, base, digit); } u64Push(pVM->pStack, accum); PUSHPTR(cp); PUSHUNS(count); return; } /************************************************************************** q u i t & a b o r t ** quit CORE ( -- ) ( R: i*x -- ) ** Empty the return stack, store zero in SOURCE-ID if it is present, make ** the user input device the input source, and enter interpretation state. ** Do not display a message. Repeat the following: ** ** Accept a line from the input source into the input buffer, set >IN to ** zero, and interpret. ** Display the implementation-defined system prompt if in ** interpretation state, all processing has been completed, and no ** ambiguous condition exists. **************************************************************************/ static void quit(FICL_VM *pVM) { vmThrow(pVM, VM_QUIT); return; } static void ficlAbort(FICL_VM *pVM) { vmThrow(pVM, VM_ABORT); return; } /************************************************************************** a c c e p t ** accept CORE ( c-addr +n1 -- +n2 ) ** Receive a string of at most +n1 characters. An ambiguous condition ** exists if +n1 is zero or greater than 32,767. Display graphic characters ** as they are received. A program that depends on the presence or absence ** of non-graphic characters in the string has an environmental dependency. ** The editing functions, if any, that the system performs in order to ** construct the string are implementation-defined. ** ** (Although the standard text doesn't say so, I assume that the intent ** of 'accept' is to store the string at the address specified on ** the stack.) ** Implementation: if there's more text in the TIB, use it. Otherwise ** throw out for more text. Copy characters up to the max count into the ** address given, and return the number of actual characters copied. ** ** Note (sobral) this may not be the behavior you'd expect if you're ** trying to get user input at load time! **************************************************************************/ static void accept(FICL_VM *pVM) { FICL_UNS count, len; char *cp; char *pBuf, *pEnd; #if FICL_ROBUST > 1 vmCheckStack(pVM,2,1); #endif pBuf = vmGetInBuf(pVM); pEnd = vmGetInBufEnd(pVM); len = pEnd - pBuf; if (len == 0) vmThrow(pVM, VM_RESTART); /* ** Now we have something in the text buffer - use it */ count = stackPopINT(pVM->pStack); cp = stackPopPtr(pVM->pStack); len = (count < len) ? count : len; strncpy(cp, vmGetInBuf(pVM), len); pBuf += len; vmUpdateTib(pVM, pBuf); PUSHINT(len); return; } /************************************************************************** a l i g n ** 6.1.0705 ALIGN CORE ( -- ) ** If the data-space pointer is not aligned, reserve enough space to ** align it. **************************************************************************/ static void align(FICL_VM *pVM) { FICL_DICT *dp = vmGetDict(pVM); IGNORE(pVM); dictAlign(dp); return; } /************************************************************************** a l i g n e d ** **************************************************************************/ static void aligned(FICL_VM *pVM) { void *addr; #if FICL_ROBUST > 1 vmCheckStack(pVM,1,1); #endif addr = POPPTR(); PUSHPTR(alignPtr(addr)); return; } /************************************************************************** b e g i n & f r i e n d s ** Indefinite loop control structures ** A.6.1.0760 BEGIN ** Typical use: ** : X ... BEGIN ... test UNTIL ; ** or ** : X ... BEGIN ... test WHILE ... REPEAT ; **************************************************************************/ static void beginCoIm(FICL_VM *pVM) { FICL_DICT *dp = vmGetDict(pVM); markBranch(dp, pVM, destTag); return; } static void untilCoIm(FICL_VM *pVM) { FICL_DICT *dp = vmGetDict(pVM); assert(pVM->pSys->pBranch0); dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pBranch0)); resolveBackBranch(dp, pVM, destTag); return; } static void whileCoIm(FICL_VM *pVM) { FICL_DICT *dp = vmGetDict(pVM); assert(pVM->pSys->pBranch0); dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pBranch0)); markBranch(dp, pVM, origTag); twoSwap(pVM); dictAppendUNS(dp, 1); return; } static void repeatCoIm(FICL_VM *pVM) { FICL_DICT *dp = vmGetDict(pVM); assert(pVM->pSys->pBranchParen); dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pBranchParen)); /* expect "begin" branch marker */ resolveBackBranch(dp, pVM, destTag); /* expect "while" branch marker */ resolveForwardBranch(dp, pVM, origTag); return; } static void againCoIm(FICL_VM *pVM) { FICL_DICT *dp = vmGetDict(pVM); assert(pVM->pSys->pBranchParen); dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pBranchParen)); /* expect "begin" branch marker */ resolveBackBranch(dp, pVM, destTag); return; } /************************************************************************** c h a r & f r i e n d s ** 6.1.0895 CHAR CORE ( "name" -- char ) ** Skip leading space delimiters. Parse name delimited by a space. ** Put the value of its first character onto the stack. ** ** bracket-char CORE ** Interpretation: Interpretation semantics for this word are undefined. ** Compilation: ( "name" -- ) ** Skip leading space delimiters. Parse name delimited by a space. ** Append the run-time semantics given below to the current definition. ** Run-time: ( -- char ) ** Place char, the value of the first character of name, on the stack. **************************************************************************/ static void ficlChar(FICL_VM *pVM) { STRINGINFO si; #if FICL_ROBUST > 1 vmCheckStack(pVM,0,1); #endif si = vmGetWord(pVM); PUSHUNS((FICL_UNS)(si.cp[0])); return; } static void charCoIm(FICL_VM *pVM) { ficlChar(pVM); literalIm(pVM); return; } /************************************************************************** c h a r P l u s ** char-plus CORE ( c-addr1 -- c-addr2 ) ** Add the size in address units of a character to c-addr1, giving c-addr2. **************************************************************************/ static void charPlus(FICL_VM *pVM) { char *cp; #if FICL_ROBUST > 1 vmCheckStack(pVM,1,1); #endif cp = POPPTR(); PUSHPTR(cp + 1); return; } /************************************************************************** c h a r s ** chars CORE ( n1 -- n2 ) ** n2 is the size in address units of n1 characters. ** For most processors, this function can be a no-op. To guarantee ** portability, we'll multiply by sizeof (char). **************************************************************************/ #if defined (_M_IX86) #pragma warning(disable: 4127) #endif static void ficlChars(FICL_VM *pVM) { if (sizeof (char) > 1) { FICL_INT i; #if FICL_ROBUST > 1 vmCheckStack(pVM,1,1); #endif i = POPINT(); PUSHINT(i * sizeof (char)); } /* otherwise no-op! */ return; } #if defined (_M_IX86) #pragma warning(default: 4127) #endif /************************************************************************** c o u n t ** COUNT CORE ( c-addr1 -- c-addr2 u ) ** Return the character string specification for the counted string stored ** at c-addr1. c-addr2 is the address of the first character after c-addr1. ** u is the contents of the character at c-addr1, which is the length in ** characters of the string at c-addr2. **************************************************************************/ static void count(FICL_VM *pVM) { FICL_STRING *sp; #if FICL_ROBUST > 1 vmCheckStack(pVM,1,2); #endif sp = POPPTR(); PUSHPTR(sp->text); PUSHUNS(sp->count); return; } /************************************************************************** e n v i r o n m e n t ? ** environment-query CORE ( c-addr u -- false | i*x true ) ** c-addr is the address of a character string and u is the string's ** character count. u may have a value in the range from zero to an ** implementation-defined maximum which shall not be less than 31. The ** character string should contain a keyword from 3.2.6 Environmental ** queries or the optional word sets to be checked for correspondence ** with an attribute of the present environment. If the system treats the ** attribute as unknown, the returned flag is false; otherwise, the flag ** is true and the i*x returned is of the type specified in the table for ** the attribute queried. **************************************************************************/ static void environmentQ(FICL_VM *pVM) { FICL_DICT *envp; FICL_WORD *pFW; STRINGINFO si; #if FICL_ROBUST > 1 vmCheckStack(pVM,2,1); #endif envp = pVM->pSys->envp; si.count = (FICL_COUNT)stackPopUNS(pVM->pStack); si.cp = stackPopPtr(pVM->pStack); pFW = dictLookup(envp, si); if (pFW != NULL) { vmExecute(pVM, pFW); PUSHINT(FICL_TRUE); } else { PUSHINT(FICL_FALSE); } return; } /************************************************************************** e v a l u a t e ** EVALUATE CORE ( i*x c-addr u -- j*x ) ** Save the current input source specification. Store minus-one (-1) in ** SOURCE-ID if it is present. Make the string described by c-addr and u ** both the input source and input buffer, set >IN to zero, and interpret. ** When the parse area is empty, restore the prior input source ** specification. Other stack effects are due to the words EVALUATEd. ** **************************************************************************/ static void evaluate(FICL_VM *pVM) { FICL_UNS count; char *cp; CELL id; int result; #if FICL_ROBUST > 1 vmCheckStack(pVM,2,0); #endif count = POPUNS(); cp = POPPTR(); IGNORE(count); id = pVM->sourceID; pVM->sourceID.i = -1; result = ficlExecC(pVM, cp, count); pVM->sourceID = id; if (result != VM_OUTOFTEXT) vmThrow(pVM, result); return; } /************************************************************************** s t r i n g q u o t e ** Interpreting: get string delimited by a quote from the input stream, ** copy to a scratch area, and put its count and address on the stack. ** Compiling: compile code to push the address and count of a string ** literal, compile the string from the input stream, and align the dict ** pointer. **************************************************************************/ static void stringQuoteIm(FICL_VM *pVM) { FICL_DICT *dp = vmGetDict(pVM); if (pVM->state == INTERPRET) { FICL_STRING *sp = (FICL_STRING *) dp->here; vmGetString(pVM, sp, '\"'); PUSHPTR(sp->text); PUSHUNS(sp->count); } else /* COMPILE state */ { dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pStringLit)); dp->here = PTRtoCELL vmGetString(pVM, (FICL_STRING *)dp->here, '\"'); dictAlign(dp); } return; } /************************************************************************** t y p e ** Pop count and char address from stack and print the designated string. **************************************************************************/ static void type(FICL_VM *pVM) { FICL_UNS count = stackPopUNS(pVM->pStack); char *cp = stackPopPtr(pVM->pStack); char *pDest = (char *)ficlMalloc(count + 1); /* ** Since we don't have an output primitive for a counted string ** (oops), make sure the string is null terminated. If not, copy ** and terminate it. */ if (!pDest) vmThrowErr(pVM, "Error: out of memory"); strncpy(pDest, cp, count); pDest[count] = '\0'; vmTextOut(pVM, pDest, 0); ficlFree(pDest); return; } /************************************************************************** w o r d ** word CORE ( char "ccc" -- c-addr ) ** Skip leading delimiters. Parse characters ccc delimited by char. An ** ambiguous condition exists if the length of the parsed string is greater ** than the implementation-defined length of a counted string. ** ** c-addr is the address of a transient region containing the parsed word ** as a counted string. If the parse area was empty or contained no ** characters other than the delimiter, the resulting string has a zero ** length. A space, not included in the length, follows the string. A ** program may replace characters within the string. ** NOTE! Ficl also NULL-terminates the dest string. **************************************************************************/ static void ficlWord(FICL_VM *pVM) { FICL_STRING *sp; char delim; STRINGINFO si; #if FICL_ROBUST > 1 vmCheckStack(pVM,1,1); #endif sp = (FICL_STRING *)pVM->pad; delim = (char)POPINT(); si = vmParseStringEx(pVM, delim, 1); if (SI_COUNT(si) > nPAD-1) SI_SETLEN(si, nPAD-1); sp->count = (FICL_COUNT)SI_COUNT(si); strncpy(sp->text, SI_PTR(si), SI_COUNT(si)); /*#$-GUY CHANGE: I added this.-$#*/ sp->text[sp->count] = 0; strcat(sp->text, " "); PUSHPTR(sp); return; } /************************************************************************** p a r s e - w o r d ** ficl PARSE-WORD ( name -- c-addr u ) ** Skip leading spaces and parse name delimited by a space. c-addr is the ** address within the input buffer and u is the length of the selected ** string. If the parse area is empty, the resulting string has a zero length. **************************************************************************/ static void parseNoCopy(FICL_VM *pVM) { STRINGINFO si; #if FICL_ROBUST > 1 vmCheckStack(pVM,0,2); #endif si = vmGetWord0(pVM); PUSHPTR(SI_PTR(si)); PUSHUNS(SI_COUNT(si)); return; } /************************************************************************** p a r s e ** CORE EXT ( char "ccc" -- c-addr u ) ** Parse ccc delimited by the delimiter char. ** c-addr is the address (within the input buffer) and u is the length of ** the parsed string. If the parse area was empty, the resulting string has ** a zero length. ** NOTE! PARSE differs from WORD: it does not skip leading delimiters. **************************************************************************/ static void parse(FICL_VM *pVM) { STRINGINFO si; char delim; #if FICL_ROBUST > 1 vmCheckStack(pVM,1,2); #endif delim = (char)POPINT(); si = vmParseStringEx(pVM, delim, 0); PUSHPTR(SI_PTR(si)); PUSHUNS(SI_COUNT(si)); return; } /************************************************************************** f i l l ** CORE ( c-addr u char -- ) ** If u is greater than zero, store char in each of u consecutive ** characters of memory beginning at c-addr. **************************************************************************/ static void fill(FICL_VM *pVM) { char ch; FICL_UNS u; char *cp; #if FICL_ROBUST > 1 vmCheckStack(pVM,3,0); #endif ch = (char)POPINT(); u = POPUNS(); cp = (char *)POPPTR(); while (u > 0) { *cp++ = ch; u--; } return; } /************************************************************************** f i n d ** FIND CORE ( c-addr -- c-addr 0 | xt 1 | xt -1 ) ** Find the definition named in the counted string at c-addr. If the ** definition is not found, return c-addr and zero. If the definition is ** found, return its execution token xt. If the definition is immediate, ** also return one (1), otherwise also return minus-one (-1). For a given ** string, the values returned by FIND while compiling may differ from ** those returned while not compiling. **************************************************************************/ static void do_find(FICL_VM *pVM, STRINGINFO si, void *returnForFailure) { FICL_WORD *pFW; pFW = dictLookup(vmGetDict(pVM), si); if (pFW) { PUSHPTR(pFW); PUSHINT((wordIsImmediate(pFW) ? 1 : -1)); } else { PUSHPTR(returnForFailure); PUSHUNS(0); } return; } /************************************************************************** f i n d ** FIND CORE ( c-addr -- c-addr 0 | xt 1 | xt -1 ) ** Find the definition named in the counted string at c-addr. If the ** definition is not found, return c-addr and zero. If the definition is ** found, return its execution token xt. If the definition is immediate, ** also return one (1), otherwise also return minus-one (-1). For a given ** string, the values returned by FIND while compiling may differ from ** those returned while not compiling. **************************************************************************/ static void cFind(FICL_VM *pVM) { FICL_STRING *sp; STRINGINFO si; #if FICL_ROBUST > 1 vmCheckStack(pVM,1,2); #endif sp = POPPTR(); SI_PFS(si, sp); do_find(pVM, si, sp); } /************************************************************************** s f i n d ** FICL ( c-addr u -- 0 0 | xt 1 | xt -1 ) ** Like FIND, but takes "c-addr u" for the string. **************************************************************************/ static void sFind(FICL_VM *pVM) { STRINGINFO si; #if FICL_ROBUST > 1 vmCheckStack(pVM,2,2); #endif si.count = stackPopINT(pVM->pStack); si.cp = stackPopPtr(pVM->pStack); do_find(pVM, si, NULL); } /************************************************************************** f m S l a s h M o d ** f-m-slash-mod CORE ( d1 n1 -- n2 n3 ) ** Divide d1 by n1, giving the floored quotient n3 and the remainder n2. ** Input and output stack arguments are signed. An ambiguous condition ** exists if n1 is zero or if the quotient lies outside the range of a ** single-cell signed integer. **************************************************************************/ static void fmSlashMod(FICL_VM *pVM) { DPINT d1; FICL_INT n1; INTQR qr; #if FICL_ROBUST > 1 vmCheckStack(pVM,3,2); #endif n1 = POPINT(); d1 = i64Pop(pVM->pStack); qr = m64FlooredDivI(d1, n1); PUSHINT(qr.rem); PUSHINT(qr.quot); return; } /************************************************************************** s m S l a s h R e m ** s-m-slash-rem CORE ( d1 n1 -- n2 n3 ) ** Divide d1 by n1, giving the symmetric quotient n3 and the remainder n2. ** Input and output stack arguments are signed. An ambiguous condition ** exists if n1 is zero or if the quotient lies outside the range of a ** single-cell signed integer. **************************************************************************/ static void smSlashRem(FICL_VM *pVM) { DPINT d1; FICL_INT n1; INTQR qr; #if FICL_ROBUST > 1 vmCheckStack(pVM,3,2); #endif n1 = POPINT(); d1 = i64Pop(pVM->pStack); qr = m64SymmetricDivI(d1, n1); PUSHINT(qr.rem); PUSHINT(qr.quot); return; } static void ficlMod(FICL_VM *pVM) { DPINT d1; FICL_INT n1; INTQR qr; #if FICL_ROBUST > 1 vmCheckStack(pVM,2,1); #endif n1 = POPINT(); d1.lo = POPINT(); i64Extend(d1); qr = m64SymmetricDivI(d1, n1); PUSHINT(qr.rem); return; } /************************************************************************** u m S l a s h M o d ** u-m-slash-mod CORE ( ud u1 -- u2 u3 ) ** Divide ud by u1, giving the quotient u3 and the remainder u2. ** All values and arithmetic are unsigned. An ambiguous condition ** exists if u1 is zero or if the quotient lies outside the range of a ** single-cell unsigned integer. *************************************************************************/ static void umSlashMod(FICL_VM *pVM) { DPUNS ud; FICL_UNS u1; UNSQR qr; u1 = stackPopUNS(pVM->pStack); ud = u64Pop(pVM->pStack); qr = ficlLongDiv(ud, u1); PUSHUNS(qr.rem); PUSHUNS(qr.quot); return; } /************************************************************************** l s h i f t ** l-shift CORE ( x1 u -- x2 ) ** Perform a logical left shift of u bit-places on x1, giving x2. ** Put zeroes into the least significant bits vacated by the shift. ** An ambiguous condition exists if u is greater than or equal to the ** number of bits in a cell. ** ** r-shift CORE ( x1 u -- x2 ) ** Perform a logical right shift of u bit-places on x1, giving x2. ** Put zeroes into the most significant bits vacated by the shift. An ** ambiguous condition exists if u is greater than or equal to the ** number of bits in a cell. **************************************************************************/ static void lshift(FICL_VM *pVM) { FICL_UNS nBits; FICL_UNS x1; #if FICL_ROBUST > 1 vmCheckStack(pVM,2,1); #endif nBits = POPUNS(); x1 = POPUNS(); PUSHUNS(x1 << nBits); return; } static void rshift(FICL_VM *pVM) { FICL_UNS nBits; FICL_UNS x1; #if FICL_ROBUST > 1 vmCheckStack(pVM,2,1); #endif nBits = POPUNS(); x1 = POPUNS(); PUSHUNS(x1 >> nBits); return; } /************************************************************************** m S t a r ** m-star CORE ( n1 n2 -- d ) ** d is the signed product of n1 times n2. **************************************************************************/ static void mStar(FICL_VM *pVM) { FICL_INT n2; FICL_INT n1; DPINT d; #if FICL_ROBUST > 1 vmCheckStack(pVM,2,2); #endif n2 = POPINT(); n1 = POPINT(); d = m64MulI(n1, n2); i64Push(pVM->pStack, d); return; } static void umStar(FICL_VM *pVM) { FICL_UNS u2; FICL_UNS u1; DPUNS ud; #if FICL_ROBUST > 1 vmCheckStack(pVM,2,2); #endif u2 = POPUNS(); u1 = POPUNS(); ud = ficlLongMul(u1, u2); u64Push(pVM->pStack, ud); return; } /************************************************************************** m a x & m i n ** **************************************************************************/ static void ficlMax(FICL_VM *pVM) { FICL_INT n2; FICL_INT n1; #if FICL_ROBUST > 1 vmCheckStack(pVM,2,1); #endif n2 = POPINT(); n1 = POPINT(); PUSHINT((n1 > n2) ? n1 : n2); return; } static void ficlMin(FICL_VM *pVM) { FICL_INT n2; FICL_INT n1; #if FICL_ROBUST > 1 vmCheckStack(pVM,2,1); #endif n2 = POPINT(); n1 = POPINT(); PUSHINT((n1 < n2) ? n1 : n2); return; } /************************************************************************** m o v e ** CORE ( addr1 addr2 u -- ) ** If u is greater than zero, copy the contents of u consecutive address ** units at addr1 to the u consecutive address units at addr2. After MOVE ** completes, the u consecutive address units at addr2 contain exactly ** what the u consecutive address units at addr1 contained before the move. ** NOTE! This implementation assumes that a char is the same size as ** an address unit. **************************************************************************/ static void move(FICL_VM *pVM) { FICL_UNS u; char *addr2; char *addr1; #if FICL_ROBUST > 1 vmCheckStack(pVM,3,0); #endif u = POPUNS(); addr2 = POPPTR(); addr1 = POPPTR(); if (u == 0) return; /* ** Do the copy carefully, so as to be ** correct even if the two ranges overlap */ if (addr1 >= addr2) { for (; u > 0; u--) *addr2++ = *addr1++; } else { addr2 += u-1; addr1 += u-1; for (; u > 0; u--) *addr2-- = *addr1--; } return; } /************************************************************************** r e c u r s e ** **************************************************************************/ static void recurseCoIm(FICL_VM *pVM) { FICL_DICT *pDict = vmGetDict(pVM); IGNORE(pVM); dictAppendCell(pDict, LVALUEtoCELL(pDict->smudge)); return; } /************************************************************************** s t o d ** s-to-d CORE ( n -- d ) ** Convert the number n to the double-cell number d with the same ** numerical value. **************************************************************************/ static void sToD(FICL_VM *pVM) { FICL_INT s; #if FICL_ROBUST > 1 vmCheckStack(pVM,1,2); #endif s = POPINT(); /* sign extend to 64 bits.. */ PUSHINT(s); PUSHINT((s < 0) ? -1 : 0); return; } /************************************************************************** s o u r c e ** CORE ( -- c-addr u ) ** c-addr is the address of, and u is the number of characters in, the ** input buffer. **************************************************************************/ static void source(FICL_VM *pVM) { #if FICL_ROBUST > 1 vmCheckStack(pVM,0,2); #endif PUSHPTR(pVM->tib.cp); PUSHINT(vmGetInBufLen(pVM)); return; } /************************************************************************** v e r s i o n ** non-standard... **************************************************************************/ static void ficlVersion(FICL_VM *pVM) { vmTextOut(pVM, "ficl Version " FICL_VER, 1); return; } /************************************************************************** t o I n ** to-in CORE **************************************************************************/ static void toIn(FICL_VM *pVM) { #if FICL_ROBUST > 1 vmCheckStack(pVM,0,1); #endif PUSHPTR(&pVM->tib.index); return; } /************************************************************************** c o l o n N o N a m e ** CORE EXT ( C: -- colon-sys ) ( S: -- xt ) ** Create an unnamed colon definition and push its address. ** Change state to compile. **************************************************************************/ static void colonNoName(FICL_VM *pVM) { FICL_DICT *dp = vmGetDict(pVM); FICL_WORD *pFW; STRINGINFO si; SI_SETLEN(si, 0); SI_SETPTR(si, NULL); pVM->state = COMPILE; pFW = dictAppendWord2(dp, si, colonParen, FW_DEFAULT | FW_SMUDGE); PUSHPTR(pFW); markControlTag(pVM, colonTag); return; } /************************************************************************** u s e r V a r i a b l e ** user ( u -- ) "name" ** Get a name from the input stream and create a user variable ** with the name and the index supplied. The run-time effect ** of a user variable is to push the address of the indexed cell ** in the running vm's user array. ** ** User variables are vm local cells. Each vm has an array of ** FICL_USER_CELLS of them when FICL_WANT_USER is nonzero. ** Ficl's user facility is implemented with two primitives, ** "user" and "(user)", a variable ("nUser") (in softcore.c) that ** holds the index of the next free user cell, and a redefinition ** (also in softcore) of "user" that defines a user word and increments ** nUser. **************************************************************************/ #if FICL_WANT_USER static void userParen(FICL_VM *pVM) { FICL_INT i = pVM->runningWord->param[0].i; PUSHPTR(&pVM->user[i]); return; } static void userVariable(FICL_VM *pVM) { FICL_DICT *dp = vmGetDict(pVM); STRINGINFO si = vmGetWord(pVM); CELL c; c = stackPop(pVM->pStack); if (c.i >= FICL_USER_CELLS) { vmThrowErr(pVM, "Error - out of user space"); } dictAppendWord2(dp, si, userParen, FW_DEFAULT); dictAppendCell(dp, c); return; } #endif /************************************************************************** t o V a l u e ** CORE EXT ** Interpretation: ( x "name" -- ) ** Skip leading spaces and parse name delimited by a space. Store x in ** name. An ambiguous condition exists if name was not defined by VALUE. ** NOTE: In ficl, VALUE is an alias of CONSTANT **************************************************************************/ static void toValue(FICL_VM *pVM) { STRINGINFO si = vmGetWord(pVM); FICL_DICT *dp = vmGetDict(pVM); FICL_WORD *pFW; #if FICL_WANT_LOCALS if ((pVM->pSys->nLocals > 0) && (pVM->state == COMPILE)) { FICL_DICT *pLoc = ficlGetLoc(pVM->pSys); pFW = dictLookup(pLoc, si); if (pFW && (pFW->code == doLocalIm)) { dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pToLocalParen)); dictAppendCell(dp, LVALUEtoCELL(pFW->param[0])); return; } else if (pFW && pFW->code == do2LocalIm) { dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pTo2LocalParen)); dictAppendCell(dp, LVALUEtoCELL(pFW->param[0])); return; } } #endif assert(pVM->pSys->pStore); pFW = dictLookup(dp, si); if (!pFW) { int i = SI_COUNT(si); vmThrowErr(pVM, "%.*s not found", i, SI_PTR(si)); } if (pVM->state == INTERPRET) pFW->param[0] = stackPop(pVM->pStack); else /* compile code to store to word's param */ { PUSHPTR(&pFW->param[0]); literalIm(pVM); dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pStore)); } return; } #if FICL_WANT_LOCALS /************************************************************************** l i n k P a r e n ** ( -- ) ** Link a frame on the return stack, reserving nCells of space for ** locals - the value of nCells is the next cell in the instruction ** stream. **************************************************************************/ static void linkParen(FICL_VM *pVM) { FICL_INT nLink = *(FICL_INT *)(pVM->ip); vmBranchRelative(pVM, 1); stackLink(pVM->rStack, nLink); return; } static void unlinkParen(FICL_VM *pVM) { stackUnlink(pVM->rStack); return; } /************************************************************************** d o L o c a l I m ** Immediate - cfa of a local while compiling - when executed, compiles ** code to fetch the value of a local given the local's index in the ** word's pfa **************************************************************************/ static void getLocalParen(FICL_VM *pVM) { FICL_INT nLocal = *(FICL_INT *)(pVM->ip++); stackPush(pVM->pStack, pVM->rStack->pFrame[nLocal]); return; } static void toLocalParen(FICL_VM *pVM) { FICL_INT nLocal = *(FICL_INT *)(pVM->ip++); pVM->rStack->pFrame[nLocal] = stackPop(pVM->pStack); return; } static void getLocal0(FICL_VM *pVM) { stackPush(pVM->pStack, pVM->rStack->pFrame[0]); return; } static void toLocal0(FICL_VM *pVM) { pVM->rStack->pFrame[0] = stackPop(pVM->pStack); return; } static void getLocal1(FICL_VM *pVM) { stackPush(pVM->pStack, pVM->rStack->pFrame[1]); return; } static void toLocal1(FICL_VM *pVM) { pVM->rStack->pFrame[1] = stackPop(pVM->pStack); return; } /* ** Each local is recorded in a private locals dictionary as a ** word that does doLocalIm at runtime. DoLocalIm compiles code ** into the client definition to fetch the value of the ** corresponding local variable from the return stack. ** The private dictionary gets initialized at the end of each block ** that uses locals (in ; and does> for example). */ static void doLocalIm(FICL_VM *pVM) { FICL_DICT *pDict = vmGetDict(pVM); FICL_INT nLocal = pVM->runningWord->param[0].i; if (pVM->state == INTERPRET) { stackPush(pVM->pStack, pVM->rStack->pFrame[nLocal]); } else { if (nLocal == 0) { dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->pGetLocal0)); } else if (nLocal == 1) { dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->pGetLocal1)); } else { dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->pGetLocalParen)); dictAppendCell(pDict, LVALUEtoCELL(nLocal)); } } return; } /************************************************************************** l o c a l P a r e n ** paren-local-paren LOCAL ** Interpretation: Interpretation semantics for this word are undefined. ** Execution: ( c-addr u -- ) ** When executed during compilation, (LOCAL) passes a message to the ** system that has one of two meanings. If u is non-zero, ** the message identifies a new local whose definition name is given by ** the string of characters identified by c-addr u. If u is zero, ** the message is last local and c-addr has no significance. ** ** The result of executing (LOCAL) during compilation of a definition is ** to create a set of named local identifiers, each of which is ** a definition name, that only have execution semantics within the scope ** of that definition's source. ** ** local Execution: ( -- x ) ** ** Push the local's value, x, onto the stack. The local's value is ** initialized as described in 13.3.3 Processing locals and may be ** changed by preceding the local's name with TO. An ambiguous condition ** exists when local is executed while in interpretation state. **************************************************************************/ static void localParen(FICL_VM *pVM) { FICL_DICT *pDict; STRINGINFO si; #if FICL_ROBUST > 1 vmCheckStack(pVM,2,0); #endif pDict = vmGetDict(pVM); SI_SETLEN(si, POPUNS()); SI_SETPTR(si, (char *)POPPTR()); if (SI_COUNT(si) > 0) { /* add a local to the **locals** dict and update nLocals */ FICL_DICT *pLoc = ficlGetLoc(pVM->pSys); if (pVM->pSys->nLocals >= FICL_MAX_LOCALS) { vmThrowErr(pVM, "Error: out of local space"); } dictAppendWord2(pLoc, si, doLocalIm, FW_COMPIMMED); dictAppendCell(pLoc, LVALUEtoCELL(pVM->pSys->nLocals)); if (pVM->pSys->nLocals == 0) { /* compile code to create a local stack frame */ dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->pLinkParen)); /* save location in dictionary for #locals */ pVM->pSys->pMarkLocals = pDict->here; dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->nLocals)); /* compile code to initialize first local */ dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->pToLocal0)); } else if (pVM->pSys->nLocals == 1) { dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->pToLocal1)); } else { dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->pToLocalParen)); dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->nLocals)); } (pVM->pSys->nLocals)++; } else if (pVM->pSys->nLocals > 0) { /* write nLocals to (link) param area in dictionary */ *(FICL_INT *)(pVM->pSys->pMarkLocals) = pVM->pSys->nLocals; } return; } static void get2LocalParen(FICL_VM *pVM) { FICL_INT nLocal = *(FICL_INT *)(pVM->ip++); stackPush(pVM->pStack, pVM->rStack->pFrame[nLocal]); stackPush(pVM->pStack, pVM->rStack->pFrame[nLocal+1]); return; } static void do2LocalIm(FICL_VM *pVM) { FICL_DICT *pDict = vmGetDict(pVM); FICL_INT nLocal = pVM->runningWord->param[0].i; if (pVM->state == INTERPRET) { stackPush(pVM->pStack, pVM->rStack->pFrame[nLocal]); stackPush(pVM->pStack, pVM->rStack->pFrame[nLocal+1]); } else { dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->pGet2LocalParen)); dictAppendCell(pDict, LVALUEtoCELL(nLocal)); } return; } static void to2LocalParen(FICL_VM *pVM) { FICL_INT nLocal = *(FICL_INT *)(pVM->ip++); pVM->rStack->pFrame[nLocal+1] = stackPop(pVM->pStack); pVM->rStack->pFrame[nLocal] = stackPop(pVM->pStack); return; } static void twoLocalParen(FICL_VM *pVM) { FICL_DICT *pDict = vmGetDict(pVM); STRINGINFO si; SI_SETLEN(si, stackPopUNS(pVM->pStack)); SI_SETPTR(si, (char *)stackPopPtr(pVM->pStack)); if (SI_COUNT(si) > 0) { /* add a local to the **locals** dict and update nLocals */ FICL_DICT *pLoc = ficlGetLoc(pVM->pSys); if (pVM->pSys->nLocals >= FICL_MAX_LOCALS) { vmThrowErr(pVM, "Error: out of local space"); } dictAppendWord2(pLoc, si, do2LocalIm, FW_COMPIMMED); dictAppendCell(pLoc, LVALUEtoCELL(pVM->pSys->nLocals)); if (pVM->pSys->nLocals == 0) { /* compile code to create a local stack frame */ dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->pLinkParen)); /* save location in dictionary for #locals */ pVM->pSys->pMarkLocals = pDict->here; dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->nLocals)); } dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->pTo2LocalParen)); dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->nLocals)); pVM->pSys->nLocals += 2; } else if (pVM->pSys->nLocals > 0) { /* write nLocals to (link) param area in dictionary */ *(FICL_INT *)(pVM->pSys->pMarkLocals) = pVM->pSys->nLocals; } return; } #endif /************************************************************************** c o m p a r e ** STRING ( c-addr1 u1 c-addr2 u2 -- n ) ** Compare the string specified by c-addr1 u1 to the string specified by ** c-addr2 u2. The strings are compared, beginning at the given addresses, ** character by character, up to the length of the shorter string or until a ** difference is found. If the two strings are identical, n is zero. If the two ** strings are identical up to the length of the shorter string, n is minus-one ** (-1) if u1 is less than u2 and one (1) otherwise. If the two strings are not ** identical up to the length of the shorter string, n is minus-one (-1) if the ** first non-matching character in the string specified by c-addr1 u1 has a ** lesser numeric value than the corresponding character in the string specified ** by c-addr2 u2 and one (1) otherwise. **************************************************************************/ static void compareInternal(FICL_VM *pVM, int caseInsensitive) { char *cp1, *cp2; FICL_UNS u1, u2, uMin; int n = 0; vmCheckStack(pVM, 4, 1); u2 = stackPopUNS(pVM->pStack); cp2 = (char *)stackPopPtr(pVM->pStack); u1 = stackPopUNS(pVM->pStack); cp1 = (char *)stackPopPtr(pVM->pStack); uMin = (u1 < u2)? u1 : u2; for ( ; (uMin > 0) && (n == 0); uMin--) { char c1 = *cp1++; char c2 = *cp2++; if (caseInsensitive) { c1 = (char)tolower(c1); c2 = (char)tolower(c2); } n = (int)(c1 - c2); } if (n == 0) n = (int)(u1 - u2); if (n < 0) n = -1; else if (n > 0) n = 1; PUSHINT(n); return; } static void compareString(FICL_VM *pVM) { compareInternal(pVM, FALSE); } static void compareStringInsensitive(FICL_VM *pVM) { compareInternal(pVM, TRUE); } /************************************************************************** p a d ** CORE EXT ( -- c-addr ) ** c-addr is the address of a transient region that can be used to hold ** data for intermediate processing. **************************************************************************/ static void pad(FICL_VM *pVM) { stackPushPtr(pVM->pStack, pVM->pad); } /************************************************************************** s o u r c e - i d ** CORE EXT, FILE ( -- 0 | -1 | fileid ) ** Identifies the input source as follows: ** ** SOURCE-ID Input source ** --------- ------------ ** fileid Text file fileid ** -1 String (via EVALUATE) ** 0 User input device **************************************************************************/ static void sourceid(FICL_VM *pVM) { PUSHINT(pVM->sourceID.i); return; } /************************************************************************** r e f i l l ** CORE EXT ( -- flag ) ** Attempt to fill the input buffer from the input source, returning a true ** flag if successful. ** When the input source is the user input device, attempt to receive input ** into the terminal input buffer. If successful, make the result the input ** buffer, set >IN to zero, and return true. Receipt of a line containing no ** characters is considered successful. If there is no input available from ** the current input source, return false. ** When the input source is a string from EVALUATE, return false and ** perform no other action. **************************************************************************/ static void refill(FICL_VM *pVM) { FICL_INT ret = (pVM->sourceID.i == -1) ? FICL_FALSE : FICL_TRUE; if (ret && (pVM->fRestart == 0)) vmThrow(pVM, VM_RESTART); PUSHINT(ret); return; } /************************************************************************** freebsd exception handling words ** Catch, from ANS Forth standard. Installs a safety net, then EXECUTE ** the word in ToS. If an exception happens, restore the state to what ** it was before, and pushes the exception value on the stack. If not, ** push zero. ** ** Notice that Catch implements an inner interpreter. This is ugly, ** but given how ficl works, it cannot be helped. The problem is that ** colon definitions will be executed *after* the function returns, ** while "code" definitions will be executed immediately. I considered ** other solutions to this problem, but all of them shared the same ** basic problem (with added disadvantages): if ficl ever changes it's ** inner thread modus operandi, one would have to fix this word. ** ** More comments can be found throughout catch's code. ** ** Daniel C. Sobral Jan 09/1999 ** sadler may 2000 -- revised to follow ficl.c:ficlExecXT. **************************************************************************/ static void ficlCatch(FICL_VM *pVM) { int except; jmp_buf vmState; FICL_VM VM; FICL_STACK pStack; FICL_STACK rStack; FICL_WORD *pFW; assert(pVM); assert(pVM->pSys->pExitInner); /* ** Get xt. ** We need this *before* we save the stack pointer, or ** we'll have to pop one element out of the stack after ** an exception. I prefer to get done with it up front. :-) */ #if FICL_ROBUST > 1 vmCheckStack(pVM, 1, 0); #endif pFW = stackPopPtr(pVM->pStack); /* ** Save vm's state -- a catch will not back out environmental ** changes. ** ** We are *not* saving dictionary state, since it is ** global instead of per vm, and we are not saving ** stack contents, since we are not required to (and, ** thus, it would be useless). We save pVM, and pVM ** "stacks" (a structure containing general information ** about it, including the current stack pointer). */ memcpy((void*)&VM, (void*)pVM, sizeof(FICL_VM)); memcpy((void*)&pStack, (void*)pVM->pStack, sizeof(FICL_STACK)); memcpy((void*)&rStack, (void*)pVM->rStack, sizeof(FICL_STACK)); /* ** Give pVM a jmp_buf */ pVM->pState = &vmState; /* ** Safety net */ except = setjmp(vmState); switch (except) { /* ** Setup condition - push poison pill so that the VM throws ** VM_INNEREXIT if the XT terminates normally, then execute ** the XT */ case 0: vmPushIP(pVM, &(pVM->pSys->pExitInner)); /* Open mouth, insert emetic */ vmExecute(pVM, pFW); vmInnerLoop(pVM); break; /* ** Normal exit from XT - lose the poison pill, ** restore old setjmp vector and push a zero. */ case VM_INNEREXIT: vmPopIP(pVM); /* Gack - hurl poison pill */ pVM->pState = VM.pState; /* Restore just the setjmp vector */ PUSHINT(0); /* Push 0 -- everything is ok */ break; /* ** Some other exception got thrown - restore pre-existing VM state ** and push the exception code */ default: /* Restore vm's state */ memcpy((void*)pVM, (void*)&VM, sizeof(FICL_VM)); memcpy((void*)pVM->pStack, (void*)&pStack, sizeof(FICL_STACK)); memcpy((void*)pVM->rStack, (void*)&rStack, sizeof(FICL_STACK)); PUSHINT(except);/* Push error */ break; } } /************************************************************************** ** t h r o w ** EXCEPTION ** Throw -- From ANS Forth standard. ** ** Throw takes the ToS and, if that's different from zero, ** returns to the last executed catch context. Further throws will ** unstack previously executed "catches", in LIFO mode. ** ** Daniel C. Sobral Jan 09/1999 **************************************************************************/ static void ficlThrow(FICL_VM *pVM) { int except; except = stackPopINT(pVM->pStack); if (except) vmThrow(pVM, except); } /************************************************************************** ** a l l o c a t e ** MEMORY **************************************************************************/ static void ansAllocate(FICL_VM *pVM) { size_t size; void *p; size = stackPopINT(pVM->pStack); p = ficlMalloc(size); PUSHPTR(p); if (p) PUSHINT(0); else PUSHINT(1); } /************************************************************************** ** f r e e ** MEMORY **************************************************************************/ static void ansFree(FICL_VM *pVM) { void *p; p = stackPopPtr(pVM->pStack); ficlFree(p); PUSHINT(0); } /************************************************************************** ** r e s i z e ** MEMORY **************************************************************************/ static void ansResize(FICL_VM *pVM) { size_t size; void *new, *old; size = stackPopINT(pVM->pStack); old = stackPopPtr(pVM->pStack); new = ficlRealloc(old, size); if (new) { PUSHPTR(new); PUSHINT(0); } else { PUSHPTR(old); PUSHINT(1); } } /************************************************************************** ** e x i t - i n n e r ** Signals execXT that an inner loop has completed **************************************************************************/ static void ficlExitInner(FICL_VM *pVM) { vmThrow(pVM, VM_INNEREXIT); } /************************************************************************** d n e g a t e ** DOUBLE ( d1 -- d2 ) ** d2 is the negation of d1. **************************************************************************/ static void dnegate(FICL_VM *pVM) { DPINT i = i64Pop(pVM->pStack); i = m64Negate(i); i64Push(pVM->pStack, i); return; } #if 0 /************************************************************************** ** **************************************************************************/ static void funcname(FICL_VM *pVM) { IGNORE(pVM); return; } #endif /************************************************************************** f i c l W o r d C l a s s i f y ** This public function helps to classify word types for SEE ** and the deugger in tools.c. Given a pointer to a word, it returns ** a member of WOR **************************************************************************/ WORDKIND ficlWordClassify(FICL_WORD *pFW) { typedef struct { WORDKIND kind; FICL_CODE code; } CODEtoKIND; static CODEtoKIND codeMap[] = { {BRANCH, branchParen}, {COLON, colonParen}, {CONSTANT, constantParen}, {CREATE, createParen}, {DO, doParen}, {DOES, doDoes}, {IF, branch0}, {LITERAL, literalParen}, {LOOP, loopParen}, {OF, ofParen}, {PLOOP, plusLoopParen}, {QDO, qDoParen}, {CSTRINGLIT, cstringLit}, {STRINGLIT, stringLit}, #if FICL_WANT_USER {USER, userParen}, #endif {VARIABLE, variableParen}, }; #define nMAP (sizeof(codeMap) / sizeof(CODEtoKIND)) FICL_CODE code = pFW->code; int i; for (i=0; i < nMAP; i++) { if (codeMap[i].code == code) return codeMap[i].kind; } return PRIMITIVE; } #ifdef TESTMAIN /************************************************************************** ** r a n d o m ** FICL-specific **************************************************************************/ static void ficlRandom(FICL_VM *pVM) { PUSHINT(rand()); } /************************************************************************** ** s e e d - r a n d o m ** FICL-specific **************************************************************************/ static void ficlSeedRandom(FICL_VM *pVM) { srand(POPINT()); } #endif /************************************************************************** f i c l C o m p i l e C o r e ** Builds the primitive wordset and the environment-query namespace. **************************************************************************/ void ficlCompileCore(FICL_SYSTEM *pSys) { FICL_DICT *dp = pSys->dp; assert (dp); /* ** CORE word set ** see softcore.c for definitions of: abs bl space spaces abort" */ pSys->pStore = dictAppendWord(dp, "!", store, FW_DEFAULT); dictAppendWord(dp, "#", numberSign, FW_DEFAULT); dictAppendWord(dp, "#>", numberSignGreater,FW_DEFAULT); dictAppendWord(dp, "#s", numberSignS, FW_DEFAULT); dictAppendWord(dp, "\'", ficlTick, FW_DEFAULT); dictAppendWord(dp, "(", commentHang, FW_IMMEDIATE); dictAppendWord(dp, "*", mul, FW_DEFAULT); dictAppendWord(dp, "*/", mulDiv, FW_DEFAULT); dictAppendWord(dp, "*/mod", mulDivRem, FW_DEFAULT); dictAppendWord(dp, "+", add, FW_DEFAULT); dictAppendWord(dp, "+!", plusStore, FW_DEFAULT); dictAppendWord(dp, "+loop", plusLoopCoIm, FW_COMPIMMED); dictAppendWord(dp, ",", comma, FW_DEFAULT); dictAppendWord(dp, "-", sub, FW_DEFAULT); dictAppendWord(dp, ".", displayCell, FW_DEFAULT); dictAppendWord(dp, ".\"", dotQuoteCoIm, FW_COMPIMMED); dictAppendWord(dp, "/", ficlDiv, FW_DEFAULT); dictAppendWord(dp, "/mod", slashMod, FW_DEFAULT); dictAppendWord(dp, "0<", zeroLess, FW_DEFAULT); dictAppendWord(dp, "0=", zeroEquals, FW_DEFAULT); dictAppendWord(dp, "1+", onePlus, FW_DEFAULT); dictAppendWord(dp, "1-", oneMinus, FW_DEFAULT); dictAppendWord(dp, "2!", twoStore, FW_DEFAULT); dictAppendWord(dp, "2*", twoMul, FW_DEFAULT); dictAppendWord(dp, "2/", twoDiv, FW_DEFAULT); dictAppendWord(dp, "2@", twoFetch, FW_DEFAULT); dictAppendWord(dp, "2drop", twoDrop, FW_DEFAULT); dictAppendWord(dp, "2dup", twoDup, FW_DEFAULT); dictAppendWord(dp, "2over", twoOver, FW_DEFAULT); dictAppendWord(dp, "2swap", twoSwap, FW_DEFAULT); dictAppendWord(dp, ":", colon, FW_DEFAULT); dictAppendWord(dp, ";", semicolonCoIm, FW_COMPIMMED); dictAppendWord(dp, "<", isLess, FW_DEFAULT); dictAppendWord(dp, "<#", lessNumberSign, FW_DEFAULT); dictAppendWord(dp, "=", isEqual, FW_DEFAULT); dictAppendWord(dp, ">", isGreater, FW_DEFAULT); dictAppendWord(dp, ">body", toBody, FW_DEFAULT); dictAppendWord(dp, ">in", toIn, FW_DEFAULT); dictAppendWord(dp, ">number", toNumber, FW_DEFAULT); dictAppendWord(dp, ">r", toRStack, FW_COMPILE); dictAppendWord(dp, "?dup", questionDup, FW_DEFAULT); dictAppendWord(dp, "@", fetch, FW_DEFAULT); dictAppendWord(dp, "abort", ficlAbort, FW_DEFAULT); dictAppendWord(dp, "accept", accept, FW_DEFAULT); dictAppendWord(dp, "align", align, FW_DEFAULT); dictAppendWord(dp, "aligned", aligned, FW_DEFAULT); dictAppendWord(dp, "allot", allot, FW_DEFAULT); dictAppendWord(dp, "and", bitwiseAnd, FW_DEFAULT); dictAppendWord(dp, "base", base, FW_DEFAULT); dictAppendWord(dp, "begin", beginCoIm, FW_COMPIMMED); dictAppendWord(dp, "c!", cStore, FW_DEFAULT); dictAppendWord(dp, "c,", cComma, FW_DEFAULT); dictAppendWord(dp, "c@", cFetch, FW_DEFAULT); dictAppendWord(dp, "case", caseCoIm, FW_COMPIMMED); dictAppendWord(dp, "cell+", cellPlus, FW_DEFAULT); dictAppendWord(dp, "cells", cells, FW_DEFAULT); dictAppendWord(dp, "char", ficlChar, FW_DEFAULT); dictAppendWord(dp, "char+", charPlus, FW_DEFAULT); dictAppendWord(dp, "chars", ficlChars, FW_DEFAULT); dictAppendWord(dp, "constant", constant, FW_DEFAULT); dictAppendWord(dp, "count", count, FW_DEFAULT); dictAppendWord(dp, "cr", cr, FW_DEFAULT); dictAppendWord(dp, "create", create, FW_DEFAULT); dictAppendWord(dp, "decimal", decimal, FW_DEFAULT); dictAppendWord(dp, "depth", depth, FW_DEFAULT); dictAppendWord(dp, "do", doCoIm, FW_COMPIMMED); dictAppendWord(dp, "does>", doesCoIm, FW_COMPIMMED); pSys->pDrop = dictAppendWord(dp, "drop", drop, FW_DEFAULT); dictAppendWord(dp, "dup", dup, FW_DEFAULT); dictAppendWord(dp, "else", elseCoIm, FW_COMPIMMED); dictAppendWord(dp, "emit", emit, FW_DEFAULT); dictAppendWord(dp, "endcase", endcaseCoIm, FW_COMPIMMED); dictAppendWord(dp, "endof", endofCoIm, FW_COMPIMMED); dictAppendWord(dp, "environment?", environmentQ,FW_DEFAULT); dictAppendWord(dp, "evaluate", evaluate, FW_DEFAULT); dictAppendWord(dp, "execute", execute, FW_DEFAULT); dictAppendWord(dp, "exit", exitCoIm, FW_COMPIMMED); dictAppendWord(dp, "fallthrough",fallthroughCoIm,FW_COMPIMMED); dictAppendWord(dp, "fill", fill, FW_DEFAULT); dictAppendWord(dp, "find", cFind, FW_DEFAULT); dictAppendWord(dp, "fm/mod", fmSlashMod, FW_DEFAULT); dictAppendWord(dp, "here", here, FW_DEFAULT); dictAppendWord(dp, "hold", hold, FW_DEFAULT); dictAppendWord(dp, "i", loopICo, FW_COMPILE); dictAppendWord(dp, "if", ifCoIm, FW_COMPIMMED); dictAppendWord(dp, "immediate", immediate, FW_DEFAULT); dictAppendWord(dp, "invert", bitwiseNot, FW_DEFAULT); dictAppendWord(dp, "j", loopJCo, FW_COMPILE); dictAppendWord(dp, "k", loopKCo, FW_COMPILE); dictAppendWord(dp, "leave", leaveCo, FW_COMPILE); dictAppendWord(dp, "literal", literalIm, FW_IMMEDIATE); dictAppendWord(dp, "loop", loopCoIm, FW_COMPIMMED); dictAppendWord(dp, "lshift", lshift, FW_DEFAULT); dictAppendWord(dp, "m*", mStar, FW_DEFAULT); dictAppendWord(dp, "max", ficlMax, FW_DEFAULT); dictAppendWord(dp, "min", ficlMin, FW_DEFAULT); dictAppendWord(dp, "mod", ficlMod, FW_DEFAULT); dictAppendWord(dp, "move", move, FW_DEFAULT); dictAppendWord(dp, "negate", negate, FW_DEFAULT); dictAppendWord(dp, "of", ofCoIm, FW_COMPIMMED); dictAppendWord(dp, "or", bitwiseOr, FW_DEFAULT); dictAppendWord(dp, "over", over, FW_DEFAULT); dictAppendWord(dp, "postpone", postponeCoIm, FW_COMPIMMED); dictAppendWord(dp, "quit", quit, FW_DEFAULT); dictAppendWord(dp, "r>", fromRStack, FW_COMPILE); dictAppendWord(dp, "r@", fetchRStack, FW_COMPILE); dictAppendWord(dp, "recurse", recurseCoIm, FW_COMPIMMED); dictAppendWord(dp, "repeat", repeatCoIm, FW_COMPIMMED); dictAppendWord(dp, "rot", rot, FW_DEFAULT); dictAppendWord(dp, "rshift", rshift, FW_DEFAULT); dictAppendWord(dp, "s\"", stringQuoteIm, FW_IMMEDIATE); dictAppendWord(dp, "s>d", sToD, FW_DEFAULT); dictAppendWord(dp, "sign", sign, FW_DEFAULT); dictAppendWord(dp, "sm/rem", smSlashRem, FW_DEFAULT); dictAppendWord(dp, "source", source, FW_DEFAULT); dictAppendWord(dp, "state", state, FW_DEFAULT); dictAppendWord(dp, "swap", swap, FW_DEFAULT); dictAppendWord(dp, "then", endifCoIm, FW_COMPIMMED); dictAppendWord(dp, "type", type, FW_DEFAULT); dictAppendWord(dp, "u.", uDot, FW_DEFAULT); dictAppendWord(dp, "u<", uIsLess, FW_DEFAULT); dictAppendWord(dp, "um*", umStar, FW_DEFAULT); dictAppendWord(dp, "um/mod", umSlashMod, FW_DEFAULT); dictAppendWord(dp, "unloop", unloopCo, FW_COMPILE); dictAppendWord(dp, "until", untilCoIm, FW_COMPIMMED); dictAppendWord(dp, "variable", variable, FW_DEFAULT); dictAppendWord(dp, "while", whileCoIm, FW_COMPIMMED); dictAppendWord(dp, "word", ficlWord, FW_DEFAULT); dictAppendWord(dp, "xor", bitwiseXor, FW_DEFAULT); dictAppendWord(dp, "[", lbracketCoIm, FW_COMPIMMED); dictAppendWord(dp, "[\']", bracketTickCoIm,FW_COMPIMMED); dictAppendWord(dp, "[char]", charCoIm, FW_COMPIMMED); dictAppendWord(dp, "]", rbracket, FW_DEFAULT); /* ** CORE EXT word set... ** see softcore.fr for other definitions */ /* "#tib" */ dictAppendWord(dp, ".(", dotParen, FW_IMMEDIATE); /* ".r" */ dictAppendWord(dp, "0>", zeroGreater, FW_DEFAULT); dictAppendWord(dp, "2>r", twoToR, FW_COMPILE); dictAppendWord(dp, "2r>", twoRFrom, FW_COMPILE); dictAppendWord(dp, "2r@", twoRFetch, FW_COMPILE); dictAppendWord(dp, ":noname", colonNoName, FW_DEFAULT); dictAppendWord(dp, "?do", qDoCoIm, FW_COMPIMMED); dictAppendWord(dp, "again", againCoIm, FW_COMPIMMED); dictAppendWord(dp, "c\"", cstringQuoteIm, FW_IMMEDIATE); dictAppendWord(dp, "hex", hex, FW_DEFAULT); dictAppendWord(dp, "pad", pad, FW_DEFAULT); dictAppendWord(dp, "parse", parse, FW_DEFAULT); dictAppendWord(dp, "pick", pick, FW_DEFAULT); /* query restore-input save-input tib u.r u> unused [compile] */ dictAppendWord(dp, "roll", roll, FW_DEFAULT); dictAppendWord(dp, "refill", refill, FW_DEFAULT); dictAppendWord(dp, "source-id", sourceid, FW_DEFAULT); dictAppendWord(dp, "to", toValue, FW_IMMEDIATE); dictAppendWord(dp, "value", constant, FW_DEFAULT); dictAppendWord(dp, "\\", commentLine, FW_IMMEDIATE); /* ** Set CORE environment query values */ ficlSetEnv(pSys, "/counted-string", FICL_STRING_MAX); ficlSetEnv(pSys, "/hold", nPAD); ficlSetEnv(pSys, "/pad", nPAD); ficlSetEnv(pSys, "address-unit-bits", 8); ficlSetEnv(pSys, "core", FICL_TRUE); ficlSetEnv(pSys, "core-ext", FICL_FALSE); ficlSetEnv(pSys, "floored", FICL_FALSE); ficlSetEnv(pSys, "max-char", UCHAR_MAX); ficlSetEnvD(pSys,"max-d", 0x7fffffff, 0xffffffff); ficlSetEnv(pSys, "max-n", 0x7fffffff); ficlSetEnv(pSys, "max-u", 0xffffffff); ficlSetEnvD(pSys,"max-ud", 0xffffffff, 0xffffffff); ficlSetEnv(pSys, "return-stack-cells",FICL_DEFAULT_STACK); ficlSetEnv(pSys, "stack-cells", FICL_DEFAULT_STACK); /* ** DOUBLE word set (partial) */ dictAppendWord(dp, "2constant", twoConstant, FW_IMMEDIATE); dictAppendWord(dp, "2literal", twoLiteralIm, FW_IMMEDIATE); dictAppendWord(dp, "2variable", twoVariable, FW_IMMEDIATE); dictAppendWord(dp, "dnegate", dnegate, FW_DEFAULT); /* ** EXCEPTION word set */ dictAppendWord(dp, "catch", ficlCatch, FW_DEFAULT); dictAppendWord(dp, "throw", ficlThrow, FW_DEFAULT); ficlSetEnv(pSys, "exception", FICL_TRUE); ficlSetEnv(pSys, "exception-ext", FICL_TRUE); /* ** LOCAL and LOCAL EXT ** see softcore.c for implementation of locals| */ #if FICL_WANT_LOCALS pSys->pLinkParen = dictAppendWord(dp, "(link)", linkParen, FW_COMPILE); pSys->pUnLinkParen = dictAppendWord(dp, "(unlink)", unlinkParen, FW_COMPILE); dictAppendWord(dp, "doLocal", doLocalIm, FW_COMPIMMED); pSys->pGetLocalParen = dictAppendWord(dp, "(@local)", getLocalParen, FW_COMPILE); pSys->pToLocalParen = dictAppendWord(dp, "(toLocal)", toLocalParen, FW_COMPILE); pSys->pGetLocal0 = dictAppendWord(dp, "(@local0)", getLocal0, FW_COMPILE); pSys->pToLocal0 = dictAppendWord(dp, "(toLocal0)",toLocal0, FW_COMPILE); pSys->pGetLocal1 = dictAppendWord(dp, "(@local1)", getLocal1, FW_COMPILE); pSys->pToLocal1 = dictAppendWord(dp, "(toLocal1)",toLocal1, FW_COMPILE); dictAppendWord(dp, "(local)", localParen, FW_COMPILE); pSys->pGet2LocalParen = dictAppendWord(dp, "(@2local)", get2LocalParen, FW_COMPILE); pSys->pTo2LocalParen = dictAppendWord(dp, "(to2Local)",to2LocalParen, FW_COMPILE); dictAppendWord(dp, "(2local)", twoLocalParen, FW_COMPILE); ficlSetEnv(pSys, "locals", FICL_TRUE); ficlSetEnv(pSys, "locals-ext", FICL_TRUE); ficlSetEnv(pSys, "#locals", FICL_MAX_LOCALS); #endif /* ** Optional MEMORY-ALLOC word set */ dictAppendWord(dp, "allocate", ansAllocate, FW_DEFAULT); dictAppendWord(dp, "free", ansFree, FW_DEFAULT); dictAppendWord(dp, "resize", ansResize, FW_DEFAULT); ficlSetEnv(pSys, "memory-alloc", FICL_TRUE); /* ** optional SEARCH-ORDER word set */ ficlCompileSearch(pSys); /* ** TOOLS and TOOLS EXT */ ficlCompileTools(pSys); /* ** FILE and FILE EXT */ #if FICL_WANT_FILE ficlCompileFile(pSys); #endif /* ** Ficl extras */ #if FICL_WANT_FLOAT dictAppendWord(dp, ".hash", dictHashSummary,FW_DEFAULT); #endif dictAppendWord(dp, ".ver", ficlVersion, FW_DEFAULT); dictAppendWord(dp, "-roll", minusRoll, FW_DEFAULT); dictAppendWord(dp, ">name", toName, FW_DEFAULT); dictAppendWord(dp, "add-parse-step", addParseStep, FW_DEFAULT); dictAppendWord(dp, "body>", fromBody, FW_DEFAULT); dictAppendWord(dp, "compare", compareString, FW_DEFAULT); /* STRING */ dictAppendWord(dp, "compare-insensitive", compareStringInsensitive, FW_DEFAULT); /* STRING */ dictAppendWord(dp, "compile-only", compileOnly, FW_DEFAULT); dictAppendWord(dp, "endif", endifCoIm, FW_COMPIMMED); dictAppendWord(dp, "last-word", getLastWord, FW_DEFAULT); dictAppendWord(dp, "hash", hash, FW_DEFAULT); dictAppendWord(dp, "objectify", setObjectFlag, FW_DEFAULT); dictAppendWord(dp, "?object", isObject, FW_DEFAULT); dictAppendWord(dp, "parse-word",parseNoCopy, FW_DEFAULT); dictAppendWord(dp, "sfind", sFind, FW_DEFAULT); dictAppendWord(dp, "sliteral", sLiteralCoIm, FW_COMPIMMED); /* STRING */ dictAppendWord(dp, "sprintf", ficlSprintf, FW_DEFAULT); dictAppendWord(dp, "strlen", ficlStrlen, FW_DEFAULT); dictAppendWord(dp, "q@", quadFetch, FW_DEFAULT); dictAppendWord(dp, "q!", quadStore, FW_DEFAULT); dictAppendWord(dp, "w@", wFetch, FW_DEFAULT); dictAppendWord(dp, "w!", wStore, FW_DEFAULT); dictAppendWord(dp, "x.", hexDot, FW_DEFAULT); #if FICL_WANT_USER dictAppendWord(dp, "(user)", userParen, FW_DEFAULT); dictAppendWord(dp, "user", userVariable, FW_DEFAULT); #endif #ifdef TESTMAIN dictAppendWord(dp, "random", ficlRandom, FW_DEFAULT); dictAppendWord(dp, "seed-random",ficlSeedRandom,FW_DEFAULT); #endif /* ** internal support words */ dictAppendWord(dp, "(create)", createParen, FW_COMPILE); pSys->pExitParen = dictAppendWord(dp, "(exit)", exitParen, FW_COMPILE); pSys->pSemiParen = dictAppendWord(dp, "(;)", semiParen, FW_COMPILE); pSys->pLitParen = dictAppendWord(dp, "(literal)", literalParen, FW_COMPILE); pSys->pTwoLitParen = dictAppendWord(dp, "(2literal)",twoLitParen, FW_COMPILE); pSys->pStringLit = dictAppendWord(dp, "(.\")", stringLit, FW_COMPILE); pSys->pCStringLit = dictAppendWord(dp, "(c\")", cstringLit, FW_COMPILE); pSys->pBranch0 = dictAppendWord(dp, "(branch0)", branch0, FW_COMPILE); pSys->pBranchParen = dictAppendWord(dp, "(branch)", branchParen, FW_COMPILE); pSys->pDoParen = dictAppendWord(dp, "(do)", doParen, FW_COMPILE); pSys->pDoesParen = dictAppendWord(dp, "(does>)", doesParen, FW_COMPILE); pSys->pQDoParen = dictAppendWord(dp, "(?do)", qDoParen, FW_COMPILE); pSys->pLoopParen = dictAppendWord(dp, "(loop)", loopParen, FW_COMPILE); pSys->pPLoopParen = dictAppendWord(dp, "(+loop)", plusLoopParen, FW_COMPILE); pSys->pInterpret = dictAppendWord(dp, "interpret", interpret, FW_DEFAULT); dictAppendWord(dp, "lookup", lookup, FW_DEFAULT); pSys->pOfParen = dictAppendWord(dp, "(of)", ofParen, FW_DEFAULT); dictAppendWord(dp, "(variable)",variableParen, FW_COMPILE); dictAppendWord(dp, "(constant)",constantParen, FW_COMPILE); dictAppendWord(dp, "(parse-step)", parseStepParen, FW_DEFAULT); pSys->pExitInner = dictAppendWord(dp, "exit-inner",ficlExitInner, FW_DEFAULT); /* ** Set up system's outer interpreter loop - maybe this should be in initSystem? */ pSys->pInterp[0] = pSys->pInterpret; pSys->pInterp[1] = pSys->pBranchParen; pSys->pInterp[2] = (FICL_WORD *)(void *)(-2); assert(dictCellsAvail(dp) > 0); return; } Index: stable/10/sys/boot/ficl32/Makefile =================================================================== --- stable/10/sys/boot/ficl32/Makefile (nonexistent) +++ stable/10/sys/boot/ficl32/Makefile (revision 271135) @@ -0,0 +1,8 @@ +# $FreeBSD$ + +FICL32= +FICLDIR= ${.CURDIR}/../ficl + +.PATH: ${FICLDIR} + +.include "${FICLDIR}/Makefile" Property changes on: stable/10/sys/boot/ficl32/Makefile ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/10/sys/boot/forth/beastie.4th =================================================================== --- stable/10/sys/boot/forth/beastie.4th (revision 271134) +++ stable/10/sys/boot/forth/beastie.4th (revision 271135) @@ -1,270 +1,275 @@ \ Copyright (c) 2003 Scott Long \ Copyright (c) 2003 Aleksander Fafula \ Copyright (c) 2006-2013 Devin Teske \ All rights reserved. \ \ Redistribution and use in source and binary forms, with or without \ modification, are permitted provided that the following conditions \ are met: \ 1. Redistributions of source code must retain the above copyright \ notice, this list of conditions and the following disclaimer. \ 2. Redistributions in binary form must reproduce the above copyright \ notice, this list of conditions and the following disclaimer in the \ documentation and/or other materials provided with the distribution. \ \ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND \ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE \ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE \ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE \ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL \ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS \ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) \ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT \ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY \ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF \ SUCH DAMAGE. \ \ $FreeBSD$ marker task-beastie.4th only forth definitions also support-functions variable logoX variable logoY \ Initialize logo placement to defaults 46 logoX ! 4 logoY ! : beastie-logo ( x y -- ) \ color BSD mascot (19 rows x 34 columns) 2dup at-xy ." , ," 1+ 2dup at-xy ." /( )`" 1+ 2dup at-xy ." \ \___ / |" 1+ 2dup at-xy ." /- _ `-/ '" 1+ 2dup at-xy ." (/\/ \ \ /\" 1+ 2dup at-xy ." / / | ` \" 1+ 2dup at-xy ." O O ) / |" 1+ 2dup at-xy ." `-^--'`< '" 1+ 2dup at-xy ." (_.) _ ) /" 1+ 2dup at-xy ." `.___/` /" 1+ 2dup at-xy ." `-----' /" 1+ 2dup at-xy ." <----. __ / __ \" 1+ 2dup at-xy ." <----|====O)))==) \) /====|" 1+ 2dup at-xy ." <----' `--' `.__,' \" 1+ 2dup at-xy ." | |" 1+ 2dup at-xy ." \ / /\" 1+ 2dup at-xy ." ______( (_ / \______/" 1+ 2dup at-xy ." ,' ,-----' |" 1+ at-xy ." `--{__________)" \ Put the cursor back at the bottom 0 25 at-xy ; : beastiebw-logo ( x y -- ) \ B/W BSD mascot (19 rows x 34 columns) 2dup at-xy ." , ," 1+ 2dup at-xy ." /( )`" 1+ 2dup at-xy ." \ \___ / |" 1+ 2dup at-xy ." /- _ `-/ '" 1+ 2dup at-xy ." (/\/ \ \ /\" 1+ 2dup at-xy ." / / | ` \" 1+ 2dup at-xy ." O O ) / |" 1+ 2dup at-xy ." `-^--'`< '" 1+ 2dup at-xy ." (_.) _ ) /" 1+ 2dup at-xy ." `.___/` /" 1+ 2dup at-xy ." `-----' /" 1+ 2dup at-xy ." <----. __ / __ \" 1+ 2dup at-xy ." <----|====O)))==) \) /====|" 1+ 2dup at-xy ." <----' `--' `.__,' \" 1+ 2dup at-xy ." | |" 1+ 2dup at-xy ." \ / /\" 1+ 2dup at-xy ." ______( (_ / \______/" 1+ 2dup at-xy ." ,' ,-----' |" 1+ at-xy ." `--{__________)" \ Put the cursor back at the bottom 0 25 at-xy ; : fbsdbw-logo ( x y -- ) \ "FreeBSD" logo in B/W (13 rows x 21 columns) \ We used to use the beastie himself as our default... until the \ eventual complaint derided his reign of the advanced boot-menu. \ \ This is the replacement of beastie to satiate the haters of our \ beloved helper-daemon (ready to track down and spear bugs with \ his trident and sporty sneakers; see above). \ \ Since we merely just changed the default and not the default- \ location, below is an adjustment to the passed-in coordinates, \ forever influenced by the proper location of beastie himself \ kept as the default loader_logo_x/loader_logo_y values. \ 5 + swap 6 + swap 2dup at-xy ." ______" 1+ 2dup at-xy ." | ____| __ ___ ___ " 1+ 2dup at-xy ." | |__ | '__/ _ \/ _ \" 1+ 2dup at-xy ." | __|| | | __/ __/" 1+ 2dup at-xy ." | | | | | | |" 1+ 2dup at-xy ." |_| |_| \___|\___|" 1+ 2dup at-xy ." ____ _____ _____" 1+ 2dup at-xy ." | _ \ / ____| __ \" 1+ 2dup at-xy ." | |_) | (___ | | | |" 1+ 2dup at-xy ." | _ < \___ \| | | |" 1+ 2dup at-xy ." | |_) |____) | |__| |" 1+ 2dup at-xy ." | | | |" 1+ at-xy ." |____/|_____/|_____/" \ Put the cursor back at the bottom 0 25 at-xy ; : orb-logo ( x y -- ) \ color Orb mascot (15 rows x 30 columns) 3 + \ beastie adjustment (see `fbsdbw-logo' comments above) 2dup at-xy ." ``` `" 1+ 2dup at-xy ." s` `.....---.......--.``` -/" 1+ 2dup at-xy ." +o .--` /y:` +." 1+ 2dup at-xy ." yo`:. :o `+-" 1+ 2dup at-xy ." y/ -/` -o/" 1+ 2dup at-xy ." .- ::/sy+:." 1+ 2dup at-xy ." / `-- /" 1+ 2dup at-xy ." `: :`" 1+ 2dup at-xy ." `: :`" 1+ 2dup at-xy ." / /" 1+ 2dup at-xy ." .- -." 1+ 2dup at-xy ." -- -." 1+ 2dup at-xy ." `:` `:`" 1+ 2dup at-xy ." .-- `--." 1+ at-xy ." .---.....----." \ Put the cursor back at the bottom 0 25 at-xy ; : orbbw-logo ( x y -- ) \ B/W Orb mascot (15 rows x 32 columns) 3 + \ beastie adjustment (see `fbsdbw-logo' comments above) 2dup at-xy ." ``` `" 1+ 2dup at-xy ." s` `.....---.......--.``` -/" 1+ 2dup at-xy ." +o .--` /y:` +." 1+ 2dup at-xy ." yo`:. :o `+-" 1+ 2dup at-xy ." y/ -/` -o/" 1+ 2dup at-xy ." .- ::/sy+:." 1+ 2dup at-xy ." / `-- /" 1+ 2dup at-xy ." `: :`" 1+ 2dup at-xy ." `: :`" 1+ 2dup at-xy ." / /" 1+ 2dup at-xy ." .- -." 1+ 2dup at-xy ." -- -." 1+ 2dup at-xy ." `:` `:`" 1+ 2dup at-xy ." .-- `--." 1+ at-xy ." .---.....----." \ Put the cursor back at the bottom 0 25 at-xy ; \ This function draws any number of beastie logos at (loader_logo_x, \ loader_logo_y) if defined, else (46,4) (to the right of the menu). To choose \ your beastie, set the variable `loader_logo' to the respective logo name. \ \ Currently available: \ \ NAME DESCRIPTION \ beastie Color ``Helper Daemon'' mascot (19 rows x 34 columns) \ beastiebw B/W ``Helper Daemon'' mascot (19 rows x 34 columns) \ fbsdbw "FreeBSD" logo in B/W (13 rows x 21 columns) \ orb Color ``Orb'' mascot (15 rows x 30 columns) (2nd default) \ orbbw B/W ``Orb'' mascot (15 rows x 32 columns) \ tribute Color ``Tribute'' (must fit 19 rows x 34 columns) (default) \ tributebw B/W ``Tribute'' (must fit 19 rows x 34 columns) \ \ NOTE: Setting `loader_logo' to an undefined value (such as "none") will \ prevent beastie from being drawn. \ : draw-beastie ( -- ) \ at (loader_logo_x,loader_logo_y), else (46,4) s" loader_logo_x" getenv dup -1 <> if ?number 1 = if logoX ! then else drop then s" loader_logo_y" getenv dup -1 <> if ?number 1 = if logoY ! then else drop then s" loader_logo" getenv dup -1 <> if dup 5 + allocate if ENOMEM throw then 0 2swap strcat s" -logo" strcat over -rot ( a-addr/u -- a-addr a-addr/u ) sfind ( a-addr a-addr/u -- a-addr xt bool ) rot ( a-addr xt bool -- xt bool a-addr ) free ( xt bool a-addr -- xt bool ior ) if EFREE throw then else 0 ( cruft -- cruft bool ) \ load the default below then 0= if drop ( cruft -- ) loader_color? if ['] orb-logo else ['] orbbw-logo then then logoX @ logoY @ rot execute ; : clear-beastie ( -- ) \ clears beastie from the screen logoX @ logoY @ 2dup at-xy 34 spaces 1+ 2dup at-xy 34 spaces 1+ 2dup at-xy 34 spaces 1+ 2dup at-xy 34 spaces 1+ 2dup at-xy 34 spaces 1+ 2dup at-xy 34 spaces 1+ 2dup at-xy 34 spaces 1+ 2dup at-xy 34 spaces 1+ 2dup at-xy 34 spaces 1+ 2dup at-xy 34 spaces 1+ 2dup at-xy 34 spaces 1+ 2dup at-xy 34 spaces 1+ 2dup at-xy 34 spaces 1+ 2dup at-xy 34 spaces 1+ 2dup at-xy 34 spaces 1+ 2dup at-xy 34 spaces 1+ 2dup at-xy 34 spaces 1+ 2dup at-xy 34 spaces 1+ 2dup at-xy 34 spaces 2drop \ Put the cursor back at the bottom 0 25 at-xy ; : beastie-start ( -- ) \ starts the menu + s" console" getenv dup -1 <> if + s" efi" 2swap contains? if + s" set beastie_disable=YES" evaluate + then + else drop then s" beastie_disable" getenv dup -1 <> if s" YES" compare-insensitive 0= if any_conf_read? if load_kernel load_modules then exit \ to autoboot (default) then else drop then s" loader_delay" getenv -1 = if s" include /boot/menu.rc" evaluate else drop ." Loading Menu (Ctrl-C to Abort)" cr s" set delay_command='include /boot/menu.rc'" evaluate s" set delay_showdots" evaluate delay_execute then ; only forth also Index: stable/10/sys/boot/forth/beastie.4th.8 =================================================================== --- stable/10/sys/boot/forth/beastie.4th.8 (revision 271134) +++ stable/10/sys/boot/forth/beastie.4th.8 (revision 271135) @@ -1,172 +1,174 @@ .\" Copyright (c) 2011-2012 Devin Teske .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" $FreeBSD$ .\" -.Dd May 16, 2011 +.Dd April 27, 2014 .Dt BEASTIE.4TH 8 .Os .Sh NAME .Nm beastie.4th .Nd FreeBSD ASCII art boot module .Sh DESCRIPTION The file that goes by the name of .Nm is a set of commands designed to draw the ASCII art FreeBSD mascot .Nd known simply as .Ic beastie .Nd to the right of the boot loader menu. The commands of .Nm by themselves are not enough for most uses. Please refer to the examples below for the most common situations, and to .Xr loader 8 for additional commands. .Pp Before using any of the commands provided in .Nm , it must be included through the command: .Pp .Dl include beastie.4th .Pp This line is present in the default .Pa /boot/loader.rc file, so it is not needed (and should not be re-issued) in a normal setup. .Pp The commands provided by it are: .Pp .Bl -tag -width disable-module_module -compact -offset indent .It Ic draw-beastie Draws the FreeBSD logo. .Pp The logo that is drawn is configured by setting the .Ic loader_logo variable in .Xr loader.conf 5 to one of .Dq Li beastie , .Dq Li beastiebw , .Dq Li fbsdbw , .Dq Li orb , and .Dq Li orbbw (the default). .Pp The position of the logo can be configured by setting the .Ic loader_logo_x and .Ic loader_logo_y variables in .Xr loader.conf 5 . The default values are 46 (x) and 4 (y). .Pp .It Ic clear-beastie Clears the screen of beastie. .Pp .It Ic beastie-start Initializes the interactive boot loader menu. .Pp The .Ic loader_delay variable can be configured in .Xr loader.conf 5 to the number of seconds you would like to delay loading the boot menu. During the delay the user can press Ctrl-C to fall back to .Ic autoboot or ENTER to proceed. The default behavior is to not delay. .El .Pp The environment variables that effect its behavior are: .Bl -tag -width bootfile -offset indent .It Va loader_logo Selects the desired logo in the beastie boot menu. Possible values are: .Dq Li fbsdbw , .Dq Li beastie , .Dq Li beastiebw , .Dq Li orb , .Dq Li orbbw (default), and .Dq Li none . .It Va loader_logo_x Sets the desired column position of the logo. Default is 46. .It Va loader_logo_y Sets the desired row position of the logo. Default is 4. .It Va beastie_disable If set to .Dq YES , the beastie boot menu will be skipped. +The beastie boot menu is always skipped if booting UEFI or running non-x86 +hardware. .It Va loader_delay If set to a number higher than zero, introduces a delay before starting the beastie boot menu. During the delay the user can press either Ctrl-C to skip the menu or ENTER to proceed to the menu. The default is to not delay when loading the menu. .El .Sh FILES .Bl -tag -width /boot/loader.4th -compact .It Pa /boot/loader The .Xr loader 8 . .It Pa /boot/beastie.4th .Nm itself. .It Pa /boot/loader.rc .Xr loader 8 bootstrapping script. .El .Sh EXAMPLES Standard i386 .Pa /boot/loader.rc : .Pp .Bd -literal -offset indent -compact include /boot/beastie.4th beastie-start .Ed .Pp Set a different logo in .Xr loader.conf 5 : .Pp .Bd -literal -offset indent -compact loader_logo="beastie" .Ed .Sh SEE ALSO .Xr loader.conf 5 , .Xr loader 8 , .Xr loader.4th 8 .Sh HISTORY The .Nm set of commands first appeared in .Fx 5.1 . .Sh AUTHORS The .Nm set of commands was written by .An -nosplit .An Scott Long Aq scottl@FreeBSD.org , .An Aleksander Fafula Aq alex@fafula.com and .An Devin Teske Aq dteske@FreeBSD.org . Index: stable/10/sys/boot/forth/loader.conf.5 =================================================================== --- stable/10/sys/boot/forth/loader.conf.5 (revision 271134) +++ stable/10/sys/boot/forth/loader.conf.5 (revision 271135) @@ -1,290 +1,292 @@ .\" Copyright (c) 1999 Daniel C. Sobral .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" $FreeBSD$ -.Dd October 18, 2013 +.Dd April 27, 2014 .Dt LOADER.CONF 5 .Os .Sh NAME .Nm loader.conf .Nd "system bootstrap configuration information" .Sh DESCRIPTION The file .Nm contains descriptive information on bootstrapping the system. Through it you can specify the kernel to be booted, parameters to be passed to it, and additional modules to be loaded; and generally set all variables described in .Xr loader 8 . .Pp The file .Pa /boot/loader.rc must contain the following two lines for .Nm to be automatically processed: .Pp .Dl include /boot/loader.4th .Dl start .Pp If no .Pa /boot/loader.rc exists at installworld time, one with the above lines will be installed. .Sh SYNTAX Though .Nm Ns 's format was defined explicitly to resemble .Xr rc.conf 5 , and can be sourced by .Xr sh 1 , some settings are treated in a special fashion. Also, the behavior of some settings is defined by the setting's suffix; the prefix identifies which module the setting controls. .Pp The general parsing rules are: .Bl -bullet .It Spaces and empty lines are ignored. .It A # sign will mark the remainder of the line as a comment. .It Only one setting can be present on each line. .El .Pp All settings have the following format: .Pp .Dl variable="value" .Pp Unless it belongs to one of the classes of settings that receive special treatment, a setting will set the value of a .Xr loader 8 environment variable. The settings that receive special treatment are listed below. Settings beginning with .Qq * below define the modules to be loaded and may have any prefix; the prefix identifies a module. All such settings sharing a common prefix refer to the same module. .Bl -tag -width Ar .It Ar exec Immediately executes a .Xr loader 8 command. This type of setting cannot be processed by programs other than .Xr loader 8 , so its use should be avoided. Multiple instances of it will be processed independently. .It Ar loader_conf_files Defines additional configuration files to be processed right after the present file. .It Ar kernel Name of the kernel to be loaded. If no kernel name is set, no additional modules will be loaded. The name must be a subdirectory of .Pa /boot that contains a kernel. .It Ar kernel_options Flags to be passed to the kernel. .It Ar password Protect boot menu with a password without interrupting .Ic autoboot process. The password should be in clear text format. If a password is set, boot menu will not appear until any key is pressed during countdown period specified by .Va autoboot_delay variable or .Ic autoboot process fails. In both cases user should provide specified password to be able to access boot menu. .It Ar bootlock_password Provides a password to be required by check-password before execution is allowed to continue. The password should be in clear text format. If a password is set, the user must provide specified password to boot. .It Ar verbose_loading If set to .Dq YES , module names will be displayed as they are loaded. .It Ar *_load If set to .Dq YES , that module will be loaded. If no name is defined (see below), the module's name is taken to be the same as the prefix. .It Ar *_name Defines the name of the module. .It Ar *_type Defines the module's type. If none is given, it defaults to a kld module. .It Ar *_flags Flags and parameters to be passed to the module. .It Ar *_before Commands to be executed before the module is loaded. Use of this setting should be avoided. .It Ar *_after Commands to be executed after the module is loaded. Use of this setting should be avoided. .It Ar *_error Commands to be executed if the loading of a module fails. Except for the special value .Dq abort , which aborts the bootstrap process, use of this setting should be avoided. .El .Pp .Em WARNING: developers should never use these suffixes for any kernel environment variables (tunables) or conflicts will result. .Sh DEFAULT SETTINGS Most of .Nm Ns 's default settings can be ignored. The few of them which are important or useful are: .Bl -tag -width bootfile -offset indent .It Va bitmap_load .Pq Dq NO If set to .Dq YES , a bitmap will be loaded to be displayed on screen while booting. .It Va bitmap_name .Pq Dq Pa /boot/splash.bmp Name of the bitmap to be loaded. Any other name can be used. .It Va comconsole_speed .Dq ( 9600 or the value of the .Va BOOT_COMCONSOLE_SPEED variable when .Xr loader 8 was compiled). Sets the speed of the serial console. If the previous boot loader stage specified that a serial console is in use then the default speed is determined from the current serial port speed setting. .It Va console .Pq Dq vidconsole .Dq comconsole selects serial console, .Dq vidconsole selects the video console, .Dq nullconsole selects a mute console (useful for systems with neither a video console nor a serial port), and .Dq spinconsole selects the video console which prevents any input and hides all output replacing it with .Dq spinning character (useful for embedded products and such). .It Va kernel .Pq Dq kernel .It Va kernels .Pq Dq kernel kernel.old Space or comma separated list of kernels to present in the boot menu. .It Va loader_conf_files .Pq Dq Pa /boot/loader.conf /boot/loader.conf.local .It Va splash_bmp_load .Pq Dq NO If set to .Dq YES , will load the splash screen module, making it possible to display a bmp image on the screen while booting. .It Va splash_pcx_load .Pq Dq NO If set to .Dq YES , will load the splash screen module, making it possible to display a pcx image on the screen while booting. .It Va vesa_load .Pq Dq NO If set to .Dq YES , the vesa module will be loaded, enabling bitmaps above VGA resolution to be displayed. .It Va beastie_disable If set to .Dq YES , the beastie boot menu will be skipped. +The beastie boot menu is always skipped if booting UEFI or running non-x86 +hardware. .It Va loader_logo Pq Dq Li orbbw Selects a desired logo in the beastie boot menu. Possible values are: .Dq Li orbbw , .Dq Li orb , .Dq Li fbsdbw , .Dq Li beastiebw , .Dq Li beastie , and .Dq Li none . .It Va loader_color If set to .Dq NO , the beastie boot menu will be displayed without ANSI coloring. .El .Sh FILES .Bl -tag -width /boot/defaults/loader.conf -compact .It Pa /boot/defaults/loader.conf default settings -- do not change this file. .It Pa /boot/loader.4th defines the commands used by loader to read and process .Nm . .It Pa /boot/loader.conf user defined settings. .It Pa /boot/loader.conf.local machine-specific settings for sites with a common loader.conf. .It Pa /boot/loader.rc contains the instructions to automatically process .Nm . .El .Sh SEE ALSO .Xr boot 8 , .Xr loader 8 , .Xr loader.4th 8 .Sh HISTORY The file .Nm first appeared in .Fx 3.2 . .Sh AUTHORS This manual page was written by .An Daniel C. Sobral Aq dcs@FreeBSD.org . .Sh BUGS The .Xr loader 8 stops reading .Nm when it encounters a syntax error, so any options which are vital for booting a particular system (i.e.\& .Dq Va hw.ata.ata_dma Ns "=0" ) should precede any experimental additions to .Nm . Index: stable/10/sys/boot/i386/efi/main.c =================================================================== --- stable/10/sys/boot/i386/efi/main.c (revision 271134) +++ stable/10/sys/boot/i386/efi/main.c (nonexistent) @@ -1,371 +0,0 @@ -/*- - * Copyright (c) 2008-2010 Rui Paulo - * Copyright (c) 2006 Marcel Moolenaar - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include - -#include -#include - -#include -#include "../libi386/libi386.h" - -extern char bootprog_name[]; -extern char bootprog_rev[]; -extern char bootprog_date[]; -extern char bootprog_maker[]; - -struct devdesc currdev; /* our current device */ -struct arch_switch archsw; /* MI/MD interface boundary */ - -EFI_GUID acpi = ACPI_TABLE_GUID; -EFI_GUID acpi20 = ACPI_20_TABLE_GUID; -EFI_GUID devid = DEVICE_PATH_PROTOCOL; -EFI_GUID imgid = LOADED_IMAGE_PROTOCOL; -EFI_GUID mps = MPS_TABLE_GUID; -EFI_GUID netid = EFI_SIMPLE_NETWORK_PROTOCOL; -EFI_GUID smbios = SMBIOS_TABLE_GUID; - -EFI_STATUS -main(int argc, CHAR16 *argv[]) -{ - char vendor[128]; - EFI_LOADED_IMAGE *img; - int i; - - /* - * XXX Chicken-and-egg problem; we want to have console output - * early, but some console attributes may depend on reading from - * eg. the boot device, which we can't do yet. We can use - * printf() etc. once this is done. - */ - cons_probe(); - - /* - * March through the device switch probing for things. - */ - for (i = 0; devsw[i] != NULL; i++) - if (devsw[i]->dv_init != NULL) - (devsw[i]->dv_init)(); - - /* Get our loaded image protocol interface structure. */ - BS->HandleProtocol(IH, &imgid, (VOID**)&img); - - printf("Image base: 0x%lx\n", (u_long)img->ImageBase); - printf("EFI version: %d.%02d\n", ST->Hdr.Revision >> 16, - ST->Hdr.Revision & 0xffff); - printf("EFI Firmware: "); - /* printf doesn't understand EFI Unicode */ - ST->ConOut->OutputString(ST->ConOut, ST->FirmwareVendor); - printf(" (rev %d.%02d)\n", ST->FirmwareRevision >> 16, - ST->FirmwareRevision & 0xffff); - - printf("\n"); - printf("%s, Revision %s\n", bootprog_name, bootprog_rev); - printf("(%s, %s)\n", bootprog_maker, bootprog_date); - - efi_handle_lookup(img->DeviceHandle, &currdev.d_dev, &currdev.d_unit); - currdev.d_type = currdev.d_dev->dv_type; - - /* - * Disable the watchdog timer. By default the boot manager sets - * the timer to 5 minutes before invoking a boot option. If we - * want to return to the boot manager, we have to disable the - * watchdog timer and since we're an interactive program, we don't - * want to wait until the user types "quit". The timer may have - * fired by then. We don't care if this fails. It does not prevent - * normal functioning in any way... - */ - BS->SetWatchdogTimer(0, 0, 0, NULL); - - env_setenv("currdev", EV_VOLATILE, i386_fmtdev(&currdev), - i386_setcurrdev, env_nounset); - env_setenv("loaddev", EV_VOLATILE, i386_fmtdev(&currdev), env_noset, - env_nounset); - - setenv("LINES", "24", 1); /* optional */ - - archsw.arch_autoload = i386_autoload; - archsw.arch_getdev = i386_getdev; - archsw.arch_copyin = i386_copyin; - archsw.arch_copyout = i386_copyout; - archsw.arch_readin = i386_readin; - - interact(); /* doesn't return */ - - return (EFI_SUCCESS); /* keep compiler happy */ -} - -COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot); - -static int -command_reboot(int argc, char *argv[]) -{ - int i; - - for (i = 0; devsw[i] != NULL; ++i) - if (devsw[i]->dv_cleanup != NULL) - (devsw[i]->dv_cleanup)(); - - RS->ResetSystem(EfiResetCold, EFI_SUCCESS, 23, - (CHAR16 *)"Reboot from the loader"); - - /* NOTREACHED */ - return (CMD_ERROR); -} - -COMMAND_SET(quit, "quit", "exit the loader", command_quit); - -static int -command_quit(int argc, char *argv[]) -{ - exit(0); - return (CMD_OK); -} - -COMMAND_SET(memmap, "memmap", "print memory map", command_memmap); - -static int -command_memmap(int argc, char *argv[]) -{ - UINTN sz; - EFI_MEMORY_DESCRIPTOR *map, *p; - UINTN key, dsz; - UINT32 dver; - EFI_STATUS status; - int i, ndesc; - static char *types[] = { - "Reserved", - "LoaderCode", - "LoaderData", - "BootServicesCode", - "BootServicesData", - "RuntimeServicesCode", - "RuntimeServicesData", - "ConventionalMemory", - "UnusableMemory", - "ACPIReclaimMemory", - "ACPIMemoryNVS", - "MemoryMappedIO", - "MemoryMappedIOPortSpace", - "PalCode" - }; - - sz = 0; - status = BS->GetMemoryMap(&sz, 0, &key, &dsz, &dver); - if (status != EFI_BUFFER_TOO_SMALL) { - printf("Can't determine memory map size\n"); - return CMD_ERROR; - } - map = malloc(sz); - status = BS->GetMemoryMap(&sz, map, &key, &dsz, &dver); - if (EFI_ERROR(status)) { - printf("Can't read memory map\n"); - return CMD_ERROR; - } - - ndesc = sz / dsz; - printf("%23s %12s %12s %8s %4s\n", - "Type", "Physical", "Virtual", "#Pages", "Attr"); - - for (i = 0, p = map; i < ndesc; - i++, p = NextMemoryDescriptor(p, dsz)) { - printf("%23s %012lx %012lx %08lx ", - types[p->Type], - p->PhysicalStart, - p->VirtualStart, - p->NumberOfPages); - if (p->Attribute & EFI_MEMORY_UC) - printf("UC "); - if (p->Attribute & EFI_MEMORY_WC) - printf("WC "); - if (p->Attribute & EFI_MEMORY_WT) - printf("WT "); - if (p->Attribute & EFI_MEMORY_WB) - printf("WB "); - if (p->Attribute & EFI_MEMORY_UCE) - printf("UCE "); - if (p->Attribute & EFI_MEMORY_WP) - printf("WP "); - if (p->Attribute & EFI_MEMORY_RP) - printf("RP "); - if (p->Attribute & EFI_MEMORY_XP) - printf("XP "); - printf("\n"); - } - - return CMD_OK; -} - -COMMAND_SET(configuration, "configuration", - "print configuration tables", command_configuration); - -static const char * -guid_to_string(EFI_GUID *guid) -{ - static char buf[40]; - - sprintf(buf, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", - guid->Data1, guid->Data2, guid->Data3, guid->Data4[0], - guid->Data4[1], guid->Data4[2], guid->Data4[3], guid->Data4[4], - guid->Data4[5], guid->Data4[6], guid->Data4[7]); - return (buf); -} - -static int -command_configuration(int argc, char *argv[]) -{ - int i; - - printf("NumberOfTableEntries=%ld\n", ST->NumberOfTableEntries); - for (i = 0; i < ST->NumberOfTableEntries; i++) { - EFI_GUID *guid; - - printf(" "); - guid = &ST->ConfigurationTable[i].VendorGuid; - if (!memcmp(guid, &mps, sizeof(EFI_GUID))) - printf("MPS Table"); - else if (!memcmp(guid, &acpi, sizeof(EFI_GUID))) - printf("ACPI Table"); - else if (!memcmp(guid, &acpi20, sizeof(EFI_GUID))) - printf("ACPI 2.0 Table"); - else if (!memcmp(guid, &smbios, sizeof(EFI_GUID))) - printf("SMBIOS Table"); - else - printf("Unknown Table (%s)", guid_to_string(guid)); - printf(" at %p\n", ST->ConfigurationTable[i].VendorTable); - } - - return CMD_OK; -} - - -COMMAND_SET(mode, "mode", "change or display text modes", command_mode); - -static int -command_mode(int argc, char *argv[]) -{ - unsigned int cols, rows, mode; - int i; - char *cp; - char rowenv[8]; - EFI_STATUS status; - SIMPLE_TEXT_OUTPUT_INTERFACE *conout; - - conout = ST->ConOut; - - if (argc > 1) { - mode = strtol(argv[1], &cp, 0); - if (cp[0] != '\0') { - printf("Invalid mode\n"); - return (CMD_ERROR); - } - status = conout->QueryMode(conout, mode, &cols, &rows); - if (EFI_ERROR(status)) { - printf("invalid mode %d\n", mode); - return (CMD_ERROR); - } - status = conout->SetMode(conout, mode); - if (EFI_ERROR(status)) { - printf("couldn't set mode %d\n", mode); - return (CMD_ERROR); - } - sprintf(rowenv, "%d", rows); - setenv("LINES", rowenv, 1); - - return (CMD_OK); - } - - for (i = 0; ; i++) { - status = conout->QueryMode(conout, i, &cols, &rows); - if (EFI_ERROR(status)) - break; - printf("Mode %d: %d columns, %d rows\n", i, cols, rows); - } - - if (i != 0) - printf("Choose the mode with \"col \"\n"); - - return (CMD_OK); -} - - -COMMAND_SET(nvram, "nvram", "get or set NVRAM variables", command_nvram); - -static int -command_nvram(int argc, char *argv[]) -{ - CHAR16 var[128]; - CHAR16 *data; - EFI_STATUS status; - EFI_GUID varguid = { 0,0,0,{0,0,0,0,0,0,0,0} }; - unsigned int varsz; - unsigned int datasz; - SIMPLE_TEXT_OUTPUT_INTERFACE *conout; - int i; - - conout = ST->ConOut; - - /* Initiate the search */ - status = RS->GetNextVariableName(&varsz, NULL, NULL); - - for (; status != EFI_NOT_FOUND; ) { - status = RS->GetNextVariableName(&varsz, var, - &varguid); - //if (EFI_ERROR(status)) - //break; - - conout->OutputString(conout, var); - printf("="); - datasz = 0; - status = RS->GetVariable(var, &varguid, NULL, &datasz, - NULL); - /* XXX: check status */ - data = malloc(datasz); - status = RS->GetVariable(var, &varguid, NULL, &datasz, - data); - if (EFI_ERROR(status)) - printf(""); - else { - for (i = 0; i < datasz; i++) { - if (isalnum(data[i]) || isspace(data[i])) - printf("%c", data[i]); - else - printf("\\x%02x", data[i]); - } - } - /* XXX */ - pager_output("\n"); - free(data); - } - - return (CMD_OK); -} Property changes on: stable/10/sys/boot/i386/efi/main.c ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: stable/10/sys/boot/i386/efi/version =================================================================== --- stable/10/sys/boot/i386/efi/version (revision 271134) +++ stable/10/sys/boot/i386/efi/version (nonexistent) @@ -1,7 +0,0 @@ -$FreeBSD$ - -NOTE ANY CHANGES YOU MAKE TO THE BOOTBLOCKS HERE. The format of this -file is important. Make sure the current version number is on line 6. - -1.1: Keep in sync with i386 version. -0.1: Initial i386 version. Derived from ia64. Property changes on: stable/10/sys/boot/i386/efi/version ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: stable/10/sys/boot/i386/efi/autoload.c =================================================================== --- stable/10/sys/boot/i386/efi/autoload.c (revision 271134) +++ stable/10/sys/boot/i386/efi/autoload.c (nonexistent) @@ -1,35 +0,0 @@ -/*- - * Copyright (c) 2010 Rui Paulo - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -int -i386_autoload(void) -{ - - return (0); -} Property changes on: stable/10/sys/boot/i386/efi/autoload.c ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: stable/10/sys/boot/i386/efi/conf.c =================================================================== --- stable/10/sys/boot/i386/efi/conf.c (revision 271134) +++ stable/10/sys/boot/i386/efi/conf.c (nonexistent) @@ -1,77 +0,0 @@ -/*- - * Copyright (c) 2006 Marcel Moolenaar - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include - -struct devsw *devsw[] = { - &efipart_dev, - &efinet_dev, - NULL -}; - -struct fs_ops *file_system[] = { - &dosfs_fsops, - &ufs_fsops, - &cd9660_fsops, - &nfs_fsops, - &gzipfs_fsops, - NULL -}; - -struct netif_driver *netif_drivers[] = { - &efinetif, - NULL -}; - -#ifdef notyet -extern struct file_format amd64_elf; -extern struct file_format amd64_elf_obj; -#endif -extern struct file_format i386_elf; -extern struct file_format i386_elf_obj; - -struct file_format *file_formats[] = { -#ifdef notyet - &amd64_elf, - &amd64_elf_obj, -#endif - &i386_elf, - &i386_elf_obj, - NULL -}; - -extern struct console efi_console; - -struct console *consoles[] = { - &efi_console, - NULL -}; Property changes on: stable/10/sys/boot/i386/efi/conf.c ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: stable/10/sys/boot/i386/efi/devicename.c =================================================================== --- stable/10/sys/boot/i386/efi/devicename.c (revision 271134) +++ stable/10/sys/boot/i386/efi/devicename.c (nonexistent) @@ -1,169 +0,0 @@ -/*- - * Copyright (c) 1998 Michael Smith - * Copyright (c) 2006 Marcel Moolenaar - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include "bootstrap.h" - -#include -#include - -static int i386_parsedev(struct devdesc **, const char *, const char **); - -/* - * Point (dev) at an allocated device specifier for the device matching the - * path in (devspec). If it contains an explicit device specification, - * use that. If not, use the default device. - */ -int -i386_getdev(void **vdev, const char *devspec, const char **path) -{ - struct devdesc **dev = (struct devdesc **)vdev; - int rv; - - /* - * If it looks like this is just a path and no device, then - * use the current device instead. - */ - if (devspec == NULL || *devspec == '/' || !strchr(devspec, ':')) { - rv = i386_parsedev(dev, getenv("currdev"), NULL); - if (rv == 0 && path != NULL) - *path = devspec; - return (rv); - } - - /* Parse the device name off the beginning of the devspec. */ - return (i386_parsedev(dev, devspec, path)); -} - -/* - * Point (dev) at an allocated device specifier matching the string version - * at the beginning of (devspec). Return a pointer to the remaining - * text in (path). - * - * In all cases, the beginning of (devspec) is compared to the names - * of known devices in the device switch, and then any following text - * is parsed according to the rules applied to the device type. - * - * For disk-type devices, the syntax is: - * - * fs: - */ -static int -i386_parsedev(struct devdesc **dev, const char *devspec, const char **path) -{ - struct devdesc *idev; - struct devsw *dv; - char *cp; - const char *np; - int i, err; - - /* minimum length check */ - if (strlen(devspec) < 2) - return (EINVAL); - - /* look for a device that matches */ - for (i = 0; devsw[i] != NULL; i++) { - dv = devsw[i]; - if (!strncmp(devspec, dv->dv_name, strlen(dv->dv_name))) - break; - } - if (devsw[i] == NULL) - return (ENOENT); - - idev = malloc(sizeof(struct devdesc)); - if (idev == NULL) - return (ENOMEM); - - idev->d_dev = dv; - idev->d_type = dv->dv_type; - idev->d_unit = -1; - - err = 0; - np = devspec + strlen(dv->dv_name); - if (*np != '\0' && *np != ':') { - idev->d_unit = strtol(np, &cp, 0); - if (cp == np) { - idev->d_unit = -1; - free(idev); - return (EUNIT); - } - } - if (*cp != '\0' && *cp != ':') { - free(idev); - return (EINVAL); - } - - if (path != NULL) - *path = (*cp == 0) ? cp : cp + 1; - if (dev != NULL) - *dev = idev; - else - free(idev); - return (0); -} - -char * -i386_fmtdev(void *vdev) -{ - struct devdesc *dev = (struct devdesc *)vdev; - static char buf[32]; /* XXX device length constant? */ - - switch(dev->d_type) { - case DEVT_NONE: - strcpy(buf, "(no device)"); - break; - - default: - sprintf(buf, "%s%d:", dev->d_dev->dv_name, dev->d_unit); - break; - } - - return(buf); -} - -/* - * Set currdev to suit the value being supplied in (value) - */ -int -i386_setcurrdev(struct env_var *ev, int flags, const void *value) -{ - struct devdesc *ncurr; - int rv; - - rv = i386_parsedev(&ncurr, value, NULL); - if (rv != 0) - return(rv); - - free(ncurr); - env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL); - return (0); -} Property changes on: stable/10/sys/boot/i386/efi/devicename.c ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: stable/10/sys/boot/i386/efi/ldscript.amd64 =================================================================== --- stable/10/sys/boot/i386/efi/ldscript.amd64 (revision 271134) +++ stable/10/sys/boot/i386/efi/ldscript.amd64 (nonexistent) @@ -1,75 +0,0 @@ -/* $FreeBSD$ */ -OUTPUT_FORMAT("elf64-x86-64-freebsd", "elf64-x86-64-freebsd", "elf64-x86-64-freebsd") -OUTPUT_ARCH(i386:x86-64) -ENTRY(_start) -SECTIONS -{ - /* Read-only sections, merged into text segment: */ - . = 0; - ImageBase = .; - . = SIZEOF_HEADERS; - . = ALIGN(4096); - .eh_frame : { - *(.eh_frame) - } - .text : { - *(.text .stub .text.* .gnu.linkonce.t.*) - /* .gnu.warning sections are handled specially by elf32.em. */ - *(.gnu.warning) - *(.plt) - } =0x00300000010070000002000001000400 - . = ALIGN(4096); - .data : { - *(.rodata .rodata.* .gnu.linkonce.r.*) - *(.rodata1) - *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) - *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) - *(.opd) - *(.data .data.* .gnu.linkonce.d.*) - *(.data1) - *(.plabel) - *(.dynbss) - *(.bss .bss.* .gnu.linkonce.b.*) - *(COMMON) - } - . = ALIGN(4096); - set_Xcommand_set : { - __start_set_Xcommand_set = .; - *(set_Xcommand_set) - __stop_set_Xcommand_set = .; - } - . = ALIGN(4096); - __gp = .; - .sdata : { - *(.got.plt .got) - *(.sdata .sdata.* .gnu.linkonce.s.*) - *(dynsbss) - *(.sbss .sbss.* .gnu.linkonce.sb.*) - *(.scommon) - } - . = ALIGN(4096); - .dynamic : { *(.dynamic) } - . = ALIGN(4096); - .rela.dyn : { - *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) - *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) - *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) - *(.rela.got) - *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) - *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) - *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) - *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) - *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) - *(.rela.plt) - *(.relset_*) - *(.rela.dyn .rela.dyn.*) - } - . = ALIGN(4096); - .reloc : { *(.reloc) } - . = ALIGN(4096); - .hash : { *(.hash) } - . = ALIGN(4096); - .dynsym : { *(.dynsym) } - . = ALIGN(4096); - .dynstr : { *(.dynstr) } -} Property changes on: stable/10/sys/boot/i386/efi/ldscript.amd64 ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: stable/10/sys/boot/i386/efi/Makefile =================================================================== --- stable/10/sys/boot/i386/efi/Makefile (revision 271134) +++ stable/10/sys/boot/i386/efi/Makefile (nonexistent) @@ -1,77 +0,0 @@ -# $FreeBSD$ - -NO_MAN= -BUILDING_EFI= - -.include -MK_SSP= no - -PROG= loader.sym -INTERNALPROG= - -# architecture-specific loader code -SRCS= main.c exec.c conf.c vers.c reloc.c start.S elf32_freebsd.c -SRCS+= i386_copy.c bootinfo.c autoload.c devicename.c efimd.c - -CFLAGS+= -I${.CURDIR}/../../efi/include -CFLAGS+= -I${.CURDIR}/../../efi/include/i386 - -.if ${MK_FORTH} != "no" -BOOT_FORTH= yes -CFLAGS+= -DBOOT_FORTH -CFLAGS+= -I${.CURDIR}/../../ficl -CFLAGS+= -I${.CURDIR}/../../ficl/i386 -LIBFICL= ${.OBJDIR}/../../ficl/libficl.a -.endif - -# Include bcache code. -HAVE_BCACHE= yes - -# Always add MI sources -.PATH: ${.CURDIR}/../../common -.include "${.CURDIR}/../../common/Makefile.inc" -CFLAGS+= -I${.CURDIR}/../../common - -FILES= loader.efi -FILESMODE_loader.efi= ${BINMODE} - -LDSCRIPT= ${.CURDIR}/ldscript.i386 -LDFLAGS= -Wl,-T${LDSCRIPT} -Wl,-Bsymbolic -shared - -${PROG}: ${LDSCRIPT} - -CLEANFILES= vers.c loader.efi - -NEWVERSWHAT= "EFI loader" x86 - -vers.c: ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version - sh ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version ${NEWVERSWHAT} - -OBJCOPY?= objcopy -OBJDUMP?= objdump - -loader.efi: loader.sym - if [ `${OBJDUMP} -t ${.ALLSRC} | fgrep '*UND*' | wc -l` != 0 ]; then \ - ${OBJDUMP} -t ${.ALLSRC} | fgrep '*UND*'; \ - exit 1; \ - fi - ${OBJCOPY} -j .data -j .dynamic -j .dynstr -j .dynsym -j .hash \ - -j .rel.dyn -j .reloc -j .sdata -j .text -j set_Xcommand_set \ - --target=efi-app-ia32 ${.ALLSRC} ${.TARGET} - -LIBEFI= ${.OBJDIR}/../../efi/libefi/libefi.a -LIBSTAND= ${.OBJDIR}/../../libstand32/libstand.a -CFLAGS+= -I${.CURDIR}/../libi386 -CFLAGS+= -I${.CURDIR}/../btx/lib - -DPADD= ${LIBFICL} ${LIBEFI} ${LIBSTAND} -LDADD= ${LIBFICL} ${LIBEFI} ${LIBSTAND} - -.include - -.if ${MACHINE_CPUARCH} == "amd64" -CFLAGS+= -I. -beforedepend ${OBJS}: machine -machine: - ln -sf ${.CURDIR}/../../../i386/include machine -.endif Property changes on: stable/10/sys/boot/i386/efi/Makefile ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: stable/10/sys/boot/i386/libi386/Makefile =================================================================== --- stable/10/sys/boot/i386/libi386/Makefile (revision 271134) +++ stable/10/sys/boot/i386/libi386/Makefile (revision 271135) @@ -1,69 +1,72 @@ # $FreeBSD$ # LIB= i386 INTERNALLIB= SRCS= biosacpi.c bioscd.c biosdisk.c biosmem.c biospnp.c \ biospci.c biossmap.c bootinfo.c bootinfo32.c bootinfo64.c \ comconsole.c devicename.c elf32_freebsd.c \ elf64_freebsd.c \ i386_copy.c i386_module.c nullconsole.c pxe.c pxetramp.s \ smbios.c time.c vidconsole.c amd64_tramp.S spinconsole.c .PATH: ${.CURDIR}/../../zfs SRCS+= devicename_stubs.c # Enable PXE TFTP or NFS support, not both. .if defined(LOADER_TFTP_SUPPORT) CFLAGS+= -DLOADER_TFTP_SUPPORT .else CFLAGS+= -DLOADER_NFS_SUPPORT .endif BOOT_COMCONSOLE_PORT?= 0x3f8 CFLAGS+= -DCOMPORT=${BOOT_COMCONSOLE_PORT} BOOT_COMCONSOLE_SPEED?= 9600 CFLAGS+= -DCOMSPEED=${BOOT_COMCONSOLE_SPEED} .ifdef(BOOT_BIOSDISK_DEBUG) # Make the disk code more talkative CFLAGS+= -DDISK_DEBUG .endif .if !defined(BOOT_HIDE_SERIAL_NUMBERS) # Export serial numbers, UUID, and asset tag from loader. CFLAGS+= -DSMBIOS_SERIAL_NUMBERS .if defined(BOOT_LITTLE_ENDIAN_UUID) # Use little-endian UUID format as defined in SMBIOS 2.6. CFLAGS+= -DSMBIOS_LITTLE_ENDIAN_UUID .endif .endif # Include simple terminal emulation (cons25-compatible) CFLAGS+= -DTERM_EMU # XXX: make alloca() useable CFLAGS+= -Dalloca=__builtin_alloca CFLAGS+= -I${.CURDIR}/../../common -I${.CURDIR}/../common \ -I${.CURDIR}/../btx/lib \ -I${.CURDIR}/../../../contrib/dev/acpica/include \ -I${.CURDIR}/../../.. -I. # the location of libstand CFLAGS+= -I${.CURDIR}/../../../../lib/libstand/ +# Suppress warning from clang for FreeBSD %b and %D formats +CFLAGS+= -fformat-extensions + .if ${MACHINE_CPUARCH} == "amd64" CLEANFILES+= machine machine: ln -sf ${.CURDIR}/../../../i386/include machine .endif .include # XXX: clang integrated-as doesn't grok .codeNN directives yet CFLAGS.amd64_tramp.S= ${CLANG_NO_IAS} CFLAGS+= ${CFLAGS.${.IMPSRC:T}} .if ${MACHINE_CPUARCH} == "amd64" beforedepend ${OBJS}: machine .endif Index: stable/10/sys/boot/i386/loader/Makefile =================================================================== --- stable/10/sys/boot/i386/loader/Makefile (revision 271134) +++ stable/10/sys/boot/i386/loader/Makefile (revision 271135) @@ -1,133 +1,137 @@ # $FreeBSD$ .include MK_SSP= no LOADER?= loader PROG= ${LOADER}.sym INTERNALPROG= NEWVERSWHAT?= "bootstrap loader" x86 # architecture-specific loader code SRCS= main.c conf.c vers.c # Put LOADER_FIREWIRE_SUPPORT=yes in /etc/make.conf for FireWire/dcons support .if defined(LOADER_FIREWIRE_SUPPORT) CFLAGS+= -DLOADER_FIREWIRE_SUPPORT LIBFIREWIRE= ${.OBJDIR}/../libfirewire/libfirewire.a .endif # Set by zfsloader Makefile .if defined(LOADER_ZFS_SUPPORT) CFLAGS+= -DLOADER_ZFS_SUPPORT LIBZFSBOOT= ${.OBJDIR}/../../zfs/libzfsboot.a .endif # Enable PXE TFTP or NFS support, not both. .if defined(LOADER_TFTP_SUPPORT) CFLAGS+= -DLOADER_TFTP_SUPPORT .else CFLAGS+= -DLOADER_NFS_SUPPORT .endif # Include bcache code. HAVE_BCACHE= yes # Enable PnP and ISA-PnP code. HAVE_PNP= yes HAVE_ISABUS= yes .if ${MK_FORTH} != "no" # Enable BootForth BOOT_FORTH= yes CFLAGS+= -DBOOT_FORTH -I${.CURDIR}/../../ficl -I${.CURDIR}/../../ficl/i386 +.if ${MACHINE_CPUARCH} == "amd64" +LIBFICL= ${.OBJDIR}/../../ficl32/libficl.a +.else LIBFICL= ${.OBJDIR}/../../ficl/libficl.a +.endif .endif .if defined(LOADER_BZIP2_SUPPORT) CFLAGS+= -DLOADER_BZIP2_SUPPORT .endif .if !defined(LOADER_NO_GZIP_SUPPORT) CFLAGS+= -DLOADER_GZIP_SUPPORT .endif .if defined(LOADER_NANDFS_SUPPORT) CFLAGS+= -DLOADER_NANDFS_SUPPORT .endif # Always add MI sources .PATH: ${.CURDIR}/../../common .include "${.CURDIR}/../../common/Makefile.inc" CFLAGS+= -I${.CURDIR}/../../common CFLAGS+= -I. CLEANFILES= vers.c ${LOADER} ${LOADER}.bin loader.help CFLAGS+= -Wall LDFLAGS= -static -Ttext 0x0 # i386 standalone support library LIBI386= ${.OBJDIR}/../libi386/libi386.a CFLAGS+= -I${.CURDIR}/.. LIBSTAND= ${.OBJDIR}/../../libstand32/libstand.a # BTX components CFLAGS+= -I${.CURDIR}/../btx/lib # Debug me! #CFLAGS+= -g #LDFLAGS+= -g # Pick up ../Makefile.inc early. .include vers.c: ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/../loader/version sh ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/../loader/version \ ${NEWVERSWHAT} ${LOADER}: ${LOADER}.bin ${BTXLDR} ${BTXKERN} btxld -v -f aout -e ${LOADER_ADDRESS} -o ${.TARGET} -l ${BTXLDR} \ -b ${BTXKERN} ${LOADER}.bin ${LOADER}.bin: ${LOADER}.sym cp ${.ALLSRC} ${.TARGET} strip -R .comment -R .note ${.TARGET} loader.help: help.common help.i386 cat ${.ALLSRC} | awk -f ${.CURDIR}/../../common/merge_help.awk > ${.TARGET} FILES= ${LOADER} # XXX INSTALLFLAGS_loader= -b FILESMODE_${LOADER}= ${BINMODE} -b .if !defined(LOADER_ONLY) .PATH: ${.CURDIR}/../../forth FILES+= loader.help loader.4th support.4th loader.conf FILES+= screen.4th frames.4th beastie.4th FILES+= brand.4th check-password.4th color.4th delay.4th FILES+= menu.4th menu-commands.4th menusets.4th shortcuts.4th version.4th FILESDIR_loader.conf= /boot/defaults .if !exists(${DESTDIR}/boot/loader.rc) FILES+= loader.rc .endif .if !exists(${DESTDIR}/boot/menu.rc) FILES+= menu.rc .endif .endif # XXX crt0.o needs to be first for pxeboot(8) to work OBJS= ${BTXCRT} DPADD= ${LIBFICL} ${LIBFIREWIRE} ${LIBZFSBOOT} ${LIBI386} ${LIBSTAND} LDADD= ${LIBFICL} ${LIBFIREWIRE} ${LIBZFSBOOT} ${LIBI386} ${LIBSTAND} .include .if ${MACHINE_CPUARCH} == "amd64" beforedepend ${OBJS}: machine CLEANFILES+= machine CFLAGS+= -DLOADER_PREFER_AMD64 machine: ln -sf ${.CURDIR}/../../../i386/include machine .endif Index: stable/10 =================================================================== --- stable/10 (revision 271134) +++ stable/10 (revision 271135) Property changes on: stable/10 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r258741,261568,261603,261668,263115,263117,263968,264078,264087-264088,264092,264095,264115,264132,264208,264261-264263,264319,265028,265057,268974