Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:olh:xen-4.16
qemu-2.6
_service:obs_scm:sgabios-23d474943dcd55d0550a3d...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:obs_scm:sgabios-23d474943dcd55d0550a3d20b3d30e9040a4f15b.obscpio of Package qemu-2.6
07070100000000000081A40000000000000000000000014BCF925C00002C5E000000000000000000000000000000000000003900000000sgabios-23d474943dcd55d0550a3d20b3d30e9040a4f15b/COPYING Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 07070100000001000081A40000000000000000000000014BCF925C0000072A000000000000000000000000000000000000003A00000000sgabios-23d474943dcd55d0550a3d20b3d30e9040a4f15b/Makefile# Copyright 2010 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # $Id$ BUILD_DATE = \"$(shell date -u)\" BUILD_SHORT_DATE = \"$(shell date -u +%D)\" BUILD_HOST = \"$(shell hostname)\" BUILD_USER = \"$(shell whoami)\" CFLAGS := -Wall -Os -m32 -nostdlib ASFLAGS := $(CFLAGS) ASFLAGS += -DBUILD_DATE="$(BUILD_DATE)" ASFLAGS += -DBUILD_SHORT_DATE="$(BUILD_SHORT_DATE)" ASFLAGS += -DBUILD_HOST="$(BUILD_HOST)" ASFLAGS += -DBUILD_USER="$(BUILD_USER)" LDSCRIPT := rom16.ld LDFLAGS := -T $(LDSCRIPT) -nostdlib OBJCOPY := objcopy ASRCS = sgabios.S CSRCS = SRCS = $(CSRCS) $(ASRCS) OBJS = ${CSRCS:.c=.o} ${ASRCS:.S=.o} INCS = ${CSRCS:.c=.h} ${ASRCS:.S=.h} PROGS = sgabios.bin csum8 .SUFFIXES: .bin .elf .PHONY: buildinfo all: $(PROGS) sgabios.bin: sgabios.elf $(OBJCOPY) -O binary $< $@ ./csum8 $@ sgabios.elf: .depend $(OBJS) $(LDSCRIPT) csum8 $(LD) $(LDFLAGS) $(OBJS) -o $@ csum8: csum8.c $(CC) -Wall -O2 -o $@ $< sgabios.o: buildinfo buildinfo: touch sgabios.S clean: $(RM) $(PROGS) $(OBJS) *.elf *.srec *.com version.h .depend:: $(INCS) $(SRCS) Makefile $(RM) .depend $(CPP) -M $(CFLAGS) $(SRCS) >.tmpdepend && mv .tmpdepend .depend ifeq (.depend, $(wildcard .depend)) include .depend else # if no .depend file existed, add a make clean to the end of building .depend .depend:: $(MAKE) clean endif 07070100000002000081A40000000000000000000000014BCF925C00000686000000000000000000000000000000000000003900000000sgabios-23d474943dcd55d0550a3d20b3d30e9040a4f15b/csum8.c/* * Copyright 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * compute rom checksum byte */ #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <fcntl.h> #include <sys/types.h> #define MAX_SIZE 65536 unsigned char buf[MAX_SIZE]; int main(int argc, char **argv) { ssize_t fsize; int i, sum, fd; unsigned char csum; if (argc < 2) { fprintf(stderr, "usage: %s filename\n", argv[0]); exit(1); } if ((fd = open(argv[1], O_RDWR)) < 0) { perror(argv[1]); exit(1); } if ((fsize = read(fd, buf, MAX_SIZE)) < 0) { perror(argv[1]); exit(1); } if (fsize >= MAX_SIZE && read(fd, &buf[MAX_SIZE - 1], 1) > 0) { fprintf(stderr, "FAIL: %s is larger than %d bytes\n", argv[1], MAX_SIZE); exit(1); } i = fsize - 2048 * (fsize / 2048); if (i != 2047) { fprintf(stderr, "FAIL: %s is %zd bytes, need 2K pad-1\n", argv[1], fsize); exit(1); } for (i = sum = 0; i < fsize; i++) { sum += buf[i]; } sum &= 0xff; csum = -sum & 0xff; write(fd, &csum, 1); close(fd); fprintf(stderr, "%s: sum = 0x%02x, wrote byte 0x%02x\n", argv[1], sum, csum); return 0; } 07070100000003000081A40000000000000000000000014BCF925C0000362B000000000000000000000000000000000000003C00000000sgabios-23d474943dcd55d0550a3d20b3d30e9040a4f15b/design.txt============================================= Google Serial Graphics Adapter BIOS (SGABIOS) Copyright 2007 Google Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ============================================= Status: Implemented (as of 2007-08-08) Nathan Laredo <nil@google.com> Modified: 2008-02-14 13:45 PDT Objective --------- The Google Serial Graphics Adapter BIOS or SGABIOS provides a means for legacy pc software to communicate with an attached serial console as if a vga card is attached. Background ---------- The headless server problem When building a lot of systems for data center use, it makes no sense to install hardware that will rarely if ever be used. Graphics adapters are not very useful even if they are installed in a data center environment since often the person interested in seeing the output is separated from the device by tens to thousands of miles. While it's possible to use remote management hardware that provides a remotely accessible display and keyboard, this hardware is much more expensive than the hardware that it replaces, and often this hardware sends only images of the display rather than something suitable for logging. Since most systems already have a serial port, it's an obvious target as a replacement for the primary display and keyboard. The problem is that while an operating system like Linux can support this arrangement, all of the output that would normally appear on a graphics adapter before Linux boots is lost on modern x86 hardware without modifications to the system firmware. While some vendors provide firmware that enables the serial port to be used as the primary display, this is usually a "premium" option and isn't universally available for all x86 platforms. Often such services aren't implemented in a way that is friendly to saving logs of boot activity. One particularly ugly implementation might send the same text hundreds of times as it tries to refresh the entire display each timer tick. Others have ansi control sequences between every single character output which, while readable in a terminal, is almost unusable when referring to serial log files. Behavior like this slows down the serial output by up to fifteen times in some cases, using sometimes that many extra characters of control sequences for each character output. The need for detailed system logs None of the vendor-supplied serial redirection implementations include facilities for logging boot message for later capture by an operating system. Being able to refer to the boot messages after an operating system has loaded, or having a history of such messages can be a useful debug, analysis, and management feature. Even on systems with graphics adapters attached, once the display is scrolled or refreshed with enough new text, the old messages are only available in the user's own brain, which often isn't very good at accurately recalling more than two or three items that aren't grammatically meaningful in the user's native language. Overview --------- SGABIOS is designed to be inserted into a bios as an option rom to provide over a serial port the display and input capabilites normally handled by a VGA adapter and a keyboard, and additionally provide hooks for logging displayed characters for later collection after an operating system boots. It is designed to handle all text mode output sent to the legacy bios int 10h service routine. Int 10h is the most common method for displaying characters in 16-bit legacy x86 code. Occasionally some code may write directly to the vga memory in the interest of "speed," and this output will be missed, but it's rather uncommon for any code involved in booting a system to be concerned with the speed of display output. SGABIOS is not designed to handle these cases since those applications that make such assumptions generally write to an area of memory that typically already in use for system management mode and unusable outside of that mode. Paging tricks could be used to capture such output, but enabling paging requires protected mode to be enabled which instantly breaks all segment loads in legacy 16-bit real- mode code (which is the traditional boot environment). Detailed Design ---------------- VGA BIOS int 10h is hooked and chained to any existing handler or the default handler that the BIOS previously setup. During initialization, the option rom also probes the serial port for reply from an attached terminal. If the terminal replies to a specific sequence, the terminal size is recorded and used for all future display calculations. If a VGA card is attached at the same time, the width of the terminal is limited to 80 columns in order to have sensible output on both the VGA card and on the serial console. If no reply comes from the serial terminal within a very short timeout of about 8 milliseconds (or more accurately, 65536 reads of the serial status port), a default size of 80x24 is used. The detected size is displayed at the end of option rom init to the serial console. Because of the way the cursor is updated, if the cursor is never moved upwards or more than one line down by int 10h calls, output will still be appear completely appropriate for whatever sized terminal is attached but failed to get detected. Whenever int 10h is invoked, SGABIOS gets control first and decides whether to act based on register state. With the exception of functions for getting current mode info or the current cursor position, whether it acts or not, register state is ultimately restored to the state on entry and a far jump is made to the original handler. SGABIOS maintains two active cursor positions. One contains the traditional VGA cursor position at the traditional location in the BIOS Data Area, while the other maintains the position the serial console's cursor is located. The serial cursor position is located in a BDA location that traditionally contains the base io port address for LPT3, but since builtin printer ports are disappearing over time, this location is reused. These two values will often differ since serial terminal output will always move the cursor to the next position on the screen while many VGA operations don't update the cursor position at all, or some only at the start of the string, but leave the old value at the end. Keeping track of two active cursor positions means that SGABIOS can collapse a string of "set cursor" calls into perhaps a single one or none if the serial console cursor already happens to be at the target location. Cursor movements are further optimized by sending newline characters to move the cursor down one row, carriage return characters to move the cursor back to column 0, and backspace characters to send the cursor back one or two spaces. To avoid problems when a video card is connected, any Bios Data Area location that would be updated by a VGA card is left alone to be updated by the VGA card. SGABIOS will update the cursor position as usual, but just before chaining to an existing vga card's handler, it will restore the values to those on entry, and for those functions that return data, it will defer completely to the chained routines rather than taking those over as it does when no video card is detected. Cursor position updates to serial console are deferred until the next character of terminal output is available. This collapses the cases where the cursor is updated more than one time between each character output (this is surprisingly common). The goal of tracking the cursor so closely and minimizing the number of characters required to update the cursor position is to both to make the display of output as efficient and fast as possible and to allow one to grep a raw log of serial console output for text (which without such optimization may be impossible or extremely difficult with movement escape sequences between every character). In the same way cursor position is tracked, vga character attributes are tracked so that it's possible to minimize the number of times an attribute change escape sequence is sent to the serial console. A BIOS Data Area location traditionally used for storing the current palette value is used to store the last attribute sent to the serial console. As SGABIOS processes new calls, if the value is the same, after masking off bright background colors which aren't supported in ansi escape codes, then no attribute update is sent to the serial console, else an escape sequence is sent that gives the new background and foreground colors and whether the foreground is bold or not. Data communication Whenever the call is made to output text, SGABIOS first updates the serial terminal cursor to match the current position of the vga cursor (if necessary), outputs any attribute change if applicable to the particular int 10h call made, and finally sends the text character (or characters) out to the serial port, and then updates its own view of where the serial console cursor is located. After the text is sent, a logging routine is called to store that text in a private area of memory allocated at option rom init. For keyboard/terminal input, SGABIOS hooks bios int 16h which is typically called to poll for a keypress. Before passing the call along, SGABIOS looks for any pending input on the serial port and stuffs the keyboard buffer with any pending byte after translating it to a compatible keyboard scancode. If the character received is an escape, SGABIOS will continue to poll for up to four extra characters of input for several milliseconds in order to detect ANSI/VT100/xterm/etc cursor keys and function keys, looking up appropriate scancodes in a table of escape sequences for all known non-conflicting terminal types. SGABIOS also hooks the serial port interrupts, and on receiving an interrupt blocks out interrupts, calls the same polling routines as above, following the same processing of multi-byte input as well, stuffing the keyboard buffer as appropriate, and finally acknowledging the interrupt and returning from the handler. [ serial port interrupts are now DISABLED ] Optionally the serial port input/output can be replaced with a SMI trigger that calls into an EFI BIOS in order to tie into its own console input and output routines rather than directly hitting the serial port. In this particular case it's assumed that all logging is handled in the EFI module that will be called. BIOS int 15h, ax = 0d042h is used to trigger SMI. The parameters passed will need to be changed to be specific to the EFI or SMI handler put in place. In the example in SMBIOS, for output, ebx = 0xf00d0000 | (char << 8), and for input, ebx = 0xfeed0000, with the character, if any, returned in the eax register with ZF set and eax=0 if no character was available. Summary of new enhancements --------------------------- SGABIOS now keeps a log of the last 256 characters written to the screen and where they were written in the event an application like lilo asks for the current character under the cursor. These are currently stored in a 1KB EBDA allocation which can be expanded as needed. This method avoids having to store a 64KB buffer for the largest possible serial terminal supported (255x255). When lilo 22.6 is detected, SGABIOS now knows how to disable lilo's serial output in favor of its own. This avoids having double character output from both serial and VGABIOS interleaved. Possible future enhancements ---------------------------- Previous future ideas have now been implemented. Known Bugs ---------- With some versions of DOS, only the last character of every line is displayed once dos boots since DOS will use direct access to the VGA framebuffer until the end of line is reached, at which point it will start using int 10h. Dual cursor tracking might fix this issue by maintaining positions for dos that look like the end of line and another for internal use to know where to output next. Caveats ------- It may be possible for someone to construct a terminal reply for the terminal sizing code that is completely invalid and attempts to either setup variables to overrun buffers or else overruns the input buffer itself. This situation is currently handled by limiting the reply to between eight and fourteen characters and ignoring any values outside the range from ten to two hundred fifty-five for both the number of rows and the number of columns. In these situations a default size of 80x24 is used (unless a video card is present, in which case its size is used). If the resize code detects several unexpected characters during the terminal size detection, it currently assumes that someone has left a loopback device plugged into the serial port and redirects the serial input and output to the fourth serial port at 0x2e8. Security considerations ----------------------- None. This is already 16-bit real-mode x86 code. The entire system may be crashed or bent to do anyone's bidding at any time by any other running code outside of SGABIOS. Opensource Plan --------------- This source code was approved for release to the public for use under the Apache License, Version 2.0 on http://code.google.com/p/sgabios Document History ---------------- Date Author Description 2008-02-14 nil fix for release 2007-10-04 nil new features 2007-08-31 nil sga+vga fixes 2007-08-08 nil Initial version $Id$ 07070100000004000081A40000000000000000000000014BCF925C00000F1A000000000000000000000000000000000000003A00000000sgabios-23d474943dcd55d0550a3d20b3d30e9040a4f15b/rom16.ld/* * Linker script for ROM16 binaries */ /* Script for -z combreloc: combine and sort reloc sections */ OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") OUTPUT_ARCH(i386) EXTERN(_start) ENTRY(_start) SECTIONS { /* Read-only sections, merged into text segment: */ . = 0x0; PROVIDE (__executable_start = .); .init : { KEEP (*(.init)) } =0x90909090 .text : { *(.text .stub .text.* .gnu.linkonce.t.*) /* .gnu.warning sections are handled specially by elf32.em. */ *(.gnu.warning) } =0x90909090 .fini : { KEEP (*(.fini)) } =0x90909090 PROVIDE (__etext = .); PROVIDE (_etext = .); PROVIDE (etext = .); .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } .rodata1 : { *(.rodata1) } /* Ensure the __preinit_array_start label is properly aligned. We could instead move the label definition inside the section, but the linker would then create the section even if it turns out to be empty, which isn't pretty. */ . = ALIGN(4); PROVIDE (__preinit_array_start = .); .preinit_array : { *(.preinit_array) } PROVIDE (__preinit_array_end = .); PROVIDE (__init_array_start = .); .init_array : { *(.init_array) } PROVIDE (__init_array_end = .); PROVIDE (__fini_array_start = .); .fini_array : { *(.fini_array) } PROVIDE (__fini_array_end = .); PROVIDE (__ctors_start = .); .ctors : { KEEP (*(SORT(.ctors.*))) KEEP (*(.ctors)) } PROVIDE (__ctors_end = .); PROVIDE (__dtors_start = .); .dtors : { KEEP (*(SORT(.dtors.*))) KEEP (*(.dtors)) } PROVIDE (__dtors_end = .); /* Adjust the address for the data segment. Avoid mixing code and data within same 128-byte chunk. */ . = ALIGN(128); .data : { *(.data .data.* .gnu.linkonce.d.*) SORT(CONSTRUCTORS) } .data1 : { *(.data1) } _edata = .; PROVIDE (edata = .); __bss_start = .; .bss : { *(.dynbss) *(.bss .bss.* .gnu.linkonce.b.*) *(COMMON) /* Align here to ensure that the .bss section occupies space up to _end. Align after .bss to ensure correct alignment even if the .bss section disappears because there are no input sections. */ . = ALIGN(32 / 8); } .csum : { . = ALIGN(2048) - 5; LONG(0xff4c494e); /* BYTE(_rom_size_byte); */ } =0xffffffff _end = .; PROVIDE (end = .); PROVIDE(_rom_size_byte = (511 + end) / 512); /* Stabs debugging sections. */ .stab 0 : { *(.stab) } .stabstr 0 : { *(.stabstr) } .stab.excl 0 : { *(.stab.excl) } .stab.exclstr 0 : { *(.stab.exclstr) } .stab.index 0 : { *(.stab.index) } .stab.indexstr 0 : { *(.stab.indexstr) } .comment 0 : { *(.comment) } /* DWARF debug sections. Symbols in the DWARF debugging sections are relative to the beginning of the section so we begin them at 0. */ /* DWARF 1 */ .debug 0 : { *(.debug) } .line 0 : { *(.line) } /* GNU DWARF 1 extensions */ .debug_srcinfo 0 : { *(.debug_srcinfo) } .debug_sfnames 0 : { *(.debug_sfnames) } /* DWARF 1.1 and DWARF 2 */ .debug_aranges 0 : { *(.debug_aranges) } .debug_pubnames 0 : { *(.debug_pubnames) } /* DWARF 2 */ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } .debug_abbrev 0 : { *(.debug_abbrev) } .debug_line 0 : { *(.debug_line) } .debug_frame 0 : { *(.debug_frame) } .debug_str 0 : { *(.debug_str) } .debug_loc 0 : { *(.debug_loc) } .debug_macinfo 0 : { *(.debug_macinfo) } /* SGI/MIPS DWARF 2 extensions */ .debug_weaknames 0 : { *(.debug_weaknames) } .debug_funcnames 0 : { *(.debug_funcnames) } .debug_typenames 0 : { *(.debug_typenames) } .debug_varnames 0 : { *(.debug_varnames) } /DISCARD/ : { *(.note.GNU-stack) } } 07070100000005000081A40000000000000000000000014BCF925C00013CCB000000000000000000000000000000000000003B00000000sgabios-23d474943dcd55d0550a3d20b3d30e9040a4f15b/sgabios.S/* * Copyright 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "sgabios.h" #define BUILD_CL "$Id$" .code16 .text .section ".init","ax" .globl _start .type _start,@object _start: /* option rom header */ .byte 0x55 .byte 0xaa .byte _rom_size_byte .size _start, .-_start .globl legacy_entry .type legacy_entry,@function legacy_entry: jmp sga_init /* pnp entry here to avoid changing PnP table as code moves */ pnp_init: jmp pnp_sga_init /* * do_old_int10h * * Patched at option rom init to be a far jump to old int 10h isr * */ do_old_int10h: .byte 0xea /* jmp absolute segment:offset */ old_int10h: /* store what was at offset 0x40 */ .word 0xf065 /* placeholder for chained ISR offset */ /* if the chained segment is detected as 0xc000, use 80 cols only */ /* since it's assumed that a vga card is attached and 80 cols max */ old_int10h_seg: .word 0xf000 /* placeholder for chained ISR segment */ /* * do_old_int16h * * Patched at option rom init to be a far jump to old int 16h isr * */ do_old_int16h: .byte 0xea /* jmp absolute segment:offset */ old_int16h: /* store what was at offset 0x58 */ .word 0xe82e /* placeholder for chained ISR offset */ .word 0xf000 /* placeholder for chained ISR segment */ .org 0x18 .word 0 /* offset to PCI data, 0 = none */ .word pnp_table /* offset to PnP expansion header */ .org 0x20 pnp_table: /* FIXME: **** PnP header currently disabled by PoO **** */ /* legacy entry only called once, PnP entry called multiple times */ /* The code isn't yet written to deal with multiple inits properly */ .ascii "$PoO" /* PnP expansion header signature */ .byte 1 /* structure revision */ .byte 2 /* length in 16-byte increments */ .word 0 /* offset of next header, 0 if none */ .byte 0 /* reserved */ .byte 0x52 /* checksum - update manually! FIXME */ .long 0 /* device identifier */ .word mfg_string /* pointer to manufacturer string */ .word prod_string /* pointer to product name string */ .byte 3, 0x80, 0x80 /* device type code = other display */ .byte 0xe3 /* device indicators, kbd/display dev */ .word 0 /* boot connection vector, 0 if none */ .word 0 /* disconnect vector, 0 if none */ .word pnp_init /* bootstrap entry vector */ .word 0 /* reserved */ .word 0 /* static resource information vector */ /* WARNING: changing mfg_string / prod_string locations will */ /* affect pnp table above -- recalculate checksum manually! */ mfg_string: .asciz "Google, Inc." prod_string: .ascii "Serial Graphics Adapter " build_date: .asciz BUILD_SHORT_DATE long_version: .ascii "SGABIOS " .ascii BUILD_CL .ascii " (" .ascii BUILD_USER .ascii "@" .ascii BUILD_HOST .ascii ") " .asciz BUILD_DATE term_cols: .byte 80 /* overwritten at rom init with detected value */ term_rows: .byte 24 /* overwritten at rom init with detected value */ term_init_string: /* terminal reply: \033[n;mR n=row, m=col */ .asciz "\033[1;256r\033[256;256H\033[6n" /* reset the scroll, move to col 256, row 256, ask current position */ /* bios cursor positions >255 rows or cols can't be used anyway */ term_info: .asciz "Term: " ebda_info: .asciz "EBDA: " /* * do_old_irq3 - exception 0x0b, int 0x0a * * Patched at option rom init to be a far jump to old irq 3 isr * */ do_old_irq3: .byte 0xea /* jmp absolute segment:offset */ old_irq3: /* store what was at offset 0x28 */ .word 0xeef3 /* placeholder for chained ISR offset */ .word 0xf000 /* placeholder for chained ISR segment */ /* * do_old_irq4 - exception 0x0c, int 0x0b * * Patched at option rom init to be a far jump to old irq 4 isr * */ do_old_irq4: .byte 0xea /* jmp absolute segment:offset */ old_irq4: /* store what was at offset 0x2c */ .word 0xeef3 /* placeholder for chained ISR offset */ .word 0xf000 /* placeholder for chained ISR segment */ /* * do_old_int14h * * Patched at option rom init to be a far jump to old int 14h isr * */ do_old_int14h: .byte 0xea /* jmp absolute segment:offset */ old_int14h: /* store what was at offset 0x50 */ .word 0xe739 /* placeholder for chained ISR offset */ .word 0xf000 /* placeholder for chained ISR segment */ .align 16, 0xff /* aligning this table only makes hexdump prettier */ /* ascii -> scancode, bit 7=shifted, char < 32 = +ctrl */ /* except chars 8, 9, 13, 27 (bs, tab, enter, esc) */ /* most int16h consumers will probably never use */ ascii2scan: /*00*/ .byte 0x00, 0x1e, 0x30, 0x2e, 0x20, 0x12, 0x21, 0x22 /*08*/ .byte 0x0e, 0x17, 0x24, 0x25, 0x26, 0x1c, 0x31, 0x18 /*10*/ .byte 0x19, 0x0f, 0x13, 0x1f, 0x14, 0x16, 0x2f, 0x11 /*18*/ .byte 0x2d, 0x15, 0x2c, 0x01, 0x2b, 0x1b, 0x87, 0x8c /*20*/ .byte 0x39, 0x82, 0xa8, 0x84, 0x85, 0x86, 0x88, 0x28 /*28*/ .byte 0x8a, 0x8b, 0x89, 0x8d, 0x33, 0x0c, 0x34, 0x35 /*30*/ .byte 0x0b, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 /*38*/ .byte 0x09, 0x0a, 0xa7, 0x27, 0xb3, 0x0d, 0x34, 0xb5 /*40*/ .byte 0x83, 0x9e, 0xb0, 0xae, 0xa0, 0x92, 0xa1, 0xa2 /*48*/ .byte 0xa3, 0x97, 0xa4, 0xa5, 0xa6, 0xb2, 0xb1, 0x98 /*50*/ .byte 0x99, 0x90, 0x93, 0x9f, 0x94, 0x96, 0xaf, 0x91 /*58*/ .byte 0xad, 0x95, 0xac, 0x1a, 0x2b, 0x1b, 0x87, 0x8c /*60*/ .byte 0x29, 0x1e, 0x30, 0x2e, 0x20, 0x12, 0x21, 0x22 /*68*/ .byte 0x23, 0x17, 0x24, 0x25, 0x26, 0x32, 0x31, 0x18 /*70*/ .byte 0x19, 0x10, 0x13, 0x1f, 0x14, 0x16, 0x2f, 0x11 /*78*/ .byte 0x2d, 0x15, 0x2c, 0x9a, 0xab, 0x9b, 0xa9, 0x0e /* TABLES FOR NON-ASCII VGA CHARACTERS (CP437) TO ASCII */ /* Unicode at: http://en.wikipedia.org/wiki/Code_page_437 */ ctrl2ascii: /* translate vga (CP437) first 32 characters to ascii */ /* for char 0, update the cursor position, but output nothing */ /* lilo uses this "trick" for a background attribute update */ .ascii "\0@@v***........*><|!PS-|^v><L-^v" high2ascii: /* translate vga (CP437) chars 0x80 to 0xff to ascii */ /* these characters are mostly to visually approximate */ /* line art characters will probably need tweaking */ /*80*/ .ascii "CueaaaaceeeiiiAAEaAooouuyOUcLYPf" /*a0*/ .ascii "aiounNao?--24!<>###||||++||+++++" /*c0*/ .ascii "+--|-+||++--|-+----++++++++#-||-" /*e0*/ .ascii "abgpesut00osiye^=+><||-=...vn2* " colortable: /* vga text color is IRGB, ansi color is BGR */ /* this table is effectively a nibble bit-reverse */ .byte 0, 4, 2, 6, 1, 5, 3, 7 serial_port_base_address: .word COM_BASE_ADDR /* in-memory console log * * It's expected that the EBDA contains a magic signature * like 0xdeadbabe, followed by a byte of flags, followed * by a 32-bit buffer pointer, followed by a 16-bit start * index, followed by a 16-bit end index, followed by 16- * bit logged character count, followed by an 8-bit flag. */ #define MEMCONSOLE_BUFFER_SIZE 32768 #define MEMCONSOLE_SIGNATURE 0xdeadbabe #define MEMCONSOLE_ENDINDEX_OFF 0x0b #define SGABIOS_EBDA_SIGNATURE 0x00414753 memconsole_buffer_start: /* pulled from ebda struct */ .long 0x00000000 /* 0 = not found/no logging */ memconsole_ebda_deadbabe_offset: /* bytes from start of ebda */ .word 0x0000 /* 40:0e contains ebda seg */ sgabios_ebda_logbuf_offset: /* bytes from start of ebda */ .word 0x0000 /* 40:0e contains ebda seg */ /* * setup_memconsole * * Initialize the option rom variables associated with logging * of the legacy console output * * If these variables are left at zero, no logging will occur * * There are no parameters * All registers except flags should be preserved */ setup_memconsole: pushaw pushw %ds pushw %es pushw $BDA_SEG popw %ds /* ds = 0x40 */ pushw BDA_EBDA /* push word at 0x0e */ popw %es /* es = EBDA_SEG */ /* search for memconsole signature in ebda */ movl $MEMCONSOLE_SIGNATURE, %eax xorw %di, %di /* start at zero */ movzbw %es:(%di), %cx /* cx = size of EBDA in KB */ shlw $8, %cx /* cx = (cx * 1024) / 4 */ cld repnz scasl /* search until sig found */ subw $4, %di /* scasl always increments di, undo */ cmpl %eax, %es:(%di) /* is signature here? */ jnz setup_memconsole_end /* bail if so */ movw %di, %cs:memconsole_ebda_deadbabe_offset /* save offset */ movl %es:5(%di), %eax /* get 32-bit buffer base address */ movl %eax, %cs:memconsole_buffer_start setup_memconsole_end: popw %es popw %ds popaw ret /* * memconsole_log_char * * Log the character passed in %al to the next available memory * console log position, if any. * * If memconsole_buffer_start is zero, no logging will occur * * %al = character to be logged * All registers except flags should be preserved */ memconsole_log_char: pushaw pushw %ds pushw %es pushw %fs pushw $BDA_SEG popw %ds /* ds = 0x40 */ pushw BDA_EBDA /* push word at 0x0e */ popw %es /* es = EBDA_SEG */ movw %ax, %si /* %si = %al = byte to write */ movl %cs:memconsole_buffer_start, %ebp movw %cs:memconsole_ebda_deadbabe_offset, %di addw $MEMCONSOLE_ENDINDEX_OFF, %di /* %di points to char pos */ orl %ebp, %ebp jz memconsole_log_tail /* bufptr==0, no logging */ movw %es:(%di), %bx /* bx = current position in buffer */ cmpw $MEMCONSOLE_BUFFER_SIZE, %bx /* at end of buffer? */ jnc memconsole_log_tail /* don't log any more if so */ cmpb $0xd, %al /* is the char CR? */ jz memconsole_log_tail /* if so, ignore it */ cmpb $0x8, %al /* is the char backspace? */ jnz memconsole_update_fsbase /* if not, log char as usual... */ orw %bx, %bx /* make sure ptr isn't already zero */ jz memconsole_log_tail /* if so, bail */ decw %bx /* else point to previous character */ jmp memconsole_update_end_ptr /* and go directly to save it */ memconsole_update_fsbase: movl $0xc0000100, %ecx /* ecx = IA32_FS_BASE (AMD64+) */ rdmsr /* read what was there before */ pushl %eax /* save away previous FS_BASE eax */ pushl %edx /* save away previous FS_BASE edx */ xorl %edx, %edx /* clear high 32 bits */ movl %ebp, %eax /* eax = memconsole buffer start */ wrmsr /* fs_base = memconsole buffer start */ movw %si, %ax /* %ax = saved value on entry */ movb %al, %fs:(%bx) /* log character */ popl %edx /* restore previous FS_BASE edx */ popl %eax /* restore previous FS_BASE eax */ wrmsr /* write what was there before */ incw %bx /* update character count */ memconsole_update_end_ptr: movw %bx, %es:(%di) /* save new end pointer */ addw $2, %di /* numchars stored at next word */ movw %bx, %es:(%di) /* save new numchar value */ memconsole_log_tail: popw %fs popw %es popw %ds popaw ret /* sgabioslog_setup_ebda * * SGABIOS makes its own 1KB EBDA allocation to save non- * translated characters with associated cursor positions * for the last 256 characters output. This is organized * with 256 bytes reserved for houskeeping, 256 bytes for * the raw character codes, and 512 bytes of 16bit cursor * positions to record the associated position for each. * * The first 4 bytes contain "SGA\0" followed by a 16-bit * size of the allocation in bytes, followed by a 16-bit * index indicating the next spot to be overwritten. * * There are no parameters * All registers should be preserved */ sgabioslog_setup_ebda: pushf pushaw pushw %ds pushw %es pushw $BDA_SEG popw %ds /* ds = 0x40 */ movw BDA_EBDA, %ax /* ax = old ebda segment from 0x0e */ subw $SGABIOS_EBDA_DELTA, %ax movw %ax, %es /* es = new EBDA segment start */ cmpw $EBDA_MIN_SEG, %ax /* is there room for the allocation? */ jc sgabioslog_setup_ebda_tail /* if not, don't change anything */ cli /* paranoid in case irq uses EBDA */ movw %ax, BDA_EBDA /* save new EBDA segment start */ subw $SGABIOS_EBDA_KB, BDA_MEM_SIZE /* subtract extra allocation */ movw %ax, %ds /* ds = new EBDA segment start */ movw $SGABIOS_EBDA_BYTES, %si /* si = offset of first byte to move */ movzbw (%si), %cx /* cx = number of KB in EBDA */ addb $SGABIOS_EBDA_KB, (%si) /* update EBDA size in kb */ shlw $10, %cx /* cx = KB * 1024 = bytes in EBDA */ movw %cx, %cs:sgabios_ebda_logbuf_offset /* new ebda space */ xorw %di, %di /* di = new EBDA start */ cld rep movsb /* move ebda by SGABIOS_EBDA_BYTES */ movw %cs:sgabios_ebda_logbuf_offset, %bx /* bx = new buffer */ movl $SGABIOS_EBDA_SIGNATURE, (%bx) /* setup signature */ movw $SGABIOS_EBDA_BYTES, 4(%bx) /* bytes in new ebda buffer */ movw $0, 6(%bx) /* next log index, new ebda buffer */ sgabioslog_setup_ebda_tail: popw %es popw %ds popaw popf ret /* * sgabioslog_save_char * * Like memconsole_log_char, except the original, untranslated * character is expected to be given in the %al register. * * The original character and its corresponding cursor position * are logged to the sgabios ebda memory allocation. * * %al = character to be logged * All registers except flags should be preserved */ sgabioslog_save_char: pushaw pushw %ds pushw %es pushw $BDA_SEG popw %ds /* ds = 0x40 */ pushw BDA_EBDA /* push word at 0x0e */ popw %es /* es = EBDA_SEG */ movw %cs:sgabios_ebda_logbuf_offset, %di orw %di, %di /* is offset zero? */ jz sgabioslog_save_tail /* if so, bail */ cmpl $SGABIOS_EBDA_SIGNATURE, %es:(%di) jnz sgabioslog_save_tail /* bail if magic not found */ movw %es:6(%di), %bx /* bx = index of next char output */ movb %al, %es:SGABIOS_EBDA_LOG_START(%bx,%di) /* store character */ movzbw %bl, %ax /* %ax = next cursor buffer index */ shlw $1, %ax /* %ax = offset to cursor storage */ call get_current_cursor /* %dh = row, %dl = column */ addw $SGABIOS_EBDA_POS_START, %di /* cursor storage */ addw %ax, %di /* %di = next cursor storage offset */ movw %dx, %es:(%di) /* save position for logged char */ incw %bx /* point to next char to log */ cmpw $SGABIOS_EBDA_LOG_SIZE, %bx jnz sgabioslog_save_index xorw %bx, %bx /* wrap around to start */ sgabioslog_save_index: movw %cs:sgabios_ebda_logbuf_offset, %di movw %bx, %es:6(%di) /* save new index */ sgabioslog_save_tail: popw %es popw %ds popaw ret /* * sgabioslog_get_char * * Return the character at current cursor position, last recorded * to sgabios ebda allocation, if available. * * If the current cursor postition contains one of the last 256 characters * written to the ebda buffer, return that character, else return 0. * * If sgabios_ebdda_logbuf_offset is zero, %al will be 0 and zf set * * All registers except flags and %al should be preserved */ sgabioslog_get_char: pushaw movw %sp, %bp movb $0, 14(%bp) /* %al on stack = 0 */ pushw %ds pushw %es pushw $BDA_SEG popw %ds /* ds = 0x40 */ pushw BDA_EBDA /* push word at 0x0e */ popw %es /* es = EBDA_SEG */ movw %cs:sgabios_ebda_logbuf_offset, %di orw %di, %di jz sgabioslog_get_tail /* offset==0, no logging */ cmpl $SGABIOS_EBDA_SIGNATURE, %es:(%di) jnz sgabioslog_get_tail /* bail if magic not found */ call get_current_cursor /* dh = row, dl = col */ std /* scan backwards in mem */ movw %es:6(%di), %bx /* bx = index of next char output */ decw %bx /* %bx = offset of last char in buf */ jnc sgabioslog_got_pos addw $SGABIOS_EBDA_LOG_SIZE, %bx /* bx position wrap around */ sgabioslog_got_pos: movw %bx, %ax /* %ax = last cursor pos written */ shlw $1, %ax /* %ax = offset of last cursor pos */ addw $SGABIOS_EBDA_POS_START, %di /* %di = first cursor position */ addw %ax, %di /* %di = offset in ebda */ movw %dx, %ax /* %ax = cursor pos to compare */ movw %bx, %cx /* %cx = positions before wrap */ jcxz sgabioslog_cmp_wrap /* if zero, try from end next */ repnz scasw /* search until position match */ addw $2, %di /* scasd always decrements di, undo */ cmpw %ax, %es:(%di) /* did it really match? */ jz sgabioslog_cursor_match /* if so, do something */ sgabioslog_cmp_wrap: movw %cs:sgabios_ebda_logbuf_offset, %di addw $SGABIOS_EBDA_POS_LAST, %di /* %di = last cursor storage */ movw $SGABIOS_EBDA_LOG_SIZE, %cx /* %cx = compare all positions */ repnz scasw /* search until position match */ addw $2, %di /* scasd always decrements di, undo */ cmpw %ax, %es:(%di) /* did it really match? */ jnz sgabioslog_get_tail /* if not, bail */ sgabioslog_cursor_match: /* %di contains the EBDA offset of the matching position */ /* convert this into a memconsole offset */ subw $512, %di /* take off the storage offset */ subw %cs:sgabios_ebda_logbuf_offset, %di /* and ebda offset */ shrw $1, %di /* %di = char position index */ addw %cs:sgabios_ebda_logbuf_offset, %di /* add back ebda offset */ addw $SGABIOS_EBDA_LOG_START, %di /* and add back log offset */ movb %es:(%di), %al /* get related saved character */ movb %al, 14(%bp) /* %al on stack = logged char */ sgabioslog_get_tail: popw %es popw %ds popaw ret /* * multibyteinput * * When an escape key is detected, the input routines will attempt to * capture as many characters as arrive up until a timeout, or six, * whichever is less. * * This table is intended to decide what the characters after the * initial escape key translate to in terms of high and low bytes * that go into the keyboard buffer the high byte is the scancode, * the low byte is ascii, but for special keys this is usually 0xe0 * or 0x00. * * This table is formatted so that the first word is a scancode + * ascii pair (as returned by int 16h, ah = 10h or 11h). Immediately * following is a nul-terminated ascii string to match in order to * use the corresponding scancode+ascii word. * * The search through this table is terminated by a match or finding * a 0 scancode+ascii word. * * FIXME: all the low bytes are now zero, get rid of them? */ multibyteinput: .byte 0x3b /* F1 */ .asciz "[[A" /* F1/screen */ .byte 0x3b /* F1 */ .asciz "OP" /* F1/xterm/ansi */ .byte 0x3b /* F1 */ .asciz "[11~" /* F1/vt400 */ .byte 0x3c /* F2 */ .asciz "[[B" /* F2/screen */ .byte 0x3c /* F2 */ .asciz "OQ" /* F2/xterm/ansi */ .byte 0x3c /* F2 */ .asciz "[12~" /* F2/vt400 */ .byte 0x3d /* F3 */ .asciz "[[C" /* F3/screen */ .byte 0x3d /* F3 */ .asciz "OR" /* F3/xterm/ansi */ .byte 0x3d /* F3 */ .asciz "[13~" /* F3/vt400 */ .byte 0x3e /* F4 */ .asciz "[[D" /* F4/screen */ .byte 0x3e /* F4 */ .asciz "OS" /* F4/xterm/ansi */ .byte 0x3e /* F4 */ .asciz "[14~" /* F4/vt400 */ .byte 0x3f /* F5 */ .asciz "[[E" /* F5/screen */ .byte 0x3f /* F5 */ .asciz "[15~" /* F5/xterm */ .byte 0x3f /* F5 */ .asciz "OT" /* F5/ansi */ .byte 0x40 /* F6 */ .asciz "[17~" /* F6/screen/vt220/xterm/vt400 */ .byte 0x40 /* F6 */ .asciz "OU" /* F6/ansi */ .byte 0x41 /* F7 */ .asciz "[18~" /* F7/screen/vt220/xterm/vt400 */ .byte 0x41 /* F7 */ .asciz "OV" /* F7/ansi */ .byte 0x42 /* F8 */ .asciz "[19~" /* F8/screen/vt220/xterm/vt400 */ .byte 0x42 /* F8 */ .asciz "OW" /* F8/ansi */ .byte 0x43 /* F9 */ .asciz "[20~" /* F9/screen/vt220/xterm/vt400 */ .byte 0x43 /* F9 */ .asciz "OX" /* F9/ansi */ .byte 0x44 /* F10 */ .asciz "[21~" /* F10/screen/vt220/xterm/vt400 */ .byte 0x44 /* F10 */ .asciz "OY" /* F10/ansi */ .byte 0x85 /* F11 */ .asciz "[23~" /* F11/screen/xterm/vt400 */ .byte 0x85 /* F11 */ .asciz "OZ" /* F11/ansi */ .byte 0x86 /* F12 */ .asciz "[24~" /* F12/screen/xterm/vt400 */ .byte 0x52 /* Insert */ .asciz "[2~" /* Insert/screen/vt102/xterm */ .byte 0x53 /* Delete */ .asciz "[3~" /* Delete/screen/vt102/xterm */ .byte 0x4b /* Left */ .asciz "OD" /* Left/screen/vt102 */ .byte 0x4b /* Left */ .asciz "[D" /* Left/xterm */ .byte 0x47 /* Home */ .asciz "[1~" /* Home/screen/vt102 */ .byte 0x47 /* Home */ .asciz "[H" /* Home/xterm */ .byte 0x4f /* End */ .asciz "[4~" /* End/screen/vt102 */ .byte 0x4f /* End */ .asciz "[F" /* End/xterm */ .byte 0x48 /* Up */ .asciz "OA" /* Up/screen/vt102 app */ .byte 0x48 /* Up */ .asciz "[A" /* Up/xterm/vt102 ansi */ .byte 0x50 /* Down */ .asciz "OB" /* Down/screen/vt102 app */ .byte 0x50 /* Down */ .asciz "[B" /* Down/xterm/vt102 ansi */ .byte 0x49 /* PageUp */ .asciz "[5~" /* PageUp/screen/vt102/xterm */ .byte 0x51 /* PageDown */ .asciz "[6~" /* PageDown/screen/vt102/xterm */ .byte 0x4d /* Right */ .asciz "OC" /* Right/screen/vt102 app */ .byte 0x4d /* Right */ .asciz "[C" /* Right/xterm/vt102 ansi */ .byte 0 /* end of table marker */ /* init_serial_port * * Initialize serial port to 115200,8n1 * Serial interrupts disabled * * All registers except flags preserved */ init_serial_port: pushw %ax pushw %dx pushw %bx movw %cs:serial_port_base_address, %dx addw $IER_OFFSET, %dx xorb %al, %al outb %al, %dx /* disable all serial interrupts */ addw $(LCR_OFFSET - IER_OFFSET), %dx /* LCR */ movb $(LCR_VALUE|LCR_DLAB), %al outb %al, %dx /* enable divisor access */ movw %cs:serial_port_base_address, %dx movw $(PORT_DIVISOR/PORT_SPEED), %bx movb %bl, %al /* al = lsb of divisor */ outb %al, %dx /* set divisor latch lsb */ movb %bh, %al /* al = msb of divisor */ incw %dx outb %al, %dx /* set divisor latch msb */ movw %cs:serial_port_base_address, %dx addw $LCR_OFFSET, %dx movb $LCR_VALUE, %al outb %al, %dx /* disable divisor access */ addw $(MCR_OFFSET - LCR_OFFSET), %dx /* MCR */ movb $MCR_DTRRTS, %al outb %al, %dx /* enable DTR + RTS */ movw %cs:serial_port_base_address, %dx addw $FCR_OFFSET, %dx movb $FCR_FIFO_ENABLE, %al outb %al, %dx /* enable FIFOs */ popw %bx popw %dx popw %ax ret /* get_serial_lsr * * return serial line status register in %al * return offset to serial port line status register io port in %dx * all other registers except flags unchanged * * if status == 0xff return ZF=1, else return ZF=0 */ get_serial_lsr: movw %cs:serial_port_base_address, %dx addw $LSR_OFFSET, %dx inb %dx, %al cmpb $0xff, %al ret /* * get_byte * * get serial byte in %al, scancode in %ah [FIXME: EFI console input] * * all registers except %ax preserved * */ get_byte: pushw %dx pushw %bx next_serial_char: call get_serial_lsr /* get serial lsr in %al */ jz get_byte_tail /* no port present... */ testb $1, %al /* bit 0 of LSR = 1 = data available */ jz get_byte_tail /* no input waiting */ /* new character found on serial port */ /* convert it to a scancode */ movw %cs:serial_port_base_address, %dx inb %dx, %al /* al = serial input char */ testb $0x80, %al /* non-ascii char received? */ jnz next_serial_char /* throw char away */ movb %al, %dl /* dl = character read */ pushw %ds pushw %cs popw %ds /* ds = cs */ movw $ascii2scan, %bx /* table to translate ascii->scan */ xlatb /* translate char to scancode */ popw %ds /* shift status is ignored at this point, may be used later */ andb $0x7f, %al /* strip shift status from table */ movb %al, %ah /* scancode goes in high byte */ movb %dl, %al /* "translated" ascii in lower byte */ cmpb $0x7f, %al /* Did the user transmit ascii DEL? */ jnz get_byte_not_del /* if not, don't do anything to al */ movb $0x08, %al /* else delete becomes backspace */ get_byte_not_del: testw %ax, %ax /* clear zero flag */ get_byte_tail: popw %bx popw %dx ret /* * poll_byte * * get serial byte in %al, scancode in %ah [FIXME: EFI console input] * retry up to 65536 times for an expected input byte * * all registers except %ax preserved * */ poll_byte: pushw %cx xorw %cx, %cx poll_byte_retry: inb $0xed, %al call get_byte loopz poll_byte_retry /* repeat while zf set or cx != 0 */ popw %cx ret /* * get_multibyte * * after an escape character, poll for terminal keys that generate * an escape code plus multiple bytes (up to four). * * if no byte is waiting, all registers preserved except flags * if more bytes are waiting, all registers preserved except %ax and flags * */ get_multibyte: pushw %bp /* bp points to temp buffer on stack */ pushw %bx /* bx points to multibyteinput table */ pushw %cx /* cx will count chars */ pushw %ax /* ax will receive chars */ pushl $0 /* make space on stack for 4 chars */ xorw %cx, %cx /* cx = 0 */ movw %sp, %bp /* point bp at temp data */ call poll_byte /* is a character waiting? */ jz get_multibyte_tail /* if not, bail */ get_multibyte_store: movb %al, (%bp) /* store char received */ incb %cl /* mark one char received */ incw %bp /* point to next char */ cmpb $4, %cl /* got enough chars? */ jz got_multibyte /* no strings longer than 4 chars */ call poll_byte /* is another char waiting? */ jnz get_multibyte_store /* store a new one if it's there */ got_multibyte: movw $multibyteinput, %bx /* point to first scancode */ got_multibyte_findkey: movw %sp, %bp /* bp = start of buffer */ movb %cs:(%bx), %ah /* ah = scancode */ incw %bx /* bx = start of test string */ orb %ah, %ah /* is it zero? */ jz get_multibyte_tail /* if so, bail, key not found */ got_multibyte_nextchar: movb %cs:(%bx), %ch /* ch = test char to compare */ incw %bx /* point to next char */ orb %ch, %ch /* is char to compare NUL? */ jz got_multibyte_key /* matched to end of a string! */ cmpb %ch, (%bp) /* input tmp buf equal to test char? */ jnz got_multibyte_try_next_key /* note: expected that test string will be nul before input string */ /* no attempt is made to ensure no more than 4 bytes stack read */ incw %bp /* point to next input */ jmp got_multibyte_nextchar got_multibyte_try_next_key: /* align to next scancode/ascii pair */ movb %cs:(%bx), %ch /* ch = test char to compare */ incw %bx /* point to next char */ orb %ch, %ch /* is char to compare NUL? */ jnz got_multibyte_try_next_key jmp got_multibyte_findkey got_multibyte_key: xorb %al, %al /* ascii value = 0 for special keys */ movw %sp, %bp movw %ax, 4(%bp) /* overwrite old %ax value with key */ get_multibyte_tail: addw $4, %sp /* pop temp space */ popw %ax popw %cx popw %bx popw %bp ret /* * send_byte * * send character in %al to serial port [FIXME: EFI console out] * * all registers preserved except flags * */ send_byte: pushw %ax pushw %dx pushw %cx testb $0x80, %al /* don't send non-ascii chars */ jnz send_tail /* these should be translated earlier */ movb %al, %ah /* save char to output in %ah */ movw $0xFFF0, %cx /* only retry 65520 times */ serial_ready_test: call get_serial_lsr /* get serial lsr in %al */ testb $TRANSMIT_READY_BIT, %al loopz serial_ready_test /* if !tx ready, loop while cx!=0 */ movb %ah, %al movw %cs:serial_port_base_address, %dx outb %al, %dx send_tail: popw %cx popw %dx popw %ax ret /* * translate_char * * translate vga character in %al to ascii * * returns: * al = translated character * * all registers except %al preserved * */ translate_char: pushw %bx pushw %ds pushw %cs popw %ds /* ds = cs */ testb $0x80, %al jz translate_char_ctrl andb $0x7f, %al movw $high2ascii, %bx xlatb translate_char_ctrl: cmpb $0x20, %al jnc translate_char_tail movw $ctrl2ascii, %bx xlatb translate_char_tail: popw %ds popw %bx ret /* * translate_char_tty * * translate vga character in %al to ascii * unless %al == 7, 8, 10, or 13 (bell, bs, lf, cr) * * returns: * al = translated character * * all registers except %al preserved * */ translate_char_tty: cmpb $0x07, %al /* bell */ jz translate_char_tty_tail cmpb $0x08, %al /* backspace */ jz translate_char_tty_tail cmpb $0x0a, %al /* LF */ jz translate_char_tty_tail cmpb $0x0d, %al /* CR */ jz translate_char_tty_tail call translate_char translate_char_tty_tail: ret /* * send_char * * send character 0 - 255 in %al out through serial port * increment cursor position without control processing * * send_byte is used for data that isn't tracked * * send_char is used for text that should be tracked * send_char outputs all characters as non-control chars * * returns: * al = translated character * * all registers except %al preserved * */ send_char: call sgabioslog_save_char /* save original char+pos */ call translate_char jmp send_char_tty_out /* after ctrl translation, same as send_char_tty */ /* * send_char_tty * * send character 0 - 255 in %al out through serial port * increment cursor position *with* control processing * for bell, linefeed, cr, and backspace (others all printable) * * send_byte is used for data that isn't tracked * * send_char_tty is used for text that should be tracked * * returns: * al = translated character * * all registers except %al preserved * */ /* send character 0 - 255 in %al out through serial port */ /* increment cursor position with CR/LF/Backspace processing */ send_char_tty: call sgabioslog_save_char /* save original char+pos */ call translate_char_tty send_char_tty_out: pushw %dx call update_serial_cursor call get_current_cursor /* vga cursor in %dx */ cmpb $0x0d, %al /* CR */ jnz send_char_tty_nul /* if not CR, check for NUL */ orb %dl, %dl /* already at col 0? */ jz send_char_tty_tail /* no need to re-send CR */ send_char_tty_nul: orb %al, %al /* %al == 0 ? (nul) */ /* more than likely, we have NUL at this point because the caller */ /* tried to read a char using int $0x10, %ah=8, and is trying */ /* to re-output it with different attributes - for now send nothing */ jz send_char_tty_tail send_char_tty_write: call memconsole_log_char /* log character sent */ call send_byte cmpb $0x07, %al /* bell */ jz send_char_tty_tail /* no cursor update for bell */ cmpb $0x08, %al /* backspace */ jz send_char_tty_backspace cmpb $0x0a, %al /* LF */ jz send_char_tty_lf cmpb $0x0d, %al /* CR */ jz send_char_tty_cr incb %dl jmp send_char_tty_tail send_char_tty_backspace: orb %dl, %dl jz send_char_tty_tail decb %dl jmp send_char_tty_tail send_char_tty_lf: incb %dh jmp send_char_tty_tail send_char_tty_cr: xorb %dl, %dl send_char_tty_tail: cmpb %cs:term_cols, %dl jc send_char_tty_check_rows movb %cs:term_cols, %dl decb %dl /* dl = cols - 1 */ send_char_tty_check_rows: cmpb %cs:term_rows, %dh jc send_char_tty_save_cursor movb %cs:term_rows, %dh decb %dh /* dh = rows - 1 */ send_char_tty_save_cursor: call set_current_cursor pushw %ds pushw $BDA_SEG popw %ds /* save current position as the serial terminal position */ /* since a character was just output at that position */ movw %dx, BDA_SERIAL_POS popw %ds popw %dx ret /* * send_asciz_out * * send nul terminated string pointed to by %ds:%si * to serial port without text tracking * * indended to be used for multi-byte send_byte * * all registers preserved except flags */ send_asciz_out: pushw %ax pushw %si cld send_asciz_loop: lodsb test %al,%al jz send_asciz_end call send_byte jmp send_asciz_loop send_asciz_end: popw %si popw %ax ret /* * send_string * * send cx chars in string pointed to by %ds:%si * to serial port with tty tracking * * indended to be used for multi-byte send_char_tty * * all registers preserved except flags */ send_string: pushw %ax pushw %si cld send_string_loop: lodsb call send_char_tty loop send_string_loop popw %si popw %ax ret /* * send_string * * send cx chars in string pointed to by %ds:%si * with interleaved attribute data * * indended to be used for multi-byte send_char_tty * with interleaved vga attribute updates * * all registers preserved except flags */ send_attr_string: pushw %ax pushw %bx pushw %si cld send_attr_string_loop: lodsb call send_char_tty lodsb movb %al, %bl call send_attribute /* send attribute in %bl */ loop send_attr_string_loop popw %si popw %bx popw %ax ret /* * send_number * * send ascii version of number in %al to serial port * * intended for ansi cursor positions and attributes, * so cursor position is not tracked/updated * * all registers preserved except flags */ send_number: pushw %ax pushw %bx aam /* ah = al/10, al = al mod 10 */ movw %ax, %bx /* bh = al/10, bl = al mod 10 */ movb %bh, %al aam /* ah = bh/10, al = bh mod 10 */ movb %al, %bh /* bh = 10s digit, bl = 1s digit */ movb %ah, %al /* ah = al = 100s digit */ testb %al, %al /* is there a 100s digit? */ jz send_tens /* move to tens if not */ orb $0x30, %al /* al = ascii value of digit */ call send_byte send_tens: orb %bh, %ah /* bh = 10s, ah = 100s digits */ jz send_ones /* non-zero = must send tens */ movb %bh, %al /* al = bh = 10s digit */ orb $0x30, %al /* al = ascii value of digit */ call send_byte send_ones: movb %bl, %al /* al = bl = 1s digit */ orb $0x30, %al /* al = ascii value of digit */ call send_byte popw %bx popw %ax ret /* * send_crlf * * send CRLF to serial port * * FIXME: used at vga init and for scrolling terminal * so position is not tracked. Callers of this routine * predate the code that does smart tty/cursor output. * * Callers should probably be changed to use those * routines or send_crlf changed to use them and * terminal scrolling fixed to use linefeed only. * * all registers preserved except flags */ send_crlf: pushw %ax movb $0x0d, %al call send_byte movb $0x0a, %al call send_byte popw %ax ret /* * send_ansi_csi * * send ESCAPE [ to serial port * * output is not tracked since these are control sequences * * all registers preserved except flags */ send_ansi_csi: /* transmit ESC [ */ pushw %ax movb $0x1b, %al /* escape */ call send_byte movb $0x5b, %al /* [ */ call send_byte popw %ax ret /* * send_ansi_csi_2num * * send ESC [ %dh ; %dl to serial port * * since both position and attribute updates generally have * two parameters, this function converts values in dx to * two ascii numbers. It's expected that the caller will * output the final trailing H or m or whatever is required. * * output is not tracked since these are control sequences * * all registers preserved except flags */ send_ansi_csi_2num: /* send ESC [ %dh ; %dl */ pushw %ax call send_ansi_csi /* esc [ */ movb %dh, %al call send_number movb $0x3b, %al /* semicolon */ call send_byte movb %dl, %al call send_number popw %ax ret /* * send_ansi_cursor_pos * * send ESC [ %dh+1 ; %dl+1 to serial port to position * cursor * * since both position and attribute updates generally have * two parameters, this function converts values in dx to * two ascii numbers, after adding 1 to both dh and dl. * * output is not tracked since this is a control sequence * * all registers preserved except flags */ send_ansi_cursor_pos: pushw %ax pushw %dx addw $0x0101, %dx /* dh += 1, dl += 1 */ call send_ansi_csi_2num /* send esc [ %dh+1;%dl+1 */ movb $0x48, %al /* H */ call send_byte popw %dx popw %ax ret /* * send_attribute * * send ansi attribute change ESC [ 4x ; 3y ; (1|22)m * if the attribute has changed since last sent (stored in bda) * * output is not tracked since this is a control sequence * * all registers preserved except flags */ send_attribute: andb $0x7f, %bl /* ansi has no bright bg */ pushw %ds pushw %es pushw %ax pushw %bx pushw %dx pushw $BDA_SEG popw %es /* es = 0x40 */ pushw %cs popw %ds /* ds = cs */ cmpb %es:BDA_COLOR_VAL, %bl jz send_attribute_tail cmpb $0x07, %bl /* is it white on black? */ jnz send_attribute_color /* for white on black, send esc [ m */ call send_ansi_csi jmp send_attribute_m /* send the m, return */ send_attribute_color: movb %bl, %ah /* ah = attribute */ movw $colortable, %bx movb %ah, %al andb $7, %al /* al = fg attr */ xlatb /* al = fg ansi num */ movb %al, %dl /* dl = fg ansi num */ movb %ah, %al shrb $4, %al /* al = bg attr */ xlatb /* al = bg ansi num */ movb %al, %dh /* dh = bg ansi num */ addw $0x281e, %dx /* 3x=setfg, 4x=setbg */ call send_ansi_csi_2num movb $0x3b, %al /* semicolon */ call send_byte shlb $4, %ah /* bright text? */ sets %al /* if bit 7, al = 1 */ js send_attribute_intensity movb $22, %al /* 22 = normal intensity */ send_attribute_intensity: call send_number /* either 22 or 1 */ send_attribute_m: movb $0x6d, %al /* m */ call send_byte send_attribute_tail: popw %dx popw %bx /* mark attribute in %bl the current one */ movb %bl, %es:BDA_COLOR_VAL popw %ax popw %es popw %ds ret /* * serial_get_input * * common code for both interrupt-driven and non-interrupt * driven serial input. Called only when LSR bit 1 is set. * * No parameters, no return values * * Preserves all registers */ serial_get_input: pushf /* be paranoid about int 9h happening during update */ cli pushaw pushw %ds /* next char input buffer is at 0x40:0x1c */ pushw $BDA_SEG popw %ds /* es = 0x40 */ call get_byte /* next scancode/byte in %ax */ cmpb $0x1b, %al /* look for escape */ jnz serial_gotkey /* not escape, don't look for more bytes */ call get_multibyte /* look for any chars after escape */ serial_gotkey: movw KBD_TAIL, %bx /* bx = keyboard tail pointer */ movw %ax, (%bx) /* store key in buffer */ addw $2, %bx /* point to next location */ cmpw $KBD_BUF_END, %bx /* did the buffer wrap? */ jb kbd_buf_no_wrap movw $KBD_BUF_START, %bx kbd_buf_no_wrap: movw %bx, KBD_TAIL /* update tail pointer to show key */ popw %ds popaw popf ret /* * irq3_isr * * entry point for irq 3 / int 0x0b / exception 11 * * Called when COM2 or COM4 have characters pending * * The segment not present exception should never happen * in real mode 16-bit code like this, but just to be safe, * if this interrupt is invoked and no characters are * pending on the port found in serial_port_base_address, * this routine will chain to the original handler. * * If characters are found pending, they will be processed * and control returned via iret. */ irq3_isr: #if 0 pushw %ax pushw %dx /* placeholder, this shouldn't ever happen */ /* no interrupts are configured outside COM1 */ call get_serial_lsr /* get serial lsr in %al */ jz chain_irq3 /* no port present... */ testb $1, %al /* bit 0 of LSR = 1 = data available */ jz chain_irq3 /* no input waiting */ call serial_get_input /* get input and stuff kbd buffer */ movb $0x20, %al outb %al, $0x20 /* send non-specific EOI */ popw %dx popw %ax iret chain_irq3: popw %dx popw %ax #endif jmp do_old_irq3 /* * irq4_isr * * entry point for irq 4 / int 0x0c / exception 12 * * Called when COM1 or COM3 have characters pending * * The stack fault exception may occur if code attempts to * read from sp:0xffff, so if this interrupt is invoked and * no characters are pending on the port found in * serial_port_base_address, this routine will chain to the * original handler. * * If characters are found pending, they will be processed * and control returned via iret. */ irq4_isr: #if 0 pushw %ax pushw %dx call get_serial_lsr /* get serial lsr in %al */ jz chain_irq4 /* no port present... */ testb $1, %al /* bit 0 of LSR = 1 = data available */ jz chain_irq4 /* no input waiting */ call serial_get_input /* get input and stuff kbd buffer */ movb $0x20, %al outb %al, $0x20 /* send non-specific EOI */ popw %dx popw %ax iret chain_irq4: popw %dx popw %ax #endif jmp do_old_irq4 /* * int14h_isr * * entry point for int 14h * */ int14h_isr: pushaw movw %sp, %bp addw $16, %bp /* bp points to return address */ orb %ah, %ah /* fn 0x00, initialize port */ jz int14h_init_port cmpb $0x04, %ah /* fn 0x04, extended intialize */ jnz chain_isr14h int14h_init_port: /* check for init port = current port */ pushw %ds pushw $BDA_SEG popw %ds /* ds = 0x40 */ movw %dx, %bx /* bx = port number */ shlw $1, %bx /* bx = port number * 2 */ andw $7, %bx /* bx = bda offset of serial io addr */ movw (%bx), %cx /* cx = io address of port to init */ popw %ds /* restore original ds */ cmpw %cx, %cs:serial_port_base_address jnz chain_isr14h /* if different, don't get in the way */ /* init port == current port */ pushw %ds /* LILO 22.6 HACK STARTS HERE */ movw (%bp), %bx /* return address for int 14h call */ movw 2(%bp), %ds /* return segment for int 14h call */ cmpl $0x4f4c494c, 0x06 /* does segment have lilo signature? */ jnz int14h_init_tail /* not lilo, bail on hack */ cmpw $0x0616, 0x0a /* does version match lilo 22.6? */ jnz int14h_init_tail /* unknown lilo release, bail on hack */ movb $0, 0x12 /* set lilo com port = 0 */ movl $0x90c3585a, (%bx) /* return code= pop dx;pop ax;ret;nop */ /* now lilo 22.6's own serial out is permanently disabled */ /* this prevents double-character output from int10h + serial */ /* this also prevents lilo from stealing serial input chars */ /* END LILO 22.6 HACK */ int14h_init_tail: popw %ds popaw pushw %dx /* get_serial_lsr trashes %dx */ call get_serial_lsr /* return serial status in %al */ xorb %ah, %ah /* return serial status in %ax */ popw %dx /* restore %dx */ iret chain_isr14h: popaw jmp do_old_int14h /* * int16h_isr * * entry point for int 16h * * keyboard characters are usually retrieved by calling * int 16h, generally placed in the keyboard buffer by * irq 1 (int 9h). Poll serial port for new data before * chaining to int 16h to fake irq 1 behavior * * all registers preserved except flags (later iret will restore) * bda updated with a new keypress if available * * FIXME: handle multi-byte keypresses like cursor up/down * to send proper scancodes for navigating lilo menus */ int16h_isr: pushw %ax pushw %dx /* each time int 16h is invoked, fake an int 9h */ /* except read the serial input buffer */ /* then chain to the original int 16h for processing */ call get_serial_lsr jz chain_isr16h /* no port present... */ testb $1, %al /* bit 0 of LSR = 1 = data available */ jz chain_isr16h /* no input waiting */ call serial_get_input /* get input and stuff kbd buffer */ /* for now, leave remaining chars pending in serial fifo */ /* int 16h callers only get one char at a time anyway */ chain_isr16h: popw %dx popw %ax jmp do_old_int16h /* * update serial_cursor * * figure out where the cursor was, and where it's going * use the minimal amount of serial output to get it there * input: vga cursor and serial cursor positions stored in BDA * * all registers preserved except flags * bda updated with new position for serial console cursor */ update_serial_cursor: pushw %ax pushw %bx pushw %dx pushw %ds pushw $BDA_SEG popw %ds /* ds = 0x40 */ call get_current_cursor /* dh = row, dl = col */ movw BDA_SERIAL_POS, %bx /* bh = row, bl = col */ subb %dl, %bl /* -col update */ negb %bl /* col update */ subb %dh, %bh /* -row update */ negb %bh /* row update */ /* handle a few special movement cases */ /* cr, lf, bs, bs+bs, space, else send full ansi position */ orb %dl, %dl /* column zero? */ jnz update_serial_cursor_lf movb $0x0d, %al /* CR */ call send_byte xorb %bl, %bl /* mark no diff in col */ update_serial_cursor_lf: cmpb $1, %bh /* +1 row? */ jnz update_serial_cursor_bs movb $0x0a, %al /* LF */ call send_byte xorb %bh, %bh /* mark no diff in row */ update_serial_cursor_bs: cmpb $-1, %bl /* one char back */ jz update_serial_cursor_one_bs cmpb $-2, %bl /* two chars back */ jnz update_serial_cursor_space /* check for space */ movb $0x08, %al /* BS */ call send_byte update_serial_cursor_one_bs: movb $0x08, %al /* BS */ call send_byte xorb %bl, %bl /* mark no diff in col */ update_serial_cursor_space: cmpb $1, %bl /* one char forward */ jnz update_serial_cursor_up movb $0x20, %al /* space */ call send_byte xorb %bl, %bl /* mark no diff in col */ update_serial_cursor_up: cmpb $-1, %bh /* -1 row? */ jnz update_serial_cursor_full /* do full ansi pos update */ call send_ansi_csi /* send ESC [ A (cursor up) */ movb $0x41, %al /* A */ call send_byte xorb %bh, %bh /* mark no diff in row */ update_serial_cursor_full: orw %bx, %bx /* diff = 0? */ jz update_serial_cursor_done call send_ansi_cursor_pos /* set cursor pos from dh,dl */ update_serial_cursor_done: movw %dx, BDA_SERIAL_POS popw %ds popw %dx popw %bx popw %ax ret /* * write_teletype * * handle int 10h, function 0eh * * ah = 0x0e write teletype character * al = character ascii code * bh = display page number * * all registers except %al preserved * caller will restore all registers */ write_teletype: pushw %bx movb $0x07, %bl /* black bg, white fg */ call send_attribute popw %bx call send_char_tty ret /* * write_attr_char * * handle int 10h, function 09h * * ah = 0x09 write attribute/character at current cursor position * al = character ascii code * bh = display page number * bl = character attribute * cx = repetition count * * does not update cursor position * all registers except %cx and %al preserved * caller will restore all registers */ write_attr_char: call send_attribute /* send attribute in %bl */ jmp write_char_common /* * write_char * * handle int 10h, function 0ah * * ah = 0x0a write character at current cursor position * al = character ascii code * bh = display page number * cx = repetition count * * does not update cursor position * all registers except %cx and %al preserved * caller will restore all registers */ write_char: pushw %bx movb $0x07, %bl /* black bg, white fg */ call send_attribute popw %bx write_char_common: call get_current_cursor call send_char /* make cx=0 and cx=1 only output one char */ cmpw $1, %cx jbe write_char_tail decw %cx jmp write_char write_char_tail: /* put cursor back where it was on entry */ call set_current_cursor ret /* * write_string * * handle int 10h, function 13h * * ah = 0x13 write character at current cursor position * al = 0, data = char, ..., no cursor update * al = 1, data = char, ..., cursor at end of string * al = 2, data = char+attr, ..., no cursor update * al = 3, data = char+attr, ..., cursor at end of string * bh = display page number * bl = character attribute for all chars (if al = 0 or 1) * cx = characters in string (attributes don't count) * dh = cursor row start * dl = cursor column start * es:bp = pointer to source text string in memory * * all registers preserved except flags * caller will restore all registers */ write_string: call set_cursor_position pushw %ds pushw %es pushw %es popw %ds /* ds = es */ movw %bp, %si /* si = bp */ testb $2, %al jnz write_attr_string call send_attribute /* send attribute in %bl */ test %cx, %cx jz write_string_empty call send_string /* plaintext out */ write_string_empty: jmp write_string_update_cursor write_attr_string: call send_attr_string /* text+attrib out */ write_string_update_cursor: testb $1, %al /* cursor update? */ jnz write_string_tail /* yes? already happened */ /* restore entry cursor position if no update */ call set_cursor_position write_string_tail: popw %es popw %ds ret /* * set_cursor_position * * handle int 10h, function 02h * * ah = 0x02 set cursor position * bh = display page number * dh = cursor row * dl = cursor column * * update bda cursor position with value in %dx * serial console cursor only updated on text output * this routine also called by set_current_cursor * which won't bother setting ah = 2 * * all registers preserved except flags */ set_cursor_position: pushw %ax pushw %ds pushw $BDA_SEG popw %ds /* ds = 0x40 */ movzbw %bh, %ax /* ax = page number */ andb $0x07, %al /* prevent invalid page number */ shlb $1, %al /* calculate word offset */ addb $BDA_CURSOR_BUF, %al /* ax = cursor save offset */ movw %ax, %bx /* bx = cursor save offset */ movw %dx, (%bx) /* save new cursor value */ popw %ds popw %ax ret /* * set_current_cursor * * get current display page number and call set_cursor_positon * to store the row/column value in dx to the bda * * all registers preserved except flags */ set_current_cursor: pushw %ds pushw %bx pushw $BDA_SEG popw %ds /* ds = 0x40 */ movb BDA_ACTIVE_PAGE, %bh call set_cursor_position popw %bx popw %ds ret /* * get_cursor_common * * read cursor position for page %bh from bda into %dx * * returns: * dh = cursor row * dl = cursor column * ch = cursor start scanline * cl = cursor end scanline * * all registers except %dx, %cx preserved */ get_cursor_common: pushw %bx pushw %ds pushw $BDA_SEG popw %ds /* ds = 0x40 */ movzbw %bh, %bx /* dx = current page */ andb $7, %bl shlb $1, %bl addb $BDA_CURSOR_BUF, %bl movw (%bx), %dx /* get cursor pos */ movw BDA_CURSOR_SCAN, %cx popw %ds popw %bx ret /* * get_current_cursor * * read cursor position for current page from bda into %dx * * returns: * dh = cursor row * dl = cursor column * * all registers except %dx preserved */ get_current_cursor: pushw %ds pushw %bx pushw %cx pushw $BDA_SEG popw %ds /* ds = 0x40 */ movb BDA_ACTIVE_PAGE, %bh call get_cursor_common popw %cx popw %bx popw %ds ret /* * get_cursor_position * * handle int 10h, function 03h * * ah = 0x02 get cursor position * bh = display page number * * returns: * ax = 0 * ch = cursor start scanline * ch = cursor end scanline * dh = cursor row * dl = cursor column * * all registers except %ax, %cx, %dx preserved */ get_cursor_position: call bail_if_vga_attached /* does not return if vga attached */ popw %ax /* not chaining, pop fake return address */ popw %dx /* not chaining, pop saved cursor position */ popaw /* not chaining to old int 10h, pop saved state */ call get_cursor_common xorw %ax, %ax iret /* * return_current_video_state * * handle int 10h, function 0fh * * ah = 0x0f return current video state * * returns: * ah = number of columns on screen (from 40:4a) * al = current video mode setting (from 40:49) * bh = active display page number (from 40:62) * * all registers except %ax and %bh preserved */ read_current_video_state: call bail_if_vga_attached /* does not return if vga attached */ popw %ax /* not chaining, pop fake return address */ popw %dx /* not chaining, pop saved cursor position */ popaw /* not chaining to old int 10h, pop saved state */ pushw %ds pushw $BDA_SEG popw %ds /* ds = 0x40 */ movb BDA_COLS, %ah movb BDA_MODE_NUM, %al movb BDA_ACTIVE_PAGE, %bh popw %ds iret /* * read_attr_char * * handle int 10h, function 08h * * ah = 0x08 read character/attribute from screen * * returns: * ah = attribute at current cursor position * al = character read from current cursor position * * all registers preserved except %ax and flags */ read_attr_char: call bail_if_vga_attached /* does not return if vga attached */ popw %ax /* not chaining, pop fake return address */ popw %dx /* not chaining, pop saved cursor position */ popaw /* not chaining to old int 10h, pop saved state */ pushw %ds pushw $BDA_SEG popw %ds /* ds = 0x40 */ movb BDA_COLOR_VAL, %ah /* return last color value */ call sgabioslog_get_char popw %ds iret /* * set_video_mode * * handle int 10h, function 00h * * ah = 0x00 set video mode * al = video mode * * unless bit 7 of al = 1, setting mode clears screen * * all registers preserved except %bh, %dx, flags */ set_video_mode: testb $0x80, %al /* preserve screen flag? */ jnz set_video_mode_tail call send_ansi_csi movb $0x32, %al /* 2 */ call send_byte movb $0x4a, %al /* J */ call send_byte set_video_mode_tail: movb $0x07, %bl /* white on black text */ call send_attribute /* send attribute in %bl */ /* set cursor position to 0,0 */ xorb %bh, %bh /* page 0 */ xorw %dx, %dx jmp set_cursor_position /* * scroll_page_up * * handle int 10h, function 06h * * ah = 0x06 scroll current page up * al = scroll distance in character rows (0 blanks entire area) * bh = attribute to used on blanked lines * ch = top row (upper left corner) of window * cl = left-most column (upper left corner) of window * dh = bottom row (lower right corner) of window * dl = right-most column (lower right corner) of window * * all registers preserved except flags */ scroll_page_up: pushw %si pushw %dx call get_current_cursor /* save current cursor */ movw %dx, %si /* si = vga cursor pos */ popw %dx cmpb $0, %al /* al = 0 = clear window */ jz scroll_common_clear pushw %ax call send_ansi_csi /* CSI [ %al S */ call send_number movb $0x53, %al /* S */ call send_byte popw %dx popw %si ret /* * scroll_common_clear * * common tail for up/down scrolls to clear window specified * in %cx and %dx. * * stack should contain saved copy of si * si = original vga cursor position on service entry * * bh = attribute to used on blanked lines * ch = top row (upper left corner) of window * cl = left-most column (upper left corner) of window * dh = bottom row (lower right corner) of window * dl = right-most column (lower right corner) of window */ scroll_common_clear: pushw %ax xchgb %bl, %bh /* bl = attribute, bh = old bl */ call send_attribute /* send attribute in %bl */ xchgb %bl, %bh /* restore bx */ pushw %ds pushw $BDA_SEG popw %ds /* ds = 0x40 */ /* check to see if region is full screen, and attribute default */ orw %cx, %cx /* is top left 0,0? */ jnz scroll_common_window /* no, handle window */ cmpb $0x07, %bh /* is attribute white on black? */ jnz scroll_common_window /* no, must write spaces */ #ifdef LILO_CLEAR_WORKAROUND_NOT_REQUIRED cmpb %cs:term_cols, %dl /* is right less than cols ? */ jc scroll_common_window /* if so, handle window */ cmpb %cs:term_rows, %dh /* is bottom less than rows ? */ jc scroll_common_window /* if so, handle window */ #endif /* safe to send standard clear screen sequence */ call send_ansi_csi /* send ESC [ */ movb $0x32, %al /* 2 */ call send_byte movb $0x4a, %al /* J */ call send_byte jmp scroll_common_tail scroll_common_window: pushw %dx movw %cx, %dx /* dx = upper right */ call set_current_cursor popw %dx pushw %cx /* setup cx with count of chars to clear per row */ xorb %ch, %ch negb %cl addb %dl, %cl /* cl = dl - cl */ incb %cl /* start = end col = clear 1 col */ cmpb %cs:term_cols, %cl /* is count < cols? */ jc scroll_common_row_ok /* if so then skip limit */ movb %cs:term_cols, %cl /* limit count to cols */ scroll_common_row_ok: jz scroll_common_row_done /* count == 0 ? */ movb $0x20, %al /* space */ scroll_common_space_loop: call send_char loop scroll_common_space_loop /* send cx spaces */ scroll_common_row_done: popw %cx incb %ch /* top left now next row */ cmpb %dh, %ch jbe scroll_common_window /* do next row */ scroll_common_tail: popw %ds popw %ax pushw %dx movw %si, %dx /* dx = saved vga cursor pos */ call set_current_cursor /* restore saved cursor */ popw %dx popw %si ret /* * scroll_page_down * * handle int 10h, function 07h * * ah = 0x07 scroll current page down * al = scroll distance in character rows (0 blanks entire area) * bh = attribute to used on blanked lines * ch = top row (upper left corner) of window * cl = left-most column (upper left corner) of window * dh = bottom row (lower right corner) of window * dl = right-most column (lower right corner) of window * * FIXME: this routine doesn't handle windowing, it currently * only handles one line screen scrolls and erasing entire screen * * all registers preserved except flags */ scroll_page_down: pushw %si pushw %dx call get_current_cursor /* save current cursor */ movw %dx, %si /* si = vga cursor pos */ popw %dx cmpb $0, %al /* al = 0 = clear window */ jz scroll_common_clear pushw %ax call send_ansi_csi /* CSI [ %al T */ call send_number movb $0x54, %al /* T */ call send_byte popw %dx popw %si ret /* * bail_if_vga_attached * * Check for vga installed, if not, return to caller. * If so, pop return address, return to chain_isr_10h * * expected that routine calling this one has chain_isr_10h * as the next item on the stack * * all registers except flags and sp preserved */ bail_if_vga_attached: cmpw $0xc000, %cs:old_int10h_seg /* vga attached? */ jnz bail_tail /* if not, don't modify stack */ addw $2, %sp /* else drop first return address */ bail_tail: ret /* return to caller or chain_isr_10h */ /* * int10h_isr * * entry point for int 10h * * save all registers, force return to chain to previous int10h isr * decide which function in ah needs to be dispatched * * ah = 0x00 set mode * ah = 0x01 set cursor type * ah = 0x02 set cursor position * ah = 0x03 read cursor position * ah = 0x04 read light pen position * ah = 0x05 set active display page * ah = 0x06 scroll active page up * ah = 0x07 scroll active page down * ah = 0x08 read attribute/character at cursor * ah = 0x09 write attribute/character at cursor * ah = 0x0a write character at cursor position * ah = 0x0b set color palette * ah = 0x0c write pixel * ah = 0x0d read pixel * ah = 0x0e write teletype * ah = 0x0f read current video state * ah = 0x10 set individual palette registers * ah = 0x11 character generation (font control/info) * ah = 0x12 alternate select (video control/info) * ah = 0x13 write string * ah = 0x1a read/write display combination code * ah = 0x1b return functionality/state information * ah = 0x1c save/restore video state * ah = 0x4f vesa bios calls * all registers preserved except flags (later iret will restore) */ int10h_isr: pushaw call get_current_cursor pushw %dx /* save current cursor */ pushw %bp /* need bp for indexing off stack */ movw %sp, %bp /* bp = sp */ movw 14(%bp), %dx /* restore dx from earlier pushaw */ popw %bp /* restore old bp */ pushw $chain_isr10h /* force return to chain_isr10h */ testb %ah, %ah jnz int10h_02 jmp set_video_mode int10h_02: cmpb $0x02, %ah jnz int10h_03 jmp set_cursor_position int10h_03: cmpb $0x03, %ah jnz int10h_06 jmp get_cursor_position int10h_06: cmpb $0x06, %ah jnz int10h_07 jmp scroll_page_up int10h_07: cmpb $0x07, %ah jnz int10h_08 jmp scroll_page_down int10h_08: cmpb $0x08, %ah jnz int10h_09 jmp read_attr_char int10h_09: cmpb $0x09, %ah jnz int10h_0a jmp write_attr_char int10h_0a: cmpb $0x0a, %ah jnz int10h_0e jmp write_char int10h_0e: cmpb $0x0e, %ah jnz int10h_0f jmp write_teletype int10h_0f: cmpb $0x0f, %ah jnz int10h_13 jmp read_current_video_state int10h_13: cmpb $0x13, %ah jnz int10h_default jmp write_string int10h_default: popw %ax /* pop chain_isr10h return address */ chain_isr10h: popw %dx /* pop saved cursor */ cmpw $0xc000, %cs:old_int10h_seg /* vga attached? */ jnz chain_post_cursor /* if not, don't restore the cursor */ call set_current_cursor /* restore cursor if vga attached */ chain_post_cursor: popaw jmp do_old_int10h /* * pnp_sga_init * * handle PnP initialization of option rom * * es:di = pointer to PnP structure * ax = indication as to which vectors should be hooked * by specifying th type of boot device this has * been selected as * bit 7..3= reserved(0) * bit 2 = 1 = connect as IPL (int 13h) * bit 1 = 1 = connect as primary video (int 10h) * bit 0 = 1 = connect as primary input (int 9h) * bx = card select number (probably 0xffff) * dx = read data port address (probably 0xffff) * * return: * ax = initialization status * bit 8 = 1 = IPL device supports int 13h block dev format * bit 7 = 1 = Output device supports int 10h char output * bit 6 = 1 = Input device supports int 9h char input * bit 5..4 = 00 = no IPL device attached * 01 = unknown whether or not IPL device attached * 10 = IPL device attached (RPL devices have connection) * 11 = reserved * bit 3..2 = 00 = no display device attached * 01 = unknown whether or not display device attached * 10 = display device attached * 11 = reserved * bit 1..0 = 00 = no input device attached * 01 = unknown whether or not input device attached * 10 = input device attached * 11 = reserved * * all registers preserved except %ax */ pnp_sga_init: /* FIXME: this is *wrong* -- init only what bios says to init */ movw $0xca, %ax /* 0xca = attached int 10h, 9h display, input */ /* * sga_init * * legacy option rom entry point * * all registers preserved */ sga_init: /* this is probably paranoid about register preservation */ pushfw cli /* more paranoia */ pushaw pushw %ds pushw %es pushw $0 popw %es /* es = 0 */ pushw %cs popw %ds /* ds = cs */ /* get original ISR */ movl %es:0x28, %eax /* eax = old irq 3/int 0bh */ movl %eax, old_irq3 /* save away old irq 4/int 0bh */ movl %es:0x2c, %eax /* eax = old irq 4/int 0ch */ movl %eax, old_irq4 /* save away old irq 4/int 0ch */ movl %es:0x40, %eax /* eax = old int 10h */ movl %eax, old_int10h /* save away old int 10h */ movl %es:0x50, %eax /* eax = old int 14h */ movl %eax, old_int14h /* save away old int 14h */ movl %es:0x58, %eax /* eax = old int 16h */ movl %eax, old_int16h /* save away old int 16h */ movw $irq3_isr, %es:0x28 /* new irq 3 offset */ movw %cs, %es:0x2a /* write new irq 3 seg */ movw $irq4_isr, %es:0x2c /* new irq 4 offset */ movw %cs, %es:0x2e /* write new irq 4 seg */ movw $int10h_isr, %es:0x40 /* new int 10h offset */ movw %cs, %es:0x42 /* write new int10h seg */ movw $int14h_isr, %es:0x50 /* new int 14h offset */ movw %cs, %es:0x52 /* write new int14h seg */ movw $int16h_isr, %es:0x58 /* new int 16h offset */ movw %cs, %es:0x5a /* write new int16h seg */ /* empty input buffer to prepare for terminal sizing */ call init_serial_port input_clear_loop: call get_byte jnz input_clear_loop movw $term_init_string, %si call send_asciz_out push $BDA_SEG push $BDA_SEG popw %ds /* ds = 0x40 */ popw %es /* es = 0x40 */ movw $BDA_CURSOR_BUF, %di input_timeout_loop: /* get input from terminal until timeout found */ /* store input at 40:50 - 40:5e (cursor pos) */ call poll_byte jz input_timeout stosb /* es:di */ cmpw $0x5f, %di /* 14 characters max */ jnz input_timeout_loop /* good for more data */ input_timeout: xorb %al, %al /* nul terminate input */ stosb cmpw $0x58, %di /* less than 8 chars? */ jc resize_end /* too small to have valid data */ movw $BDA_CURSOR_BUF, %si /* point to start */ lodsw /* ax = first 2 chars */ cmpw $0x5b1b, %ax /* was it "ESC[" ? */ jnz resize_end /* reply starts ESC[row;colR */ xorb %bl, %bl /* bl = ascii->int conversion */ input_first_number: lodsb /* al = next char */ cmpb $0x30, %al jc resize_end /* char < 0x30 invalid */ cmpb $0x3a, %al /* is char < 0x3a */ jnc input_semicolon andb $0x0f, %al /* al = 0 - 9 */ movb %bl, %ah /* ah = last conversion */ aad /* ax = (al + ah * 10) & 0xff */ movb %al, %bl /* bl = row ascii->int conversion */ jmp input_first_number input_semicolon: /* at this point bl should contain rows, al = ; */ /* sanity check, bail if invalid */ cmpb $0x3b, %al jnz resize_end /* invalid input found */ cmpb $0x0a, %bl /* less than 10 rows? */ jc suspect_loopback /* consider input invalid */ xorb %bh, %bh /* bh = col ascii->int conversion */ input_second_number: lodsb /* al = next char */ cmpb $0x30, %al jc resize_end /* char < 0x30 invalid */ cmpb $0x3a, %al /* is char < 0x3a */ jnc input_final_r andb $0x0f, %al /* al = 0 - 9 */ movb %bh, %ah /* ah = last conversion */ aad /* ax = (al + ah * 10) & 0xff */ movb %al, %bh /* bh = ascii->int conversion */ jmp input_second_number input_final_r: cmpb $0x52, %al /* is al = 'R' ? */ jnz suspect_loopback /* invalid input found */ movb %bl, %cs:term_rows /* save away bl rows value */ cmpw $0xc000, %cs:old_int10h_seg /* vga attached? */ jz resize_end /* if so, leave term_cols at 80 */ movb %bh, %cs:term_cols /* save away bh cols value */ jmp resize_end suspect_loopback: /* * characters were received that look like what we sent out * at this point, assume that a loopback device was plugged in * and disable any future serial port reads or writes, by pointing * output to port 0x2e8 (COM4) instead of 0x3f8 -- it's expected * that this is safe since a real port responds correctly and a * missing port will respond with 0xff which will terminate the * loop that waits for the "right" status on the port. */ movw $0x2e8, %cs:serial_port_base_address resize_end: /* clear (hopefully) overwritten cursor position buffer */ xorb %al, %al movw $BDA_CURSOR_BUF, %di movw $0x10, %cx cld rep stosb /* fill 40:50 - 40:5f with 0 */ pushw %cs popw %ds /* ds = cs */ call get_byte /* flush any remaining "wrong" input */ jnz resize_end call send_crlf /* place cursor on start of last line */ movw $mfg_string, %si call send_asciz_out call send_crlf movw $prod_string, %si call send_asciz_out call send_crlf movw $long_version, %si call send_asciz_out call send_crlf /* if vga attached, skip terminal message and bda setup... */ cmpw $0xc000, %cs:old_int10h_seg /* vga attached? */ jz post_bda_init_tail /* if so, don't modify BDA */ /* show detected terminal size, or default if none detected */ movw $term_info, %si call send_asciz_out pushw $BDA_SEG popw %ds /* ds = 0x40 */ movb %cs:term_cols, %al movb %al, BDA_COLS /* 40:4a = number of character cols */ movb $0, BDA_CURSOR_COL /* 40:51 = cursor0 col */ call send_number movb $0x78, %al /* x */ call send_byte movb %cs:term_rows, %al movb %al, %ah decb %ah /* ah = rows-1 */ movb %ah, BDA_ROWS /* 40:84 = num character rows - 1 */ movb %ah, BDA_CURSOR_ROW /* 40:50 = cursor0 row */ call send_number call send_crlf movb $3, BDA_MODE_NUM movb $0x29, BDA_MODE_SEL movw $VGA_IO_BASE, BDA_6845_ADDR movw $0x4000, BDA_PAGE_SIZE /* 16KB per video page */ /* to avoid ansi colors every character, store last attribute */ movb $0x07, BDA_COLOR_VAL /* 07 = black bg, white fg */ movw %cs, %ax movw $_start, BDA_ROM_OFF movw %ax, BDA_ROM_SEG post_bda_init_tail: /* copy BDA rows/cols to sgabios location... */ /* if vga card is installed, reuse those values... */ /* if no vga card is installed, this shouldn't change anything */ pushw $BDA_SEG popw %ds /* ds = 0x40 */ movb BDA_ROWS, %al incb %al /* bda holds rows-1 */ movb %al, %cs:term_rows /* sgabios rows */ movb BDA_COLS, %ah movb %ah, %cs:term_cols /* sgabios cols */ /* setup in-memory logging of console if desired... */ call setup_memconsole /* setup logging of last 256 characters output, if ebda has room */ call sgabioslog_setup_ebda movw $ebda_info, %si call send_asciz_out movw %cs:sgabios_ebda_logbuf_offset, %ax xchgb %ah, %al call send_number movb $0x20, %al call send_byte movb %ah, %al call send_number call send_crlf popw %es popw %ds popaw popf lret _end_sgabios: 07070100000006000081A40000000000000000000000014BCF925C00000AE2000000000000000000000000000000000000003B00000000sgabios-23d474943dcd55d0550a3d20b3d30e9040a4f15b/sgabios.h/* * Copyright 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* don't allocate ebda if new value at 0x40e will be less than this */ #define EBDA_MIN_SEG 0x9800 #define SGABIOS_EBDA_KB 1 /* note: no testing has yet been done logging other than 256 bytes */ #define SGABIOS_EBDA_BYTES (SGABIOS_EBDA_KB*1024) #define SGABIOS_EBDA_DELTA (SGABIOS_EBDA_BYTES/16) #define SGABIOS_EBDA_LOG_START 256 #define SGABIOS_EBDA_LOG_SIZE 256 #define SGABIOS_EBDA_POS_START (SGABIOS_EBDA_LOG_START+SGABIOS_EBDA_LOG_SIZE) #define SGABIOS_EBDA_POS_LAST (SGABIOS_EBDA_POS_START+(SGABIOS_EBDA_LOG_SIZE*2)-2) /* serial costants that may require modification */ #define COM_BASE_ADDR 0x3f8 #define PORT_SPEED 115200 #define LCR_VALUE 0x13 /* 8n1 */ /* serial constants below shouldn't require modification */ #define IER_OFFSET 0x01 #define FCR_OFFSET 0x02 #define LCR_OFFSET 0x03 #define MCR_OFFSET 0x04 #define LSR_OFFSET 0x05 #define MSR_OFFSET 0x06 #define SCR_OFFSET 0x07 #define LCR_DLAB 0x80 #define MCR_DTRRTS 0x03 #define FCR_FIFO_ENABLE 0x01 #define PORT_DIVISOR 115200 #define TRANSMIT_READY_BIT 0x20 #define BIOS_BUILD_VERSION "$Id: sgabios.S 7 2009-11-13 00:21:26Z smiles@google.com $" #define KBD_HEAD 0x1a #define KBD_TAIL 0x1c #define KBD_BUF_START 0x1e #define KBD_BUF_END 0x3e #define VGA_IO_BASE 0x3d4 #define BDA_SEG 0x40 #define BDA_EBDA 0x0e #define BDA_MEM_SIZE 0x13 #define BDA_MODE_NUM 0x49 #define BDA_COLS 0x4a #define BDA_PAGE_SIZE 0x4c /* BDA word 40:0c traditionally holds the LPT3 io port address... */ /* Reuse it for tracking where the serial console cursor was left */ /* Don't send ansi cursor pos update without text ready to output */ /* Some operations don't update cursor position, but next int 10h */ /* call is often one that might update to where cursor already is */ #define BDA_SERIAL_POS 0x0c #define BDA_CURSOR_BUF 0x50 #define BDA_CURSOR_COL 0x50 #define BDA_CURSOR_ROW 0x51 #define BDA_CURSOR_SCAN 0x60 #define BDA_ACTIVE_PAGE 0x62 #define BDA_6845_ADDR 0x63 #define BDA_MODE_SEL 0x65 #define BDA_COLOR_VAL 0x66 #define BDA_ROM_OFF 0x67 #define BDA_ROM_SEG 0x69 #define BDA_ROWS 0x84 07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000B00000000TRAILER!!!231 blocks
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor