├── .gitignore ├── COPYING ├── COPYING.LESSER ├── Makefile ├── README ├── docs ├── Build_overview.md ├── Contributing.md ├── Debugging.md ├── Developer_Documentation.md ├── Developer_links.md ├── Download.md ├── Execution_and_code_flow.md ├── Linking_overview.md ├── Mailinglist.md ├── Memory_Model.md ├── README ├── Releases.md ├── Runtime_config.md ├── SeaBIOS.md ├── SeaVGABIOS.md └── developer-certificate-of-origin ├── scripts ├── acpi_extract.py ├── acpi_extract_preprocess.py ├── buildrom.py ├── buildversion.py ├── checkrom.py ├── checkstack.py ├── checksum.py ├── encodeint.py ├── gen-offsets.sh ├── kconfig │ ├── .gitignore │ ├── Makefile │ ├── POTFILES.in │ ├── check.sh │ ├── conf.c │ ├── confdata.c │ ├── expr.c │ ├── expr.h │ ├── gconf.c │ ├── gconf.glade │ ├── images.c │ ├── kxgettext.c │ ├── lex.zconf.c │ ├── list.h │ ├── lkc.h │ ├── lkc_proto.h │ ├── lxdialog │ │ ├── .gitignore │ │ ├── BIG.FAT.WARNING │ │ ├── check-lxdialog.sh │ │ ├── checklist.c │ │ ├── dialog.h │ │ ├── inputbox.c │ │ ├── menubox.c │ │ ├── textbox.c │ │ ├── util.c │ │ └── yesno.c │ ├── mconf.c │ ├── menu.c │ ├── merge_config.sh │ ├── nconf.c │ ├── nconf.gui.c │ ├── nconf.h │ ├── qconf.cc │ ├── qconf.h │ ├── streamline_config.pl │ ├── symbol.c │ ├── util.c │ ├── zconf.gperf │ ├── zconf.hash.c_shipped │ ├── zconf.l │ ├── zconf.lex.c_shipped │ ├── zconf.tab.c_shipped │ └── zconf.y ├── layoutrom.py ├── ldnoexec.py ├── readserial.py ├── tarball.sh ├── test-build.sh ├── transdump.py └── vgafixup.py ├── src ├── Kconfig ├── apm.c ├── asm-offsets.c ├── biosvar.h ├── block.c ├── block.h ├── bmp.c ├── boot.c ├── bootsplash.c ├── bregs.h ├── byteorder.h ├── cdrom.c ├── clock.c ├── code16gcc.s ├── config.h ├── cp437.c ├── cp437.h ├── disk.c ├── e820map.c ├── e820map.h ├── entryfuncs.S ├── farptr.h ├── font.c ├── fw │ ├── acpi.c │ ├── biostables.c │ ├── coreboot.c │ ├── csm.c │ ├── dev-pci.h │ ├── dev-piix.h │ ├── dev-q35.h │ ├── dsdt_parser.c │ ├── lzmadecode.c │ ├── lzmadecode.h │ ├── mptable.c │ ├── mtrr.c │ ├── multiboot.c │ ├── paravirt.c │ ├── paravirt.h │ ├── pciinit.c │ ├── pirtable.c │ ├── romfile_loader.c │ ├── romfile_loader.h │ ├── shadow.c │ ├── smbios.c │ ├── smm.c │ ├── smp.c │ ├── xen.c │ └── xen.h ├── gen-defs.h ├── hw │ ├── ahci.c │ ├── ahci.h │ ├── ata.c │ ├── ata.h │ ├── blockcmd.c │ ├── blockcmd.h │ ├── dma.c │ ├── esp-scsi.c │ ├── esp-scsi.h │ ├── floppy.c │ ├── lsi-scsi.c │ ├── lsi-scsi.h │ ├── megasas.c │ ├── megasas.h │ ├── mpt-scsi.c │ ├── mpt-scsi.h │ ├── nvme-int.h │ ├── nvme.c │ ├── nvme.h │ ├── pci.c │ ├── pci.h │ ├── pci_ids.h │ ├── pci_regs.h │ ├── pcidevice.c │ ├── pcidevice.h │ ├── pic.c │ ├── pic.h │ ├── ps2port.c │ ├── ps2port.h │ ├── pvscsi.c │ ├── pvscsi.h │ ├── ramdisk.c │ ├── rtc.c │ ├── rtc.h │ ├── sdcard.c │ ├── serialio.c │ ├── serialio.h │ ├── timer.c │ ├── tpm_drivers.c │ ├── tpm_drivers.h │ ├── usb-ehci.c │ ├── usb-ehci.h │ ├── usb-hid.c │ ├── usb-hid.h │ ├── usb-hub.c │ ├── usb-hub.h │ ├── usb-msc.c │ ├── usb-msc.h │ ├── usb-ohci.c │ ├── usb-ohci.h │ ├── usb-uas.c │ ├── usb-uas.h │ ├── usb-uhci.c │ ├── usb-uhci.h │ ├── usb-xhci.c │ ├── usb-xhci.h │ ├── usb.c │ ├── usb.h │ ├── virtio-blk.c │ ├── virtio-blk.h │ ├── virtio-mmio.c │ ├── virtio-mmio.h │ ├── virtio-pci.c │ ├── virtio-pci.h │ ├── virtio-ring.c │ ├── virtio-ring.h │ ├── virtio-scsi.c │ └── virtio-scsi.h ├── jpeg.c ├── kbd.c ├── list.h ├── malloc.c ├── malloc.h ├── memmap.h ├── misc.c ├── mouse.c ├── optionroms.c ├── output.c ├── output.h ├── pcibios.c ├── pmm.c ├── pnpbios.c ├── post.c ├── resume.c ├── romfile.c ├── romfile.h ├── romlayout.S ├── sercon.c ├── serial.c ├── sha.h ├── sha1.c ├── sha256.c ├── sha512.c ├── stacks.c ├── stacks.h ├── std │ ├── LegacyBios.h │ ├── acpi.h │ ├── bda.h │ ├── disk.h │ ├── mptable.h │ ├── multiboot.h │ ├── optionrom.h │ ├── pirtable.h │ ├── pmm.h │ ├── pnpbios.h │ ├── smbios.h │ ├── tcg.h │ ├── vbe.h │ └── vga.h ├── string.c ├── string.h ├── system.c ├── tcgbios.c ├── tcgbios.h ├── types.h ├── util.h ├── version.c ├── vgahooks.c ├── x86.c └── x86.h └── vgasrc ├── Kconfig ├── ati-tables.S ├── atiext.c ├── bochsdisplay.c ├── bochsvga.c ├── bochsvga.h ├── cbvga.c ├── clext.c ├── geodevga.c ├── geodevga.h ├── ramfb.c ├── stdvga.c ├── stdvga.h ├── stdvgaio.c ├── stdvgamodes.c ├── svgamodes.c ├── svgamodes.h ├── swcursor.c ├── vbe.c ├── vgabios.c ├── vgabios.h ├── vgaentry.S ├── vgafb.c ├── vgafb.h ├── vgafonts.c ├── vgahw.h ├── vgainit.c ├── vgalayout.lds.S ├── vgautil.h └── vgaversion.c /.gitignore: -------------------------------------------------------------------------------- 1 | out 2 | *.pyc 3 | .config 4 | .config.old 5 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Welcome to the SeaBIOS project! This project implements an X86 legacy 2 | bios that is built with standard GNU tools. 3 | 4 | Please see build and developer information at: 5 | 6 | http://seabios.org/Developer_Documentation 7 | 8 | For the impatient, SeaBIOS is built for QEMU and tested on QEMU with: 9 | 10 | make 11 | qemu -bios out/bios.bin 12 | 13 | SeaBIOS can be configured with kconfig. To change the default 14 | configuration one can run "make menuconfig" prior to running "make". 15 | 16 | For other types of builds, and for more detailed developer 17 | documentation, please see the online documentation listed above. 18 | -------------------------------------------------------------------------------- /docs/Contributing.md: -------------------------------------------------------------------------------- 1 | SeaBIOS welcomes contributions of code (either fixing bugs or adding 2 | new functionality). At a high level, the process to contribute a 3 | change is: 4 | 5 | 1. [Obtain](Download) the current code and documentation 6 | 2. Enhance and test the code locally 7 | 3. Submit changes to the SeaBIOS [mailing list](Mailinglist) as a 8 | patch 9 | 4. Receive feedback, answer questions, and possibly provide updated 10 | patches 11 | 5. When accepted, a maintainer (Kevin O'Connor or Gerd Hoffman) will 12 | commit the change to the master SeaBIOS repository 13 | 14 | The SeaBIOS patch submission process is similar to the 15 | [QEMU process](http://wiki.qemu.org/Contribute/SubmitAPatch). Please 16 | review the QEMU process for more details and tips on the best way to 17 | submit patches. The SeaBIOS C code does follow a slightly different 18 | coding style from QEMU (eg, mixed code and C99 style variable 19 | declarations are encouraged, braces are not required around single 20 | statement blocks), however patches in the QEMU style are acceptable. 21 | 22 | As with QEMU, commits must contain a "Signed-off-by" line using your 23 | real name (sorry, no pseudonyms or anonymous contributions) and a 24 | current email address. It indicates agreement with the terms of the 25 | [developer certificate of origin](developer-certificate-of-origin). 26 | -------------------------------------------------------------------------------- /docs/Developer_Documentation.md: -------------------------------------------------------------------------------- 1 | This page is intended for developers interested in understanding and 2 | enhancing SeaBIOS. Please also consider joining the [mailing 3 | list](Mailinglist). 4 | 5 | The SeaBIOS code can be obtained via the [download](Download) 6 | page. For specific information on building SeaBIOS for coreboot, 7 | please see the [coreboot SeaBIOS](http://www.coreboot.org/SeaBIOS) 8 | page. 9 | 10 | See details on [building SeaBIOS](Build overview). 11 | 12 | There is also information on the SeaBIOS [Memory Model](Memory Model). 13 | Along with information on SeaBIOS [Execution and code flow](Execution 14 | and code flow). A description of the process of linking the final 15 | SeaBIOS binary is available at [Linking overview](Linking overview). 16 | 17 | The list of available runtime configuration items is at 18 | [runtime config](Runtime_config). 19 | 20 | To debug SeaBIOS and report problems see SeaBIOS 21 | [debugging](Debugging). To contribute changes to SeaBIOS see 22 | [contributing](Contributing). 23 | 24 | Useful links to specifications is available at [Developer 25 | links](Developer links). 26 | -------------------------------------------------------------------------------- /docs/Developer_links.md: -------------------------------------------------------------------------------- 1 | Links to pages with more information. 2 | 3 | BIOS interfaces 4 | =============== 5 | 6 | Ralf Brown's interrupt list 7 | 8 | * 9 | 10 | Memory layout info 11 | 12 | * 13 | 14 | Old PNP BIOS spec 15 | 16 | * 17 | 18 | T13 BIOS Enhanced Disk Drive (drafts): 19 | 20 | * 21 | 22 | Exported BIOS tables 23 | ==================== 24 | 25 | ACPI spec 26 | 27 | * 28 | 29 | PCI IRQ Routing Table Specification 30 | 31 | * 32 | 33 | MP configuration table 34 | 35 | * 36 | 37 | SM BIOS (aka DMI): 38 | 39 | * 40 | 41 | Hardware information 42 | ==================== 43 | 44 | info on PIC 45 | 46 | * 47 | 48 | info on kbd 49 | 50 | * 51 | 52 | info on vga 53 | 54 | * 55 | 56 | info on lpt 57 | 58 | * 59 | 60 | info on floppy 61 | 62 | * 63 | 64 | info on ata 65 | 66 | * 67 | * 68 | 69 | info on serial 70 | 71 | * 72 | 73 | General information 74 | =================== 75 | 76 | Bochs tech document list 77 | 78 | * 79 | 80 | Phoenix documents 81 | 82 | * 83 | 84 | Dosemu information 85 | 86 | * 87 | -------------------------------------------------------------------------------- /docs/Download.md: -------------------------------------------------------------------------------- 1 | SeaBIOS may be distributed under the terms of the [GNU 2 | LGPLv3](https://www.gnu.org/licenses/lgpl-3.0-standalone.html) license. 3 | Both source code and binaries are available. 4 | 5 | Latest source code 6 | ================== 7 | 8 | The SeaBIOS project uses the [git](https://git-scm.com/) revision 9 | control system. To download the latest source from revision control, 10 | run: 11 | 12 | ``` 13 | $ git clone https://git.seabios.org/seabios.git 14 | $ cd seabios 15 | ``` 16 | 17 | There's also a [website](http://git.seabios.org/) to browse the latest 18 | source code online. 19 | 20 | Released versions 21 | ================= 22 | 23 | Released versions of the source code are available at: 24 | 25 | 26 | 27 | Please see [releases](Releases) for information on each release. 28 | -------------------------------------------------------------------------------- /docs/Mailinglist.md: -------------------------------------------------------------------------------- 1 | For questions and general information about SeaBIOS, please subscribe 2 | to the 3 | [SeaBIOS mailing list](https://mail.coreboot.org/postorius/lists/seabios.seabios.org/). It 4 | is necessary to subscribe to the list in order to send emails (to 5 | combat spam). 6 | 7 | A mailing list archive is available at: 8 | 9 | 10 | Messages prior to January 2019 are archived at: 11 | 12 | 13 | An unofficial archive is also available at: 14 | 15 | -------------------------------------------------------------------------------- /docs/README: -------------------------------------------------------------------------------- 1 | This directory contains SeaBIOS documentation as found on the SeaBIOS 2 | wiki. All the files in this directory (with the exclusion of this 3 | README file) correspond to a page on the wiki. 4 | 5 | The documentation files use markdown syntax. 6 | -------------------------------------------------------------------------------- /docs/SeaBIOS.md: -------------------------------------------------------------------------------- 1 | SeaBIOS is an open source implementation of a 16bit X86 BIOS. SeaBIOS 2 | can run in an emulator or it can run natively on X86 hardware with the 3 | use of [coreboot](http://www.coreboot.org/). 4 | 5 | SeaBIOS is the default BIOS for [qemu](http://www.qemu.org/) and 6 | [kvm](http://www.linux-kvm.org/). 7 | 8 | The [coreboot SeaBIOS](http://www.coreboot.org/SeaBIOS) page has 9 | information on using SeaBIOS in coreboot. Please see the 10 | [releases](Releases) page for information on recent releases. See the 11 | [download](Download) page to obtain SeaBIOS. 12 | 13 | [SeaVGABIOS](SeaVGABIOS) is a sub-project of SeaBIOS. 14 | 15 | Please join the [mailing list](Mailinglist) to contribute to 16 | SeaBIOS. Information on the internals of SeaBIOS is available on the 17 | [Developer Documentation](Developer Documentation) page. 18 | -------------------------------------------------------------------------------- /docs/SeaVGABIOS.md: -------------------------------------------------------------------------------- 1 | SeaVGABIOS is a sub-project of the SeaBIOS project - it is an open 2 | source implementation of a 16bit X86 3 | [VGA BIOS](http://en.wikipedia.org/wiki/Video_BIOS). SeaVGABIOS is the 4 | default VGA BIOS on [QEMU](http://www.qemu.org/). SeaVGABIOS can also 5 | run natively on some X86 VGA hardware with 6 | [coreboot](http://www.coreboot.org/). 7 | 8 | Building SeaVGABIOS 9 | =================== 10 | 11 | To build SeaVGABIOS, obtain the [code](Download), run `make 12 | menuconfig` and select the type of VGA BIOS to build in the "VGA ROM" 13 | menu. Once selected, run `make` and the final VGA BIOS binary will be 14 | located in "out/vgabios.bin". 15 | 16 | The choice of available VGA BIOSes within "make menuconfig" is 17 | dependent on whether CONFIG_QEMU, CONFIG_COREBOOT, or CONFIG_CSM is 18 | selected. Also, the debug options under the "Debugging" menu apply to 19 | SeaVGABIOS. All other options found in "make menuconfig" apply only to 20 | SeaBIOS and will not impact the SeaVGABIOS build. 21 | 22 | If SeaVGABIOS is needed for multiple different devices (eg, QEMU's 23 | cirrus emulation and QEMU's "dispi" emulation), then one must compile 24 | SeaVGABIOS multiple times with the appropriate config for each build. 25 | 26 | SeaVGABIOS code 27 | =============== 28 | 29 | The source code for SeaVGABIOS is located in the SeaBIOS 30 | [git repository](Download). The main VGA BIOS code is located in the 31 | "vgasrc/" directory. The VGA BIOS code is always compiled in 16bit 32 | mode. 33 | 34 | The SeaVGABIOS builds to a separate binary from the main SeaBIOS 35 | binary, and much of the VGA BIOS code is separate from the main BIOS 36 | code. However, much of the SeaBIOS 37 | [developer documentation](Developer_Documentation) applies to 38 | SeaVGABIOS. To contribute, please join the 39 | [SeaBIOS mailing list](Mailinglist). 40 | -------------------------------------------------------------------------------- /docs/developer-certificate-of-origin: -------------------------------------------------------------------------------- 1 | Developer Certificate of Origin 2 | Version 1.1 3 | 4 | Copyright (C) 2004, 2006 The Linux Foundation and its contributors. 5 | 1 Letterman Drive 6 | Suite D4700 7 | San Francisco, CA, 94129 8 | 9 | Everyone is permitted to copy and distribute verbatim copies of this 10 | license document, but changing it is not allowed. 11 | 12 | 13 | Developer's Certificate of Origin 1.1 14 | 15 | By making a contribution to this project, I certify that: 16 | 17 | (a) The contribution was created in whole or in part by me and I 18 | have the right to submit it under the open source license 19 | indicated in the file; or 20 | 21 | (b) The contribution is based upon previous work that, to the best 22 | of my knowledge, is covered under an appropriate open source 23 | license and I have the right under that license to submit that 24 | work with modifications, whether created in whole or in part 25 | by me, under the same open source license (unless I am 26 | permitted to submit under a different license), as indicated 27 | in the file; or 28 | 29 | (c) The contribution was provided directly to me by some other 30 | person who certified (a), (b) or (c) and I have not modified 31 | it. 32 | 33 | (d) I understand and agree that this project and the contribution 34 | are public and that a record of the contribution (including all 35 | personal information I submit with it, including my sign-off) is 36 | maintained indefinitely and may be redistributed consistent with 37 | this project or the open source license(s) involved. 38 | -------------------------------------------------------------------------------- /scripts/acpi_extract_preprocess.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Copyright (C) 2011 Red Hat, Inc., Michael S. Tsirkin 3 | # 4 | # This file may be distributed under the terms of the GNU GPLv3 license. 5 | 6 | # Read a preprocessed ASL listing and put each ACPI_EXTRACT 7 | # directive in a comment, to make iasl skip it. 8 | # We also put each directive on a new line, the machinery 9 | # in scripts/acpi_extract.py requires this. 10 | 11 | import re 12 | import sys 13 | import fileinput 14 | 15 | def die(diag): 16 | sys.stderr.write("Error: %s\n" % (diag)) 17 | sys.exit(1) 18 | 19 | # Note: () around pattern make split return matched string as part of list 20 | psplit = re.compile(r''' ( 21 | \b # At word boundary 22 | ACPI_EXTRACT_\w+ # directive 23 | \s+ # some whitespace 24 | \w+ # array name 25 | )''', re.VERBOSE) 26 | 27 | lineno = 0 28 | for line in fileinput.input(): 29 | # line number and debug string to output in case of errors 30 | lineno = lineno + 1 31 | debug = "input line %d: %s" % (lineno, line.rstrip()) 32 | 33 | s = psplit.split(line) 34 | # The way split works, each odd item is the matching ACPI_EXTRACT directive. 35 | # Put each in a comment, and on a line by itself. 36 | for i in range(len(s)): 37 | if (i % 2): 38 | sys.stdout.write("\n/* %s */\n" % s[i]) 39 | else: 40 | sys.stdout.write(s[i]) 41 | 42 | -------------------------------------------------------------------------------- /scripts/buildrom.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Fill in checksum/size of an option rom, and pad it to proper length. 3 | # 4 | # Copyright (C) 2009 Kevin O'Connor 5 | # 6 | # This file may be distributed under the terms of the GNU GPLv3 license. 7 | 8 | import sys, struct 9 | 10 | def alignpos(pos, alignbytes): 11 | mask = alignbytes - 1 12 | return (pos + mask) & ~mask 13 | 14 | def checksum(data): 15 | if (sys.version_info > (3, 0)): 16 | cksum = sum(data) 17 | else: 18 | cksum = sum(map(ord, data)) 19 | return struct.pack(' 5 | # 6 | # This file may be distributed under the terms of the GNU GPLv3 license. 7 | 8 | import sys, struct 9 | import layoutrom, buildrom 10 | 11 | def subst(data, offset, new): 12 | return data[:offset] + new + data[offset + len(new):] 13 | 14 | def checksum(data, start, size, csum): 15 | sumbyte = buildrom.checksum(data[start:start+size]) 16 | return subst(data, start+csum, sumbyte) 17 | 18 | def main(): 19 | # Get args 20 | objinfo, finalsize, rawfile, outfile = sys.argv[1:] 21 | 22 | # Read in symbols 23 | objinfofile = open(objinfo, 'r') 24 | symbols = layoutrom.parseObjDump(objinfofile, 'in')[1] 25 | 26 | # Read in raw file 27 | f = open(rawfile, 'rb') 28 | rawdata = f.read() 29 | f.close() 30 | datasize = len(rawdata) 31 | finalsize = int(finalsize) * 1024 32 | if finalsize == 0: 33 | finalsize = 64*1024 34 | if datasize > 64*1024: 35 | finalsize = 128*1024 36 | if datasize > 128*1024: 37 | finalsize = 256*1024 38 | if datasize > finalsize: 39 | print("Error! ROM doesn't fit (%d > %d)" % (datasize, finalsize)) 40 | print(" You have to either increase the size (CONFIG_ROM_SIZE)") 41 | print(" or turn off some features (such as hardware support not") 42 | print(" needed) to make it fit. Trying a more recent gcc version") 43 | print(" might work too.") 44 | sys.exit(1) 45 | 46 | # Sanity checks 47 | start = symbols['code32flat_start'].offset 48 | end = symbols['code32flat_end'].offset 49 | expend = layoutrom.BUILD_BIOS_ADDR + layoutrom.BUILD_BIOS_SIZE 50 | if end != expend: 51 | print("Error! Code does not end at 0x%x (got 0x%x)" % ( 52 | expend, end)) 53 | sys.exit(1) 54 | if datasize > finalsize: 55 | print("Error! Code is too big (0x%x vs 0x%x)" % ( 56 | datasize, finalsize)) 57 | sys.exit(1) 58 | expdatasize = end - start 59 | if datasize != expdatasize: 60 | print("Error! Unknown extra data (0x%x vs 0x%x)" % ( 61 | datasize, expdatasize)) 62 | sys.exit(1) 63 | 64 | # Fix up CSM Compatibility16 table 65 | if 'csm_compat_table' in symbols and 'entry_csm' in symbols: 66 | # Field offsets within EFI_COMPATIBILITY16_TABLE 67 | ENTRY_FIELD_OFS = 14 # Compatibility16CallOffset (UINT16) 68 | SIZE_FIELD_OFS = 5 # TableLength (UINT8) 69 | CSUM_FIELD_OFS = 4 # TableChecksum (UINT8) 70 | 71 | tableofs = symbols['csm_compat_table'].offset - symbols['code32flat_start'].offset 72 | entry_addr = symbols['entry_csm'].offset - layoutrom.BUILD_BIOS_ADDR 73 | entry_addr = struct.pack(' 5 | # 6 | # This file may be distributed under the terms of the GNU GPLv3 license. 7 | 8 | import sys 9 | 10 | def main(): 11 | data = sys.stdin.read() 12 | ords = map(ord, data) 13 | print("sum=%x\n" % sum(ords)) 14 | 15 | if __name__ == '__main__': 16 | main() 17 | -------------------------------------------------------------------------------- /scripts/encodeint.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Encode an integer in little endian format in a file. 3 | # 4 | # Copyright (C) 2011 Kevin O'Connor 5 | # 6 | # This file may be distributed under the terms of the GNU GPLv3 license. 7 | 8 | import sys 9 | import struct 10 | 11 | def main(): 12 | filename = sys.argv[1] 13 | value = int(sys.argv[2], 0) 14 | 15 | outval = struct.pack(' "$OUTFILE" </{s:->#\(.*\):/* \1 */:; \ 13 | s:^->\([^ ]*\) [\$\#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \ 14 | s:->::; p;}" < "$INFILE" >> "$OUTFILE" 15 | cat >> "$OUTFILE" < /dev/null 2>&1 << EOF 4 | #include 5 | int main() 6 | { 7 | gettext(""); 8 | return 0; 9 | } 10 | EOF 11 | if [ ! "$?" -eq "0" ]; then 12 | echo -DKBUILD_NO_NLS; 13 | fi 14 | -------------------------------------------------------------------------------- /scripts/kconfig/list.h: -------------------------------------------------------------------------------- 1 | #ifndef LIST_H 2 | #define LIST_H 3 | 4 | /* 5 | * Copied from include/linux/... 6 | */ 7 | 8 | #undef offsetof 9 | #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 10 | 11 | /** 12 | * container_of - cast a member of a structure out to the containing structure 13 | * @ptr: the pointer to the member. 14 | * @type: the type of the container struct this is embedded in. 15 | * @member: the name of the member within the struct. 16 | * 17 | */ 18 | #define container_of(ptr, type, member) ({ \ 19 | const typeof( ((type *)0)->member ) *__mptr = (ptr); \ 20 | (type *)( (char *)__mptr - offsetof(type,member) );}) 21 | 22 | 23 | struct list_head { 24 | struct list_head *next, *prev; 25 | }; 26 | 27 | 28 | #define LIST_HEAD_INIT(name) { &(name), &(name) } 29 | 30 | #define LIST_HEAD(name) \ 31 | struct list_head name = LIST_HEAD_INIT(name) 32 | 33 | /** 34 | * list_entry - get the struct for this entry 35 | * @ptr: the &struct list_head pointer. 36 | * @type: the type of the struct this is embedded in. 37 | * @member: the name of the list_struct within the struct. 38 | */ 39 | #define list_entry(ptr, type, member) \ 40 | container_of(ptr, type, member) 41 | 42 | /** 43 | * list_for_each_entry - iterate over list of given type 44 | * @pos: the type * to use as a loop cursor. 45 | * @head: the head for your list. 46 | * @member: the name of the list_struct within the struct. 47 | */ 48 | #define list_for_each_entry(pos, head, member) \ 49 | for (pos = list_entry((head)->next, typeof(*pos), member); \ 50 | &pos->member != (head); \ 51 | pos = list_entry(pos->member.next, typeof(*pos), member)) 52 | 53 | /** 54 | * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry 55 | * @pos: the type * to use as a loop cursor. 56 | * @n: another type * to use as temporary storage 57 | * @head: the head for your list. 58 | * @member: the name of the list_struct within the struct. 59 | */ 60 | #define list_for_each_entry_safe(pos, n, head, member) \ 61 | for (pos = list_entry((head)->next, typeof(*pos), member), \ 62 | n = list_entry(pos->member.next, typeof(*pos), member); \ 63 | &pos->member != (head); \ 64 | pos = n, n = list_entry(n->member.next, typeof(*n), member)) 65 | 66 | /** 67 | * list_empty - tests whether a list is empty 68 | * @head: the list to test. 69 | */ 70 | static inline int list_empty(const struct list_head *head) 71 | { 72 | return head->next == head; 73 | } 74 | 75 | /* 76 | * Insert a new entry between two known consecutive entries. 77 | * 78 | * This is only for internal list manipulation where we know 79 | * the prev/next entries already! 80 | */ 81 | static inline void __list_add(struct list_head *_new, 82 | struct list_head *prev, 83 | struct list_head *next) 84 | { 85 | next->prev = _new; 86 | _new->next = next; 87 | _new->prev = prev; 88 | prev->next = _new; 89 | } 90 | 91 | /** 92 | * list_add_tail - add a new entry 93 | * @new: new entry to be added 94 | * @head: list head to add it before 95 | * 96 | * Insert a new entry before the specified head. 97 | * This is useful for implementing queues. 98 | */ 99 | static inline void list_add_tail(struct list_head *_new, struct list_head *head) 100 | { 101 | __list_add(_new, head->prev, head); 102 | } 103 | 104 | /* 105 | * Delete a list entry by making the prev/next entries 106 | * point to each other. 107 | * 108 | * This is only for internal list manipulation where we know 109 | * the prev/next entries already! 110 | */ 111 | static inline void __list_del(struct list_head *prev, struct list_head *next) 112 | { 113 | next->prev = prev; 114 | prev->next = next; 115 | } 116 | 117 | #define LIST_POISON1 ((void *) 0x00100100) 118 | #define LIST_POISON2 ((void *) 0x00200200) 119 | /** 120 | * list_del - deletes entry from list. 121 | * @entry: the element to delete from the list. 122 | * Note: list_empty() on entry does not return true after this, the entry is 123 | * in an undefined state. 124 | */ 125 | static inline void list_del(struct list_head *entry) 126 | { 127 | __list_del(entry->prev, entry->next); 128 | entry->next = (struct list_head*)LIST_POISON1; 129 | entry->prev = (struct list_head*)LIST_POISON2; 130 | } 131 | #endif 132 | -------------------------------------------------------------------------------- /scripts/kconfig/lkc_proto.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* confdata.c */ 4 | P(conf_parse,void,(const char *name)); 5 | P(conf_read,int,(const char *name)); 6 | P(conf_read_simple,int,(const char *name, int)); 7 | P(conf_write_defconfig,int,(const char *name)); 8 | P(conf_write,int,(const char *name)); 9 | P(conf_write_autoconf,int,(void)); 10 | P(conf_get_changed,bool,(void)); 11 | P(conf_set_changed_callback, void,(void (*fn)(void))); 12 | P(conf_set_message_callback, void,(void (*fn)(const char *fmt, va_list ap))); 13 | 14 | /* menu.c */ 15 | P(rootmenu,struct menu,); 16 | 17 | P(menu_is_empty, bool, (struct menu *menu)); 18 | P(menu_is_visible, bool, (struct menu *menu)); 19 | P(menu_has_prompt, bool, (struct menu *menu)); 20 | P(menu_get_prompt,const char *,(struct menu *menu)); 21 | P(menu_get_root_menu,struct menu *,(struct menu *menu)); 22 | P(menu_get_parent_menu,struct menu *,(struct menu *menu)); 23 | P(menu_has_help,bool,(struct menu *menu)); 24 | P(menu_get_help,const char *,(struct menu *menu)); 25 | P(get_symbol_str, void, (struct gstr *r, struct symbol *sym, struct list_head 26 | *head)); 27 | P(get_relations_str, struct gstr, (struct symbol **sym_arr, struct list_head 28 | *head)); 29 | P(menu_get_ext_help,void,(struct menu *menu, struct gstr *help)); 30 | 31 | /* symbol.c */ 32 | P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]); 33 | 34 | P(sym_lookup,struct symbol *,(const char *name, int flags)); 35 | P(sym_find,struct symbol *,(const char *name)); 36 | P(sym_expand_string_value,const char *,(const char *in)); 37 | P(sym_escape_string_value, const char *,(const char *in)); 38 | P(sym_re_search,struct symbol **,(const char *pattern)); 39 | P(sym_type_name,const char *,(enum symbol_type type)); 40 | P(sym_calc_value,void,(struct symbol *sym)); 41 | P(sym_get_type,enum symbol_type,(struct symbol *sym)); 42 | P(sym_tristate_within_range,bool,(struct symbol *sym,tristate tri)); 43 | P(sym_set_tristate_value,bool,(struct symbol *sym,tristate tri)); 44 | P(sym_toggle_tristate_value,tristate,(struct symbol *sym)); 45 | P(sym_string_valid,bool,(struct symbol *sym, const char *newval)); 46 | P(sym_string_within_range,bool,(struct symbol *sym, const char *str)); 47 | P(sym_set_string_value,bool,(struct symbol *sym, const char *newval)); 48 | P(sym_is_changable,bool,(struct symbol *sym)); 49 | P(sym_get_choice_prop,struct property *,(struct symbol *sym)); 50 | P(sym_get_default_prop,struct property *,(struct symbol *sym)); 51 | P(sym_get_string_value,const char *,(struct symbol *sym)); 52 | 53 | P(prop_get_type_name,const char *,(enum prop_type type)); 54 | 55 | /* expr.c */ 56 | P(expr_compare_type,int,(enum expr_type t1, enum expr_type t2)); 57 | P(expr_print,void,(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken)); 58 | -------------------------------------------------------------------------------- /scripts/kconfig/lxdialog/.gitignore: -------------------------------------------------------------------------------- 1 | # 2 | # Generated files 3 | # 4 | lxdialog 5 | -------------------------------------------------------------------------------- /scripts/kconfig/lxdialog/BIG.FAT.WARNING: -------------------------------------------------------------------------------- 1 | This is NOT the official version of dialog. This version has been 2 | significantly modified from the original. It is for use by the Linux 3 | kernel configuration script. Please do not bother Savio Lam with 4 | questions about this program. 5 | -------------------------------------------------------------------------------- /scripts/kconfig/lxdialog/check-lxdialog.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Check ncurses compatibility 3 | 4 | # What library to link 5 | ldflags() 6 | { 7 | pkg-config --libs ncursesw 2>/dev/null && exit 8 | pkg-config --libs ncurses 2>/dev/null && exit 9 | for ext in so a dll.a dylib ; do 10 | for lib in ncursesw ncurses curses ; do 11 | $cc -print-file-name=lib${lib}.${ext} | grep -q / 12 | if [ $? -eq 0 ]; then 13 | echo "-l${lib}" 14 | exit 15 | fi 16 | done 17 | done 18 | exit 1 19 | } 20 | 21 | # Where is ncurses.h? 22 | ccflags() 23 | { 24 | if [ -f /usr/include/ncursesw/curses.h ]; then 25 | echo '-I/usr/include/ncursesw -DCURSES_LOC=""' 26 | echo ' -DNCURSES_WIDECHAR=1' 27 | elif [ -f /usr/include/ncurses/ncurses.h ]; then 28 | echo '-I/usr/include/ncurses -DCURSES_LOC=""' 29 | elif [ -f /usr/include/ncurses/curses.h ]; then 30 | echo '-I/usr/include/ncurses -DCURSES_LOC=""' 31 | elif [ -f /usr/include/ncurses.h ]; then 32 | echo '-DCURSES_LOC=""' 33 | else 34 | echo '-DCURSES_LOC=""' 35 | fi 36 | } 37 | 38 | # Temp file, try to clean up after us 39 | tmp=.lxdialog.tmp 40 | trap "rm -f $tmp" 0 1 2 3 15 41 | 42 | # Check if we can link to ncurses 43 | check() { 44 | $cc -x c - -o $tmp 2>/dev/null <<'EOF' 45 | #include CURSES_LOC 46 | main() {} 47 | EOF 48 | if [ $? != 0 ]; then 49 | echo " *** Unable to find the ncurses libraries or the" 1>&2 50 | echo " *** required header files." 1>&2 51 | echo " *** 'make menuconfig' requires the ncurses libraries." 1>&2 52 | echo " *** " 1>&2 53 | echo " *** Install ncurses (ncurses-devel) and try again." 1>&2 54 | echo " *** " 1>&2 55 | exit 1 56 | fi 57 | } 58 | 59 | usage() { 60 | printf "Usage: $0 [-check compiler options|-ccflags|-ldflags compiler options]\n" 61 | } 62 | 63 | if [ $# -eq 0 ]; then 64 | usage 65 | exit 1 66 | fi 67 | 68 | cc="" 69 | case "$1" in 70 | "-check") 71 | shift 72 | cc="$@" 73 | check 74 | ;; 75 | "-ccflags") 76 | ccflags 77 | ;; 78 | "-ldflags") 79 | shift 80 | cc="$@" 81 | ldflags 82 | ;; 83 | "*") 84 | usage 85 | exit 1 86 | ;; 87 | esac 88 | -------------------------------------------------------------------------------- /scripts/kconfig/lxdialog/yesno.c: -------------------------------------------------------------------------------- 1 | /* 2 | * yesno.c -- implements the yes/no box 3 | * 4 | * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) 5 | * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License 9 | * as published by the Free Software Foundation; either version 2 10 | * of the License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | */ 21 | 22 | #include "dialog.h" 23 | 24 | /* 25 | * Display termination buttons 26 | */ 27 | static void print_buttons(WINDOW * dialog, int height, int width, int selected) 28 | { 29 | int x = width / 2 - 10; 30 | int y = height - 2; 31 | 32 | print_button(dialog, gettext(" Yes "), y, x, selected == 0); 33 | print_button(dialog, gettext(" No "), y, x + 13, selected == 1); 34 | 35 | wmove(dialog, y, x + 1 + 13 * selected); 36 | wrefresh(dialog); 37 | } 38 | 39 | /* 40 | * Display a dialog box with two buttons - Yes and No 41 | */ 42 | int dialog_yesno(const char *title, const char *prompt, int height, int width) 43 | { 44 | int i, x, y, key = 0, button = 0; 45 | WINDOW *dialog; 46 | 47 | do_resize: 48 | if (getmaxy(stdscr) < (height + YESNO_HEIGTH_MIN)) 49 | return -ERRDISPLAYTOOSMALL; 50 | if (getmaxx(stdscr) < (width + YESNO_WIDTH_MIN)) 51 | return -ERRDISPLAYTOOSMALL; 52 | 53 | /* center dialog box on screen */ 54 | x = (getmaxx(stdscr) - width) / 2; 55 | y = (getmaxy(stdscr) - height) / 2; 56 | 57 | draw_shadow(stdscr, y, x, height, width); 58 | 59 | dialog = newwin(height, width, y, x); 60 | keypad(dialog, TRUE); 61 | 62 | draw_box(dialog, 0, 0, height, width, 63 | dlg.dialog.atr, dlg.border.atr); 64 | wattrset(dialog, dlg.border.atr); 65 | mvwaddch(dialog, height - 3, 0, ACS_LTEE); 66 | for (i = 0; i < width - 2; i++) 67 | waddch(dialog, ACS_HLINE); 68 | wattrset(dialog, dlg.dialog.atr); 69 | waddch(dialog, ACS_RTEE); 70 | 71 | print_title(dialog, title, width); 72 | 73 | wattrset(dialog, dlg.dialog.atr); 74 | print_autowrap(dialog, prompt, width - 2, 1, 3); 75 | 76 | print_buttons(dialog, height, width, 0); 77 | 78 | while (key != KEY_ESC) { 79 | key = wgetch(dialog); 80 | switch (key) { 81 | case 'Y': 82 | case 'y': 83 | delwin(dialog); 84 | return 0; 85 | case 'N': 86 | case 'n': 87 | delwin(dialog); 88 | return 1; 89 | 90 | case TAB: 91 | case KEY_LEFT: 92 | case KEY_RIGHT: 93 | button = ((key == KEY_LEFT ? --button : ++button) < 0) ? 1 : (button > 1 ? 0 : button); 94 | 95 | print_buttons(dialog, height, width, button); 96 | wrefresh(dialog); 97 | break; 98 | case ' ': 99 | case '\n': 100 | delwin(dialog); 101 | return button; 102 | case KEY_ESC: 103 | key = on_key_esc(dialog); 104 | break; 105 | case KEY_RESIZE: 106 | delwin(dialog); 107 | on_key_resize(); 108 | goto do_resize; 109 | } 110 | } 111 | 112 | delwin(dialog); 113 | return key; /* ESC pressed */ 114 | } 115 | -------------------------------------------------------------------------------- /scripts/kconfig/merge_config.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # merge_config.sh - Takes a list of config fragment values, and merges 3 | # them one by one. Provides warnings on overridden values, and specified 4 | # values that did not make it to the resulting .config file (due to missed 5 | # dependencies or config symbol removal). 6 | # 7 | # Portions reused from kconf_check and generate_cfg: 8 | # http://git.yoctoproject.org/cgit/cgit.cgi/yocto-kernel-tools/tree/tools/kconf_check 9 | # http://git.yoctoproject.org/cgit/cgit.cgi/yocto-kernel-tools/tree/tools/generate_cfg 10 | # 11 | # Copyright (c) 2009-2010 Wind River Systems, Inc. 12 | # Copyright 2011 Linaro 13 | # 14 | # This program is free software; you can redistribute it and/or modify 15 | # it under the terms of the GNU General Public License version 2 as 16 | # published by the Free Software Foundation. 17 | # 18 | # This program is distributed in the hope that it will be useful, 19 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 21 | # See the GNU General Public License for more details. 22 | 23 | clean_up() { 24 | rm -f $TMP_FILE 25 | exit 26 | } 27 | trap clean_up HUP INT TERM 28 | 29 | usage() { 30 | echo "Usage: $0 [OPTIONS] [CONFIG [...]]" 31 | echo " -h display this help text" 32 | echo " -m only merge the fragments, do not execute the make command" 33 | echo " -n use allnoconfig instead of alldefconfig" 34 | echo " -r list redundant entries when merging fragments" 35 | echo " -O dir to put generated output files" 36 | } 37 | 38 | MAKE=true 39 | ALLTARGET=alldefconfig 40 | WARNREDUN=false 41 | OUTPUT=. 42 | 43 | while true; do 44 | case $1 in 45 | "-n") 46 | ALLTARGET=allnoconfig 47 | shift 48 | continue 49 | ;; 50 | "-m") 51 | MAKE=false 52 | shift 53 | continue 54 | ;; 55 | "-h") 56 | usage 57 | exit 58 | ;; 59 | "-r") 60 | WARNREDUN=true 61 | shift 62 | continue 63 | ;; 64 | "-O") 65 | if [ -d $2 ];then 66 | OUTPUT=$(echo $2 | sed 's/\/*$//') 67 | else 68 | echo "output directory $2 does not exist" 1>&2 69 | exit 1 70 | fi 71 | shift 2 72 | continue 73 | ;; 74 | *) 75 | break 76 | ;; 77 | esac 78 | done 79 | 80 | INITFILE=$1 81 | shift; 82 | 83 | MERGE_LIST=$* 84 | SED_CONFIG_EXP="s/^\(# \)\{0,1\}\(CONFIG_[a-zA-Z0-9_]*\)[= ].*/\2/p" 85 | TMP_FILE=$(mktemp ./.tmp.config.XXXXXXXXXX) 86 | 87 | echo "Using $INITFILE as base" 88 | cat $INITFILE > $TMP_FILE 89 | 90 | # Merge files, printing warnings on overrided values 91 | for MERGE_FILE in $MERGE_LIST ; do 92 | echo "Merging $MERGE_FILE" 93 | CFG_LIST=$(sed -n "$SED_CONFIG_EXP" $MERGE_FILE) 94 | 95 | for CFG in $CFG_LIST ; do 96 | grep -q -w $CFG $TMP_FILE 97 | if [ $? -eq 0 ] ; then 98 | PREV_VAL=$(grep -w $CFG $TMP_FILE) 99 | NEW_VAL=$(grep -w $CFG $MERGE_FILE) 100 | if [ "x$PREV_VAL" != "x$NEW_VAL" ] ; then 101 | echo Value of $CFG is redefined by fragment $MERGE_FILE: 102 | echo Previous value: $PREV_VAL 103 | echo New value: $NEW_VAL 104 | echo 105 | elif [ "$WARNREDUN" = "true" ]; then 106 | echo Value of $CFG is redundant by fragment $MERGE_FILE: 107 | fi 108 | sed -i "/$CFG[ =]/d" $TMP_FILE 109 | fi 110 | done 111 | cat $MERGE_FILE >> $TMP_FILE 112 | done 113 | 114 | if [ "$MAKE" = "false" ]; then 115 | cp $TMP_FILE $OUTPUT/.config 116 | echo "#" 117 | echo "# merged configuration written to $OUTPUT/.config (needs make)" 118 | echo "#" 119 | clean_up 120 | exit 121 | fi 122 | 123 | # If we have an output dir, setup the O= argument, otherwise leave 124 | # it blank, since O=. will create an unnecessary ./source softlink 125 | OUTPUT_ARG="" 126 | if [ "$OUTPUT" != "." ] ; then 127 | OUTPUT_ARG="O=$OUTPUT" 128 | fi 129 | 130 | 131 | # Use the merged file as the starting point for: 132 | # alldefconfig: Fills in any missing symbols with Kconfig default 133 | # allnoconfig: Fills in any missing symbols with # CONFIG_* is not set 134 | make KCONFIG_ALLCONFIG=$TMP_FILE $OUTPUT_ARG $ALLTARGET 135 | 136 | 137 | # Check all specified config values took (might have missed-dependency issues) 138 | for CFG in $(sed -n "$SED_CONFIG_EXP" $TMP_FILE); do 139 | 140 | REQUESTED_VAL=$(grep -w -e "$CFG" $TMP_FILE) 141 | ACTUAL_VAL=$(grep -w -e "$CFG" $OUTPUT/.config) 142 | if [ "x$REQUESTED_VAL" != "x$ACTUAL_VAL" ] ; then 143 | echo "Value requested for $CFG not in final .config" 144 | echo "Requested value: $REQUESTED_VAL" 145 | echo "Actual value: $ACTUAL_VAL" 146 | echo "" 147 | fi 148 | done 149 | 150 | clean_up 151 | -------------------------------------------------------------------------------- /scripts/kconfig/nconf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 Nir Tzachar 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #include "ncurses.h" 28 | 29 | #define max(a, b) ({\ 30 | typeof(a) _a = a;\ 31 | typeof(b) _b = b;\ 32 | _a > _b ? _a : _b; }) 33 | 34 | #define min(a, b) ({\ 35 | typeof(a) _a = a;\ 36 | typeof(b) _b = b;\ 37 | _a < _b ? _a : _b; }) 38 | 39 | typedef enum { 40 | NORMAL = 1, 41 | MAIN_HEADING, 42 | MAIN_MENU_BOX, 43 | MAIN_MENU_FORE, 44 | MAIN_MENU_BACK, 45 | MAIN_MENU_GREY, 46 | MAIN_MENU_HEADING, 47 | SCROLLWIN_TEXT, 48 | SCROLLWIN_HEADING, 49 | SCROLLWIN_BOX, 50 | DIALOG_TEXT, 51 | DIALOG_MENU_FORE, 52 | DIALOG_MENU_BACK, 53 | DIALOG_BOX, 54 | INPUT_BOX, 55 | INPUT_HEADING, 56 | INPUT_TEXT, 57 | INPUT_FIELD, 58 | FUNCTION_TEXT, 59 | FUNCTION_HIGHLIGHT, 60 | ATTR_MAX 61 | } attributes_t; 62 | extern attributes_t attributes[]; 63 | 64 | typedef enum { 65 | F_HELP = 1, 66 | F_SYMBOL = 2, 67 | F_INSTS = 3, 68 | F_CONF = 4, 69 | F_BACK = 5, 70 | F_SAVE = 6, 71 | F_LOAD = 7, 72 | F_SEARCH = 8, 73 | F_EXIT = 9, 74 | } function_key; 75 | 76 | void set_colors(void); 77 | 78 | /* this changes the windows attributes !!! */ 79 | void print_in_middle(WINDOW *win, 80 | int starty, 81 | int startx, 82 | int width, 83 | const char *string, 84 | chtype color); 85 | int get_line_length(const char *line); 86 | int get_line_no(const char *text); 87 | const char *get_line(const char *text, int line_no); 88 | void fill_window(WINDOW *win, const char *text); 89 | int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...); 90 | int dialog_inputbox(WINDOW *main_window, 91 | const char *title, const char *prompt, 92 | const char *init, char **resultp, int *result_len); 93 | void refresh_all_windows(WINDOW *main_window); 94 | void show_scroll_win(WINDOW *main_window, 95 | const char *title, 96 | const char *text); 97 | -------------------------------------------------------------------------------- /scripts/kconfig/util.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002-2005 Roman Zippel 3 | * Copyright (C) 2002-2005 Sam Ravnborg 4 | * 5 | * Released under the terms of the GNU GPL v2.0. 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include "lkc.h" 12 | 13 | /* file already present in list? If not add it */ 14 | struct file *file_lookup(const char *name) 15 | { 16 | struct file *file; 17 | const char *file_name = sym_expand_string_value(name); 18 | 19 | for (file = file_list; file; file = file->next) { 20 | if (!strcmp(name, file->name)) { 21 | free((void *)file_name); 22 | return file; 23 | } 24 | } 25 | 26 | file = xmalloc(sizeof(*file)); 27 | memset(file, 0, sizeof(*file)); 28 | file->name = file_name; 29 | file->next = file_list; 30 | file_list = file; 31 | return file; 32 | } 33 | 34 | /* write a dependency file as used by kbuild to track dependencies */ 35 | int file_write_dep(const char *name) 36 | { 37 | struct symbol *sym, *env_sym; 38 | struct expr *e; 39 | struct file *file; 40 | FILE *out; 41 | 42 | if (!name) 43 | name = ".kconfig.d"; 44 | out = fopen("..config.tmp", "w"); 45 | if (!out) 46 | return 1; 47 | fprintf(out, "deps_config := \\\n"); 48 | for (file = file_list; file; file = file->next) { 49 | if (file->next) 50 | fprintf(out, "\t%s \\\n", file->name); 51 | else 52 | fprintf(out, "\t%s\n", file->name); 53 | } 54 | fprintf(out, "\n%s: \\\n" 55 | "\t$(deps_config)\n\n", conf_get_autoconfig_name()); 56 | 57 | expr_list_for_each_sym(sym_env_list, e, sym) { 58 | struct property *prop; 59 | const char *value; 60 | 61 | prop = sym_get_env_prop(sym); 62 | env_sym = prop_get_symbol(prop); 63 | if (!env_sym) 64 | continue; 65 | value = getenv(env_sym->name); 66 | if (!value) 67 | value = ""; 68 | fprintf(out, "ifneq \"$(%s)\" \"%s\"\n", env_sym->name, value); 69 | fprintf(out, "%s: FORCE\n", conf_get_autoconfig_name()); 70 | fprintf(out, "endif\n"); 71 | } 72 | 73 | fprintf(out, "\n$(deps_config): ;\n"); 74 | fclose(out); 75 | rename("..config.tmp", name); 76 | return 0; 77 | } 78 | 79 | 80 | /* Allocate initial growable string */ 81 | struct gstr str_new(void) 82 | { 83 | struct gstr gs; 84 | gs.s = xmalloc(sizeof(char) * 64); 85 | gs.len = 64; 86 | gs.max_width = 0; 87 | strcpy(gs.s, "\0"); 88 | return gs; 89 | } 90 | 91 | /* Allocate and assign growable string */ 92 | struct gstr str_assign(const char *s) 93 | { 94 | struct gstr gs; 95 | gs.s = strdup(s); 96 | gs.len = strlen(s) + 1; 97 | gs.max_width = 0; 98 | return gs; 99 | } 100 | 101 | /* Free storage for growable string */ 102 | void str_free(struct gstr *gs) 103 | { 104 | if (gs->s) 105 | free(gs->s); 106 | gs->s = NULL; 107 | gs->len = 0; 108 | } 109 | 110 | /* Append to growable string */ 111 | void str_append(struct gstr *gs, const char *s) 112 | { 113 | size_t l; 114 | if (s) { 115 | l = strlen(gs->s) + strlen(s) + 1; 116 | if (l > gs->len) { 117 | gs->s = realloc(gs->s, l); 118 | gs->len = l; 119 | } 120 | strcat(gs->s, s); 121 | } 122 | } 123 | 124 | /* Append printf formatted string to growable string */ 125 | void str_printf(struct gstr *gs, const char *fmt, ...) 126 | { 127 | va_list ap; 128 | char s[10000]; /* big enough... */ 129 | va_start(ap, fmt); 130 | vsnprintf(s, sizeof(s), fmt, ap); 131 | str_append(gs, s); 132 | va_end(ap); 133 | } 134 | 135 | /* Retrieve value of growable string */ 136 | const char *str_get(struct gstr *gs) 137 | { 138 | return gs->s; 139 | } 140 | 141 | void *xmalloc(size_t size) 142 | { 143 | void *p = malloc(size); 144 | if (p) 145 | return p; 146 | fprintf(stderr, "Out of memory.\n"); 147 | exit(1); 148 | } 149 | 150 | void *xcalloc(size_t nmemb, size_t size) 151 | { 152 | void *p = calloc(nmemb, size); 153 | if (p) 154 | return p; 155 | fprintf(stderr, "Out of memory.\n"); 156 | exit(1); 157 | } 158 | -------------------------------------------------------------------------------- /scripts/kconfig/zconf.gperf: -------------------------------------------------------------------------------- 1 | %language=ANSI-C 2 | %define hash-function-name kconf_id_hash 3 | %define lookup-function-name kconf_id_lookup 4 | %define string-pool-name kconf_id_strings 5 | %compare-strncmp 6 | %enum 7 | %pic 8 | %struct-type 9 | 10 | struct kconf_id; 11 | 12 | static const struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len); 13 | 14 | %% 15 | mainmenu, T_MAINMENU, TF_COMMAND 16 | menu, T_MENU, TF_COMMAND 17 | endmenu, T_ENDMENU, TF_COMMAND 18 | source, T_SOURCE, TF_COMMAND 19 | choice, T_CHOICE, TF_COMMAND 20 | endchoice, T_ENDCHOICE, TF_COMMAND 21 | comment, T_COMMENT, TF_COMMAND 22 | config, T_CONFIG, TF_COMMAND 23 | menuconfig, T_MENUCONFIG, TF_COMMAND 24 | help, T_HELP, TF_COMMAND 25 | if, T_IF, TF_COMMAND|TF_PARAM 26 | endif, T_ENDIF, TF_COMMAND 27 | depends, T_DEPENDS, TF_COMMAND 28 | optional, T_OPTIONAL, TF_COMMAND 29 | default, T_DEFAULT, TF_COMMAND, S_UNKNOWN 30 | prompt, T_PROMPT, TF_COMMAND 31 | tristate, T_TYPE, TF_COMMAND, S_TRISTATE 32 | def_tristate, T_DEFAULT, TF_COMMAND, S_TRISTATE 33 | bool, T_TYPE, TF_COMMAND, S_BOOLEAN 34 | boolean, T_TYPE, TF_COMMAND, S_BOOLEAN 35 | def_bool, T_DEFAULT, TF_COMMAND, S_BOOLEAN 36 | int, T_TYPE, TF_COMMAND, S_INT 37 | hex, T_TYPE, TF_COMMAND, S_HEX 38 | string, T_TYPE, TF_COMMAND, S_STRING 39 | select, T_SELECT, TF_COMMAND 40 | range, T_RANGE, TF_COMMAND 41 | visible, T_VISIBLE, TF_COMMAND 42 | option, T_OPTION, TF_COMMAND 43 | on, T_ON, TF_PARAM 44 | modules, T_OPT_MODULES, TF_OPTION 45 | defconfig_list, T_OPT_DEFCONFIG_LIST,TF_OPTION 46 | env, T_OPT_ENV, TF_OPTION 47 | allnoconfig_y, T_OPT_ALLNOCONFIG_Y,TF_OPTION 48 | %% 49 | -------------------------------------------------------------------------------- /scripts/ldnoexec.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Script to remove EXEC flag from an ELF file 3 | # 4 | # Copyright (C) 2020 Kevin O'Connor 5 | # 6 | # This file may be distributed under the terms of the GNU GPLv3 license. 7 | import optparse 8 | 9 | FLAG_OFFSET = 16 10 | 11 | def main(): 12 | # Parse command-line arguments 13 | usage = "%prog " 14 | opts = optparse.OptionParser(usage) 15 | options, args = opts.parse_args() 16 | if len(args) != 2: 17 | opts.error("Incorrect number of arguments") 18 | infilename, outfilename = args 19 | # Read input 20 | f = open(infilename, "rb") 21 | srcdata = f.read() 22 | f.close() 23 | # Update 24 | outdata = bytearray(srcdata) 25 | outdata[FLAG_OFFSET] = 0x01 # change ET_EXEC to ET_REL 26 | # Write output 27 | f = open(outfilename, "wb") 28 | f.write(outdata) 29 | f.close() 30 | 31 | if __name__ == '__main__': 32 | main() 33 | -------------------------------------------------------------------------------- /scripts/tarball.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Script to create seabios release and snapshot tarballs. 4 | # Accepts conmmit (hash, tag, branch, ...) as first argument, 5 | # uses HEAD if unspecified. 6 | # 7 | 8 | commit="${1-HEAD}" 9 | 10 | # figure name for the tarball 11 | reltag="$(git describe --tags --match 'rel-*' --exact $commit 2>/dev/null)" 12 | if test "$reltag" != ""; then 13 | # release 14 | name="${reltag#rel-}" 15 | else 16 | # snapshot 17 | reltag="$(git describe --tags --match 'rel-*' $commit 2>/dev/null)" 18 | name="snap-${reltag#rel-}" 19 | fi 20 | 21 | # export tarball archive from git 22 | prefix="seabios-${name}/" 23 | output="seabios-${name}.tar" 24 | echo "# commit $commit -> tarball: ${output}.gz" 25 | rm -f "$output" "${output}.gz" 26 | git archive --format=tar --prefix="$prefix" "$commit" > "$output" 27 | 28 | # add .version file to tarball 29 | dotver="$(mktemp dotver.XXXXXX)" 30 | echo "$name" > "$dotver" 31 | tar --append --file="$output" --owner=root --group=root --mode=0664 \ 32 | --transform "s:${dotver}:${prefix}.version:" "$dotver" 33 | rm -f "$dotver" 34 | 35 | # finally compress it 36 | gzip "$output" 37 | -------------------------------------------------------------------------------- /scripts/test-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Script to test if the build works properly. 3 | 4 | mkdir -p ${OUT} 5 | TMPFILE1=${OUT}/tmp_testcompile1.c 6 | TMPFILE1o=${OUT}/tmp_testcompile1.o 7 | TMPFILE1_ld=${OUT}/tmp_testcompile1.lds 8 | TMPFILE2=${OUT}/tmp_testcompile2.c 9 | TMPFILE2o=${OUT}/tmp_testcompile2.o 10 | TMPFILE3o=${OUT}/tmp_testcompile3.o 11 | 12 | # Test if ld's alignment handling is correct. This is a known problem 13 | # with the linker that ships with Ubuntu 11.04. 14 | cat - > $TMPFILE1 < $TMPFILE1_ld < /dev/null 2>&1 31 | if [ $? -ne 0 ]; then 32 | echo "Unable to execute the C compiler ($CC)." >&2 33 | echo "" >&2 34 | echo "Please install a working compiler and retry." >&2 35 | echo -1 36 | exit 0 37 | fi 38 | $LD -T $TMPFILE1_ld $TMPFILE1o -o $TMPFILE2o > /dev/null 2>&1 39 | if [ $? -ne 0 ]; then 40 | echo "The version of LD on this system ($LD) does not properly handle" >&2 41 | echo "alignments. As a result, this project can not be built." >&2 42 | echo "" >&2 43 | echo "The problem may be the result of this LD bug report:" >&2 44 | echo " http://sourceware.org/bugzilla/show_bug.cgi?id=12726" >&2 45 | echo "" >&2 46 | echo "Please update to a working version of binutils and retry." >&2 47 | echo -1 48 | exit 0 49 | fi 50 | 51 | # Test for "-fwhole-program". Older versions of gcc (pre v4.1) don't 52 | # support the whole-program optimization - detect that. 53 | $CC -fwhole-program -S -o /dev/null -xc /dev/null > /dev/null 2>&1 54 | if [ $? -ne 0 ]; then 55 | echo " Working around no -fwhole-program" >&2 56 | echo 2 57 | exit 0 58 | fi 59 | 60 | # Test if "visible" variables and functions are marked global. On 61 | # OpenSuse 10.3 "visible" variables declared with "extern" first 62 | # aren't marked as global in the resulting assembler. On Ubuntu 7.10 63 | # "visible" functions aren't marked as global in the resulting 64 | # assembler. 65 | cat - > $TMPFILE1 < /dev/null 2>&1 71 | cat - > $TMPFILE2 < /dev/null 2>&1 77 | $CC -nostdlib -Os $TMPFILE1o $TMPFILE2o -o $TMPFILE3o > /dev/null 2>&1 78 | if [ $? -ne 0 ]; then 79 | echo " Working around non-functional -fwhole-program" >&2 80 | echo 2 81 | exit 0 82 | fi 83 | 84 | echo 0 85 | 86 | # Also, the Ubuntu 8.04 compiler has a bug causing corruption when the 87 | # "ebp" register is clobberred in an "asm" statement. The code has 88 | # been modified to not clobber "ebp" - no test is available yet. 89 | 90 | rm -f $TMPFILE1 $TMPFILE1o $TMPFILE1_ld $TMPFILE2 $TMPFILE2o $TMPFILE3o 91 | -------------------------------------------------------------------------------- /scripts/transdump.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # This script is useful for taking the output of memdump() and 4 | # converting it back into binary output. This can be useful, for 5 | # example, when one wants to push that data into other tools like 6 | # objdump or hexdump. 7 | # 8 | # (C) Copyright 2010 Kevin O'Connor 9 | # 10 | # This file may be distributed under the terms of the GNU GPLv3 license. 11 | 12 | import sys 13 | import struct 14 | 15 | def unhex(str): 16 | return int(str, 16) 17 | 18 | def parseMem(filehdl): 19 | mem = [] 20 | for line in filehdl: 21 | parts = line.split(':') 22 | if len(parts) < 2: 23 | continue 24 | try: 25 | vaddr = unhex(parts[0]) 26 | parts = parts[1].split() 27 | mem.extend([unhex(v) for v in parts]) 28 | except ValueError: 29 | continue 30 | return mem 31 | 32 | def printUsage(): 33 | sys.stderr.write("Usage:\n %s \n" 34 | % (sys.argv[0],)) 35 | sys.exit(1) 36 | 37 | def main(): 38 | if len(sys.argv) != 2: 39 | printUsage() 40 | filename = sys.argv[1] 41 | if filename == '-': 42 | filehdl = sys.stdin 43 | else: 44 | filehdl = open(filename, 'r') 45 | mem = parseMem(filehdl) 46 | for i in mem: 47 | if (sys.version_info > (3, 0)): 48 | sys.stdout.buffer.write(struct.pack(" 5 | # 6 | # This file may be distributed under the terms of the GNU GPLv3 license. 7 | 8 | # The x86emu code widely used in Linux distributions when running Xorg 9 | # in vesamode is known to have issues with "retl", "leavel", "entryl", 10 | # "leal", and some variants of "calll". This code modifies those 11 | # instructions that are known to be generated by gcc to avoid 12 | # triggering the x86emu bugs. 13 | 14 | # It is also known that the Windows vgabios emulator has issues with 15 | # addressing negative offsets to the %esp register. That has been 16 | # worked around by not using the gcc parameter "-fomit-frame-pointer" 17 | # when compiling. 18 | 19 | import sys, re 20 | 21 | # leal parameter regex - example string: -3(%edx,%eax,8), %eax 22 | re_leal = re.compile( 23 | r'^\s*(?P[^(]*?)\s*' 24 | r'\(\s*(?P[^,)]*?)\s*(?:,\s*(?P[^,)]*?)\s*)?' 25 | r'(?:,\s*(?P[^,)]*?)\s*)?\)\s*' 26 | r',\s*(?P.*?)\s*$') 27 | 28 | # Find an alternate set of instructions for a given "leal" instruction 29 | def handle_leal(sline): 30 | m = re_leal.match(sline[5:]) 31 | if m is None or m.group('index') == '%esp': 32 | print("Unable to fixup leal instruction: %s" % (sline,)) 33 | sys.exit(-1) 34 | offset, base, index, scale, dest = m.group( 35 | 'offset', 'base', 'index', 'scale', 'dest') 36 | if dest == '%esp': 37 | # If destination is %esp then just use 16bit leaw instead 38 | return 'leaw %s\n' % (sline[5:].replace('%e', '%'),) 39 | if not scale: 40 | scale = '1' 41 | scale = {1: 0, 2: 1, 4: 2, 8: 3}[int(scale, 0)] 42 | # Try to rearrange arguments to simplify 'base' (to improve code gen) 43 | if not scale and base == index: 44 | base, index, scale = '', index, 1 45 | elif not index or (not scale and base in (dest, '%esp') and index != dest): 46 | base, index, scale = index, base, 0 47 | # Produce instructions to calculate "leal" 48 | insns = ['pushfw'] 49 | if base != dest: 50 | # Calculate "leal" directly in dest register 51 | if index != dest: 52 | insns.insert(0, 'movl %s, %s' % (index, dest)) 53 | if scale: 54 | insns.append('shll $%d, %s' % (scale, dest)) 55 | if base: 56 | if base == '%esp': 57 | offset += '+2' 58 | insns.append('addl %s, %s' % (base, dest)) 59 | elif base == index: 60 | # Use "imull" method 61 | insns.append('imull $%d, %s' % ((1< %s\n %s" % (sline, out[-1].strip())) 88 | else: 89 | out.append(line) 90 | infile.close() 91 | outfile = open(outfilename, 'w') 92 | outfile.write(''.join(out)) 93 | outfile.close() 94 | 95 | if __name__ == '__main__': 96 | main() 97 | -------------------------------------------------------------------------------- /src/asm-offsets.c: -------------------------------------------------------------------------------- 1 | // Generate assembler offsets. 2 | 3 | #include "gen-defs.h" // OFFSET 4 | #include "bregs.h" // struct bregs 5 | 6 | /* workaround for a warning with -Wmissing-prototypes */ 7 | void foo(void) VISIBLE16; 8 | 9 | void foo(void) 10 | { 11 | COMMENT("BREGS"); 12 | OFFSET(BREGS_es, bregs, es); 13 | OFFSET(BREGS_ds, bregs, ds); 14 | OFFSET(BREGS_eax, bregs, eax); 15 | OFFSET(BREGS_ebx, bregs, ebx); 16 | OFFSET(BREGS_ecx, bregs, ecx); 17 | OFFSET(BREGS_edx, bregs, edx); 18 | OFFSET(BREGS_ebp, bregs, ebp); 19 | OFFSET(BREGS_esi, bregs, esi); 20 | OFFSET(BREGS_edi, bregs, edi); 21 | OFFSET(BREGS_flags, bregs, flags); 22 | OFFSET(BREGS_code, bregs, code); 23 | } 24 | -------------------------------------------------------------------------------- /src/block.h: -------------------------------------------------------------------------------- 1 | #ifndef __BLOCK_H 2 | #define __BLOCK_H 3 | 4 | #include "types.h" // u32 5 | 6 | 7 | /**************************************************************** 8 | * Disk command request 9 | ****************************************************************/ 10 | 11 | struct disk_op_s { 12 | void *buf_fl; 13 | struct drive_s *drive_fl; 14 | u8 command; 15 | u16 count; 16 | union { 17 | // Commands: READ, WRITE, VERIFY, SEEK, FORMAT 18 | u64 lba; 19 | // Commands: SCSI 20 | struct { 21 | u16 blocksize; 22 | void *cdbcmd; 23 | }; 24 | }; 25 | }; 26 | 27 | #define CMD_RESET 0x00 28 | #define CMD_READ 0x02 29 | #define CMD_WRITE 0x03 30 | #define CMD_VERIFY 0x04 31 | #define CMD_FORMAT 0x05 32 | #define CMD_SEEK 0x07 33 | #define CMD_ISREADY 0x10 34 | #define CMD_SCSI 0x20 35 | 36 | 37 | /**************************************************************** 38 | * Global storage 39 | ****************************************************************/ 40 | 41 | struct chs_s { 42 | u16 head; 43 | u16 cylinder; 44 | u16 sector; 45 | u16 pad; 46 | }; 47 | 48 | struct drive_s { 49 | u8 type; // Driver type (DTYPE_*) 50 | u8 floppy_type; // Type of floppy (only for floppy drives). 51 | struct chs_s lchs; // Logical CHS 52 | u64 sectors; // Total sectors count 53 | u32 cntl_id; // Unique id for a given driver type. 54 | u8 removable; // Is media removable (currently unused) 55 | 56 | // Info for EDD calls 57 | u8 translation; // type of translation 58 | u16 blksize; // block size 59 | struct chs_s pchs; // Physical CHS 60 | u32 max_segment_size; //max_segment_size 61 | u32 max_segments; //max_segments 62 | }; 63 | 64 | #define DISK_SECTOR_SIZE 512 65 | #define CDROM_SECTOR_SIZE 2048 66 | 67 | #define DTYPE_NONE 0x00 68 | #define DTYPE_FLOPPY 0x10 69 | #define DTYPE_ATA 0x20 70 | #define DTYPE_ATA_ATAPI 0x21 71 | #define DTYPE_RAMDISK 0x30 72 | #define DTYPE_CDEMU 0x40 73 | #define DTYPE_AHCI 0x50 74 | #define DTYPE_AHCI_ATAPI 0x51 75 | #define DTYPE_VIRTIO_SCSI 0x60 76 | #define DTYPE_VIRTIO_BLK 0x61 77 | #define DTYPE_USB 0x70 78 | #define DTYPE_USB_32 0x71 79 | #define DTYPE_UAS 0x72 80 | #define DTYPE_UAS_32 0x73 81 | #define DTYPE_LSI_SCSI 0x80 82 | #define DTYPE_ESP_SCSI 0x81 83 | #define DTYPE_MEGASAS 0x82 84 | #define DTYPE_PVSCSI 0x83 85 | #define DTYPE_MPT_SCSI 0x84 86 | #define DTYPE_SDCARD 0x90 87 | #define DTYPE_NVME 0x91 88 | 89 | #define MAXDESCSIZE 80 90 | 91 | #define TRANSLATION_NONE 0 92 | #define TRANSLATION_LBA 1 93 | #define TRANSLATION_LARGE 2 94 | #define TRANSLATION_RECHS 3 95 | #define TRANSLATION_HOST 4 96 | 97 | #define EXTTYPE_FLOPPY 0 98 | #define EXTTYPE_HD 1 99 | #define EXTTYPE_CD 2 100 | 101 | #define EXTSTART_HD 0x80 102 | #define EXTSTART_CD 0xE0 103 | 104 | 105 | /**************************************************************** 106 | * Function defs 107 | ****************************************************************/ 108 | 109 | // block.c 110 | extern u8 FloppyCount, CDCount; 111 | extern u8 *bounce_buf_fl; 112 | struct drive_s *getDrive(u8 exttype, u8 extdriveoffset); 113 | int getDriveId(u8 exttype, struct drive_s *drive); 114 | void map_floppy_drive(struct drive_s *drive); 115 | void map_hd_drive(struct drive_s *drive); 116 | void map_cd_drive(struct drive_s *drive); 117 | struct int13dpt_s; 118 | int fill_edd(struct segoff_s edd, struct drive_s *drive_fl); 119 | void block_setup(void); 120 | int default_process_op(struct disk_op_s *op); 121 | int process_op(struct disk_op_s *op); 122 | int create_bounce_buf(void); 123 | 124 | #endif // block.h 125 | -------------------------------------------------------------------------------- /src/bmp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Basic BMP data process and Raw picture data handle functions. 3 | * Could be used to adjust pixel data format, get information, etc. 4 | * 5 | * Copyright (C) 2011 Wayne Xia 6 | * 7 | * This work is licensed under the terms of the GNU LGPLv3. 8 | */ 9 | #include "malloc.h" // malloc_tmphigh 10 | #include "string.h" // memcpy 11 | #include "util.h" // struct bmp_decdata 12 | 13 | struct bmp_decdata { 14 | struct tagRGBQUAD *quadp; 15 | unsigned char *datap; 16 | int width; 17 | int height; 18 | int bpp; 19 | }; 20 | 21 | #define bmp_load4byte(addr) (*(u32 *)(addr)) 22 | #define bmp_load2byte(addr) (*(u16 *)(addr)) 23 | 24 | typedef struct tagBITMAPFILEHEADER { 25 | u8 bfType[2]; 26 | u8 bfSize[4]; 27 | u8 bfReserved1[2]; 28 | u8 bfReserved2[2]; 29 | u8 bfOffBits[4]; 30 | } BITMAPFILEHEADER, tagBITMAPFILEHEADER; 31 | 32 | typedef struct tagBITMAPINFOHEADER { 33 | u8 biSize[4]; 34 | u8 biWidth[4]; 35 | u8 biHeight[4]; 36 | u8 biPlanes[2]; 37 | u8 biBitCount[2]; 38 | u8 biCompression[4]; 39 | u8 biSizeImage[4]; 40 | u8 biXPelsPerMeter[4]; 41 | u8 biYPelsPerMeter[4]; 42 | u8 biClrUsed[4]; 43 | u8 biClrImportant[4]; 44 | } BITMAPINFOHEADER, tagBITMAPINFOHEADER; 45 | 46 | typedef struct tagRGBQUAD { 47 | u8 rgbBlue; 48 | u8 rgbGreen; 49 | u8 rgbRed; 50 | u8 rgbReserved; 51 | } RGBQUAD, tagRGBQUAD; 52 | 53 | /* flat picture data adjusting function 54 | * description: 55 | * switch the vertical line sequence 56 | * arrange horizontal pixel data, add extra space in the dest buffer 57 | * for every line 58 | */ 59 | static void raw_data_format_adjust(u8 *src, u8 *dest, int width, 60 | int height, int bytes_per_line_src, int bytes_per_line_dest) 61 | { 62 | int i; 63 | for (i = 0 ; i < height ; i++) { 64 | memcpy(dest + i * bytes_per_line_dest, 65 | src + (height - 1 - i) * bytes_per_line_src, bytes_per_line_src); 66 | } 67 | } 68 | 69 | /* allocate decdata struct */ 70 | struct bmp_decdata *bmp_alloc(void) 71 | { 72 | struct bmp_decdata *bmp = malloc_tmphigh(sizeof(*bmp)); 73 | return bmp; 74 | } 75 | 76 | /* extract information from bmp file data */ 77 | int bmp_decode(struct bmp_decdata *bmp, unsigned char *data, int data_size) 78 | { 79 | if (data_size < 54) 80 | return 1; 81 | 82 | u16 bmp_filehead = bmp_load2byte(data + 0); 83 | if (bmp_filehead != 0x4d42) 84 | return 2; 85 | u32 bmp_recordsize = bmp_load4byte(data + 2); 86 | if (bmp_recordsize != data_size) 87 | return 3; 88 | u32 bmp_dataoffset = bmp_load4byte(data + 10); 89 | bmp->datap = (unsigned char *)data + bmp_dataoffset; 90 | bmp->width = bmp_load4byte(data + 18); 91 | bmp->height = bmp_load4byte(data + 22); 92 | bmp->bpp = bmp_load2byte(data + 28); 93 | return 0; 94 | } 95 | 96 | /* get bmp properties */ 97 | void bmp_get_info(struct bmp_decdata *bmp, int *width, int *height, int *bpp) 98 | { 99 | *width = bmp->width; 100 | *height = bmp->height; 101 | *bpp = bmp->bpp; 102 | } 103 | 104 | /* flush flat picture data to *pc */ 105 | int bmp_show(struct bmp_decdata *bmp, unsigned char *pic, int width, 106 | int height, int depth, int bytes_per_line_dest) 107 | { 108 | if (bmp->datap == pic) 109 | return 0; 110 | if ((depth == bmp->bpp) && (bmp->bpp%8 == 0)) { 111 | raw_data_format_adjust(bmp->datap, pic, width, height, 112 | (bmp->bpp/8)*width, bytes_per_line_dest); 113 | return 0; 114 | } 115 | return 1; 116 | } 117 | -------------------------------------------------------------------------------- /src/bregs.h: -------------------------------------------------------------------------------- 1 | // Structure layout of cpu registers that the bios uses. 2 | // 3 | // Copyright (C) 2008 Kevin O'Connor 4 | // 5 | // This file may be distributed under the terms of the GNU LGPLv3 license. 6 | 7 | #ifndef __BREGS_H 8 | #define __BREGS_H 9 | 10 | #include "types.h" // u16 11 | #include "x86.h" // F_CF 12 | 13 | 14 | /**************************************************************** 15 | * Registers saved/restored in romlayout.S 16 | ****************************************************************/ 17 | 18 | #define UREG(ER, R, RH, RL) union { u32 ER; struct { u16 R; u16 R ## _hi; }; struct { u8 RL; u8 RH; u8 R ## _hilo; u8 R ## _hihi; }; } 19 | 20 | // Layout of registers passed in to irq handlers. Note that this 21 | // layout corresponds to code in romlayout.S - don't change it here 22 | // without also updating the assembler code. 23 | struct bregs { 24 | u16 ds; 25 | u16 es; 26 | UREG(edi, di, di8u, di8l); 27 | UREG(esi, si, si8u, si8l); 28 | UREG(ebp, bp, bp8u, bp8l); 29 | UREG(ebx, bx, bh, bl); 30 | UREG(edx, dx, dh, dl); 31 | UREG(ecx, cx, ch, cl); 32 | UREG(eax, ax, ah, al); 33 | struct segoff_s code; 34 | u16 flags; 35 | } PACKED; 36 | 37 | 38 | /**************************************************************** 39 | * Helper functions 40 | ****************************************************************/ 41 | 42 | static inline void 43 | set_cf(struct bregs *regs, int cond) 44 | { 45 | if (cond) 46 | regs->flags |= F_CF; 47 | else 48 | regs->flags &= ~F_CF; 49 | } 50 | 51 | // Frequently used return codes 52 | #define RET_EUNSUPPORTED 0x86 53 | 54 | static inline void 55 | set_success(struct bregs *regs) 56 | { 57 | set_cf(regs, 0); 58 | } 59 | 60 | static inline void 61 | set_code_success(struct bregs *regs) 62 | { 63 | regs->ah = 0; 64 | set_cf(regs, 0); 65 | } 66 | 67 | static inline void 68 | set_invalid_silent(struct bregs *regs) 69 | { 70 | set_cf(regs, 1); 71 | } 72 | 73 | static inline void 74 | set_code_invalid_silent(struct bregs *regs, u8 code) 75 | { 76 | regs->ah = code; 77 | set_cf(regs, 1); 78 | } 79 | 80 | #endif // bregs.h 81 | -------------------------------------------------------------------------------- /src/byteorder.h: -------------------------------------------------------------------------------- 1 | #ifndef __BYTEORDER_H 2 | #define __BYTEORDER_H 3 | 4 | #include "types.h" // u32 5 | 6 | static inline u16 __swab16_constant(u16 val) { 7 | return (val<<8) | (val>>8); 8 | } 9 | static inline u32 __swab32_constant(u32 val) { 10 | return (val<<24) | ((val&0xff00)<<8) | ((val&0xff0000)>>8) | (val>>24); 11 | } 12 | static inline u64 __swab64_constant(u64 val) { 13 | return ((u64)__swab32_constant(val) << 32) | __swab32_constant(val>>32); 14 | } 15 | static inline u32 __swab32(u32 val) { 16 | asm("bswapl %0" : "+r"(val)); 17 | return val; 18 | } 19 | static inline u64 __swab64(u64 val) { 20 | union u64_u32_u i, o; 21 | i.val = val; 22 | o.lo = __swab32(i.hi); 23 | o.hi = __swab32(i.lo); 24 | return o.val; 25 | } 26 | 27 | #define swab16(x) __swab16_constant(x) 28 | #define swab32(x) (__builtin_constant_p((u32)(x)) \ 29 | ? __swab32_constant(x) : __swab32(x)) 30 | #define swab64(x) (__builtin_constant_p((u64)(x)) \ 31 | ? __swab64_constant(x) : __swab64(x)) 32 | 33 | static inline u16 cpu_to_le16(u16 x) { 34 | return x; 35 | } 36 | static inline u32 cpu_to_le32(u32 x) { 37 | return x; 38 | } 39 | static inline u64 cpu_to_le64(u64 x) { 40 | return x; 41 | } 42 | static inline u16 le16_to_cpu(u16 x) { 43 | return x; 44 | } 45 | static inline u32 le32_to_cpu(u32 x) { 46 | return x; 47 | } 48 | static inline u64 le64_to_cpu(u64 x) { 49 | return x; 50 | } 51 | 52 | static inline u16 cpu_to_be16(u16 x) { 53 | return swab16(x); 54 | } 55 | static inline u32 cpu_to_be32(u32 x) { 56 | return swab32(x); 57 | } 58 | static inline u64 cpu_to_be64(u64 x) { 59 | return swab64(x); 60 | } 61 | static inline u16 be16_to_cpu(u16 x) { 62 | return swab16(x); 63 | } 64 | static inline u32 be32_to_cpu(u32 x) { 65 | return swab32(x); 66 | } 67 | static inline u64 be64_to_cpu(u64 x) { 68 | return swab64(x); 69 | } 70 | 71 | #endif // byteorder.h 72 | -------------------------------------------------------------------------------- /src/code16gcc.s: -------------------------------------------------------------------------------- 1 | .code16gcc 2 | -------------------------------------------------------------------------------- /src/config.h: -------------------------------------------------------------------------------- 1 | #ifndef __CONFIG_H 2 | #define __CONFIG_H 3 | 4 | #include "autoconf.h" 5 | 6 | // Configuration definitions. 7 | 8 | //#define BUILD_APPNAME "QEMU" 9 | //#define BUILD_CPUNAME8 "QEMUCPU " 10 | //#define BUILD_APPNAME6 "QEMU " 11 | //#define BUILD_APPNAME4 "QEMU" 12 | #define BUILD_APPNAME "Bochs" 13 | #define BUILD_CPUNAME8 "BOCHSCPU" 14 | #define BUILD_APPNAME6 "BOCHS " 15 | #define BUILD_APPNAME4 "BXPC" 16 | 17 | // Maximum number of map entries in the e820 map 18 | #define BUILD_MAX_E820 128 19 | // Space to reserve in high-memory for tables 20 | #define BUILD_MIN_HIGHTABLE (256*1024) 21 | #define BUILD_MAX_HIGHTABLE (16*1024*1024) 22 | // Largest supported externaly facing drive id 23 | #define BUILD_MAX_EXTDRIVE 16 24 | // Number of bytes the smbios may be and still live in the f-segment 25 | #define BUILD_MAX_SMBIOS_FSEG 600 26 | // Maximum number of bytes the mptable may be and still be copied to f-segment 27 | #define BUILD_MAX_MPTABLE_FSEG 600 28 | 29 | #define BUILD_MODEL_ID 0xFC 30 | #define BUILD_SUBMODEL_ID 0x00 31 | #define BUILD_BIOS_REVISION 0x01 32 | 33 | // Various memory addresses used by the code. 34 | #define BUILD_STACK_ADDR 0x7000 35 | #define BUILD_S3RESUME_STACK_ADDR 0x1000 36 | #define BUILD_AP_BOOT_ADDR 0x10000 37 | #define BUILD_EBDA_MINIMUM 0x90000 38 | #define BUILD_LOWRAM_END 0xa0000 39 | #define BUILD_ROM_START 0xc0000 40 | #define BUILD_BIOS_ADDR 0xf0000 41 | #define BUILD_BIOS_SIZE 0x10000 42 | #define BUILD_EXTRA_STACK_SIZE 0x800 43 | #define BUILD_SMM_INIT_ADDR 0x30000 44 | #define BUILD_SMM_ADDR 0xa0000 45 | 46 | #define BUILD_PCIMEM_START 0xe0000000 47 | #define BUILD_PCIMEM_END 0xfec00000 /* IOAPIC is mapped at */ 48 | #define BUILD_PCIMEM64_START 0x8000000000ULL 49 | #define BUILD_PCIMEM64_END 0x10000000000ULL 50 | 51 | #define BUILD_IOAPIC_ADDR 0xfec00000 52 | #define BUILD_IOAPIC_ID 0 53 | #define BUILD_HPET_ADDRESS 0xfed00000 54 | #define BUILD_APIC_ADDR 0xfee00000 55 | 56 | // PCI IRQS 57 | #define BUILD_PCI_IRQS ((1<<5) | (1<<9) | (1<<10) | (1<<11)) 58 | 59 | // Important real-mode segments 60 | #define SEG_IVT 0x0000 61 | #define SEG_BDA 0x0040 62 | #define SEG_BIOS 0xf000 63 | 64 | // Segment definitions in protected mode (see rombios32_gdt in misc.c) 65 | #define SEG32_MODE32_CS (1 << 3) 66 | #define SEG32_MODE32_DS (2 << 3) 67 | #define SEG32_MODE16_CS (3 << 3) 68 | #define SEG32_MODE16_DS (4 << 3) 69 | #define SEG32_MODE16BIG_CS (5 << 3) 70 | #define SEG32_MODE16BIG_DS (6 << 3) 71 | 72 | // Debugging levels. If non-zero and CONFIG_DEBUG_LEVEL is greater 73 | // than the specified value, then the corresponding irq handler will 74 | // report every enter event. 75 | #define DEBUG_ISR_02 1 76 | #define DEBUG_HDL_05 1 77 | #define DEBUG_ISR_08 20 78 | #define DEBUG_ISR_09 9 79 | #define DEBUG_ISR_0e 9 80 | #define DEBUG_HDL_11 2 81 | #define DEBUG_HDL_12 2 82 | #define DEBUG_HDL_13 10 83 | #define DEBUG_HDL_14 2 84 | #define DEBUG_HDL_15 9 85 | #define DEBUG_HDL_16 9 86 | #define DEBUG_HDL_17 2 87 | #define DEBUG_HDL_18 1 88 | #define DEBUG_HDL_19 1 89 | #define DEBUG_HDL_1a 9 90 | #define DEBUG_HDL_40 1 91 | #define DEBUG_ISR_70 9 92 | #define DEBUG_ISR_74 9 93 | #define DEBUG_ISR_75 1 94 | #define DEBUG_ISR_76 10 95 | #define DEBUG_ISR_hwpic1 5 96 | #define DEBUG_ISR_hwpic2 5 97 | #define DEBUG_HDL_smi 9 98 | #define DEBUG_HDL_smp 1 99 | #define DEBUG_HDL_pnp 1 100 | #define DEBUG_HDL_pmm 1 101 | #define DEBUG_HDL_pcibios 9 102 | #define DEBUG_HDL_apm 9 103 | 104 | #define DEBUG_unimplemented 2 105 | #define DEBUG_invalid 3 106 | #define DEBUG_thread 2 107 | #define DEBUG_tcg 20 108 | 109 | #endif // config.h 110 | -------------------------------------------------------------------------------- /src/cp437.h: -------------------------------------------------------------------------------- 1 | u16 cp437_to_unicode(u8 cp437); 2 | -------------------------------------------------------------------------------- /src/e820map.h: -------------------------------------------------------------------------------- 1 | #ifndef __E820MAP_H 2 | #define __E820MAP_H 3 | 4 | #include "types.h" // u64 5 | 6 | #define E820_RAM 1 7 | #define E820_RESERVED 2 8 | #define E820_ACPI 3 9 | #define E820_NVS 4 10 | #define E820_UNUSABLE 5 11 | 12 | struct e820entry { 13 | u64 start; 14 | u64 size; 15 | u32 type; 16 | }; 17 | 18 | void e820_add(u64 start, u64 size, u32 type); 19 | void e820_remove(u64 start, u64 size); 20 | void e820_prepboot(void); 21 | int e820_is_used(u64 start, u64 size); 22 | 23 | // e820 map storage 24 | extern struct e820entry e820_list[]; 25 | extern int e820_count; 26 | 27 | #endif // e820map.h 28 | -------------------------------------------------------------------------------- /src/fw/acpi.c: -------------------------------------------------------------------------------- 1 | // Support for generating ACPI tables (on emulators) 2 | // DO NOT ADD NEW FEATURES HERE. (See paravirt.c / biostables.c instead.) 3 | // 4 | // Copyright (C) 2008-2010 Kevin O'Connor 5 | // Copyright (C) 2006 Fabrice Bellard 6 | // 7 | // This file may be distributed under the terms of the GNU LGPLv3 license. 8 | 9 | #include "config.h" // CONFIG_* 10 | #include "output.h" // dprintf 11 | 12 | void 13 | acpi_setup(void) 14 | { 15 | if (! CONFIG_ACPI) 16 | return; 17 | 18 | dprintf(1, "ACPI tables for qemu 1.6 and older are not supported any more.\n"); 19 | } 20 | -------------------------------------------------------------------------------- /src/fw/dev-pci.h: -------------------------------------------------------------------------------- 1 | #ifndef _PCI_CAP_H 2 | #define _PCI_CAP_H 3 | 4 | #include "types.h" 5 | 6 | /* 7 | * 8 | * QEMU-specific vendor(Red Hat)-specific capability. 9 | * It's intended to provide some hints for firmware to init PCI devices. 10 | * 11 | * Its structure is shown below: 12 | * 13 | * Header: 14 | * 15 | * u8 id; Standard PCI Capability Header field 16 | * u8 next; Standard PCI Capability Header field 17 | * u8 len; Standard PCI Capability Header field 18 | * u8 type; Red Hat vendor-specific capability type 19 | * Data: 20 | * 21 | * u32 bus_res; minimum bus number to reserve; 22 | * this is necessary for PCI Express Root Ports 23 | * to support PCI bridges hotplug 24 | * u64 io; IO space to reserve 25 | * u32 mem; non-prefetchable memory to reserve 26 | * 27 | * At most of the following two fields may be set to a value 28 | * different from 0xFF...F: 29 | * u32 prefetchable_mem_32; prefetchable memory to reserve (32-bit MMIO) 30 | * u64 prefetchable_mem_64; prefetchable memory to reserve (64-bit MMIO) 31 | * 32 | * If any field value in Data section is 0xFF...F, 33 | * it means that such kind of reservation is not needed and must be ignored. 34 | * 35 | */ 36 | 37 | /* Offset of vendor-specific capability type field */ 38 | #define PCI_CAP_REDHAT_TYPE_OFFSET 3 39 | 40 | /* List of valid Red Hat vendor-specific capability types */ 41 | #define REDHAT_CAP_RESOURCE_RESERVE 1 42 | 43 | 44 | /* Offsets of RESOURCE_RESERVE capability fields */ 45 | #define RES_RESERVE_BUS_RES 4 46 | #define RES_RESERVE_IO 8 47 | #define RES_RESERVE_MEM 16 48 | #define RES_RESERVE_PREF_MEM_32 20 49 | #define RES_RESERVE_PREF_MEM_64 24 50 | #define RES_RESERVE_CAP_SIZE 32 51 | 52 | #endif /* _PCI_CAP_H */ 53 | -------------------------------------------------------------------------------- /src/fw/dev-piix.h: -------------------------------------------------------------------------------- 1 | #ifndef __DEV_PIIX_H 2 | #define __DEV_PIIX_H 3 | 4 | #define I440FX_PAM0 0x59 5 | #define I440FX_SMRAM 0x72 6 | 7 | #define PIIX_PMBASE 0x40 8 | #define PIIX_PMREGMISC 0x80 9 | #define PIIX_SMBHSTBASE 0x90 10 | #define PIIX_SMBHSTCFG 0xd2 11 | #define PIIX_DEVACTB 0x58 12 | #define PIIX_DEVACTB_APMC_EN (1 << 25) 13 | 14 | #define PIIX_PORT_ELCR1 0x4d0 15 | #define PIIX_PORT_ELCR2 0x4d1 16 | 17 | /* ICH9 PM I/O registers */ 18 | #define PIIX_GPE0_BLK 0xafe0 19 | #define PIIX_GPE0_BLK_LEN 4 20 | #define PIIX_PMIO_GLBCTL 0x28 21 | #define PIIX_PMIO_GLBCTL_SMI_EN 1 22 | 23 | /* FADT ACPI_ENABLE/ACPI_DISABLE */ 24 | #define PIIX_ACPI_ENABLE 0xf1 25 | #define PIIX_ACPI_DISABLE 0xf0 26 | 27 | #define PIIX_PM_INTRRUPT 9 // irq 9 28 | 29 | #endif // dev-piix.h 30 | -------------------------------------------------------------------------------- /src/fw/dev-q35.h: -------------------------------------------------------------------------------- 1 | #ifndef __DEV_Q35_H 2 | #define __DEV_Q35_H 3 | 4 | #include "types.h" // u16 5 | 6 | #define PCI_DEVICE_ID_INTEL_Q35_MCH 0x29c0 7 | #define Q35_HOST_BRIDGE_PAM0 0x90 8 | #define Q35_HOST_BRIDGE_SMRAM 0x9d 9 | #define Q35_HOST_BRIDGE_PCIEXBAR 0x60 10 | #define Q35_HOST_BRIDGE_PCIEXBAR_SIZE (256 * 1024 * 1024) 11 | #define Q35_HOST_BRIDGE_PCIEXBAR_ADDR 0xb0000000 12 | #define Q35_HOST_BRIDGE_PCIEXBAREN ((u64)1) 13 | #define Q35_HOST_PCIE_PCI_SEGMENT 0 14 | #define Q35_HOST_PCIE_START_BUS_NUMBER 0 15 | #define Q35_HOST_PCIE_END_BUS_NUMBER 255 16 | 17 | #define PCI_DEVICE_ID_INTEL_ICH9_LPC 0x2918 18 | #define ICH9_LPC_PMBASE 0x40 19 | #define ICH9_LPC_PMBASE_RTE 0x1 20 | 21 | #define ICH9_LPC_ACPI_CTRL 0x44 22 | #define ICH9_LPC_ACPI_CTRL_ACPI_EN 0x80 23 | #define ICH9_LPC_PIRQA_ROUT 0x60 24 | #define ICH9_LPC_PIRQE_ROUT 0x68 25 | #define ICH9_LPC_PIRQ_ROUT_IRQEN 0x80 26 | #define ICH9_LPC_GEN_PMCON_1 0xa0 27 | #define ICH9_LPC_GEN_PMCON_1_SMI_LOCK (1 << 4) 28 | #define ICH9_LPC_PORT_ELCR1 0x4d0 29 | #define ICH9_LPC_PORT_ELCR2 0x4d1 30 | #define ICH9_LPC_RCBA 0xf0 31 | #define ICH9_LPC_RCBA_ADDR 0xfed1c000 32 | #define ICH9_LPC_RCBA_EN 0x1 33 | #define PCI_DEVICE_ID_INTEL_ICH9_SMBUS 0x2930 34 | #define ICH9_SMB_SMB_BASE 0x20 35 | #define ICH9_SMB_HOSTC 0x40 36 | #define ICH9_SMB_HOSTC_HST_EN 0x01 37 | 38 | #define ICH9_ACPI_ENABLE 0x2 39 | #define ICH9_ACPI_DISABLE 0x3 40 | 41 | /* ICH9 LPC PM I/O registers are 128 ports and 128-aligned */ 42 | #define ICH9_PMIO_GPE0_STS 0x20 43 | #define ICH9_PMIO_GPE0_BLK_LEN 0x10 44 | #define ICH9_PMIO_SMI_EN 0x30 45 | #define ICH9_PMIO_SMI_EN_APMC_EN (1 << 5) 46 | #define ICH9_PMIO_SMI_EN_GLB_SMI_EN (1 << 0) 47 | 48 | /* FADT ACPI_ENABLE/ACPI_DISABLE */ 49 | #define ICH9_APM_ACPI_ENABLE 0x2 50 | #define ICH9_APM_ACPI_DISABLE 0x3 51 | 52 | #endif // dev-q35.h 53 | -------------------------------------------------------------------------------- /src/fw/lzmadecode.h: -------------------------------------------------------------------------------- 1 | /* 2 | LzmaDecode.h 3 | LZMA Decoder interface 4 | 5 | LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) 6 | http://www.7-zip.org/ 7 | 8 | LZMA SDK is licensed under two licenses: 9 | 1) GNU Lesser General Public License (GNU LGPL) 10 | 2) Common Public License (CPL) 11 | It means that you can select one of these two licenses and 12 | follow rules of that license. 13 | 14 | SPECIAL EXCEPTION: 15 | Igor Pavlov, as the author of this code, expressly permits you to 16 | statically or dynamically link your code (or bind by name) to the 17 | interfaces of this file without subjecting your linked code to the 18 | terms of the CPL or GNU LGPL. Any modifications or additions 19 | to this file, however, are subject to the LGPL or CPL terms. 20 | */ 21 | 22 | #ifndef __LZMADECODE_H 23 | #define __LZMADECODE_H 24 | 25 | typedef unsigned char Byte; 26 | typedef unsigned short UInt16; 27 | typedef unsigned int UInt32; 28 | typedef UInt32 SizeT; 29 | 30 | #define CProb UInt16 31 | 32 | #define LZMA_RESULT_OK 0 33 | #define LZMA_RESULT_DATA_ERROR 1 34 | 35 | 36 | #define LZMA_BASE_SIZE 1846 37 | #define LZMA_LIT_SIZE 768 38 | 39 | #define LZMA_PROPERTIES_SIZE 5 40 | 41 | typedef struct _CLzmaProperties 42 | { 43 | int lc; 44 | int lp; 45 | int pb; 46 | }CLzmaProperties; 47 | 48 | int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size); 49 | 50 | #define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp))) 51 | 52 | #define kLzmaNeedInitId (-2) 53 | 54 | typedef struct _CLzmaDecoderState 55 | { 56 | CLzmaProperties Properties; 57 | CProb *Probs; 58 | 59 | 60 | } CLzmaDecoderState; 61 | 62 | 63 | int LzmaDecode(CLzmaDecoderState *vs, 64 | const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, 65 | unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed); 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /src/fw/mtrr.c: -------------------------------------------------------------------------------- 1 | // Initialize MTRRs - mostly useful on KVM. 2 | // 3 | // Copyright (C) 2006 Fabrice Bellard 4 | // 5 | // This file may be distributed under the terms of the GNU LGPLv3 license. 6 | 7 | #include "config.h" // CONFIG_* 8 | #include "output.h" // dprintf 9 | #include "paravirt.h" // RamSize 10 | #include "util.h" // mtrr_setup 11 | #include "x86.h" // cpuid 12 | 13 | #define MSR_MTRRcap 0x000000fe 14 | #define MSR_MTRRfix64K_00000 0x00000250 15 | #define MSR_MTRRfix16K_80000 0x00000258 16 | #define MSR_MTRRfix16K_A0000 0x00000259 17 | #define MSR_MTRRfix4K_C0000 0x00000268 18 | #define MSR_MTRRfix4K_C8000 0x00000269 19 | #define MSR_MTRRfix4K_D0000 0x0000026a 20 | #define MSR_MTRRfix4K_D8000 0x0000026b 21 | #define MSR_MTRRfix4K_E0000 0x0000026c 22 | #define MSR_MTRRfix4K_E8000 0x0000026d 23 | #define MSR_MTRRfix4K_F0000 0x0000026e 24 | #define MSR_MTRRfix4K_F8000 0x0000026f 25 | #define MSR_MTRRdefType 0x000002ff 26 | 27 | #define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg)) 28 | #define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1) 29 | 30 | #define MTRR_MEMTYPE_UC 0 31 | #define MTRR_MEMTYPE_WC 1 32 | #define MTRR_MEMTYPE_WT 4 33 | #define MTRR_MEMTYPE_WP 5 34 | #define MTRR_MEMTYPE_WB 6 35 | 36 | void mtrr_setup(void) 37 | { 38 | if (!CONFIG_MTRR_INIT) 39 | return; 40 | 41 | u32 eax, ebx, ecx, edx, cpuid_features; 42 | cpuid(1, &eax, &ebx, &ecx, &cpuid_features); 43 | if (!(cpuid_features & CPUID_MTRR)) 44 | return; 45 | if (!(cpuid_features & CPUID_MSR)) 46 | return; 47 | 48 | dprintf(3, "init mtrr\n"); 49 | 50 | u32 mtrr_cap = rdmsr(MSR_MTRRcap); 51 | int vcnt = mtrr_cap & 0xff; 52 | int fix = mtrr_cap & 0x100; 53 | if (!vcnt || !fix) 54 | return; 55 | 56 | // Disable MTRRs 57 | wrmsr_smp(MSR_MTRRdefType, 0); 58 | 59 | // Set fixed MTRRs 60 | union u64b { 61 | u8 valb[8]; 62 | u64 val; 63 | } u; 64 | u.val = 0; 65 | int i; 66 | for (i = 0; i < 8; i++) 67 | if (RamSize >= 65536 * (i + 1)) 68 | u.valb[i] = MTRR_MEMTYPE_WB; 69 | wrmsr_smp(MSR_MTRRfix64K_00000, u.val); 70 | u.val = 0; 71 | for (i = 0; i < 8; i++) 72 | if (RamSize >= 0x80000 + 16384 * (i + 1)) 73 | u.valb[i] = MTRR_MEMTYPE_WB; 74 | wrmsr_smp(MSR_MTRRfix16K_80000, u.val); 75 | wrmsr_smp(MSR_MTRRfix16K_A0000, 0); // 0xA0000-0xC0000 is uncached 76 | int j; 77 | for (j = 0; j < 8; j++) { 78 | u.val = 0; 79 | for (i = 0; i < 8; i++) 80 | if (RamSize >= 0xC0000 + j * 0x8000 + 4096 * (i + 1)) 81 | u.valb[i] = MTRR_MEMTYPE_WP; 82 | wrmsr_smp(MSR_MTRRfix4K_C0000 + j, u.val); 83 | } 84 | 85 | // Set variable MTRRs 86 | int phys_bits = 36; 87 | cpuid(0x80000000u, &eax, &ebx, &ecx, &edx); 88 | if (eax >= 0x80000008) { 89 | /* Get physical bits from leaf 0x80000008 (if available) */ 90 | cpuid(0x80000008u, &eax, &ebx, &ecx, &edx); 91 | phys_bits = eax & 0xff; 92 | } 93 | u64 phys_mask = ((1ull << phys_bits) - 1); 94 | for (i=0; i 4 | // 5 | // This file may be distributed under the terms of the GNU LGPLv3 license. 6 | 7 | #include "config.h" // CONFIG_* 8 | #include "malloc.h" // free 9 | #include "output.h" // dprintf 10 | #include "romfile.h" // romfile_add 11 | #include "std/multiboot.h" // MULTIBOOT_* 12 | #include "string.h" // memset 13 | #include "util.h" // multiboot_init 14 | 15 | struct mbfs_romfile_s { 16 | struct romfile_s file; 17 | void *data; 18 | }; 19 | 20 | static int 21 | extract_filename(char *dest, char *src, size_t lim) 22 | { 23 | char *ptr; 24 | for (ptr = src; *ptr; ptr++) { 25 | if (!(ptr == src || ptr[-1] == ' ' || ptr[-1] == '\t')) 26 | continue; 27 | /* memcmp stops early if it encounters \0 as it doesn't match name=. */ 28 | if (memcmp(ptr, "name=", 5) == 0) { 29 | int i; 30 | char *optr = dest; 31 | for (i = 0, ptr += 5; *ptr && *ptr != ' ' && i < lim; i++) { 32 | *optr++ = *ptr++; 33 | } 34 | *optr++ = '\0'; 35 | return 1; 36 | } 37 | } 38 | return 0; 39 | } 40 | 41 | // Copy a file to memory 42 | static int 43 | mbfs_copyfile(struct romfile_s *file, void *dst, u32 maxlen) 44 | { 45 | struct mbfs_romfile_s *cfile; 46 | cfile = container_of(file, struct mbfs_romfile_s, file); 47 | u32 size = cfile->file.size; 48 | void *src = cfile->data; 49 | 50 | // Not compressed. 51 | dprintf(3, "Copying data %d@%p to %d@%p\n", size, src, maxlen, dst); 52 | if (size > maxlen) { 53 | warn_noalloc(); 54 | return -1; 55 | } 56 | iomemcpy(dst, src, size); 57 | return size; 58 | } 59 | 60 | u32 __VISIBLE entry_elf_eax, entry_elf_ebx; 61 | 62 | void 63 | multiboot_init(void) 64 | { 65 | struct multiboot_info *mbi; 66 | if (!CONFIG_MULTIBOOT) 67 | return; 68 | dprintf(1, "multiboot: eax=%x, ebx=%x\n", entry_elf_eax, entry_elf_ebx); 69 | if (entry_elf_eax != MULTIBOOT_BOOTLOADER_MAGIC) 70 | return; 71 | mbi = (void *)entry_elf_ebx; 72 | dprintf(1, "mbptr=%p\n", mbi); 73 | dprintf(1, "flags=0x%x, mods=0x%x, mods_c=%d\n", mbi->flags, mbi->mods_addr, 74 | mbi->mods_count); 75 | if (!(mbi->flags & MULTIBOOT_INFO_MODS)) 76 | return; 77 | int i; 78 | struct multiboot_mod_list *mod = (void *)mbi->mods_addr; 79 | for (i = 0; i < mbi->mods_count; i++) { 80 | struct mbfs_romfile_s *cfile; 81 | u8 *copy; 82 | u32 len; 83 | if (!mod[i].cmdline) 84 | continue; 85 | len = mod[i].mod_end - mod[i].mod_start; 86 | cfile = malloc_tmp(sizeof(*cfile)); 87 | if (!cfile) { 88 | warn_noalloc(); 89 | return; 90 | } 91 | memset(cfile, 0, sizeof(*cfile)); 92 | dprintf(1, "module %s, size 0x%x\n", (char *)mod[i].cmdline, len); 93 | if (!extract_filename(cfile->file.name, (char *)mod[i].cmdline, 94 | sizeof(cfile->file.name))) { 95 | free(cfile); 96 | continue; 97 | } 98 | dprintf(1, "assigned file name <%s>\n", cfile->file.name); 99 | cfile->file.size = len; 100 | copy = malloc_tmp(len); 101 | if (!copy) { 102 | warn_noalloc(); 103 | free(cfile); 104 | return; 105 | } 106 | memcpy(copy, (void *)mod[i].mod_start, len); 107 | cfile->file.copy = mbfs_copyfile; 108 | cfile->data = copy; 109 | romfile_add(&cfile->file); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/fw/paravirt.h: -------------------------------------------------------------------------------- 1 | #ifndef __PV_H 2 | #define __PV_H 3 | 4 | #include "config.h" // CONFIG_* 5 | #include "biosvar.h" // GET_GLOBAL 6 | #include "romfile.h" // struct romfile_s 7 | 8 | // kvmclock 9 | struct pvclock_vcpu_time_info { 10 | u32 version; 11 | u32 pad0; 12 | u64 tsc_timestamp; 13 | u64 system_time; 14 | u32 tsc_to_system_mul; 15 | s8 tsc_shift; 16 | u8 flags; 17 | u8 pad[2]; 18 | } __attribute__((__packed__)); /* 32 bytes */ 19 | 20 | // Types of paravirtualized platforms. 21 | #define PF_QEMU (1<<0) 22 | #define PF_XEN (1<<1) 23 | #define PF_KVM (1<<2) 24 | 25 | typedef struct QemuCfgDmaAccess { 26 | u32 control; 27 | u32 length; 28 | u64 address; 29 | } PACKED QemuCfgDmaAccess; 30 | 31 | extern u32 RamSize; 32 | extern u64 RamSizeOver4G; 33 | extern int PlatformRunningOn; 34 | extern u8 CPUPhysBits; 35 | extern u8 CPULongMode; 36 | 37 | static inline int runningOnQEMU(void) { 38 | return CONFIG_QEMU || ( 39 | CONFIG_QEMU_HARDWARE && GET_GLOBAL(PlatformRunningOn) & PF_QEMU); 40 | } 41 | static inline int runningOnXen(void) { 42 | return CONFIG_XEN && GET_GLOBAL(PlatformRunningOn) & PF_XEN; 43 | } 44 | static inline int runningOnKVM(void) { 45 | return CONFIG_QEMU && GET_GLOBAL(PlatformRunningOn) & PF_KVM; 46 | } 47 | 48 | // Common paravirt ports. 49 | #define PORT_SMI_CMD 0x00b2 50 | #define PORT_SMI_STATUS 0x00b3 51 | #define PORT_QEMU_CFG_CTL 0x0510 52 | #define PORT_QEMU_CFG_DATA 0x0511 53 | #define PORT_QEMU_CFG_DMA_ADDR_HIGH 0x0514 54 | #define PORT_QEMU_CFG_DMA_ADDR_LOW 0x0518 55 | 56 | // QEMU_CFG_DMA_CONTROL bits 57 | #define QEMU_CFG_DMA_CTL_ERROR 0x01 58 | #define QEMU_CFG_DMA_CTL_READ 0x02 59 | #define QEMU_CFG_DMA_CTL_SKIP 0x04 60 | #define QEMU_CFG_DMA_CTL_SELECT 0x08 61 | #define QEMU_CFG_DMA_CTL_WRITE 0x10 62 | 63 | // QEMU_CFG_DMA ID bit 64 | #define QEMU_CFG_VERSION_DMA 2 65 | 66 | // QEMU debugcon read value 67 | #define QEMU_DEBUGCON_READBACK 0xe9 68 | 69 | int qemu_cfg_enabled(void); 70 | int qemu_cfg_dma_enabled(void); 71 | void qemu_preinit(void); 72 | void qemu_platform_setup(void); 73 | void qemu_cfg_init(void); 74 | 75 | u16 qemu_get_present_cpus_count(void); 76 | int qemu_cfg_write_file(void *src, struct romfile_s *file, u32 offset, u32 len); 77 | int qemu_cfg_write_file_simple(void *src, u16 key, u32 offset, u32 len); 78 | u16 qemu_get_romfile_key(struct romfile_s *file); 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /src/fw/pirtable.c: -------------------------------------------------------------------------------- 1 | // PIR table generation (for emulators) 2 | // DO NOT ADD NEW FEATURES HERE. (See paravirt.c / biostables.c instead.) 3 | // 4 | // Copyright (C) 2008 Kevin O'Connor 5 | // Copyright (C) 2002 MandrakeSoft S.A. 6 | // 7 | // This file may be distributed under the terms of the GNU LGPLv3 license. 8 | 9 | #include "config.h" // CONFIG_* 10 | #include "output.h" // dprintf 11 | #include "std/pirtable.h" // struct pir_header 12 | #include "string.h" // checksum 13 | #include "util.h" // PirAddr 14 | 15 | struct pir_table { 16 | struct pir_header pir; 17 | struct pir_slot slots[6]; 18 | } PACKED; 19 | 20 | static struct pir_table PIR_TABLE = { 21 | .pir = { 22 | .version = 0x0100, 23 | .size = sizeof(struct pir_table), 24 | .router_devfunc = 0x08, 25 | .compatible_devid = 0x122e8086, 26 | }, 27 | .slots = { 28 | { 29 | // first slot entry PCI-to-ISA (embedded) 30 | .dev = 1<<3, 31 | .links = { 32 | {.link = 0x60, .bitmap = 0xdef8}, // INTA# 33 | {.link = 0x61, .bitmap = 0xdef8}, // INTB# 34 | {.link = 0x62, .bitmap = 0xdef8}, // INTC# 35 | {.link = 0x63, .bitmap = 0xdef8}, // INTD# 36 | }, 37 | .slot_nr = 0, // embedded 38 | }, { 39 | // second slot entry: 1st PCI slot 40 | .dev = 2<<3, 41 | .links = { 42 | {.link = 0x61, .bitmap = 0xdef8}, // INTA# 43 | {.link = 0x62, .bitmap = 0xdef8}, // INTB# 44 | {.link = 0x63, .bitmap = 0xdef8}, // INTC# 45 | {.link = 0x60, .bitmap = 0xdef8}, // INTD# 46 | }, 47 | .slot_nr = 1, 48 | }, { 49 | // third slot entry: 2nd PCI slot 50 | .dev = 3<<3, 51 | .links = { 52 | {.link = 0x62, .bitmap = 0xdef8}, // INTA# 53 | {.link = 0x63, .bitmap = 0xdef8}, // INTB# 54 | {.link = 0x60, .bitmap = 0xdef8}, // INTC# 55 | {.link = 0x61, .bitmap = 0xdef8}, // INTD# 56 | }, 57 | .slot_nr = 2, 58 | }, { 59 | // 4th slot entry: 3rd PCI slot 60 | .dev = 4<<3, 61 | .links = { 62 | {.link = 0x63, .bitmap = 0xdef8}, // INTA# 63 | {.link = 0x60, .bitmap = 0xdef8}, // INTB# 64 | {.link = 0x61, .bitmap = 0xdef8}, // INTC# 65 | {.link = 0x62, .bitmap = 0xdef8}, // INTD# 66 | }, 67 | .slot_nr = 3, 68 | }, { 69 | // 5th slot entry: 4th PCI slot 70 | .dev = 5<<3, 71 | .links = { 72 | {.link = 0x60, .bitmap = 0xdef8}, // INTA# 73 | {.link = 0x61, .bitmap = 0xdef8}, // INTB# 74 | {.link = 0x62, .bitmap = 0xdef8}, // INTC# 75 | {.link = 0x63, .bitmap = 0xdef8}, // INTD# 76 | }, 77 | .slot_nr = 4, 78 | }, { 79 | // 6th slot entry: 5th PCI slot 80 | .dev = 6<<3, 81 | .links = { 82 | {.link = 0x61, .bitmap = 0xdef8}, // INTA# 83 | {.link = 0x62, .bitmap = 0xdef8}, // INTB# 84 | {.link = 0x63, .bitmap = 0xdef8}, // INTC# 85 | {.link = 0x60, .bitmap = 0xdef8}, // INTD# 86 | }, 87 | .slot_nr = 5, 88 | }, 89 | } 90 | }; 91 | 92 | void 93 | pirtable_setup(void) 94 | { 95 | if (! CONFIG_PIRTABLE) 96 | return; 97 | 98 | dprintf(3, "init PIR table\n"); 99 | 100 | PIR_TABLE.pir.signature = PIR_SIGNATURE; 101 | PIR_TABLE.pir.checksum -= checksum(&PIR_TABLE, sizeof(PIR_TABLE)); 102 | copy_pir(&PIR_TABLE); 103 | } 104 | -------------------------------------------------------------------------------- /src/fw/romfile_loader.h: -------------------------------------------------------------------------------- 1 | #ifndef __ROMFILE_LOADER_H 2 | #define __ROMFILE_LOADER_H 3 | 4 | #include "types.h" // u8 5 | #include "util.h" // romfile_s 6 | 7 | #define ROMFILE_LOADER_FILESZ 56 8 | 9 | /* ROM file linker/loader interface. Linker uses little endian format */ 10 | struct romfile_loader_entry_s { 11 | u32 command; 12 | union { 13 | /* 14 | * COMMAND_ALLOCATE - allocate a table from @alloc.file 15 | * subject to @alloc.align alignment (must be power of 2) 16 | * and @alloc.zone (can be HIGH or FSEG) requirements. 17 | * 18 | * Must appear exactly once for each file, and before 19 | * this file is referenced by any other command. 20 | */ 21 | struct { 22 | char file[ROMFILE_LOADER_FILESZ]; 23 | u32 align; 24 | u8 zone; 25 | } alloc; 26 | 27 | /* 28 | * COMMAND_ADD_POINTER - patch the table (originating from 29 | * @dest_file) at @pointer.offset, by adding a pointer to the table 30 | * originating from @src_file. 1,2,4 or 8 byte unsigned 31 | * addition is used depending on @pointer.size. 32 | */ 33 | struct { 34 | char dest_file[ROMFILE_LOADER_FILESZ]; 35 | char src_file[ROMFILE_LOADER_FILESZ]; 36 | u32 offset; 37 | u8 size; 38 | } pointer; 39 | 40 | /* 41 | * COMMAND_ADD_CHECKSUM - calculate checksum of the range specified by 42 | * @cksum.start and @cksum.length fields, 43 | * and then add the value at @cksum_offset. 44 | * Checksum simply sums -X for each byte X in the range 45 | * using 8-bit math. 46 | */ 47 | struct { 48 | char file[ROMFILE_LOADER_FILESZ]; 49 | u32 offset; 50 | u32 start; 51 | u32 length; 52 | } cksum; 53 | 54 | /* 55 | * COMMAND_WRITE_POINTER - Write back to a host file via DMA, 56 | * @wr_pointer.dest_file at offset @wr_pointer.dst_offset, a pointer 57 | * to the table originating from @wr_pointer.src_file at offset 58 | * @wr_pointer.src_offset. 59 | * 1,2,4 or 8 byte unsigned addition is used depending on 60 | * @wr_pointer.size. 61 | */ 62 | struct { 63 | char dest_file[ROMFILE_LOADER_FILESZ]; 64 | char src_file[ROMFILE_LOADER_FILESZ]; 65 | u32 dst_offset; 66 | u32 src_offset; 67 | u8 size; 68 | } wr_pointer; 69 | 70 | /* padding */ 71 | char pad[124]; 72 | }; 73 | }; 74 | 75 | enum { 76 | ROMFILE_LOADER_COMMAND_ALLOCATE = 0x1, 77 | ROMFILE_LOADER_COMMAND_ADD_POINTER = 0x2, 78 | ROMFILE_LOADER_COMMAND_ADD_CHECKSUM = 0x3, 79 | ROMFILE_LOADER_COMMAND_WRITE_POINTER = 0x4, 80 | }; 81 | 82 | enum { 83 | ROMFILE_LOADER_ALLOC_ZONE_HIGH = 0x1, 84 | ROMFILE_LOADER_ALLOC_ZONE_FSEG = 0x2, 85 | }; 86 | 87 | int romfile_loader_execute(const char *name); 88 | 89 | void romfile_fw_cfg_resume(void); 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /src/gen-defs.h: -------------------------------------------------------------------------------- 1 | // Tool for building defintions accessible from assembler code. This 2 | // is based on code from the Linux Kernel. 3 | #ifndef __GEN_DEFS_H 4 | #define __GEN_DEFS_H 5 | 6 | 7 | #define DEFINE(sym, val) \ 8 | asm volatile("\n->" #sym " %0 " #val : : "i" (val)) 9 | 10 | #define BLANK() \ 11 | asm volatile("\n->" : : ) 12 | 13 | #define OFFSET(sym, str, mem) \ 14 | DEFINE(sym, offsetof(struct str, mem)) 15 | 16 | #define COMMENT(x) \ 17 | asm volatile("\n->#" x) 18 | 19 | #endif // gen-defs.h 20 | -------------------------------------------------------------------------------- /src/hw/blockcmd.h: -------------------------------------------------------------------------------- 1 | // Definitions for SCSI style command data blocks. 2 | #ifndef __BLOCKCMD_H 3 | #define __BLOCKCMD_H 4 | 5 | #include "types.h" // u8 6 | 7 | #define CDB_CMD_READ_10 0x28 8 | #define CDB_CMD_VERIFY_10 0x2f 9 | #define CDB_CMD_WRITE_10 0x2a 10 | 11 | struct cdb_rwdata_10 { 12 | u8 command; 13 | u8 flags; 14 | u32 lba; 15 | u8 resreved_06; 16 | u16 count; 17 | u8 reserved_09; 18 | u8 pad[6]; 19 | } PACKED; 20 | 21 | #define CDB_CMD_READ_16 0x88 22 | #define CDB_CMD_WRITE_16 0x8A 23 | struct cdb_rwdata_16 { 24 | u8 command; 25 | u8 flags; 26 | u64 lba; 27 | u32 count; 28 | u16 reserved_14; 29 | } PACKED; 30 | 31 | #define CDB_CMD_READ_CAPACITY 0x25 32 | 33 | struct cdb_read_capacity { 34 | u8 command; 35 | u8 flags; 36 | u8 resreved_02[8]; 37 | u8 pad[6]; 38 | } PACKED; 39 | 40 | struct cdbres_read_capacity { 41 | u32 sectors; 42 | u32 blksize; 43 | } PACKED; 44 | 45 | 46 | #define CDB_CMD_SERVICE_ACTION_IN 0x9E 47 | #define CDB_CMD_SAI_READ_CAPACITY_16 0x10 48 | struct cdb_sai_read_capacity_16 { 49 | u8 command; 50 | u8 flags; 51 | u64 lba; //marked as obsolete? 52 | u32 len; 53 | u16 reserved_14; 54 | } PACKED; 55 | 56 | struct cdbres_read_capacity_16 { 57 | u64 sectors; 58 | u32 blksize; 59 | u8 reserved_12[20]; 60 | } PACKED; 61 | 62 | #define CDB_CMD_TEST_UNIT_READY 0x00 63 | #define CDB_CMD_INQUIRY 0x12 64 | #define CDB_CMD_REQUEST_SENSE 0x03 65 | 66 | struct cdb_request_sense { 67 | u8 command; 68 | u8 flags; 69 | u16 reserved_02; 70 | u8 length; 71 | u8 reserved_05; 72 | u8 pad[10]; 73 | } PACKED; 74 | 75 | struct cdbres_request_sense { 76 | u8 errcode; 77 | u8 segment; 78 | u8 flags; 79 | u32 info; 80 | u8 additional; 81 | u32 specific; 82 | u8 asc; 83 | u8 ascq; 84 | u32 reserved_0e; 85 | } PACKED; 86 | 87 | #define SCSI_TYPE_DISK 0x00 88 | #define SCSI_TYPE_CDROM 0x05 89 | 90 | struct cdbres_inquiry { 91 | u8 pdt; 92 | u8 removable; 93 | u8 reserved_02[2]; 94 | u8 additional; 95 | u8 reserved_05[3]; 96 | char vendor[8]; 97 | char product[16]; 98 | char rev[4]; 99 | } PACKED; 100 | 101 | #define CDB_CMD_MODE_SENSE 0x5A 102 | #define MODE_PAGE_HD_GEOMETRY 0x04 103 | 104 | struct cdb_mode_sense { 105 | u8 command; 106 | u8 flags; 107 | u8 page; 108 | u32 reserved_03; 109 | u16 count; 110 | u8 reserved_09; 111 | u8 pad[6]; 112 | } PACKED; 113 | 114 | struct cdbres_mode_sense_geom { 115 | u8 unused_00[3]; 116 | u8 read_only; 117 | u32 unused_04; 118 | u8 page; 119 | u8 length; 120 | u8 cyl[3]; 121 | u8 heads; 122 | u8 precomp[3]; 123 | u8 reduced[3]; 124 | u16 step_rate; 125 | u8 landing[3]; 126 | u16 rpm; 127 | } PACKED; 128 | 129 | // blockcmd.c 130 | struct disk_op_s; 131 | int scsi_fill_cmd(struct disk_op_s *op, void *cdbcmd, int maxcdb); 132 | int scsi_is_read(struct disk_op_s *op); 133 | int scsi_is_ready(struct disk_op_s *op); 134 | struct drive_s; 135 | int scsi_drive_setup(struct drive_s *drive, const char *s, int prio); 136 | typedef int (*scsi_add_lun)(u32 lun, struct drive_s *tmpl_drv); 137 | int scsi_rep_luns_scan(struct drive_s *tmp_drive, scsi_add_lun add_lun); 138 | int scsi_sequential_scan(struct drive_s *tmp_drive, u32 maxluns, 139 | scsi_add_lun add_lun); 140 | 141 | #endif // blockcmd.h 142 | -------------------------------------------------------------------------------- /src/hw/dma.c: -------------------------------------------------------------------------------- 1 | // Code to support legacy Intel 8237 DMA chip. 2 | // 3 | // Copyright (C) 2008,2009 Kevin O'Connor 4 | // Copyright (C) 2002 MandrakeSoft S.A. 5 | // 6 | // This file may be distributed under the terms of the GNU LGPLv3 license. 7 | 8 | #include "util.h" // dma_setup 9 | #include "x86.h" // outb 10 | 11 | #define PORT_DMA_ADDR_2 0x0004 12 | #define PORT_DMA_CNT_2 0x0005 13 | #define PORT_DMA1_MASK_REG 0x000a 14 | #define PORT_DMA1_MODE_REG 0x000b 15 | #define PORT_DMA1_CLEAR_FF_REG 0x000c 16 | #define PORT_DMA1_MASTER_CLEAR 0x000d 17 | #define PORT_DMA_PAGE_2 0x0081 18 | #define PORT_DMA2_MASK_REG 0x00d4 19 | #define PORT_DMA2_MODE_REG 0x00d6 20 | #define PORT_DMA2_MASTER_CLEAR 0x00da 21 | 22 | // Setup the DMA controller for a floppy transfer. 23 | int 24 | dma_floppy(u32 addr, int count, int isWrite) 25 | { 26 | // check for 64K boundary overrun 27 | u16 end = count - 1; 28 | u32 last_addr = addr + end; 29 | if ((addr >> 16) != (last_addr >> 16)) 30 | return -1; 31 | 32 | u8 mode_register = 0x46; // single mode, increment, autoinit disable, 33 | if (isWrite) 34 | mode_register = 0x4a; 35 | 36 | outb(0x06, PORT_DMA1_MASK_REG); 37 | outb(0x00, PORT_DMA1_CLEAR_FF_REG); // clear flip-flop 38 | outb(addr, PORT_DMA_ADDR_2); 39 | outb(addr>>8, PORT_DMA_ADDR_2); 40 | outb(0x00, PORT_DMA1_CLEAR_FF_REG); // clear flip-flop 41 | outb(end, PORT_DMA_CNT_2); 42 | outb(end>>8, PORT_DMA_CNT_2); 43 | 44 | // port 0b: DMA-1 Mode Register 45 | // transfer type=write, channel 2 46 | outb(mode_register, PORT_DMA1_MODE_REG); 47 | 48 | // port 81: DMA-1 Page Register, channel 2 49 | outb(addr>>16, PORT_DMA_PAGE_2); 50 | 51 | outb(0x02, PORT_DMA1_MASK_REG); // unmask channel 2 52 | 53 | return 0; 54 | } 55 | 56 | // Reset DMA controller 57 | void 58 | dma_setup(void) 59 | { 60 | // first reset the DMA controllers 61 | outb(0, PORT_DMA1_MASTER_CLEAR); 62 | outb(0, PORT_DMA2_MASTER_CLEAR); 63 | 64 | // then initialize the DMA controllers 65 | outb(0xc0, PORT_DMA2_MODE_REG); 66 | outb(0x00, PORT_DMA2_MASK_REG); 67 | } 68 | -------------------------------------------------------------------------------- /src/hw/esp-scsi.h: -------------------------------------------------------------------------------- 1 | #ifndef __ESP_SCSI_H 2 | #define __ESP_SCSI_H 3 | 4 | struct disk_op_s; 5 | int esp_scsi_process_op(struct disk_op_s *op); 6 | void esp_scsi_setup(void); 7 | 8 | #endif /* __ESP_SCSI_H */ 9 | -------------------------------------------------------------------------------- /src/hw/lsi-scsi.h: -------------------------------------------------------------------------------- 1 | #ifndef __LSI_SCSI_H 2 | #define __LSI_SCSI_H 3 | 4 | struct disk_op_s; 5 | int lsi_scsi_process_op(struct disk_op_s *op); 6 | void lsi_scsi_setup(void); 7 | 8 | #endif /* __LSI_SCSI_H */ 9 | -------------------------------------------------------------------------------- /src/hw/megasas.h: -------------------------------------------------------------------------------- 1 | #ifndef __MEGASAS_H 2 | #define __MEGASAS_H 3 | 4 | struct disk_op_s; 5 | int megasas_process_op(struct disk_op_s *op); 6 | void megasas_setup(void); 7 | 8 | #endif /* __MEGASAS_H */ 9 | -------------------------------------------------------------------------------- /src/hw/mpt-scsi.h: -------------------------------------------------------------------------------- 1 | #ifndef __MPT_SCSI_H 2 | #define __MPT_SCSI_H 3 | 4 | struct disk_op_s; 5 | int mpt_scsi_process_op(struct disk_op_s *op); 6 | void mpt_scsi_setup(void); 7 | 8 | #endif /* __MPT_SCSI_H */ 9 | -------------------------------------------------------------------------------- /src/hw/nvme.h: -------------------------------------------------------------------------------- 1 | // External interfaces for low level NVMe support 2 | // 3 | // Copyright 2017 Amazon.com, Inc. or its affiliates. 4 | // 5 | // This file may be distributed under the terms of the GNU LGPLv3 license. 6 | 7 | #ifndef __NVME_H 8 | #define __NVME_H 9 | 10 | #include "block.h" // struct disk_op_s 11 | 12 | void nvme_setup(void); 13 | int nvme_process_op(struct disk_op_s *op); 14 | 15 | #endif 16 | 17 | /* EOF */ 18 | -------------------------------------------------------------------------------- /src/hw/pci.h: -------------------------------------------------------------------------------- 1 | #ifndef __PCI_H 2 | #define __PCI_H 3 | 4 | #include "types.h" // u32 5 | 6 | #define PORT_PCI_REBOOT 0x0cf9 7 | 8 | static inline u8 pci_bdf_to_bus(u16 bdf) { 9 | return bdf >> 8; 10 | } 11 | static inline u8 pci_bdf_to_devfn(u16 bdf) { 12 | return bdf & 0xff; 13 | } 14 | static inline u16 pci_bdf_to_busdev(u16 bdf) { 15 | return bdf & ~0x07; 16 | } 17 | static inline u8 pci_bdf_to_dev(u16 bdf) { 18 | return (bdf >> 3) & 0x1f; 19 | } 20 | static inline u8 pci_bdf_to_fn(u16 bdf) { 21 | return bdf & 0x07; 22 | } 23 | static inline u16 pci_to_bdf(int bus, int dev, int fn) { 24 | return (bus<<8) | (dev<<3) | fn; 25 | } 26 | static inline u16 pci_bus_devfn_to_bdf(int bus, u16 devfn) { 27 | return (bus << 8) | devfn; 28 | } 29 | 30 | #define pci_ioconfig_foreachbdf(BDF, BUS) \ 31 | for (BDF=pci_ioconfig_next(pci_bus_devfn_to_bdf((BUS), 0)-1, (BUS)) \ 32 | ; BDF >= 0 \ 33 | ; BDF=pci_ioconfig_next(BDF, (BUS))) 34 | 35 | #define foreachbdf(BDF, BUS) \ 36 | for (BDF=pci_next(pci_bus_devfn_to_bdf((BUS), 0)-1, (BUS)) \ 37 | ; BDF >= 0 \ 38 | ; BDF=pci_next(BDF, (BUS))) 39 | 40 | // standard PCI configration access mechanism 41 | void pci_ioconfig_writel(u16 bdf, u32 addr, u32 val); 42 | void pci_ioconfig_writew(u16 bdf, u32 addr, u16 val); 43 | void pci_ioconfig_writeb(u16 bdf, u32 addr, u8 val); 44 | u32 pci_ioconfig_readl(u16 bdf, u32 addr); 45 | u16 pci_ioconfig_readw(u16 bdf, u32 addr); 46 | u8 pci_ioconfig_readb(u16 bdf, u32 addr); 47 | int pci_ioconfig_next(int bdf, int bus); 48 | 49 | // PCI configuration access using either PCI CAM or PCIe ECAM 50 | void pci_config_writel(u16 bdf, u32 addr, u32 val); 51 | void pci_config_writew(u16 bdf, u32 addr, u16 val); 52 | void pci_config_writeb(u16 bdf, u32 addr, u8 val); 53 | u32 pci_config_readl(u16 bdf, u32 addr); 54 | u16 pci_config_readw(u16 bdf, u32 addr); 55 | u8 pci_config_readb(u16 bdf, u32 addr); 56 | void pci_config_maskw(u16 bdf, u32 addr, u16 off, u16 on); 57 | u8 pci_find_capability(u16 bdf, u8 cap_id, u8 cap); 58 | int pci_next(int bdf, int bus); 59 | 60 | void pci_enable_mmconfig(u64 addr, const char *name); 61 | int pci_probe_host(void); 62 | void pci_reboot(void); 63 | 64 | #endif // pci.h 65 | -------------------------------------------------------------------------------- /src/hw/pcidevice.h: -------------------------------------------------------------------------------- 1 | #ifndef __PCIDEVICE_H 2 | #define __PCIDEVICE_H 3 | 4 | #include "types.h" // u32 5 | #include "list.h" // hlist_node 6 | 7 | struct pci_device { 8 | u16 bdf; 9 | u8 rootbus; 10 | struct hlist_node node; 11 | struct pci_device *parent; 12 | 13 | // Configuration space device information 14 | u16 vendor, device; 15 | u16 class; 16 | u8 prog_if, revision; 17 | u8 header_type; 18 | u8 secondary_bus; 19 | 20 | // Local information on device. 21 | int have_driver; 22 | }; 23 | extern struct hlist_head PCIDevices; 24 | extern int MaxPCIBus; 25 | 26 | static inline u32 pci_classprog(struct pci_device *pci) { 27 | return (pci->class << 8) | pci->prog_if; 28 | } 29 | 30 | #define foreachpci(PCI) \ 31 | hlist_for_each_entry(PCI, &PCIDevices, node) 32 | 33 | #define PCI_ANY_ID (~0) 34 | struct pci_device_id { 35 | u32 vendid; 36 | u32 devid; 37 | u32 class; 38 | u32 class_mask; 39 | void (*func)(struct pci_device *pci, void *arg); 40 | }; 41 | 42 | #define PCI_DEVICE(vendor_id, device_id, init_func) \ 43 | { \ 44 | .vendid = (vendor_id), \ 45 | .devid = (device_id), \ 46 | .class = PCI_ANY_ID, \ 47 | .class_mask = 0, \ 48 | .func = (init_func) \ 49 | } 50 | 51 | #define PCI_DEVICE_CLASS(vendor_id, device_id, class_code, init_func) \ 52 | { \ 53 | .vendid = (vendor_id), \ 54 | .devid = (device_id), \ 55 | .class = (class_code), \ 56 | .class_mask = ~0, \ 57 | .func = (init_func) \ 58 | } 59 | 60 | #define PCI_DEVICE_END \ 61 | { \ 62 | .vendid = 0, \ 63 | } 64 | 65 | void pci_probe_devices(void); 66 | struct pci_device *pci_find_device(u16 vendid, u16 devid); 67 | struct pci_device *pci_find_class(u16 classid); 68 | int pci_init_device(const struct pci_device_id *ids 69 | , struct pci_device *pci, void *arg); 70 | struct pci_device *pci_find_init_device(const struct pci_device_id *ids 71 | , void *arg); 72 | void pci_enable_busmaster(struct pci_device *pci); 73 | u16 pci_enable_iobar(struct pci_device *pci, u32 addr); 74 | void *pci_enable_membar(struct pci_device *pci, u32 addr); 75 | 76 | #endif // pcidevice.h 77 | -------------------------------------------------------------------------------- /src/hw/pic.c: -------------------------------------------------------------------------------- 1 | // Helpers for working with i8259 interrupt controller. 2 | // 3 | // Copyright (C) 2008 Kevin O'Connor 4 | // Copyright (C) 2002 MandrakeSoft S.A. 5 | // 6 | // This file may be distributed under the terms of the GNU LGPLv3 license. 7 | 8 | #include "biosvar.h" // SET_IVT 9 | #include "config.h" // CONFIG_* 10 | #include "output.h" // dprintf 11 | #include "pic.h" // pic_* 12 | 13 | u16 14 | pic_irqmask_read(void) 15 | { 16 | if (!CONFIG_HARDWARE_IRQ) 17 | return 0; 18 | return inb(PORT_PIC1_DATA) | (inb(PORT_PIC2_DATA) << 8); 19 | } 20 | 21 | void 22 | pic_irqmask_write(u16 mask) 23 | { 24 | if (!CONFIG_HARDWARE_IRQ) 25 | return; 26 | outb(mask, PORT_PIC1_DATA); 27 | outb(mask >> 8, PORT_PIC2_DATA); 28 | } 29 | 30 | void 31 | pic_irqmask_mask(u16 off, u16 on) 32 | { 33 | if (!CONFIG_HARDWARE_IRQ) 34 | return; 35 | u8 pic1off = off, pic1on = on, pic2off = off>>8, pic2on = on>>8; 36 | outb((inb(PORT_PIC1_DATA) & ~pic1off) | pic1on, PORT_PIC1_DATA); 37 | outb((inb(PORT_PIC2_DATA) & ~pic2off) | pic2on, PORT_PIC2_DATA); 38 | } 39 | 40 | void 41 | pic_reset(u8 irq0, u8 irq8) 42 | { 43 | if (!CONFIG_HARDWARE_IRQ) 44 | return; 45 | // Send ICW1 (select OCW1 + will send ICW4) 46 | outb(0x11, PORT_PIC1_CMD); 47 | outb(0x11, PORT_PIC2_CMD); 48 | // Send ICW2 (base irqs: 0x08-0x0f for irq0-7, 0x70-0x77 for irq8-15) 49 | outb(irq0, PORT_PIC1_DATA); 50 | outb(irq8, PORT_PIC2_DATA); 51 | // Send ICW3 (cascaded pic ids) 52 | outb(0x04, PORT_PIC1_DATA); 53 | outb(0x02, PORT_PIC2_DATA); 54 | // Send ICW4 (enable 8086 mode) 55 | outb(0x01, PORT_PIC1_DATA); 56 | outb(0x01, PORT_PIC2_DATA); 57 | // Mask all irqs (except cascaded PIC2 irq) 58 | pic_irqmask_write(PIC_IRQMASK_DEFAULT); 59 | } 60 | 61 | void 62 | pic_setup(void) 63 | { 64 | dprintf(3, "init pic\n"); 65 | pic_reset(BIOS_HWIRQ0_VECTOR, BIOS_HWIRQ8_VECTOR); 66 | } 67 | 68 | void 69 | enable_hwirq(int hwirq, struct segoff_s func) 70 | { 71 | if (!CONFIG_HARDWARE_IRQ) 72 | return; 73 | pic_irqmask_mask(1 << hwirq, 0); 74 | int vector; 75 | if (hwirq < 8) 76 | vector = BIOS_HWIRQ0_VECTOR + hwirq; 77 | else 78 | vector = BIOS_HWIRQ8_VECTOR + hwirq - 8; 79 | SET_IVT(vector, func); 80 | } 81 | 82 | static u8 83 | pic_isr1_read(void) 84 | { 85 | if (!CONFIG_HARDWARE_IRQ) 86 | return 0; 87 | // 0x0b == select OCW1 + read ISR 88 | outb(0x0b, PORT_PIC1_CMD); 89 | return inb(PORT_PIC1_CMD); 90 | } 91 | 92 | static u8 93 | pic_isr2_read(void) 94 | { 95 | if (!CONFIG_HARDWARE_IRQ) 96 | return 0; 97 | // 0x0b == select OCW1 + read ISR 98 | outb(0x0b, PORT_PIC2_CMD); 99 | return inb(PORT_PIC2_CMD); 100 | } 101 | 102 | // Handler for otherwise unused hardware irqs. 103 | void VISIBLE16 104 | handle_hwpic1(void) 105 | { 106 | dprintf(DEBUG_ISR_hwpic1, "handle_hwpic1 irq=%x\n", pic_isr1_read()); 107 | pic_eoi1(); 108 | } 109 | 110 | void VISIBLE16 111 | handle_hwpic2(void) 112 | { 113 | dprintf(DEBUG_ISR_hwpic2, "handle_hwpic2 irq=%x\n", pic_isr2_read()); 114 | pic_eoi2(); 115 | } 116 | -------------------------------------------------------------------------------- /src/hw/pic.h: -------------------------------------------------------------------------------- 1 | // Helpers for working with i8259 interrupt controller. 2 | // 3 | // Copyright (C) 2008 Kevin O'Connor 4 | // Copyright (C) 2002 MandrakeSoft S.A. 5 | // 6 | // This file may be distributed under the terms of the GNU LGPLv3 license. 7 | #ifndef __PIC_H 8 | #define __PIC_H 9 | 10 | #include "x86.h" // outb 11 | 12 | #define PORT_PIC1_CMD 0x0020 13 | #define PORT_PIC1_DATA 0x0021 14 | #define PORT_PIC2_CMD 0x00a0 15 | #define PORT_PIC2_DATA 0x00a1 16 | 17 | // PORT_PIC1 bitdefs 18 | #define PIC1_IRQ0 (1<<0) 19 | #define PIC1_IRQ1 (1<<1) 20 | #define PIC1_IRQ2 (1<<2) 21 | #define PIC1_IRQ5 (1<<5) 22 | #define PIC1_IRQ6 (1<<6) 23 | // PORT_PIC2 bitdefs 24 | #define PIC2_IRQ8 (1<<8) 25 | #define PIC2_IRQ12 (1<<12) 26 | #define PIC2_IRQ13 (1<<13) 27 | #define PIC2_IRQ14 (1<<14) 28 | 29 | #define PIC_IRQMASK_DEFAULT ((u16)~PIC1_IRQ2) 30 | 31 | #define BIOS_HWIRQ0_VECTOR 0x08 32 | #define BIOS_HWIRQ8_VECTOR 0x70 33 | 34 | static inline void 35 | pic_eoi1(void) 36 | { 37 | if (!CONFIG_HARDWARE_IRQ) 38 | return; 39 | // Send eoi (select OCW2 + eoi) 40 | outb(0x20, PORT_PIC1_CMD); 41 | } 42 | 43 | static inline void 44 | pic_eoi2(void) 45 | { 46 | if (!CONFIG_HARDWARE_IRQ) 47 | return; 48 | // Send eoi (select OCW2 + eoi) 49 | outb(0x20, PORT_PIC2_CMD); 50 | pic_eoi1(); 51 | } 52 | 53 | u16 pic_irqmask_read(void); 54 | void pic_irqmask_write(u16 mask); 55 | void pic_irqmask_mask(u16 off, u16 on); 56 | void pic_reset(u8 irq0, u8 irq8); 57 | void pic_setup(void); 58 | void enable_hwirq(int hwirq, struct segoff_s func); 59 | 60 | #endif // pic.h 61 | -------------------------------------------------------------------------------- /src/hw/ps2port.h: -------------------------------------------------------------------------------- 1 | // Basic ps2 port (keyboard/mouse) command handling. 2 | #ifndef __PS2PORT_H 3 | #define __PS2PORT_H 4 | 5 | #include "types.h" // u8 6 | 7 | #define PORT_PS2_DATA 0x0060 8 | #define PORT_PS2_STATUS 0x0064 9 | 10 | // Standard commands. 11 | #define I8042_CMD_CTL_RCTR 0x0120 12 | #define I8042_CMD_CTL_WCTR 0x1060 13 | #define I8042_CMD_CTL_TEST 0x01aa 14 | 15 | #define I8042_CMD_KBD_TEST 0x01ab 16 | #define I8042_CMD_KBD_DISABLE 0x00ad 17 | #define I8042_CMD_KBD_ENABLE 0x00ae 18 | 19 | #define I8042_CMD_AUX_DISABLE 0x00a7 20 | #define I8042_CMD_AUX_ENABLE 0x00a8 21 | #define I8042_CMD_AUX_SEND 0x10d4 22 | 23 | // Keyboard commands 24 | #define ATKBD_CMD_SETLEDS 0x10ed 25 | #define ATKBD_CMD_SSCANSET 0x10f0 26 | #define ATKBD_CMD_GETID 0x02f2 27 | #define ATKBD_CMD_ENABLE 0x00f4 28 | #define ATKBD_CMD_RESET_DIS 0x00f5 29 | #define ATKBD_CMD_RESET_BAT 0x01ff 30 | 31 | // Mouse commands 32 | #define PSMOUSE_CMD_SETSCALE11 0x00e6 33 | #define PSMOUSE_CMD_SETSCALE21 0x00e7 34 | #define PSMOUSE_CMD_SETRES 0x10e8 35 | #define PSMOUSE_CMD_GETINFO 0x03e9 36 | #define PSMOUSE_CMD_GETID 0x02f2 37 | #define PSMOUSE_CMD_SETRATE 0x10f3 38 | #define PSMOUSE_CMD_ENABLE 0x00f4 39 | #define PSMOUSE_CMD_DISABLE 0x00f5 40 | #define PSMOUSE_CMD_RESET_BAT 0x02ff 41 | 42 | // Status register bits. 43 | #define I8042_STR_PARITY 0x80 44 | #define I8042_STR_TIMEOUT 0x40 45 | #define I8042_STR_AUXDATA 0x20 46 | #define I8042_STR_KEYLOCK 0x10 47 | #define I8042_STR_CMDDAT 0x08 48 | #define I8042_STR_MUXERR 0x04 49 | #define I8042_STR_IBF 0x02 50 | #define I8042_STR_OBF 0x01 51 | 52 | // Control register bits. 53 | #define I8042_CTR_KBDINT 0x01 54 | #define I8042_CTR_AUXINT 0x02 55 | #define I8042_CTR_IGNKEYLOCK 0x08 56 | #define I8042_CTR_KBDDIS 0x10 57 | #define I8042_CTR_AUXDIS 0x20 58 | #define I8042_CTR_XLATE 0x40 59 | 60 | // ps2port.c 61 | void i8042_reboot(void); 62 | int ps2_kbd_command(int command, u8 *param); 63 | int ps2_mouse_command(int command, u8 *param); 64 | void ps2_check_event(void); 65 | void ps2port_setup(void); 66 | 67 | #endif // ps2port.h 68 | -------------------------------------------------------------------------------- /src/hw/pvscsi.h: -------------------------------------------------------------------------------- 1 | #ifndef _PVSCSI_H_ 2 | #define _PVSCSI_H_ 3 | 4 | struct disk_op_s; 5 | int pvscsi_process_op(struct disk_op_s *op); 6 | void pvscsi_setup(void); 7 | 8 | #endif /* _PVSCSI_H_ */ 9 | -------------------------------------------------------------------------------- /src/hw/ramdisk.c: -------------------------------------------------------------------------------- 1 | // Code for emulating a drive via high-memory accesses. 2 | // 3 | // Copyright (C) 2009 Kevin O'Connor 4 | // 5 | // This file may be distributed under the terms of the GNU LGPLv3 license. 6 | 7 | #include "biosvar.h" // GET_GLOBALFLAT 8 | #include "block.h" // struct drive_s 9 | #include "bregs.h" // struct bregs 10 | #include "e820map.h" // e820_add 11 | #include "malloc.h" // memalign_tmphigh 12 | #include "memmap.h" // PAGE_SIZE 13 | #include "output.h" // dprintf 14 | #include "romfile.h" // romfile_findprefix 15 | #include "stacks.h" // call16_int 16 | #include "std/disk.h" // DISK_RET_SUCCESS 17 | #include "string.h" // memset 18 | #include "util.h" // process_ramdisk_op 19 | 20 | void 21 | ramdisk_setup(void) 22 | { 23 | if (!CONFIG_FLASH_FLOPPY) 24 | return; 25 | 26 | // Find image. 27 | struct romfile_s *file = romfile_findprefix("floppyimg/", NULL); 28 | if (!file) 29 | return; 30 | const char *filename = file->name; 31 | u32 size = file->size; 32 | dprintf(3, "Found floppy file %s of size %d\n", filename, size); 33 | int ftype = find_floppy_type(size); 34 | if (ftype < 0) { 35 | dprintf(3, "No floppy type found for ramdisk size\n"); 36 | return; 37 | } 38 | 39 | // Allocate ram for image. 40 | void *pos = memalign_tmphigh(PAGE_SIZE, size); 41 | if (!pos) { 42 | warn_noalloc(); 43 | return; 44 | } 45 | e820_add((u32)pos, size, E820_RESERVED); 46 | 47 | // Copy image into ram. 48 | int ret = file->copy(file, pos, size); 49 | if (ret < 0) 50 | return; 51 | 52 | // Setup driver. 53 | struct drive_s *drive = init_floppy((u32)pos, ftype); 54 | if (!drive) 55 | return; 56 | drive->type = DTYPE_RAMDISK; 57 | dprintf(1, "Mapping floppy %s to addr %p\n", filename, pos); 58 | char *desc = znprintf(MAXDESCSIZE, "Ramdisk [%s]", &filename[10]); 59 | boot_add_floppy(drive, desc, bootprio_find_named_rom(filename, 0)); 60 | } 61 | 62 | static int 63 | ramdisk_copy(struct disk_op_s *op, int iswrite) 64 | { 65 | u32 offset = GET_GLOBALFLAT(op->drive_fl->cntl_id); 66 | offset += (u32)op->lba * DISK_SECTOR_SIZE; 67 | u64 opd = GDT_DATA | GDT_LIMIT(0xfffff) | GDT_BASE((u32)op->buf_fl); 68 | u64 ramd = GDT_DATA | GDT_LIMIT(0xfffff) | GDT_BASE(offset); 69 | 70 | u64 gdt[6]; 71 | if (iswrite) { 72 | gdt[2] = opd; 73 | gdt[3] = ramd; 74 | } else { 75 | gdt[2] = ramd; 76 | gdt[3] = opd; 77 | } 78 | 79 | // Call int 1587 to copy data. 80 | struct bregs br; 81 | memset(&br, 0, sizeof(br)); 82 | br.flags = F_CF|F_IF; 83 | br.ah = 0x87; 84 | br.es = GET_SEG(SS); 85 | br.si = (u32)gdt; 86 | br.cx = op->count * DISK_SECTOR_SIZE / 2; 87 | call16_int(0x15, &br); 88 | 89 | if (br.flags & F_CF) 90 | return DISK_RET_EBADTRACK; 91 | return DISK_RET_SUCCESS; 92 | } 93 | 94 | int 95 | ramdisk_process_op(struct disk_op_s *op) 96 | { 97 | if (!CONFIG_FLASH_FLOPPY) 98 | return 0; 99 | 100 | switch (op->command) { 101 | case CMD_READ: 102 | return ramdisk_copy(op, 0); 103 | case CMD_WRITE: 104 | return ramdisk_copy(op, 1); 105 | default: 106 | return default_process_op(op); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/hw/rtc.c: -------------------------------------------------------------------------------- 1 | // Support for MC146818 Real Time Clock chip. 2 | // 3 | // Copyright (C) 2008-2013 Kevin O'Connor 4 | // Copyright (C) 2002 MandrakeSoft S.A. 5 | // 6 | // This file may be distributed under the terms of the GNU LGPLv3 license. 7 | 8 | #include "biosvar.h" // GET_LOW 9 | #include "rtc.h" // rtc_read 10 | #include "stacks.h" // yield 11 | #include "util.h" // timer_calc 12 | #include "x86.h" // inb 13 | 14 | u8 15 | rtc_read(u8 index) 16 | { 17 | index |= NMI_DISABLE_BIT; 18 | outb(index, PORT_CMOS_INDEX); 19 | return inb(PORT_CMOS_DATA); 20 | } 21 | 22 | void 23 | rtc_write(u8 index, u8 val) 24 | { 25 | index |= NMI_DISABLE_BIT; 26 | outb(index, PORT_CMOS_INDEX); 27 | outb(val, PORT_CMOS_DATA); 28 | } 29 | 30 | void 31 | rtc_mask(u8 index, u8 off, u8 on) 32 | { 33 | index |= NMI_DISABLE_BIT; 34 | outb(index, PORT_CMOS_INDEX); 35 | u8 val = inb(PORT_CMOS_DATA); 36 | outb((val & ~off) | on, PORT_CMOS_DATA); 37 | } 38 | 39 | int 40 | rtc_updating(void) 41 | { 42 | // This function checks to see if the update-in-progress bit 43 | // is set in CMOS Status Register A. If not, it returns 0. 44 | // If it is set, it tries to wait until there is a transition 45 | // to 0, and will return 0 if such a transition occurs. A -1 46 | // is returned only after timing out. The maximum period 47 | // that this bit should be set is constrained to (1984+244) 48 | // useconds, but we wait for longer just to be sure. 49 | 50 | if ((rtc_read(CMOS_STATUS_A) & RTC_A_UIP) == 0) 51 | return 0; 52 | u32 end = timer_calc(15); 53 | for (;;) { 54 | if ((rtc_read(CMOS_STATUS_A) & RTC_A_UIP) == 0) 55 | return 0; 56 | if (timer_check(end)) 57 | // update-in-progress never transitioned to 0 58 | return -1; 59 | yield(); 60 | } 61 | } 62 | 63 | void 64 | rtc_setup(void) 65 | { 66 | if (!CONFIG_RTC_TIMER) 67 | return; 68 | rtc_write(CMOS_STATUS_A, 0x26); // 32,768Khz src, 976.5625us updates 69 | rtc_mask(CMOS_STATUS_B, ~RTC_B_DSE, RTC_B_24HR); 70 | rtc_read(CMOS_STATUS_C); 71 | rtc_read(CMOS_STATUS_D); 72 | } 73 | 74 | int RTCusers VARLOW; 75 | 76 | void 77 | rtc_use(void) 78 | { 79 | if (!CONFIG_RTC_TIMER) 80 | return; 81 | int count = GET_LOW(RTCusers); 82 | SET_LOW(RTCusers, count+1); 83 | if (count) 84 | return; 85 | // Turn on the Periodic Interrupt timer 86 | rtc_mask(CMOS_STATUS_B, 0, RTC_B_PIE); 87 | } 88 | 89 | void 90 | rtc_release(void) 91 | { 92 | if (!CONFIG_RTC_TIMER) 93 | return; 94 | int count = GET_LOW(RTCusers); 95 | SET_LOW(RTCusers, count-1); 96 | if (count != 1) 97 | return; 98 | // Clear the Periodic Interrupt. 99 | rtc_mask(CMOS_STATUS_B, RTC_B_PIE, 0); 100 | } 101 | -------------------------------------------------------------------------------- /src/hw/rtc.h: -------------------------------------------------------------------------------- 1 | #ifndef __RTC_H 2 | #define __RTC_H 3 | 4 | #define PORT_CMOS_INDEX 0x0070 5 | #define PORT_CMOS_DATA 0x0071 6 | 7 | // PORT_CMOS_INDEX nmi disable bit 8 | #define NMI_DISABLE_BIT 0x80 9 | 10 | // Standard BIOS RTC chip entries 11 | #define CMOS_RTC_SECONDS 0x00 12 | #define CMOS_RTC_SECONDS_ALARM 0x01 13 | #define CMOS_RTC_MINUTES 0x02 14 | #define CMOS_RTC_MINUTES_ALARM 0x03 15 | #define CMOS_RTC_HOURS 0x04 16 | #define CMOS_RTC_HOURS_ALARM 0x05 17 | #define CMOS_RTC_DAY_WEEK 0x06 18 | #define CMOS_RTC_DAY_MONTH 0x07 19 | #define CMOS_RTC_MONTH 0x08 20 | #define CMOS_RTC_YEAR 0x09 21 | #define CMOS_STATUS_A 0x0a 22 | #define CMOS_STATUS_B 0x0b 23 | #define CMOS_STATUS_C 0x0c 24 | #define CMOS_STATUS_D 0x0d 25 | #define CMOS_RESET_CODE 0x0f 26 | 27 | // QEMU cmos config fields. DO NOT ADD MORE. (All new content should 28 | // be passed via the fw_cfg "file" interface.) 29 | #define CMOS_FLOPPY_DRIVE_TYPE 0x10 30 | #define CMOS_DISK_DATA 0x12 31 | #define CMOS_EQUIPMENT_INFO 0x14 32 | #define CMOS_DISK_DRIVE1_TYPE 0x19 33 | #define CMOS_DISK_DRIVE2_TYPE 0x1a 34 | #define CMOS_DISK_DRIVE1_CYL 0x1b 35 | #define CMOS_DISK_DRIVE2_CYL 0x24 36 | #define CMOS_MEM_EXTMEM_LOW 0x30 37 | #define CMOS_MEM_EXTMEM_HIGH 0x31 38 | #define CMOS_CENTURY 0x32 39 | #define CMOS_MEM_EXTMEM2_LOW 0x34 40 | #define CMOS_MEM_EXTMEM2_HIGH 0x35 41 | #define CMOS_BIOS_BOOTFLAG1 0x38 42 | #define CMOS_BIOS_DISKTRANSFLAG 0x39 43 | #define CMOS_BIOS_BOOTFLAG2 0x3d 44 | #define CMOS_MEM_HIGHMEM_LOW 0x5b 45 | #define CMOS_MEM_HIGHMEM_MID 0x5c 46 | #define CMOS_MEM_HIGHMEM_HIGH 0x5d 47 | #define CMOS_BIOS_SMP_COUNT 0x5f 48 | 49 | // RTC register flags 50 | #define RTC_A_UIP 0x80 51 | 52 | #define RTC_B_SET 0x80 53 | #define RTC_B_PIE 0x40 54 | #define RTC_B_AIE 0x20 55 | #define RTC_B_UIE 0x10 56 | #define RTC_B_BIN 0x04 57 | #define RTC_B_24HR 0x02 58 | #define RTC_B_DSE 0x01 59 | 60 | #ifndef __ASSEMBLY__ 61 | 62 | #include "types.h" // u8 63 | 64 | // rtc.c 65 | u8 rtc_read(u8 index); 66 | void rtc_write(u8 index, u8 val); 67 | void rtc_mask(u8 index, u8 off, u8 on); 68 | int rtc_updating(void); 69 | void rtc_setup(void); 70 | void rtc_use(void); 71 | void rtc_release(void); 72 | 73 | #endif // !__ASSEMBLY__ 74 | 75 | #endif // rtc.h 76 | -------------------------------------------------------------------------------- /src/hw/serialio.c: -------------------------------------------------------------------------------- 1 | // Low-level serial (and serial-like) device access. 2 | // 3 | // Copyright (C) 2008-1013 Kevin O'Connor 4 | // 5 | // This file may be distributed under the terms of the GNU LGPLv3 license. 6 | 7 | #include "config.h" // CONFIG_DEBUG_SERIAL 8 | #include "fw/paravirt.h" // RunningOnQEMU 9 | #include "output.h" // dprintf 10 | #include "serialio.h" // serial_debug_preinit 11 | #include "x86.h" // outb 12 | 13 | 14 | /**************************************************************** 15 | * Serial port debug output 16 | ****************************************************************/ 17 | 18 | #define DEBUG_TIMEOUT 100000 19 | 20 | // Write to a serial port register 21 | static void 22 | serial_debug_write(u8 offset, u8 val) 23 | { 24 | if (CONFIG_DEBUG_SERIAL) { 25 | outb(val, CONFIG_DEBUG_SERIAL_PORT + offset); 26 | } else if (CONFIG_DEBUG_SERIAL_MMIO) { 27 | ASSERT32FLAT(); 28 | writeb((void*)CONFIG_DEBUG_SERIAL_MEM_ADDRESS + 4*offset, val); 29 | } 30 | } 31 | 32 | // Read from a serial port register 33 | static u8 34 | serial_debug_read(u8 offset) 35 | { 36 | if (CONFIG_DEBUG_SERIAL) 37 | return inb(CONFIG_DEBUG_SERIAL_PORT + offset); 38 | if (CONFIG_DEBUG_SERIAL_MMIO) { 39 | ASSERT32FLAT(); 40 | return readb((void*)CONFIG_DEBUG_SERIAL_MEM_ADDRESS + 4*offset); 41 | } 42 | } 43 | 44 | // Setup the debug serial port for output. 45 | void 46 | serial_debug_preinit(void) 47 | { 48 | if (!CONFIG_DEBUG_SERIAL && (!CONFIG_DEBUG_SERIAL_MMIO || MODESEGMENT)) 49 | return; 50 | // setup for serial logging: 8N1 51 | u8 oldparam, newparam = 0x03; 52 | oldparam = serial_debug_read(SEROFF_LCR); 53 | serial_debug_write(SEROFF_LCR, newparam); 54 | // Disable irqs 55 | u8 oldier, newier = 0; 56 | oldier = serial_debug_read(SEROFF_IER); 57 | serial_debug_write(SEROFF_IER, newier); 58 | 59 | if (oldparam != newparam || oldier != newier) 60 | dprintf(1, "Changing serial settings was %x/%x now %x/%x\n" 61 | , oldparam, oldier, newparam, newier); 62 | } 63 | 64 | // Write a character to the serial port. 65 | static void 66 | serial_debug(char c) 67 | { 68 | if (!CONFIG_DEBUG_SERIAL && (!CONFIG_DEBUG_SERIAL_MMIO || MODESEGMENT)) 69 | return; 70 | int timeout = DEBUG_TIMEOUT; 71 | while ((serial_debug_read(SEROFF_LSR) & 0x20) != 0x20) 72 | if (!timeout--) 73 | // Ran out of time. 74 | return; 75 | serial_debug_write(SEROFF_DATA, c); 76 | } 77 | 78 | void 79 | serial_debug_putc(char c) 80 | { 81 | if (c == '\n') 82 | serial_debug('\r'); 83 | serial_debug(c); 84 | } 85 | 86 | // Make sure all serial port writes have been completely sent. 87 | void 88 | serial_debug_flush(void) 89 | { 90 | if (!CONFIG_DEBUG_SERIAL && (!CONFIG_DEBUG_SERIAL_MMIO || MODESEGMENT)) 91 | return; 92 | int timeout = DEBUG_TIMEOUT; 93 | while ((serial_debug_read(SEROFF_LSR) & 0x60) != 0x60) 94 | if (!timeout--) 95 | // Ran out of time. 96 | return; 97 | } 98 | 99 | 100 | /**************************************************************** 101 | * QEMU debug port 102 | ****************************************************************/ 103 | 104 | u16 DebugOutputPort VARFSEG = 0x402; 105 | 106 | void 107 | qemu_debug_preinit(void) 108 | { 109 | /* Xen doesn't support checking if debug output is active. */ 110 | if (runningOnXen()) 111 | return; 112 | 113 | /* Check if the QEMU debug output port is active */ 114 | if (CONFIG_DEBUG_IO && 115 | inb(GET_GLOBAL(DebugOutputPort)) != QEMU_DEBUGCON_READBACK) 116 | DebugOutputPort = 0; 117 | } 118 | 119 | // Write a character to the special debugging port. 120 | void 121 | qemu_debug_putc(char c) 122 | { 123 | if (!CONFIG_DEBUG_IO || !runningOnQEMU()) 124 | return; 125 | u16 port = GET_GLOBAL(DebugOutputPort); 126 | if (port) 127 | // Send character to debug port. 128 | outb(c, port); 129 | } 130 | -------------------------------------------------------------------------------- /src/hw/serialio.h: -------------------------------------------------------------------------------- 1 | #ifndef __SERIALIO_H 2 | #define __SERIALIO_H 3 | 4 | #include "types.h" // u16 5 | 6 | #define PORT_LPT2 0x0278 7 | #define PORT_SERIAL4 0x02e8 8 | #define PORT_SERIAL2 0x02f8 9 | #define PORT_LPT1 0x0378 10 | #define PORT_SERIAL3 0x03e8 11 | #define PORT_SERIAL1 0x03f8 12 | 13 | // Serial port offsets 14 | #define SEROFF_DATA 0 15 | #define SEROFF_DLL 0 16 | #define SEROFF_IER 1 17 | #define SEROFF_DLH 1 18 | #define SEROFF_IIR 2 19 | #define SEROFF_LCR 3 20 | #define SEROFF_LSR 5 21 | #define SEROFF_MSR 6 22 | 23 | void serial_debug_preinit(void); 24 | void serial_debug_putc(char c); 25 | void serial_debug_flush(void); 26 | extern u16 DebugOutputPort; 27 | void qemu_debug_preinit(void); 28 | void qemu_debug_putc(char c); 29 | 30 | #endif // serialio.h 31 | -------------------------------------------------------------------------------- /src/hw/usb-hid.h: -------------------------------------------------------------------------------- 1 | #ifndef __USB_HID_H 2 | #define __USB_HID_H 3 | 4 | // usb-hid.c 5 | struct usbdevice_s; 6 | int usb_hid_setup(struct usbdevice_s *usbdev); 7 | int usb_kbd_active(void); 8 | int usb_kbd_command(int command, u8 *param); 9 | int usb_mouse_active(void); 10 | int usb_mouse_command(int command, u8 *param); 11 | void usb_check_event(void); 12 | 13 | 14 | /**************************************************************** 15 | * hid flags 16 | ****************************************************************/ 17 | 18 | #define USB_INTERFACE_SUBCLASS_BOOT 1 19 | #define USB_INTERFACE_PROTOCOL_KEYBOARD 1 20 | #define USB_INTERFACE_PROTOCOL_MOUSE 2 21 | 22 | #define HID_REQ_GET_REPORT 0x01 23 | #define HID_REQ_GET_IDLE 0x02 24 | #define HID_REQ_GET_PROTOCOL 0x03 25 | #define HID_REQ_SET_REPORT 0x09 26 | #define HID_REQ_SET_IDLE 0x0A 27 | #define HID_REQ_SET_PROTOCOL 0x0B 28 | 29 | #endif // ush-hid.h 30 | -------------------------------------------------------------------------------- /src/hw/usb-hub.h: -------------------------------------------------------------------------------- 1 | #ifndef __USB_HUB_H 2 | #define __USB_HUB_H 3 | 4 | // usb-hub.c 5 | struct usbdevice_s; 6 | int usb_hub_setup(struct usbdevice_s *usbdev); 7 | 8 | 9 | /**************************************************************** 10 | * hub flags 11 | ****************************************************************/ 12 | 13 | #define USB_DT_HUB (USB_TYPE_CLASS | 0x09) 14 | #define USB_DT_HUB3 (USB_TYPE_CLASS | 0x0a) 15 | 16 | #define HUB_REQ_SET_HUB_DEPTH 0x0C 17 | 18 | struct usb_hub_descriptor { 19 | u8 bDescLength; 20 | u8 bDescriptorType; 21 | u8 bNbrPorts; 22 | u16 wHubCharacteristics; 23 | u8 bPwrOn2PwrGood; 24 | u8 bHubContrCurrent; 25 | // Variable length fields for DeviceRemovable[], PortPwrCtrlMask[] follow. 26 | } PACKED; 27 | 28 | #define USB_PORT_FEAT_CONNECTION 0 29 | #define USB_PORT_FEAT_ENABLE 1 30 | #define USB_PORT_FEAT_SUSPEND 2 31 | #define USB_PORT_FEAT_OVER_CURRENT 3 32 | #define USB_PORT_FEAT_RESET 4 33 | #define USB_PORT_FEAT_POWER 8 34 | #define USB_PORT_FEAT_LOWSPEED 9 35 | #define USB_PORT_FEAT_C_CONNECTION 16 36 | #define USB_PORT_FEAT_C_ENABLE 17 37 | #define USB_PORT_FEAT_C_SUSPEND 18 38 | #define USB_PORT_FEAT_C_OVER_CURRENT 19 39 | #define USB_PORT_FEAT_C_RESET 20 40 | #define USB_PORT_FEAT_TEST 21 41 | #define USB_PORT_FEAT_INDICATOR 22 42 | #define USB_PORT_FEAT_C_PORT_L1 23 43 | 44 | struct usb_port_status { 45 | u16 wPortStatus; 46 | u16 wPortChange; 47 | } PACKED; 48 | 49 | #define USB_PORT_STAT_CONNECTION 0x0001 50 | #define USB_PORT_STAT_ENABLE 0x0002 51 | #define USB_PORT_STAT_SUSPEND 0x0004 52 | #define USB_PORT_STAT_OVERCURRENT 0x0008 53 | #define USB_PORT_STAT_RESET 0x0010 54 | #define USB_PORT_STAT_LINK_SHIFT 5 55 | #define USB_PORT_STAT_LINK_MASK (0x7 << USB_PORT_STAT_LINK_SHIFT) 56 | #define USB_PORT_STAT_POWER 0x0100 57 | #define USB_PORT_STAT_SPEED_SHIFT 9 58 | #define USB_PORT_STAT_SPEED_MASK (0x3 << USB_PORT_STAT_SPEED_SHIFT) 59 | #define USB_PORT_STAT_LOW_SPEED 0x0200 60 | #define USB_PORT_STAT_HIGH_SPEED 0x0400 61 | #define USB_PORT_STAT_TEST 0x0800 62 | #define USB_PORT_STAT_INDICATOR 0x1000 63 | 64 | #endif // ush-hid.h 65 | -------------------------------------------------------------------------------- /src/hw/usb-msc.h: -------------------------------------------------------------------------------- 1 | #ifndef __USB_MSC_H 2 | #define __USB_MSC_H 3 | 4 | // usb-msc.c 5 | struct disk_op_s; 6 | int usb_process_op(struct disk_op_s *op); 7 | struct usbdevice_s; 8 | int usb_msc_setup(struct usbdevice_s *usbdev); 9 | 10 | #endif // ush-msc.h 11 | -------------------------------------------------------------------------------- /src/hw/usb-ohci.h: -------------------------------------------------------------------------------- 1 | #ifndef __USB_OHCI_H 2 | #define __USB_OHCI_H 3 | 4 | // usb-ohci.c 5 | void ohci_setup(void); 6 | struct usbdevice_s; 7 | struct usb_endpoint_descriptor; 8 | struct usb_pipe; 9 | struct usb_pipe *ohci_realloc_pipe(struct usbdevice_s *usbdev 10 | , struct usb_pipe *upipe 11 | , struct usb_endpoint_descriptor *epdesc); 12 | int ohci_send_pipe(struct usb_pipe *p, int dir, const void *cmd 13 | , void *data, int datasize); 14 | int ohci_poll_intr(struct usb_pipe *p, void *data); 15 | 16 | 17 | /**************************************************************** 18 | * ohci structs and flags 19 | ****************************************************************/ 20 | 21 | struct ohci_ed { 22 | u32 hwINFO; 23 | u32 hwTailP; 24 | u32 hwHeadP; 25 | u32 hwNextED; 26 | } PACKED; 27 | 28 | #define ED_ISO (1 << 15) 29 | #define ED_SKIP (1 << 14) 30 | #define ED_LOWSPEED (1 << 13) 31 | #define ED_OUT (0x01 << 11) 32 | #define ED_IN (0x02 << 11) 33 | 34 | #define ED_C (0x02) 35 | #define ED_H (0x01) 36 | 37 | struct ohci_td { 38 | u32 hwINFO; 39 | u32 hwCBP; 40 | u32 hwNextTD; 41 | u32 hwBE; 42 | } PACKED; 43 | 44 | #define TD_CC 0xf0000000 45 | #define TD_CC_GET(td_p) ((td_p >>28) & 0x0f) 46 | #define TD_DI 0x00E00000 47 | 48 | #define TD_DONE 0x00020000 49 | #define TD_ISO 0x00010000 50 | 51 | #define TD_EC 0x0C000000 52 | #define TD_T 0x03000000 53 | #define TD_T_DATA0 0x02000000 54 | #define TD_T_DATA1 0x03000000 55 | #define TD_T_TOGGLE 0x00000000 56 | #define TD_DP 0x00180000 57 | #define TD_DP_SETUP 0x00000000 58 | #define TD_DP_IN 0x00100000 59 | #define TD_DP_OUT 0x00080000 60 | 61 | #define TD_R 0x00040000 62 | 63 | struct ohci_hcca { 64 | u32 int_table[32]; 65 | u32 frame_no; 66 | u32 done_head; 67 | u8 reserved[120]; 68 | } PACKED; 69 | 70 | struct ohci_regs { 71 | u32 revision; 72 | u32 control; 73 | u32 cmdstatus; 74 | u32 intrstatus; 75 | u32 intrenable; 76 | u32 intrdisable; 77 | 78 | u32 hcca; 79 | u32 ed_periodcurrent; 80 | u32 ed_controlhead; 81 | u32 ed_controlcurrent; 82 | u32 ed_bulkhead; 83 | u32 ed_bulkcurrent; 84 | u32 donehead; 85 | 86 | u32 fminterval; 87 | u32 fmremaining; 88 | u32 fmnumber; 89 | u32 periodicstart; 90 | u32 lsthresh; 91 | 92 | u32 roothub_a; 93 | u32 roothub_b; 94 | u32 roothub_status; 95 | u32 roothub_portstatus[15]; 96 | } PACKED; 97 | 98 | #define OHCI_CTRL_CBSR (3 << 0) 99 | #define OHCI_CTRL_PLE (1 << 2) 100 | #define OHCI_CTRL_CLE (1 << 4) 101 | #define OHCI_CTRL_BLE (1 << 5) 102 | #define OHCI_CTRL_HCFS (3 << 6) 103 | # define OHCI_USB_RESET (0 << 6) 104 | # define OHCI_USB_OPER (2 << 6) 105 | #define OHCI_CTRL_RWC (1 << 9) 106 | 107 | #define OHCI_HCR (1 << 0) 108 | #define OHCI_CLF (1 << 1) 109 | #define OHCI_BLF (1 << 2) 110 | 111 | #define OHCI_INTR_MIE (1 << 31) 112 | 113 | #define RH_PS_CCS 0x00000001 114 | #define RH_PS_PES 0x00000002 115 | #define RH_PS_PSS 0x00000004 116 | #define RH_PS_POCI 0x00000008 117 | #define RH_PS_PRS 0x00000010 118 | #define RH_PS_PPS 0x00000100 119 | #define RH_PS_LSDA 0x00000200 120 | #define RH_PS_CSC 0x00010000 121 | #define RH_PS_PESC 0x00020000 122 | #define RH_PS_PSSC 0x00040000 123 | #define RH_PS_OCIC 0x00080000 124 | #define RH_PS_PRSC 0x00100000 125 | 126 | #define RH_HS_LPS 0x00000001 127 | #define RH_HS_OCI 0x00000002 128 | #define RH_HS_DRWE 0x00008000 129 | #define RH_HS_LPSC 0x00010000 130 | #define RH_HS_OCIC 0x00020000 131 | #define RH_HS_CRWE 0x80000000 132 | 133 | #define RH_B_DR 0x0000ffff 134 | #define RH_B_PPCM 0xffff0000 135 | 136 | #define RH_A_NDP (0xff << 0) 137 | #define RH_A_PSM (1 << 8) 138 | #define RH_A_NPS (1 << 9) 139 | #define RH_A_DT (1 << 10) 140 | #define RH_A_OCPM (1 << 11) 141 | #define RH_A_NOCP (1 << 12) 142 | #define RH_A_POTPGT (0xff << 24) 143 | 144 | #endif // usb-ohci.h 145 | -------------------------------------------------------------------------------- /src/hw/usb-uas.h: -------------------------------------------------------------------------------- 1 | #ifndef __USB_UAS_H 2 | #define __USB_UAS_H 3 | 4 | struct disk_op_s; 5 | int uas_process_op(struct disk_op_s *op); 6 | struct usbdevice_s; 7 | int usb_uas_setup(struct usbdevice_s *usbdev); 8 | 9 | #endif /* __USB_UAS_H */ 10 | -------------------------------------------------------------------------------- /src/hw/usb-xhci.h: -------------------------------------------------------------------------------- 1 | #ifndef __USB_XHCI_H 2 | #define __USB_XHCI_H 3 | 4 | struct usbdevice_s; 5 | struct usb_endpoint_descriptor; 6 | struct usb_pipe; 7 | 8 | // -------------------------------------------------------------- 9 | 10 | // usb-xhci.c 11 | void xhci_setup(void); 12 | struct usb_pipe *xhci_realloc_pipe(struct usbdevice_s *usbdev 13 | , struct usb_pipe *upipe 14 | , struct usb_endpoint_descriptor *epdesc); 15 | int xhci_send_pipe(struct usb_pipe *p, int dir, const void *cmd 16 | , void *data, int datasize); 17 | int xhci_poll_intr(struct usb_pipe *p, void *data); 18 | 19 | // -------------------------------------------------------------- 20 | // register interface 21 | 22 | // capabilities 23 | struct xhci_caps { 24 | u8 caplength; 25 | u8 reserved_01; 26 | u16 hciversion; 27 | u32 hcsparams1; 28 | u32 hcsparams2; 29 | u32 hcsparams3; 30 | u32 hccparams; 31 | u32 dboff; 32 | u32 rtsoff; 33 | } PACKED; 34 | 35 | // extended capabilities 36 | struct xhci_xcap { 37 | u32 cap; 38 | u32 data[]; 39 | } PACKED; 40 | 41 | // operational registers 42 | struct xhci_op { 43 | u32 usbcmd; 44 | u32 usbsts; 45 | u32 pagesize; 46 | u32 reserved_01[2]; 47 | u32 dnctl; 48 | u32 crcr_low; 49 | u32 crcr_high; 50 | u32 reserved_02[4]; 51 | u32 dcbaap_low; 52 | u32 dcbaap_high; 53 | u32 config; 54 | } PACKED; 55 | 56 | // port registers 57 | struct xhci_pr { 58 | u32 portsc; 59 | u32 portpmsc; 60 | u32 portli; 61 | u32 reserved_01; 62 | } PACKED; 63 | 64 | // doorbell registers 65 | struct xhci_db { 66 | u32 doorbell; 67 | } PACKED; 68 | 69 | // runtime registers 70 | struct xhci_rts { 71 | u32 mfindex; 72 | } PACKED; 73 | 74 | // interrupter registers 75 | struct xhci_ir { 76 | u32 iman; 77 | u32 imod; 78 | u32 erstsz; 79 | u32 reserved_01; 80 | u32 erstba_low; 81 | u32 erstba_high; 82 | u32 erdp_low; 83 | u32 erdp_high; 84 | } PACKED; 85 | 86 | // -------------------------------------------------------------- 87 | // memory data structs 88 | 89 | // slot context 90 | struct xhci_slotctx { 91 | u32 ctx[4]; 92 | u32 reserved_01[4]; 93 | } PACKED; 94 | 95 | // endpoint context 96 | struct xhci_epctx { 97 | u32 ctx[2]; 98 | u32 deq_low; 99 | u32 deq_high; 100 | u32 length; 101 | u32 reserved_01[3]; 102 | } PACKED; 103 | 104 | // device context array element 105 | struct xhci_devlist { 106 | u32 ptr_low; 107 | u32 ptr_high; 108 | } PACKED; 109 | 110 | // input context 111 | struct xhci_inctx { 112 | u32 del; 113 | u32 add; 114 | u32 reserved_01[6]; 115 | } PACKED; 116 | 117 | // transfer block (ring element) 118 | struct xhci_trb { 119 | u32 ptr_low; 120 | u32 ptr_high; 121 | u32 status; 122 | u32 control; 123 | } PACKED; 124 | 125 | // event ring segment 126 | struct xhci_er_seg { 127 | u32 ptr_low; 128 | u32 ptr_high; 129 | u32 size; 130 | u32 reserved_01; 131 | } PACKED; 132 | 133 | #endif // usb-xhci.h 134 | -------------------------------------------------------------------------------- /src/hw/virtio-blk.h: -------------------------------------------------------------------------------- 1 | #ifndef _VIRTIO_BLK_H 2 | #define _VIRTIO_BLK_H 3 | 4 | struct virtio_blk_config 5 | { 6 | u64 capacity; 7 | u32 size_max; 8 | u32 seg_max; 9 | u16 cylinders; 10 | u8 heads; 11 | u8 sectors; 12 | u32 blk_size; 13 | u8 physical_block_exp; 14 | u8 alignment_offset; 15 | u16 min_io_size; 16 | u32 opt_io_size; 17 | } __attribute__((packed)); 18 | 19 | /* Feature bits */ 20 | #define VIRTIO_BLK_F_SIZE_MAX 1 /* Maximum size of any single segment */ 21 | #define VIRTIO_BLK_F_SEG_MAX 2 /* Maximum number of segments in a request */ 22 | #define VIRTIO_BLK_F_BLK_SIZE 6 23 | 24 | /* These two define direction. */ 25 | #define VIRTIO_BLK_T_IN 0 26 | #define VIRTIO_BLK_T_OUT 1 27 | 28 | /* This is the first element of the read scatter-gather list. */ 29 | struct virtio_blk_outhdr { 30 | /* VIRTIO_BLK_T* */ 31 | u32 type; 32 | /* io priority. */ 33 | u32 ioprio; 34 | /* Sector (ie. 512 byte offset) */ 35 | u64 sector; 36 | }; 37 | 38 | #define VIRTIO_BLK_S_OK 0 39 | #define VIRTIO_BLK_S_IOERR 1 40 | #define VIRTIO_BLK_S_UNSUPP 2 41 | 42 | struct disk_op_s; 43 | int virtio_blk_process_op(struct disk_op_s *op); 44 | void virtio_blk_setup(void); 45 | void init_virtio_blk_mmio(void *mmio); 46 | 47 | #endif /* _VIRTIO_BLK_H */ 48 | -------------------------------------------------------------------------------- /src/hw/virtio-mmio.c: -------------------------------------------------------------------------------- 1 | #include "config.h" // CONFIG_DEBUG_LEVEL 2 | #include "malloc.h" // free 3 | #include "output.h" // dprintf 4 | #include "stacks.h" // run_thread 5 | #include "string.h" // memset 6 | #include "util.h" // acpi_dsdt_* 7 | #include "virtio-pci.h" 8 | #include "virtio-blk.h" 9 | #include "virtio-scsi.h" 10 | #include "virtio-ring.h" 11 | #include "virtio-mmio.h" 12 | 13 | void virtio_mmio_setup_acpi(void) 14 | { 15 | static const char *virtio_hid = "LNRO0005"; 16 | struct acpi_device *dev; 17 | u64 mem, irq, unused; 18 | 19 | for (dev = acpi_dsdt_find_string(NULL, virtio_hid); 20 | dev != NULL; 21 | dev = acpi_dsdt_find_string(dev, virtio_hid)) { 22 | if (acpi_dsdt_find_mem(dev, &mem, &unused) < 0) 23 | continue; 24 | if (acpi_dsdt_find_irq(dev, &irq) < 0) 25 | continue; 26 | dprintf(1, "ACPI: virtio-mmio device %s at 0x%llx, irq %lld\n", 27 | acpi_dsdt_name(dev), mem, irq); 28 | virtio_mmio_setup_one(mem); 29 | } 30 | } 31 | 32 | void virtio_mmio_setup_one(u64 addr) 33 | { 34 | static const char *names[] = { 35 | [ 1 ] = "net", 36 | [ 2 ] = "blk", 37 | [ 3 ] = "console", 38 | [ 4 ] = "rng", 39 | [ 8 ] = "scsi", 40 | [ 9 ] = "9p", 41 | [ 16 ] = "gpu", 42 | [ 19 ] = "vsock", 43 | [ 18 ] = "input", 44 | [ 26 ] = "fs", 45 | }; 46 | const char *name; 47 | u32 magic, version, devid; 48 | void *mmio; 49 | 50 | if (addr >= 0x100000000) { 51 | dprintf(1, "virtio-mmio: %llx: above 4G\n", addr); 52 | return; 53 | } 54 | 55 | mmio = (void*)(u32)(addr); 56 | magic = readl(mmio); 57 | if (magic != 0x74726976) { 58 | dprintf(1, "virtio-mmio: %llx: magic mismatch\n", addr); 59 | return; 60 | } 61 | version = readl(mmio+4); 62 | if (version != 1 /* legacy */ && 63 | version != 2 /* 1.0 */) { 64 | dprintf(1, "virtio-mmio: %llx: unknown version %d\n", addr, version); 65 | return; 66 | } 67 | devid = readl(mmio+8); 68 | 69 | name = (devid < ARRAY_SIZE(names) && names[devid] != NULL) 70 | ? names[devid] : "unknown"; 71 | dprintf(1, "virtio-mmio: %llx: device id %x (%s%s)\n", 72 | addr, devid, name, version == 1 ? ", legacy" : ""); 73 | 74 | switch (devid) { 75 | case 2: /* blk */ 76 | run_thread(init_virtio_blk_mmio, mmio); 77 | break; 78 | case 8: /* scsi */ 79 | run_thread(init_virtio_scsi_mmio, mmio); 80 | break; 81 | default: 82 | break; 83 | } 84 | } 85 | 86 | void vp_init_mmio(struct vp_device *vp, void *mmio) 87 | { 88 | memset(vp, 0, sizeof(*vp)); 89 | vp->use_mmio = 1; 90 | vp->common.mode = VP_ACCESS_MMIO; 91 | vp->common.memaddr = mmio; 92 | vp->device.mode = VP_ACCESS_MMIO; 93 | vp->device.memaddr = mmio + 0x100; 94 | vp_reset(vp); 95 | vp_set_status(vp, VIRTIO_CONFIG_S_ACKNOWLEDGE | 96 | VIRTIO_CONFIG_S_DRIVER); 97 | } 98 | -------------------------------------------------------------------------------- /src/hw/virtio-mmio.h: -------------------------------------------------------------------------------- 1 | #ifndef _VIRTIO_MMIO_H 2 | #define _VIRTIO_MMIO_H 3 | 4 | struct vp_device; 5 | 6 | typedef struct virtio_mmio_cfg { 7 | u32 magic; 8 | u32 version; 9 | u32 device_id; 10 | u32 vendor_id; 11 | 12 | u32 device_feature; 13 | u32 device_feature_select; 14 | u32 res_18; 15 | u32 res_1c; 16 | 17 | u32 guest_feature; 18 | u32 guest_feature_select; 19 | u32 legacy_guest_page_size; 20 | u32 res_2c; 21 | 22 | u32 queue_select; 23 | u32 queue_num_max; 24 | u32 queue_num; 25 | u32 legacy_queue_align; 26 | 27 | u32 legacy_queue_pfn; 28 | u32 queue_ready; 29 | u32 res_48; 30 | u32 res_4c; 31 | 32 | u32 queue_notify; 33 | u32 res_54; 34 | u32 res_58; 35 | u32 res_5c; 36 | 37 | u32 irq_status; 38 | u32 irq_ack; 39 | u32 res_68; 40 | u32 res_6c; 41 | 42 | u32 device_status; 43 | u32 res_74; 44 | u32 res_78; 45 | u32 res_7c; 46 | 47 | u32 queue_desc_lo; 48 | u32 queue_desc_hi; 49 | u32 res_88; 50 | u32 res_8c; 51 | 52 | u32 queue_driver_lo; 53 | u32 queue_driver_hi; 54 | u32 res_98; 55 | u32 res_9c; 56 | 57 | u32 queue_device_lo; 58 | u32 queue_device_hi; 59 | u32 res_a8; 60 | u32 shm_sel; 61 | 62 | u32 shmem_len_lo; 63 | u32 shmem_len_hi; 64 | u32 shmem_base_lo; 65 | u32 shmem_base_hi; 66 | 67 | u32 res_c0_f7[14]; 68 | 69 | u32 res_f8; 70 | u32 config_generation; 71 | } virtio_mmio_cfg; 72 | 73 | void virtio_mmio_setup_acpi(void); 74 | void virtio_mmio_setup_one(u64 mmio); 75 | void vp_init_mmio(struct vp_device *vp, void *mmio); 76 | 77 | #endif /* _VIRTIO_MMIO_H */ 78 | -------------------------------------------------------------------------------- /src/hw/virtio-ring.c: -------------------------------------------------------------------------------- 1 | /* virtio-pci.c - virtio ring management 2 | * 3 | * (c) Copyright 2008 Bull S.A.S. 4 | * 5 | * Author: Laurent Vivier 6 | * 7 | * some parts from Linux Virtio Ring 8 | * 9 | * Copyright Rusty Russell IBM Corporation 2007 10 | * 11 | * Adopted for Seabios: Gleb Natapov 12 | * 13 | * This work is licensed under the terms of the GNU LGPLv3 14 | * See the COPYING file in the top-level directory. 15 | * 16 | * 17 | */ 18 | 19 | #include "output.h" // panic 20 | #include "virtio-ring.h" 21 | #include "virtio-pci.h" 22 | 23 | #define BUG() do { \ 24 | panic("BUG: failure at %d/%s()!\n", __LINE__, __func__); \ 25 | } while (0) 26 | #define BUG_ON(condition) do { if (condition) BUG(); } while (0) 27 | 28 | /* 29 | * vring_more_used 30 | * 31 | * is there some used buffers ? 32 | * 33 | */ 34 | 35 | int vring_more_used(struct vring_virtqueue *vq) 36 | { 37 | struct vring_used *used = vq->vring.used; 38 | int more = vq->last_used_idx != used->idx; 39 | /* Make sure ring reads are done after idx read above. */ 40 | smp_rmb(); 41 | return more; 42 | } 43 | 44 | /* 45 | * vring_free 46 | * 47 | * put at the begin of the free list the current desc[head] 48 | */ 49 | 50 | void vring_detach(struct vring_virtqueue *vq, unsigned int head) 51 | { 52 | struct vring *vr = &vq->vring; 53 | struct vring_desc *desc = GET_LOWFLAT(vr->desc); 54 | unsigned int i; 55 | 56 | /* find end of given descriptor */ 57 | 58 | i = head; 59 | while (desc[i].flags & VRING_DESC_F_NEXT) 60 | i = desc[i].next; 61 | 62 | /* link it with free list and point to it */ 63 | 64 | desc[i].next = vq->free_head; 65 | vq->free_head = head; 66 | } 67 | 68 | /* 69 | * vring_get_buf 70 | * 71 | * get a buffer from the used list 72 | * 73 | */ 74 | 75 | int vring_get_buf(struct vring_virtqueue *vq, unsigned int *len) 76 | { 77 | struct vring *vr = &vq->vring; 78 | struct vring_used_elem *elem; 79 | struct vring_used *used = vq->vring.used; 80 | u32 id; 81 | int ret; 82 | 83 | // BUG_ON(!vring_more_used(vq)); 84 | 85 | elem = &used->ring[vq->last_used_idx % vr->num]; 86 | id = elem->id; 87 | if (len != NULL) 88 | *len = elem->len; 89 | 90 | ret = vq->vdata[id]; 91 | 92 | vring_detach(vq, id); 93 | 94 | vq->last_used_idx = vq->last_used_idx + 1; 95 | 96 | return ret; 97 | } 98 | 99 | void vring_add_buf(struct vring_virtqueue *vq, 100 | struct vring_list list[], 101 | unsigned int out, unsigned int in, 102 | int index, int num_added) 103 | { 104 | struct vring *vr = &vq->vring; 105 | int i, av, head, prev; 106 | struct vring_desc *desc = vr->desc; 107 | struct vring_avail *avail = vr->avail; 108 | 109 | BUG_ON(out + in == 0); 110 | 111 | prev = 0; 112 | head = vq->free_head; 113 | for (i = head; out; i = desc[i].next, out--) { 114 | desc[i].flags = VRING_DESC_F_NEXT; 115 | desc[i].addr = (u64)virt_to_phys(list->addr); 116 | desc[i].len = list->length; 117 | prev = i; 118 | list++; 119 | } 120 | for ( ; in; i = desc[i].next, in--) { 121 | desc[i].flags = VRING_DESC_F_NEXT|VRING_DESC_F_WRITE; 122 | desc[i].addr = (u64)virt_to_phys(list->addr); 123 | desc[i].len = list->length; 124 | prev = i; 125 | list++; 126 | } 127 | desc[prev].flags = desc[prev].flags & ~VRING_DESC_F_NEXT; 128 | 129 | vq->free_head = i; 130 | 131 | vq->vdata[head] = index; 132 | 133 | av = (avail->idx + num_added) % vr->num; 134 | avail->ring[av] = head; 135 | } 136 | 137 | void vring_kick(struct vp_device *vp, struct vring_virtqueue *vq, int num_added) 138 | { 139 | struct vring *vr = &vq->vring; 140 | struct vring_avail *avail = vr->avail; 141 | 142 | /* Make sure idx update is done after ring write. */ 143 | smp_wmb(); 144 | avail->idx = avail->idx + num_added; 145 | 146 | vp_notify(vp, vq); 147 | } 148 | -------------------------------------------------------------------------------- /src/hw/virtio-ring.h: -------------------------------------------------------------------------------- 1 | #ifndef _VIRTIO_RING_H 2 | #define _VIRTIO_RING_H 3 | 4 | #include "types.h" // u64 5 | #include "memmap.h" // PAGE_SIZE 6 | 7 | /* Status byte for guest to report progress, and synchronize features. */ 8 | /* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */ 9 | #define VIRTIO_CONFIG_S_ACKNOWLEDGE 1 10 | /* We have found a driver for the device. */ 11 | #define VIRTIO_CONFIG_S_DRIVER 2 12 | /* Driver has used its parts of the config, and is happy */ 13 | #define VIRTIO_CONFIG_S_DRIVER_OK 4 14 | /* Driver has finished configuring features */ 15 | #define VIRTIO_CONFIG_S_FEATURES_OK 8 16 | /* We've given up on this device. */ 17 | #define VIRTIO_CONFIG_S_FAILED 0x80 18 | 19 | /* v1.0 compliant. */ 20 | #define VIRTIO_F_VERSION_1 32 21 | #define VIRTIO_F_IOMMU_PLATFORM 33 22 | 23 | #define MAX_QUEUE_NUM (256) 24 | 25 | #define VRING_DESC_F_NEXT 1 26 | #define VRING_DESC_F_WRITE 2 27 | 28 | #define VRING_AVAIL_F_NO_INTERRUPT 1 29 | 30 | #define VRING_USED_F_NO_NOTIFY 1 31 | 32 | struct vring_desc 33 | { 34 | u64 addr; 35 | u32 len; 36 | u16 flags; 37 | u16 next; 38 | }; 39 | 40 | struct vring_avail 41 | { 42 | u16 flags; 43 | u16 idx; 44 | u16 ring[0]; 45 | }; 46 | 47 | struct vring_used_elem 48 | { 49 | u32 id; 50 | u32 len; 51 | }; 52 | 53 | struct vring_used 54 | { 55 | u16 flags; 56 | u16 idx; 57 | struct vring_used_elem ring[]; 58 | }; 59 | 60 | struct vring { 61 | unsigned int num; 62 | struct vring_desc *desc; 63 | struct vring_avail *avail; 64 | struct vring_used *used; 65 | }; 66 | 67 | #define vring_size(num) \ 68 | (ALIGN(sizeof(struct vring_desc) * num + sizeof(struct vring_avail) \ 69 | + sizeof(u16) * num, PAGE_SIZE) \ 70 | + sizeof(struct vring_used) + sizeof(struct vring_used_elem) * num) 71 | 72 | typedef unsigned char virtio_queue_t[vring_size(MAX_QUEUE_NUM)]; 73 | 74 | struct vring_virtqueue { 75 | virtio_queue_t queue; 76 | struct vring vring; 77 | u16 free_head; 78 | u16 last_used_idx; 79 | u16 vdata[MAX_QUEUE_NUM]; 80 | /* PCI */ 81 | int queue_index; 82 | int queue_notify_off; 83 | }; 84 | 85 | struct vring_list { 86 | char *addr; 87 | unsigned int length; 88 | }; 89 | 90 | static inline void 91 | vring_init(struct vring *vr, unsigned int num, unsigned char *queue) 92 | { 93 | ASSERT32FLAT(); 94 | vr->num = num; 95 | 96 | /* physical address of desc must be page aligned */ 97 | vr->desc = (void*)ALIGN((u32)queue, PAGE_SIZE); 98 | 99 | vr->avail = (struct vring_avail *)&vr->desc[num]; 100 | /* disable interrupts */ 101 | vr->avail->flags |= VRING_AVAIL_F_NO_INTERRUPT; 102 | 103 | /* physical address of used must be page aligned */ 104 | vr->used = (void*)ALIGN((u32)&vr->avail->ring[num], PAGE_SIZE); 105 | 106 | int i; 107 | for (i = 0; i < num - 1; i++) 108 | vr->desc[i].next = i + 1; 109 | vr->desc[i].next = 0; 110 | } 111 | 112 | struct vp_device; 113 | int vring_more_used(struct vring_virtqueue *vq); 114 | void vring_detach(struct vring_virtqueue *vq, unsigned int head); 115 | int vring_get_buf(struct vring_virtqueue *vq, unsigned int *len); 116 | void vring_add_buf(struct vring_virtqueue *vq, struct vring_list list[], 117 | unsigned int out, unsigned int in, 118 | int index, int num_added); 119 | void vring_kick(struct vp_device *vp, struct vring_virtqueue *vq, int num_added); 120 | 121 | #endif /* _VIRTIO_RING_H_ */ 122 | -------------------------------------------------------------------------------- /src/hw/virtio-scsi.h: -------------------------------------------------------------------------------- 1 | #ifndef _VIRTIO_SCSI_H 2 | #define _VIRTIO_SCSI_H 3 | 4 | #define VIRTIO_SCSI_CDB_SIZE 32 5 | #define VIRTIO_SCSI_SENSE_SIZE 96 6 | 7 | struct virtio_scsi_config 8 | { 9 | u32 num_queues; 10 | u32 seg_max; 11 | u32 max_sectors; 12 | u32 cmd_per_lun; 13 | u32 event_info_size; 14 | u32 sense_size; 15 | u32 cdb_size; 16 | u16 max_channel; 17 | u16 max_target; 18 | u32 max_lun; 19 | } __attribute__((packed)); 20 | 21 | /* This is the first element of the "out" scatter-gather list. */ 22 | struct virtio_scsi_req_cmd { 23 | u8 lun[8]; 24 | u64 id; 25 | u8 task_attr; 26 | u8 prio; 27 | u8 crn; 28 | char cdb[VIRTIO_SCSI_CDB_SIZE]; 29 | } __attribute__((packed)); 30 | 31 | /* This is the first element of the "in" scatter-gather list. */ 32 | struct virtio_scsi_resp_cmd { 33 | u32 sense_len; 34 | u32 residual; 35 | u16 status_qualifier; 36 | u8 status; 37 | u8 response; 38 | u8 sense[VIRTIO_SCSI_SENSE_SIZE]; 39 | } __attribute__((packed)); 40 | 41 | #define VIRTIO_SCSI_S_OK 0 42 | 43 | struct disk_op_s; 44 | int virtio_scsi_process_op(struct disk_op_s *op); 45 | void virtio_scsi_setup(void); 46 | void init_virtio_scsi_mmio(void *data); 47 | 48 | #endif /* _VIRTIO_SCSI_H */ 49 | -------------------------------------------------------------------------------- /src/list.h: -------------------------------------------------------------------------------- 1 | #ifndef __LIST_H 2 | #define __LIST_H 3 | 4 | #include "types.h" // container_of 5 | 6 | 7 | /**************************************************************** 8 | * hlist - Double linked lists with a single pointer list head 9 | ****************************************************************/ 10 | 11 | struct hlist_node { 12 | struct hlist_node *next, **pprev; 13 | }; 14 | 15 | struct hlist_head { 16 | struct hlist_node *first; 17 | }; 18 | 19 | static inline int 20 | hlist_empty(const struct hlist_head *h) 21 | { 22 | return !h->first; 23 | } 24 | 25 | static inline void 26 | hlist_del(struct hlist_node *n) 27 | { 28 | struct hlist_node *next = n->next; 29 | struct hlist_node **pprev = n->pprev; 30 | *pprev = next; 31 | if (next) 32 | next->pprev = pprev; 33 | } 34 | 35 | static inline void 36 | hlist_add(struct hlist_node *n, struct hlist_node **pprev) 37 | { 38 | struct hlist_node *next = *pprev; 39 | n->pprev = pprev; 40 | n->next = next; 41 | if (next) 42 | next->pprev = &n->next; 43 | *pprev = n; 44 | } 45 | 46 | static inline void 47 | hlist_add_head(struct hlist_node *n, struct hlist_head *h) 48 | { 49 | hlist_add(n, &h->first); 50 | } 51 | 52 | static inline void 53 | hlist_add_before(struct hlist_node *n, struct hlist_node *next) 54 | { 55 | hlist_add(n, next->pprev); 56 | } 57 | 58 | static inline void 59 | hlist_add_after(struct hlist_node *n, struct hlist_node *prev) 60 | { 61 | hlist_add(n, &prev->next); 62 | } 63 | 64 | static inline void 65 | hlist_replace(struct hlist_node *old, struct hlist_node *new) 66 | { 67 | new->next = old->next; 68 | if (new->next) 69 | new->next->pprev = &new->next; 70 | new->pprev = old->pprev; 71 | *new->pprev = new; 72 | } 73 | 74 | #define hlist_for_each_entry(pos, head, member) \ 75 | for (pos = container_of((head)->first, typeof(*pos), member) \ 76 | ; pos != container_of(NULL, typeof(*pos), member) \ 77 | ; pos = container_of(pos->member.next, typeof(*pos), member)) 78 | 79 | #define hlist_for_each_entry_safe(pos, n, head, member) \ 80 | for (pos = container_of((head)->first, typeof(*pos), member) \ 81 | ; pos != container_of(NULL, typeof(*pos), member) \ 82 | && ({ n = pos->member.next; 1; }) \ 83 | ; pos = container_of(n, typeof(*pos), member)) 84 | 85 | #define hlist_for_each_entry_pprev(pos, pprev, head, member) \ 86 | for (pprev = &(head)->first \ 87 | ; *pprev && ({ pos=container_of(*pprev, typeof(*pos), member); 1; }) \ 88 | ; pprev = &(*pprev)->next) 89 | 90 | 91 | #endif // list.h 92 | -------------------------------------------------------------------------------- /src/malloc.h: -------------------------------------------------------------------------------- 1 | #ifndef __MALLOC_H 2 | #define __MALLOC_H 3 | 4 | #include "types.h" // u32 5 | 6 | // malloc.c 7 | extern struct zone_s ZoneLow, ZoneHigh, ZoneFSeg, ZoneTmpLow, ZoneTmpHigh; 8 | u32 rom_get_max(void); 9 | u32 rom_get_last(void); 10 | struct rom_header *rom_reserve(u32 size); 11 | int rom_confirm(u32 size); 12 | void malloc_csm_preinit(u32 low_pmm, u32 low_pmm_size, u32 hi_pmm, 13 | u32 hi_pmm_size); 14 | void malloc_preinit(void); 15 | extern u32 LegacyRamSize; 16 | void malloc_init(void); 17 | void malloc_prepboot(void); 18 | u32 malloc_palloc(struct zone_s *zone, u32 size, u32 align); 19 | void *_malloc(struct zone_s *zone, u32 size, u32 align); 20 | int malloc_pfree(u32 data); 21 | void free(void *data); 22 | u32 malloc_getspace(struct zone_s *zone); 23 | void malloc_sethandle(u32 data, u32 handle); 24 | u32 malloc_findhandle(u32 handle); 25 | 26 | #define MALLOC_DEFAULT_HANDLE 0xFFFFFFFF 27 | // Minimum alignment of malloc'd memory 28 | #define MALLOC_MIN_ALIGN 16 29 | // Helper functions for memory allocation. 30 | static inline void *malloc_low(u32 size) { 31 | return _malloc(&ZoneLow, size, MALLOC_MIN_ALIGN); 32 | } 33 | static inline void *malloc_high(u32 size) { 34 | return _malloc(&ZoneHigh, size, MALLOC_MIN_ALIGN); 35 | } 36 | static inline void *malloc_fseg(u32 size) { 37 | return _malloc(&ZoneFSeg, size, MALLOC_MIN_ALIGN); 38 | } 39 | static inline void *malloc_tmplow(u32 size) { 40 | return _malloc(&ZoneTmpLow, size, MALLOC_MIN_ALIGN); 41 | } 42 | static inline void *malloc_tmphigh(u32 size) { 43 | return _malloc(&ZoneTmpHigh, size, MALLOC_MIN_ALIGN); 44 | } 45 | static inline void *malloc_tmp(u32 size) { 46 | void *ret = malloc_tmphigh(size); 47 | if (ret) 48 | return ret; 49 | return malloc_tmplow(size); 50 | } 51 | static inline void *memalign_low(u32 align, u32 size) { 52 | return _malloc(&ZoneLow, size, align); 53 | } 54 | static inline void *memalign_high(u32 align, u32 size) { 55 | return _malloc(&ZoneHigh, size, align); 56 | } 57 | static inline void *memalign_tmplow(u32 align, u32 size) { 58 | return _malloc(&ZoneTmpLow, size, align); 59 | } 60 | static inline void *memalign_tmphigh(u32 align, u32 size) { 61 | return _malloc(&ZoneTmpHigh, size, align); 62 | } 63 | static inline void *memalign_tmp(u32 align, u32 size) { 64 | void *ret = memalign_tmphigh(align, size); 65 | if (ret) 66 | return ret; 67 | return memalign_tmplow(align, size); 68 | } 69 | 70 | #endif // malloc.h 71 | -------------------------------------------------------------------------------- /src/memmap.h: -------------------------------------------------------------------------------- 1 | #ifndef __MEMMAP_H 2 | #define __MEMMAP_H 3 | 4 | #include "types.h" // u32 5 | 6 | // A typical OS page size 7 | #define PAGE_SIZE 4096 8 | #define PAGE_SHIFT 12 9 | 10 | static inline u32 virt_to_phys(void *v) { 11 | return (u32)v; 12 | } 13 | static inline void *memremap(u32 addr, u32 len) { 14 | return (void*)addr; 15 | } 16 | 17 | // Return the value of a linker script symbol (see scripts/layoutrom.py) 18 | #define SYMBOL(SYM) ({ extern char SYM[]; (u32)SYM; }) 19 | #define VSYMBOL(SYM) ((void*)SYMBOL(SYM)) 20 | 21 | #endif // memmap.h 22 | -------------------------------------------------------------------------------- /src/output.h: -------------------------------------------------------------------------------- 1 | #ifndef __OUTPUT_H 2 | #define __OUTPUT_H 3 | 4 | #include "config.h" // CONFIG_DEBUG_LEVEL 5 | #include "types.h" // u32 6 | 7 | // output.c 8 | void debug_banner(void); 9 | void panic(const char *fmt, ...) 10 | __attribute__ ((format (printf, 1, 2))) __noreturn; 11 | void printf(const char *fmt, ...) 12 | __attribute__ ((format (printf, 1, 2))); 13 | int snprintf(char *str, size_t size, const char *fmt, ...) 14 | __attribute__ ((format (printf, 3, 4))); 15 | char * znprintf(size_t size, const char *fmt, ...) 16 | __attribute__ ((format (printf, 2, 3))); 17 | void __dprintf(const char *fmt, ...) 18 | __attribute__ ((format (printf, 1, 2))); 19 | struct bregs; 20 | void __debug_enter(struct bregs *regs, const char *fname); 21 | void __debug_isr(const char *fname); 22 | void __debug_stub(struct bregs *regs, int lineno, const char *fname); 23 | void __warn_invalid(struct bregs *regs, int lineno, const char *fname); 24 | void __warn_unimplemented(struct bregs *regs, int lineno, const char *fname); 25 | void __warn_internalerror(int lineno, const char *fname); 26 | void __warn_noalloc(int lineno, const char *fname); 27 | void __warn_timeout(int lineno, const char *fname); 28 | void __set_invalid(struct bregs *regs, int lineno, const char *fname); 29 | void __set_unimplemented(struct bregs *regs, int lineno, const char *fname); 30 | void __set_code_invalid(struct bregs *regs, u32 linecode, const char *fname); 31 | void __set_code_unimplemented(struct bregs *regs, u32 linecode 32 | , const char *fname); 33 | void hexdump(const void *d, int len); 34 | 35 | #define dprintf(lvl, fmt, args...) do { \ 36 | if (CONFIG_DEBUG_LEVEL && (lvl) <= CONFIG_DEBUG_LEVEL) \ 37 | __dprintf((fmt) , ##args ); \ 38 | } while (0) 39 | #define debug_enter(regs, lvl) do { \ 40 | if ((lvl) && (lvl) <= CONFIG_DEBUG_LEVEL) \ 41 | __debug_enter((regs), __func__); \ 42 | } while (0) 43 | #define debug_isr(lvl) do { \ 44 | if ((lvl) && (lvl) <= CONFIG_DEBUG_LEVEL) \ 45 | __debug_isr(__func__); \ 46 | } while (0) 47 | #define debug_stub(regs) \ 48 | __debug_stub((regs), __LINE__, __func__) 49 | #define warn_invalid(regs) \ 50 | __warn_invalid((regs), __LINE__, __func__) 51 | #define warn_unimplemented(regs) \ 52 | __warn_unimplemented((regs), __LINE__, __func__) 53 | #define warn_internalerror() \ 54 | __warn_internalerror(__LINE__, __func__) 55 | #define warn_noalloc() \ 56 | __warn_noalloc(__LINE__, __func__) 57 | #define warn_timeout() \ 58 | __warn_timeout(__LINE__, __func__) 59 | #define set_invalid(regs) \ 60 | __set_invalid((regs), __LINE__, __func__) 61 | #define set_code_invalid(regs, code) \ 62 | __set_code_invalid((regs), (code) | (__LINE__ << 8), __func__) 63 | #define set_unimplemented(regs) \ 64 | __set_unimplemented((regs), __LINE__, __func__) 65 | #define set_code_unimplemented(regs, code) \ 66 | __set_code_unimplemented((regs), (code) | (__LINE__ << 8), __func__) 67 | 68 | #endif // output.h 69 | -------------------------------------------------------------------------------- /src/pnpbios.c: -------------------------------------------------------------------------------- 1 | // PNP BIOS calls 2 | // 3 | // Copyright (C) 2008 Kevin O'Connor 4 | // 5 | // This file may be distributed under the terms of the GNU LGPLv3 license. 6 | 7 | #include "config.h" // BUILD_BIOS_ADDR 8 | #include "farptr.h" // SET_FARVAR 9 | #include "output.h" // dprintf 10 | #include "std/pnpbios.h" // PNP_SIGNATURE 11 | #include "string.h" // checksum 12 | #include "util.h" // pnp_init 13 | 14 | extern struct pnpheader PNPHEADER; 15 | extern char pnp_string[]; 16 | 17 | #if CONFIG_PNPBIOS 18 | struct pnpheader PNPHEADER __aligned(16) VARFSEG = { 19 | .signature = PNP_SIGNATURE, 20 | .version = 0x10, 21 | .length = sizeof(PNPHEADER), 22 | .real_cs = SEG_BIOS, 23 | .prot_base = BUILD_BIOS_ADDR, 24 | .real_ds = SEG_BIOS, 25 | .prot_database = BUILD_BIOS_ADDR, 26 | }; 27 | #else 28 | // We need a copy of this string in the 0xf000 segment, but we are not 29 | // actually a PnP BIOS, so make sure it is *not* aligned, so OSes will 30 | // not see it if they scan. 31 | char pnp_string[] __aligned(2) VARFSEG = " $PnP"; 32 | #endif 33 | 34 | // BBS - Get Version and Installation Check 35 | static u16 36 | handle_pnp60(u16 *args) 37 | { 38 | u16 version_ptr = args[1]; 39 | u16 version_seg = args[2]; 40 | SET_FARVAR(version_seg, *(u16*)(version_ptr+0), 0x0101); 41 | return 0; 42 | } 43 | 44 | static u16 45 | handle_pnpXX(u16 *args) 46 | { 47 | return FUNCTION_NOT_SUPPORTED; 48 | } 49 | 50 | u16 VISIBLE16 51 | handle_pnp(u16 *args) 52 | { 53 | if (! CONFIG_PNPBIOS) 54 | return FUNCTION_NOT_SUPPORTED; 55 | 56 | u16 arg1 = args[0]; 57 | dprintf(DEBUG_HDL_pnp, "pnp call arg1=%x\n", arg1); 58 | 59 | switch (arg1) { 60 | case 0x60: return handle_pnp60(args); 61 | default: return handle_pnpXX(args); 62 | } 63 | } 64 | 65 | u16 66 | get_pnp_offset(void) 67 | { 68 | if (! CONFIG_PNPBIOS) 69 | return (u32)pnp_string + 1 - BUILD_BIOS_ADDR; 70 | return (u32)&PNPHEADER - BUILD_BIOS_ADDR; 71 | } 72 | 73 | // romlayout.S 74 | extern void entry_pnp_real(void); 75 | extern void entry_pnp_prot(void); 76 | 77 | void 78 | pnp_init(void) 79 | { 80 | if (! CONFIG_PNPBIOS) 81 | return; 82 | 83 | dprintf(3, "init PNPBIOS table\n"); 84 | 85 | PNPHEADER.real_ip = (u32)entry_pnp_real - BUILD_BIOS_ADDR; 86 | PNPHEADER.prot_ip = (u32)entry_pnp_prot - BUILD_BIOS_ADDR; 87 | PNPHEADER.checksum -= checksum(&PNPHEADER, sizeof(PNPHEADER)); 88 | } 89 | -------------------------------------------------------------------------------- /src/resume.c: -------------------------------------------------------------------------------- 1 | // Code for handling calls to "post" that are resume related. 2 | // 3 | // Copyright (C) 2008,2009 Kevin O'Connor 4 | // 5 | // This file may be distributed under the terms of the GNU LGPLv3 license. 6 | 7 | #include "bregs.h" // struct bregs 8 | #include "config.h" // CONFIG_* 9 | #include "farptr.h" // FLATPTR_TO_SEGOFF 10 | #include "hw/pci.h" // pci_reboot 11 | #include "hw/pic.h" // pic_eoi2 12 | #include "hw/ps2port.h" // i8042_reboot 13 | #include "hw/rtc.h" // rtc_read 14 | #include "output.h" // dprintf 15 | #include "stacks.h" // farcall16big 16 | #include "std/bda.h" // struct bios_data_area_s 17 | #include "string.h" // memset 18 | #include "util.h" // dma_setup 19 | #include "tcgbios.h" // tpm_s3_resume 20 | #include "fw/romfile_loader.h" // romfile_fw_cfg_resume 21 | 22 | // Handler for post calls that look like a resume. 23 | void VISIBLE16 24 | handle_resume(void) 25 | { 26 | ASSERT16(); 27 | int status = rtc_read(CMOS_RESET_CODE); 28 | rtc_write(CMOS_RESET_CODE, 0); 29 | dprintf(1, "In resume (status=%d)\n", status); 30 | 31 | dma_setup(); 32 | 33 | switch (status) { 34 | case 0x01 ... 0x04: 35 | case 0x06 ... 0x09: 36 | panic("Unimplemented shutdown status: %02x\n", status); 37 | 38 | case 0x05: 39 | // flush keyboard (issue EOI) and jump via 40h:0067h 40 | pic_eoi2(); 41 | // NO BREAK 42 | case 0x0a: 43 | #define BDA_JUMP (((struct bios_data_area_s *)0)->jump) 44 | // resume execution by jump via 40h:0067h 45 | asm volatile( 46 | "movw %w1, %%ds\n" 47 | "ljmpw *%0\n" 48 | : : "m"(BDA_JUMP), "r"(SEG_BDA) 49 | ); 50 | break; 51 | 52 | case 0x0b: 53 | // resume execution via IRET via 40h:0067h 54 | asm volatile( 55 | "movw %w1, %%ds\n" 56 | "lssw %0, %%sp\n" 57 | "iretw\n" 58 | : : "m"(BDA_JUMP), "r"(SEG_BDA) 59 | ); 60 | break; 61 | 62 | case 0x0c: 63 | // resume execution via RETF via 40h:0067h 64 | asm volatile( 65 | "movw %w1, %%ds\n" 66 | "lssw %0, %%sp\n" 67 | "lretw\n" 68 | : : "m"(BDA_JUMP), "r"(SEG_BDA) 69 | ); 70 | break; 71 | 72 | default: 73 | break; 74 | } 75 | 76 | // Not a 16bit resume - do remaining checks in 32bit mode 77 | asm volatile( 78 | "movw %w1, %%ss\n" 79 | "movl %0, %%esp\n" 80 | "movl $_cfunc32flat_handle_resume32, %%edx\n" 81 | "jmp transition32\n" 82 | : : "i"(BUILD_S3RESUME_STACK_ADDR), "r"(0), "a"(status) 83 | ); 84 | } 85 | 86 | // Handle an S3 resume event 87 | static void 88 | s3_resume(void) 89 | { 90 | if (!CONFIG_S3_RESUME) 91 | return; 92 | 93 | u32 s3_resume_vector = find_resume_vector(); 94 | if (!s3_resume_vector) { 95 | dprintf(1, "No resume vector set!\n"); 96 | return; 97 | } 98 | 99 | pic_setup(); 100 | smm_setup(); 101 | smp_resume(); 102 | 103 | pci_resume(); 104 | 105 | /* resume TPM before we may measure option roms */ 106 | tpm_s3_resume(); 107 | s3_resume_vga(); 108 | 109 | /* Replay any fw_cfg entries that go back to the host */ 110 | romfile_fw_cfg_resume(); 111 | 112 | make_bios_readonly(); 113 | 114 | // Invoke the resume vector. 115 | struct bregs br; 116 | memset(&br, 0, sizeof(br)); 117 | dprintf(1, "Jump to resume vector (%x)\n", s3_resume_vector); 118 | br.code = FLATPTR_TO_SEGOFF((void*)s3_resume_vector); 119 | farcall16big(&br); 120 | } 121 | 122 | // Attempt to invoke a hard-reboot. 123 | static void 124 | tryReboot(void) 125 | { 126 | dprintf(1, "Attempting a hard reboot\n"); 127 | 128 | // Use a QEMU specific reboot on QEMU 129 | qemu_reboot(); 130 | 131 | // Reboot using ACPI RESET_REG 132 | acpi_reboot(); 133 | 134 | // Try keyboard controller reboot. 135 | i8042_reboot(); 136 | 137 | // Try PCI 0xcf9 reboot 138 | pci_reboot(); 139 | 140 | // Try triple fault 141 | asm volatile("int3"); 142 | 143 | panic("Could not reboot"); 144 | } 145 | 146 | void VISIBLE32FLAT 147 | handle_resume32(int status) 148 | { 149 | ASSERT32FLAT(); 150 | dprintf(1, "In 32bit resume\n"); 151 | 152 | if (status == 0xfe) 153 | s3_resume(); 154 | 155 | // Must be a soft reboot - invoke a hard reboot. 156 | tryReboot(); 157 | } 158 | -------------------------------------------------------------------------------- /src/romfile.h: -------------------------------------------------------------------------------- 1 | #ifndef __ROMFILE_H 2 | #define __ROMFILE_H 3 | 4 | #include "types.h" // u32 5 | 6 | // romfile.c 7 | struct romfile_s { 8 | struct romfile_s *next; 9 | char name[128]; 10 | u32 size; 11 | int (*copy)(struct romfile_s *file, void *dest, u32 maxlen); 12 | }; 13 | void romfile_add(struct romfile_s *file); 14 | struct romfile_s *romfile_findprefix(const char *prefix, struct romfile_s *prev); 15 | struct romfile_s *romfile_find(const char *name); 16 | void *romfile_loadfile(const char *name, int *psize); 17 | u64 romfile_loadint(const char *name, u64 defval); 18 | u32 romfile_loadbool(const char *name, u32 defval); 19 | 20 | void const_romfile_add_int(char *name, u32 value); 21 | 22 | #endif // romfile.h 23 | -------------------------------------------------------------------------------- /src/sha.h: -------------------------------------------------------------------------------- 1 | #ifndef __SHA_H 2 | #define __SHA_H 3 | 4 | #include "types.h" // u32 5 | 6 | void sha1(const u8 *data, u32 length, u8 *hash); 7 | void sha256(const u8 *data, u32 length, u8 *hash); 8 | void sha384(const u8 *data, u32 length, u8 *hash); 9 | void sha512(const u8 *data, u32 length, u8 *hash); 10 | 11 | #endif // sha.h 12 | -------------------------------------------------------------------------------- /src/sha1.c: -------------------------------------------------------------------------------- 1 | // Support for Calculation of SHA1 in SW 2 | // 3 | // Copyright (C) 2006-2011 IBM Corporation 4 | // 5 | // Authors: 6 | // Stefan Berger 7 | // 8 | // This file may be distributed under the terms of the GNU LGPLv3 license. 9 | // 10 | // See: http://www.itl.nist.gov/fipspubs/fip180-1.htm 11 | // RFC3174, Wikipedia's SHA1 alogrithm description 12 | // 13 | 14 | #include "config.h" 15 | #include "byteorder.h" // cpu_to_*, __swab64 16 | #include "sha.h" // sha1 17 | #include "string.h" // memcpy 18 | #include "x86.h" // rol 19 | 20 | typedef struct _sha1_ctx { 21 | u32 h[5]; 22 | } sha1_ctx; 23 | 24 | 25 | static void 26 | sha1_block(u32 *w, sha1_ctx *ctx) 27 | { 28 | u32 i; 29 | u32 a,b,c,d,e,f; 30 | u32 tmp; 31 | u32 idx; 32 | 33 | static const u32 sha_ko[4] = { 34 | 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6 }; 35 | 36 | /* change endianness of given data */ 37 | for (i = 0; i < 16; i++) 38 | w[i] = be32_to_cpu(w[i]); 39 | 40 | for (i = 16; i <= 79; i++) { 41 | tmp = w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]; 42 | w[i] = rol(tmp,1); 43 | } 44 | 45 | a = ctx->h[0]; 46 | b = ctx->h[1]; 47 | c = ctx->h[2]; 48 | d = ctx->h[3]; 49 | e = ctx->h[4]; 50 | 51 | for (i = 0; i <= 79; i++) { 52 | if (i <= 19) { 53 | f = (b & c) | ((b ^ 0xffffffff) & d); 54 | idx = 0; 55 | } else if (i <= 39) { 56 | f = b ^ c ^ d; 57 | idx = 1; 58 | } else if (i <= 59) { 59 | f = (b & c) | (b & d) | (c & d); 60 | idx = 2; 61 | } else { 62 | f = b ^ c ^ d; 63 | idx = 3; 64 | } 65 | 66 | tmp = rol(a, 5) + 67 | f + 68 | e + 69 | sha_ko[idx] + 70 | w[i]; 71 | e = d; 72 | d = c; 73 | c = rol(b, 30); 74 | b = a; 75 | a = tmp; 76 | } 77 | 78 | ctx->h[0] += a; 79 | ctx->h[1] += b; 80 | ctx->h[2] += c; 81 | ctx->h[3] += d; 82 | ctx->h[4] += e; 83 | } 84 | 85 | 86 | static void 87 | sha1_do(sha1_ctx *ctx, const u8 *data32, u32 length) 88 | { 89 | u32 offset; 90 | u16 num; 91 | u32 bits = 0; 92 | u32 w[80]; 93 | u64 tmp; 94 | 95 | /* treat data in 64-byte chunks */ 96 | for (offset = 0; length - offset >= 64; offset += 64) { 97 | memcpy(w, data32 + offset, 64); 98 | sha1_block((u32 *)w, ctx); 99 | bits += (64 * 8); 100 | } 101 | 102 | /* last block with less than 64 bytes */ 103 | num = length - offset; 104 | bits += (num << 3); 105 | 106 | memcpy(w, data32 + offset, num); 107 | ((u8 *)w)[num] = 0x80; 108 | if (64 - (num + 1) > 0) 109 | memset( &((u8 *)w)[num + 1], 0x0, 64 - (num + 1)); 110 | 111 | if (num >= 56) { 112 | /* cannot append number of bits here */ 113 | sha1_block((u32 *)w, ctx); 114 | memset(w, 0x0, 60); 115 | } 116 | 117 | /* write number of bits to end of block */ 118 | tmp = __swab64(bits); 119 | memcpy(&w[14], &tmp, 8); 120 | 121 | sha1_block(w, ctx); 122 | 123 | /* need to switch result's endianness */ 124 | for (num = 0; num < 5; num++) 125 | ctx->h[num] = cpu_to_be32(ctx->h[num]); 126 | } 127 | 128 | 129 | void 130 | sha1(const u8 *data, u32 length, u8 *hash) 131 | { 132 | if (!CONFIG_TCGBIOS) 133 | return; 134 | 135 | sha1_ctx ctx = { 136 | .h[0] = 0x67452301, 137 | .h[1] = 0xefcdab89, 138 | .h[2] = 0x98badcfe, 139 | .h[3] = 0x10325476, 140 | .h[4] = 0xc3d2e1f0, 141 | }; 142 | 143 | sha1_do(&ctx, data, length); 144 | memcpy(hash, &ctx.h[0], 20); 145 | 146 | return; 147 | } 148 | -------------------------------------------------------------------------------- /src/stacks.h: -------------------------------------------------------------------------------- 1 | // Misc function and variable declarations. 2 | #ifndef __STACKS_H 3 | #define __STACKS_H 4 | 5 | #include "types.h" // u32 6 | 7 | #define CALL32SMM_CMDID 0xb5 8 | #define CALL32SMM_ENTERID 0x1234 9 | #define CALL32SMM_RETURNID 0x5678 10 | 11 | // stacks.c 12 | extern int HaveSmmCall32; 13 | u32 __call32(void *func, u32 eax, u32 errret); 14 | #define call32(func, eax, errret) ({ \ 15 | extern void _cfunc32flat_ ##func (void); \ 16 | __call32( _cfunc32flat_ ##func , (u32)(eax), (errret)); \ 17 | }) 18 | extern u8 ExtraStack[], *StackPos; 19 | u32 __stack_hop(u32 eax, u32 edx, void *func); 20 | #define stack_hop(func, eax, edx) \ 21 | __stack_hop((u32)(eax), (u32)(edx), (func)) 22 | u32 __stack_hop_back(u32 eax, u32 edx, void *func); 23 | #define stack_hop_back(func, eax, edx) ({ \ 24 | extern void _cfunc16_ ##func (void); \ 25 | __stack_hop_back((u32)(eax), (u32)(edx), _cfunc16_ ##func ); \ 26 | }) 27 | int on_extra_stack(void); 28 | struct bregs; 29 | void farcall16(struct bregs *callregs); 30 | void farcall16big(struct bregs *callregs); 31 | void __call16_int(struct bregs *callregs, u16 offset); 32 | #define call16_int(nr, callregs) do { \ 33 | extern void irq_trampoline_ ##nr (void); \ 34 | __call16_int((callregs), (u32)&irq_trampoline_ ##nr ); \ 35 | } while (0) 36 | void reset(void); 37 | extern struct thread_info MainThread; 38 | struct thread_info *getCurThread(void); 39 | void yield(void); 40 | void yield_toirq(void); 41 | void thread_setup(void); 42 | int threads_during_optionroms(void); 43 | void run_thread(void (*func)(void*), void *data); 44 | void wait_threads(void); 45 | struct mutex_s { u32 isLocked; }; 46 | void mutex_lock(struct mutex_s *mutex); 47 | void mutex_unlock(struct mutex_s *mutex); 48 | void start_preempt(void); 49 | void finish_preempt(void); 50 | int wait_preempt(void); 51 | void check_preempt(void); 52 | u32 __call32_params(void *func, u32 eax, u32 edx, u32 ecx, u32 errret); 53 | #define call32_params(func, eax, edx, ecx, errret) ({ \ 54 | extern void _cfunc32flat_ ##func (void); \ 55 | __call32_params( _cfunc32flat_ ##func , (u32)(eax), (u32)(edx) \ 56 | , (u32)(ecx), (errret)); \ 57 | }) 58 | 59 | // Inline functions 60 | 61 | // Check if a call to stack_hop_back is needed. 62 | static inline int 63 | need_hop_back(void) 64 | { 65 | return !MODESEGMENT || on_extra_stack(); 66 | } 67 | 68 | #endif // stacks.h 69 | -------------------------------------------------------------------------------- /src/std/disk.h: -------------------------------------------------------------------------------- 1 | // Standard disk BIOS definitions. 2 | #ifndef __DISK_H 3 | #define __DISK_H 4 | 5 | #include "types.h" // u8 6 | 7 | #define DISK_RET_SUCCESS 0x00 8 | #define DISK_RET_EPARAM 0x01 9 | #define DISK_RET_EADDRNOTFOUND 0x02 10 | #define DISK_RET_EWRITEPROTECT 0x03 11 | #define DISK_RET_ECHANGED 0x06 12 | #define DISK_RET_EBOUNDARY 0x09 13 | #define DISK_RET_EBADTRACK 0x0c 14 | #define DISK_RET_ECONTROLLER 0x20 15 | #define DISK_RET_ETIMEOUT 0x80 16 | #define DISK_RET_ENOTLOCKED 0xb0 17 | #define DISK_RET_ELOCKED 0xb1 18 | #define DISK_RET_ENOTREMOVABLE 0xb2 19 | #define DISK_RET_ETOOMANYLOCKS 0xb4 20 | #define DISK_RET_EMEDIA 0xC0 21 | #define DISK_RET_ENOTREADY 0xAA 22 | 23 | 24 | /**************************************************************** 25 | * Interface structs 26 | ****************************************************************/ 27 | 28 | // Bios disk structures. 29 | struct int13ext_s { 30 | u8 size; 31 | u8 reserved; 32 | u16 count; 33 | struct segoff_s data; 34 | u64 lba; 35 | } PACKED; 36 | 37 | // DPTE definition 38 | struct dpte_s { 39 | u16 iobase1; 40 | u16 iobase2; 41 | u8 prefix; 42 | u8 unused; 43 | u8 irq; 44 | u8 blkcount; 45 | u8 dma; 46 | u8 pio; 47 | u16 options; 48 | u16 reserved; 49 | u8 revision; 50 | u8 checksum; 51 | }; 52 | 53 | // Disk Physical Table definition 54 | struct int13dpt_s { 55 | u16 size; 56 | u16 infos; 57 | u32 cylinders; 58 | u32 heads; 59 | u32 spt; 60 | u64 sector_count; 61 | u16 blksize; 62 | struct segoff_s dpte; 63 | u16 key; 64 | u8 dpi_length; 65 | u8 reserved1; 66 | u16 reserved2; 67 | u8 host_bus[4]; 68 | u8 iface_type[8]; 69 | u64 iface_path; 70 | union { 71 | struct { 72 | u64 device_path; 73 | u8 reserved3; 74 | u8 checksum; 75 | } phoenix; 76 | struct { 77 | u64 device_path[2]; 78 | u8 reserved3; 79 | u8 checksum; 80 | } t13; 81 | }; 82 | } PACKED; 83 | 84 | // Floppy info 85 | struct fdpt_s { 86 | u16 cylinders; 87 | u8 heads; 88 | u8 a0h_signature; 89 | u8 phys_sectors; 90 | u16 precompensation; 91 | u8 reserved; 92 | u8 drive_control_byte; 93 | u16 phys_cylinders; 94 | u8 phys_heads; 95 | u16 landing_zone; 96 | u8 sectors; 97 | u8 checksum; 98 | } PACKED; 99 | 100 | // Floppy "Disk Base Table" 101 | struct floppy_dbt_s { 102 | u8 specify1; 103 | u8 specify2; 104 | u8 shutoff_ticks; 105 | u8 bps_code; 106 | u8 sectors; 107 | u8 interblock_len; 108 | u8 data_len; 109 | u8 gap_len; 110 | u8 fill_byte; 111 | u8 settle_time; 112 | u8 startup_time; 113 | } PACKED; 114 | 115 | struct floppy_ext_dbt_s { 116 | struct floppy_dbt_s dbt; 117 | // Extra fields 118 | u8 max_track; 119 | u8 data_rate; 120 | u8 drive_type; 121 | } PACKED; 122 | 123 | 124 | /**************************************************************** 125 | * Master boot record 126 | ****************************************************************/ 127 | 128 | struct packed_chs_s { 129 | u8 heads; 130 | u8 sptcyl; 131 | u8 cyllow; 132 | } PACKED; 133 | 134 | struct partition_s { 135 | u8 status; 136 | struct packed_chs_s first; 137 | u8 type; 138 | struct packed_chs_s last; 139 | u32 lba; 140 | u32 count; 141 | } PACKED; 142 | 143 | struct mbr_s { 144 | u8 code[440]; 145 | // 0x01b8 146 | u32 diskseg; 147 | // 0x01bc 148 | u16 null; 149 | // 0x01be 150 | struct partition_s partitions[4]; 151 | // 0x01fe 152 | u16 signature; 153 | } PACKED; 154 | 155 | #define MBR_SIGNATURE 0xaa55 156 | 157 | 158 | /**************************************************************** 159 | * ElTorito CDROM interface 160 | ****************************************************************/ 161 | 162 | struct eltorito_s { 163 | u8 size; 164 | u8 media; 165 | u8 emulated_drive; 166 | u8 controller_index; 167 | u32 ilba; 168 | u16 device_spec; 169 | u16 buffer_segment; 170 | u16 load_segment; 171 | u16 sector_count; 172 | struct packed_chs_s chs; 173 | } PACKED; 174 | 175 | #endif // disk.h 176 | -------------------------------------------------------------------------------- /src/std/mptable.h: -------------------------------------------------------------------------------- 1 | #ifndef __MPTABLE_H 2 | #define __MPTABLE_H 3 | 4 | #include "types.h" // u32 5 | 6 | #define MPTABLE_SIGNATURE 0x5f504d5f // "_MP_" 7 | 8 | struct mptable_floating_s { 9 | u32 signature; 10 | u32 physaddr; 11 | u8 length; 12 | u8 spec_rev; 13 | u8 checksum; 14 | u8 feature1; 15 | u8 feature2; 16 | u8 reserved[3]; 17 | }; 18 | 19 | #define MPCONFIG_SIGNATURE 0x504d4350 // "PCMP" 20 | 21 | struct mptable_config_s { 22 | u32 signature; 23 | u16 length; 24 | u8 spec; 25 | u8 checksum; 26 | char oemid[8]; 27 | char productid[12]; 28 | u32 oemptr; 29 | u16 oemsize; 30 | u16 entrycount; 31 | u32 lapic; 32 | u16 exttable_length; 33 | u8 exttable_checksum; 34 | u8 reserved; 35 | } PACKED; 36 | 37 | #define MPT_TYPE_CPU 0 38 | #define MPT_TYPE_BUS 1 39 | #define MPT_TYPE_IOAPIC 2 40 | #define MPT_TYPE_INTSRC 3 41 | #define MPT_TYPE_LOCAL_INT 4 42 | 43 | struct mpt_cpu { 44 | u8 type; 45 | u8 apicid; 46 | u8 apicver; 47 | u8 cpuflag; 48 | u32 cpusignature; 49 | u32 featureflag; 50 | u32 reserved[2]; 51 | } PACKED; 52 | 53 | struct mpt_bus { 54 | u8 type; 55 | u8 busid; 56 | char bustype[6]; 57 | } PACKED; 58 | 59 | struct mpt_ioapic { 60 | u8 type; 61 | u8 apicid; 62 | u8 apicver; 63 | u8 flags; 64 | u32 apicaddr; 65 | } PACKED; 66 | 67 | struct mpt_intsrc { 68 | u8 type; 69 | u8 irqtype; 70 | u16 irqflag; 71 | u8 srcbus; 72 | u8 srcbusirq; 73 | u8 dstapic; 74 | u8 dstirq; 75 | } PACKED; 76 | 77 | #endif // mptable.h 78 | -------------------------------------------------------------------------------- /src/std/optionrom.h: -------------------------------------------------------------------------------- 1 | #ifndef __OPTIONROMS_H 2 | #define __OPTIONROMS_H 3 | 4 | #include "types.h" // u32 5 | 6 | #define OPTION_ROM_SIGNATURE 0xaa55 7 | 8 | struct rom_header { 9 | u16 signature; 10 | u8 size; 11 | u8 initVector[4]; 12 | u8 reserved[17]; 13 | u16 pcioffset; 14 | u16 pnpoffset; 15 | } PACKED; 16 | 17 | #define PCI_ROM_SIGNATURE 0x52494350 // "PCIR" 18 | 19 | struct pci_data { 20 | u32 signature; 21 | u16 vendor; 22 | u16 device; 23 | u16 vitaldata; 24 | u16 dlen; 25 | u8 drevision; 26 | u8 class_lo; 27 | u16 class_hi; 28 | u16 ilen; 29 | u16 irevision; 30 | u8 type; 31 | u8 indicator; 32 | u16 reserved; 33 | } PACKED; 34 | 35 | struct pnp_data { 36 | u32 signature; 37 | u8 revision; 38 | u8 len; 39 | u16 nextoffset; 40 | u8 reserved_08; 41 | u8 checksum; 42 | u32 devid; 43 | u16 manufacturer; 44 | u16 productname; 45 | u8 type_lo; 46 | u16 type_hi; 47 | u8 dev_flags; 48 | u16 bcv; 49 | u16 dv; 50 | u16 bev; 51 | u16 reserved_1c; 52 | u16 staticresource; 53 | } PACKED; 54 | 55 | #define OPTION_ROM_ALIGN 2048 56 | #define OPTION_ROM_INITVECTOR offsetof(struct rom_header, initVector[0]) 57 | #define PCIROM_CODETYPE_X86 0 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /src/std/pirtable.h: -------------------------------------------------------------------------------- 1 | #ifndef __PIRTABLE_H 2 | #define __PIRTABLE_H 3 | 4 | #include "types.h" // u32 5 | 6 | struct link_info { 7 | u8 link; 8 | u16 bitmap; 9 | } PACKED; 10 | 11 | struct pir_slot { 12 | u8 bus; 13 | u8 dev; 14 | struct link_info links[4]; 15 | u8 slot_nr; 16 | u8 reserved; 17 | } PACKED; 18 | 19 | struct pir_header { 20 | u32 signature; 21 | u16 version; 22 | u16 size; 23 | u8 router_bus; 24 | u8 router_devfunc; 25 | u16 exclusive_irqs; 26 | u32 compatible_devid; 27 | u32 miniport_data; 28 | u8 reserved[11]; 29 | u8 checksum; 30 | struct pir_slot slots[0]; 31 | } PACKED; 32 | 33 | #define PIR_SIGNATURE 0x52495024 // $PIR 34 | 35 | #endif // pirtable.h 36 | -------------------------------------------------------------------------------- /src/std/pmm.h: -------------------------------------------------------------------------------- 1 | #ifndef __PMM_H 2 | #define __PMM_H 3 | 4 | #include "types.h" // u32 5 | 6 | #define PMM_SIGNATURE 0x4d4d5024 // $PMM 7 | 8 | struct pmmheader { 9 | u32 signature; 10 | u8 version; 11 | u8 length; 12 | u8 checksum; 13 | struct segoff_s entry; 14 | u8 reserved[5]; 15 | } PACKED; 16 | 17 | #define PMM_FUNCTION_NOT_SUPPORTED 0xffffffff 18 | 19 | #endif // pmm.h 20 | -------------------------------------------------------------------------------- /src/std/pnpbios.h: -------------------------------------------------------------------------------- 1 | #ifndef __PNPHEADER_H 2 | #define __PNPHEADER_H 3 | 4 | #define PNP_SIGNATURE 0x506e5024 // $PnP 5 | 6 | struct pnpheader { 7 | u32 signature; 8 | u8 version; 9 | u8 length; 10 | u16 control; 11 | u8 checksum; 12 | u32 eventloc; 13 | u16 real_ip; 14 | u16 real_cs; 15 | u16 prot_ip; 16 | u32 prot_base; 17 | u32 oemid; 18 | u16 real_ds; 19 | u32 prot_database; 20 | } PACKED; 21 | 22 | #define FUNCTION_NOT_SUPPORTED 0x82 23 | 24 | #endif // pnpheader.h 25 | -------------------------------------------------------------------------------- /src/std/vga.h: -------------------------------------------------------------------------------- 1 | #ifndef __VGA_H 2 | #define __VGA_H 3 | // Standard structure definitions for vgabios video tables 4 | 5 | #include "types.h" // u8 6 | 7 | // standard BIOS Video Parameter Table 8 | struct video_param_s { 9 | u8 twidth; 10 | u8 theightm1; 11 | u8 cheight; 12 | u16 slength; 13 | u8 sequ_regs[4]; 14 | u8 miscreg; 15 | u8 crtc_regs[25]; 16 | u8 actl_regs[20]; 17 | u8 grdc_regs[9]; 18 | } PACKED; 19 | 20 | // Standard Video Save Pointer Table 21 | struct video_save_pointer_s { 22 | struct segoff_s videoparam; 23 | struct segoff_s paramdynamicsave; 24 | struct segoff_s textcharset; 25 | struct segoff_s graphcharset; 26 | struct segoff_s secsavepointer; 27 | u8 reserved[8]; 28 | } PACKED; 29 | 30 | // Data returned by int101B 31 | struct video_func_static { 32 | u32 modes; 33 | u8 reserved_0x04[3]; 34 | u8 scanlines; 35 | u8 cblocks; 36 | u8 active_cblocks; 37 | u16 misc_flags; 38 | u8 reserved_0x0c[2]; 39 | u8 save_flags; 40 | u8 reserved_0x0f; 41 | } PACKED; 42 | 43 | struct video_func_info { 44 | struct segoff_s static_functionality; 45 | u8 bda_0x49[30]; 46 | u8 bda_0x84[3]; 47 | u8 dcc_index; 48 | u8 dcc_alt; 49 | u16 colors; 50 | u8 pages; 51 | u8 scan_lines; 52 | u8 primary_char; 53 | u8 secondar_char; 54 | u8 misc; 55 | u8 non_vga_mode; 56 | u8 reserved_2f[2]; 57 | u8 video_mem; 58 | u8 save_flags; 59 | u8 disp_info; 60 | u8 reserved_34[12]; 61 | } PACKED; 62 | 63 | #endif // vga.h 64 | -------------------------------------------------------------------------------- /src/string.h: -------------------------------------------------------------------------------- 1 | // String manipulation function defs. 2 | #ifndef __STRING_H 3 | #define __STRING_H 4 | 5 | #include "types.h" // u32 6 | 7 | // string.c 8 | u8 checksum_far(u16 buf_seg, void *buf_far, u32 len); 9 | u8 checksum(void *buf, u32 len); 10 | size_t strlen(const char *s); 11 | int memcmp_far(u16 s1seg, const void *s1, u16 s2seg, const void *s2, size_t n); 12 | int memcmp(const void *s1, const void *s2, size_t n); 13 | int strcmp(const char *s1, const char *s2); 14 | void memset_far(u16 d_seg, void *d_far, u8 c, size_t len); 15 | void memset16_far(u16 d_seg, void *d_far, u16 c, size_t len); 16 | void *memset(void *s, int c, size_t n); 17 | void memset_fl(void *ptr, u8 val, size_t size); 18 | void memcpy_far(u16 d_seg, void *d_far 19 | , u16 s_seg, const void *s_far, size_t len); 20 | void memcpy_fl(void *d_fl, const void *s_fl, size_t len); 21 | void *memcpy(void *d1, const void *s1, size_t len); 22 | #if MODESEGMENT == 0 23 | #define memcpy __builtin_memcpy 24 | #endif 25 | void iomemcpy(void *d, const void *s, u32 len); 26 | void *memmove(void *d, const void *s, size_t len); 27 | char *strtcpy(char *dest, const char *src, size_t len); 28 | char *strchr(const char *s, int c); 29 | char *nullTrailingSpace(char *buf); 30 | 31 | #endif // string.h 32 | -------------------------------------------------------------------------------- /src/tcgbios.h: -------------------------------------------------------------------------------- 1 | #ifndef TCGBIOS_H 2 | #define TCGBIOS_H 3 | 4 | #include "types.h" 5 | 6 | struct bregs; 7 | void tpm_interrupt_handler32(struct bregs *regs); 8 | 9 | void tpm_setup(void); 10 | void tpm_prepboot(void); 11 | void tpm_s3_resume(void); 12 | void tpm_add_bcv(u32 bootdrv, const u8 *addr, u32 length); 13 | void tpm_add_cdrom(u32 bootdrv, const u8 *addr, u32 length); 14 | void tpm_add_cdrom_catalog(const u8 *addr, u32 length); 15 | void tpm_option_rom(const void *addr, u32 len); 16 | int tpm_can_show_menu(void); 17 | void tpm_menu(void); 18 | 19 | #endif /* TCGBIOS_H */ 20 | -------------------------------------------------------------------------------- /src/version.c: -------------------------------------------------------------------------------- 1 | // Place build generated version into a C variable 2 | #include "autoversion.h" 3 | 4 | char VERSION[] = BUILD_VERSION; 5 | char BUILDINFO[] = BUILD_TOOLS; 6 | -------------------------------------------------------------------------------- /src/x86.c: -------------------------------------------------------------------------------- 1 | // X86 utility functions. 2 | // 3 | // Copyright (C) 2013 Kevin O'Connor 4 | // 5 | // This file may be distributed under the terms of the GNU LGPLv3 license. 6 | 7 | #include "x86.h" // __cpuid 8 | 9 | void 10 | cpuid(u32 index, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx) 11 | { 12 | // Check for cpu id 13 | u32 origflags = save_flags(); 14 | restore_flags(origflags ^ F_ID); 15 | u32 newflags = save_flags(); 16 | restore_flags(origflags); 17 | 18 | if (((origflags ^ newflags) & F_ID) != F_ID) 19 | // no cpuid 20 | *eax = *ebx = *ecx = *edx = 0; 21 | else 22 | __cpuid(index, eax, ebx, ecx, edx); 23 | } 24 | -------------------------------------------------------------------------------- /vgasrc/ati-tables.S: -------------------------------------------------------------------------------- 1 | // 2 | // Fake ati bios tables. 3 | // 4 | // aty128fb and radeonfb try to gather informations from these tables, 5 | // so add some stuff here to make the drivers happy. Specifically 6 | // radeonfb needs the pll information, otherwise it'll crash with a 7 | // division by zero ... 8 | // 9 | .org 0x48 10 | .word _ati_main 11 | 12 | // main info 13 | .org 0x50 14 | _ati_main: 15 | .org 0x50 + 0x30 16 | .word _ati_pll 17 | .org 0x50 + 0x50 18 | .word _ati_connector 19 | 20 | // pll info 21 | .org 0x100 22 | _ati_pll: 23 | .word 0 // ??? (not used by radeonfb) 24 | .word 0 25 | .word 0 26 | .word 0 27 | .word 23000 // sclk 28 | .word 23000 // mclk 29 | .word 0 30 | .word 2700 // ref_clk 31 | .word 4 // ref_div 32 | .long 12000 // ppll_min 33 | .long 35000 // ppll_max 34 | 35 | // connector info 36 | .org 0x140 37 | _ati_connector: 38 | .byte 0x10 // one chip 39 | .byte 0x01 // one connector 40 | .word 0x3000 // type DVI-I 41 | .word 0 // end of list 42 | 43 | .org 0x200 44 | -------------------------------------------------------------------------------- /vgasrc/bochsdisplay.c: -------------------------------------------------------------------------------- 1 | // Simple framebuffer vgabios for use with qemu bochs-display device 2 | // 3 | // Copyright (C) 2019 Gerd Hoffmann 4 | // 5 | // This file may be distributed under the terms of the GNU LGPLv3 license. 6 | 7 | #include "biosvar.h" // GET_BDA 8 | #include "output.h" // dprintf 9 | #include "string.h" // memset16_far 10 | #include "bochsvga.h" // VBE_BOCHS_* 11 | #include "hw/pci.h" // pci_config_readl 12 | #include "hw/pci_regs.h" // PCI_BASE_ADDRESS_0 13 | #include "vgabios.h" // SET_VGA 14 | #include "vgautil.h" // VBE_total_memory 15 | 16 | #define FRAMEBUFFER_WIDTH 1024 17 | #define FRAMEBUFFER_HEIGHT 768 18 | #define FRAMEBUFFER_BPP 4 19 | 20 | int 21 | bochs_display_setup(void) 22 | { 23 | dprintf(1, "bochs-display: setup called\n"); 24 | 25 | if (GET_GLOBAL(HaveRunInit)) 26 | return 0; 27 | 28 | int bdf = GET_GLOBAL(VgaBDF); 29 | if (bdf == 0) 30 | return 0; 31 | 32 | u32 bar = pci_config_readl(bdf, PCI_BASE_ADDRESS_0); 33 | u32 lfb_addr = bar & PCI_BASE_ADDRESS_MEM_MASK; 34 | bar = pci_config_readl(bdf, PCI_BASE_ADDRESS_2); 35 | u32 io_addr = bar & PCI_BASE_ADDRESS_IO_MASK; 36 | dprintf(1, "bochs-display: bdf %02x:%02x.%x, bar 0 at 0x%x, bar 1 at 0x%x\n" 37 | , pci_bdf_to_bus(bdf) , pci_bdf_to_dev(bdf), pci_bdf_to_fn(bdf), 38 | lfb_addr, io_addr); 39 | 40 | u16 *dispi = (void*)(io_addr + 0x500); 41 | u8 *vga = (void*)(io_addr + 0x400); 42 | u16 id = readw(dispi + VBE_DISPI_INDEX_ID); 43 | dprintf(1, "bochs-display: id is 0x%x, %s\n", id 44 | , id == VBE_DISPI_ID5 ? "good" : "FAIL"); 45 | if (id != VBE_DISPI_ID5) 46 | return -1; 47 | 48 | int i; 49 | u8 *edid = (void*)(io_addr); 50 | for (i = 0; i < sizeof(VBE_edid); i++) 51 | SET_VGA(VBE_edid[i], readb(edid + i)); 52 | 53 | int fb_width = FRAMEBUFFER_WIDTH; 54 | int fb_height = FRAMEBUFFER_HEIGHT; 55 | if (GET_GLOBAL(VBE_edid[0]) == 0x00 && 56 | GET_GLOBAL(VBE_edid[1]) == 0xff) { 57 | fb_width = GET_GLOBAL(VBE_edid[54 + 2]); 58 | fb_width |= (GET_GLOBAL(VBE_edid[54 + 4]) & 0xf0) << 4; 59 | fb_height = GET_GLOBAL(VBE_edid[54 + 5]); 60 | fb_height |= (GET_GLOBAL(VBE_edid[54 + 7]) & 0xf0) << 4; 61 | } 62 | int fb_stride = FRAMEBUFFER_BPP * fb_width; 63 | 64 | dprintf(1, "bochs-display: using %dx%d, %d bpp (%d stride)\n" 65 | , fb_width, fb_height 66 | , FRAMEBUFFER_BPP * 8, fb_stride); 67 | 68 | cbvga_setup_modes(lfb_addr, FRAMEBUFFER_BPP * 8, 69 | fb_width, fb_height, fb_stride); 70 | 71 | writew(dispi + VBE_DISPI_INDEX_XRES, fb_width); 72 | writew(dispi + VBE_DISPI_INDEX_YRES, fb_height); 73 | writew(dispi + VBE_DISPI_INDEX_BPP, FRAMEBUFFER_BPP * 8); 74 | writew(dispi + VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED); 75 | 76 | writeb(vga, 0x20); /* unblank (for qemu -device VGA) */ 77 | 78 | return 0; 79 | } 80 | -------------------------------------------------------------------------------- /vgasrc/bochsvga.h: -------------------------------------------------------------------------------- 1 | #ifndef __BOCHSVGA_H 2 | #define __BOCHSVGA_H 3 | 4 | #include "types.h" // u8 5 | 6 | #define VBE_DISPI_BANK_ADDRESS 0xA0000 7 | #define VBE_DISPI_BANK_SIZE_KB 64 8 | 9 | #define VBE_DISPI_MAX_XRES 2560 10 | #define VBE_DISPI_MAX_YRES 1600 11 | 12 | #define VBE_DISPI_IOPORT_INDEX 0x01CE 13 | #define VBE_DISPI_IOPORT_DATA 0x01CF 14 | 15 | #define VBE_DISPI_INDEX_ID 0x0 16 | #define VBE_DISPI_INDEX_XRES 0x1 17 | #define VBE_DISPI_INDEX_YRES 0x2 18 | #define VBE_DISPI_INDEX_BPP 0x3 19 | #define VBE_DISPI_INDEX_ENABLE 0x4 20 | #define VBE_DISPI_INDEX_BANK 0x5 21 | #define VBE_DISPI_INDEX_VIRT_WIDTH 0x6 22 | #define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7 23 | #define VBE_DISPI_INDEX_X_OFFSET 0x8 24 | #define VBE_DISPI_INDEX_Y_OFFSET 0x9 25 | #define VBE_DISPI_INDEX_VIDEO_MEMORY_64K 0xa 26 | 27 | #define VBE_DISPI_ID0 0xB0C0 28 | #define VBE_DISPI_ID1 0xB0C1 29 | #define VBE_DISPI_ID2 0xB0C2 30 | #define VBE_DISPI_ID3 0xB0C3 31 | #define VBE_DISPI_ID4 0xB0C4 32 | #define VBE_DISPI_ID5 0xB0C5 33 | 34 | #define VBE_DISPI_DISABLED 0x00 35 | #define VBE_DISPI_ENABLED 0x01 36 | #define VBE_DISPI_GETCAPS 0x02 37 | #define VBE_DISPI_8BIT_DAC 0x20 38 | #define VBE_DISPI_LFB_ENABLED 0x40 39 | #define VBE_DISPI_NOCLEARMEM 0x80 40 | 41 | #define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE0000000 42 | 43 | struct vgamode_s *bochsvga_find_mode(int mode); 44 | void bochsvga_list_modes(u16 seg, u16 *dest, u16 *last); 45 | int bochsvga_get_window(struct vgamode_s *curmode_g, int window); 46 | int bochsvga_set_window(struct vgamode_s *curmode_g, int window, int val); 47 | int bochsvga_get_linelength(struct vgamode_s *curmode_g); 48 | int bochsvga_set_linelength(struct vgamode_s *curmode_g, int val); 49 | int bochsvga_get_displaystart(struct vgamode_s *curmode_g); 50 | int bochsvga_set_displaystart(struct vgamode_s *curmode_g, int val); 51 | int bochsvga_get_dacformat(struct vgamode_s *curmode_g); 52 | int bochsvga_set_dacformat(struct vgamode_s *curmode_g, int val); 53 | int bochsvga_save_restore(int cmd, u16 seg, void *data); 54 | int bochsvga_set_mode(struct vgamode_s *vmode_g, int flags); 55 | int bochsvga_setup(void); 56 | 57 | #endif // bochsvga.h 58 | -------------------------------------------------------------------------------- /vgasrc/geodevga.h: -------------------------------------------------------------------------------- 1 | // Geode GX2/LX VGA functions 2 | // 3 | // Copyright (C) 2009 Chris Kindt 4 | // 5 | // Written for Google Summer of Code 2009 for the coreboot project 6 | // 7 | // This file may be distributed under the terms of the GNU LGPLv3 license. 8 | 9 | #ifndef GEODEVGA_H 10 | #define GEODEVGA_H 11 | 12 | #define VRC_INDEX 0xAC1C // Index register 13 | #define VRC_DATA 0xAC1E // Data register 14 | #define VR_UNLOCK 0xFC53 // Virtual register unlock code 15 | 16 | // Graphics-specific registers: 17 | #define OEM_BAR0 0x50 18 | #define OEM_BAR1 0x54 19 | #define OEM_BAR2 0x58 20 | #define OEM_BAR3 0x5C 21 | 22 | #define DC_LOCK_LOCK 0x00000000 23 | #define DC_LOCK_UNLOCK 0x00004758 24 | 25 | /* LX MSRs */ 26 | #define MSR_GLIU0 (1 << 28) 27 | #define MSR_GLIU0_BASE4 (MSR_GLIU0 + 0x23) /* LX */ 28 | #define GLIU0_P2D_BM_4 (MSR_GLIU0 + 0x24) /* GX2 */ 29 | #define GLIU0_P2D_RO (MSR_GLIU0 + 0x29) 30 | #define GLIU0_IOD_BM_0 (MSR_GLIU0 + 0xE0) 31 | #define GLIU0_IOD_BM_1 (MSR_GLIU0 + 0xE1) 32 | #define DC_SPARE 0x80000011 33 | #define VP_MSR_CONFIG_GX2 0xc0002001 /* GX2 */ 34 | #define VP_MSR_CONFIG_LX 0x48002001 /* LX */ 35 | #define VP_MSR_PADSEL 0x48002011 36 | 37 | #define VP_MSR_PADSEL_TFT_SEL_LOW 0xDFFFFFFF 38 | #define VP_MSR_PADSEL_TFT_SEL_HIGH 0x0000003F 39 | 40 | /* VP_MSR_CONFIG bits */ 41 | #define VP_MSR_CONFIG_FMT_CRT (0) 42 | #define VP_MSR_CONFIG_FMT_FP (1 << 3) 43 | #define VP_MSR_CONFIG_FPC (1 << 15) 44 | #define VP_MSR_CONFIG_FMT ((1 << 3) | (1 << 4) | (1 << 5)) 45 | 46 | 47 | /* DC REG OFFSET */ 48 | #define DC_UNLOCK 0x0 49 | #define DC_GENERAL_CFG 0x4 50 | #define DC_DISPLAY_CFG 0x8 51 | #define DC_FB_ST_OFFSET 0x10 52 | #define DC_CB_ST_OFFSET 0x14 53 | #define DC_CURS_ST_OFFSET 0x18 54 | #define DC_GLIU0_MEM_OFFSET 0x84 55 | 56 | /* VP REG OFFSET */ 57 | #define VP_VCFG 0x0 58 | #define VP_DCFG 0x8 59 | #define VP_MISC 0x50 60 | 61 | /* FP REG OFFSET */ 62 | #define FP_PT1 0x00 63 | #define FP_PT2 0x08 64 | #define FP_PM 0x10 65 | 66 | 67 | /* DC bits */ 68 | #define DC_GENERAL_CFG_VGAE (1 << 7) 69 | #define DC_DISPLAY_CFG_GDEN (1 << 3) 70 | #define DC_DISPLAY_CFG_TRUP (1 << 6) 71 | 72 | /* VP bits */ 73 | #define VP_DCFG_CRT_EN (1 << 0) 74 | #define VP_DCFG_HSYNC_EN (1 << 1) 75 | #define VP_DCFG_VSYNC_EN (1 << 2) 76 | #define VP_DCFG_DAC_BL_EN (1 << 3) 77 | #define VP_DCFG_CRT_SKEW (1 << 16) 78 | #define VP_DCFG_BYP_BOTH (1 << 0) 79 | 80 | /* FP bits */ 81 | #define FP_PM_P (1 << 24) /* panel power ctl */ 82 | #define FP_PT2_SCRC (1 << 27) /* panel shift clock retrace activity ctl */ 83 | 84 | /* Mask */ 85 | #define DC_CFG_MSK 0xf000a6 86 | 87 | int geodevga_setup(); 88 | 89 | #endif 90 | -------------------------------------------------------------------------------- /vgasrc/stdvgaio.c: -------------------------------------------------------------------------------- 1 | // Standard VGA IO port access 2 | // 3 | // Copyright (C) 2012 Kevin O'Connor 4 | // 5 | // This file may be distributed under the terms of the GNU LGPLv3 license. 6 | 7 | #include "farptr.h" // GET_FARVAR 8 | #include "stdvga.h" // VGAREG_PEL_MASK 9 | #include "x86.h" // inb 10 | 11 | u8 12 | stdvga_pelmask_read(void) 13 | { 14 | return inb(VGAREG_PEL_MASK); 15 | } 16 | 17 | void 18 | stdvga_pelmask_write(u8 value) 19 | { 20 | outb(value, VGAREG_PEL_MASK); 21 | } 22 | 23 | 24 | u8 25 | stdvga_misc_read(void) 26 | { 27 | return inb(VGAREG_READ_MISC_OUTPUT); 28 | } 29 | 30 | void 31 | stdvga_misc_write(u8 value) 32 | { 33 | outb(value, VGAREG_WRITE_MISC_OUTPUT); 34 | } 35 | 36 | void 37 | stdvga_misc_mask(u8 off, u8 on) 38 | { 39 | stdvga_misc_write((stdvga_misc_read() & ~off) | on); 40 | } 41 | 42 | 43 | u8 44 | stdvga_sequ_read(u8 index) 45 | { 46 | outb(index, VGAREG_SEQU_ADDRESS); 47 | return inb(VGAREG_SEQU_DATA); 48 | } 49 | 50 | void 51 | stdvga_sequ_write(u8 index, u8 value) 52 | { 53 | outw((value<<8) | index, VGAREG_SEQU_ADDRESS); 54 | } 55 | 56 | void 57 | stdvga_sequ_mask(u8 index, u8 off, u8 on) 58 | { 59 | outb(index, VGAREG_SEQU_ADDRESS); 60 | u8 v = inb(VGAREG_SEQU_DATA); 61 | outb((v & ~off) | on, VGAREG_SEQU_DATA); 62 | } 63 | 64 | 65 | u8 66 | stdvga_grdc_read(u8 index) 67 | { 68 | outb(index, VGAREG_GRDC_ADDRESS); 69 | return inb(VGAREG_GRDC_DATA); 70 | } 71 | 72 | void 73 | stdvga_grdc_write(u8 index, u8 value) 74 | { 75 | outw((value<<8) | index, VGAREG_GRDC_ADDRESS); 76 | } 77 | 78 | void 79 | stdvga_grdc_mask(u8 index, u8 off, u8 on) 80 | { 81 | outb(index, VGAREG_GRDC_ADDRESS); 82 | u8 v = inb(VGAREG_GRDC_DATA); 83 | outb((v & ~off) | on, VGAREG_GRDC_DATA); 84 | } 85 | 86 | 87 | u8 88 | stdvga_crtc_read(u16 crtc_addr, u8 index) 89 | { 90 | outb(index, crtc_addr); 91 | return inb(crtc_addr + 1); 92 | } 93 | 94 | void 95 | stdvga_crtc_write(u16 crtc_addr, u8 index, u8 value) 96 | { 97 | outw((value<<8) | index, crtc_addr); 98 | } 99 | 100 | void 101 | stdvga_crtc_mask(u16 crtc_addr, u8 index, u8 off, u8 on) 102 | { 103 | outb(index, crtc_addr); 104 | u8 v = inb(crtc_addr + 1); 105 | outb((v & ~off) | on, crtc_addr + 1); 106 | } 107 | 108 | 109 | u8 110 | stdvga_attr_read(u8 index) 111 | { 112 | inb(VGAREG_ACTL_RESET); 113 | u8 orig = inb(VGAREG_ACTL_ADDRESS); 114 | outb(index, VGAREG_ACTL_ADDRESS); 115 | u8 v = inb(VGAREG_ACTL_READ_DATA); 116 | inb(VGAREG_ACTL_RESET); 117 | outb(orig, VGAREG_ACTL_ADDRESS); 118 | return v; 119 | } 120 | 121 | void 122 | stdvga_attr_write(u8 index, u8 value) 123 | { 124 | inb(VGAREG_ACTL_RESET); 125 | u8 orig = inb(VGAREG_ACTL_ADDRESS); 126 | outb(index, VGAREG_ACTL_ADDRESS); 127 | outb(value, VGAREG_ACTL_WRITE_DATA); 128 | outb(orig, VGAREG_ACTL_ADDRESS); 129 | } 130 | 131 | void 132 | stdvga_attr_mask(u8 index, u8 off, u8 on) 133 | { 134 | inb(VGAREG_ACTL_RESET); 135 | u8 orig = inb(VGAREG_ACTL_ADDRESS); 136 | outb(index, VGAREG_ACTL_ADDRESS); 137 | u8 v = inb(VGAREG_ACTL_READ_DATA); 138 | outb((v & ~off) | on, VGAREG_ACTL_WRITE_DATA); 139 | outb(orig, VGAREG_ACTL_ADDRESS); 140 | } 141 | 142 | u8 143 | stdvga_attrindex_read(void) 144 | { 145 | inb(VGAREG_ACTL_RESET); 146 | return inb(VGAREG_ACTL_ADDRESS); 147 | } 148 | 149 | void 150 | stdvga_attrindex_write(u8 value) 151 | { 152 | inb(VGAREG_ACTL_RESET); 153 | outb(value, VGAREG_ACTL_ADDRESS); 154 | } 155 | 156 | 157 | struct vbe_palette_entry 158 | stdvga_dac_read(u8 color) 159 | { 160 | outb(color, VGAREG_DAC_READ_ADDRESS); 161 | u8 r = inb(VGAREG_DAC_DATA); 162 | u8 g = inb(VGAREG_DAC_DATA); 163 | u8 b = inb(VGAREG_DAC_DATA); 164 | return (struct vbe_palette_entry){ .red=r, .green=g, .blue=b }; 165 | } 166 | 167 | void 168 | stdvga_dac_write(u8 color, struct vbe_palette_entry rgb) 169 | { 170 | outb(color, VGAREG_DAC_WRITE_ADDRESS); 171 | outb(rgb.red, VGAREG_DAC_DATA); 172 | outb(rgb.green, VGAREG_DAC_DATA); 173 | outb(rgb.blue, VGAREG_DAC_DATA); 174 | } 175 | -------------------------------------------------------------------------------- /vgasrc/svgamodes.h: -------------------------------------------------------------------------------- 1 | #ifndef __SVGAMODES_H 2 | #define __SVGAMODES_H 3 | 4 | struct generic_svga_mode { 5 | u16 mode; 6 | struct vgamode_s info; 7 | }; 8 | 9 | extern struct generic_svga_mode svga_modes[]; 10 | extern unsigned int svga_mcount; 11 | 12 | #endif /* __SVGAMODES_H */ 13 | -------------------------------------------------------------------------------- /vgasrc/swcursor.c: -------------------------------------------------------------------------------- 1 | // Virtual software based cursor support 2 | // 3 | // Copyright (C) 2014-2016 Kevin O'Connor 4 | // 5 | // This file may be distributed under the terms of the GNU LGPLv3 license. 6 | 7 | #include "biosvar.h" // GET_BDA 8 | #include "bregs.h" // struct bregs 9 | #include "vgabios.h" // get_cursor_pos 10 | #include "vgafb.h" // handle_gfx_op 11 | #include "vgautil.h" // swcursor_check_event 12 | 13 | // Draw/undraw a cursor on the framebuffer by xor'ing the cursor cell 14 | static void 15 | gfx_set_swcursor(struct vgamode_s *curmode_g, int enable, struct cursorpos cp) 16 | { 17 | u16 cursor_type = get_cursor_shape(); 18 | u8 start = cursor_type >> 8, end = cursor_type & 0xff; 19 | struct gfx_op op; 20 | init_gfx_op(&op, curmode_g); 21 | op.x = cp.x * 8; 22 | int cheight = GET_BDA(char_height); 23 | op.y = cp.y * cheight + start; 24 | 25 | int i; 26 | for (i = start; i < cheight && i <= end; i++, op.y++) { 27 | op.op = GO_READ8; 28 | handle_gfx_op(&op); 29 | int j; 30 | for (j = 0; j < 8; j++) 31 | op.pixels[j] ^= 0x07; 32 | op.op = GO_WRITE8; 33 | handle_gfx_op(&op); 34 | } 35 | } 36 | 37 | // Draw/undraw a cursor on the screen 38 | static void 39 | set_swcursor(int enable) 40 | { 41 | u8 flags = GET_BDA_EXT(flags); 42 | if (!!(flags & BF_SWCURSOR) == enable) 43 | // Already in requested mode. 44 | return; 45 | struct vgamode_s *curmode_g = get_current_mode(); 46 | if (!curmode_g) 47 | return; 48 | struct cursorpos cp = get_cursor_pos(GET_BDA(video_page)); 49 | if (cp.x >= GET_BDA(video_cols) || cp.y > GET_BDA(video_rows) 50 | || GET_BDA(cursor_type) >= 0x2000) 51 | // Cursor not visible 52 | return; 53 | 54 | SET_BDA_EXT(flags, (flags & ~BF_SWCURSOR) | (enable ? BF_SWCURSOR : 0)); 55 | 56 | if (GET_GLOBAL(curmode_g->memmodel) != MM_TEXT) { 57 | gfx_set_swcursor(curmode_g, enable, cp); 58 | return; 59 | } 60 | 61 | // In text mode, swap foreground and background attributes for cursor 62 | void *dest_far = text_address(cp) + 1; 63 | u8 attr = GET_FARVAR(GET_GLOBAL(curmode_g->sstart), *(u8*)dest_far); 64 | attr = (attr >> 4) | (attr << 4); 65 | SET_FARVAR(GET_GLOBAL(curmode_g->sstart), *(u8*)dest_far, attr); 66 | } 67 | 68 | // Disable virtual cursor if a vgabios call accesses the framebuffer 69 | void 70 | swcursor_pre_handle10(struct bregs *regs) 71 | { 72 | if (!vga_emulate_text()) 73 | return; 74 | switch (regs->ah) { 75 | case 0x4f: 76 | if (!CONFIG_VGA_VBE || regs->al != 0x02) 77 | break; 78 | // NO BREAK 79 | case 0x00 ... 0x02: 80 | case 0x05 ... 0x0e: 81 | case 0x13: 82 | set_swcursor(0); 83 | break; 84 | default: 85 | break; 86 | } 87 | } 88 | 89 | // Called by periodic (18.2hz) timer 90 | void 91 | swcursor_check_event(void) 92 | { 93 | if (!vga_emulate_text()) 94 | return; 95 | set_swcursor(GET_BDA(timer_counter) % 18 < 9); 96 | } 97 | -------------------------------------------------------------------------------- /vgasrc/vgabios.h: -------------------------------------------------------------------------------- 1 | #ifndef __VGABIOS_H 2 | #define __VGABIOS_H 3 | 4 | #include "config.h" // CONFIG_VGA_EMULATE_TEXT 5 | #include "farptr.h" // GET_FARVAR 6 | #include "types.h" // u8 7 | 8 | // Save/Restore flags 9 | #define SR_HARDWARE 0x0001 10 | #define SR_BDA 0x0002 11 | #define SR_DAC 0x0004 12 | #define SR_REGISTERS 0x0008 13 | #define SR_SAVE 0x0100 14 | #define SR_RESTORE 0x0200 15 | 16 | // Mode flags 17 | #define MF_LEGACY 0x0001 18 | #define MF_GRAYSUM 0x0002 19 | #define MF_NOPALETTE 0x0008 20 | #define MF_CUSTOMCRTC 0x0800 21 | #define MF_LINEARFB 0x4000 22 | #define MF_NOCLEARMEM 0x8000 23 | #define MF_VBEFLAGS 0xfe00 24 | 25 | // Memory model types 26 | #define MM_TEXT 0x00 27 | #define MM_CGA 0x01 28 | #define MM_HERCULES 0x02 29 | #define MM_PLANAR 0x03 30 | #define MM_PACKED 0x04 31 | #define MM_NON_CHAIN_4_256 0x05 32 | #define MM_DIRECT 0x06 33 | #define MM_YUV 0x07 34 | 35 | struct vgamode_s { 36 | u8 memmodel; 37 | u16 width; 38 | u16 height; 39 | u8 depth; 40 | u8 cwidth; 41 | u8 cheight; 42 | u16 sstart; 43 | }; 44 | 45 | // Custom internal storage in BDA (don't change here without also 46 | // updating vgaentry.S) 47 | #define VGA_CUSTOM_BDA 0xb9 48 | 49 | struct vga_bda_s { 50 | u8 flags; 51 | u16 vbe_mode; 52 | u16 vgamode_offset; 53 | } PACKED; 54 | 55 | #define BF_PM_MASK 0x0f 56 | #define BF_EMULATE_TEXT 0x10 57 | #define BF_SWCURSOR 0x20 58 | #define BF_EXTRA_STACK 0x40 59 | 60 | #define GET_BDA_EXT(var) \ 61 | GET_FARVAR(SEG_BDA, ((struct vga_bda_s *)VGA_CUSTOM_BDA)->var) 62 | #define SET_BDA_EXT(var, val) \ 63 | SET_FARVAR(SEG_BDA, ((struct vga_bda_s *)VGA_CUSTOM_BDA)->var, (val)) 64 | #define MASK_BDA_EXT(var, off, on) \ 65 | SET_BDA_EXT(var, (GET_BDA_EXT(var) & ~(off)) | (on)) 66 | 67 | static inline int vga_emulate_text(void) { 68 | return CONFIG_VGA_EMULATE_TEXT && GET_BDA_EXT(flags) & BF_EMULATE_TEXT; 69 | } 70 | 71 | // Write to global variables (during "post" phase only) 72 | #define SET_VGA(var, val) SET_FARVAR(get_global_seg(), (var), (val)) 73 | 74 | // Debug settings 75 | #define DEBUG_VGA_POST 1 76 | #define DEBUG_VGA_10 9 77 | 78 | // vgabios.c 79 | int vga_bpp(struct vgamode_s *vmode_g); 80 | u16 calc_page_size(u8 memmodel, u16 width, u16 height); 81 | u16 get_cursor_shape(void); 82 | struct cursorpos get_cursor_pos(u8 page); 83 | int bda_save_restore(int cmd, u16 seg, void *data); 84 | struct vgamode_s *get_current_mode(void); 85 | int vga_set_mode(int mode, int flags); 86 | extern struct video_func_static static_functionality; 87 | 88 | #endif // vgabios.h 89 | -------------------------------------------------------------------------------- /vgasrc/vgafb.h: -------------------------------------------------------------------------------- 1 | #ifndef __VGAFB_H 2 | #define __VGAFB_H 3 | 4 | // Graphics pixel operations. 5 | struct gfx_op { 6 | struct vgamode_s *curmode_g; 7 | u32 linelength; 8 | u32 displaystart; 9 | 10 | u8 op; 11 | u16 x, y; 12 | 13 | u8 pixels[8]; 14 | u16 xlen, ylen; 15 | u16 srcy; 16 | }; 17 | 18 | #define GO_READ8 1 19 | #define GO_WRITE8 2 20 | #define GO_MEMSET 3 21 | #define GO_MEMMOVE 4 22 | 23 | struct cursorpos { 24 | u8 x, y, page, pad; 25 | }; 26 | 27 | struct carattr { 28 | u8 car, attr, use_attr, pad; 29 | }; 30 | 31 | // vgafb.c 32 | void memcpy_high(void *dest, void *src, u32 len); 33 | void init_gfx_op(struct gfx_op *op, struct vgamode_s *curmode_g); 34 | void handle_gfx_op(struct gfx_op *op); 35 | void *text_address(struct cursorpos cp); 36 | void vgafb_scroll(struct cursorpos win, struct cursorpos winsize 37 | , int lines, struct carattr ca); 38 | void vgafb_write_char(struct cursorpos cp, struct carattr ca); 39 | struct carattr vgafb_read_char(struct cursorpos cp); 40 | void vgafb_write_pixel(u8 color, u16 x, u16 y); 41 | u8 vgafb_read_pixel(u16 x, u16 y); 42 | 43 | #endif // vgafb.h 44 | -------------------------------------------------------------------------------- /vgasrc/vgalayout.lds.S: -------------------------------------------------------------------------------- 1 | // Linker definitions for an option rom 2 | // 3 | // Copyright (C) 2009 Kevin O'Connor 4 | // 5 | // This file may be distributed under the terms of the GNU LGPLv3 license. 6 | 7 | OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") 8 | OUTPUT_ARCH("i386") 9 | ENTRY(_optionrom_entry) 10 | SECTIONS 11 | { 12 | .text 0 : { 13 | KEEP(*(.rom.header)) 14 | *(.text.*) 15 | _rodata = . ; 16 | *(.rodata*) 17 | *(.data16.*) 18 | } 19 | 20 | // Discard regular data sections to force a link error if 21 | // 16bit code attempts to access data not marked with VAR16. 22 | /DISCARD/ : { 23 | *(.text*) 24 | *(.rodata*) 25 | *(.data*) 26 | *(.bss*) 27 | *(COMMON) 28 | *(.note*) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /vgasrc/vgautil.h: -------------------------------------------------------------------------------- 1 | // Misc function and variable declarations. 2 | #ifndef __VGAUTIL_H 3 | #define __VGAUTIL_H 4 | 5 | #include "types.h" // u8 6 | 7 | // cbvga.c 8 | struct vgamode_s *cbvga_find_mode(int mode); 9 | void cbvga_list_modes(u16 seg, u16 *dest, u16 *last); 10 | int cbvga_get_window(struct vgamode_s *curmode_g, int window); 11 | int cbvga_set_window(struct vgamode_s *curmode_g, int window, int val); 12 | int cbvga_minimum_linelength(struct vgamode_s *vmode_g); 13 | int cbvga_get_linelength(struct vgamode_s *curmode_g); 14 | int cbvga_set_linelength(struct vgamode_s *curmode_g, int val); 15 | int cbvga_get_displaystart(struct vgamode_s *curmode_g); 16 | int cbvga_set_displaystart(struct vgamode_s *curmode_g, int val); 17 | int cbvga_get_dacformat(struct vgamode_s *curmode_g); 18 | int cbvga_set_dacformat(struct vgamode_s *curmode_g, int val); 19 | int cbvga_save_restore(int cmd, u16 seg, void *data); 20 | int cbvga_set_mode(struct vgamode_s *vmode_g, int flags); 21 | void cbvga_setup_modes(u64 addr, u8 bpp, u32 xlines, u32 ylines, u32 linelength); 22 | int cbvga_setup(void); 23 | 24 | // bochsdisplay.c 25 | int bochs_display_setup(void); 26 | 27 | // ramfb.c 28 | int ramfb_setup(void); 29 | 30 | // clext.c 31 | struct vgamode_s *clext_find_mode(int mode); 32 | void clext_list_modes(u16 seg, u16 *dest, u16 *last); 33 | int clext_get_window(struct vgamode_s *curmode_g, int window); 34 | int clext_set_window(struct vgamode_s *curmode_g, int window, int val); 35 | int clext_get_linelength(struct vgamode_s *curmode_g); 36 | int clext_set_linelength(struct vgamode_s *curmode_g, int val); 37 | int clext_get_displaystart(struct vgamode_s *curmode_g); 38 | int clext_set_displaystart(struct vgamode_s *curmode_g, int val); 39 | int clext_save_restore(int cmd, u16 seg, void *data); 40 | int clext_set_mode(struct vgamode_s *vmode_g, int flags); 41 | struct bregs; 42 | void clext_1012(struct bregs *regs); 43 | int clext_setup(void); 44 | 45 | // atiext.c 46 | struct vgamode_s *ati_find_mode(int mode); 47 | void ati_list_modes(u16 seg, u16 *dest, u16 *last); 48 | int ati_set_mode(struct vgamode_s *vmode_g, int flags); 49 | int ati_setup(void); 50 | 51 | // stdvgamodes.c 52 | struct vgamode_s *stdvga_find_mode(int mode); 53 | void stdvga_list_modes(u16 seg, u16 *dest, u16 *last); 54 | void stdvga_build_video_param(void); 55 | void stdvga_override_crtc(int mode, u8 *crtc); 56 | int stdvga_set_mode(struct vgamode_s *vmode_g, int flags); 57 | void stdvga_set_packed_palette(void); 58 | 59 | // swcursor.c 60 | void swcursor_pre_handle10(struct bregs *regs); 61 | void swcursor_check_event(void); 62 | 63 | // vbe.c 64 | extern u32 VBE_total_memory; 65 | extern u32 VBE_capabilities; 66 | extern u32 VBE_framebuffer; 67 | extern u16 VBE_win_granularity; 68 | extern u8 VBE_edid[256]; 69 | void handle_104f(struct bregs *regs); 70 | 71 | // vgafonts.c 72 | extern u8 vgafont8[]; 73 | extern u8 vgafont14[]; 74 | extern u8 vgafont16[]; 75 | extern u8 vgafont14alt[]; 76 | extern u8 vgafont16alt[]; 77 | 78 | // vgainit.c 79 | extern int VgaBDF; 80 | extern int HaveRunInit; 81 | u32 allocate_pmm(u32 size, int highmem, int aligned); 82 | 83 | // vgaversion.c 84 | extern const char VERSION[], BUILDINFO[]; 85 | 86 | #endif // vgautil.h 87 | -------------------------------------------------------------------------------- /vgasrc/vgaversion.c: -------------------------------------------------------------------------------- 1 | // Place build generated version into a C variable 2 | #include "autovgaversion.h" 3 | #include "types.h" 4 | 5 | char VERSION[] VAR16 = BUILD_VERSION; 6 | char BUILDINFO[] VAR16 = BUILD_TOOLS; 7 | --------------------------------------------------------------------------------