├── .gitignore ├── CHANGELOG.md ├── 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 ├── fmap.c ├── fmap.h ├── font.c ├── fw │ ├── acpi-dsdt-cpu-hotplug.dsl │ ├── acpi-dsdt-dbug.dsl │ ├── acpi-dsdt-hpet.dsl │ ├── acpi-dsdt-isa.dsl │ ├── acpi-dsdt-pci-crs.dsl │ ├── acpi-dsdt.dsl │ ├── acpi-dsdt.hex │ ├── acpi.c │ ├── biostables.c │ ├── coreboot.c │ ├── coreboot.h │ ├── csm.c │ ├── dev-pci.h │ ├── dev-piix.h │ ├── dev-q35.h │ ├── dsdt_parser.c │ ├── lib_vpd.c │ ├── lib_vpd.h │ ├── lzmadecode.c │ ├── lzmadecode.h │ ├── mptable.c │ ├── mtrr.c │ ├── multiboot.c │ ├── paravirt.c │ ├── paravirt.h │ ├── pciinit.c │ ├── pirtable.c │ ├── q35-acpi-dsdt.dsl │ ├── romfile_loader.c │ ├── romfile_loader.h │ ├── shadow.c │ ├── smbios.c │ ├── smm.c │ ├── smp.c │ ├── ssdt-misc.dsl │ ├── ssdt-misc.hex │ ├── ssdt-pcihp.dsl │ ├── ssdt-pcihp.hex │ ├── ssdt-proc.dsl │ ├── ssdt-proc.hex │ ├── vpd.c │ ├── vpd.h │ ├── vpd_tables.h │ ├── 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 | 19 | 20 | Issues 21 | ------- 22 | 23 | If you have any trouble or find any bug, please report an issue in 24 | this location: 25 | 26 | https://github.com/pcengines/apu2-documentation/issues). 27 | 28 | To create the issue, from the list of available templates select the one, that fits 29 | best the nature of the issue (bug, feature, question or task) and fill it. 30 | -------------------------------------------------------------------------------- /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/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/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/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_10 20 81 | #define DEBUG_HDL_11 2 82 | #define DEBUG_HDL_12 2 83 | #define DEBUG_HDL_13 10 84 | #define DEBUG_HDL_14 2 85 | #define DEBUG_HDL_15 9 86 | #define DEBUG_HDL_16 9 87 | #define DEBUG_HDL_17 2 88 | #define DEBUG_HDL_18 1 89 | #define DEBUG_HDL_19 1 90 | #define DEBUG_HDL_1a 9 91 | #define DEBUG_HDL_40 1 92 | #define DEBUG_ISR_70 9 93 | #define DEBUG_ISR_74 9 94 | #define DEBUG_ISR_75 1 95 | #define DEBUG_ISR_76 10 96 | #define DEBUG_ISR_hwpic1 5 97 | #define DEBUG_ISR_hwpic2 5 98 | #define DEBUG_HDL_smi 9 99 | #define DEBUG_HDL_smp 1 100 | #define DEBUG_HDL_pnp 1 101 | #define DEBUG_HDL_pmm 1 102 | #define DEBUG_HDL_pcibios 9 103 | #define DEBUG_HDL_apm 9 104 | 105 | #define DEBUG_unimplemented 2 106 | #define DEBUG_invalid 3 107 | #define DEBUG_thread 2 108 | #define DEBUG_tcg 20 109 | 110 | #endif // config.h 111 | -------------------------------------------------------------------------------- /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 | extern void coreboot_update_memtable(void); 28 | 29 | #endif // e820map.h 30 | -------------------------------------------------------------------------------- /src/fmap.c: -------------------------------------------------------------------------------- 1 | // Flashmap support. 2 | // 3 | // Copyright (C) 2019 3mdeb 4 | // 5 | // This file may be distributed under the terms of the GNU LGPLv3 license. 6 | 7 | #include "malloc.h" // malloc 8 | #include "string.h" // memcpy 9 | #include "output.h" // dprintf 10 | #include "util.h" // find_cb_subtable 11 | #include "fmap.h" // find_fmap_directory 12 | 13 | static void* fmap_entry = NULL; 14 | static void* rom_begin = NULL; 15 | 16 | #define ROM_END ((void *)0xFFFFFFFF) 17 | 18 | #define CB_TAG_BOOT_MEDIA_PARAMS 0x0030 19 | 20 | struct cb_boot_media_params { 21 | u32 tag; 22 | u32 size; 23 | /* offsets are relative to start of boot media */ 24 | u64 fmap_offset; 25 | u64 cbfs_offset; 26 | u64 cbfs_size; 27 | u64 boot_media_size; 28 | }; 29 | 30 | void find_fmap_directory(void) 31 | { 32 | struct cb_boot_media_params *cbbmp; 33 | 34 | // Find coreboot table. 35 | struct cb_header *cbh = find_cb_table(); 36 | 37 | if (!cbh) { 38 | dprintf(1, "coreboot table not found\n"); 39 | return; 40 | } 41 | 42 | cbbmp = find_cb_subtable(cbh, CB_TAG_BOOT_MEDIA_PARAMS); 43 | 44 | if (!cbbmp) { 45 | dprintf(1, "Boot Media Params not found\n"); 46 | return; 47 | } 48 | 49 | if (cbbmp->fmap_offset != 0 && cbbmp->boot_media_size != 0) { 50 | rom_begin = (void *)(ROM_END - cbbmp->boot_media_size + 1); 51 | fmap_entry = (void *)((u32)rom_begin + (u32)cbbmp->fmap_offset); 52 | dprintf(1, "FMAP found @ %p\n", fmap_entry); 53 | } else { 54 | dprintf(1, "FMAP not found\n"); 55 | } 56 | } 57 | 58 | int fmap_locate_area(const char *name, struct region *ar) 59 | { 60 | size_t offset; 61 | 62 | if (!fmap_entry || !rom_begin) 63 | return -1; 64 | 65 | /* Start reading the areas just after fmap header. */ 66 | offset = sizeof(struct fmap); 67 | 68 | struct fmap_area *area = malloc_tmp(sizeof(*area)); 69 | if (!area) { 70 | warn_noalloc(); 71 | return -1; 72 | } 73 | 74 | while (1) { 75 | iomemcpy(area, fmap_entry + offset, sizeof(*area)); 76 | 77 | if (strcmp((const char *)area->name, name)) { 78 | offset += sizeof(struct fmap_area); 79 | continue; 80 | } 81 | 82 | dprintf(1, "FMAP: area %s found @ %p (%d bytes)\n", 83 | name, (void *) area->offset, area->size); 84 | 85 | ar->offset = (u32)rom_begin + area->offset; 86 | ar->size = area->size; 87 | free(area); 88 | return 0; 89 | } 90 | 91 | free(area); 92 | dprintf(1, "FMAP: area %s not found\n", name); 93 | 94 | return -1; 95 | } 96 | -------------------------------------------------------------------------------- /src/fmap.h: -------------------------------------------------------------------------------- 1 | // Flashmap support. 2 | // 3 | // Copyright (C) 2019 3mdeb 4 | // 5 | // This file may be distributed under the terms of the GNU LGPLv3 license. 6 | 7 | #ifndef _FMAP_H 8 | #define _FMAP_H 9 | 10 | #define FMAP_SIGNATURE "__FMAP__" 11 | #define FMAP_VER_MAJOR 1 /* this header's FMAP minor version */ 12 | #define FMAP_VER_MINOR 1 /* this header's FMAP minor version */ 13 | #define FMAP_STRLEN 32 /* maximum length for strings, */ 14 | /* including null-terminator */ 15 | 16 | enum fmap_flags { 17 | FMAP_AREA_STATIC = 1 << 0, 18 | FMAP_AREA_COMPRESSED = 1 << 1, 19 | FMAP_AREA_RO = 1 << 2, 20 | FMAP_AREA_PRESERVE = 1 << 3, 21 | }; 22 | 23 | /* Mapping of volatile and static regions in firmware binary */ 24 | struct fmap_area { 25 | u32 offset; /* offset relative to base */ 26 | u32 size; /* size in bytes */ 27 | u8 name[FMAP_STRLEN]; /* descriptive name */ 28 | u16 flags; /* flags for this area */ 29 | } PACKED; 30 | 31 | struct fmap { 32 | u8 signature[8]; /* "__FMAP__" (0x5F5F464D41505F5F) */ 33 | u8 ver_major; /* major version */ 34 | u8 ver_minor; /* minor version */ 35 | u64 base; /* address of the firmware binary */ 36 | u32 size; /* size of firmware binary in bytes */ 37 | u8 name[FMAP_STRLEN]; /* name of this firmware binary */ 38 | u16 nareas; /* number of areas described by 39 | fmap_areas[] below */ 40 | struct fmap_area areas[]; 41 | } PACKED; 42 | 43 | struct region { 44 | size_t offset; 45 | size_t size; 46 | }; 47 | 48 | void find_fmap_directory(void); 49 | int fmap_locate_area(const char *name, struct region *ar); 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /src/fw/acpi-dsdt-cpu-hotplug.dsl: -------------------------------------------------------------------------------- 1 | /**************************************************************** 2 | * CPU hotplug 3 | ****************************************************************/ 4 | 5 | Scope(\_SB) { 6 | /* Objects filled in by run-time generated SSDT */ 7 | External(NTFY, MethodObj) 8 | External(CPON, PkgObj) 9 | 10 | /* Methods called by run-time generated SSDT Processor objects */ 11 | Method(CPMA, 1, NotSerialized) { 12 | // _MAT method - create an madt apic buffer 13 | // Arg0 = Processor ID = Local APIC ID 14 | // Local0 = CPON flag for this cpu 15 | Store(DerefOf(Index(CPON, Arg0)), Local0) 16 | // Local1 = Buffer (in madt apic form) to return 17 | Store(Buffer(8) {0x00, 0x08, 0x00, 0x00, 0x00, 0, 0, 0}, Local1) 18 | // Update the processor id, lapic id, and enable/disable status 19 | Store(Arg0, Index(Local1, 2)) 20 | Store(Arg0, Index(Local1, 3)) 21 | Store(Local0, Index(Local1, 4)) 22 | Return (Local1) 23 | } 24 | Method(CPST, 1, NotSerialized) { 25 | // _STA method - return ON status of cpu 26 | // Arg0 = Processor ID = Local APIC ID 27 | // Local0 = CPON flag for this cpu 28 | Store(DerefOf(Index(CPON, Arg0)), Local0) 29 | If (Local0) { 30 | Return (0xF) 31 | } Else { 32 | Return (0x0) 33 | } 34 | } 35 | Method(CPEJ, 2, NotSerialized) { 36 | // _EJ0 method - eject callback 37 | Sleep(200) 38 | } 39 | 40 | /* CPU hotplug notify method */ 41 | OperationRegion(PRST, SystemIO, 0xaf00, 32) 42 | Field(PRST, ByteAcc, NoLock, Preserve) { 43 | PRS, 256 44 | } 45 | Method(PRSC, 0) { 46 | // Local5 = active cpu bitmap 47 | Store(PRS, Local5) 48 | // Local2 = last read byte from bitmap 49 | Store(Zero, Local2) 50 | // Local0 = Processor ID / APIC ID iterator 51 | Store(Zero, Local0) 52 | While (LLess(Local0, SizeOf(CPON))) { 53 | // Local1 = CPON flag for this cpu 54 | Store(DerefOf(Index(CPON, Local0)), Local1) 55 | If (And(Local0, 0x07)) { 56 | // Shift down previously read bitmap byte 57 | ShiftRight(Local2, 1, Local2) 58 | } Else { 59 | // Read next byte from cpu bitmap 60 | Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2) 61 | } 62 | // Local3 = active state for this cpu 63 | Store(And(Local2, 1), Local3) 64 | 65 | If (LNotEqual(Local1, Local3)) { 66 | // State change - update CPON with new state 67 | Store(Local3, Index(CPON, Local0)) 68 | // Do CPU notify 69 | If (LEqual(Local3, 1)) { 70 | NTFY(Local0, 1) 71 | } Else { 72 | NTFY(Local0, 3) 73 | } 74 | } 75 | Increment(Local0) 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/fw/acpi-dsdt-dbug.dsl: -------------------------------------------------------------------------------- 1 | /**************************************************************** 2 | * Debugging 3 | ****************************************************************/ 4 | 5 | Scope(\) { 6 | /* Debug Output */ 7 | OperationRegion(DBG, SystemIO, 0x0402, 0x01) 8 | Field(DBG, ByteAcc, NoLock, Preserve) { 9 | DBGB, 8, 10 | } 11 | 12 | /* Debug method - use this method to send output to the QEMU 13 | * BIOS debug port. This method handles strings, integers, 14 | * and buffers. For example: DBUG("abc") DBUG(0x123) */ 15 | Method(DBUG, 1) { 16 | ToHexString(Arg0, Local0) 17 | ToBuffer(Local0, Local0) 18 | Subtract(SizeOf(Local0), 1, Local1) 19 | Store(Zero, Local2) 20 | While (LLess(Local2, Local1)) { 21 | Store(DerefOf(Index(Local0, Local2)), DBGB) 22 | Increment(Local2) 23 | } 24 | Store(0x0A, DBGB) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/fw/acpi-dsdt-hpet.dsl: -------------------------------------------------------------------------------- 1 | /**************************************************************** 2 | * HPET 3 | ****************************************************************/ 4 | 5 | Scope(\_SB) { 6 | Device(HPET) { 7 | Name(_HID, EISAID("PNP0103")) 8 | Name(_UID, 0) 9 | OperationRegion(HPTM, SystemMemory, 0xFED00000, 0x400) 10 | Field(HPTM, DWordAcc, Lock, Preserve) { 11 | VEND, 32, 12 | PRD, 32, 13 | } 14 | Method(_STA, 0, NotSerialized) { 15 | Store(VEND, Local0) 16 | Store(PRD, Local1) 17 | ShiftRight(Local0, 16, Local0) 18 | If (LOr(LEqual(Local0, 0), LEqual(Local0, 0xffff))) { 19 | Return (0x0) 20 | } 21 | If (LOr(LEqual(Local1, 0), LGreater(Local1, 100000000))) { 22 | Return (0x0) 23 | } 24 | Return (0x0F) 25 | } 26 | Name(_CRS, ResourceTemplate() { 27 | #if 0 /* This makes WinXP BSOD for not yet figured reasons. */ 28 | IRQNoFlags() {2, 8} 29 | #endif 30 | Memory32Fixed(ReadOnly, 31 | 0xFED00000, // Address Base 32 | 0x00000400, // Address Length 33 | ) 34 | }) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/fw/acpi-dsdt-isa.dsl: -------------------------------------------------------------------------------- 1 | /* Common legacy ISA style devices. */ 2 | Scope(\_SB.PCI0.ISA) { 3 | 4 | Device(RTC) { 5 | Name(_HID, EisaId("PNP0B00")) 6 | Name(_CRS, ResourceTemplate() { 7 | IO(Decode16, 0x0070, 0x0070, 0x10, 0x02) 8 | IRQNoFlags() { 8 } 9 | IO(Decode16, 0x0072, 0x0072, 0x02, 0x06) 10 | }) 11 | } 12 | 13 | Device(KBD) { 14 | Name(_HID, EisaId("PNP0303")) 15 | Method(_STA, 0, NotSerialized) { 16 | Return (0x0f) 17 | } 18 | Name(_CRS, ResourceTemplate() { 19 | IO(Decode16, 0x0060, 0x0060, 0x01, 0x01) 20 | IO(Decode16, 0x0064, 0x0064, 0x01, 0x01) 21 | IRQNoFlags() { 1 } 22 | }) 23 | } 24 | 25 | Device(MOU) { 26 | Name(_HID, EisaId("PNP0F13")) 27 | Method(_STA, 0, NotSerialized) { 28 | Return (0x0f) 29 | } 30 | Name(_CRS, ResourceTemplate() { 31 | IRQNoFlags() { 12 } 32 | }) 33 | } 34 | 35 | Device(FDC0) { 36 | Name(_HID, EisaId("PNP0700")) 37 | Method(_STA, 0, NotSerialized) { 38 | Store(FDEN, Local0) 39 | If (LEqual(Local0, 0)) { 40 | Return (0x00) 41 | } Else { 42 | Return (0x0F) 43 | } 44 | } 45 | Name(_CRS, ResourceTemplate() { 46 | IO(Decode16, 0x03F2, 0x03F2, 0x00, 0x04) 47 | IO(Decode16, 0x03F7, 0x03F7, 0x00, 0x01) 48 | IRQNoFlags() { 6 } 49 | DMA(Compatibility, NotBusMaster, Transfer8) { 2 } 50 | }) 51 | } 52 | 53 | Device(LPT) { 54 | Name(_HID, EisaId("PNP0400")) 55 | Method(_STA, 0, NotSerialized) { 56 | Store(LPEN, Local0) 57 | If (LEqual(Local0, 0)) { 58 | Return (0x00) 59 | } Else { 60 | Return (0x0F) 61 | } 62 | } 63 | Name(_CRS, ResourceTemplate() { 64 | IO(Decode16, 0x0378, 0x0378, 0x08, 0x08) 65 | IRQNoFlags() { 7 } 66 | }) 67 | } 68 | 69 | Device(COM1) { 70 | Name(_HID, EisaId("PNP0501")) 71 | Name(_UID, 0x01) 72 | Method(_STA, 0, NotSerialized) { 73 | Store(CAEN, Local0) 74 | If (LEqual(Local0, 0)) { 75 | Return (0x00) 76 | } Else { 77 | Return (0x0F) 78 | } 79 | } 80 | Name(_CRS, ResourceTemplate() { 81 | IO(Decode16, 0x03F8, 0x03F8, 0x00, 0x08) 82 | IRQNoFlags() { 4 } 83 | }) 84 | } 85 | 86 | Device(COM2) { 87 | Name(_HID, EisaId("PNP0501")) 88 | Name(_UID, 0x02) 89 | Method(_STA, 0, NotSerialized) { 90 | Store(CBEN, Local0) 91 | If (LEqual(Local0, 0)) { 92 | Return (0x00) 93 | } Else { 94 | Return (0x0F) 95 | } 96 | } 97 | Name(_CRS, ResourceTemplate() { 98 | IO(Decode16, 0x02F8, 0x02F8, 0x00, 0x08) 99 | IRQNoFlags() { 3 } 100 | }) 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/fw/coreboot.h: -------------------------------------------------------------------------------- 1 | //***************************************************************************** 2 | // 3 | // Copyright (c) 2015 Eltan B.V. All rights reserved. 4 | // Software License Agreement 5 | // 6 | // THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED 7 | // OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF 8 | // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. 9 | // ELTAN SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, 10 | // OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. 11 | // 12 | //***************************************************************************** 13 | 14 | #ifndef __COREBOOT_H 15 | #define __COREBOOT_H 16 | 17 | struct cbmem_entry { 18 | u32 magic; 19 | u32 id; 20 | u64 base; 21 | u64 size; 22 | }; 23 | 24 | // 25 | // Intended for cbfs file overrides 26 | // 27 | struct file_container { 28 | u32 file_signature; /* "FILE" */ 29 | u32 file_size; /* size of file_data[] */ 30 | char file_name[32]; 31 | char file_data[0]; /* Variable size */ 32 | }; 33 | 34 | #define CBMEM_ID_FILE 0x46494c45 //'FILE' 35 | #define CB_TAG_FILE 0x25 36 | #define CBMEM_MAGIC 0x434f5245 37 | 38 | struct cbfile_record { 39 | u32 tag; 40 | u32 size; 41 | u64 forward; 42 | }; 43 | char * get_cbmem_file( char * filename, int * size ); 44 | 45 | #endif //__COREBOOT_H 46 | -------------------------------------------------------------------------------- /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/lib_vpd.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #include "lib_vpd.h" 8 | #include "output.h" // dprintf 9 | 10 | /* Given an encoded string, this functions decodes the length field which varies 11 | * from 1 byte to many bytes. 12 | * 13 | * The in points the actual byte going to be decoded. The *length returns 14 | * the decoded length field. The number of consumed bytes will be stroed in 15 | * decoded_len. 16 | * 17 | * Returns VPD_FAIL if more bit is 1, but actually reaches the end of string. 18 | */ 19 | int VPDdecodeLen(const s32 max_len,const u8 *in, s32 *length, s32 *decoded_len) 20 | { 21 | u8 more; 22 | int i = 0; 23 | 24 | if (!length) 25 | return VPD_FAIL; 26 | 27 | if (!decoded_len) 28 | return VPD_FAIL; 29 | 30 | *length = 0; 31 | do { 32 | if (i >= max_len) 33 | return VPD_FAIL; 34 | 35 | more = in[i] & 0x80; 36 | *length <<= 7; 37 | *length |= in[i] & 0x7f; 38 | ++i; 39 | } while (more); 40 | 41 | *decoded_len = i; 42 | 43 | return VPD_OK; 44 | } 45 | 46 | /* Given the encoded string, this function invokes callback with extracted 47 | * (key, value). The *consumed will be plused the number of bytes consumed in 48 | * this function. 49 | * 50 | * The input_buf points to the first byte of the input buffer. 51 | * 52 | * The *consumed starts from 0, which is actually the next byte to be decoded. 53 | * It can be non-zero to be used in multiple calls. 54 | * 55 | * If one entry is successfully decoded, sends it to callback and returns the 56 | * result. 57 | */ 58 | int decodeVpdString(const s32 max_len, const u8 *input_buf, s32 *consumed, 59 | VpdDecodeCallback callback, void *callback_arg) 60 | { 61 | int type; 62 | s32 key_len, value_len; 63 | s32 decoded_len; 64 | const u8 *key, *value; 65 | 66 | /* type */ 67 | if (*consumed >= max_len) 68 | return VPD_FAIL; 69 | 70 | type = input_buf[*consumed]; 71 | switch (type) { 72 | case VPD_TYPE_INFO: 73 | case VPD_TYPE_STRING: 74 | (*consumed)++; 75 | /* key */ 76 | if (VPD_OK != VPDdecodeLen(max_len - *consumed, 77 | &input_buf[*consumed], &key_len, 78 | &decoded_len) || 79 | *consumed + decoded_len >= max_len) { 80 | return VPD_FAIL; 81 | } 82 | 83 | *consumed += decoded_len; 84 | key = &input_buf[*consumed]; 85 | *consumed += key_len; 86 | 87 | /* value */ 88 | if (VPD_OK != VPDdecodeLen(max_len - *consumed, 89 | &input_buf[*consumed], 90 | &value_len, &decoded_len) || 91 | *consumed + decoded_len > max_len) { 92 | return VPD_FAIL; 93 | } 94 | *consumed += decoded_len; 95 | value = &input_buf[*consumed]; 96 | *consumed += value_len; 97 | 98 | if (type == VPD_TYPE_STRING) 99 | return callback(key, key_len, value, value_len, 100 | callback_arg); 101 | 102 | return VPD_OK; 103 | 104 | default: 105 | return VPD_FAIL; 106 | break; 107 | } 108 | 109 | return VPD_OK; 110 | } 111 | -------------------------------------------------------------------------------- /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/fw/ssdt-misc.dsl: -------------------------------------------------------------------------------- 1 | ACPI_EXTRACT_ALL_CODE ssdp_misc_aml 2 | 3 | DefinitionBlock ("ssdt-misc.aml", "SSDT", 0x01, "BXPC", "BXSSDTSU", 0x1) 4 | { 5 | 6 | /**************************************************************** 7 | * PCI memory ranges 8 | ****************************************************************/ 9 | 10 | Scope(\) { 11 | ACPI_EXTRACT_NAME_DWORD_CONST acpi_pci32_start 12 | Name(P0S, 0x12345678) 13 | ACPI_EXTRACT_NAME_DWORD_CONST acpi_pci32_end 14 | Name(P0E, 0x12345678) 15 | ACPI_EXTRACT_NAME_BYTE_CONST acpi_pci64_valid 16 | Name(P1V, 0x12) 17 | ACPI_EXTRACT_NAME_BUFFER8 acpi_pci64_start 18 | Name(P1S, Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }) 19 | ACPI_EXTRACT_NAME_BUFFER8 acpi_pci64_end 20 | Name(P1E, Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }) 21 | ACPI_EXTRACT_NAME_BUFFER8 acpi_pci64_length 22 | Name(P1L, Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }) 23 | } 24 | 25 | 26 | /**************************************************************** 27 | * Suspend 28 | ****************************************************************/ 29 | 30 | Scope(\) { 31 | /* 32 | * S3 (suspend-to-ram), S4 (suspend-to-disk) and S5 (power-off) type codes: 33 | * must match piix4 emulation. 34 | */ 35 | 36 | ACPI_EXTRACT_NAME_STRING acpi_s3_name 37 | Name(_S3, Package(0x04) { 38 | One, /* PM1a_CNT.SLP_TYP */ 39 | One, /* PM1b_CNT.SLP_TYP */ 40 | Zero, /* reserved */ 41 | Zero /* reserved */ 42 | }) 43 | ACPI_EXTRACT_NAME_STRING acpi_s4_name 44 | ACPI_EXTRACT_PKG_START acpi_s4_pkg 45 | Name(_S4, Package(0x04) { 46 | 0x2, /* PM1a_CNT.SLP_TYP */ 47 | 0x2, /* PM1b_CNT.SLP_TYP */ 48 | Zero, /* reserved */ 49 | Zero /* reserved */ 50 | }) 51 | Name(_S5, Package(0x04) { 52 | Zero, /* PM1a_CNT.SLP_TYP */ 53 | Zero, /* PM1b_CNT.SLP_TYP */ 54 | Zero, /* reserved */ 55 | Zero /* reserved */ 56 | }) 57 | } 58 | 59 | External(\_SB.PCI0, DeviceObj) 60 | External(\_SB.PCI0.ISA, DeviceObj) 61 | 62 | Scope(\_SB.PCI0.ISA) { 63 | Device(PEVT) { 64 | Name(_HID, "QEMU0001") 65 | /* PEST will be patched to be Zero if no such device */ 66 | ACPI_EXTRACT_NAME_WORD_CONST ssdt_isa_pest 67 | Name(PEST, 0xFFFF) 68 | OperationRegion(PEOR, SystemIO, PEST, 0x01) 69 | Field(PEOR, ByteAcc, NoLock, Preserve) { 70 | PEPT, 8, 71 | } 72 | 73 | Method(_STA, 0, NotSerialized) { 74 | Store(PEST, Local0) 75 | If (LEqual(Local0, Zero)) { 76 | Return (0x00) 77 | } Else { 78 | Return (0x0F) 79 | } 80 | } 81 | 82 | Method(RDPT, 0, NotSerialized) { 83 | Store(PEPT, Local0) 84 | Return (Local0) 85 | } 86 | 87 | Method(WRPT, 1, NotSerialized) { 88 | Store(Arg0, PEPT) 89 | } 90 | 91 | Name(_CRS, ResourceTemplate() { 92 | IO(Decode16, 0x00, 0x00, 0x01, 0x01, IO) 93 | }) 94 | 95 | CreateWordField(_CRS, IO._MIN, IOMN) 96 | CreateWordField(_CRS, IO._MAX, IOMX) 97 | 98 | Method(_INI, 0, NotSerialized) { 99 | Store(PEST, IOMN) 100 | Store(PEST, IOMX) 101 | } 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/fw/ssdt-misc.hex: -------------------------------------------------------------------------------- 1 | /* DO NOT EDIT! This is an autogenerated file. See scripts/acpi_extract.py. */ 2 | static unsigned char acpi_pci64_length[] = { 3 | 0x6f 4 | }; 5 | 6 | static unsigned char acpi_s4_pkg[] = { 7 | 0x8f 8 | }; 9 | 10 | static unsigned char acpi_s3_name[] = { 11 | 0x7c 12 | }; 13 | 14 | static unsigned char acpi_pci32_start[] = { 15 | 0x2f 16 | }; 17 | 18 | static unsigned char acpi_pci64_valid[] = { 19 | 0x43 20 | }; 21 | 22 | static unsigned char ssdp_misc_aml[] = { 23 | 0x53, 0x53, 0x44, 0x54, 0x62, 0x01, 0x00, 0x00, 24 | 0x01, 0x7f, 0x42, 0x58, 0x50, 0x43, 0x00, 0x00, 25 | 0x42, 0x58, 0x53, 0x53, 0x44, 0x54, 0x53, 0x55, 26 | 0x01, 0x00, 0x00, 0x00, 0x49, 0x4e, 0x54, 0x4c, 27 | 0x18, 0x08, 0x15, 0x20, 0x10, 0x42, 0x05, 0x5c, 28 | 0x00, 0x08, 0x50, 0x30, 0x53, 0x5f, 0x0c, 0x78, 29 | 0x56, 0x34, 0x12, 0x08, 0x50, 0x30, 0x45, 0x5f, 30 | 0x0c, 0x78, 0x56, 0x34, 0x12, 0x08, 0x50, 0x31, 31 | 0x56, 0x5f, 0x0a, 0x12, 0x08, 0x50, 0x31, 0x53, 32 | 0x5f, 0x11, 0x0b, 0x0a, 0x08, 0x00, 0x00, 0x00, 33 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x50, 0x31, 34 | 0x45, 0x5f, 0x11, 0x0b, 0x0a, 0x08, 0x00, 0x00, 35 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x50, 36 | 0x31, 0x4c, 0x5f, 0x11, 0x0b, 0x0a, 0x08, 0x00, 37 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 38 | 0x29, 0x5c, 0x00, 0x08, 0x5f, 0x53, 0x33, 0x5f, 39 | 0x12, 0x06, 0x04, 0x01, 0x01, 0x00, 0x00, 0x08, 40 | 0x5f, 0x53, 0x34, 0x5f, 0x12, 0x08, 0x04, 0x0a, 41 | 0x02, 0x0a, 0x02, 0x00, 0x00, 0x08, 0x5f, 0x53, 42 | 0x35, 0x5f, 0x12, 0x06, 0x04, 0x00, 0x00, 0x00, 43 | 0x00, 0x10, 0x40, 0x0c, 0x5c, 0x2f, 0x03, 0x5f, 44 | 0x53, 0x42, 0x5f, 0x50, 0x43, 0x49, 0x30, 0x49, 45 | 0x53, 0x41, 0x5f, 0x5b, 0x82, 0x4d, 0x0a, 0x50, 46 | 0x45, 0x56, 0x54, 0x08, 0x5f, 0x48, 0x49, 0x44, 47 | 0x0d, 0x51, 0x45, 0x4d, 0x55, 0x30, 0x30, 0x30, 48 | 0x31, 0x00, 0x08, 0x50, 0x45, 0x53, 0x54, 0x0b, 49 | 0xff, 0xff, 0x5b, 0x80, 0x50, 0x45, 0x4f, 0x52, 50 | 0x01, 0x50, 0x45, 0x53, 0x54, 0x01, 0x5b, 0x81, 51 | 0x0b, 0x50, 0x45, 0x4f, 0x52, 0x01, 0x50, 0x45, 52 | 0x50, 0x54, 0x08, 0x14, 0x18, 0x5f, 0x53, 0x54, 53 | 0x41, 0x00, 0x70, 0x50, 0x45, 0x53, 0x54, 0x60, 54 | 0xa0, 0x06, 0x93, 0x60, 0x00, 0xa4, 0x00, 0xa1, 55 | 0x04, 0xa4, 0x0a, 0x0f, 0x14, 0x0e, 0x52, 0x44, 56 | 0x50, 0x54, 0x00, 0x70, 0x50, 0x45, 0x50, 0x54, 57 | 0x60, 0xa4, 0x60, 0x14, 0x0c, 0x57, 0x52, 0x50, 58 | 0x54, 0x01, 0x70, 0x68, 0x50, 0x45, 0x50, 0x54, 59 | 0x08, 0x5f, 0x43, 0x52, 0x53, 0x11, 0x0d, 0x0a, 60 | 0x0a, 0x47, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 61 | 0x01, 0x79, 0x00, 0x8b, 0x5f, 0x43, 0x52, 0x53, 62 | 0x0a, 0x02, 0x49, 0x4f, 0x4d, 0x4e, 0x8b, 0x5f, 63 | 0x43, 0x52, 0x53, 0x0a, 0x04, 0x49, 0x4f, 0x4d, 64 | 0x58, 0x14, 0x18, 0x5f, 0x49, 0x4e, 0x49, 0x00, 65 | 0x70, 0x50, 0x45, 0x53, 0x54, 0x49, 0x4f, 0x4d, 66 | 0x4e, 0x70, 0x50, 0x45, 0x53, 0x54, 0x49, 0x4f, 67 | 0x4d, 0x58 68 | }; 69 | 70 | static unsigned char ssdt_isa_pest[] = { 71 | 0xd0 72 | }; 73 | 74 | static unsigned char acpi_s4_name[] = { 75 | 0x88 76 | }; 77 | 78 | static unsigned char acpi_pci64_start[] = { 79 | 0x4d 80 | }; 81 | 82 | static unsigned char acpi_pci64_end[] = { 83 | 0x5e 84 | }; 85 | 86 | static unsigned char acpi_pci32_end[] = { 87 | 0x39 88 | }; 89 | -------------------------------------------------------------------------------- /src/fw/ssdt-pcihp.dsl: -------------------------------------------------------------------------------- 1 | ACPI_EXTRACT_ALL_CODE ssdp_pcihp_aml 2 | 3 | DefinitionBlock ("ssdt-pcihp.aml", "SSDT", 0x01, "BXPC", "BXSSDTPC", 0x1) 4 | { 5 | 6 | /**************************************************************** 7 | * PCI hotplug 8 | ****************************************************************/ 9 | 10 | /* Objects supplied by DSDT */ 11 | External(\_SB.PCI0, DeviceObj) 12 | External(\_SB.PCI0.PCEJ, MethodObj) 13 | 14 | Scope(\_SB.PCI0) { 15 | 16 | /* Bulk generated PCI hotplug devices */ 17 | ACPI_EXTRACT_DEVICE_START ssdt_pcihp_start 18 | ACPI_EXTRACT_DEVICE_END ssdt_pcihp_end 19 | ACPI_EXTRACT_DEVICE_STRING ssdt_pcihp_name 20 | 21 | // Method _EJ0 can be patched by BIOS to EJ0_ 22 | // at runtime, if the slot is detected to not support hotplug. 23 | // Extract the offset of the address dword and the 24 | // _EJ0 name to allow this patching. 25 | Device(SAA) { 26 | ACPI_EXTRACT_NAME_BYTE_CONST ssdt_pcihp_id 27 | Name(_SUN, 0xAA) 28 | ACPI_EXTRACT_NAME_DWORD_CONST ssdt_pcihp_adr 29 | Name(_ADR, 0xAA0000) 30 | ACPI_EXTRACT_METHOD_STRING ssdt_pcihp_ej0 31 | Method(_EJ0, 1) { 32 | PCEJ(_SUN) 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/fw/ssdt-pcihp.hex: -------------------------------------------------------------------------------- 1 | /* DO NOT EDIT! This is an autogenerated file. See scripts/acpi_extract.py. */ 2 | static unsigned char ssdt_pcihp_name[] = { 3 | 0x33 4 | }; 5 | 6 | static unsigned char ssdt_pcihp_adr[] = { 7 | 0x44 8 | }; 9 | 10 | static unsigned char ssdt_pcihp_end[] = { 11 | 0x57 12 | }; 13 | 14 | static unsigned char ssdp_pcihp_aml[] = { 15 | 0x53, 0x53, 0x44, 0x54, 0x57, 0x00, 0x00, 0x00, 16 | 0x01, 0x27, 0x42, 0x58, 0x50, 0x43, 0x00, 0x00, 17 | 0x42, 0x58, 0x53, 0x53, 0x44, 0x54, 0x50, 0x43, 18 | 0x01, 0x00, 0x00, 0x00, 0x49, 0x4e, 0x54, 0x4c, 19 | 0x18, 0x08, 0x15, 0x20, 0x10, 0x32, 0x5c, 0x2e, 20 | 0x5f, 0x53, 0x42, 0x5f, 0x50, 0x43, 0x49, 0x30, 21 | 0x5b, 0x82, 0x25, 0x53, 0x41, 0x41, 0x5f, 0x08, 22 | 0x5f, 0x53, 0x55, 0x4e, 0x0a, 0xaa, 0x08, 0x5f, 23 | 0x41, 0x44, 0x52, 0x0c, 0x00, 0x00, 0xaa, 0x00, 24 | 0x14, 0x0e, 0x5f, 0x45, 0x4a, 0x30, 0x01, 0x50, 25 | 0x43, 0x45, 0x4a, 0x5f, 0x53, 0x55, 0x4e 26 | }; 27 | 28 | static unsigned char ssdt_pcihp_start[] = { 29 | 0x30 30 | }; 31 | 32 | static unsigned char ssdt_pcihp_id[] = { 33 | 0x3d 34 | }; 35 | 36 | static unsigned char ssdt_pcihp_ej0[] = { 37 | 0x4a 38 | }; 39 | -------------------------------------------------------------------------------- /src/fw/ssdt-proc.dsl: -------------------------------------------------------------------------------- 1 | /* This file is the basis for the ssdt table generated in src/acpi.c. 2 | * It defines the contents of the per-cpu Processor() object. At 3 | * runtime, a dynamically generated SSDT will contain one copy of this 4 | * AML snippet for every possible cpu in the system. The objects will 5 | * be placed in the \_SB_ namespace. 6 | * 7 | * In addition to the aml code generated from this file, the 8 | * src/acpi.c file creates a NTFY method with an entry for each cpu: 9 | * Method(NTFY, 2) { 10 | * If (LEqual(Arg0, 0x00)) { Notify(CP00, Arg1) } 11 | * If (LEqual(Arg0, 0x01)) { Notify(CP01, Arg1) } 12 | * ... 13 | * } 14 | * and a CPON array with the list of active and inactive cpus: 15 | * Name(CPON, Package() { One, One, ..., Zero, Zero, ... }) 16 | */ 17 | 18 | ACPI_EXTRACT_ALL_CODE ssdp_proc_aml 19 | 20 | DefinitionBlock ("ssdt-proc.aml", "SSDT", 0x01, "BXPC", "BXSSDT", 0x1) 21 | { 22 | ACPI_EXTRACT_PROCESSOR_START ssdt_proc_start 23 | ACPI_EXTRACT_PROCESSOR_END ssdt_proc_end 24 | ACPI_EXTRACT_PROCESSOR_STRING ssdt_proc_name 25 | Processor(CPAA, 0xAA, 0x0000b010, 0x06) { 26 | ACPI_EXTRACT_NAME_BYTE_CONST ssdt_proc_id 27 | Name(ID, 0xAA) 28 | /* 29 | * The src/acpi.c code requires the above ACP_EXTRACT tags so that it can update 30 | * CPAA and 0xAA with the appropriate CPU id (see 31 | * SD_OFFSET_CPUHEX/CPUID1/CPUID2). Don't change the above without 32 | * also updating the C code. 33 | */ 34 | Name(_HID, "ACPI0007") 35 | External(CPMA, MethodObj) 36 | External(CPST, MethodObj) 37 | External(CPEJ, MethodObj) 38 | Method(_MAT, 0) { 39 | Return (CPMA(ID)) 40 | } 41 | Method(_STA, 0) { 42 | Return (CPST(ID)) 43 | } 44 | Method(_EJ0, 1, NotSerialized) { 45 | CPEJ(ID, Arg0) 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/fw/ssdt-proc.hex: -------------------------------------------------------------------------------- 1 | /* DO NOT EDIT! This is an autogenerated file. See scripts/acpi_extract.py. */ 2 | static unsigned char ssdt_proc_name[] = { 3 | 0x28 4 | }; 5 | 6 | static unsigned char ssdp_proc_aml[] = { 7 | 0x53, 0x53, 0x44, 0x54, 0x78, 0x00, 0x00, 0x00, 8 | 0x01, 0xbb, 0x42, 0x58, 0x50, 0x43, 0x00, 0x00, 9 | 0x42, 0x58, 0x53, 0x53, 0x44, 0x54, 0x00, 0x00, 10 | 0x01, 0x00, 0x00, 0x00, 0x49, 0x4e, 0x54, 0x4c, 11 | 0x18, 0x08, 0x15, 0x20, 0x5b, 0x83, 0x42, 0x05, 12 | 0x43, 0x50, 0x41, 0x41, 0xaa, 0x10, 0xb0, 0x00, 13 | 0x00, 0x06, 0x08, 0x49, 0x44, 0x5f, 0x5f, 0x0a, 14 | 0xaa, 0x08, 0x5f, 0x48, 0x49, 0x44, 0x0d, 0x41, 15 | 0x43, 0x50, 0x49, 0x30, 0x30, 0x30, 0x37, 0x00, 16 | 0x14, 0x0f, 0x5f, 0x4d, 0x41, 0x54, 0x00, 0xa4, 17 | 0x43, 0x50, 0x4d, 0x41, 0x49, 0x44, 0x5f, 0x5f, 18 | 0x14, 0x0f, 0x5f, 0x53, 0x54, 0x41, 0x00, 0xa4, 19 | 0x43, 0x50, 0x53, 0x54, 0x49, 0x44, 0x5f, 0x5f, 20 | 0x14, 0x0f, 0x5f, 0x45, 0x4a, 0x30, 0x01, 0x43, 21 | 0x50, 0x45, 0x4a, 0x49, 0x44, 0x5f, 0x5f, 0x68, 22 | 23 | }; 24 | 25 | static unsigned char ssdt_proc_id[] = { 26 | 0x38 27 | }; 28 | 29 | static unsigned char ssdt_proc_end[] = { 30 | 0x78 31 | }; 32 | 33 | static unsigned char ssdt_proc_start[] = { 34 | 0x24 35 | }; 36 | -------------------------------------------------------------------------------- /src/fw/vpd.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #ifndef __VPD_H__ 8 | #define __VPD_H__ 9 | 10 | enum vpd_region { 11 | VPD_ANY = 0, 12 | VPD_RO = 1, 13 | VPD_RW = 2 14 | }; 15 | /* 16 | * Reads VPD string value by key. 17 | * 18 | * Reads in at most one less than size characters from VPD and stores them 19 | * into buffer. A terminating null byte ('\0') is stored after the last 20 | * character in the buffer. 21 | * 22 | * Returns NULL if key is not found, otherwise buffer. 23 | */ 24 | char *vpd_gets(const char *key, char *buffer, int size, enum vpd_region region); 25 | 26 | /* 27 | * Find VPD value by key. 28 | * 29 | * Searches for a VPD entry in the VPD cache. If found, places the size of the 30 | * entry into '*size' and returns the pointer to the entry data. 31 | * 32 | * This function presumes that VPD is cached in DRAM (which is the case in the 33 | * current implementation) and as such returns the pointer into the cache. The 34 | * user is not supposed to modify the data, and does not have to free the 35 | * memory. 36 | * 37 | * Returns NULL if key is not found. 38 | */ 39 | 40 | const void *vpd_find_key(const char *key, int *size, enum vpd_region region); 41 | 42 | #endif /* __VPD_H__ */ 43 | -------------------------------------------------------------------------------- /src/fw/vpd_tables.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | * 6 | * Ported from mosys project (http://code.google.com/p/mosys/). 7 | */ 8 | 9 | #ifndef __LIB_VPD_TABLES_H__ 10 | #define __LIB_VPD_TABLES_H__ 11 | 12 | #include "types.h" 13 | 14 | #define VPD_ENTRY_MAGIC "_SM_" 15 | #define VPD_INFO_MAGIC \ 16 | "\xfe" /* type: VPD header */ \ 17 | "\x09" /* key length, 9 = 1 + 8 */ \ 18 | "\x01" /* info version, 1 */ \ 19 | "gVpdInfo" /* signature, 8 bytes */ \ 20 | "\x04" /* value length */ 21 | 22 | /* Google specific VPD info */ 23 | struct google_vpd_info { 24 | union { 25 | struct { 26 | u8 type; 27 | u8 key_len; 28 | u8 info_ver; 29 | u8 signature[8]; 30 | u8 value_len; 31 | } tlv; 32 | u8 magic[12]; 33 | } header; 34 | u32 size; 35 | } PACKED; 36 | 37 | /* Entry */ 38 | struct vpd_entry { 39 | u8 anchor_string[4]; 40 | u8 entry_cksum; 41 | u8 entry_length; 42 | u8 major_ver; 43 | u8 minor_ver; 44 | u16 max_size; 45 | u8 entry_rev; 46 | u8 format_area[5]; 47 | u8 inter_anchor_string[5]; 48 | u8 inter_anchor_cksum; 49 | u16 table_length; 50 | u32 table_address; 51 | u16 table_entry_count; 52 | u8 bcd_revision; 53 | } PACKED; 54 | 55 | /* Header */ 56 | struct vpd_header { 57 | u8 type; 58 | u8 length; 59 | u16 handle; 60 | } PACKED; 61 | 62 | /* Type 0 - firmware information */ 63 | struct vpd_table_firmware { 64 | u8 vendor; 65 | u8 version; 66 | u16 start_address; 67 | u8 release_date; 68 | u8 rom_size_64k_blocks; 69 | u32 characteristics; 70 | u8 extension[2]; /* v2.4+ */ 71 | u8 major_ver; /* v2.4+ */ 72 | u8 minor_ver; /* v2.4+ */ 73 | u8 ec_major_ver; /* v2.4+ */ 74 | u8 ec_minor_ver; /* v2.4+ */ 75 | } PACKED; 76 | 77 | /* Type 1 - system information */ 78 | struct vpd_table_system { 79 | u8 manufacturer; 80 | u8 name; 81 | u8 version; 82 | u8 serial_number; 83 | u8 uuid[16]; 84 | u8 wakeup_type; 85 | u8 sku_number; /* v2.4+ */ 86 | u8 family; /* v2.4+ */ 87 | } PACKED; 88 | 89 | /* Type 127 - end of table */ 90 | struct vpd_table_eot { 91 | struct vpd_header header; 92 | } PACKED; 93 | 94 | /* Type 241 - binary blob pointer */ 95 | struct vpd_table_binary_blob_pointer { 96 | u8 struct_major_version; 97 | u8 struct_minor_version; 98 | u8 vendor; 99 | u8 description; 100 | u8 major_version; 101 | u8 minor_version; 102 | u8 variant; 103 | u8 reserved[5]; 104 | u8 uuid[16]; 105 | u32 offset; 106 | u32 size; 107 | } PACKED; 108 | 109 | /* The length and number of strings defined here is not a limitation of VPD. 110 | * These numbers were deemed good enough during development. */ 111 | #define VPD_MAX_STRINGS 10 112 | #define VPD_MAX_STRING_LENGTH 64 113 | 114 | #endif /* __LIB_VPD_TABLES_H__ */ 115 | -------------------------------------------------------------------------------- /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_CAPACITY 0x25 22 | 23 | struct cdb_read_capacity { 24 | u8 command; 25 | u8 flags; 26 | u8 resreved_02[8]; 27 | u8 pad[6]; 28 | } PACKED; 29 | 30 | struct cdbres_read_capacity { 31 | u32 sectors; 32 | u32 blksize; 33 | } PACKED; 34 | 35 | #define CDB_CMD_TEST_UNIT_READY 0x00 36 | #define CDB_CMD_INQUIRY 0x12 37 | #define CDB_CMD_REQUEST_SENSE 0x03 38 | 39 | struct cdb_request_sense { 40 | u8 command; 41 | u8 flags; 42 | u16 reserved_02; 43 | u8 length; 44 | u8 reserved_05; 45 | u8 pad[10]; 46 | } PACKED; 47 | 48 | struct cdbres_request_sense { 49 | u8 errcode; 50 | u8 segment; 51 | u8 flags; 52 | u32 info; 53 | u8 additional; 54 | u32 specific; 55 | u8 asc; 56 | u8 ascq; 57 | u32 reserved_0e; 58 | } PACKED; 59 | 60 | #define SCSI_TYPE_DISK 0x00 61 | #define SCSI_TYPE_CDROM 0x05 62 | 63 | struct cdbres_inquiry { 64 | u8 pdt; 65 | u8 removable; 66 | u8 reserved_02[2]; 67 | u8 additional; 68 | u8 reserved_05[3]; 69 | char vendor[8]; 70 | char product[16]; 71 | char rev[4]; 72 | } PACKED; 73 | 74 | #define CDB_CMD_MODE_SENSE 0x5A 75 | #define MODE_PAGE_HD_GEOMETRY 0x04 76 | 77 | struct cdb_mode_sense { 78 | u8 command; 79 | u8 flags; 80 | u8 page; 81 | u32 reserved_03; 82 | u16 count; 83 | u8 reserved_09; 84 | u8 pad[6]; 85 | } PACKED; 86 | 87 | struct cdbres_mode_sense_geom { 88 | u8 unused_00[3]; 89 | u8 read_only; 90 | u32 unused_04; 91 | u8 page; 92 | u8 length; 93 | u8 cyl[3]; 94 | u8 heads; 95 | u8 precomp[3]; 96 | u8 reduced[3]; 97 | u16 step_rate; 98 | u8 landing[3]; 99 | u16 rpm; 100 | } PACKED; 101 | 102 | // blockcmd.c 103 | struct disk_op_s; 104 | int scsi_fill_cmd(struct disk_op_s *op, void *cdbcmd, int maxcdb); 105 | int scsi_is_read(struct disk_op_s *op); 106 | int scsi_is_ready(struct disk_op_s *op); 107 | struct drive_s; 108 | int scsi_drive_setup(struct drive_s *drive, const char *s, int prio); 109 | typedef int (*scsi_add_lun)(u32 lun, struct drive_s *tmpl_drv); 110 | int scsi_rep_luns_scan(struct drive_s *tmp_drive, scsi_add_lun add_lun); 111 | int scsi_sequential_scan(struct drive_s *tmp_drive, u32 maxluns, 112 | scsi_add_lun add_lun); 113 | 114 | #endif // blockcmd.h 115 | -------------------------------------------------------------------------------- /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 | void pci_enable_mmconfig(u64 addr, const char *name); 58 | u8 pci_find_capability(u16 bdf, u8 cap_id, u8 cap); 59 | int pci_next(int bdf, int bus); 60 | 61 | void pci_enable_mmconfig(u64 addr, const char *name); 62 | int pci_probe_host(void); 63 | void pci_reboot(void); 64 | 65 | #endif // pci.h 66 | -------------------------------------------------------------------------------- /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.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-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.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/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 | 19 | void const_romfile_add_int(char *name, u32 value); 20 | 21 | #endif // romfile.h 22 | -------------------------------------------------------------------------------- /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/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 *vmode_g, int window); 46 | int bochsvga_set_window(struct vgamode_s *vmode_g, int window, int val); 47 | int bochsvga_get_linelength(struct vgamode_s *vmode_g); 48 | int bochsvga_set_linelength(struct vgamode_s *vmode_g, int val); 49 | int bochsvga_get_displaystart(struct vgamode_s *vmode_g); 50 | int bochsvga_set_displaystart(struct vgamode_s *vmode_g, int val); 51 | int bochsvga_get_dacformat(struct vgamode_s *vmode_g); 52 | int bochsvga_set_dacformat(struct vgamode_s *vmode_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/stdvga.h: -------------------------------------------------------------------------------- 1 | #ifndef __STDVGA_H 2 | #define __STDVGA_H 3 | 4 | #include "types.h" // u8 5 | 6 | // VGA registers 7 | #define VGAREG_ACTL_ADDRESS 0x3c0 8 | #define VGAREG_ACTL_WRITE_DATA 0x3c0 9 | #define VGAREG_ACTL_READ_DATA 0x3c1 10 | 11 | #define VGAREG_INPUT_STATUS 0x3c2 12 | #define VGAREG_WRITE_MISC_OUTPUT 0x3c2 13 | #define VGAREG_VIDEO_ENABLE 0x3c3 14 | #define VGAREG_SEQU_ADDRESS 0x3c4 15 | #define VGAREG_SEQU_DATA 0x3c5 16 | 17 | #define VGAREG_PEL_MASK 0x3c6 18 | #define VGAREG_DAC_STATE 0x3c7 19 | #define VGAREG_DAC_READ_ADDRESS 0x3c7 20 | #define VGAREG_DAC_WRITE_ADDRESS 0x3c8 21 | #define VGAREG_DAC_DATA 0x3c9 22 | 23 | #define VGAREG_READ_FEATURE_CTL 0x3ca 24 | #define VGAREG_READ_MISC_OUTPUT 0x3cc 25 | 26 | #define VGAREG_GRDC_ADDRESS 0x3ce 27 | #define VGAREG_GRDC_DATA 0x3cf 28 | 29 | #define VGAREG_MDA_CRTC_ADDRESS 0x3b4 30 | #define VGAREG_MDA_CRTC_DATA 0x3b5 31 | #define VGAREG_VGA_CRTC_ADDRESS 0x3d4 32 | #define VGAREG_VGA_CRTC_DATA 0x3d5 33 | 34 | #define VGAREG_MDA_WRITE_FEATURE_CTL 0x3ba 35 | #define VGAREG_VGA_WRITE_FEATURE_CTL 0x3da 36 | #define VGAREG_ACTL_RESET 0x3da 37 | 38 | #define VGAREG_MDA_MODECTL 0x3b8 39 | #define VGAREG_CGA_MODECTL 0x3d8 40 | #define VGAREG_CGA_PALETTE 0x3d9 41 | 42 | /* Video memory */ 43 | #define SEG_GRAPH 0xA000 44 | #define SEG_CTEXT 0xB800 45 | #define SEG_MTEXT 0xB000 46 | 47 | // stdvga.c 48 | void stdvga_set_border_color(u8 color); 49 | void stdvga_set_overscan_border_color(u8 color); 50 | u8 stdvga_get_overscan_border_color(void); 51 | void stdvga_set_palette(u8 palid); 52 | void stdvga_set_all_palette_reg(u16 seg, u8 *data_far); 53 | void stdvga_get_all_palette_reg(u16 seg, u8 *data_far); 54 | void stdvga_toggle_intensity(u8 flag); 55 | void stdvga_select_video_dac_color_page(u8 flag, u8 data); 56 | void stdvga_read_video_dac_state(u8 *pmode, u8 *curpage); 57 | void stdvga_perform_gray_scale_summing(u16 start, u16 count); 58 | void stdvga_set_text_block_specifier(u8 spec); 59 | void stdvga_planar4_plane(int plane); 60 | void stdvga_load_font(u16 seg, void *src_far, u16 count 61 | , u16 start, u8 destflags, u8 fontsize); 62 | u16 stdvga_get_crtc(void); 63 | struct vgamode_s; 64 | int stdvga_vram_ratio(struct vgamode_s *vmode_g); 65 | void stdvga_set_cursor_shape(u16 cursor_type); 66 | void stdvga_set_cursor_pos(int address); 67 | void stdvga_set_scan_lines(u8 lines); 68 | u16 stdvga_get_vde(void); 69 | int stdvga_get_window(struct vgamode_s *vmode_g, int window); 70 | int stdvga_set_window(struct vgamode_s *vmode_g, int window, int val); 71 | int stdvga_get_linelength(struct vgamode_s *vmode_g); 72 | int stdvga_set_linelength(struct vgamode_s *vmode_g, int val); 73 | int stdvga_get_displaystart(struct vgamode_s *vmode_g); 74 | int stdvga_set_displaystart(struct vgamode_s *vmode_g, int val); 75 | int stdvga_get_dacformat(struct vgamode_s *vmode_g); 76 | int stdvga_set_dacformat(struct vgamode_s *vmode_g, int val); 77 | int stdvga_save_restore(int cmd, u16 seg, void *data); 78 | void stdvga_enable_video_addressing(u8 disable); 79 | int stdvga_setup(void); 80 | 81 | #endif // stdvga.h 82 | -------------------------------------------------------------------------------- /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 *vmode_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, vmode_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 *vmode_g = get_current_mode(); 46 | if (!vmode_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(vmode_g->memmodel) != MM_TEXT) { 57 | gfx_set_swcursor(vmode_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(vmode_g->sstart), *(u8*)dest_far); 64 | attr = (attr >> 4) | (attr << 4); 65 | SET_FARVAR(GET_GLOBAL(vmode_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 *vmode_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 *vmode_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/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 | --------------------------------------------------------------------------------