Contact US

Creating a Corporation

May

 

SITE MAP

Class Training For Pc Repair

A Plus Guide

A plus Os

LAPTOPS

 

X86 Tech

January

February

March

Osi

auto parts

Winserver8

windows7

 

Virtualization

Cloud Computing

Security

Cash fast

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 INT 0x13). Note that this is similar to many erstwhile Apple systems where the Macintosh ROM contained both low-level code (such as for hardware initialization, diagnostics, drivers, etc.) and the higher level "Toolbox" -- a collection of reusable software routines.

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:

bulletx86 computers always come up in the IA-32 "real mode" -- an emulation of the ancient 80886/8088 Intel processors. The BIOS executes in this mode, which is severely limited (particularly for an ambitious BIOS, say, one that wants to provide a powerful pre-boot environment). Effective memory addresses in real mode are calculated by multiplying the segment (a 16-bit number) by 16, and adding the offset (another 16-bit number) to it. Thus, a segment is 16-bits wide -- restricted to 65,536 bytes (64 KB), and a memory address is 20-bits wide -- restricted to 1,048,576 bytes (1 MB). In particular, the IP (instruction) register is also 16-bits wide -- placing a 64 KB size limit on the code segment. Memory is a very limited resource in real mode.

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.

bulletA BIOS usually has hardcoded knowledge of supported boot devices. Support for booting off "newer" devices gets added to most BIOSs very slowly, if at all.
bulletAn "option ROM" is firmware usually residing on a plug-in card (but may also live on the system board). It is executed by the BIOS during platform initialization. The legacy option ROM space is limited to 128 KB: shared by all option ROMs. An option ROM typically compacts itself by getting rid of some initialization code (leaving behind a smaller runtime code). Nevertheless, this is a severe limitation.
bulletLegacy BIOS depends on VGA, which is a legacy standard, and is unnecessarily complicated to program for.
bulletThe PC partitioning scheme is tied to the BIOS, and is rather inadequate, particularly when it comes to multibooting, or having a large number of partitions. PC partitions may be primary, extended, or logical, with at most 4 primary partitions allowed on a disk. The first (512-byte) sector of a PC disk, the Master Boot Record (MBR), has its 512 bytes divided as follows: 446 bytes for bootstrap code, 64 bytes for four partition table entries of 16 bytes each, and 2 bytes for a signature. Thus, the size of a PC partition table is rather limited, hence the limit on the number of primary partitions. However, one of the primary partitions may be an extended partition, and an arbitrary number of logical partitions could be defined within it. Note that Apple's partitioning scheme is much better in this regard.
bulletEven with standards like PXE and related security enhancements such as Boot Integrity Services (BIS), it is rather difficult, and often impossible, to deploy and manage computers in a "zero-touch" fashion, particularly when it comes to remote management at the system firmware level, or of the system firmware itself.

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 Problem

64-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 Beginning

64-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:

bulletInterruption entry points such as those invoked by hardware events (processor reset, processor initialization, machine checks, etc.)
bulletProcedures that can be invoked by the operating system or higher level firmware, such as procedures for obtaining processor identification, configuration, capability information, cache initialization, enabling and disabling processor features.

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 Interface

The 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:

bulletEFI device drivers
bulletEFI diagnostics and system utilities
bulletEFI shell
bulletOperating system loaders
bulletOperating systems

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 Services

There 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 ExitBootServices() function, after which boot services will not be available. Alternatively, an operating system kernel could call this function.

Runtime services are available both before and after ExitBootServices(). This category includes services for:

bulletManaging variables (key-value pairs)
bulletManaging hardware time devices
bulletVirtual memory (for example, to allow an operating system loader, or an operating system, to invoke runtime services with virtual memory addressing instead of physical addressing)
bulletRetrieving the platform's monotonic counter
bulletResetting the system

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 Drivers

EFI 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:

