|
B & I SNOWDEN-Find a Wealth of Products and Services
|
BIOS and 64bit One reason for the longevity of the BIOS, and for its sustained
primitivity, is the insanely successful DOS (for the PC), which was built on top
of the BIOS. DOS programs call BIOS routines via software interrupts (for
example, the BIOS disk routine corresponds to In a "modern" setting, the old-fashioned BIOS has severe limitations, even though it has seen numerous tweaks, improvements, extensions, and additions over the years. Consider some examples:
A small range of extended memory addresses can be accessed in real mode (Gate A20). 386 and higher x86 processors can be switched from protected mode to real mode without a reset, which allows them to operate in the Big Real Mode: a modified real mode in which the processor can access up to 4 GB of memory. BIOSs can put the processor in this mode during POST (Power On Self Test) to make access to extended memory easier.
A representative legacy BIOS could be visualized as containing three sets of procedures: those that are the same on all BIOSs (the core procedures), those that are specific to chips on the platform (the silicon support procedures), and those that are specific to the system board. There is a great deal of "secret-sauce" element in the BIOS. The BIOS APIs are very limited, and it is very hard to extend the BIOS -- it is a black box not just to end users, but also to those who wish to develop pre-boot or pre-OS applications (as value-add, say). Even if such developers license the BIOS source, the environment is expensive to develop for in all respects (including deployment). A Bit of a Problem64-bit computing came relatively late to the PC world. With the advent of 64-bit PCs (those based on the Itanium Processor Family, for example), a better solution to the "BIOS problem" was sought, although the x86 real mode can be emulated in IA-64. New Beginning64-bit PCs do not use legacy BIOS. The IA-64 firmware is divided into three primary components: the Processor Abstraction Layer (PAL), the System Abstraction Layer (SAL), and the Extensible Firmware Interface (EFI). PAL abstracts the processor hardware implementation from the point of view of SAL and the operating system. Different processor models with potential implementation differences appear uniformly via PAL. Examples of the PAL layer's functionality include:
PAL has no knowledge of platform implementation details. Note however that PAL is part of the IA-64 architecture. The firmware implementation of PAL is supplied by the processor vendor, and it resides in OEM flash memory. SAL provides an abstraction for the platform implementation, without any knowledge of processor implementation details. SAL is not part of the IA-64 architecture -- it is part of the Developer's Interface Guide for 64-bit Intel Architecture (DIG64). The firmware implementation of PAL is provided by the OEM. As on IA-32 systems, Advanced Configuration and Power Interface (ACPI) exists as an interface for allowing the operating system to direct configuration and power management on the computer. ACPI is also a part of the firmware, and could be listed as the fourth primary component. Note that since EFI also exists for IA-32, only PAL and SAL are the IA-64 specific parts of an IA-64 firmware. The remaining component, EFI, could be thought of as the grand solution to the BIOS problem -- for PCs. Extensible Firmware InterfaceThe Extensible Firmware Interface (EFI) can be traced back to the "Intel Boot Initiative" (IBI) program (1998, but see Innovate[2] later in this document)). The EFI specification, developed and maintained by a consortium of companies (including Intel and Microsoft), defines a set of APIs and data structures to be exported by a system's firmware, and to be used by a variety of clients, such as:
In a representative EFI system, a thin Pre-EFI Initialization Layer (PEI) might do most of the POST-related work that is traditionally done by the BIOS POST. This includes things like chipset initialization, memory initialization, bus enumeration, etc. EFI prepares a Driver Execution Environment (DXE) to provide generic platform functions that EFI drivers may use. The drivers themselves provide specific platform capabilities and customizations. EFI ServicesThere are two types of services available in the EFI environment: Boot Services and Runtime Services. Applications that run only within the pre-boot environment make use of boot services, which include services for events, timer, and task priority, for memory allocation, for handling EFI protocols, for loading various types of images (EFI applications, EFI boot services drivers, EFI runtime drivers), and for miscellaneous purposes. An operating system loader also uses boot services to determine
and access the boot device, allocate memory, and create a functional environment
for the operating system to start loading. At this point, an OS loader could
call the Runtime services are available both before and after
EFI was designed for computers based on the Itanium Processor Family (IPF), but its scope has been widened to include the next generation of IA-32 computers, with provisions for compatibility with legacy BIOS through a Compatibility Support Module (CSM) -- a series of drivers cooperating with a legacy BIOS runtime component. CSM loads into memory in well-known legacy areas (below 1 MB). Standard BIOS memory areas such as the Bios Data Area (BDA) and the Extended BDA are initialized. The Boot Device Selection (BDS) mechanism appropriately selects either EFI or legacy BIOS. Current day IA-64 computers use EFI-based firmware. Gateway even sells an IA-32 system with EFI-based firmware: the Media Center 6x0, which uses Insyde Software's InsydeH2O firmware. InsydeH2O includes a CSM for legacy BIOS runtime compatibility. Intel and Microsoft are behind EFI. One of the major BIOS manufacturers, American Megatrends, Inc. (AMI) already has products based on EFI: AMI Enterprise64 for IPF, and AMIBIOS8 with an add-on EFI-32 eModule for the IA-32. Another major player, Phoenix, is currently adopting a somewhat more incremental approach, but apparently has intentions for supporting EFI. Device vendors such as ATI and Adaptec are also supporting EFI. It is expected (by those behind EFI) that EFI would be the primary, if not the only, firmware used in new PC systems within the next two to three years. EFI DriversEFI drivers can come from non-volatile memory, from the option ROM of a card, or from a device that EFI supports natively. Most EFI drivers would conform to the EFI Driver Model. Such drivers are written in C and operate in a flat memory model. Driver images may be converted to EFI Byte Code (EBC), and are typically compressed (using Deflate, a combination of LZ77 compression and Huffman coding). Examples include:
Drivers that may not conform to the EFI Driver Model include:
EFI drivers consume various protocols (PCI I/O, Device Path, USB I/O, USB Path, etc.) and produce several other protocols (Simple Input, Simple Pointer, Block I/O, UGA Draw, UGA I/O, Simple Text Output, SCSI Block I/O, SCSI Passthrough, Network Interface Identification, Serial I/O, Debug Port, Load File, etc.) BenefitsEFI aims to be a powerful and modular firmware that is readily extensible, even by (power) users. Some noteworthy aspects of EFI include:
Preeminence of Pre-bootAs PC hardware and software vendors try to differentiate their offerings, the pre-boot environment is getting increasingly important. A computer with pre-boot functionality for backup and restore, recovery, virus scanning, etc. would have more perceived value than one without. In some cases, an application must be pre-boot, because it cannot rely on the operating system -- for example, applications for performing low-level diagnostics, recovering the operating system, and updating certain firmware. In some other cases, an application may not need the "full" operating system, and may explicitly wish to run without the operating system, so as to make the computer behave like an appliance -- for example, a DVD or MP3 player, a mail client, web browser, etc. With legacy BIOS, such pre-boot applications are rather expensive to develop, deploy, and run. EFI strives to simplify this domain greatly and includes specifications for creating pre-boot software. Even the end-user could create a pre-boot application using familiar development tools. EFI's pre-boot environment is also meant to facilitate robust solutions for secure network booting, secure network resetting, remote provisioning and setup (through bootable "agents" that are EFI objects), remote management of system firmware, and so on. Thus, it is easier to deploy and manage a large number of "headless" servers. Example EFI EnvironmentFollowing is a "site map" of a hypothetical user-visible EFI environment you may be presented with on an EFI-based machine:
EFI ShellThe EFI environment (optionally) includes an interactive shell that allows a user to do a wide variety of tasks:
The EFI shell has flavors of both the DOS command prompt and a rudimentary Unix shell. It is implemented in C, and is developer extensible. GUID Based Partitioning SchemeEFI defines GUID Partition Table (GPT), a new partitioning scheme that must be supported by EFI firmware. GPT uses globally unique identifiers to tag partitions. It is used by the 64-bit version of Windows, and offers several advantages over the legacy MBR-based partitioning scheme:
The primary header structure of a GUID partition table is stored on block 1 of the logical device, while the backup is stored on the last block. A GUID partition table header may never span more than one block on the device. Moreover, although GPT does not support nesting of partitions, it is legal to have a legacy MBR nested inside a GPT partition. Note however that the boot code on a legacy MBR is not executed by EFI firmware. GUIDsA GUID (also called UUID, for Universally Unique Identifier) is specified to be 128 bits long in Intel's Wired for Management (WfM) specification, and is unique across time (for example, until 3400 A.D. as per one GUID generation algorithm) and space (relative to other GUIDs). A key to generating a GUID without requiring a centralized authority is the use of a globally unique value that is available to each GUID generator -- a node identifier. For networked systems, this is a 48-bit IEEE 802 address (usually the host address, or some host address in case of multiple interfaces). For a host without an IEEE 802 address, this value is chosen in a probabilistically unique fashion. This is not sufficient for uniqueness, though. Other values involved in GUID generation include a timestamp, a clock sequence, and a version number. A sample implementation of GPT disk utilities is available from
Intel. The package includes
Universal Graphics Adapter (UGA)As mentioned earlier, legacy BIOS depends on VGA, a legacy standard. Thus, given the growing needs of pre-boot applications, graphics support in a firmware environment is both very limited and hard to program with (consider factors like 640x480 maximum resolution, small framebuffer, use of palette modes, and so on). EFI defines the UGA specification as a replacement for VGA and VESA. Microsoft is behind UGA, with support from major graphics device manufacturers like ATI. Any graphics device with UGA firmware can be considered a UGA device. It may also contain VGA firmware for compatibility. The firmware execution environment interprets UGA firmware, which again is implemented in a high level language. Similarly, programming a UGA device does not require you to deal with hardware registers, etc. The UGA model would work as follows: the UGA firmware may reside on the graphics device, may be a part of the system firmware in case of an onboard graphics device, or may even come from a regular storage device. The firmware contains an EFI driver, which is still a "lowest common denominator" driver, and is not meant to replace a "high-performance" device specific driver that would normally be part of the operating system. That said, the UGA driver may be used in the post-boot environment in various scenarios:
Unlike VGA, the UGA firmware does not access the graphics hardware directly. It operates within an EFI virtual machine. Microsoft provides a generic Virtual Machine Library (VML) that a UGA firmware is linked with. This virtual machine -- a thin logical layer above EFI -- wraps (encapsulates) a specific UGA firmware implementation. EFI Byte CodeOption ROMs require different executable images for different processors and platforms. EFI defines an EFI Byte Code (EBC) Virtual Machine to abstract such differences. The interpreter for this virtual machine is part of the firmware. C source can be compiled into EBC, then linked to yield drivers that "run" on the interpreter. The EBC virtual machine uses two sets of 64-bit registers: 8
general purpose, and 2 dedicated registers. Further, it uses natural
indexing for data offsets (relative to a base address) -- instead of a
fixed number of bytes as an "offset unit", it uses a "natural unit", which is
defined as the operation (as opposed to a constant) There exists a C to EBC compiler. Note that you have several restrictions for the kind of C you can use: floating point and inline assembly are not supported, for example. You cannot use C++ either. Experimenting with EFIIt is possible to develop and test your own EFI applications, even on an IA-32 computer. You need an EFI runtime environment to explore EFI and run EFI programs, while you need an EFI development environment to create your own EFI programs. You have choices for each environment: Runtime Environment: You can explore EFI on an IA-64 system, which would have a real implementation of the EFI firmware. It may also be possible to acquire an "artificial" EFI environment, such as within an EFI emulator or an IA-64 simulator. An EFI BIOS32 boot floppy is also available from Intel, using which you can simply "boot into" a real EFI environment on an x86 machine with a legacy BIOS. Development Environment: You can develop EFI programs on Windows and Linux (perhaps on some others even). An example Windows development environment for EFI could consist of (but not limited to) the following:
EFI emulation under Windows should allow for convenient application development and debugging. Following is source for an example EFI program, DownloadSource for Towers of Hanoi in the EFI environment.
You can also develop EFI applications for IA-64 and x86 using the GNU toolchain on Linux. You need:
The ELF32 (or ELF64 on IA-64) binaries normally produced on
Linux must be converted to EFI binaries, which are supposed to be in the PE32+
format. ELF sections are copied (via
More details of this process can be found in the file README.gnuefi within the GNU EFI package. PE32+The executable and object file formats under Microsoft Windows are called Portable Executable (PE) and Common Object File Format (COFF), respectively. A PE file is essentially a COFF file with an MS-DOS 2.0 compatible header (see Microsoft Portable Executable and Common Object File Format Specification for details). An optional header contains a magic number that further designates a PE files as "PE32" or "PE32+". PE32+ images allow for a 64-bit address space, although the image size is limited to 4 GB. The Subsystem ID in an EFI PE image header is one of 0xa, 0xb, or 0xc, corresponding to an image that is an EFI application, an EFI boot service driver, or an EFI runtime driver, respectively. Note that an operating system loader is a special type of EFI application. The Machine ID in the same header corresponds to one for IA-32, IA-64, or EFI Byte Code (EBC). Elilo, the EFI Linux boot loader, allows booting of Linux on EFI systems (both IA-64 and IA-32). The Linux kernel also supports EFI, that is, the Linux kernel provides an interface to the EFI runtime services (you need a recent 2.6 kernel for such support on IA-32). Innovate[2]It should still be a few years before we should see widespread adoption and deployment of EFI.
Open FirmwareWe discuss Open Firmware briefly in the following section. More details on interacting with Open Firmware may be found in Booting Mac OS X. BackgroundOpen Firmware originated at Sun Microsystems in 1988, and was later adopted by Apple and some other vendors. Sun's implementation is trade-marked as OpenBoot, while Apple simply calls it Open Firmware. Open Firmware is a non-proprietary, platform- (CPU and system) independent, programmable, and extensible environment for use in boot ROMs. Consider:
InteractionYou can enter Open Firmware by pressing the key combination
You can continue booting the machine by typing For more details on Open Firmware, refer to Booting Mac OS X. OthersLet us take a quick look at some other firmware related efforts. Open SourceThere is some "firmware activity" in the open source world, aimed both at developing open source alternatives to the BIOS, or to even replace the BIOS with Linux. LinuxBIOS LinuxBIOS is an open source project that uses the Linux kernel as the firmware. LinuxBIOS uses a system call, FreeBIOS FreeBIOS aims to provide an open source replacement for any computer's firmware, with initial support for Intel-based processors and chipsets. OpenBIOS OpenBIOS is work-in-progress towards an open source firmware implementation that aims to be 100% compliant with Open Firmware. Phoenix Core System Software (CSS)As mentioned earlier, Phoenix currently seems to be taking a more incremental approach to EFI adoption. Phoenix has been extending the functionality of their BIOS products through features such as:
Phoenix plans to support both EFI and legacy boot methods in Longhorn timeframe, with a gradual transition to EFI, leading to an eventual removal of legacy. Phoenix says this is a low-risk, low-cost, and non-disruptive approach. In the next sections, we look at examples of using graphics and mouse within Open Firmware. Part II: GUI Widgets In Open Firmware(Having Fun On A Mac Without An Operating System)The implementation of Open Firmware used in Apple computers includes the device support extensions for several devices, and in particular, for the graphics and the mouse devices. Thus, it is possible for you to write Open Firmware programs that use the mouse and draw to the framebuffer. We look at two examples: creating a "window" that you can move around using the mouse, and animating Towers of Hanoi. Creating WindowsThe sample Forth code in this section (see link below) creates a small, fixed size window that you can move around. Specifically, the code does the following:
UsageThe following example demonstrates how to "boot" into a
window-drawing demo from the Open Firmware prompt, assuming the program file
(called
\ Open Firmware Windows Demo
\ Copyright (c) 2004 Amit Singh. All Rights Reserved.
\ http://www.kernelthread.com
\ Commentary required for "booting" this program.
decimal
16 value m-w
16 value m-h
m-w m-h * value m-dim
m-dim buffer: smask
m-dim buffer: cmask
m-dim buffer: scrnbg
m-dim buffer: oldbg
: load-cmask ( -- )
0 cmask 0 + c! 0 cmask 1 + c! 0 cmask 2 + c! 0 cmask 3 + c!
0 cmask 4 + c! 0 cmask 5 + c! 0 cmask 6 + c! 0 cmask 7 + c!
0 cmask 8 + c! 0 cmask 9 + c! 0 cmask 10 + c! 0 cmask 11 + c!
0 cmask 12 + c! 0 cmask 13 + c! 0 cmask 14 + c! 0 cmask 15 + c!
0 cmask 16 + c! 0 cmask 17 + c! 1 cmask 18 + c! 0 cmask 19 + c!
0 cmask 20 + c! 0 cmask 21 + c! 0 cmask 22 + c! 0 cmask 23 + c!
0 cmask 24 + c! 0 cmask 25 + c! 0 cmask 26 + c! 0 cmask 27 + c!
0 cmask 28 + c! 0 cmask 29 + c! 0 cmask 30 + c! 0 cmask 31 + c!
0 cmask 32 + c! 0 cmask 33 + c! 1 cmask 34 + c! 1 cmask 35 + c!
0 cmask 36 + c! 0 cmask 37 + c! 0 cmask 38 + c! 0 cmask 39 + c!
0 cmask 40 + c! 0 cmask 41 + c! 0 cmask 42 + c! 0 cmask 43 + c!
0 cmask 44 + c! 0 cmask 45 + c! 0 cmask 46 + c! 0 cmask 47 + c!
0 cmask 48 + c! 0 cmask 49 + c! 1 cmask 50 + c! 1 cmask 51 + c!
1 cmask 52 + c! 0 cmask 53 + c! 0 cmask 54 + c! 0 cmask 55 + c!
0 cmask 56 + c! 0 cmask 57 + c! 0 cmask 58 + c! 0 cmask 59 + c!
0 cmask 60 + c! 0 cmask 61 + c! 0 cmask 62 + c! 0 cmask 63 + c!
0 cmask 64 + c! 0 cmask 65 + c! 1 cmask 66 + c! 1 cmask 67 + c!
1 cmask 68 + c! 1 cmask 69 + c! 0 cmask 70 + c! 0 cmask 71 + c!
0 cmask 72 + c! 0 cmask 73 + c! 0 cmask 74 + c! 0 cmask 75 + c!
0 cmask 76 + c! 0 cmask 77 + c! 0 cmask 78 + c! 0 cmask 79 + c!
0 cmask 80 + c! 0 cmask 81 + c! 1 cmask 82 + c! 1 cmask 83 + c!
1 cmask 84 + c! 1 cmask 85 + c! 1 cmask 86 + c! 0 cmask 87 + c!
0 cmask 88 + c! 0 cmask 89 + c! 0 cmask 90 + c! 0 cmask 91 + c!
0 cmask 92 + c! 0 cmask 93 + c! 0 cmask 94 + c! 0 cmask 95 + c!
0 cmask 96 + c! 0 cmask 97 + c! 1 cmask 98 + c! 1 cmask 99 + c!
1 cmask 100 + c! 1 cmask 101 + c! 1 cmask 102 + c! 1 cmask 103 + c!
0 cmask 104 + c! 0 cmask 105 + c! 0 cmask 106 + c! 0 cmask 107 + c!
0 cmask 108 + c! 0 cmask 109 + c! 0 cmask 110 + c! 0 cmask 111 + c!
0 cmask 112 + c! 0 cmask 113 + c! 1 cmask 114 + c! 1 cmask 115 + c!
1 cmask 116 + c! 1 cmask 117 + c! 1 cmask 118 + c! 1 cmask 119 + c!
1 cmask 120 + c! 0 cmask 121 + c! 0 cmask 122 + c! 0 cmask 123 + c!
0 cmask 124 + c! 0 cmask 125 + c! 0 cmask 126 + c! 0 cmask 127 + c!
0 cmask 128 + c! 0 cmask 129 + c! 1 cmask 130 + c! 1 cmask 131 + c!
1 cmask 132 + c! 1 cmask 133 + c! 1 cmask 134 + c! 1 cmask 135 + c!
1 cmask 136 + c! 1 cmask 137 + c! 0 cmask 138 + c! 0 cmask 139 + c!
0 cmask 140 + c! 0 cmask 141 + c! 0 cmask 142 + c! 0 cmask 143 + c!
0 cmask 144 + c! 0 cmask 145 + c! 1 cmask 146 + c! 1 cmask 147 + c!
1 cmask 148 + c! 1 cmask 149 + c! 1 cmask 150 + c! 0 cmask 151 + c!
0 cmask 152 + c! 0 cmask 153 + c! 0 cmask 154 + c! 0 cmask 155 + c!
0 cmask 156 + c! 0 cmask 157 + c! 0 cmask 158 + c! 0 cmask 159 + c!
0 cmask 160 + c! 0 cmask 161 + c! 1 cmask 162 + c! 1 cmask 163 + c!
0 cmask 164 + c! 1 cmask 165 + c! 1 cmask 166 + c! 0 cmask 167 + c!
0 cmask 168 + c! 0 cmask 169 + c! 0 cmask 170 + c! 0 cmask 171 + c!
0 cmask 172 + c! 0 cmask 173 + c! 0 cmask 174 + c! 0 cmask 175 + c!
0 cmask 176 + c! 0 cmask 177 + c! 1 cmask 178 + c! 0 cmask 179 + c!
0 cmask 180 + c! 0 cmask 181 + c! 1 cmask 182 + c! 1 cmask 183 + c!
0 cmask 184 + c! 0 cmask 185 + c! 0 cmask 186 + c! 0 cmask 187 + c!
0 cmask 188 + c! 0 cmask 189 + c! 0 cmask 190 + c! 0 cmask 191 + c!
0 cmask 192 + c! 0 cmask 193 + c! 0 cmask 194 + c! 0 cmask 195 + c!
0 cmask 196 + c! 0 cmask 197 + c! 1 cmask 198 + c! 1 cmask 199 + c!
0 cmask 200 + c! 0 cmask 201 + c! 0 cmask 202 + c! 0 cmask 203 + c!
0 cmask 204 + c! 0 cmask 205 + c! 0 cmask 206 + c! 0 cmask 207 + c!
0 cmask 208 + c! 0 cmask 209 + c! 0 cmask 210 + c! 0 cmask 211 + c!
0 cmask 212 + c! 0 cmask 213 + c! 0 cmask 214 + c! 1 cmask 215 + c!
1 cmask 216 + c! 0 cmask 217 + c! 0 cmask 218 + c! 0 cmask 219 + c!
0 cmask 220 + c! 0 cmask 221 + c! 0 cmask 222 + c! 0 cmask 223 + c!
0 cmask 224 + c! 0 cmask 225 + c! 0 cmask 226 + c! 0 cmask 227 + c!
0 cmask 228 + c! 0 cmask 229 + c! 0 cmask 230 + c! 1 cmask 231 + c!
1 cmask 232 + c! 0 cmask 233 + c! 0 cmask 234 + c! 0 cmask 235 + c!
0 cmask 236 + c! 0 cmask 237 + c! 0 cmask 238 + c! 0 cmask 239 + c!
0 cmask 240 + c! 0 cmask 241 + c! 0 cmask 242 + c! 0 cmask 243 + c!
0 cmask 244 + c! 0 cmask 245 + c! 0 cmask 246 + c! 0 cmask 247 + c!
0 cmask 248 + c! 0 cmask 249 + c! 0 cmask 250 + c! 0 cmask 251 + c!
0 cmask 252 + c! 0 cmask 253 + c! 0 cmask 254 + c! 0 cmask 255 + c!
;
: load-smask ( -- )
1 smask 0 + c! 0 smask 1 + c! 0 smask 2 + c! 1 smask 3 + c!
1 smask 4 + c! 1 smask 5 + c! 1 smask 6 + c! 1 smask 7 + c!
1 smask 8 + c! 1 smask 9 + c! 1 smask 10 + c! 1 smask 11 + c!
1 smask 12 + c! 1 smask 13 + c! 1 smask 14 + c! 1 smask 15 + c!
1 smask 16 + c! 0 smask 17 + c! 0 smask 18 + c! 0 smask 19 + c!
1 smask 20 + c! 1 smask 21 + c! 1 smask 22 + c! 1 smask 23 + c!
1 smask 24 + c! 1 smask 25 + c! 1 smask 26 + c! 1 smask 27 + c!
1 smask 28 + c! 1 smask 29 + c! 1 smask 30 + c! 1 smask 31 + c!
1 smask 32 + c! 0 smask 33 + c! 0 smask 34 + c! 0 smask 35 + c!
0 smask 36 + c! 1 smask 37 + c! 1 smask 38 + c! 1 smask 39 + c!
1 smask 40 + c! 1 smask 41 + c! 1 smask 42 + c! 1 smask 43 + c!
1 smask 44 + c! 1 smask 45 + c! 1 smask 46 + c! 1 smask 47 + c!
1 smask 48 + c! 0 smask 49 + c! 0 smask 50 + c! 0 smask 51 + c!
0 smask 52 + c! 0 smask 53 + c! 1 smask 54 + c! 1 smask 55 + c!
1 smask 56 + c! 1 smask 57 + c! 1 smask 58 + c! 1 smask 59 + c!
1 smask 60 + c! 1 smask 61 + c! 1 smask 62 + c! 1 smask 63 + c!
1 smask 64 + c! 0 smask 65 + c! 0 smask 66 + c! 0 smask 67 + c!
0 smask 68 + c! 0 smask 69 + c! 0 smask 70 + c! 1 smask 71 + c!
1 smask 72 + c! 1 smask 73 + c! 1 smask 74 + c! 1 smask 75 + c!
1 smask 76 + c! 1 smask 77 + c! 1 smask 78 + c! 1 smask 79 + c!
1 smask 80 + c! 0 smask 81 + c! 0 smask 82 + c! 0 smask 83 + c!
0 smask 84 + c! 0 smask 85 + c! 0 smask 86 + c! 0 smask 87 + c!
1 smask 88 + c! 1 smask 89 + c! 1 smask 90 + c! 1 smask 91 + c!
1 smask 92 + c! 1 smask 93 + c! 1 smask 94 + c! 1 smask 95 + c!
1 smask 96 + c! 0 smask 97 + c! 0 smask 98 + c! 0 smask 99 + c!
0 smask 100 + c! 0 smask 101 + c! 0 smask 102 + c! 0 smask 103 + c!
0 smask 104 + c! 1 smask 105 + c! 1 smask 106 + c! 1 smask 107 + c!
1 smask 108 + c! 1 smask 109 + c! 1 smask 110 + c! 1 smask 111 + c!
1 smask 112 + c! 0 smask 113 + c! 0 smask 114 + c! 0 smask 115 + c!
0 smask 116 + c! 0 smask 117 + c! 0 smask 118 + c! 0 smask 119 + c!
0 smask 120 + c! 0 smask 121 + c! 1 smask 122 + c! 1 smask 123 + c!
1 smask 124 + c! 1 smask 125 + c! 1 smask 126 + c! 1 smask 127 + c!
1 smask 128 + c! 0 smask 129 + c! 0 smask 130 + c! 0 smask 131 + c!
0 smask 132 + c! 0 smask 133 + c! 0 smask 134 + c! 0 smask 135 + c!
0 smask 136 + c! 0 smask 137 + c! 0 smask 138 + c! 1 smask 139 + c!
1 smask 140 + c! 1 smask 141 + c! 1 smask 142 + c! 1 smask 143 + c!
1 smask 144 + c! 0 smask 145 + c! 0 smask 146 + c! 0 smask 147 + c!
0 smask 148 + c! 0 smask 149 + c! 0 smask 150 + c! 0 smask 151 + c!
0 smask 152 + c! 0 smask 153 + c! 0 smask 154 + c! 0 smask 155 + c!
1 smask 156 + c! 1 smask 157 + c! 1 smask 158 + c! 1 smask 159 + c!
1 smask 160 + c! 0 smask 161 + c! 0 smask 162 + c! 0 smask 163 + c!
0 smask 164 + c! 0 smask 165 + c! 0 smask 166 + c! 0 smask 167 + c!
1 smask 168 + c! 1 smask 169 + c! 1 smask 170 + c! 1 smask 171 + c!
1 smask 172 + c! 1 smask 173 + c! 1 smask 174 + c! 1 smask 175 + c!
1 smask 176 + c! 0 smask 177 + c! 0 smask 178 + c! 0 smask 179 + c!
1 smask 180 + c! 0 smask 181 + c! 0 smask 182 + c! 0 smask 183 + c!
0 smask 184 + c! 1 smask 185 + c! 1 smask 186 + c! 1 smask 187 + c!
1 smask 188 + c! 1 smask 189 + c! 1 smask 190 + c! 1 smask 191 + c!
1 smask 192 + c! 0 smask 193 + c! 0 smask 194 + c! 1 smask 195 + c!
1 smask 196 + c! 0 smask 197 + c! 0 smask 198 + c! 0 smask 199 + c!
0 smask 200 + c! 1 smask 201 + c! 1 smask 202 + c! 1 smask 203 + c!
1 smask 204 + c! 1 smask 205 + c! 1 smask 206 + c! 1 smask 207 + c!
1 smask 208 + c! 1 smask 209 + c! 1 smask 210 + c! 1 smask 211 + c!
1 smask 212 + c! 1 smask 213 + c! 0 smask 214 + c! 0 smask 215 + c!
0 smask 216 + c! 0 smask 217 + c! 1 smask 218 + c! 1 smask 219 + c!
1 smask 220 + c! 1 smask 221 + c! 1 smask 222 + c! 1 smask 223 + c!
1 smask 224 + c! 1 smask 225 + c! 1 smask 226 + c! 1 smask 227 + c!
1 smask 228 + c! 1 smask 229 + c! 0 smask 230 + c! 0 smask 231 + c!
0 smask 232 + c! 0 smask 233 + c! 1 smask 234 + c! 1 smask 235 + c!
1 smask 236 + c! 1 smask 237 + c! 1 smask 238 + c! 1 smask 239 + c!
1 smask 240 + c! 1 smask 241 + c! 1 smask 242 + c! 1 smask 243 + c!
1 smask 244 + c! 1 smask 245 + c! 1 smask 246 + c! 0 smask 247 + c!
0 smask 248 + c! 0 smask 249 + c! 1 smask 250 + c! 1 smask 251 + c!
1 smask 252 + c! 1 smask 253 + c! 1 smask 254 + c! 1 smask 255 + c!
;
\ Pointer
variable m-oldx 0 m-oldx !
variable m-oldy 0 m-oldy !
variable goodptr false goodptr !
\ Window
160 value w-w
120 value w-h
w-w w-h * buffer: wbuf
w-w w-h * buffer: wbufbs
variable w-oldx 100 w-oldx !
variable w-oldy 100 w-oldy !
variable todowin false todowin !
\ Button
variable inbutton false inbutton !
variable bcleanup false bcleanup !
variable b_shutdown_x
variable b_shutdown_y
0 value myscreen
" screen" open-dev to myscreen
0 value mymouse
" mouse" open-dev to mymouse
0 0 0 0 " color!" myscreen $call-method
255 255 255 1 " color!" myscreen $call-method
: ofw-readrect ( addr x y w h -- ) " read-rectangle" myscreen $call-method ;
: ofw-drawrect ( addr x y w h -- ) " draw-rectangle" myscreen $call-method ;
: ofw-fillrect ( color x y w h -- ) " fill-rectangle" myscreen $call-method ;
: ofw-getmevent ( msec -- pos.x pos.y buttons true|false )
" get-event" mymouse $call-method ;
\ Font stuff ...
\ Starts from (x, y) = (4 * 6, 6 + 6 + 11) = (24, 23)
\ =
\ _ok
\ =
\ 0_>_0123...
\
\ ASCII 32 (sp) to 126 (~) decimal
\
." ! #$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
cr cr
32 value ascii_min
126 value ascii_max
char-height char-width * 8 * value fontsz
variable fontbuffer
53248 alloc-mem
fontbuffer !
95
0
do
fontbuffer @ fontsz i * + i char-width * 4 char-width char-height ofw-readrect
loop
erase-screen
variable glstring
variable glx
variable gly
: validate_char ( char -- char )
dup
ascii_min
<
if
drop
ascii_min
else
dup
ascii_max
>
if
drop
ascii_max
then
then
;
: puts ( string x y -- )
gly !
glx !
0
rot
glstring !
do
glstring @ i + c@
validate_char
32 -
fontsz *
fontbuffer @ +
glx @ i char-width * +
gly @
char-width
char-height
ofw-drawrect
loop
;
: isxin ( x1 x w -- bool )
2 pick ( x1 x w x1 )
2 pick ( x1 x w x1 x)
< if
3drop false
else
( x1 x w )
2 pick ( x1 x w x1 )
\ 16 +
2 pick ( x1 x w x1 x )
2 pick ( x1 x w x1 x w )
+ \ width
> if
3drop false
else
3drop true
then
then
;
: isin ( x1 y1 x y w h -- bool )
5 pick ( x1 y1 x y w h x1 )
4 pick ( x1 y1 x y w h x1 x )
3 pick ( x1 y1 x y w h x1 x w )
isxin
false
= if
3drop 3drop false
else
4 pick ( x1 y1 x y w h y1 )
3 pick ( x1 y1 x y w h y1 y )
2 pick ( x1 y1 x y w h y1 y h )
isxin
false
= if
3drop 3drop false
else
3drop 3drop true
then
then
;
: create-buttons ( -- )
screen-width 64 - 2 - b_shutdown_x !
screen-height 0 2 + b_shutdown_y !
0 b_shutdown_x @ b_shutdown_y @ 64 24 ofw-fillrect
1 b_shutdown_x @ 1 + b_shutdown_y @ 1 + 62 22 ofw-fillrect
" Shut Down" b_shutdown_x @ 2 + 3 + b_shutdown_y @ 6 + puts
;
: create-window ( x y )
2dup ( x y x y )
wbufbs -rot ( x y wbufbs x y )
w-w w-h ofw-readrect
2dup ( x y x y )
0 -rot ( x y 1 x y )
w-w w-h ( x y 1 x y w-w w-h )
ofw-fillrect ( x y )
2dup ( x y x y )
1 -rot
2 + swap
2 + swap
w-w 4 -
19
ofw-fillrect ( x y )
2dup ( x y x y )
0 -rot
4 + swap
4 + swap
15
15
ofw-fillrect ( x y )
2dup ( x y x y )
1 -rot
6 + swap
6 + swap
11
11
ofw-fillrect ( x y )
2dup ( x y x y )
1 -rot
23 + swap
2 + swap
w-w 4 -
w-h 25 -
ofw-fillrect ( x y )
2dup ( x y x y )
0 -rot
24 + swap
3 + swap
w-w 6 -
w-h 27 -
ofw-fillrect
5 1 do
2dup
0 -rot
4 i * + swap
23 + swap
w-w 28 -
2
ofw-fillrect
loop
2dup
1 -rot
32 + swap
6 + swap
w-w 12 -
char-height 3 *
ofw-fillrect
" Screen Resolution"
3 pick
3 pick
34 + swap
8 + swap
puts
screen-width (u.) ( x y s l )
3 pick ( x y s l x )
3 pick ( x y s l x y )
36 + char-height + swap ( x y s l y' x )
8 + swap ( x y s l x' y' )
puts
" x "
3 pick
3 pick
36 + char-height + swap
8 + 4 char-width * + swap
puts
screen-height (u.)
3 pick
3 pick
36 + char-height + swap
8 + 7 char-width * + swap
puts
wbuf -rot w-w w-h ofw-readrect
;
: ofwindows ( -- )
cr ." Press control-z to quit the Open Firmware Windows demo." cr
load-cmask
load-smask
create-buttons
oldbg m-oldx @ m-oldy @ m-w m-h ofw-readrect
100 100 create-window
begin
0
ofw-getmevent
true = ( pos.x pos.y buttons true|false true = )
if
0 = ( pos.x pos.y buttons 0 = )
if
goodptr @ true =
if
true todowin !
then
false goodptr !
2dup ( pos.x pos.y )
m-oldy @ + swap
m-oldx @ + swap
b_shutdown_x @
b_shutdown_y @
64 24
isin
true =
if
inbutton @ false =
if
\ create border
0 b_shutdown_x @ b_shutdown_y @ 1 - 64 1 ofw-fillrect
0 b_shutdown_x @ b_shutdown_y @ 24 + 64 1 ofw-fillrect
true inbutton !
then
else
inbutton @ true =
if
\ uncreate border
1 b_shutdown_x @ b_shutdown_y @ 1 - 64 1 ofw-fillrect
1 b_shutdown_x @ b_shutdown_y @ 24 + 64 1 ofw-fillrect
false inbutton !
true bcleanup !
then
then
else
2dup ( pos.x pos.y )
m-oldy @ + swap
m-oldx @ + swap
b_shutdown_x @
b_shutdown_y @
64 24
isin
true =
if
shut-down
then
goodptr @ false =
if
2dup ( pos.x pos.y pos.x pos.y )
m-oldy @ ( pos.x pos.y pos.x pos.y m-oldy )
+ ( pos.x pos.y pos.x newy )
swap ( pos.x pos.y newy pos.x )
m-oldx @ ( pos.x pos.y newy pos.x m-oldx )
+ ( pos.x pos.y newy newx )
swap ( pos.x pos.y newx newy )
w-oldx @ ( pos.x pos.y newx newy m-oldx )
w-oldy @ ( pos.x pos.y newx newy m-oldx m-oldy )
w-w ( pos.x pos.y newx newy m-oldx m-oldy w )
20 ( pos.x pos.y newx newy m-oldx m-oldy w 20 )
isin ( pos.x pos.y tf? )
goodptr ! ( pos.x pos.y )
goodptr @ true =
if
true todowin !
else
false todowin !
then
then
then
oldbg ( pos.x pos.y oldbg )
m-oldx @ ( pos.x pos.y oldbg m-oldx )
m-oldy @ ( pos.x pos.y oldbg m-oldx m-oldy )
m-w ( pos.x pos.y oldbg m-oldx m-oldy m-w )
m-h ( pos.x pos.y oldbg m-oldx m-oldy m-w m-h )
ofw-drawrect ( pos.x pos.y )
bcleanup @ true =
if
1 b_shutdown_x @ b_shutdown_y @ 1 - 64 1 ofw-fillrect
1 b_shutdown_x @ b_shutdown_y @ 24 + 64 1 ofw-fillrect
false bcleanup !
then
todowin @ true =
if
goodptr @ false =
if
false todowin !
then
wbufbs
w-oldx @
w-oldy @
w-w
w-h
ofw-drawrect
2dup
w-oldy @ +
swap
w-oldx @ +
swap
2dup
w-oldy !
w-oldx !
wbufbs
-rot
w-w
w-h
ofw-readrect
wbuf
w-oldx @
w-oldy @
w-w
w-h
ofw-drawrect
then
2dup ( pos.x pos.y pos.x pos.y )
oldbg ( pos.x pos.y pos.x pos.y oldbg )
-rot ( pos.x pos.y oldbg pos.x pos.y )
m-oldy @ + ( pos.x pos.y oldbg pos.x newy )
swap ( pos.x pos.y oldbg newy pos.x )
m-oldx @ + ( pos.x pos.y oldbg newy newx )
swap ( pos.x pos.y oldbg newx newy )
m-w m-h ( pos.x pos.y oldbg newx newy m-w m-h )
ofw-readrect ( pos.x pos.y )
m-dim 0 do
oldbg i + c@ ( pos.x pos.y scrnbg[i] )
smask i + c@ ( pos.x pos.y scrnbg[i] ptrand[i] )
and ( pos.x pos.y s&p )
cmask i + c@ ( pos.x pos.y s&p ptrxor[i] )
xor ( pos.x pos.y s&p^P )
scrnbg i + c! ( pos.x pos.y )
loop
scrnbg ( pos.x pos.y scrnbg )
-rot ( scrnbg pos.x pos.y )
m-oldy @ ( m-color-ptr pos.x pos.y m-oldy )
+ ( m_color pos.x newy )
swap ( m-color-ptr newy pos.x )
m-oldx @ ( m-color-ptr newy pos.x m-oldx )
+ ( m-color-ptr newy newx )
swap ( m-color-ptr newx newy )
2dup ( m-color-ptr newx newy newx newy )
m-oldy ! ( m-color-ptr newx newy newx )
m-oldx ! ( m-color-ptr newx newy )
m-w m-h ( m-color-ptr newx newy m-w m-h )
ofw-drawrect
then
again
;
BIOS OR Itanium-64 need other links go to SITE MAP |
Bisnowden,3330 Adeline st. Berkeley,Ca94703 or send to bisnowden@yahoo.com Tele 510-595-1332send mail to
about this web site.
|