├── .gdbinit ├── .gitignore ├── .travis.yml ├── COPYING ├── Dockerfile ├── README.md ├── build.sh ├── run.sh └── src ├── .gitignore ├── Makefile ├── drivers ├── cpu │ ├── cpu.h │ ├── cputools.c │ └── ioapic.c ├── pci │ ├── BootInterrupts.c │ ├── i2cio.c │ ├── int_handlers.S │ └── pci.c ├── serial │ └── serial.c └── video │ ├── BootVgaInitialization.c │ ├── BootVgaInitialization.h │ ├── BootVideo.h │ ├── BootVideoHelpers.c │ ├── VideoInitialization.c │ ├── VideoInitialization.h │ ├── conexant.c │ ├── conexant.h │ └── encoder.h ├── include ├── asm │ └── bitops.h ├── boot.h ├── config.h ├── consts.h ├── cromwell_types.h ├── linux │ ├── bitops.h │ └── pci_ids.h ├── list.h ├── memory_layout.h ├── stdint.h ├── stdio.h ├── stdlib.h ├── string.h ├── sys │ ├── mman.h │ └── types.h ├── video.h └── xboxkrnl.h ├── init.c ├── lib ├── eeprom │ ├── BootEEPROM.c │ └── BootEEPROM.h ├── font │ ├── font.c │ ├── font.h │ └── fontx16.h ├── misc │ ├── BootLibrary.c │ └── vsprintf.c └── xbe │ ├── xbe.c │ └── xbe.h ├── mm ├── dlmalloc.c └── paging.c ├── printk.c ├── rom.ld ├── rtl └── mem.c ├── start.nasm ├── stubs.c ├── xdecl.h ├── ximports.h └── xtypes.h /.gdbinit: -------------------------------------------------------------------------------- 1 | set architecture i386 2 | set disassembly-flavor intel 3 | symbol-file src/rom.elf 4 | 5 | # If you're debugging an nxdk-built XBE, you can uncomment the following line. 6 | # You'll need to double-check the .text address though. 7 | # add-symbol-file /path/to/nxdk/samples/triangle/main.exe 0x17000 8 | 9 | # If you built using a different path (e.g. via Docker), you'll need to set 10 | # a substitution path for GDB to locate the source files. 11 | # set substitute-path /work /path/to/src/ 12 | 13 | target remote 127.0.0.1:1234 14 | layout src 15 | b init 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.bin 3 | *.elf 4 | *.a 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | 3 | services: 4 | - docker 5 | 6 | before_install: 7 | - docker build -t xboxkrnl . 8 | - chmod 777 -R . 9 | 10 | script: 11 | - ./build.sh 12 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 5 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Library General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License 307 | along with this program; if not, write to the Free Software 308 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 309 | 310 | 311 | Also add information on how to contact you by electronic and paper mail. 312 | 313 | If the program is interactive, make it output a short notice like this 314 | when it starts in an interactive mode: 315 | 316 | Gnomovision version 69, Copyright (C) year name of author 317 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 318 | This is free software, and you are welcome to redistribute it 319 | under certain conditions; type `show c' for details. 320 | 321 | The hypothetical commands `show w' and `show c' should show the appropriate 322 | parts of the General Public License. Of course, the commands you use may 323 | be called something other than `show w' and `show c'; they could even be 324 | mouse-clicks or menu items--whatever suits your program. 325 | 326 | You should also get your employer (if you work as a programmer) or your 327 | school, if any, to sign a "copyright disclaimer" for the program, if 328 | necessary. Here is a sample; alter the names: 329 | 330 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 331 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 332 | 333 | , 1 April 1989 334 | Ty Coon, President of Vice 335 | 336 | This General Public License does not permit incorporating your program into 337 | proprietary programs. If your program is a subroutine library, you may 338 | consider it more useful to permit linking proprietary applications with the 339 | library. If this is what you want to do, use the GNU Library General 340 | Public License instead of this License. 341 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:18.04 2 | USER root 3 | RUN apt-get update && apt-get install -y git nasm build-essential sudo libclang-4.0-dev python 4 | RUN useradd -m docker 5 | RUN echo "docker:docker" | chpasswd && adduser docker sudo 6 | 7 | USER docker 8 | CMD /bin/bash 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | xqemu-kernel 2 | ============ 3 | 4 | An open-source Xbox kernel alternative, designed for use with XQEMU. 5 | 6 | [![Build Status](https://travis-ci.org/mborgerson/xqemu-kernel.svg?branch=master)](https://travis-ci.org/mborgerson/xqemu-kernel) 7 | 8 | ## Introduction 9 | 10 | [XQEMU](https://xqemu.com) is a low-level machine emulator, which needs a copy 11 | of the Xbox system software to start and run games. Unfortunately, this system 12 | software cannot be freely distributed due to it being copyrighted material. This 13 | means that in order to run XQEMU, the user must dump the MCPX ROM and TSOP flash 14 | images from their own physical Xbox. This, of course, can be a significant 15 | barrier to entry for many users. 16 | 17 | Though it is a goal for XQEMU to continue to maintain compatibility with the 18 | official Xbox system software, it is benificial to also have an open-source 19 | alternative path for multiple reasons, namely licensing and performance 20 | optimizations. Fortunately, the interface between title and the kernel (API) is 21 | simple, clean, and largely documented and can therefore be implemented by an 22 | open-source alternative kernel, maintaining binary compatibility with 23 | unmodified title code. 24 | 25 | **Please note:** by design, this project contains no copyrighted code from the 26 | official Xbox kernel. 27 | 28 | ## Current State 29 | 30 | Currently able to boot [nxdk](https://github.com/XboxDev/nxdk) samples with full 31 | 3D graphics! It'll be a little while before this can boot a real game. 32 | 33 | In order to use this kernel, you'll need to use a [development branch of 34 | XQEMU](https://github.com/mborgerson/xqemu/tree/khle) which facilitates loading 35 | an XBE. 36 | 37 | ## What's Here 38 | 39 | A very basic kernel that will: 40 | 41 | * Switch to protected mode 42 | * Enable the serial port (`printk`) 43 | * Perform barebones device init (PCI, VGA, etc) 44 | * Read the EEPROM 45 | * Poke XQEMU to load an XBE into memory 46 | * Patch XBE imports with stub functions 47 | * Jump to XBE entry point 48 | * Handle a handful of kernel function calls 49 | 50 | ## What's Needed 51 | 52 | High-level list of major things that need to be implemented next: 53 | 54 | Core Stuff: 55 | - Proper kernel memory allocator (SLAB, SLOB might be fine) 56 | - Proper virtual memory allocator for title 57 | - Thread/DPC Scheduler 58 | - Interrupt stuff 59 | 60 | HLE Interfaces: 61 | - XQEMU HLE File IO 62 | - etc. 63 | 64 | Other Kernel things... 65 | - Rtl functions 66 | - Kernel data exports 67 | - Lots of other kernel stuff 68 | 69 | ## Getting Started 70 | 71 | ### How to Build 72 | Standard build tools and NASM are needed, then `make -C src`. 73 | 74 | ### How to Run 75 | Check out run.sh to see how to use this with XQEMU. Please note that you'll need 76 | the dev branch of XQEMU (mentioned above). Also note that you should **not** 77 | provide a `bootrom` image when running this kernel. 78 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | set -x 4 | 5 | CMD=$@ 6 | if [[ "$CMD" == "" ]]; then 7 | CMD="make -C src clean && make -C src" 8 | fi 9 | 10 | docker run --rm -v $PWD:/work -w /work xboxkrnl bash -c "$CMD" 11 | -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | XQEMU=$PWD/../xqemu/i386-softmmu/qemu-system-i386 2 | BIOS=$PWD/src/rom.bin 3 | export KHLE_XBE=$PWD/../nxdk/samples/mesh/bin/default.xbe 4 | 5 | export QEMU_AUDIO_DRV=none 6 | $XQEMU \ 7 | -cpu pentium3 \ 8 | -machine xbox -m 64 \ 9 | -bios $BIOS \ 10 | -net nic,model=nvnet \ 11 | -usb \ 12 | -device usb-xbox-gamepad \ 13 | -accel tcg \ 14 | -display sdl \ 15 | -device lpc47m157 \ 16 | -serial stdio \ 17 | -s \ 18 | 2>&1 19 | -------------------------------------------------------------------------------- /src/.gitignore: -------------------------------------------------------------------------------- 1 | *.d 2 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | CC := gcc 2 | CFLAGS := -Wall -O0 -march=pentium -m32 -g -fno-stack-protector -ffreestanding -fno-pic 3 | LD := ld 4 | LDFLAGS := --script=rom.ld -m elf_i386 --gc-sections 5 | NASM := nasm 6 | NASM_FLAGS := -felf 7 | OBJCOPY := objcopy 8 | OBJCOPYFLAGS := --output-target=binary 9 | TARGET := rom.bin 10 | SOURCES := \ 11 | start.nasm \ 12 | init.c \ 13 | stubs.c \ 14 | printk.c \ 15 | mm/dlmalloc.c \ 16 | mm/paging.c \ 17 | drivers/cpu/cputools.c \ 18 | drivers/cpu/ioapic.c \ 19 | drivers/pci/int_handlers.S \ 20 | drivers/pci/BootInterrupts.c \ 21 | drivers/pci/i2cio.c \ 22 | drivers/pci/pci.c \ 23 | drivers/serial/serial.c \ 24 | drivers/video/BootVgaInitialization.c \ 25 | drivers/video/BootVideoHelpers.c \ 26 | drivers/video/conexant.c \ 27 | drivers/video/VideoInitialization.c \ 28 | lib/eeprom/BootEEPROM.c \ 29 | lib/misc/BootLibrary.c \ 30 | lib/misc/vsprintf.c \ 31 | lib/xbe/xbe.c \ 32 | rtl/mem.c \ 33 | 34 | OBJECTS := $(SOURCES:%.nasm=%.o) 35 | OBJECTS := $(OBJECTS:%.S=%.o) 36 | OBJECTS := $(OBJECTS:%.c=%.o) 37 | 38 | # C include dependency tracking 39 | DEPS := $(filter %.c,$(SOURCES)) 40 | DEPS := $(DEPS:%.c=%.d) 41 | 42 | INCLUDE = -I. -Iinclude -Ilib/eeprom -Ilib/misc -Ilib/font -Idrivers/video -Idrivers/cpu 43 | CFLAGS += $(INCLUDE) 44 | 45 | all: $(TARGET) 46 | .PRECIOUS: $(OBJECTS) $(TARGET:.bin=.elf) 47 | 48 | # Quiet (pass V=1 to make to get full commands) 49 | V = 50 | ifeq ($(V),) 51 | Q = @ 52 | endif 53 | 54 | # Special flags for dlmalloc 55 | mm/dlmalloc.o.cflags = -DHAVE_MORECORE=0 -DHAVE_MREMAP=0 \ 56 | -DDEFAULT_GRANULARITY=4096 -DMSPACES=1 -DUSE_DL_PREFIX=1 \ 57 | -DLACKS_ERRNO_H=1 \ 58 | -DLACKS_FCNTL_H=1 \ 59 | -DLACKS_SCHED_H=1 \ 60 | -DLACKS_STRINGS_H=1 \ 61 | -DLACKS_SYS_PARAM_H=1 \ 62 | -DLACKS_TIME_H=1 \ 63 | -DLACKS_UNISTD_H=1 \ 64 | -DUSE_LOCKS=0 65 | 66 | %.bin: %.elf 67 | @echo "objcopy $@" 68 | $(Q) $(OBJCOPY) $(OBJCOPYFLAGS) $^ $@ 69 | 70 | %.elf: $(OBJECTS) rom.ld 71 | @echo "ld $@" 72 | $(Q) $(LD) $(LDFLAGS) -o $@ $(OBJECTS) 73 | 74 | %.o: %.c 75 | @echo "cc $@" 76 | $(Q) $(CC) $(CFLAGS) $($@.cflags) -MMD -o $@ -c $< 77 | 78 | %.o: %.S 79 | @echo "as $@" 80 | $(Q) $(CC) $(CFLAGS) -o $@ -c $< 81 | 82 | %.o: %.nasm 83 | @echo "nasm $@" 84 | $(Q) $(NASM) -o $@ $(NASM_FLAGS) $< 85 | 86 | .PHONY: clean 87 | clean: 88 | $(Q) rm -f $(TARGET) $(TARGET:.bin=.elf) $(OBJECTS) $(DEPS) 89 | 90 | -include $(DEPS) 91 | -------------------------------------------------------------------------------- /src/drivers/cpu/cpu.h: -------------------------------------------------------------------------------- 1 | 2 | #define rdmsr(msr,val1,val2) \ 3 | __asm__ __volatile__("rdmsr" \ 4 | : "=a" (val1), "=d" (val2) \ 5 | : "c" (msr)) 6 | 7 | #define wrmsr(msr,val1,val2) \ 8 | __asm__ __volatile__("wrmsr" \ 9 | : /* no outputs */ \ 10 | : "c" (msr), "a" (val1), "d" (val2)) 11 | 12 | #define rdtsc(low,high) \ 13 | __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high)) 14 | 15 | #define rdtscl(low) \ 16 | __asm__ __volatile__ ("rdtsc" : "=a" (low) : : "edx") 17 | 18 | #define rdtscll(val) \ 19 | __asm__ __volatile__ ("rdtsc" : "=A" (val)) 20 | 21 | #define rdpmc(counter,low,high) \ 22 | __asm__ __volatile__("rdpmc" \ 23 | : "=a" (low), "=d" (high) \ 24 | : "c" (counter)) 25 | 26 | extern void intel_interrupts_on(void); 27 | extern void cache_disable(void); 28 | extern void cache_enable(void); 29 | extern void cpuid(int op, int *eax, int *ebx, int *ecx, int *edx); 30 | void display_cpuid_update_microcode(void); 31 | void setup_ioapic(void); 32 | -------------------------------------------------------------------------------- /src/drivers/cpu/cputools.c: -------------------------------------------------------------------------------- 1 | #include "boot.h" 2 | #include "config.h" 3 | #include "cpu.h" 4 | 5 | 6 | extern void cpuid(int op, int *eax, int *ebx, int *ecx, int *edx) 7 | { 8 | __asm__("pushl %%ebx\n\t" 9 | "cpuid\n\t" 10 | "movl %%ebx, %%esi\n\t" 11 | "popl %%ebx\n\t" 12 | : "=a" (*eax), 13 | "=S" (*ebx), 14 | "=c" (*ecx), 15 | "=d" (*edx) 16 | : "a" (op) 17 | : "cc"); 18 | } 19 | 20 | extern void intel_interrupts_on() 21 | { 22 | unsigned long low, high; 23 | 24 | // printk("Disabling local apic..."); 25 | 26 | /* this is so interrupts work. This is very limited scope -- 27 | * linux will do better later, we hope ... 28 | */ 29 | rdmsr(0x1b, low, high); 30 | low &= ~0x800; 31 | wrmsr(0x1b, low, high); 32 | } 33 | 34 | extern void cache_disable(void) 35 | { 36 | unsigned int tmp; 37 | 38 | /* Disable cache */ 39 | //printk("Disable Cache\n"); 40 | 41 | /* Write back the cache and flush TLB */ 42 | asm volatile ("movl %%cr0, %0\n\t" 43 | "orl $0x40000000, %0\n\t" 44 | "wbinvd\n\t" 45 | "movl %0, %%cr0\n\t" 46 | "wbinvd\n\t" 47 | : "=r" (tmp) : : "memory"); 48 | } 49 | 50 | extern void cache_enable(void) 51 | { 52 | unsigned int tmp; 53 | 54 | asm volatile ("movl %%cr0, %0\n\t" 55 | "andl $0x9fffffff, %0\n\t" 56 | "movl %0, %%cr0\n\t" 57 | :"=r" (tmp) : : "memory"); 58 | 59 | //printk("Enable Cache\n"); 60 | } 61 | -------------------------------------------------------------------------------- /src/drivers/cpu/ioapic.c: -------------------------------------------------------------------------------- 1 | #include "boot.h" 2 | #include "config.h" 3 | #include "cpu.h" 4 | 5 | struct ioapicreg { 6 | unsigned int reg; 7 | unsigned int value_low, value_high; 8 | }; 9 | struct ioapicreg ioapicregvalues[] = { 10 | #define ALL (0xff << 24) 11 | #define NONE (0) 12 | #define DISABLED (1 << 16) 13 | #define ENABLED (0 << 16) 14 | #define TRIGGER_EDGE (0 << 15) 15 | #define TRIGGER_LEVEL (1 << 15) 16 | #define POLARITY_HIGH (0 << 13) 17 | #define POLARITY_LOW (1 << 13) 18 | #define PHYSICAL_DEST (0 << 11) 19 | #define LOGICAL_DEST (1 << 11) 20 | #define ExtINT (7 << 8) 21 | #define NMI (4 << 8) 22 | #define SMI (2 << 8) 23 | #define INT (1 << 8) 24 | /* mask, trigger, polarity, destination, delivery, vector */ 25 | {0x00, DISABLED, NONE}, 26 | {0x01, DISABLED, NONE}, 27 | {0x02, DISABLED, NONE}, 28 | {0x03, DISABLED, NONE}, 29 | {0x04, DISABLED, NONE}, 30 | {0x05, DISABLED, NONE}, 31 | {0x06, DISABLED, NONE}, 32 | {0x07, DISABLED, NONE}, 33 | {0x08, DISABLED, NONE}, 34 | {0x09, DISABLED, NONE}, 35 | {0x0a, DISABLED, NONE}, 36 | {0x0b, DISABLED, NONE}, 37 | {0x0c, DISABLED, NONE}, 38 | {0x0d, DISABLED, NONE}, 39 | {0x0e, DISABLED, NONE}, 40 | {0x0f, DISABLED, NONE}, 41 | {0x10, DISABLED, NONE}, 42 | {0x11, DISABLED, NONE}, 43 | {0x12, DISABLED, NONE}, 44 | {0x13, DISABLED, NONE}, 45 | {0x14, DISABLED, NONE}, 46 | {0x14, DISABLED, NONE}, 47 | {0x15, DISABLED, NONE}, 48 | {0x16, DISABLED, NONE}, 49 | {0x17, DISABLED, NONE}, 50 | }; 51 | 52 | void setup_ioapic(void) 53 | { 54 | int i; 55 | unsigned long value_low;//, value_high; 56 | unsigned long nvram = 0xfec00000; 57 | volatile unsigned long *l; 58 | struct ioapicreg *a = ioapicregvalues; 59 | 60 | l = (unsigned long *) nvram; 61 | 62 | for (i = 0; i < sizeof(ioapicregvalues) / sizeof(ioapicregvalues[0]); 63 | i++, a++) { 64 | l[0] = (a->reg * 2) + 0x10; 65 | l[4] = a->value_low; 66 | value_low = l[4]; 67 | l[0] = (a->reg *2) + 0x11; 68 | l[4] = a->value_high; 69 | // value_high = l[4]; 70 | if ((i==0) && (value_low == 0xffffffff)) { 71 | printk("IO APIC not responding.\n"); 72 | return; 73 | } 74 | printk("for IRQ, reg 0x%08x value 0x%08x 0x%08x\n", 75 | a->reg, a->value_low, a->value_high); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/drivers/pci/BootInterrupts.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * * 3 | * This program is free software; you can redistribute it and/or modify * 4 | * it under the terms of the GNU General Public License as published by * 5 | * the Free Software Foundation; either version 2 of the License, or * 6 | * (at your option) any later version. * 7 | * * 8 | *************************************************************************** 9 | 10 | */ 11 | 12 | #include "boot.h" 13 | #include "config.h" 14 | #include "cpu.h" 15 | #include "memory_layout.h" 16 | 17 | volatile int nCountI2cinterrupts, nCountUnusedInterrupts, nCountUnusedInterruptsPic2, nCountInterruptsSmc, nCountInterruptsIde; 18 | volatile bool fSeenPowerdown; 19 | volatile TRAY_STATE traystate; 20 | unsigned int wait_ms_time; 21 | 22 | volatile int nInteruptable = 0; 23 | 24 | // interrupt service stubs defined in BootStartup.S 25 | extern void IntHandlerTimer0(void); 26 | extern void IntHandlerI2C(void); 27 | extern void IntHandlerSmc(void); 28 | extern void IntHandlerIde(void); 29 | extern void IntHandlerUnused(void); 30 | extern void IntHandlerUnusedPic2(void); 31 | 32 | extern void IntHandler1(void); 33 | extern void IntHandler2(void); 34 | extern void IntHandler3(void); 35 | extern void IntHandler4(void); 36 | extern void IntHandler5(void); 37 | extern void IntHandler6(void); 38 | extern void IntHandler7(void); 39 | extern void IntHandler8(void); 40 | extern void IntHandler9(void); 41 | extern void IntHandler10(void); 42 | extern void IntHandler13(void); 43 | extern void IntHandler15(void); 44 | 45 | extern void IntHandlerException0(void); 46 | extern void IntHandlerException1(void); 47 | extern void IntHandlerException2(void); 48 | extern void IntHandlerException3(void); 49 | extern void IntHandlerException4(void); 50 | extern void IntHandlerException5(void); 51 | extern void IntHandlerException6(void); 52 | extern void IntHandlerException7(void); 53 | extern void IntHandlerException8(void); 54 | extern void IntHandlerException9(void); 55 | extern void IntHandlerExceptionA(void); 56 | extern void IntHandlerExceptionB(void); 57 | extern void IntHandlerExceptionC(void); 58 | extern void IntHandlerExceptionD(void); 59 | extern void IntHandlerExceptionE(void); 60 | extern void IntHandlerExceptionF(void); 61 | extern void IntHandlerException10(void); 62 | 63 | // structure defining our ISRs 64 | 65 | typedef struct { 66 | u8 m_bInterruptCpu; 67 | u32 m_dwpVector; 68 | } ISR_PREP; 69 | 70 | const ISR_PREP isrprep[] = { 71 | { 0x00, (u32)IntHandlerException0 }, 72 | { 0x01, (u32)IntHandlerException1 }, 73 | { 0x02, (u32)IntHandlerException2 }, 74 | { 0x03, (u32)IntHandlerException3 }, 75 | { 0x04, (u32)IntHandlerException4 }, 76 | { 0x05, (u32)IntHandlerException5 }, 77 | { 0x06, (u32)IntHandlerException6 }, 78 | { 0x07, (u32)IntHandlerException7 }, 79 | { 0x08, (u32)IntHandlerException8 }, 80 | { 0x09, (u32)IntHandlerException9 }, 81 | { 0x0a, (u32)IntHandlerExceptionA }, 82 | { 0x0b, (u32)IntHandlerExceptionB }, 83 | { 0x0c, (u32)IntHandlerExceptionC }, 84 | { 0x0d, (u32)IntHandlerExceptionD }, 85 | { 0x0e, (u32)IntHandlerExceptionE }, 86 | { 0x0f, (u32)IntHandlerExceptionF }, 87 | { 0x10, (u32)IntHandlerException10 }, 88 | 89 | // interrupts from PIC1 90 | 91 | { 0x20, (u32)IntHandlerTimer0 }, 92 | { 0x21, (u32)IntHandler1 }, 93 | { 0x22, (u32)IntHandler2 }, 94 | { 0x23, (u32)IntHandler3 }, 95 | { 0x24, (u32)IntHandler4 }, 96 | { 0x25, (u32)IntHandler5 }, 97 | { 0x26, (u32)IntHandler6 }, 98 | { 0x27, (u32)IntHandler7 }, 99 | 100 | // interrupts from PIC 2 101 | 102 | { 0x70, (u32)IntHandler8 }, 103 | { 0x71, (u32)IntHandler9 }, 104 | { 0x72, (u32)IntHandler10 }, 105 | { 0x73, (u32)IntHandlerI2C }, 106 | { 0x74, (u32)IntHandlerSmc }, 107 | { 0x75, (u32)IntHandler13 }, 108 | { 0x76, (u32)IntHandlerIde }, 109 | { 0x77, (u32)IntHandler15 }, 110 | 111 | { 0, 0 } 112 | }; 113 | 114 | 115 | 116 | void wait_smalldelay(void) { 117 | wait_us(80); 118 | } 119 | 120 | void wait_us(u32 ticks) { 121 | 122 | /* 123 | 32 Bit range = 1200 sec ! => 20 min 124 | 1. sec = 0x369E99 125 | 1 ms = 3579,545 126 | 127 | */ 128 | 129 | u32 COUNT_start; 130 | u32 temp; 131 | u32 COUNT_TO; 132 | u32 HH; 133 | 134 | // Maximum Input range 135 | if (ticks>(1200*1000)) ticks = 1200*1000; 136 | 137 | COUNT_TO = (u32) ((float)(ticks*3.579545)); 138 | COUNT_start = IoInputDword(0x8008); 139 | 140 | while(1) { 141 | 142 | // Reads out the System timer 143 | HH = IoInputDword(0x8008); 144 | temp = HH-COUNT_start; 145 | // We reached the counter 146 | if (temp>COUNT_TO) break; 147 | 148 | }; 149 | 150 | 151 | } 152 | 153 | void wait_ms(u32 ticks) { 154 | 155 | /* 156 | 32 Bit range = 1200 sec ! => 20 min 157 | 1. sec = 0x369E99 158 | 1 ms = 3579,545 159 | 160 | */ 161 | 162 | u32 COUNT_start; 163 | u32 temp; 164 | u32 COUNT_TO; 165 | u32 HH; 166 | 167 | // Maximum Input range 168 | if (ticks>(1200*1000)) ticks = 1200*1000; 169 | 170 | COUNT_TO = (u32) ((float)(ticks*3579.545)); 171 | COUNT_start = IoInputDword(0x8008); 172 | 173 | while(1) { 174 | // Reads out the System timer 175 | HH = IoInputDword(0x8008); 176 | temp = HH-COUNT_start; 177 | // We reached the counter 178 | if (temp>COUNT_TO) break; 179 | }; 180 | 181 | 182 | } 183 | 184 | 185 | void (*video_interrupt_hook)(void) = 0; 186 | ts_pm_interrupt IDT_LOC[256]; 187 | 188 | #pragma pack(1) 189 | struct dbg_idtr 190 | { 191 | uint16_t len; 192 | uint32_t offset; 193 | }; 194 | #pragma pack() 195 | 196 | /* 197 | * Load a new IDT. 198 | */ 199 | int dbg_load_idt(struct dbg_idtr *idtr) 200 | { 201 | asm volatile ( 202 | "lidt %0" 203 | /* Outputs */ : /* None */ 204 | /* Inputs */ : "m" (*idtr) 205 | /* Clobbers */ : /* None */ 206 | ); 207 | 208 | return 0; 209 | } 210 | 211 | 212 | void BootInterruptsWriteIdt() { 213 | 214 | volatile ts_pm_interrupt * ptspmi=(volatile ts_pm_interrupt *)(IDT_LOC); // ie, start of IDT area 215 | int n, n1=0; 216 | 217 | struct dbg_idtr idtr; 218 | idtr.len = sizeof(IDT_LOC)-1; 219 | idtr.offset = (uint32_t)IDT_LOC; 220 | dbg_load_idt(&idtr); 221 | 222 | 223 | // init storage used by ISRs 224 | 225 | VIDEO_VSYNC_POSITION=0; 226 | BIOS_TICK_COUNT=0; 227 | VIDEO_VSYNC_DIR=0; 228 | nCountI2cinterrupts=0; 229 | nCountUnusedInterrupts=0; 230 | nCountUnusedInterruptsPic2=0; 231 | nCountInterruptsSmc=0; 232 | nCountInterruptsIde=0; 233 | fSeenPowerdown=false; 234 | traystate=ETS_OPEN_OR_OPENING; 235 | VIDEO_LUMASCALING=0; 236 | VIDEO_RSCALING=0; 237 | VIDEO_BSCALING=0; 238 | 239 | // set up default exception, interrupt vectors to dummy stubs 240 | 241 | for(n=0;n<0x100;n++) { // have to do 256 242 | ptspmi[n].m_wSelector=0x8; 243 | ptspmi[n].m_wType=0x8e00; // interrupt gate, 32-bit 244 | if(n==isrprep[n1].m_bInterruptCpu) { // is it next on our prep list? If so, stick it in 245 | ptspmi[n].m_wHandlerHighAddressLow16=(u16)isrprep[n1].m_dwpVector; 246 | ptspmi[n].m_wHandlerLinearAddressHigh16=(u16)(((u32)isrprep[n1].m_dwpVector)>>16); 247 | n1++; 248 | } else { // otherwise default handler (pretty useless, but will catch it) 249 | ptspmi[n].m_wHandlerHighAddressLow16=(u16)(u32)IntHandlerUnused; 250 | ptspmi[n].m_wHandlerLinearAddressHigh16=(u16)(((u32)IntHandlerUnused)>>16); 251 | } 252 | } 253 | 254 | // set up the Programmable Inetrrupt Controllers 255 | 256 | IoOutputByte(0x20, 0x15); // master PIC setup 257 | IoOutputByte(0x21, 0x20); // base interrupt vector address 258 | IoOutputByte(0x21, 0x04); // am master, INT2 is hooked to slave 259 | IoOutputByte(0x21, 0x01); // x86 mode, normal EOI 260 | IoOutputByte(0x21, 0x00); // enable all ints 261 | 262 | IoOutputByte(0xa0, 0x15); // slave PIC setup 263 | IoOutputByte(0xa1, 0x70); // base interrupt vector address 264 | IoOutputByte(0xa1, 0x02); // am slave, hooked to INT2 on master 265 | IoOutputByte(0xa1, 0x01); // x86 mode normal EOI 266 | 267 | IoOutputByte(0xa1, 0x00); // enable int14(IDE) int12(SMI) 268 | 269 | // enable interrupts 270 | intel_interrupts_on(); 271 | } 272 | 273 | 274 | 275 | /////////////////////////////////////////// 276 | // 277 | // ISRs 278 | 279 | 280 | void IntHandlerCSmc(void) 281 | { 282 | u8 bStatus, nBit=0; 283 | unsigned int temp; 284 | u8 temp_AV_mode; 285 | 286 | nCountInterruptsSmc++; 287 | 288 | 289 | temp = IoInputWord(0x8000); 290 | if (temp!=0x0) { 291 | IoOutputWord(0x8000,temp); 292 | //printk("System Timer wants to sleep we kill him"); 293 | // return; 294 | } 295 | 296 | 297 | 298 | bStatus=I2CTransmitByteGetReturn(0x10, 0x11); // Query PIC for interrupt reason 299 | 300 | // we do nothing, if there is not Interrupt reason 301 | if (bStatus==0x0) return; 302 | 303 | while(nBit<7) { 304 | if(bStatus & 1) { 305 | u8 b=0x04; 306 | switch(nBit) { 307 | case 0: // POWERDOWN EVENT 308 | bprintf("SMC Interrupt %d: Powerdown\n", nCountInterruptsSmc); 309 | I2CTransmitWord(0x10, 0x0200); 310 | I2CTransmitWord(0x10, 0x0100|b); 311 | I2CTransmitWord(0x10, 0x0500|b); 312 | I2CTransmitWord(0x10, 0x0600|b); 313 | I2CTransmitWord(0x10, 0x0900|b); 314 | I2CTransmitWord(0x10, 0x0a00|b); 315 | I2CTransmitWord(0x10, 0x0b00|b); 316 | I2CTransmitWord(0x10, 0x0d00|b); 317 | I2CTransmitWord(0x10, 0x0e00|b); 318 | I2CTransmitWord(0x10, 0x0f00|b); 319 | I2CTransmitWord(0x10, 0x1000|b); 320 | I2CTransmitWord(0x10, 0x1200|b); 321 | I2CTransmitWord(0x10, 0x1300|b); 322 | I2CTransmitWord(0x10, 0x1400|b); 323 | I2CTransmitWord(0x10, 0x1500|b); 324 | I2CTransmitWord(0x10, 0x1600|b); 325 | I2CTransmitWord(0x10, 0x1700|b); 326 | I2CTransmitWord(0x10, 0x1800|b); 327 | fSeenPowerdown=true; 328 | break; 329 | 330 | case 1: // CDROM TRAY IS NOW CLOSED 331 | traystate=ETS_CLOSED; 332 | bprintf("SMC Interrupt %d: CDROM Tray now Closed\n", nCountInterruptsSmc); 333 | DVD_TRAY_STATE = DVD_CLOSED; 334 | break; 335 | 336 | case 2: // CDROM TRAY IS STARTING OPENING 337 | traystate=ETS_OPEN_OR_OPENING; 338 | DVD_TRAY_STATE = DVD_OPENING; 339 | I2CTransmitWord(0x10, 0x0d02); 340 | bprintf("SMC Interrupt %d: CDROM starting opening\n", nCountInterruptsSmc); 341 | break; 342 | 343 | case 3: // AV CABLE HAS BEEN PLUGGED IN 344 | 345 | temp_AV_mode =I2CTransmitByteGetReturn(0x10, 0x04); 346 | // Compare to global variable 347 | if (VIDEO_AV_MODE != temp_AV_mode ) { 348 | VIDEO_AV_MODE = 0xff; 349 | wait_ms(30); 350 | VIDEO_AV_MODE = temp_AV_mode; 351 | BootVgaInitializationKernelNG((CURRENT_VIDEO_MODE_DETAILS *)&vmode); 352 | wait_ms(200); 353 | BootVgaInitializationKernelNG((CURRENT_VIDEO_MODE_DETAILS *)&vmode); 354 | 355 | } 356 | break; 357 | 358 | case 4: // AV CABLE HAS BEEN UNPLUGGED 359 | bprintf("SMC Interrupt %d: AV cable unplugged\n", nCountInterruptsSmc); 360 | VIDEO_AV_MODE=0xff; 361 | //vmode.m_bAvPack=0xff; 362 | break; 363 | 364 | case 5: // BUTTON PRESSED REQUESTING TRAY OPEN 365 | traystate=ETS_OPEN_OR_OPENING; 366 | I2CTransmitWord(0x10, 0x0d04); 367 | I2CTransmitWord(0x10, 0x0c00); 368 | bprintf("SMC Interrupt %d: CDROM tray opening by Button press\n", nCountInterruptsSmc); 369 | bStatus&=~0x02; // kill possibility of conflicting closing report 370 | break; 371 | 372 | case 6: // CDROM TRAY IS STARTING CLOSING 373 | traystate=ETS_CLOSING; 374 | DVD_TRAY_STATE = DVD_CLOSING; 375 | bprintf("SMC Interrupt %d: CDROM tray starting closing\n", nCountInterruptsSmc); 376 | break; 377 | 378 | case 7: // UNKNOWN 379 | bprintf("SMC Interrupt %d: b7 Reason code\n", nCountInterruptsSmc); 380 | break; 381 | } 382 | } 383 | nBit++; 384 | bStatus>>=1; 385 | } 386 | } 387 | 388 | // FIXME: clean this up 389 | #undef bprintf 390 | #define bprintf printk 391 | 392 | void IntHandlerCIde(void) 393 | { 394 | if(!nInteruptable) return; 395 | IoInputByte(0x1f7); 396 | bprintf("IDE Interrupt\n"); 397 | nCountInterruptsIde++; 398 | } 399 | 400 | void IntHandlerCI2C(void) 401 | { 402 | if(!nInteruptable) return; 403 | nCountI2cinterrupts++; 404 | } 405 | void IntHandlerUnusedC(void) 406 | { 407 | if(!nInteruptable) return; 408 | bprintf("Unhandled Interrupt\n"); 409 | //printk("Unhandled Interrupt"); 410 | nCountUnusedInterrupts++; 411 | //while(1) ; 412 | } 413 | 414 | 415 | void IntHandlerUnusedC2(void) 416 | { 417 | if(!nInteruptable) return; 418 | 419 | bprintf("Unhandled Interrupt 2\n"); 420 | nCountUnusedInterruptsPic2++; 421 | } 422 | 423 | 424 | 425 | // this guy is getting called at 1kHz 426 | 427 | void IntHandlerCTimer0(void) 428 | { 429 | BIOS_TICK_COUNT++; 430 | } 431 | 432 | 433 | // USB interrupt 434 | 435 | void IntHandler1C(void) 436 | { 437 | // Interrupt for OHCI controller located on 0xfed00000 438 | if(!nInteruptable) return; 439 | // USBGetEvents(); 440 | } 441 | void IntHandler9C(void) 442 | { 443 | // Interrupt for OHCI controller located on 0xfed08000 444 | if(!nInteruptable) return; 445 | // USBGetEvents(); 446 | } 447 | 448 | 449 | void IntHandler2C(void) 450 | { 451 | if(!nInteruptable) return; 452 | bprintf("Interrupt 2\n"); 453 | } 454 | 455 | void IntHandler3VsyncC(void) // video VSYNC 456 | { 457 | if (video_interrupt_hook) { 458 | video_interrupt_hook(); 459 | } else { 460 | *((volatile u32 *)0xfd600100)=0x1; // clear VSYNC int 461 | } 462 | } 463 | 464 | 465 | void IntHandler4C(void) 466 | { 467 | if(!nInteruptable) return; 468 | bprintf("Interrupt 4\n"); 469 | } 470 | void IntHandler5C(void) 471 | { 472 | if(!nInteruptable) return; 473 | bprintf("Interrupt 5\n"); 474 | } 475 | 476 | void IntHandler6C(void) { 477 | 478 | bprintf("Interrupt 6\n"); 479 | } 480 | 481 | void IntHandler7C(void) 482 | { 483 | if(!nInteruptable) return; 484 | bprintf("Interrupt 7\n"); 485 | } 486 | 487 | void IntHandler8C(void) 488 | { 489 | bprintf("Interrupt 8\n"); 490 | } 491 | 492 | 493 | void IntHandler10C(void) 494 | { 495 | if(!nInteruptable) return; 496 | bprintf("Interrupt 10\n"); 497 | } 498 | 499 | void IntHandler13C(void) 500 | { 501 | bprintf("Interrupt 13\n"); 502 | } 503 | 504 | void IntHandler15C(void) 505 | { 506 | if(!nInteruptable) return; 507 | bprintf("Unhandled Interrupt 15\n"); 508 | } 509 | 510 | //void IntHandlerException0C(void) { bprintf("CPU Exc: Divide by Zero\n"); while(1) ; } 511 | void IntHandlerException0C(void) { bprintf("CPU Exc: Divide by Zero\n");} 512 | void IntHandlerException1C(void) { bprintf("CPU Exc: Single Step\n"); while(1) ; } 513 | void IntHandlerException2C(void) { bprintf("CPU Exc: NMI\n"); while(1) ; } 514 | void IntHandlerException3C(void) { bprintf("CPU Exc: Breakpoint\n"); while(1) ; } 515 | void IntHandlerException4C(void) { bprintf("CPU Exc: Overflow Trap\n"); while(1) ; } 516 | void IntHandlerException5C(void) { bprintf("CPU Exc: BOUND exceeded\n"); while(1) ; } 517 | void IntHandlerException6C(void) { 518 | u32 dwEbp=0; 519 | bprintf("CPU Exc: Invalid Opcode\n"); 520 | __asm__ __volatile__ ( " mov %%esp, %%eax\n " : "=a" (dwEbp) ); 521 | bprintf(" %08lX:%08lX\n", *((volatile u32 *)(dwEbp+0x48)), *((volatile u32 *)(dwEbp+0x44))); 522 | while(1) ; 523 | } 524 | //void IntHandlerException7C(void) { bprintf("CPU Exc: Coprocessor Absent\n"); while(1) ; } 525 | void IntHandlerException7C(void) { bprintf("CPU Exc: Coprocessor Absent\n");} 526 | void IntHandlerException8C(void) { bprintf("CPU Exc: Double Fault\n"); while(1) ; } 527 | //void IntHandlerException9C(void) { bprintf("CPU Exc: Copro Seg Overrun\n"); while(1) ; } 528 | void IntHandlerException9C(void) { bprintf("CPU Exc: Copro Seg Overrun\n");} 529 | void IntHandlerExceptionAC(void) { bprintf("CPU Exc: Invalid TSS\n"); while(1) ; } 530 | void IntHandlerExceptionBC(void) { bprintf("CPU Exc: Segment not present\n"); while(1) ; } 531 | void IntHandlerExceptionCC(void) { bprintf("CPU Exc: Stack Exception\n"); while(1) ; } 532 | void IntHandlerExceptionDC(void) { bprintf("CPU Exc: General Protection Fault\n"); while(1) ; } 533 | void IntHandlerExceptionEC(void) { bprintf("CPU Exc: Page Fault\n"); while(1) ; } 534 | void IntHandlerExceptionFC(void) { bprintf("CPU Exc: Reserved\n"); while(1) ; } 535 | //void IntHandlerException10C(void) { bprintf("CPU Exc: Copro Error\n"); while(1) ; } 536 | void IntHandlerException10C(void) { bprintf("CPU Exc: Copro Error\n");} 537 | 538 | 539 | -------------------------------------------------------------------------------- /src/drivers/pci/i2cio.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * * 3 | * This program is free software; you can redistribute it and/or modify * 4 | * it under the terms of the GNU General Public License as published by * 5 | * the Free Software Foundation; either version 2 of the License, or * 6 | * (at your option) any later version. * 7 | * * 8 | ***************************************************************************/ 9 | 10 | #include "boot.h" 11 | 12 | /* 13 | WriteToSMBus() by Lehner Franz (franz@caos.at) 14 | ReadfromSMBus() by Lehner Franz (franz@caos.at) 15 | */ 16 | 17 | int WriteToSMBus(u8 Address,u8 bRegister,u8 Size,u32 Data_to_smbus) 18 | { 19 | int nRetriesToLive=50; 20 | 21 | while(IoInputWord(I2C_IO_BASE+0)&0x0800) ; // Franz's spin while bus busy with any master traffic 22 | 23 | while(nRetriesToLive--) { 24 | 25 | u8 b; 26 | unsigned int temp; 27 | 28 | IoOutputByte(I2C_IO_BASE+4, (Address<<1)|0); 29 | IoOutputByte(I2C_IO_BASE+8, bRegister); 30 | 31 | switch (Size) { 32 | case 4: 33 | IoOutputByte(I2C_IO_BASE+9, Data_to_smbus&0xff); 34 | IoOutputByte(I2C_IO_BASE+9, (Data_to_smbus >> 8) & 0xff ); 35 | IoOutputByte(I2C_IO_BASE+9, (Data_to_smbus >> 16) & 0xff ); 36 | IoOutputByte(I2C_IO_BASE+9, (Data_to_smbus >> 24) & 0xff ); 37 | IoOutputWord(I2C_IO_BASE+6, 4); 38 | break; 39 | case 2: 40 | IoOutputWord(I2C_IO_BASE+6, Data_to_smbus&0xffff); 41 | break; 42 | default: // 1 43 | IoOutputWord(I2C_IO_BASE+6, Data_to_smbus&0xff); 44 | break; 45 | } 46 | 47 | 48 | temp = IoInputWord(I2C_IO_BASE+0); 49 | IoOutputWord(I2C_IO_BASE+0, temp); // clear down all preexisting errors 50 | 51 | switch (Size) { 52 | case 4: 53 | IoOutputByte(I2C_IO_BASE+2, 0x1d); // u32 modus 54 | break; 55 | case 2: 56 | IoOutputByte(I2C_IO_BASE+2, 0x1b); // u16 modus 57 | break; 58 | default: // 1 59 | IoOutputByte(I2C_IO_BASE+2, 0x1a); // u8 modus 60 | break; 61 | } 62 | 63 | b = 0; 64 | 65 | while( (b&0x36)==0 ) { b=IoInputByte(I2C_IO_BASE+0); } 66 | 67 | if ((b&0x10) != 0) { 68 | return ERR_SUCCESS; 69 | 70 | } 71 | 72 | wait_us(1); 73 | } 74 | 75 | return ERR_I2C_ERROR_BUS; 76 | 77 | } 78 | 79 | 80 | 81 | int ReadfromSMBus(u8 Address,u8 bRegister,u8 Size,u32 *Data_to_smbus) 82 | { 83 | int nRetriesToLive=50; 84 | 85 | while(IoInputWord(I2C_IO_BASE+0)&0x0800) ; // Franz's spin while bus busy with any master traffic 86 | 87 | while(nRetriesToLive--) { 88 | u8 b; 89 | int temp; 90 | 91 | IoOutputByte(I2C_IO_BASE+4, (Address<<1)|1); 92 | IoOutputByte(I2C_IO_BASE+8, bRegister); 93 | 94 | temp = IoInputWord(I2C_IO_BASE+0); 95 | IoOutputWord(I2C_IO_BASE+0, temp); // clear down all preexisting errors 96 | 97 | switch (Size) { 98 | case 4: 99 | IoOutputByte(I2C_IO_BASE+2, 0x0d); // u32 modus ? 100 | break; 101 | case 2: 102 | IoOutputByte(I2C_IO_BASE+2, 0x0b); // u16 modus 103 | break; 104 | default: 105 | IoOutputByte(I2C_IO_BASE+2, 0x0a); // u8 106 | break; 107 | } 108 | 109 | b = 0; 110 | 111 | 112 | while( (b&0x36)==0 ) { b=IoInputByte(I2C_IO_BASE+0); } 113 | 114 | if(b&0x24) { 115 | //printf("I2CTransmitByteGetReturn error %x\n", b); 116 | } 117 | 118 | if(!(b&0x10)) { 119 | //printf("I2CTransmitByteGetReturn no complete, retry\n"); 120 | } else { 121 | switch (Size) { 122 | case 4: 123 | IoInputByte(I2C_IO_BASE+6); 124 | IoInputByte(I2C_IO_BASE+9); 125 | IoInputByte(I2C_IO_BASE+9); 126 | IoInputByte(I2C_IO_BASE+9); 127 | IoInputByte(I2C_IO_BASE+9); 128 | break; 129 | case 2: 130 | *Data_to_smbus = IoInputWord(I2C_IO_BASE+6); 131 | break; 132 | default: 133 | *Data_to_smbus = IoInputByte(I2C_IO_BASE+6); 134 | break; 135 | } 136 | 137 | 138 | return ERR_SUCCESS; 139 | 140 | } 141 | 142 | } 143 | 144 | return ERR_I2C_ERROR_BUS; 145 | } 146 | 147 | /* ************************************************************************************************************* */ 148 | 149 | 150 | 151 | int I2CWriteWordtoRegister(u8 bPicAddressI2cFormat,u8 bRegister ,u16 wDataToWrite) 152 | { 153 | // int WriteToSMBus(u8 Address,u8 bRegister,u8 Size,u32 Data_to_smbus) 154 | return WriteToSMBus(bPicAddressI2cFormat,bRegister,2,wDataToWrite); 155 | } 156 | 157 | 158 | /* --------------------- Normal 8 bit operations -------------------------- */ 159 | 160 | 161 | int I2CTransmitByteGetReturn(u8 bPicAddressI2cFormat, u8 bDataToWrite) 162 | { 163 | unsigned int temp; 164 | if (ReadfromSMBus(bPicAddressI2cFormat,bDataToWrite,1,&temp) != ERR_SUCCESS) return ERR_I2C_ERROR_BUS; 165 | return temp; 166 | } 167 | 168 | 169 | // transmit a word, no returned data from I2C device 170 | 171 | int I2CTransmitWord(u8 bPicAddressI2cFormat, u16 wDataToWrite) 172 | { 173 | return WriteToSMBus(bPicAddressI2cFormat,(wDataToWrite>>8)&0xff,1,(wDataToWrite&0xff)); 174 | } 175 | 176 | 177 | int I2CWriteBytetoRegister(u8 bPicAddressI2cFormat, u8 bRegister, u8 wDataToWrite) 178 | { 179 | return WriteToSMBus(bPicAddressI2cFormat,bRegister,1,(wDataToWrite&0xff)); 180 | 181 | } 182 | 183 | 184 | void I2CModifyBits(u8 bAds, u8 bReg, u8 bData, u8 bMask) 185 | { 186 | u8 b=I2CTransmitByteGetReturn(0x45, bReg)&(~bMask); 187 | I2CTransmitWord(0x45, (bReg<<8)|((bData)&bMask)|b); 188 | } 189 | 190 | // ---------------------------- PIC challenge/response ----------------------------------------------------------- 191 | 192 | extern int I2cSetFrontpanelLed(u8 b) 193 | { 194 | I2CTransmitWord( 0x10, 0x800 | b); // sequencing thanks to Jarin the Penguin! 195 | I2CTransmitWord( 0x10, 0x701); 196 | 197 | 198 | return ERR_SUCCESS; 199 | } 200 | 201 | bool I2CGetTemperature(int * pnLocalTemp, int * pExternalTemp) 202 | { 203 | *pnLocalTemp=I2CTransmitByteGetReturn(0x4c, 0x01); 204 | *pExternalTemp=I2CTransmitByteGetReturn(0x4c, 0x00); 205 | 206 | //Check for bus error - 1.6 xboxes have no readable 207 | //temperature sensors. 208 | if (*pnLocalTemp==ERR_I2C_ERROR_BUS || 209 | *pExternalTemp==ERR_I2C_ERROR_BUS) 210 | return false; 211 | return true; 212 | } 213 | 214 | void I2CRebootQuick(void) { 215 | WriteToSMBus(0x10,0x02,1,0x01); 216 | while (1); 217 | } 218 | 219 | 220 | void I2CRebootSlow(void) { 221 | WriteToSMBus(0x10,0x02,1,0x40); 222 | while (1); 223 | } 224 | 225 | void I2CPowerOff(void) { 226 | WriteToSMBus(0x10,0x02,1,0x80); 227 | while (1); 228 | } 229 | -------------------------------------------------------------------------------- /src/drivers/pci/int_handlers.S: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * BIOS ROM Startup Assembler 4 | */ 5 | 6 | /*************************************************************************** 7 | * * 8 | * This program is free software; you can redistribute it and/or modify * 9 | * it under the terms of the GNU General Public License as published by * 10 | * the Free Software Foundation; either version 2 of the License, or * 11 | * (at your option) any later version. * 12 | * * 13 | ***************************************************************************/ 14 | #include "consts.h" 15 | #include "memory_layout.h" 16 | 17 | 18 | .code32 19 | 20 | .section .text, "ax" 21 | 22 | /////////////////////////////////////////// 23 | // 24 | // Interrupt Service Routines 25 | // 26 | 27 | 28 | .global IntHandlerTimer0 29 | IntHandlerTimer0: 30 | cli 31 | pusha 32 | pushf 33 | call IntHandlerCTimer0 34 | mov $0x20, %al 35 | outb %al, $0x20 36 | popf 37 | // sti 38 | popa 39 | iret 40 | 41 | 42 | .global IntHandler1 43 | IntHandler1: 44 | pusha 45 | pushf 46 | cli 47 | call IntHandler1C 48 | mov $0x21, %al 49 | outb %al, $0x20 50 | popf 51 | // sti 52 | popa 53 | iret 54 | 55 | 56 | .global IntHandler2 57 | IntHandler2: 58 | cli 59 | pusha 60 | pushf 61 | call IntHandler2C 62 | mov $0x22, %al 63 | outb %al, $0x20 64 | popf 65 | popa 66 | // sti 67 | iret 68 | 69 | 70 | 71 | .global IntHandler3 72 | IntHandler3: 73 | cli 74 | pusha 75 | pushf 76 | call IntHandler3VsyncC 77 | mov $0x23, %al 78 | outb %al, $0x20 79 | popf 80 | popa 81 | // sti 82 | iret 83 | 84 | 85 | .global IntHandler4 86 | IntHandler4: 87 | cli 88 | pusha 89 | pushf 90 | call IntHandler4C 91 | mov $0x24, %al 92 | outb %al, $0x20 93 | popf 94 | popa 95 | // sti 96 | iret 97 | 98 | 99 | .global IntHandler5 100 | IntHandler5: 101 | cli 102 | pusha 103 | pushf 104 | call IntHandler5C 105 | mov $0x25, %al 106 | outb %al, $0x20 107 | popf 108 | popa 109 | // sti 110 | iret 111 | 112 | 113 | .global IntHandler6 114 | IntHandler6: 115 | cli 116 | pusha 117 | pushf 118 | call IntHandler6C 119 | mov $0x26, %al 120 | outb %al, $0x20 121 | popf 122 | popa 123 | sti 124 | iret 125 | 126 | 127 | 128 | .global IntHandler7 129 | IntHandler7: 130 | cli 131 | pusha 132 | pushf 133 | call IntHandler7C 134 | mov $0x27, %al 135 | outb %al, $0x20 136 | popf 137 | popa 138 | sti 139 | iret 140 | 141 | 142 | 143 | .global IntHandler8 144 | IntHandler8: 145 | cli 146 | pusha 147 | pushf 148 | call IntHandler8C 149 | // EOI on master and slave needed 150 | mov $0x60, %al 151 | out %al, $0xa0 152 | mov $0x62, %al 153 | out %al, $0x20 154 | popf 155 | popa 156 | iret 157 | 158 | 159 | 160 | 161 | .global IntHandler9 162 | IntHandler9: 163 | pusha 164 | pushf 165 | cli 166 | call IntHandler9C 167 | // EOI on master and slave needed 168 | mov $0x61, %al 169 | out %al, $0xa0 170 | mov $0x62, %al 171 | out %al, $0x20 172 | popf 173 | popa 174 | iret 175 | 176 | // Int 10 interrupts 177 | 178 | .global IntHandler10 179 | IntHandler10: 180 | pusha 181 | pushf 182 | cli 183 | call IntHandler10C 184 | // EOI on master and slave needed 185 | mov $0x62, %al 186 | out %al, $0xa0 187 | mov $0x62, %al 188 | out %al, $0x20 189 | popf 190 | popa 191 | iret 192 | 193 | // Int 11 interrupts 194 | 195 | .global IntHandlerI2C 196 | IntHandlerI2C: 197 | pusha 198 | pushf 199 | cli 200 | call IntHandlerCI2C 201 | 202 | // EOI on master and slave needed 203 | mov $0x63, %al 204 | out %al, $0xa0 205 | mov $0x62, %al 206 | out %al, $0x20 207 | popf 208 | popa 209 | iret 210 | 211 | // Int 12 interrupts 212 | 213 | .global IntHandlerSmc 214 | IntHandlerSmc: 215 | cli 216 | pusha 217 | pushf 218 | 219 | call IntHandlerCSmc 220 | 221 | // acknowledge EXTSMI# action (from PIC p6) 222 | 223 | mov $0x8020, %dx 224 | inw %dx, %ax 225 | or $0x0200, %ax 226 | outw %ax, %dx 227 | 228 | // EOI on master and slave needed 229 | mov $0x64, %al // is int12 230 | out %al, $0xa0 231 | mov $0x62, %al // do cascaded master 232 | out %al, $0x20 233 | popf 234 | popa 235 | iret 236 | 237 | // Int 13 interrupts 238 | 239 | .global IntHandler13 240 | IntHandler13: 241 | cli 242 | pusha 243 | pushf 244 | 245 | call IntHandler13C 246 | // EOI on master and slave needed 247 | mov $0x65, %al 248 | out %al, $0xa0 249 | mov $0x62, %al 250 | out %al, $0x20 251 | popf 252 | popa 253 | iret 254 | 255 | // Int 14 interrupts 256 | 257 | .global IntHandlerIde 258 | IntHandlerIde: 259 | cli 260 | pusha 261 | pushf 262 | 263 | call IntHandlerCIde 264 | 265 | // EOI on master and slave needed 266 | mov $0x66, %al // was $0x20 267 | out %al, $0xa0 268 | mov $0x62, %al 269 | out %al, $0x20 270 | popf 271 | popa 272 | iret 273 | 274 | // Int 15 interrupts 275 | 276 | .global IntHandler15 277 | IntHandler15: 278 | cli 279 | pusha 280 | pushf 281 | 282 | call IntHandler15C 283 | // EOI on master and slave needed 284 | mov $0x67, %al 285 | out %al, $0xa0 286 | mov $0x62, %al 287 | out %al, $0x20 288 | popf 289 | popa 290 | iret 291 | 292 | 293 | // unused interrupts on master PIC 294 | 295 | .global IntHandlerUnused 296 | IntHandlerUnused: 297 | cli 298 | pusha 299 | pushf 300 | 301 | call IntHandlerUnusedC 302 | mov $0x20, %al 303 | out %al, $0x20 304 | popf 305 | popa 306 | iret 307 | 308 | // unused interrupts on slave PIC 309 | 310 | .global IntHandlerUnusedPic2 311 | IntHandlerUnusedPic2: 312 | cli 313 | pusha 314 | pushf 315 | 316 | call IntHandlerUnusedC2 317 | mov $0xffff, %ax 318 | mov $0x8028, %dx 319 | outw %ax, %dx 320 | mov $0x80cc, %dx 321 | mov $0x40, %al 322 | outb %al, %dx 323 | 324 | mov $0x20, %al 325 | out %al, $0xa0 326 | mov $0x62, %al 327 | out %al, $0x20 328 | popf 329 | popa 330 | iret 331 | 332 | .global SpareIntNop 333 | SpareIntNop: 334 | iret 335 | 336 | 337 | // CPU Exception Interrupts 338 | 339 | .global IntHandlerException0 340 | IntHandlerException0: 341 | pusha 342 | pushf 343 | cli 344 | call IntHandlerException0C 345 | popf 346 | popa 347 | iret 348 | 349 | .global IntHandlerException1 350 | IntHandlerException1: 351 | pusha 352 | pushf 353 | cli 354 | call IntHandlerException1C 355 | popf 356 | popa 357 | iret 358 | 359 | .global IntHandlerException2 360 | IntHandlerException2: 361 | pusha 362 | pushf 363 | cli 364 | call IntHandlerException2C 365 | popf 366 | popa 367 | iret 368 | 369 | .global IntHandlerException3 370 | IntHandlerException3: 371 | pusha 372 | pushf 373 | cli 374 | call IntHandlerException3C 375 | popf 376 | popa 377 | iret 378 | 379 | .global IntHandlerException4 380 | IntHandlerException4: 381 | pusha 382 | pushf 383 | cli 384 | call IntHandlerException4C 385 | popf 386 | popa 387 | iret 388 | 389 | .global IntHandlerException5 390 | IntHandlerException5: 391 | pusha 392 | pushf 393 | cli 394 | call IntHandlerException5C 395 | popf 396 | popa 397 | iret 398 | 399 | .global IntHandlerException6 400 | IntHandlerException6: 401 | pusha 402 | pushf 403 | cli 404 | call IntHandlerException6C 405 | popf 406 | popa 407 | iret 408 | 409 | .global IntHandlerException7 410 | IntHandlerException7: 411 | pusha 412 | pushf 413 | cli 414 | call IntHandlerException7C 415 | popf 416 | popa 417 | iret 418 | 419 | .global IntHandlerException8 420 | IntHandlerException8: 421 | pusha 422 | pushf 423 | cli 424 | call IntHandlerException8C 425 | popf 426 | popa 427 | iret 428 | 429 | .global IntHandlerException9 430 | IntHandlerException9: 431 | pusha 432 | pushf 433 | cli 434 | call IntHandlerException9C 435 | popf 436 | popa 437 | iret 438 | 439 | .global IntHandlerExceptionA 440 | IntHandlerExceptionA: 441 | pusha 442 | pushf 443 | cli 444 | call IntHandlerExceptionAC 445 | popf 446 | popa 447 | iret 448 | 449 | .global IntHandlerExceptionB 450 | IntHandlerExceptionB: 451 | pusha 452 | pushf 453 | cli 454 | call IntHandlerExceptionBC 455 | popf 456 | popa 457 | iret 458 | 459 | .global IntHandlerExceptionC 460 | IntHandlerExceptionC: 461 | pusha 462 | pushf 463 | cli 464 | call IntHandlerExceptionCC 465 | popf 466 | popa 467 | iret 468 | 469 | .global IntHandlerExceptionD 470 | IntHandlerExceptionD: 471 | pusha 472 | pushf 473 | cli 474 | call IntHandlerExceptionDC 475 | popf 476 | popa 477 | iret 478 | 479 | .global IntHandlerExceptionE 480 | IntHandlerExceptionE: 481 | pusha 482 | pushf 483 | cli 484 | call IntHandlerExceptionEC 485 | popf 486 | popa 487 | iret 488 | 489 | .global IntHandlerExceptionF 490 | IntHandlerExceptionF: 491 | pusha 492 | pushf 493 | cli 494 | call IntHandlerExceptionFC 495 | popf 496 | popa 497 | iret 498 | 499 | .global IntHandlerException10 500 | IntHandlerException10: 501 | pusha 502 | pushf 503 | cli 504 | call IntHandlerException10C 505 | popf 506 | popa 507 | iret 508 | 509 | 510 | 511 | 512 | 513 | -------------------------------------------------------------------------------- /src/drivers/serial/serial.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Matt Borgerson 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | */ 18 | 19 | #include "boot.h" 20 | 21 | #define SERIAL_PORT 0x3f8 22 | #define SERIAL_THR 0 23 | #define SERIAL_LSR 5 24 | 25 | void serial_init() 26 | { 27 | IoOutputByte(0x2e, 0x55); /* Enter Configuration */ 28 | 29 | /* Select serial device */ 30 | IoOutputByte(0x2e, 0x07); 31 | IoOutputByte(0x2f, 0x04); 32 | 33 | /* Enable device */ 34 | IoOutputByte(0x2e, 0x30); 35 | IoOutputByte(0x2f, 0x01); 36 | 37 | /* Set Serial Base = 0x3f8 */ 38 | IoOutputByte(0x2e, 0x61); 39 | IoOutputByte(0x2f, SERIAL_PORT & 0xff); 40 | 41 | IoOutputByte(0x2e, 0x60); 42 | IoOutputByte(0x2f, SERIAL_PORT >> 8); 43 | 44 | IoOutputByte(0x2e, 0xAA); /* Exit Configuration */ 45 | } 46 | 47 | int serial_putchar(int ch) 48 | { 49 | /* Wait for THRE (bit 5) to be high */ 50 | while ((IoInputByte(SERIAL_PORT + SERIAL_LSR) & (1<<5)) == 0); 51 | IoOutputByte(SERIAL_PORT + SERIAL_THR, ch); 52 | return ch; 53 | } 54 | -------------------------------------------------------------------------------- /src/drivers/video/BootVgaInitialization.c: -------------------------------------------------------------------------------- 1 | /* 2 | * video-related stuff 3 | * 2004-03-03 dmp@davidmpye.dyndns.org Synced with kernel fb driver, added proper focus support etc 4 | * 2003-02-02 andy@warmcat.com Major reshuffle, threw out tons of unnecessary init 5 | Made a good start on separating the video mode from the AV cable 6 | Consolidated init tables into a big struct (see boot.h) 7 | * 2002-12-04 andy@warmcat.com Video now working :-) 8 | */ 9 | 10 | /*************************************************************************** 11 | * * 12 | * This program is free software; you can redistribute it and/or modify * 13 | * it under the terms of the GNU General Public License as published by * 14 | * the Free Software Foundation; either version 2 of the License, or * 15 | * (at your option) any later version. * 16 | * * 17 | ***************************************************************************/ 18 | 19 | #include "boot.h" 20 | #include "BootEEPROM.h" 21 | #include "config.h" 22 | #include "BootVideo.h" 23 | #include "video.h" 24 | #include "memory_layout.h" 25 | #include "VideoInitialization.h" 26 | #include "BootVgaInitialization.h" 27 | #include "encoder.h" 28 | // #include "xcalibur.h" 29 | #include "conexant.h" 30 | // #include "focus.h" 31 | 32 | void DetectVideoEncoder(void) { 33 | if (I2CTransmitByteGetReturn(0x45,0x00) != ERR_I2C_ERROR_BUS) video_encoder = ENCODER_CONEXANT; 34 | else if (I2CTransmitByteGetReturn(0x6a,0x00) != ERR_I2C_ERROR_BUS) video_encoder = ENCODER_FOCUS; 35 | else video_encoder = ENCODER_XCALIBUR; 36 | } 37 | 38 | char *VideoEncoderName(void) { 39 | char *focus_name="Focus"; 40 | char *conexant_name="Conexant"; 41 | char *xcalibur_name="Xcalibur"; 42 | char *unknown_name="Unknown"; 43 | 44 | switch (video_encoder) { 45 | case ENCODER_CONEXANT: 46 | return conexant_name; 47 | case ENCODER_FOCUS: 48 | return focus_name; 49 | case ENCODER_XCALIBUR: 50 | return xcalibur_name; 51 | default: 52 | return unknown_name; 53 | } 54 | } 55 | 56 | char *AvCableName(void) { 57 | char *composite_name="Composite"; 58 | char *svideo_name="S-Video"; 59 | char *rgb_name="RGB SCART"; 60 | char *hdtv_name="HDTV"; 61 | char *vga_name="VGA"; 62 | char *vgasog_name="VGA SoG"; 63 | char *unknown_name="Unknown"; 64 | 65 | xbox_av_type av_type = DetectAvType(); 66 | switch (av_type) { 67 | case AV_SCART_RGB: 68 | return rgb_name; 69 | case AV_SVIDEO: 70 | return svideo_name; 71 | case AV_VGA_SOG: 72 | return vgasog_name; 73 | case AV_HDTV: 74 | return hdtv_name; 75 | case AV_COMPOSITE: 76 | return composite_name; 77 | case AV_VGA: 78 | return vga_name; 79 | default: 80 | return unknown_name; 81 | } 82 | } 83 | 84 | void BootVgaInitializationKernelNG(CURRENT_VIDEO_MODE_DETAILS * pvmode) { 85 | xbox_tv_encoding tv_encoding; 86 | xbox_av_type av_type; 87 | u8 b; 88 | RIVA_HW_INST riva; 89 | struct riva_regs newmode; 90 | int encoder_ok = 0; 91 | int i=0; 92 | GPU_PARAMETER gpu; 93 | xbox_video_mode encoder_mode; 94 | 95 | tv_encoding = DetectVideoStd(); 96 | DetectVideoEncoder(); 97 | 98 | // Dump to global variable 99 | VIDEO_AV_MODE=I2CTransmitByteGetReturn(0x10, 0x04); 100 | av_type = DetectAvType(); 101 | gpu.av_type = av_type; 102 | 103 | memset((void *)pvmode,0,sizeof(CURRENT_VIDEO_MODE_DETAILS)); 104 | 105 | //Focus driver (presumably XLB also) doesnt do widescreen yet - only blackscreens otherwise. 106 | if(((u8 *)&eeprom)[0x96]&0x01 && video_encoder == ENCODER_CONEXANT) { // 16:9 widescreen TV 107 | pvmode->m_nVideoModeIndex=VIDEO_MODE_1024x576; 108 | } else { // 4:3 TV 109 | pvmode->m_nVideoModeIndex=VIDEO_PREFERRED_MODE; 110 | } 111 | 112 | // If the client hasn't set the frame buffer start address, assume 113 | // it should be at 4M from the end of RAM. 114 | 115 | pvmode->m_dwFrameBufferStart = FB_START; 116 | 117 | (*(unsigned int*)0xFD600800) = (FB_START & 0x0fffffff); 118 | 119 | pvmode->m_bAvPack=I2CTransmitByteGetReturn(0x10, 0x04); 120 | pvmode->m_pbBaseAddressVideo=(u8 *)0xfd000000; 121 | pvmode->m_fForceEncoderLumaAndChromaToZeroInitially=1; 122 | pvmode->m_bBPP = 32; 123 | 124 | // The values for hoc and voc are stolen from nvtv small mode 125 | switch (tv_encoding) { 126 | case TV_ENC_PALBDGHI: 127 | pvmode->hoc = 13.44; 128 | pvmode->voc = 14.24; 129 | break; 130 | case TV_ENC_NTSC: 131 | default: 132 | pvmode->hoc = 15.11; 133 | pvmode->voc = 14.81; 134 | break; 135 | } 136 | 137 | pvmode->hoc /= 100.0; 138 | pvmode->voc /= 100.0; 139 | 140 | mapNvMem(&riva,pvmode->m_pbBaseAddressVideo); 141 | unlockCrtNv(&riva,0); 142 | 143 | if (xbox_ram == 128) { 144 | MMIO_H_OUT32(riva.PFB,0,0x200,0x03070103); 145 | } else { 146 | MMIO_H_OUT32(riva.PFB,0,0x200,0x03070003); 147 | } 148 | 149 | MMIO_H_OUT32 (riva.PCRTC, 0, 0x800, pvmode->m_dwFrameBufferStart); 150 | 151 | IoOutputByte(0x80d3, 5); // Kill all video out using an ACPI control pin 152 | 153 | MMIO_H_OUT32(riva.PRAMDAC,0,0x884,0x0); 154 | MMIO_H_OUT32(riva.PRAMDAC,0,0x888,0x0); 155 | MMIO_H_OUT32(riva.PRAMDAC,0,0x88c,0x10001000); 156 | MMIO_H_OUT32(riva.PRAMDAC,0,0x890,0x10000000); 157 | MMIO_H_OUT32(riva.PRAMDAC,0,0x894,0x10000000); 158 | MMIO_H_OUT32(riva.PRAMDAC,0,0x898,0x10000000); 159 | MMIO_H_OUT32(riva.PRAMDAC,0,0x89c,0x10000000); 160 | 161 | if (video_encoder==ENCODER_XCALIBUR) { 162 | MMIO_H_OUT32(riva.PRAMDAC,0,0x880,0x21101100); 163 | //Leave GPU in YUV for Xcalibur 164 | MMIO_H_OUT32(riva.PRAMDAC,0,0x630,0x2); 165 | MMIO_H_OUT32(riva.PRAMDAC,0,0x84c,0x00801080); 166 | MMIO_H_OUT32(riva.PRAMDAC,0,0x8c4,0x40801080); 167 | } 168 | else { 169 | MMIO_H_OUT32(riva.PRAMDAC,0,0x880,0); 170 | //Other encoders use RGB 171 | MMIO_H_OUT32(riva.PRAMDAC,0,0x630,0x0); 172 | MMIO_H_OUT32(riva.PRAMDAC,0,0x84c,0x0); 173 | MMIO_H_OUT32(riva.PRAMDAC,0,0x8c4,0x0); 174 | } 175 | 176 | writeCrtNv (&riva, 0, 0x14, 0x00); 177 | writeCrtNv (&riva, 0, 0x17, 0xe3); // Set CRTC mode register 178 | writeCrtNv (&riva, 0, 0x19, 0x10); // ? 179 | writeCrtNv (&riva, 0, 0x1b, 0x05); // arbitration0 180 | writeCrtNv (&riva, 0, 0x22, 0xff); // ? 181 | writeCrtNv (&riva, 0, 0x33, 0x11); // ? 182 | 183 | if (av_type == AV_HDTV) { 184 | unsigned char pll_int; 185 | xbox_hdtv_mode hdtv_mode = HDTV_480p; 186 | //Only 480p supported at present 187 | /*if (video_mode->yres > 800) { 188 | hdtv_mode = HDTV_1080i; 189 | } 190 | else if (video_mode->yres > 600) { 191 | hdtv_mode = HDTV_720p; 192 | }*/ 193 | 194 | // Settings for 720x480@60Hz (480p) 195 | pvmode->width=720; 196 | pvmode->height=480; 197 | pvmode->xmargin=0; 198 | pvmode->ymargin=0; 199 | 200 | if (video_encoder==ENCODER_XCALIBUR) { 201 | /* This info should be in the xcalibur.c file, but 202 | * the HDTV api doesn't allow for it right now. */ 203 | gpu.nvhtotal = 779; 204 | gpu.nvvtotal = 524; 205 | } 206 | else { 207 | /* HDTV uses hardcoded settings for these - these are the 208 | * correct ones for 480p */ 209 | gpu.nvhtotal = 858; 210 | gpu.nvvtotal = 525; 211 | } 212 | 213 | gpu.xres = pvmode->width; 214 | gpu.yres = pvmode->height; 215 | gpu.nvhstart = 738; 216 | gpu.nvvstart = 489; 217 | gpu.pixelDepth = (32 + 1) / 8; 218 | gpu.crtchdispend = pvmode->width; 219 | gpu.crtcvstart = gpu.nvvstart; 220 | gpu.crtcvtotal = gpu.nvvtotal; 221 | 222 | pll_int = (unsigned char)((double)27027 * 6.0 / 13.5e3 + 0.5); 223 | switch (video_encoder) { 224 | case ENCODER_CONEXANT: 225 | encoder_ok = conexant_calc_hdtv_mode(hdtv_mode, pll_int, &(newmode.encoder_regs)); 226 | break; 227 | #if 0 228 | case ENCODER_FOCUS: 229 | encoder_ok = focus_calc_hdtv_mode(hdtv_mode, pll_int, &(newmode.encoder_regs)); 230 | break; 231 | case ENCODER_XCALIBUR: 232 | encoder_ok = xcalibur_calc_hdtv_mode(hdtv_mode, pll_int, &(newmode.encoder_regs)); 233 | break; 234 | #endif 235 | } 236 | } 237 | else if ((av_type == AV_VGA_SOG) || (av_type == AV_VGA)) { 238 | unsigned char pll_int; 239 | // Settings for 800x600@56Hz, 35 kHz HSync 240 | pvmode->width=800; 241 | pvmode->height=600; 242 | pvmode->xmargin=20; 243 | pvmode->ymargin=20; 244 | 245 | gpu.xres = pvmode->width; 246 | gpu.nvhstart = 900; 247 | gpu.nvhtotal = 1028; 248 | gpu.yres = pvmode->height; 249 | gpu.nvvstart = 614; 250 | gpu.nvvtotal = 630; 251 | gpu.pixelDepth = (32 + 1) / 8; 252 | gpu.crtchdispend = pvmode->width; 253 | gpu.crtcvstart = gpu.nvvstart; 254 | gpu.crtcvtotal = gpu.nvvtotal; 255 | pll_int = (unsigned char)((double)36000 * 6.0 / 13.5e3 + 0.5); 256 | 257 | switch (video_encoder) { 258 | case ENCODER_CONEXANT: 259 | encoder_ok = conexant_calc_vga_mode(av_type, pll_int, &(newmode.encoder_regs)); 260 | break; 261 | case ENCODER_FOCUS: 262 | case ENCODER_XCALIBUR: 263 | //No support for these yet 264 | break; 265 | } 266 | } 267 | else { 268 | /* All other cable types - normal SDTV */ 269 | switch(pvmode->m_nVideoModeIndex) { 270 | case VIDEO_MODE_640x480: 271 | pvmode->width=640; 272 | pvmode->height=480; 273 | pvmode->xmargin=0; 274 | pvmode->ymargin=0; 275 | break; 276 | case VIDEO_MODE_640x576: 277 | pvmode->width=640; 278 | pvmode->height=576; 279 | pvmode->xmargin=40; // pixels 280 | pvmode->ymargin=40; // lines 281 | break; 282 | case VIDEO_MODE_720x576: 283 | pvmode->width=720; 284 | pvmode->height=576; 285 | pvmode->xmargin=40; // pixels 286 | pvmode->ymargin=40; // lines 287 | break; 288 | case VIDEO_MODE_800x600: // 800x600 289 | pvmode->width=800; 290 | pvmode->height=600; 291 | pvmode->xmargin=20; 292 | pvmode->ymargin=20; // lines 293 | break; 294 | case VIDEO_MODE_1024x576: // 1024x576 295 | pvmode->width=1024; 296 | pvmode->height=576; 297 | pvmode->xmargin=20; 298 | pvmode->ymargin=20; // lines 299 | break; 300 | } 301 | encoder_mode.xres = pvmode->width; 302 | encoder_mode.yres = pvmode->height; 303 | encoder_mode.tv_encoding = tv_encoding; 304 | encoder_mode.bpp = 32; 305 | encoder_mode.hoc = pvmode->hoc; 306 | encoder_mode.voc = pvmode->voc; 307 | encoder_mode.av_type = av_type; 308 | encoder_mode.tv_encoding = tv_encoding; 309 | 310 | switch (video_encoder) { 311 | case ENCODER_CONEXANT: 312 | encoder_ok = conexant_calc_mode(&encoder_mode, &newmode); 313 | break; 314 | #if 0 315 | case ENCODER_FOCUS: 316 | encoder_ok = focus_calc_mode(&encoder_mode, &newmode); 317 | break; 318 | case ENCODER_XCALIBUR: 319 | encoder_ok = xcalibur_calc_mode(&encoder_mode, &newmode); 320 | break; 321 | #endif 322 | } 323 | 324 | gpu.xres = pvmode->width; 325 | gpu.nvhstart = newmode.ext.hsyncstart; 326 | gpu.nvhtotal = newmode.ext.htotal; 327 | gpu.yres = pvmode->height; 328 | gpu.nvvstart = newmode.ext.vsyncstart; 329 | gpu.nvvtotal = newmode.ext.vtotal; 330 | gpu.pixelDepth = (32 + 1) / 8; 331 | gpu.crtchdispend = pvmode->width; 332 | gpu.crtcvstart = newmode.ext.vsyncstart; 333 | gpu.crtcvtotal = newmode.ext.vtotal; 334 | } 335 | 336 | if (encoder_ok) { 337 | //Load registers into chip 338 | unsigned char *regs; 339 | // unsigned long *XCal_Reg; 340 | int n1=0; 341 | 342 | //Set up the GPU 343 | SetGPURegister(&gpu, pvmode->m_pbBaseAddressVideo); 344 | 345 | switch (video_encoder) { 346 | case ENCODER_CONEXANT: 347 | I2CWriteBytetoRegister(0x45,0xc4, 0x00); // EN_OUT = 1 348 | // Conexant init (starts at register 0x2e) 349 | regs = newmode.encoder_regs; 350 | for(i=0x2e,n1=0;i<0x100;i+=2,n1++) { 351 | switch(i) { 352 | case 0x6c: // reset 353 | I2CWriteBytetoRegister(0x45,i, regs[n1] & 0x7f); 354 | break; 355 | case 0xc4: // EN_OUT 356 | I2CWriteBytetoRegister(0x45,i, regs[n1] & 0xfe); 357 | break; 358 | case 0xb8: // autoconfig 359 | break; 360 | default: 361 | I2CWriteBytetoRegister(0x45,i, regs[n1]); 362 | break; 363 | } 364 | wait_us(500); 365 | } 366 | // Timing Reset 367 | b=I2CTransmitByteGetReturn(0x45,0x6c) & (0x7f); 368 | I2CWriteBytetoRegister(0x45, 0x6c, 0x80|b); 369 | b=I2CTransmitByteGetReturn(0x45,0xc4) & (0xfe); 370 | I2CWriteBytetoRegister(0x45, 0xc4, 0x01|b); // EN_OUT = 1 371 | break; 372 | 373 | #if 0 374 | case ENCODER_FOCUS: 375 | regs = newmode.encoder_regs; 376 | for (i=0; i<0xc4; ++i) { 377 | I2CWriteBytetoRegister(0x6a, i, regs[i]); 378 | wait_us(500); 379 | } 380 | break; 381 | case ENCODER_XCALIBUR: 382 | //Xlb init 383 | XCal_Reg = newmode.encoder_regs; 384 | regs = malloc(4); 385 | 386 | ReadfromSMBus(0x70,4,4,&i); 387 | WriteToSMBus(0x70,4,4,0x0F000000); 388 | ReadfromSMBus(0x70,0,4,&i); 389 | WriteToSMBus(0x70,0,4,0x00000000); 390 | 391 | for(i = 0; i < 0x90; i++) { 392 | //Endianness. 393 | memcpy(regs,(unsigned char*)(&XCal_Reg[i])+3,0x01); 394 | memcpy(regs+1,(unsigned char*)(&XCal_Reg[i])+2,0x01); 395 | memcpy(regs+2,(unsigned char*)(&XCal_Reg[i])+1,0x01); 396 | memcpy(regs+3,(unsigned char*)(&XCal_Reg[i]),0x01); 397 | 398 | WriteToSMBus(0x70, i, 4, *(unsigned long*)regs); 399 | wait_us(500); 400 | } 401 | free(regs); 402 | break; 403 | #endif 404 | } 405 | } 406 | //Free the malloc'd registers 407 | free(newmode.encoder_regs); 408 | 409 | NVDisablePalette (&riva, 0); 410 | writeCrtNv (&riva, 0, 0x44, 0x03); 411 | NVInitGrSeq(&riva); 412 | writeCrtNv (&riva, 0, 0x44, 0x00); 413 | NVInitAttr(&riva,0); 414 | IoOutputByte(0x80d8, 4); // ACPI IO thing seen in kernel, set to 4 415 | IoOutputByte(0x80d6, 5); // ACPI IO thing seen in kernel, set to 4 or 5 416 | NVVertIntrEnabled (&riva,0); 417 | NVSetFBStart (&riva, 0, pvmode->m_dwFrameBufferStart); 418 | IoOutputByte(0x80d3, 4); // ACPI IO video enable REQUIRED <-- particularly crucial to get composite out 419 | 420 | //Dim Conexant video out. 421 | if (video_encoder == ENCODER_CONEXANT) { 422 | I2CTransmitWord(0x45, (0xa8<<8)|0); 423 | I2CTransmitWord(0x45, (0xaa<<8)|0); 424 | I2CTransmitWord(0x45, (0xac<<8)|0); 425 | } 426 | 427 | NVWriteSeq(&riva, 0x01, 0x01); /* reenable display */ 428 | 429 | //Turn on the output 430 | switch (video_encoder) { 431 | case ENCODER_CONEXANT: 432 | I2CWriteBytetoRegister(0x45, 0xA8, 0x81); 433 | I2CWriteBytetoRegister(0x45, 0xAA, 0x49); 434 | I2CWriteBytetoRegister(0x45, 0xAC, 0x8C); 435 | break; 436 | #if 0 437 | case ENCODER_FOCUS: 438 | b = I2CTransmitByteGetReturn(0x6a,0x0c); 439 | b &= ~0x01; 440 | I2CWriteBytetoRegister(0x6a,0x0c,b); 441 | b = I2CTransmitByteGetReturn(0x6a,0x0d); 442 | I2CWriteBytetoRegister(0x6a,0x0d,b); 443 | break; 444 | case ENCODER_XCALIBUR: 445 | //No action required 446 | break; 447 | #endif 448 | } 449 | } 450 | 451 | 452 | static void NVSetFBStart (RIVA_HW_INST *riva, int head, u32 dwFBStart) { 453 | MMIO_H_OUT32 (riva->PCRTC, head, 0x8000, dwFBStart); 454 | MMIO_H_OUT32 (riva->PMC, head, 0x8000, dwFBStart); 455 | } 456 | 457 | static void NVVertIntrEnabled (RIVA_HW_INST *riva, int head) 458 | { 459 | MMIO_H_OUT32 (riva->PCRTC, head, 0x140, 0x1); 460 | MMIO_H_OUT32 (riva->PCRTC, head, 0x100, 0x1); 461 | MMIO_H_OUT32 (riva->PCRTC, head, 0x140, 1); 462 | MMIO_H_OUT32 (riva->PMC, head, 0x140, 0x1); 463 | MMIO_H_OUT32 (riva->PMC, head, 0x100, 0x1); 464 | MMIO_H_OUT32 (riva->PMC, head, 0x140, 1); 465 | } 466 | 467 | static inline void unlockCrtNv (RIVA_HW_INST *riva, int head) 468 | { 469 | writeCrtNv (riva, head, 0x1f, 0x57); /* unlock extended registers */ 470 | } 471 | 472 | static inline void lockCrtNv (RIVA_HW_INST *riva, int head) 473 | { 474 | writeCrtNv (riva, head, 0x1f, 0x99); /* lock extended registers */ 475 | } 476 | 477 | 478 | static void writeCrtNv (RIVA_HW_INST *riva, int head, int reg, u8 val) 479 | { 480 | VGA_WR08(riva->PCIO, CRT_INDEX(head), reg); 481 | VGA_WR08(riva->PCIO, CRT_DATA(head), val); 482 | } 483 | 484 | static void mapNvMem (RIVA_HW_INST *riva, u8 *IOAddress) 485 | { 486 | riva->PMC = IOAddress+0x000000; 487 | riva->PFB = IOAddress+0x100000; 488 | riva->PEXTDEV = IOAddress+0x101000; 489 | riva->PCRTC = IOAddress+0x600000; 490 | riva->PCIO = riva->PCRTC + 0x1000; 491 | riva->PVIO = IOAddress+0x0C0000; 492 | riva->PRAMDAC = IOAddress+0x680000; 493 | riva->PDIO = riva->PRAMDAC + 0x1000; 494 | riva->PVIDEO = IOAddress+0x008000; 495 | riva->PTIMER = IOAddress+0x009000; 496 | } 497 | 498 | static void NVDisablePalette (RIVA_HW_INST *riva, int head) 499 | { 500 | (void)VGA_RD08(riva->PCIO + head * HEAD, VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); 501 | VGA_WR08(riva->PCIO + head * HEAD, VGA_ATTR_INDEX, 0x20); 502 | } 503 | 504 | 505 | static void NVWriteSeq(RIVA_HW_INST *riva, CARD8 index, CARD8 value) 506 | { 507 | 508 | VGA_WR08(riva->PVIO, VGA_SEQ_INDEX, index); 509 | VGA_WR08(riva->PVIO, VGA_SEQ_DATA, value); 510 | 511 | } 512 | 513 | static void NVWriteGr(RIVA_HW_INST *riva, CARD8 index, CARD8 value) 514 | { 515 | VGA_WR08(riva->PVIO, VGA_GRAPH_INDEX, index); 516 | VGA_WR08(riva->PVIO, VGA_GRAPH_DATA, value); 517 | } 518 | 519 | static void NVInitGrSeq (RIVA_HW_INST *riva) 520 | { 521 | NVWriteSeq(riva, 0x00, 0x03); 522 | NVWriteSeq(riva, 0x01, 0x21); 523 | NVWriteSeq(riva, 0x02, 0x0f); 524 | NVWriteSeq(riva, 0x03, 0x00); 525 | NVWriteSeq(riva, 0x04, 0x06); 526 | NVWriteGr(riva, 0x00, 0x00); 527 | NVWriteGr(riva, 0x01, 0x00); 528 | NVWriteGr(riva, 0x02, 0x00); 529 | NVWriteGr(riva, 0x03, 0x00); 530 | NVWriteGr(riva, 0x04, 0x00); /* depth != 1 */ 531 | NVWriteGr(riva, 0x05, 0x40); /* depth != 1 && depth != 4 */ 532 | NVWriteGr(riva, 0x06, 0x05); 533 | NVWriteGr(riva, 0x07, 0x0f); 534 | NVWriteGr(riva, 0x08, 0xff); 535 | } 536 | 537 | static void NVWriteAttr(RIVA_HW_INST *riva, int head, CARD8 index, CARD8 value) 538 | { 539 | MMIO_H_OUT8(riva->PCIO, head, VGA_ATTR_INDEX, index); 540 | MMIO_H_OUT8(riva->PCIO, head, VGA_ATTR_DATA_W, value); 541 | } 542 | 543 | static void NVInitAttr (RIVA_HW_INST *riva, int head) 544 | { 545 | NVWriteAttr(riva,0, 0, 0x01); 546 | NVWriteAttr(riva,0, 1, 0x02); 547 | NVWriteAttr(riva,0, 2, 0x03); 548 | NVWriteAttr(riva,0, 3, 0x04); 549 | NVWriteAttr(riva,0, 4, 0x05); 550 | NVWriteAttr(riva,0, 5, 0x06); 551 | NVWriteAttr(riva,0, 6, 0x07); 552 | NVWriteAttr(riva,0, 7, 0x08); 553 | NVWriteAttr(riva,0, 8, 0x09); 554 | NVWriteAttr(riva,0, 9, 0x0a); 555 | NVWriteAttr(riva,0, 10, 0x0b); 556 | NVWriteAttr(riva,0, 11, 0x0c); 557 | NVWriteAttr(riva,0, 12, 0x0d); 558 | NVWriteAttr(riva,0, 13, 0x0e); 559 | NVWriteAttr(riva,0, 14, 0x0f); 560 | NVWriteAttr(riva,0, 15, 0x01); 561 | NVWriteAttr(riva,0, 16, 0x4a); 562 | NVWriteAttr(riva,0, 17, 0x0f); 563 | NVWriteAttr(riva,0, 18, 0x00); 564 | NVWriteAttr(riva,0, 19, 0x00); 565 | } 566 | 567 | -------------------------------------------------------------------------------- /src/drivers/video/BootVgaInitialization.h: -------------------------------------------------------------------------------- 1 | #ifndef BOOTVGAINITIALIZATION_H 2 | #define BOOTVGAINITIALIZATION_H 3 | 4 | /* Standard VGA registers */ 5 | #define VGA_ATTR_INDEX 0x3C0 6 | #define VGA_ATTR_DATA_W 0x3C0 7 | #define VGA_ATTR_DATA_R 0x3C1 8 | #define VGA_IN_STAT_0 0x3C2 /* read */ 9 | #define VGA_MISC_OUT_W 0x3C2 /* write */ 10 | #define VGA_ENABLE 0x3C3 11 | #define VGA_SEQ_INDEX 0x3C4 12 | #define VGA_SEQ_DATA 0x3C5 13 | #define VGA_DAC_MASK 0x3C6 14 | #define VGA_DAC_READ_ADDR 0x3C7 15 | #define VGA_DAC_WRITE_ADDR 0x3C8 16 | #define VGA_DAC_DATA 0x3C9 17 | #define VGA_FEATURE_R 0x3CA /* read */ 18 | #define VGA_MISC_OUT_R 0x3CC /* read */ 19 | #define VGA_GRAPH_INDEX 0x3CE 20 | #define VGA_GRAPH_DATA 0x3CF 21 | 22 | #define VGA_IOBASE_MONO 0x3B0 23 | #define VGA_IOBASE_COLOR 0x3D0 24 | 25 | #define VGA_CRTC_INDEX_OFFSET 0x04 26 | #define VGA_CRTC_DATA_OFFSET 0x05 27 | #define VGA_IN_STAT_1_OFFSET 0x0A /* read */ 28 | #define VGA_FEATURE_W_OFFSET 0x0A /* write */ 29 | 30 | /* Little macro to construct bitmask for contiguous ranges of bits */ 31 | 32 | #define BITMASK(t,b) (((unsigned)(1U << (((t)-(b)+1)))-1) << (b)) 33 | #define MASKEXPAND(mask) BITMASK(1?mask,0?mask) 34 | 35 | /* Macro to set specific bitfields (mask has to be a macro x:y) ! */ 36 | 37 | #define SetBF(mask,value) ((value) << (0?mask)) 38 | #define GetBF(var,mask) (((unsigned)((var) & MASKEXPAND(mask))) >> (0?mask) ) 39 | 40 | #define MaskAndSetBF(var,mask,value) (var)=(((var)&(~MASKEXPAND(mask)) \ 41 | | SetBF(mask,value))) 42 | 43 | /* SetBitField: Move bit-range in 'from' to bit-range in 'to' */ 44 | 45 | #define SetBitField(value,from,to) SetBF(to, GetBF(value,from)) 46 | #define SetBitFlag(value,mask,to) ((value & mask) ? (1 << to) : 0) 47 | #define SetBit(n) (1<<(n)) 48 | #define GetBit(value,n) ((value)&(1<<(n))) 49 | #define GetBitFlag(value,from,mask) (GetBit(value,from) ? mask : 0) 50 | #define Set8Bits(value) ((value)&0xff) 51 | 52 | #define HEAD 0x2000 53 | 54 | #define CARD8 u8 55 | #define CARD32 u32 56 | 57 | #define MMIO_IN8(base, offset) \ 58 | *(volatile CARD8 *)(((CARD8*)(base)) + (offset)) 59 | #define MMIO_IN16(base, offset) \ 60 | *(volatile CARD16 *)(void *)(((CARD8*)(base)) + (offset)) 61 | #define MMIO_IN32(base, offset) \ 62 | *(volatile CARD32 *)(void *)(((CARD8*)(base)) + (offset)) 63 | #define MMIO_OUT8(base, offset, val) \ 64 | *(volatile CARD8 *)(((CARD8*)(base)) + (offset)) = (val) 65 | #define MMIO_OUT16(base, offset, val) \ 66 | *(volatile CARD16 *)(void *)(((CARD8*)(base)) + (offset)) = (val) 67 | #define MMIO_OUT32(base, offset, val) \ 68 | *(volatile CARD32 *)(void *)(((CARD8*)(base)) + (offset)) = (val) 69 | #define MMIO_ONB8(base, offset, val) MMIO_OUT8(base, offset, val) 70 | #define MMIO_ONB16(base, offset, val) MMIO_OUT16(base, offset, val) 71 | #define MMIO_ONB32(base, offset, val) MMIO_OUT32(base, offset, val) 72 | 73 | #define MMIO_H_IN8(base,h,offset) MMIO_IN8(base,(offset)+(h)*HEAD) 74 | #define MMIO_H_IN32(base,h,offset) MMIO_IN32(base,(offset)+(h)*HEAD) 75 | #define MMIO_H_OUT8(base,h,offset,val) MMIO_OUT8(base,(offset)+(h)*HEAD,val) 76 | #define MMIO_H_OUT32(base,h,offset,val) MMIO_OUT32(base,(offset)+(h)*HEAD,val) 77 | 78 | #define MMIO_H_AND32(base,h,offset,val) MMIO_AND32(base,(offset)+(h)*HEAD,val) 79 | #define MMIO_H_OR32(base,h,offset,val) MMIO_OR32(base,(offset)+(h)*HEAD,val) 80 | 81 | #define MMIO_AND32(base, offset, val) \ 82 | *(volatile CARD32 *)(void *)(((CARD8*)(base)) + (offset)) &= (val) 83 | #define MMIO_OR32(base, offset, val) \ 84 | *(volatile CARD32 *)(void *)(((CARD8*)(base)) + (offset)) |= (val) 85 | 86 | 87 | /* these assume memory-mapped I/O, and not normal I/O space */ 88 | #define NV_WR08(p,i,d) MMIO_OUT8((volatile void *)(p), (i), (d)) 89 | #define NV_RD08(p,i) MMIO_IN8((volatile void *)(p), (i)) 90 | #define NV_WR16(p,i,d) MMIO_OUT16((volatile void *)(p), (i), (d)) 91 | #define NV_RD16(p,i) MMIO_IN16((volatile void *)(p), (i)) 92 | #define NV_WR32(p,i,d) MMIO_OUT32((volatile void *)(p), (i), (d)) 93 | #define NV_RD32(p,i) MMIO_IN32((volatile void *)(p), (i)) 94 | 95 | #define VGA_WR08(p,i,d) NV_WR08(p,i,d) 96 | #define VGA_RD08(p,i) NV_RD08(p,i) 97 | 98 | #define CRT_INDEX(h) (0x3d4 + (h) * HEAD) 99 | #define CRT_DATA(h) (0x3d5 + (h) * HEAD) 100 | 101 | #define NV_FLAG_DOUBLE_PIX (1 << 1) 102 | #define NV_FLAG_DOUBLE_SCAN (1 << 0) 103 | 104 | #define DEV_TELEVISION (1 << 1) 105 | #define DEV_FLATPANEL (1 << 2) 106 | 107 | #define NVCRTC 0x6013D4 108 | 109 | typedef struct _riva_hw_inst 110 | { 111 | /* 112 | * Non-FIFO registers. 113 | */ 114 | volatile u8 *PCRTC; 115 | volatile u8 *PRAMDAC; 116 | volatile u8 *PFB; 117 | volatile u8 *PFIFO; 118 | volatile u8 *PGRAPH; 119 | volatile u8 *PEXTDEV; 120 | volatile u8 *PTIMER; 121 | volatile u8 *PMC; 122 | volatile u8 *PRAMIN; 123 | volatile u8 *FIFO; 124 | volatile u8 *CURSOR; 125 | volatile u8 *CURSORPOS; 126 | volatile u8 *VBLANKENABLE; 127 | volatile u8 *VBLANK; 128 | 129 | volatile u8 *PCIO; 130 | volatile u8 *PVIO; 131 | volatile u8 *PDIO; 132 | volatile u8 *PVIDEO; 133 | } RIVA_HW_INST; 134 | 135 | // function prototypes, not to be called from outside BootVgaInitialization 136 | static void mapNvMem (RIVA_HW_INST *riva, u8 *IOAddress); 137 | static void NVDisablePalette (RIVA_HW_INST *riva, int head); 138 | static void NVWriteSeq(RIVA_HW_INST *riva, CARD8 index, CARD8 value); 139 | static void NVWriteGr(RIVA_HW_INST *riva, CARD8 index, CARD8 value); 140 | static void NVInitGrSeq (RIVA_HW_INST *riva); 141 | static void NVInitAttr (RIVA_HW_INST *riva, int head); 142 | static inline void unlockCrtNv (RIVA_HW_INST *riva, int head); 143 | static inline void lockCrtNv (RIVA_HW_INST *riva, int head); 144 | static void writeCrtNv (RIVA_HW_INST *riva, int head, int reg, u8 val); 145 | static void NVVertIntrEnabled (RIVA_HW_INST *riva, int head); 146 | static void NVSetFBStart (RIVA_HW_INST *riva, int head, u32 dwFBStart); 147 | 148 | #endif 149 | -------------------------------------------------------------------------------- /src/drivers/video/BootVideo.h: -------------------------------------------------------------------------------- 1 | #ifndef _BootVideo_H_ 2 | #define _BootVideo_H_ 3 | 4 | enum { 5 | VIDEO_MODE_UNKNOWN=-1, 6 | VIDEO_MODE_640x480=0, 7 | VIDEO_MODE_640x576, 8 | VIDEO_MODE_720x576, 9 | VIDEO_MODE_800x600, 10 | VIDEO_MODE_1024x576, 11 | VIDEO_MODE_COUNT 12 | }; 13 | 14 | typedef struct { 15 | // fill on entry 16 | int m_nVideoModeIndex; // fill on entry to BootVgaInitializationKernel(), eg, VIDEO_MODE_800x600 17 | u8 m_fForceEncoderLumaAndChromaToZeroInitially; // fill on entry to BootVgaInitializationKernel(), 0=mode change visible immediately, !0=initially forced to black raster 18 | u32 m_dwFrameBufferStart; // frame buffer start address, set to zero to use default 19 | u8 * volatile m_pbBaseAddressVideo; // base address of video, usually 0xfd000000 20 | // filled on exit 21 | u32 width; // everything else filled by BootVgaInitializationKernel() on return 22 | u32 height; 23 | u32 xmargin; 24 | u32 ymargin; 25 | u8 m_bAvPack; 26 | u32 m_dwVideoFadeupTimer; 27 | double hoc; 28 | double voc; 29 | u8 m_bBPP; 30 | } CURRENT_VIDEO_MODE_DETAILS; 31 | 32 | void BootVgaInitializationKernelNG(CURRENT_VIDEO_MODE_DETAILS * pvmode); 33 | 34 | #endif // _BootVideo_H_ 35 | -------------------------------------------------------------------------------- /src/drivers/video/BootVideoHelpers.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * * 3 | * This program is free software; you can redistribute it and/or modify * 4 | * it under the terms of the GNU General Public License as published by * 5 | * the Free Software Foundation; either version 2 of the License, or * 6 | * (at your option) any later version. * 7 | * * 8 | ***************************************************************************/ 9 | 10 | // 2002-09-10 agreen@warmcat.com created 11 | 12 | // These are helper functions for displaying bitmap video 13 | // includes an antialiased (4bpp) proportional bitmap font (n x 16 pixel) 14 | 15 | 16 | #include "boot.h" 17 | #include "video.h" 18 | #include "memory_layout.h" 19 | //#include "string.h" 20 | #include "fontx16.h" // brings in font struct 21 | #include 22 | // #include "decode-jpg.h" 23 | #define WIDTH_SPACE_PIXELS 5 24 | 25 | // returns number of x pixels taken up by ascii character bCharacter 26 | 27 | unsigned int BootVideoGetCharacterWidth(u8 bCharacter, bool fDouble) 28 | { 29 | unsigned int nStart, nWidth; 30 | int nSpace=WIDTH_SPACE_PIXELS; 31 | 32 | if(fDouble) nSpace=8; 33 | 34 | // we only have glyphs for 0x21 through 0x7e inclusive 35 | 36 | if(bCharacter<0x21) return nSpace; 37 | if(bCharacter>0x7e) return nSpace; 38 | 39 | nStart=waStarts[bCharacter-0x21]; 40 | nWidth=waStarts[bCharacter-0x20]-nStart; 41 | 42 | if(fDouble) return nWidth<<1; else return nWidth; 43 | } 44 | 45 | // returns number of x pixels taken up by string 46 | 47 | unsigned int BootVideoGetStringTotalWidth(const char * szc) { 48 | unsigned int nWidth=0; 49 | bool fDouble=false; 50 | while(*szc) { 51 | if(*szc=='\2') { 52 | fDouble=!fDouble; 53 | szc++; 54 | } else { 55 | nWidth+=BootVideoGetCharacterWidth(*szc++, fDouble); 56 | } 57 | } 58 | return nWidth; 59 | } 60 | 61 | // convert pixel count to size of memory in bytes required to hold it, given the character height 62 | 63 | unsigned int BootVideoFontWidthToBitmapBytecount(unsigned int uiWidth) 64 | { 65 | return (uiWidth << 2) * uiPixelsY; 66 | } 67 | 68 | void BootVideoJpegBlitBlend( 69 | u8 *pDst, 70 | u32 dst_width, 71 | JPEG * pJpeg, 72 | u8 *pFront, 73 | RGBA m_rgbaTransparent, 74 | u8 *pBack, 75 | int x, 76 | int y 77 | ) { 78 | int n=0; 79 | 80 | int nTransAsByte=m_rgbaTransparent>>24; 81 | int nBackTransAsByte=255-nTransAsByte; 82 | u32 dw; 83 | 84 | m_rgbaTransparent|=0xff000000; 85 | m_rgbaTransparent&=0xffc0c0c0; 86 | 87 | while(y--) { 88 | 89 | for(n=0;n>8; 95 | pDst[1]=((pFront[1]*nTransAsByte)+(pBack[1]*nBackTransAsByte))>>8; 96 | pDst[0]=((pFront[2]*nTransAsByte)+(pBack[2]*nBackTransAsByte))>>8; 97 | } 98 | pDst+=4; 99 | pFront+=pJpeg->bpp; 100 | pBack+=pJpeg->bpp; 101 | } 102 | pBack+=(pJpeg->width*pJpeg->bpp) -(x * pJpeg->bpp); 103 | pDst+=(dst_width * 4) - (x * 4); 104 | pFront+=(pJpeg->width*pJpeg->bpp) -(x * pJpeg->bpp); 105 | } 106 | } 107 | 108 | // usable for direct write or for prebuffered write 109 | // returns width of character in pixels 110 | // RGBA .. full-on RED is opaque --> 0xFF0000FF <-- red 111 | 112 | int BootVideoOverlayCharacter( 113 | u32 * pdwaTopLeftDestination, 114 | u32 m_dwCountBytesPerLineDestination, 115 | RGBA rgbaColourAndOpaqueness, 116 | u8 bCharacter, 117 | bool fDouble 118 | ) { 119 | int nSpace; 120 | unsigned int n, nStart, nWidth, y, nHeight 121 | // nOpaquenessMultiplied, 122 | // nTransparentnessMultiplied 123 | ; 124 | u8 b=0, b1; // *pbColour=(u8 *)&rgbaColourAndOpaqueness; 125 | u8 * pbaDestStart; 126 | 127 | // we only have glyphs for 0x21 through 0x7e inclusive 128 | 129 | if(bCharacter=='\t') { 130 | u32 dw=((u32)pdwaTopLeftDestination) % m_dwCountBytesPerLineDestination; 131 | u32 dw1=((dw+1)%(32<<2)); // distance from previous boundary 132 | return ((32<<2)-dw1)>>2; 133 | } 134 | nSpace=WIDTH_SPACE_PIXELS; 135 | if(fDouble) nSpace=8; 136 | if(bCharacter<'!') return nSpace; 137 | if(bCharacter>'~') return nSpace; 138 | 139 | nStart=waStarts[bCharacter-(' '+1)]; 140 | nWidth=waStarts[bCharacter-' ']-nStart; 141 | nHeight=uiPixelsY; 142 | 143 | if(fDouble) { nWidth<<=1; nHeight<<=1; } 144 | 145 | // nStart=0; 146 | // nWidth=300; 147 | 148 | pbaDestStart=((u8 *)pdwaTopLeftDestination); 149 | 150 | for(y=0;y>1]; 156 | if(!(n1&1)) { 157 | b1=b>>4; 158 | } else { 159 | b1=b&0x0f; 160 | } 161 | if(fDouble) { 162 | if(n & 1) n1++; 163 | } else { 164 | n1++; 165 | } 166 | 167 | if(b1) { 168 | *pbaDest=(u8)((b1*(rgbaColourAndOpaqueness&0xff))>>4); pbaDest++; 169 | *pbaDest=(u8)((b1*((rgbaColourAndOpaqueness>>8)&0xff))>>4); pbaDest++; 170 | *pbaDest=(u8)((b1*((rgbaColourAndOpaqueness>>16)&0xff))>>4); pbaDest++; 171 | *pbaDest++=0xff; 172 | } else { 173 | pbaDest+=4; 174 | } 175 | } 176 | if(fDouble) { 177 | if(y&1) nStart+=uiPixelsX; 178 | } else { 179 | nStart+=uiPixelsX; 180 | } 181 | pbaDestStart+=m_dwCountBytesPerLineDestination; 182 | } 183 | 184 | return nWidth; 185 | } 186 | 187 | // usable for direct write or for prebuffered write 188 | // returns width of string in pixels 189 | 190 | int BootVideoOverlayString(u32 * pdwaTopLeftDestination, u32 m_dwCountBytesPerLineDestination, RGBA rgbaOpaqueness, const char * szString) 191 | { 192 | unsigned int uiWidth=0; 193 | bool fDouble=0; 194 | while((*szString != 0) && (*szString != '\n')) { 195 | if(*szString=='\2') { 196 | fDouble=!fDouble; 197 | } else { 198 | uiWidth+=BootVideoOverlayCharacter( 199 | pdwaTopLeftDestination+uiWidth, m_dwCountBytesPerLineDestination, rgbaOpaqueness, *szString, fDouble 200 | ); 201 | } 202 | szString++; 203 | } 204 | return uiWidth; 205 | } 206 | 207 | void BootVideoClearScreen(JPEG *pJpeg, int nStartLine, int nEndLine) 208 | { 209 | VIDEO_CURSOR_POSX=vmode.xmargin; 210 | VIDEO_CURSOR_POSY=vmode.ymargin; 211 | 212 | if(nEndLine>=vmode.height) nEndLine=vmode.height-1; 213 | 214 | { 215 | if(pJpeg->pData!=NULL) { 216 | volatile u32 *pdw=((u32 *)FB_START)+vmode.width*nStartLine; 217 | int n1=pJpeg->bpp * pJpeg->width * nStartLine; 218 | u8 *pbJpegBitmapAdjustedDatum=pJpeg->pBackdrop; 219 | 220 | while(nStartLine++bpp; 229 | } 230 | n1+=pJpeg->bpp * (pJpeg->width - vmode.width); 231 | pdw+=vmode.width; // adding u32 footprints 232 | } 233 | } 234 | } 235 | } 236 | 237 | int VideoDumpAddressAndData(u32 dwAds, const u8 * baData, u32 dwCountBytesUsable) { // returns bytes used 238 | int nCountUsed=0; 239 | while(dwCountBytesUsable) { 240 | 241 | u32 dw=(dwAds & 0xfffffff0); 242 | char szAscii[17]; 243 | char sz[256]; 244 | int n=sprintf(sz, "%08X: ", dw); 245 | int nBytes=0; 246 | 247 | szAscii[16]='\0'; 248 | while(nBytes<16) { 249 | if((dw126)) szAscii[nBytes]='.'; else szAscii[nBytes]=b; 256 | nCountUsed++; 257 | dwCountBytesUsable--; 258 | } 259 | nBytes++; 260 | if(nBytes==8) n+=sprintf(&sz[n], ": "); 261 | dw++; 262 | } 263 | n+=sprintf(&sz[n], " "); 264 | n+=sprintf(&sz[n], "%s", szAscii); 265 | sz[n++]='\n'; 266 | sz[n++]='\0'; 267 | 268 | printk(sz, n); 269 | 270 | dwAds=dw; 271 | } 272 | return 1; 273 | } 274 | void BootVideoChunkedPrint(const char * szBuffer) { 275 | int n=0; 276 | int nDone=0; 277 | 278 | while (szBuffer[n] != 0) 279 | { 280 | if(szBuffer[n]=='\n') { 281 | BootVideoOverlayString( 282 | (u32 *)((FB_START) + VIDEO_CURSOR_POSY * (vmode.width*4) + VIDEO_CURSOR_POSX), 283 | vmode.width*4, VIDEO_ATTR, &szBuffer[nDone] 284 | ); 285 | nDone=n+1; 286 | VIDEO_CURSOR_POSY+=16; 287 | VIDEO_CURSOR_POSX=vmode.xmargin<<2; 288 | } 289 | n++; 290 | } 291 | if (n != nDone) 292 | { 293 | VIDEO_CURSOR_POSX+=BootVideoOverlayString( 294 | (u32 *)((FB_START) + VIDEO_CURSOR_POSY * (vmode.width*4) + VIDEO_CURSOR_POSX), 295 | vmode.width*4, VIDEO_ATTR, &szBuffer[nDone] 296 | )<<2; 297 | if (VIDEO_CURSOR_POSX > (vmode.width - 298 | vmode.xmargin) <<2) 299 | { 300 | VIDEO_CURSOR_POSY+=16; 301 | VIDEO_CURSOR_POSX=vmode.xmargin<<2; 302 | } 303 | 304 | } 305 | 306 | } 307 | 308 | int console_putchar(int c) 309 | { 310 | char buf[2]; 311 | buf[0] = (char)c; 312 | buf[1] = 0; 313 | BootVideoChunkedPrint(buf); 314 | return (int)buf[0]; 315 | } 316 | -------------------------------------------------------------------------------- /src/drivers/video/VideoInitialization.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Common library functions for video initialization 3 | * 4 | * Oliver Schwartz, May 2003 5 | */ 6 | 7 | /*************************************************************************** 8 | * * 9 | * This program is free software; you can redistribute it and/or modify * 10 | * it under the terms of the GNU General Public License as published by * 11 | * the Free Software Foundation; either version 2 of the License, or * 12 | * (at your option) any later version. * 13 | * * 14 | ***************************************************************************/ 15 | 16 | 17 | #ifdef JUSTVIDEO 18 | #include 19 | #include 20 | #endif 21 | #include 22 | 23 | #include "VideoInitialization.h" 24 | 25 | extern u8 VIDEO_AV_MODE; 26 | // functions defined elsewhere 27 | int I2CTransmitByteGetReturn(u8 bPicAddressI2cFormat, u8 bDataToWrite); 28 | int I2CTransmitWord(u8 bPicAddressI2cFormat, u16 wDataToWrite); 29 | 30 | // internally used structures 31 | 32 | typedef struct { 33 | long h_blanki; 34 | long h_blanko; 35 | long v_blanki; 36 | long v_blanko; 37 | long vscale; 38 | } BLANKING_PARAMETER; 39 | 40 | static u8 NvGetCrtc(u8 * pbRegs, int nIndex) { 41 | *((volatile u8 *)&pbRegs[0x6013d4])=nIndex; 42 | return *((volatile u8 *)&pbRegs[0x6013d5]); 43 | } 44 | 45 | static void NvSetCrtc(u8 * pbRegs, int nIndex, u8 b) { 46 | *((volatile u8 *)&pbRegs[0x6013d4])=nIndex; 47 | *((volatile u8 *)&pbRegs[0x6013d5])=b; 48 | } 49 | 50 | xbox_tv_encoding DetectVideoStd(void) { 51 | xbox_tv_encoding videoStd; 52 | u8 b=I2CTransmitByteGetReturn(0x54, 0x5A); // the eeprom defines the TV standard for the box 53 | 54 | if(b == 0x40) { 55 | videoStd = TV_ENC_NTSC; 56 | } else { 57 | videoStd = TV_ENC_PALBDGHI; 58 | } 59 | 60 | return videoStd; 61 | } 62 | 63 | xbox_av_type DetectAvType(void) { 64 | xbox_av_type avType; 65 | 66 | switch (VIDEO_AV_MODE) { 67 | case 0: avType = AV_SCART_RGB; break; 68 | case 1: avType = AV_HDTV; break; 69 | case 2: avType = AV_VGA_SOG; break; 70 | case 4: avType = AV_SVIDEO; break; 71 | case 6: avType = AV_COMPOSITE; break; 72 | case 7: avType = AV_VGA; break; 73 | default: avType = AV_COMPOSITE; break; 74 | } 75 | return avType; 76 | } 77 | 78 | void SetGPURegister(const GPU_PARAMETER* gpu, u8 *pbRegs) { 79 | u8 b; 80 | u32 m = 0; 81 | // NVHDISPEND 82 | *((volatile u32 *)&pbRegs[0x680820]) = gpu->crtchdispend - 1; 83 | // NVHTOTAL 84 | *((volatile u32 *)&pbRegs[0x680824]) = gpu->nvhtotal; 85 | // NVHCRTC 86 | *((volatile u32 *)&pbRegs[0x680828]) = gpu->xres - 1; 87 | // NVHVALIDSTART 88 | *((volatile u32 *)&pbRegs[0x680834]) = 0; 89 | // NVHSYNCSTART 90 | *((volatile u32 *)&pbRegs[0x68082c]) = gpu->nvhstart; 91 | // NVHSYNCEND = NVHSYNCSTART + 32 92 | *((volatile u32 *)&pbRegs[0x680830]) = gpu->nvhstart+32; 93 | // NVHVALIDEND 94 | *((volatile u32 *)&pbRegs[0x680838]) = gpu->xres - 1; 95 | // CRTC_HSYNCSTART = h_total - 32 (heuristic) 96 | m = gpu->nvhtotal - 32; 97 | NvSetCrtc(pbRegs, 4, m/8); 98 | // CRTC_HSYNCEND = CRTC_HSYNCSTART + 16 99 | NvSetCrtc(pbRegs, 5, (NvGetCrtc(pbRegs, 5)&0xe0) | ((((m + 16)/8)-1)&0x1f) ); 100 | // CRTC_HTOTAL = nvh_total (heuristic) 101 | NvSetCrtc(pbRegs, 0, (gpu->nvhtotal/8)-5); 102 | // CRTC_HBLANKSTART = crtchdispend 103 | NvSetCrtc(pbRegs, 2, ((gpu->crtchdispend)/8)-1); 104 | // CRTC_HBLANKEND = CRTC_HTOTAL = nvh_total 105 | NvSetCrtc(pbRegs, 3, (NvGetCrtc(pbRegs, 3)&0xe0) |(((gpu->nvhtotal/8)-1)&0x1f)); 106 | NvSetCrtc(pbRegs, 5, (NvGetCrtc(pbRegs, 5)&(~0x80)) | ((((gpu->nvhtotal/8)-1)&0x20)<<2) ); 107 | // CRTC_HDISPEND 108 | NvSetCrtc(pbRegs, 0x17, (NvGetCrtc(pbRegs, 0x17)&0x7f)); 109 | NvSetCrtc(pbRegs, 1, ((gpu->crtchdispend)/8)-1); 110 | NvSetCrtc(pbRegs, 2, ((gpu->crtchdispend)/8)-1); 111 | NvSetCrtc(pbRegs, 0x17, (NvGetCrtc(pbRegs, 0x17)&0x7f)|0x80); 112 | // CRTC_LINESTRIDE = (xres / 8) * pixelDepth 113 | m=(gpu->xres / 8) * gpu->pixelDepth; 114 | NvSetCrtc(pbRegs, 0x19, (NvGetCrtc(pbRegs, 0x19)&0x1f) | ((m >> 3) & 0xe0)); 115 | NvSetCrtc(pbRegs, 0x13, (m & 0xff)); 116 | // NVVDISPEND 117 | *((volatile u32 *)&pbRegs[0x680800]) = gpu->yres - 1; 118 | // NVVTOTAL 119 | *((volatile u32 *)&pbRegs[0x680804]) = gpu->nvvtotal; 120 | // NVVCRTC 121 | *((volatile u32 *)&pbRegs[0x680808]) = gpu->yres - 1; 122 | // NVVVALIDSTART 123 | *((volatile u32 *)&pbRegs[0x680814]) = 0; 124 | // NVVSYNCSTART 125 | *((volatile u32 *)&pbRegs[0x68080c])=gpu->nvvstart; 126 | // NVVSYNCEND = NVVSYNCSTART + 3 127 | *((volatile u32 *)&pbRegs[0x680810])=(gpu->nvvstart+3); 128 | // NVVVALIDEND 129 | *((volatile u32 *)&pbRegs[0x680818]) = gpu->yres - 1; 130 | // CRTC_VSYNCSTART 131 | b = NvGetCrtc(pbRegs, 7) & 0x7b; 132 | NvSetCrtc(pbRegs, 7, b | ((gpu->crtcvstart >> 2) & 0x80) | ((gpu->crtcvstart >> 6) & 0x04)); 133 | NvSetCrtc(pbRegs, 0x10, (gpu->crtcvstart & 0xff)); 134 | // CRTC_VTOTAL 135 | b = NvGetCrtc(pbRegs, 7) & 0xde; 136 | NvSetCrtc(pbRegs, 7, b | ((gpu->crtcvtotal >> 4) & 0x20) | ((gpu->crtcvtotal >> 8) & 0x01)); 137 | NvSetCrtc(pbRegs, 6, (gpu->crtcvtotal & 0xff)); 138 | // CRTC_VBLANKEND = CRTC_VTOTAL 139 | b = NvGetCrtc(pbRegs, 0x16) & 0x80; 140 | NvSetCrtc(pbRegs, 0x16, b |(gpu->crtcvtotal & 0x7f)); 141 | // CRTC_VDISPEND = yres 142 | b = NvGetCrtc(pbRegs, 7) & 0xbd; 143 | NvSetCrtc(pbRegs, 7, b | (((gpu->yres - 1) >> 3) & 0x40) | (((gpu->yres - 1) >> 7) & 0x02)); 144 | NvSetCrtc(pbRegs, 0x12, ((gpu->yres - 1) & 0xff)); 145 | // CRTC_VBLANKSTART 146 | b = NvGetCrtc(pbRegs, 9) & 0xdf; 147 | NvSetCrtc(pbRegs, 9, b | (((gpu->yres - 1)>> 4) & 0x20)); 148 | b = NvGetCrtc(pbRegs, 7) & 0xf7; 149 | NvSetCrtc(pbRegs, 7, b | (((gpu->yres - 1) >> 5) & 0x08)); 150 | NvSetCrtc(pbRegs, 0x15, ((gpu->yres - 1) & 0xff)); 151 | // CRTC_LINECOMP 152 | m = 0x3ff; // 0x3ff = disable 153 | b = NvGetCrtc(pbRegs, 7) & 0xef; 154 | NvSetCrtc(pbRegs, 7, b | ((m>> 4) & 0x10)); 155 | b = NvGetCrtc(pbRegs, 9) & 0xbf; 156 | NvSetCrtc(pbRegs, 9, b | ((m >> 3) & 0x40)); 157 | NvSetCrtc(pbRegs, 0x18, (m & 0xff)); 158 | // CRTC_REPAINT1 159 | if (gpu->xres < 1280) { 160 | b = 0x04; 161 | } 162 | else { 163 | b = 0x00; 164 | } 165 | NvSetCrtc(pbRegs, 0x1a, b); 166 | // Overflow bits 167 | /* 168 | b = ((hTotal & 0x040) >> 2) 169 | | ((vDisplay & 0x400) >> 7) 170 | | ((vStart & 0x400) >> 8) 171 | | ((vDisplay & 0x400) >> 9) 172 | | ((vTotal & 0x400) >> 10); 173 | */ 174 | b = (((gpu->nvhtotal / 8 - 5) & 0x040) >> 2) 175 | | (((gpu->yres - 1) & 0x400) >> 7) 176 | | ((gpu->crtcvstart & 0x400) >> 8) 177 | | (((gpu->yres - 1) & 0x400) >> 9) 178 | | ((gpu->crtcvtotal & 0x400) >> 10); 179 | NvSetCrtc(pbRegs, 0x25, b); 180 | 181 | b = gpu->pixelDepth; 182 | if (b >= 3) b = 3; 183 | /* switch pixel mode to TV */ 184 | b |= 0x80; 185 | NvSetCrtc(pbRegs, 0x28, b); 186 | 187 | b = NvGetCrtc(pbRegs, 0x2d) & 0xe0; 188 | if ((gpu->nvhtotal / 8 - 1) >= 260) { 189 | b |= 0x01; 190 | } 191 | NvSetCrtc(pbRegs, 0x2d, b); 192 | } 193 | 194 | -------------------------------------------------------------------------------- /src/drivers/video/VideoInitialization.h: -------------------------------------------------------------------------------- 1 | #ifndef VIDEOINITIALIZATION_H 2 | #define VIDEOINITIALIZATION_H 3 | 4 | typedef enum enumVideoStandards { 5 | TV_ENC_INVALID=-1, 6 | TV_ENC_NTSC=0, 7 | TV_ENC_NTSC60, 8 | TV_ENC_PALBDGHI, 9 | TV_ENC_PALN, 10 | TV_ENC_PALNC, 11 | TV_ENC_PALM, 12 | TV_ENC_PAL60 13 | } xbox_tv_encoding; 14 | 15 | typedef enum enumAvTypes { 16 | AV_INVALID=-1, 17 | AV_SCART_RGB, 18 | AV_SVIDEO, 19 | AV_VGA_SOG, 20 | AV_HDTV, 21 | AV_COMPOSITE, 22 | AV_VGA 23 | } xbox_av_type; 24 | 25 | typedef enum enumHdtvModes { 26 | HDTV_480p, 27 | HDTV_720p, 28 | HDTV_1080i 29 | } xbox_hdtv_mode; 30 | 31 | /* Used to configure the GPU */ 32 | typedef struct { 33 | long xres; 34 | long crtchdispend; 35 | long nvhstart; 36 | long nvhtotal; 37 | long yres; 38 | long nvvstart; 39 | long crtcvstart; 40 | long crtcvtotal; 41 | long nvvtotal; 42 | long pixelDepth; 43 | xbox_av_type av_type; 44 | } GPU_PARAMETER; 45 | 46 | ///////// VideoInitialization.c 47 | 48 | xbox_tv_encoding DetectVideoStd(void); 49 | xbox_av_type DetectAvType(void); 50 | 51 | void SetGPURegister(const GPU_PARAMETER* gpu, unsigned char *pbRegs); 52 | #endif 53 | -------------------------------------------------------------------------------- /src/drivers/video/conexant.h: -------------------------------------------------------------------------------- 1 | /* 2 | * linux/drivers/video/riva/conexant.h - Xbox driver for conexant chip 3 | * 4 | * Maintainer: Oliver Schwartz 5 | * 6 | * Contributors: 7 | * 8 | * This file is subject to the terms and conditions of the GNU General Public 9 | * License. See the file COPYING in the main directory of this archive 10 | * for more details. 11 | * 12 | * Known bugs and issues: 13 | * 14 | * none 15 | */ 16 | 17 | #ifndef conexant_h 18 | #define conexant_h 19 | 20 | //#include 21 | //include "xboxfb.h" 22 | #include "boot.h" 23 | #include "encoder.h" 24 | 25 | int conexant_calc_mode(xbox_video_mode * mode, struct riva_regs * riva_out); 26 | int conexant_calc_vga_mode(xbox_av_type av_type, unsigned char pll_int, void **mode_out); 27 | int conexant_calc_hdtv_mode(xbox_hdtv_mode hdtv_mode, unsigned char pll_int, void **mode_out); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /src/drivers/video/encoder.h: -------------------------------------------------------------------------------- 1 | /* 2 | * linux/drivers/video/riva/encoder.h - Xbox driver for encoder chip 3 | * 4 | * Maintainer: Oliver Schwartz 5 | * 6 | * Contributors: 7 | * 8 | * This file is subject to the terms and conditions of the GNU General Public 9 | * License. See the file COPYING in the main directory of this archive 10 | * for more details. 11 | * 12 | * Known bugs and issues: 13 | * 14 | * none 15 | */ 16 | #define NUM_SEQ_REGS 0x05 17 | #define NUM_CRT_REGS 0x41 18 | #define NUM_GRC_REGS 0x09 19 | #define NUM_ATC_REGS 0x15 20 | 21 | #define NUM_CONEXANT_REGS 0x69 22 | #define MAX_ENCODER_REGS 256 23 | 24 | #define U032 long 25 | #ifndef encoder_h 26 | #define encoder_h 27 | 28 | //#include 29 | #include "VideoInitialization.h" 30 | #include "boot.h" 31 | 32 | typedef struct { 33 | double m_dHzBurstFrequency; 34 | double m_dSecBurstStart; 35 | double m_dSecBurstEnd; 36 | double m_dSecHsyncWidth; 37 | double m_dSecHsyncPeriod; 38 | double m_dSecActiveBegin; 39 | double m_dSecImageCentre; 40 | double m_dSecBlankBeginToHsync; 41 | unsigned int m_dwALO; 42 | double m_TotalLinesOut; 43 | double m_dSecHsyncToBlankEnd; 44 | } conexant_video_parameter; 45 | 46 | typedef struct _xbox_video_mode { 47 | int xres; 48 | int yres; 49 | int bpp; 50 | double hoc; 51 | double voc; 52 | xbox_av_type av_type; 53 | xbox_tv_encoding tv_encoding; 54 | } xbox_video_mode; 55 | 56 | typedef struct _riva_hw_state 57 | { 58 | U032 bpp; 59 | U032 width; 60 | U032 height; 61 | U032 repaint0; 62 | U032 repaint1; 63 | U032 screen; 64 | U032 pixel; 65 | U032 horiz; 66 | U032 arbitration0; 67 | U032 arbitration1; 68 | U032 vpll; 69 | U032 pllsel; 70 | U032 general; 71 | U032 config; 72 | U032 cursor0; 73 | U032 cursor1; 74 | U032 cursor2; 75 | U032 offset0; 76 | U032 offset1; 77 | U032 offset2; 78 | U032 offset3; 79 | U032 pitch0; 80 | U032 pitch1; 81 | U032 pitch2; 82 | U032 pitch3; 83 | //#ifdef CONFIG_XBOX 84 | U032 fb_start; 85 | U032 vend; 86 | U032 vtotal; 87 | U032 vcrtc; 88 | U032 vsyncstart; 89 | U032 vsyncend; 90 | U032 vvalidstart; 91 | U032 vvalidend; 92 | U032 hend; 93 | U032 htotal; 94 | U032 hcrtc; 95 | U032 hsyncstart; 96 | U032 hsyncend; 97 | U032 hvalidstart; 98 | U032 hvalidend; 99 | U032 crtchdispend; 100 | U032 crtcvstart; 101 | U032 crtcvtotal; 102 | U032 checksum; 103 | //#endif 104 | } RIVA_HW_STATE; 105 | 106 | struct riva_regs { 107 | u8 attr[NUM_ATC_REGS]; 108 | u8 crtc[NUM_CRT_REGS]; 109 | u8 gra[NUM_GRC_REGS]; 110 | u8 seq[NUM_SEQ_REGS]; 111 | u8 misc_output; 112 | RIVA_HW_STATE ext; 113 | void *encoder_regs; 114 | }; 115 | 116 | typedef enum enumEncoderType { 117 | ENCODER_CONEXANT, 118 | ENCODER_FOCUS, 119 | ENCODER_XCALIBUR 120 | } xbox_encoder_type; 121 | 122 | /*static const conexant_video_parameter vidstda[]; 123 | 124 | int tv_init(void); 125 | void tv_exit(void); 126 | xbox_encoder_type tv_get_video_encoder(void); 127 | 128 | void tv_save_mode(unsigned char * mode_out); 129 | void tv_load_mode(unsigned char * mode); 130 | xbox_tv_encoding get_tv_encoding(void); 131 | xbox_av_type detect_av_type(void); 132 | */ 133 | #endif 134 | -------------------------------------------------------------------------------- /src/include/asm/bitops.h: -------------------------------------------------------------------------------- 1 | #ifndef _I386_BITOPS_H 2 | #define _I386_BITOPS_H 3 | 4 | /* 5 | * Copyright 1992, Linus Torvalds. 6 | */ 7 | 8 | #include 9 | 10 | /* 11 | * These have to be done with inline assembly: that way the bit-setting 12 | * is guaranteed to be atomic. All bit operations return 0 if the bit 13 | * was cleared before the operation and != 0 if it was not. 14 | * 15 | * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1). 16 | */ 17 | 18 | #ifdef CONFIG_SMP 19 | #define LOCK_PREFIX "lock ; " 20 | #else 21 | #define LOCK_PREFIX "" 22 | #endif 23 | 24 | #define ADDR (*(volatile long *) addr) 25 | 26 | /** 27 | * set_bit - Atomically set a bit in memory 28 | * @nr: the bit to set 29 | * @addr: the address to start counting from 30 | * 31 | * This function is atomic and may not be reordered. See __set_bit() 32 | * if you do not require the atomic guarantees. 33 | * Note that @nr may be almost arbitrarily large; this function is not 34 | * restricted to acting on a single-word quantity. 35 | */ 36 | static __inline__ void set_bit(int nr, volatile void * addr) 37 | { 38 | __asm__ __volatile__( LOCK_PREFIX 39 | "btsl %1,%0" 40 | :"=m" (ADDR) 41 | :"Ir" (nr)); 42 | } 43 | 44 | /** 45 | * __set_bit - Set a bit in memory 46 | * @nr: the bit to set 47 | * @addr: the address to start counting from 48 | * 49 | * Unlike set_bit(), this function is non-atomic and may be reordered. 50 | * If it's called on the same region of memory simultaneously, the effect 51 | * may be that only one operation succeeds. 52 | */ 53 | static __inline__ void __set_bit(int nr, volatile void * addr) 54 | { 55 | __asm__( 56 | "btsl %1,%0" 57 | :"=m" (ADDR) 58 | :"Ir" (nr)); 59 | } 60 | 61 | /** 62 | * clear_bit - Clears a bit in memory 63 | * @nr: Bit to clear 64 | * @addr: Address to start counting from 65 | * 66 | * clear_bit() is atomic and may not be reordered. However, it does 67 | * not contain a memory barrier, so if it is used for locking purposes, 68 | * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit() 69 | * in order to ensure changes are visible on other processors. 70 | */ 71 | static __inline__ void clear_bit(int nr, volatile void * addr) 72 | { 73 | __asm__ __volatile__( LOCK_PREFIX 74 | "btrl %1,%0" 75 | :"=m" (ADDR) 76 | :"Ir" (nr)); 77 | } 78 | #define smp_mb__before_clear_bit() barrier() 79 | #define smp_mb__after_clear_bit() barrier() 80 | 81 | /** 82 | * __change_bit - Toggle a bit in memory 83 | * @nr: the bit to set 84 | * @addr: the address to start counting from 85 | * 86 | * Unlike change_bit(), this function is non-atomic and may be reordered. 87 | * If it's called on the same region of memory simultaneously, the effect 88 | * may be that only one operation succeeds. 89 | */ 90 | static __inline__ void __change_bit(int nr, volatile void * addr) 91 | { 92 | __asm__ __volatile__( 93 | "btcl %1,%0" 94 | :"=m" (ADDR) 95 | :"Ir" (nr)); 96 | } 97 | 98 | /** 99 | * change_bit - Toggle a bit in memory 100 | * @nr: Bit to clear 101 | * @addr: Address to start counting from 102 | * 103 | * change_bit() is atomic and may not be reordered. 104 | * Note that @nr may be almost arbitrarily large; this function is not 105 | * restricted to acting on a single-word quantity. 106 | */ 107 | static __inline__ void change_bit(int nr, volatile void * addr) 108 | { 109 | __asm__ __volatile__( LOCK_PREFIX 110 | "btcl %1,%0" 111 | :"=m" (ADDR) 112 | :"Ir" (nr)); 113 | } 114 | 115 | /** 116 | * test_and_set_bit - Set a bit and return its old value 117 | * @nr: Bit to set 118 | * @addr: Address to count from 119 | * 120 | * This operation is atomic and cannot be reordered. 121 | * It also implies a memory barrier. 122 | */ 123 | static __inline__ int test_and_set_bit(int nr, volatile void * addr) 124 | { 125 | int oldbit; 126 | 127 | __asm__ __volatile__( LOCK_PREFIX 128 | "btsl %2,%1\n\tsbbl %0,%0" 129 | :"=r" (oldbit),"=m" (ADDR) 130 | :"Ir" (nr) : "memory"); 131 | return oldbit; 132 | } 133 | 134 | /** 135 | * __test_and_set_bit - Set a bit and return its old value 136 | * @nr: Bit to set 137 | * @addr: Address to count from 138 | * 139 | * This operation is non-atomic and can be reordered. 140 | * If two examples of this operation race, one can appear to succeed 141 | * but actually fail. You must protect multiple accesses with a lock. 142 | */ 143 | static __inline__ int __test_and_set_bit(int nr, volatile void * addr) 144 | { 145 | int oldbit; 146 | 147 | __asm__( 148 | "btsl %2,%1\n\tsbbl %0,%0" 149 | :"=r" (oldbit),"=m" (ADDR) 150 | :"Ir" (nr)); 151 | return oldbit; 152 | } 153 | 154 | /** 155 | * test_and_clear_bit - Clear a bit and return its old value 156 | * @nr: Bit to set 157 | * @addr: Address to count from 158 | * 159 | * This operation is atomic and cannot be reordered. 160 | * It also implies a memory barrier. 161 | */ 162 | static __inline__ int test_and_clear_bit(int nr, volatile void * addr) 163 | { 164 | int oldbit; 165 | 166 | __asm__ __volatile__( LOCK_PREFIX 167 | "btrl %2,%1\n\tsbbl %0,%0" 168 | :"=r" (oldbit),"=m" (ADDR) 169 | :"Ir" (nr) : "memory"); 170 | return oldbit; 171 | } 172 | 173 | /** 174 | * __test_and_clear_bit - Clear a bit and return its old value 175 | * @nr: Bit to set 176 | * @addr: Address to count from 177 | * 178 | * This operation is non-atomic and can be reordered. 179 | * If two examples of this operation race, one can appear to succeed 180 | * but actually fail. You must protect multiple accesses with a lock. 181 | */ 182 | static __inline__ int __test_and_clear_bit(int nr, volatile void * addr) 183 | { 184 | int oldbit; 185 | 186 | __asm__( 187 | "btrl %2,%1\n\tsbbl %0,%0" 188 | :"=r" (oldbit),"=m" (ADDR) 189 | :"Ir" (nr)); 190 | return oldbit; 191 | } 192 | 193 | /* WARNING: non atomic and it can be reordered! */ 194 | static __inline__ int __test_and_change_bit(int nr, volatile void * addr) 195 | { 196 | int oldbit; 197 | 198 | __asm__ __volatile__( 199 | "btcl %2,%1\n\tsbbl %0,%0" 200 | :"=r" (oldbit),"=m" (ADDR) 201 | :"Ir" (nr) : "memory"); 202 | return oldbit; 203 | } 204 | 205 | /** 206 | * test_and_change_bit - Change a bit and return its new value 207 | * @nr: Bit to set 208 | * @addr: Address to count from 209 | * 210 | * This operation is atomic and cannot be reordered. 211 | * It also implies a memory barrier. 212 | */ 213 | static __inline__ int test_and_change_bit(int nr, volatile void * addr) 214 | { 215 | int oldbit; 216 | 217 | __asm__ __volatile__( LOCK_PREFIX 218 | "btcl %2,%1\n\tsbbl %0,%0" 219 | :"=r" (oldbit),"=m" (ADDR) 220 | :"Ir" (nr) : "memory"); 221 | return oldbit; 222 | } 223 | 224 | #if 0 /* Fool kernel-doc since it doesn't do macros yet */ 225 | /** 226 | * test_bit - Determine whether a bit is set 227 | * @nr: bit number to test 228 | * @addr: Address to start counting from 229 | */ 230 | static int test_bit(int nr, const volatile void * addr); 231 | #endif 232 | 233 | static __inline__ int constant_test_bit(int nr, const volatile void * addr) 234 | { 235 | return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0; 236 | } 237 | 238 | static __inline__ int variable_test_bit(int nr, volatile void * addr) 239 | { 240 | int oldbit; 241 | 242 | __asm__ __volatile__( 243 | "btl %2,%1\n\tsbbl %0,%0" 244 | :"=r" (oldbit) 245 | :"m" (ADDR),"Ir" (nr)); 246 | return oldbit; 247 | } 248 | 249 | #define test_bit(nr,addr) \ 250 | (__builtin_constant_p(nr) ? \ 251 | constant_test_bit((nr),(addr)) : \ 252 | variable_test_bit((nr),(addr))) 253 | 254 | /** 255 | * find_first_zero_bit - find the first zero bit in a memory region 256 | * @addr: The address to start the search at 257 | * @size: The maximum size to search 258 | * 259 | * Returns the bit-number of the first zero bit, not the number of the byte 260 | * containing a bit. 261 | */ 262 | static __inline__ int find_first_zero_bit(void * addr, unsigned size) 263 | { 264 | int d0, d1, d2; 265 | int res; 266 | 267 | if (!size) 268 | return 0; 269 | /* This looks at memory. Mark it volatile to tell gcc not to move it around */ 270 | __asm__ __volatile__( 271 | "movl $-1,%%eax\n\t" 272 | "xorl %%edx,%%edx\n\t" 273 | "repe; scasl\n\t" 274 | "je 1f\n\t" 275 | "xorl -4(%%edi),%%eax\n\t" 276 | "subl $4,%%edi\n\t" 277 | "bsfl %%eax,%%edx\n" 278 | "1:\tsubl %%ebx,%%edi\n\t" 279 | "shll $3,%%edi\n\t" 280 | "addl %%edi,%%edx" 281 | :"=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2) 282 | :"1" ((size + 31) >> 5), "2" (addr), "b" (addr)); 283 | return res; 284 | } 285 | 286 | /** 287 | * find_next_zero_bit - find the first zero bit in a memory region 288 | * @addr: The address to base the search on 289 | * @offset: The bitnumber to start searching at 290 | * @size: The maximum size to search 291 | */ 292 | static __inline__ int find_next_zero_bit (void * addr, int size, int offset) 293 | { 294 | unsigned long * p = ((unsigned long *) addr) + (offset >> 5); 295 | int set = 0, bit = offset & 31, res; 296 | 297 | if (bit) { 298 | /* 299 | * Look for zero in first byte 300 | */ 301 | __asm__("bsfl %1,%0\n\t" 302 | "jne 1f\n\t" 303 | "movl $32, %0\n" 304 | "1:" 305 | : "=r" (set) 306 | : "r" (~(*p >> bit))); 307 | if (set < (32 - bit)) 308 | return set + offset; 309 | set = 32 - bit; 310 | p++; 311 | } 312 | /* 313 | * No zero yet, search remaining full bytes for a zero 314 | */ 315 | res = find_first_zero_bit (p, size - 32 * (p - (unsigned long *) addr)); 316 | return (offset + set + res); 317 | } 318 | 319 | /** 320 | * ffz - find first zero in word. 321 | * @word: The word to search 322 | * 323 | * Undefined if no zero exists, so code should check against ~0UL first. 324 | */ 325 | static __inline__ unsigned long ffz(unsigned long word) 326 | { 327 | __asm__("bsfl %1,%0" 328 | :"=r" (word) 329 | :"r" (~word)); 330 | return word; 331 | } 332 | 333 | #ifdef __KERNEL__ 334 | 335 | /** 336 | * ffs - find first bit set 337 | * @x: the word to search 338 | * 339 | * This is defined the same way as 340 | * the libc and compiler builtin ffs routines, therefore 341 | * differs in spirit from the above ffz (man ffs). 342 | */ 343 | static __inline__ int ffs(int x) 344 | { 345 | int r; 346 | 347 | __asm__("bsfl %1,%0\n\t" 348 | "jnz 1f\n\t" 349 | "movl $-1,%0\n" 350 | "1:" : "=r" (r) : "rm" (x)); 351 | return r+1; 352 | } 353 | 354 | /** 355 | * hweightN - returns the hamming weight of a N-bit word 356 | * @x: the word to weigh 357 | * 358 | * The Hamming Weight of a number is the total number of bits set in it. 359 | */ 360 | 361 | #define hweight32(x) generic_hweight32(x) 362 | #define hweight16(x) generic_hweight16(x) 363 | #define hweight8(x) generic_hweight8(x) 364 | 365 | #endif /* __KERNEL__ */ 366 | 367 | #ifdef __KERNEL__ 368 | 369 | #define ext2_set_bit __test_and_set_bit 370 | #define ext2_clear_bit __test_and_clear_bit 371 | #define ext2_test_bit test_bit 372 | #define ext2_find_first_zero_bit find_first_zero_bit 373 | #define ext2_find_next_zero_bit find_next_zero_bit 374 | 375 | /* Bitmap functions for the minix filesystem. */ 376 | #define minix_test_and_set_bit(nr,addr) __test_and_set_bit(nr,addr) 377 | #define minix_set_bit(nr,addr) __set_bit(nr,addr) 378 | #define minix_test_and_clear_bit(nr,addr) __test_and_clear_bit(nr,addr) 379 | #define minix_test_bit(nr,addr) test_bit(nr,addr) 380 | #define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size) 381 | 382 | #endif /* __KERNEL__ */ 383 | 384 | #endif /* _I386_BITOPS_H */ 385 | -------------------------------------------------------------------------------- /src/include/boot.h: -------------------------------------------------------------------------------- 1 | #ifndef _Boot_H_ 2 | #define _Boot_H_ 3 | 4 | #include "config.h" 5 | 6 | /*************************************************************************** 7 | Includes used by XBox boot code 8 | ***************************************************************************/ 9 | /*************************************************************************** 10 | * * 11 | * This program is free software; you can redistribute it and/or modify * 12 | * it under the terms of the GNU General Public License as published by * 13 | * the Free Software Foundation; either version 2 of the License, or * 14 | * (at your option) any later version. * 15 | * * 16 | ***************************************************************************/ 17 | 18 | ///////////////////////////////// 19 | // configuration 20 | 21 | #include "consts.h" 22 | #include "stdint.h" 23 | #include "cromwell_types.h" 24 | 25 | unsigned int xbox_ram; 26 | 27 | static inline double min (double a, double b) 28 | { 29 | if (a < b) return a; else return b; 30 | } 31 | 32 | static inline double max (double a, double b) 33 | { 34 | if (a > b) return a; else return b; 35 | } 36 | 37 | // #include "iso_fs.h" 38 | #include "BootVideo.h" 39 | 40 | #define ASSERT(exp) { if(!(exp)) { bprintf("Assert failed file " __FILE__ " line %d\n", __LINE__); } } 41 | 42 | extern volatile CURRENT_VIDEO_MODE_DETAILS vmode; 43 | unsigned int video_encoder; 44 | 45 | volatile u32 VIDEO_CURSOR_POSX; 46 | volatile u32 VIDEO_CURSOR_POSY; 47 | volatile u32 VIDEO_ATTR; 48 | volatile u32 VIDEO_LUMASCALING; 49 | volatile u32 VIDEO_RSCALING; 50 | volatile u32 VIDEO_BSCALING; 51 | volatile u32 BIOS_TICK_COUNT; 52 | volatile u32 VIDEO_VSYNC_POSITION; 53 | volatile u32 VIDEO_VSYNC_DIR; 54 | volatile u32 DVD_TRAY_STATE; 55 | 56 | u8 VIDEO_AV_MODE ; 57 | 58 | #define DVD_CLOSED 0 59 | #define DVD_CLOSING 1 60 | #define DVD_OPEN 2 61 | #define DVD_OPENING 3 62 | 63 | ///////////////////////////////// 64 | // Superfunky i386 internal structures 65 | 66 | typedef struct gdt_t { 67 | unsigned short m_wSize __attribute__ ((packed)); 68 | unsigned long m_dwBase32 __attribute__ ((packed)); 69 | unsigned short m_wDummy __attribute__ ((packed)); 70 | } ts_descriptor_pointer; 71 | 72 | typedef struct { // inside an 8-byte protected mode interrupt vector 73 | u16 m_wHandlerHighAddressLow16; 74 | u16 m_wSelector; 75 | u16 m_wType; 76 | u16 m_wHandlerLinearAddressHigh16; 77 | } ts_pm_interrupt; 78 | 79 | typedef enum { 80 | EDT_UNKNOWN= 0, 81 | EDT_XBOXFS 82 | } enumDriveType; 83 | 84 | ///////////////////////////////// 85 | // LED-flashing codes 86 | // or these together as argument to I2cSetFrontpanelLed 87 | 88 | enum { 89 | I2C_LED_RED0 = 0x80, 90 | I2C_LED_RED1 = 0x40, 91 | I2C_LED_RED2 = 0x20, 92 | I2C_LED_RED3 = 0x10, 93 | I2C_LED_GREEN0 = 0x08, 94 | I2C_LED_GREEN1 = 0x04, 95 | I2C_LED_GREEN2 = 0x02, 96 | I2C_LED_GREEN3 = 0x01 97 | }; 98 | 99 | /////////////////////////////// 100 | /* BIOS-wide error codes all have b31 set */ 101 | 102 | enum { 103 | ERR_SUCCESS = 0, // completed without error 104 | 105 | ERR_I2C_ERROR_TIMEOUT = 0x80000001, // I2C action failed because it did not complete in a reasonable time 106 | ERR_I2C_ERROR_BUS = 0x80000002, // I2C action failed due to non retryable bus error 107 | 108 | ERR_BOOT_PIC_ALG_BROKEN = 0x80000101 // PIC algorithm did not pass its self-test 109 | }; 110 | 111 | ///////////////////////////////// 112 | // some Boot API prototypes 113 | 114 | //////// BootPerformPicChallengeResponseAction.c 115 | 116 | /* ---------------------------- IO primitives ----------------------------------------------------------- 117 | */ 118 | 119 | static __inline void IoOutputByte(u16 wAds, u8 bValue) { 120 | // __asm__ (" out %%al,%%dx" : : "edx" (dwAds), "al" (bValue) ); 121 | __asm__ __volatile__ ("outb %b0,%w1": :"a" (bValue), "Nd" (wAds)); 122 | } 123 | 124 | static __inline void IoOutputWord(u16 wAds, u16 wValue) { 125 | // __asm__ (" out %%ax,%%dx " : : "edx" (dwAds), "ax" (wValue) ); 126 | __asm__ __volatile__ ("outw %0,%w1": :"a" (wValue), "Nd" (wAds)); 127 | } 128 | 129 | static __inline void IoOutputDword(u16 wAds, u32 dwValue) { 130 | // __asm__ (" out %%eax,%%dx " : : "edx" (dwAds), "ax" (wValue) ); 131 | __asm__ __volatile__ ("outl %0,%w1": :"a" (dwValue), "Nd" (wAds)); 132 | } 133 | 134 | 135 | static __inline u8 IoInputByte(u16 wAds) { 136 | unsigned char _v; 137 | 138 | __asm__ __volatile__ ("inb %w1,%0":"=a" (_v):"Nd" (wAds)); 139 | return _v; 140 | } 141 | 142 | static __inline u16 IoInputWord(u16 wAds) { 143 | u16 _v; 144 | 145 | __asm__ __volatile__ ("inw %w1,%0":"=a" (_v):"Nd" (wAds)); 146 | return _v; 147 | } 148 | 149 | static __inline u32 IoInputDword(u16 wAds) { 150 | u32 _v; 151 | 152 | __asm__ __volatile__ ("inl %w1,%0":"=a" (_v):"Nd" (wAds)); 153 | return _v; 154 | } 155 | 156 | #define rdmsr(msr,val1,val2) \ 157 | __asm__ __volatile__("rdmsr" \ 158 | : "=a" (val1), "=d" (val2) \ 159 | : "c" (msr)) 160 | 161 | #define wrmsr(msr,val1,val2) \ 162 | __asm__ __volatile__("wrmsr" \ 163 | : /* no outputs */ \ 164 | : "c" (msr), "a" (val1), "d" (val2)) 165 | 166 | 167 | void BootPciInterruptEnable(void); 168 | 169 | // boot process 170 | int BootPerformPicChallengeResponseAction(void); 171 | // LED control (see associated enum above) 172 | int I2cSetFrontpanelLed(u8 b); 173 | 174 | #define bprintf(...) 175 | 176 | #if PRINT_TRACE 177 | #define TRACE bprintf(__FILE__ " :%d\n\r",__LINE__); 178 | #else 179 | #define TRACE 180 | #endif 181 | 182 | #if 0 183 | typedef struct _LIST_ENTRY { 184 | struct _LIST_ENTRY *m_plistentryNext; 185 | struct _LIST_ENTRY *m_plistentryPrevious; 186 | } LIST_ENTRY; 187 | 188 | void ListEntryInsertAfterCurrent(LIST_ENTRY *plistentryCurrent, LIST_ENTRY *plistentryNew); 189 | void ListEntryRemove(LIST_ENTRY *plistentryCurrent); 190 | #endif 191 | 192 | 193 | #include "BootEEPROM.h" 194 | 195 | ////////// BootResetActions.c 196 | int printk(const char *szFormat, ...); 197 | void BiosCmosWrite(u8 bAds, u8 bData); 198 | u8 BiosCmosRead(u8 bAds); 199 | 200 | 201 | ///////// BootPciPeripheralInitialization.c 202 | void BootPciPeripheralInitialization(void); 203 | void BootAGPBUSInitialization(void); 204 | void BootDetectMemorySize(void); 205 | 206 | void PciWriteByte(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, unsigned char byteval); 207 | u8 PciReadByte(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off); 208 | void PciWriteDword(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, u32 dw); 209 | u32 PciReadDword(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off); 210 | 211 | ///////// BootPerformPicChallengeResponseAction.c 212 | 213 | int I2CTransmitWord(u8 bPicAddressI2cFormat, u16 wDataToWrite); 214 | int I2CTransmitByteGetReturn(u8 bPicAddressI2cFormat, u8 bDataToWrite); 215 | bool I2CGetTemperature(int *, int *); 216 | void I2CModifyBits(u8 bAds, u8 bReg, u8 bData, u8 bMask); 217 | 218 | extern void wait_ms(u32 ticks); 219 | extern void wait_us(u32 ticks); 220 | extern void wait_smalldelay(void); 221 | 222 | 223 | void * memcpy(void *dest, const void *src, size_t size); 224 | void * memset(void *dest, int data, size_t size); 225 | int memcmp(const void *buffer1, const void *buffer2, size_t num); 226 | int _strncmp(const char *sz1, const char *sz2, int nMax); 227 | char * strcpy(char *sz, const char *szc); 228 | char * _strncpy (char * dest, const char * src, size_t n); 229 | void chrreplace(char *string, char search, char ch); 230 | void *memmove(void *dest, const void *src, size_t n); 231 | 232 | #define printf printk 233 | // #define sleep wait_ms 234 | int tolower(int ch); 235 | int isspace (int c); 236 | 237 | void MemoryManagementInitialization(void * pvStartAddress, u32 dwTotalMemoryAllocLength); 238 | void * malloc(size_t size); 239 | void free(void *); 240 | 241 | extern volatile int nCountI2cinterrupts, nCountUnusedInterrupts, nCountUnusedInterruptsPic2, nCountInterruptsSmc, nCountInterruptsIde; 242 | extern volatile bool fSeenPowerdown; 243 | typedef enum { 244 | ETS_OPEN_OR_OPENING=0, 245 | ETS_CLOSING, 246 | ETS_CLOSED 247 | } TRAY_STATE; 248 | extern volatile TRAY_STATE traystate; 249 | 250 | 251 | extern void BootInterruptsWriteIdt(void); 252 | 253 | int copy_swap_trim(unsigned char *dst, unsigned char *src, int len); 254 | void HMAC_SHA1( unsigned char *result, 255 | unsigned char *key, int key_length, 256 | unsigned char *text1, int text1_length, 257 | unsigned char *text2, int text2_length ); 258 | 259 | char *strrchr0(char *string, char ch); 260 | 261 | void setLED(void *pattern); 262 | 263 | size_t strlen(const char * s); 264 | int sprintf(char * buf, const char *fmt, ...); 265 | char * strncpy(char * dest, const char *src, size_t count); 266 | char * strstr(const char * s1, const char * s2); 267 | int strncmp(const char * cs,const char * ct,size_t count); 268 | 269 | 270 | 271 | 272 | void serial_init(void); 273 | int I2CWriteBytetoRegister(u8 bPicAddressI2cFormat, u8 bRegister, u8 wDataToWrite); 274 | int ReadfromSMBus(u8 Address,u8 bRegister,u8 Size,u32 *Data_to_smbus); 275 | int WriteToSMBus(u8 Address,u8 bRegister,u8 Size,u32 Data_to_smbus); 276 | 277 | #include 278 | int vsprintf(char *buf, const char *fmt, va_list args); 279 | char *VideoEncoderName(void); 280 | char *AvCableName(void); 281 | 282 | 283 | 284 | 285 | static inline uint32_t align_up(uint32_t addr, uint32_t alignment) 286 | { 287 | addr += alignment-1; 288 | addr &= ~(alignment-1); 289 | return addr; 290 | } 291 | 292 | static inline uint32_t align_down(uint32_t addr, uint32_t alignment) 293 | { 294 | addr &= ~(alignment-1); 295 | return addr; 296 | } 297 | 298 | 299 | #define assert(x) do { \ 300 | if (!(x)) { \ 301 | printf("ASSERTION FAILED %s:%d\n", __FILE__, __LINE__); \ 302 | while(1); \ 303 | } \ 304 | } while(0) 305 | 306 | #endif // _Boot_H_ 307 | -------------------------------------------------------------------------------- /src/include/config.h: -------------------------------------------------------------------------------- 1 | ////////////////////// compile-time options //////////////////////////////// 2 | 3 | // selects between the supported video modes, see boot.h for enum listing those available 4 | //#define VIDEO_PREFERRED_MODE VIDEO_MODE_800x600 5 | #define VIDEO_PREFERRED_MODE VIDEO_MODE_640x480 6 | -------------------------------------------------------------------------------- /src/include/consts.h: -------------------------------------------------------------------------------- 1 | #ifndef _Consts_H_ 2 | #define _Consts_H_ 3 | 4 | /* 5 | * 6 | * includes for startup code in a form usable by the .S files 7 | * 8 | */ 9 | 10 | /*************************************************************************** 11 | * * 12 | * This program is free software; you can redistribute it and/or modify * 13 | * it under the terms of the GNU General Public License as published by * 14 | * the Free Software Foundation; either version 2 of the License, or * 15 | * (at your option) any later version. * 16 | * * 17 | ***************************************************************************/ 18 | 19 | #define PCI_CFG_ADDR 0x0CF8 20 | #define PCI_CFG_DATA 0x0CFC 21 | 22 | 23 | #define I2C_IO_BASE 0xc000 24 | 25 | #define BUS_0 0 26 | #define BUS_1 1 27 | 28 | #define DEV_0 0 29 | #define DEV_1 1 30 | #define DEV_2 2 31 | #define DEV_3 3 32 | #define DEV_4 4 33 | #define DEV_5 5 34 | #define DEV_6 6 35 | #define DEV_7 7 36 | #define DEV_8 8 37 | #define DEV_9 9 38 | #define DEV_a 0xa 39 | #define DEV_b 0xb 40 | #define DEV_c 0xc 41 | #define DEV_d 0xd 42 | #define DEV_e 0xe 43 | #define DEV_f 0xf 44 | #define DEV_10 0x10 45 | #define DEV_11 0x11 46 | #define DEV_12 0x12 47 | #define DEV_13 0x13 48 | #define DEV_14 0x14 49 | #define DEV_15 0x15 50 | #define DEV_16 0x16 51 | #define DEV_17 0x17 52 | #define DEV_18 0x18 53 | #define DEV_19 0x19 54 | #define DEV_1a 0x1a 55 | #define DEV_1b 0x1b 56 | #define DEV_1c 0x1c 57 | #define DEV_1d 0x1d 58 | #define DEV_1e 0x1e 59 | #define DEV_1f 0x1f 60 | 61 | #define FUNC_0 0 62 | /* 63 | #define boot_post_macro(value) \ 64 | movb $(value), %al ;\ 65 | outb %al, $0x80 66 | */ 67 | 68 | #endif // _Consts_H_ 69 | 70 | 71 | -------------------------------------------------------------------------------- /src/include/cromwell_types.h: -------------------------------------------------------------------------------- 1 | #ifndef cromwell_types_h 2 | #define cromwell_types_h 3 | 4 | ///////////////////////////////// 5 | // some typedefs to make for easy sizing 6 | 7 | //typedef unsigned long ULONG; 8 | typedef unsigned int u32; 9 | typedef unsigned short u16; 10 | typedef unsigned char u8; 11 | #ifndef bool_already_defined_ 12 | typedef int bool; 13 | #endif 14 | typedef unsigned long RGBA; // LSB=R -> MSB = A 15 | typedef long long __int64; 16 | 17 | #define guint int 18 | #define guint8 unsigned char 19 | 20 | #define true 1 21 | #define false 0 22 | 23 | #ifndef NULL 24 | #define NULL ((void *)0) 25 | #endif 26 | 27 | #endif /* #ifndef cromwell_types_h */ 28 | -------------------------------------------------------------------------------- /src/include/linux/bitops.h: -------------------------------------------------------------------------------- 1 | #ifndef _LINUX_BITOPS_H 2 | #define _LINUX_BITOPS_H 3 | 4 | 5 | /* 6 | * ffs: find first bit set. This is defined the same way as 7 | * the libc and compiler builtin ffs routines, therefore 8 | * differs in spirit from the above ffz (man ffs). 9 | */ 10 | 11 | static inline int generic_ffs(int x) 12 | { 13 | int r = 1; 14 | 15 | if (!x) 16 | return 0; 17 | if (!(x & 0xffff)) { 18 | x >>= 16; 19 | r += 16; 20 | } 21 | if (!(x & 0xff)) { 22 | x >>= 8; 23 | r += 8; 24 | } 25 | if (!(x & 0xf)) { 26 | x >>= 4; 27 | r += 4; 28 | } 29 | if (!(x & 3)) { 30 | x >>= 2; 31 | r += 2; 32 | } 33 | if (!(x & 1)) { 34 | x >>= 1; 35 | r += 1; 36 | } 37 | return r; 38 | } 39 | 40 | /* 41 | * hweightN: returns the hamming weight (i.e. the number 42 | * of bits set) of a N-bit word 43 | */ 44 | 45 | static inline unsigned int generic_hweight32(unsigned int w) 46 | { 47 | unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555); 48 | res = (res & 0x33333333) + ((res >> 2) & 0x33333333); 49 | res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F); 50 | res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF); 51 | return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF); 52 | } 53 | 54 | static inline unsigned int generic_hweight16(unsigned int w) 55 | { 56 | unsigned int res = (w & 0x5555) + ((w >> 1) & 0x5555); 57 | res = (res & 0x3333) + ((res >> 2) & 0x3333); 58 | res = (res & 0x0F0F) + ((res >> 4) & 0x0F0F); 59 | return (res & 0x00FF) + ((res >> 8) & 0x00FF); 60 | } 61 | 62 | static inline unsigned int generic_hweight8(unsigned int w) 63 | { 64 | unsigned int res = (w & 0x55) + ((w >> 1) & 0x55); 65 | res = (res & 0x33) + ((res >> 2) & 0x33); 66 | return (res & 0x0F) + ((res >> 4) & 0x0F); 67 | } 68 | 69 | #include "asm/bitops.h" 70 | 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /src/include/list.h: -------------------------------------------------------------------------------- 1 | /* COMES FROM LINUX, GPL */ 2 | 3 | #ifndef _LIST_H 4 | #define _LIST_H 5 | 6 | /* 7 | * Simple doubly linked list implementation. 8 | * 9 | * Some of the internal functions ("__xxx") are useful when 10 | * manipulating whole lists rather than single entries, as 11 | * sometimes we already know the next/prev entries and we can 12 | * generate better code by using them directly rather than 13 | * using the generic single-entry routines. 14 | */ 15 | 16 | struct list_head { 17 | struct list_head *next, *prev; 18 | }; 19 | 20 | #define LIST_HEAD_INIT(name) { &(name), &(name) } 21 | 22 | #define LIST_HEAD(name) \ 23 | struct list_head name = LIST_HEAD_INIT(name) 24 | 25 | #define INIT_LIST_HEAD(ptr) do { \ 26 | (ptr)->next = (ptr); (ptr)->prev = (ptr); \ 27 | } while (0) 28 | 29 | /* 30 | * Insert a new entry between two known consecutive entries. 31 | * 32 | * This is only for internal list manipulation where we know 33 | * the prev/next entries already! 34 | */ 35 | static inline void __list_add(struct list_head *new, 36 | struct list_head *prev, 37 | struct list_head *next) 38 | { 39 | next->prev = new; 40 | new->next = next; 41 | new->prev = prev; 42 | prev->next = new; 43 | } 44 | 45 | /** 46 | * list_add - add a new entry 47 | * @new: new entry to be added 48 | * @head: list head to add it after 49 | * 50 | * Insert a new entry after the specified head. 51 | * This is good for implementing stacks. 52 | */ 53 | static inline void list_add(struct list_head *new, struct list_head *head) 54 | { 55 | __list_add(new, head, head->next); 56 | } 57 | 58 | /** 59 | * list_add_tail - add a new entry 60 | * @new: new entry to be added 61 | * @head: list head to add it before 62 | * 63 | * Insert a new entry before the specified head. 64 | * This is useful for implementing queues. 65 | */ 66 | static inline void list_add_tail(struct list_head *new, struct list_head *head) 67 | { 68 | __list_add(new, head->prev, head); 69 | } 70 | 71 | /* 72 | * Delete a list entry by making the prev/next entries 73 | * point to each other. 74 | * 75 | * This is only for internal list manipulation where we know 76 | * the prev/next entries already! 77 | */ 78 | static inline void __list_del(struct list_head *prev, struct list_head *next) 79 | { 80 | next->prev = prev; 81 | prev->next = next; 82 | } 83 | 84 | /** 85 | * list_del - deletes entry from list. 86 | * @entry: the element to delete from the list. 87 | * Note: list_empty on entry does not return true after this, the entry is in an undefined state. 88 | */ 89 | static inline void list_del(struct list_head *entry) 90 | { 91 | __list_del(entry->prev, entry->next); 92 | entry->next = (void *) 0; 93 | entry->prev = (void *) 0; 94 | } 95 | 96 | /** 97 | * list_del_init - deletes entry from list and reinitialize it. 98 | * @entry: the element to delete from the list. 99 | */ 100 | static inline void list_del_init(struct list_head *entry) 101 | { 102 | __list_del(entry->prev, entry->next); 103 | INIT_LIST_HEAD(entry); 104 | } 105 | 106 | /** 107 | * list_move - delete from one list and add as another's head 108 | * @list: the entry to move 109 | * @head: the head that will precede our entry 110 | */ 111 | static inline void list_move(struct list_head *list, struct list_head *head) 112 | { 113 | __list_del(list->prev, list->next); 114 | list_add(list, head); 115 | } 116 | 117 | /** 118 | * list_move_tail - delete from one list and add as another's tail 119 | * @list: the entry to move 120 | * @head: the head that will follow our entry 121 | */ 122 | static inline void list_move_tail(struct list_head *list, 123 | struct list_head *head) 124 | { 125 | __list_del(list->prev, list->next); 126 | list_add_tail(list, head); 127 | } 128 | 129 | /** 130 | * list_empty - tests whether a list is empty 131 | * @head: the list to test. 132 | */ 133 | static inline int list_empty(struct list_head *head) 134 | { 135 | return head->next == head; 136 | } 137 | 138 | static inline void __list_splice(struct list_head *list, 139 | struct list_head *head) 140 | { 141 | struct list_head *first = list->next; 142 | struct list_head *last = list->prev; 143 | struct list_head *at = head->next; 144 | 145 | first->prev = head; 146 | head->next = first; 147 | 148 | last->next = at; 149 | at->prev = last; 150 | } 151 | 152 | /** 153 | * list_splice - join two lists 154 | * @list: the new list to add. 155 | * @head: the place to add it in the first list. 156 | */ 157 | static inline void list_splice(struct list_head *list, struct list_head *head) 158 | { 159 | if (!list_empty(list)) 160 | __list_splice(list, head); 161 | } 162 | 163 | /** 164 | * list_splice_init - join two lists and reinitialise the emptied list. 165 | * @list: the new list to add. 166 | * @head: the place to add it in the first list. 167 | * 168 | * The list at @list is reinitialised 169 | */ 170 | static inline void list_splice_init(struct list_head *list, 171 | struct list_head *head) 172 | { 173 | if (!list_empty(list)) { 174 | __list_splice(list, head); 175 | INIT_LIST_HEAD(list); 176 | } 177 | } 178 | 179 | /** 180 | * list_entry - get the struct for this entry 181 | * @ptr: the &struct list_head pointer. 182 | * @type: the type of the struct this is embedded in. 183 | * @member: the name of the list_struct within the struct. 184 | */ 185 | #define list_entry(ptr, type, member) \ 186 | ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) 187 | 188 | /** 189 | * list_for_each - iterate over a list 190 | * @pos: the &struct list_head to use as a loop counter. 191 | * @head: the head for your list. 192 | */ 193 | #define list_for_each(pos, head) \ 194 | for (pos = (head)->next; pos != (head); \ 195 | pos = pos->next) 196 | /** 197 | * list_for_each_prev - iterate over a list backwards 198 | * @pos: the &struct list_head to use as a loop counter. 199 | * @head: the head for your list. 200 | */ 201 | #define list_for_each_prev(pos, head) \ 202 | for (pos = (head)->prev; pos != (head); \ 203 | pos = pos->prev) 204 | 205 | /** 206 | * list_for_each_safe - iterate over a list safe against removal of list entry 207 | * @pos: the &struct list_head to use as a loop counter. 208 | * @n: another &struct list_head to use as temporary storage 209 | * @head: the head for your list. 210 | */ 211 | #define list_for_each_safe(pos, n, head) \ 212 | for (pos = (head)->next, n = pos->next; pos != (head); \ 213 | pos = n, n = pos->next) 214 | 215 | /** 216 | * list_for_each_entry - iterate over list of given type 217 | * @pos: the type * to use as a loop counter. 218 | * @head: the head for your list. 219 | * @member: the name of the list_struct within the struct. 220 | */ 221 | #define list_for_each_entry(pos, head, member) \ 222 | for (pos = list_entry((head)->next, typeof(*pos), member); \ 223 | &pos->member != (head); \ 224 | pos = list_entry(pos->member.next, typeof(*pos), member)) 225 | 226 | #endif 227 | -------------------------------------------------------------------------------- /src/include/memory_layout.h: -------------------------------------------------------------------------------- 1 | #ifndef memory_layout_h 2 | #define memory_layout_h 3 | 4 | /* a retail Xbox has 64 MB of RAM */ 5 | #define RAMSIZE (64 * 1024*1024) 6 | #define FB_SIZE 0x00400000 7 | #define FB_START (0xf0000000 | (RAMSIZE - FB_SIZE)) 8 | 9 | /* let's reserve 4 MB at the top for the framebuffer */ 10 | #define RAMSIZE_USE (RAMSIZE - FB_SIZE) 11 | 12 | #endif /* #ifndef memory_layout_h */ 13 | -------------------------------------------------------------------------------- /src/include/stdint.h: -------------------------------------------------------------------------------- 1 | #ifndef STDINT_H 2 | #define STDINT_H 3 | 4 | typedef unsigned size_t; 5 | typedef signed ssize_t; 6 | 7 | typedef unsigned char uint8_t; 8 | typedef unsigned short uint16_t; 9 | typedef unsigned long uint32_t; 10 | typedef unsigned long long uint64_t; 11 | 12 | typedef signed char int8_t; 13 | typedef signed short int16_t; 14 | typedef signed long int32_t; 15 | typedef signed long long int64_t; 16 | 17 | typedef short int int_least16_t; 18 | typedef unsigned short int uint_least16_t; 19 | 20 | #endif /* STDINT_H */ 21 | -------------------------------------------------------------------------------- /src/include/stdio.h: -------------------------------------------------------------------------------- 1 | #ifndef stdio_h 2 | #define stdio_h 3 | 4 | #include "sys/types.h" 5 | 6 | #include "boot.h" 7 | #define fprintf(f, ...) printk(__VA_ARGS__) 8 | #define stderr 2 9 | 10 | #endif /* #ifndef stdio_h */ 11 | -------------------------------------------------------------------------------- /src/include/stdlib.h: -------------------------------------------------------------------------------- 1 | #ifndef stdlib_h 2 | #define stdlib_h 3 | 4 | #include "sys/types.h" 5 | 6 | #endif /* #ifndef stdlib.h */ 7 | -------------------------------------------------------------------------------- /src/include/string.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mborgerson/xqemu-kernel/71917116247abd1f449c1384adf579b1a47af390/src/include/string.h -------------------------------------------------------------------------------- /src/include/sys/mman.h: -------------------------------------------------------------------------------- 1 | #ifndef MMAN_H 2 | #define MMAN_H 3 | 4 | /* Linux mman.h */ 5 | #define PROT_READ 0x1 /* page can be read */ 6 | #define PROT_WRITE 0x2 /* page can be written */ 7 | #define PROT_EXEC 0x4 /* page can be executed */ 8 | #define PROT_SEM 0x8 /* page may be used for atomic ops */ 9 | #define PROT_NONE 0x0 /* page can not be accessed */ 10 | 11 | #define MAP_SHARED 0x01 /* Share changes */ 12 | #define MAP_PRIVATE 0x02 /* Changes are private */ 13 | #define MAP_TYPE 0x0f /* Mask for type of mapping */ 14 | #define MAP_FIXED 0x10 /* Interpret addr exactly */ 15 | #define MAP_ANONYMOUS 0x20 /* don't use a file */ 16 | 17 | void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); 18 | int munmap(void *addr, size_t length); 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /src/include/sys/types.h: -------------------------------------------------------------------------------- 1 | #ifndef sys_types_h 2 | #define sys_types_h 3 | 4 | typedef unsigned short int u_int16_t; 5 | typedef unsigned int u_int32_t; 6 | typedef unsigned long long int u_int64_t; 7 | 8 | #define FILE int 9 | 10 | 11 | #include 12 | 13 | typedef unsigned size_t; 14 | typedef unsigned ptrdiff_t; 15 | typedef long int off_t; 16 | 17 | void abort(); 18 | extern int errno; 19 | 20 | enum { 21 | ENOMEM = -1, 22 | EINVAL = -2, 23 | }; 24 | 25 | #endif /* #ifndef sys_types_h */ 26 | -------------------------------------------------------------------------------- /src/include/video.h: -------------------------------------------------------------------------------- 1 | #ifndef video_h 2 | #define video_h 3 | 4 | #include "stdlib.h" 5 | 6 | // video helpers 7 | typedef struct { 8 | u8 * pData; 9 | u8 * pBackdrop; 10 | int width; 11 | int height; 12 | int bpp; 13 | } JPEG; 14 | 15 | int BootVideoOverlayString(u32 * pdwaTopLeftDestination, u32 m_dwCountBytesPerLineDestination, RGBA rgbaOpaqueness, const char * szString); 16 | void BootVideoChunkedPrint(const char * szBuffer); 17 | int VideoDumpAddressAndData(u32 dwAds, const u8 * baData, u32 dwCountBytesUsable); 18 | unsigned int BootVideoGetStringTotalWidth(const char * szc); 19 | void BootVideoClearScreen(JPEG * pJpeg, int nStartLine, int nEndLine); 20 | 21 | void BootVideoEnableOutput(u8 bAvPack); 22 | u8 * BootVideoGetPointerToEffectiveJpegTopLeft(JPEG * pJpeg); 23 | 24 | extern u8 baBackdrop[60*72*4]; 25 | extern JPEG jpegBackdrop; 26 | 27 | #endif /* #ifndef video_h */ 28 | -------------------------------------------------------------------------------- /src/init.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Matt Borgerson 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | */ 18 | 19 | #include "boot.h" 20 | #include "BootEEPROM.h" 21 | #include "video.h" 22 | #include "memory_layout.h" 23 | #include "xdecl.h" 24 | #include "lib/xbe/xbe.h" 25 | 26 | volatile CURRENT_VIDEO_MODE_DETAILS vmode; 27 | extern char HEAP_BASE[], HEAP_SIZE[]; 28 | extern volatile int nInteruptable; 29 | extern void (*video_interrupt_hook)(void); 30 | 31 | void init(void) 32 | { 33 | nInteruptable = 0; 34 | 35 | serial_init(); 36 | printk("XQEMU HLE Kernel\n"); 37 | 38 | m_import_addrs[156] = (void*)&BIOS_TICK_COUNT; // KeTickCount 39 | 40 | MemoryManagementInitialization(HEAP_BASE, (u32)HEAP_SIZE); 41 | BootInterruptsWriteIdt(); 42 | BootPciPeripheralInitialization(); 43 | BootAGPBUSInitialization(); 44 | BootDetectMemorySize(); 45 | BootEepromReadEntireEEPROM(); 46 | memset((void *)FB_START,0x00,0x400000); 47 | BootVgaInitializationKernelNG((CURRENT_VIDEO_MODE_DETAILS *)&vmode); 48 | 49 | I2CTransmitWord(0x10, 0x1a01); 50 | I2CTransmitWord(0x10, 0x1901); // no reset on eject 51 | 52 | /* Here, the interrupts are Switched on now */ 53 | BootPciInterruptEnable(); 54 | nInteruptable = 1; 55 | 56 | // FIXME: Move this into a NIC init function 57 | // set Ethernet MAC address from EEPROM 58 | { 59 | volatile u8 * pb=(u8 *)0xfef000a8; // Ethernet MMIO base + MAC register offset (<--thanks to Anders Gustafsson) 60 | int n; 61 | for(n=5;n>=0;n--) { *pb++= eeprom.MACAddress[n]; } // send it in backwards, its reversed by the driver 62 | } 63 | 64 | // FIXME: Move this into a HLE init function 65 | // Setup the HLE device 66 | #define KHLE_BAR 0xfed0c000 67 | PciWriteDword(0, 0x11, 0, 0x04, 7); 68 | PciWriteDword(0, 0x11, 0, 0x10, KHLE_BAR); 69 | 70 | // 71 | // FIXME: Until we have proper file i/o and virtual memory allocation, 72 | // just punt to XQEMU HLE to DMA the XBE right into memory. 73 | // 74 | // The right way is to implement the necessary kernel functions, 75 | // then call them to find and load the XBE. 76 | // 77 | 78 | // Get XBE size 79 | size_t xbe_size = *((volatile uint32_t *)(KHLE_BAR + 0x10)); 80 | printk("XBE Size: %x\n", xbe_size); 81 | 82 | // Allocate some memory for the XBE 83 | void *xbe_load_addr = MmAllocateContiguousMemoryEx(align_up(xbe_size, 0x1000), 0, 0x3FFFFFF, 0, 0); 84 | // FIXME: Leak 85 | 86 | printk("XBE Load Address: %x\n", xbe_load_addr); 87 | assert(xbe_load_addr != NULL); 88 | 89 | // Poke the KHLE device to load an XBE into RAM for us 90 | *((volatile uint32_t *)(KHLE_BAR + 0x10)) = (uint32_t)xbe_load_addr & ~0x80000000; 91 | 92 | XBE_HEADER *hdr = load_xbe(xbe_load_addr); 93 | 94 | // Get unscrambled XBE entry point 95 | void (*xbe_entry)(void) = get_xbe_entry(hdr); 96 | printk("Jumping to XBE entry point %p\n", xbe_entry); 97 | xbe_entry(); 98 | 99 | while(1); 100 | } 101 | 102 | //----------------------------------------------------------------------------- 103 | 104 | #define PCI_SLOT(device, function) (((function) << 5) | (device)) 105 | #define PCI_DEV(slot) ((slot) & 0x1f) 106 | #define PCI_FUNC(slot) (((slot) >> 5) & 0x7) 107 | 108 | /** 109 | * AvSendTVEncoderOption 110 | */ 111 | XBAPI VOID NTAPI AvSendTVEncoderOption( 112 | PVOID RegisterBase, 113 | ULONG Option, 114 | ULONG Param, 115 | PULONG Result 116 | ) 117 | { 118 | printf("AvSendTVEncoderOption(%x, %x, %x, %x)\n", RegisterBase, Option, Param, Result); 119 | if (Result != NULL) { 120 | *Result = 0x00400101; 121 | } 122 | } 123 | 124 | /** 125 | * AvSetDisplayMode 126 | */ 127 | XBAPI ULONG NTAPI AvSetDisplayMode( 128 | PVOID RegisterBase, 129 | ULONG Step, 130 | ULONG DisplayMode, 131 | ULONG SourceColorFormat, 132 | ULONG Pitch, 133 | ULONG FrameBuffer 134 | ) 135 | { 136 | return 0; 137 | } 138 | 139 | /** 140 | * HalGetInterruptVector 141 | */ 142 | XBAPI ULONG NTAPI HalGetInterruptVector( 143 | ULONG BusInterruptLevel, 144 | PKIRQL Irql 145 | ) 146 | { 147 | if (BusInterruptLevel == 3) { 148 | *Irql = 3; 149 | } 150 | 151 | return 0; 152 | } 153 | 154 | /** 155 | * HalReadWritePCISpace 156 | */ 157 | XBAPI VOID NTAPI HalReadWritePCISpace( 158 | ULONG BusNumber, 159 | ULONG SlotNumber, 160 | ULONG RegisterNumber, 161 | PVOID Buffer, 162 | ULONG Length, 163 | BOOLEAN WritePCISpace 164 | ) 165 | { 166 | if (WritePCISpace == FALSE) { 167 | if (Length == 4) { 168 | *(volatile DWORD *)Buffer = PciReadDword(BusNumber, PCI_DEV(SlotNumber), PCI_FUNC(SlotNumber), RegisterNumber); 169 | return; 170 | } 171 | } 172 | 173 | assert(0); 174 | } 175 | 176 | /** 177 | * KeConnectInterrupt 178 | */ 179 | XBAPI BOOLEAN NTAPI 180 | KeConnectInterrupt( 181 | PKINTERRUPT Interrupt 182 | ) 183 | { 184 | return TRUE; 185 | } 186 | 187 | /** 188 | * KeDelayExecutionThread 189 | */ 190 | XBAPI NTSTATUS NTAPI 191 | KeDelayExecutionThread( 192 | KPROCESSOR_MODE WaitMode, 193 | BOOLEAN Alertable, 194 | PLARGE_INTEGER Interval 195 | ) 196 | { 197 | wait_ms(100); 198 | return STATUS_SUCCESS; 199 | } 200 | 201 | /** 202 | * KeInitializeDpc 203 | */ 204 | XBAPI VOID NTAPI 205 | KeInitializeDpc( 206 | PKDPC Dpc, 207 | PKDEFERRED_ROUTINE DeferredRoutine, 208 | PVOID DeferredContext 209 | ) 210 | { 211 | Dpc->DeferredRoutine = DeferredRoutine; 212 | Dpc->DeferredContext = DeferredContext; 213 | } 214 | 215 | /** 216 | * KeInitializeInterrupt 217 | */ 218 | XBAPI VOID NTAPI 219 | KeInitializeInterrupt( 220 | PKINTERRUPT Interrupt, 221 | PKSERVICE_ROUTINE ServiceRoutine, 222 | PVOID ServiceContext, 223 | ULONG Vector, 224 | KIRQL Irql, 225 | KINTERRUPT_MODE InterruptMode, 226 | BOOLEAN ShareVector 227 | ) 228 | { 229 | if (Irql == 3) { 230 | video_interrupt_hook = (void*)ServiceRoutine; 231 | } 232 | } 233 | 234 | /** 235 | * KeInsertQueueDpc 236 | */ 237 | XBAPI BOOLEAN NTAPI 238 | KeInsertQueueDpc( 239 | PRKDPC Dpc, 240 | PVOID SystemArgument1, 241 | PVOID SystemArgument2 242 | ) 243 | { 244 | assert(Dpc != NULL); 245 | 246 | // Just call the DPC for now 247 | void (*dpc_func)(void) = Dpc->DeferredRoutine; 248 | dpc_func(); 249 | return TRUE; 250 | } 251 | 252 | /** 253 | * MmClaimGpuInstanceMemory 254 | */ 255 | XBAPI PVOID NTAPI 256 | MmClaimGpuInstanceMemory( 257 | SIZE_T NumberOfBytes, 258 | PSIZE_T NumberOfPaddingBytes 259 | ) 260 | { 261 | if (NumberOfPaddingBytes != NULL) { 262 | *NumberOfPaddingBytes = 0x10000; 263 | } 264 | 265 | return (PVOID)0x83FF0000; 266 | } 267 | 268 | /** 269 | * NtCreateEvent 270 | */ 271 | XBAPI NTSTATUS NTAPI 272 | NtCreateEvent( 273 | PHANDLE EventHandle, 274 | POBJECT_ATTRIBUTES ObjectAttributes, 275 | EVENT_TYPE EventType, 276 | BOOLEAN InitialState 277 | ) 278 | { 279 | return STATUS_SUCCESS; 280 | } 281 | 282 | /** 283 | * NtPulseEvent 284 | */ 285 | XBAPI NTSTATUS NTAPI 286 | NtPulseEvent( 287 | HANDLE EventHandle, 288 | PLONG PreviousState 289 | ) 290 | { 291 | return STATUS_SUCCESS; 292 | } 293 | 294 | /** 295 | * NtWaitForSingleObject 296 | */ 297 | XBAPI NTSTATUS NTAPI 298 | NtWaitForSingleObject( 299 | HANDLE Handle, 300 | BOOLEAN Alertable, 301 | PLARGE_INTEGER Timeout 302 | ) 303 | { 304 | return STATUS_SUCCESS; 305 | } 306 | 307 | /** 308 | * HalRegisterShutdownNotification 309 | */ 310 | XBAPI VOID NTAPI 311 | HalRegisterShutdownNotification( 312 | PHAL_SHUTDOWN_REGISTRATION ShutdownRegistration, 313 | BOOLEAN Register 314 | ) 315 | { 316 | } 317 | 318 | //////////////////////////////////////////////////////////////////////////////// 319 | // dlmalloc support 320 | 321 | int errno; 322 | 323 | void abort() 324 | { 325 | printk("abort()!\n"); 326 | while (1); 327 | } 328 | 329 | int time() 330 | { 331 | // FIXME: Should be since EPOCH 332 | return BIOS_TICK_COUNT; 333 | } 334 | -------------------------------------------------------------------------------- /src/lib/eeprom/BootEEPROM.c: -------------------------------------------------------------------------------- 1 | #include "boot.h" 2 | #include "VideoInitialization.h" 3 | #include "BootEEPROM.h" 4 | 5 | void BootEepromReadEntireEEPROM() { 6 | int i; 7 | u8 *pb=(u8 *)&eeprom; 8 | for(i = 0; i < 256; i++) { 9 | *pb++ = I2CTransmitByteGetReturn(0x54, i); 10 | } 11 | } 12 | 13 | void BootEepromPrintInfo() { 14 | VIDEO_ATTR=0xffc8c8c8; 15 | printk("MAC : "); 16 | VIDEO_ATTR=0xffc8c800; 17 | printk("%02X%02X%02X%02X%02X%02X ", 18 | eeprom.MACAddress[0], eeprom.MACAddress[1], eeprom.MACAddress[2], 19 | eeprom.MACAddress[3], eeprom.MACAddress[4], eeprom.MACAddress[5] 20 | ); 21 | 22 | VIDEO_ATTR=0xffc8c8c8; 23 | printk("Vid: "); 24 | VIDEO_ATTR=0xffc8c800; 25 | 26 | switch(*((VIDEO_STANDARD *)&eeprom.VideoStandard)) { 27 | case VID_INVALID: 28 | printk("0 "); 29 | break; 30 | case NTSC_M: 31 | printk("NTSC-M "); 32 | break; 33 | case NTSC_J: 34 | printk("NTSC-J "); 35 | break; 36 | case PAL_I: 37 | printk("PAL-I "); 38 | break; 39 | default: 40 | printk("%X ", (int)*((VIDEO_STANDARD *)&eeprom.VideoStandard)); 41 | break; 42 | } 43 | 44 | VIDEO_ATTR=0xffc8c8c8; 45 | printk("Serial: "); 46 | VIDEO_ATTR=0xffc8c800; 47 | 48 | { 49 | char sz[13]; 50 | memcpy(sz, &eeprom.SerialNumber[0], 12); 51 | sz[12]='\0'; 52 | printk(" %s", sz); 53 | } 54 | 55 | printk("\n"); 56 | VIDEO_ATTR=0xffc8c8c8; 57 | } 58 | 59 | /* The EepromCRC algorithm was obtained from the XKUtils 0.2 source released by 60 | * TeamAssembly under the GNU GPL. 61 | * Specifically, from XKCRC.cpp 62 | * 63 | * Rewritten to ANSI C by David Pye (dmp@davidmpye.dyndns.org) 64 | * 65 | * Thanks! */ 66 | void EepromCRC(unsigned char *crc, unsigned char *data, long dataLen) { 67 | unsigned char* CRC_Data = (unsigned char *)malloc(dataLen+4); 68 | int pos=0; 69 | memset(crc,0x00,4); 70 | 71 | memset(CRC_Data,0x00, dataLen+4); 72 | //Circle shift input data one byte right 73 | memcpy(CRC_Data + 0x01 , data, dataLen-1); 74 | memcpy(CRC_Data, data + dataLen-1, 0x01); 75 | 76 | for (pos=0; pos<4; ++pos) { 77 | unsigned short CRCPosVal = 0xFFFF; 78 | unsigned long l; 79 | for (l=pos; l> 8); 84 | } 85 | free(CRC_Data); 86 | } 87 | 88 | void EepromSetWidescreen(int enable) { 89 | //Changing this setting requires that Checksum3 90 | //be recalculated. 91 | 92 | unsigned char sum[4]; 93 | if (enable) { 94 | //Enable WS 95 | WriteToSMBus(0x54, 0x96, 0, 1); 96 | eeprom.VideoFlags[2] = 0x01; 97 | } 98 | else { 99 | //Disable WSS 100 | WriteToSMBus(0x54, 0x96, 0, 0); 101 | eeprom.VideoFlags[2] = 0x00; 102 | } 103 | 104 | EepromCRC(sum,eeprom.TimeZoneBias,0x5b); 105 | WriteToSMBus(0x54, 0x60, 1, sum[0]); 106 | WriteToSMBus(0x54, 0x61, 1, sum[1]); 107 | WriteToSMBus(0x54, 0x62, 1, sum[2]); 108 | WriteToSMBus(0x54, 0x63, 1, sum[3]); 109 | } 110 | 111 | void EepromSetVideoStandard(VIDEO_STANDARD standard) { 112 | //Changing this setting requires that Checksum2 113 | //be recalculated. 114 | unsigned char sum[4]; 115 | unsigned int i; 116 | 117 | //Write the four bytes to the EEPROM 118 | for (i=0; i<4; ++i) { 119 | WriteToSMBus(0x54,0x58+i, 1, (u8)(standard>>(8*i))&0xff); 120 | } 121 | 122 | memcpy(eeprom.VideoStandard, &standard, 0x04); 123 | 124 | EepromCRC(sum,eeprom.SerialNumber,0x28); 125 | WriteToSMBus(0x54, 0x30, 0, sum[0]); 126 | WriteToSMBus(0x54, 0x31, 0, sum[1]); 127 | WriteToSMBus(0x54, 0x32, 0, sum[2]); 128 | WriteToSMBus(0x54, 0x33, 0, sum[3]); 129 | } 130 | -------------------------------------------------------------------------------- /src/lib/eeprom/BootEEPROM.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Parts are from the Team-Assembly XKUtils thx. 3 | * 4 | */ 5 | 6 | #ifndef _BootEEPROM_H_ 7 | #define _BootEEPROM_H_ 8 | 9 | #include "VideoInitialization.h" 10 | //Defines for Data structure sizes.. 11 | #define EEPROM_SIZE 0x100 12 | #define CONFOUNDER_SIZE 0x008 13 | #define HDDKEY_SIZE 0x010 14 | #define XBEREGION_SIZE 0x001 15 | #define SERIALNUMBER_SIZE 0x00C 16 | #define MACADDRESS_SIZE 0x006 17 | #define ONLINEKEY_SIZE 0x010 18 | #define DVDREGION_SIZE 0x001 19 | #define VIDEOSTANDARD_SIZE 0x004 20 | 21 | //EEPROM Data structe value enums 22 | typedef enum { 23 | ZONE_NONE = 0x00, 24 | ZONE1 = 0x01, 25 | ZONE2 = 0x02, 26 | ZONE3 = 0x03, 27 | ZONE4 = 0x04, 28 | ZONE5 = 0x05, 29 | ZONE6 = 0x06 30 | } DVD_ZONE; 31 | 32 | typedef enum { 33 | VID_INVALID = 0x00000000, 34 | NTSC_M = 0x00400100, 35 | NTSC_J = 0x00400200, 36 | PAL_I = 0x00800300 37 | } VIDEO_STANDARD; 38 | 39 | typedef enum { 40 | XBE_INVALID = 0x00, 41 | NORTH_AMERICA = 0x01, 42 | JAPAN = 0x02, 43 | EURO_AUSTRALIA = 0x04 44 | } XBE_REGION; 45 | 46 | 47 | //Structure that holds contents of 256 byte EEPROM image.. 48 | typedef struct _EEPROMDATA { 49 | u8 HMAC_SHA1_Hash[20]; // 0x00 - 0x13 HMAC_SHA1 Hash 50 | u8 Confounder[8]; // 0x14 - 0x1B RC4 Encrypted Confounder ?? 51 | u8 HDDKkey[16]; // 0x1C - 0x2B RC4 Encrypted HDD key 52 | u8 XBERegion[4]; // 0x2C - 0x2F RC4 Encrypted Region code (0x01 North America, 0x02 Japan, 0x04 Europe) 53 | 54 | u8 Checksum2[4]; // 0x30 - 0x33 Checksum of next 44 bytes 55 | u8 SerialNumber[12]; // 0x34 - 0x3F Xbox serial number 56 | u8 MACAddress[6]; // 0x40 - 0x45 Ethernet MAC address 57 | u8 UNKNOWN2[2]; // 0x46 - 0x47 Unknown Padding ? 58 | 59 | u8 OnlineKey[16]; // 0x48 - 0x57 Online Key ? 60 | 61 | u8 VideoStandard[4]; // 0x58 - 0x5B ** 0x00014000 = NTSC, 0x00038000 = PAL, 0x00400100 = NTSC_J 62 | 63 | u8 UNKNOWN3[4]; // 0x5C - 0x5F Unknown Padding ? 64 | 65 | //Comes configured up to here from factory.. everything after this can be zero'd out... 66 | //To reset XBOX to Factory settings, Make checksum3 0xFFFFFFFF and zero all data below (0x64-0xFF) 67 | //Doing this will Reset XBOX and upon startup will get Language & Setup screen... 68 | u8 Checksum3[4]; // 0x60 - 0x63 other Checksum of next 69 | 70 | u8 TimeZoneBias[4]; // 0x64 - 0x67 Zone Bias? 71 | u8 TimeZoneStdName[4]; // 0x68 - 0x6B Standard timezone 72 | u8 TimeZoneDltName[4]; // 0x5C - 0x6F Daylight timezone 73 | u8 UNKNOWN4[8]; // 0x70 - 0x77 Unknown Padding ? 74 | u8 TimeZoneStdDate[4]; // 0x78 - 0x7B 10-05-00-02 (Month-Day-DayOfWeek-Hour) 75 | u8 TimeZoneDltDate[4]; // 0x7C - 0x7F 04-01-00-02 (Month-Day-DayOfWeek-Hour) 76 | u8 UNKNOWN5[8]; // 0x80 - 0x87 Unknown Padding ? 77 | u8 TimeZoneStdBias[4]; // 0x88 - 0x8B Standard Bias? 78 | u8 TimeZoneDltBias[4]; // 0x8C - 0x8F Daylight Bias? 79 | 80 | u8 LanguageID[4]; // 0x90 - 0x93 Language ID 81 | 82 | u8 VideoFlags[4]; // 0x94 - 0x97 Video Settings - 0x96 b0==widescreen 0x96 b4 == letterbox 83 | u8 AudioFlags[4]; // 0x98 - 0x9B Audio Settings 84 | 85 | u8 ParentalControlGames[4]; // 0x9C - 0x9F 0=MAX rating 86 | u8 ParentalControlPwd[4]; // 0xA0 - 0xA3 7=X, 8=Y, B=LTrigger, C=RTrigger 87 | u8 ParentalControlMovies[4]; // 0xA4 - 0xA7 0=Max rating 88 | 89 | u8 XBOXLiveIPAddress[4]; // 0xA8 - 0xAB XBOX Live IP Address.. 90 | u8 XBOXLiveDNS[4]; // 0xAC - 0xAF XBOX Live DNS Server.. 91 | u8 XBOXLiveGateWay[4]; // 0xB0 - 0xB3 XBOX Live Gateway Address.. 92 | u8 XBOXLiveSubNetMask[4]; // 0xB4 - 0xB7 XBOX Live Subnet Mask.. 93 | u8 OtherSettings[4]; // 0xA8 - 0xBB Other XBLive settings ? 94 | 95 | u8 DVDPlaybackKitZone[4]; // 0xBC - 0xBF DVD Playback Kit Zone 96 | 97 | u8 UNKNOWN6[64]; // 0xC0 - 0xFF Unknown Codes / Memory timing data ? 98 | } EEPROMDATA; 99 | 100 | EEPROMDATA eeprom; 101 | 102 | void BootEepromReadEntireEEPROM(void); 103 | void BootEepromPrintInfo(void); 104 | void EepromCRC(unsigned char *crc, unsigned char *data, long dataLen); 105 | void EepromSetVideoStandard(VIDEO_STANDARD standard); 106 | void EepromSetWidescreen(int enable); 107 | #endif // _BootEEPROM_H_ 108 | -------------------------------------------------------------------------------- /src/lib/font/font.c: -------------------------------------------------------------------------------- 1 | #include "font.h" 2 | 3 | 4 | main() 5 | { 6 | int n, n1=0; 7 | 8 | printf("const unsigned short waStarts[] = {\n"); 9 | printf(" 0, 4, 12, 20, 29, 42, 53, 56, // <-- (\n"); 10 | printf(" 62, 67, 73, 81, 85, 91, 95, 100, // <-- 0\n"); 11 | printf(" 109, 117, 125, 133, 142, 149, 158, 166, // <-- 8\n"); 12 | printf(" 174, 184, 189, 193, 202, 211, 219, 229, // <-- @\n"); 13 | printf(" 243, 254, 265, 276, 288, 297, 306, 318, // <-- H\n"); 14 | printf(" 330, 333, 343, 353, 362, 376, 386, 398, // <-- P\n"); 15 | printf(" 407, 420, 430, 440, 449, 460, 470, 484, // <-- X\n"); 16 | printf(" 495, 505, 514, 518, 523, 529, 535, 546, // <-- `\n"); 17 | printf(" 550, 559, 568, 577, 585, 594, 600, 608, // <-- h\n"); 18 | printf(" 618, 621, 626, 635, 639, 652, 662, 671, // <-- p\n"); 19 | printf(" 680, 690, 696, 704, 709, 718, 727, 738, // <-- x\n"); 20 | printf(" 747, 756, 763, 769, 774, 779, 788 // <-- end of bitmap\n"); 21 | printf("};\n\nconst unsigned int uiPixelsX=%u, uiPixelsY=%u;\n\n", gimp_image.width, gimp_image.height); 22 | 23 | printf("const unsigned char baCharset[] = {\n"); 24 | for(n=0;n>4; 27 | printf("0x%02X", b^0xff); 28 | if((n+8)= l2) { 128 | l1--; 129 | if (!memcmp(s1,s2,l2)) return (char *) s1; 130 | s1++; 131 | } 132 | return NULL; 133 | } 134 | 135 | char * strpbrk(const char * cs,const char * ct) 136 | { 137 | const char *sc1,*sc2; 138 | 139 | for( sc1 = cs; *sc1 != '\0'; ++sc1) { 140 | for( sc2 = ct; *sc2 != '\0'; ++sc2) { 141 | if (*sc1 == *sc2) return (char *) sc1; 142 | } 143 | } 144 | return NULL; 145 | } 146 | 147 | char * strsep(char **s, const char *ct) 148 | { 149 | char *sbegin = *s, *end; 150 | 151 | if (sbegin == NULL) return NULL; 152 | 153 | end = strpbrk(sbegin, ct); 154 | if (end) *end++ = '\0'; 155 | *s = end; 156 | return sbegin; 157 | } 158 | 159 | int strncmp(const char * cs,const char * ct,size_t count) 160 | { 161 | register int __res; 162 | int d0, d1, d2; 163 | __asm__ __volatile__( 164 | "1:\tdecl %3\n\t" 165 | "js 2f\n\t" 166 | "lodsb\n\t" 167 | "scasb\n\t" 168 | "jne 3f\n\t" 169 | "testb %%al,%%al\n\t" 170 | "jne 1b\n" 171 | "2:\txorl %%eax,%%eax\n\t" 172 | "jmp 4f\n" 173 | "3:\tsbbl %%eax,%%eax\n\t" 174 | "orb $1,%%al\n" 175 | "4:" 176 | :"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2) 177 | :"1" (cs),"2" (ct),"3" (count)); 178 | return __res; 179 | } 180 | 181 | 182 | 183 | 184 | char *strrchr0(char *string, char ch) 185 | { 186 | char *ptr = string; 187 | while(*ptr != 0) { 188 | if(*ptr == ch) { 189 | return ptr; 190 | } else { 191 | ptr++; 192 | } 193 | } 194 | return NULL; 195 | } 196 | 197 | void chrreplace(char *string, char search, char ch) { 198 | char *ptr = string; 199 | while(*ptr != 0) { 200 | if(*ptr == search) { 201 | *ptr = ch; 202 | } else { 203 | ptr++; 204 | } 205 | } 206 | } 207 | 208 | /* Shamelessly copied from linux-2.6.15.1/lib/string.c */ 209 | void *memmove(void *dest, const void *src, size_t count) 210 | { 211 | char *tmp; 212 | const char *s; 213 | 214 | if (dest <= src) { 215 | tmp = dest; 216 | s = src; 217 | while (count--) 218 | *tmp++ = *s++; 219 | } else { 220 | tmp = dest; 221 | tmp += count; 222 | s = src; 223 | s += count; 224 | while (count--) 225 | *--tmp = *--s; 226 | } 227 | return dest; 228 | } 229 | 230 | /* -------------------------------------------------------------------- */ 231 | 232 | #if 0 233 | 234 | unsigned int MemoryManagerStartAddress=0; 235 | 236 | int MemoryManagerGetFree(void) { 237 | 238 | unsigned char *memsmall = (void*)MemoryManagerStartAddress; 239 | int freeblocks = 0; 240 | int counter; 241 | for (counter=0;counter<0x400;counter++) { 242 | if (memsmall[counter]==0x0) freeblocks++; 243 | } 244 | return freeblocks; 245 | 246 | } 247 | 248 | void MemoryManagementInitialization(void * pvStartAddress, u32 dwTotalMemoryAllocLength) 249 | { 250 | unsigned char *mem = pvStartAddress; 251 | //if (dwTotalMemoryAllocLength!=0x1000000) return 1; 252 | 253 | MemoryManagerStartAddress = (unsigned int)pvStartAddress; 254 | 255 | // Prepare the memory cluster Table to be free 256 | memset(mem,0x0,0x4000); 257 | // Set the first cluster to be "reserved" 258 | mem[0] = 0xff; 259 | 260 | return ; 261 | } 262 | 263 | 264 | void * t_malloc(size_t size) 265 | { 266 | unsigned char *memsmall = (void*)MemoryManagerStartAddress; 267 | unsigned int counter; 268 | unsigned int dummy = 0; 269 | unsigned int blockcount = 0; 270 | unsigned int temp; 271 | 272 | // this is for 16 kbyes allocations (quick & fast) 273 | if (size<(0x4000+1)) { 274 | for (counter=1;counter<0x400;counter++) { 275 | if (memsmall[counter]==0) 276 | { 277 | memsmall[counter] = 0xAA; 278 | return (void*)(MemoryManagerStartAddress+counter*0x4000); 279 | } 280 | } 281 | // No free Memory found 282 | return 0; 283 | } 284 | 285 | // this is for 64 kbyte allocations (also quick) 286 | if (size<(0x10000+1)) { 287 | for (counter=1;counter<0x400;counter++) { 288 | if (memcmp(&memsmall[counter],&dummy,4)==0) 289 | { 290 | dummy = 0xB8BADCFE; 291 | memcpy(&memsmall[counter],&dummy,4); 292 | return (void*)(MemoryManagerStartAddress+counter*0x4000); 293 | } 294 | } 295 | // No free Memory found 296 | return 0; 297 | } 298 | 299 | if (size<(5*1024*1024+1)) { 300 | 301 | for (counter=1;counter<0x400;counter++) { 302 | unsigned int needsectory; 303 | unsigned int foundstart; 304 | 305 | temp = (size & 0xffffc000) + 0x4000; 306 | needsectory = temp / 0x4000; 307 | 308 | //printf("Need Sectors %x\n",needsectory); 309 | 310 | foundstart = 1; 311 | for (blockcount=0;blockcountm_plistentryPrevious=plistentryCurrent; 453 | plistentryNew->m_plistentryNext=plistentryCurrent->m_plistentryNext; 454 | plistentryCurrent->m_plistentryNext=plistentryNew; 455 | if(plistentryNew->m_plistentryNext!=NULL) { 456 | plistentryNew->m_plistentryNext->m_plistentryPrevious=plistentryNew; 457 | } 458 | } 459 | 460 | void ListEntryRemove(LIST_ENTRY *plistentryCurrent) 461 | { 462 | if(plistentryCurrent->m_plistentryPrevious) { 463 | plistentryCurrent->m_plistentryPrevious->m_plistentryNext=plistentryCurrent->m_plistentryNext; 464 | } 465 | if(plistentryCurrent->m_plistentryNext) { 466 | plistentryCurrent->m_plistentryNext->m_plistentryPrevious=plistentryCurrent->m_plistentryPrevious; 467 | } 468 | } 469 | #endif -------------------------------------------------------------------------------- /src/lib/misc/vsprintf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * linux/lib/vsprintf.c 3 | * 4 | * Copyright (C) 1991, 1992 Linus Torvalds 5 | */ 6 | 7 | /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */ 8 | /* 9 | * Wirzenius wrote this portably, Torvalds fucked it up :-) 10 | */ 11 | 12 | 13 | #include 14 | // #include 15 | // #include 16 | 17 | /* haha, don't need ctype.c */ 18 | #define isdigit(c) ((c) >= '0' && (c) <= '9') 19 | #define is_digit isdigit 20 | #define isxdigit(c) (((c) >= '0' && (c) <= '9') || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F')) 21 | #define islower(c) ((c) >= 'a' && (c) <= 'z') 22 | #define toupper(c) __toupper(c) 23 | #define ETH_ALEN 6 24 | 25 | static inline unsigned char __toupper(unsigned char c) 26 | { 27 | if (islower(c)) 28 | c -= 'a'-'A'; 29 | return c; 30 | } 31 | 32 | 33 | unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base) 34 | { 35 | unsigned long result = 0,value; 36 | 37 | if (!base) { 38 | base = 10; 39 | if (*cp == '0') { 40 | base = 8; 41 | cp++; 42 | if ((*cp == 'x') && isxdigit(cp[1])) { 43 | cp++; 44 | base = 16; 45 | } 46 | } 47 | } 48 | while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp) 49 | ? toupper(*cp) : *cp)-'A'+10) < base) { 50 | result = result*base + value; 51 | cp++; 52 | } 53 | if (endp) 54 | *endp = (char *)cp; 55 | return result; 56 | } 57 | 58 | long simple_strtol(const char *cp,char **endp,unsigned int base) 59 | { 60 | if(*cp=='-') 61 | return -simple_strtoul(cp+1,endp,base); 62 | return simple_strtoul(cp,endp,base); 63 | } 64 | 65 | 66 | static int skip_atoi(const char **s) 67 | { 68 | int i=0; 69 | 70 | while (is_digit(**s)) 71 | i = i*10 + *((*s)++) - '0'; 72 | return i; 73 | } 74 | 75 | #define ZEROPAD 1 /* pad with zero */ 76 | #define SIGN 2 /* unsigned/signed long */ 77 | #define PLUS 4 /* show plus */ 78 | #define SPACE 8 /* space if plus */ 79 | #define LEFT 16 /* left justified */ 80 | #define SPECIAL 32 /* 0x */ 81 | #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ 82 | 83 | #define do_div(n,base) ({ \ 84 | int __res; \ 85 | __res = ((unsigned long) n) % (unsigned) base; \ 86 | n = ((unsigned long) n) / (unsigned) base; \ 87 | __res; }) 88 | 89 | static char * number(char * str, long num, int base, int size, int precision 90 | ,int type) 91 | { 92 | char c,sign,tmp[66]; 93 | const char *digits="0123456789abcdefghijklmnopqrstuvwxyz"; 94 | int i; 95 | 96 | if (type & LARGE) 97 | digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 98 | if (type & LEFT) 99 | type &= ~ZEROPAD; 100 | if (base < 2 || base > 36) 101 | return 0; 102 | c = (type & ZEROPAD) ? '0' : ' '; 103 | sign = 0; 104 | if (type & SIGN) { 105 | if (num < 0) { 106 | sign = '-'; 107 | num = -num; 108 | size--; 109 | } else if (type & PLUS) { 110 | sign = '+'; 111 | size--; 112 | } else if (type & SPACE) { 113 | sign = ' '; 114 | size--; 115 | } 116 | } 117 | if (type & SPECIAL) { 118 | if (base == 16) 119 | size -= 2; 120 | else if (base == 8) 121 | size--; 122 | } 123 | i = 0; 124 | if (num == 0) 125 | tmp[i++]='0'; 126 | else while (num != 0) 127 | tmp[i++] = digits[do_div(num,base)]; 128 | if (i > precision) 129 | precision = i; 130 | size -= precision; 131 | if (!(type&(ZEROPAD+LEFT))) 132 | while(size-->0) 133 | *str++ = ' '; 134 | if (sign) 135 | *str++ = sign; 136 | if (type & SPECIAL) { 137 | if (base==8) 138 | *str++ = '0'; 139 | else if (base==16) { 140 | *str++ = '0'; 141 | *str++ = digits[33]; 142 | } 143 | } 144 | if (!(type & LEFT)) 145 | while (size-- > 0) 146 | *str++ = c; 147 | while (i < precision--) 148 | *str++ = '0'; 149 | while (i-- > 0) 150 | *str++ = tmp[i]; 151 | while (size-- > 0) 152 | *str++ = ' '; 153 | return str; 154 | } 155 | 156 | /* Forward decl. needed for IP address printing stuff... */ 157 | int sprintf(char * buf, const char *fmt, ...); 158 | 159 | int vsprintf(char *buf, const char *fmt, va_list args) 160 | { 161 | int len; 162 | unsigned long num; 163 | int i, base; 164 | char * str; 165 | const char *s; 166 | 167 | int flags; /* flags to number() */ 168 | 169 | int field_width; /* width of output field */ 170 | int precision; /* min. # of digits for integers; max 171 | number of chars for from string */ 172 | int qualifier; /* 'h', 'l', or 'L' for integer fields */ 173 | 174 | 175 | for (str=buf ; *fmt ; ++fmt) { 176 | if (*fmt != '%') { 177 | *str++ = *fmt; 178 | continue; 179 | } 180 | 181 | /* process flags */ 182 | flags = 0; 183 | repeat: 184 | ++fmt; /* this also skips first '%' */ 185 | switch (*fmt) { 186 | case '-': flags |= LEFT; goto repeat; 187 | case '+': flags |= PLUS; goto repeat; 188 | case ' ': flags |= SPACE; goto repeat; 189 | case '#': flags |= SPECIAL; goto repeat; 190 | case '0': flags |= ZEROPAD; goto repeat; 191 | } 192 | 193 | /* get field width */ 194 | field_width = -1; 195 | if (is_digit(*fmt)) 196 | field_width = skip_atoi(&fmt); 197 | else if (*fmt == '*') { 198 | ++fmt; 199 | /* it's the next argument */ 200 | field_width = va_arg(args, int); 201 | if (field_width < 0) { 202 | field_width = -field_width; 203 | flags |= LEFT; 204 | } 205 | } 206 | 207 | /* get the precision */ 208 | precision = -1; 209 | if (*fmt == '.') { 210 | ++fmt; 211 | if (is_digit(*fmt)) 212 | precision = skip_atoi(&fmt); 213 | else if (*fmt == '*') { 214 | ++fmt; 215 | /* it's the next argument */ 216 | precision = va_arg(args, int); 217 | } 218 | if (precision < 0) 219 | precision = 0; 220 | } 221 | 222 | /* get the conversion qualifier */ 223 | qualifier = -1; 224 | if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') { 225 | qualifier = *fmt; 226 | ++fmt; 227 | } 228 | 229 | 230 | /* default base */ 231 | base = 10; 232 | 233 | switch (*fmt) { 234 | case 'c': 235 | if (!(flags & LEFT)) 236 | while (--field_width > 0) 237 | *str++ = ' '; 238 | *str++ = (unsigned char) va_arg(args, int); 239 | while (--field_width > 0) 240 | *str++ = ' '; 241 | continue; 242 | 243 | case 's': 244 | 245 | s = va_arg(args, char *); 246 | 247 | if (!s) 248 | s = ""; 249 | 250 | // len = strnlen(s, precision); 251 | { len=0; while ((s[len]!='\0') && ((unsigned int)len<(unsigned int)precision)) len++; } 252 | 253 | if (!(flags & LEFT)) 254 | while (len < field_width--) 255 | *str++ = ' '; 256 | for (i = 0; i < len; ++i) 257 | *str++ = *s++; 258 | while (len < field_width--) 259 | *str++ = ' '; 260 | continue; 261 | 262 | case 'p': 263 | if (field_width == -1) { 264 | field_width = 2*sizeof(void *); 265 | flags |= ZEROPAD; 266 | } 267 | str = number(str, 268 | (unsigned long) va_arg(args, void *), 16, 269 | field_width, precision, flags); 270 | continue; 271 | 272 | 273 | case 'n': 274 | if (qualifier == 'l') { 275 | long * ip = va_arg(args, long *); 276 | *ip = (str - buf); 277 | } else { 278 | int * ip = va_arg(args, int *); 279 | *ip = (str - buf); 280 | } 281 | continue; 282 | 283 | case '%': 284 | *str++ = '%'; 285 | continue; 286 | 287 | /* integer number formats - set up the flags and "break" */ 288 | case 'o': 289 | base = 8; 290 | break; 291 | 292 | case 'X': 293 | flags |= LARGE; 294 | case 'x': 295 | base = 16; 296 | break; 297 | 298 | case 'd': 299 | case 'i': 300 | flags |= SIGN; 301 | case 'u': 302 | break; 303 | case '@': 304 | { 305 | unsigned char *r; 306 | union { 307 | unsigned long l; 308 | unsigned char c[4]; 309 | } u; 310 | u.l = va_arg(args, unsigned long); 311 | for (r = &u.c[0]; r < &u.c[4]; ++r) 312 | str += sprintf(str, "%d.", *r); 313 | --str; 314 | continue; 315 | } 316 | case '!': 317 | { 318 | unsigned char *r; 319 | unsigned char *p = va_arg(args, unsigned char *); 320 | for (r = p + ETH_ALEN; p < r; ++p) 321 | str += sprintf(str, "%02hX:", *p); 322 | --str; 323 | continue; 324 | } 325 | default: 326 | 327 | *str++ = '%'; 328 | if (*fmt) 329 | *str++ = *fmt; 330 | else 331 | --fmt; 332 | continue; 333 | } 334 | 335 | if (qualifier == 'l') 336 | num = va_arg(args, unsigned long); 337 | else if (qualifier == 'h') { 338 | num = (unsigned short) va_arg(args, int); 339 | if (flags & SIGN) 340 | num = (short) num; 341 | } else if (flags & SIGN) 342 | num = va_arg(args, int); 343 | else 344 | num = va_arg(args, unsigned int); 345 | str = number(str, num, base, field_width, precision, flags); 346 | } 347 | *str = '\0'; 348 | return str-buf; 349 | } 350 | 351 | int sprintf(char * buf, const char *fmt, ...) 352 | { 353 | va_list args; 354 | int i; 355 | 356 | va_start(args, fmt); 357 | i=vsprintf(buf,fmt,args); 358 | va_end(args); 359 | return i; 360 | } 361 | -------------------------------------------------------------------------------- /src/lib/xbe/xbe.c: -------------------------------------------------------------------------------- 1 | #include "xbe.h" 2 | 3 | // Kernel Import Table 4 | //----------------------------------------------------------------------------- 5 | 6 | 7 | #include "xdecl.h" 8 | 9 | void *m_import_addrs[400] = { 10 | #define KERNEL_IMPORT_NULL(i) [i] = 0, 11 | #define KERNEL_IMPORT_FUNC(i, n) [i] = &n, 12 | #define KERNEL_IMPORT_DATA(i, n) [i] = (void*)(0xfed0c030+i), // FIXME 13 | #include "ximports.h" 14 | KERNEL_IMPORTS 15 | #undef KERNEL_IMPORT_NULL 16 | #undef KERNEL_IMPORT_FUNC 17 | #undef KERNEL_IMPORT_DATA 18 | }; 19 | 20 | uint32_t xbe_unscramble(uint32_t addr, uint32_t debug, uint32_t retail) 21 | { 22 | uint32_t addr_out; 23 | 24 | #define XBOX_RAM_SIZE (64*0x100000) 25 | 26 | addr_out = addr ^ retail; 27 | if (addr_out < XBOX_RAM_SIZE) { 28 | return addr_out; 29 | } 30 | 31 | return addr ^ debug; 32 | } 33 | 34 | void xbe_patch_imports(XBE_HEADER *hdr) 35 | { 36 | // Patch Kernel Imports 37 | volatile uint32_t *imports = (volatile uint32_t*)xbe_unscramble(hdr->KernelThunkTable, XOR_KT_DEBUG, XOR_KT_RETAIL); 38 | for (int i = 0; imports[i] != 0; i++) { 39 | uint32_t import_num = imports[i] - 0x80000000; 40 | // assert(import_num < 379); 41 | imports[i] = (uint32_t)m_import_addrs[import_num]; 42 | } 43 | } 44 | 45 | #include "boot.h" 46 | 47 | XBE_HEADER *load_xbe(char *xbe_data) 48 | { 49 | XBE_HEADER *header = (XBE_HEADER *)xbe_data; 50 | 51 | if (strncmp((char*)header->Magic, "XBEH", 4) != 0) { 52 | printf("Invalid Magic!\n"); 53 | while (1); 54 | } 55 | 56 | printf("Base Address: %x\n", header->BaseAddress); 57 | 58 | XBE_SECTION *sections = (XBE_SECTION *)(xbe_data + header->Sections - header->BaseAddress); 59 | 60 | // Copy header data 61 | PVOID BaseAddress = (PVOID)header->BaseAddress; 62 | SIZE_T RegionSize = header->HeaderSize; 63 | printf("HeaderSize = %x\n", RegionSize); 64 | 65 | NtAllocateVirtualMemory(&BaseAddress, 0, &RegionSize, 0, 0); 66 | // FIXME: Leak, check return status (we assert now) 67 | memcpy((void*)(header->BaseAddress), xbe_data, header->HeaderSize); 68 | 69 | // Copy section data 70 | int i; 71 | for (i = 0; i < header->NumSections; i++) { 72 | XBE_SECTION *s = §ions[i]; 73 | printf("[Section %d] %s\n", i, &xbe_data[s->SectionName-header->BaseAddress]); 74 | 75 | printf("\tVirtualAddress = %08x\n", s->VirtualAddress); 76 | printf("\tVirtualSize = %08x\n", s->VirtualSize); 77 | printf("\tFileAddress = %08x\n", s->FileAddress); 78 | printf("\tFileSize = %08x\n", s->FileSize); 79 | 80 | BaseAddress = (void*)s->VirtualAddress; 81 | RegionSize = s->VirtualSize; 82 | NtAllocateVirtualMemory(&BaseAddress, 0, &RegionSize, 0, 0); 83 | // FIXME: Leak, check return status (we assert now) 84 | printf("Copying %x bytes from %x to %x\n", s->FileSize, &xbe_data[s->FileAddress], (void*)(s->VirtualAddress)); 85 | memcpy((void*)(s->VirtualAddress), &xbe_data[s->FileAddress], s->FileSize); 86 | memset((void*)(s->VirtualAddress+s->FileSize), 0, s->VirtualSize-s->FileSize); 87 | 88 | printf("\tLoaded\n"); 89 | } 90 | 91 | xbe_patch_imports(header); 92 | return (XBE_HEADER *)header->BaseAddress; 93 | } 94 | 95 | void *get_xbe_entry(XBE_HEADER *hdr) 96 | { 97 | return (void*)xbe_unscramble(hdr->EntryPoint, XOR_EP_DEBUG, XOR_EP_RETAIL); 98 | } 99 | -------------------------------------------------------------------------------- /src/lib/xbe/xbe.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * * 3 | * This program is free software; you can redistribute it and/or modify * 4 | * it under the terms of the GNU General Public License as published by * 5 | * the Free Software Foundation; either version 2 of the License, or * 6 | * (at your option) any later version. * 7 | * * 8 | ***************************************************************************/ 9 | 10 | #include 11 | 12 | #ifndef XBE_H 13 | #define XBE_H 14 | 15 | // XBE header information 16 | typedef struct _XBE_HEADER { 17 | uint8_t Magic[4]; // 000 "XBEH" 18 | uint8_t HeaderSignature[256]; // 004 RSA digital signature of the entire header area 19 | uint32_t BaseAddress; // 104 Base address of XBE image (must be 0x00010000?) 20 | uint32_t HeaderSize; // 108 Size of all headers combined - other headers must be within this 21 | uint32_t ImageSize; // 10C Size of entire image 22 | uint32_t XbeHeaderSize; // 110 Size of this header (always 0x178?) 23 | uint32_t Timestamp; // 114 Image timestamp - unknown format 24 | uint32_t Certificate; // 118 Pointer to certificate data (must be within HeaderSize) 25 | int32_t NumSections; // 11C Number of sections 26 | uint32_t Sections; // 120 Pointer to section headers (must be within HeaderSize) 27 | uint32_t InitFlags; // 124 Initialization flags 28 | uint32_t EntryPoint; // 128 Entry point 29 | uint32_t TlsDirectory; // 12C Pointer to TLS directory 30 | uint32_t StackCommit; // 130 Stack commit size 31 | uint32_t HeapReserve; // 134 Heap reserve size 32 | uint32_t HeapCommit; // 138 Heap commit size 33 | uint32_t PeBaseAddress; // 13C PE base address (?) 34 | uint32_t PeImageSize; // 140 PE image size (?) 35 | uint32_t PeChecksum; // 144 PE checksum (?) 36 | uint32_t PeTimestamp; // 148 PE timestamp (?) 37 | uint32_t PcExePath; // 14C PC path and filename to EXE file from which XBE is derived 38 | uint32_t PcExeFilename; // 150 PC filename (last part of PcExePath) from which XBE is derived 39 | uint32_t PcExeFilenameUnicode; // 154 PC filename (Unicode version of PcExeFilename) 40 | uint32_t KernelThunkTable; // 158 Pointer to kernel thunk table (XOR'd; EFB1F152 debug) 41 | uint32_t DebugImportTable; // 15C Non-kernel import table (debug only) 42 | int32_t NumLibraries; // 160 Number of library headers 43 | uint32_t Libraries; // 164 Pointer to library headers 44 | uint32_t KernelLibrary; // 168 Pointer to kernel library header 45 | uint32_t XapiLibrary; // 16C Pointer to XAPI library 46 | uint32_t LogoBitmap; // 170 Pointer to logo bitmap (NULL = use default of Microsoft) 47 | uint32_t LogoBitmapSize; // 174 Size of logo bitmap 48 | } XBE_HEADER, *PXBE_HEADER; 49 | 50 | // Certificate structure 51 | typedef struct _XBE_CERTIFICATE { 52 | uint32_t Size; // 000 Size of certificate 53 | uint32_t Timestamp; // 004 Certificate timestamp (unknown format) 54 | uint32_t TitleId; // 008 Title ID 55 | int16_t TitleName[40]; // 00C Name of the game (Unicode) 56 | uint32_t AlternateTitleIds[16]; // 05C Alternate title ID's (0-terminated) 57 | uint32_t MediaTypes; // 09C Allowed media types - 1 bit match between XBE and media = boots 58 | uint32_t GameRegion; // 0A0 Allowed game regions - 1 bit match between this and XBOX = boots 59 | uint32_t GameRating; // 0A4 Allowed game ratings - 1 bit match between this and XBOX = boots 60 | uint32_t DiskNumber; // 0A8 Disk number (?) 61 | uint32_t Version; // 0AC Version (?) 62 | uint8_t LanKey[16]; // 0B0 LAN key for this game 63 | uint8_t SignatureKey[16]; // 0C0 Signature key for this game 64 | uint8_t AlternateSignatureKeys[16][16]; // 0D0 Signature keys for the alternate title ID's 65 | // 1D0 66 | } XBE_CERTIFICATE, *PXBE_CERTIFICATE; 67 | 68 | // Section headers 69 | typedef struct _XBE_SECTION { 70 | uint32_t Flags; // 000 Flags 71 | uint32_t VirtualAddress; // 004 Virtual address (where this section loads in RAM) 72 | uint32_t VirtualSize; // 008 Virtual size (size of section in RAM; after FileSize it's 00'd) 73 | uint32_t FileAddress; // 00C File address (where in the file from which this section comes) 74 | uint32_t FileSize; // 010 File size (size of the section in the XBE file) 75 | uint32_t SectionName; // 014 Pointer to section name 76 | int32_t SectionReferenceCount; // 018 Section reference count - when >= 1, section is loaded 77 | uint32_t HeadReferenceCount; // 01C Pointer to head shared page reference count 78 | uint32_t TailReferenceCount; // 020 Pointer to tail shared page reference count 79 | uint8_t ShaHash[20]; // 024 SHA1 hash. Hash int32_t containing FileSize, then hash section. 80 | } XBE_SECTION, *PXBE_SECTION; 81 | 82 | // TLS directory information 83 | typedef struct _XBE_TLS { 84 | int32_t RawStart; // 000 raw data start address 85 | int32_t RawEnd; // 004 raw data end address 86 | int32_t TlsIndex; // 008 TLS index address 87 | int32_t TlsCallbacks; // 00C TLS callbacks address 88 | int32_t SizeZeroFill; // 010 size of zero fill 89 | uint8_t Characteristics[8]; // 014 Characteristics 90 | } XBE_TLS, *PXBE_TLS; 91 | 92 | // Library version data 93 | typedef struct _XBE_LIBRARY { 94 | uint8_t Name[8]; // 000 Library Name 95 | int16_t MajorVersion; // 008 Major Version 96 | int16_t MiddleVersion; // 00A Middle Version 97 | int16_t MinorVersion; // 00C Minor Version 98 | int16_t Flags; // 00E Flags 99 | } XBE_LIBRARY, *PXBELIBRARY; 100 | 101 | // Initialization flags 102 | #define XBE_INIT_MOUNT_UTILITY 0x00000001 103 | #define XBE_INIT_FORMAT_UTILITY 0x00000002 104 | #define XBE_INIT_64M_RAM_ONLY 0x00000004 105 | #define XBE_INIT_DONT_SETUP_HDD 0x00000008 106 | 107 | // Region codes 108 | #define XBE_REGION_US_CANADA 0x00000001 109 | #define XBE_REGION_JAPAN 0x00000002 110 | #define XBE_REGION_ELSEWHERE 0x00000004 111 | #define XBE_REGION_DEBUG 0x80000000 112 | 113 | // Media types 114 | #define XBE_MEDIA_HDD 0x00000001 115 | #define XBE_MEDIA_XBOX_DVD 0x00000002 116 | #define XBE_MEDIA_ANY_CD_OR_DVD 0x00000004 117 | #define XBE_MEDIA_CD 0x00000008 118 | #define XBE_MEDIA_1LAYER_DVDROM 0x00000010 119 | #define XBE_MEDIA_2LAYER_DVDROM 0x00000020 120 | #define XBE_MEDIA_1LAYER_DVDR 0x00000040 121 | #define XBE_MEDIA_2LAYER_DVDR 0x00000080 122 | #define XBE_MEDIA_USB 0x00000100 123 | #define XBE_MEDIA_ALLOW_UNLOCKED_HDD 0x40000000 124 | 125 | // Section flags 126 | #define XBE_SEC_WRITABLE 0x00000001 127 | #define XBE_SEC_PRELOAD 0x00000002 128 | #define XBE_SEC_EXECUTABLE 0x00000004 129 | #define XBE_SEC_INSERTED_FILE 0x00000008 130 | #define XBE_SEC_RO_HEAD_PAGE 0x00000010 131 | #define XBE_SEC_RO_TAIL_PAGE 0x00000020 132 | 133 | // XOR keys 134 | #define XOR_EP_DEBUG 0x94859D4B // Entry Point (Debug) 135 | #define XOR_EP_RETAIL 0xA8FC57AB // Entry Point (Retail) 136 | #define XOR_KT_DEBUG 0xEFB1F152 // Kernel Thunk (Debug) 137 | #define XOR_KT_RETAIL 0x5B6D40B6 // Kernel Thunk (Retail) 138 | 139 | uint32_t xbe_unscramble(uint32_t addr, uint32_t debug, uint32_t retail); 140 | void xbe_patch_imports(XBE_HEADER *hdr); 141 | XBE_HEADER *load_xbe(char *xbe_data); 142 | void *get_xbe_entry(XBE_HEADER *hdr); 143 | 144 | extern void *m_import_addrs[400]; 145 | 146 | #endif 147 | -------------------------------------------------------------------------------- /src/mm/paging.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Matt Borgerson 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | */ 18 | 19 | #include "boot.h" 20 | #include "memory_layout.h" // FIXME: Factor this out 21 | 22 | #include 23 | #include 24 | #include 25 | // #include 26 | #include "list.h" 27 | 28 | #define DEBUG_PAGING 0 29 | #if DEBUG_PAGING 30 | #define DPRINTK printk 31 | #else 32 | #define DPRINTK(...) do {} while(0) 33 | #endif 34 | 35 | typedef uint32_t hwaddr; 36 | 37 | #define PDE_P (1<<0) // Present 38 | #define PDE_RW (1<<1) // Read/Write 39 | #define PDE_U (1<<2) // User/Supervisor 40 | #define PDE_W (1<<3) // Write Through 41 | #define PDE_D (1<<4) // Cache Disabled 42 | #define PDE_A (1<<5) // Accessed 43 | #define PDE_S (1<<7) // Size 44 | 45 | #define PTE_P (1<<0) // Present 46 | #define PTE_RW (1<<1) // Read/Write 47 | #define PTE_U (1<<2) // User/Supervisor 48 | #define PTE_W (1<<3) // Write Through 49 | #define PTE_C (1<<4) // Cache Disabled 50 | #define PTE_A (1<<5) // Accessed 51 | #define PTE_D (1<<6) // Dirty 52 | #define PTE_G (1<<8) // Global 53 | 54 | #define PAGE_BITS 12 55 | #define PAGE_SIZE (1<> 22) // One 32b PDE covers 4 MiB 58 | #define addr_to_pfn(x) ((x) >> PAGE_BITS) // One 32b PTE covers 4 KiB 59 | 60 | extern unsigned char PDB[]; 61 | extern int32_t page_tables[]; 62 | 63 | // Statically allocated kernel memory 64 | extern char KRESERVED_START[]; 65 | extern char KRESERVED_SIZE[]; 66 | 67 | static inline void *phys_to_virt(void *phys) 68 | { 69 | return (void*)((uint32_t)phys | 0x80000000); 70 | } 71 | 72 | static inline void *virt_to_phys(void *virt) 73 | { 74 | return (void*)((uint32_t)virt & 0x7fffffff); 75 | } 76 | 77 | /* 78 | * Early initialization of page tables. 79 | * 80 | * Called pretty early from assembly code (start.nasm) to set up the address 81 | * space. Keep in mind that this runs out of physical memory (kernel data 82 | * and BSS not initialized yet)! 83 | */ 84 | void early_paging_init() 85 | { 86 | volatile unsigned int *pde = (unsigned int *)PDB; 87 | unsigned int i, addr; 88 | 89 | // Zero out PDE 90 | for (i = 0; i < 1024; i++) { 91 | pde[i] = 0; 92 | } 93 | 94 | // Map 128M of virtual address space page tables into PD 95 | for (i=0; i < 128/4; i++) { 96 | // One 4 KiB page covers 4 MiB of addresses 97 | addr = (uint32_t)virt_to_phys(page_tables) + (i << PAGE_BITS); 98 | pde[i] = addr | PDE_P | PDE_RW | PDE_U | PDE_A; 99 | } 100 | 101 | // Map 128M of physical RAM at 0x800000000 102 | for (i=0; i < 128/4; i++) { 103 | addr = 0x80000000 + (i << 22); 104 | pde[addr_to_pdn(addr)] = (i << 22) | PDE_P | PDE_RW | PDE_U | PDE_S; 105 | } 106 | 107 | // Not sure about c0XXXXXX 108 | // c0000000 -> be000 109 | // c010XXXX -> 3ffXXX 110 | // c0300000 -> f000 111 | // c03c0000 -> f0000000 112 | // c03c1000 -> f0400000 113 | // c03c2000 -> f0800000 114 | // ... 115 | // Not sure about d00XXXXX (maps to low mem) 116 | 117 | // -> jfr: 0xC0000000 is the block used for MmIoMapSpace etc - so various 118 | // mappings to hardware. and 0xD0000000 is the block used for kernel pools 119 | // iirc [ExAllocatePool] 120 | 121 | // Identity map MMIO 122 | // mem at 0xf0000000 [0xf3ffffff] // (nv2a, bar 1) 123 | // mem at 0xfd000000 [0xfdffffff] // (nv2a, bar 0) 124 | // mem at 0xfe800000 [0xfe87ffff] // (apu, bar 0) 125 | // mem at 0xfec00000 [0xfec00fff] // (aci, bar 2) 126 | // mem at 0xfed00000 [0xfed000ff] // (ohci, bar 0) 127 | // mem at 0xfed08000 [0xfed080ff] // (ohci, bar 0) 128 | // mem at 0xfef00000 [0xfef003ff] // (nvnet, bar 0) 129 | 130 | // GPU MEM [0xf0000000, 0xf8000000) 131 | for (i=0; i < 128/4; i++) { 132 | addr = 0xf0000000 + (i << 22); 133 | pde[addr_to_pdn(addr)] = addr | PDE_P | PDE_RW | PDE_U | PDE_S; // Should be write-combine 134 | } 135 | 136 | // Other MMIO [0xf8000000, 0xffffffff] 137 | for (i=0; i < 128/4; i++) { 138 | addr = 0xf8000000 + (i << 22); 139 | pde[addr_to_pdn(addr)] = addr | PDE_P | PDE_RW | PDE_U | PDE_D | PDE_S; 140 | } 141 | } 142 | 143 | //////////////////////////////////////////////////////////////////////////////// 144 | // Dumb first-fit page allocator to keep track of contiguous page allocations 145 | // in an arena. This should probably just be replaced with a buddy allocator. 146 | 147 | struct mem_arena { 148 | hwaddr min, max; 149 | struct list_head h; 150 | }; 151 | 152 | struct mem_alloc { 153 | struct list_head h; 154 | hwaddr addr; 155 | size_t len; 156 | }; 157 | 158 | // Given obj x, return internal list_head* 159 | #define LHEAD(x) (&((x)->h)) 160 | 161 | hwaddr alloc_pages(struct mem_arena *arena, size_t num_pages, size_t alignment); 162 | int reserve_pages(struct mem_arena *arena, hwaddr addr, size_t num_pages); 163 | void free_pages(struct mem_arena *arena, hwaddr addr); 164 | 165 | /* 166 | * Find available block of contiguous pages in arena 167 | */ 168 | hwaddr alloc_pages(struct mem_arena *arena, size_t num_bytes, size_t alignment) 169 | { 170 | struct mem_alloc *cur, *after = NULL; 171 | ssize_t gap; 172 | 173 | if (alignment == 0) { 174 | alignment = PAGE_SIZE; 175 | } 176 | 177 | num_bytes = align_up(num_bytes, PAGE_SIZE); 178 | hwaddr limit_l = align_up(arena->min, alignment); 179 | hwaddr limit_u = arena->max; 180 | 181 | // List is sorted. Step through each node, compare space between it and last 182 | list_for_each_entry(cur, &arena->h, h) { 183 | gap = cur->addr - limit_l; 184 | 185 | // Check gap. Note: cast here as compiler would otherwise cast 186 | // `gap` to unsigned and not handle negatives correctly! 187 | if (gap >= (ssize_t)num_bytes) { 188 | // Found first fit! 189 | limit_u = cur->addr; 190 | break; 191 | } 192 | 193 | limit_l = cur->addr + ((cur->len + 1) << PAGE_BITS); 194 | limit_l = align_up(limit_l, alignment); 195 | after = cur; 196 | } 197 | 198 | // Check bounds 199 | if ((limit_l + num_bytes) > limit_u) { 200 | return 0; 201 | } 202 | 203 | struct mem_alloc *new = malloc(sizeof(struct mem_alloc)); 204 | new->addr = limit_l; 205 | new->len = (num_bytes >> PAGE_BITS) - 1; 206 | list_add(LHEAD(new), (after != NULL) ? LHEAD(after) : &arena->h); 207 | return new->addr; 208 | } 209 | 210 | /* 211 | * Reserve a range of addresses in the arena 212 | */ 213 | int reserve_pages(struct mem_arena *arena, hwaddr addr, size_t num_bytes) 214 | { 215 | struct mem_alloc *cur, *after = NULL; 216 | hwaddr limit_l = arena->min; 217 | hwaddr limit_u = arena->max; 218 | 219 | num_bytes = align_up(num_bytes, PAGE_SIZE); 220 | 221 | // List is sorted. Find left-most, non-overlapping block 222 | list_for_each_entry(cur, &arena->h, h) { 223 | if (cur->addr > addr) { 224 | limit_u = cur->addr; 225 | break; 226 | } 227 | limit_l = cur->addr + ((cur->len + 1) << PAGE_BITS); 228 | after = cur; 229 | } 230 | 231 | // Check bounds 232 | if ((addr < limit_l) || ((addr + num_bytes) > limit_u)) { 233 | return -1; 234 | } 235 | 236 | struct mem_alloc *new = malloc(sizeof(struct mem_alloc)); 237 | new->addr = addr; 238 | new->len = (num_bytes >> PAGE_BITS) - 1; 239 | list_add(LHEAD(new), (after != NULL) ? LHEAD(after) : &arena->h); 240 | 241 | return 0; 242 | } 243 | 244 | /* 245 | * Free an allocation 246 | */ 247 | void free_pages(struct mem_arena *arena, hwaddr addr) 248 | { 249 | struct mem_alloc *cur; 250 | 251 | list_for_each_entry(cur, &arena->h, h) { 252 | if (cur->addr == addr) { 253 | list_del(LHEAD(cur)); 254 | free(cur); 255 | return; 256 | } 257 | } 258 | 259 | assert(0); // bad addr! 260 | } 261 | 262 | /* 263 | * Print all allocations in the arena 264 | */ 265 | void print_allocations(struct mem_arena *arena) 266 | { 267 | struct mem_alloc *cur; 268 | list_for_each_entry(cur, &arena->h, h) { 269 | hwaddr cur_end = cur->addr + ((cur->len + 1) << PAGE_BITS); 270 | printf("[%08x, %08x)\n", cur->addr, cur_end); 271 | } 272 | } 273 | 274 | //////////////////////////////////////////////////////////////////////////////// 275 | 276 | #include 277 | 278 | typedef void *mspace; 279 | static mspace kheap; 280 | 281 | mspace create_mspace_with_base(void *base, size_t capacity, int locked); 282 | void *mspace_malloc(mspace msp, size_t bytes); 283 | void mspace_free(mspace msp, void *mem); 284 | 285 | struct mem_arena phys_arena; // Keeps track of physical memory 286 | struct mem_arena virt_arena; // Keeps track of virtual memory (0-128MiB addrs) 287 | 288 | 289 | void MemoryManagementInitialization(void * pvStartAddress, u32 dwTotalMemoryAllocLength) 290 | { 291 | // Initialize statically-allocated heap 292 | // FIXME: should grow on-demand, but malloc depends on the page allocator, which depends on malloc 293 | kheap = create_mspace_with_base(pvStartAddress, dwTotalMemoryAllocLength, 0); 294 | 295 | xbox_ram = 128; // FIXME: Not set yet, must set it ourselves for now 296 | 297 | // Set up page allocator 298 | INIT_LIST_HEAD(&phys_arena.h); 299 | phys_arena.min = 0; 300 | phys_arena.max = xbox_ram * 1024 * 1024; 301 | 302 | INIT_LIST_HEAD(&virt_arena.h); 303 | virt_arena.min = 0; 304 | virt_arena.max = 128 * 1024 * 1024; 305 | 306 | // Reserve 0-0x10000 307 | reserve_pages(&phys_arena, 0, 0x10000); 308 | reserve_pages(&virt_arena, 0, 0x10000); 309 | 310 | // Reserve pre-allocated kernel pages (.data/.bss) 311 | reserve_pages(&phys_arena, (hwaddr)virt_to_phys(KRESERVED_START), (size_t)KRESERVED_SIZE); 312 | 313 | // Reserve framebuffer area 314 | reserve_pages(&phys_arena, phys_arena.max - FB_SIZE, FB_SIZE); 315 | 316 | // TEMP: Reserve 1 MiB range at 0x10000 where XBE is loaded 317 | reserve_pages(&phys_arena, 0x10000, 0x100000); 318 | 319 | #if DEBUG_PAGING 320 | printk("Early MMAP:\n"); 321 | print_allocations(&phys_arena); 322 | #endif 323 | 324 | // Identity map the PD 325 | uint32_t addr; 326 | addr = (uint32_t)PDB; 327 | page_tables[addr_to_pfn(addr)] = addr | PTE_P | PTE_RW | PTE_U | PTE_A; 328 | } 329 | 330 | //////////////////////////////////////////////////////////////////////////////// 331 | // Pool allocation helpers 332 | 333 | void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) 334 | { 335 | printk("mmap(%x, %x, %x, %x, %x, %x)\n", 336 | addr, length, prot, flags, fd, offset); 337 | printk("mmap page allocator not ready yet!\n"); 338 | abort(); 339 | return NULL; 340 | } 341 | 342 | int munmap(void *addr, size_t length) 343 | { 344 | printk("munmap(%x, %x)\n", addr, length); 345 | return 0; 346 | } 347 | 348 | void *malloc(size_t bytes) 349 | { 350 | return mspace_malloc(kheap, bytes); 351 | } 352 | 353 | void free(void *ptr) 354 | { 355 | mspace_free(kheap, ptr); 356 | } 357 | 358 | //////////////////////////////////////////////////////////////////////////////// 359 | // Finally, our contiguous and virtual memory allocation 360 | 361 | #include "xdecl.h" 362 | 363 | /** 364 | * MmAllocateContiguousMemoryEx 365 | */ 366 | XBAPI PVOID NTAPI 367 | MmAllocateContiguousMemoryEx( 368 | SIZE_T NumberOfBytes, 369 | ULONG_PTR LowestAcceptableAddress, 370 | ULONG_PTR HighestAcceptableAddress, 371 | ULONG_PTR Alignment, 372 | ULONG Protect 373 | ) 374 | { 375 | DPRINTK("MmAllocateContiguousMemoryEx(%x, %x, %x, %x, %x) = ", 376 | NumberOfBytes, 377 | LowestAcceptableAddress, 378 | HighestAcceptableAddress, 379 | Alignment, 380 | Protect); 381 | void *xbe_mem = (void*)alloc_pages(&phys_arena, NumberOfBytes, Alignment); 382 | assert(xbe_mem != NULL); 383 | xbe_mem = phys_to_virt(xbe_mem); 384 | DPRINTK("%x\n", xbe_mem); 385 | return (PVOID)xbe_mem; 386 | } 387 | 388 | /** 389 | * NtAllocateVirtualMemory 390 | */ 391 | XBAPI NTSTATUS NTAPI 392 | NtAllocateVirtualMemory( 393 | PPVOID BaseAddress, 394 | ULONG_PTR ZeroBits, 395 | PSIZE_T RegionSize, 396 | ULONG AllocationType, 397 | ULONG Protect 398 | ) 399 | { 400 | DPRINTK("NtAllocateVirtualMemory(%x, %x, %x, %x, %x)\n", 401 | BaseAddress, 402 | ZeroBits, 403 | RegionSize, 404 | AllocationType, 405 | Protect); 406 | 407 | assert(BaseAddress != NULL); 408 | assert(ZeroBits == 0); // FIXME: if (ZeroBits < 32) { # high order zero bits } else { bitmask } 409 | assert(RegionSize != NULL); 410 | 411 | // Let's first try to allocate some memory from physical address space 412 | // FIXME: allocating contiguously here for now, should support getting 413 | // smaller chunks too... 414 | size_t num_bytes = align_up(*RegionSize, PAGE_SIZE); 415 | uint32_t phys_mem = alloc_pages(&phys_arena, num_bytes, 0 /* FIXME */); 416 | assert(phys_mem != 0); 417 | 418 | hwaddr virt_mem = (hwaddr)*BaseAddress; 419 | DPRINTK(" *BaseAddress = %x\n", virt_mem); 420 | 421 | if (virt_mem == 0) { 422 | // Try to allocate from virtual memory 423 | virt_mem = alloc_pages(&virt_arena, num_bytes, 0 /* FIXME */); 424 | assert(virt_mem != 0); 425 | } else { 426 | // Specific address requested, try to reserve it 427 | int status = reserve_pages(&virt_arena, virt_mem, num_bytes); 428 | assert(status == 0); 429 | } 430 | 431 | // Now map the virtual memory to physical memory 432 | unsigned int i; 433 | for (i=0; i < (num_bytes >> PAGE_BITS); i++) { 434 | hwaddr vaddr = virt_mem + (i << PAGE_BITS); 435 | hwaddr paddr = phys_mem + (i << PAGE_BITS); 436 | DPRINTK(" %x -> %x\n", vaddr, paddr); 437 | page_tables[addr_to_pfn(vaddr)] = paddr | PTE_P | PTE_RW | PTE_U | PTE_A; 438 | asm volatile ("invlpg (%%eax);" : : "a" (vaddr)); // Update TLB 439 | } 440 | 441 | *BaseAddress = (void*)virt_mem; 442 | *RegionSize = num_bytes; 443 | return STATUS_SUCCESS; 444 | } 445 | 446 | /** 447 | * NtFreeVirtualMemory 448 | */ 449 | XBAPI NTSTATUS NTAPI 450 | NtFreeVirtualMemory( 451 | PPVOID BaseAddress, 452 | PSIZE_T RegionSize, 453 | ULONG FreeType 454 | ) 455 | { 456 | assert(0); 457 | } 458 | -------------------------------------------------------------------------------- /src/printk.c: -------------------------------------------------------------------------------- 1 | #include "boot.h" 2 | 3 | int putchar(int c); 4 | int serial_putchar(int c); 5 | int console_putchar(int c); 6 | 7 | int printk(const char *szFormat, ...) { // printk displays to video 8 | char szBuffer[512*2]; 9 | u16 wLength=0; 10 | va_list argList; 11 | va_start(argList, szFormat); 12 | wLength=(u16) vsprintf(szBuffer, szFormat, argList); 13 | va_end(argList); 14 | 15 | szBuffer[sizeof(szBuffer)-1]=0; 16 | if (wLength>(sizeof(szBuffer)-1)) wLength = sizeof(szBuffer)-1; 17 | szBuffer[wLength]='\0'; 18 | 19 | // BootVideoChunkedPrint(szBuffer); 20 | 21 | char *p = szBuffer; 22 | for (; *p; p++) putchar(*p); 23 | 24 | return wLength; 25 | } 26 | 27 | int putchar(int c) 28 | { 29 | return serial_putchar(c); 30 | // return console_putchar(c); 31 | } 32 | -------------------------------------------------------------------------------- /src/rom.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Matt Borgerson 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | */ 18 | 19 | ENTRY(start_16) 20 | 21 | MEMORY 22 | { 23 | ROM (RX) : ORIGIN = (4096M-1M), LENGTH = 1M, 24 | PRAM (RW) : ORIGIN = 0, LENGTH = 128M, 25 | RAM (RW) : ORIGIN = 0x80000000, LENGTH = 128M, 26 | KRAM (RW) : ORIGIN = 0x80010000, LENGTH = 12K + 16K + 128K 27 | } 28 | 29 | EARLY_STACK_END = 0x100000; 30 | PDB = 0xf000; 31 | 32 | ROM_BASE = ORIGIN(ROM); 33 | ROM_SIZE = LENGTH(ROM); 34 | ROM_END = ROM_BASE + ROM_SIZE; 35 | 36 | RESET_VECTOR_BLOCK_SIZE = 64; 37 | RESET_VECTOR_BLOCK_BASE = ROM_END - RESET_VECTOR_BLOCK_SIZE; 38 | 39 | SECTIONS 40 | { 41 | .text : { 42 | *(.text*) 43 | } >ROM = 0xff 44 | 45 | .rodata : { 46 | . = ALIGN(4); 47 | *(.rodata*) 48 | } >ROM = 0xff 49 | 50 | .data : { 51 | . = ALIGN(4K); 52 | KRESERVED_START = .; 53 | DATA_BASE = .; 54 | 55 | *(.data*) 56 | 57 | BYTE(0xFF) 58 | . = ALIGN(0x10); 59 | 60 | DATA_END = .; 61 | } >KRAM AT>ROM = 0x00 62 | 63 | .bss (NOLOAD) : { 64 | . = ALIGN(4K); 65 | 66 | page_tables = .; 67 | . += 128K; 68 | 69 | HEAP_BASE = .; 70 | . += 16K; 71 | HEAP_END = .; 72 | 73 | BSS_BASE = .; 74 | *(.bss COMMON) 75 | BSS_END = .; 76 | } >KRAM 77 | 78 | .stack (NOLOAD) : { 79 | . = ALIGN(4K); 80 | STACK_BASE = .; 81 | . += 4K; 82 | STACK_END = .; 83 | 84 | KRESERVED_END = .; 85 | } >KRAM 86 | 87 | .fill : { 88 | FREE_ROM_BASE = .; 89 | . = ORIGIN(ROM) + LENGTH(ROM) - RESET_VECTOR_BLOCK_SIZE - 1; 90 | BYTE(0xff); 91 | FREE_ROM_END = .; 92 | } >ROM = 0xff 93 | 94 | .reset_vector (RESET_VECTOR_BLOCK_BASE) : { 95 | *(.reset_vector*) 96 | } >ROM = 0xff 97 | 98 | /DISCARD/ : { 99 | *(.comment) 100 | *(.note.GNU-stack) 101 | *(.eh_frame) 102 | *(.rela.eh_frame) 103 | *(.shstrtab) 104 | *(.symtab) 105 | *(.strtab) 106 | *(.got.plt) 107 | } 108 | } 109 | 110 | DATA_LOAD = LOADADDR(.data); 111 | DATA_SIZE = DATA_END - DATA_BASE; 112 | DATA_SIZE_L = DATA_SIZE / 4; 113 | 114 | BSS_SIZE = BSS_END - BSS_BASE; 115 | BSS_SIZE_L = BSS_SIZE / 4; 116 | 117 | HEAP_SIZE = HEAP_END - HEAP_BASE; 118 | 119 | STACK_SIZE = STACK_END - STACK_BASE; 120 | FREE_ROM_SIZE = FREE_ROM_END - FREE_ROM_BASE; 121 | 122 | 123 | KRESERVED_SIZE = KRESERVED_END - KRESERVED_START; 124 | -------------------------------------------------------------------------------- /src/rtl/mem.c: -------------------------------------------------------------------------------- 1 | #include "boot.h" // FIXME 2 | #include "xdecl.h" 3 | 4 | 5 | /** 6 | * RtlFillMemory 7 | */ 8 | XBAPI VOID NTAPI 9 | RtlFillMemory( 10 | PVOID Destination, 11 | ULONG Length, 12 | UCHAR Fill 13 | ) 14 | { 15 | memset(Destination, Fill, Length); 16 | } 17 | 18 | /** 19 | * RtlMoveMemory 20 | */ 21 | XBAPI VOID NTAPI 22 | RtlMoveMemory( 23 | PVOID Destination, 24 | CONST PVOID Source, 25 | ULONG Length 26 | ) 27 | { 28 | memmove(Destination, Source, Length); 29 | } 30 | -------------------------------------------------------------------------------- /src/start.nasm: -------------------------------------------------------------------------------- 1 | ; 2 | ; Copyright (C) 2018 Matt Borgerson 3 | ; 4 | ; This program is free software; you can redistribute it and/or modify 5 | ; it under the terms of the GNU General Public License as published by 6 | ; the Free Software Foundation; either version 2 of the License, or 7 | ; (at your option) any later version. 8 | ; 9 | ; This program is distributed in the hope that it will be useful, 10 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ; GNU General Public License for more details. 13 | ; 14 | ; You should have received a copy of the GNU General Public License along 15 | ; with this program; if not, write to the Free Software Foundation, Inc., 16 | ; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | ; 18 | 19 | global start_16 20 | extern PDB 21 | extern EARLY_STACK_END 22 | extern STACK_END 23 | extern BSS_SIZE_L 24 | extern BSS_BASE 25 | extern DATA_SIZE_L 26 | extern DATA_BASE 27 | extern DATA_LOAD 28 | 29 | extern early_paging_init 30 | extern init 31 | 32 | %macro WR_MSR 3 ; addr, hi, lo 33 | mov ecx, %1 34 | mov edx, %2 35 | mov eax, %3 36 | wrmsr 37 | %endmacro 38 | 39 | ; 40 | ; 41 | ; Protected Mode Entry - Early system init before jumping to C code 42 | ; 43 | ; 44 | 45 | section .text 46 | bits 32 47 | 48 | start_32: 49 | ; Setup Segment Selectors 50 | xor eax, eax 51 | mov al, GDT_DATA_SEL 52 | mov ds, eax 53 | mov ss, eax 54 | mov es, eax 55 | xor eax, eax 56 | mov fs, eax 57 | mov gs, eax 58 | 59 | ; 60 | ; Initialize MTRRs 61 | ; 62 | 63 | WR_MSR 0x2ff, 0, 0 64 | 65 | ; 0 +128M WB (RAM) 66 | WR_MSR 0x200, 0x00000000, 0x00000006 ; Base 67 | WR_MSR 0x201, 0x0000000f, 0xf8000800 ; Mask 68 | 69 | ; 0xf0000000 +128M WC (VRAM) 70 | WR_MSR 0x202, 0x00000000, 0xf0000001 ; Base 71 | WR_MSR 0x203, 0x0000000f, 0xf8000800 ; Mask 72 | 73 | ; 0xfff00000 +1M WP (Flash) 74 | WR_MSR 0x204, 0x00000000, 0xfff00005 ; Base 75 | WR_MSR 0x205, 0x0000000f, 0xfff00800 ; Mask 76 | 77 | ; Clear other MTTRs 78 | xor eax, eax 79 | xor edx, edx 80 | mov ecx, 0x206 81 | .clear: 82 | wrmsr 83 | inc cl 84 | cmp cl, 0x0f 85 | jbe .clear 86 | 87 | ; Enable MTRRs 88 | WR_MSR 0x2ff, 0x00000000, 0x00000800 89 | 90 | ; Enable Caching 91 | mov eax, cr0 92 | and eax,0x9fffffff 93 | mov cr0, eax 94 | 95 | ; 96 | ; Initialize Page Tables 97 | ; 98 | 99 | mov esp, EARLY_STACK_END 100 | call early_paging_init 101 | 102 | mov eax, PDB ; Load Page Directory 103 | mov cr3, eax 104 | 105 | mov eax, cr4 ; Enable PSE (4 MiB pages) 106 | or eax, 0x10 107 | mov cr4, eax 108 | 109 | mov eax, cr0 ; Enable Paging 110 | or eax, 0x80000000 111 | mov cr0, eax 112 | 113 | ; Setup stack 114 | mov esp, STACK_END 115 | 116 | ; Clear out .bss 117 | xor eax, eax 118 | mov ecx, BSS_SIZE_L 119 | mov edi, BSS_BASE 120 | rep stosd 121 | 122 | ; Load .data 123 | mov ecx, DATA_SIZE_L 124 | mov edi, DATA_BASE 125 | mov esi, DATA_LOAD 126 | rep movsd 127 | 128 | ; Enable Floating Point 129 | mov eax, cr4 ; Enable SSE and SSE exceptions 130 | or eax, (1<<9 | 1<<10) 131 | mov cr4, eax 132 | clts 133 | fninit 134 | 135 | ; Jump to C init code 136 | jmp init 137 | 138 | ; 139 | ; 140 | ; Initial 16-bit x86 Boot Block 141 | ; 142 | ; 143 | 144 | section .reset_vector 145 | %define RB_SIZE 64 ; Fixed size of this reset vector block 146 | 147 | ; 148 | ; x86 Global Descriptor Table (GDT) 149 | ; 150 | 151 | align 0x10 152 | gdt: 153 | GDT_NULL_SEL equ $-gdt ; Null Segment 154 | dq 0 ; Invalid 155 | 156 | GDT_CODE_SEL equ $-gdt ; Code Segment 157 | dq 0x00cf9b000000ffff ; [0-ffffffff], Ring 0, R/X 158 | 159 | GDT_DATA_SEL equ $-gdt ; Data Segment 160 | dq 0x00cf93000000ffff ; [0-ffffffff], Ring 0, R/W 161 | 162 | GDT_SIZE equ $-gdt 163 | 164 | gdt_desc: 165 | dw GDT_SIZE-1 166 | dd gdt 167 | 168 | times RB_SIZE-32-($-$$) db 0x90 ; Pad up to Reset Vector 169 | 170 | ; 171 | ; x86 Reset Vector (start of execution) 172 | ; 173 | 174 | bits 16 175 | 176 | _switch_to_protected_mode: 177 | mov eax, cr0 ; Enable "Protected Mode" 178 | or al, 1 ; - Bit 0: Protected Mode Enable 179 | mov cr0, eax ; 180 | jmp dword GDT_CODE_SEL:start_32 ; Far jump to complete switch 181 | 182 | times RB_SIZE-16-($-$$) db 0x90 ; Pad up to Reset Vector 183 | 184 | start_16: ; ** Entry point ** 185 | cli ; Disable interrupts 186 | o32 lgdt [cs:gdt_desc] ; Load 32-bit GDT 187 | jmp _switch_to_protected_mode 188 | times start_16+16-$ db 0x90 ; Pad up to 16 byte boundary 189 | --------------------------------------------------------------------------------