bulletBus Drivers (manage and enumerate bus controllers, such as a PCI Network Interface Controller -- installed onto the bus's controller handle)
bulletHybrid Drivers (manage and enumerate bus controllers, such as a SCSI Host Controller -- installed onto the bus's controller handle and the bus's child handles)
bulletDevice Drivers (manage controllers or peripheral devices, such as a PS/2 or USB keyboard)

Drivers that may not conform to the EFI Driver Model include:

bulletInitializing Drivers (perform one-time initialization functions)
bulletInitializing Drivers (perform one-time initialization functions)
bulletRoot Bridge Drivers (manage part of the core chipset)
bulletService Drivers (provides services to other EFI drivers, such as the decompression protocol and the EFI Byte Code Virtual Machine)
bulletOlder EFI drivers

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.)

Benefits

EFI aims to be a powerful and modular firmware that is readily extensible, even by (power) users. Some noteworthy aspects of EFI include:

bulletEFI is implementation agnostic.
bulletEFI does not require real mode.
bulletEFI runs in a flat memory model, with the entire address space being addressable.
bulletEFI is written in C. Therefore, it is both easy to write and portable.
bulletEFI does not place a restriction on the total size of option ROMs. EFI drivers can be loaded anywhere in the EFI address space.
bulletEFI aims to replace VGA over time with simple graphics primitives courtesy the Universal Graphics Adapter (UGA).
bulletEFI includes an optional shell that gives the user a lot of freedom and flexibility.
bulletThe pre-boot environment provided by EFI has a BSD socket compatible network interface, with a port of the FreeBSD TCP/IPv4 protocol stack.
Preeminence of Pre-boot

As 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 Environment

Following is a "site map" of a hypothetical user-visible EFI environment you may be presented with on an EFI-based machine:

(o) Power On | +-+ Boot Manager | +-+ Device Path(s) To OS Loader(s) | | | +-- Windows XP-64 | +-- Linux IA-64 | +_+ Boot Maintenance | | | +-- Change Boot Order | +-- Boot From Specified File | +-- Add Boot Options | +-- Select Console I/O | +-+ Launch EFI Shell | +-- Various shell functions

EFI Shell

The EFI environment (optionally) includes an interactive shell that allows a user to do a wide variety of tasks:

bulletLaunch other EFI programs.
bulletLoad, test, and debug drivers manually (you can also load a ROM image).
bulletView or manipulate memory and hardware state.
bulletManage system variables.
bulletManage files.
bulletDo text editing.
bulletRun shell scripts.
bulletAccess the network, say, via Ethernet or a dial-up connection.

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 Scheme

EFI 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:

bullet64-bit LBA (thus, disk offsets are 64-bit).
bulletSupports many partitions (without resorting to nesting schemes like "extended" partitions).
bulletUses version number/size fields for future expansion.
bulletUses CRC32 fields for improving data integrity.
bulletEach partition contains a 36 Unicode character human readable name.
bulletUses a GUID and attributes to define partition content type (note that tagging each partition with a GUID makes relocation easier).
bulletUses a primary and backup table for redundancy.

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.

GUIDs

A 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 diskpart (disk partitioning tool), efifmt (formatting tool), and efichk (disk checking tool).

fs0:\diskutils> diskpart ... DiskPart> select 0 Selected Disk = 0 DiskPart> inspect Selected Disk = 0 ### BlkSize BlkCount --- ------- ---------------- * 0 200 167CA00 0: EFISYS C13A7328-F81F-11D2 = EFISYS 34D22C00-1DD2-1000 @ 0 22 - C8021 1: MSDATA EBD0A0A2-B9E5-4432 = MSDATA 1845F401-1DD2-1000 @ 0 C8022 - 167C9DE

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:

bulletAs a fallback when the regular driver is corrupt or missing from the operating system.
bulletAs the primary driver in machines where graphics performance is irrelevant, such as a server.
bulletIn certain operating system modes such as "safe" and "panic".
bulletFor displaying graphical elements when the primary driver may not be available temporarily, such as during operating system installation, early startup, hibernation, etc.

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 Code

Option 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) sizeof(void *). This allows EFI byte code to execute seamlessly on 64-bit and 32-bit systems.

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 EFI

It 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:

bulletMicrosoft Windows XP (or 2000)
bulletMicrosoft Visual Studio .NET (2003 or 2002)
bulletIntel EFI Application Toolkit (downloadable from Intel)

EFI emulation under Windows should allow for convenient application development and debugging.

Following is source for an example EFI program, hanoi.efi, that solves Towers of Hanoi. You can build the program in an environment similar to the one described above. You can run it from the EFI shell. Refer to instructions in the README file within the source archive for details.

Download

Source for Towers of Hanoi in the EFI environment.

fs1:\> ls Directory of: fs1:\ 06/12/04 05:11a 15,872 hanoi.efi 1 File(s) 15,872 bytes 0 Dir(s) fs1:\> hanoi usage: hanoi N Exit status code: Invalid Parameter fs1:\> hanoi 3 move 1 --> 3 move 1 --> 2 move 3 --> 2 move 1 --> 3 move 2 --> 1 move 2 --> 3 move 1 --> 3

You can also develop EFI applications for IA-64 and x86 using the GNU toolchain on Linux. You need:

bulletGNU CC 3.x
bulletA recent version of objcopy, specifically, one that supports efi-app-ia32 (for x86) or efi-app-ia64 (for IA-64) as targets.
bulletgnu-efi, the GNU EFI package.

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 objcopy) into PE32+. The EFI specific crt0's _start function calls a relocator function, followed by a call to efi_main. Compiling an EFI application on Linux looks like the following:

# Compile position independent, force wide characters to shorts % gcc -I/usr/include/efi/ia32 -fpic -fshort-wchar -c hanoi.c # Use EFI specific linker script % ld -Bsymbolic --no-check-sections -nostdlib -L/usr/lib \ -T elf_ia32_efi.lds -shared /usr/lib/crt0-efi-ia32.o \ -o hanoi.so hanoi.o -lefi -lgnuefi \ /usr/lib/gcc-lib/i486-linux/3.3.3/libgcc.a # Copy specified sections to target % objcopy --target=efi-app-ia32 -j .text -j .sdata -j .data \ -j .dynamic -j .dynsym -j .rel -j .rela -j .reloc \ hanoi.so hanoi.efi

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]

Accepted connotations of the word "Innovate": Innovate [1] To introduce something new. Innovate [2] To introduce something as if new. - Some dictionary.

EFI has been described grandiloquently by Marketing, understandably. Phrases such as "Application Development Meets Firmware" and "Nothing Similar Existed Before" have been used to qualify and quantify EFI's importance. It is path-breaking. I agree that it finally gets rid of several painful issues with legacy BIOS in one blow.

It should still be a few years before we should see widespread adoption and deployment of EFI.

Now, I must point out that something "similar" has existed in the non-PC world for over 15 years: Open Firmware, which first shipped in 1989. In my opinion, EFI could be considered a new-generation implementation of the philosophy of Open Firmware. It has more features, and does several things better than Open Firmware, but it would be strange if it did not, with 15 years of hindsight!

Let me add something that I find remarkable: I have not seen a single reference to Open Firmware in any EFI specification, presentation, whitepaper, or related document. Perhaps I did not look hard enough. This is not a criticism though. Some might argue that EFI's pathbreaking-ness is valid in the context of PCs, so it is appropriate not to mention prior similar ideas.

 

Open Firmware

We discuss Open Firmware briefly in the following section. More details on interacting with Open Firmware may be found in Booting Mac OS X.

Background

Open 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:

bulletThe Open Firmware software architecture is defined by IEEE Standard for Boot (Initialization Configuration) Firmware, also known as IEEE-1275. Thus, the standard is open to all and anybody may create an implementation.
bulletThe architecture is independent of the underlying instruction set, bus, operating system, and so on. However, the core requirements and practices specified by the standard are augmented by platform-specific requirements. For example, processors such as PowerPC and SPARC, or buses such as PCI and Sun's SBus, have their own requirements and bindings. The union of the core and platform-specific requirements provides a complete firmware specification for that platform.
bulletOpen Firmware exposes various interfaces, such as one for interaction with an end user, another for use by an operating system, and yet another for use by developers of plug-in devices. Open Firmware presents a machine's various hardware components and their interconnections as a hierarchical data structure: the Device Tree.
bulletAn Open Firmware implementation is based on the Forth programming language, in particular, the FCode dialect. FCode is an American National Standards (ANS) compliant dialect that supports compilation of source to machine-independent bytecode. This allows for FCode drivers to be used on different platforms. Moreover, FCode bytecodes need less storage space (than text strings), and are evaluated faster (as compared to Forth text). An FCode evaluator is a part of the PROM resident firmware implementation.
bulletOpen Firmware is modular in the sense that many features of the architecture are optional for an implementation. Moreover, if certain plug-in devices are required at boot-time, the expansion ROMs on the cards for such devices usually contain FCode-based drivers. As an Open Firmware equipped machine is powered-on, the main ROM begins execution; it probes both on-board and plug-in devices, as part of which the FCode programs on the plug-in ROMs are also executed. Consequently, such plug-in device drivers become part of the Open Firmware environment. A plug-in FCode driver's references to procedures in the main firmware are resolved in a linking process similar to one involving shared libraries in a traditional environment. Note that FCode is position-independent.
bulletOpen Firmware provides access to the filesystem and limited access to the network.
bulletOpen Firmware provides useful facilities for diagnosing hardware, and for debugging its own programs as well as the operating system.
Interaction

You can enter Open Firmware by pressing the key combination cmd-opt-O-F just as you power on a Macintosh. The cmd key is the one with the Apple logo, and the opt (option) key is the same as the alt key. You should see a welcome message and some other verbiage, and should be dropped into a prompt like the following:

ok 0 >

You can continue booting the machine by typing mac-boot, or shut it down by typing shut-down.

For more details on Open Firmware, refer to Booting Mac OS X.

Others

Let us take a quick look at some other firmware related efforts.

Open Source

There 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, LOBOS (Linux OS Boots OS), to boot a new Linux kernel from a running Linux kernel -- without going into real-mode, and without using the BIOS. Thus, LinuxBIOS can be used as a network bootstrapper, and even as a BIOS replacement.

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:

bulletDevice-level protection of Flash ROM integrity
bulletEmbedded cryptography engine
bulletSecure authentication and launching of pre-OS anti-virus and system recovery applications
bulletTrusted Computing support
bulletNetwork based management
bulletA firmware development environment based on Microsoft Visual Studio .NET

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 Windows

The 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:

bulletCreates a mouse pointer using the standard AND-XOR mask technique.
bulletCreates a window with a rudimentary title bar. The window contains text representing the screen's resolution in pixels.
bulletCreates a backing store for repairing damage to the portion of the screen under our window.
bulletCreates a clickable button for shutting down the computer.
Usage

The following example demonstrates how to "boot" into a window-drawing demo from the Open Firmware prompt, assuming the program file (called ofwindows, say) resides in user amit's home directory on the default hard disk:

0 > boot hd:\Users\amit\ofwindows ... ok 0 > ofwindows Press control-z to quit the Open Firmware Windows demo. ...

\ 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

home B & I SNOWDEN-Find a Wealth of Products and Services

   Bisnowden,3330 Adeline st. Berkeley,Ca94703 or send to bisnowden@yahoo.com Tele 510-595-1332
send mail to bisnowden@yahoo.com with questions or comments
  about this web site.

Last modified: July 07, 2011