Index: branches/slice/coding_standards.txt =================================================================== --- branches/slice/coding_standards.txt (revision 1168) +++ branches/slice/coding_standards.txt (revision 1169) @@ -1,83 +0,0 @@ -Coding Standard rev. 0 (First Draft) - -1. Indentation - having seen most indentation styles going from 2 to 8 spaces, I would suggest a indentation of 4 spaces. - -2. Comments -I see here two main differents cases: -function description comments and one-line code quite comments - -For functions documentation, I suggest to use this syntax -/** - * - */ -Note the use of /** that will make future html auto-documentation easier (i.e: Doxygen at least recognize this marker) - -for punctual, short code comment, let's use: -// -3) #define at top of document -4) Global vars right below #include / #define (notation: gLobal) -Note that global vars and static vars should be avoided as much as possible in favor of local variables use, get/set functions (properties). - -5) No curly brackets for single lines - -6) else -{ - .... -} - -instead of: - -else { - .... -} - -7) if -{ - .... -} -instead of: - -if { - .... -} - -8) fall through code (using indention) or bail out early (using returns)? -Using early bail out for preconditions early in the function code, -use common sense to avoid as an example more than 4 imbricated if() constructions. -In the later case, consider decomposing your function in more manageable primitives. - -9) Spaces/readability i.e. not: if (fd<0) -but: if (fd < 0) - -10. types, variables, functions, naming -non const variables should follow the (currently mostly used) CamelCase convention: -int myVariableIsFine; -instead of : -int my_variable_is_ok; - -Functions should follow the same conventions except for standard c lib related functions. -Types should share the same convention but start with a Captial letter instead of lower case. - -11. Please make sure you extensively initialize variables: -avoid as much as possible: -int myVar -... -myVar = 10; - -but use instead: -int myVar = 10; - -12. const values: -const int MY_CONST_VARIABLE=42; is also ok for me, depending on the context of use. -or -const int MyConstVariable = 42; (with a Capital first letter) - -13. macro definitions should follow this convention: -#define MY_HANDY_MACROS_PSEUDO_FUNC() ... - -14. Macros use should be limited to really special cases where they bring real value (like special optimization cases) -Most of the time inlining a function is much better than the use of macros - -15. Don't optimize your code blindly, always favor readability when in doubt. -Very often, optimization is not necessary where you think it is, think about the bubble sort algorithm, where people would code it in assembly, where a heap or quick sort algorithm would be much more efficient (n log(n) instead of quadratic complexity), as an example when values count to be sorted get high. Index: branches/slice/version =================================================================== --- branches/slice/version (revision 1168) +++ branches/slice/version (revision 1169) @@ -1 +0,0 @@ -2.5-RC5m \ No newline at end of file Index: branches/slice/CreditsToMeklort.rtf =================================================================== --- branches/slice/CreditsToMeklort.rtf (revision 1168) +++ branches/slice/CreditsToMeklort.rtf (revision 1169) @@ -1,7 +0,0 @@ -{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf350 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\paperw11900\paperh16840\margl1440\margr1440\vieww9000\viewh8400\viewkind0 -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural - -\f0\fs24 \cf0 I do not want to compete with Meklort. I just want to propose my numerous changes.} \ No newline at end of file Index: branches/slice/CREDITS =================================================================== --- branches/slice/CREDITS (revision 1168) +++ branches/slice/CREDITS (revision 1169) @@ -1,37 +0,0 @@ -Credit goes to: -=============== - -Developers: ----------- - Crazor - Dense - fassl - iNDi - JrCs - Kabyl - kaitek - mackerintel - mercurysquad - munky - meklort - mozodojo - rekursor - Turbo - valv - zef - -Thanks to: ---------- - asereBLN - Azimutz - bumby - cosmo1t - dfe - Galaxy - kalyway - Krazubu - MasterChief - netkas - sckevyn - smith@@ - THeKiNG Index: branches/slice/revision =================================================================== --- branches/slice/revision (revision 1168) +++ branches/slice/revision (revision 1169) @@ -1 +0,0 @@ -676:727 \ No newline at end of file Index: branches/slice/APPLE_LICENSE =================================================================== --- branches/slice/APPLE_LICENSE (revision 1168) +++ branches/slice/APPLE_LICENSE (revision 1169) @@ -1,367 +0,0 @@ -APPLE PUBLIC SOURCE LICENSE -Version 2.0 - August 6, 2003 - -Please read this License carefully before downloading this software. -By downloading or using this software, you are agreeing to be bound by -the terms of this License. If you do not or cannot agree to the terms -of this License, please do not download or use the software. - -1. General; Definitions. This License applies to any program or other -work which Apple Computer, Inc. ("Apple") makes publicly available and -which contains a notice placed by Apple identifying such program or -work as "Original Code" and stating that it is subject to the terms of -this Apple Public Source License version 2.0 ("License"). As used in -this License: - -1.1 "Applicable Patent Rights" mean: (a) in the case where Apple is -the grantor of rights, (i) claims of patents that are now or hereafter -acquired, owned by or assigned to Apple and (ii) that cover subject -matter contained in the Original Code, but only to the extent -necessary to use, reproduce and/or distribute the Original Code -without infringement; and (b) in the case where You are the grantor of -rights, (i) claims of patents that are now or hereafter acquired, -owned by or assigned to You and (ii) that cover subject matter in Your -Modifications, taken alone or in combination with Original Code. - -1.2 "Contributor" means any person or entity that creates or -contributes to the creation of Modifications. - -1.3 "Covered Code" means the Original Code, Modifications, the -combination of Original Code and any Modifications, and/or any -respective portions thereof. - -1.4 "Externally Deploy" means: (a) to sublicense, distribute or -otherwise make Covered Code available, directly or indirectly, to -anyone other than You; and/or (b) to use Covered Code, alone or as -part of a Larger Work, in any way to provide a service, including but -not limited to delivery of content, through electronic communication -with a client other than You. - -1.5 "Larger Work" means a work which combines Covered Code or portions -thereof with code not governed by the terms of this License. - -1.6 "Modifications" mean any addition to, deletion from, and/or change -to, the substance and/or structure of the Original Code, any previous -Modifications, the combination of Original Code and any previous -Modifications, and/or any respective portions thereof. When code is -released as a series of files, a Modification is: (a) any addition to -or deletion from the contents of a file containing Covered Code; -and/or (b) any new file or other representation of computer program -statements that contains any part of Covered Code. - -1.7 "Original Code" means (a) the Source Code of a program or other -work as originally made available by Apple under this License, -including the Source Code of any updates or upgrades to such programs -or works made available by Apple under this License, and that has been -expressly identified by Apple as such in the header file(s) of such -work; and (b) the object code compiled from such Source Code and -originally made available by Apple under this License. - -1.8 "Source Code" means the human readable form of a program or other -work that is suitable for making modifications to it, including all -modules it contains, plus any associated interface definition files, -scripts used to control compilation and installation of an executable -(object code). - -1.9 "You" or "Your" means an individual or a legal entity exercising -rights under this License. For legal entities, "You" or "Your" -includes any entity which controls, is controlled by, or is under -common control with, You, where "control" means (a) the power, direct -or indirect, to cause the direction or management of such entity, -whether by contract or otherwise, or (b) ownership of fifty percent -(50%) or more of the outstanding shares or beneficial ownership of -such entity. - -2. Permitted Uses; Conditions & Restrictions. Subject to the terms -and conditions of this License, Apple hereby grants You, effective on -the date You accept this License and download the Original Code, a -world-wide, royalty-free, non-exclusive license, to the extent of -Apple's Applicable Patent Rights and copyrights covering the Original -Code, to do the following: - -2.1 Unmodified Code. You may use, reproduce, display, perform, -internally distribute within Your organization, and Externally Deploy -verbatim, unmodified copies of the Original Code, for commercial or -non-commercial purposes, provided that in each instance: - -(a) You must retain and reproduce in all copies of Original Code the -copyright and other proprietary notices and disclaimers of Apple as -they appear in the Original Code, and keep intact all notices in the -Original Code that refer to this License; and - -(b) You must include a copy of this License with every copy of Source -Code of Covered Code and documentation You distribute or Externally -Deploy, and You may not offer or impose any terms on such Source Code -that alter or restrict this License or the recipients' rights -hereunder, except as permitted under Section 6. - -2.2 Modified Code. You may modify Covered Code and use, reproduce, -display, perform, internally distribute within Your organization, and -Externally Deploy Your Modifications and Covered Code, for commercial -or non-commercial purposes, provided that in each instance You also -meet all of these conditions: - -(a) You must satisfy all the conditions of Section 2.1 with respect to -the Source Code of the Covered Code; - -(b) You must duplicate, to the extent it does not already exist, the -notice in Exhibit A in each file of the Source Code of all Your -Modifications, and cause the modified files to carry prominent notices -stating that You changed the files and the date of any change; and - -(c) If You Externally Deploy Your Modifications, You must make -Source Code of all Your Externally Deployed Modifications either -available to those to whom You have Externally Deployed Your -Modifications, or publicly available. Source Code of Your Externally -Deployed Modifications must be released under the terms set forth in -this License, including the license grants set forth in Section 3 -below, for as long as you Externally Deploy the Covered Code or twelve -(12) months from the date of initial External Deployment, whichever is -longer. You should preferably distribute the Source Code of Your -Externally Deployed Modifications electronically (e.g. download from a -web site). - -2.3 Distribution of Executable Versions. In addition, if You -Externally Deploy Covered Code (Original Code and/or Modifications) in -object code, executable form only, You must include a prominent -notice, in the code itself as well as in related documentation, -stating that Source Code of the Covered Code is available under the -terms of this License with information on how and where to obtain such -Source Code. - -2.4 Third Party Rights. You expressly acknowledge and agree that -although Apple and each Contributor grants the licenses to their -respective portions of the Covered Code set forth herein, no -assurances are provided by Apple or any Contributor that the Covered -Code does not infringe the patent or other intellectual property -rights of any other entity. Apple and each Contributor disclaim any -liability to You for claims brought by any other entity based on -infringement of intellectual property rights or otherwise. As a -condition to exercising the rights and licenses granted hereunder, You -hereby assume sole responsibility to secure any other intellectual -property rights needed, if any. For example, if a third party patent -license is required to allow You to distribute the Covered Code, it is -Your responsibility to acquire that license before distributing the -Covered Code. - -3. Your Grants. In consideration of, and as a condition to, the -licenses granted to You under this License, You hereby grant to any -person or entity receiving or distributing Covered Code under this -License a non-exclusive, royalty-free, perpetual, irrevocable license, -under Your Applicable Patent Rights and other intellectual property -rights (other than patent) owned or controlled by You, to use, -reproduce, display, perform, modify, sublicense, distribute and -Externally Deploy Your Modifications of the same scope and extent as -Apple's licenses under Sections 2.1 and 2.2 above. - -4. Larger Works. You may create a Larger Work by combining Covered -Code with other code not governed by the terms of this License and -distribute the Larger Work as a single product. In each such instance, -You must make sure the requirements of this License are fulfilled for -the Covered Code or any portion thereof. - -5. Limitations on Patent License. Except as expressly stated in -Section 2, no other patent rights, express or implied, are granted by -Apple herein. Modifications and/or Larger Works may require additional -patent licenses from Apple which Apple may grant in its sole -discretion. - -6. Additional Terms. You may choose to offer, and to charge a fee for, -warranty, support, indemnity or liability obligations and/or other -rights consistent with the scope of the license granted herein -("Additional Terms") to one or more recipients of Covered Code. -However, You may do so only on Your own behalf and as Your sole -responsibility, and not on behalf of Apple or any Contributor. You -must obtain the recipient's agreement that any such Additional Terms -are offered by You alone, and You hereby agree to indemnify, defend -and hold Apple and every Contributor harmless for any liability -incurred by or claims asserted against Apple or such Contributor by -reason of any such Additional Terms. - -7. Versions of the License. Apple may publish revised and/or new -versions of this License from time to time. Each version will be given -a distinguishing version number. Once Original Code has been published -under a particular version of this License, You may continue to use it -under the terms of that version. You may also choose to use such -Original Code under the terms of any subsequent version of this -License published by Apple. No one other than Apple has the right to -modify the terms applicable to Covered Code created under this -License. - -8. NO WARRANTY OR SUPPORT. The Covered Code may contain in whole or in -part pre-release, untested, or not fully tested works. The Covered -Code may contain errors that could cause failures or loss of data, and -may be incomplete or contain inaccuracies. You expressly acknowledge -and agree that use of the Covered Code, or any portion thereof, is at -Your sole and entire risk. THE COVERED CODE IS PROVIDED "AS IS" AND -WITHOUT WARRANTY, UPGRADES OR SUPPORT OF ANY KIND AND APPLE AND -APPLE'S LICENSOR(S) (COLLECTIVELY REFERRED TO AS "APPLE" FOR THE -PURPOSES OF SECTIONS 8 AND 9) AND ALL CONTRIBUTORS EXPRESSLY DISCLAIM -ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, BUT -NOT LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF -MERCHANTABILITY, OF SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR -PURPOSE, OF ACCURACY, OF QUIET ENJOYMENT, AND NONINFRINGEMENT OF THIRD -PARTY RIGHTS. APPLE AND EACH CONTRIBUTOR DOES NOT WARRANT AGAINST -INTERFERENCE WITH YOUR ENJOYMENT OF THE COVERED CODE, THAT THE -FUNCTIONS CONTAINED IN THE COVERED CODE WILL MEET YOUR REQUIREMENTS, -THAT THE OPERATION OF THE COVERED CODE WILL BE UNINTERRUPTED OR -ERROR-FREE, OR THAT DEFECTS IN THE COVERED CODE WILL BE CORRECTED. NO -ORAL OR WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE, AN APPLE -AUTHORIZED REPRESENTATIVE OR ANY CONTRIBUTOR SHALL CREATE A WARRANTY. -You acknowledge that the Covered Code is not intended for use in the -operation of nuclear facilities, aircraft navigation, communication -systems, or air traffic control machines in which case the failure of -the Covered Code could lead to death, personal injury, or severe -physical or environmental damage. - -9. LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO -EVENT SHALL APPLE OR ANY CONTRIBUTOR BE LIABLE FOR ANY INCIDENTAL, -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING -TO THIS LICENSE OR YOUR USE OR INABILITY TO USE THE COVERED CODE, OR -ANY PORTION THEREOF, WHETHER UNDER A THEORY OF CONTRACT, WARRANTY, -TORT (INCLUDING NEGLIGENCE), PRODUCTS LIABILITY OR OTHERWISE, EVEN IF -APPLE OR SUCH CONTRIBUTOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES AND NOTWITHSTANDING THE FAILURE OF ESSENTIAL PURPOSE OF ANY -REMEDY. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF LIABILITY OF -INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT APPLY -TO YOU. In no event shall Apple's total liability to You for all -damages (other than as may be required by applicable law) under this -License exceed the amount of fifty dollars ($50.00). - -10. Trademarks. This License does not grant any rights to use the -trademarks or trade names "Apple", "Apple Computer", "Mac", "Mac OS", -"QuickTime", "QuickTime Streaming Server" or any other trademarks, -service marks, logos or trade names belonging to Apple (collectively -"Apple Marks") or to any trademark, service mark, logo or trade name -belonging to any Contributor. You agree not to use any Apple Marks in -or as part of the name of products derived from the Original Code or -to endorse or promote products derived from the Original Code other -than as expressly permitted by and in strict compliance at all times -with Apple's third party trademark usage guidelines which are posted -at http://www.apple.com/legal/guidelinesfor3rdparties.html. - -11. Ownership. Subject to the licenses granted under this License, -each Contributor retains all rights, title and interest in and to any -Modifications made by such Contributor. Apple retains all rights, -title and interest in and to the Original Code and any Modifications -made by or on behalf of Apple ("Apple Modifications"), and such Apple -Modifications will not be automatically subject to this License. Apple -may, at its sole discretion, choose to license such Apple -Modifications under this License, or on different terms from those -contained in this License or may choose not to license them at all. - -12. Termination. - -12.1 Termination. This License and the rights granted hereunder will -terminate: - -(a) automatically without notice from Apple if You fail to comply with -any term(s) of this License and fail to cure such breach within 30 -days of becoming aware of such breach; - -(b) immediately in the event of the circumstances described in Section -13.5(b); or - -(c) automatically without notice from Apple if You, at any time during -the term of this License, commence an action for patent infringement -against Apple; provided that Apple did not first commence -an action for patent infringement against You in that instance. - -12.2 Effect of Termination. Upon termination, You agree to immediately -stop any further use, reproduction, modification, sublicensing and -distribution of the Covered Code. All sublicenses to the Covered Code -which have been properly granted prior to termination shall survive -any termination of this License. Provisions which, by their nature, -should remain in effect beyond the termination of this License shall -survive, including but not limited to Sections 3, 5, 8, 9, 10, 11, -12.2 and 13. No party will be liable to any other for compensation, -indemnity or damages of any sort solely as a result of terminating -this License in accordance with its terms, and termination of this -License will be without prejudice to any other right or remedy of -any party. - -13. Miscellaneous. - -13.1 Government End Users. The Covered Code is a "commercial item" as -defined in FAR 2.101. Government software and technical data rights in -the Covered Code include only those rights customarily provided to the -public as defined in this License. This customary commercial license -in technical data and software is provided in accordance with FAR -12.211 (Technical Data) and 12.212 (Computer Software) and, for -Department of Defense purchases, DFAR 252.227-7015 (Technical Data -- -Commercial Items) and 227.7202-3 (Rights in Commercial Computer -Software or Computer Software Documentation). Accordingly, all U.S. -Government End Users acquire Covered Code with only those rights set -forth herein. - -13.2 Relationship of Parties. This License will not be construed as -creating an agency, partnership, joint venture or any other form of -legal association between or among You, Apple or any Contributor, and -You will not represent to the contrary, whether expressly, by -implication, appearance or otherwise. - -13.3 Independent Development. Nothing in this License will impair -Apple's right to acquire, license, develop, have others develop for -it, market and/or distribute technology or products that perform the -same or similar functions as, or otherwise compete with, -Modifications, Larger Works, technology or products that You may -develop, produce, market or distribute. - -13.4 Waiver; Construction. Failure by Apple or any Contributor to -enforce any provision of this License will not be deemed a waiver of -future enforcement of that or any other provision. Any law or -regulation which provides that the language of a contract shall be -construed against the drafter will not apply to this License. - -13.5 Severability. (a) If for any reason a court of competent -jurisdiction finds any provision of this License, or portion thereof, -to be unenforceable, that provision of the License will be enforced to -the maximum extent permissible so as to effect the economic benefits -and intent of the parties, and the remainder of this License will -continue in full force and effect. (b) Notwithstanding the foregoing, -if applicable law prohibits or restricts You from fully and/or -specifically complying with Sections 2 and/or 3 or prevents the -enforceability of either of those Sections, this License will -immediately terminate and You must immediately discontinue any use of -the Covered Code and destroy all copies of it that are in your -possession or control. - -13.6 Dispute Resolution. Any litigation or other dispute resolution -between You and Apple relating to this License shall take place in the -Northern District of California, and You and Apple hereby consent to -the personal jurisdiction of, and venue in, the state and federal -courts within that District with respect to this License. The -application of the United Nations Convention on Contracts for the -International Sale of Goods is expressly excluded. - -13.7 Entire Agreement; Governing Law. This License constitutes the -entire agreement between the parties with respect to the subject -matter hereof. This License shall be governed by the laws of the -United States and the State of California, except that body of -California law concerning conflicts of law. - -Where You are located in the province of Quebec, Canada, the following -clause applies: The parties hereby confirm that they have requested -that this License and all related documents be drafted in English. Les -parties ont exige que le present contrat et tous les documents -connexes soient rediges en anglais. - -EXHIBIT A. - -"Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights -Reserved. - -This file contains Original Code and/or Modifications of Original Code -as defined in and that are subject to the Apple Public Source License -Version 2.0 (the 'License'). You may not use this file except in -compliance with the License. Please obtain a copy of the License at -http://www.opensource.apple.com/apsl/ and read it before using this -file. - -The Original Code and all software distributed under the License are -distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER -EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, -INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. -Please see the License for the specific language governing rights and -limitations under the License." Index: branches/slice/TODO =================================================================== --- branches/slice/TODO (revision 1168) +++ branches/slice/TODO (revision 1169) @@ -1,101 +0,0 @@ -TODO List for Chameleon Boot Loader -==================================== -31.01.2011 Slice -- linux detection -- proper bootArgs when starting from CD - -27.12.2010 Slice -- numerous errors, mistakes, reservation, non-finished codes... Spaghetti sources! -- kernelcache never used (adler32 is wrong?) -- resolved -- more careful CPU detection -- readNVRAM is wrong -- resolved -- graphicsEnabler for X3100 is not good -- ATI Radeon enabler is not perfect - - -16.12.2010 Slice -- I want to implement NVRAM for use with nvram, bless, StartupDisk.prefPane, and with VoodooHDA in future. -1. Write a script rc.shutdown.local and place it into /etc -<-------------- -#!/bin/sh -nvram -p >nvram.inf -echo Hello! NVRAM is saved! ---------------> -2. Read and interpret nvram.inf to place variables into /options node -3. Prepare some other boot-time variables in the node (platform-uuid, BootOrder, FirmwareFeatures, efi-boot-device and so on) -4. Implement boot flag -c to clear growing amount of nvram savings. - -- ATI GraphicsEnabler is not perfect. -1. ATY,SCLK, ATY,MCLK, ATY,RefCLK must be read from VideoBIOS but not constant values. Excluded! -2. FakeDeviceID needed - -- Intel GraphicsEnabler needs to be corrected by calculating LCD info. Done! --------------------------------------------------------------------------------------------------------- -- Integrate Prasys current work on options and quick shortcut modified version of 18seven - -- Add autodetection of efistring algorythm to enabke graphics enabler to beanbled by default while not conflicting whith other efi string overriden content - (original idea of Galaxy) - -- Add a more sophisticated acpi loading mechanism to enable loading custom acpi tables when dsdtdrop=y - Here's a specification to think about: - First we must care about if a forced DSDT full path has been specified (was the pb smith had in - his first tries) and take it for the DSDT path as is. - Then we have the case where no DSDT path was set where we run our usual DSDT search algorithm to find this file. - In the latter case, the file has to be named DSDT.aml and be in one of the / /Extra or bt(0,0)/Extra directory. - - Now a first idea to implement correctly the acpi tables loading would be: - - Whatever the path was hardcoded in the DSDT option or was automatically found, we extract the path part of - the DSDT file that has been successfully found and we run a loop to enumerate all other acpi files in the same directory. - Now for each acpi file found, we should compare the name with an existing acpi table found in the system that - we would normally load and replace this usual injection by the content of the file. - - Once DropDSDT=y is set, no other acpi table than dsdt is loaded, then it is the responsability of user - to provide any other acpi table. - -- Add a new module capable of writing proprietary Chameleon data to ioreg: - Using the DT__xxx() API, we will create a set of functions to write - to log info, chameleon boot info to be retrieved by helper applications... - the only public function for log info purpose of this module would be: - logMessageToIOREG(...); // var args printf style format - flushLogToIOREG(); // store a unique log info property to the ioreg - - The preferred internal behavior of the log info ioreg buffer - would be to store the messages in a consolidated buffer then only write once, - this buffer (i.e just before call the kernel) with flushLogToIOREG(); - The other public function for writing chameleon boot info data would be: - - verbose() should incorporate a call to logMessageToIOREG() - to permit helper applications to extract - this log info (i.e: the chameleon system pref pane) - -- Add API for displaying and logging messages like: - - void verbose(...) - { - ... - logMessageToIOREG("%s: %sn", title, s); - - } - - void display_and_log( const char* title, const char* msg) - { - printf("%s: %sn", title, s); - logMessageToIOREG(title,s); - } - - void deprecated(const char * s) - { - display_and_log("WARNING: Deprecated option",s); - sleep(1); - } - - void error_message(const char * s) - { - display_and_log("ERROR",s); - getc(); - } - - - Case unsensitive parsing for the bootConfig options: - should help the common/novice user to setup more easily. - Index: branches/slice/CHANGES =================================================================== --- branches/slice/CHANGES (revision 1168) +++ branches/slice/CHANGES (revision 1169) @@ -1,83 +0,0 @@ -Slice: -rev712 -- correct module system as Meklort did to be Symbols.dylib embedded. -- return acpi_patcher to main sources to exclude obligatory module -- correct modules.c procedure register_hook_callback. -rev692 -- add ATI 5xxx Enabler module on Kabyl's sources (not checked) -- corrections to open standards: EFI, UUID, SMBIOS, ACPI, EDID -- getResolution from BIOS EDID now works -- exclude Intel BIOS from patch, because it has other structure -rev673 -- not agree with claim "Removed obsolete -f option, use -x instead" - -f - ignore kernel cache (rebuild it) - -x - boot with restricted set of drivers (without Graphics card etc.) -- kernelcache location depends on OS vesion. It differs for 10.4, 10.5, 10.6 -- don't need to include headers twice, other cosmetics -- don't need to call getSMBIOS ten times, just global pointer to patched one. -- more correct detect system type Mobile or Desktop based on CPU MSR registers and DMI info. -- write system-type into FACP if incorrect. Sometimes it happen. -- create ACPI2.0 structure for old BIOSes having only ACPI1.0. It is only way to boot SamsungP29 notebook -- place patched DSDT at the ACPI1.0 pointer. It is only way to patch DSDT for SamsungP29 notebook. Nontheless acpi_patcher works for any system -- delete messages like "Loading HFS+ file [xxx]xxx...". No info for user but very slow. -- correct UUID to be LittleEndian as used by ACPI.org, Microsoft, Apple -- some corrections to detect CPU, ATI, NVidia -- other current corrections by Mozo and Meklort ------------------------------------ -- Added Booter Log Dump Tool -- Added Booter message Logging (":/boot-log" ioreg property) -- Removed obsolete -f option, use -x instead -- Removed -x32 option, use arch=i386 instead -- Added automatic SMBusspeed detection for lga1156 core i5/7 cpus -- Added new iMac11,1 sbios default model for lga1156 core i5/17 mobos -- md0 code. Notified xnu when an md ramdisk is specified -- Added rollover image support for selected device icons. - Use device__o.png in theme folder. Credits goes to Blackosx. -- Revisited theme resource embedding. Using the device_ icons are optional with - the exception of device_generic. -- Optimized memory detection speed -- Added displaying source device and partition number for file read operations. -- Increased boot2's maximum size from 383.5k to 447.5k. - Updated stage 1 loaders for handling the new size limit. -- Added alternate format for setting the default partition. The user can specify the selected - volume UUID for the "Default Partition" key. -- Implemented SPD memory automatic detection and injection,seems to work really great ... -- Factorized code to prepare a dynamic memory detection algorithm ... -- Optimized smbios table address search -- Optimized cursor spinout in textmode if no verbose mode is set -- Added ram table structures definitions -- Added getSmbios() a param permitting to select between orig and new smbios entries -- Changed "Default Partition" behaviour to accept only native system volumes or foreign partitions. -- Added NVIDIA new NVCAP customization support and support for ION gfx cards from aserebln -- Added ATI new framebuffers support and new cards from PCEFI10.6 -- improved ACPI file search algo by implementing a cache. -- Nvidia injection fix -- pciroot would not always return correct uuid in autodection mode -- Fixed the hibernation problem in boot2/resume.c -- Fixed all new booter versions with SystemType would override the facp value even if correct, - now keeps the facp value if correct and no override has been done, implemented a best effort algo. - for maximizing the chance to get the most correct value before we decide to use a fixed value (1=desktop) -- Fixed display cosmetics of UUID, now a convert.c file contains all - conversions api, to be completed by function that we should reuse. - -- Fixed SystemType would be always forced to a value, now optionally changed - only if ovveriden -- Kept SystemID as the only option to change manually the system-id - For theses reasons, SystemId from bootConfig and SMUUID from smbiosConfig aer now DEPRECATED. - -- Integrated JrCs fadt patch (kept for RC5 the existing DSDT.aml retry algo that disapeared in his patch, should be more discussed for RC6) -- Added JrCs modified convention name change to coding_standards -- Now malloc (ex. MALLOC in Asere patch) is renamed malloc(size) and is an alias - to safe_malloc(size, file, line) with _FILE_ and _LINE_ prerocessor definitions -- Added a new 'Rename Partition Feature', now permitting to rename partition - like 'System reserved' to a more meaningful name -- Added SystemID option permitting to change the System UUID to a fixed value. -- Added the PciRoot autodetection feature imported from pcefi10.5 -- Added automatic "system-id" injection from dmi bios, also compatible - with SystemID boot option and former SMUUID from smbios,plist -- Added "system-type' automatic injection (1=Desktop) plus override possibility - with the new system-type option in bootConfig -- Added SMserial and SMproductname new options for smbios.plist -- Merged with asere patch, while keeping my fake_efi.c changes, and adding a new - stringForKey() API, also changed the DT__XXXX() set of functions - to handle const char * values instead of char*. Index: branches/slice/rev749/Distribution =================================================================== --- branches/slice/rev749/Distribution (revision 0) +++ branches/slice/rev749/Distribution (revision 1169) @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + Chameleon_title + + Index: branches/slice/rev749/libsaio/fake_efi.h =================================================================== --- branches/slice/rev749/libsaio/fake_efi.h (revision 0) +++ branches/slice/rev749/libsaio/fake_efi.h (revision 1169) @@ -0,0 +1,22 @@ +/* + * Copyright 2007 David F. Elliott. All rights reserved. + */ + +#ifndef __LIBSAIO_FAKE_EFI_H +#define __LIBSAIO_FAKE_EFI_H +#include "platform.h" +#include "pci.h" + +/* Set up space for up to 10 configuration table entries */ +#define MAX_CONFIGURATION_TABLE_ENTRIES 10 + +extern void setupFakeEfi(void); +extern void setupSystemType(void); +extern inline uint64_t ptov64(uint32_t addr); +extern struct SMBEntryPoint * getSmbios(int which); // now cached +//extern void setup_pci_devs(pci_dt_t *pci_dt); //into pci.h +extern uint64_t smbios_p; +//extern void scan_cpu_DMI(void); //PlatformInfo_t *); //Slice + + +#endif /* !__LIBSAIO_FAKE_EFI_H */ Index: branches/slice/rev749/libsaio/xml.c =================================================================== --- branches/slice/rev749/libsaio/xml.c (revision 0) +++ branches/slice/rev749/libsaio/xml.c (revision 1169) @@ -0,0 +1,1150 @@ +/* + * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 2003 Apple Computer, Inc. All Rights + * Reserved. + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 2.0 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include "bootstruct.h" +#include "libsaio.h" +#include "sl.h" +#include "xml.h" + +string_ref *ref_strings = NULL; + +/// TODO: remove below +static char* buffer_start = NULL; +// TODO: redo the next two functions +void SaveRefString(char* string, int id) +{ + //printf("Adding Ref String %d (%s)\n", id, string); + string_ref* tmp = ref_strings; + while(tmp) + { + if(tmp->id == id) + { + tmp->string = malloc(strlen(string)+1); + sprintf(tmp->string, "%s", string); + return; + } + tmp = tmp->next; + } + + string_ref* new_ref = malloc(sizeof(string_ref)); + new_ref->string = malloc(strlen(string)+1); + sprintf(new_ref->string, "%s", string); + new_ref->id = id; + new_ref->next = ref_strings; + ref_strings = new_ref; +} + +char* GetRefString(int id) +{ + string_ref* tmp = ref_strings; + while(tmp) + { + if(tmp->id == id) return tmp->string; + tmp = tmp->next; + } + //verbose("Unable to locate Ref String %d\n", id); + return ""; +} + + +struct Module { + struct Module *nextModule; + long willLoad; + TagPtr dict; + char *plistAddr; + long plistLength; + char *driverPath; +}; +typedef struct Module Module, *ModulePtr; + +struct DriverInfo { + char *plistAddr; + long plistLength; + void *moduleAddr; + long moduleLength; +}; +typedef struct DriverInfo DriverInfo, *DriverInfoPtr; + +#define kDriverPackageSignature1 'MKXT' +#define kDriverPackageSignature2 'MOSX' + +struct DriversPackage { + unsigned long signature1; + unsigned long signature2; + unsigned long length; + unsigned long alder32; + unsigned long version; + unsigned long numDrivers; + unsigned long reserved1; + unsigned long reserved2; +}; +typedef struct DriversPackage DriversPackage; + +enum { + kCFBundleType2, + kCFBundleType3 +}; + + +#define USEMALLOC 1 +#define DOFREE 1 + +static long ParseTagList(char *buffer, TagPtr *tag, long type, long empty); +static long ParseTagKey(char *buffer, TagPtr *tag); +static long ParseTagString(char *buffer, TagPtr *tag); +static long ParseTagInteger(char *buffer, TagPtr *tag); +static long ParseTagData(char *buffer, TagPtr *tag); +static long ParseTagDate(char *buffer, TagPtr *tag); +static long ParseTagBoolean(char *buffer, TagPtr *tag, long type); +static long GetNextTag(char *buffer, char **tag, long *start); +static long FixDataMatchingTag(char *buffer, char *tag); +static TagPtr NewTag(void); +static char *NewSymbol(char *string); +#if DOFREE +static void FreeSymbol(char *string); +#endif + + +//========================================================================== +// XMLGetProperty + +TagPtr +XMLGetProperty( TagPtr dict, const char * key ) +{ + TagPtr tagList, tag; + + if (dict->type != kTagTypeDict) return 0; + + tag = 0; + tagList = dict->tag; + while (tagList) + { + tag = tagList; + tagList = tag->tagNext; + + if ((tag->type != kTagTypeKey) || (tag->string == 0)) continue; + + if (!strcmp(tag->string, key)) return tag->tag; + } + + return 0; +} + + +// XMLGetTag(int index) + +// XMLTagCount( TagPtr dict ) +int XMLTagCount( TagPtr dict ) +{ + int count = 0; + TagPtr tagList, tag; + + if (dict->type != kTagTypeDict && dict->type != kTagTypeArray) return 0; + tag = 0; + tagList = dict->tag; + while (tagList) + { + tag = tagList; + tagList = tag->tagNext; + + if (((tag->type != kTagTypeKey) && ((tag->string == 0) || (tag->string[0] == 0))) + && (dict->type != kTagTypeArray) // If we are an array, any element is valid + ) continue; + + if(tag->type == kTagTypeKey) printf("Located key %s\n", tag->string); + + count++; + } + + return count; +} + +TagPtr XMLGetElement( TagPtr dict, int id ) +{ + if(dict->type != kTagTypeArray) return 0; + + int element = 0; + TagPtr tmp = dict->tag; + + while(element < id) + { + element++; + tmp = tmp->tagNext; + } + + return tmp; +} +/* Function for basic XML character entities parsing */ + +char* +XMLDecode(const char* src) +{ + typedef const struct XMLEntity { + const char* name; + size_t nameLen; + char value; + } XMLEntity; + + /* This is ugly, but better than specifying the lengths by hand */ + #define _e(str,c) {str,sizeof(str)-1,c} + const XMLEntity ents[] = { + _e("quot;",'"'), _e("apos;",'\''), + _e("lt;", '<'), _e("gt;", '>'), + _e("amp;", '&') + }; + + size_t len; + const char *s; + char *out, *o; + + if ( !src || !(len = strlen(src)) || !(out = malloc(len+1)) ) + return 0; + + o = out; + s = src; + while (s <= src+len) /* Make sure the terminator is also copied */ + { + if ( *s == '&' ) + { + bool entFound = false; + int i; + + s++; + for ( i = 0; i < sizeof(ents); i++) + { + if ( strncmp(s, ents[i].name, ents[i].nameLen) == 0 ) + { + entFound = true; + break; + } + } + if ( entFound ) + { + *o++ = ents[i].value; + s += ents[i].nameLen; + continue; + } + } + + *o++ = *s++; + } + + return out; +} + +//#if UNUSED +//========================================================================== +// XMLParseFile +// Expects to see one dictionary in the XML file, the final pos will be returned +// If the pos is not equal to the strlen, then there are multiple dicts +// Puts the first dictionary it finds in the +// tag pointer and returns the end of the dic, or returns -1 if not found. +// +long +XMLParseFile( char * buffer, TagPtr * dict ) +{ + long length, pos; + TagPtr tag; + pos = 0; + char *configBuffer; + + + + configBuffer = malloc(strlen(buffer)+1); + strcpy(configBuffer, buffer); + + buffer_start = configBuffer; + + while (1) + { + length = XMLParseNextTag(configBuffer + pos, &tag); + if (length == -1) break; + + pos += length; + + if (tag == 0) continue; + if (tag->type == kTagTypeDict) break; + + XMLFreeTag(tag); + } + free(configBuffer); + if (length < 0) { + return -1; + } + *dict = tag; + return pos; +} +//#endif /* UNUSED */ + +//========================================================================== +// ParseNextTag +// TODO: cleanup +long +XMLParseNextTag( char * buffer, TagPtr * tag ) +{ + long length, pos; + char * tagName; + + length = GetNextTag(buffer, &tagName, 0); + if (length == -1) return -1; + + pos = length; + if (!strncmp(tagName, kXMLTagPList, 6)) + { + length = 0; + } + /***** dict ****/ + else if (!strcmp(tagName, kXMLTagDict)) + { + length = ParseTagList(buffer + pos, tag, kTagTypeDict, 0); + } + else if (!strncmp(tagName, kXMLTagDict, strlen(kXMLTagDict)) && tagName[strlen(tagName)-1] == '/') + { + length = ParseTagList(buffer + pos, tag, kTagTypeDict, 1); + } + else if (!strncmp(tagName, kXMLTagDict " ", strlen(kXMLTagDict " "))) + { + length = ParseTagList(buffer + pos, tag, kTagTypeDict, 0); + } + /***** key ****/ + else if (!strcmp(tagName, kXMLTagKey)) + { + length = ParseTagKey(buffer + pos, tag); + } + + /***** string ****/ + else if (!strcmp(tagName, kXMLTagString)) + { + length = ParseTagString(buffer + pos, tag); + } + else if (!strncmp(tagName, kXMLTagString " ", strlen(kXMLTagString " "))) + { + // TODO: save tag if if found + if(!strncmp(tagName + strlen(kXMLTagString " "), kXMLStringID, strlen(kXMLStringID))) + { + // ID= + int id = 0; + int cnt = strlen(kXMLTagString " " kXMLStringID "\"") + 1; + while ((tagName[cnt] != '\0') && (tagName[cnt] != '"')) cnt++; + tagName[cnt] = 0; + char* val = tagName + strlen(kXMLTagString " " kXMLStringID "\""); + while(*val) + { + if ((*val >= '0' && *val <= '9')) // 0 - 9 + { + id = (id * 10) + (*val++ - '0'); + } + else + { + verbose("ParseStringID error (0x%x)\n", *val); + getc(); + return -1; + + } + + } + length = ParseTagString(buffer + pos, tag); + + SaveRefString(buffer + pos, id); + } + else if(!strncmp(tagName + strlen(kXMLTagString " "), kXMLStringIDRef, strlen(kXMLStringIDRef))) + { + // IDREF= + int id = 0; + int cnt = strlen(kXMLTagString " " kXMLStringIDRef "\"") + 1; + while ((tagName[cnt] != '\0') && (tagName[cnt] != '"')) cnt++; + tagName[cnt] = 0; + char* val = tagName + strlen(kXMLTagString " " kXMLStringIDRef "\""); + while(*val) + { + if ((*val >= '0' && *val <= '9')) // 0 - 9 + { + id = (id * 10) + (*val++ - '0'); + } + else + { + printf("ParseStringIDREF error (0x%x)\n", *val); + getc(); + return -1; + + } + + } + char* str = GetRefString(id); + + TagPtr tmpTag = NewTag(); + tmpTag->type = kTagTypeString; + tmpTag->string = str; + tmpTag->tag = 0; + tmpTag->tagNext = 0; + tmpTag->offset = buffer_start ? buffer - buffer_start + pos : 0; + *tag = tmpTag; + + length = 0; + //printf("Located IDREF, id = %d, string = %s\n", id, str); + } + + } + + /***** integer ****/ + else if (!strcmp(tagName, kXMLTagInteger)) + { + length = ParseTagInteger(buffer + pos, tag); + } + else if (!strncmp(tagName, kXMLTagInteger " ", strlen(kXMLTagInteger " "))) + { + if(!strncmp(tagName + strlen(kXMLTagInteger " "), kXMLStringID, strlen(kXMLStringID))) + { + // ID= + int id = 0; + int cnt = strlen(kXMLTagInteger " " kXMLStringID "\"") + 1; + while ((tagName[cnt] != '\0') && (tagName[cnt] != '"')) cnt++; + tagName[cnt] = 0; + char* val = tagName + strlen(kXMLTagInteger " " kXMLStringID "\""); + while(*val) + { + if ((*val >= '0' && *val <= '9')) // 0 - 9 + { + id = (id * 10) + (*val++ - '0'); + } + else + { + verbose("ParseIntegerID error (0x%x)\n", *val); + getc(); + return -1; + + } + + } + length = ParseTagInteger(buffer + pos, tag); + + SaveRefString((*tag)->string, id); + } + else if(!strncmp(tagName + strlen(kXMLTagInteger " "), kXMLStringIDRef, strlen(kXMLStringIDRef))) + { + // IDREF= + int id = 0; + int cnt = strlen(kXMLTagInteger " " kXMLStringIDRef "\"") + 1; + while ((tagName[cnt] != '\0') && (tagName[cnt] != '"')) cnt++; + tagName[cnt] = 0; + char* val = tagName + strlen(kXMLTagInteger " " kXMLStringIDRef "\""); + while(*val) + { + if ((*val >= '0' && *val <= '9')) // 0 - 9 + { + id = (id * 10) + (*val++ - '0'); + } + else + { + verbose("ParseStringIDREF error (0x%x)\n", *val); + getc(); + return -1; + + } + + } + int integer = (int)GetRefString(id); + + TagPtr tmpTag = NewTag(); + tmpTag->type = kTagTypeInteger; + tmpTag->string = (char*) integer; + tmpTag->tag = 0; + tmpTag->tagNext = 0; + tmpTag->offset = buffer_start ? buffer - buffer_start + pos : 0; + + *tag = tmpTag; + + length = 0; + //printf("Located IDREF, id = %d, string = %s\n", id, str); + } + else + { + length = ParseTagInteger(buffer + pos, tag); + } + } + + /***** data ****/ + else if (!strcmp(tagName, kXMLTagData)) + { + length = ParseTagData(buffer + pos, tag); + } + else if (!strncmp(tagName, kXMLTagData " ", strlen(kXMLTagData " "))) + { + length = ParseTagData(buffer + pos, tag); + } + else if (!strcmp(tagName, kXMLTagDate)) + { + length = ParseTagDate(buffer + pos, tag); + } + + /***** date ****/ + else if (!strncmp(tagName, kXMLTagDate " ", strlen(kXMLTagDate " "))) + { + length = ParseTagDate(buffer + pos, tag); + } + + /***** false ****/ + else if (!strcmp(tagName, kXMLTagFalse)) + { + length = ParseTagBoolean(buffer + pos, tag, kTagTypeFalse); + } + /***** true ****/ + else if (!strcmp(tagName, kXMLTagTrue)) + { + length = ParseTagBoolean(buffer + pos, tag, kTagTypeTrue); + } + + /***** array ****/ + else if (!strcmp(tagName, kXMLTagArray)) + { + length = ParseTagList(buffer + pos, tag, kTagTypeArray, 0); + } + else if (!strncmp(tagName, kXMLTagArray " ", strlen(kXMLTagArray " "))) + { + length = ParseTagList(buffer + pos, tag, kTagTypeArray, 0); + } + else if (!strcmp(tagName, kXMLTagArray "/")) + { + length = ParseTagList(buffer + pos, tag, kTagTypeArray, 1); + } + + /***** unknown ****/ + else + { + *tag = 0; + length = 0; + } + + + if (length == -1) return -1; + + return pos + length; +} + +//========================================================================== +// ParseTagList + +static long +ParseTagList( char * buffer, TagPtr * tag, long type, long empty ) +{ + long length, pos; + TagPtr tagList, tmpTag; + + tagList = 0; + pos = 0; + + if (!empty) + { + while (1) + { + length = XMLParseNextTag(buffer + pos, &tmpTag); + if (length == -1) break; + + pos += length; + + if (tmpTag == 0) break; + tmpTag->tagNext = tagList; + tagList = tmpTag; + } + + if (length == -1) + { + XMLFreeTag(tagList); + return -1; + } + } + + tmpTag = NewTag(); + if (tmpTag == 0) + { + XMLFreeTag(tagList); + return -1; + } + + tmpTag->type = type; + tmpTag->string = 0; + tmpTag->offset = buffer_start ? buffer - buffer_start : 0; + tmpTag->tag = tagList; + tmpTag->tagNext = 0; + + *tag = tmpTag; + + return pos; +} + +//========================================================================== +// ParseTagKey + +static long +ParseTagKey( char * buffer, TagPtr * tag ) +{ + long length, length2; + char *string; + TagPtr tmpTag, subTag; + + length = FixDataMatchingTag(buffer, kXMLTagKey); + if (length == -1) return -1; + + length2 = XMLParseNextTag(buffer + length, &subTag); + if (length2 == -1) return -1; + + tmpTag = NewTag(); + if (tmpTag == 0) + { + XMLFreeTag(subTag); + return -1; + } + + string = NewSymbol(buffer); + if (string == 0) + { + XMLFreeTag(subTag); + XMLFreeTag(tmpTag); + return -1; + } + + tmpTag->type = kTagTypeKey; + tmpTag->string = string; + tmpTag->tag = subTag; + tmpTag->offset = buffer_start ? buffer - buffer_start: 0; + tmpTag->tagNext = 0; + + *tag = tmpTag; + + return length + length2; +} + +//========================================================================== +// ParseTagString + +static long +ParseTagString( char * buffer, TagPtr * tag ) +{ + long length; + char * string; + TagPtr tmpTag; + + length = FixDataMatchingTag(buffer, kXMLTagString); + if (length == -1) return -1; + + tmpTag = NewTag(); + if (tmpTag == 0) return -1; + + string = NewSymbol(buffer); + if (string == 0) + { + XMLFreeTag(tmpTag); + return -1; + } + + tmpTag->type = kTagTypeString; + tmpTag->string = string; + tmpTag->tag = 0; + tmpTag->offset = buffer_start ? buffer - buffer_start: 0; + tmpTag->tagNext = 0; + + *tag = tmpTag; + return length; +} + +//========================================================================== +// ParseTagInteger + +static long +ParseTagInteger( char * buffer, TagPtr * tag ) +{ + long length, integer; + bool negative = false; + TagPtr tmpTag; + char* val = buffer; + int size; + + size = length = FixDataMatchingTag(buffer, kXMLTagInteger); + if (length == -1) return -1; + + tmpTag = NewTag(); + if (tmpTag == 0) return -1; + + integer = 0; + + if(buffer[0] == '<') + { + verbose("Warning integer is non existant\n"); + //getc(); + tmpTag->type = kTagTypeInteger; + tmpTag->string = 0; + tmpTag->tag = 0; + tmpTag->offset = 0; + tmpTag->tagNext = 0; + + *tag = tmpTag; + + return 0; + } + + + if(size > 1 && (val[1] == 'x' || val[1] == 'X')) // Hex value + { + val += 2; + while(*val) + { + if ((*val >= '0' && *val <= '9')) // 0 - 9 + { + integer = (integer * 16) + (*val++ - '0'); + } + else if ((*val >= 'a' && *val <= 'f')) // a - f + { + integer = (integer * 16) + (*val++ - 'a' + 10); + } + else if ((*val >= 'A' && *val <= 'F')) // A - F + { + integer = (integer * 16) + (*val++ - 'a' + 10); + } + else + { + verbose("ParseTagInteger hex error (0x%x) in buffer %s\n", *val, buffer); + getc(); + return -1; + + } + + } + } + else if ( size ) // Decimal value + { + if (*val == '-') + { + negative = true; + val++; + size--; + } + + for (integer = 0; size > 0; size--) + { + if(*val) // UGLY HACK, fix me. + { + if (*val < '0' || *val > '9') + { + verbose("ParseTagInteger decimal error (0x%x) in buffer %s\n", *val, buffer); + getc(); + return -1; + } + + integer = (integer * 10) + (*val++ - '0'); + } + } + + if (negative) + integer = -integer; + } + + tmpTag->type = kTagTypeInteger; + tmpTag->string = (char *)integer; + tmpTag->tag = 0; + tmpTag->offset = buffer_start ? buffer - buffer_start: 0; + tmpTag->tagNext = 0; + + *tag = tmpTag; + + return length; +} + +//========================================================================== +// ParseTagData + +static long +ParseTagData( char * buffer, TagPtr * tag ) +{ + long length; + TagPtr tmpTag; + + length = FixDataMatchingTag(buffer, kXMLTagData); + if (length == -1) return -1; + + tmpTag = NewTag(); + if (tmpTag == 0) return -1; + + //printf("ParseTagData unimplimented\n"); + //printf("Data: %s\n", buffer); + // getc(); + + // TODO: base64 decode + + char* string = NewSymbol(buffer); + tmpTag->type = kTagTypeData; + tmpTag->string = string; + tmpTag->tag = 0; + tmpTag->offset = buffer_start ? buffer - buffer_start: 0; + tmpTag->tagNext = 0; + + *tag = tmpTag; + + return length; +} + +//========================================================================== +// ParseTagDate + +static long +ParseTagDate( char * buffer, TagPtr * tag ) +{ + long length; + TagPtr tmpTag; + + length = FixDataMatchingTag(buffer, kXMLTagDate); + if (length == -1) return -1; + + tmpTag = NewTag(); + if (tmpTag == 0) return -1; + + verbose("ParseTagDate unimplimented\n"); + getc(); + + tmpTag->type = kTagTypeDate; + tmpTag->string = 0; + tmpTag->tag = 0; + tmpTag->offset = buffer_start ? buffer - buffer_start: 0; + tmpTag->tagNext = 0; + + *tag = tmpTag; + + return length; +} + +//========================================================================== +// ParseTagBoolean + +static long +ParseTagBoolean( char * buffer, TagPtr * tag, long type ) +{ + TagPtr tmpTag; + + tmpTag = NewTag(); + if (tmpTag == 0) return -1; + + tmpTag->type = type; + tmpTag->string = 0; + tmpTag->tag = 0; + tmpTag->offset = buffer_start ? buffer - buffer_start: 0; + tmpTag->tagNext = 0; + + *tag = tmpTag; + + return 0; +} + +//========================================================================== +// GetNextTag + +static long +GetNextTag( char * buffer, char ** tag, long * start ) +{ + long cnt, cnt2; + + if (tag == 0) return -1; + + // Find the start of the tag. + cnt = 0; + while ((buffer[cnt] != '\0') && (buffer[cnt] != '<')) cnt++; + if (buffer[cnt] == '\0') return -1; + + // Find the end of the tag. + cnt2 = cnt + 1; + while ((buffer[cnt2] != '\0') && (buffer[cnt2] != '>')) cnt2++; + if (buffer[cnt2] == '\0') return -1; + + // Fix the tag data. + *tag = buffer + cnt + 1; + buffer[cnt2] = '\0'; + if (start) *start = cnt; + + return cnt2 + 1; +} + +//========================================================================== +// FixDataMatchingTag +// Modifies 'buffer' to add a '\0' at the end of the tag matching 'tag'. +// Returns the length of the data found, counting the end tag, +// or -1 if the end tag was not found. + +static long +FixDataMatchingTag( char * buffer, char * tag ) +{ + long length, start, stop; + char * endTag; + + start = 0; + while (1) + { + length = GetNextTag(buffer + start, &endTag, &stop); + if (length == -1) return -1; + + if ((*endTag == '/') && !strcmp(endTag + 1, tag)) break; + start += length; + } + + buffer[start + stop] = '\0'; + + return start + length; +} + +//========================================================================== +// NewTag + +#define kTagsPerBlock (0x1000) + +static TagPtr gTagsFree; + +static TagPtr +NewTag( void ) +{ + long cnt; + TagPtr tag; + + if (gTagsFree == 0) + { +#if USEMALLOC + tag = (TagPtr)malloc(kTagsPerBlock * sizeof(Tag)); +#else + tag = (TagPtr)AllocateBootXMemory(kTagsPerBlock * sizeof(Tag)); +#endif + if (tag == 0) return 0; + + // Initalize the new tags. + for (cnt = 0; cnt < kTagsPerBlock; cnt++) + { + tag[cnt].type = kTagTypeNone; + tag[cnt].string = 0; + tag[cnt].tag = 0; + tag[cnt].tagNext = tag + cnt + 1; + } + tag[kTagsPerBlock - 1].tagNext = 0; + + gTagsFree = tag; + } + + tag = gTagsFree; + gTagsFree = tag->tagNext; + + return tag; +} + +//========================================================================== +// XMLFreeTag + +void +XMLFreeTag( TagPtr tag ) +{ +#if DOFREE + if (tag == 0) return; + + if (tag->string) FreeSymbol(tag->string); + + XMLFreeTag(tag->tag); + XMLFreeTag(tag->tagNext); + + // Clear and free the tag. + tag->type = kTagTypeNone; + tag->string = 0; + tag->tag = 0; + tag->offset = 0; + tag->tagNext = gTagsFree; + gTagsFree = tag; +#else + return; +#endif +} + +//========================================================================== +// Symbol object. + +struct Symbol +{ + long refCount; + struct Symbol *next; + char string[]; +}; +typedef struct Symbol Symbol, *SymbolPtr; + +static SymbolPtr FindSymbol(char * string, SymbolPtr * prevSymbol); + +static SymbolPtr gSymbolsHead; + +//========================================================================== +// NewSymbol + +static char * +NewSymbol( char * string ) +{ +static SymbolPtr lastGuy = 0; + SymbolPtr symbol; + + // Look for string in the list of symbols. + symbol = FindSymbol(string, 0); + + // Add the new symbol. + if (symbol == 0) + { +#if USEMALLOC + symbol = (SymbolPtr)malloc(sizeof(Symbol) + 1 + strlen(string)); +#else + symbol = (SymbolPtr)AllocateBootXMemory(sizeof(Symbol) + 1 + strlen(string)); +#endif + if (symbol == 0) //return 0; + stop("NULL symbol!"); + + // Set the symbol's data. + symbol->refCount = 0; + strcpy(symbol->string, string); + + // Add the symbol to the list. + symbol->next = gSymbolsHead; + gSymbolsHead = symbol; + } + + // Update the refCount and return the string. + symbol->refCount++; + + if (lastGuy && lastGuy->next != 0) stop("last guy not last!"); + return symbol->string; +} + +//========================================================================== +// FreeSymbol + +#if DOFREE +static void +FreeSymbol( char * string ) +{ + SymbolPtr symbol, prev; + prev = 0; + + // Look for string in the list of symbols. + symbol = FindSymbol(string, &prev); + if (symbol == 0) return; + + // Update the refCount. + symbol->refCount--; + + if (symbol->refCount != 0) return; + + // Remove the symbol from the list. + if (prev != 0) prev->next = symbol->next; + else gSymbolsHead = symbol->next; + + // Free the symbol's memory. + free(symbol); +} +#endif + +//========================================================================== +// FindSymbol + +static SymbolPtr +FindSymbol( char * string, SymbolPtr * prevSymbol ) +{ + SymbolPtr symbol, prev; + + symbol = gSymbolsHead; + prev = 0; + + while (symbol != 0) { + if (!strcmp(symbol->string, string)) break; + + prev = symbol; + symbol = symbol->next; + } + + if ((symbol != 0) && (prevSymbol != 0)) *prevSymbol = prev; + + return symbol; +} + + + +bool XMLIsType(TagPtr dict, enum xmltype type) +{ + if(!dict) return (type == kTagTypeNone); + return (dict->type == type); +} + + +/*** Cast functions ***/ +TagPtr XMLCastArray(TagPtr dict) +{ + if(!dict) return NULL; + if(dict->type == kTagTypeArray) return dict; + else return NULL; +} + + +TagPtr XMLCastDict(TagPtr dict) +{ + if(!dict) return NULL; + if(dict->type == kTagTypeDict) return dict; + else return NULL; +} + +char* XMLCastString(TagPtr dict) +{ + if(!dict) return NULL; + + if((dict->type == kTagTypeString) || + (dict->type == kTagTypeKey)) return dict->string; + + return NULL; +} + +long XMLCastStringOffset(TagPtr dict) +{ + if(dict && + ((dict->type == kTagTypeString) || + (dict->type == kTagTypeKey))) + { + return dict->offset; + } + else + { + return -1; + } +} + + +bool XMLCastBoolean(TagPtr dict) +{ + if(!dict) return false; + if(dict->type == kTagTypeTrue) return true; + return false; +} + +int XMLCastInteger(TagPtr dict) +{ + if(!dict) + { + verbose("XMLCastInteger: null dict\n"); + return 0; + } + if(dict->type == kTagTypeInteger) return (int)(dict->string); + return 0; +} Index: branches/slice/rev749/libsaio/asm.s =================================================================== --- branches/slice/rev749/libsaio/asm.s (revision 0) +++ branches/slice/rev749/libsaio/asm.s (revision 1169) @@ -0,0 +1,550 @@ +/* + * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 2.0 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Mach Operating System + * Copyright (c) 1990 Carnegie-Mellon University + * Copyright (c) 1989 Carnegie-Mellon University + * All rights reserved. The CMU software License Agreement specifies + * the terms and conditions for use and redistribution. + */ +/* + * HISTORY + * $Log: asm.s,v $ + * Revision 1.8 2005/06/24 22:47:12 curtisg + * Merging changes for 4159531 to pass data to the kernel in EFI format. + * + * Revision 1.7 2004/05/13 17:58:38 curtisg + * Integrating: + * : (Silent boot) + * : (5 sec boot timeout is too short) + * : (Boot option to display graphics modes) + * : (Default graphics mode should be 32-bit) + * : (Booter should always find a video mode) + * : (Booter displays "0MB" VRAM) + * + * Revision 1.6 2003/11/05 20:51:02 curtisg + * Integrated 3069695,3331770,3370488,3371823 + * + * Revision 1.5.26.1 2003/10/27 23:57:59 curtisg + * Added printing of volume names, better handling of extended + * partitions, and updated Apple license strings. + * New chain booter should work better with foreign operating + * systems. + * + * Revision 1.5 2002/11/05 20:34:26 jliu + * Integrating: + * 3051234 boot shouldnt require Graphics = Yes + * 3091627 Need support for refresh rate adjustment + * + * Revision 1.4 2002/10/02 00:06:18 curtisg + * Integrating PR-3032510. + * + * Revision 1.3.6.1 2002/08/30 21:16:29 curtisg + * KERNBOOTSTRUCT is going away in favor of KernelBootArgs_t in . + * + * Revision 1.3 2002/07/09 14:06:21 jliu + * Merging changes from PR-2954224 branch in boot/i386. + * + * Revision 1.2.30.1 2002/07/05 16:24:51 jliu + * Merged UFS/HFS/HFS+ filesystem support from BootX. + * Moved boot2 load address due to increased size. boot0/boot1 also changed. + * Updated boot graphics and CLUT. + * Added support to chain load foreign booters. + * Fixed param passing bug in network loader. + * Misc cleanup in libsaio. + * + * Revision 1.2 2000/05/23 23:01:11 lindak + * Merged PR-2309530 into Kodiak (liu i386 booter: does not support label-less + * ufs partitions) + * + * Revision 1.1.1.2.4.1 2000/05/13 17:07:39 jliu + * New boot0 (boot1 has been deprecated). Booter must now reside in its own partition, no disk label required. + * + * Revision 1.1.1.2 1999/08/04 21:16:57 wsanchez + * Impoort of boot-66 + * + * Revision 1.3 1999/08/04 21:12:12 wsanchez + * Update APSL + * + * Revision 1.2 1999/03/25 05:48:30 wsanchez + * Add APL. + * Remove unused gzip code. + * Remove unused Adobe fonts. + * + * Revision 1.1.1.1.66.2 1999/03/16 16:08:54 wsanchez + * Substitute License + * + * Revision 1.1.1.1.66.1 1999/03/16 07:33:21 wsanchez + * Add APL + * + * Revision 1.1.1.1 1997/12/05 21:57:57 wsanchez + * Import of boot-25 (~mwatson) + * + * Revision 2.1.1.2 90//03//22 17:59:50 rvb + * Added _sp() => where is the stack at. [kupfer] + * + * Revision 2.1.1.1 90//02//09 17:25:04 rvb + * Add Intel copyright + * [90//02//09 rvb] + * + */ + + +// INTEL CORPORATION PROPRIETARY INFORMATION +// +// This software is supplied under the terms of a license agreement or +// nondisclosure agreement with Intel Corporation and may not be copied +// nor disclosed except in accordance with the terms of that agreement. +// +// Copyright 1988 Intel Corporation +// Copyright 1988, 1989 by Intel Corporation +// + +#include +#include "memory.h" + +#define data32 .byte 0x66 +#define addr32 .byte 0x67 + + .file "asm.s" + +CR0_PE_ON = 0x1 +#ifdef BOOT1 +CR0_PE_OFF = 0x7ffffffe +#else +CR0_PE_OFF = 0x7ffffff0 +#endif + +STACK32_BASE = ADDR32(STACK_SEG, 0) +STACK16_SEG = STACK_SEG +CODE32_BASE = ADDR32(BASE_SEG, 0) +CODE16_SEG = BASE_SEG + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Pointer to 6-bytes in memory that contains the base address and the limit +// (size of GDT table in bytes) of the GDT. The LGDT is the only instruction +// that directly loads a linear address (not a segment relative address) and +// a limit in protected mode. + +.globl _Gdtr + //.data + .section __INIT,__data // turbo - Data that must be in the first segment + .align 2, 0x90 +_Gdtr: + .word GDTLIMIT + .long vtop(_Gdt) + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// IDTR representing real-mode IVT. The values are constant. + //.const + .section __INIT,__data // turbo - Data that must be in the first segment +// Real mode IDT + .align 2 +.globl _Idtr_real +_Idtr_real: + .word 0x03ff + .long 0x00000000 + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// IDTR representing protected-mode IDT. It is initially NULL which tells the +// procesor that no IDT is available. After we get into protected mode we can +// allocate memory for a proper IDT and update this IDTR to point to it. + //.data + .section __INIT,__data // turbo - Data that must be in the first segment + .align 2 +.globl _Idtr_prot +_Idtr_prot: + .word 0 + .long 0 + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Data area for __switch_stack. +// +save_sp: .long STACK_OFS +save_ss: .long STACK_SEG + + //.text + .section __INIT,__text // turbo - This code must reside within the first segment +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// real_to_prot() +// +// Transfer from real mode to protected mode. +// Preserves all registers except EAX. +// +LABEL(__real_to_prot) + + // Interrupts are disabled in protected mode. + + cli + + // Load the Global Descriptor Table Register (GDTR). + + addr32 + data32 + lgdt OFFSET16(_Gdtr) + + // Enter protected mode by setting the PE bit in CR0. + + mov %cr0, %eax + data32 + or $CR0_PE_ON, %eax + mov %eax, %cr0 + + // Make intrasegment jump to flush the processor pipeline and + // reload CS register. + + data32 + ljmp $0x08, $xprot + +xprot: + // we are in USE32 mode now + // set up the protected mode segment registers : DS, SS, ES, FS, GS + + mov $0x10, %eax + movw %ax, %ds + movw %ax, %ss + movw %ax, %es + movw %ax, %fs + movw %ax, %gs + + // set up the PM IDT + lidt _Idtr_prot + + // Convert STACK_SEG:SP to 32-bit linear stack pointer. + + movzwl %sp, %eax + addl $STACK32_BASE, %eax + movl %eax, %esp + + // Convert STACK_SEG:BP to 32-bit linear base pointer. + + movzwl %bp, %eax + addl $STACK32_BASE, %eax + movl %eax, %ebp + + // Modify the caller's return address on the stack from + // segment offset to linear address. + + popl %eax + addl $CODE32_BASE, %eax + pushl %eax + + ret + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// prot_to_real() +// +// Transfer from protected mode to real mode. +// Preserves all registers except EAX. +// +LABEL(__prot_to_real) + + // Load real-mode IDT while we're still in USE32 mode so we don't need + // 32-bit addressing prefixes. + lidt _Idtr_real + + // Set up segment registers appropriate for real mode. + + movw $0x30, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + movw %ax, %gs + movw %ax, %ss + + ljmp $0x18, $x16 // change to USE16 mode + +x16: + mov %cr0, %eax // clear the PE bit of CR0 + data32 + and $CR0_PE_OFF, %eax + mov %eax, %cr0 + + // make intersegment jmp to flush the processor pipeline + // and reload CS register + + data32 + ljmp $CODE16_SEG, $xreal - CODE32_BASE + +xreal: + // we are in real mode now + // set up the real mode segment registers : DS, DS, ES, FS, GS + + movw %cs, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + movw %ax, %gs + + // load stack segment register SS. + + data32 + movl $STACK16_SEG, %eax + movw %ax, %ss + + // clear top 16-bits of ESP and EBP. + + data32 + movzwl %sp, %esp + data32 + movzwl %bp, %ebp + + // Modify caller's return address on the stack + // from linear address to segment offset. + + data32 + popl %eax + data32 + movzwl %ax, %eax + data32 + pushl %eax + + // Reenable maskable interrupts. + + sti + + data32 + ret + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// halt() +// +LABEL(_halt) +#ifdef BOOT1 + hlt +#else + call _bgetc +#endif + jmp _halt + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// disableIRQs() +// +// Port of original patch by: CPARM (who basically did this in boot.c) Thanks! +// +LABEL(_disableIRQs) + // The ACPI specification dictates that the 8259 (PC-AT compatible) vectors + // must be disabled (that is, masked) when enabling the ACPI APIC operation + // but this isn't done (apparently) on all mobo's and thus we do that here. + + push %eax // Saving register data + + movb $0x80, %al // Block NMI + outb %al, $0x70 + + movb $0xff, %al // Load mask + outb %al, $0x21 // Disable IRQ's 0-7 on Master PIC + outb %al, $0xa1 // Disable IRQ's 8-15 on Slave PIC + + popl %eax // Restore register data + + ret + + +#ifndef BOOT1 +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// startMachKernel(phyaddr, bootargs) +// +// Starts the Mach Kernel in protected mode where phyaddr is the entry point. +// Passes boot arguments in %eax. +// +LABEL(_startMachKernel) + call _disableIRQs // Taking care of a ACPI bug. + + push %ebp + mov %esp, %ebp + + mov 0xc(%ebp), %eax // bootargs to mach_kernel + mov 0x8(%ebp), %ecx // entry offset + mov $0x28, %ebx // segment + push %ebx + push %ecx + + // set up %ds and %es + + mov $0x20, %ebx + movw %bx, %ds + movw %bx, %es + + lret + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// startprog(phyaddr, arg) +// Start the program on protected mode where phyaddr is the entry point. +// Passes arg to the program in %eax. +// +LABEL(_startprog) + push %ebp + mov %esp, %ebp + + mov 0xc(%ebp), %eax // argument to program + mov 0x8(%ebp), %ecx // entry offset + mov $0x28, %ebx // segment + push %ebx + push %ecx + + // set up %ds and %es + + mov $0x20, %ebx + movw %bx, %ds + movw %bx, %es + + lret +#endif + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Returns the current stack pointer. +// +LABEL(__sp) + mov %esp, %eax + ret + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Returns the current frame pointer. +// +LABEL(__bp) + mov %ebp, %eax + ret + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// switch_stack() +// +// Switches stack pointer between SS:SP and memory save_ss:save_sp. +// Call this function from real mode only!!! +// +// AX, DI, and SI are clobbered. +// +LABEL(__switch_stack) + popl %eax # save return address + popl %edi # discard upper 16-bit + + data32 + addr32 + movl OFFSET16(save_ss), %esi # new SS to SI + + data32 + addr32 + movl OFFSET16(save_sp), %edi # new SP to DI + + addr32 + mov %ss, OFFSET16(save_ss) # save current SS to memory + + data32 + addr32 + movl %esp, OFFSET16(save_sp) # save current SP to memory + + cli + mov %si, %ss # switch stack + mov %di, %sp + sti + + pushl %eax # push IP of caller onto the new stack + + xorl %eax, %eax + xorl %esi, %esi + xorl %edi, %edi + + ret + +#ifndef BOOT1 +#if UNUSED +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// loader() +// +// Issue a request to the network loader. +// +LABEL(_loader) + enter $0, $0 + pushal + + # + # Pass a far pointer to the command structure + # to the INT call through DX:CX. + # + # The command code is in BX. + # + + movw 8(%ebp), %bx # 8[EBP] = command code + movw 12(%ebp), %cx # 12[EBP] = command structure offset + movw 14(%ebp), %dx # 14[EBP] = command structure segment + + call __prot_to_real # Revert to real mode + + ###### Real Mode Begin ###### + + data32 + call __switch_stack # Switch to NBP stack + + int $0x2b # Call NBP + + data32 + call __switch_stack # Restore stack + + data32 + call __real_to_prot # Back to protected mode + + ###### Real Mode End ###### + + popal + leave + ret +#endif +#endif + +#if UNUSED +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// pcpy(src, dst, cnt) +// where src is a virtual address and dst is a physical address +// +LABEL(_pcpy) + push %ebp + mov %esp, %ebp + push %es + push %esi + push %edi + push %ecx + + cld + + // set %es to point at the flat segment + + mov $0x20, %eax + movw %ax , %es + + mov 0x8(%ebp), %esi // source + mov 0xc(%ebp), %edi // destination + mov 0x10(%ebp), %ecx // count + + rep + movsb + + pop %ecx + pop %edi + pop %esi + pop %es + pop %ebp + + ret +#endif Index: branches/slice/rev749/libsaio/console.c =================================================================== --- branches/slice/rev749/libsaio/console.c (revision 0) +++ branches/slice/rev749/libsaio/console.c (revision 1169) @@ -0,0 +1,246 @@ +/* + * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 2.0 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Mach Operating System + * Copyright (c) 1990 Carnegie-Mellon University + * Copyright (c) 1989 Carnegie-Mellon University + * All rights reserved. The CMU software License Agreement specifies + * the terms and conditions for use and redistribution. + */ + +/* + * INTEL CORPORATION PROPRIETARY INFORMATION + * + * This software is supplied under the terms of a license agreement or + * nondisclosure agreement with Intel Corporation and may not be copied + * nor disclosed except in accordance with the terms of that agreement. + * + * Copyright 1988, 1989 Intel Corporation + */ + +/* + * Copyright 1993 NeXT, Inc. + * All rights reserved. + */ + +#include "libsaio.h" +#include "bootstruct.h" + +extern int vprf(const char * fmt, va_list ap); + +bool gVerboseMode; +bool gErrors; + +/* Kabyl: BooterLog */ +#define BOOTER_LOG_SIZE (64 * 1024) +#define SAFE_LOG_SIZE 80 + +char *msgbuf = 0; +char *cursor = 0; + +struct putc_info { + char * str; + char * last_str; +}; + +void sputc(int c, struct putc_info * pi) +{ + if (pi->last_str) + if (pi->str == pi->last_str) + { + *(pi->str) = '\0'; + return; + } + *(pi->str)++ = c; +} + +void initBooterLog(void) +{ + msgbuf = malloc(BOOTER_LOG_SIZE); + bzero(msgbuf, BOOTER_LOG_SIZE); + cursor = msgbuf; +} + +void msglog(const char * fmt, ...) +{ + va_list ap; + struct putc_info pi; + + if (!msgbuf) + return; + + if (((cursor - msgbuf) > (BOOTER_LOG_SIZE - SAFE_LOG_SIZE))) + return; + + va_start(ap, fmt); + pi.str = cursor; + pi.last_str = 0; + prf(fmt, ap, sputc, &pi); + va_end(ap); + cursor += strlen((char *)cursor); +} + +void setupBooterLog(void) +{ + if (!msgbuf) + return; + + Node *node = DT__FindNode("/", false); + if (node) + DT__AddProperty(node, "boot-log", strlen((char *)msgbuf) + 1, msgbuf); +} +/* Kabyl: !BooterLog */ + + +/* + * write one character to console + */ +void putchar(int c) +{ + if ( c == '\t' ) + { + for (c = 0; c < 8; c++) putc(' '); + return; + } + + if ( c == '\n' ) + { + putc('\r'); + } + + putc(c); +} + +int getc() +{ + int c = bgetc(); + + if ((c & 0xff) == 0) + return c; + else + return (c & 0xff); +} + +// Read and echo a character from console. This doesn't echo backspace +// since that screws up higher level handling + +int getchar() +{ + register int c = getc(); + + if ( c == '\r' ) c = '\n'; + + if ( c >= ' ' && c < 0x7f) putchar(c); + + return (c); +} + +int printf(const char * fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + + prf(fmt, ap, putchar, 0); + + { + /* Kabyl: BooterLog */ + struct putc_info pi; + + if (!msgbuf) + return 0; + + if (((cursor - msgbuf) > (BOOTER_LOG_SIZE - SAFE_LOG_SIZE))) + return 0; + pi.str = cursor; + pi.last_str = 0; + prf(fmt, ap, sputc, &pi); + cursor += strlen((char *)cursor); + } + + va_end(ap); + return 0; +} + +int verbose(const char * fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + if (gVerboseMode) + { + prf(fmt, ap, putchar, 0); + } + + { + /* Kabyl: BooterLog */ + struct putc_info pi; + + if (!msgbuf) + return 0; + + if (((cursor - msgbuf) > (BOOTER_LOG_SIZE - SAFE_LOG_SIZE))) + return 0; + pi.str = cursor; + pi.last_str = 0; + prf(fmt, ap, sputc, &pi); + cursor += strlen((char *)cursor); + } + + va_end(ap); + return(0); +} + +int error(const char * fmt, ...) +{ + va_list ap; + gErrors = true; + va_start(ap, fmt); + + prf(fmt, ap, putchar, 0); + + va_end(ap); + return(0); +} + +void stop(const char * fmt, ...) +{ + va_list ap; + + printf("\n"); + va_start(ap, fmt); + + prf(fmt, ap, putchar, 0); + + va_end(ap); + printf("\nThis is a non recoverable error! System HALTED!!!"); + halt(); + while (1); +} + +/** Print a "Press a key to continue..." message and wait for a key press. */ +void pause() +{ + printf("Press a key to continue..."); + getc(); +} Index: branches/slice/rev749/libsaio/shortatombios.h =================================================================== --- branches/slice/rev749/libsaio/shortatombios.h (revision 0) +++ branches/slice/rev749/libsaio/shortatombios.h (revision 1169) @@ -0,0 +1,192 @@ +/****************************************************************************/ +/*Portion I: Definitions shared between VBIOS and Driver */ +/****************************************************************************/ + + +#ifndef _SHORT_ATOMBIOS_H +#define _SHORT_ATOMBIOS_H + +#define ATOM_VERSION_MAJOR 0x00020000 +#define ATOM_VERSION_MINOR 0x00000002 + +#define ATOM_HEADER_VERSION (ATOM_VERSION_MAJOR | ATOM_VERSION_MINOR) + +typedef unsigned char BOOLEAN; +typedef signed char INT8; +typedef unsigned char UINT8; +typedef signed short INT16; +typedef unsigned short UINT16; +typedef signed long INT32; +typedef unsigned long UINT32; +typedef unsigned char CHAR8; +typedef unsigned short CHAR16; +typedef unsigned short USHORT; +typedef unsigned char UCHAR; +typedef unsigned long ULONG; + +#pragma pack(1) /* BIOS data must use byte aligment */ + +/* Define offset to location of ROM header. */ + +#define OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER 0x00000048L +#define OFFSET_TO_ATOM_ROM_IMAGE_SIZE 0x00000002L + +typedef struct _ATOM_COMMON_TABLE_HEADER +{ + USHORT usStructureSize; + UCHAR ucTableFormatRevision; /*Change it when the Parser is not backward compatible */ + UCHAR ucTableContentRevision; /*Change it only when the table needs to change but the firmware */ + /*Image can't be updated, while Driver needs to carry the new table! */ +} ATOM_COMMON_TABLE_HEADER; + +typedef struct _ATOM_ROM_HEADER +{ + ATOM_COMMON_TABLE_HEADER sHeader; + UCHAR uaFirmWareSignature[4]; /*Signature to distinguish between Atombios and non-atombios, + + atombios should init it as "ATOM", don't change the position */ + USHORT usBiosRuntimeSegmentAddress; + USHORT usProtectedModeInfoOffset; + USHORT usConfigFilenameOffset; + USHORT usCRC_BlockOffset; + USHORT usBIOS_BootupMessageOffset; + USHORT usInt10Offset; + USHORT usPciBusDevInitCode; + USHORT usIoBaseAddress; + USHORT usSubsystemVendorID; + USHORT usSubsystemID; + USHORT usPCI_InfoOffset; + USHORT usMasterCommandTableOffset; /*Offset for SW to get all command table offsets, Don't change the position */ + USHORT usMasterDataTableOffset; /*Offset for SW to get all data table offsets, Don't change the position */ + UCHAR ucExtendedFunctionCode; + UCHAR ucReserved; +} ATOM_ROM_HEADER; + +/****************************************************************************/ +// Structure used in Data.mtb +/****************************************************************************/ +typedef struct _ATOM_MASTER_LIST_OF_DATA_TABLES +{ + USHORT UtilityPipeLine; // Offest for the utility to get parser info,Don't change this position! + USHORT MultimediaCapabilityInfo; // Only used by MM Lib,latest version 1.1, not configuable from Bios, need to include the table to build Bios + USHORT MultimediaConfigInfo; // Only used by MM Lib,latest version 2.1, not configuable from Bios, need to include the table to build Bios + USHORT StandardVESA_Timing; // Only used by Bios + USHORT FirmwareInfo; // Shared by various SW components,latest version 1.4 + USHORT DAC_Info; // Will be obsolete from R600 + USHORT LVDS_Info; // Shared by various SW components,latest version 1.1 + USHORT TMDS_Info; // Will be obsolete from R600 + USHORT AnalogTV_Info; // Shared by various SW components,latest version 1.1 + USHORT SupportedDevicesInfo; // Will be obsolete from R600 + USHORT GPIO_I2C_Info; // Shared by various SW components,latest version 1.2 will be used from R600 + USHORT VRAM_UsageByFirmware; // Shared by various SW components,latest version 1.3 will be used from R600 + USHORT GPIO_Pin_LUT; // Shared by various SW components,latest version 1.1 + USHORT VESA_ToInternalModeLUT; // Only used by Bios + USHORT ComponentVideoInfo; // Shared by various SW components,latest version 2.1 will be used from R600 + USHORT PowerPlayInfo; // Shared by various SW components,latest version 2.1,new design from R600 + USHORT CompassionateData; // Will be obsolete from R600 + USHORT SaveRestoreInfo; // Only used by Bios + USHORT PPLL_SS_Info; // Shared by various SW components,latest version 1.2, used to call SS_Info, change to new name because of int ASIC SS info + USHORT OemInfo; // Defined and used by external SW, should be obsolete soon + USHORT XTMDS_Info; // Will be obsolete from R600 + USHORT MclkSS_Info; // Shared by various SW components,latest version 1.1, only enabled when ext SS chip is used + USHORT Object_Header; // Shared by various SW components,latest version 1.1 + USHORT IndirectIOAccess; // Only used by Bios,this table position can't change at all!! + USHORT MC_InitParameter; // Only used by command table + USHORT ASIC_VDDC_Info; // Will be obsolete from R600 + USHORT ASIC_InternalSS_Info; // New tabel name from R600, used to be called "ASIC_MVDDC_Info" + USHORT TV_VideoMode; // Only used by command table + USHORT VRAM_Info; // Only used by command table, latest version 1.3 + USHORT MemoryTrainingInfo; // Used for VBIOS and Diag utility for memory training purpose since R600. the new table rev start from 2.1 + USHORT IntegratedSystemInfo; // Shared by various SW components + USHORT ASIC_ProfilingInfo; // New table name from R600, used to be called "ASIC_VDDCI_Info" for pre-R600 + USHORT VoltageObjectInfo; // Shared by various SW components, latest version 1.1 + USHORT PowerSourceInfo; // Shared by various SW components, latest versoin 1.1 +} ATOM_MASTER_LIST_OF_DATA_TABLES; + +typedef struct _ATOM_MASTER_DATA_TABLE +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ATOM_MASTER_LIST_OF_DATA_TABLES ListOfDataTables; +} ATOM_MASTER_DATA_TABLE; + +typedef union _ATOM_MODE_MISC_INFO_ACCESS +{ + USHORT usAccess; +} ATOM_MODE_MISC_INFO_ACCESS; + +/****************************************************************************/ +// Structure used in StandardVESA_TimingTable +// AnalogTV_InfoTable +// ComponentVideoInfoTable +/****************************************************************************/ +typedef struct _ATOM_MODE_TIMING +{ + USHORT usCRTC_H_Total; + USHORT usCRTC_H_Disp; + USHORT usCRTC_H_SyncStart; + USHORT usCRTC_H_SyncWidth; + USHORT usCRTC_V_Total; + USHORT usCRTC_V_Disp; + USHORT usCRTC_V_SyncStart; + USHORT usCRTC_V_SyncWidth; + USHORT usPixelClock; //in 10Khz unit + ATOM_MODE_MISC_INFO_ACCESS susModeMiscInfo; + USHORT usCRTC_OverscanRight; + USHORT usCRTC_OverscanLeft; + USHORT usCRTC_OverscanBottom; + USHORT usCRTC_OverscanTop; + USHORT usReserve; + UCHAR ucInternalModeNumber; + UCHAR ucRefreshRate; +} ATOM_MODE_TIMING; + +typedef struct _ATOM_DTD_FORMAT +{ + USHORT usPixClk; + USHORT usHActive; + USHORT usHBlanking_Time; + USHORT usVActive; + USHORT usVBlanking_Time; + USHORT usHSyncOffset; + USHORT usHSyncWidth; + USHORT usVSyncOffset; + USHORT usVSyncWidth; + USHORT usImageHSize; + USHORT usImageVSize; + UCHAR ucHBorder; + UCHAR ucVBorder; + ATOM_MODE_MISC_INFO_ACCESS susModeMiscInfo; + UCHAR ucInternalModeNumber; + UCHAR ucRefreshRate; +} ATOM_DTD_FORMAT; + +typedef struct _ATOM_LVDS_INFO_V12 +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ATOM_DTD_FORMAT sLCDTiming; + USHORT usExtInfoTableOffset; + USHORT usSupportedRefreshRate; //Refer to panel info table in ATOMBIOS extension Spec. + USHORT usOffDelayInMs; + UCHAR ucPowerSequenceDigOntoDEin10Ms; + UCHAR ucPowerSequenceDEtoBLOnin10Ms; + UCHAR ucLVDS_Misc; // Bit0:{=0:single, =1:dual},Bit1 {=0:666RGB, =1:888RGB},Bit2:3:{Grey level} + // Bit4:{=0:LDI format for RGB888, =1 FPDI format for RGB888} + // Bit5:{=0:Spatial Dithering disabled;1 Spatial Dithering enabled} + // Bit6:{=0:Temporal Dithering disabled;1 Temporal Dithering enabled} + UCHAR ucPanelDefaultRefreshRate; + UCHAR ucPanelIdentification; + UCHAR ucSS_Id; + USHORT usLCDVenderID; + USHORT usLCDProductID; + UCHAR ucLCDPanel_SpecialHandlingCap; + UCHAR ucPanelInfoSize; // start from ATOM_DTD_FORMAT to end of panel info, include ExtInfoTable + UCHAR ucReserved[2]; +} ATOM_LVDS_INFO_V12; + + +typedef struct _ATOM_STANDARD_VESA_TIMING +{ + ATOM_COMMON_TABLE_HEADER sHeader; + char * aModeTimings; // 16 is not the real array number, just for initial allocation +} ATOM_STANDARD_VESA_TIMING; + +#endif \ No newline at end of file Index: branches/slice/rev749/libsaio/xml.h =================================================================== --- branches/slice/rev749/libsaio/xml.h (revision 0) +++ branches/slice/rev749/libsaio/xml.h (revision 1169) @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 2003 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 2.0 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef __LIBSAIO_XML_H +#define __LIBSAIO_XML_H + +enum xmltype { + kTagTypeNone = 0, + kTagTypeDict, + kTagTypeKey, + kTagTypeString, + kTagTypeInteger, + kTagTypeData, + kTagTypeDate, + kTagTypeFalse, + kTagTypeTrue, + kTagTypeArray +}; + + +struct string_ref +{ + char* string; + int id; + struct string_ref* next; +}; +typedef struct string_ref string_ref; + +extern string_ref* ref_strings; + +#define kXMLTagPList "plist " +#define kXMLTagDict "dict" +#define kXMLTagKey "key" +#define kXMLTagString "string" +#define kXMLTagInteger "integer" +#define kXMLTagData "data" +#define kXMLTagDate "date" +#define kXMLTagFalse "false/" +#define kXMLTagTrue "true/" +#define kXMLTagArray "array" + +#define kXMLStringID "ID=" +#define kXMLStringIDRef "IDREF=" + + +#define kPropCFBundleIdentifier ("CFBundleIdentifier") +#define kPropCFBundleExecutable ("CFBundleExecutable") +#define kPropOSBundleRequired ("OSBundleRequired") +#define kPropOSBundleLibraries ("OSBundleLibraries") +#define kPropIOKitPersonalities ("IOKitPersonalities") +#define kPropIONameMatch ("IONameMatch") + +/* +struct Tag { + long type; + char *string; + struct Tag *tag; + struct Tag *tagNext; +}; +typedef struct Tag Tag, *TagPtr; + */ + +extern long gImageFirstBootXAddr; +extern long gImageLastKernelAddr; + +TagPtr XMLGetProperty( TagPtr dict, const char * key ); +TagPtr XMLGetElement( TagPtr dict, int id ); +int XMLTagCount( TagPtr dict ); + +bool XMLIsType(TagPtr dict, enum xmltype type); + +bool XMLCastBoolean( TagPtr dict ); +char* XMLCastString( TagPtr dict ); +long XMLCastStringOffset(TagPtr dict); +int XMLCastInteger ( TagPtr dict ); +TagPtr XMLCastDict ( TagPtr dict ); +TagPtr XMLCastArray( TagPtr dict ); + +long XMLParseNextTag(char *buffer, TagPtr *tag); +void XMLFreeTag(TagPtr tag); +char* XMLDecode(const char *in); +//========================================================================== +// XMLParseFile +// Expects to see one dictionary in the XML file. +// Puts the first dictionary it finds in the +// tag pointer and returns 0, or returns -1 if not found. +// +long XMLParseFile( char * buffer, TagPtr * dict ); + +#endif /* __LIBSAIO_XML_H */ Index: branches/slice/rev749/libsaio/efi.h =================================================================== --- branches/slice/rev749/libsaio/efi.h (revision 0) +++ branches/slice/rev749/libsaio/efi.h (revision 1169) @@ -0,0 +1,571 @@ +/* + * Copyright (c) 2005 Apple Computer, Inc. All rights reserved. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ + */ + +#ifndef _PEXPERT_I386_EFI_H +#define _PEXPERT_I386_EFI_H + +#include + +typedef uint8_t EFI_UINT8; +typedef uint16_t EFI_UINT16; +typedef uint32_t EFI_UINT32; +typedef uint64_t EFI_UINT64; + +typedef uint32_t EFI_UINTN; /* natural size for firmware, not kernel */ + +typedef int8_t EFI_INT8; +typedef int16_t EFI_INT16; +typedef int32_t EFI_INT32; +typedef int64_t EFI_INT64; + +typedef int8_t EFI_CHAR8; +typedef int16_t EFI_CHAR16; +typedef int32_t EFI_CHAR32; +typedef int64_t EFI_CHAR64; + +typedef uint32_t EFI_STATUS; +typedef uint8_t EFI_BOOLEAN; +typedef void VOID; + +typedef uint32_t EFI_PTR32; +typedef uint32_t EFI_HANDLE32; + +typedef uint64_t EFI_PTR64; +typedef uint64_t EFI_HANDLE64; +/* + +Portions Copyright 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +*/ + + +// +// Modifiers for EFI Runtime and Boot Services +// +#define EFI_RUNTIMESERVICE +#define EFIAPI +#define IN +#define OUT +#define OPTIONAL + +#define EFI_MAX_BIT 0x80000000 + +// +// Set the upper bit to indicate EFI Error. +// +#define EFIERR(a) (EFI_MAX_BIT | (a)) + +#define EFIWARN(a) (a) +#define EFI_ERROR(a) (((INTN) (a)) < 0) + +#define EFI_SUCCESS 0 +#define EFI_LOAD_ERROR EFIERR (1) +#define EFI_INVALID_PARAMETER EFIERR (2) +#define EFI_UNSUPPORTED EFIERR (3) +#define EFI_BAD_BUFFER_SIZE EFIERR (4) +#define EFI_BUFFER_TOO_SMALL EFIERR (5) +#define EFI_NOT_READY EFIERR (6) +#define EFI_DEVICE_ERROR EFIERR (7) +#define EFI_WRITE_PROTECTED EFIERR (8) +#define EFI_OUT_OF_RESOURCES EFIERR (9) +#define EFI_VOLUME_CORRUPTED EFIERR (10) +#define EFI_VOLUME_FULL EFIERR (11) +#define EFI_NO_MEDIA EFIERR (12) +#define EFI_MEDIA_CHANGED EFIERR (13) +#define EFI_NOT_FOUND EFIERR (14) +#define EFI_ACCESS_DENIED EFIERR (15) +#define EFI_NO_RESPONSE EFIERR (16) +#define EFI_NO_MAPPING EFIERR (17) +#define EFI_TIMEOUT EFIERR (18) +#define EFI_NOT_STARTED EFIERR (19) +#define EFI_ALREADY_STARTED EFIERR (20) +#define EFI_ABORTED EFIERR (21) +#define EFI_ICMP_ERROR EFIERR (22) +#define EFI_TFTP_ERROR EFIERR (23) +#define EFI_PROTOCOL_ERROR EFIERR (24) +#define EFI_INCOMPATIBLE_VERSION EFIERR (25) +#define EFI_SECURITY_VIOLATION EFIERR (26) +#define EFI_CRC_ERROR EFIERR (27) + +#define EFI_WARN_UNKNOWN_GLYPH EFIWARN (1) +#define EFI_WARN_DELETE_FAILURE EFIWARN (2) +#define EFI_WARN_WRITE_FAILURE EFIWARN (3) +#define EFI_WARN_BUFFER_TOO_SMALL EFIWARN (4) + +// +// EFI Specification Revision information +// +#define EFI_SPECIFICATION_MAJOR_REVISION 1 +#define EFI_SPECIFICATION_MINOR_REVISION 10 +//rfc4122 +typedef struct { + EFI_UINT32 time_low; + EFI_UINT16 time_mid; + EFI_UINT16 time_hi_and_version; + EFI_UINT8 clock_seq_hi_and_reserved; + EFI_UINT8 clock_seq_low; + EFI_UINT8 node[6]; +} EFI_GUID; + +#define APPLE_VENDOR_GUID \ + {0xAC39C713, 0x7E50, 0x423D, 0x88, 0x9D, {0x27,0x8F, 0xCC, 0x34, 0x22, 0xB6} } + +#define EFI_GLOBAL_VARIABLE_GUID \ + {0x8BE4DF61, 0x93CA, 0x11d2, 0xAA, 0x0D, {0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C} } + +typedef union { + EFI_GUID Guid; + EFI_UINT8 Raw[16]; +} EFI_GUID_UNION; + +// +// EFI Time Abstraction: +// Year: 2000 - 20XX +// Month: 1 - 12 +// Day: 1 - 31 +// Hour: 0 - 23 +// Minute: 0 - 59 +// Second: 0 - 59 +// Nanosecond: 0 - 999,999,999 +// TimeZone: -1440 to 1440 or 2047 +// +typedef struct { + EFI_UINT16 Year; + EFI_UINT8 Month; + EFI_UINT8 Day; + EFI_UINT8 Hour; + EFI_UINT8 Minute; + EFI_UINT8 Second; + EFI_UINT8 Pad1; + EFI_UINT32 Nanosecond; + EFI_INT16 TimeZone; + EFI_UINT8 Daylight; + EFI_UINT8 Pad2; +} EFI_TIME; + +// +// Bit definitions for EFI_TIME.Daylight +// +#define EFI_TIME_ADJUST_DAYLIGHT 0x01 +#define EFI_TIME_IN_DAYLIGHT 0x02 + +// +// Value definition for EFI_TIME.TimeZone +// +#define EFI_UNSPECIFIED_TIMEZONE 0x07FF + +typedef enum { + EfiReservedMemoryType, + EfiLoaderCode, + EfiLoaderData, + EfiBootServicesCode, + EfiBootServicesData, + EfiRuntimeServicesCode, + EfiRuntimeServicesData, + EfiConventionalMemory, + EfiUnusableMemory, + EfiACPIReclaimMemory, + EfiACPIMemoryNVS, + EfiMemoryMappedIO, + EfiMemoryMappedIOPortSpace, + EfiPalCode, + EfiMaxMemoryType +} EFI_MEMORY_TYPE; + +typedef struct { + EFI_UINT64 Signature; + EFI_UINT32 Revision; + EFI_UINT32 HeaderSize; + EFI_UINT32 CRC32; + EFI_UINT32 Reserved; +} __attribute__((aligned(8))) EFI_TABLE_HEADER; + +// +// possible caching types for the memory range +// +#define EFI_MEMORY_UC 0x0000000000000001ULL +#define EFI_MEMORY_WC 0x0000000000000002ULL +#define EFI_MEMORY_WT 0x0000000000000004ULL +#define EFI_MEMORY_WB 0x0000000000000008ULL +#define EFI_MEMORY_UCE 0x0000000000000010ULL + +// +// physical memory protection on range +// +#define EFI_MEMORY_WP 0x0000000000001000ULL +#define EFI_MEMORY_RP 0x0000000000002000ULL +#define EFI_MEMORY_XP 0x0000000000004000ULL + +// +// range requires a runtime mapping +// +#define EFI_MEMORY_RUNTIME 0x8000000000000000ULL + +typedef EFI_UINT64 EFI_PHYSICAL_ADDRESS; +typedef EFI_UINT64 EFI_VIRTUAL_ADDRESS; + +#define EFI_MEMORY_DESCRIPTOR_VERSION 1 +typedef struct { + EFI_UINT32 Type; + EFI_UINT32 Pad; + EFI_PHYSICAL_ADDRESS PhysicalStart; + EFI_VIRTUAL_ADDRESS VirtualStart; + EFI_UINT64 NumberOfPages; + EFI_UINT64 Attribute; +} __attribute__((aligned(8))) EFI_MEMORY_DESCRIPTOR; + + +typedef +EFI_RUNTIMESERVICE +EFI_STATUS +(EFIAPI *EFI_SET_VIRTUAL_ADDRESS_MAP) ( + IN EFI_UINTN MemoryMapSize, + IN EFI_UINTN DescriptorSize, + IN EFI_UINT32 DescriptorVersion, + IN EFI_MEMORY_DESCRIPTOR * VirtualMap + ) __attribute__((regparm(0))); + +typedef +EFI_RUNTIMESERVICE +EFI_STATUS +(EFIAPI *EFI_CONVERT_POINTER) ( + IN EFI_UINTN DebugDisposition, + IN OUT VOID **Address + ) __attribute__((regparm(0))); + +// +// Variable attributes +// +#define EFI_VARIABLE_NON_VOLATILE 0x00000001 +#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002 +#define EFI_VARIABLE_RUNTIME_ACCESS 0x00000004 +#define EFI_VARIABLE_READ_ONLY 0x00000008 + +typedef +EFI_RUNTIMESERVICE +EFI_STATUS +(EFIAPI *EFI_GET_VARIABLE) ( + IN EFI_CHAR16 * VariableName, + IN EFI_GUID * VendorGuid, + OUT EFI_UINT32 * Attributes OPTIONAL, + IN OUT EFI_UINTN * DataSize, + OUT VOID * Data + ) __attribute__((regparm(0))); + +typedef +EFI_RUNTIMESERVICE +EFI_STATUS +(EFIAPI *EFI_GET_NEXT_VARIABLE_NAME) ( + IN OUT EFI_UINTN * VariableNameSize, + IN OUT EFI_CHAR16 * VariableName, + IN OUT EFI_GUID * VendorGuid + ) __attribute__((regparm(0))); + +typedef +EFI_RUNTIMESERVICE +EFI_STATUS +(EFIAPI *EFI_SET_VARIABLE) ( + IN EFI_CHAR16 * VariableName, + IN EFI_GUID * VendorGuid, + IN EFI_UINT32 Attributes, + IN EFI_UINTN DataSize, + IN VOID * Data + ) __attribute__((regparm(0))); + +// +// EFI Time +// +typedef struct { + EFI_UINT32 Resolution; + EFI_UINT32 Accuracy; + EFI_BOOLEAN SetsToZero; +} __attribute__((aligned(4))) EFI_TIME_CAPABILITIES; + +typedef +EFI_RUNTIMESERVICE +EFI_STATUS +(EFIAPI *EFI_GET_TIME) ( + OUT EFI_TIME * Time, + OUT EFI_TIME_CAPABILITIES * Capabilities OPTIONAL + ) __attribute__((regparm(0))); + +typedef +EFI_RUNTIMESERVICE +EFI_STATUS +(EFIAPI *EFI_SET_TIME) ( + IN EFI_TIME * Time + ) __attribute__((regparm(0))); + +typedef +EFI_RUNTIMESERVICE +EFI_STATUS +(EFIAPI *EFI_GET_WAKEUP_TIME) ( + OUT EFI_BOOLEAN * Enabled, + OUT EFI_BOOLEAN * Pending, + OUT EFI_TIME * Time + ) __attribute__((regparm(0))); + +typedef +EFI_RUNTIMESERVICE +EFI_STATUS +(EFIAPI *EFI_SET_WAKEUP_TIME) ( + IN EFI_BOOLEAN Enable, + IN EFI_TIME * Time OPTIONAL + ) __attribute((regparm(0))); + +typedef enum { + EfiResetCold, + EfiResetWarm, + EfiResetShutdown, + +#ifdef TIANO_EXTENSION_FLAG + EfiResetUpdate +#endif + +} EFI_RESET_TYPE; + +typedef +EFI_RUNTIMESERVICE +VOID +(EFIAPI *EFI_RESET_SYSTEM) ( + IN EFI_RESET_TYPE ResetType, + IN EFI_STATUS ResetStatus, + IN EFI_UINTN DataSize, + IN EFI_CHAR16 * ResetData OPTIONAL + ) __attribute__((regparm(0))); + +typedef +EFI_RUNTIMESERVICE +EFI_STATUS +(EFIAPI *EFI_GET_NEXT_HIGH_MONO_COUNT) ( + OUT EFI_UINT32 * HighCount + ) __attribute__((regparm(0))); + +// +// Definition of Status Code extended data header +// +// HeaderSize The size of the architecture. This is specified to enable +// the future expansion +// +// Size The size of the data in bytes. This does not include the size +// of the header structure. +// +// Type A GUID defining the type of the data +// +// +#ifdef TIANO_EXTENSION_FLAG + +typedef +EFI_RUNTIMESERVICE +EFI_STATUS +(EFIAPI *EFI_REPORT_STATUS_CODE) ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN EFI_UINT32 Instance, + IN EFI_GUID * CallerId OPTIONAL, + IN EFI_STATUS_CODE_DATA * Data OPTIONAL + ) __attribute__((regparm(0))); + +#endif +// +// EFI Runtime Services Table +// +#define EFI_RUNTIME_SERVICES_SIGNATURE 0x56524553544e5552ULL +#define EFI_RUNTIME_SERVICES_REVISION ((EFI_SPECIFICATION_MAJOR_REVISION << 16) | (EFI_SPECIFICATION_MINOR_REVISION)) + +typedef struct { + EFI_TABLE_HEADER Hdr; + + // + // Time services + // + EFI_PTR32 GetTime; + EFI_PTR32 SetTime; + EFI_PTR32 GetWakeupTime; + EFI_PTR32 SetWakeupTime; + + // + // Virtual memory services + // + EFI_PTR32 SetVirtualAddressMap; + EFI_PTR32 ConvertPointer; + + // + // Variable services + // + EFI_PTR32 GetVariable; + EFI_PTR32 GetNextVariableName; + EFI_PTR32 SetVariable; + + // + // Misc + // + EFI_PTR32 GetNextHighMonotonicCount; + EFI_PTR32 ResetSystem; + +#ifdef TIANO_EXTENSION_FLAG + // + // //////////////////////////////////////////////////// + // Extended EFI Services + ////////////////////////////////////////////////////// + // + EFI_PTR32 ReportStatusCode; +#endif + +} __attribute__((aligned(8))) EFI_RUNTIME_SERVICES_32; + +typedef struct { + EFI_TABLE_HEADER Hdr; + + // + // Time services + // + EFI_PTR64 GetTime; + EFI_PTR64 SetTime; + EFI_PTR64 GetWakeupTime; + EFI_PTR64 SetWakeupTime; + + // + // Virtual memory services + // + EFI_PTR64 SetVirtualAddressMap; + EFI_PTR64 ConvertPointer; + + // + // Variable services + // + EFI_PTR64 GetVariable; + EFI_PTR64 GetNextVariableName; + EFI_PTR64 SetVariable; + + // + // Misc + // + EFI_PTR64 GetNextHighMonotonicCount; + EFI_PTR64 ResetSystem; + +#ifdef TIANO_EXTENSION_FLAG + // + // //////////////////////////////////////////////////// + // Extended EFI Services + ////////////////////////////////////////////////////// + // + EFI_PTR64 ReportStatusCode; +#endif + +} __attribute__((aligned(8))) EFI_RUNTIME_SERVICES_64; + +// +// EFI Configuration Table +// +typedef struct { + EFI_GUID VendorGuid; + EFI_PTR32 VendorTable; +} EFI_CONFIGURATION_TABLE_32; + +typedef struct { + EFI_GUID VendorGuid; + EFI_PTR64 VendorTable; +} __attribute__((aligned(8))) EFI_CONFIGURATION_TABLE_64; + +// +// EFI System Table +// +#define EFI_SYSTEM_TABLE_SIGNATURE 0x5453595320494249ULL +#define EFI_SYSTEM_TABLE_REVISION ((EFI_SPECIFICATION_MAJOR_REVISION << 16) | (EFI_SPECIFICATION_MINOR_REVISION)) +#define EFI_2_00_SYSTEM_TABLE_REVISION ((2 << 16) | 00) +#define EFI_1_02_SYSTEM_TABLE_REVISION ((1 << 16) | 02) +#define EFI_1_10_SYSTEM_TABLE_REVISION ((1 << 16) | 10) + +typedef struct EFI_SYSTEM_TABLE_32 { + EFI_TABLE_HEADER Hdr; + + EFI_PTR32 FirmwareVendor; + EFI_UINT32 FirmwareRevision; + + EFI_HANDLE32 ConsoleInHandle; + EFI_PTR32 ConIn; + + EFI_HANDLE32 ConsoleOutHandle; + EFI_PTR32 ConOut; + + EFI_HANDLE32 StandardErrorHandle; + EFI_PTR32 StdErr; + + EFI_PTR32 RuntimeServices; + EFI_PTR32 BootServices; + + EFI_UINT32 NumberOfTableEntries; + EFI_PTR32 ConfigurationTable; + +} __attribute__((aligned(8))) EFI_SYSTEM_TABLE_32; + +typedef struct EFI_SYSTEM_TABLE_64 { + EFI_TABLE_HEADER Hdr; + + EFI_PTR64 FirmwareVendor; + EFI_UINT32 FirmwareRevision; + + EFI_UINT32 __pad; + + EFI_HANDLE64 ConsoleInHandle; + EFI_PTR64 ConIn; + + EFI_HANDLE64 ConsoleOutHandle; + EFI_PTR64 ConOut; + + EFI_HANDLE64 StandardErrorHandle; + EFI_PTR64 StdErr; + + EFI_PTR64 RuntimeServices; + EFI_PTR64 BootServices; + + EFI_UINT64 NumberOfTableEntries; + EFI_PTR64 ConfigurationTable; + +} __attribute__((aligned(8))) EFI_SYSTEM_TABLE_64; + +typedef EFI_UINT8 EFI_DEVICE_PATH_PROTOCOL; + +typedef struct _BLESS_EFI_LOAD_OPTION { + EFI_UINT32 Attributes; + EFI_UINT16 FilePathListLength; + EFI_CHAR16 Description[0]; + EFI_DEVICE_PATH_PROTOCOL FilePathList[0]; + EFI_UINT8 OptionalData[0]; +} BLESS_EFI_LOAD_OPTION; + + +#endif /* _PEXPERT_I386_EFI_H */ Index: branches/slice/rev749/libsaio/bootstruct.c =================================================================== --- branches/slice/rev749/libsaio/bootstruct.c (revision 0) +++ branches/slice/rev749/libsaio/bootstruct.c (revision 1169) @@ -0,0 +1,173 @@ +/* + * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 2.0 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright 1993 NeXT, Inc. + * All rights reserved. + */ + +#include "libsaio.h" +#include "bootstruct.h" + +/*========================================================================== + * Initialize the structure of parameters passed to + * the kernel by the booter. + */ + +boot_args *bootArgs; +PrivateBootInfo_t *bootInfo; +Node *gMemoryMapNode; + +static char platformName[64]; + +void initKernBootStruct( void ) +{ + Node *node; + int nameLen; + static int init_done = 0; + + if ( !init_done ) + { + bootArgs = (boot_args *)malloc(sizeof(boot_args)); + bootInfo = (PrivateBootInfo_t *)malloc(sizeof(PrivateBootInfo_t)); + if (bootArgs == 0 || bootInfo == 0) + stop("Couldn't allocate boot info\n"); + + bzero(bootArgs, sizeof(boot_args)); + bzero(bootInfo, sizeof(PrivateBootInfo_t)); + + // Get system memory map. Also update the size of the + // conventional/extended memory for backwards compatibility. + + bootInfo->memoryMapCount = + getMemoryMap( bootInfo->memoryMap, kMemoryMapCountMax, + (unsigned long *) &bootInfo->convmem, + (unsigned long *) &bootInfo->extmem ); + + if ( bootInfo->memoryMapCount == 0 ) + { + // BIOS did not provide a memory map, systems with + // discontiguous memory or unusual memory hole locations + // may have problems. + + bootInfo->convmem = getConventionalMemorySize(); + bootInfo->extmem = getExtendedMemorySize(); + } + + bootInfo->configEnd = bootInfo->config; + bootArgs->Video.v_display = VGA_TEXT_MODE; + + DT__Initialize(); + + node = DT__FindNode("/", true); + if (node == 0) { + stop("Couldn't create root node"); + } + getPlatformName(platformName); + nameLen = strlen(platformName) + 1; + DT__AddProperty(node, "compatible", nameLen, platformName); + DT__AddProperty(node, "model", nameLen, platformName); + + gMemoryMapNode = DT__FindNode("/chosen/memory-map", true); + + bootArgs->Version = kBootArgsVersion; + bootArgs->Revision = 5; + + init_done = 1; + } + +} + + +/* Copy boot args after kernel and record address. */ + +void +reserveKernBootStruct(void) +{ + void *oldAddr = bootArgs; + bootArgs = (boot_args *)AllocateKernelMemory(sizeof(boot_args)); + bcopy(oldAddr, bootArgs, sizeof(boot_args)); +} + +void +finalizeBootStruct(void) +{ + uint32_t size; + void *addr; + int i; + EfiMemoryRange *memoryMap; + MemoryRange *range; + int memoryMapCount = bootInfo->memoryMapCount; + + if (memoryMapCount == 0) { + // XXX could make a two-part map here + stop("Unable to convert memory map into proper format\n"); + } + + // convert memory map to boot_args memory map + memoryMap = (EfiMemoryRange *)AllocateKernelMemory(sizeof(EfiMemoryRange) * memoryMapCount); + bootArgs->MemoryMap = (uint32_t)memoryMap; + bootArgs->MemoryMapSize = sizeof(EfiMemoryRange) * memoryMapCount; + bootArgs->MemoryMapDescriptorSize = sizeof(EfiMemoryRange); + bootArgs->MemoryMapDescriptorVersion = 0; + + for (i=0; imemoryMap[i]; + switch(range->type) { + case kMemoryRangeACPI: + memoryMap->Type = kEfiACPIReclaimMemory; + break; + case kMemoryRangeNVS: + memoryMap->Type = kEfiACPIMemoryNVS; + break; + case kMemoryRangeUsable: + memoryMap->Type = kEfiConventionalMemory; + break; + case kMemoryRangeReserved: + default: + memoryMap->Type = kEfiReservedMemoryType; + break; + } + memoryMap->PhysicalStart = range->base; + memoryMap->VirtualStart = range->base; + memoryMap->NumberOfPages = range->length >> I386_PGSHIFT; + memoryMap->Attribute = 0; + } + + // copy bootFile into device tree + // XXX + + // add PCI info somehow into device tree + // XXX + + // Flatten device tree + DT__FlattenDeviceTree(0, &size); + addr = (void *)AllocateKernelMemory(size); + if (addr == 0) { + stop("Couldn't allocate device tree\n"); + } + + DT__FlattenDeviceTree((void **)&addr, &size); + bootArgs->deviceTreeP = (uint32_t)addr; + bootArgs->deviceTreeLength = size; +} Index: branches/slice/rev749/libsaio/cpuid.h =================================================================== --- branches/slice/rev749/libsaio/cpuid.h (revision 0) +++ branches/slice/rev749/libsaio/cpuid.h (revision 1169) @@ -0,0 +1,437 @@ +/* + * cpuid.h + * + */ + +#ifndef M_CPUID_H +#define M_CPUID_H + +#include +#include +#include +#include + + +#define CPUID_VID_INTEL "GenuineIntel" +#define CPUID_VID_AMD "AuthenticAMD" + +#define CPUID_STRING_UNKNOWN "Unknown CPU Typ" + +#define MSR_CORE_THREAD_COUNT 0x035 + +#define _Bit(n) (1ULL << n) +#define _HBit(n) (1ULL << ((n)+32)) + +/* + * The CPUID_FEATURE_XXX values define 64-bit values + * returned in %ecx:%edx to a CPUID request with %eax of 1: + */ +#define CPUID_FEATURE_FPU _Bit(0) /* Floating point unit on-chip */ +#define CPUID_FEATURE_VME _Bit(1) /* Virtual Mode Extension */ +#define CPUID_FEATURE_DE _Bit(2) /* Debugging Extension */ +#define CPUID_FEATURE_PSE _Bit(3) /* Page Size Extension */ +#define CPUID_FEATURE_TSC _Bit(4) /* Time Stamp Counter */ +#define CPUID_FEATURE_MSR _Bit(5) /* Model Specific Registers */ +#define CPUID_FEATURE_PAE _Bit(6) /* Physical Address Extension */ +#define CPUID_FEATURE_MCE _Bit(7) /* Machine Check Exception */ +#define CPUID_FEATURE_CX8 _Bit(8) /* CMPXCHG8B */ +#define CPUID_FEATURE_APIC _Bit(9) /* On-chip APIC */ +#define CPUID_FEATURE_SEP _Bit(11) /* Fast System Call */ +#define CPUID_FEATURE_MTRR _Bit(12) /* Memory Type Range Register */ +#define CPUID_FEATURE_PGE _Bit(13) /* Page Global Enable */ +#define CPUID_FEATURE_MCA _Bit(14) /* Machine Check Architecture */ +#define CPUID_FEATURE_CMOV _Bit(15) /* Conditional Move Instruction */ +#define CPUID_FEATURE_PAT _Bit(16) /* Page Attribute Table */ +#define CPUID_FEATURE_PSE36 _Bit(17) /* 36-bit Page Size Extension */ +#define CPUID_FEATURE_PSN _Bit(18) /* Processor Serial Number */ +#define CPUID_FEATURE_CLFSH _Bit(19) /* CLFLUSH Instruction supported */ +#define CPUID_FEATURE_DS _Bit(21) /* Debug Store */ +#define CPUID_FEATURE_ACPI _Bit(22) /* Thermal monitor and Clock Ctrl */ +#define CPUID_FEATURE_MMX _Bit(23) /* MMX supported */ +#define CPUID_FEATURE_FXSR _Bit(24) /* Fast floating pt save/restore */ +#define CPUID_FEATURE_SSE _Bit(25) /* Streaming SIMD extensions */ +#define CPUID_FEATURE_SSE2 _Bit(26) /* Streaming SIMD extensions 2 */ +#define CPUID_FEATURE_SS _Bit(27) /* Self-Snoop */ +#define CPUID_FEATURE_HTT _Bit(28) /* Hyper-Threading Technology */ +#define CPUID_FEATURE_TM _Bit(29) /* Thermal Monitor (TM1) */ +#define CPUID_FEATURE_PBE _Bit(31) /* Pend Break Enable */ + +#define CPUID_FEATURE_SSE3 _HBit(0) /* Streaming SIMD extensions 3 */ +#define CPUID_FEATURE_PCLMULQDQ _HBit(1) /* PCLMULQDQ Instruction */ + +#define CPUID_FEATURE_MONITOR _HBit(3) /* Monitor/mwait */ +#define CPUID_FEATURE_DSCPL _HBit(4) /* Debug Store CPL */ +#define CPUID_FEATURE_VMX _HBit(5) /* VMX */ +#define CPUID_FEATURE_SMX _HBit(6) /* SMX */ +#define CPUID_FEATURE_EST _HBit(7) /* Enhanced SpeedsTep (GV3) */ +#define CPUID_FEATURE_TM2 _HBit(8) /* Thermal Monitor 2 */ +#define CPUID_FEATURE_SSSE3 _HBit(9) /* Supplemental SSE3 instructions */ +#define CPUID_FEATURE_CID _HBit(10) /* L1 Context ID */ + +#define CPUID_FEATURE_CX16 _HBit(13) /* CmpXchg16b instruction */ +#define CPUID_FEATURE_xTPR _HBit(14) /* Send Task PRiority msgs */ +#define CPUID_FEATURE_PDCM _HBit(15) /* Perf/Debug Capability MSR */ + +#define CPUID_FEATURE_DCA _HBit(18) /* Direct Cache Access */ +#define CPUID_FEATURE_SSE4_1 _HBit(19) /* Streaming SIMD extensions 4.1 */ +#define CPUID_FEATURE_SSE4_2 _HBit(20) /* Streaming SIMD extensions 4.2 */ +#define CPUID_FEATURE_xAPIC _HBit(21) /* Extended APIC Mode */ +#define CPUID_FEATURE_POPCNT _HBit(23) /* POPCNT instruction */ +#define CPUID_FEATURE_AES _HBit(25) /* AES instructions */ +#define CPUID_FEATURE_VMM _HBit(31) /* VMM (Hypervisor) present */ + +/* + * The CPUID_EXTFEATURE_XXX values define 64-bit values + * returned in %ecx:%edx to a CPUID request with %eax of 0x80000001: + */ +#define CPUID_EXTFEATURE_SYSCALL _Bit(11) /* SYSCALL/sysret */ +#define CPUID_EXTFEATURE_XD _Bit(20) /* eXecute Disable */ +#define CPUID_EXTFEATURE_1GBPAGE _Bit(26) /* 1G-Byte Page support */ +#define CPUID_EXTFEATURE_RDTSCP _Bit(27) /* RDTSCP */ +#define CPUID_EXTFEATURE_EM64T _Bit(29) /* Extended Mem 64 Technology */ + +//#define CPUID_EXTFEATURE_LAHF _HBit(20) /* LAFH/SAHF instructions */ +// New definition with Snow kernel +#define CPUID_EXTFEATURE_LAHF _HBit(0) /* LAHF/SAHF instructions */ +/* + * The CPUID_EXTFEATURE_XXX values define 64-bit values + * returned in %ecx:%edx to a CPUID request with %eax of 0x80000007: + */ +#define CPUID_EXTFEATURE_TSCI _Bit(8) /* TSC Invariant */ + +#define CPUID_CACHE_SIZE 16 /* Number of descriptor values */ + +#define CPUID_MWAIT_EXTENSION _Bit(0) /* enumeration of WMAIT extensions */ +#define CPUID_MWAIT_BREAK _Bit(1) /* interrupts are break events */ + +#define CPU_MODEL_PENTIUM_M 0x0D +#define CPU_MODEL_YONAH 0x0E +#define CPU_MODEL_MEROM 0x0F +#define CPU_MODEL_PENRYN 0x17 +#define CPU_MODEL_NEHALEM 0x1A +#define CPU_MODEL_ATOM 0x1C +#define CPU_MODEL_FIELDS 0x1E /* Lynnfield, Clarksfield, Jasper */ +#define CPU_MODEL_DALES 0x1F /* Havendale, Auburndale */ +#define CPU_MODEL_DALES_32NM 0x25 /* Clarkdale, Arrandale */ +#define CPU_MODEL_WESTMERE 0x2C /* Gulftown, Westmere-EP, Westmere-WS */ +#define CPU_MODEL_NEHALEM_EX 0x2E +#define CPU_MODEL_WESTMERE_EX 0x2F + +#include +#include +#include +#include + + +typedef enum { eax, ebx, ecx, edx } cpuid_register_t; +static inline void +cpuid(uint32_t *data) +{ + __asm__ volatile("cpuid" + : "=a" (data[eax]), + "=b" (data[ebx]), + "=c" (data[ecx]), + "=d" (data[edx]) + : "a" (data[eax]), + "b" (data[ebx]), + "c" (data[ecx]), + "d" (data[edx])); +} +static inline void +do_cpuid(uint32_t selector, uint32_t *data) +{ + __asm__ volatile("cpuid" + : "=a" (data[0]), + "=b" (data[1]), + "=c" (data[2]), + "=d" (data[3]) + : "a"(selector)); +} + +/* + * Cache ID descriptor structure, used to parse CPUID leaf 2. + * Note: not used in kernel. + */ +typedef enum { Lnone, L1I, L1D, L2U, L3U, LCACHE_MAX } cache_type_t ; +typedef struct { + unsigned char value; /* Descriptor value */ + cache_type_t type; /* Cache type */ + unsigned int size; /* Cache size */ + unsigned int linesize; /* Cache line size */ + const char *description; /* Cache description */ +} cpuid_cache_desc_t; + + +#define CACHE_DESC(value,type,size,linesize,text) \ +{ value, type, size, linesize, text } + +#define _Bit(n) (1ULL << n) +//#define _HBit(n) (1ULL << ((n) + 32)) + +#define min(a,b) ((a) < (b) ? (a) : (b)) +#define quad(hi,lo) (((uint64_t)(hi)) << 32 | (lo)) +#define bit(n) (1UL << (n)) +#define bitmask(h,l) ((bit(h) | (bit(h) - 1)) & ~(bit(l) - 1)) +#define bitfield(x,h,l) (((x) & bitmask(h, l)) >> l) + +/* Physical CPU info - this is exported out of the kernel (kexts), so be wary of changes */ +typedef struct { + char cpuid_vendor[16]; + char cpuid_brand_string[48]; + const char *cpuid_model_string; + + cpu_type_t cpuid_type; /* this is *not* a cpu_type_t in our */ + uint8_t cpuid_family; + uint8_t cpuid_model; + uint8_t cpuid_extmodel; + uint8_t cpuid_extfamily; + uint8_t cpuid_stepping; + uint64_t cpuid_features; + uint64_t cpuid_extfeatures; + uint32_t cpuid_signature; + uint8_t cpuid_brand; + + uint32_t cache_size[LCACHE_MAX]; + uint32_t cache_linesize; + + uint8_t cache_info[64]; /* list of cache descriptors */ + + uint32_t cpuid_cores_per_package; + uint32_t cpuid_logical_per_package; + uint32_t cache_sharing[LCACHE_MAX]; + uint32_t cache_partitions[LCACHE_MAX]; + + cpu_type_t cpuid_cpu_type; /* */ + cpu_subtype_t cpuid_cpu_subtype; /* */ + + /* Monitor/mwait Leaf: */ + uint32_t cpuid_mwait_linesize_min; + uint32_t cpuid_mwait_linesize_max; + uint32_t cpuid_mwait_extensions; + uint32_t cpuid_mwait_sub_Cstates; + + /* Thermal and Power Management Leaf: */ + boolean_t cpuid_thermal_sensor; + boolean_t cpuid_thermal_dynamic_acceleration; + uint32_t cpuid_thermal_thresholds; + boolean_t cpuid_thermal_ACNT_MCNT; + + /* Architectural Performance Monitoring Leaf: */ + uint8_t cpuid_arch_perf_version; + uint8_t cpuid_arch_perf_number; + uint8_t cpuid_arch_perf_width; + uint8_t cpuid_arch_perf_events_number; + uint32_t cpuid_arch_perf_events; + uint8_t cpuid_arch_perf_fixed_number; + uint8_t cpuid_arch_perf_fixed_width; + + /* Cache details: */ + uint32_t cpuid_cache_linesize; + uint32_t cpuid_cache_L2_associativity; + uint32_t cpuid_cache_size; + + /* Virtual and physical address aize: */ + uint32_t cpuid_address_bits_physical; + uint32_t cpuid_address_bits_virtual; + + uint32_t cpuid_microcode_version; + + /* Numbers of tlbs per processor [i|d, small|large, level0|level1] */ + uint32_t cpuid_tlb[2][2][2]; +#define TLB_INST 0 +#define TLB_DATA 1 +#define TLB_SMALL 0 +#define TLB_LARGE 1 + uint32_t cpuid_stlb; + + uint32_t core_count; + uint32_t thread_count; + + /* Max leaf ids available from CPUID */ + uint32_t cpuid_max_basic; + uint32_t cpuid_max_ext; +} i386_cpu_info_t; + +static i386_cpu_info_t cpuid_cpu_info; + +static i386_cpu_info_t *cpuid_info(void) +{ + return &cpuid_cpu_info; +} +/* +static uint32_t cpuid_count_cores() +{ + uint32_t cpuid_reg[4]; + + do_cpuid(1, cpuid_reg); + + return bitfield(cpuid_reg[1], 23, 16); +} +*/ + +static void cpuid_update_generic_info() +{ + uint32_t cpuid_reg[4]; + uint32_t max_extid; + char str[128]; + char* p; + i386_cpu_info_t* info_p = cpuid_info(); + + /* Get vendor */ + do_cpuid(0, cpuid_reg); + bcopy((char *)&cpuid_reg[ebx], &info_p->cpuid_vendor[0], 4); /* ug */ + bcopy((char *)&cpuid_reg[ecx], &info_p->cpuid_vendor[8], 4); + bcopy((char *)&cpuid_reg[edx], &info_p->cpuid_vendor[4], 4); + info_p->cpuid_vendor[12] = 0; + + /* Get extended CPUID results */ + do_cpuid(0x80000000, cpuid_reg); + max_extid = cpuid_reg[eax]; + + /* Check to see if we can get the brand string */ + if (max_extid >= 0x80000004) { + /* + * The brand string is up to 48 bytes and is guaranteed to be + * NUL terminated. + */ + do_cpuid(0x80000002, cpuid_reg); + bcopy((char *)cpuid_reg, &str[0], 16); + do_cpuid(0x80000003, cpuid_reg); + bcopy((char *)cpuid_reg, &str[16], 16); + do_cpuid(0x80000004, cpuid_reg); + bcopy((char *)cpuid_reg, &str[32], 16); + for (p = str; *p != '\0'; p++) { + if (*p != ' ') break; + } + strncpy(info_p->cpuid_brand_string, p, + sizeof(info_p->cpuid_brand_string)); + + if (!strncmp(info_p->cpuid_brand_string, CPUID_STRING_UNKNOWN, + min(sizeof(info_p->cpuid_brand_string), + strlen(CPUID_STRING_UNKNOWN) + 1))) { + /* + * This string means we have a firmware-programmable brand string, + * and the firmware couldn't figure out what sort of CPU we have. + */ + info_p->cpuid_brand_string[0] = '\0'; + } + } + + /* Get cache and addressing info */ + if (max_extid >= 0x80000006) { + do_cpuid(0x80000006, cpuid_reg); + info_p->cpuid_cache_linesize = bitfield(cpuid_reg[ecx], 7, 0); + info_p->cpuid_cache_L2_associativity = bitfield(cpuid_reg[ecx], 15, 12); + info_p->cpuid_cache_size = bitfield(cpuid_reg[ecx], 31, 16); + do_cpuid(0x80000008, cpuid_reg); + info_p->cpuid_address_bits_physical = bitfield(cpuid_reg[eax], 7, 0); + info_p->cpuid_address_bits_virtual = bitfield(cpuid_reg[eax], 15, 8); + } + + /* Get processor signature and decode */ + do_cpuid(1, cpuid_reg); + info_p->cpuid_signature = cpuid_reg[eax]; + info_p->cpuid_stepping = bitfield(cpuid_reg[eax], 3, 0); + info_p->cpuid_model = bitfield(cpuid_reg[eax], 7, 4); + info_p->cpuid_family = bitfield(cpuid_reg[eax], 11, 8); + info_p->cpuid_type = bitfield(cpuid_reg[eax], 13, 12); + info_p->cpuid_extmodel = bitfield(cpuid_reg[eax], 19, 16); + info_p->cpuid_extfamily = bitfield(cpuid_reg[eax], 27, 20); + info_p->cpuid_brand = bitfield(cpuid_reg[ebx], 7, 0); + info_p->cpuid_features = quad(cpuid_reg[ecx], cpuid_reg[edx]); + + /* Fold extensions into family/model */ + if (info_p->cpuid_family == 0x0f) { + info_p->cpuid_family += info_p->cpuid_extfamily; + } + if (info_p->cpuid_family == 0x0f || info_p->cpuid_family== 0x06) { + info_p->cpuid_model += (info_p->cpuid_extmodel << 4); + } + + if (info_p->cpuid_features & CPUID_FEATURE_HTT) { + info_p->cpuid_logical_per_package = bitfield(cpuid_reg[ebx], 23, 16); + } else { + info_p->cpuid_logical_per_package = 1; + } + + if (max_extid >= 0x80000001) { + do_cpuid(0x80000001, cpuid_reg); + info_p->cpuid_extfeatures = quad(cpuid_reg[ecx], cpuid_reg[edx]); + } + + if (info_p->cpuid_extfeatures & CPUID_FEATURE_MONITOR) { + + do_cpuid(5, cpuid_reg); + info_p->cpuid_mwait_linesize_min = cpuid_reg[eax]; + info_p->cpuid_mwait_linesize_max = cpuid_reg[ebx]; + info_p->cpuid_mwait_extensions = cpuid_reg[ecx]; + info_p->cpuid_mwait_sub_Cstates = cpuid_reg[edx]; + + do_cpuid(6, cpuid_reg); + info_p->cpuid_thermal_sensor = bitfield(cpuid_reg[eax], 0, 0); + info_p->cpuid_thermal_dynamic_acceleration = + bitfield(cpuid_reg[eax], 1, 1); + info_p->cpuid_thermal_thresholds = bitfield(cpuid_reg[ebx], 3, 0); + info_p->cpuid_thermal_ACNT_MCNT = bitfield(cpuid_reg[ecx], 0, 0); + + do_cpuid(0xa, cpuid_reg); + info_p->cpuid_arch_perf_version = bitfield(cpuid_reg[eax], 7, 0); + info_p->cpuid_arch_perf_number = bitfield(cpuid_reg[eax],15, 8); + info_p->cpuid_arch_perf_width = bitfield(cpuid_reg[eax],23,16); + info_p->cpuid_arch_perf_events_number = bitfield(cpuid_reg[eax],31,24); + info_p->cpuid_arch_perf_events = cpuid_reg[ebx]; + info_p->cpuid_arch_perf_fixed_number = bitfield(cpuid_reg[edx], 4, 0); + info_p->cpuid_arch_perf_fixed_width = bitfield(cpuid_reg[edx],12, 5); + + } + + do_cpuid(4, cpuid_reg); + info_p->cpuid_cores_per_package = bitfield(cpuid_reg[eax], 31, 26) + 1; + + if (info_p->cpuid_cores_per_package == 0) { + info_p->cpuid_cores_per_package = 1; + + } + + switch (info_p->cpuid_model) + { + case 0x1C: + { + //uint64_t msr = rdmsr64(MSR_CORE_THREAD_COUNT); + info_p->core_count = 1; //bitfield((uint32_t)msr, 19, 16); + info_p->thread_count = 2; //bitfield((uint32_t)msr, 15, 0); + } + break; + + case 0x1A: // Intel Core i7 LGA1366 (45nm) + case 0x1E: // Intel Core i5, i7 LGA1156 (45nm) + case 0x25: // Intel Core i3, i5, i7 LGA1156 (32nm) + { + uint64_t msr = rdmsr64(MSR_CORE_THREAD_COUNT); + info_p->core_count = bitfield((uint32_t)msr, 31, 16); + info_p->thread_count = bitfield((uint32_t)msr, 15, 0); + } break; + case 0x2C: // Intel Core i7 LGA1366 (32nm) 6 Core + case 0x1F: + case 0x2F: + { + uint64_t msr = rdmsr64(MSR_CORE_THREAD_COUNT); + info_p->core_count = bitfield((uint32_t)msr, 19, 16); + info_p->thread_count = bitfield((uint32_t)msr, 15, 0); + break; + } + + default: + { + do_cpuid(1, cpuid_reg); + info_p->core_count = bitfield(cpuid_reg[1], 23, 16); + } break; + } + if (info_p->core_count == 0) { + info_p->core_count = info_p->cpuid_cores_per_package; + info_p->thread_count = info_p->cpuid_logical_per_package; + } + +} + +#endif /*M_CPUID_H*/ Index: branches/slice/rev749/libsaio/ntfs_private.h =================================================================== --- branches/slice/rev749/libsaio/ntfs_private.h (revision 0) +++ branches/slice/rev749/libsaio/ntfs_private.h (revision 1169) @@ -0,0 +1,399 @@ +/* + * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $NetBSD: ntfs.h,v 1.9 1999/10/31 19:45:26 jdolecek Exp $ */ + +/*- + * Copyright (c) 1998, 1999 Semen Ustimenko + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/sys/fs/ntfs/ntfs.h,v 1.14 2001/11/27 00:18:33 jhb Exp $ + */ + +/*#define NTFS_DEBUG 1*/ + +#ifdef APPLE +/* We're using FreeBSD style byte order macros in the source. */ +#include +#define le16toh(x) OSSwapLittleToHostInt16(x) +#define le32toh(x) OSSwapLittleToHostInt32(x) +#define le64toh(x) OSSwapLittleToHostInt64(x) + +/* FreeBSD mutexes correspond to Darwin's simple locks */ +#define mtx_lock(lock) simple_lock(lock) +#define mtx_unlock(lock) simple_unlock(lock) +#define mtx_destroy(lock) /* Nothing. */ + +#define lockdestroy(lock) /* Nothing. */ + +#endif + +typedef u_int64_t cn_t; +typedef u_int16_t wchar; + +#pragma pack(1) +#define BBSIZE 1024 +#define BBOFF ((off_t)(0)) +#define BBLOCK ((daddr_t)(0)) +#define NTFS_MFTINO 0 +#define NTFS_VOLUMEINO 3 +#define NTFS_ATTRDEFINO 4 +#define NTFS_ROOTINO 5 +#define NTFS_BITMAPINO 6 +#define NTFS_BOOTINO 7 +#define NTFS_BADCLUSINO 8 +#define NTFS_UPCASEINO 10 +#define NTFS_MAXFILENAME 255 + +struct fixuphdr { + u_int32_t fh_magic; + u_int16_t fh_foff; + u_int16_t fh_fnum; +}; + +#define NTFS_AF_INRUN 0x00000001 +struct attrhdr { + u_int32_t a_type; + u_int32_t reclen; + u_int8_t a_flag; + u_int8_t a_namelen; + u_int8_t a_nameoff; + u_int8_t reserved1; + u_int8_t a_compression; + u_int8_t reserved2; + u_int16_t a_index; +}; +#define NTFS_A_STD 0x10 +#define NTFS_A_ATTRLIST 0x20 +#define NTFS_A_NAME 0x30 +#define NTFS_A_VOLUMENAME 0x60 +#define NTFS_A_DATA 0x80 +#define NTFS_A_INDXROOT 0x90 +#define NTFS_A_INDX 0xA0 +#define NTFS_A_INDXBITMAP 0xB0 + +#define NTFS_MAXATTRNAME 255 +struct attr { + struct attrhdr a_hdr; + union { + struct { + u_int16_t a_datalen; + u_int16_t reserved1; + u_int16_t a_dataoff; + u_int16_t a_indexed; + } a_S_r; + struct { + cn_t a_vcnstart; + cn_t a_vcnend; + u_int16_t a_dataoff; + u_int16_t a_compressalg; + u_int32_t reserved1; + u_int64_t a_allocated; + u_int64_t a_datalen; + u_int64_t a_initialized; + } a_S_nr; + } a_S; +}; +#define a_r a_S.a_S_r +#define a_nr a_S.a_S_nr + +typedef struct { + u_int64_t t_create; + u_int64_t t_write; + u_int64_t t_mftwrite; + u_int64_t t_access; +} ntfs_times_t; + +#define NTFS_FFLAG_RDONLY 0x01LL +#define NTFS_FFLAG_HIDDEN 0x02LL +#define NTFS_FFLAG_SYSTEM 0x04LL +#define NTFS_FFLAG_ARCHIVE 0x20LL +#define NTFS_FFLAG_COMPRESSED 0x0800LL +#define NTFS_FFLAG_DIR 0x10000000LL + +struct attr_name { + u_int32_t n_pnumber; /* Parent ntnode */ + u_int32_t reserved; + ntfs_times_t n_times; + u_int64_t n_size; + u_int64_t n_attrsz; + u_int64_t n_flag; + u_int8_t n_namelen; + u_int8_t n_nametype; + u_int16_t n_name[1]; +}; + +#define NTFS_IRFLAG_INDXALLOC 0x00000001 +struct attr_indexroot { + u_int32_t ir_unkn1; /* attribute type (0x30 for $FILE_NAME) */ + u_int32_t ir_unkn2; /* collation rule (0x01 for file names) */ + u_int32_t ir_size; /* size of index allocation entry */ + u_int32_t ir_unkn3; /* clusters per index record, and 3 bytes padding */ + u_int32_t ir_unkn4; /* (offset to first index entry?) always 0x10 */ + u_int32_t ir_datalen; /* (total size of index enties?) sizeof something */ + u_int32_t ir_allocated; /* (allocated size of index entries?) */ + u_int8_t ir_flag; /* 1=index allocation needed (large index) */ + u_int8_t ir_pad1; /* padding */ + u_int16_t ir_pad2; /* padding */ +}; + +struct attr_attrlist { + u_int32_t al_type; /* Attribute type */ + u_int16_t reclen; /* length of this entry */ + u_int8_t al_namelen; /* Attribute name len */ + u_int8_t al_nameoff; /* Name offset from entry start */ + u_int64_t al_vcnstart; /* VCN number */ + u_int32_t al_inumber; /* Parent ntnode */ + u_int32_t reserved; + u_int16_t al_index; /* Attribute index in MFT record */ + u_int16_t al_name[1]; /* Name */ +}; + +#define NTFS_INDXMAGIC (u_int32_t)(0x58444E49) +struct attr_indexalloc { + struct fixuphdr ia_fixup; + u_int64_t unknown1; + cn_t ia_bufcn; + u_int16_t ia_hdrsize; + u_int16_t unknown2; + u_int32_t ia_inuse; + u_int32_t ia_allocated; +}; + +#define NTFS_IEFLAG_SUBNODE 0x00000001 +#define NTFS_IEFLAG_LAST 0x00000002 + +struct attr_indexentry { + u_int32_t ie_number; + u_int32_t unknown1; + u_int16_t reclen; + u_int16_t ie_size; + u_int32_t ie_flag;/* 1 - has subnodes, 2 - last */ + u_int32_t ie_fpnumber; + u_int32_t unknown2; + ntfs_times_t ie_ftimes; + u_int64_t ie_fallocated; + u_int64_t ie_fsize; + u_int32_t ie_fflag; + u_int32_t unknown3; /* used by reparse points and external attributes? */ + u_int8_t ie_fnamelen; + u_int8_t ie_fnametype; + wchar ie_fname[NTFS_MAXFILENAME]; + /* cn_t ie_bufcn; buffer with subnodes */ +}; + +#define NTFS_FILEMAGIC (u_int32_t)(0x454C4946) +#define NTFS_FRFLAG_DIR 0x0002 +struct filerec { + struct fixuphdr fr_fixup; + u_int8_t reserved[8]; + u_int16_t fr_seqnum; /* Sequence number */ + u_int16_t fr_nlink; + u_int16_t fr_attroff; /* offset to attributes */ + u_int16_t fr_flags; /* 1-nonresident attr, 2-directory */ + u_int32_t fr_size;/* hdr + attributes */ + u_int32_t fr_allocated; /* allocated length of record */ + u_int64_t fr_mainrec; /* main record */ + u_int16_t fr_attrnum; /* maximum attr number + 1 ??? */ +}; + +#define NTFS_ATTRNAME_MAXLEN 0x40 +#define NTFS_ADFLAG_NONRES 0x0080 /* Attrib can be non resident */ +#define NTFS_ADFLAG_INDEX 0x0002 /* Attrib can be indexed */ +struct attrdef { + wchar ad_name[NTFS_ATTRNAME_MAXLEN]; + u_int32_t ad_type; + u_int32_t reserved1[2]; + u_int32_t ad_flag; + u_int64_t ad_minlen; + u_int64_t ad_maxlen; /* -1 for nonlimited */ +}; + +struct ntvattrdef { + char ad_name[0x40]; + int ad_namelen; + u_int32_t ad_type; +}; + +#define NTFS_BBID "NTFS " +#define NTFS_BBIDLEN 8 +struct bootfile { + u_int8_t reserved1[3]; /* asm jmp near ... */ + u_int8_t bf_sysid[8]; /* 'NTFS ' */ + u_int16_t bf_bps; /* bytes per sector */ + u_int8_t bf_spc; /* sectors per cluster */ + u_int8_t reserved2[7]; /* unused (zeroed) */ + u_int8_t bf_media; /* media desc. (0xF8) */ + u_int8_t reserved3[2]; + u_int16_t bf_spt; /* sectors per track */ + u_int16_t bf_heads; /* number of heads */ + u_int8_t reserver4[12]; + u_int64_t bf_spv; /* sectors per volume */ + cn_t bf_mftcn; /* $MFT cluster number */ + cn_t bf_mftmirrcn; /* $MFTMirr cn */ + u_int8_t bf_mftrecsz; /* MFT record size (clust) */ + /* 0xF6 inducates 1/4 */ + u_int8_t reserved5[3]; + u_int8_t bf_ibsz; /* index buffer size */ + u_int8_t reserved6[3]; + u_int64_t bf_volsn; /* volume ser. num. */ +}; + +/* + * Darwin's ntfs.util needs to include this file to get definitions + * for the on-disk structures. It doesn't need the ntfsmount structure. + * In fact, since it doesn't #define KERNEL, the struct netexport below + * won't be defined. + * + * So, I'm using #ifdef KERNEL around the things that are only relevant + * to the in-kernel implementation. + * + * I don't know if FreeBSD defines KERNEL, or if I need to use or + * invent a different conditional here. + */ +#ifdef KERNEL + +#define NTFS_SYSNODESNUM 0x0B +struct ntfsmount { + struct mount *ntm_mountp; /* filesystem vfs structure */ + struct bootfile ntm_bootfile; + dev_t ntm_dev; /* device mounted */ + struct vnode *ntm_devvp; /* block device mounted vnode */ + struct vnode *ntm_sysvn[NTFS_SYSNODESNUM]; + u_int32_t ntm_bpmftrec; + uid_t ntm_uid; + gid_t ntm_gid; + mode_t ntm_mode; + u_long ntm_flag; + cn_t ntm_cfree; + struct ntvattrdef *ntm_ad; /* attribute names are stored in native byte order */ + int ntm_adnum; + wchar * ntm_82u; /* 8bit to Unicode */ + char ** ntm_u28; /* Unicode to 8 bit */ +#ifdef APPLE + struct netexport ntm_export; /* NFS export information */ +#endif +}; + +#define ntm_mftcn ntm_bootfile.bf_mftcn +#define ntm_mftmirrcn ntm_bootfile.bf_mftmirrcn +#define ntm_mftrecsz ntm_bootfile.bf_mftrecsz +#define ntm_spc ntm_bootfile.bf_spc +#define ntm_bps ntm_bootfile.bf_bps + +#pragma pack() + +#define NTFS_NEXTREC(s, type) ((type)(((caddr_t) s) + le16toh((s)->reclen))) + +/* Convert mount ptr to ntfsmount ptr. */ +#define VFSTONTFS(mp) ((struct ntfsmount *)((mp)->mnt_data)) +#define VTONT(v) FTONT(VTOF(v)) +#define VTOF(v) ((struct fnode *)((v)->v_data)) +#define FTOV(f) ((f)->f_vp) +#define FTONT(f) ((f)->f_ip) +#define ntfs_cntobn(cn) ((daddr_t)(cn) * (ntmp->ntm_spc)) +#define ntfs_cntob(cn) ((off_t)(cn) * (ntmp)->ntm_spc * (ntmp)->ntm_bps) +#define ntfs_btocn(off) (cn_t)((off) / ((ntmp)->ntm_spc * (ntmp)->ntm_bps)) +#define ntfs_btocl(off) (cn_t)((off + ntfs_cntob(1) - 1) / ((ntmp)->ntm_spc * (ntmp)->ntm_bps)) +#define ntfs_btocnoff(off) (off_t)((off) % ((ntmp)->ntm_spc * (ntmp)->ntm_bps)) +#define ntfs_bntob(bn) (daddr_t)((bn) * (ntmp)->ntm_bps) + +#define ntfs_bpbl (daddr_t)((ntmp)->ntm_bps) + +#ifdef MALLOC_DECLARE +MALLOC_DECLARE(M_NTFSMNT); +MALLOC_DECLARE(M_NTFSNTNODE); +MALLOC_DECLARE(M_NTFSFNODE); +MALLOC_DECLARE(M_NTFSDIR); +MALLOC_DECLARE(M_NTFSNTHASH); +#endif + +#ifndef M_NTFSMNT +#define M_NTFSMNT M_TEMP +#endif +#ifndef M_NTFSNTNODE +#define M_NTFSNTNODE M_TEMP +#endif +#ifndef M_NTFSFNODE +#define M_NTFSFNODE M_TEMP +#endif +#ifndef M_NTFSDIR +#define M_NTFSDIR M_TEMP +#endif +#ifndef M_NTFSNTHASH +#define M_NTFSNTHASH M_TEMP +#endif +#ifndef M_NTFSRUN +#define M_NTFSRUN M_TEMP +#endif +#ifndef M_NTFSRDATA +#define M_NTFSRDATA M_TEMP +#endif +#ifndef M_NTFSNTVATTR +#define M_NTFSNTVATTR M_TEMP +#endif +#ifndef M_NTFSDECOMP +#define M_NTFSDECOMP M_TEMP +#endif +#define VT_NTFS VT_OTHER + +#if defined(NTFS_DEBUG) +#define dprintf(a) printf a +#if NTFS_DEBUG > 1 +#define ddprintf(a) printf a +#else +#define ddprintf(a) +#endif +#else +#define dprintf(a) +#define ddprintf(a) +#endif + +#ifdef APPLE +typedef int vop_t(void *); +#else +#endif +extern vop_t **ntfs_vnodeop_p; +#endif /* KERNEL */ Index: branches/slice/rev749/libsaio/io_inline.h =================================================================== --- branches/slice/rev749/libsaio/io_inline.h (revision 0) +++ branches/slice/rev749/libsaio/io_inline.h (revision 1169) @@ -0,0 +1,82 @@ +/* + * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 2.0 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1992 NeXT Computer, Inc. + * + * Inlines for io space access. + * + * HISTORY + * + * 20 May 1992 ? at NeXT + * Created. + */ + +#ifndef __LIBSAIO_IO_INLINE_H +#define __LIBSAIO_IO_INLINE_H + +/* + *############################################################################ + * + * x86 IN/OUT I/O inline functions. + * + * IN : inb, inw, inl + * IN(port) + * + * OUT: outb, outw, outl + * OUT(port, data) + * + *############################################################################ + */ + +#define __IN(s, u) \ +static inline unsigned u \ +in##s(unsigned short port) \ +{ \ + unsigned u data; \ + asm volatile ( \ + "in" #s " %1,%0" \ + : "=a" (data) \ + : "d" (port)); \ + return (data); \ +} + +#define __OUT(s, u) \ +static inline void \ +out##s(unsigned short port, unsigned u data) \ +{ \ + asm volatile ( \ + "out" #s " %1,%0" \ + : \ + : "d" (port), "a" (data)); \ +} + +__IN(b, char) /* inb() */ +__IN(w, short) /* inw() */ +__IN(l, long) /* inl() */ + +__OUT(b, char) /* outb() */ +__OUT(w, short) /* outw() */ +__OUT(l, long) /* outl() */ + +#endif /* !__LIBSAIO_IO_INLINE_H */ Index: branches/slice/rev749/libsaio/ext2fs.c =================================================================== --- branches/slice/rev749/libsaio/ext2fs.c (revision 0) +++ branches/slice/rev749/libsaio/ext2fs.c (revision 1169) @@ -0,0 +1,43 @@ +/* + * ext2fs.c + * + * + * Created by mackerintel on 1/26/09. + * Copyright 2009 __MyCompanyName__. All rights reserved. + * + */ +#ifndef OPTION_ROM +#include "libsaio.h" +#include "sl.h" +#include "ext2fs.h" + +#define EX2ProbeSize 2048 + +bool EX2Probe (const void *buf) +{ + return (OSReadLittleInt16(buf+0x438,0)==0xEF53); // +} + +void EX2GetDescription(CICell ih, char *str, long strMaxLen) +{ + char * buf=malloc (EX2ProbeSize); + str[0]=0; + if (!buf) + return; + Seek(ih, 0); + Read(ih, (long)buf, EX2ProbeSize); + if (!EX2Probe (buf)) + { + free (buf); + return; + } + if (OSReadLittleInt32 (buf+0x44c,0)<1) + { + free (buf); + return; + } + str[strMaxLen]=0; + strncpy (str, buf+0x478, min (strMaxLen, 16)); + free (buf); +} +#endif \ No newline at end of file Index: branches/slice/rev749/libsaio/hfs_CaseTables.h =================================================================== --- branches/slice/rev749/libsaio/hfs_CaseTables.h (revision 0) +++ branches/slice/rev749/libsaio/hfs_CaseTables.h (revision 1169) @@ -0,0 +1,560 @@ +/* + * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 2.0 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + File: CaseTables.h +*/ + + +/* The lower case table consists of a 256-entry high-byte table followed by some number of + 256-entry subtables. The high-byte table contains either an offset to the subtable for + characters with that high byte or zero, which means that there are no case mappings or + ignored characters in that block. Ignored characters are mapped to zero. + */ + +#if UNCOMPRESSED +u_int16_t gLowerCaseTable[] = { + + // High-byte indices ( == 0 iff no case mapping and no ignorables ) + + /* 0 */ 0x0100, 0x0200, 0x0000, 0x0300, 0x0400, 0x0500, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 1 */ 0x0600, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 2 */ 0x0700, 0x0800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 3 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 4 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 5 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 6 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 7 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 8 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 9 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* A */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* B */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* C */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* D */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* E */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* F */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0900, 0x0A00, + + // Table 1 (for high byte 0x00) + + /* 0 */ 0xFFFF, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, + /* 1 */ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, + /* 2 */ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, + /* 3 */ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, + /* 4 */ 0x0040, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, + /* 5 */ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, + /* 6 */ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, + /* 7 */ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, + /* 8 */ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, + /* 9 */ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, + /* A */ 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + /* B */ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, + /* C */ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00E6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, + /* D */ 0x00F0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00F8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00FE, 0x00DF, + /* E */ 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, + /* F */ 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF, + + // Table 2 (for high byte 0x01) + + /* 0 */ 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x0108, 0x0109, 0x010A, 0x010B, 0x010C, 0x010D, 0x010E, 0x010F, + /* 1 */ 0x0111, 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116, 0x0117, 0x0118, 0x0119, 0x011A, 0x011B, 0x011C, 0x011D, 0x011E, 0x011F, + /* 2 */ 0x0120, 0x0121, 0x0122, 0x0123, 0x0124, 0x0125, 0x0127, 0x0127, 0x0128, 0x0129, 0x012A, 0x012B, 0x012C, 0x012D, 0x012E, 0x012F, + /* 3 */ 0x0130, 0x0131, 0x0133, 0x0133, 0x0134, 0x0135, 0x0136, 0x0137, 0x0138, 0x0139, 0x013A, 0x013B, 0x013C, 0x013D, 0x013E, 0x0140, + /* 4 */ 0x0140, 0x0142, 0x0142, 0x0143, 0x0144, 0x0145, 0x0146, 0x0147, 0x0148, 0x0149, 0x014B, 0x014B, 0x014C, 0x014D, 0x014E, 0x014F, + /* 5 */ 0x0150, 0x0151, 0x0153, 0x0153, 0x0154, 0x0155, 0x0156, 0x0157, 0x0158, 0x0159, 0x015A, 0x015B, 0x015C, 0x015D, 0x015E, 0x015F, + /* 6 */ 0x0160, 0x0161, 0x0162, 0x0163, 0x0164, 0x0165, 0x0167, 0x0167, 0x0168, 0x0169, 0x016A, 0x016B, 0x016C, 0x016D, 0x016E, 0x016F, + /* 7 */ 0x0170, 0x0171, 0x0172, 0x0173, 0x0174, 0x0175, 0x0176, 0x0177, 0x0178, 0x0179, 0x017A, 0x017B, 0x017C, 0x017D, 0x017E, 0x017F, + /* 8 */ 0x0180, 0x0253, 0x0183, 0x0183, 0x0185, 0x0185, 0x0254, 0x0188, 0x0188, 0x0256, 0x0257, 0x018C, 0x018C, 0x018D, 0x01DD, 0x0259, + /* 9 */ 0x025B, 0x0192, 0x0192, 0x0260, 0x0263, 0x0195, 0x0269, 0x0268, 0x0199, 0x0199, 0x019A, 0x019B, 0x026F, 0x0272, 0x019E, 0x0275, + /* A */ 0x01A0, 0x01A1, 0x01A3, 0x01A3, 0x01A5, 0x01A5, 0x01A6, 0x01A8, 0x01A8, 0x0283, 0x01AA, 0x01AB, 0x01AD, 0x01AD, 0x0288, 0x01AF, + /* B */ 0x01B0, 0x028A, 0x028B, 0x01B4, 0x01B4, 0x01B6, 0x01B6, 0x0292, 0x01B9, 0x01B9, 0x01BA, 0x01BB, 0x01BD, 0x01BD, 0x01BE, 0x01BF, + /* C */ 0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C6, 0x01C6, 0x01C6, 0x01C9, 0x01C9, 0x01C9, 0x01CC, 0x01CC, 0x01CC, 0x01CD, 0x01CE, 0x01CF, + /* D */ 0x01D0, 0x01D1, 0x01D2, 0x01D3, 0x01D4, 0x01D5, 0x01D6, 0x01D7, 0x01D8, 0x01D9, 0x01DA, 0x01DB, 0x01DC, 0x01DD, 0x01DE, 0x01DF, + /* E */ 0x01E0, 0x01E1, 0x01E2, 0x01E3, 0x01E5, 0x01E5, 0x01E6, 0x01E7, 0x01E8, 0x01E9, 0x01EA, 0x01EB, 0x01EC, 0x01ED, 0x01EE, 0x01EF, + /* F */ 0x01F0, 0x01F3, 0x01F3, 0x01F3, 0x01F4, 0x01F5, 0x01F6, 0x01F7, 0x01F8, 0x01F9, 0x01FA, 0x01FB, 0x01FC, 0x01FD, 0x01FE, 0x01FF, + + // Table 3 (for high byte 0x03) + + /* 0 */ 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, 0x0308, 0x0309, 0x030A, 0x030B, 0x030C, 0x030D, 0x030E, 0x030F, + /* 1 */ 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317, 0x0318, 0x0319, 0x031A, 0x031B, 0x031C, 0x031D, 0x031E, 0x031F, + /* 2 */ 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327, 0x0328, 0x0329, 0x032A, 0x032B, 0x032C, 0x032D, 0x032E, 0x032F, + /* 3 */ 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, 0x0335, 0x0336, 0x0337, 0x0338, 0x0339, 0x033A, 0x033B, 0x033C, 0x033D, 0x033E, 0x033F, + /* 4 */ 0x0340, 0x0341, 0x0342, 0x0343, 0x0344, 0x0345, 0x0346, 0x0347, 0x0348, 0x0349, 0x034A, 0x034B, 0x034C, 0x034D, 0x034E, 0x034F, + /* 5 */ 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357, 0x0358, 0x0359, 0x035A, 0x035B, 0x035C, 0x035D, 0x035E, 0x035F, + /* 6 */ 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367, 0x0368, 0x0369, 0x036A, 0x036B, 0x036C, 0x036D, 0x036E, 0x036F, + /* 7 */ 0x0370, 0x0371, 0x0372, 0x0373, 0x0374, 0x0375, 0x0376, 0x0377, 0x0378, 0x0379, 0x037A, 0x037B, 0x037C, 0x037D, 0x037E, 0x037F, + /* 8 */ 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0386, 0x0387, 0x0388, 0x0389, 0x038A, 0x038B, 0x038C, 0x038D, 0x038E, 0x038F, + /* 9 */ 0x0390, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, + /* A */ 0x03C0, 0x03C1, 0x03A2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, 0x03C9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF, + /* B */ 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, + /* C */ 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x03CF, + /* D */ 0x03D0, 0x03D1, 0x03D2, 0x03D3, 0x03D4, 0x03D5, 0x03D6, 0x03D7, 0x03D8, 0x03D9, 0x03DA, 0x03DB, 0x03DC, 0x03DD, 0x03DE, 0x03DF, + /* E */ 0x03E0, 0x03E1, 0x03E3, 0x03E3, 0x03E5, 0x03E5, 0x03E7, 0x03E7, 0x03E9, 0x03E9, 0x03EB, 0x03EB, 0x03ED, 0x03ED, 0x03EF, 0x03EF, + /* F */ 0x03F0, 0x03F1, 0x03F2, 0x03F3, 0x03F4, 0x03F5, 0x03F6, 0x03F7, 0x03F8, 0x03F9, 0x03FA, 0x03FB, 0x03FC, 0x03FD, 0x03FE, 0x03FF, + + // Table 4 (for high byte 0x04) + + /* 0 */ 0x0400, 0x0401, 0x0452, 0x0403, 0x0454, 0x0455, 0x0456, 0x0407, 0x0458, 0x0459, 0x045A, 0x045B, 0x040C, 0x040D, 0x040E, 0x045F, + /* 1 */ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0419, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, + /* 2 */ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, + /* 3 */ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, + /* 4 */ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, + /* 5 */ 0x0450, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, 0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x045D, 0x045E, 0x045F, + /* 6 */ 0x0461, 0x0461, 0x0463, 0x0463, 0x0465, 0x0465, 0x0467, 0x0467, 0x0469, 0x0469, 0x046B, 0x046B, 0x046D, 0x046D, 0x046F, 0x046F, + /* 7 */ 0x0471, 0x0471, 0x0473, 0x0473, 0x0475, 0x0475, 0x0476, 0x0477, 0x0479, 0x0479, 0x047B, 0x047B, 0x047D, 0x047D, 0x047F, 0x047F, + /* 8 */ 0x0481, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487, 0x0488, 0x0489, 0x048A, 0x048B, 0x048C, 0x048D, 0x048E, 0x048F, + /* 9 */ 0x0491, 0x0491, 0x0493, 0x0493, 0x0495, 0x0495, 0x0497, 0x0497, 0x0499, 0x0499, 0x049B, 0x049B, 0x049D, 0x049D, 0x049F, 0x049F, + /* A */ 0x04A1, 0x04A1, 0x04A3, 0x04A3, 0x04A5, 0x04A5, 0x04A7, 0x04A7, 0x04A9, 0x04A9, 0x04AB, 0x04AB, 0x04AD, 0x04AD, 0x04AF, 0x04AF, + /* B */ 0x04B1, 0x04B1, 0x04B3, 0x04B3, 0x04B5, 0x04B5, 0x04B7, 0x04B7, 0x04B9, 0x04B9, 0x04BB, 0x04BB, 0x04BD, 0x04BD, 0x04BF, 0x04BF, + /* C */ 0x04C0, 0x04C1, 0x04C2, 0x04C4, 0x04C4, 0x04C5, 0x04C6, 0x04C8, 0x04C8, 0x04C9, 0x04CA, 0x04CC, 0x04CC, 0x04CD, 0x04CE, 0x04CF, + /* D */ 0x04D0, 0x04D1, 0x04D2, 0x04D3, 0x04D4, 0x04D5, 0x04D6, 0x04D7, 0x04D8, 0x04D9, 0x04DA, 0x04DB, 0x04DC, 0x04DD, 0x04DE, 0x04DF, + /* E */ 0x04E0, 0x04E1, 0x04E2, 0x04E3, 0x04E4, 0x04E5, 0x04E6, 0x04E7, 0x04E8, 0x04E9, 0x04EA, 0x04EB, 0x04EC, 0x04ED, 0x04EE, 0x04EF, + /* F */ 0x04F0, 0x04F1, 0x04F2, 0x04F3, 0x04F4, 0x04F5, 0x04F6, 0x04F7, 0x04F8, 0x04F9, 0x04FA, 0x04FB, 0x04FC, 0x04FD, 0x04FE, 0x04FF, + + // Table 5 (for high byte 0x05) + + /* 0 */ 0x0500, 0x0501, 0x0502, 0x0503, 0x0504, 0x0505, 0x0506, 0x0507, 0x0508, 0x0509, 0x050A, 0x050B, 0x050C, 0x050D, 0x050E, 0x050F, + /* 1 */ 0x0510, 0x0511, 0x0512, 0x0513, 0x0514, 0x0515, 0x0516, 0x0517, 0x0518, 0x0519, 0x051A, 0x051B, 0x051C, 0x051D, 0x051E, 0x051F, + /* 2 */ 0x0520, 0x0521, 0x0522, 0x0523, 0x0524, 0x0525, 0x0526, 0x0527, 0x0528, 0x0529, 0x052A, 0x052B, 0x052C, 0x052D, 0x052E, 0x052F, + /* 3 */ 0x0530, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567, 0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F, + /* 4 */ 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577, 0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F, + /* 5 */ 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0557, 0x0558, 0x0559, 0x055A, 0x055B, 0x055C, 0x055D, 0x055E, 0x055F, + /* 6 */ 0x0560, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567, 0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F, + /* 7 */ 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577, 0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F, + /* 8 */ 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0587, 0x0588, 0x0589, 0x058A, 0x058B, 0x058C, 0x058D, 0x058E, 0x058F, + /* 9 */ 0x0590, 0x0591, 0x0592, 0x0593, 0x0594, 0x0595, 0x0596, 0x0597, 0x0598, 0x0599, 0x059A, 0x059B, 0x059C, 0x059D, 0x059E, 0x059F, + /* A */ 0x05A0, 0x05A1, 0x05A2, 0x05A3, 0x05A4, 0x05A5, 0x05A6, 0x05A7, 0x05A8, 0x05A9, 0x05AA, 0x05AB, 0x05AC, 0x05AD, 0x05AE, 0x05AF, + /* B */ 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7, 0x05B8, 0x05B9, 0x05BA, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF, + /* C */ 0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05C4, 0x05C5, 0x05C6, 0x05C7, 0x05C8, 0x05C9, 0x05CA, 0x05CB, 0x05CC, 0x05CD, 0x05CE, 0x05CF, + /* D */ 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, + /* E */ 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0x05EB, 0x05EC, 0x05ED, 0x05EE, 0x05EF, + /* F */ 0x05F0, 0x05F1, 0x05F2, 0x05F3, 0x05F4, 0x05F5, 0x05F6, 0x05F7, 0x05F8, 0x05F9, 0x05FA, 0x05FB, 0x05FC, 0x05FD, 0x05FE, 0x05FF, + + // Table 6 (for high byte 0x10) + + /* 0 */ 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1008, 0x1009, 0x100A, 0x100B, 0x100C, 0x100D, 0x100E, 0x100F, + /* 1 */ 0x1010, 0x1011, 0x1012, 0x1013, 0x1014, 0x1015, 0x1016, 0x1017, 0x1018, 0x1019, 0x101A, 0x101B, 0x101C, 0x101D, 0x101E, 0x101F, + /* 2 */ 0x1020, 0x1021, 0x1022, 0x1023, 0x1024, 0x1025, 0x1026, 0x1027, 0x1028, 0x1029, 0x102A, 0x102B, 0x102C, 0x102D, 0x102E, 0x102F, + /* 3 */ 0x1030, 0x1031, 0x1032, 0x1033, 0x1034, 0x1035, 0x1036, 0x1037, 0x1038, 0x1039, 0x103A, 0x103B, 0x103C, 0x103D, 0x103E, 0x103F, + /* 4 */ 0x1040, 0x1041, 0x1042, 0x1043, 0x1044, 0x1045, 0x1046, 0x1047, 0x1048, 0x1049, 0x104A, 0x104B, 0x104C, 0x104D, 0x104E, 0x104F, + /* 5 */ 0x1050, 0x1051, 0x1052, 0x1053, 0x1054, 0x1055, 0x1056, 0x1057, 0x1058, 0x1059, 0x105A, 0x105B, 0x105C, 0x105D, 0x105E, 0x105F, + /* 6 */ 0x1060, 0x1061, 0x1062, 0x1063, 0x1064, 0x1065, 0x1066, 0x1067, 0x1068, 0x1069, 0x106A, 0x106B, 0x106C, 0x106D, 0x106E, 0x106F, + /* 7 */ 0x1070, 0x1071, 0x1072, 0x1073, 0x1074, 0x1075, 0x1076, 0x1077, 0x1078, 0x1079, 0x107A, 0x107B, 0x107C, 0x107D, 0x107E, 0x107F, + /* 8 */ 0x1080, 0x1081, 0x1082, 0x1083, 0x1084, 0x1085, 0x1086, 0x1087, 0x1088, 0x1089, 0x108A, 0x108B, 0x108C, 0x108D, 0x108E, 0x108F, + /* 9 */ 0x1090, 0x1091, 0x1092, 0x1093, 0x1094, 0x1095, 0x1096, 0x1097, 0x1098, 0x1099, 0x109A, 0x109B, 0x109C, 0x109D, 0x109E, 0x109F, + /* A */ 0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10D7, 0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10DD, 0x10DE, 0x10DF, + /* B */ 0x10E0, 0x10E1, 0x10E2, 0x10E3, 0x10E4, 0x10E5, 0x10E6, 0x10E7, 0x10E8, 0x10E9, 0x10EA, 0x10EB, 0x10EC, 0x10ED, 0x10EE, 0x10EF, + /* C */ 0x10F0, 0x10F1, 0x10F2, 0x10F3, 0x10F4, 0x10F5, 0x10C6, 0x10C7, 0x10C8, 0x10C9, 0x10CA, 0x10CB, 0x10CC, 0x10CD, 0x10CE, 0x10CF, + /* D */ 0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10D7, 0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10DD, 0x10DE, 0x10DF, + /* E */ 0x10E0, 0x10E1, 0x10E2, 0x10E3, 0x10E4, 0x10E5, 0x10E6, 0x10E7, 0x10E8, 0x10E9, 0x10EA, 0x10EB, 0x10EC, 0x10ED, 0x10EE, 0x10EF, + /* F */ 0x10F0, 0x10F1, 0x10F2, 0x10F3, 0x10F4, 0x10F5, 0x10F6, 0x10F7, 0x10F8, 0x10F9, 0x10FA, 0x10FB, 0x10FC, 0x10FD, 0x10FE, 0x10FF, + + // Table 7 (for high byte 0x20) + + /* 0 */ 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x200B, 0x0000, 0x0000, 0x0000, 0x0000, + /* 1 */ 0x2010, 0x2011, 0x2012, 0x2013, 0x2014, 0x2015, 0x2016, 0x2017, 0x2018, 0x2019, 0x201A, 0x201B, 0x201C, 0x201D, 0x201E, 0x201F, + /* 2 */ 0x2020, 0x2021, 0x2022, 0x2023, 0x2024, 0x2025, 0x2026, 0x2027, 0x2028, 0x2029, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x202F, + /* 3 */ 0x2030, 0x2031, 0x2032, 0x2033, 0x2034, 0x2035, 0x2036, 0x2037, 0x2038, 0x2039, 0x203A, 0x203B, 0x203C, 0x203D, 0x203E, 0x203F, + /* 4 */ 0x2040, 0x2041, 0x2042, 0x2043, 0x2044, 0x2045, 0x2046, 0x2047, 0x2048, 0x2049, 0x204A, 0x204B, 0x204C, 0x204D, 0x204E, 0x204F, + /* 5 */ 0x2050, 0x2051, 0x2052, 0x2053, 0x2054, 0x2055, 0x2056, 0x2057, 0x2058, 0x2059, 0x205A, 0x205B, 0x205C, 0x205D, 0x205E, 0x205F, + /* 6 */ 0x2060, 0x2061, 0x2062, 0x2063, 0x2064, 0x2065, 0x2066, 0x2067, 0x2068, 0x2069, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 7 */ 0x2070, 0x2071, 0x2072, 0x2073, 0x2074, 0x2075, 0x2076, 0x2077, 0x2078, 0x2079, 0x207A, 0x207B, 0x207C, 0x207D, 0x207E, 0x207F, + /* 8 */ 0x2080, 0x2081, 0x2082, 0x2083, 0x2084, 0x2085, 0x2086, 0x2087, 0x2088, 0x2089, 0x208A, 0x208B, 0x208C, 0x208D, 0x208E, 0x208F, + /* 9 */ 0x2090, 0x2091, 0x2092, 0x2093, 0x2094, 0x2095, 0x2096, 0x2097, 0x2098, 0x2099, 0x209A, 0x209B, 0x209C, 0x209D, 0x209E, 0x209F, + /* A */ 0x20A0, 0x20A1, 0x20A2, 0x20A3, 0x20A4, 0x20A5, 0x20A6, 0x20A7, 0x20A8, 0x20A9, 0x20AA, 0x20AB, 0x20AC, 0x20AD, 0x20AE, 0x20AF, + /* B */ 0x20B0, 0x20B1, 0x20B2, 0x20B3, 0x20B4, 0x20B5, 0x20B6, 0x20B7, 0x20B8, 0x20B9, 0x20BA, 0x20BB, 0x20BC, 0x20BD, 0x20BE, 0x20BF, + /* C */ 0x20C0, 0x20C1, 0x20C2, 0x20C3, 0x20C4, 0x20C5, 0x20C6, 0x20C7, 0x20C8, 0x20C9, 0x20CA, 0x20CB, 0x20CC, 0x20CD, 0x20CE, 0x20CF, + /* D */ 0x20D0, 0x20D1, 0x20D2, 0x20D3, 0x20D4, 0x20D5, 0x20D6, 0x20D7, 0x20D8, 0x20D9, 0x20DA, 0x20DB, 0x20DC, 0x20DD, 0x20DE, 0x20DF, + /* E */ 0x20E0, 0x20E1, 0x20E2, 0x20E3, 0x20E4, 0x20E5, 0x20E6, 0x20E7, 0x20E8, 0x20E9, 0x20EA, 0x20EB, 0x20EC, 0x20ED, 0x20EE, 0x20EF, + /* F */ 0x20F0, 0x20F1, 0x20F2, 0x20F3, 0x20F4, 0x20F5, 0x20F6, 0x20F7, 0x20F8, 0x20F9, 0x20FA, 0x20FB, 0x20FC, 0x20FD, 0x20FE, 0x20FF, + + // Table 8 (for high byte 0x21) + + /* 0 */ 0x2100, 0x2101, 0x2102, 0x2103, 0x2104, 0x2105, 0x2106, 0x2107, 0x2108, 0x2109, 0x210A, 0x210B, 0x210C, 0x210D, 0x210E, 0x210F, + /* 1 */ 0x2110, 0x2111, 0x2112, 0x2113, 0x2114, 0x2115, 0x2116, 0x2117, 0x2118, 0x2119, 0x211A, 0x211B, 0x211C, 0x211D, 0x211E, 0x211F, + /* 2 */ 0x2120, 0x2121, 0x2122, 0x2123, 0x2124, 0x2125, 0x2126, 0x2127, 0x2128, 0x2129, 0x212A, 0x212B, 0x212C, 0x212D, 0x212E, 0x212F, + /* 3 */ 0x2130, 0x2131, 0x2132, 0x2133, 0x2134, 0x2135, 0x2136, 0x2137, 0x2138, 0x2139, 0x213A, 0x213B, 0x213C, 0x213D, 0x213E, 0x213F, + /* 4 */ 0x2140, 0x2141, 0x2142, 0x2143, 0x2144, 0x2145, 0x2146, 0x2147, 0x2148, 0x2149, 0x214A, 0x214B, 0x214C, 0x214D, 0x214E, 0x214F, + /* 5 */ 0x2150, 0x2151, 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159, 0x215A, 0x215B, 0x215C, 0x215D, 0x215E, 0x215F, + /* 6 */ 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F, + /* 7 */ 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F, + /* 8 */ 0x2180, 0x2181, 0x2182, 0x2183, 0x2184, 0x2185, 0x2186, 0x2187, 0x2188, 0x2189, 0x218A, 0x218B, 0x218C, 0x218D, 0x218E, 0x218F, + /* 9 */ 0x2190, 0x2191, 0x2192, 0x2193, 0x2194, 0x2195, 0x2196, 0x2197, 0x2198, 0x2199, 0x219A, 0x219B, 0x219C, 0x219D, 0x219E, 0x219F, + /* A */ 0x21A0, 0x21A1, 0x21A2, 0x21A3, 0x21A4, 0x21A5, 0x21A6, 0x21A7, 0x21A8, 0x21A9, 0x21AA, 0x21AB, 0x21AC, 0x21AD, 0x21AE, 0x21AF, + /* B */ 0x21B0, 0x21B1, 0x21B2, 0x21B3, 0x21B4, 0x21B5, 0x21B6, 0x21B7, 0x21B8, 0x21B9, 0x21BA, 0x21BB, 0x21BC, 0x21BD, 0x21BE, 0x21BF, + /* C */ 0x21C0, 0x21C1, 0x21C2, 0x21C3, 0x21C4, 0x21C5, 0x21C6, 0x21C7, 0x21C8, 0x21C9, 0x21CA, 0x21CB, 0x21CC, 0x21CD, 0x21CE, 0x21CF, + /* D */ 0x21D0, 0x21D1, 0x21D2, 0x21D3, 0x21D4, 0x21D5, 0x21D6, 0x21D7, 0x21D8, 0x21D9, 0x21DA, 0x21DB, 0x21DC, 0x21DD, 0x21DE, 0x21DF, + /* E */ 0x21E0, 0x21E1, 0x21E2, 0x21E3, 0x21E4, 0x21E5, 0x21E6, 0x21E7, 0x21E8, 0x21E9, 0x21EA, 0x21EB, 0x21EC, 0x21ED, 0x21EE, 0x21EF, + /* F */ 0x21F0, 0x21F1, 0x21F2, 0x21F3, 0x21F4, 0x21F5, 0x21F6, 0x21F7, 0x21F8, 0x21F9, 0x21FA, 0x21FB, 0x21FC, 0x21FD, 0x21FE, 0x21FF, + + // Table 9 (for high byte 0xFE) + + /* 0 */ 0xFE00, 0xFE01, 0xFE02, 0xFE03, 0xFE04, 0xFE05, 0xFE06, 0xFE07, 0xFE08, 0xFE09, 0xFE0A, 0xFE0B, 0xFE0C, 0xFE0D, 0xFE0E, 0xFE0F, + /* 1 */ 0xFE10, 0xFE11, 0xFE12, 0xFE13, 0xFE14, 0xFE15, 0xFE16, 0xFE17, 0xFE18, 0xFE19, 0xFE1A, 0xFE1B, 0xFE1C, 0xFE1D, 0xFE1E, 0xFE1F, + /* 2 */ 0xFE20, 0xFE21, 0xFE22, 0xFE23, 0xFE24, 0xFE25, 0xFE26, 0xFE27, 0xFE28, 0xFE29, 0xFE2A, 0xFE2B, 0xFE2C, 0xFE2D, 0xFE2E, 0xFE2F, + /* 3 */ 0xFE30, 0xFE31, 0xFE32, 0xFE33, 0xFE34, 0xFE35, 0xFE36, 0xFE37, 0xFE38, 0xFE39, 0xFE3A, 0xFE3B, 0xFE3C, 0xFE3D, 0xFE3E, 0xFE3F, + /* 4 */ 0xFE40, 0xFE41, 0xFE42, 0xFE43, 0xFE44, 0xFE45, 0xFE46, 0xFE47, 0xFE48, 0xFE49, 0xFE4A, 0xFE4B, 0xFE4C, 0xFE4D, 0xFE4E, 0xFE4F, + /* 5 */ 0xFE50, 0xFE51, 0xFE52, 0xFE53, 0xFE54, 0xFE55, 0xFE56, 0xFE57, 0xFE58, 0xFE59, 0xFE5A, 0xFE5B, 0xFE5C, 0xFE5D, 0xFE5E, 0xFE5F, + /* 6 */ 0xFE60, 0xFE61, 0xFE62, 0xFE63, 0xFE64, 0xFE65, 0xFE66, 0xFE67, 0xFE68, 0xFE69, 0xFE6A, 0xFE6B, 0xFE6C, 0xFE6D, 0xFE6E, 0xFE6F, + /* 7 */ 0xFE70, 0xFE71, 0xFE72, 0xFE73, 0xFE74, 0xFE75, 0xFE76, 0xFE77, 0xFE78, 0xFE79, 0xFE7A, 0xFE7B, 0xFE7C, 0xFE7D, 0xFE7E, 0xFE7F, + /* 8 */ 0xFE80, 0xFE81, 0xFE82, 0xFE83, 0xFE84, 0xFE85, 0xFE86, 0xFE87, 0xFE88, 0xFE89, 0xFE8A, 0xFE8B, 0xFE8C, 0xFE8D, 0xFE8E, 0xFE8F, + /* 9 */ 0xFE90, 0xFE91, 0xFE92, 0xFE93, 0xFE94, 0xFE95, 0xFE96, 0xFE97, 0xFE98, 0xFE99, 0xFE9A, 0xFE9B, 0xFE9C, 0xFE9D, 0xFE9E, 0xFE9F, + /* A */ 0xFEA0, 0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4, 0xFEA5, 0xFEA6, 0xFEA7, 0xFEA8, 0xFEA9, 0xFEAA, 0xFEAB, 0xFEAC, 0xFEAD, 0xFEAE, 0xFEAF, + /* B */ 0xFEB0, 0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4, 0xFEB5, 0xFEB6, 0xFEB7, 0xFEB8, 0xFEB9, 0xFEBA, 0xFEBB, 0xFEBC, 0xFEBD, 0xFEBE, 0xFEBF, + /* C */ 0xFEC0, 0xFEC1, 0xFEC2, 0xFEC3, 0xFEC4, 0xFEC5, 0xFEC6, 0xFEC7, 0xFEC8, 0xFEC9, 0xFECA, 0xFECB, 0xFECC, 0xFECD, 0xFECE, 0xFECF, + /* D */ 0xFED0, 0xFED1, 0xFED2, 0xFED3, 0xFED4, 0xFED5, 0xFED6, 0xFED7, 0xFED8, 0xFED9, 0xFEDA, 0xFEDB, 0xFEDC, 0xFEDD, 0xFEDE, 0xFEDF, + /* E */ 0xFEE0, 0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4, 0xFEE5, 0xFEE6, 0xFEE7, 0xFEE8, 0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC, 0xFEED, 0xFEEE, 0xFEEF, + /* F */ 0xFEF0, 0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4, 0xFEF5, 0xFEF6, 0xFEF7, 0xFEF8, 0xFEF9, 0xFEFA, 0xFEFB, 0xFEFC, 0xFEFD, 0xFEFE, 0x0000, + + // Table 10 (for high byte 0xFF) + + /* 0 */ 0xFF00, 0xFF01, 0xFF02, 0xFF03, 0xFF04, 0xFF05, 0xFF06, 0xFF07, 0xFF08, 0xFF09, 0xFF0A, 0xFF0B, 0xFF0C, 0xFF0D, 0xFF0E, 0xFF0F, + /* 1 */ 0xFF10, 0xFF11, 0xFF12, 0xFF13, 0xFF14, 0xFF15, 0xFF16, 0xFF17, 0xFF18, 0xFF19, 0xFF1A, 0xFF1B, 0xFF1C, 0xFF1D, 0xFF1E, 0xFF1F, + /* 2 */ 0xFF20, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, + /* 3 */ 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, 0xFF58, 0xFF59, 0xFF5A, 0xFF3B, 0xFF3C, 0xFF3D, 0xFF3E, 0xFF3F, + /* 4 */ 0xFF40, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, + /* 5 */ 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, 0xFF58, 0xFF59, 0xFF5A, 0xFF5B, 0xFF5C, 0xFF5D, 0xFF5E, 0xFF5F, + /* 6 */ 0xFF60, 0xFF61, 0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF66, 0xFF67, 0xFF68, 0xFF69, 0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, 0xFF6E, 0xFF6F, + /* 7 */ 0xFF70, 0xFF71, 0xFF72, 0xFF73, 0xFF74, 0xFF75, 0xFF76, 0xFF77, 0xFF78, 0xFF79, 0xFF7A, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F, + /* 8 */ 0xFF80, 0xFF81, 0xFF82, 0xFF83, 0xFF84, 0xFF85, 0xFF86, 0xFF87, 0xFF88, 0xFF89, 0xFF8A, 0xFF8B, 0xFF8C, 0xFF8D, 0xFF8E, 0xFF8F, + /* 9 */ 0xFF90, 0xFF91, 0xFF92, 0xFF93, 0xFF94, 0xFF95, 0xFF96, 0xFF97, 0xFF98, 0xFF99, 0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, 0xFF9E, 0xFF9F, + /* A */ 0xFFA0, 0xFFA1, 0xFFA2, 0xFFA3, 0xFFA4, 0xFFA5, 0xFFA6, 0xFFA7, 0xFFA8, 0xFFA9, 0xFFAA, 0xFFAB, 0xFFAC, 0xFFAD, 0xFFAE, 0xFFAF, + /* B */ 0xFFB0, 0xFFB1, 0xFFB2, 0xFFB3, 0xFFB4, 0xFFB5, 0xFFB6, 0xFFB7, 0xFFB8, 0xFFB9, 0xFFBA, 0xFFBB, 0xFFBC, 0xFFBD, 0xFFBE, 0xFFBF, + /* C */ 0xFFC0, 0xFFC1, 0xFFC2, 0xFFC3, 0xFFC4, 0xFFC5, 0xFFC6, 0xFFC7, 0xFFC8, 0xFFC9, 0xFFCA, 0xFFCB, 0xFFCC, 0xFFCD, 0xFFCE, 0xFFCF, + /* D */ 0xFFD0, 0xFFD1, 0xFFD2, 0xFFD3, 0xFFD4, 0xFFD5, 0xFFD6, 0xFFD7, 0xFFD8, 0xFFD9, 0xFFDA, 0xFFDB, 0xFFDC, 0xFFDD, 0xFFDE, 0xFFDF, + /* E */ 0xFFE0, 0xFFE1, 0xFFE2, 0xFFE3, 0xFFE4, 0xFFE5, 0xFFE6, 0xFFE7, 0xFFE8, 0xFFE9, 0xFFEA, 0xFFEB, 0xFFEC, 0xFFED, 0xFFEE, 0xFFEF, + /* F */ 0xFFF0, 0xFFF1, 0xFFF2, 0xFFF3, 0xFFF4, 0xFFF5, 0xFFF6, 0xFFF7, 0xFFF8, 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, 0xFFFD, 0xFFFE, 0xFFFF, +}; + +/* RelString case folding table */ + +unsigned short gCompareTable[] = { + + /* 0 */ 0x0000, 0x0100, 0x0200, 0x0300, 0x0400, 0x0500, 0x0600, 0x0700, 0x0800, 0x0900, 0x0A00, 0x0B00, 0x0C00, 0x0D00, 0x0E00, 0x0F00, + /* 1 */ 0x1000, 0x1100, 0x1200, 0x1300, 0x1400, 0x1500, 0x1600, 0x1700, 0x1800, 0x1900, 0x1A00, 0x1B00, 0x1C00, 0x1D00, 0x1E00, 0x1F00, + /* 2 */ 0x2000, 0x2100, 0x2200, 0x2300, 0x2400, 0x2500, 0x2600, 0x2700, 0x2800, 0x2900, 0x2A00, 0x2B00, 0x2C00, 0x2D00, 0x2E00, 0x2F00, + /* 3 */ 0x3000, 0x3100, 0x3200, 0x3300, 0x3400, 0x3500, 0x3600, 0x3700, 0x3800, 0x3900, 0x3A00, 0x3B00, 0x3C00, 0x3D00, 0x3E00, 0x3F00, + /* 4 */ 0x4000, 0x4100, 0x4200, 0x4300, 0x4400, 0x4500, 0x4600, 0x4700, 0x4800, 0x4900, 0x4A00, 0x4B00, 0x4C00, 0x4D00, 0x4E00, 0x4F00, + /* 5 */ 0x5000, 0x5100, 0x5200, 0x5300, 0x5400, 0x5500, 0x5600, 0x5700, 0x5800, 0x5900, 0x5A00, 0x5B00, 0x5C00, 0x5D00, 0x5E00, 0x5F00, + + // 0x60 maps to 'a' + // range 0x61 to 0x7a ('a' to 'z') map to upper case + + /* 6 */ 0x4180, 0x4100, 0x4200, 0x4300, 0x4400, 0x4500, 0x4600, 0x4700, 0x4800, 0x4900, 0x4A00, 0x4B00, 0x4C00, 0x4D00, 0x4E00, 0x4F00, + /* 7 */ 0x5000, 0x5100, 0x5200, 0x5300, 0x5400, 0x5500, 0x5600, 0x5700, 0x5800, 0x5900, 0x5A00, 0x7B00, 0x7C00, 0x7D00, 0x7E00, 0x7F00, + + // range 0x80 to 0xd8 gets mapped... + + /* 8 */ 0x4108, 0x410C, 0x4310, 0x4502, 0x4E0A, 0x4F08, 0x5508, 0x4182, 0x4104, 0x4186, 0x4108, 0x410A, 0x410C, 0x4310, 0x4502, 0x4584, + /* 9 */ 0x4586, 0x4588, 0x4982, 0x4984, 0x4986, 0x4988, 0x4E0A, 0x4F82, 0x4F84, 0x4F86, 0x4F08, 0x4F0A, 0x5582, 0x5584, 0x5586, 0x5508, + /* A */ 0xA000, 0xA100, 0xA200, 0xA300, 0xA400, 0xA500, 0xA600, 0x5382, 0xA800, 0xA900, 0xAA00, 0xAB00, 0xAC00, 0xAD00, 0x4114, 0x4F0E, + /* B */ 0xB000, 0xB100, 0xB200, 0xB300, 0xB400, 0xB500, 0xB600, 0xB700, 0xB800, 0xB900, 0xBA00, 0x4192, 0x4F92, 0xBD00, 0x4114, 0x4F0E, + /* C */ 0xC000, 0xC100, 0xC200, 0xC300, 0xC400, 0xC500, 0xC600, 0x2206, 0x2208, 0xC900, 0x2000, 0x4104, 0x410A, 0x4F0A, 0x4F14, 0x4F14, + /* D */ 0xD000, 0xD100, 0x2202, 0x2204, 0x2702, 0x2704, 0xD600, 0xD700, 0x5988, 0xD900, 0xDA00, 0xDB00, 0xDC00, 0xDD00, 0xDE00, 0xDF00, + + /* E */ 0xE000, 0xE100, 0xE200, 0xE300, 0xE400, 0xE500, 0xE600, 0xE700, 0xE800, 0xE900, 0xEA00, 0xEB00, 0xEC00, 0xED00, 0xEE00, 0xEF00, + /* F */ 0xF000, 0xF100, 0xF200, 0xF300, 0xF400, 0xF500, 0xF600, 0xF700, 0xF800, 0xF900, 0xFA00, 0xFB00, 0xFC00, 0xFD00, 0xFE00, 0xFF00, + +}; +#else /* ! UNCOMPRESSED */ + +enum { + kTypeLiteral = 0, + kTypeAscending = 1, + kTypeAscending256 = 2 +}; + +struct compressed_block { + unsigned char type; + unsigned char count; + unsigned short data; +}; + +unsigned short *gLowerCaseTable; + +struct compressed_block gLowerCaseTableCompressed[] = { + {0x0, 0x1, 0x100}, + {0x0, 0x1, 0x200}, + {0x0, 0x1, 0x0}, + {0x0, 0x1, 0x300}, + {0x0, 0x1, 0x400}, + {0x0, 0x1, 0x500}, + {0x0, 0xa, 0x0}, + {0x0, 0x1, 0x600}, + {0x0, 0xf, 0x0}, + {0x0, 0x1, 0x700}, + {0x0, 0x1, 0x800}, + {0x0, 0xdc, 0x0}, + {0x0, 0x1, 0x900}, + {0x0, 0x1, 0xa00}, + {0x0, 0x1, 0xffff}, + {0x1, 0x40, 0x1}, + {0x1, 0x1a, 0x61}, + {0x1, 0x6b, 0x5b}, + {0x0, 0x1, 0xe6}, + {0x1, 0x9, 0xc7}, + {0x0, 0x1, 0xf0}, + {0x1, 0x7, 0xd1}, + {0x0, 0x1, 0xf8}, + {0x1, 0x5, 0xd9}, + {0x0, 0x1, 0xfe}, + {0x1, 0x31, 0xdf}, + {0x0, 0x2, 0x111}, + {0x1, 0x14, 0x112}, + {0x0, 0x2, 0x127}, + {0x1, 0xa, 0x128}, + {0x0, 0x2, 0x133}, + {0x1, 0xb, 0x134}, + {0x0, 0x2, 0x140}, + {0x0, 0x2, 0x142}, + {0x1, 0x7, 0x143}, + {0x0, 0x2, 0x14b}, + {0x1, 0x6, 0x14c}, + {0x0, 0x2, 0x153}, + {0x1, 0x12, 0x154}, + {0x0, 0x2, 0x167}, + {0x1, 0x19, 0x168}, + {0x0, 0x1, 0x253}, + {0x0, 0x2, 0x183}, + {0x0, 0x2, 0x185}, + {0x0, 0x1, 0x254}, + {0x0, 0x2, 0x188}, + {0x1, 0x2, 0x256}, + {0x0, 0x2, 0x18c}, + {0x0, 0x1, 0x18d}, + {0x0, 0x1, 0x1dd}, + {0x0, 0x1, 0x259}, + {0x0, 0x1, 0x25b}, + {0x0, 0x2, 0x192}, + {0x0, 0x1, 0x260}, + {0x0, 0x1, 0x263}, + {0x0, 0x1, 0x195}, + {0x0, 0x1, 0x269}, + {0x0, 0x1, 0x268}, + {0x0, 0x2, 0x199}, + {0x1, 0x2, 0x19a}, + {0x0, 0x1, 0x26f}, + {0x0, 0x1, 0x272}, + {0x0, 0x1, 0x19e}, + {0x0, 0x1, 0x275}, + {0x1, 0x2, 0x1a0}, + {0x0, 0x2, 0x1a3}, + {0x0, 0x2, 0x1a5}, + {0x0, 0x1, 0x1a6}, + {0x0, 0x2, 0x1a8}, + {0x0, 0x1, 0x283}, + {0x1, 0x2, 0x1aa}, + {0x0, 0x2, 0x1ad}, + {0x0, 0x1, 0x288}, + {0x1, 0x2, 0x1af}, + {0x1, 0x2, 0x28a}, + {0x0, 0x2, 0x1b4}, + {0x0, 0x2, 0x1b6}, + {0x0, 0x1, 0x292}, + {0x0, 0x2, 0x1b9}, + {0x1, 0x2, 0x1ba}, + {0x0, 0x2, 0x1bd}, + {0x1, 0x6, 0x1be}, + {0x0, 0x3, 0x1c6}, + {0x0, 0x3, 0x1c9}, + {0x0, 0x3, 0x1cc}, + {0x1, 0x17, 0x1cd}, + {0x0, 0x2, 0x1e5}, + {0x1, 0xb, 0x1e6}, + {0x0, 0x3, 0x1f3}, + {0x1, 0xc, 0x1f4}, + {0x1, 0x91, 0x300}, + {0x1, 0x11, 0x3b1}, + {0x0, 0x1, 0x3a2}, + {0x1, 0x7, 0x3c3}, + {0x1, 0x38, 0x3aa}, + {0x0, 0x2, 0x3e3}, + {0x0, 0x2, 0x3e5}, + {0x0, 0x2, 0x3e7}, + {0x0, 0x2, 0x3e9}, + {0x0, 0x2, 0x3eb}, + {0x0, 0x2, 0x3ed}, + {0x0, 0x2, 0x3ef}, + {0x1, 0x12, 0x3f0}, + {0x0, 0x1, 0x452}, + {0x0, 0x1, 0x403}, + {0x1, 0x3, 0x454}, + {0x0, 0x1, 0x407}, + {0x1, 0x4, 0x458}, + {0x1, 0x3, 0x40c}, + {0x0, 0x1, 0x45f}, + {0x1, 0x9, 0x430}, + {0x0, 0x1, 0x419}, + {0x1, 0x16, 0x43a}, + {0x1, 0x30, 0x430}, + {0x0, 0x2, 0x461}, + {0x0, 0x2, 0x463}, + {0x0, 0x2, 0x465}, + {0x0, 0x2, 0x467}, + {0x0, 0x2, 0x469}, + {0x0, 0x2, 0x46b}, + {0x0, 0x2, 0x46d}, + {0x0, 0x2, 0x46f}, + {0x0, 0x2, 0x471}, + {0x0, 0x2, 0x473}, + {0x0, 0x2, 0x475}, + {0x1, 0x2, 0x476}, + {0x0, 0x2, 0x479}, + {0x0, 0x2, 0x47b}, + {0x0, 0x2, 0x47d}, + {0x0, 0x2, 0x47f}, + {0x0, 0x2, 0x481}, + {0x1, 0xe, 0x482}, + {0x0, 0x2, 0x491}, + {0x0, 0x2, 0x493}, + {0x0, 0x2, 0x495}, + {0x0, 0x2, 0x497}, + {0x0, 0x2, 0x499}, + {0x0, 0x2, 0x49b}, + {0x0, 0x2, 0x49d}, + {0x0, 0x2, 0x49f}, + {0x0, 0x2, 0x4a1}, + {0x0, 0x2, 0x4a3}, + {0x0, 0x2, 0x4a5}, + {0x0, 0x2, 0x4a7}, + {0x0, 0x2, 0x4a9}, + {0x0, 0x2, 0x4ab}, + {0x0, 0x2, 0x4ad}, + {0x0, 0x2, 0x4af}, + {0x0, 0x2, 0x4b1}, + {0x0, 0x2, 0x4b3}, + {0x0, 0x2, 0x4b5}, + {0x0, 0x2, 0x4b7}, + {0x0, 0x2, 0x4b9}, + {0x0, 0x2, 0x4bb}, + {0x0, 0x2, 0x4bd}, + {0x0, 0x2, 0x4bf}, + {0x1, 0x3, 0x4c0}, + {0x0, 0x2, 0x4c4}, + {0x1, 0x2, 0x4c5}, + {0x0, 0x2, 0x4c8}, + {0x1, 0x2, 0x4c9}, + {0x0, 0x2, 0x4cc}, + {0x1, 0x64, 0x4cd}, + {0x1, 0x26, 0x561}, + {0x1, 0xa9, 0x557}, + {0x1, 0xa0, 0x1000}, + {0x1, 0x26, 0x10d0}, + {0x1, 0x3a, 0x10c6}, + {0x1, 0xc, 0x2000}, + {0x0, 0x4, 0x0}, + {0x1, 0x1a, 0x2010}, + {0x0, 0x5, 0x0}, + {0x1, 0x3b, 0x202f}, + {0x0, 0x6, 0x0}, + {0x1, 0xf0, 0x2070}, + {0x1, 0x10, 0x2170}, + {0x1, 0x90, 0x2170}, + {0x1, 0xff, 0xfe00}, + {0x0, 0x1, 0x0}, + {0x1, 0x21, 0xff00}, + {0x1, 0x1a, 0xff41}, + {0x1, 0xc5, 0xff3b}, +}; +// Please update count if you add/remove entries but also please just let +// the compiler calculate it so you don't get it wrong. +//#define kLowerCaseTableNBlocks 182 +#define kLowerCaseTableNBlocks (sizeof(gLowerCaseTableCompressed)/sizeof(*gLowerCaseTableCompressed)) +// WARNING: The expanded size MUST be updated if you change the table and +// cannot be calculated at compile time. +#define kLowerCaseTableDataSize 5632 /* size of uncompressed structure in bytes */ + +unsigned short *gCompareTable; + +struct compressed_block gCompareTableCompressed[] = { + {0x2, 0x60, 0x0}, + {0x0, 0x1, 0x4180}, + {0x2, 0x1a, 0x4100}, + {0x2, 0x5, 0x7b00}, + {0x0, 0x1, 0x4108}, + {0x0, 0x1, 0x410c}, + {0x0, 0x1, 0x4310}, + {0x0, 0x1, 0x4502}, + {0x0, 0x1, 0x4e0a}, + {0x0, 0x1, 0x4f08}, + {0x0, 0x1, 0x5508}, + {0x0, 0x1, 0x4182}, + {0x0, 0x1, 0x4104}, + {0x0, 0x1, 0x4186}, + {0x0, 0x1, 0x4108}, + {0x0, 0x1, 0x410a}, + {0x0, 0x1, 0x410c}, + {0x0, 0x1, 0x4310}, + {0x0, 0x1, 0x4502}, + {0x0, 0x1, 0x4584}, + {0x0, 0x1, 0x4586}, + {0x0, 0x1, 0x4588}, + {0x0, 0x1, 0x4982}, + {0x0, 0x1, 0x4984}, + {0x0, 0x1, 0x4986}, + {0x0, 0x1, 0x4988}, + {0x0, 0x1, 0x4e0a}, + {0x0, 0x1, 0x4f82}, + {0x0, 0x1, 0x4f84}, + {0x0, 0x1, 0x4f86}, + {0x0, 0x1, 0x4f08}, + {0x0, 0x1, 0x4f0a}, + {0x0, 0x1, 0x5582}, + {0x0, 0x1, 0x5584}, + {0x0, 0x1, 0x5586}, + {0x0, 0x1, 0x5508}, + {0x2, 0x7, 0xa000}, + {0x0, 0x1, 0x5382}, + {0x2, 0x6, 0xa800}, + {0x0, 0x1, 0x4114}, + {0x0, 0x1, 0x4f0e}, + {0x2, 0xb, 0xb000}, + {0x0, 0x1, 0x4192}, + {0x0, 0x1, 0x4f92}, + {0x0, 0x1, 0xbd00}, + {0x0, 0x1, 0x4114}, + {0x0, 0x1, 0x4f0e}, + {0x2, 0x7, 0xc000}, + {0x0, 0x1, 0x2206}, + {0x0, 0x1, 0x2208}, + {0x0, 0x1, 0xc900}, + {0x0, 0x1, 0x2000}, + {0x0, 0x1, 0x4104}, + {0x0, 0x1, 0x410a}, + {0x0, 0x1, 0x4f0a}, + {0x0, 0x2, 0x4f14}, + {0x2, 0x2, 0xd000}, + {0x0, 0x1, 0x2202}, + {0x0, 0x1, 0x2204}, + {0x0, 0x1, 0x2702}, + {0x0, 0x1, 0x2704}, + {0x2, 0x2, 0xd600}, + {0x0, 0x1, 0x5988}, + {0x2, 0x27, 0xd900}, +}; +// Please update count if you add/remove entries but also please just let +// the compiler calculate it so you don't get it wrong. +//#define kCompareTableNBlocks 64 +#define kCompareTableNBlocks (sizeof(gCompareTableCompressed)/sizeof(*gCompareTableCompressed)) +// WARNING: The expanded size MUST be updated if you change the table and +// cannot be calculated at compile time. +#define kCompareTableDataSize 512 /* size of uncompressed structure in bytes */ + +#endif /* UNCOMPRESSED */ Index: branches/slice/rev749/libsaio/vbe.c =================================================================== --- branches/slice/rev749/libsaio/vbe.c (revision 0) +++ branches/slice/rev749/libsaio/vbe.c (revision 1169) @@ -0,0 +1,304 @@ +/* + * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 2.0 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright 1993 NeXT, Inc. + * All rights reserved. + */ + +#include "libsaio.h" +#include "vbe.h" + +/* + * Globals + */ +static biosBuf_t bb; + +int getVBEInfo( void * infoBlock ) +{ + bb.intno = 0x10; + bb.eax.rr = funcGetControllerInfo; + bb.es = SEG( infoBlock ); + bb.edi.rr = OFF( infoBlock ); + bios( &bb ); + return(bb.eax.r.h); +} + +int getVBEModeInfo( int mode, void * minfo_p ) +{ + bb.intno = 0x10; + bb.eax.rr = funcGetModeInfo; + bb.ecx.rr = mode; + bb.es = SEG(minfo_p); + bb.edi.rr = OFF(minfo_p); + bios(&bb); + return(bb.eax.r.h); +} +#if UNUSED +int getVBEDACFormat(unsigned char *format) +{ + bb.intno = 0x10; + bb.eax.rr = funcGetSetPaletteFormat; + bb.ebx.r.l = subfuncGet; + bios(&bb); + *format = bb.ebx.r.h; + return(bb.eax.r.h); +} + +int setVBEDACFormat(unsigned char format) +{ + bb.intno = 0x10; + bb.eax.rr = funcGetSetPaletteFormat; + bb.ebx.r.l = subfuncSet; + bb.ebx.r.h = format; + bios(&bb); + return(bb.eax.r.h); +} +#endif + +int getEDID( void * edidBlock, UInt8 block) +{ + bzero(&bb, sizeof(bb)); + bb.intno = 0x10; + bb.eax.rr = funcGetEDID; + bb.ebx.r.l= 0x01; + bb.edx.rr = block; + + bb.es = SEG( edidBlock ); + bb.edi.rr = OFF( edidBlock ); + + bios( &bb ); + return(bb.eax.r.h); +} + + + +/* + * Default GTF parameter values. + */ +#define kCellGranularity 8.0 // character cell granularity +#define kMinVSyncPlusBP 550.0 // min VSync + BP interval (us) +#define kMinFrontPorch 1.0 // minimum front porch in lines(V)/cells(H) +#define kVSyncLines 3.0 // width of VSync in lines +#define kHSyncWidth 8.0 // HSync as a percent of total line width +#define kC 30.0 // C = (C'-J) * (K/256) + J +#define kM 300.0 // M = K/256 * M' + +int Round(double f) +{ + return (int)(f + 0.5); +} + +/* + * from http://www.azillionmonkeys.com/qed/sqroot.html + */ +#if UNUSED +double Sqrt( double y ) +{ + double x, z, tempf; + unsigned long *tfptr = ((unsigned long *)&tempf) + 1; + + tempf = y; + *tfptr = (0xbfcdd90a - *tfptr)>>1; /* estimate of 1/sqrt(y) */ + x = tempf; + z = y*0.5; /* hoist out the “/2” */ + x = (1.5*x) - (x*x)*(x*z); /* iteration formula */ + x = (1.5*x) - (x*x)*(x*z); + x = (1.5*x) - (x*x)*(x*z); + x = (1.5*x) - (x*x)*(x*z); + x = (1.5*x) - (x*x)*(x*z); + return x*y; +} + +int generateCRTCTiming( unsigned short width, + unsigned short height, + unsigned long paramValue, + int paramType, + VBECRTCInfoBlock * timing ) +{ + double h_period_est, h_freq, h_period, h_total_pixels, h_sync_pixels; + double h_active_pixels, h_ideal_duty_cycle, h_blank_pixels, pixel_freq = 0; + double v_sync_plus_bp = 0, v_total_lines = 0, v_field_rate_est, v_frame_rate = 0; + const double h_pixels = (double) width; + const double v_lines = (double) height; + + enum { + left_margin_pixels = 0, + right_margin_pixels = 0, + top_margin_lines = 0, + bot_margin_lines = 0, + interlace = 0 + }; + + // Total number of active pixels in image and both margins + h_active_pixels = h_pixels + left_margin_pixels + right_margin_pixels; + + if (paramType == kCRTCParamPixelClock) + { + // Pixel clock provided in MHz + pixel_freq = (double) paramValue / 1000000; + + // Ideal horizontal period from the blanking duty cycle equation + h_period = ((kC - 100) + (Sqrt(((100 - kC) * (100 - kC)) + (0.4 * kM * + (h_active_pixels + right_margin_pixels + left_margin_pixels) / + pixel_freq)))) / 2.0 / kM * 1000; + } + else /* kCRTCParamRefreshRate */ + { + double v_field_rate_in = (double) paramValue; + + // Estimate the horizontal period + h_period_est = ((1 / v_field_rate_in) - kMinVSyncPlusBP / 1000000) / + (v_lines + (2 * top_margin_lines) + kMinFrontPorch + interlace) * + 1000000; + + // Number of lines in Vsync + back porch + v_sync_plus_bp = Round(kMinVSyncPlusBP / h_period_est); + + // Total number of lines in Vetical field period + v_total_lines = v_lines + top_margin_lines + bot_margin_lines + + v_sync_plus_bp + interlace + kMinFrontPorch; + + // Estimate the vertical field frequency + v_field_rate_est = 1 / h_period_est / v_total_lines * 1000000; + + // Find the actual horizontal period + h_period = h_period_est / (v_field_rate_in / v_field_rate_est); + + // Find the vertical frame rate (no interlace) + v_frame_rate = 1 / h_period / v_total_lines * 1000000; + } + + // Ideal blanking duty cycle from the blanking duty cycle equation + h_ideal_duty_cycle = kC - (kM * h_period / 1000); + + // Number of pixels in the blanking time to the nearest double character cell + h_blank_pixels = Round(h_active_pixels * h_ideal_duty_cycle / + (100 - h_ideal_duty_cycle) / (2 * kCellGranularity)) * + (2 * kCellGranularity); + + // Total number of horizontal pixels + h_total_pixels = h_active_pixels + h_blank_pixels; + + if (paramType == kCRTCParamPixelClock) + { + // Horizontal frequency + h_freq = pixel_freq / h_total_pixels * 1000; + + // Number of lines in V sync + back porch + v_sync_plus_bp = Round(kMinVSyncPlusBP * h_freq / 1000); + + // Total number of lines in vertical field period + v_total_lines = v_lines + top_margin_lines + bot_margin_lines + + interlace + v_sync_plus_bp + kMinFrontPorch; + + // Vertical frame frequency + v_frame_rate = Round(h_freq / v_total_lines * 1000); + } + else + { + // Find pixel clock frequency + pixel_freq = Round(h_total_pixels / h_period); + } + + h_sync_pixels = Round(h_total_pixels * kHSyncWidth / 100 / kCellGranularity) * + kCellGranularity; + + timing->HTotal = h_total_pixels; + timing->HSyncStart = h_active_pixels + (h_blank_pixels / 2) - h_sync_pixels; + timing->HSyncEnd = timing->HSyncStart + h_sync_pixels; + timing->VTotal = v_total_lines; + timing->VSyncStart = v_total_lines - v_sync_plus_bp; + timing->VSyncEnd = timing->VSyncStart + kVSyncLines; + timing->Flags = kCRTCNegativeHorizontalSync; + timing->PixelClock = pixel_freq * 1000000; + timing->RefreshRate = v_frame_rate * 100; + + return 0; +} + +#endif + +int setVBEMode(unsigned short mode, const VBECRTCInfoBlock * timing) +{ + bb.intno = 0x10; + bb.eax.rr = funcSetMode; + bb.ebx.rr = mode; + if (timing) { + bb.es = SEG(timing); + bb.edi.rr = OFF(timing); + } + bios(&bb); + return(bb.eax.r.h); +} + + +int setVBEPalette(void *palette) +{ + bb.intno = 0x10; + bb.eax.rr = funcGetSetPaletteData; + bb.ebx.r.l = subfuncSet; + bb.ecx.rr = 256; + bb.edx.rr = 0; + bb.es = SEG(palette); + bb.edi.rr = OFF(palette); + bios(&bb); + return(bb.eax.r.h); +} + +#if UNUSED + +int getVBEPalette(void *palette) +{ + bb.intno = 0x10; + bb.eax.rr = funcGetSetPaletteData; + bb.ebx.r.l = subfuncGet; + bb.ecx.rr = 256; + bb.edx.rr = 0; + bb.es = SEG(palette); + bb.edi.rr = OFF(palette); + bios(&bb); + return(bb.eax.r.h); +} + +int getVBECurrentMode(unsigned short *mode) +{ + bb.intno = 0x10; + bb.eax.rr = funcGetCurrentMode; + bios(&bb); + *mode = bb.ebx.rr; + return(bb.eax.r.h); +} + +int getVBEPixelClock(unsigned short mode, unsigned long * pixelClock) +{ + bb.intno = 0x10; + bb.eax.rr = funcGetSetPixelClock; + bb.ebx.r.l = 0; + bb.ecx.rx = *pixelClock; + bb.edx.rr = mode; + bios(&bb); + *pixelClock = bb.ecx.rx; + return(bb.eax.r.h); +} +#endif Index: branches/slice/rev749/libsaio/bootstruct.h =================================================================== --- branches/slice/rev749/libsaio/bootstruct.h (revision 0) +++ branches/slice/rev749/libsaio/bootstruct.h (revision 1169) @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 2002-2003 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 2.0 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef __BOOTSTRUCT_H +#define __BOOTSTRUCT_H + +#include +#include "saio_types.h" +#include "bios.h" +#include "device_tree.h" + +/*! + Kernel boot args global also used by booter for its own data. + */ +extern boot_args *bootArgs; +extern Node *gMemoryMapNode; +extern void *new_dsdt; + +#define VGA_TEXT_MODE 0 +//defined in /usr/../boot.h + +//#define GRAPHICS_MODE 1 +//#define FB_TEXT_MODE 2 + +/* + * Maximum number of boot drivers that can be loaded. + */ +#define NDRIVERS 500 + +#define CONFIG_SIZE (40 * 4096) + +/* + * Max size fo config data array, in bytes. + */ +#define IO_CONFIG_DATA_SIZE 163840 + +#define kMemoryMapCountMax 40 + +/* + * PCI bus information. + */ +typedef struct _PCI_bus_info_t { + union { + struct { + unsigned char configMethod1 :1; + unsigned char configMethod2 :1; + unsigned char :2; + unsigned char specialCycle1 :1; + unsigned char specialCycle2 :1; + } s; + unsigned char d; + } u_bus; + unsigned char maxBusNum; + unsigned char majorVersion; + unsigned char minorVersion; + unsigned char BIOSPresent; +} PCI_bus_info_t; + +typedef struct { + unsigned long address; // address where driver was loaded + unsigned long size; // number of bytes + unsigned long type; // driver type +} driver_config_t; + +/* + * INT15, E820h - Query System Address Map. + * + * Documented in ACPI Specification Rev 2.0, + * Chapter 15 (System Address Map Interfaces). + */ + +/* + * ACPI defined memory range types. + */ +enum { + kMemoryRangeUsable = 1, // RAM usable by the OS. + kMemoryRangeReserved = 2, // Reserved. (Do not use) + kMemoryRangeACPI = 3, // ACPI tables. Can be reclaimed. + kMemoryRangeNVS = 4, // ACPI NVS memory. (Do not use) + + /* Undefined types should be treated as kMemoryRangeReserved */ +}; + +/*! + PrivateBootInfo has fields used by the booter that used to be part of + KernelBootArgs_t *bootArgs. When the switch was made to EFI the structure + completely changed to boot_args *bootArgs. This (new to boot-132) structure + contains the fields the kernel no longer cares about but the booter still + uses internally. Some fields (e.g. the video information) remain interesting + to the kernel and are thus located in bootArgs although with different field names. + */ +typedef struct PrivateBootInfo { + int convmem; // conventional memory + int extmem; // extended memory +#if 0 + int numBootDrivers; // number of drivers loaded +#endif + char bootFile[128]; // kernel file name + + unsigned long memoryMapCount; + MemoryRange memoryMap[kMemoryMapCountMax]; + + PCI_bus_info_t pciInfo; + +#if 0 + driver_config_t driverConfig[NDRIVERS]; +#endif + char * configEnd; // pointer to end of config files + char config[CONFIG_SIZE]; + + config_file_t bootConfig; // boot.plist + config_file_t overrideConfig; // additional boot.plist which can override bootConfig keys + config_file_t themeConfig; // theme.plist + config_file_t smbiosConfig; // smbios.plist + config_file_t helperConfig; // boot helper partition's boot.plist + config_file_t ramdiskConfig; // RAMDisk.plist +} PrivateBootInfo_t; + +extern PrivateBootInfo_t *bootInfo; + +#endif /* __BOOTSTRUCT_H */ Index: branches/slice/rev749/libsaio/device_tree.c =================================================================== --- branches/slice/rev749/libsaio/device_tree.c (revision 0) +++ branches/slice/rev749/libsaio/device_tree.c (revision 1169) @@ -0,0 +1,540 @@ +/* + * Copyright (c) 2005 Apple Computer, Inc. All Rights Reserved. + */ + +#if 1 +/* + + Structures for a Flattened Device Tree + */ + +#define kPropNameLength 32 + +typedef struct DeviceTreeNodeProperty { + char name[kPropNameLength]; // NUL terminated property name + unsigned long length; // Length (bytes) of folloing prop value + // unsigned long value[1]; // Variable length value of property + // Padded to a multiple of a longword? +} DeviceTreeNodeProperty; + +typedef struct OpaqueDTEntry { + unsigned long nProperties; // Number of props[] elements (0 => end) + unsigned long nChildren; // Number of children[] elements + // DeviceTreeNodeProperty props[];// array size == nProperties + // DeviceTreeNode children[]; // array size == nChildren +} DeviceTreeNode; + +typedef char DTPropertyNameBuf[32]; +/* Entry Name Definitions (Entry Names are C-Strings)*/ +enum { + kDTMaxEntryNameLength = 31 /* Max length of a C-String Entry Name (terminator not included) */ +}; + +/* length of DTEntryNameBuf = kDTMaxEntryNameLength +1*/ +typedef char DTEntryNameBuf[32]; +#endif + +#include "libsaio.h" +#include "device_tree.h" + +#if DEBUG +#define DPRINTF(args...) printf(args) +void +DT__PrintTree(Node *node); +#else +#define DPRINTF(args...) +#endif + + +#define RoundToLong(x) (((x) + 3) & ~3) + +static struct _DTSizeInfo { + uint32_t numNodes; + uint32_t numProperties; + uint32_t totalPropertySize; +} DTInfo; + +#define kAllocSize 4096 + +static Node *rootNode; + +static Node *freeNodes, *allocedNodes; +static Property *freeProperties, *allocedProperties; + +Property * +DT__AddProperty(Node *node, const char *name, uint32_t length, void *value) +{ + Property *prop; + + DPRINTF("DT__AddProperty([Node '%s'], '%s', %d, 0x%x)\n", DT__GetName(node), name, length, value); + if (freeProperties == NULL) { + void *buf = malloc(kAllocSize); + int i; + + DPRINTF("Allocating more free properties\n"); + if (buf == 0) return 0; + bzero(buf, kAllocSize); + // Use the first property to record the allocated buffer + // for later freeing. + prop = (Property *)buf; + prop->next = allocedProperties; + allocedProperties = prop; + prop->value = buf; + prop++; + for (i=1; i<(kAllocSize / sizeof(Property)); i++) { + prop->next = freeProperties; + freeProperties = prop; + prop++; + } + } + prop = freeProperties; + freeProperties = prop->next; + + prop->name = name; + prop->length = length; + prop->value = value; + + // Always add to end of list + if (node->properties == 0) { + node->properties = prop; + } else { + node->last_prop->next = prop; + } + node->last_prop = prop; + prop->next = 0; + + DPRINTF("Done [0x%x]\n", prop); + + DTInfo.numProperties++; + DTInfo.totalPropertySize += RoundToLong(length); + + return prop; +} + +Node * +DT__AddChild(Node *parent, const char *name) +{ + Node *node; + + if (freeNodes == NULL) { + void *buf = malloc(kAllocSize); + int i; + + DPRINTF("Allocating more free nodes\n"); + if (buf == 0) return 0; + bzero(buf, kAllocSize); + node = (Node *)buf; + // Use the first node to record the allocated buffer + // for later freeing. + node->next = allocedNodes; + allocedNodes = node; + node->children = (Node *)buf; + node++; + for (i=1; i<(kAllocSize / sizeof(Node)); i++) { + node->next = freeNodes; + freeNodes = node; + node++; + } + } + DPRINTF("DT__AddChild(0x%x, '%s')\n", parent, name); + node = freeNodes; + freeNodes = node->next; + DPRINTF("Got free node 0x%x\n", node); + DPRINTF("prop = 0x%x, children = 0x%x, next = 0x%x\n", node->properties, node->children, node->next); + + if (parent == NULL) { + rootNode = node; + node->next = 0; + } else { + node->next = parent->children; + parent->children = node; + } + DTInfo.numNodes++; + DT__AddProperty(node, "name", strlen(name) + 1, (void *) name); + return node; +} + +void +DT__FreeProperty(Property *prop) +{ + prop->next = freeProperties; + freeProperties = prop; +} +void +DT__FreeNode(Node *node) +{ + node->next = freeNodes; + freeNodes = node; +} + +void +DT__Initialize(void) +{ + DPRINTF("DT__Initialize\n"); + + freeNodes = 0; + allocedNodes = 0; + freeProperties = 0; + allocedProperties = 0; + + DTInfo.numNodes = 0; + DTInfo.numProperties = 0; + DTInfo.totalPropertySize = 0; + + rootNode = DT__AddChild(NULL, "/"); + DPRINTF("DT__Initialize done\n"); +} + +/* + * Free up memory used by in-memory representation + * of device tree. + */ +void +DT__Finalize(void) +{ + Node *node; + Property *prop; + + DPRINTF("DT__Finalize\n"); + for (prop = allocedProperties; prop != NULL; prop = prop->next) { + free(prop->value); + } + allocedProperties = NULL; + freeProperties = NULL; + + for (node = allocedNodes; node != NULL; node = node->next) { + free((void *)node->children); + } + allocedNodes = NULL; + freeNodes = NULL; + rootNode = NULL; + + // XXX leaks any created strings + + DTInfo.numNodes = 0; + DTInfo.numProperties = 0; + DTInfo.totalPropertySize = 0; +} + +static void * +FlattenNodes(Node *node, void *buffer) +{ + Property *prop; + DeviceTreeNode *flatNode; + DeviceTreeNodeProperty *flatProp; + int count; + + if (node == 0) return buffer; + + flatNode = (DeviceTreeNode *)buffer; + buffer += sizeof(DeviceTreeNode); + + for (count = 0, prop = node->properties; prop != 0; count++, prop = prop->next) { + flatProp = (DeviceTreeNodeProperty *)buffer; + strcpy(flatProp->name, prop->name); + flatProp->length = prop->length; + buffer += sizeof(DeviceTreeNodeProperty); + bcopy(prop->value, buffer, prop->length); + buffer += RoundToLong(prop->length); + } + flatNode->nProperties = count; + + for (count = 0, node = node->children; node != 0; count++, node = node->next) { + buffer = FlattenNodes(node, buffer); + } + flatNode->nChildren = count; + + return buffer; +} + +/* + * Flatten the in-memory representation of the device tree + * into a binary DT block. + * To get the buffer size needed, call with result = 0. + * To have a buffer allocated for you, call with *result = 0. + * To use your own buffer, call with *result = &buffer. + */ + +void +DT__FlattenDeviceTree(void **buffer_p, uint32_t *length) +{ + uint32_t totalSize; + void *buf; + + DPRINTF("DT__FlattenDeviceTree(0x%x, 0x%x)\n", buffer_p, length); +#if DEBUG + if (buffer_p) DT__PrintTree(rootNode); +#endif + + totalSize = DTInfo.numNodes * sizeof(DeviceTreeNode) + + DTInfo.numProperties * sizeof(DeviceTreeNodeProperty) + + DTInfo.totalPropertySize; + + DPRINTF("Total size 0x%x\n", totalSize); + if (buffer_p != 0) { + if (totalSize == 0) { + buf = 0; + } else { + if (*buffer_p == 0) { + buf = malloc(totalSize); + } else { + buf = *buffer_p; + } + bzero(buf, totalSize); + + FlattenNodes(rootNode, buf); + } + *buffer_p = buf; + } + if (length) + *length = totalSize; +} + +char * +DT__GetName(Node *node) +{ + Property *prop; + + //DPRINTF("DT__GetName(0x%x)\n", node); + //DPRINTF("Node properties = 0x%x\n", node->properties); + for (prop = node->properties; prop; prop = prop->next) { + //DPRINTF("Prop '%s'\n", prop->name); + if (strcmp(prop->name, "name") == 0) { + return prop->value; + } + } + //DPRINTF("DT__GetName returns 0\n"); + return "(null)"; +} + +Node * +DT__FindNode(const char *path, bool createIfMissing) +{ + Node *node, *child; + DTPropertyNameBuf nameBuf; + char *bp; + int i; + + DPRINTF("DT__FindNode('%s', %d)\n", path, createIfMissing); + + // Start at root + node = rootNode; + DPRINTF("root = 0x%x\n", rootNode); + + while (node) { + // Skip leading slash + while (*path == '/') path++; + + for (i=0, bp = nameBuf; ++i < kDTMaxEntryNameLength && *path && *path != '/'; bp++, path++) *bp = *path; + *bp = '\0'; + + if (nameBuf[0] == '\0') { + // last path entry + break; + } + DPRINTF("Node '%s'\n", nameBuf); + + for (child = node->children; child != 0; child = child->next) { + DPRINTF("Child 0x%x\n", child); + if (strcmp(DT__GetName(child), nameBuf) == 0) { + break; + } + } + if (child == 0 && createIfMissing) { + DPRINTF("Creating node\n"); + char *str = malloc(strlen(nameBuf) + 1); + // XXX this will leak + strcpy(str, nameBuf); + + child = DT__AddChild(node, str); + } + node = child; + } + return node; +} + +#if DEBUG + +void +DT__PrintNode(Node *node, int level) +{ + char spaces[10], *cp = spaces; + Property *prop; + + if (level > 9) level = 9; + while (level--) *cp++ = ' '; + *cp = '\0'; + + verbose("%s===Node===\n", spaces); + for (prop = node->properties; prop; prop = prop->next) { + char c = *((char *)prop->value); + if (prop->length < 64 && ( + strcmp(prop->name, "name") == 0 || + (c >= '0' && c <= '9') || + (c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || c == '_')) { + verbose("%s Property '%s' [%d] = '%s'\n", spaces, prop->name, prop->length, prop->value); + } else { + verbose("%s Property '%s' [%d] = (data)\n", spaces, prop->name, prop->length); + } + } + verbose("%s==========\n", spaces); +} + +static void +_PrintTree(Node *node, int level) +{ + DT__PrintNode(node, level); + level++; + for (node = node->children; node; node = node->next) + _PrintTree(node, level); +} + +void +DT__PrintTree(Node *node) +{ + if (node == 0) node = rootNode; + _PrintTree(node, 0); +} + +void +DT__PrintFlattenedNode(DTEntry entry, int level) +{ + char spaces[10], *cp = spaces; + DTPropertyIterator propIter; + char *name; + void *prop; + int propSize; + + if (level > 9) level = 9; + while (level--) *cp++ = ' '; + *cp = '\0'; + + verbose("%s===Entry %p===\n", spaces, entry); + if (kSuccess != DTCreatePropertyIterator(entry, &propIter)) { + verbose("Couldn't create property iterator\n"); + return; + } + while( kSuccess == DTIterateProperties( propIter, &name)) { + if( kSuccess != DTGetProperty( entry, name, &prop, &propSize )) + continue; + verbose("%s Property %s = %s\n", spaces, name, prop); + } + DTDisposePropertyIterator(propIter); + + verbose("%s==========\n", spaces); +} + +static void +_PrintFlattenedTree(DTEntry entry, int level) +{ + DTEntryIterator entryIter; + + PrintFlattenedNode(entry, level); + + if (kSuccess != DTCreateEntryIterator(entry, &entryIter)) { + printf("Couldn't create entry iterator\n"); + return; + } + level++; + while (kSuccess == DTIterateEntries( entryIter, &entry )) { + _PrintFlattenedTree(entry, level); + } + DTDisposeEntryIterator(entryIter); +} + +void +DT__PrintFlattenedTree(DTEntry entry) +{ + _PrintFlattenedTree(entry, 0); +} + + +int +main(int argc, char **argv) +{ + DTEntry dtEntry; + DTPropertyIterator propIter; + DTEntryIterator entryIter; + void *prop; + int propSize; + char *name; + void *flatTree; + uint32_t flatSize; + + Node *node; + + node = AddChild(NULL, "device-tree"); + AddProperty(node, "potato", 4, "foo"); + AddProperty(node, "chemistry", 4, "bar"); + AddProperty(node, "physics", 4, "baz"); + + node = AddChild(node, "dev"); + AddProperty(node, "one", 4, "one"); + AddProperty(node, "two", 4, "two"); + AddProperty(node, "three", 6, "three"); + + node = AddChild(rootNode, "foo"); + AddProperty(node, "aaa", 4, "aab"); + AddProperty(node, "bbb", 4, "bbc"); + AddProperty(node, "cccc", 6, "ccccd"); + + node = FindNode("/this/is/a/test", 1); + AddProperty(node, "dddd", 12, "abcdefghijk"); + + verbose("In-memory tree:\n\n"); + + PrintTree(rootNode); + + FlattenDeviceTree(&flatTree, &flatSize); + + verbose("Flat tree = %p, size %d\n", flatTree, flatSize); + + dtEntry = (DTEntry)flatTree; + + verbose("\n\nPrinting flat tree\n\n"); + + DTInit(dtEntry); + + PrintFlattenedTree((DTEntry)flatTree); +#if 0 + printf("=== Entry %p ===\n", dtEntry); + if (kSuccess != DTCreatePropertyIterator(dtEntry, &propIter)) { + printf("Couldn't create property iterator\n"); + return 1; + } + while( kSuccess == DTIterateProperties( propIter, &name)) { + if( kSuccess != DTGetProperty( dtEntry, name, &prop, &propSize )) + continue; + printf(" Property %s = %s\n", name, prop); + } + DTDisposePropertyIterator(propIter); + printf("========\n"); + + if (kSuccess != DTCreateEntryIterator(dtEntry, &entryIter)) { + printf("Couldn't create entry iterator\n"); + return 1; + } + while (kSuccess == DTIterateEntries( entryIter, &dtEntry )) { + printf("=== Entry %p ===\n", dtEntry); + + if (kSuccess != DTCreatePropertyIterator(dtEntry, &propIter)) { + printf("Couldn't create property iterator\n"); + return 1; + } + while( kSuccess == DTIterateProperties( propIter, &name)) { + if( kSuccess != DTGetProperty( dtEntry, name, &prop, &propSize )) + continue; + printf(" Property %s = %s\n", name, prop); + } + DTDisposePropertyIterator(propIter); + printf("========\n"); + } + DTDisposeEntryIterator(entryIter); +#endif + + return 0; +} + +#endif + Index: branches/slice/rev749/libsaio/hfs.c =================================================================== --- branches/slice/rev749/libsaio/hfs.c (revision 0) +++ branches/slice/rev749/libsaio/hfs.c (revision 1169) @@ -0,0 +1,1064 @@ +/* + * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 2.0 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * hfs.c - File System Module for HFS and HFS+. + * + * Copyright (c) 1999-2002 Apple Computer, Inc. + * + * DRI: Josh de Cesare + */ + +#include +#include + +#include "hfs.h" + +#define kBlockSize (0x200) + +#define kMDBBaseOffset (2 * kBlockSize) + +#define kBTreeCatalog (0) +#define kBTreeExtents (1) + +#ifdef __i386__ + +static CICell gCurrentIH; +static long long gAllocationOffset; +static long gIsHFSPlus; +static long gCaseSensitive; +static long gBlockSize; +static long gCacheBlockSize; +static char *gBTreeHeaderBuffer; +static BTHeaderRec *gBTHeaders[2]; +static char *gHFSMdbVib; +static HFSMasterDirectoryBlock *gHFSMDB; +static char *gHFSPlusHeader; +static HFSPlusVolumeHeader *gHFSPlus; +static char *gLinkTemp; +static long long gVolID; +static char *gTempStr; + +#else /* !__i386__ */ + +static CICell gCurrentIH; +static long long gAllocationOffset; +static long gIsHFSPlus; +static long gBlockSize; +static long gCaseSensitive; +static long gCacheBlockSize; +static char gBTreeHeaderBuffer[512]; +static BTHeaderRec *gBTHeaders[2]; +static char gHFSMdbVib[kBlockSize]; +static HFSMasterDirectoryBlock *gHFSMDB =(HFSMasterDirectoryBlock*)gHFSMdbVib; +static char gHFSPlusHeader[kBlockSize]; +static HFSPlusVolumeHeader *gHFSPlus =(HFSPlusVolumeHeader*)gHFSPlusHeader; +static char gLinkTemp[64]; +static long long gVolID; + +#endif /* !__i386__ */ + +static long ReadFile(void *file, uint64_t *length, void *base, uint64_t offset); +static long GetCatalogEntryInfo(void *entry, long *flags, long *time, + FinderInfo *finderInfo, long *infoValid); +static long ResolvePathToCatalogEntry(char *filePath, long *flags, + void *entry, long dirID, long long *dirIndex); + +static long GetCatalogEntry(long long *dirIndex, char **name, + long *flags, long *time, + FinderInfo *finderInfo, long *infoValid); +static long ReadCatalogEntry(char *fileName, long dirID, void *entry, + long long *dirIndex); +static long ReadExtentsEntry(long fileID, long startBlock, void *entry); + +static long ReadBTreeEntry(long btree, void *key, char *entry, long long *dirIndex); +static void GetBTreeRecord(long index, char *nodeBuffer, long nodeSize, + char **key, char **data); + +static long ReadExtent(char *extent, uint64_t extentSize, long extentFile, + uint64_t offset, uint64_t size, void *buffer, long cache); + +static long GetExtentStart(void *extents, long index); +static long GetExtentSize(void *extents, long index); + +static long CompareHFSCatalogKeys(void *key, void *testKey); +static long CompareHFSPlusCatalogKeys(void *key, void *testKey); +static long CompareHFSExtentsKeys(void *key, void *testKey); +static long CompareHFSPlusExtentsKeys(void *key, void *testKey); + +extern long FastRelString(u_int8_t *str1, u_int8_t *str2); +extern long BinaryUnicodeCompare(u_int16_t *uniStr1, u_int32_t len1, + u_int16_t *uniStr2, u_int32_t len2); + + +static void SwapFinderInfo(FndrFileInfo *dst, FndrFileInfo *src) +{ + dst->fdType = SWAP_BE32(src->fdType); + dst->fdCreator = SWAP_BE32(src->fdCreator); + dst->fdFlags = SWAP_BE16(src->fdFlags); + // Don't bother with location +} + +void HFSFree(CICell ih) +{ + if(gCurrentIH == ih) + gCurrentIH = 0; + free(ih); +} + +bool HFSProbe (const void *buf) +{ + const HFSMasterDirectoryBlock *mdb; + const HFSPlusVolumeHeader *header; + mdb=(const HFSMasterDirectoryBlock *)(((const char*)buf)+kMDBBaseOffset); + header=(const HFSPlusVolumeHeader *)(((const char*)buf)+kMDBBaseOffset); + + if ( SWAP_BE16(mdb->drSigWord) == kHFSSigWord ) + return true; + if (SWAP_BE16(header->signature) != kHFSPlusSigWord && + SWAP_BE16(header->signature) != kHFSXSigWord) + return false; + return true; +} + +long HFSInitPartition(CICell ih) +{ + long extentSize, extentFile, nodeSize; + void *extent; + + if (ih == gCurrentIH) { +#ifdef __i386__ + CacheInit(ih, gCacheBlockSize); +#endif + return 0; + } + +#ifdef __i386__ + if (!gTempStr) gTempStr = (char *)malloc(4096); + if (!gLinkTemp) gLinkTemp = (char *)malloc(64); + if (!gBTreeHeaderBuffer) gBTreeHeaderBuffer = (char *)malloc(512); + if (!gHFSMdbVib) { + gHFSMdbVib = (char *)malloc(kBlockSize); + gHFSMDB = (HFSMasterDirectoryBlock *)gHFSMdbVib; + } + if (!gHFSPlusHeader) { + gHFSPlusHeader = (char *)malloc(kBlockSize); + gHFSPlus = (HFSPlusVolumeHeader *)gHFSPlusHeader; + } + if (!gTempStr || !gLinkTemp || !gBTreeHeaderBuffer || + !gHFSMdbVib || !gHFSPlusHeader) return -1; +#endif /* __i386__ */ + + gAllocationOffset = 0; + gIsHFSPlus = 0; + gCaseSensitive = 0; + gBTHeaders[0] = 0; + gBTHeaders[1] = 0; + + // Look for the HFS MDB + Seek(ih, kMDBBaseOffset); + Read(ih, (long)gHFSMdbVib, kBlockSize); + + if ( SWAP_BE16(gHFSMDB->drSigWord) == kHFSSigWord ) { + gAllocationOffset = SWAP_BE16(gHFSMDB->drAlBlSt) * kBlockSize; + + // See if it is HFSPlus + if (SWAP_BE16(gHFSMDB->drEmbedSigWord) != kHFSPlusSigWord) { + // Normal HFS; + gCacheBlockSize = gBlockSize = SWAP_BE32(gHFSMDB->drAlBlkSiz); + CacheInit(ih, gCacheBlockSize); + gCurrentIH = ih; + + // grab the 64 bit volume ID + bcopy(&gHFSMDB->drFndrInfo[6], &gVolID, 8); + + // Get the Catalog BTree node size. + extent = (HFSExtentDescriptor *)&gHFSMDB->drCTExtRec; + extentSize = SWAP_BE32(gHFSMDB->drCTFlSize); + extentFile = kHFSCatalogFileID; + ReadExtent(extent, extentSize, extentFile, 0, 256, + gBTreeHeaderBuffer + kBTreeCatalog * 256, 0); + + nodeSize = SWAP_BE16(((BTHeaderRec *)(gBTreeHeaderBuffer + kBTreeCatalog * 256 + + sizeof(BTNodeDescriptor)))->nodeSize); + + // If the BTree node size is larger than the block size, reset the cache. + if (nodeSize > gBlockSize) { + gCacheBlockSize = nodeSize; + CacheInit(ih, gCacheBlockSize); + } + + return 0; + } + + // Calculate the offset to the embeded HFSPlus volume. + gAllocationOffset += (long long)SWAP_BE16(gHFSMDB->drEmbedExtent.startBlock) * + SWAP_BE32(gHFSMDB->drAlBlkSiz); + } + + // Look for the HFSPlus Header + Seek(ih, gAllocationOffset + kMDBBaseOffset); + Read(ih, (long)gHFSPlusHeader, kBlockSize); + + // Not a HFS+ or HFSX volume. + if (SWAP_BE16(gHFSPlus->signature) != kHFSPlusSigWord && + SWAP_BE16(gHFSPlus->signature) != kHFSXSigWord) { + verbose("HFS signature was not present.\n"); + gCurrentIH = 0; + return -1; + } + + gIsHFSPlus = 1; + gCacheBlockSize = gBlockSize = SWAP_BE32(gHFSPlus->blockSize); + CacheInit(ih, gCacheBlockSize); + gCurrentIH = ih; + + ih->modTime = SWAP_BE32(gHFSPlus->modifyDate) - 2082844800; + + // grab the 64 bit volume ID + bcopy(&gHFSPlus->finderInfo[24], &gVolID, 8); + + // Get the Catalog BTree node size. + extent = &gHFSPlus->catalogFile.extents; + extentSize = SWAP_BE64(gHFSPlus->catalogFile.logicalSize); + extentFile = kHFSCatalogFileID; + + ReadExtent(extent, extentSize, extentFile, 0, 256, + gBTreeHeaderBuffer + kBTreeCatalog * 256, 0); + + nodeSize = SWAP_BE16(((BTHeaderRec *)(gBTreeHeaderBuffer + kBTreeCatalog * 256 + + sizeof(BTNodeDescriptor)))->nodeSize); + + // If the BTree node size is larger than the block size, reset the cache. + if (nodeSize > gBlockSize) { + gCacheBlockSize = nodeSize; + CacheInit(ih, gCacheBlockSize); + } + + return 0; +} + +long HFSLoadFile(CICell ih, char * filePath) +{ + return HFSReadFile(ih, filePath, (void *)gFSLoadAddress, 0, 0); +} + +long HFSReadFile(CICell ih, char * filePath, void *base, uint64_t offset, uint64_t length) +{ + char entry[512]; + char devStr[12]; + long dirID, result, flags; + + if (HFSInitPartition(ih) == -1) return -1; + + dirID = kHFSRootFolderID; + // Skip a lead '\'. Start in the system folder if there are two. + if (filePath[0] == '/') { + if (filePath[1] == '/') { + if (gIsHFSPlus) dirID = SWAP_BE32(((long *)gHFSPlus->finderInfo)[5]); + else dirID = SWAP_BE32(gHFSMDB->drFndrInfo[5]); + if (dirID == 0) { + return -1; + } + filePath++; + } + filePath++; + } + + result = ResolvePathToCatalogEntry(filePath, &flags, entry, dirID, 0); + if ((result == -1) || ((flags & kFileTypeMask) != kFileTypeFlat)) { + return -1; + } + +#if UNUSED + // Not yet for Intel. System.config/Default.table will fail this check. + // Check file owner and permissions. + if (flags & (kOwnerNotRoot | kPermGroupWrite | kPermOtherWrite)) return -1; +#endif + + result = ReadFile(entry, &length, base, offset); + if (result == -1) { + return -1; + } + + getDeviceDescription(ih, devStr); +// verbose("Read HFS%s file: [%s/%s] %d bytes.\n", +// (gIsHFSPlus ? "+" : ""), devStr, filePath, (uint32_t)length); + + return length; +} + +long HFSGetDirEntry(CICell ih, char * dirPath, long long * dirIndex, char ** name, + long * flags, long * time, + FinderInfo * finderInfo, long * infoValid) +{ + char entry[512]; + long dirID, dirFlags; + + if (HFSInitPartition(ih) == -1) return -1; + + if (*dirIndex == -1) return -1; + + dirID = kHFSRootFolderID; + // Skip a lead '\'. Start in the system folder if there are two. + if (dirPath[0] == '/') { + if (dirPath[1] == '/') { + if (gIsHFSPlus) dirID = SWAP_BE32(((long *)gHFSPlus->finderInfo)[5]); + else dirID = SWAP_BE32(gHFSMDB->drFndrInfo[5]); + if (dirID == 0) return -1; + dirPath++; + } + dirPath++; + } + + if (*dirIndex == 0) { + ResolvePathToCatalogEntry(dirPath, &dirFlags, entry, dirID, dirIndex); + if (*dirIndex == 0) *dirIndex = -1; + if ((dirFlags & kFileTypeMask) != kFileTypeUnknown) return -1; + } + + GetCatalogEntry(dirIndex, name, flags, time, finderInfo, infoValid); + if (*dirIndex == 0) *dirIndex = -1; + if ((*flags & kFileTypeMask) == kFileTypeUnknown) return -1; + + return 0; +} + +void +HFSGetDescription(CICell ih, char *str, long strMaxLen) +{ + + UInt16 nodeSize; + UInt32 firstLeafNode; + long long dirIndex; + char *name; + long flags, time; + + if (HFSInitPartition(ih) == -1) { return; } + + /* Fill some crucial data structures by side effect. */ + dirIndex = 0; + HFSGetDirEntry(ih, "/", &dirIndex, &name, &flags, &time, 0, 0); + + /* Now we can loook up the volume name node. */ + nodeSize = SWAP_BE16(gBTHeaders[kBTreeCatalog]->nodeSize); + firstLeafNode = SWAP_BE32(gBTHeaders[kBTreeCatalog]->firstLeafNode); + + dirIndex = (long long) firstLeafNode * nodeSize; + + GetCatalogEntry(&dirIndex, &name, &flags, &time, 0, 0); + + strncpy(str, name, strMaxLen); + str[strMaxLen] = '\0'; +} + + +long +HFSGetFileBlock(CICell ih, char *filePath, unsigned long long *firstBlock) +{ + char entry[512]; + long dirID, result, flags; + void *extents; + HFSCatalogFile *hfsFile = (void *)entry; + HFSPlusCatalogFile *hfsPlusFile = (void *)entry; + + if (HFSInitPartition(ih) == -1) return -1; + + dirID = kHFSRootFolderID; + // Skip a lead '\'. Start in the system folder if there are two. + if (filePath[0] == '/') { + if (filePath[1] == '/') { + if (gIsHFSPlus) dirID = SWAP_BE32(((long *)gHFSPlus->finderInfo)[5]); + else dirID = SWAP_BE32(gHFSMDB->drFndrInfo[5]); + if (dirID == 0) { + return -1; + } + filePath++; + } + filePath++; + } + + result = ResolvePathToCatalogEntry(filePath, &flags, entry, dirID, 0); + if ((result == -1) || ((flags & kFileTypeMask) != kFileTypeFlat)) { + printf("HFS: Resolve path %s failed\n", filePath); + return -1; + } + + if (gIsHFSPlus) { + extents = &hfsPlusFile->dataFork.extents; + } else { + extents = &hfsFile->dataExtents; + } + +#if DEBUG + printf("extent start 0x%x\n", (unsigned long)GetExtentStart(extents, 0)); + printf("block size 0x%x\n", (unsigned long)gBlockSize); + printf("Allocation offset 0x%x\n", (unsigned long)gAllocationOffset); +#endif + *firstBlock = ((unsigned long long)GetExtentStart(extents, 0) * (unsigned long long) gBlockSize + gAllocationOffset) / 512ULL; + return 0; +} + +long HFSGetUUID(CICell ih, char *uuidStr) +{ + if (HFSInitPartition(ih) == -1) return -1; + if (gVolID == 0LL) return -1; + + return CreateUUIDString((uint8_t*)(&gVolID), sizeof(gVolID), uuidStr); +} + +// Private Functions + +static long ReadFile(void * file, uint64_t * length, void * base, uint64_t offset) +{ + void *extents; + long fileID; + uint64_t fileLength; + HFSCatalogFile *hfsFile = file; + HFSPlusCatalogFile *hfsPlusFile = file; + + if (gIsHFSPlus) { + fileID = SWAP_BE32(hfsPlusFile->fileID); + fileLength = (uint64_t)SWAP_BE64(hfsPlusFile->dataFork.logicalSize); + extents = &hfsPlusFile->dataFork.extents; + } else { + fileID = SWAP_BE32(hfsFile->fileID); + fileLength = SWAP_BE32(hfsFile->dataLogicalSize); + extents = &hfsFile->dataExtents; + } + + if (offset > fileLength) { + printf("Offset is too large.\n"); + return -1; + } + + if ((*length == 0) || ((offset + *length) > fileLength)) { + *length = fileLength - offset; + } + +/* if (*length > kLoadSize) { + printf("File is too large.\n"); + return -1; + }*/ + + *length = ReadExtent((char *)extents, fileLength, fileID, + offset, *length, (char *)base, 0); + + return 0; +} + +static long GetCatalogEntryInfo(void * entry, long * flags, long * time, + FinderInfo * finderInfo, long * infoValid) +{ + long tmpTime = 0; + long valid = 0; + + // Get information about the file. + + switch ( SWAP_BE16(*(short *)entry) ) + { + case kHFSFolderRecord : + *flags = kFileTypeDirectory; + tmpTime = SWAP_BE32(((HFSCatalogFolder *)entry)->modifyDate); + break; + + case kHFSPlusFolderRecord : + *flags = kFileTypeDirectory | + (SWAP_BE16(((HFSPlusCatalogFolder *)entry)->bsdInfo.fileMode) & kPermMask); + if (SWAP_BE32(((HFSPlusCatalogFolder *)entry)->bsdInfo.ownerID) != 0) + *flags |= kOwnerNotRoot; + tmpTime = SWAP_BE32(((HFSPlusCatalogFolder *)entry)->contentModDate); + break; + + case kHFSFileRecord : + *flags = kFileTypeFlat; + tmpTime = SWAP_BE32(((HFSCatalogFile *)entry)->modifyDate); + if (finderInfo) { + SwapFinderInfo((FndrFileInfo *)finderInfo, &((HFSCatalogFile *)entry)->userInfo); + valid = 1; + } + break; + + case kHFSPlusFileRecord : + *flags = kFileTypeFlat | + (SWAP_BE16(((HFSPlusCatalogFile *)entry)->bsdInfo.fileMode) & kPermMask); + if (SWAP_BE32(((HFSPlusCatalogFile *)entry)->bsdInfo.ownerID) != 0) + *flags |= kOwnerNotRoot; + tmpTime = SWAP_BE32(((HFSPlusCatalogFile *)entry)->contentModDate); + if (finderInfo) { + SwapFinderInfo((FndrFileInfo *)finderInfo, &((HFSPlusCatalogFile *)entry)->userInfo); + valid = 1; + } + break; + + case kHFSFileThreadRecord : + case kHFSPlusFileThreadRecord : + case kHFSFolderThreadRecord : + case kHFSPlusFolderThreadRecord : + *flags = kFileTypeUnknown; + tmpTime = 0; + break; + } + + if (time != 0) { + // Convert base time from 1904 to 1970. + *time = tmpTime - 2082844800; + } + if (infoValid) *infoValid = valid; + + return 0; +} + +static long ResolvePathToCatalogEntry(char * filePath, long * flags, + void * entry, long dirID, long long * dirIndex) +{ + char *restPath; + long result, cnt, subFolderID = 0; + long long tmpDirIndex; + HFSPlusCatalogFile *hfsPlusFile; + + // Copy the file name to gTempStr + cnt = 0; + while ((filePath[cnt] != '/') && (filePath[cnt] != '\0')) cnt++; + strlcpy(gTempStr, filePath, cnt+1); + + // Move restPath to the right place. + if (filePath[cnt] != '\0') cnt++; + restPath = filePath + cnt; + + // gTempStr is a name in the current Dir. + // restPath is the rest of the path if any. + + result = ReadCatalogEntry(gTempStr, dirID, entry, dirIndex); + if (result == -1) { + return -1; + } + + GetCatalogEntryInfo(entry, flags, 0, 0, 0); + + if ((*flags & kFileTypeMask) == kFileTypeDirectory) { + if (gIsHFSPlus) + subFolderID = SWAP_BE32(((HFSPlusCatalogFolder *)entry)->folderID); + else + subFolderID = SWAP_BE32(((HFSCatalogFolder *)entry)->folderID); + } + + if ((*flags & kFileTypeMask) == kFileTypeDirectory) + result = ResolvePathToCatalogEntry(restPath, flags, entry, + subFolderID, dirIndex); + + if (gIsHFSPlus && ((*flags & kFileTypeMask) == kFileTypeFlat)) { + hfsPlusFile = (HFSPlusCatalogFile *)entry; + if ((SWAP_BE32(hfsPlusFile->userInfo.fdType) == kHardLinkFileType) && + (SWAP_BE32(hfsPlusFile->userInfo.fdCreator) == kHFSPlusCreator)) { + sprintf(gLinkTemp, "%s/%s%ld", HFSPLUSMETADATAFOLDER, + HFS_INODE_PREFIX, SWAP_BE32(hfsPlusFile->bsdInfo.special.iNodeNum)); + result = ResolvePathToCatalogEntry(gLinkTemp, flags, entry, + kHFSRootFolderID, &tmpDirIndex); + } + } + + return result; +} + +static long GetCatalogEntry(long long * dirIndex, char ** name, + long * flags, long * time, + FinderInfo * finderInfo, long * infoValid) +{ + long extentSize, nodeSize, curNode, index; + void *extent; + char *nodeBuf, *testKey, *entry; + BTNodeDescriptor *node; + + if (gIsHFSPlus) { + extent = &gHFSPlus->catalogFile.extents; + extentSize = SWAP_BE64(gHFSPlus->catalogFile.logicalSize); + } else { + extent = (HFSExtentDescriptor *)&gHFSMDB->drCTExtRec; + extentSize = SWAP_BE32(gHFSMDB->drCTFlSize); + } + + nodeSize = SWAP_BE16(gBTHeaders[kBTreeCatalog]->nodeSize); + nodeBuf = (char *)malloc(nodeSize); + node = (BTNodeDescriptor *)nodeBuf; + + index = (long) (*dirIndex % nodeSize); + curNode = (long) (*dirIndex / nodeSize); + + // Read the BTree node and get the record for index. + ReadExtent(extent, extentSize, kHFSCatalogFileID, + (long long) curNode * nodeSize, nodeSize, nodeBuf, 1); + GetBTreeRecord(index, nodeBuf, nodeSize, &testKey, &entry); + + GetCatalogEntryInfo(entry, flags, time, finderInfo, infoValid); + + // Get the file name. + if (gIsHFSPlus) { + utf_encodestr(((HFSPlusCatalogKey *)testKey)->nodeName.unicode, + SWAP_BE16(((HFSPlusCatalogKey *)testKey)->nodeName.length), + (u_int8_t *)gTempStr, 256, OSBigEndian); + } else { + strncpy(gTempStr, + (const char *)&((HFSCatalogKey *)testKey)->nodeName[1], + ((HFSCatalogKey *)testKey)->nodeName[0]); + gTempStr[((HFSCatalogKey *)testKey)->nodeName[0]] = '\0'; + } + *name = gTempStr; + + // Update dirIndex. + index++; + if (index == SWAP_BE16(node->numRecords)) { + index = 0; + curNode = SWAP_BE32(node->fLink); + } + *dirIndex = (long long) curNode * nodeSize + index; + + free(nodeBuf); + + return 0; +} + +static long ReadCatalogEntry(char * fileName, long dirID, + void * entry, long long * dirIndex) +{ + long length; + char key[sizeof(HFSPlusCatalogKey)]; + HFSCatalogKey *hfsKey = (HFSCatalogKey *)key; + HFSPlusCatalogKey *hfsPlusKey = (HFSPlusCatalogKey *)key; + + // Make the catalog key. + if ( gIsHFSPlus ) + { + hfsPlusKey->parentID = SWAP_BE32(dirID); + length = strlen(fileName); + if (length > 255) length = 255; + utf_decodestr((u_int8_t *)fileName, hfsPlusKey->nodeName.unicode, + &(hfsPlusKey->nodeName.length), 512, OSBigEndian); + } else { + hfsKey->parentID = SWAP_BE32(dirID); + length = strlen(fileName); + if (length > 31) length = 31; + hfsKey->nodeName[0] = length; + strncpy((char *)(hfsKey->nodeName + 1), fileName, length); + } + + return ReadBTreeEntry(kBTreeCatalog, &key, entry, dirIndex); +} + +static long ReadExtentsEntry(long fileID, long startBlock, void * entry) +{ + char key[sizeof(HFSPlusExtentKey)]; + HFSExtentKey *hfsKey = (HFSExtentKey *)key; + HFSPlusExtentKey *hfsPlusKey = (HFSPlusExtentKey *)key; + + // Make the extents key. + if (gIsHFSPlus) { + hfsPlusKey->forkType = 0; + hfsPlusKey->fileID = SWAP_BE32(fileID); + hfsPlusKey->startBlock = SWAP_BE32(startBlock); + } else { + hfsKey->forkType = 0; + hfsKey->fileID = SWAP_BE32(fileID); + hfsKey->startBlock = SWAP_BE16(startBlock); + } + + return ReadBTreeEntry(kBTreeExtents, &key, entry, 0); +} + +static long ReadBTreeEntry(long btree, void * key, char * entry, long long * dirIndex) +{ + long extentSize; + void *extent; + short extentFile; + char *nodeBuf; + BTNodeDescriptor *node; + long nodeSize, result = 0, entrySize = 0; + long curNode, index = 0, lowerBound, upperBound; + char *testKey, *recordData; + + // Figure out which tree is being looked at. + if (btree == kBTreeCatalog) { + if (gIsHFSPlus) { + extent = &gHFSPlus->catalogFile.extents; + extentSize = SWAP_BE64(gHFSPlus->catalogFile.logicalSize); + } else { + extent = (HFSExtentDescriptor *)&gHFSMDB->drCTExtRec; + extentSize = SWAP_BE32(gHFSMDB->drCTFlSize); + } + extentFile = kHFSCatalogFileID; + } else { + if (gIsHFSPlus) { + extent = &gHFSPlus->extentsFile.extents; + extentSize = SWAP_BE64(gHFSPlus->extentsFile.logicalSize); + } else { + extent = (HFSExtentDescriptor *)&gHFSMDB->drXTExtRec; + extentSize = SWAP_BE32(gHFSMDB->drXTFlSize); + } + extentFile = kHFSExtentsFileID; + } + + // Read the BTree Header if needed. + if (gBTHeaders[btree] == 0) { + ReadExtent(extent, extentSize, extentFile, 0, 256, + gBTreeHeaderBuffer + btree * 256, 0); + gBTHeaders[btree] = (BTHeaderRec *)(gBTreeHeaderBuffer + btree * 256 + + sizeof(BTNodeDescriptor)); + if ((gIsHFSPlus && btree == kBTreeCatalog) && + (gBTHeaders[btree]->keyCompareType == kHFSBinaryCompare)) { + gCaseSensitive = 1; + } + } + + curNode = SWAP_BE32(gBTHeaders[btree]->rootNode); + nodeSize = SWAP_BE16(gBTHeaders[btree]->nodeSize); + nodeBuf = (char *)malloc(nodeSize); + node = (BTNodeDescriptor *)nodeBuf; + + while (1) { + // Read the current node. + ReadExtent(extent, extentSize, extentFile, + (long long) curNode * nodeSize, nodeSize, nodeBuf, 1); + + // Find the matching key. + lowerBound = 0; + upperBound = SWAP_BE16(node->numRecords) - 1; + while (lowerBound <= upperBound) { + index = (lowerBound + upperBound) / 2; + + GetBTreeRecord(index, nodeBuf, nodeSize, &testKey, &recordData); + + if (gIsHFSPlus) { + if (btree == kBTreeCatalog) { + result = CompareHFSPlusCatalogKeys(key, testKey); + } else { + result = CompareHFSPlusExtentsKeys(key, testKey); + } + } else { + if (btree == kBTreeCatalog) { + result = CompareHFSCatalogKeys(key, testKey); + } else { + result = CompareHFSExtentsKeys(key, testKey); + } + } + + if (result < 0) upperBound = index - 1; // search < trial + else if (result > 0) lowerBound = index + 1; // search > trial + else break; // search = trial + } + + if (result < 0) { + index = upperBound; + GetBTreeRecord(index, nodeBuf, nodeSize, &testKey, &recordData); + } + + // Found the closest key... Recurse on it if this is an index node. + if (node->kind == kBTIndexNode) { + curNode = SWAP_BE32( *((long *)recordData) ); + } else break; + } + + // Return error if the file was not found. + if (result != 0) { free(nodeBuf); return -1; } + + if (btree == kBTreeCatalog) { + switch (SWAP_BE16(*(short *)recordData)) { + case kHFSFolderRecord : entrySize = 70; break; + case kHFSFileRecord : entrySize = 102; break; + case kHFSFolderThreadRecord : entrySize = 46; break; + case kHFSFileThreadRecord : entrySize = 46; break; + case kHFSPlusFolderRecord : entrySize = 88; break; + case kHFSPlusFileRecord : entrySize = 248; break; + case kHFSPlusFolderThreadRecord : entrySize = 264; break; + case kHFSPlusFileThreadRecord : entrySize = 264; break; + } + } else { + if (gIsHFSPlus) entrySize = sizeof(HFSPlusExtentRecord); + else entrySize = sizeof(HFSExtentRecord); + } + + bcopy(recordData, entry, entrySize); + + // Update dirIndex. + if (dirIndex != 0) { + index++; + if (index == SWAP_BE16(node->numRecords)) { + index = 0; + curNode = SWAP_BE32(node->fLink); + } + *dirIndex = (long long) curNode * nodeSize + index; + } + + free(nodeBuf); + + return 0; +} + +static void GetBTreeRecord(long index, char * nodeBuffer, long nodeSize, + char ** key, char ** data) +{ + long keySize; + long recordOffset; + + recordOffset = SWAP_BE16(*((short *)(nodeBuffer + (nodeSize - 2 * index - 2)))); + *key = nodeBuffer + recordOffset; + if (gIsHFSPlus) { + keySize = SWAP_BE16(*(short *)*key); + *data = *key + 2 + keySize; + } else { + keySize = **key; + *data = *key + 2 + keySize - (keySize & 1); + } +} + +static long ReadExtent(char * extent, uint64_t extentSize, + long extentFile, uint64_t offset, uint64_t size, + void * buffer, long cache) +{ + uint64_t lastOffset; + long long blockNumber, countedBlocks = 0; + long long nextExtent = 0, sizeRead = 0, readSize; + long long nextExtentBlock, currentExtentBlock = 0; + long long readOffset; + long long extentDensity, sizeofExtent, currentExtentSize; + char *currentExtent, *extentBuffer = 0, *bufferPos = buffer; + + if (offset >= extentSize) return 0; + + if (gIsHFSPlus) { + extentDensity = kHFSPlusExtentDensity; + sizeofExtent = sizeof(HFSPlusExtentDescriptor); + } else { + extentDensity = kHFSExtentDensity; + sizeofExtent = sizeof(HFSExtentDescriptor); + } + + lastOffset = offset + size; + while (offset < lastOffset) { + blockNumber = offset / gBlockSize; + + // Find the extent for the offset. + for (; ; nextExtent++) { + if (nextExtent < extentDensity) { + if ((countedBlocks+GetExtentSize(extent, nextExtent)-1)= blockNumber) { + currentExtent = extentBuffer + sizeofExtent * (nextExtent % extentDensity); + break; + } + + countedBlocks += currentExtentSize; + } + + readOffset = ((blockNumber - countedBlocks) * gBlockSize) + + (offset % gBlockSize); + + // MacWen: fix overflow in multiplication by forcing 64bit multiplication + readSize = (long long)GetExtentSize(currentExtent, 0) * gBlockSize - readOffset; + if (readSize > (size - sizeRead)) readSize = size - sizeRead; + + readOffset += (long long)GetExtentStart(currentExtent, 0) * gBlockSize; + + CacheRead(gCurrentIH, bufferPos, gAllocationOffset + readOffset, + readSize, cache); + + sizeRead += readSize; + offset += readSize; + bufferPos += readSize; + } + + if (extentBuffer) free(extentBuffer); + + return sizeRead; +} + +static long GetExtentStart(void * extents, long index) +{ + long start; + HFSExtentDescriptor *hfsExtents = extents; + HFSPlusExtentDescriptor *hfsPlusExtents = extents; + + if (gIsHFSPlus) start = SWAP_BE32(hfsPlusExtents[index].startBlock); + else start = SWAP_BE16(hfsExtents[index].startBlock); + + return start; +} + +static long GetExtentSize(void * extents, long index) +{ + long size; + HFSExtentDescriptor *hfsExtents = extents; + HFSPlusExtentDescriptor *hfsPlusExtents = extents; + + if (gIsHFSPlus) size = SWAP_BE32(hfsPlusExtents[index].blockCount); + else size = SWAP_BE16(hfsExtents[index].blockCount); + + return size; +} + +static long CompareHFSCatalogKeys(void * key, void * testKey) +{ + HFSCatalogKey *searchKey, *trialKey; + long result, searchParentID, trialParentID; + + searchKey = key; + trialKey = testKey; + + searchParentID = SWAP_BE32(searchKey->parentID); + trialParentID = SWAP_BE32(trialKey->parentID); + + // parent dirID is unsigned + if (searchParentID > trialParentID) result = 1; + else if (searchParentID < trialParentID) result = -1; + else { + // parent dirID's are equal, compare names + result = FastRelString(searchKey->nodeName, trialKey->nodeName); + } + + return result; +} + +static long CompareHFSPlusCatalogKeys(void * key, void * testKey) +{ + HFSPlusCatalogKey *searchKey, *trialKey; + long result, searchParentID, trialParentID; + + searchKey = key; + trialKey = testKey; + + searchParentID = SWAP_BE32(searchKey->parentID); + trialParentID = SWAP_BE32(trialKey->parentID); + + // parent dirID is unsigned + if (searchParentID > trialParentID) result = 1; + else if (searchParentID < trialParentID) result = -1; + else { + // parent dirID's are equal, compare names + if ((searchKey->nodeName.length == 0) || (trialKey->nodeName.length == 0)) + result = searchKey->nodeName.length - trialKey->nodeName.length; + else + if (gCaseSensitive) { + result = BinaryUnicodeCompare(&searchKey->nodeName.unicode[0], + SWAP_BE16(searchKey->nodeName.length), + &trialKey->nodeName.unicode[0], + SWAP_BE16(trialKey->nodeName.length)); + } else { + result = FastUnicodeCompare(&searchKey->nodeName.unicode[0], + SWAP_BE16(searchKey->nodeName.length), + &trialKey->nodeName.unicode[0], + SWAP_BE16(trialKey->nodeName.length), OSBigEndian); + } + } + + return result; +} + +static long CompareHFSExtentsKeys(void * key, void * testKey) +{ + HFSExtentKey *searchKey, *trialKey; + long result; + + searchKey = key; + trialKey = testKey; + + // assume searchKey < trialKey + result = -1; + + if (searchKey->fileID == trialKey->fileID) { + // FileNum's are equal; compare fork types + if (searchKey->forkType == trialKey->forkType) { + // Fork types are equal; compare allocation block number + if (searchKey->startBlock == trialKey->startBlock) { + // Everything is equal + result = 0; + } else { + // Allocation block numbers differ; determine sign + if (SWAP_BE16(searchKey->startBlock) > SWAP_BE16(trialKey->startBlock)) + result = 1; + } + } else { + // Fork types differ; determine sign + if (searchKey->forkType > trialKey->forkType) result = 1; + } + } else { + // FileNums differ; determine sign + if (SWAP_BE32(searchKey->fileID) > SWAP_BE32(trialKey->fileID)) + result = 1; + } + + return result; +} + +static long CompareHFSPlusExtentsKeys(void * key, void * testKey) +{ + HFSPlusExtentKey *searchKey, *trialKey; + long result; + + searchKey = key; + trialKey = testKey; + + // assume searchKey < trialKey + result = -1; + + if (searchKey->fileID == trialKey->fileID) { + // FileNum's are equal; compare fork types + if (searchKey->forkType == trialKey->forkType) { + // Fork types are equal; compare allocation block number + if (searchKey->startBlock == trialKey->startBlock) { + // Everything is equal + result = 0; + } else { + // Allocation block numbers differ; determine sign + if (SWAP_BE32(searchKey->startBlock) > SWAP_BE32(trialKey->startBlock)) + result = 1; + } + } else { + // Fork types differ; determine sign + if (searchKey->forkType > trialKey->forkType) result = 1; + } + } else { + // FileNums differ; determine sign + if (SWAP_BE32(searchKey->fileID) > SWAP_BE32(trialKey->fileID)) + result = 1; + } + + return result; +} + Index: branches/slice/rev749/libsaio/ext2fs.h =================================================================== --- branches/slice/rev749/libsaio/ext2fs.h (revision 0) +++ branches/slice/rev749/libsaio/ext2fs.h (revision 1169) @@ -0,0 +1,11 @@ +/* + * ext2fs.h + * + * + * Created by mackerintel on 1/26/09. + * Copyright 2009 __MyCompanyName__. All rights reserved. + * + */ + +extern bool EX2Probe (const void *buf); +extern void EX2GetDescription(CICell ih, char *str, long strMaxLen); Index: branches/slice/rev749/libsaio/vbe.h =================================================================== --- branches/slice/rev749/libsaio/vbe.h (revision 0) +++ branches/slice/rev749/libsaio/vbe.h (revision 1169) @@ -0,0 +1,289 @@ +/* + * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 2.0 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +// Copyright 1997 by Apple Computer, Inc., all rights reserved. +/* Copyright 1996-1997 NeXT Software, Inc. + * + * vesa.h - mode info obtained via int10 + * + * Revision History + * ---------------- + * 30 Jul 1996 Doug Mitchell at NeXT + * Created. + */ + +#ifndef __LIBSAIO_VBE_H +#define __LIBSAIO_VBE_H + +#define MIN_VESA_VERSION 0x200 + +#define SEG(address) \ + ((unsigned short)(((unsigned long)address & 0xffff0000) >> 4)) + +#define OFF(address) \ + ((unsigned short)((unsigned long)address & 0x0000ffff)) + +#define VBEMakeUInt32(x) \ + (((unsigned long)x##_high << 24) | \ + ((unsigned long)x##_2 << 16) | \ + ((unsigned long)x##_1 << 8) | \ + (unsigned long)x##_low) + +#define VBEDecodeFP(t, fp) \ + ((t)(((fp ## _low) | ((fp ## _1 ) << 8)) + \ + (((fp ## _2) << 4) | ((fp ## _high ) << 12)))) + +/* + * Functions + */ +enum { + funcGetControllerInfo = 0x4F00, + funcGetModeInfo = 0x4F01, + funcSetMode = 0x4F02, + funcGetCurrentMode = 0x4F03, + funcSaveRestoreState = 0x4F04, + funcWindowControl = 0x4F05, + funcGetSetScanLineLength = 0x4F06, + funcGetSetDisplayStart = 0x4F07, + funcGetSetPaletteFormat = 0x4F08, + funcGetSetPaletteData = 0x4F09, + funcGetProtModeInterdace = 0x4F0A, + funcGetSetPixelClock = 0x4F0B, + funcGetEDID = 0x4F15 + +}; + +enum { + subfuncSet = 0x00, + subfuncGet = 0x01, + subfuncSetSecondary = 0x02, + subfuncGetSecondary = 0x03 +}; + +/* + * errors. + */ +enum { + errSuccess = 0, + errFuncFailed = 1, + errFuncNotSupported = 2, + errFuncInvalid = 3 +}; + +/* + * Per-controller info, returned in function 4f00. + */ +typedef struct { + unsigned char VESASignature[4]; + unsigned short VESAVersion; + /* + * Avoid packing problem... + */ + unsigned char OEMStringPtr_low; + unsigned char OEMStringPtr_1; + unsigned char OEMStringPtr_2; + unsigned char OEMStringPtr_high; + unsigned char Capabilities_low; + unsigned char Capabilities_1; + unsigned char Capabilities_2; + unsigned char Capabilities_high; + unsigned char VideoModePtr_low; + unsigned char VideoModePtr_1; + unsigned char VideoModePtr_2; + unsigned char VideoModePtr_high; + unsigned short TotalMemory; + unsigned char Reserved[236]; + unsigned char OEMData[256]; +} VBEInfoBlock; + +/* + * Capabilites + */ +enum { + capDACWidthIsSwitchableBit = (1 << 0), /* 1 = yes; 0 = no */ + capControllerIsNotVGACompatableBit = (1 << 1), /* 1 = no; 0 = yes */ + capOldRAMDAC = (1 << 2) /* 1 = yes; 0 = no */ +}; + +/* + * Per-mode info, returned in function 4f02. + */ +typedef struct { + unsigned short ModeAttributes; + unsigned char WinAAttributes; + unsigned char WinBAttributes; + unsigned short WinGranularity; + unsigned short WinSize; + unsigned short WinASegment; + unsigned short WinABegment; + void * WinFuncPtr; + unsigned short BytesPerScanline; + unsigned short XResolution; + unsigned short YResolution; + unsigned char XCharSize; + unsigned char YCharSize; + unsigned char NumberOfPlanes; + unsigned char BitsPerPixel; + unsigned char NumberOfBanks; + unsigned char MemoryModel; + unsigned char BankSize; + unsigned char NumberOfImagePages; + unsigned char Reserved; + unsigned char RedMaskSize; + unsigned char RedFieldPosition; + unsigned char GreenMaskSize; + unsigned char GreenFieldPosition; + unsigned char BlueMaskSize; + unsigned char BlueFieldPosition; + unsigned char RsvdMaskSize; + unsigned char RsvdFieldPosition; + unsigned char DirectColorModeInfo; + unsigned char PhysBasePtr_low; + unsigned char PhysBasePtr_1; + unsigned char PhysBasePtr_2; + unsigned char PhysBasePtr_high; + void * OffScreenMemOffset; + unsigned short OffScreenMemSize; + unsigned char Reserved1[206]; +} VBEModeInfoBlock; + +/* + * ModeAttributes bits + */ +enum { + maModeIsSupportedBit = (1 << 0), /* mode is supported */ + maExtendedInfoAvailableBit = (1 << 1), /* extended info available */ + maOutputFuncSupportedBit = (1 << 2), /* output functions supported */ + maColorModeBit = (1 << 3), /* 1 = color; 0 = mono */ + maGraphicsModeBit = (1 << 4), /* 1 = graphics; 0 = text */ + maModeIsNotVGACompatableBit = (1 << 5), /* 1 = not compat; 0 = compat */ + maVGAMemoryModeNotAvailBit = (1 << 6), /* 1 = not avail; 0 = avail */ + maLinearFrameBufferAvailBit = (1 << 7) /* 1 = avail; 0 = not avail */ +}; + +/* + * Modes + */ +enum { + mode640x400x256 = 0x100, + mode640x480x256 = 0x101, + mode800x600x16 = 0x102, + mode800x600x256 = 0x103, + mode1024x768x16 = 0x104, + mode1024x768x256 = 0x105, + mode1280x1024x16 = 0x106, + mode1280x1024x256 = 0x107, + mode80Cx60R = 0x108, + mode132Cx25R = 0x109, + mode132Cx43R = 0x10A, + mode132Cx50R = 0x10B, + mode132Cx60R = 0x10C, + mode320x200x555 = 0x10D, + mode320x200x565 = 0x10E, + mode320x200x888 = 0x10F, + mode640x480x555 = 0x110, + mode640x480x565 = 0x111, + mode640x480x888 = 0x112, + mode800x600x555 = 0x113, + mode800x600x565 = 0x114, + mode800x600x888 = 0x115, + mode1024x768x555 = 0x116, + mode1024x768x565 = 0x117, + mode1024x768x888 = 0x118, + mode1280x1024x555 = 0x119, + mode1280x1024x565 = 0x11A, + mode1280x1024x888 = 0x11B, + modeSpecial = 0x81FF, + modeEndOfList = 0xFFFF +}; + +/* + * Get/Set VBE Mode parameters + */ +enum { + kCustomRefreshRateBit = (1 << 11), + kLinearFrameBufferBit = (1 << 14), + kPreserveMemoryBit = (1 << 15) +}; + +/* + * CRTC information block passed to function 4F02 + * to override default refresh rate. + */ +#pragma pack(1) + +typedef struct { + unsigned short HTotal; + unsigned short HSyncStart; + unsigned short HSyncEnd; + unsigned short VTotal; + unsigned short VSyncStart; + unsigned short VSyncEnd; + unsigned char Flags; + unsigned long PixelClock; /* in Hz */ + unsigned short RefreshRate; /* units of 0.01 Hz */ + unsigned char Reserved[40]; +} VBECRTCInfoBlock; + +#pragma pack() + +/* + * Defined flags for 'Flags' field in VBECRTCInfoBlock. + */ +enum { + kCRTCDoubleScannedMode = (1 << 0), + kCRTCInterlacedMode = (1 << 1), + kCRTCNegativeHorizontalSync = (1 << 2), + kCRTCNegativeVerticalSync = (1 << 3) +}; + +/* + * The type of paramter passed to generateCRTCTimings(). + */ +enum { + kCRTCParamRefreshRate, + kCRTCParamPixelClock +}; + +/* + * Palette + */ +typedef unsigned long VBEPalette[256]; + +extern int getVBEInfo(void *vinfo_p); +extern int getEDID( void * edidBlock, UInt8 block); +extern int getVBEModeInfo(int mode, void *minfo_p); +extern int getVBEDACFormat(unsigned char *format); +extern int setVBEDACFormat(unsigned char format); +extern int setVBEPalette(void *palette); +extern int getVBEPalette(void *palette); +extern int setVBEMode(unsigned short mode, const VBECRTCInfoBlock *timing); +extern int getVBECurrentMode(unsigned short *mode); +extern int getVBEPixelClock(unsigned short mode, unsigned long *pixelClock); +extern int generateCRTCTiming(unsigned short width, + unsigned short height, + unsigned long paramValue, + int paramType, + VBECRTCInfoBlock * timing); + +#endif /* !__LIBSAIO_VBE_H */ Index: branches/slice/rev749/libsaio/acpi_patcher.c =================================================================== --- branches/slice/rev749/libsaio/acpi_patcher.c (revision 0) +++ branches/slice/rev749/libsaio/acpi_patcher.c (revision 1169) @@ -0,0 +1,1289 @@ +/* + * Copyright 2008 mackerintel + */ + +#include "libsaio.h" +#include "boot.h" +#include "bootstruct.h" +#include "acpi.h" +#include "efi_tables.h" +#include "fake_efi.h" +#include "acpi_patcher.h" +#include "platform.h" +#include "cpu.h" +#include "aml_generator.h" +#include "smbios_patcher.h" + +#ifndef DEBUG_ACPI +#define DEBUG_ACPI 0 +#endif + +#if DEBUG_ACPI==2 +#define DBG(x...) {printf(x); sleep(1);} +#elif DEBUG_ACPI==3 +#define DBG(x...) verbose(x) +#elif DEBUG_ACPI==1 +#define DBG(x...) msglog(x) +#else +#define DBG(x...) +#endif + +bool fix_restart; +uint64_t acpi10_p; +uint64_t acpi20_p; + +int rsdplength; +void *new_dsdt=NULL; + +extern char* gSMBIOSBoardModel; + +// Slice: New signature compare function +boolean_t tableSign(char *table, const char *sgn) +{ + int i; + for (i=0; i<4; i++) { + if ((table[i] &~0x20) != (sgn[i] &~0x20)) { + return false; + } + } + return true; +} + +char st[20]; +char * FourChar(char * s) +{ + int i; + for(i=0; i<4;i++){ + st[i] = (isalpha(s[i])?s[i]:'.'); + } + // strncpy(st, s, 4); + st[4] = '\0'; + return st; +} + + +/* Gets the ACPI 1.0 RSDP address */ +static struct acpi_2_rsdp* getAddressOfAcpiTable() +{ + /* TODO: Before searching the BIOS space we are supposed to search the first 1K of the EBDA */ + + void *acpi_addr = (void*)ACPI_RANGE_START; + for(; acpi_addr <= (void*)ACPI_RANGE_END; acpi_addr += 16) + { + if(*(uint64_t *)acpi_addr == ACPI_SIGNATURE_UINT64_LE) + { + uint8_t csum = checksum8(acpi_addr, 20); + if(csum == 0) + { + // Only return the table if it is a true version 1.0 table (Revision 0) + if(((struct acpi_2_rsdp*)acpi_addr)->Revision == 0) + return acpi_addr; + } + } + } + return NULL; +} + +/* Gets the ACPI 2.0 RSDP address */ +static struct acpi_2_rsdp* getAddressOfAcpi20Table() +{ + /* TODO: Before searching the BIOS space we are supposed to search the first 1K of the EBDA */ + + void *acpi_addr = (void*)ACPI_RANGE_START; + for(; acpi_addr <= (void*)ACPI_RANGE_END; acpi_addr += 16) + { + if(*(uint64_t *)acpi_addr == ACPI_SIGNATURE_UINT64_LE) + { + uint8_t csum = checksum8(acpi_addr, 20); + + /* Only assume this is a 2.0 or better table if the revision is greater than 0 + * NOTE: ACPI 3.0 spec only seems to say that 1.0 tables have revision 1 + * and that the current revision is 2.. I am going to assume that rev > 0 is 2.0. + */ + + if(csum == 0 && (((struct acpi_2_rsdp*)acpi_addr)->Revision > 0)) + { + uint8_t csum2 = checksum8(acpi_addr, sizeof(struct acpi_2_rsdp)); + if(csum2 == 0) + return acpi_addr; + } + } + } + return NULL; +} +/** The folowing ACPI Table search algo. should be reused anywhere needed:*/ +int search_and_get_acpi_fd(const char * filename, const char ** outDirspec) +{ + int fd = -1; + char dirSpec[512] = ""; + + // Try finding 'filename' in the usual places + // Start searching any potential location for ACPI Table + + if(gSMBIOSBoardModel) + { + sprintf(dirSpec,"%s.%s", gSMBIOSBoardModel, filename); + fd = open(dirSpec, 0); + } + + if (fd < 0) + { + sprintf(dirSpec, "%s", filename); + fd = open(dirSpec, 0); + if (fd < 0) + { + if(gSMBIOSBoardModel) + { + sprintf(dirSpec, "/Extra/%s.%s", gSMBIOSBoardModel, filename); + fd = open(dirSpec, 0); + } + if (fd < 0) + { + sprintf(dirSpec, "/Extra/%s", filename); + fd = open(dirSpec, 0); + if (fd < 0) + { + if(gSMBIOSBoardModel) + { + sprintf(dirSpec, "bt(0,0)/Extra/%s.%s", gSMBIOSBoardModel, filename); + fd = open(dirSpec, 0); + } + if (fd < 0) + { + sprintf(dirSpec, "bt(0,0)/Extra/%s", filename); + fd = open(dirSpec, 0); + } + } + } + } + } + + if (fd < 0) + { + // NOT FOUND: + DBG("ACPI table not found: %s\n", filename); + *dirSpec = '\0'; + } + + if (outDirspec) *outDirspec = dirSpec; + return fd; +} + + +void *loadACPITable (const char * filename) +{ + void *tableAddr; + const char * dirspec=NULL; + + int fd = search_and_get_acpi_fd(filename, &dirspec); + + if (fd>=0) + { + tableAddr=(void*)AllocateKernelMemory(file_size (fd)); + if (tableAddr) + { + if (read (fd, tableAddr, file_size (fd))!=file_size (fd)) + { + verbose("Couldn't read table %s\n",dirspec); + free (tableAddr); + close (fd); + return NULL; + } + + DBG("Table %s read and stored at: %x\n", dirspec, tableAddr); + close (fd); + return tableAddr; + } + close (fd); + verbose("Couldn't allocate memory for table \n", dirspec); + } + //printf("Couldn't find table %s\n", filename); + return NULL; +} + +uint8_t acpi_cpu_count = 0; +char* acpi_cpu_name[32]; + +void get_acpi_cpu_names(unsigned char* dsdt, uint32_t length) +{ + uint32_t i; + + for (i=0; i> 6); + + bool add_name = true; + + uint8_t j; + + for (j=0; j<4; j++) + { + char c = dsdt[offset+j]; + + if (!aml_isvalidchar(c)) + { + add_name = false; + DBG("Invalid character found in ProcessorOP 0x%x!\n", c); + break; + } + } + + if (add_name) + { + acpi_cpu_name[acpi_cpu_count] = malloc(4); + memcpy(acpi_cpu_name[acpi_cpu_count], dsdt+offset, 4); + i = offset + 5; + + DBG("Found ACPI CPU: %c%c%c%c\n", acpi_cpu_name[acpi_cpu_count][0], acpi_cpu_name[acpi_cpu_count][1], acpi_cpu_name[acpi_cpu_count][2], acpi_cpu_name[acpi_cpu_count][3]); + + if (++acpi_cpu_count == 32) return; + } + } + } +} + +struct acpi_2_ssdt *generate_cst_ssdt(struct acpi_2_fadt* fadt) +{ + char ssdt_header[] = + { + 0x53, 0x53, 0x44, 0x54, 0xE7, 0x00, 0x00, 0x00, /* SSDT.... */ + 0x01, 0x17, 0x50, 0x6D, 0x52, 0x65, 0x66, 0x41, /* ..PmRefA */ + 0x43, 0x70, 0x75, 0x43, 0x73, 0x74, 0x00, 0x00, /* CpuCst.. */ + 0x00, 0x10, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C, /* ....INTL */ + 0x31, 0x03, 0x10, 0x20 /* 1.._ */ + }; + + char cstate_resource_template[] = + { + 0x11, 0x14, 0x0A, 0x11, 0x82, 0x0C, 0x00, 0x7F, + 0x01, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x79, 0x00 + }; + + if (Platform->CPU.Vendor != 0x756E6547) { + verbose ("Not an Intel platform: C-States will not be generated !!!\n"); + return NULL; + } + + if (fadt == NULL) { + verbose ("FACP not exists: C-States will not be generated !!!\n"); + return NULL; + } + + struct acpi_2_dsdt* dsdt = (void*)fadt->DSDT; + + if (dsdt == NULL) { + verbose ("DSDT not found: C-States will not be generated !!!\n"); + return NULL; + } + + if (acpi_cpu_count == 0) + get_acpi_cpu_names((void*)dsdt, dsdt->Length); + + if (acpi_cpu_count > 0) + { + bool c2_enabled = false; + bool c3_enabled = false; + bool c4_enabled = false; + + getBoolForKey(kEnableC2States, &c2_enabled, &bootInfo->bootConfig); + getBoolForKey(kEnableC3States, &c3_enabled, &bootInfo->bootConfig); + getBoolForKey(kEnableC4States, &c4_enabled, &bootInfo->bootConfig); + + c2_enabled = c2_enabled | (fadt->C2_Latency < 100); + c3_enabled = c3_enabled | (fadt->C3_Latency < 1000); + + unsigned char cstates_count = 1 + (c2_enabled ? 1 : 0) + (c3_enabled ? 1 : 0); + + struct aml_chunk* root = aml_create_node(NULL); + aml_add_buffer(root, ssdt_header, sizeof(ssdt_header)); // SSDT header + struct aml_chunk* scop = aml_add_scope(root, "\\_PR_"); + struct aml_chunk* name = aml_add_name(scop, "CST_"); + struct aml_chunk* pack = aml_add_package(name); + aml_add_byte(pack, cstates_count); + + struct aml_chunk* tmpl = aml_add_package(pack); + cstate_resource_template[11] = 0x00; // C1 + aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template)); + aml_add_byte(tmpl, 0x01); // C1 + aml_add_byte(tmpl, 0x01); // Latency + aml_add_word(tmpl, 0x03e8); // Power + + // C2 + if (c2_enabled) + { + tmpl = aml_add_package(pack); + cstate_resource_template[11] = 0x10; // C2 + aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template)); + aml_add_byte(tmpl, 0x02); // C2 + aml_add_byte(tmpl, fadt->C2_Latency); + aml_add_word(tmpl, 0x01f4); // Power + } + // C4 + if (c4_enabled) + { + tmpl = aml_add_package(pack); + cstate_resource_template[11] = 0x30; // C4 + aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template)); + aml_add_byte(tmpl, 0x04); // C4 + aml_add_word(tmpl, fadt->C3_Latency / 2); // TODO: right latency for C4 + aml_add_byte(tmpl, 0xfa); // Power + } + else + // C3 + if (c3_enabled) + { + tmpl = aml_add_package(pack); + cstate_resource_template[11] = 0x20; // C3 + aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template)); + aml_add_byte(tmpl, 0x03); // C3 + aml_add_word(tmpl, fadt->C3_Latency); + aml_add_word(tmpl, 0x015e); // Power + } + + + // Aliaces + int i; + for (i = 0; i < acpi_cpu_count; i++) + { + char name[9]; + sprintf(name, "_PR_%c%c%c%c", acpi_cpu_name[i][0], acpi_cpu_name[i][1], acpi_cpu_name[i][2], acpi_cpu_name[i][3]); + + scop = aml_add_scope(root, name); + aml_add_alias(scop, "CST_", "_CST"); + } + + aml_calculate_size(root); + + struct acpi_2_ssdt *ssdt = (struct acpi_2_ssdt *)AllocateKernelMemory(root->Size); + + aml_write_node(root, (void*)ssdt, 0); + + ssdt->Length = root->Size; + ssdt->Checksum = 0; + ssdt->Checksum = 256 - checksum8(ssdt, ssdt->Length); + + aml_destroy_node(root); + + //dumpPhysAddr("C-States SSDT content: ", ssdt, ssdt->Length); + + verbose ("SSDT with CPU C-States generated successfully\n"); + + return ssdt; + } + else + { + verbose ("ACPI CPUs not found: C-States not generated !!!\n"); + } + + return NULL; +} + +struct acpi_2_ssdt *generate_pss_ssdt(struct acpi_2_dsdt* dsdt) +{ + char ssdt_header[] = + { + 0x53, 0x53, 0x44, 0x54, 0x7E, 0x00, 0x00, 0x00, /* SSDT.... */ + 0x01, 0x6A, 0x50, 0x6D, 0x52, 0x65, 0x66, 0x00, /* ..PmRef. */ + 0x43, 0x70, 0x75, 0x50, 0x6D, 0x00, 0x00, 0x00, /* CpuPm... */ + 0x00, 0x30, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C, /* .0..INTL */ + 0x31, 0x03, 0x10, 0x20, /* 1.._ */ + }; + cpuid_update_generic_info(); + if (Platform->CPU.Vendor != 0x756E6547) { + verbose ("Not an Intel platform: P-States will not be generated !!!\n"); + return NULL; + } + + if (!(Platform->CPU.Features & CPU_FEATURE_MSR)) { + verbose ("Unsupported CPU: P-States will not be generated !!!\n"); + return NULL; + } + + if (acpi_cpu_count == 0) + get_acpi_cpu_names((void*)dsdt, dsdt->Length); + + if (acpi_cpu_count > 0) + { + struct p_state initial, maximum, minimum, p_states[32]; + uint8_t p_states_count = 0; + + // Retrieving P-States, ported from code by superhai (c) + switch (Platform->CPU.Family) { + case 0x06: + { + switch (Platform->CPU.Model) + { + case CPU_MODEL_PENTIUM_M: // ? + case CPU_MODEL_YONAH: // Yonah + case CPU_MODEL_MEROM: // Merom + case CPU_MODEL_PENRYN: // Penryn + case CPU_MODEL_ATOM: // Intel Atom (45nm) + { + bool cpu_dynamic_fsb = false; + + if (rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 27)) + { + wrmsr64(MSR_IA32_EXT_CONFIG, (rdmsr64(MSR_IA32_EXT_CONFIG) | (1 << 28))); + delay(1); + cpu_dynamic_fsb = rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 28); + } + + bool cpu_noninteger_bus_ratio = (rdmsr64(MSR_IA32_PERF_STATUS) & (1ULL << 46)); + + initial.Control = rdmsr64(MSR_IA32_PERF_STATUS); + + maximum.Control = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 32) & 0x1F3F) | (0x4000 * cpu_noninteger_bus_ratio); + maximum.CID = ((maximum.FID & 0x1F) << 1) | cpu_noninteger_bus_ratio; + + minimum.FID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 24) & 0x1F) | (0x80 * cpu_dynamic_fsb); + minimum.VID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 48) & 0x3F); + + if (minimum.FID == 0) + { + uint64_t msr; + uint8_t i; + // Probe for lowest fid + for (i = maximum.FID; i >= 0x6; i--) + { + msr = rdmsr64(MSR_IA32_PERF_CONTROL); + wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (i << 8) | minimum.VID); + intel_waitforsts(); + minimum.FID = (rdmsr64(MSR_IA32_PERF_STATUS) >> 8) & 0x1F; + delay(1); + } + + msr = rdmsr64(MSR_IA32_PERF_CONTROL); + wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID); + intel_waitforsts(); + } + + if (minimum.VID == maximum.VID) + { + uint64_t msr; + uint8_t i; + // Probe for lowest vid + for (i = maximum.VID; i > 0xA; i--) + { + msr = rdmsr64(MSR_IA32_PERF_CONTROL); + wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (minimum.FID << 8) | i); + intel_waitforsts(); + minimum.VID = rdmsr64(MSR_IA32_PERF_STATUS) & 0x3F; + delay(1); + } + + msr = rdmsr64(MSR_IA32_PERF_CONTROL); + wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID); + intel_waitforsts(); + } + + minimum.CID = ((minimum.FID & 0x1F) << 1) >> cpu_dynamic_fsb; + + // Sanity check + if (maximum.CID < minimum.CID) + { + DBG("Insane FID values!"); + p_states_count = 0; + } + else + { + // Finalize P-States + // Find how many P-States machine supports + p_states_count = maximum.CID - minimum.CID + 1; + + if (p_states_count > 32) + p_states_count = 32; + + uint8_t vidstep; + uint8_t i = 0, u, invalid = 0; + + vidstep = ((maximum.VID << 2) - (minimum.VID << 2)) / (p_states_count - 1); + + for (u = 0; u < p_states_count; u++) + { + i = u - invalid; + + p_states[i].CID = maximum.CID - u; + p_states[i].FID = (p_states[i].CID >> 1); + + if (p_states[i].FID < 0x6) + { + if (cpu_dynamic_fsb) + p_states[i].FID = (p_states[i].FID << 1) | 0x80; + } + else if (cpu_noninteger_bus_ratio) + { + p_states[i].FID = p_states[i].FID | (0x40 * (p_states[i].CID & 0x1)); + } + + if (i && p_states[i].FID == p_states[i-1].FID) + invalid++; + + p_states[i].VID = ((maximum.VID << 2) - (vidstep * u)) >> 2; + + uint32_t multiplier = p_states[i].FID & 0x1f; // = 0x08 + bool half = p_states[i].FID & 0x40; // = 0x01 + bool dfsb = p_states[i].FID & 0x80; // = 0x00 + uint32_t fsb = Platform->CPU.FSBFrequency / 1000000; // = 400 + uint32_t halffsb = (fsb + 1) >> 1; // = 200 + uint32_t frequency = (multiplier * fsb); // = 3200 + + p_states[i].Frequency = (frequency + (half * halffsb)) >> dfsb; // = 3200 + 200 = 3400 + } + + p_states_count -= invalid; + } + } break; + case CPU_MODEL_FIELDS: + case CPU_MODEL_DALES: + case CPU_MODEL_DALES_32NM: + case CPU_MODEL_NEHALEM: + case CPU_MODEL_NEHALEM_EX: + case CPU_MODEL_WESTMERE: + case CPU_MODEL_WESTMERE_EX: + { + maximum.Control = rdmsr64(MSR_IA32_PERF_STATUS) & 0xff; // Seems it always contains maximum multiplier value (with turbo, that's we need)... + minimum.Control = (rdmsr64(MSR_PLATFORM_INFO) >> 40) & 0xff; + + verbose("P-States: min 0x%x, max 0x%x\n", minimum.Control, maximum.Control); + + // Sanity check + if (maximum.Control < minimum.Control) + { + DBG("Insane control values!"); + p_states_count = 0; + } + else + { + uint8_t i; + p_states_count = 0; + + for (i = maximum.Control; i >= minimum.Control; i--) + { + p_states[p_states_count].Control = i; + p_states[p_states_count].CID = p_states[p_states_count].Control << 1; + p_states[p_states_count].Frequency = (Platform->CPU.FSBFrequency / 1000000) * i; + p_states_count++; + } + } + + break; + } + default: + verbose ("Unsupported CPU (0x%X): P-States not generated !!!\n", Platform->CPU.Family); + break; + } + } + } + + // Generating SSDT + if (p_states_count > 0) + { + int i; + + struct aml_chunk* root = aml_create_node(NULL); + aml_add_buffer(root, ssdt_header, sizeof(ssdt_header)); // SSDT header + struct aml_chunk* scop = aml_add_scope(root, "\\_PR_"); + struct aml_chunk* name = aml_add_name(scop, "PSS_"); + struct aml_chunk* pack = aml_add_package(name); + + for (i = 0; i < p_states_count; i++) + { + struct aml_chunk* pstt = aml_add_package(pack); + + aml_add_dword(pstt, p_states[i].Frequency); + aml_add_dword(pstt, 0x00000000); // Power + aml_add_dword(pstt, 0x0000000A); // Latency + aml_add_dword(pstt, 0x0000000A); // Latency + aml_add_dword(pstt, p_states[i].Control); + aml_add_dword(pstt, i+1); // Status + } + + // Add aliaces + for (i = 0; i < acpi_cpu_count; i++) + { + char name[9]; + sprintf(name, "_PR_%c%c%c%c", acpi_cpu_name[i][0], acpi_cpu_name[i][1], acpi_cpu_name[i][2], acpi_cpu_name[i][3]); + + scop = aml_add_scope(root, name); + aml_add_alias(scop, "PSS_", "_PSS"); + } + + aml_calculate_size(root); + + struct acpi_2_ssdt *ssdt = (struct acpi_2_ssdt *)AllocateKernelMemory(root->Size); + + aml_write_node(root, (void*)ssdt, 0); + + ssdt->Length = root->Size; + ssdt->Checksum = 0; + ssdt->Checksum = 256 - checksum8(ssdt, ssdt->Length); + + aml_destroy_node(root); + + //dumpPhysAddr("P-States SSDT content: ", ssdt, ssdt->Length); + + verbose ("SSDT with CPU P-States generated successfully\n"); + + return ssdt; + } + } + else + { + verbose ("ACPI CPUs not found: P-States not generated !!!\n"); + } + + return NULL; +} + +struct acpi_2_fadt *patch_fadt(struct acpi_2_fadt *fadt, struct acpi_2_dsdt *new_dsdt) +{ + extern void setupSystemType(); + + struct acpi_2_fadt *fadt_mod = NULL; + bool fadt_rev2_needed = false; +// bool fix_restart; + const char * value; + + // Restart Fix + if (Platform->CPU.Vendor == 0x756E6547) { /* Intel */ + fix_restart = true; + getBoolForKey(kRestartFix, &fix_restart, &bootInfo->bootConfig); + } else { + DBG ("Not an Intel platform: Restart Fix not applied !!!\n"); + fix_restart = false; + } + + if (fix_restart) fadt_rev2_needed = true; + + // Allocate new fadt table + if (fadt->Length < 0x84 && fadt_rev2_needed) + { + fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(0x84); + memcpy(fadt_mod, fadt, fadt->Length); + fadt_mod->Length = 0x84; + fadt_mod->Revision = 0x02; // FADT rev 2 (ACPI 1.0B MS extensions) + } + else + { + fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(fadt->Length); + memcpy(fadt_mod, fadt, fadt->Length); + } + // Determine system type / PM_Model + if (fadt_mod && Platform->Type) { + fadt_mod->PM_Profile = Platform->Type; + } else if(fadt) + Platform->Type = fadt->PM_Profile; + else + Platform->Type = 1; + + //User override default value + if ( (value=getStringForKey(kSystemType, &bootInfo->bootConfig))!=NULL) + { + if (Platform->Type > 6) + { + if(fadt_mod->PM_Profile<=6) + Platform->Type = fadt_mod->PM_Profile; // get the fadt if correct + else + Platform->Type = 1; /* Set a fixed value (Desktop) */ + verbose("Error: system-type must be 0..6. Defaulting to %d !\n", Platform->Type); + } + else + Platform->Type = (unsigned char) strtoul(value, NULL, 10); + } + // Set PM_Profile from System-type if only user wanted this value to be forced + if (fadt_mod->PM_Profile != Platform->Type) + { + if (value) + { // user has overriden the SystemType so take care of it in FACP + DBG("FADT: changing PM_Profile from 0x%02x to 0x%02x\n", fadt_mod->PM_Profile, Platform->Type); + fadt_mod->PM_Profile = Platform->Type; + } + else + { // PM_Profile has a different value and no override has been set, so reflect the user value to ioregs + Platform->Type = fadt_mod->PM_Profile <= 6 ? fadt_mod->PM_Profile : 1; + } + } + // We now have to write the systemm-type in ioregs: we cannot do it before in setupDeviceTree() + // because we need to take care of facp original content, if it is correct. + setupSystemType(); + + // Patch FADT to fix restart + if (fix_restart) + { + fadt_mod->Flags|= 0x400; + fadt_mod->Reset_SpaceID = 0x01; // System I/O + fadt_mod->Reset_BitWidth = 0x08; // 1 byte + fadt_mod->Reset_BitOffset = 0x00; // Offset 0 + fadt_mod->Reset_AccessWidth = 0x01; // Byte access + fadt_mod->Reset_Address = 0x0cf9; // Address of the register + fadt_mod->Reset_Value = 0x06; // Value to write to reset the system + msglog("FADT: Restart Fix applied!\n"); + } + + // Patch DSDT Address if we have loaded DSDT.aml + if(new_dsdt) + { + DBG("DSDT: Old @%x,%x, ",fadt_mod->DSDT,fadt_mod->X_DSDT); + + // Insert old dsdt into the IORegistery + Node* node = DT__FindNode("/dsdt", false); + if(node == NULL) + { + // Only add if not already here + Node* node = DT__FindNode("/", false); + + if(node != NULL) + { + node = DT__AddChild(node, "dsdt"); + + struct acpi_2_dsdt *dsdt; + dsdt = (struct acpi_2_dsdt*) (fadt_mod->DSDT); + DT__AddProperty(node, "originaldsdt", (dsdt->Length + sizeof(struct acpi_2_dsdt) - 1), (void*)dsdt); /// Insert old dsdt. Length is header length (36) + dsdt length + + } + } + + fadt_mod->DSDT=(uint32_t)new_dsdt; + if ((uint32_t)(&(fadt_mod->X_DSDT))-(uint32_t)fadt_mod+8<=fadt_mod->Length) + fadt_mod->X_DSDT=(uint32_t)new_dsdt; + + DBG("New @%x,%x\n",fadt_mod->DSDT,fadt_mod->X_DSDT); + + DBG("FADT: Using custom DSDT!\n"); + } + + // Correct the checksum + fadt_mod->Checksum=0; + fadt_mod->Checksum=256-checksum8(fadt_mod,fadt_mod->Length); + + return fadt_mod; +} + +/* Setup ACPI without replacing DSDT. */ +int setupAcpiNoMod() +{ + // addConfigurationTable(&gEfiAcpiTableGuid, getAddressOfAcpiTable(), "ACPI"); + // addConfigurationTable(&gEfiAcpi20TableGuid, getAddressOfAcpi20Table(), "ACPI_20"); + /* XXX aserebln why uint32 cast if pointer is uint64 ? */ + //Slice (uint64_t) + acpi10_p = (uint64_t)(uint32_t)getAddressOfAcpiTable(); + acpi20_p = (uint64_t)(uint32_t)getAddressOfAcpi20Table(); + addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI"); + if(acpi20_p) addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20"); + else { + DBG("no ACPI 2\n"); + } + return 1; +} + +static struct acpi_2_xsdt* createNewXSDTfromRSDT(struct acpi_2_rsdt * rsdt) +{ + struct acpi_2_xsdt *xsdt; + int xsdt_entries_num, i; + uint32_t xsdt_len; + if (!rsdt) { + return NULL; + } + //Create XSDT in addition to RSDT as a 64bit copy + if((rsdt->Length<0) || (rsdt->Length>1000)){ + DBG(" incorrect RSDT length: %08lx\n", rsdt->Length); +#if DEBUG_DSDT + getc(); +#endif + return NULL; + } + xsdt_entries_num = (rsdt->Length - sizeof(struct acpi_2_rsdt)) >> 2; + xsdt_len = sizeof(struct acpi_2_rsdt) + (xsdt_entries_num << 3); + xsdt = (struct acpi_2_xsdt*)AllocateKernelMemory(xsdt_len); + bcopy(rsdt, xsdt, sizeof(struct acpi_2_rsdt)); + //Change signature from RSDT to XSDT + strncpy(xsdt->Signature, FourChar("XSDT"), 4); + //Now copy address table + uint64_t *table1 = (uint64_t *)(xsdt+1); + uint32_t *table2 = (uint32_t *)(rsdt+1); + if ((xsdt_entries_num>0) && (xsdt_entries_num<20)) { + for(i=0; iLength = xsdt_len; + //Correct checksums + xsdt->Checksum=0; + xsdt->Checksum=256-checksum8(xsdt,xsdt_len); + return xsdt; +} + +static struct acpi_2_rsdp* createNewACPI20(struct acpi_2_rsdp * old_rsdp) +{ + if(!old_rsdp) return NULL; + //Slice I want to copy acpi10 table to create ACPI20 + // uint64_t *xsdt_entries; + if(*(uint64_t *)old_rsdp != ACPI_SIGNATURE_UINT64_LE){ + DBG(" wrong signature %08lx\n", (*(uint64_t *)old_rsdp)); + return NULL; + } + DBG(" old_rsdp = %08lx\n", (uint32_t)old_rsdp); + // if(((int)old_rsdp->Length < 0) || ((int)old_rsdp->Length > 84)) + // return NULL; + //No! ACPI10_rsdp_length=20 and no such field old_rsdp->Length + + struct acpi_2_rsdp * rsdp=(struct acpi_2_rsdp *) AllocateKernelMemory(36); + DBG(" new_rsdp = %08lx\n", (uint32_t)rsdp); + bzero(rsdp, 36); + bcopy(old_rsdp, rsdp, 20); + strncpy(rsdp->OEMID, "Apple ", 6); + rsdp->Revision = 2; + rsdp->Length = 36; + struct acpi_2_rsdt *rsdt = (struct acpi_2_rsdt *)(rsdp->RsdtAddress); //copied from old +// dumpRSDT(rsdt, 0); + rsdp->XsdtAddress = (uint64_t)(uint32_t)createNewXSDTfromRSDT(rsdt); +// dumpRSDT((struct acpi_2_rsdt *)(uint32_t)(rsdp->XsdtAddress), 0); + rsdp->Checksum=0; + rsdp->Checksum=256-checksum8(rsdp,20); + rsdp->ExtendedChecksum=0; + rsdp->ExtendedChecksum=256-checksum8(rsdp,36); + return rsdp; +} + + +/* Setup ACPI. Replace DSDT if DSDT.aml is found */ +int setupAcpi(void) +{ + int version; +// void *new_dsdt; + + const char *filename; + char dirSpec[128]; + int len = 0, old_dsdt_len = 0; + struct acpi_2_rsdp *rsdp, *rsdp_mod, *rsdp1 = 0; + struct acpi_2_rsdt *rsdt, *rsdt_mod = 0; + struct acpi_2_rsdt *xsdt; //, *xsdt_mod = 0; + char* old_dsdt = 0; + + // Try using the file specified with the DSDT option + if (getValueForKey(kDSDT, &filename, &len, &bootInfo->bootConfig)) + { + sprintf(dirSpec, filename); + } + else + { + sprintf(dirSpec, "DSDT.aml"); + } + + // Load replacement DSDT + new_dsdt = loadACPITable(dirSpec); + if(!new_dsdt) + { + sprintf(dirSpec, "DSDT.%s.aml", gSMBIOSBoardModel); + new_dsdt = loadACPITable(dirSpec); + } + + // Mozodojo: going to patch FACP and load SSDT's even if DSDT.aml is not present + /*if (!new_dsdt) + { + return setupAcpiNoMod(); + }*/ + + // Mozodojo: Load additional SSDTs + struct acpi_2_ssdt *new_ssdt[32]; // 30 + 2 additional tables for pss & cst + int ssdt_count=0; + + // SSDT Options + bool drop_ssdt=false, generate_pstates=false, generate_cstates=false; + + getBoolForKey(kDropSSDT, &drop_ssdt, &bootInfo->bootConfig); + getBoolForKey(kGeneratePStates, &generate_pstates, &bootInfo->bootConfig); + getBoolForKey(kGenerateCStates, &generate_cstates, &bootInfo->bootConfig); + + { + int i; + + for (i=0; i<30; i++) + { + char filename[512]; + + sprintf(filename, i>0?"SSDT-%d.aml":"SSDT.aml", i); + + if(new_ssdt[ssdt_count] = loadACPITable(filename)) + { + ssdt_count++; + } + else + { + break; + } + } + } + + // Do the same procedure for both versions of ACPI + for (version=0; version<2; version++) { +// int rsdplength; + //Here version=0 for ACPI 1.0 and version=1 for ACPI 2.0 + // Find original rsdp + rsdp=(struct acpi_2_rsdp *)(version?getAddressOfAcpi20Table():getAddressOfAcpiTable()); + //Slice + if (!rsdp) + { + if (version){ + DBG("No ACPI version 2 found. Creating...\n"); + rsdp=createNewACPI20(rsdp1); + if(!rsdp){ + addConfigurationTable(&gEfiAcpi20TableGuid, NULL, "ACPI_20"); + continue; + } + } else { + DBG("No ACPI version 1 found. Ignoring\n"); + addConfigurationTable(&gEfiAcpiTableGuid, NULL, "ACPI"); + continue; + } + } + if(!version) rsdp1 = rsdp; //save to create new. + rsdplength=version?rsdp->Length:20; + + DBG("RSDP version %d found @%x. Length=%d\n",version+1,rsdp,rsdplength); + + /* FIXME: no check that memory allocation succeeded + * Copy and patch RSDP,RSDT, XSDT and FADT + * For more info see ACPI Specification pages 110 and following + */ + + rsdp_mod=(struct acpi_2_rsdp *) AllocateKernelMemory(rsdplength); + memcpy(rsdp_mod, rsdp, rsdplength); + rsdt=(struct acpi_2_rsdt *)(rsdp->RsdtAddress); + xsdt=(struct acpi_2_rsdt *)(uint32_t)(rsdp->XsdtAddress); + DBG("RSDT @%x, Length %d\n",rsdt, rsdt->Length); + + //if we have RSDT table + if (rsdt && (uint32_t)rsdt !=0xffffffff && rsdt->Length<0x10000) + { + uint32_t *rsdt_entries; + int rsdt_entries_num; + int dropoffset=0, i; + + // mozo: using malloc cos I didn't found how to free already allocated kernel memory + rsdt_mod=(struct acpi_2_rsdt *)malloc(rsdt->Length); + memcpy (rsdt_mod, rsdt, rsdt->Length); + rsdp_mod->RsdtAddress=(uint32_t)rsdt_mod; + rsdt_entries_num=(rsdt_mod->Length-sizeof(struct acpi_2_rsdt))/4; + rsdt_entries=(uint32_t *)(rsdt_mod+1); + for (i=0;iOEMID, "Apple ", 6); + strncpy(t->OEMTableId, MacModel, 8); + t->OEMRevision = ModelRev; + t->Checksum=0; + t->Checksum=256-checksum8(t,t->Length); + + } + if (tableSign(table, "FACP")) + { + struct acpi_2_fadt *fadt, *fadt_mod; + fadt=(struct acpi_2_fadt *)rsdt_entries[i]; + + DBG("FADT found @%x, Length %d\n",fadt, fadt->Length); + + if (!fadt || (uint32_t)fadt == 0xffffffff || fadt->Length>0x10000) + { + printf("FADT incorrect. Not modified\n"); + continue; + } + DBG("Old DSDT @%x, X_DSDT %x from FADT\n",fadt->DSDT,fadt->X_DSDT); + + if(version && fix_restart){ //ACPI 2.0 + fadt_mod = patch_fadt(fadt, new_dsdt); + rsdt_entries[i-dropoffset]=(uint32_t)fadt_mod; + } else { + if (fadt && Platform->Type) + fadt->PM_Profile = Platform->Type; //For ACPI1.0 the only patch + fadt_mod = fadt; + rsdt_entries[i-dropoffset]=(uint32_t)fadt; + } + DBG("FADT_mod table sign: %s\n", fadt_mod->Signature); + //Slice + //Now I want to replace DSDT in place + // it is only way to patch DSDT on some platform + old_dsdt = (char *)fadt->DSDT; + if(!old_dsdt || !tableSign(old_dsdt, "DSDT")){ + if(fadt_mod->Length > 140) old_dsdt = (char *)(uint32_t)fadt_mod->X_DSDT; + if(!old_dsdt || !tableSign(old_dsdt, "DSDT")) old_dsdt = (char *)new_dsdt; + } + DBG("New DSDT @%x, X_DSDT %x after FADT patch\n",fadt_mod->DSDT,fadt_mod->X_DSDT); + + if(tableSign(old_dsdt, "DSDT")) + old_dsdt_len = ((struct acpi_2_rsdt *)old_dsdt)->Length; + int new_dsdt_len = ((struct acpi_2_rsdt *)new_dsdt)->Length; + if(new_dsdt_len > old_dsdt_len) { + old_dsdt = (char *)new_dsdt; + DBG(" New DSDT is longer then old\n"); + len = 0; + } + else len = new_dsdt_len; + + + // Generate _CST SSDT + if (generate_cstates && (new_ssdt[ssdt_count] = generate_cst_ssdt(fadt_mod))) + { + generate_cstates = false; // Generate SSDT only once! + ssdt_count++; + } + + // Generating _PSS SSDT + if (generate_pstates && (new_ssdt[ssdt_count] = generate_pss_ssdt((void*)fadt_mod->DSDT))) + { + generate_pstates = false; // Generate SSDT only once! + ssdt_count++; + } + + continue; + } + }//for rsdt entries + DBG("\n"); + //Slice - Correct header to MacModel & Vendor, correct chechsum + strncpy(rsdt_mod->OEMID, "Apple ", 6); + strncpy(rsdt_mod->OEMTableId, MacModel, 8); + rsdt_mod->OEMRevision = ModelRev; + + // Allocate rsdt in Kernel memory area + rsdt_mod->Length += 4*ssdt_count - 4*dropoffset; + struct acpi_2_rsdt *rsdt_copy = (struct acpi_2_rsdt *)AllocateKernelMemory(rsdt_mod->Length); + memcpy (rsdt_copy, rsdt_mod, rsdt_mod->Length); + free(rsdt_mod); rsdt_mod = rsdt_copy; + rsdp_mod->RsdtAddress=(uint32_t)rsdt_mod; + rsdt_entries_num=(rsdt_mod->Length-sizeof(struct acpi_2_rsdt))/4; + rsdt_entries=(uint32_t *)(rsdt_mod+1); + + // Mozodojo: Insert additional SSDTs into RSDT + if(ssdt_count>0) + { + int j; + + for (j=0; jChecksum); + + rsdt_mod->Checksum=0; + rsdt_mod->Checksum=256-checksum8(rsdt_mod,rsdt_mod->Length); + +// DBG("New checksum %d at %x\n", rsdt_mod->Checksum,rsdt_mod); + } + else + { + rsdp_mod->RsdtAddress=0; + verbose("RSDT not found or RSDT incorrect\n"); + } + + if (version) + { + struct acpi_2_xsdt *xsdt, *xsdt_mod; + + // FIXME: handle 64-bit address correctly + + xsdt=(struct acpi_2_xsdt*) ((uint32_t)rsdp->XsdtAddress); + DBG("XSDT @%x;%x, Length=%d Sign=%c%c%c%c\n", (uint32_t)(rsdp->XsdtAddress>>32), + (uint32_t)rsdp->XsdtAddress, xsdt->Length, xsdt[0], xsdt[1], xsdt[2], xsdt[3]); + if (xsdt && (uint64_t)rsdp->XsdtAddress<0xffffffff && xsdt->Length<0x10000) + { + uint64_t *xsdt_entries; + int xsdt_entries_num, i; + int dropoffset=0; + + // mozo: using malloc cos I didn't found how to free already allocated kernel memory + xsdt_mod=(struct acpi_2_xsdt*)malloc(xsdt->Length); + memcpy(xsdt_mod, xsdt, xsdt->Length); + rsdp_mod->XsdtAddress=(uint32_t)xsdt_mod; + xsdt_entries_num=(xsdt_mod->Length-sizeof(struct acpi_2_xsdt))/8; + xsdt_entries=(uint64_t *)(xsdt_mod+1); + for (i=0;i>32),fadt, + fadt->Length); + + if (!fadt || (uint64_t)xsdt_entries[i] >= 0xffffffff || fadt->Length>0x10000) + { + DBG("FADT incorrect or after 4GB. Dropping XSDT\n"); + goto drop_xsdt; + } + + fadt_mod = patch_fadt(fadt, new_dsdt); + xsdt_entries[i-dropoffset]=(uint32_t)fadt_mod; + + DBG("TABLE %c%c%c%c@%x \n", table[0],table[1],table[2],table[3],xsdt_entries[i]); + + // Generate _CST SSDT + if (generate_cstates && (new_ssdt[ssdt_count] = generate_cst_ssdt(fadt_mod))) + { + generate_cstates = false; // Generate SSDT only once! + ssdt_count++; + } + + // Generating _PSS SSDT + if (generate_pstates && (new_ssdt[ssdt_count] = generate_pss_ssdt((void*)fadt_mod->DSDT))) + { + generate_pstates = false; // Generate SSDT only once! + ssdt_count++; + } + + continue; + } + + DBG("TABLE %c%c%c%c@%x \n", table[0],table[1],table[2],table[3],xsdt_entries[i]); + + } + + // Allocate xsdt in Kernel memory area + xsdt_mod->Length += 8*ssdt_count - 8*dropoffset; + struct acpi_2_xsdt *xsdt_copy = (struct acpi_2_xsdt *)AllocateKernelMemory(xsdt_mod->Length); + memcpy(xsdt_copy, xsdt_mod, xsdt_mod->Length); + free(xsdt_mod); xsdt_mod = xsdt_copy; + rsdp_mod->XsdtAddress=(uint32_t)xsdt_mod; + xsdt_entries_num=(xsdt_mod->Length-sizeof(struct acpi_2_xsdt))/8; + xsdt_entries=(uint64_t *)(xsdt_mod+1); + + // Mozodojo: Insert additional SSDTs into XSDT + if(ssdt_count>0) + { + int j; + + for (j=0; jChecksum=0; + xsdt_mod->Checksum=256-checksum8(xsdt_mod,xsdt_mod->Length); + } + else + { + drop_xsdt: + + DBG("About to drop XSDT\n"); + + /*FIXME: Now we just hope that if MacOS doesn't find XSDT it reverts to RSDT. + * A Better strategy would be to generate + */ + //Slice - it is possible only for ACPI20 + if (version) { + if(rsdp->RsdtAddress){ + rsdp_mod->XsdtAddress = + (uint64_t)(uint32_t)createNewXSDTfromRSDT((struct acpi_2_rsdt*)rsdp->RsdtAddress); + continue; + } + else + DBG(" no sample to create XSDT, dropping\n"); + } + + rsdp_mod->XsdtAddress=0xffffffffffffffffLL; + DBG("XSDT not found or XSDT incorrect\n"); + } + } + //Slice - correct DSDT in place + if(len && old_dsdt && new_dsdt && (old_dsdt != new_dsdt)){ + DBG("old_dsdt=%08x new_dsdt=%08x new_len=%d\n", (unsigned int)old_dsdt, (unsigned int)new_dsdt, len); + bcopy(new_dsdt, old_dsdt, len); + } + + // Correct the checksum of RSDP + + DBG("RSDP: Original checksum %d, ", rsdp_mod->Checksum); + + rsdp_mod->Checksum=0; + rsdp_mod->Checksum=256-checksum8(rsdp_mod,20); + + DBG("New checksum %d\n", rsdp_mod->Checksum); + + if (version) + { + DBG("RSDP: Original extended checksum %d", rsdp_mod->ExtendedChecksum); + + rsdp_mod->ExtendedChecksum=0; + rsdp_mod->ExtendedChecksum=256-checksum8(rsdp_mod,rsdp_mod->Length); + + DBG("New extended checksum %d\n", rsdp_mod->ExtendedChecksum); + + } + + //verbose("Patched ACPI version %d DSDT\n", version+1); + if (version) + { + /* XXX aserebln why uint32 cast if pointer is uint64 ? */ + //Slice because rsdp_mod is a pointer (32bit in i386) to a structure uint64_t* + acpi20_p = (uint64_t)(uint32_t)rsdp_mod; + addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20"); + } + else + { + /* XXX aserebln why uint32 cast if pointer is uint64 ? */ + acpi10_p = (uint64_t)(uint32_t)rsdp_mod; + addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI"); + } + } +#if DEBUG_ACPI + printf("Press a key to continue... (DEBUG_ACPI)\n"); + getc(); +#endif + return 1; +} Index: branches/slice/rev749/libsaio/device_tree.h =================================================================== --- branches/slice/rev749/libsaio/device_tree.h (revision 0) +++ branches/slice/rev749/libsaio/device_tree.h (revision 1169) @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2005 Apple Computer, Inc. All Rights Reserved. + */ + +#ifndef __DEVICE_TREE_H +#define __DEVICE_TREE_H + +#include +#include + +typedef struct _Property { + const char * name; + uint32_t length; + void * value; + + struct _Property * next; +} Property; + +typedef struct _Node { + struct _Property * properties; + struct _Property * last_prop; + + struct _Node * children; + + struct _Node * next; +} Node; + + +extern Property * +DT__AddProperty(Node *node, const char *name, uint32_t length, void *value); + +extern Node * +DT__AddChild(Node *parent, const char *name); + +Node * +DT__FindNode(const char *path, bool createIfMissing); + +extern void +DT__FreeProperty(Property *prop); + +extern void +DT__FreeNode(Node *node); + +extern char * +DT__GetName(Node *node); + +void +DT__Initialize(void); + +/* + * Free up memory used by in-memory representation + * of device tree. + */ +extern void +DT__Finalize(void); + +void +DT__FlattenDeviceTree(void **result, uint32_t *length); + + +#endif /* __DEVICE_TREE_H */ Index: branches/slice/rev749/libsaio/allocate.c =================================================================== --- branches/slice/rev749/libsaio/allocate.c (revision 0) +++ branches/slice/rev749/libsaio/allocate.c (revision 1169) @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 2003 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 2.0 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include "sl.h" +#include "saio_internal.h" +#include "bootstruct.h" +#include "device_tree.h" + +static long gImageLastKernelAddr; + +#define kPageSize 4096 +#define RoundPage(x) ((((unsigned)(x)) + kPageSize - 1) & ~(kPageSize - 1)) + + +long +AllocateMemoryRange(char * rangeName, long start, long length, long type) +{ + char *nameBuf; + uint32_t *buffer; + + nameBuf = malloc(strlen(rangeName) + 1); + if (nameBuf == 0) return -1; + strcpy(nameBuf, rangeName); + + buffer = malloc(2 * sizeof(uint32_t)); + if (buffer == 0) return -1; + + buffer[0] = start; + buffer[1] = length; + + DT__AddProperty(gMemoryMapNode, nameBuf, 2 * sizeof(uint32_t), (char *)buffer); + + return 0; +} + +long +AllocateKernelMemory( long inSize ) +{ + long addr; + + if (gImageLastKernelAddr == 0) { + gImageLastKernelAddr = RoundPage( bootArgs->kaddr + + bootArgs->ksize ); + } + addr = gImageLastKernelAddr; + gImageLastKernelAddr += RoundPage(inSize); + + if ( gImageLastKernelAddr >= (KERNEL_ADDR + KERNEL_LEN) ) { + stop ("AllocateKernelMemory error"); + } + + bootArgs->ksize = gImageLastKernelAddr - bootArgs->kaddr; + + return addr; +} Index: branches/slice/rev749/libsaio/hfs.h =================================================================== --- branches/slice/rev749/libsaio/hfs.h (revision 0) +++ branches/slice/rev749/libsaio/hfs.h (revision 1169) @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 2.0 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +extern long HFSInitPartition(CICell ih); +extern long HFSLoadFile(CICell ih, char * filePath); +extern long HFSReadFile(CICell ih, char * filePath, void *base, uint64_t offset, uint64_t length); +extern long HFSGetDirEntry(CICell ih, char * dirPath, long long * dirIndex, + char ** name, long * flags, long * time, + FinderInfo * finderInfo, long * infoValid); +extern void HFSGetDescription(CICell ih, char *str, long strMaxLen); +extern long HFSGetFileBlock(CICell ih, char *str, unsigned long long *firstBlock); +extern long HFSGetUUID(CICell ih, char *uuidStr); +extern void HFSFree(CICell ih); +extern bool HFSProbe (const void *buf); Index: branches/slice/rev749/libsaio/hfs_compare.c =================================================================== --- branches/slice/rev749/libsaio/hfs_compare.c (revision 0) +++ branches/slice/rev749/libsaio/hfs_compare.c (revision 1169) @@ -0,0 +1,421 @@ +/* + * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 2.0 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * HFSCompare.c - Functions for working with and comparing HFS nams. + * + * Copyright (c) 1999-2000 Apple Computer, Inc. + * + * DRI: Josh de Cesare + */ + +#include +#include "hfs_CaseTables.h" + +#if ! UNCOMPRESSED + +static unsigned short * +UncompressStructure(struct compressed_block *bp, int count, int size) +{ + unsigned short *out = malloc(size); + unsigned short *op = out; + unsigned short data; + int i, j; + + for (i=0; icount) + { + stop("HFS+ Unicode tables are malformed\n"); + } + data = bp->data; + for (j=0; jcount; j++) { + *op++ = data; + if (bp->type == kTypeAscending) data++; + else if (bp->type == kTypeAscending256) data += 256; + } + } + return out; +} + +static void +InitCompareTables(void) +{ + if (gCompareTable == 0) { + gCompareTable = UncompressStructure(gCompareTableCompressed, + kCompareTableNBlocks, kCompareTableDataSize); + gLowerCaseTable = UncompressStructure(gLowerCaseTableCompressed, + kLowerCaseTableNBlocks, kLowerCaseTableDataSize); + } +} + +#endif /* ! UNCOMPRESSED */ + +//_______________________________________________________________________ +// +// Routine: FastRelString +// +// Output: returns -1 if str1 < str2 +// returns 1 if str1 > str2 +// return 0 if equal +// +//_______________________________________________________________________ + +int32_t FastRelString(u_int8_t * str1, u_int8_t * str2) +{ + int32_t bestGuess; + u_int8_t length, length2; + +#if ! UNCOMPRESED + InitCompareTables(); +#endif + + length = *(str1++); + length2 = *(str2++); + + if (length == length2) + bestGuess = 0; + else if (length < length2) + bestGuess = -1; + else + { + bestGuess = 1; + length = length2; + } + + while (length--) + { + u_int32_t aChar, bChar; + + aChar = *(str1++); + bChar = *(str2++); + + if (aChar != bChar) /* If they don't match exacly, do case conversion */ + { + u_int16_t aSortWord, bSortWord; + + aSortWord = gCompareTable[aChar]; + bSortWord = gCompareTable[bChar]; + + if (aSortWord > bSortWord) + return 1; + + if (aSortWord < bSortWord) + return -1; + } + + /* + * If characters match exactly, then go on to next character + * immediately without doing any extra work. + */ + } + + /* if you got to here, then return bestGuess */ + return bestGuess; +} + + +// +// FastUnicodeCompare - Compare two Unicode strings; produce a relative ordering +// +// IF RESULT +// -------------------------- +// str1 < str2 => -1 +// str1 = str2 => 0 +// str1 > str2 => +1 +// +// The lower case table starts with 256 entries (one for each of the upper bytes +// of the original Unicode char). If that entry is zero, then all characters with +// that upper byte are already case folded. If the entry is non-zero, then it is +// the _index_ (not byte offset) of the start of the sub-table for the characters +// with that upper byte. All ignorable characters are folded to the value zero. +// +// In pseudocode: +// +// Let c = source Unicode character +// Let table[] = lower case table +// +// lower = table[highbyte(c)] +// if (lower == 0) +// lower = c +// else +// lower = table[lower+lowbyte(c)] +// +// if (lower == 0) +// ignore this character +// +// To handle ignorable characters, we now need a loop to find the next valid character. +// Also, we can't pre-compute the number of characters to compare; the string length might +// be larger than the number of non-ignorable characters. Further, we must be able to handle +// ignorable characters at any point in the string, including as the first or last characters. +// We use a zero value as a sentinel to detect both end-of-string and ignorable characters. +// Since the File Manager doesn't prevent the NUL character (value zero) as part of a filename, +// the case mapping table is assumed to map u+0000 to some non-zero value (like 0xFFFF, which is +// an invalid Unicode character). +// +// Pseudocode: +// +// while (1) { +// c1 = GetNextValidChar(str1) // returns zero if at end of string +// c2 = GetNextValidChar(str2) +// +// if (c1 != c2) break // found a difference +// +// if (c1 == 0) // reached end of string on both strings at once? +// return 0; // yes, so strings are equal +// } +// +// // When we get here, c1 != c2. So, we just need to determine which one is less. +// if (c1 < c2) +// return -1; +// else +// return 1; +// + +int32_t FastUnicodeCompare( u_int16_t * str1, register u_int32_t length1, + u_int16_t * str2, register u_int32_t length2, int byte_order ) +{ + register u_int16_t c1,c2; + register u_int16_t temp; + +#if ! UNCOMPRESSED + InitCompareTables(); +#endif + + while (1) { + /* Set default values for c1, c2 in case there are no more valid chars */ + c1 = 0; + c2 = 0; + + /* Find next non-ignorable char from str1, or zero if no more */ + while (length1 && c1 == 0) { + if (byte_order == OSBigEndian) + c1 = SWAP_BE16(*(str1++)); + else + c1 = SWAP_LE16(*(str1++)); + --length1; + if ((temp = gLowerCaseTable[c1>>8]) != 0) // is there a subtable for this upper byte? + c1 = gLowerCaseTable[temp + (c1 & 0x00FF)]; // yes, so fold the char + } + + /* Find next non-ignorable char from str2, or zero if no more */ + while (length2 && c2 == 0) { + if (byte_order == OSBigEndian) + c2 = SWAP_BE16(*(str2++)); + else + c2 = SWAP_LE16(*(str2++)); + --length2; + if ((temp = gLowerCaseTable[c2>>8]) != 0) // is there a subtable for this upper byte? + c2 = gLowerCaseTable[temp + (c2 & 0x00FF)]; // yes, so fold the char + } + + if (c1 != c2) /* found a difference, so stop looping */ + break; + + if (c1 == 0) /* did we reach the end of both strings at the same time? */ + return 0; /* yes, so strings are equal */ + } + + if (c1 < c2) + return -1; + else + return 1; +} + + +// +// BinaryUnicodeCompare - Compare two Unicode strings; produce a relative ordering +// Compared using a 16-bit binary comparison (no case folding) +// +int32_t BinaryUnicodeCompare (u_int16_t * str1, u_int32_t length1, + u_int16_t * str2, u_int32_t length2) +{ + register u_int16_t c1, c2; + int32_t bestGuess; + u_int32_t length; + + bestGuess = 0; + + if (length1 < length2) { + length = length1; + --bestGuess; + } else if (length1 > length2) { + length = length2; + ++bestGuess; + } else { + length = length1; + } + + while (length--) { + c1 = *(str1++); + c2 = *(str2++); + + if (c1 > c2) + return (1); + if (c1 < c2) + return (-1); + } + + return (bestGuess); +} + + +/* + * UTF-8 (UCS Transformation Format) + * + * The following subset of UTF-8 is used to encode UCS-2 filenames. It + * requires a maximum of three 3 bytes per UCS-2 character. Only the + * shortest encoding required to represent the significant UCS-2 bits + * is legal. + * + * UTF-8 Multibyte Codes + * + * Bytes Bits UCS-2 Min UCS-2 Max UTF-8 Byte Sequence (binary) + * ------------------------------------------------------------------- + * 1 7 0x0000 0x007F 0xxxxxxx + * 2 11 0x0080 0x07FF 110xxxxx 10xxxxxx + * 3 16 0x0800 0xFFFF 1110xxxx 10xxxxxx 10xxxxxx + * ------------------------------------------------------------------- + */ + + +/* + * utf_encodestr - Encodes the UCS-2 (Unicode) string at ucsp into a + * null terminated UTF-8 string at utf8p. + * + * ucslen is the number of UCS-2 input characters (not bytes) + * bufsize is the size of the output buffer in bytes + */ +void +utf_encodestr( const u_int16_t * ucsp, int ucslen, + u_int8_t * utf8p, u_int32_t bufsize, int byte_order ) +{ + u_int8_t *bufend; + u_int16_t ucs_ch; + + bufend = utf8p + bufsize; + + while (ucslen-- > 0) { + if (byte_order == OSBigEndian) + ucs_ch = SWAP_BE16(*ucsp++); + else + ucs_ch = SWAP_LE16(*ucsp++); + + if (ucs_ch < 0x0080) { + if (utf8p >= bufend) + break; + if (ucs_ch == '\0') + continue; /* skip over embedded NULLs */ + *utf8p++ = ucs_ch; + + } else if (ucs_ch < 0x800) { + if ((utf8p + 1) >= bufend) + break; + *utf8p++ = (ucs_ch >> 6) | 0xc0; + *utf8p++ = (ucs_ch & 0x3f) | 0x80; + + } else { + if ((utf8p + 2) >= bufend) + break; + *utf8p++ = (ucs_ch >> 12) | 0xe0; + *utf8p++ = ((ucs_ch >> 6) & 0x3f) | 0x80; + *utf8p++ = ((ucs_ch) & 0x3f) | 0x80; + } + } + + *utf8p = '\0'; +} + + +/* + * utf_decodestr - Decodes the null terminated UTF-8 string at + * utf8p into a UCS-2 (Unicode) string at ucsp. + * + * ucslen is the number of UCS-2 output characters (not bytes) + * bufsize is the size of the output buffer in bytes + */ +void utf_decodestr(const u_int8_t * utf8p, u_int16_t * ucsp, u_int16_t * ucslen, u_int32_t bufsize, int byte_order) +{ + u_int16_t *bufstart; + u_int16_t *bufend; + u_int16_t ucs_ch; + u_int8_t byte; + + bufstart = ucsp; + bufend = (u_int16_t *)((u_int8_t *)ucsp + bufsize); + + while ((byte = *utf8p++) != '\0') { + if (ucsp >= bufend) + break; + + /* check for ascii */ + if (byte < 0x80) { + ucs_ch = byte; + + if (byte_order == OSBigEndian) + *ucsp++ = SWAP_BE16(ucs_ch); + else + *ucsp++ = SWAP_LE16(ucs_ch); + + continue; + } + + switch (byte & 0xf0) { + /* 2 byte sequence*/ + case 0xc0: + case 0xd0: + /* extract bits 6 - 10 from first byte */ + ucs_ch = (byte & 0x1F) << 6; + break; + /* 3 byte sequence*/ + case 0xe0: + /* extract bits 12 - 15 from first byte */ + ucs_ch = (byte & 0x0F) << 6; + + /* extract bits 6 - 11 from second byte */ + if (((byte = *utf8p++) & 0xc0) != 0x80) + goto stop; + + ucs_ch += (byte & 0x3F); + ucs_ch <<= 6; + break; + default: + goto stop; + } + + /* extract bits 0 - 5 from final byte */ + if (((byte = *utf8p++) & 0xc0) != 0x80) + goto stop; + ucs_ch += (byte & 0x3F); + + if (byte_order == OSBigEndian) + *ucsp++ = SWAP_BE16(ucs_ch); + else + *ucsp++ = SWAP_LE16(ucs_ch); + } +stop: + if (byte_order == OSBigEndian) + *ucslen = SWAP_BE16(ucsp - bufstart); + else + *ucslen = SWAP_LE16(ucsp - bufstart); +} Index: branches/slice/rev749/libsaio/libsaio.h =================================================================== --- branches/slice/rev749/libsaio/libsaio.h (revision 0) +++ branches/slice/rev749/libsaio/libsaio.h (revision 1169) @@ -0,0 +1,35 @@ +/* + * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 2.0 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* libsaio.h */ + +#ifndef __LIBSAIO_LIBSAIO_H +#define __LIBSAIO_LIBSAIO_H + +#include "libsa.h" +#include "memory.h" +#include "io_inline.h" +#include "saio_types.h" +#include "saio_internal.h" + +#endif /* !__LIBSAIO_LIBSAIO_H */ Index: branches/slice/rev749/libsaio/acpi_patcher.h =================================================================== --- branches/slice/rev749/libsaio/acpi_patcher.h (revision 0) +++ branches/slice/rev749/libsaio/acpi_patcher.h (revision 1169) @@ -0,0 +1,39 @@ +/* + * Copyright 2008 mackerintel + */ + +#ifndef __LIBSAIO_ACPI_PATCHER_H +#define __LIBSAIO_ACPI_PATCHER_H + +#include "libsaio.h" +#include "efi.h" +//#include "ACPIPatcher.h" + +extern void *new_dsdt; +extern uint64_t smbios_p; + +extern int setupAcpi(); + +extern EFI_STATUS addConfigurationTable(); +extern int search_and_get_acpi_fd(const char *, const char **); + +extern EFI_GUID gEfiAcpiTableGuid; +extern EFI_GUID gEfiAcpi20TableGuid; + +struct p_state +{ + union + { + uint16_t Control; + struct + { + uint8_t VID; // Voltage ID + uint8_t FID; // Frequency ID + }; + }; + + uint8_t CID; // Compare ID + uint32_t Frequency; +}; + +#endif /* !__LIBSAIO_ACPI_PATCHER_H */ Index: branches/slice/rev749/libsaio/Makefile =================================================================== --- branches/slice/rev749/libsaio/Makefile (revision 0) +++ branches/slice/rev749/libsaio/Makefile (revision 1169) @@ -0,0 +1,97 @@ + +DIR = libsaio +include ../MakePaths.dir + +UTILDIR = ../util +LIBSADIR = ../libsa +BOOT2DIR = ../boot2 +INSTALLDIR = $(DSTROOT)/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders/standalone +#SYMROOT= + +OPTIM = -Os -Oz +DEBUG = -DNOTHING +#DEBUG = -DDEBUG_CPU=1 -DDEBUG_MEM=1 -DDEBUG_SPD=1 -DDEBUG_PCI=1 -DDEBUG_SMBIOS=1 +CFLAGS = $(RC_CFLAGS) $(OPTIM) $(MORECPP) -arch i386 -g -Wmost \ + -D__ARCHITECTURE__=\"i386\" -DSAIO_INTERNAL_USER \ + -DRCZ_COMPRESSED_FILE_SUPPORT $(DEBUG) \ + -fno-builtin -static $(OMIT_FRAME_POINTER_CFLAG) \ + -mpreferred-stack-boundary=2 -fno-align-functions -fno-stack-protector \ + -march=pentium4 -msse2 -mfpmath=sse -msoft-float + +DEFINES= +CONFIG = hd +INC = -I. -I$(SYMROOT) -I$(UTILDIR) -I$(LIBSADIR) -I$(BOOT2DIR) +ifneq "" "$(wildcard /bin/mkdirs)" + MKDIRS = /bin/mkdirs +else + MKDIRS = /bin/mkdir -p +endif +AS = as +LD = ld +# LIBS= -lc_static +LIBS= + +VPATH = $(OBJROOT):$(SYMROOT) + +SAIO_OBJS = table.o asm.o bios.o biosfn.o \ + disk.o sys.o cache.o bootstruct.o \ + stringTable.o load.o pci.o allocate.o misc.o \ + ufs.o ufs_byteorder.o \ + vbe.o nbp.o smbios_patcher.o hfs.o hfs_compare.o \ + xml.o ntfs.o msdos.o md5c.o device_tree.o \ + cpu.o platform.o acpi_patcher.o aml_generator.o \ + fake_efi.o ext2fs.o \ + pci_setup.o \ + device_inject.o pci_root.o \ + convert.o + + +SAIO_EXTERN_OBJS = console.o + +SFILES = +CFILES = +HFILES = +EXPORTED_HFILES = +INSTALLED_HFILES = +OTHERFILES = Makefile +ALLSRC = $(SFILES) $(CFILES) \ + $(HFILES) $(OTHERFILES) +LIBS = libsaio.a +DIRS_NEEDED = $(OBJROOT) $(SYMROOT) +#GENFILES = $(SYMROOT)/saio_internal.h \ +# $(SYMROOT)/saio_external.h \ +# $(SYMROOT)/saio_defs.h \ +# $(SYMROOT)/saio_table.c + +#SIG = $(SYMROOT)/sig + +optionrom: CFLAGS += -DOPTION_ROM + +all embedtheme optionrom: $(DIRS_NEEDED) libsaio.h $(LIBS) + +#libsaio_static.a: $(SAIO_OBJS) +# rm -f $(SYMROOT)/$@ +# ar q $(SYMROOT)/$@ $(SAIO_OBJS) +# ranlib $(SYMROOT)/$@ + +libsaio.a: $(SAIO_EXTERN_OBJS) $(SAIO_OBJS) + @echo "\t[RM] $(SYMROOT)/$(@F)" + @rm -f $(SYMROOT)/$(@F) + @echo "\t[AR] $@" + @ar q $(SYMROOT)/$(@F) $^ &> /dev/null + @echo "\t[RANLIB] $@" + @ranlib $(SYMROOT)/$(@F) + +#saio_internal.h: saio_external.h +#saio_table.c: saio_external.h +#saio_defs.h: saio_external.h +#saio_external.h: saio.def +# $(SIG) -d $(SYMROOT) -n saio saio.def + +#installhdrs:: $(INSTALLDIR) +# cp $(INSTALLED_HFILES) $(INSTALLDIR) + +include ../MakeInc.dir + +# dependencies +-include $(OBJROOT)/Makedep Index: branches/slice/rev749/libsaio/ufs.c =================================================================== --- branches/slice/rev749/libsaio/ufs.c (revision 0) +++ branches/slice/rev749/libsaio/ufs.c (revision 1169) @@ -0,0 +1,534 @@ +/* + * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 2.0 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * ufs.c - File System Module for UFS. + * + * Copyright (c) 1998-2002 Apple Computer, Inc. + * + * DRI: Josh de Cesare + */ +#include + +#include "ufs.h" +#include "ufs_byteorder.h" + +#if !defined(MAXNAMLEN) && defined(UFSMAXNAMLEN) +#define MAXNAMLEN UFSMAXNAMLEN +#endif + +typedef struct dinode Inode, *InodePtr; + +// Private function prototypes + +static char *ReadBlock(long fragNum, long fragOffset, long length, + char *buffer, long cache); +static long ReadInode(long inodeNum, InodePtr inode, long *flags, long *time); +static long ResolvePathToInode(char *filePath, long *flags, + InodePtr fileInode, InodePtr dirInode); +static long ReadDirEntry(InodePtr dirInode, long *fileInodeNum, + long long *dirIndex, char **name); +static long FindFileInDir(char *fileName, long *flags, + InodePtr fileInode, InodePtr dirInode); +static char *ReadFileBlock(InodePtr fileInode, long fragNum, long blockOffset, + long length, char *buffer, long cache); +static long ReadFile(InodePtr fileInode, uint64_t *length, void *base, uint64_t offset); + +#define kDevBlockSize (0x200) // Size of each disk block. +#define kDiskLabelBlock (15) // Block the DL is in. + +#ifdef __i386__ + +static CICell gCurrentIH; +static long long gPartitionBase; +static char *gULBuf; +static char *gFSBuf; +static struct fs *gFS; +#if !BOOT1 +static struct ufslabel gUFSLabel; // for UUID +#endif +static long gBlockSize; +static long gFragSize; +static long gFragsPerBlock; +static char *gTempBlock; +static char *gTempName; +static char *gTempName2; +static InodePtr gRootInodePtr; +static InodePtr gFileInodePtr; + +#else /* !__i386__ */ + +static CICell gCurrentIH; +static long long gPartitionBase; +static char gDLBuf[8192]; +static char gFSBuf[SBSIZE]; +static struct fs *gFS; +#if !BOOT1 +static struct ufslabel gUFSLabel; // for UUID +#endif +static long gBlockSize; +static long gFragSize; +static long gFragsPerBlock; +static char *gTempBlock; +static char gTempName[MAXNAMLEN + 1]; +static char gTempName2[MAXNAMLEN + 1]; +static Inode _gRootInode; +static Inode _gFileInode; +static InodePtr gRootInodePtr = &_gRootInode; +static InodePtr gFileInodePtr = &_gFileInode; + +#endif /* !__i386__ */ + +// Public functions + +void UFSFree(CICell ih) +{ + if(gCurrentIH == ih) + gCurrentIH = 0; + free(ih); +} + +long UFSInitPartition( CICell ih ) +{ +#if !BOOT1 + long ret; +#endif + + if (ih == gCurrentIH) { +#ifdef __i386__ + CacheInit(ih, gBlockSize); +#endif + return 0; + } + +#if !BOOT1 + verbose("UFSInitPartition: %x\n", ih); +#endif + + gCurrentIH = 0; + +#ifdef __i386__ + if (!gULBuf) gULBuf = (char *) malloc(UFS_LABEL_SIZE); + if (!gFSBuf) gFSBuf = (char *) malloc(SBSIZE); + if (!gTempName) gTempName = (char *) malloc(MAXNAMLEN + 1); + if (!gTempName2) gTempName2 = (char *) malloc(MAXNAMLEN + 1); + if (!gRootInodePtr) gRootInodePtr = (InodePtr) malloc(sizeof(Inode)); + if (!gFileInodePtr) gFileInodePtr = (InodePtr) malloc(sizeof(Inode)); + if (!gULBuf || !gFSBuf || !gTempName || !gTempName2 || + !gRootInodePtr || !gFileInodePtr) return -1; +#endif + + // Assume there is no Disk Label + gPartitionBase = 0; + +#if !BOOT1 + // read the disk label to get the UUID + // (rumor has it that UFS headers can be either-endian on disk; hopefully + // that isn't true for this UUID field). + Seek(ih, gPartitionBase + UFS_LABEL_OFFSET); + ret = Read(ih, (long)&gUFSLabel, UFS_LABEL_SIZE); + if(ret != 0) + bzero(&gUFSLabel, UFS_LABEL_SIZE); +#endif /* !BOOT1 */ + + // Look for the Super Block + Seek(ih, gPartitionBase + SBOFF); + Read(ih, (long)gFSBuf, SBSIZE); + + gFS = (struct fs *)gFSBuf; + byte_swap_superblock(gFS); + + if (gFS->fs_magic != FS_MAGIC) { + return -1; + } + + ih->modTime = gFS->fs_time; + + // Calculate the block size and set up the block cache. + gBlockSize = gFS->fs_bsize; + gFragSize = gFS->fs_fsize; + gFragsPerBlock = gBlockSize / gFragSize; + if (gTempBlock != 0) free(gTempBlock); + gTempBlock = malloc(gBlockSize); + CacheInit(ih, gBlockSize); + + gCurrentIH = ih; + + // Read the Root Inode + ReadInode(ROOTINO, gRootInodePtr, 0, 0); + + return 0; +} + +#if !BOOT1 + +long UFSGetUUID(CICell ih, char *uuidStr) +{ + long long uuid = gUFSLabel.ul_uuid; + + if (UFSInitPartition(ih) == -1) return -1; + if (uuid == 0LL) return -1; + + return CreateUUIDString((uint8_t*)(&uuid), sizeof(uuid), uuidStr); +} + +#endif /* !BOOT1 */ + +long UFSLoadFile( CICell ih, char * filePath ) +{ + return UFSReadFile(ih, filePath, (void *)gFSLoadAddress, 0, 0); +} + +long UFSReadFile( CICell ih, char * filePath, void * base, uint64_t offset, uint64_t length ) +{ + long ret, flags; + +#if !BOOT1 + verbose("Loading UFS file: [%s] from %x.\n", filePath, (unsigned)ih); +#endif + + if (UFSInitPartition(ih) == -1) return -1; + + // Skip one or two leading '/'. + if (*filePath == '/') filePath++; + if (*filePath == '/') filePath++; + + ret = ResolvePathToInode(filePath, &flags, gFileInodePtr, gRootInodePtr); + if ((ret == -1) || ((flags & kFileTypeMask) != kFileTypeFlat)) return -1; + + ret = ReadFile(gFileInodePtr, &length, base, offset); + if (ret == -1) return -1; + + return length; +} + +#ifndef BOOT1 + +long UFSGetDirEntry( CICell ih, char * dirPath, long long * dirIndex, + char ** name, long * flags, long * time, + FinderInfo * finderInfo, long * infoValid) +{ + long ret, fileInodeNum, dirFlags; + Inode tmpInode; + + if (UFSInitPartition(ih) == -1) return -1; + + if (infoValid) *infoValid = 0; + + // Skip a leading '/' if present + if (*dirPath == '/') dirPath++; + if (*dirPath == '/') dirPath++; + + ret = ResolvePathToInode(dirPath, &dirFlags, gFileInodePtr, gRootInodePtr); + if ((ret == -1) || ((dirFlags & kFileTypeMask) != kFileTypeDirectory)) + return -1; + + ret = ReadDirEntry(gFileInodePtr, &fileInodeNum, dirIndex, name); + if (ret != 0) return ret; + + ReadInode(fileInodeNum, &tmpInode, flags, time); + + return 0; +} + +void +UFSGetDescription(CICell ih, char *str, long strMaxLen) +{ + if (UFSInitPartition(ih) == -1) { return; } + + struct ufslabel *ul; + + // Look for the Disk Label + Seek(ih, 1ULL * UFS_LABEL_OFFSET); + Read(ih, (long)gULBuf, UFS_LABEL_SIZE); + + ul = (struct ufslabel *)gULBuf; + + unsigned char magic_bytes[] = UFS_LABEL_MAGIC; + int i; + unsigned char *p = (unsigned char *)&ul->ul_magic; + + for (i=0; iul_name, strMaxLen); +} + +long +UFSGetFileBlock(CICell ih, char *filePath, unsigned long long *firstBlock) +{ + long ret, flags; + + if (UFSInitPartition(ih) == -1) return -1; + + // Skip one or two leading '/'. + if (*filePath == '/') filePath++; + if (*filePath == '/') filePath++; + + ret = ResolvePathToInode(filePath, &flags, gFileInodePtr, gRootInodePtr); + if ((ret == -1) || ((flags & kFileTypeMask) != kFileTypeFlat)) return -1; + + *firstBlock = (gPartitionBase + 1ULL * gFileInodePtr->di_db[0] * gBlockSize) / 512ULL; + + return 0; +} + + +#endif /* !BOOT1 */ + +// Private functions + +static char * ReadBlock( long fragNum, long blockOffset, long length, + char * buffer, long cache ) +{ + long long offset; + long blockNum; + + blockNum = fragNum / gFragsPerBlock; + fragNum -= blockNum * gFragsPerBlock; + + blockOffset += fragNum * gFragSize; + + offset = gPartitionBase + 1ULL * blockNum * gBlockSize; + + if (cache && ((blockOffset + length) <= gBlockSize)) { + CacheRead(gCurrentIH, gTempBlock, offset, gBlockSize, 1); + if (buffer != 0) bcopy(gTempBlock + blockOffset, buffer, length); + else buffer = gTempBlock + blockOffset; + } else { + offset += blockOffset; + CacheRead(gCurrentIH, buffer, offset, length, 0); + } + + return buffer; +} + +static long ReadInode( long inodeNum, InodePtr inode, long * flags, long * time ) +{ + long fragNum = ino_to_fsba(gFS, inodeNum); + long blockOffset = ino_to_fsbo(gFS, inodeNum) * sizeof(Inode); + + ReadBlock(fragNum, blockOffset, sizeof(Inode), (char *)inode, 1); + byte_swap_dinode_in(inode); + + if (time != 0) *time = inode->di_mtime; + + if (flags != 0) { + switch (inode->di_mode & IFMT) { + case IFREG: *flags = kFileTypeFlat; break; + case IFDIR: *flags = kFileTypeDirectory; break; + case IFLNK: *flags = kFileTypeLink; break; + default : *flags = kFileTypeUnknown; break; + } + + *flags |= inode->di_mode & kPermMask; + + if (inode->di_uid != 0) *flags |= kOwnerNotRoot; + } + + return 0; +} + +static long ResolvePathToInode( char * filePath, long * flags, + InodePtr fileInode, InodePtr dirInode ) +{ + char * restPath; + long ret, cnt; + + // if filePath is empty the we want this directory. + if (*filePath == '\0') { + bcopy((char *)dirInode, (char *)fileInode, sizeof(Inode)); + return 0; + } + + // Copy the file name to gTempName + cnt = 0; + while ((filePath[cnt] != '/') && (filePath[cnt] != '\0')) cnt++; + strlcpy(gTempName, filePath, cnt+1); + + // Move restPath to the right place. + if (filePath[cnt] != '\0') cnt++; + restPath = filePath + cnt; + + // gTempName is a name in the current Dir. + // restPath is the rest of the path if any. + + ret = FindFileInDir(gTempName, flags, fileInode, dirInode); + if (ret == -1) return -1; + + if ((*restPath != '\0') && ((*flags & kFileTypeMask) == kFileTypeDirectory)) + ret = ResolvePathToInode(restPath, flags, fileInode, fileInode); + + return ret; +} + +static long ReadDirEntry( InodePtr dirInode, long * fileInodeNum, + long long * dirIndex, char ** name ) +{ + struct direct *dir; + char *buffer; + long long index; + long dirBlockNum, dirBlockOffset; + + while (1) { + index = *dirIndex; + + dirBlockOffset = (long) (index % DIRBLKSIZ); + dirBlockNum = (long) (index / DIRBLKSIZ); + + buffer = ReadFileBlock(dirInode, dirBlockNum, 0, DIRBLKSIZ, 0, 1); + if (buffer == 0) return -1; + + dir = (struct direct *)(buffer + dirBlockOffset); + byte_swap_dir_block_in((char *)dir, 1); + + *dirIndex += dir->d_reclen; + + if (dir->d_ino != 0) break; + + if (dirBlockOffset != 0) return -1; + } + + *fileInodeNum = dir->d_ino; + *name = strlcpy(gTempName2, dir->d_name, dir->d_namlen+1); + + return 0; +} + +static long FindFileInDir( char * fileName, long * flags, + InodePtr fileInode, InodePtr dirInode ) +{ + long ret, inodeNum; + long long index = 0; + char *name; + + while (1) { + ret = ReadDirEntry(dirInode, &inodeNum, &index, &name); + if (ret == -1) return -1; + + if (strcmp(fileName, name) == 0) break; + } + + ReadInode(inodeNum, fileInode, flags, 0); + + return 0; +} + +static char * ReadFileBlock( InodePtr fileInode, long fragNum, long blockOffset, + long length, char * buffer, long cache ) +{ + long fragCount, blockNum; + long diskFragNum, indFragNum, indBlockOff, refsPerBlock; + char *indBlock; + + fragCount = (fileInode->di_size + gFragSize - 1) / gFragSize; + if (fragNum >= fragCount) return 0; + + refsPerBlock = gBlockSize / sizeof(ufs_daddr_t); + + blockNum = fragNum / gFragsPerBlock; + fragNum -= blockNum * gFragsPerBlock; + + // Get Direct Block Number. + if (blockNum < NDADDR) { + diskFragNum = fileInode->di_db[blockNum]; + } else { + blockNum -= NDADDR; + + // Get Single Indirect Fragment Number. + if (blockNum < refsPerBlock) { + indFragNum = fileInode->di_ib[0]; + } else { + blockNum -= refsPerBlock; + + // Get Double Indirect Fragment Number. + if (blockNum < (refsPerBlock * refsPerBlock)) { + indFragNum = fileInode->di_ib[1]; + } else { + blockNum -= refsPerBlock * refsPerBlock; + + // Get Triple Indirect Fragment Number. + indFragNum = fileInode->di_ib[2]; + + indBlock = ReadBlock(indFragNum, 0, gBlockSize, 0, 1); + indBlockOff = blockNum / (refsPerBlock * refsPerBlock); + blockNum %= (refsPerBlock * refsPerBlock); + indFragNum = SWAP_BE32(((ufs_daddr_t *)indBlock)[indBlockOff]); + } + + indBlock = ReadBlock(indFragNum, 0, gBlockSize, 0, 1); + indBlockOff = blockNum / refsPerBlock; + blockNum %= refsPerBlock; + indFragNum = SWAP_BE32(((ufs_daddr_t *)indBlock)[indBlockOff]); + } + + indBlock = ReadBlock(indFragNum, 0, gBlockSize, 0, 1); + diskFragNum = SWAP_BE32(((ufs_daddr_t *)indBlock)[blockNum]); + } + + buffer = ReadBlock(diskFragNum+fragNum, blockOffset, length, buffer, cache); + + return buffer; +} + +static long ReadFile( InodePtr fileInode, uint64_t * length, void * base, uint64_t offset ) +{ + long bytesLeft, curSize, curFrag; + char *buffer, *curAddr = (char *)base; + + bytesLeft = fileInode->di_size; + + if (offset > bytesLeft) { + printf("Offset is too large.\n"); + return -1; + } + + if ((*length == 0) || ((offset + *length) > bytesLeft)) { + *length = bytesLeft - offset; + } +/* + if (bytesLeft > kLoadSize) { + printf("File is too large.\n"); + return -1; + } +*/ + bytesLeft = *length; + curFrag = (offset / gBlockSize) * gFragsPerBlock; + offset %= gBlockSize; + + while (bytesLeft) { + curSize = gBlockSize; + if (curSize > bytesLeft) curSize = bytesLeft; + if ((offset + curSize) > gBlockSize) curSize = (gBlockSize - offset); + + buffer = ReadFileBlock(fileInode, curFrag, offset, curSize, curAddr, 0); + if (buffer == 0) break; + + if (offset != 0) offset = 0; + + curFrag += gFragsPerBlock; + curAddr += curSize; + bytesLeft -= curSize; + } + + return bytesLeft; +} \ No newline at end of file Index: branches/slice/rev749/libsaio/bios.h =================================================================== --- branches/slice/rev749/libsaio/bios.h (revision 0) +++ branches/slice/rev749/libsaio/bios.h (revision 1169) @@ -0,0 +1,105 @@ +/* + * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 2.0 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright 1994 NeXT Computer, Inc. + * All rights reserved. + */ + +#ifndef __LIBSAIO_BIOS_H +#define __LIBSAIO_BIOS_H + +#include + +typedef union { + unsigned int rx; + unsigned short rr; + struct { + unsigned char l; + unsigned char h; + } r; +} machineRegister_t; + +typedef struct { + unsigned short cf :1; + unsigned short :1; + unsigned short pf :1; + unsigned short :1; + unsigned short af :1; + unsigned short :1; + unsigned short zf :1; + unsigned short sf :1; + unsigned short tf :1; + unsigned short _if :1; + unsigned short df :1; + unsigned short of :1; + unsigned short iopl:2; + unsigned short nt :1; +} machineFlags_t; + +typedef struct { + unsigned int intno; + machineRegister_t eax; + machineRegister_t ebx; + machineRegister_t ecx; + machineRegister_t edx; + machineRegister_t edi; + machineRegister_t esi; + machineRegister_t ebp; + unsigned short cs; + unsigned short ds; + unsigned short es; + machineFlags_t flags; +} biosBuf_t; + +#define EBIOS_FIXED_DISK_ACCESS 0x01 +#define EBIOS_LOCKING_ACCESS 0x02 +#define EBIOS_ENHANCED_DRIVE_INFO 0x04 + +#define BASE_HD_DRIVE 0x80 + +#if 0 +/* + * ACPI defined memory range types. + */ +enum { + kMemoryRangeUsable = 1, // RAM usable by the OS. + kMemoryRangeReserved = 2, // Reserved. (Do not use) + kMemoryRangeACPI = 3, // ACPI tables. Can be reclaimed. + kMemoryRangeNVS = 4, // ACPI NVS memory. (Do not use) + + /* Undefined types should be treated as kMemoryRangeReserved */ +}; +#endif + +/* + * Memory range descriptor. + */ +typedef struct MemoryRange { + unsigned long long base; // 64-bit base address + unsigned long long length; // 64-bit length in bytes + unsigned long type; // type of memory range + unsigned long reserved; +} MemoryRange; + +#endif /* !__LIBSAIO_BIOS_H */ Index: branches/slice/rev749/libsaio/SMBIOS.h =================================================================== --- branches/slice/rev749/libsaio/SMBIOS.h (revision 0) +++ branches/slice/rev749/libsaio/SMBIOS.h (revision 1169) @@ -0,0 +1,451 @@ +/* + * Copyright (c) 1998-2006 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* This file is a stripped-down version of the one found in the AppleSMBIOS project. + * Changes: + * - Don't use pragma pack but instead use GCC's packed attribute + */ + +#ifndef _LIBSAIO_SMBIOS_H +#define _LIBSAIO_SMBIOS_H + +/* + * Based on System Management BIOS Reference Specification v2.5, //Slice - 2.7.0 + */ + +typedef uint8_t SMBString; +typedef uint8_t SMBByte; +typedef uint16_t SMBWord; +typedef uint32_t SMBDWord; +typedef uint64_t SMBQWord; + +// Apple known types + enum { + kSMBTypeBIOSInformation = 0, + kSMBTypeSystemInformation = 1, + kSMBTypeBaseBoard = 2, + kSMBTypeSystemEnclosure = 3, + kSMBTypeProcessorInformation = 4, + kSMBTypeMemoryModule = 6, + kSMBTypeCacheInformation = 7, + kSMBTypeSystemSlot = 9, + kSMBTypePhysicalMemoryArray = 16, + kSMBTypeMemoryDevice = 17, + kSMBType32BitMemoryErrorInfo = 18, + kSMBType64BitMemoryErrorInfo = 33, + + // Apple Specific Structures + kSMBTypeFirmwareVolume = 128, + kSMBTypeMemorySPD = 130, + kSMBTypeOemProcessorType = 131, + kSMBTypeOemProcessorBusSpeed = 132 + }; + + +struct DMIHeader { + SMBByte type; + SMBByte length; + SMBWord handle; +} __attribute__((packed)); +typedef struct DMIHeader DMIHeader; + +#define SMB_STRUCT_HEADER struct DMIHeader dmiHeader; + +struct DMIEntryPoint { + SMBByte anchor[5]; + SMBByte checksum; + SMBWord tableLength; + SMBDWord tableAddress; + SMBWord structureCount; + SMBByte bcdRevision; +} __attribute__((packed)); +typedef struct DMIEntryPoint DMIEntryPoint; + +struct SMBEntryPoint { + SMBByte anchor[4]; + SMBByte checksum; + SMBByte entryPointLength; + SMBByte majorVersion; + SMBByte minorVersion; + SMBWord maxStructureSize; + SMBByte entryPointRevision; + SMBByte formattedArea[5]; + struct DMIEntryPoint dmi; +} __attribute__((packed)); +typedef struct SMBEntryPoint SMBEntryPoint; + + +// +// BIOS Information (Type 0) //min len 18+num_of_extChars. Max=18h=24 +// +struct SMBBIOSInformation { + struct DMIHeader dmiHeader; // Type 0 + SMBString vendor; // BIOS vendor name + SMBString version; // BIOS version + SMBWord startSegment; // BIOS segment start + SMBString releaseDate; // BIOS release date + SMBByte romSize; // (n); 64K * (n+1) bytes + SMBQWord characteristics; // supported BIOS functions + SMBByte extChars[2]; //BIOS Characteristics Extension Bytes +}; + +//BIOS Characteristics Extension Bits +/* + Characteristics Ext1 0x87 + Bit0 ACPI supported - 1 (Yes) + Bit1 USB Legacy is supported - 1 (Yes) + Bit2 AGP is supported - 1 (Yes) + Bit3 I2O boot is supported - 0 (No) + Bit4 LS-120 boot is supported - 0 (No) + Bit5 ATAPI ZIP Drive boot is supported - 0 (No) + Bit6 1394 boot is supported - 0 (No) + Bit7 Smart Battery supported - 1 (Yes) + Characteristics Ext2 0x07 + Bit0 BIOS Boot Specification supported - 1 (Yes) + Bit1 Function key-initiated Network Service boot supported - 1 (Yes) + Bit2 Enable Targeted Content Distribution - 1 (Yes) + + Bit 0 BIOS Boot Specification is supported. + Bit 1 Function key-initiated Network Service boot is supported. When function key-uninitiated Network Service Boot is not supported, a network adapter option ROM may choose to offer this functionality on its own, thus offering this capability to legacy systems. When the function is supported, the network adapter option ROM shall not offer this capability. + Bit 2 Enable Targeted Content Distribution. The manufacturer has ensured that the SMBIOS data is useful in identifying the computer for targeted delivery of model-specific software and firmware content through third-party content distribution services. + Bit 3 UEFI Specification is supported. + Bit 4 The SMBIOS table describes a virtual machine. (If this bit is not set, no inference can be made about the virtuality of the system.) + + Bits 5:7 Reserved for future assignment by this specification + */ + +// +// System Information (Type 1) +// + +struct DMISystemInformation { + // 2.0+ spec (8 bytes) + struct DMIHeader dmiHeader; // Type 1 + SMBString manufacturer; + SMBString productName; + SMBString version; + SMBString serialNumber; + // 2.1+ spec (25 bytes) + SMBByte uuid[16]; // can be all 0 or all 1's + SMBByte wakeupReason; // reason for system wakeup + // 2.4+ spec + SMBString SKUNumber; // purchase order number +}; +typedef struct DMISystemInformation DMISystemInformation; +// +// Base Board (Type 2) +// + +struct DMIBaseBoard { + struct DMIHeader dmiHeader; // Type 2 + SMBString manufacturer; + SMBString product; + SMBString version; + SMBString serialNumber; + SMBString assetTagNumber; + SMBByte featureFlags; + SMBString locationInChassis; + SMBWord chassisHandle; + SMBByte boardType; + SMBByte numberOfContainedHandles; + // 0 - 255 contained handles go here but we do not include + // them in our structure. Be careful to use numberOfContainedHandles + // times sizeof(SMBWord) when computing the actual record size, + // if you need it. +}; +typedef struct DMIBaseBoard DMIBaseBoard; +// Values for boardType in Type 2 records +enum { + kSMBBaseBoardUnknown = 0x01, + kSMBBaseBoardOther = 0x02, + kSMBBaseBoardServerBlade = 0x03, + kSMBBaseBoardConnectivitySwitch = 0x04, + kSMBBaseBoardSystemMgmtModule = 0x05, + kSMBBaseBoardProcessorModule = 0x06, + kSMBBaseBoardIOModule = 0x07, + kSMBBaseBoardMemoryModule = 0x08, + kSMBBaseBoardDaughter = 0x09, + kSMBBaseBoardMotherboard = 0x0A, + kSMBBaseBoardProcessorMemoryModule = 0x0B, + kSMBBaseBoardProcessorIOModule = 0x0C, + kSMBBaseBoardInterconnect = 0x0D, +}; + + +// +// System Enclosure (Type 3) +// + +struct DMISystemEnclosure { + struct DMIHeader dmiHeader; // Type 3 len=13 + SMBString manufacturer; + SMBByte type; + SMBString version; + SMBString serialNumber; + SMBString assetTagNumber; + SMBByte bootupState; + SMBByte powerSupplyState; + SMBByte thermalState; + SMBByte securityStatus; + SMBDWord oemDefined; +}; +typedef struct DMISystemEnclosure DMISystemEnclosure; +// +// Processor Information (Type 4) +// + +struct DMIProcessorInformation { + // 2.0+ spec (26 bytes) + struct DMIHeader dmiHeader; // Type 4 + SMBString socketDesignation; + SMBByte processorType; // CPU = 3 + SMBByte processorFamily; // processor family enum + SMBString manufacturer; + SMBQWord processorID; // based on CPUID + SMBString processorVersion; + SMBByte voltage; // bit7 cleared indicate legacy mode + SMBWord externalClock; // external clock in MHz + SMBWord maximumClock; // max internal clock in MHz + SMBWord currentClock; // current internal clock in MHz + SMBByte status; + SMBByte processorUpgrade; // processor upgrade enum + // 2.1+ spec (32 bytes) + SMBWord L1CacheHandle; + SMBWord L2CacheHandle; + SMBWord L3CacheHandle; + // 2.3+ spec (35 bytes) + SMBString serialNumber; + SMBString assetTag; + SMBString partNumber; + // 2.5+ spec (38 bytes) + SMBByte coreCount; + SMBByte coreEnabled; + SMBByte Threads; +} __attribute__((packed)); + +#define kSMBProcessorInformationMinSize 26 + + + + +struct DMIMemoryControllerInfo {/* 3.3.6 Memory Controller Information (Type 5) */ + struct DMIHeader dmiHeader; + SMBByte errorDetectingMethod; + SMBByte errorCorrectingCapability; + SMBByte supportedInterleave; + SMBByte currentInterleave; + SMBByte maxMemoryModuleSize; + SMBWord supportedSpeeds; + SMBWord supportedMemoryTypes; + SMBByte memoryModuleVoltage; + SMBByte numberOfMemorySlots; +} __attribute__((packed)); +typedef struct DMIMemoryControllerInfo DMIMemoryControllerInfo; + +struct DMIMemoryModuleInfo { /* 3.3.7 Memory Module Information (Type 6) */ + struct DMIHeader dmiHeader; + SMBByte socketDesignation; + SMBByte bankConnections; + SMBByte currentSpeed; + SMBWord currentMemoryType; + SMBByte installedSize; + SMBByte enabledSize; + SMBByte errorStatus; +} __attribute__((packed)); +typedef struct DMIMemoryModuleInfo DMIMemoryModuleInfo; + + +#define kSMBMemoryModuleSizeNotDeterminable 0x7D +#define kSMBMemoryModuleSizeNotEnabled 0x7E +#define kSMBMemoryModuleSizeNotInstalled 0x7F + +// +// Cache Information (Type 7) +// + +struct DMICacheInformation { + SMB_STRUCT_HEADER // Type 7 + SMBString socketDesignation; + SMBWord cacheConfiguration; + SMBWord maximumCacheSize; + SMBWord installedSize; + SMBWord supportedSRAMType; + SMBWord currentSRAMType; + SMBByte cacheSpeed; + SMBByte errorCorrectionType; + SMBByte systemCacheType; + SMBByte associativity; +} __attribute__((packed)); + +struct DMISystemSlot { + // 2.0+ spec (12 bytes) + SMB_STRUCT_HEADER // Type 9 + SMBString slotDesignation; + SMBByte slotType; + SMBByte slotDataBusWidth; + SMBByte currentUsage; + SMBByte slotLength; + SMBWord slotID; + SMBByte slotCharacteristics1; + // 2.1+ spec (13 bytes) + SMBByte slotCharacteristics2; +} __attribute__((packed)); + + + +struct DMIPhysicalMemoryArray { /* 3.3.17 Physical Memory Array (Type 16) */ + struct DMIHeader dmiHeader; + SMBByte location; + SMBByte use; + SMBByte memoryCorrectionError; + SMBDWord maximumCapacity; + SMBWord memoryErrorInformationHandle; + SMBWord numberOfMemoryDevices; +} __attribute__((packed)); +typedef struct DMIPhysicalMemoryArray DMIPhysicalMemoryArray; + +struct DMIMemoryDevice { /* 3.3.18 Memory Device (Type 17) */ + struct DMIHeader dmiHeader; + SMBWord physicalMemoryArrayHandle; + SMBWord memoryErrorInformationHandle; + SMBWord totalWidth; + SMBWord dataWidth; + SMBWord size; + SMBByte formFactor; + SMBByte deviceSet; + SMBByte deviceLocator; + SMBByte bankLocator; + SMBByte memoryType; + SMBWord typeDetail; + // 2.3+ spec (27 bytes) + SMBWord memorySpeed; // speed of device in MHz (0 for unknown) + SMBString manufacturer; + SMBString serialNumber; + SMBString assetTag; + SMBString partNumber; +} __attribute__((packed)); +typedef struct DMIMemoryDevice DMIMemoryDevice; + +//Apple specific fields +// +// Firmware Volume Description (Apple Specific - Type 128) +// + +enum { + FW_REGION_RESERVED = 0, + FW_REGION_RECOVERY = 1, + FW_REGION_MAIN = 2, + FW_REGION_NVRAM = 3, + FW_REGION_CONFIG = 4, + FW_REGION_DIAGVAULT = 5, + NUM_FLASHMAP_ENTRIES = 8 +}; + + +struct SMBStructHeader { + SMBByte type; + SMBByte length; + SMBWord handle; +}; + +typedef struct SMBStructHeader SMBStructHeader; + +struct FW_REGION_INFO +{ + SMBDWord StartAddress; + SMBDWord EndAddress; +}; + + +struct DMIFirmwareVolume { + struct DMIHeader dmiHeader; // Type 128 + SMBByte RegionCount; + SMBByte Reserved[3]; + SMBDWord FirmwareFeatures; + SMBDWord FirmwareFeaturesMask; + SMBByte RegionType[ NUM_FLASHMAP_ENTRIES ]; + struct FW_REGION_INFO FlashMap[ NUM_FLASHMAP_ENTRIES ]; +} __attribute__((packed)); + +// +// Memory SPD Data (Apple Specific - Type 130) +// + +struct DMIMemorySPD { + struct DMIHeader dmiHeader; // Type 130 + SMBWord Type17Handle; + SMBWord Offset; + SMBWord Size; + SMBWord Data[]; +} __attribute__((packed)); + +// +// OEM Processor Type (Apple Specific - Type 131) +// + +struct DMIOemProcessorType { + SMB_STRUCT_HEADER + SMBWord ProcessorType; +} __attribute__((packed)); + +// +// OEM Processor Bus Speed (Apple Specific - Type 132) +// +struct DMIOemProcessorBusSpeed { + SMB_STRUCT_HEADER + SMBWord ProcessorBusSpeed; // MT/s unit +} __attribute__((packed)); + + +#if UNUSED +static const char * +SMBMemoryDeviceTypes[] = +{ + "RAM", /* 00h Undefined */ + "RAM", /* 01h Other */ + "RAM", /* 02h Unknown */ + "DRAM", /* 03h DRAM */ + "EDRAM", /* 04h EDRAM */ + "VRAM", /* 05h VRAM */ + "SRAM", /* 06h SRAM */ + "RAM", /* 07h RAM */ + "ROM", /* 08h ROM */ + "FLASH", /* 09h FLASH */ + "EEPROM", /* 0Ah EEPROM */ + "FEPROM", /* 0Bh FEPROM */ + "EPROM", /* 0Ch EPROM */ + "CDRAM", /* 0Dh CDRAM */ + "3DRAM", /* 0Eh 3DRAM */ + "SDRAM", /* 0Fh SDRAM */ + "SGRAM", /* 10h SGRAM */ + "RDRAM", /* 11h RDRAM */ + "DDR SDRAM", /* 12h DDR */ + "DDR2 SDRAM", /* 13h DDR2 */ + "DDR2 FB-DIMM", /* 14h DDR2 FB-DIMM */ + "RAM", /* 15h unused */ + "RAM", /* 16h unused */ + "RAM", /* 17h unused */ + "DDR3", /* 18h DDR3, chosen in [5776134] */ +}; +#endif + +#endif /* !_LIBSAIO_SMBIOS_H */ Index: branches/slice/rev749/libsaio/smbios_patcher.c =================================================================== --- branches/slice/rev749/libsaio/smbios_patcher.c (revision 0) +++ branches/slice/rev749/libsaio/smbios_patcher.c (revision 1169) @@ -0,0 +1,1352 @@ +/* + * Copyright 2008 mackerintel + */ + +#include "libsaio.h" +#include "boot.h" +#include "bootstruct.h" +#include "acpi.h" +#include "convert.h" +#include "efi_tables.h" +#include "fake_efi.h" +#include "platform.h" +#include "smbios_patcher.h" +#include "SMBIOS.h" +#include "pci.h" + +#ifndef DEBUG_SMBIOS +#define DEBUG_SMBIOS 0 +#endif + +#if DEBUG_SMBIOS +#define DBG(x...) verbose(x) +#else +#define DBG(x...) +#endif +//Slice - for ACPI patcher templates +int ModelLength = 0; +char MacModel[8] = "MacBook"; +unsigned int ModelRev = 0x00010001; +uint64_t smbios_p; + +char* gSMBIOSBoardModel; + +typedef struct { + const char* key; + const char* value; +} SMStrEntryPair; +//Slice - TODO must be unique UUID for each model? +/* Random values +19422392-C343-4A3A-92A3-AB1F0A6C3E52 +E3314823-659D-42B6-B42C-147E4E3484D4 +C3D73A74-809A-4804-A747-DDB934A737D0 +*/ +// defaults for a MacBook +static const SMStrEntryPair const sm_macbook11_defaults[]={ + {"SMbiosvendor", "Apple Inc." }, + {"SMbiosversion", "MB11.0061.B03.0809221748" }, + {"SMbiosdate", "04/01/2007" }, + {"SMmanufacter", "Apple Inc." }, + {"SMproductname", "MacBook1,1" }, + {"SMsystemversion", "1.0" }, + {"SMserial", "W88033AKY51" }, + {"SMfamily", "MacBook" }, + {"SMboardmanufacter", "Apple Inc." }, + {"SMboardproduct", "Mac-F4208CA9" }, + {"SMUUID" , "19422392-C343-106B-80A3-001F0A6C3E52"}, + { "","" } +}; + +static const SMStrEntryPair const sm_macbook_defaults[]={ + {"SMbiosvendor", "Apple Inc." }, + {"SMbiosversion", "MB41.88Z.0073.B00.0809221748" }, + {"SMbiosdate", "04/01/2008" }, + {"SMmanufacter", "Apple Inc." }, + {"SMproductname", "MacBook4,1" }, + {"SMsystemversion", "1.0" }, + {"SMserial", "W88033AKY51" }, + {"SMfamily", "MacBook" }, + {"SMboardmanufacter", "Apple Inc." }, + {"SMboardproduct", "Mac-F42D89C8" }, + {"SMUUID" , "26A96EAC-CD73-7A49-8B7C-2DA8F466D971"}, + { "","" } +}; +/* + MacBookAir + Board Id: Mac-F42C8CC8 + Model Id: MacBookAir1,1 + Boot ROM Version: MBA11.88Z.00BB.B00.0712201139 + Serial Nr: W881101T12G + W88033AKY51 + SMBIOS Version: 1.0 + SMC Version: 1.3f4 (SMC 1.0) + */ + +// defaults for a MacBook Pro +static const SMStrEntryPair const sm_macbookpro_defaults[]={ + {"SMbiosvendor", "Apple Inc." }, + {"SMbiosversion", "MBP51.88Z.0073.B00.0809221748" }, + {"SMbiosdate", "04/01/2008" }, + {"SMmanufacter", "Apple Inc." }, + {"SMproductname", "MacBookPro5,1" }, + {"SMsystemversion", "1.0" }, + {"SMserial", "W8841NP21G0" }, + {"SMfamily", "MacBookPro" }, + {"SMboardmanufacter", "Apple Inc." }, + {"SMboardproduct", "Mac-F42D89C8" }, + {"SMUUID" , "DCE37B2F-B608-53C2-A314-C248A24A9D06"}, + { "","" } +}; + +// defaults for a Mac mini +static const SMStrEntryPair const sm_macmini_defaults[]={ + {"SMbiosvendor", "Apple Inc." }, + {"SMbiosversion", "MM21.88Z.009A.B00.0706281359" }, + {"SMbiosdate", "04/01/2008" }, + {"SMmanufacter", "Apple Inc." }, + {"SMproductname", "MacMini2,1" }, + {"SMsystemversion", "1.1" }, + {"SMserial", "YM6094QPU36" }, + {"SMfamily", "Napa Mac" }, + {"SMboardmanufacter", "Apple Inc." }, + {"SMboardproduct", "Mac-F4208EAA" }, + {"SMUUID" , "E3314823-659D-42B6-B42C-147E4E3484D4"}, + { "","" } +}; + +// defaults for an iMac +static const SMStrEntryPair const sm_imac_defaults[]={ + {"SMbiosvendor", "Apple Inc." }, + {"SMbiosversion", "IM91.88Z.00C1.B00.0802091538" }, + {"SMbiosdate", "04/01/2008" }, + {"SMmanufacter", "Apple Inc." }, + {"SMproductname", "iMac9,1" }, + {"SMsystemversion", "1.0" }, + {"SMserial", "SOMESRLNMBR" }, + {"SMfamily", "Mac" }, + {"SMboardmanufacter", "Apple Inc." }, + {"SMboardproduct", "Mac-F227BEC8" }, + {"SMUUID" , "862F78AF-9B36-40AF-B67A-ABBA8C14A528"}, + { "","" } +}; + +// defaults for a Mac Pro +static const SMStrEntryPair const sm_macpro_defaults[]={ + {"SMbiosvendor", "Apple Computer, Inc." }, + {"SMbiosversion", "MP31.88Z.006C.B05.0802291410" }, + {"SMbiosdate", "04/01/2008" }, + {"SMmanufacter", "Apple Computer, Inc." }, + {"SMproductname", "MacPro3,1" }, + {"SMsystemversion", "1.0" }, + {"SMserial", "W88033AKY51" }, + {"SMfamily", "MacPro" }, + {"SMboardmanufacter", "Apple Computer, Inc." }, + {"SMboardproduct", "Mac-F4208DC8" }, + {"SMUUID" , "862F78AF-9B36-40AF-B67A-ABBA8C14A528"}, + { "","" } +}; + +// defaults for an iMac11,1 core i3/i5/i7 +static const SMStrEntryPair const sm_imac_core_defaults[]={ + {"SMbiosvendor", "Apple Inc." }, + {"SMbiosversion", "IM111.88Z.0034.B00.0802091538" }, + {"SMbiosdate", "06/01/2009" }, + {"SMmanufacter", "Apple Inc." }, + {"SMproductname", "iMac11,1" }, + {"SMsystemversion", "1.0" }, + {"SMserial", "W87234JHYA4" }, + {"SMfamily", "iMac" }, + {"SMboardmanufacter", "Apple Computer, Inc." }, + {"SMboardproduct", "Mac-F2268DAE" }, + {"SMUUID" , "862F78AF-9B36-40AF-B67A-ABBA8C14A528"}, + { "","" } +}; +#if NEVER_USE_MACPRO41 +// defaults for a Mac Pro 4,1 Xeon +static const SMStrEntryPair const sm_macpro_core_defaults[]={ + {"SMbiosvendor", "Apple Computer, Inc." }, + {"SMbiosversion", "MP41.88Z.0081.B04.0903051113" }, + {"SMbiosdate", "11/06/2009" }, + {"SMmanufacter", "Apple Computer, Inc." }, + {"SMproductname", "MacPro4,1" }, + {"SMsystemversion", "1.0" }, + {"SMserial", "W88033AKY51" }, + {"SMfamily", "MacPro" }, + {"SMboardmanufacter", "Apple Computer, Inc." }, + {"SMboardproduct", "Mac-F221BEC8" }, + {"SMUUID" , "862F78AF-9B36-40AF-B67A-ABBA8C14A528"}, + { "","" } +}; +#endif +static const char* sm_get_defstr(const char * key, int table_num) +{ + int i; + const SMStrEntryPair* sm_defaults; + +// if (platformCPUFeature(CPU_FEATURE_MOBILE)) { + if (Platform->CPU.Mobile) { + if (Platform->CPU.NoCores > 1) { + //TODO if NVidia - MBP else MB + sm_defaults=sm_macbookpro_defaults; + } else { + sm_defaults=sm_macbook_defaults; + } + } else { + switch (Platform->CPU.NoCores) + { + case 1: + sm_defaults=sm_macmini_defaults; + break; + case 2: + sm_defaults=sm_imac_defaults; + break; + default: + { + switch (Platform->CPU.Family) + { + case 0x06: + { + switch (Platform->CPU.Model) + { + case CPU_MODEL_FIELDS: // Intel Core i5, i7 LGA1156 (45nm) + case CPU_MODEL_DALES: // Intel Core i5, i7 LGA1156 (45nm) ??? + case CPU_MODEL_DALES_32NM: // Intel Core i3, i5, i7 LGA1156 (32nm) (Clarkdale, Arrandale) + case 0x19: // Intel Core i5 650 @3.20 Ghz + // sm_defaults=sm_imac_defaults; + // break; + case CPU_MODEL_NEHALEM: + case CPU_MODEL_NEHALEM_EX: + case CPU_MODEL_WESTMERE: + case CPU_MODEL_WESTMERE_EX: + sm_defaults=sm_imac_core_defaults; + break; + default: + sm_defaults=sm_imac_core_defaults; + break; + } + break; + } + default: + sm_defaults=sm_macpro_defaults; + break; + } + break; + } + } + } + + for (i=0; sm_defaults[i].key[0]; i++) { + if (!strcmp (sm_defaults[i].key, key)) { + return sm_defaults[i].value; + } + } + + // Shouldn't happen + printf ("Error: no default for '%s' known\n", key); + sleep (2); + return ""; +} + +static int sm_get_fsb(const char *name, int table_num) +{ + return Platform->CPU.FSBFrequency/1000000; +} + +static int sm_get_cpu (const char *name, int table_num) +{ + return Platform->CPU.CPUFrequency/1000000; +} + +static int sm_get_bus_speed (const char *name, int table_num) +{ + if (Platform->CPU.Vendor == 0x756E6547) // Intel + { + switch (Platform->CPU.Family) + { + case 0x06: + { + switch (Platform->CPU.Model) + { + case CPU_MODEL_PENTIUM_M: // Pentium M 0x0D + case CPU_MODEL_YONAH: // Yonah 0x0E + case CPU_MODEL_MEROM: // Merom 0x0F + case CPU_MODEL_PENRYN: // Penryn 0x17 + case CPU_MODEL_ATOM: // Atom 45nm 0x1C + return 0; // TODO: populate bus speed for these processors + +// case CPU_MODEL_FIELDS: // Intel Core i5, i7 LGA1156 (45nm) +// if (strstr(Platform->CPU.BrandString, "Core(TM) i5")) +// return 2500; // Core i5 +// return 4800; // Core i7 + +// case CPU_MODEL_NEHALEM: // Intel Core i7 LGA1366 (45nm) +// case CPU_MODEL_NEHALEM_EX: +// case CPU_MODEL_DALES: // Intel Core i5, i7 LGA1156 (45nm) ??? +// return 4800; // GT/s / 1000 +// + case CPU_MODEL_WESTMERE_EX: // Intel Core i7 LGA1366 (45nm) 6 Core ??? + return 0; // TODO: populate bus speed for these processors + +// case 0x19: // Intel Core i5 650 @3.20 Ghz +// return 2500; // why? Intel spec says 2.5GT/s + + case 0x19: // Intel Core i5 650 @3.20 Ghz + case CPU_MODEL_NEHALEM: // Intel Core i7 LGA1366 (45nm) + case CPU_MODEL_FIELDS: // Intel Core i5, i7 LGA1156 (45nm) + case CPU_MODEL_DALES: // Intel Core i5, i7 LGA1156 (45nm) ??? + case CPU_MODEL_DALES_32NM: // Intel Core i3, i5, i7 LGA1156 (32nm) + case CPU_MODEL_WESTMERE: // Intel Core i7 LGA1366 (32nm) 6 Core + case CPU_MODEL_NEHALEM_EX: // Intel Core i7 LGA1366 (45nm) 6 Core ??? + { // thanks to dgobe for i3/i5/i7 bus speed detection + int nhm_bus = 0x3F; + static long possible_nhm_bus[] = {0xFF, 0x7F, 0x3F}; + unsigned long did, vid; + int i; + + // Nehalem supports Scrubbing + // First, locate the PCI bus where the MCH is located + for(i = 0; i < sizeof(possible_nhm_bus); i++) + { + vid = pci_config_read16(PCIADDR(possible_nhm_bus[i], 3, 4), 0x00); + did = pci_config_read16(PCIADDR(possible_nhm_bus[i], 3, 4), 0x02); + vid &= 0xFFFF; + did &= 0xFF00; + + if(vid == 0x8086 && did >= 0x2C00) + nhm_bus = possible_nhm_bus[i]; + } + + unsigned long qpimult, qpibusspeed; + qpimult = pci_config_read32(PCIADDR(nhm_bus, 2, 1), 0x50); + qpimult &= 0x7F; + DBG("qpimult %d\n", qpimult); + qpibusspeed = (qpimult * 2 * (Platform->CPU.FSBFrequency/1000000)); + // Rek: rounding decimals to match original mac profile info + if (qpibusspeed%100 != 0)qpibusspeed = ((qpibusspeed+50)/100)*100; + DBG("qpibusspeed %d\n", qpibusspeed); + return qpibusspeed; + } + } + } + } + } + return 0; +} + +static int sm_get_simplecputype() +{ + if (Platform->CPU.NoCores >= 4) + { + return 0x0501; // Quad-Core Xeon + } + else if (Platform->CPU.NoCores == 1) + { + return 0x0201; // Core Solo + }; + + return 0x0301; // Core 2 Duo +} + +static int sm_get_cputype (const char *name, int table_num) +{ + static bool done = false; + + if (Platform->CPU.Vendor == 0x756E6547) // Intel + { + if (!done) { + verbose("CPU is %s, family 0x%x, model 0x%x\n", Platform->CPU.BrandString, Platform->CPU.Family, Platform->CPU.Model); + done = true; + } + + switch (Platform->CPU.Family) + { + case 0x06: + { + switch (Platform->CPU.Model) + { + case CPU_MODEL_PENTIUM_M: // Pentium M = 0x0D + return 0x0101; + case CPU_MODEL_YONAH: // Yonah + case CPU_MODEL_MEROM: // Merom + case CPU_MODEL_PENRYN: // Penryn + case CPU_MODEL_ATOM: // Intel Atom (45nm) + return sm_get_simplecputype(); + + case CPU_MODEL_NEHALEM: // Intel Core i7 LGA1366 (45nm) + return 0x0701; // Core i7 + + case CPU_MODEL_FIELDS: // Lynnfield, Clarksfield, Jasper + if (strstr(Platform->CPU.BrandString, "Core(TM) i5")) + return 0x601; // Core i5 + return 0x701; // Core i7 + + case CPU_MODEL_DALES: // Intel Core i5, i7 LGA1156 (45nm) (Havendale, Auburndale) + if (strstr(Platform->CPU.BrandString, "Core(TM) i5")) + return 0x601; // Core i5 + return 0x0701; // Core i7 + + case CPU_MODEL_DALES_32NM: // Intel Core i3, i5, i7 LGA1156 (32nm) (Clarkdale, Arrandale) + if (strstr(Platform->CPU.BrandString, "Core(TM) i3")) + return 0x901; // Core i3 + if (strstr(Platform->CPU.BrandString, "Core(TM) i5")) + return 0x601; // Core i5 + return 0x0701; // Core i7 + + case CPU_MODEL_WESTMERE: // Intel Core i7 LGA1366 (32nm) 6 Core (Gulftown, Westmere-EP, Westmere-WS) + case CPU_MODEL_WESTMERE_EX: // Intel Core i7 LGA1366 (45nm) 6 Core ??? + return 0x0701; // Core i7 + + case 0x19: // Intel Core i5 650 @3.20 Ghz + return 0x601; // Core i5 + } + } + } + } + + return sm_get_simplecputype(); +} + +static int sm_get_memtype (const char *name, int table_num) +{ + int map; + + if (table_num < MAX_RAM_SLOTS) { + map = Platform->DMI.DIMM[table_num]; + if (Platform->RAM.DIMM[map].InUse && Platform->RAM.DIMM[map].Type != 0) { + DBG("RAM Detected Type = %d\n", Platform->RAM.DIMM[map].Type); + return Platform->RAM.DIMM[map].Type; + } + } + + return SMB_MEM_TYPE_DDR2; +} + +static int sm_get_memspeed (const char *name, int table_num) +{ + int map; + + if (table_num < MAX_RAM_SLOTS) { + map = Platform->DMI.DIMM[table_num]; + if (Platform->RAM.DIMM[map].InUse && Platform->RAM.DIMM[map].Frequency != 0) { + DBG("RAM Detected Freq = %d Mhz\n", Platform->RAM.DIMM[map].Frequency); + return Platform->RAM.DIMM[map].Frequency; + } + } + + return 800; +} + +static const char *sm_get_memvendor (const char *name, int table_num) +{ + int map; + + if (table_num < MAX_RAM_SLOTS) { + map = Platform->DMI.DIMM[table_num]; + if (Platform->RAM.DIMM[map].InUse && strlen(Platform->RAM.DIMM[map].Vendor) > 0) { + DBG("RAM Detected Vendor[%d]='%s'\n", table_num, Platform->RAM.DIMM[map].Vendor); + return Platform->RAM.DIMM[map].Vendor; + } + } + return "N/A"; +} + +static const char *sm_get_memserial (const char *name, int table_num) +{ + int map; + + if (table_num < MAX_RAM_SLOTS) { + map = Platform->DMI.DIMM[table_num]; + if (Platform->RAM.DIMM[map].InUse && strlen(Platform->RAM.DIMM[map].SerialNo) > 0) { + DBG("name = %s, map=%d, RAM Detected SerialNo[%d]='%s'\n", name ? name : "", + map, table_num, Platform->RAM.DIMM[map].SerialNo); + return Platform->RAM.DIMM[map].SerialNo; + } + } + return "N/A"; +} + +static const char *sm_get_mempartno (const char *name, int table_num) +{ + int map; + + if (table_num < MAX_RAM_SLOTS) { + map = Platform->DMI.DIMM[table_num]; + if (Platform->RAM.DIMM[map].InUse && strlen(Platform->RAM.DIMM[map].PartNo) > 0) { + DBG("Ram Detected PartNo[%d]='%s'\n", table_num, Platform->RAM.DIMM[map].PartNo); + return Platform->RAM.DIMM[map].PartNo; + } + } + return "N/A"; +} + +static int sm_one (int tablen) +{ + return 1; +} + +struct smbios_property smbios_properties[]= +{ + {.name="SMbiosvendor", .table_type= 0, .value_type=SMSTRING, .offset=0x04, .auto_str=sm_get_defstr }, + {.name="SMbiosversion", .table_type= 0, .value_type=SMSTRING, .offset=0x05, .auto_str=sm_get_defstr }, + {.name="SMbiosdate", .table_type= 0, .value_type=SMSTRING, .offset=0x08, .auto_str=sm_get_defstr }, + {.name="SMmanufacter", .table_type= 1, .value_type=SMSTRING, .offset=0x04, .auto_str=sm_get_defstr }, + {.name="SMproductname", .table_type= 1, .value_type=SMSTRING, .offset=0x05, .auto_str=sm_get_defstr }, + {.name="SMsystemversion", .table_type= 1, .value_type=SMSTRING, .offset=0x06, .auto_str=sm_get_defstr }, + {.name="SMserial", .table_type= 1, .value_type=SMSTRING, .offset=0x07, .auto_str=sm_get_defstr }, + {.name="SMUUID", .table_type= 1, .value_type=SMOWORD, .offset=0x08, .auto_oword=sm_get_defstr}, + {.name="SMfamily", .table_type= 1, .value_type=SMSTRING, .offset=0x1a, .auto_str=sm_get_defstr }, + {.name="SMboardmanufacter", .table_type= 2, .value_type=SMSTRING, .offset=0x04, .auto_str=sm_get_defstr }, + {.name="SMboardproduct", .table_type= 2, .value_type=SMSTRING, .offset=0x05, .auto_str=sm_get_defstr }, + {.name="SMexternalclock", .table_type= 4, .value_type=SMWORD, .offset=0x12, .auto_int=sm_get_fsb }, + {.name="SMmaximalclock", .table_type= 4, .value_type=SMWORD, .offset=0x14, .auto_int=sm_get_cpu }, + {.name="SMmemdevloc", .table_type=17, .value_type=SMSTRING, .offset=0x10, .auto_str=0 }, + {.name="SMmembankloc", .table_type=17, .value_type=SMSTRING, .offset=0x11, .auto_str=0 }, + {.name="SMmemtype", .table_type=17, .value_type=SMBYTE, .offset=0x12, .auto_int=sm_get_memtype}, + {.name="SMmemspeed", .table_type=17, .value_type=SMWORD, .offset=0x15, .auto_int=sm_get_memspeed}, + {.name="SMmemmanufacter", .table_type=17, .value_type=SMSTRING, .offset=0x17, .auto_str=sm_get_memvendor}, + {.name="SMmemserial", .table_type=17, .value_type=SMSTRING, .offset=0x18, .auto_str=sm_get_memserial}, + {.name="SMmempart", .table_type=17, .value_type=SMSTRING, .offset=0x1A, .auto_str=sm_get_mempartno}, + {.name="SMcputype", .table_type=131,.value_type=SMWORD, .offset=0x04, .auto_int=sm_get_cputype}, + {.name="SMbusspeed", .table_type=132,.value_type=SMWORD, .offset=0x04, .auto_int=sm_get_bus_speed} +}; + +struct smbios_table_description smbios_table_descriptions[]= +{ + {.type=kSMBTypeBIOSInformation, .len=0x18, .numfunc=sm_one}, + {.type=kSMBTypeSystemInformation, .len=0x1b, .numfunc=sm_one}, + {.type=kSMBTypeBaseBoard, .len=0x0f, .numfunc=sm_one}, //except kSMBBaseBoardProcessorMemoryModule + {.type=kSMBTypeProcessorInformation, .len=0x2a, .numfunc=sm_one}, +//kSMBTypeMemoryModule len=12 obsolete but Used by AppleSMBIOS +//kSMBTypeSystemSlot len=13 Used by AppleSMBIOS +//kSMBTypePhysicalMemoryArray len=15 Used by AppleSMBIOS + {.type=kSMBTypeMemoryDevice, .len=0x24, .numfunc=0}, +//Slice - we are not ready to fill the data +// {.type=kSMBTypeFirmwareVolume, .len=0x56, .numfunc=0}, +// {.type=kSMBTypeMemorySPD, .len=0x0c, .numfunc=0}, + {.type=kSMBTypeOemProcessorType, .len=0x06, .numfunc=sm_one}, + {.type=kSMBTypeOemProcessorBusSpeed, .len=0x06, .numfunc=sm_one} +}; +/* Apple known types + enum { + kSMBTypeBIOSInformation = 0, + kSMBTypeSystemInformation = 1, + kSMBTypeBaseBoard = 2, + kSMBTypeSystemEnclosure = 3, + kSMBTypeProcessorInformation = 4, + kSMBTypeMemoryModule = 6, + kSMBTypeCacheInformation = 7, + kSMBTypeSystemSlot = 9, + kSMBTypePhysicalMemoryArray = 16, + kSMBTypeMemoryDevice = 17, + kSMBType32BitMemoryErrorInfo = 18, + kSMBType64BitMemoryErrorInfo = 33, + + // Apple Specific Structures +kSMBTypeFirmwareVolume = 128, +kSMBTypeMemorySPD = 130, +kSMBTypeOemProcessorType = 131, +kSMBTypeOemProcessorBusSpeed = 132 +}; + + */ + +// getting smbios addr with fast compare ops, late checksum testing ... +#define COMPARE_DWORD(a,b) ( *((u_int32_t *) a) == *((u_int32_t *) b) ) +static const char * const SMTAG = "_SM_"; +static const char* const DMITAG= "_DMI_"; + +static struct SMBEntryPoint *getAddressOfSmbiosTable(void) +{ + struct SMBEntryPoint *smbios; + /* + * The logic is to start at 0xf0000 and end at 0xfffff iterating 16 bytes at a time looking + * for the SMBIOS entry-point structure anchor (literal ASCII "_SM_"). + */ + smbios = (struct SMBEntryPoint*) SMBIOS_RANGE_START; + while (smbios <= (struct SMBEntryPoint *)SMBIOS_RANGE_END) { + if (COMPARE_DWORD(smbios->anchor, SMTAG) && + COMPARE_DWORD(smbios->dmi.anchor, DMITAG) && + smbios->dmi.anchor[4]==DMITAG[4] && + checksum8(smbios, sizeof(struct SMBEntryPoint)) == 0) + { + return smbios; + } + smbios = (struct SMBEntryPoint*) ( ((char*) smbios) + 16 ); + } + printf("ERROR: Unable to find SMBIOS!\n"); + pause(); + return NULL; +} + +/** Compute necessary space requirements for new smbios */ +static struct SMBEntryPoint *smbios_dry_run(struct SMBEntryPoint *origsmbios) +{ + struct SMBEntryPoint *ret; + char *smbiostables; + char *tablesptr; + int origsmbiosnum; + int i, j; + int tablespresent[256]; + bool do_auto=true; + + bzero(tablespresent, sizeof(tablespresent)); + + getBoolForKey(kSMBIOSdefaults, &do_auto, &bootInfo->bootConfig); + + ret = (struct SMBEntryPoint *)AllocateKernelMemory(sizeof(struct SMBEntryPoint)); + if (origsmbios) { + smbiostables = (char *)origsmbios->dmi.tableAddress; + origsmbiosnum = origsmbios->dmi.structureCount; + } else { + smbiostables = NULL; + origsmbiosnum = 0; + } + + // _SM_ + ret->anchor[0] = 0x5f; + ret->anchor[1] = 0x53; + ret->anchor[2] = 0x4d; + ret->anchor[3] = 0x5f; + ret->entryPointLength = sizeof(*ret); + ret->majorVersion = 2; + ret->minorVersion = 1; + ret->maxStructureSize = 0; // will be calculated later in this function + ret->entryPointRevision = 0; + for (i=0;i<5;i++) { + ret->formattedArea[i] = 0; + } + //_DMI_ + ret->dmi.anchor[0] = 0x5f; + ret->dmi.anchor[1] = 0x44; + ret->dmi.anchor[2] = 0x4d; + ret->dmi.anchor[3] = 0x49; + ret->dmi.anchor[4] = 0x5f; + ret->dmi.tableLength = 0; // will be calculated later in this function + ret->dmi.tableAddress = 0; // will be initialized in smbios_real_run() + ret->dmi.structureCount = 0; // will be calculated later in this function + ret->dmi.bcdRevision = 0x21; + tablesptr = smbiostables; + + // add stringlen of overrides to original stringlen, update maxStructure size adequately, + // update structure count and tablepresent[type] with count of type. + if (smbiostables) { + for (i=0; ilength; + stringsptr = tablesptr; + for (; tablesptr[0]!=0 || tablesptr[1]!=0; tablesptr++); + tablesptr += 2; + stringlen = tablesptr - stringsptr - 1; + if (stringlen == 1) { + stringlen = 0; + } + for (j=0; jtype] + 1); + if (smbios_properties[j].table_type == cur->type && + smbios_properties[j].value_type == SMSTRING && + (getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig) || + getValueForKey(altname,&str, &size, &bootInfo->smbiosConfig))) + { + stringlen += size + 1; + } else if (smbios_properties[j].table_type == cur->type && + smbios_properties[j].value_type == SMSTRING && + do_auto && smbios_properties[j].auto_str) + { + stringlen += strlen(smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[cur->type])) + 1; + } + } + if (stringlen == 0) { + stringlen = 1; + } + stringlen++; + if (ret->maxStructureSize < cur->length+stringlen) { + ret->maxStructureSize=cur->length+stringlen; + } + ret->dmi.tableLength += cur->length+stringlen; + ret->dmi.structureCount++; + tablespresent[cur->type]++; + } + } + // Add eventually table types whose detected count would be < required count, and update ret header with: + // new stringlen addons, structure count, and tablepresent[type] count adequately + for (i=0; ismbiosConfig)) { + numnec = -1; + } + if (numnec==-1 && do_auto && smbios_table_descriptions[i].numfunc) { + numnec = smbios_table_descriptions[i].numfunc(smbios_table_descriptions[i].type); + } + while (tablespresent[smbios_table_descriptions[i].type] < numnec) { + int stringlen = 0; + for (j=0; jsmbiosConfig) || + getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig))) + { + stringlen += size + 1; + } else if (smbios_properties[j].table_type == smbios_table_descriptions[i].type && + smbios_properties[j].value_type==SMSTRING && + do_auto && smbios_properties[j].auto_str) + { + stringlen += strlen(smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[smbios_table_descriptions[i].type])) + 1; + } + } + if (stringlen == 0) { + stringlen = 1; + } + stringlen++; + if (ret->maxStructureSize < smbios_table_descriptions[i].len+stringlen) { + ret->maxStructureSize = smbios_table_descriptions[i].len + stringlen; + } + ret->dmi.tableLength += smbios_table_descriptions[i].len + stringlen; + ret->dmi.structureCount++; + tablespresent[smbios_table_descriptions[i].type]++; + } + } + return ret; +} + +/** From the origsmbios detected by getAddressOfSmbiosTable() to newsmbios whose entrypoint + * struct has been created by smbios_dry_run, update each table struct content of new smbios + * int the new allocated table address of size newsmbios->tablelength. + */ +static void smbios_real_run(struct SMBEntryPoint * origsmbios, struct SMBEntryPoint * newsmbios) +{ + char *smbiostables; + char *tablesptr, *newtablesptr; + int origsmbiosnum=0; + // bitmask of used handles + uint8_t handles[8192]; + uint16_t nexthandle=0; + int i, j; + int tablespresent[256]; + bool do_auto=true; + + static bool done = false; // IMPROVEME: called twice via getSmbios(), but only the second call can get all necessary info ! + + extern void dumpPhysAddr(const char * title, void * a, int len); + + bzero(tablespresent, sizeof(tablespresent)); + bzero(handles, sizeof(handles)); + + getBoolForKey(kSMBIOSdefaults, &do_auto, &bootInfo->bootConfig); + + newsmbios->dmi.tableAddress = (uint32_t)AllocateKernelMemory(newsmbios->dmi.tableLength); + if (origsmbios) { + smbiostables = (char *)origsmbios->dmi.tableAddress; + origsmbiosnum = origsmbios->dmi.structureCount; + } else { + smbiostables = NULL; + origsmbiosnum = 0; + } + tablesptr = smbiostables; + newtablesptr = (char *)newsmbios->dmi.tableAddress; + + // if old smbios exists then update new smbios with old smbios original content first + if (smbiostables) { + for (i=0; ihandle) / 8] |= 1 << ((oldcur->handle) % 8); + + // copy table length from old table to new table but not the old strings + memcpy(newcur,oldcur, oldcur->length); + + tablesptr += oldcur->length; + stringsptr = tablesptr; + newtablesptr += oldcur->length; + + // calculate the number of strings in the old content + for (;tablesptr[0]!=0 || tablesptr[1]!=0; tablesptr++) { + if (tablesptr[0] == 0) { + nstrings++; + } + } + if (tablesptr != stringsptr) { + nstrings++; + } + tablesptr += 2; + + // copy the old strings to new table + memcpy(newtablesptr, stringsptr, tablesptr-stringsptr); + + // point to next possible space for a string (deducting the second 0 char at the end) + newtablesptr += tablesptr - stringsptr - 1; + if (nstrings == 0) { // if no string was found rewind to the first 0 char of the 0,0 terminator + newtablesptr--; + } + + // now for each property in the table update the overrides if any (auto or user) + for (j=0; jtype] + 1); + if (smbios_properties[j].table_type == newcur->type) { + switch (smbios_properties[j].value_type) { + case SMSTRING: + if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) || + getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig)) + { + memcpy(newtablesptr, str, size); + newtablesptr[size] = 0; + newtablesptr += size + 1; + *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings; + } else if (do_auto && smbios_properties[j].auto_str) { + str = smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[newcur->type]); + size = strlen(str); + memcpy(newtablesptr, str, size); + newtablesptr[size] = 0; + newtablesptr += size + 1; + *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings; + } + break; + + case SMOWORD: + if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) || + getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig)) + { + //int k=0, t=0, kk=0; + //const char *ptr = str; + verbose("Set SMUUID to %s\n", str); + //memset(((char*)newcur) + smbios_properties[j].offset, 0, 16); + EFI_GUID* p = getUUIDFromString(str); + memcpy(((char*)newcur) + smbios_properties[j].offset, p, 16); + /* + while (ptr-str=2 && ptr[0]=='0' && (ptr[1]=='x' || ptr[1]=='X')) { + ptr += 2; + } + for (;ptr-str='0' && *ptr<='9') { + (t=(t<<4)|(*ptr-'0')),kk++; + } + if (*ptr>='a' && *ptr<='f') { + (t=(t<<4)|(*ptr-'a'+10)),kk++; + } + if (*ptr>='A' && *ptr<='F') { + (t=(t<<4)|(*ptr-'A'+10)),kk++; + } + if (kk == 2) { + *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset + k)) = t; + k++; + kk = 0; + t = 0; + } + } + */ + } + break; + + case SMBYTE: + if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) || + getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig)) + { + *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = num; + } else if (do_auto && smbios_properties[j].auto_int) { + *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]); + } + break; + + case SMWORD: + if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) || + getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig)) + { + *((uint16_t*)(((char*)newcur) + smbios_properties[j].offset)) = num; + } else if (do_auto && smbios_properties[j].auto_int) { + *((uint16_t*)(((char*)newcur) + smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]); + } + break; + } + } + } + if (nstrings == 0) { + newtablesptr[0] = 0; + newtablesptr++; + } + newtablesptr[0] = 0; + newtablesptr++; + tablespresent[newcur->type]++; + } + } + + // for each eventual complementary table not present in the original smbios, do the overrides + for (i=0; ismbiosConfig)) { + numnec = -1; + } + if (numnec == -1 && do_auto && smbios_table_descriptions[i].numfunc) { + numnec = smbios_table_descriptions[i].numfunc(smbios_table_descriptions[i].type); + } + while (tablespresent[smbios_table_descriptions[i].type] < numnec) { + struct smbios_table_header *newcur = (struct smbios_table_header *) newtablesptr; + int nstrings = 0; + + memset(newcur,0, smbios_table_descriptions[i].len); + while (handles[(nexthandle)/8] & (1 << ((nexthandle) % 8))) { + nexthandle++; + } + newcur->handle = nexthandle; + handles[nexthandle / 8] |= 1 << (nexthandle % 8); + newcur->type = smbios_table_descriptions[i].type; + newcur->length = smbios_table_descriptions[i].len; + newtablesptr += smbios_table_descriptions[i].len; + for (j=0; jtype] + 1); + if (smbios_properties[j].table_type == newcur->type) { + switch (smbios_properties[j].value_type) { + case SMSTRING: + if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) || + getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig)) + { + memcpy(newtablesptr, str, size); + newtablesptr[size] = 0; + newtablesptr += size + 1; + *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings; + } else if (do_auto && smbios_properties[j].auto_str) { + str = smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[newcur->type]); + size = strlen(str); + memcpy(newtablesptr, str, size); + newtablesptr[size] = 0; + newtablesptr += size + 1; + *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings; + } + break; + + case SMOWORD: + if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) || + getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig)) + { + EFI_GUID* p = getUUIDFromString(str); + memcpy(((char*)newcur) + smbios_properties[j].offset, p, 16); +/* + int k=0, t=0, kk=0; + const char *ptr = str; + verbose("Set SMUUID to %s\n", str); + + memset(((char*)newcur) + smbios_properties[j].offset, 0, 16); + while (ptr-str=2 && ptr[0]=='0' && (ptr[1]=='x' || ptr[1]=='X')) { + ptr += 2; + } + for (;ptr-str='0' && *ptr<='9') { + (t=(t<<4)|(*ptr-'0')),kk++; + } + if (*ptr>='a' && *ptr<='f') { + (t=(t<<4)|(*ptr-'a'+10)),kk++; + } + if (*ptr>='A' && *ptr<='F') { + (t=(t<<4)|(*ptr-'A'+10)),kk++; + } + if (kk == 2) { + *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset + k)) = t; + k++; + kk = 0; + t = 0; + } + } + */ + } + break; + + case SMBYTE: + if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) || + getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig)) + { + *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = num; + } else if (do_auto && smbios_properties[j].auto_int) { + *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]); + } + break; + + case SMWORD: + if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) || + getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig)) + { + *((uint16_t*)(((char*)newcur) + smbios_properties[j].offset)) = num; + } else if (do_auto && smbios_properties[j].auto_int) { + *((uint16_t*)(((char*)newcur)+smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]); + } + break; + } + } + } + if (nstrings == 0) { + newtablesptr[0] = 0; + newtablesptr++; + } + newtablesptr[0] = 0; + newtablesptr++; + tablespresent[smbios_table_descriptions[i].type]++; + } + } + + // calculate new checksums + newsmbios->dmi.checksum = 0; + newsmbios->dmi.checksum = 256 - checksum8(&newsmbios->dmi, sizeof(newsmbios->dmi)); + newsmbios->checksum = 0; + newsmbios->checksum = 256 - checksum8(newsmbios, sizeof(*newsmbios)); + + if (!done) { + verbose("Patched DMI Table\n"); + done=true; + } +} + +#define MAX_DMI_TABLES 96 +typedef struct DmiNumAssocTag { + struct DMIHeader * dmi; + uint8_t type; +} DmiNumAssoc; + +static DmiNumAssoc DmiTablePair[MAX_DMI_TABLES]; +static int DmiTablePairCount = 0; +static int current_pos=0; +static bool ftTablePairInit = true; //use twice first run and after + +/** + * Get a table structure entry from a type specification and a smbios address + * return NULL if table is not found + */ +static void getSmbiosTableStructure(struct SMBEntryPoint *smbios) +{ + struct DMIHeader * dmihdr=NULL; + SMBByte* p; + int i; + + if (ftTablePairInit && smbios!=NULL) { + ftTablePairInit = false; +#if DEBUG_SMBIOS + verbose(">>> SMBIOSAddr=0x%08x\n", smbios); + verbose(">>> DMI: addr=0x%08x, len=%d, count=%d\n", smbios->dmi.tableAddress, + smbios->dmi.tableLength, smbios->dmi.structureCount); +#endif + p = (SMBByte *) smbios->dmi.tableAddress; + for (i=0; + i < smbios->dmi.structureCount && + p + 4 <= (SMBByte *)smbios->dmi.tableAddress + smbios->dmi.tableLength; + i++) { + dmihdr = (struct DMIHeader *) p; + +#if DEBUG_SMBIOS + // verbose(">>>>>> DMI(%d): type=0x%02x, len=0x%d\n",i,dmihdr->type,dmihdr->length); +#endif + if (dmihdr->length < 4 || dmihdr->type == 127 /* EOT */) break; + if (DmiTablePairCount < MAX_DMI_TABLES) { + DmiTablePair[DmiTablePairCount].dmi = dmihdr; + DmiTablePair[DmiTablePairCount].type = dmihdr->type; + DmiTablePairCount++; + } + else { + verbose("DMI table entries list is full! Next entries won't be stored.\n"); + } +#if DEBUG_SMBIOS + verbose("DMI header found for table type %d, length = %d\n", dmihdr->type, dmihdr->length); +#endif + p = p + dmihdr->length; + while ((p - (SMBByte *)smbios->dmi.tableAddress + 1 < smbios->dmi.tableLength) && (p[0] != 0x00 || p[1] != 0x00)) { + p++; + } + p += 2; + } + + } +} + +void getSmbiosMacModel(void) +{ +#define MAX_MODEL_LEN 32 + + //Slice - I want to use MacModel for ACPITables so I need char* representation + const char *value = getStringForKey("SMproductname", &bootInfo->smbiosConfig); + int i, n=0, first=0, rev1=0, rev2=0; + for (i=0; i<8; i++) + { + char c = value[i]; + if (isalpha(c)) + { + MacModel[i]=c; + n++; + } else + if ((c) >= '0' && (c) <= '9') + { + if (first) + { + rev1 = rev1 * 10 + (int)(c) & 0xf; + } else + rev2 = rev2 * 10 + (int)(c) & 0xf; + } else + first = 1; + // printf("char=%c first=%d rev1=%d rev2=%d\n", c, first, rev1, rev2); + } + for (i=n; i<8; i++) { + MacModel[i] = 0x20; + } + ModelRev = (rev2 << 16) + rev1; +// ModelLength = (len + 1) * 2; +// printf("Model=%s %08x\n", MacModel, ModelRev); +// getc(); + +} + + static struct SMBEntryPoint *orig = NULL; // cached + static struct SMBEntryPoint *patched = NULL; // cached + +/** Get original or new smbios entry point, if successful, the addresses are cached for next time */ +struct SMBEntryPoint *getSmbios(int which) +{ + + // whatever we are called with orig or new flag, initialize asap both structures + switch (which) { + case SMBIOS_ORIGINAL: + if (orig==NULL) { + orig = getAddressOfSmbiosTable(); + getSmbiosTableStructure(orig); // generate tables entry list for fast table finding + } + return orig; + case SMBIOS_PATCHED: + if (orig==NULL && (orig = getAddressOfSmbiosTable())==NULL ) { + verbose("Could not find original SMBIOS !!\n"); + pause(); + } else { + patched = smbios_dry_run(orig); + if(patched==NULL) { + verbose("Could not create new SMBIOS !!\n"); + pause(); + } + else { + smbios_real_run(orig, patched); + } + } + getSmbiosMacModel(); //Dunno if it is a right place to do that + return patched; + default: + verbose("ERROR: invalid option for getSmbios() !!\n"); + break; + } + + return NULL; +} + +/** Find first original dmi Table with a particular type */ +struct DMIHeader* FindFirstDmiTableOfType(int type, int minlength) +{ + current_pos = 0; //static variable + + return FindNextDmiTableOfType(type, minlength); +}; + +/** Find next original dmi Table with a particular type */ +struct DMIHeader* FindNextDmiTableOfType(int type, int minlength) +{ + int i; + + if (ftTablePairInit) getSmbios(SMBIOS_ORIGINAL); + + for (i=current_pos; i < DmiTablePairCount; i++) { + if (type == DmiTablePair[i].type && + DmiTablePair[i].dmi && + DmiTablePair[i].dmi->length >= minlength ) { + current_pos = i+1; + return DmiTablePair[i].dmi; + } + } + return NULL; // not found +}; + +#if 1 //NOTUSED //Slice -- it is used? +const char * smbiosStringAtIndex(DMIHeader* smHeader, int index, int* length ) +{ + const char * last = 0; + const char * next = (const char *) smHeader + smHeader->length; + + if ( length ) *length = 0; + while ( index-- ) + { + last = 0; + const char * cp = 0; + for ( cp = next; *cp || cp[1]; cp++ ) + { + if ( *cp == '\0' ) + { + last = next; + next = cp + 1; + break; + } + } + if ( last == 0 ) break; + } + + if ( last ) + { + while (*last == ' ') last++; + if (length) + { + UInt8 len; + for ( len = next - last - 1; len && last[len - 1] == ' '; len-- ) + ; + *length = len; // number of chars not counting the terminating NULL + } + } + + return last ? last : ""; +} + + +void getSmbiosProductName() +{ +// struct SMBEntryPoint *smbios; + DMISystemInformation *p; + char* tempString; + int tmpLen; + +// smbios = getSmbios(SMBIOS_ORIGINAL); +// if (smbios==NULL) return 0; + + p = (DMISystemInformation*) FindFirstDmiTableOfType(1, 0x19); // Type 1: (3.3.2) System Information + if (p==NULL) return; // NULL; + + + tempString = (char*)smbiosStringAtIndex((DMIHeader*)p, p->productName, &tmpLen); + tempString[tmpLen] = 0; + + gSMBIOSBoardModel = malloc(tmpLen + 1); + if(gSMBIOSBoardModel) + { + strncpy(gSMBIOSBoardModel, tempString, tmpLen); + Node* node = DT__FindNode("/", false); + DT__AddProperty(node, "orig-model", tmpLen, gSMBIOSBoardModel); + } + verbose("Actual model name is '%s'\n", tempString); +} +#endif + +//Slice +//#define MEGA 1000000LL - now in mem.h +void scan_cpu_DMI(void) //PlatformInfo_t *p) +{ + // int i=0; + int maxClock = 0; + struct DMIHeader * dmihdr = NULL; + struct DMIProcessorInformation* cpuInfo; // Type 4 + + for (dmihdr = FindFirstDmiTableOfType(4, 30); dmihdr; dmihdr = FindNextDmiTableOfType(4, 30)) + { + cpuInfo = (struct DMIProcessorInformation*)dmihdr; + if (cpuInfo->processorType != 3) { // CPU + continue; + } + //TODO validate +#if 1 //NOTYET + msglog("Platform CPU Info:\n FSB=%d\n MaxSpeed=%d\n CurrentSpeed=%d\n", Platform->CPU.FSBFrequency/MEGA, Platform->CPU.TSCFrequency/MEGA, Platform->CPU.CPUFrequency/MEGA); + + if ((cpuInfo->externalClock) && (cpuInfo->externalClock < 400)) { //<400MHz + Platform->CPU.FSBFrequency = (cpuInfo->externalClock) * MEGA; + } + maxClock = cpuInfo->maximumClock; + if (cpuInfo->maximumClock < cpuInfo->currentClock) { + maxClock = cpuInfo->currentClock; + } + if ((maxClock) && (maxClock < 10000)) { //<10GHz + Platform->CPU.TSCFrequency = maxClock * MEGA; + } + if ((cpuInfo->currentClock) && (cpuInfo->currentClock < 10000)) { //<10GHz + Platform->CPU.CPUFrequency = cpuInfo->currentClock * MEGA; + } +#endif + msglog("DMI CPU Info:\n FSB=%d\n MaxSpeed=%d\n CurrentSpeed=%d\n", cpuInfo->externalClock, cpuInfo->maximumClock, cpuInfo->currentClock); + msglog("DMI CPU Info 2:\n Family=%x\n Socket=%x\n Cores=%d Enabled=%d Threads=%d\n", cpuInfo->processorFamily, cpuInfo->processorUpgrade, cpuInfo->coreCount, cpuInfo->coreEnabled, cpuInfo->Threads); +#if 1 //NOTYET + if ((cpuInfo->coreCount) && (cpuInfo->coreCountCPU.NoCores)) { + if (cpuInfo->coreEnabled < cpuInfo->coreCount) { + cpuInfo->coreCount = cpuInfo->coreEnabled; + } + Platform->CPU.NoCores = cpuInfo->coreCount; + } + if ((cpuInfo->Threads) && (cpuInfo->ThreadsCPU.NoThreads)) { + Platform->CPU.NoThreads = cpuInfo->Threads; + } +#endif + + return; + } + + return; +} +//Slice - check other DMI info +bool scanDMI(void) +{ + struct DMIHeader * dmihdr = NULL; + struct DMISystemEnclosure* encInfo; // Type 3 + + for (dmihdr = FindFirstDmiTableOfType(3, 13); dmihdr; dmihdr = FindNextDmiTableOfType(3, 13)) + { + encInfo = (struct DMISystemEnclosure*)dmihdr; + msglog("DMI Chassis Info:\n Type=%x\n Boot-up State=%x\n Power Supply=%x Thermal State=%x\n", encInfo->type, encInfo->bootupState, encInfo->powerSupplyState, encInfo->thermalState); + switch (encInfo->type) { + case 1: + case 2: + return FALSE; + case 3: + case 4: + case 6: + case 7: + Platform->CPU.Mobile = FALSE; + break; + case 8: + case 9: + case 0x0A: + case 0x0B: + case 0x0E: + Platform->CPU.Mobile = TRUE; + break; + + default: + break; + } + return TRUE; + } + return FALSE; +} Index: branches/slice/rev749/libsaio/ufs.h =================================================================== --- branches/slice/rev749/libsaio/ufs.h (revision 0) +++ branches/slice/rev749/libsaio/ufs.h (revision 1169) @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 2.0 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +extern long UFSInitPartition(CICell ih); +extern long UFSLoadFile(CICell ih, char * filePath); +extern long UFSReadFile( CICell ih, char * filePath, void * base, uint64_t offset, uint64_t length ); +extern long UFSGetDirEntry(CICell ih, char * dirPath, long long * dirIndex, + char ** name, long * flags, long * time, + FinderInfo * finderInfo, long * infoValid); +extern void UFSGetDescription(CICell ih, char *str, long strMaxLen); +extern long UFSGetFileBlock(CICell ih, char *str, unsigned long long *firstBlock); +extern long UFSGetUUID(CICell ih, char *uuidStr); +extern void UFSFree(CICell ih); + Index: branches/slice/rev749/libsaio/nbp_cmd.h =================================================================== --- branches/slice/rev749/libsaio/nbp_cmd.h (revision 0) +++ branches/slice/rev749/libsaio/nbp_cmd.h (revision 1169) @@ -0,0 +1,85 @@ +/* + * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 2.0 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef __LIBSAIO_NBP_CMD_H +#define __LIBSAIO_NBP_CMD_H + +#include + +/*========================================================================== + * NBP return status codes. + */ +typedef enum { + nbpStatusSuccess = 0, + nbpStatusFailed, + nbpStatusInvalid, +} nbpStatus_t; + +/*========================================================================== + * NBP commands codes. + */ +typedef enum { + nbpCommandTFTPReadFile = 1, + nbpCommandTFTPGetFileSize, + nbpCommandUnloadBaseCode, +} nbpCommandCode_t; + +/*========================================================================== + * NBP commands. + */ +typedef struct { + UInt32 status; /* return code from NBP */ +} nbpCommandHeader_s; + +typedef struct { + UInt32 status; /* return code from NBP */ + UInt8 filename[128]; /* name of file to be downloaded */ + UInt32 bufferSize; /* size of the download buffer */ + UInt32 buffer; /* physical address of the download buffer */ +} nbpCommandTFTPReadFile_s; + +typedef struct { + UInt32 status; /* return code from NBP */ + UInt8 filename[128]; /* name of file to be downloaded */ + UInt32 filesize; /* size of the file specified */ +} nbpCommandTFTPGetFileSize_s; + +typedef struct { + UInt32 status; /* return code from NBP */ + UInt8 sname[64]; /* server name */ + UInt32 CIP; /* client IP address */ + UInt32 SIP; /* server IP address */ + UInt32 GIP; /* gateway IP address */ +} nbpCommandGetNetworkInfo_s; + +/*========================================================================== + * An union of all NBP command structures. + */ +typedef union { + nbpCommandHeader_s header; + nbpCommandTFTPReadFile_s tftpReadFile; + nbpCommandTFTPGetFileSize_s tftpFileSize; +} nbpCommand_u; + +#endif /* !__LIBSAIO_NBP_CMD_H */ Index: branches/slice/rev749/libsaio/smbios_patcher.h =================================================================== --- branches/slice/rev749/libsaio/smbios_patcher.h (revision 0) +++ branches/slice/rev749/libsaio/smbios_patcher.h (revision 1169) @@ -0,0 +1,66 @@ +/* + * Copyright 2008 mackerintel + */ +/* + * AsereBLN: cleanup + */ + +#ifndef __LIBSAIO_SMBIOS_PATCHER_H +#define __LIBSAIO_SMBIOS_PATCHER_H + +#include "libsaio.h" +#include "SMBIOS.h" + +extern char MacModel[8]; +extern unsigned int ModelRev; +extern uint64_t smbios_p; + + +/* From Foundation/Efi/Guid/Smbios/SmBios.h */ +/* Modified to wrap Data4 array init with {} */ +#define EFI_SMBIOS_TABLE_GUID {0xeb9d2d31, 0x2d88, 0x11d3, 0x9a, 0x16, {0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d}} + +#define SMBIOS_RANGE_START 0x000F0000 +#define SMBIOS_RANGE_END 0x000FFFFF + +#define SMBIOS_ORIGINAL 0 +#define SMBIOS_PATCHED 1 + +struct smbios_table_header +{ + uint8_t type; + uint8_t length; + uint16_t handle; +} __attribute__ ((packed)); + +struct smbios_property +{ + const char *name; + uint8_t table_type; + enum {SMSTRING, SMWORD, SMBYTE, SMOWORD} value_type; + int offset; + int (*auto_int) (const char *name, int table_num); + const char *(*auto_str) (const char *name, int table_num); + const char *(*auto_oword) (const char *name, int table_num); +}; + +struct smbios_table_description +{ + uint8_t type; + int len; + int (*numfunc)(int tablen); +}; + +/** call with flag SMBIOS_ORIGINAL to get orig. entrypoint + or call with flag SMBIOS_PATCHED to get patched smbios entrypoint +*/ +extern struct SMBEntryPoint *getSmbios(int); +extern struct DMIHeader* FindNextDmiTableOfType(int type, int minlen); +extern struct DMIHeader* FindFirstDmiTableOfType(int type, int minlen); +extern void getSmbiosProductName(); +const char *smbiosStringAtIndex(DMIHeader*, int index, int *length ); +extern bool scanDMI(void); +extern void scan_cpu_DMI(void); //PlatformInfo_t *); //Slice + + +#endif /* !__LIBSAIO_SMBIOS_PATCHER_H */ Index: branches/slice/rev749/libsaio/bios.s =================================================================== --- branches/slice/rev749/libsaio/bios.s (revision 0) +++ branches/slice/rev749/libsaio/bios.s (revision 1169) @@ -0,0 +1,184 @@ +/* + * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 2.0 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright 1993 NeXT Computer, Inc. + * All rights reserved. + * + * Harness for calling real-mode BIOS functions. + */ + +/* Copyright 2007 David Elliott + 2007-12-30 dfe + - Enhanced code to use specified DS register when doing BIOS interrupt + - Fixed movl %ax,new_es bug which assembler was interpreting as + movl %eax,new_es which was overwriting the next word. + */ +#include +#include "memory.h" + +#define data32 .byte 0x66 +#define addr32 .byte 0x67 + +#define O_INT 0 +#define O_EAX 4 +#define O_EBX 8 +#define O_ECX 12 +#define O_EDX 16 +#define O_EDI 20 +#define O_ESI 24 +#define O_EBP 28 +#define O_CS 32 +#define O_DS 34 +#define O_ES 36 +#define O_FLG 38 + + .section __INIT,__data // turbo - Data that must be in the first segment + +/* Saved registers: + These used to be (and in theory ought to be) located in __DATA,__bss. + The problem is that the larger the binary grows, more of the BSS gets + pushed into the next real-mode segment. Doing it this way we waste 24 + bytes in the binary that our loader (e.g. boot1) must now load. But the + advantage is that we relocate this data to ensure it stays in the first + real-mode segment. Therefore, depending on link order, quite a lot of + new data, and possibly a lot of new executable code can be added to the + binary since with this change the BSS and most of the DATA is now only + accessed from protected mode where real-mode segment limits don't apply. + + With this change, plus the earlier change to respect DS (e.g. use huge + pointers), the binary can grow much larger, currently up to exactly 63.5k + which is the maximum that the first-stage bootsectors can handle. To get + more than that more changes are needed. In that case we would have to + play with Mach-O segments to ensure real-mode code and data got stuffed + well within the first 63.5k. Furthermore, we'd have to adjust the boot + sectors to allow them to span segments. + + Since this change alone only gains us about 4k more than where we're at + now (which is not anything to scoff at) it won't be very long before we + need to start using Mach-O segments to force the linker to locate certain + bits of code and data within the first 63.5k and modify the loaders to + be able to load more than 63.5k. + */ + .align 2 +save_eax: .space 4 + .align 2 +save_edx: .space 4 + .align 1 +save_es: .space 2 + .align 1 +save_flag: .space 2 + .align 2 +new_eax: .space 4 + .align 2 +new_edx: .space 4 + .align 1 +new_es: .space 2 + .align 1 +new_ds: .space 2 + + .section __INIT,__text // turbo - This code must reside within the first segment + + +/*============================================================================ + * Call real-mode BIOS INT functions. + * + */ +LABEL(_bios) + enter $0, $0 + pushal + + movl 8(%ebp), %edx // address of save area + movb O_INT(%edx), %al // save int number + movb %al, do_int+1 + + movl O_EBX(%edx), %ebx + movl O_ECX(%edx), %ecx + movl O_EDI(%edx), %edi + movl O_ESI(%edx), %esi + movl O_EBP(%edx), %ebp + movl %edx, save_edx + movl O_EAX(%edx), %eax + movl %eax, new_eax + movl O_EDX(%edx), %eax + movl %eax, new_edx + movw O_ES(%edx), %ax + movw %ax, new_es + movw O_DS(%edx), %ax + movw %ax, new_ds + + call __prot_to_real + + data32 + addr32 + mov OFFSET16(new_eax), %eax + data32 + addr32 + mov OFFSET16(new_edx), %edx + data32 + addr32 + mov OFFSET16(new_es), %es + + push %ds // Save DS + // Replace DS. WARNING: Don't access data until it's restored! + addr32 + data32 + mov OFFSET16(new_ds), %ds + +do_int: + int $0x00 + pop %ds // Restore DS before we do anything else + + pushf + data32 + addr32 + movl %eax, OFFSET16(save_eax) + popl %eax // actually pop %ax + addr32 + movl %eax, OFFSET16(save_flag) // actually movw + mov %es, %ax + addr32 + movl %eax, OFFSET16(save_es) // actually movw + data32 + call __real_to_prot + + movl %edx, new_edx // save new edx before clobbering + movl save_edx, %edx + movl new_edx, %eax // now move it into buffer + movl %eax, O_EDX(%edx) + movl save_eax, %eax + movl %eax, O_EAX(%edx) + movw save_es, %ax + movw %ax, O_ES(%edx) + movw save_flag, %ax + movw %ax, O_FLG(%edx) + movl %ebx, O_EBX(%edx) + movl %ecx, O_ECX(%edx) + movl %edi, O_EDI(%edx) + movl %esi, O_ESI(%edx) + movl %ebp, O_EBP(%edx) + + popal + leave + + ret Index: branches/slice/rev749/libsaio/pci_root.c =================================================================== --- branches/slice/rev749/libsaio/pci_root.c (revision 0) +++ branches/slice/rev749/libsaio/pci_root.c (revision 1169) @@ -0,0 +1,116 @@ +/* + * Copyright 2009 netkas + */ + +#include "libsaio.h" +#include "boot.h" +#include "bootstruct.h" +//#include "acpi_patcher.h" + +#ifndef DEBUG_PCIROOT +#define DEBUG_PCIROOT 0 +#endif + +#if DEBUG_PCIROOT +#define DBG(x...) verbose(x) +#else +#define DBG(x...) msglog(x) +#endif + +static int rootuid = 10; //value means function wasnt ran yet +#if NOTYET //it present in ACPIPatcher +static unsigned int findrootuid(unsigned char * dsdt, int len) +{ + int i; + for (i=0; i<64 && ibootConfig)) { + if (isdigit(val[0])) rootuid = val[0] - '0'; + goto out; + } + /* Chameleon compatibility */ + else if (getValueForKey("PciRoot", &val, &len, &bootInfo->bootConfig)) { + if (isdigit(val[0])) rootuid = val[0] - '0'; + goto out; + } + /* PCEFI compatibility */ + else if (getValueForKey("-pci0", &val, &len, &bootInfo->bootConfig)) { + rootuid = 0; + goto out; + } + else if (getValueForKey("-pci1", &val, &len, &bootInfo->bootConfig)) { + rootuid = 1; + goto out; + } +//Slice - as in Meklort +#if NOTNOW + int fd = search_and_get_acpi_fd("DSDT.aml", &dsdt_filename); + + // Check booting partition + if (fd<0) + { + verbose("No DSDT found, using 0 as uid value.\n"); + rootuid = 0; + goto out; + } + + fsize = file_size(fd); + + if ((new_dsdt = malloc(fsize)) == NULL) { + verbose("[ERROR] alloc DSDT memory failed\n"); + close (fd); + goto out; + } + if (read (fd, new_dsdt, fsize) != fsize) { + verbose("[ERROR] read %s failed\n", dsdt_filename); + close (fd); + goto out; + } + close (fd); + + rootuid = findpciroot(new_dsdt, fsize); + free(new_dsdt); + + // make sure it really works: + if (rootuid == 11) rootuid=0; //usually when _UID isnt present, it means uid is zero + else if (rootuid < 0 || rootuid > 9) + { + verbose("PciRoot uid value wasnt found, using 0, if you want it to be 1, use -PciRootUID flag"); + rootuid = 0; + } +#endif +out: + verbose("Using PCI-Root-UID value: %d\n", rootuid); + return rootuid; +} Index: branches/slice/rev749/libsaio/aml_generator.c =================================================================== --- branches/slice/rev749/libsaio/aml_generator.c (revision 0) +++ branches/slice/rev749/libsaio/aml_generator.c (revision 1169) @@ -0,0 +1,498 @@ +/* + * aml_generator.c + * Chameleon + * + * Created by Mozodojo on 20/07/10. + * Copyright 2010 mozo. All rights reserved. + * + */ + +#include "aml_generator.h" + +bool aml_add_to_parent(struct aml_chunk* parent, struct aml_chunk* node) +{ + if (parent && node) + { + switch (parent->Type) + { + case AML_CHUNK_NONE: + case AML_CHUNK_BYTE: + case AML_CHUNK_WORD: + case AML_CHUNK_DWORD: + case AML_CHUNK_QWORD: + case AML_CHUNK_ALIAS: + verbose("aml_add_to_parent: node doesn't support child nodes!"); + return false; + case AML_CHUNK_NAME: + if (parent->First) + { + verbose("aml_add_to_parent: name node supports only one child node!"); + return false; + } + break; + + default: + break; + } + + if (!parent->First) + parent->First = node; + + if (parent->Last) + parent->Last->Next = node; + + parent->Last = node; + + return TRUE; + } + + return FALSE; +} + +struct aml_chunk* aml_create_node(struct aml_chunk* parent) +{ + struct aml_chunk* node = (struct aml_chunk*)malloc(sizeof(struct aml_chunk)); + + aml_add_to_parent(parent, node); + + return node; +} + +void aml_destroy_node(struct aml_chunk* node) +{ + // Delete child nodes + struct aml_chunk* child = node->First; + + while (child) + { + struct aml_chunk* next = child->Next; + + if (child->Buffer) + free(child->Buffer); + + free(child); + + child = next; + } + + // Free node + if (node->Buffer) + free(node->Buffer); + + free(node); +} + +struct aml_chunk* aml_add_buffer(struct aml_chunk* parent, const char* buffer, unsigned int size) +{ + struct aml_chunk* node = aml_create_node(parent); + + if (node) + { + node->Type = AML_CHUNK_NONE; + node->Length = size; + node->Buffer = malloc(node->Length); + memcpy(node->Buffer, buffer, node->Length); + } + + return node; +} + +struct aml_chunk* aml_add_byte(struct aml_chunk* parent, unsigned char value) +{ + struct aml_chunk* node = aml_create_node(parent); + + if (node) + { + node->Type = AML_CHUNK_BYTE; + + node->Length = 1; + node->Buffer = malloc(node->Length); + node->Buffer[0] = value; + } + + return node; +} + +struct aml_chunk* aml_add_word(struct aml_chunk* parent, unsigned int value) +{ + struct aml_chunk* node = aml_create_node(parent); + + if (node) + { + node->Type = AML_CHUNK_WORD; + node->Length = 2; + node->Buffer = malloc(node->Length); + node->Buffer[0] = value & 0xff; + node->Buffer[1] = value >> 8; + } + + return node; +} + +struct aml_chunk* aml_add_dword(struct aml_chunk* parent, unsigned long value) +{ + struct aml_chunk* node = aml_create_node(parent); + + if (node) + { + node->Type = AML_CHUNK_DWORD; + node->Length = 4; + node->Buffer = malloc(node->Length); + node->Buffer[0] = value & 0xff; + node->Buffer[1] = (value >> 8) & 0xff; + node->Buffer[2] = (value >> 16) & 0xff; + node->Buffer[3] = (value >> 24) & 0xff; + } + + return node; +} + +struct aml_chunk* aml_add_qword(struct aml_chunk* parent, unsigned long long value) +{ + struct aml_chunk* node = aml_create_node(parent); + + if (node) + { + node->Type = AML_CHUNK_QWORD; + node->Length = 8; + node->Buffer = malloc(node->Length); + node->Buffer[0] = value & 0xff; + node->Buffer[1] = (value >> 8) & 0xff; + node->Buffer[2] = (value >> 16) & 0xff; + node->Buffer[3] = (value >> 24) & 0xff; + node->Buffer[4] = (value >> 32) & 0xff; + node->Buffer[5] = (value >> 40) & 0xff; + node->Buffer[6] = (value >> 48) & 0xff; + node->Buffer[7] = (value >> 56) & 0xff; + } + + return node; +} + +unsigned int aml_fill_simple_name(char* buffer, const char* name) +{ + if (strlen(name) < 4) + { + verbose("aml_fill_simple_name: simple name %s has incorrect lengh! Must be 4\n", name); + return 0; + } + + memcpy(buffer, name, 4); + return 4; +} + +unsigned int aml_fill_name(struct aml_chunk* node, const char* name) +{ + if (!node) + return 0; + + int len = strlen(name), offset = 0, count = len / 4; + + if ((len % 4) > 1 || count == 0) + { + verbose("aml_fill_name: pathname %s has incorrect length! Must be 4, 8, 12, 16, etc...", name); + return 0; + } + + unsigned int root = 0; + + if ((len % 4) == 1 && name[0] == '\\') + root++; + + if (count == 1) + { + node->Length = 4 + root; + node->Buffer = malloc(node->Length); + memcpy(node->Buffer, name, 4 + root); + return node->Length; + } + + if (count == 2) + { + node->Length = 2 + 8; + node->Buffer = malloc(node->Length); + node->Buffer[offset++] = 0x5c; // Root Char + node->Buffer[offset++] = 0x2e; // Double name + memcpy(node->Buffer+offset, name + root, 8); + return node->Length; + } + + node->Length = 3 + count*4; + node->Buffer = malloc(node->Length); + node->Buffer[offset++] = 0x5c; // Root Char + node->Buffer[offset++] = 0x2f; // Multi name + node->Buffer[offset++] = count; // Names count + memcpy(node->Buffer+offset, name + root, count*4); + + return node->Length; +} + +struct aml_chunk* aml_add_scope(struct aml_chunk* parent, const char* name) +{ + struct aml_chunk* node = aml_create_node(parent); + + if (node) + { + node->Type = AML_CHUNK_SCOPE; + + aml_fill_name(node, name); + } + + return node; +} + +struct aml_chunk* aml_add_name(struct aml_chunk* parent, const char* name) +{ + struct aml_chunk* node = aml_create_node(parent); + + if (node) + { + node->Type = AML_CHUNK_NAME; + + aml_fill_name(node, name); + } + + return node; +} + +struct aml_chunk* aml_add_package(struct aml_chunk* parent) +{ + struct aml_chunk* node = aml_create_node(parent); + + if (node) + { + node->Type = AML_CHUNK_PACKAGE; + + node->Length = 1; + node->Buffer = malloc(node->Length); + } + + return node; +} + +struct aml_chunk* aml_add_alias(struct aml_chunk* parent, const char* name1, const char* name2) +{ + struct aml_chunk* node = aml_create_node(parent); + + if (node) + { + node->Type = AML_CHUNK_ALIAS; + + node->Length = 8; + node->Buffer = malloc(node->Length); + aml_fill_simple_name(node->Buffer, name1); + aml_fill_simple_name(node->Buffer+4, name2); + } + + return node; +} + +unsigned char aml_get_size_length(unsigned int size) +{ + if (size + 1 <= 0x3f) + return 1; + else if (size + 2 <= 0x3fff) + return 2; + else if (size + 3 <= 0x3fffff) + return 3; + + return 4; +} + +unsigned int aml_calculate_size(struct aml_chunk* node) +{ + if (node) + { + node->Size = 0; + + // Calculate child nodes size + struct aml_chunk* child = node->First; + unsigned char child_count = 0; + + while (child) + { + child_count++; + + node->Size += aml_calculate_size(child); + + child = child->Next; + } + + switch (node->Type) + { + case AML_CHUNK_NONE: + node->Size += node->Length; + break; + case AML_CHUNK_SCOPE: + node->Size += 1 + node->Length; + node->Size += aml_get_size_length(node->Size); + break; + case AML_CHUNK_PACKAGE: + node->Buffer[0] = child_count; + node->Size += 1 + node->Length; + node->Size += aml_get_size_length(node->Size); + break; + + case AML_CHUNK_BYTE: + if (node->Buffer[0] == 0x0 || node->Buffer[0] == 0x1) + { + node->Size += node->Length; + } + else + { + node->Size += 1 + node->Length; + } + + break; + + case AML_CHUNK_WORD: + case AML_CHUNK_DWORD: + case AML_CHUNK_QWORD: + case AML_CHUNK_ALIAS: + case AML_CHUNK_NAME: + node->Size += 1 + node->Length; + break; + } + + return node->Size; + } + + return 0; +} + +unsigned int aml_write_byte(unsigned char value, char* buffer, unsigned int offset) +{ + buffer[offset++] = value; + + return offset; +} + +unsigned int aml_write_word(unsigned int value, char* buffer, unsigned int offset) +{ + buffer[offset++] = value & 0xff; + buffer[offset++] = value >> 8; + + return offset; +} + +unsigned int aml_write_dword(unsigned long value, char* buffer, unsigned int offset) +{ + buffer[offset++] = value & 0xff; + buffer[offset++] = (value >> 8) & 0xff; + buffer[offset++] = (value >> 16) & 0xff; + buffer[offset++] = (value >> 24) & 0xff; + + return offset; +} + +unsigned int aml_write_qword(unsigned long long value, char* buffer, unsigned int offset) +{ + buffer[offset++] = value & 0xff; + buffer[offset++] = (value >> 8) & 0xff; + buffer[offset++] = (value >> 16) & 0xff; + buffer[offset++] = (value >> 24) & 0xff; + buffer[offset++] = (value >> 32) & 0xff; + buffer[offset++] = (value >> 40) & 0xff; + buffer[offset++] = (value >> 48) & 0xff; + buffer[offset++] = (value >> 56) & 0xff; + + return offset; +} + +unsigned int aml_write_buffer(const char* value, unsigned int size, char* buffer, unsigned int offset) +{ + if (size > 0) + { + memcpy(buffer + offset, value, size); + } + + return offset + size; +} + +unsigned int aml_write_size(unsigned int size, char* buffer, unsigned int offset) +{ + if (size <= 0x3f) + { + buffer[offset++] = size; + } + else if (size <= 0x3fff) + { + buffer[offset++] = 0x40 | (size & 0xf); + buffer[offset++] = (size >> 4) & 0xff; + } + else if (size <= 0x3fffff) + { + buffer[offset++] = 0x80 | (size & 0xf); + buffer[offset++] = (size >> 4) & 0xff; + buffer[offset++] = (size >> 12) & 0xff; + } + else + { + buffer[offset++] = 0xc0 | (size & 0xf); + buffer[offset++] = (size >> 4) & 0xff; + buffer[offset++] = (size >> 12) & 0xff; + buffer[offset++] = (size >> 20) & 0xff; + } + + return offset; +} + +unsigned int aml_write_node(struct aml_chunk* node, char* buffer, unsigned int offset) +{ + if (node && buffer) + { + unsigned int old = offset; + + switch (node->Type) + { + case AML_CHUNK_NONE: + offset = aml_write_buffer(node->Buffer, node->Length, buffer, offset); + break; + + case AML_CHUNK_SCOPE: + case AML_CHUNK_PACKAGE: + offset = aml_write_byte(node->Type, buffer, offset); + offset = aml_write_size(node->Size-1, buffer, offset); + offset = aml_write_buffer(node->Buffer, node->Length, buffer, offset); + break; + + case AML_CHUNK_BYTE: + if (node->Buffer[0] == 0x0 || node->Buffer[0] == 0x1) + { + offset = aml_write_buffer(node->Buffer, node->Length, buffer, offset); + } + else + { + offset = aml_write_byte(node->Type, buffer, offset); + offset = aml_write_buffer(node->Buffer, node->Length, buffer, offset); + } + break; + + case AML_CHUNK_WORD: + case AML_CHUNK_DWORD: + case AML_CHUNK_QWORD: + case AML_CHUNK_ALIAS: + case AML_CHUNK_NAME: + offset = aml_write_byte(node->Type, buffer, offset); + offset = aml_write_buffer(node->Buffer, node->Length, buffer, offset); + break; + + default: + break; + } + + struct aml_chunk* child = node->First; + + while (child) + { + offset = aml_write_node(child, buffer, offset); + + child = child->Next; + } + + if (offset - old != node->Size) + verbose("Node size incorrect: 0x%x\n", node->Type); + } + + return offset; +} \ No newline at end of file Index: branches/slice/rev749/libsaio/pci_root.h =================================================================== --- branches/slice/rev749/libsaio/pci_root.h (revision 0) +++ branches/slice/rev749/libsaio/pci_root.h (revision 1169) @@ -0,0 +1,14 @@ +/* + * Copyright 2008 mackerintel + */ + +#ifndef __LIBSAIO_PCI_ROOT_H +#define __LIBSAIO_PCI_ROOT_H + +#include "libsaio.h" + + +extern int getPciRootUID(void); +//unsigned int findpciroot(unsigned char * dsdt,int len); + +#endif /* !__LIBSAIO_DSDT_PATCHER_H */ Index: branches/slice/rev749/libsaio/aml_generator.h =================================================================== --- branches/slice/rev749/libsaio/aml_generator.h (revision 0) +++ branches/slice/rev749/libsaio/aml_generator.h (revision 1169) @@ -0,0 +1,63 @@ +/* + * aml_generator.h + * Chameleon + * + * Created by Mozodojo on 20/07/10. + * Copyright 2010 mozo. All rights reserved. + * + */ + +#ifndef __LIBSAIO_AML_GENERATOR_H +#define __LIBSAIO_AML_GENERATOR_H + +#include "libsaio.h" +//#include "ACPIPatcher.h" + + +#define AML_CHUNK_NONE 0xff +#define AML_CHUNK_ZERO 0x00 +#define AML_CHUNK_ONE 0x01 +#define AML_CHUNK_ALIAS 0x06 +#define AML_CHUNK_NAME 0x08 +#define AML_CHUNK_BYTE 0x0A +#define AML_CHUNK_WORD 0x0B +#define AML_CHUNK_DWORD 0x0C +#define AML_CHUNK_STRING 0x0D +#define AML_CHUNK_QWORD 0x0E +#define AML_CHUNK_SCOPE 0x10 +#define AML_CHUNK_PACKAGE 0x12 + +struct aml_chunk +{ + unsigned char Type; + unsigned int Length; + char* Buffer; + + unsigned int Size; + + struct aml_chunk* Next; + struct aml_chunk* First; + struct aml_chunk* Last; +}; + +static inline bool aml_isvalidchar(char c) +{ + return isupper(c) || isdigit(c) || c == '_'; +}; + +bool aml_add_to_parent(struct aml_chunk* parent, struct aml_chunk* node); +struct aml_chunk* aml_create_node(struct aml_chunk* parent); +void aml_destroy_node(struct aml_chunk* node); +struct aml_chunk* aml_add_buffer(struct aml_chunk* parent, const char* buffer, unsigned int size); +struct aml_chunk* aml_add_byte(struct aml_chunk* parent, unsigned char value); +struct aml_chunk* aml_add_word(struct aml_chunk* parent, unsigned int value); +struct aml_chunk* aml_add_dword(struct aml_chunk* parent, unsigned long value); +struct aml_chunk* aml_add_qword(struct aml_chunk* parent, unsigned long long value); +struct aml_chunk* aml_add_scope(struct aml_chunk* parent, const char* name); +struct aml_chunk* aml_add_name(struct aml_chunk* parent, const char* name); +struct aml_chunk* aml_add_package(struct aml_chunk* parent); +struct aml_chunk* aml_add_alias(struct aml_chunk* parent, const char* name1, const char* name2); +unsigned int aml_calculate_size(struct aml_chunk* node); +unsigned int aml_write_node(struct aml_chunk* node, char* buffer, unsigned int offset); + +#endif /* !__LIBSAIO_AML_GENERATOR_H */ \ No newline at end of file Index: branches/slice/rev749/libsaio/memvendors.h =================================================================== --- branches/slice/rev749/libsaio/memvendors.h (revision 0) +++ branches/slice/rev749/libsaio/memvendors.h (revision 1169) @@ -0,0 +1,894 @@ +/* + * Memory module vendors as published by JEDEC 106AA + * + * Special thanks to indi, memtest and theking for the table + * + */ +#ifndef __MEMVEN_H +#define __MEMVEN_H + +typedef struct _vidTag { + uint8_t bank; + uint8_t code; + const char* name; +} VenIdName; + +VenIdName vendorMap[] = { + { 0, 0x01, "AMD"}, + { 0, 0x02, "AMI"}, + { 0, 0x83, "Fairchild"}, + { 0, 0x04, "Fujitsu"}, + { 0, 0x85, "GTE"}, + { 0, 0x86, "Harris"}, + { 0, 0x07, "Hitachi"}, + { 0, 0x08, "Inmos"}, + { 0, 0x89, "Intel"}, + { 0, 0x8a, "I.T.T."}, + { 0, 0x0b, "Intersil"}, + { 0, 0x8c, "Monolithic Memories"}, + { 0, 0x0d, "Mostek"}, + { 0, 0x0e, "Freescale (Motorola)"}, + { 0, 0x8f, "National"}, + { 0, 0x10, "NEC"}, + { 0, 0x91, "RCA"}, + { 0, 0x92, "Raytheon"}, + { 0, 0x13, "Conexant (Rockwell)"}, + { 0, 0x94, "Seeq"}, + { 0, 0x15, "NXP (Philips)"}, + { 0, 0x16, "Synertek"}, + { 0, 0x97, "Texas Instruments"}, + { 0, 0x98, "Toshiba"}, + { 0, 0x19, "Xicor"}, + { 0, 0x1a, "Zilog"}, + { 0, 0x9b, "Eurotechnique"}, + { 0, 0x1c, "Mitsubishi"}, + { 0, 0x9d, "Lucent (AT&T)"}, + { 0, 0x9e, "Exel"}, + { 0, 0x1f, "Atmel"}, + { 0, 0x20, "SGS/Thomson"}, + { 0, 0xa1, "Lattice Semi."}, + { 0, 0xa2, "NCR"}, + { 0, 0x23, "Wafer Scale Integration"}, + { 0, 0xa4, "IBM"}, + { 0, 0x25, "Tristar"}, + { 0, 0x26, "Visic"}, + { 0, 0xa7, "Intl. CMOS Technology"}, + { 0, 0xa8, "SSSI"}, + { 0, 0x29, "MicrochipTechnology"}, + { 0, 0x2a, "Ricoh"}, + { 0, 0xab, "VLSI"}, + { 0, 0x2c, "Micron Technology"}, + { 0, 0xad, "Hynix Semiconductor"}, + { 0, 0xae, "OKI Semiconductor"}, + { 0, 0x2f, "ACTEL"}, + { 0, 0xb0, "Sharp"}, + { 0, 0x31, "Catalyst"}, + { 0, 0x32, "Panasonic"}, + { 0, 0xb3, "IDT"}, + { 0, 0x34, "Cypress"}, + { 0, 0xb5, "DEC"}, + { 0, 0xb6, "LSI Logic"}, + { 0, 0x37, "Zarlink (Plessey)"}, + { 0, 0x38, "UTMC"}, + { 0, 0xb9, "Thinking Machine"}, + { 0, 0xba, "Thomson CSF"}, + { 0, 0x3b, "Integrated CMOS (Vertex)"}, + { 0, 0xbc, "Honeywell"}, + { 0, 0x3d, "Tektronix"}, + { 0, 0x3e, "Sun Microsystems"}, + { 0, 0xbf, "SST"}, + { 0, 0x40, "ProMos/Mosel Vitelic"}, + { 0, 0xc1, "Infineon (Siemens)"}, + { 0, 0xc2, "Macronix"}, + { 0, 0x43, "Xerox"}, + { 0, 0xc4, "Plus Logic"}, + { 0, 0x45, "SanDisk"}, + { 0, 0x46, "Elan Circuit Tech."}, + { 0, 0xc7, "European Silicon Str."}, + { 0, 0xc8, "Apple Computer"}, + { 0, 0x49, "Xilinx"}, + { 0, 0x4a, "Compaq"}, + { 0, 0xcb, "Protocol Engines"}, + { 0, 0x4c, "SCI"}, + { 0, 0xcd, "Seiko Instruments"}, + { 0, 0xce, "Samsung"}, + { 0, 0x4f, "I3 Design System"}, + { 0, 0xd0, "Klic"}, + { 0, 0x51, "Crosspoint Solutions"}, + { 0, 0x52, "Alliance Semiconductor"}, + { 0, 0xd3, "Tandem"}, + { 0, 0x54, "Hewlett-Packard"}, + { 0, 0xd5, "Intg. Silicon Solutions"}, + { 0, 0xd6, "Brooktree"}, + { 0, 0x57, "New Media"}, + { 0, 0x58, "MHS Electronic"}, + { 0, 0xd9, "Performance Semi."}, + { 0, 0xda, "Winbond Electronic"}, + { 0, 0x5b, "Kawasaki Steel"}, + { 0, 0xdc, "Bright Micro"}, + { 0, 0x5d, "TECMAR"}, + { 0, 0x5e, "Exar"}, + { 0, 0xdf, "PCMCIA"}, + { 0, 0xe0, "LG Semi (Goldstar)"}, + { 0, 0x61, "Northern Telecom"}, + { 0, 0x62, "Sanyo"}, + { 0, 0xe3, "Array Microsystems"}, + { 0, 0x64, "Crystal Semiconductor"}, + { 0, 0xe5, "Analog Devices"}, + { 0, 0xe6, "PMC-Sierra"}, + { 0, 0x67, "Asparix"}, + { 0, 0x68, "Convex Computer"}, + { 0, 0xe9, "Quality Semiconductor"}, + { 0, 0xea, "Nimbus Technology"}, + { 0, 0x6b, "Transwitch"}, + { 0, 0xec, "Micronas (ITT Intermetall)"}, + { 0, 0x6d, "Cannon"}, + { 0, 0x6e, "Altera"}, + { 0, 0xef, "NEXCOM"}, + { 0, 0x70, "QUALCOMM"}, + { 0, 0xf1, "Sony"}, + { 0, 0xf2, "Cray Research"}, + { 0, 0x73, "AMS(Austria Micro)"}, + { 0, 0xf4, "Vitesse"}, + { 0, 0x75, "Aster Electronics"}, + { 0, 0x76, "Bay Networks (Synoptic)"}, + { 0, 0xf7, "Zentrum/ZMD"}, + { 0, 0xf8, "TRW"}, + { 0, 0x79, "Thesys"}, + { 0, 0x7a, "Solbourne Computer"}, + { 0, 0xfb, "Allied-Signal"}, + { 0, 0x7c, "Dialog"}, + { 0, 0xfd, "Media Vision"}, + { 0, 0xfe, "Numonyx"}, + { 1, 0x01, "Cirrus Logic"}, + { 1, 0x02, "National Instruments"}, + { 1, 0x83, "ILC Data Device"}, + { 1, 0x04, "Alcatel Mietec"}, + { 1, 0x85, "Micro Linear"}, + { 1, 0x86, "Univ. of NC"}, + { 1, 0x07, "JTAG Technologies"}, + { 1, 0x08, "BAE Systems (Loral)"}, + { 1, 0x89, "Nchip"}, + { 1, 0x8a, "Galileo Tech"}, + { 1, 0x0b, "Bestlink Systems"}, + { 1, 0x8c, "Graychip"}, + { 1, 0x0d, "GENNUM"}, + { 1, 0x0e, "VideoLogic"}, + { 1, 0x8f, "Robert Bosch"}, + { 1, 0x10, "Chip Express"}, + { 1, 0x91, "DATARAM"}, + { 1, 0x92, "United Microelectronics Corp."}, + { 1, 0x13, "TCSI"}, + { 1, 0x94, "Smart Modular"}, + { 1, 0x15, "Hughes Aircraft"}, + { 1, 0x16, "Lanstar Semiconductor"}, + { 1, 0x97, "Qlogic"}, + { 1, 0x98, "Kingston"}, + { 1, 0x19, "Music Semi"}, + { 1, 0x1a, "Ericsson Components"}, + { 1, 0x9b, "SpaSE"}, + { 1, 0x1c, "Eon Silicon Devices"}, + { 1, 0x9d, "Programmable Micro Corp"}, + { 1, 0x9e, "DoD"}, + { 1, 0x1f, "Integ. Memories Tech."}, + { 1, 0x20, "Corollary"}, + { 1, 0xa1, "Dallas Semiconductor"}, + { 1, 0xa2, "Omnivision"}, + { 1, 0x23, "EIV(Switzerland)"}, + { 1, 0xa4, "Novatel Wireless"}, + { 1, 0x25, "Zarlink (Mitel)"}, + { 1, 0x26, "Clearpoint"}, + { 1, 0xa7, "Cabletron"}, + { 1, 0xa8, "STEC (Silicon Tech)"}, + { 1, 0x29, "Vanguard"}, + { 1, 0x2a, "Hagiwara Sys-Com"}, + { 1, 0xab, "Vantis"}, + { 1, 0x2c, "Celestica"}, + { 1, 0xad, "Century"}, + { 1, 0xae, "Hal Computers"}, + { 1, 0x2f, "Rohm Company"}, + { 1, 0xb0, "Juniper Networks"}, + { 1, 0x31, "Libit Signal Processing"}, + { 1, 0x32, "Mushkin Enhanced Memory"}, + { 1, 0xb3, "Tundra Semiconductor"}, + { 1, 0x34, "Adaptec"}, + { 1, 0xb5, "LightSpeed Semi."}, + { 1, 0xb6, "ZSP Corp."}, + { 1, 0x37, "AMIC Technology"}, + { 1, 0x38, "Adobe Systems"}, + { 1, 0xb9, "Dynachip"}, + { 1, 0xba, "PNY Electronics"}, + { 1, 0x3b, "Newport Digital"}, + { 1, 0xbc, "MMC Networks"}, + { 1, 0x3d, "T Square"}, + { 1, 0x3e, "Seiko Epson"}, + { 1, 0xbf, "Broadcom"}, + { 1, 0x40, "Viking Components"}, + { 1, 0xc1, "V3 Semiconductor"}, + { 1, 0xc2, "Flextronics (Orbit Semiconductor)"}, + { 1, 0x43, "Suwa Electronics"}, + { 1, 0xc4, "Transmeta"}, + { 1, 0x45, "Micron CMS"}, + { 1, 0x46, "American Computer & Digital Components"}, + { 1, 0xc7, "Enhance 3000"}, + { 1, 0xc8, "Tower Semiconductor"}, + { 1, 0x49, "CPU Design"}, + { 1, 0x4a, "Price Point"}, + { 1, 0xcb, "Maxim Integrated Product"}, + { 1, 0x4c, "Tellabs"}, + { 1, 0xcd, "Centaur Technology"}, + { 1, 0xce, "Unigen"}, + { 1, 0x4f, "Transcend Information"}, + { 1, 0xd0, "Memory Card Technology"}, + { 1, 0x51, "CKD"}, + { 1, 0x52, "Capital Instruments"}, + { 1, 0xd3, "Aica Kogyo"}, + { 1, 0x54, "Linvex Technology"}, + { 1, 0xd5, "MSC Vertriebs"}, + { 1, 0xd6, "AKM Company"}, + { 1, 0x57, "Dynamem"}, + { 1, 0x58, "NERA ASA"}, + { 1, 0xd9, "GSI Technology"}, + { 1, 0xda, "Dane-Elec (C Memory)"}, + { 1, 0x5b, "Acorn Computers"}, + { 1, 0xdc, "Lara Technology"}, + { 1, 0x5d, "Oak Technology"}, + { 1, 0x5e, "Itec Memory"}, + { 1, 0xdf, "Tanisys Technology"}, + { 1, 0xe0, "Truevision"}, + { 1, 0x61, "Wintec Industries"}, + { 1, 0x62, "Super PC Memory"}, + { 1, 0xe3, "MGV Memory"}, + { 1, 0x64, "Galvantech"}, + { 1, 0xe5, "Gadzoox Networks"}, + { 1, 0xe6, "Multi Dimensional Cons."}, + { 1, 0x67, "GateField"}, + { 1, 0x68, "Integrated Memory System"}, + { 1, 0xe9, "Triscend"}, + { 1, 0xea, "XaQti"}, + { 1, 0x6b, "Goldenram"}, + { 1, 0xec, "Clear Logic"}, + { 1, 0x6d, "Cimaron Communications"}, + { 1, 0x6e, "Nippon Steel Semi. Corp."}, + { 1, 0xef, "Advantage Memory"}, + { 1, 0x70, "AMCC"}, + { 1, 0xf1, "LeCroy"}, + { 1, 0xf2, "Yamaha"}, + { 1, 0x73, "Digital Microwave"}, + { 1, 0xf4, "NetLogic Microsystems"}, + { 1, 0x75, "MIMOS Semiconductor"}, + { 1, 0x76, "Advanced Fibre"}, + { 1, 0xf7, "BF Goodrich Data."}, + { 1, 0xf8, "Epigram"}, + { 1, 0x79, "Acbel Polytech"}, + { 1, 0x7a, "Apacer Technology"}, + { 1, 0xfb, "Admor Memory"}, + { 1, 0x7c, "FOXCONN"}, + { 1, 0xfd, "Quadratics Superconductor"}, + { 1, 0xfe, "3COM"}, + { 2, 0x01, "Camintonn"}, + { 2, 0x02, "ISOA"}, + { 2, 0x83, "Agate Semiconductor"}, + { 2, 0x04, "ADMtek"}, + { 2, 0x85, "HYPERTEC"}, + { 2, 0x86, "Adhoc Technologies"}, + { 2, 0x07, "MOSAID Technologies"}, + { 2, 0x08, "Ardent Technologies"}, + { 2, 0x89, "Switchcore"}, + { 2, 0x8a, "Cisco Systems"}, + { 2, 0x0b, "Allayer Technologies"}, + { 2, 0x8c, "WorkX AG (Wichman)"}, + { 2, 0x0d, "Oasis Semiconductor"}, + { 2, 0x0e, "Novanet Semiconductor"}, + { 2, 0x8f, "E-M Solutions"}, + { 2, 0x10, "Power General"}, + { 2, 0x91, "Advanced Hardware Arch."}, + { 2, 0x92, "Inova Semiconductors"}, + { 2, 0x13, "Telocity"}, + { 2, 0x94, "Delkin Devices"}, + { 2, 0x15, "Symagery Microsystems"}, + { 2, 0x16, "C-Port"}, + { 2, 0x97, "SiberCore Technologies"}, + { 2, 0x98, "Southland Microsystems"}, + { 2, 0x19, "Malleable Technologies"}, + { 2, 0x1a, "Kendin Communications"}, + { 2, 0x9b, "Great Technology Microcomputer"}, + { 2, 0x1c, "Sanmina"}, + { 2, 0x9d, "HADCO"}, + { 2, 0x9e, "Corsair"}, + { 2, 0x1f, "Actrans System"}, + { 2, 0x20, "ALPHA Technologies"}, + { 2, 0xa1, "Silicon Laboratories (Cygnal)"}, + { 2, 0xa2, "Artesyn Technologies"}, + { 2, 0x23, "Align Manufacturing"}, + { 2, 0xa4, "Peregrine Semiconductor"}, + { 2, 0x25, "Chameleon Systems"}, + { 2, 0x26, "Aplus Flash Technology"}, + { 2, 0xa7, "MIPS Technologies"}, + { 2, 0xa8, "Chrysalis ITS"}, + { 2, 0x29, "ADTEC"}, + { 2, 0x2a, "Kentron Technologies"}, + { 2, 0xab, "Win Technologies"}, + { 2, 0x2c, "Tachyon Semiconductor (ASIC)"}, + { 2, 0xad, "Extreme Packet Devices"}, + { 2, 0xae, "RF Micro Devices"}, + { 2, 0x2f, "Siemens AG"}, + { 2, 0xb0, "Sarnoff"}, + { 2, 0x31, "Itautec SA"}, + { 2, 0x32, "Radiata"}, + { 2, 0xb3, "Benchmark Elect. (AVEX)"}, + { 2, 0x34, "Legend"}, + { 2, 0xb5, "SpecTek"}, + { 2, 0xb6, "Hi/fn"}, + { 2, 0x37, "Enikia"}, + { 2, 0x38, "SwitchOn Networks"}, + { 2, 0xb9, "AANetcom"}, + { 2, 0xba, "Micro Memory Bank"}, + { 2, 0x3b, "ESS Technology"}, + { 2, 0xbc, "Virata"}, + { 2, 0x3d, "Excess Bandwidth"}, + { 2, 0x3e, "West Bay Semiconductor"}, + { 2, 0xbf, "DSP Group"}, + { 2, 0x40, "Newport Communications"}, + { 2, 0xc1, "Chip2Chip"}, + { 2, 0xc2, "Phobos"}, + { 2, 0x43, "Intellitech"}, + { 2, 0xc4, "Nordic VLSI ASA"}, + { 2, 0x45, "Ishoni Networks"}, + { 2, 0x46, "Silicon Spice"}, + { 2, 0xc7, "Alchemy Semiconductor"}, + { 2, 0xc8, "Agilent Technologies"}, + { 2, 0x49, "Centillium Communications"}, + { 2, 0x4a, "W.L. Gore"}, + { 2, 0xcb, "HanBit Electronics"}, + { 2, 0x4c, "GlobeSpan"}, + { 2, 0xcd, "Element 14"}, + { 2, 0xce, "Pycon"}, + { 2, 0x4f, "Saifun Semiconductors"}, + { 2, 0xd0, "Sibyte,"}, + { 2, 0x51, "MetaLink Technologies"}, + { 2, 0x52, "Feiya Technology"}, + { 2, 0xd3, "I & C Technology"}, + { 2, 0x54, "Shikatronics"}, + { 2, 0xd5, "Elektrobit"}, + { 2, 0xd6, "Megic"}, + { 2, 0x57, "Com-Tier"}, + { 2, 0x58, "Malaysia Micro Solutions"}, + { 2, 0xd9, "Hyperchip"}, + { 2, 0xda, "Gemstone Communications"}, + { 2, 0x5b, "Anadigm (Anadyne)"}, + { 2, 0xdc, "3ParData"}, + { 2, 0x5d, "Mellanox Technologies"}, + { 2, 0x5e, "Tenx Technologies"}, + { 2, 0xdf, "Helix AG"}, + { 2, 0xe0, "Domosys"}, + { 2, 0x61, "Skyup Technology"}, + { 2, 0x62, "HiNT"}, + { 2, 0xe3, "Chiaro"}, + { 2, 0x64, "MDT Technologies"}, + { 2, 0xe5, "Exbit Technology A/S"}, + { 2, 0xe6, "Integrated Technology Express"}, + { 2, 0x67, "AVED Memory"}, + { 2, 0x68, "Legerity"}, + { 2, 0xe9, "Jasmine Networks"}, + { 2, 0xea, "Caspian Networks"}, + { 2, 0x6b, "nCUBE"}, + { 2, 0xec, "Silicon Access Networks"}, + { 2, 0x6d, "FDK"}, + { 2, 0x6e, "High Bandwidth Access"}, + { 2, 0xef, "MultiLink Technology"}, + { 2, 0x70, "BRECIS"}, + { 2, 0xf1, "World Wide Packets"}, + { 2, 0xf2, "APW"}, + { 2, 0x73, "Chicory Systems"}, + { 2, 0xf4, "Xstream Logic"}, + { 2, 0x75, "Fast-Chip"}, + { 2, 0x76, "Zucotto Wireless"}, + { 2, 0xf7, "Realchip"}, + { 2, 0xf8, "Galaxy Power"}, + { 2, 0x79, "eSilicon"}, + { 2, 0x7a, "Morphics Technology"}, + { 2, 0xfb, "Accelerant Networks"}, + { 2, 0x7c, "Silicon Wave"}, + { 2, 0xfd, "SandCraft"}, + { 2, 0xfe, "Elpida"}, + { 3, 0x01, "Solectron"}, + { 3, 0x02, "Optosys Technologies"}, + { 3, 0x83, "Buffalo (Formerly Melco)"}, + { 3, 0x04, "TriMedia Technologies"}, + { 3, 0x85, "Cyan Technologies"}, + { 3, 0x86, "Global Locate"}, + { 3, 0x07, "Optillion"}, + { 3, 0x08, "Terago Communications"}, + { 3, 0x89, "Ikanos Communications"}, + { 3, 0x8a, "Preton Technology"}, + { 3, 0x0b, "Nanya Technology"}, + { 3, 0x8c, "Elite Flash Storage"}, + { 3, 0x0d, "Mysticom"}, + { 3, 0x0e, "LightSand Communications"}, + { 3, 0x8f, "ATI Technologies"}, + { 3, 0x10, "Agere Systems"}, + { 3, 0x91, "NeoMagic"}, + { 3, 0x92, "AuroraNetics"}, + { 3, 0x13, "Geil"}, + { 3, 0x94, "Mushkin"}, + { 3, 0x15, "Tioga Technologies"}, + { 3, 0x16, "Netlist"}, + { 3, 0x97, "TeraLogic"}, + { 3, 0x98, "Cicada Semiconductor"}, + { 3, 0x19, "Centon Electronics"}, + { 3, 0x1a, "Tyco Electronics"}, + { 3, 0x9b, "Magis Works"}, + { 3, 0x1c, "Zettacom"}, + { 3, 0x9d, "Cogency Semiconductor"}, + { 3, 0x9e, "Chipcon AS"}, + { 3, 0x1f, "Aspex Technology"}, + { 3, 0x20, "F5 Networks"}, + { 3, 0xa1, "Programmable Silicon Solutions"}, + { 3, 0xa2, "ChipWrights"}, + { 3, 0x23, "Acorn Networks"}, + { 3, 0xa4, "Quicklogic"}, + { 3, 0x25, "Kingmax Semiconductor"}, + { 3, 0x26, "BOPS"}, + { 3, 0xa7, "Flasys"}, + { 3, 0xa8, "BitBlitz Communications"}, + { 3, 0x29, "eMemory Technology"}, + { 3, 0x2a, "Procket Networks"}, + { 3, 0xab, "Purple Ray"}, + { 3, 0x2c, "Trebia Networks"}, + { 3, 0xad, "Delta Electronics"}, + { 3, 0xae, "Onex Communications"}, + { 3, 0x2f, "Ample Communications"}, + { 3, 0xb0, "Memory Experts Intl"}, + { 3, 0x31, "Astute Networks"}, + { 3, 0x32, "Azanda Network Devices"}, + { 3, 0xb3, "Dibcom"}, + { 3, 0x34, "Tekmos"}, + { 3, 0xb5, "API NetWorks"}, + { 3, 0xb6, "Bay Microsystems"}, + { 3, 0x37, "Firecron"}, + { 3, 0x38, "Resonext Communications"}, + { 3, 0xb9, "Tachys Technologies"}, + { 3, 0xba, "Equator Technology"}, + { 3, 0x3b, "Concept Computer"}, + { 3, 0xbc, "SILCOM"}, + { 3, 0x3d, "3Dlabs"}, + { 3, 0x3e, "c?t Magazine"}, + { 3, 0xbf, "Sanera Systems"}, + { 3, 0x40, "Silicon Packets"}, + { 3, 0xc1, "Viasystems Group"}, + { 3, 0xc2, "Simtek"}, + { 3, 0x43, "Semicon Devices Singapore"}, + { 3, 0xc4, "Satron Handelsges"}, + { 3, 0x45, "Improv Systems"}, + { 3, 0x46, "INDUSYS"}, + { 3, 0xc7, "Corrent"}, + { 3, 0xc8, "Infrant Technologies"}, + { 3, 0x49, "Ritek Corp"}, + { 3, 0x4a, "empowerTel Networks"}, + { 3, 0xcb, "Hypertec"}, + { 3, 0x4c, "Cavium Networks"}, + { 3, 0xcd, "PLX Technology"}, + { 3, 0xce, "Massana Design"}, + { 3, 0x4f, "Intrinsity"}, + { 3, 0xd0, "Valence Semiconductor"}, + { 3, 0x51, "Terawave Communications"}, + { 3, 0x52, "IceFyre Semiconductor"}, + { 3, 0xd3, "Primarion"}, + { 3, 0x54, "Picochip Designs"}, + { 3, 0xd5, "Silverback Systems"}, + { 3, 0xd6, "Jade Star Technologies"}, + { 3, 0x57, "Pijnenburg Securealink"}, + { 3, 0x58, "takeMS International AG"}, + { 3, 0xd9, "Cambridge Silicon Radio"}, + { 3, 0xda, "Swissbit"}, + { 3, 0x5b, "Nazomi Communications"}, + { 3, 0xdc, "eWave System"}, + { 3, 0x5d, "Rockwell Collins"}, + { 3, 0x5e, "Picocel Co. (Paion)"}, + { 3, 0xdf, "Alphamosaic"}, + { 3, 0xe0, "Sandburst"}, + { 3, 0x61, "SiCon Video"}, + { 3, 0x62, "NanoAmp Solutions"}, + { 3, 0xe3, "Ericsson Technology"}, + { 3, 0x64, "PrairieComm"}, + { 3, 0xe5, "Mitac International"}, + { 3, 0xe6, "Layer N Networks"}, + { 3, 0x67, "MtekVision (Atsana)"}, + { 3, 0x68, "Allegro Networks"}, + { 3, 0xe9, "Marvell Semiconductors"}, + { 3, 0xea, "Netergy Microelectronic"}, + { 3, 0x6b, "NVIDIA"}, + { 3, 0xec, "Internet Machines"}, + { 3, 0x6d, "Peak Electronics"}, + { 3, 0x6e, "Litchfield Communication"}, + { 3, 0xef, "Accton Technology"}, + { 3, 0x70, "Teradiant Networks"}, + { 3, 0xf1, "Scaleo Chip"}, + { 3, 0xf2, "Cortina Systems"}, + { 3, 0x73, "RAM Components"}, + { 3, 0xf4, "Raqia Networks"}, + { 3, 0x75, "ClearSpeed"}, + { 3, 0x76, "Matsushita Battery"}, + { 3, 0xf7, "Xelerated"}, + { 3, 0xf8, "SimpleTech"}, + { 3, 0x79, "Utron Technology"}, + { 3, 0x7a, "Astec International"}, + { 3, 0xfb, "AVM"}, + { 3, 0x7c, "Redux Communications"}, + { 3, 0xfd, "Dot Hill Systems"}, + { 3, 0xfe, "TeraChip"}, + { 4, 0x01, "T-RAM"}, + { 4, 0x02, "Innovics Wireless"}, + { 4, 0x83, "Teknovus"}, + { 4, 0x04, "KeyEye Communications"}, + { 4, 0x85, "Runcom Technologies"}, + { 4, 0x86, "RedSwitch"}, + { 4, 0x07, "Dotcast"}, + { 4, 0x08, "Silicon Mountain Memory"}, + { 4, 0x89, "Signia Technologies"}, + { 4, 0x8a, "Pixim"}, + { 4, 0x0b, "Galazar Networks"}, + { 4, 0x8c, "White Electronic Designs"}, + { 4, 0x0d, "Patriot Scientific"}, + { 4, 0x0e, "Neoaxiom"}, + { 4, 0x8f, "3Y Power Technology"}, + { 4, 0x10, "Scaleo Chip"}, + { 4, 0x91, "Potentia Power Systems"}, + { 4, 0x92, "C-guys"}, + { 4, 0x13, "Digital Communications Technology"}, + { 4, 0x94, "Silicon-Based Technology"}, + { 4, 0x15, "Fulcrum Microsystems"}, + { 4, 0x16, "Positivo Informatica"}, + { 4, 0x97, "XIOtech"}, + { 4, 0x98, "PortalPlayer"}, + { 4, 0x19, "Zhiying Software"}, + { 4, 0x1a, "ParkerVision"}, + { 4, 0x9b, "Phonex Broadband"}, + { 4, 0x1c, "Skyworks Solutions"}, + { 4, 0x9d, "Entropic Communications"}, + { 4, 0x9e, "Pacific Force Technology"}, + { 4, 0x1f, "Zensys A/S"}, + { 4, 0x20, "Legend Silicon Corp."}, + { 4, 0xa1, "Sci-worx"}, + { 4, 0xa2, "SMSC (Standard Microsystems)"}, + { 4, 0x23, "Renesas Technology"}, + { 4, 0xa4, "Raza Microelectronics"}, + { 4, 0x25, "Phyworks"}, + { 4, 0x26, "MediaTek"}, + { 4, 0xa7, "Non-cents Productions"}, + { 4, 0xa8, "US Modular"}, + { 4, 0x29, "Wintegra"}, + { 4, 0x2a, "Mathstar"}, + { 4, 0xab, "StarCore"}, + { 4, 0x2c, "Oplus Technologies"}, + { 4, 0xad, "Mindspeed"}, + { 4, 0xae, "Just Young Computer"}, + { 4, 0x2f, "Radia Communications"}, + { 4, 0xb0, "OCZ"}, + { 4, 0x31, "Emuzed"}, + { 4, 0x32, "LOGIC Devices"}, + { 4, 0xb3, "Inphi"}, + { 4, 0x34, "Quake Technologies"}, + { 4, 0xb5, "Vixel"}, + { 4, 0xb6, "SolusTek"}, + { 4, 0x37, "Kongsberg Maritime"}, + { 4, 0x38, "Faraday Technology"}, + { 4, 0xb9, "Altium"}, + { 4, 0xba, "Insyte"}, + { 4, 0x3b, "ARM"}, + { 4, 0xbc, "DigiVision"}, + { 4, 0x3d, "Vativ Technologies"}, + { 4, 0x3e, "Endicott Interconnect Technologies"}, + { 4, 0xbf, "Pericom"}, + { 4, 0x40, "Bandspeed"}, + { 4, 0xc1, "LeWiz Communications"}, + { 4, 0xc2, "CPU Technology"}, + { 4, 0x43, "Ramaxel Technology"}, + { 4, 0xc4, "DSP Group"}, + { 4, 0x45, "Axis Communications"}, + { 4, 0x46, "Legacy Electronics"}, + { 4, 0xc7, "Chrontel"}, + { 4, 0xc8, "Powerchip Semiconductor"}, + { 4, 0x49, "MobilEye Technologies"}, + { 4, 0x4a, "Excel Semiconductor"}, + { 4, 0xcb, "A-DATA Technology"}, + { 4, 0x4c, "VirtualDigm"}, + { 4, 0xcd, "G Skill Intl"}, + { 4, 0xce, "Quanta Computer"}, + { 4, 0x4f, "Yield Microelectronics"}, + { 4, 0xd0, "Afa Technologies"}, + { 4, 0x51, "KINGBOX Technology Co."}, + { 4, 0x52, "Ceva"}, + { 4, 0xd3, "iStor Networks"}, + { 4, 0x54, "Advance Modules"}, + { 4, 0xd5, "Microsoft"}, + { 4, 0xd6, "Open-Silicon"}, + { 4, 0x57, "Goal Semiconductor"}, + { 4, 0x58, "ARC International"}, + { 4, 0xd9, "Simmtec"}, + { 4, 0xda, "Metanoia"}, + { 4, 0x5b, "Key Stream"}, + { 4, 0xdc, "Lowrance Electronics"}, + { 4, 0x5d, "Adimos"}, + { 4, 0x5e, "SiGe Semiconductor"}, + { 4, 0xdf, "Fodus Communications"}, + { 4, 0xe0, "Credence Systems Corp."}, + { 4, 0x61, "Genesis Microchip"}, + { 4, 0x62, "Vihana"}, + { 4, 0xe3, "WIS Technologies"}, + { 4, 0x64, "GateChange Technologies"}, + { 4, 0xe5, "High Density Devices AS"}, + { 4, 0xe6, "Synopsys"}, + { 4, 0x67, "Gigaram"}, + { 4, 0x68, "Enigma Semiconductor"}, + { 4, 0xe9, "Century Micro"}, + { 4, 0xea, "Icera Semiconductor"}, + { 4, 0x6b, "Mediaworks Integrated Systems"}, + { 4, 0xec, "O?Neil Product Development"}, + { 4, 0x6d, "Supreme Top Technology"}, + { 4, 0x6e, "MicroDisplay"}, + { 4, 0xef, "Team Group"}, + { 4, 0x70, "Sinett"}, + { 4, 0xf1, "Toshiba"}, + { 4, 0xf2, "Tensilica"}, + { 4, 0x73, "SiRF Technology"}, + { 4, 0xf4, "Bacoc"}, + { 4, 0x75, "SMaL Camera Technologies"}, + { 4, 0x76, "Thomson SC"}, + { 4, 0xf7, "Airgo Networks"}, + { 4, 0xf8, "Wisair"}, + { 4, 0x79, "SigmaTel"}, + { 4, 0x7a, "Arkados"}, + { 4, 0xfb, "Compete IT Co. KG"}, + { 4, 0x7c, "Eudar Technology"}, + { 4, 0xfd, "Focus Enhancements"}, + { 4, 0xfe, "Xyratex"}, + { 5, 0x01, "Specular Networks"}, + { 5, 0x02, "Patriot Memory (PDP Systems)"}, + { 5, 0x83, "U-Chip Technology Corp."}, + { 5, 0x04, "Silicon Optix"}, + { 5, 0x85, "Greenfield Networks"}, + { 5, 0x86, "CompuRAM"}, + { 5, 0x07, "Stargen"}, + { 5, 0x08, "NetCell"}, + { 5, 0x89, "Excalibrus Technologies"}, + { 5, 0x8a, "SCM Microsystems"}, + { 5, 0x0b, "Xsigo Systems"}, + { 5, 0x8c, "CHIPS & Systems"}, + { 5, 0x0d, "Tier"}, + { 5, 0x0e, "CWRL Labs"}, + { 5, 0x8f, "Teradici"}, + { 5, 0x10, "Gigaram"}, + { 5, 0x91, "g2 Microsystems"}, + { 5, 0x92, "PowerFlash Semiconductor"}, + { 5, 0x13, "P.A. Semi"}, + { 5, 0x94, "NovaTech Solutions, S.A."}, + { 5, 0x15, "c2 Microsystems"}, + { 5, 0x16, "Level5 Networks"}, + { 5, 0x97, "COS Memory AG"}, + { 5, 0x98, "Innovasic Semiconductor"}, + { 5, 0x19, "02IC Co."}, + { 5, 0x1a, "Tabula,"}, + { 5, 0x9b, "Crucial Technology"}, + { 5, 0x1c, "Chelsio Communications"}, + { 5, 0x9d, "Solarflare Communications"}, + { 5, 0x9e, "Xambala"}, + { 5, 0x1f, "EADS Astrium"}, + { 5, 0x20, "Terra Semiconductor"}, + { 5, 0xa1, "Imaging Works"}, + { 5, 0xa2, "Astute Networks"}, + { 5, 0x23, "Tzero"}, + { 5, 0xa4, "Emulex"}, + { 5, 0x25, "Power-One"}, + { 5, 0x26, "Pulse~LINK"}, + { 5, 0xa7, "Hon Hai Precision Industry"}, + { 5, 0xa8, "White Rock Networks"}, + { 5, 0x29, "Telegent Systems USA"}, + { 5, 0x2a, "Atrua Technologies"}, + { 5, 0xab, "Acbel Polytech"}, + { 5, 0x2c, "eRide"}, + { 5, 0xad, "ULi Electronics"}, + { 5, 0xae, "Magnum Semiconductor"}, + { 5, 0x2f, "neoOne Technology"}, + { 5, 0xb0, "Connex Technology"}, + { 5, 0x31, "Stream Processors"}, + { 5, 0x32, "Focus Enhancements"}, + { 5, 0xb3, "Telecis Wireless"}, + { 5, 0x34, "uNav Microelectronics"}, + { 5, 0xb5, "Tarari"}, + { 5, 0xb6, "Ambric"}, + { 5, 0x37, "Newport Media"}, + { 5, 0x38, "VMTS"}, + { 5, 0xb9, "Enuclia Semiconductor"}, + { 5, 0xba, "Virtium Technology"}, + { 5, 0x3b, "Solid State System Co."}, + { 5, 0xbc, "Kian Tech LLC"}, + { 5, 0x3d, "Artimi"}, + { 5, 0x3e, "Power Quotient International"}, + { 5, 0xbf, "Avago Technologies"}, + { 5, 0x40, "ADTechnology"}, + { 5, 0xc1, "Sigma Designs"}, + { 5, 0xc2, "SiCortex"}, + { 5, 0x43, "Ventura Technology Group"}, + { 5, 0xc4, "eASIC"}, + { 5, 0x45, "M.H.S. SAS"}, + { 5, 0x46, "Micro Star International"}, + { 5, 0xc7, "Rapport"}, + { 5, 0xc8, "Makway International"}, + { 5, 0x49, "Broad Reach Engineering Co."}, + { 5, 0x4a, "Semiconductor Mfg Intl Corp"}, + { 5, 0xcb, "SiConnect"}, + { 5, 0x4c, "FCI USA"}, + { 5, 0xcd, "Validity Sensors"}, + { 5, 0xce, "Coney Technology Co."}, + { 5, 0x4f, "Spans Logic"}, + { 5, 0xd0, "Neterion"}, + { 5, 0x51, "Qimonda"}, + { 5, 0x52, "New Japan Radio Co."}, + { 5, 0xd3, "Velogix"}, + { 5, 0x54, "Montalvo Systems"}, + { 5, 0xd5, "iVivity"}, + { 5, 0xd6, "Walton Chaintech"}, + { 5, 0x57, "AENEON"}, + { 5, 0x58, "Lorom Industrial Co."}, + { 5, 0xd9, "Radiospire Networks"}, + { 5, 0xda, "Sensio Technologies"}, + { 5, 0x5b, "Nethra Imaging"}, + { 5, 0xdc, "Hexon Technology Pte"}, + { 5, 0x5d, "CompuStocx (CSX)"}, + { 5, 0x5e, "Methode Electronics"}, + { 5, 0xdf, "Connect One"}, + { 5, 0xe0, "Opulan Technologies"}, + { 5, 0x61, "Septentrio NV"}, + { 5, 0x62, "Goldenmars Technology"}, + { 5, 0xe3, "Kreton"}, + { 5, 0x64, "Cochlear"}, + { 5, 0xe5, "Altair Semiconductor"}, + { 5, 0xe6, "NetEffect"}, + { 5, 0x67, "Spansion"}, + { 5, 0x68, "Taiwan Semiconductor Mfg"}, + { 5, 0xe9, "Emphany Systems"}, + { 5, 0xea, "ApaceWave Technologies"}, + { 5, 0x6b, "Mobilygen"}, + { 5, 0xec, "Tego"}, + { 5, 0x6d, "Cswitch"}, + { 5, 0x6e, "Haier (Beijing) IC Design Co."}, + { 5, 0xef, "MetaRAM"}, + { 5, 0x70, "Axel Electronics Co."}, + { 5, 0xf1, "Tilera"}, + { 5, 0xf2, "Aquantia"}, + { 5, 0x73, "Vivace Semiconductor"}, + { 5, 0xf4, "Redpine Signals"}, + { 5, 0x75, "Octalica"}, + { 5, 0x76, "InterDigital Communications"}, + { 5, 0xf7, "Avant Technology"}, + { 5, 0xf8, "Asrock"}, + { 5, 0x79, "Availink"}, + { 5, 0x7a, "Quartics"}, + { 5, 0xfb, "Element CXI"}, + { 5, 0x7c, "Innovaciones Microelectronicas"}, + { 5, 0xfd, "VeriSilicon Microelectronics"}, + { 5, 0xfe, "W5 Networks"}, + { 6, 0x01, "MOVEKING"}, + { 6, 0x02, "Mavrix Technology"}, + { 6, 0x83, "CellGuide"}, + { 6, 0x04, "Faraday Technology"}, + { 6, 0x85, "Diablo Technologies"}, + { 6, 0x86, "Jennic"}, + { 6, 0x07, "Octasic"}, + { 6, 0x08, "Molex"}, + { 6, 0x89, "3Leaf Networks"}, + { 6, 0x8a, "Bright Micron Technology"}, + { 6, 0x0b, "Netxen"}, + { 6, 0x8c, "NextWave Broadband"}, + { 6, 0x0d, "DisplayLink"}, + { 6, 0x0e, "ZMOS Technology"}, + { 6, 0x8f, "Tec-Hill"}, + { 6, 0x10, "Multigig"}, + { 6, 0x91, "Amimon"}, + { 6, 0x92, "Euphonic Technologies"}, + { 6, 0x13, "BRN Phoenix"}, + { 6, 0x94, "InSilica"}, + { 6, 0x15, "Ember"}, + { 6, 0x16, "Avexir Technologies"}, + { 6, 0x97, "Echelon"}, + { 6, 0x98, "Edgewater Computer Systems"}, + { 6, 0x19, "XMOS Semiconductor"}, + { 6, 0x1a, "GENUSION"}, + { 6, 0x9b, "Memory Corp NV"}, + { 6, 0x1c, "SiliconBlue Technologies"}, + { 6, 0x9d, "Rambus"}, + { 6, 0x9e, "Andes Technology"}, + { 6, 0x1f, "Coronis Systems"}, + { 6, 0x20, "Achronix Semiconductor"}, + { 6, 0xa1, "Siano Mobile Silicon"}, + { 6, 0xa2, "Semtech"}, + { 6, 0x23, "Pixelworks"}, + { 6, 0xa4, "Gaisler Research AB"}, + { 6, 0x25, "Teranetics"}, + { 6, 0x26, "Toppan Printing Co."}, + { 6, 0xa7, "Kingxcon"}, + { 6, 0xa8, "Silicon Integrated Systems"}, + { 6, 0x29, "I-O Data Device"}, + { 6, 0x2a, "NDS Americas"}, + { 6, 0xab, "Solomon Systech Limited"}, + { 6, 0x2c, "On Demand Microelectronics"}, + { 6, 0xad, "Amicus Wireless"}, + { 6, 0xae, "SMARDTV SNC"}, + { 6, 0x2f, "Comsys Communication"}, + { 6, 0xb0, "Movidia"}, + { 6, 0x31, "Javad GNSS"}, + { 6, 0x32, "Montage Technology Group"}, + { 6, 0xb3, "Trident Microsystems"}, + { 6, 0x34, "Super Talent"}, + { 6, 0xb5, "Optichron"}, + { 6, 0xb6, "Future Waves UK"}, + { 6, 0x37, "SiBEAM"}, + { 6, 0x38, "Inicore,"}, + { 6, 0xb9, "Virident Systems"}, + { 6, 0xba, "M2000"}, + { 6, 0x3b, "ZeroG Wireless"}, + { 6, 0xbc, "Gingle Technology Co."}, + { 6, 0x3d, "Space Micro"}, + { 6, 0x3e, "Wilocity"}, + { 6, 0xbf, "Novafora, Ic."}, + { 6, 0x40, "iKoa"}, + { 6, 0xc1, "ASint Technology"}, + { 6, 0xc2, "Ramtron"}, + { 6, 0x43, "Plato Networks"}, + { 6, 0xc4, "IPtronics AS"}, + { 6, 0x45, "Infinite-Memories"}, + { 6, 0x46, "Parade Technologies"}, + { 6, 0xc7, "Dune Networks"}, + { 6, 0xc8, "GigaDevice Semiconductor"}, + { 6, 0x49, "Modu"}, + { 6, 0x4a, "CEITEC"}, + { 6, 0xcb, "Northrop Grumman"}, + { 6, 0x4c, "XRONET"}, + { 6, 0xcd, "Sicon Semiconductor AB"}, + { 6, 0xce, "Atla Electronics Co."}, + { 6, 0x4f, "TOPRAM Technology"}, + { 6, 0xd0, "Silego Technology"}, + { 6, 0x51, "Kinglife"}, + { 6, 0x52, "Ability Industries"}, + { 6, 0xd3, "Silicon Power Computer & Communications"}, + { 6, 0x54, "Augusta Technology"}, + { 6, 0xd5, "Nantronics Semiconductors"}, + { 6, 0xd6, "Hilscher Gesellschaft"}, + { 6, 0x57, "Quixant"}, + { 6, 0x58, "Percello"}, + { 6, 0xd9, "NextIO"}, + { 6, 0xda, "Scanimetrics"}, + { 6, 0x5b, "FS-Semi Company"}, + { 6, 0xdc, "Infinera"}, + { 6, 0x5d, "SandForce"}, + { 6, 0x5e, "Lexar Media"}, + { 6, 0xdf, "Teradyne"}, + { 6, 0xe0, "Memory Exchange Corp."}, + { 6, 0x61, "Suzhou Smartek Electronics"}, + { 6, 0x62, "Avantium"}, + { 6, 0xe3, "ATP Electronics"}, + { 6, 0x64, "Valens Semiconductor"}, + { 6, 0xe5, "Agate Logic"}, + { 6, 0xe6, "Netronome"}, + { 6, 0x67, "Zenverge"}, + { 6, 0x68, "N-trig"}, + { 6, 0xe9, "SanMax Technologies"}, + { 6, 0xea, "Contour Semiconductor"}, + { 6, 0x6b, "TwinMOS"}, + { 6, 0xec, "Silicon Systems"}, + { 6, 0x6d, "V-Color Technology"}, + { 6, 0x6e, "Certicom"}, + { 6, 0xef, "JSC ICC Milandr"}, + { 6, 0x70, "PhotoFast Global"}, + { 6, 0xf1, "InnoDisk"}, + { 6, 0xf2, "Muscle Power"}, + { 6, 0x73, "Energy Micro"}, + { 6, 0xf4, "Innofidei"}, + { 9, 0xff, ""} +}; + +#define VEN_MAP_SIZE (sizeof(vendorMap)/sizeof(VenIdName)) + +#endif Index: branches/slice/rev749/libsaio/msdos_private.h =================================================================== --- branches/slice/rev749/libsaio/msdos_private.h (revision 0) +++ branches/slice/rev749/libsaio/msdos_private.h (revision 1169) @@ -0,0 +1,351 @@ +/* + * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 2.0 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Written by Paul Popelka (paulp@uts.amdahl.com) + * + * You can do anything you want with this software, just don't say you wrote + * it, and don't remove this notice. + * + * This software is provided "as is". + * + * The author supplies this software to be publicly redistributed on the + * understanding that the author is not responsible for the correct + * functioning of this software in any circumstances and is not liable for + * any damages caused by this software. + * + * October 1992 + */ + +/* + * Format of a boot sector. This is the first sector on a DOS floppy disk + * or the fist sector of a partition on a hard disk. But, it is not the + * first sector of a partitioned hard disk. + */ +struct bootsector33 { + u_int8_t bsJump[3]; /* jump inst E9xxxx or EBxx90 */ + int8_t bsOemName[8]; /* OEM name and version */ + int8_t bsBPB[19]; /* BIOS parameter block */ + int8_t bsDriveNumber; /* drive number (0x80) */ + int8_t bsBootCode[479]; /* pad so struct is 512b */ + u_int8_t bsBootSectSig0; + u_int8_t bsBootSectSig1; +#define BOOTSIG0 0x55 +#define BOOTSIG1 0xaa +}; + +struct extboot { + int8_t exDriveNumber; /* drive number (0x80) */ + int8_t exReserved1; /* reserved */ + int8_t exBootSignature; /* ext. boot signature (0x29) */ +#define EXBOOTSIG 0x29 + int8_t exVolumeID[4]; /* volume ID number */ + int8_t exVolumeLabel[11]; /* volume label */ + int8_t exFileSysType[8]; /* fs type (FAT12 or FAT16) */ +}; + +struct bootsector50 { + u_int8_t bsJump[3]; /* jump inst E9xxxx or EBxx90 */ + int8_t bsOemName[8]; /* OEM name and version */ + int8_t bsBPB[25]; /* BIOS parameter block */ + int8_t bsExt[26]; /* Bootsector Extension */ + int8_t bsBootCode[448]; /* pad so structure is 512b */ + u_int8_t bsBootSectSig0; + u_int8_t bsBootSectSig1; +#define BOOTSIG0 0x55 +#define BOOTSIG1 0xaa +}; + +struct bootsector710 { + u_int8_t bsJump[3]; /* jump inst E9xxxx or EBxx90 */ + int8_t bsOEMName[8]; /* OEM name and version */ + int8_t bsBPB[53]; /* BIOS parameter block */ + int8_t bsExt[26]; /* Bootsector Extension */ + int8_t bsBootCode[420]; /* pad so structure is 512b */ + u_int8_t bsBootSectSig0; + u_int8_t bsBootSectSig1; +#define BOOTSIG0 0x55 +#define BOOTSIG1 0xaa +}; + +union bootsector { + struct bootsector33 bs33; + struct bootsector50 bs50; + struct bootsector710 bs710; +}; + + +/* BPB */ + +/* + * BIOS Parameter Block (BPB) for DOS 3.3 + */ +struct bpb33 { + u_int16_t bpbBytesPerSec; /* bytes per sector */ + u_int8_t bpbSecPerClust; /* sectors per cluster */ + u_int16_t bpbResSectors; /* number of reserved sectors */ + u_int8_t bpbFATs; /* number of FATs */ + u_int16_t bpbRootDirEnts; /* number of root directory entries */ + u_int16_t bpbSectors; /* total number of sectors */ + u_int8_t bpbMedia; /* media descriptor */ + u_int16_t bpbFATsecs; /* number of sectors per FAT */ + u_int16_t bpbSecPerTrack; /* sectors per track */ + u_int16_t bpbHeads; /* number of heads */ + u_int16_t bpbHiddenSecs; /* number of hidden sectors */ +} __attribute__((packed)); + +/* + * BPB for DOS 5.0 The difference is bpbHiddenSecs is a short for DOS 3.3, + * and bpbHugeSectors is not in the 3.3 bpb. + */ +struct bpb50 { + u_int16_t bpbBytesPerSec; /* bytes per sector */ + u_int8_t bpbSecPerClust; /* sectors per cluster */ + u_int16_t bpbResSectors; /* number of reserved sectors */ + u_int8_t bpbFATs; /* number of FATs */ + u_int16_t bpbRootDirEnts; /* number of root directory entries */ + u_int16_t bpbSectors; /* total number of sectors */ + u_int8_t bpbMedia; /* media descriptor */ + u_int16_t bpbFATsecs; /* number of sectors per FAT */ + u_int16_t bpbSecPerTrack; /* sectors per track */ + u_int16_t bpbHeads; /* number of heads */ + u_int32_t bpbHiddenSecs; /* # of hidden sectors */ + u_int32_t bpbHugeSectors; /* # of sectors if bpbSectors == 0 */ +} __attribute__((packed)); + +/* + * BPB for DOS 7.10 (FAT32). This one has a few extensions to bpb50. + */ +struct bpb710 { + u_int16_t bpbBytesPerSec; /* bytes per sector */ + u_int8_t bpbSecPerClust; /* sectors per cluster */ + u_int16_t bpbResSectors; /* number of reserved sectors */ + u_int8_t bpbFATs; /* number of FATs */ + u_int16_t bpbRootDirEnts; /* number of root directory entries */ + u_int16_t bpbSectors; /* total number of sectors */ + u_int8_t bpbMedia; /* media descriptor */ + u_int16_t bpbFATsecs; /* number of sectors per FAT */ + u_int16_t bpbSecPerTrack; /* sectors per track */ + u_int16_t bpbHeads; /* number of heads */ + u_int32_t bpbHiddenSecs; /* # of hidden sectors */ + u_int32_t bpbHugeSectors; /* # of sectors if bpbSectors == 0 */ + u_int32_t bpbBigFATsecs; /* like bpbFATsecs for FAT32 */ + u_int16_t bpbExtFlags; /* extended flags: */ +#define FATNUM 0xf /* mask for numbering active FAT */ +#define FATMIRROR 0x80 /* FAT is mirrored (like it always was) */ + u_int16_t bpbFSVers; /* filesystem version */ +#define FSVERS 0 /* currently only 0 is understood */ + u_int32_t bpbRootClust; /* start cluster for root directory */ + u_int16_t bpbFSInfo; /* filesystem info structure sector */ + u_int16_t bpbBackup; /* backup boot sector */ + /* There is a 12 byte filler here, but we ignore it */ +} __attribute__((packed)); + +#if 0 +/* + * BIOS Parameter Block (BPB) for DOS 3.3 + */ +struct byte_bpb33 { + int8_t bpbBytesPerSec[2]; /* bytes per sector */ + int8_t bpbSecPerClust; /* sectors per cluster */ + int8_t bpbResSectors[2]; /* number of reserved sectors */ + int8_t bpbFATs; /* number of FATs */ + int8_t bpbRootDirEnts[2]; /* number of root directory entries */ + int8_t bpbSectors[2]; /* total number of sectors */ + int8_t bpbMedia; /* media descriptor */ + int8_t bpbFATsecs[2]; /* number of sectors per FAT */ + int8_t bpbSecPerTrack[2]; /* sectors per track */ + int8_t bpbHeads[2]; /* number of heads */ + int8_t bpbHiddenSecs[2]; /* number of hidden sectors */ +}; + +/* + * BPB for DOS 5.0 The difference is bpbHiddenSecs is a short for DOS 3.3, + * and bpbHugeSectors is not in the 3.3 bpb. + */ +struct byte_bpb50 { + int8_t bpbBytesPerSec[2]; /* bytes per sector */ + int8_t bpbSecPerClust; /* sectors per cluster */ + int8_t bpbResSectors[2]; /* number of reserved sectors */ + int8_t bpbFATs; /* number of FATs */ + int8_t bpbRootDirEnts[2]; /* number of root directory entries */ + int8_t bpbSectors[2]; /* total number of sectors */ + int8_t bpbMedia; /* media descriptor */ + int8_t bpbFATsecs[2]; /* number of sectors per FAT */ + int8_t bpbSecPerTrack[2]; /* sectors per track */ + int8_t bpbHeads[2]; /* number of heads */ + int8_t bpbHiddenSecs[4]; /* number of hidden sectors */ + int8_t bpbHugeSectors[4]; /* # of sectors if bpbSectors == 0 */ +}; + +/* + * BPB for DOS 7.10 (FAT32). This one has a few extensions to bpb50. + */ +struct byte_bpb710 { + u_int8_t bpbBytesPerSec[2]; /* bytes per sector */ + u_int8_t bpbSecPerClust; /* sectors per cluster */ + u_int8_t bpbResSectors[2]; /* number of reserved sectors */ + u_int8_t bpbFATs; /* number of FATs */ + u_int8_t bpbRootDirEnts[2]; /* number of root directory entries */ + u_int8_t bpbSectors[2]; /* total number of sectors */ + u_int8_t bpbMedia; /* media descriptor */ + u_int8_t bpbFATsecs[2]; /* number of sectors per FAT */ + u_int8_t bpbSecPerTrack[2]; /* sectors per track */ + u_int8_t bpbHeads[2]; /* number of heads */ + u_int8_t bpbHiddenSecs[4]; /* # of hidden sectors */ + u_int8_t bpbHugeSectors[4]; /* # of sectors if bpbSectors == 0 */ + u_int8_t bpbBigFATsecs[4]; /* like bpbFATsecs for FAT32 */ + u_int8_t bpbExtFlags[2]; /* extended flags: */ + u_int8_t bpbFSVers[2]; /* filesystem version */ + u_int8_t bpbRootClust[4]; /* start cluster for root directory */ + u_int8_t bpbFSInfo[2]; /* filesystem info structure sector */ + u_int8_t bpbBackup[2]; /* backup boot sector */ + /* There is a 12 byte filler here, but we ignore it */ +}; +#endif + +/* + * FAT32 FSInfo block. + */ +struct fsinfo { + u_int8_t fsisig1[4]; + u_int8_t fsifill1[480]; + u_int8_t fsisig2[4]; + u_int8_t fsinfree[4]; + u_int8_t fsinxtfree[4]; + u_int8_t fsifill2[12]; + u_int8_t fsisig3[4]; +}; + + +/* direntry */ + +/*- + * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. + * Copyright (C) 1994, 1995, 1997 TooLs GmbH. + * All rights reserved. + * Original code by Paul Popelka (paulp@uts.amdahl.com) (see above). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Structure of a dos directory entry. + */ +struct direntry { + u_int8_t deName[8]; /* filename, blank filled */ +#define SLOT_EMPTY 0x00 /* slot has never been used */ +#define SLOT_E5 0x05 /* the real value is 0xe5 */ +#define SLOT_DELETED 0xe5 /* file in this slot deleted */ + u_int8_t deExtension[3]; /* extension, blank filled */ + u_int8_t deAttributes; /* file attributes */ +#define ATTR_NORMAL 0x00 /* normal file */ +#define ATTR_READONLY 0x01 /* file is read-only (immutable) */ +#define ATTR_HIDDEN 0x02 /* file is hidden */ +#define ATTR_SYSTEM 0x04 /* file is a system file */ +#define ATTR_VOLUME 0x08 /* entry is a volume label */ +#define ATTR_DIRECTORY 0x10 /* entry is a directory name */ +#define ATTR_ARCHIVE 0x20 /* file is new or modified */ + u_int8_t deLowerCase; /* NT VFAT lower case flags */ +#define LCASE_BASE 0x08 /* filename base in lower case */ +#define LCASE_EXT 0x10 /* filename extension in lower case */ + u_int8_t deCHundredth; /* hundredth of seconds in CTime */ + u_int8_t deCTime[2]; /* create time */ + u_int8_t deCDate[2]; /* create date */ + u_int8_t deADate[2]; /* access date */ + u_int8_t deHighClust[2]; /* high bytes of cluster number */ + u_int16_t deMTime; /* last update time */ + u_int16_t deMDate; /* last update date */ + u_int8_t deStartCluster[2]; /* starting cluster of file */ + u_int8_t deFileSize[4]; /* size of file in bytes */ +}; + +/* + * Structure of a Win95 long name directory entry + */ +struct winentry { + u_int8_t weCnt; +#define WIN_LAST 0x40 +#define WIN_CNT 0x3f + u_int8_t wePart1[10]; + u_int8_t weAttributes; +#define ATTR_WIN95 0x0f + u_int8_t weReserved1; + u_int8_t weChksum; + u_int8_t wePart2[12]; + u_int16_t weReserved2; + u_int8_t wePart3[4]; +}; +#define WIN_CHARS 13 /* Number of chars per winentry */ + +/* + * Maximum filename length in Win95 + * Note: Must be < sizeof(dirent.d_name) + */ +#define WIN_MAXLEN 255 + +/* + * This is the format of the contents of the deTime field in the direntry + * structure. + * We don't use bitfields because we don't know how compilers for + * arbitrary machines will lay them out. + */ +#define DT_2SECONDS_MASK 0x1F /* seconds divided by 2 */ +#define DT_2SECONDS_SHIFT 0 +#define DT_MINUTES_MASK 0x7E0 /* minutes */ +#define DT_MINUTES_SHIFT 5 +#define DT_HOURS_MASK 0xF800 /* hours */ +#define DT_HOURS_SHIFT 11 + +/* + * This is the format of the contents of the deDate field in the direntry + * structure. + */ +#define DD_DAY_MASK 0x1F /* day of month */ +#define DD_DAY_SHIFT 0 +#define DD_MONTH_MASK 0x1E0 /* month */ +#define DD_MONTH_SHIFT 5 +#define DD_YEAR_MASK 0xFE00 /* year - 1980 */ +#define DD_YEAR_SHIFT 9 + Index: branches/slice/rev749/libsaio/table.c =================================================================== --- branches/slice/rev749/libsaio/table.c (revision 0) +++ branches/slice/rev749/libsaio/table.c (revision 1169) @@ -0,0 +1,102 @@ +/* + * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 2.0 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Mach Operating System + * Copyright (c) 1990 Carnegie-Mellon University + * Copyright (c) 1989 Carnegie-Mellon University + * All rights reserved. The CMU software License Agreement specifies + * the terms and conditions for use and redistribution. + */ + +/* + * INTEL CORPORATION PROPRIETARY INFORMATION + * + * This software is supplied under the terms of a license agreement or + * nondisclosure agreement with Intel Corporation and may not be copied + * nor disclosed except in accordance with the terms of that agreement. + * + * Copyright 1988, 1989 Intel Corporation + */ + +/* + * Copyright 1993 NeXT, Inc. + * All rights reserved. + */ + +#include "memory.h" + +/* Segment Descriptor + * + * 31 24 19 16 7 0 + * ------------------------------------------------------------ + * | | |B| |A| | | |1|0|E|W|A| | + * | BASE 31..24 |G|/|0|V| LIMIT |P|DPL| TYPE | BASE 23:16 | + * | | |D| |L| 19..16| | |1|1|C|R|A| | + * ------------------------------------------------------------ + * | | | + * | BASE 15..0 | LIMIT 15..0 | + * | | | + * ------------------------------------------------------------ + */ + +struct seg_desc { + unsigned short limit_15_0; + unsigned short base_15_0; + unsigned char base_23_16; + unsigned char bit_15_8; + unsigned char bit_23_16; + unsigned char base_31_24; +}; + +// turbo - GDT must be in first 64k segment +struct seg_desc __attribute__ ((section("__INIT,__data"))) Gdt[ NGDTENT ] = { + /* 0x0 : null */ + {0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00}, + + /* 0x8 : boot protected mode 32-bit code segment + byte granularity, 1MB limit, MEMBASE offset */ + //{0xFFFF, MEMBASE, 0x00, 0x9E, 0x4F, 0x00}, + {0xFFFF, 0x0000, 0x00, 0x9E, 0xCF, 0x00}, + // TODO: Restore the correct GDT 0x8 entry before exiting the bootloader + + /* 0x10 : boot protected mode data segment + page granularity, 4GB limit, MEMBASE offset */ + {0xFFFF, MEMBASE, 0x00, 0x92, 0xCF, 0x00}, + + /* 0x18 : boot protected mode 16-bit code segment + byte granularity, 1MB limit, MEMBASE offset */ + {0xFFFF, MEMBASE, 0x00, 0x9E, 0x0F, 0x00}, + + /* 0x20 : kernel init 32-bit data segment + page granularity, 4GB limit, zero offset */ + {0xFFFF, 0x0000, 0x00, 0x92, 0xCF, 0x00}, + + /* 0x28 : kernel init 32-bit code segment + page granularity, 4GB limit, zero offset */ + {0xFFFF, 0x0000, 0x00, 0x9E, 0xCF, 0x00}, + + /* 0x30 : boot real mode data/stack segment + byte granularity, 64K limit, MEMBASE offset, expand-up */ + {0xFFFF, MEMBASE, 0x00, 0x92, 0x00, 0x00}, +}; Index: branches/slice/rev749/libsaio/device_inject.c =================================================================== --- branches/slice/rev749/libsaio/device_inject.c (revision 0) +++ branches/slice/rev749/libsaio/device_inject.c (revision 1169) @@ -0,0 +1,401 @@ +/* + * Copyright 2009 Jasmin Fazlic All rights reserved. + */ +/* + * Cleaned and merged by iNDi + */ + +#include "libsaio.h" +#include "boot.h" +#include "bootstruct.h" +#include "pci.h" +#include "pci_root.h" +#include "device_inject.h" +#include "convert.h" + +#ifndef DEBUG_INJECT +#define DEBUG_INJECT 0 +#endif + +#if DEBUG_INJECT +#define DBG(x...) verbose(x) +#else +#define DBG(x...) +#endif + +uint32_t devices_number = 1; +uint32_t builtin_set = 0; +struct DevPropString *string = 0; +uint8_t *stringdata = 0; +uint32_t stringlength = 0; + +char *efi_inject_get_devprop_string(uint32_t *len) +{ + if(string) + { + *len = string->length; + return devprop_generate_string(string); + } + //verbose("efi_inject_get_devprop_string NULL trying stringdata\n"); + return NULL; +} + +void setupDeviceProperties(Node *node) +{ + const char *val; + uint8_t *binStr; + int cnt=0, cnt2=0; + + static char DEVICE_PROPERTIES_PROP[] = "device-properties"; + + /* Generate devprop string. + */ + uint32_t strlength = 0; + char *string = efi_inject_get_devprop_string(&strlength); + + /* Use the static "device-properties" boot config key contents if available, + * otheriwse use the generated one. + */ + if (!getValueForKey(kDeviceProperties, &val, &cnt, &bootInfo->bootConfig) && string) + { + val = (const char*)string; + cnt = strlength * 2; + } + + if (cnt > 1) + { + binStr = convertHexStr2Binary(val, &cnt2); + if (cnt2 > 0) DT__AddProperty(node, DEVICE_PROPERTIES_PROP, cnt2, binStr); + } +} + +struct DevPropString *devprop_create_string(void) +{ + string = (struct DevPropString*)malloc(sizeof(struct DevPropString)); + + if(string == NULL) + { + return NULL; + } + + memset(string, 0, sizeof(struct DevPropString)); + string->length = 12; + string->WHAT2 = 0x01000000; + return string; +} + +struct DevPropDevice *devprop_add_device(struct DevPropString *string, char *path) +{ + struct DevPropDevice *device; + const char pciroot_string[] = "PciRoot(0x"; + const char pci_device_string[] = "Pci(0x"; + + if (string == NULL || path == NULL) { + return NULL; + } + device = malloc(sizeof(struct DevPropDevice)); + + if (strncmp(path, pciroot_string, strlen(pciroot_string))) { + verbose("ERROR parsing device path\n"); + return NULL; + } + + memset(device, 0, sizeof(struct DevPropDevice)); + device->acpi_dev_path._UID = getPciRootUID(); + + int numpaths = 0; + int x, curr = 0; + char buff[] = "00"; + + for (x = 0; x < strlen(path); x++) + { + if (!strncmp(&path[x], pci_device_string, strlen(pci_device_string))) + { + x+=strlen(pci_device_string); + curr=x; + while(path[++x] != ','); + if(x-curr == 2) + { + sprintf(buff, "%c%c", path[curr], path[curr+1]); + } + else if(x-curr == 1) + { + sprintf(buff, "%c", path[curr]); + } + else + { + verbose("ERROR parsing device path\n"); + numpaths = 0; + break; + } + device->pci_dev_path[numpaths].device = ascii_hex_to_int(buff); + + x += 3; // 0x + curr = x; + while(path[++x] != ')'); + if(x-curr == 2) + { + sprintf(buff, "%c%c", path[curr], path[curr+1]); + } + else if(x-curr == 1) + { + sprintf(buff, "%c", path[curr]); + } + else + { + verbose("ERROR parsing device path\n"); + numpaths = 0; + break; + } + device->pci_dev_path[numpaths].function = ascii_hex_to_int(buff); // TODO: find dev from char *path + + numpaths++; + } + } + + if(!numpaths) + { + return NULL; + } + + device->numentries = 0x00; + + device->acpi_dev_path.length = 0x0c; + device->acpi_dev_path.type = 0x02; + device->acpi_dev_path.subtype = 0x01; + device->acpi_dev_path._HID = 0xd041030a; + + device->num_pci_devpaths = numpaths; + device->length = 24 + (6*numpaths); + + int i; + + for(i = 0; i < numpaths; i++) + { + device->pci_dev_path[i].length = 0x06; + device->pci_dev_path[i].type = 0x01; + device->pci_dev_path[i].subtype = 0x01; + } + + device->path_end.length = 0x04; + device->path_end.type = 0x7f; + device->path_end.subtype = 0xff; + + device->string = string; + device->data = NULL; + string->length += device->length; + + if(!string->entries) + { + if((string->entries = (struct DevPropDevice**)malloc(sizeof(device)))== NULL) + { + return 0; + } + } + + string->entries[string->numentries++] = (struct DevPropDevice*)malloc(sizeof(device)); + string->entries[string->numentries-1] = device; + + return device; +} + +int devprop_add_value(struct DevPropDevice *device, char *nm, uint8_t *vl, uint32_t len) +{ + + if(!nm || !vl || !len) + { + return 0; + } + + uint32_t length = ((strlen(nm) * 2) + len + (2 * sizeof(uint32_t)) + 2); + uint8_t *data = (uint8_t*)malloc(length); + { + if(!data) + { + return 0; + } + + memset(data, 0, length); + uint32_t off= 0; + data[off+1] = ((strlen(nm) * 2) + 6) >> 8; + data[off] = ((strlen(nm) * 2) + 6) & 0x00FF; + + off += 4; + uint32_t i=0, l = strlen(nm); + for(i = 0 ; i < l ; i++, off += 2) + { + data[off] = *nm++; + } + + off += 2; + l = len; + uint32_t *datalength = (uint32_t*)&data[off]; + *datalength = l + 4; + off += 4; + for(i = 0 ; i < l ; i++, off++) + { + data[off] = *vl++; + } + } + + uint32_t offset = device->length - (24 + (6 * device->num_pci_devpaths)); + + uint8_t *newdata = (uint8_t*)malloc((length + offset)); + if(!newdata) + { + return 0; + } + if(device->data) + { + if(offset > 1) + { + memcpy(newdata, device->data, offset); + } + } + + memcpy(newdata + offset, data, length); + + device->length += length; + device->string->length += length; + device->numentries++; + + if(!device->data) + { + device->data = (uint8_t*)malloc(sizeof(uint8_t)); + } + else + { + free(device->data); + } + + free(data); + device->data = newdata; + + return 1; +} + +char *devprop_generate_string(struct DevPropString *string) +{ + char *buffer = (char*)malloc(string->length * 2); + char *ptr = buffer; + + if(!buffer) + { + return NULL; + } + + sprintf(buffer, "%08x%08x%04x%04x", dp_swap32(string->length), string->WHAT2, + dp_swap16(string->numentries), string->WHAT3); + buffer += 24; + int i = 0, x = 0; + + while(i < string->numentries) + { + sprintf(buffer, "%08x%04x%04x", dp_swap32(string->entries[i]->length), + dp_swap16(string->entries[i]->numentries), string->entries[i]->WHAT2); + + buffer += 16; + sprintf(buffer, "%02x%02x%04x%08x%08x", string->entries[i]->acpi_dev_path.type, + string->entries[i]->acpi_dev_path.subtype, + dp_swap16(string->entries[i]->acpi_dev_path.length), + string->entries[i]->acpi_dev_path._HID, + dp_swap32(string->entries[i]->acpi_dev_path._UID)); + + buffer += 24; + for(x=0;x < string->entries[i]->num_pci_devpaths; x++) + { + sprintf(buffer, "%02x%02x%04x%02x%02x", string->entries[i]->pci_dev_path[x].type, + string->entries[i]->pci_dev_path[x].subtype, + dp_swap16(string->entries[i]->pci_dev_path[x].length), + string->entries[i]->pci_dev_path[x].function, + string->entries[i]->pci_dev_path[x].device); + buffer += 12; + } + + sprintf(buffer, "%02x%02x%04x", string->entries[i]->path_end.type, + string->entries[i]->path_end.subtype, + dp_swap16(string->entries[i]->path_end.length)); + + buffer += 8; + uint8_t *dataptr = string->entries[i]->data; + for(x = 0; x < (string->entries[i]->length) - (24 + (6 * string->entries[i]->num_pci_devpaths)) ; x++) + { + sprintf(buffer, "%02x", *dataptr++); + buffer += 2; + } + i++; + } + return ptr; +} + +void devprop_free_string(struct DevPropString *string) +{ + if(!string) + { + return; + } + + int i; + for(i = 0; i < string->numentries; i++) + { + if(string->entries[i]) + { + if(string->entries[i]->data) + { + free(string->entries[i]->data); + string->entries[i]->data = NULL; + } + free(string->entries[i]); + string->entries[i] = NULL; + } + } + + free(string); + string = NULL; +} + +/* a fine place for this code */ +//Slice - now it is not needed? +int devprop_add_network_template(struct DevPropDevice *device, uint16_t vendor_id) +{ + if(!device) + return 0; + uint8_t builtin = 0x0; + char tmp[10]; + if((vendor_id != 0x168c) && (builtin_set == 0)) + { + builtin_set = 1; + builtin = 0x01; + } + if(!devprop_add_value(device, "built-in", (uint8_t*)&builtin, 1)) + return 0; + sprintf(tmp, "Slot-%x",devices_number); // 1 - vga card. FIXME - for 2+ vgas + if(!devprop_add_value(device, "AAPL,slot-name", (uint8_t*)&tmp, strlen(tmp))) + return 0; + devices_number++; + return 1; +} + +void set_eth_builtin(pci_dt_t *eth_dev) +{ + char *devicepath = get_pci_dev_path(eth_dev); + struct DevPropDevice *device = (struct DevPropDevice*)malloc(sizeof(struct DevPropDevice)); + + verbose("LAN Controller [%04x:%04x] :: %s\n", eth_dev->vendor_id, eth_dev->device_id, devicepath); + + if (!string) + string = devprop_create_string(); + + device = devprop_add_device(string, devicepath); + if(device) + { + verbose("Setting up lan keys\n"); + devprop_add_network_template(device, eth_dev->vendor_id); + stringdata = (uint8_t*)malloc(sizeof(uint8_t) * string->length); + if(stringdata) + { + memcpy(stringdata, (uint8_t*)devprop_generate_string(string), string->length); + stringlength = string->length; + } + } +} Index: branches/slice/rev749/libsaio/device_inject.h =================================================================== --- branches/slice/rev749/libsaio/device_inject.h (revision 0) +++ branches/slice/rev749/libsaio/device_inject.h (revision 1169) @@ -0,0 +1,74 @@ +/* + * Copyright 2009 Jasmin Fazlic All rights reserved. + */ +/* + * Cleaned and merged by iNDi + */ + +#ifndef __LIBSAIO_DEVICE_INJECT_H +#define __LIBSAIO_DEVICE_INJECT_H + +#define DP_ADD_TEMP_VAL(dev, val) devprop_add_value(dev, (char*)val[0], (uint8_t*)val[1], strlen(val[1]) + 1) +#define DP_ADD_TEMP_VAL_DATA(dev, val) devprop_add_value(dev, (char*)val.name, (uint8_t*)val.data, val.size) +#define MAX_PCI_DEV_PATHS 4 + +extern struct DevPropString *string; +extern uint8_t *stringdata; +extern uint32_t stringlength; +extern uint32_t devices_number; +extern void setupDeviceProperties(Node *node); + +struct ACPIDevPath { + uint8_t type; // = 2 ACPI device-path + uint8_t subtype; // = 1 ACPI Device-path + uint16_t length; // = 0x0c + uint32_t _HID; // = 0xD041030A ? + uint32_t _UID; // = 0x00000000 PCI ROOT +}; + +struct PCIDevPath { + uint8_t type; // = 1 Hardware device-path + uint8_t subtype; // = 1 PCI + uint16_t length; // = 6 + uint8_t function; // pci func number + uint8_t device; // pci dev number +}; + +struct DevicePathEnd { + uint8_t type; // = 0x7f + uint8_t subtype; // = 0xff + uint16_t length; // = 4; +}; + +struct DevPropDevice { + uint32_t length; + uint16_t numentries; + uint16_t WHAT2; // 0x0000 ? + struct ACPIDevPath acpi_dev_path; // = 0x02010c00 0xd041030a + struct PCIDevPath pci_dev_path[MAX_PCI_DEV_PATHS]; // = 0x01010600 func dev + struct DevicePathEnd path_end; // = 0x7fff0400 + uint8_t *data; + + // ------------------------ + uint8_t num_pci_devpaths; + struct DevPropString *string; + // ------------------------ +}; + +struct DevPropString { + uint32_t length; + uint32_t WHAT2; // 0x01000000 ? + uint16_t numentries; + uint16_t WHAT3; // 0x0000 ? + struct DevPropDevice **entries; +}; + +char *efi_inject_get_devprop_string(uint32_t *len); +int devprop_add_network_template(struct DevPropDevice *device, uint16_t vendor_id); +struct DevPropString *devprop_create_string(void); +struct DevPropDevice *devprop_add_device(struct DevPropString *string, char *path); +int devprop_add_value(struct DevPropDevice *device, char *nm, uint8_t *vl, uint32_t len); +char *devprop_generate_string(struct DevPropString *string); +void devprop_free_string(struct DevPropString *string); + +#endif /* !__LIBSAIO_DEVICE_INJECT_H */ Index: branches/slice/rev749/libsaio/fdisk.h =================================================================== --- branches/slice/rev749/libsaio/fdisk.h (revision 0) +++ branches/slice/rev749/libsaio/fdisk.h (revision 1169) @@ -0,0 +1,89 @@ +/* + * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 2.0 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1992 NeXT Computer, Inc. + * + * IBM PC disk partitioning data structures. + * + * HISTORY + * + * 8 July 1992 David E. Bohman at NeXT + * Created. + */ + +#ifndef __LIBSAIO_FDISK_H +#define __LIBSAIO_FDISK_H + +#define DISK_BLK0 0 /* blkno of boot block */ +#define DISK_BLK0SZ 512 /* size of boot block */ +#define DISK_BOOTSZ 446 /* size of boot code in boot block */ +#define DISK_SIGNATURE 0xAA55 /* signature of the boot record */ +#define FDISK_NPART 4 /* number of entries in fdisk table */ +#define FDISK_ACTIVE 0x80 /* indicator of active partition */ +#define FDISK_NEXTNAME 0xA7 /* indicator of NeXT partition */ +#define FDISK_DOS12 0x01 /* 12-bit fat < 10MB dos partition */ +#define FDISK_DOS16S 0x04 /* 16-bit fat < 32MB dos partition */ +#define FDISK_DOSEXT 0x05 /* extended dos partition */ +#define FDISK_DOS16B 0x06 /* 16-bit fat >= 32MB dos partition */ +#define FDISK_NTFS 0x07 /* NTFS partition */ +#define FDISK_SMALLFAT32 0x0b /* FAT32 partition */ +#define FDISK_FAT32 0x0c /* FAT32 partition */ +#define FDISK_DOS16SLBA 0x0e +#define FDISK_LINUX 0x83 +#define FDISK_UFS 0xa8 /* Apple UFS partition */ +#define FDISK_HFS 0xaf /* Apple HFS partition */ +#define FDISK_BOOTER 0xab /* Apple booter partition */ + +/* + * Format of fdisk partion entry (if present). + */ +struct fdisk_part { + unsigned char bootid; /* bootable or not */ + unsigned char beghead; /* begining head, sector, cylinder */ + unsigned char begsect; /* begcyl is a 10-bit number */ + unsigned char begcyl; /* High 2 bits are in begsect */ + unsigned char systid; /* OS type */ + unsigned char endhead; /* ending head, sector, cylinder */ + unsigned char endsect; /* endcyl is a 10-bit number */ + unsigned char endcyl; /* High 2 bits are in endsect */ + unsigned long relsect; /* partion physical offset on disk */ + unsigned long numsect; /* number of sectors in partition */ +} __attribute__((packed)); + +/* + * Format of boot block. + */ +struct disk_blk0 { + unsigned char bootcode[DISK_BOOTSZ]; + unsigned char parts[FDISK_NPART][sizeof (struct fdisk_part)]; + unsigned short signature; +}; + +struct REAL_disk_blk0 { + unsigned char bootcode[DISK_BOOTSZ]; + struct fdisk_part parts[FDISK_NPART]; + unsigned short signature; +} __attribute__((packed)); + +#endif /* !__LIBSAIO_FDISK_H */ Index: branches/slice/rev749/libsaio/ntfs.c =================================================================== --- branches/slice/rev749/libsaio/ntfs.c (revision 0) +++ branches/slice/rev749/libsaio/ntfs.c (revision 1169) @@ -0,0 +1,345 @@ +/* + * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Copyright (c) 1999-2004 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +#ifndef OPTION_ROM +#include "libsaio.h" +#include "sl.h" + +#define BYTE_ORDER_MARK 0xFEFF + +#include "ntfs_private.h" + +#define FS_TYPE "ntfs" +#define FS_NAME_FILE "NTFS" + +#define MAX_BLOCK_SIZE 2048 +#define MAX_CLUSTER_SIZE 32768 + +#define LABEL_LENGTH 1024 +#define UNKNOWN_LABEL "Untitled NTFS" + +#define FSUR_IO_FAIL -1 +#define FSUR_UNRECOGNIZED -1 +#define FSUR_RECOGNIZED 0 + +#define ERROR -1 + +/* + * Process per-sector "fixups" that NTFS uses to detect corruption of + * multi-sector data structures, like MFT records. + */ +static int +ntfs_fixup( + char *buf, + size_t len, + u_int32_t magic, + u_int32_t bytesPerSector) +{ + struct fixuphdr *fhp = (struct fixuphdr *) buf; + int i; + u_int16_t fixup; + u_int16_t *fxp; + u_int16_t *cfxp; + u_int32_t fixup_magic; + u_int16_t fixup_count; + u_int16_t fixup_offset; + + fixup_magic = OSReadLittleInt32(&fhp->fh_magic,0); + if (fixup_magic != magic) { + error("ntfs_fixup: magic doesn't match: %08x != %08x\n", + fixup_magic, magic); + return (ERROR); + } + fixup_count = OSReadLittleInt16(&fhp->fh_fnum,0); + if ((fixup_count - 1) * bytesPerSector != len) { + error("ntfs_fixup: " \ + "bad fixups number: %d for %ld bytes block\n", + fixup_count, (long)len); /* XXX printf kludge */ + return (ERROR); + } + fixup_offset = OSReadLittleInt16(&fhp->fh_foff,0); + if (fixup_offset >= len) { + error("ntfs_fixup: invalid offset: %x", fixup_offset); + return (ERROR); + } + fxp = (u_int16_t *) (buf + fixup_offset); + cfxp = (u_int16_t *) (buf + bytesPerSector - 2); + fixup = *fxp++; + for (i = 1; i < fixup_count; i++, fxp++) { + if (*cfxp != fixup) { + error("ntfs_fixup: fixup %d doesn't match\n", i); + return (ERROR); + } + *cfxp = *fxp; + cfxp = (u_int16_t *)(((caddr_t)cfxp) + bytesPerSector); + } + return (0); +} + +/* + * Find a resident attribute of a given type. Returns a pointer to the + * attribute data, and its size in bytes. + */ +static int +ntfs_find_attr( + char *buf, + u_int32_t attrType, + void **attrData, + size_t *attrSize) +{ + struct filerec *filerec; + struct attr *attr; + u_int16_t offset; + + filerec = (struct filerec *) buf; + offset = OSReadLittleInt16(&filerec->fr_attroff,0); + attr = (struct attr *) (buf + offset); + + /* Should we also check offset < buffer size? */ + while (attr->a_hdr.a_type != 0xFFFFFFFF) /* same for big/little endian */ + { + if (OSReadLittleInt32(&attr->a_hdr.a_type,0) == attrType) + { + if (attr->a_hdr.a_flag != 0) + { + //verbose("NTFS: attriubte 0x%X is non-resident\n", attrType); + return 1; + } + + *attrSize = OSReadLittleInt16(&attr->a_r.a_datalen,0); + *attrData = buf + offset + OSReadLittleInt16(&attr->a_r.a_dataoff,0); + return 0; /* found it! */ + } + + /* Skip to the next attribute */ + offset += OSReadLittleInt32(&attr->a_hdr.reclen,0); + attr = (struct attr *) (buf + offset); + } + + return 1; /* No matching attrType found */ +} + +/* + * Examine a volume to see if we recognize it as a mountable. + */ +void +NTFSGetDescription(CICell ih, char *str, long strMaxLen) +{ + struct bootfile *boot; + unsigned bytesPerSector; + unsigned sectorsPerCluster; + int mftRecordSize; + u_int64_t totalClusters; + u_int64_t cluster, mftCluster; + size_t mftOffset; + void *nameAttr; + size_t nameSize; + char *buf; + + buf = (char *)malloc(MAX_CLUSTER_SIZE); + if (buf == 0) { + goto error; + } + + /* + * Read the boot sector, check signatures, and do some minimal + * sanity checking. NOTE: the size of the read below is intended + * to be a multiple of all supported block sizes, so we don't + * have to determine or change the device's block size. + */ + Seek(ih, 0); + Read(ih, (long)buf, MAX_BLOCK_SIZE); + + boot = (struct bootfile *) buf; + + /* + * The first three bytes are an Intel x86 jump instruction. I assume it + * can be the same forms as DOS FAT: + * 0xE9 0x?? 0x?? + * 0xEC 0x?? 0x90 + * where 0x?? means any byte value is OK. + */ + if (boot->reserved1[0] != 0xE9 + && (boot->reserved1[0] != 0xEB || boot->reserved1[2] != 0x90)) + { + goto error; + } + + /* + * Check the "NTFS " signature. + */ + if (memcmp((const char *)boot->bf_sysid, "NTFS ", 8) != 0) + { + goto error; + } + + /* + * Make sure the bytes per sector and sectors per cluster are + * powers of two, and within reasonable ranges. + */ + bytesPerSector = OSReadLittleInt16(&boot->bf_bps,0); + if ((bytesPerSector & (bytesPerSector-1)) || bytesPerSector < 512 || bytesPerSector > 32768) + { + //verbose("NTFS: invalid bytes per sector (%d)\n", bytesPerSector); + goto error; + } + + sectorsPerCluster = boot->bf_spc; /* Just one byte; no swapping needed */ + if ((sectorsPerCluster & (sectorsPerCluster-1)) || sectorsPerCluster > 128) + { + //verbose("NTFS: invalid sectors per cluster (%d)\n", bytesPerSector); + goto error; + } + + /* + * Calculate the number of clusters from the number of sectors. + * Then bounds check the $MFT and $MFTMirr clusters. + */ + totalClusters = OSReadLittleInt64(&boot->bf_spv,0) / sectorsPerCluster; + mftCluster = OSReadLittleInt64(&boot->bf_mftcn,0); + if (mftCluster > totalClusters) + { + ////verbose("NTFS: invalid $MFT cluster (%lld)\n", mftCluster); + goto error; + } + cluster = OSReadLittleInt64(&boot->bf_mftmirrcn,0); + if (cluster > totalClusters) + { + //verbose("NTFS: invalid $MFTMirr cluster (%lld)\n", cluster); + goto error; + } + + /* + * Determine the size of an MFT record. + */ + mftRecordSize = (int8_t) boot->bf_mftrecsz; + if (mftRecordSize < 0) + mftRecordSize = 1 << -mftRecordSize; + else + mftRecordSize *= bytesPerSector * sectorsPerCluster; + //verbose("NTFS: MFT record size = %d\n", mftRecordSize); + + /* + * Read the MFT record for $Volume. This assumes the first four + * file records in the MFT are contiguous; if they aren't, we + * would have to map the $MFT itself. + * + * This will fail if the device sector size is larger than the + * MFT record size, since the $Volume record won't be aligned + * on a sector boundary. + */ + mftOffset = mftCluster * sectorsPerCluster * bytesPerSector; + mftOffset += mftRecordSize * NTFS_VOLUMEINO; + + Seek(ih, mftOffset); + Read(ih, (long)buf, mftRecordSize); +#if UNUSED + if (lseek(fd, mftOffset, SEEK_SET) == -1) + { + //verbose("NTFS: lseek to $Volume failed: %s\n", strerror(errno)); + goto error; + } + if (read(fd, buf, mftRecordSize) != mftRecordSize) + { + //verbose("NTFS: error reading MFT $Volume record: %s\n", + strerror(errno)); + goto error; + } +#endif + + if (ntfs_fixup(buf, mftRecordSize, NTFS_FILEMAGIC, bytesPerSector) != 0) + { + //verbose("NTFS: block fixup failed\n"); + goto error; + } + + /* + * Loop over the attributes, looking for $VOLUME_NAME (0x60). + */ + if(ntfs_find_attr(buf, NTFS_A_VOLUMENAME, &nameAttr, &nameSize) != 0) + { + //verbose("NTFS: $VOLUME_NAME attribute not found\n"); + goto error; + } + + str[0] = '\0'; + + utf_encodestr( nameAttr, nameSize / 2, (u_int8_t *)str, strMaxLen, OSLittleEndian ); + + free(buf); + return; + + error: + if (buf) free(buf); + return; +} + +long NTFSGetUUID(CICell ih, char *uuidStr) +{ + bool NTFSProbe(const void*); + + struct bootfile *boot; + void *buf = malloc(MAX_BLOCK_SIZE); + if ( !buf ) + return -1; + + /* + * Read the boot sector, check signatures, and do some minimal + * sanity checking. NOTE: the size of the read below is intended + * to be a multiple of all supported block sizes, so we don't + * have to determine or change the device's block size. + */ + Seek(ih, 0); + Read(ih, (long)buf, MAX_BLOCK_SIZE); + + boot = (struct bootfile *) buf; + + // Check for NTFS signature + if ( memcmp((void*)boot->bf_sysid, NTFS_BBID, NTFS_BBIDLEN) != 0 ) + return -1; + + // Check for non-null volume serial number + if( !boot->bf_volsn ) + return -1; + + // Use UUID like the one you get on Windows + sprintf(uuidStr, "%04X-%04X", (unsigned short)(boot->bf_volsn >> 16) & 0xFFFF, + (unsigned short)boot->bf_volsn & 0xFFFF); + + return 0; +} + +bool NTFSProbe(const void * buffer) +{ + bool result = false; + + const struct bootfile * part_bootfile = buffer; // NTFS boot sector structure + + // Looking for NTFS signature. + if (strncmp((const char *)part_bootfile->bf_sysid, NTFS_BBID, NTFS_BBIDLEN) == 0) + result = true; + + return result; +} +#endif \ No newline at end of file Index: branches/slice/rev749/libsaio/ufs_byteorder.c =================================================================== --- branches/slice/rev749/libsaio/ufs_byteorder.c (revision 0) +++ branches/slice/rev749/libsaio/ufs_byteorder.c (revision 1169) @@ -0,0 +1,171 @@ +/* + * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 2.0 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright 1993 NeXT, Inc. + * All rights reserved. + */ + +#include +#include +#include +#include +#include +#include "ufs_byteorder.h" +#include "libsaio.h" + +#define swapBigLongToHost(thing) ((thing) = OSSwapBigToHostInt32(thing)) +#define swapBigShortToHost(thing) ((thing) = OSSwapBigToHostInt16(thing)) +#define byte_swap_longlong(thing) ((thing) = OSSwapBigToHostInt64(thing)) +#define byte_swap_int(thing) ((thing) = OSSwapBigToHostInt32(thing)) +#define byte_swap_short(thing) ((thing) = OSSwapBigToHostInt16(thing)) + +#if UNUSED +void +byte_swap_longlongs(unsigned long long *array, int count) +{ + register unsigned long long i; + + for (i = 0; i < (unsigned long long)count; i++) + byte_swap_longlong(array[i]); +} +#endif + +void +byte_swap_ints(unsigned int *array, int count) +{ + register int i; + + for (i = 0; i < count; i++) + byte_swap_int(array[i]); +} + +void +byte_swap_shorts(unsigned short *array, int count) +{ + register int i; + + for (i = 0; i < count; i++) + byte_swap_short(array[i]); +} + +#if UNUSED +static void +swapBigIntsToHost(unsigned int *array, int count) +{ + register int i; + + for (i = 0; i < count; i++) + swapBigLongToHost(array[i]); +} + +static void +swapBigShortToHosts(unsigned short *array, int count) +{ + register int i; + + for (i = 0; i < count; i++) + swapBigShortToHost(array[i]); +} +#endif + +void +byte_swap_superblock(struct fs *sb) +{ + u_int16_t * usptr; + unsigned long size; + + byte_swap_ints(((u_int32_t *)&sb->fs_firstfield), 52); + byte_swap_int(sb->fs_cgrotor); + byte_swap_int(sb->fs_cpc); + byte_swap_shorts((u_int16_t *)sb->fs_opostbl, 16 * 8); + byte_swap_ints((u_int32_t *)sb->fs_sparecon, 50); + byte_swap_ints((u_int32_t *)&sb->fs_contigsumsize, 3); +#if UNUSED + byte_swap_longlongs((u_int64_t *)&sb->fs_maxfilesize,3); +#endif + byte_swap_ints((u_int32_t *)&sb->fs_state, 6); + + /* Got these magic numbers from mkfs.c in newfs */ + if (sb->fs_nrpos != 8 || sb->fs_cpc > 16) { + usptr = (u_int16_t *)((u_int8_t *)(sb) + (sb)->fs_postbloff); + size = sb->fs_cpc * sb->fs_nrpos; + byte_swap_shorts(usptr,size); /* fs_postbloff */ + } +} + + +/* This value should correspond to the value set in the ffs_mounts */ + +#define RESYMLNKLEN 60 + +void +byte_swap_dinode_in(struct dinode *di) +{ + int i; + + di->di_mode = OSSwapInt16(di->di_mode); + di->di_nlink = OSSwapInt16(di->di_nlink); +#ifdef LFS + di->di_u.inumber = OSSwapInt32(di->di_u.inumber); +#else + di->di_u.oldids[0] = OSSwapInt16(di->di_u.oldids[0]); + di->di_u.oldids[1] = OSSwapInt16(di->di_u.oldids[1]); +#endif + di->di_size = OSSwapInt64(di->di_size); + di->di_atime = OSSwapInt32(di->di_atime); + di->di_atimensec = OSSwapInt32(di->di_atimensec); + di->di_mtime = OSSwapInt32(di->di_mtime); + di->di_mtimensec = OSSwapInt32(di->di_mtimensec); + di->di_ctime = OSSwapInt32(di->di_ctime); + di->di_ctimensec = OSSwapInt32(di->di_ctimensec); + if (((di->di_mode & IFMT) != IFLNK ) || (di->di_size > RESYMLNKLEN)) { + for (i=0; i < NDADDR; i++) /* direct blocks */ + di->di_db[i] = OSSwapInt32(di->di_db[i]); + for (i=0; i < NIADDR; i++) /* indirect blocks */ + di->di_ib[i] = OSSwapInt32(di->di_ib[i]); + } + di->di_flags = OSSwapInt32(di->di_flags); + di->di_blocks = OSSwapInt32(di->di_blocks); + di->di_gen = OSSwapInt32(di->di_gen); + di->di_uid = OSSwapInt32(di->di_uid); + di->di_gid = OSSwapInt32(di->di_gid); + di->di_spare[0] = OSSwapInt32(di->di_spare[0]); + di->di_spare[1] = OSSwapInt32(di->di_spare[1]); +} + +void +byte_swap_dir_block_in(char *addr, int count) +{ + register struct direct * ep = (struct direct *) addr; + register int entryoffsetinblk = 0; + + while (entryoffsetinblk < count) { + ep = (struct direct *) (entryoffsetinblk + addr); + swapBigLongToHost(ep->d_ino); + swapBigShortToHost(ep->d_reclen); + entryoffsetinblk += ep->d_reclen; + if (ep->d_reclen < 12) /* handle garbage in dirs */ + break; + } +} Index: branches/slice/rev749/libsaio/sys.c =================================================================== --- branches/slice/rev749/libsaio/sys.c (revision 0) +++ branches/slice/rev749/libsaio/sys.c (revision 1169) @@ -0,0 +1,1139 @@ +/* + * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 2.0 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Mach Operating System + * Copyright (c) 1990 Carnegie-Mellon University + * Copyright (c) 1989 Carnegie-Mellon University + * Copyright (c) 1988 Carnegie-Mellon University + * Copyright (c) 1987 Carnegie-Mellon University + * All rights reserved. The CMU software License Agreement specifies + * the terms and conditions for use and redistribution. + * + */ +/* + * HISTORY + * Revision 2.3 88/08/08 13:47:07 rvb + * Allocate buffers dynamically vs statically. + * Now b[i] and i_fs and i_buf, are allocated dynamically. + * boot_calloc(size) allocates and zeros a buffer rounded to a NPG + * boundary. + * Generalize boot spec to allow, xx()/mach, xx(n,[a..h])/mach, + * xx([a..h])/mach, ... + * Also default "xx" if unspecified and alloc just "/mach", + * where everything is defaulted + * Add routine, ptol(), to parse partition letters. + * + */ + +/* + * Copyright (c) 1982, 1986 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. + * + * @(#)sys.c 7.1 (Berkeley) 6/5/86 + */ + +/* Copyright 2007 VMware Inc. + "Preboot" ramdisk support added by David Elliott + */ + +#include + +#include "libsaio.h" +#include "boot.h" +#include "bootstruct.h" +#include "disk.h" +#include "ramdisk.h" +#include "xml.h" +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +# include +#else +# include +#endif +#include +#if 0 /* No OS X release has ever included this. */ +#include +#else +/* copied from uuid/namespace.h, just like BootX's fs.c does. */ +UUID_DEFINE( kFSUUIDNamespaceSHA1, 0xB3, 0xE2, 0x0F, 0x39, 0xF2, 0x92, 0x11, 0xD6, 0x97, 0xA4, 0x00, 0x30, 0x65, 0x43, 0xEC, 0xAC ); +#endif + +#ifdef UNUSED +extern int multiboot_partition; +extern int multiboot_partition_set; +#endif + +struct devsw { + const char * name; + // size increased from char to short to handle non-BIOS internal devices + unsigned short biosdev; + int type; +}; + +// Device entries must be ordered by bios device numbers. +static struct devsw devsw[] = +{ + { "hd", 0x80, kBIOSDevTypeHardDrive }, /* DEV_HD */ + { "en", 0xE0, kBIOSDevTypeNetwork }, /* DEV_EN */ + { "rd", 0x100, kBIOSDevTypeHardDrive }, + { "bt", 0x101, kBIOSDevTypeHardDrive }, // turbo - type for booter partition + { 0, 0 } +}; + +// Pseudo BIOS devices +enum { + kPseudoBIOSDevRAMDisk = 0x100, + kPseudoBIOSDevBooter = 0x101 +}; + +/* + * Max number of file descriptors. + */ +#define NFILES 6 + +static struct iob iob[NFILES]; + +void * gFSLoadAddress = 0; + +// Turbo - save what we think is our original BIOS boot volume if we have one 0xab +BVRef gBIOSBootVolume = NULL; +BVRef gBootVolume; + +// zef - ramdisk variables +extern BVRef gRAMDiskVolume; +extern bool gRAMDiskBTAliased; + +//static BVRef getBootVolumeRef( const char * path, const char ** outPath ); +static BVRef newBootVolumeRef( int biosdev, int partno ); + +//========================================================================== +// LoadVolumeFile - LOW-LEVEL FILESYSTEM FUNCTION. +// Load the specified file from the specified volume +// to the load buffer at LOAD_ADDR. +// If the file is fat, load only the i386 portion. + +long LoadVolumeFile(BVRef bvr, const char *filePath) +{ + long fileSize; + + // Read file into load buffer. The data in the load buffer will be + // overwritten by the next LoadFile() call. + + gFSLoadAddress = (void *) LOAD_ADDR; + + fileSize = bvr->fs_loadfile(bvr, (char *)filePath); + + // Return the size of the file, or -1 if load failed. + + return fileSize; +} + +//========================================================================== +// LoadFile - LOW-LEVEL FILESYSTEM FUNCTION. +// Load the specified file to the load buffer at LOAD_ADDR. +// If the file is fat, load only the i386 portion. + +long LoadFile(const char * fileSpec) +{ + const char * filePath; + BVRef bvr; + + // Resolve the boot volume from the file spec. + + if ((bvr = getBootVolumeRef(fileSpec, &filePath)) == NULL) + return -1; + + return LoadVolumeFile(bvr, filePath); +} + +long ReadFileAtOffset(const char * fileSpec, void *buffer, uint64_t offset, uint64_t length) +{ + const char *filePath; + BVRef bvr; + + if ((bvr = getBootVolumeRef(fileSpec, &filePath)) == NULL) + return -1; + + if (bvr->fs_readfile == NULL) + return -1; + + return bvr->fs_readfile(bvr, (char *)filePath, buffer, offset, length); +} + +long LoadThinFatFile(const char *fileSpec, void **binary) +{ + const char *filePath; + FSReadFile readFile; + BVRef bvr; + unsigned long length, length2; + + // Resolve the boot volume from the file spec. + + if ((bvr = getBootVolumeRef(fileSpec, &filePath)) == NULL) + return -1; + + *binary = (void *)kLoadAddr; + + // Read file into load buffer. The data in the load buffer will be + // overwritten by the next LoadFile() call. + + gFSLoadAddress = (void *) LOAD_ADDR; + + readFile = bvr->fs_readfile; + + if (readFile != NULL) { + // Read the first 4096 bytes (fat header) + length = readFile(bvr, (char *)filePath, *binary, 0, 0x1000); + if (length > 0) { + if (ThinFatFile(binary, &length) == 0) { + if (length == 0) + return 0; + // We found a fat binary; read only the thin part + length = readFile(bvr, (char *)filePath, + (void *)kLoadAddr, (unsigned long)(*binary) - kLoadAddr, length); + *binary = (void *)kLoadAddr; + } else { + // Not a fat binary; read the rest of the file + length2 = readFile(bvr, (char *)filePath, (void *)(kLoadAddr + length), length, 0); + if (length2 == -1) return -1; + length += length2; + } + } + } else { + length = bvr->fs_loadfile(bvr, (char *)filePath); + if (length > 0) { + ThinFatFile(binary, &length); + } + } + + return length; +} + +#if UNUSED +long GetFSUUID(char *spec, char *uuidStr) +{ + BVRef bvr; + long rval = -1; + const char *devSpec; + + if ((bvr = getBootVolumeRef(spec, &devSpec)) == NULL) + return -1; + + if(bvr->fs_getuuid) + rval = bvr->fs_getuuid(bvr, uuidStr); + + return rval; +} +#endif + +// filesystem-specific getUUID functions call this shared string generator +long CreateUUIDString(uint8_t uubytes[], int nbytes, char *uuidStr) +{ + unsigned fmtbase, fmtidx, i; + uint8_t uuidfmt[] = { 4, 2, 2, 2, 6 }; + char *p = uuidStr; + MD5_CTX md5c; + uint8_t mdresult[16]; + + bzero(mdresult, sizeof(mdresult)); + + // just like AppleFileSystemDriver + MD5Init(&md5c); + MD5Update(&md5c, kFSUUIDNamespaceSHA1, sizeof(kFSUUIDNamespaceSHA1)); + MD5Update(&md5c, uubytes, nbytes); + MD5Final(mdresult, &md5c); + + // this UUID has been made version 3 style (i.e. via namespace) + // see "-uuid-urn-" IETF draft (which otherwise copies byte for byte) + mdresult[6] = 0x30 | ( mdresult[6] & 0x0F ); + mdresult[8] = 0x80 | ( mdresult[8] & 0x3F ); + + + // generate the text: e.g. 5EB1869F-C4FA-3502-BDEB-3B8ED5D87292 + i = 0; fmtbase = 0; + for(fmtidx = 0; fmtidx < sizeof(uuidfmt); fmtidx++) { + for(i=0; i < uuidfmt[fmtidx]; i++) { + uint8_t byte = mdresult[fmtbase+i]; + char nib; + + nib = byte >> 4; + *p = nib + '0'; // 0x4 -> '4' + if(*p > '9') *p = (nib - 9 + ('A'-1)); // 0xB -> 'B' + p++; + + nib = byte & 0xf; + *p = nib + '0'; // 0x4 -> '4' + if(*p > '9') *p = (nib - 9 + ('A'-1)); // 0xB -> 'B' + p++; + + } + fmtbase += i; + if(fmtidx < sizeof(uuidfmt)-1) + *(p++) = '-'; + else + *p = '\0'; + } + + return 0; +} + + +//========================================================================== +// GetDirEntry - LOW-LEVEL FILESYSTEM FUNCTION. +// Fetch the next directory entry for the given directory. + +long GetDirEntry(const char * dirSpec, long long * dirIndex, const char ** name, + long * flags, long * time) +{ + const char * dirPath; + BVRef bvr; + + // Resolve the boot volume from the dir spec. + + if ((bvr = getBootVolumeRef(dirSpec, &dirPath)) == NULL) + return -1; + + // Return 0 on success, or -1 if there are no additional entries. + + return bvr->fs_getdirentry( bvr, + /* dirPath */ (char *)dirPath, + /* dirIndex */ dirIndex, + /* dirEntry */ (char **)name, flags, time, 0, 0 ); +} + +//========================================================================== +// GetFileInfo - LOW-LEVEL FILESYSTEM FUNCTION. +// Get attributes for the specified file. + +static char* gMakeDirSpec; + +long GetFileInfo(const char * dirSpec, const char * name, + long * flags, long * time) +{ + long long index = 0; + const char * entryName; + + if (gMakeDirSpec == 0) + gMakeDirSpec = (char *)malloc(1024); + + if (!dirSpec) { + long idx, len; + + len = strlen(name); + + for (idx = len; idx && (name[idx] != '/' && name[idx] != '\\'); idx--) {} + if (idx == 0) { + gMakeDirSpec[0] = '/'; + gMakeDirSpec[1] = '\0'; + } else { + idx++; + strncpy(gMakeDirSpec, name, idx); + name += idx; + } + dirSpec = gMakeDirSpec; + } + + while (GetDirEntry(dirSpec, &index, &entryName, flags, time) == 0) + { + if (strcmp(entryName, name) == 0) + return 0; // success + } + return -1; // file not found +} + +long GetFileBlock(const char *fileSpec, unsigned long long *firstBlock) +{ + const char * filePath; + BVRef bvr; + + // Resolve the boot volume from the file spec. + + if ((bvr = getBootVolumeRef(fileSpec, &filePath)) == NULL) { + verbose("Boot volume for '%s' is bogus\n", fileSpec); + return -1; + } + + return bvr->fs_getfileblock(bvr, (char *)filePath, firstBlock); +} + +//========================================================================== +// GetFreeFD() + +static int GetFreeFd(void) +{ + int fd; + + // Locate a free descriptor slot. + for (fd = 0; fd < NFILES; fd++) { + if (iob[fd].i_flgs == 0) { + return fd; + } + } + stop("Out of file descriptors (MAX = %d)", NFILES); + // not reached + return -1; +} + +//========================================================================== +// iob_from_fdesc() +// +// Return a pointer to an allocated 'iob' based on the file descriptor +// provided. Returns NULL if the file descriptor given is invalid. + +static struct iob * iob_from_fdesc(int fdesc) +{ + register struct iob * io; + + if (fdesc < 0 || fdesc >= NFILES || + ((io = &iob[fdesc])->i_flgs & F_ALLOC) == 0) + return NULL; + else + return io; +} + +//========================================================================== +// openmem() + +int openmem(char * buf, int len) +{ + int fdesc; + struct iob * io; + + fdesc = GetFreeFd(); + io = &iob[fdesc]; + bzero(io, sizeof(*io)); + + // Mark the descriptor as taken. Set the F_MEM flag to indicate + // that the file buffer is provided by the caller. + + io->i_flgs = F_ALLOC | F_MEM; + io->i_buf = buf; + io->i_filesize = len; + + return fdesc; +} + +//========================================================================== +// open() - Open the file specified by 'path' for reading. + +static int open_bvr(BVRef bvr, const char *filePath, int flags) +{ + struct iob *io; + int fdesc; + int i; + + if (bvr == NULL) { + return -1; + } + + fdesc = GetFreeFd(); + io = &iob[fdesc]; + bzero(io, sizeof(*io)); + + // Mark the descriptor as taken. + io->i_flgs = F_ALLOC; + + // Find the next available memory block in the download buffer. + io->i_buf = (char *) LOAD_ADDR; + for (i = 0; i < NFILES; i++) { + if ((iob[i].i_flgs != F_ALLOC) || (i == fdesc)) { + continue; + } + io->i_buf = max(iob[i].i_filesize + iob[i].i_buf, io->i_buf); + } + + // Load entire file into memory. Unnecessary open() calls must be avoided. + gFSLoadAddress = io->i_buf; + io->i_filesize = bvr->fs_loadfile(bvr, (char *)filePath); + if (io->i_filesize < 0) { + close(fdesc); + return -1; + } + return fdesc; +} + +int open(const char *path, int flags) +{ + const char *filepath; + BVRef bvr; + + // Resolve the boot volume from the file spec. + if ((bvr = getBootVolumeRef(path, &filepath)) != NULL) { + return open_bvr(bvr, filepath, flags); + } + return -1; +} + +int open_bvdev(const char *bvd, const char *path, int flags) +{ + const struct devsw *dp; + const char *cp; + BVRef bvr; + int i; + int len; + int unit; + int partition; + + if ((i = open(path, flags)) >= 0) { + return i; + } + + if (bvd == NULL || (len = strlen(bvd)) < 2) { + return -1; + } + + for (dp=devsw; dp->name; dp++) { + if (bvd[0] == dp->name[0] && bvd[1] == dp->name[1]) { + unit = 0; + partition = 0; + /* get optional unit and partition */ + if (len >= 5 && bvd[2] == '(') { /* min must be present xx(0) */ + cp = &bvd[3]; + i = 0; + while ((cp - path) < len && isdigit(*cp)) { + i = i * 10 + *cp++ - '0'; + unit = i; + } + if (*cp++ == ',') { + i = 0; + while ((cp - path) < len && isdigit(*cp)) { + i = i * 10 + *cp++ - '0'; + partition = i; + } + } + } + // turbo - bt(0,0) hook + if ((dp->biosdev + unit) == 0x101) { + // zef - use the ramdisk if available and the alias is active. + if (gRAMDiskVolume != NULL && gRAMDiskBTAliased) { + bvr = gRAMDiskVolume; + } else { + bvr = gBIOSBootVolume; + } + } else { + bvr = newBootVolumeRef(dp->biosdev + unit, partition); + } + return open_bvr(bvr, path, flags); + } + } + return -1; +} + +//========================================================================== +// close() - Close a file descriptor. + +int close(int fdesc) +{ + struct iob * io; + + if ((io = iob_from_fdesc(fdesc)) == NULL) + return (-1); + + io->i_flgs = 0; + + return 0; +} + +//========================================================================== +// lseek() - Reposition the byte offset of the file descriptor from the +// beginning of the file. Returns the relocated offset. + +int b_lseek(int fdesc, int offset, int ptr) +{ + struct iob * io; + + if ((io = iob_from_fdesc(fdesc)) == NULL) + return (-1); + + io->i_offset = offset; + + return offset; +} + +//========================================================================== +// tell() - Returns the byte offset of the file descriptor. + +int tell(int fdesc) +{ + struct iob * io; + + if ((io = iob_from_fdesc(fdesc)) == NULL) + return 0; + + return io->i_offset; +} + +//========================================================================== +// read() - Read up to 'count' bytes of data from the file descriptor +// into the buffer pointed to by buf. + +int read(int fdesc, char * buf, int count) +{ + struct iob * io; + + if ((io = iob_from_fdesc(fdesc)) == NULL) + return (-1); + + if ((io->i_offset + count) > (unsigned int)io->i_filesize) + count = io->i_filesize - io->i_offset; + + if (count <= 0) + return 0; // end of file + + bcopy(io->i_buf + io->i_offset, buf, count); + + io->i_offset += count; + + return count; +} + +//========================================================================== +// write() - Write up to 'count' bytes of data to the file descriptor +// from the buffer pointed to by buf. + +int write(int fdesc, const char * buf, int count) +{ + struct iob * io; + + if ((io = iob_from_fdesc(fdesc)) == NULL) + return (-1); + + if ((io->i_offset + count) > (unsigned int)io->i_filesize) + count = io->i_filesize - io->i_offset; + + if (count <= 0) + return 0; // end of file + + bcopy(buf, io->i_buf + io->i_offset, count); + + io->i_offset += count; + + return count; +} + +int writebyte(int fdesc, char value) +{ + struct iob * io; + + if ((io = iob_from_fdesc(fdesc)) == NULL) + return (-1); + + if ((io->i_offset + 1) > (unsigned int)io->i_filesize) + return 0; // end of file + + io->i_buf[io->i_offset++] = value; + + return 1; +} + +int writeint(int fdesc, int value) +{ + struct iob * io; + + if ((io = iob_from_fdesc(fdesc)) == NULL) + return (-1); + + if ((io->i_offset + 4) > (unsigned int)io->i_filesize) + return 0; // end of file + + bcopy(&value, io->i_buf + io->i_offset, 4); + + io->i_offset += 4; + + return 4; +} + +//========================================================================== +// file_size() - Returns the size of the file described by the file +// descriptor. + +int file_size(int fdesc) +{ + struct iob * io; + + if ((io = iob_from_fdesc(fdesc)) == 0) + return 0; + + return io->i_filesize; +} + +//========================================================================== + +struct dirstuff * vol_opendir(BVRef bvr, const char * path) +{ + struct dirstuff * dirp = 0; + + dirp = (struct dirstuff *) malloc(sizeof(struct dirstuff)); + if (dirp == NULL) + goto error; + + dirp->dir_path = newString(path); + if (dirp->dir_path == NULL) + goto error; + + dirp->dir_bvr = bvr; + + return dirp; + +error: + closedir(dirp); + return NULL; +} + +//========================================================================== + +struct dirstuff * opendir(const char * path) +{ + struct dirstuff * dirp = 0; + const char * dirPath; + BVRef bvr; + + if ((bvr = getBootVolumeRef(path, &dirPath)) == NULL) + goto error; + + dirp = (struct dirstuff *) malloc(sizeof(struct dirstuff)); + if (dirp == NULL) + goto error; + + dirp->dir_path = newString(dirPath); + if (dirp->dir_path == NULL) + goto error; + + dirp->dir_bvr = bvr; + + return dirp; + +error: + closedir(dirp); + return NULL; +} + +//========================================================================== + +int closedir(struct dirstuff * dirp) +{ + if (dirp) { + if (dirp->dir_path) free(dirp->dir_path); + free(dirp); + } + return 0; +} + +//========================================================================== + +int readdir(struct dirstuff * dirp, const char ** name, long * flags, + long * time) +{ + return dirp->dir_bvr->fs_getdirentry( dirp->dir_bvr, + /* dirPath */ dirp->dir_path, + /* dirIndex */ &dirp->dir_index, + /* dirEntry */ (char **)name, flags, time, + 0, 0); +} + +//========================================================================== + +int readdir_ext(struct dirstuff * dirp, const char ** name, long * flags, + long * time, FinderInfo *finderInfo, long *infoValid) +{ + return dirp->dir_bvr->fs_getdirentry( dirp->dir_bvr, + /* dirPath */ dirp->dir_path, + /* dirIndex */ &dirp->dir_index, + /* dirEntry */ (char **)name, + flags, time, + finderInfo, infoValid); +} + +//========================================================================== + +const char * systemConfigDir() +{ + if (gBootFileType == kNetworkDeviceType) + return ""; + return "/Library/Preferences/SystemConfiguration"; +} + +//========================================================================== + +int gBootFileType; + +void scanBootVolumes( int biosdev, int * count ) +{ + BVRef bvr = 0; + + bvr = diskScanBootVolumes(biosdev, count); + if (bvr == NULL) + { +#ifndef OPTION_ROM + bvr = nbpScanBootVolumes(biosdev, count); + if (bvr != NULL) + { + gBootFileType = kNetworkDeviceType; + } +#endif + } + else + { + gBootFileType = kBlockDeviceType; + } +} + +//========================================================================== + +void scanDisks(int biosdev, int *count) +{ +#define MAX_HDD_COUNT 32 + int bvCount; + int hd = 0; + + // Testing up to MAX_HDD_COUNT hard drives. + while(!testBiosread(0x80 + hd, 0) && hd < MAX_HDD_COUNT) + { + bvCount = 0; + scanBootVolumes(0x80 + hd, &bvCount); + verbose("scanVolume %d\n", hd); + + hd++; + } + + // Also scanning CD/DVD drive. + // if (biosDevIsCDROM(gBIOSDev)) + if (biosDevIsCDROM(gBIOSDev)) // 0 = CDROM + { + bvCount = 0; + //scanBootVolumes(gBIOSDev, &bvCount); + scanBootVolumes(gBIOSDev, &bvCount); + msglog("biosDevIsCDROM and bvCount=%d\n", bvCount); + } + + *count = bvCount; //Slice - ! + +} + +//========================================================================== + +BVRef selectBootVolume( BVRef chain ) +{ + bool filteredChain = false; + bool foundPrimary = false; + BVRef bvr, bvr1 = 0, bvr2 = 0; + + if (chain->filtered) filteredChain = true; + +#ifdef UNUSED + if (multiboot_partition_set) + for ( bvr = chain; bvr; bvr = bvr->next ){ + msglog("Check muiltiboot: biosdev=%d type=0x%x flags=0x%x part_no=%d\n", + bvr->biosdev, bvr->type, bvr->flags, bvr->part_no); + if ( bvr->part_no == multiboot_partition && bvr->biosdev == gBIOSDev ) + return bvr; + } +#endif + /* + * Checking "Default Partition" key in system configuration - use format: hd(x,y), the volume UUID or label - + * to override the default selection. + * We accept only kBVFlagSystemVolume or kBVFlagForeignBoot volumes. + */ + char *val = XMLDecode(getStringForKey(kDefaultPartition, &bootInfo->bootConfig)); + if (val) { + for ( bvr = chain; bvr; bvr = bvr->next ) { + if (matchVolumeToString(bvr, val, false)) { + free(val); + return bvr; + } + } + free(val); + } + + /* + * Scannig the volume chain backwards and trying to find + * a HFS+ volume with valid boot record signature. + * If not found any active partition then we will + * select this volume as the boot volume. + */ + for ( bvr = chain; bvr; bvr = bvr->next ) + { +// msglog("scanning chain: biosdev=%d type=0x%x flags=0x%x part_no=%d\n", +// bvr->biosdev, bvr->type, bvr->flags, bvr->part_no); + if ( bvr->flags & kBVFlagPrimary && bvr->biosdev == gBIOSDev ) foundPrimary = true; + // zhell -- Undo a regression that was introduced from r491 to 492. + // if gBIOSBootVolume is set already, no change is required + if ( bvr->flags & (kBVFlagBootable|kBVFlagSystemVolume) + && gBIOSBootVolume + && (!filteredChain || (filteredChain && bvr->visible)) + && bvr->biosdev == gBIOSDev ) + bvr2 = bvr; + // zhell -- if gBIOSBootVolume is NOT set, we use the "if" statement + // from r491, + if ( bvr->flags & kBVFlagBootable + && ! gBIOSBootVolume + && bvr->biosdev == gBIOSDev ) + bvr2 = bvr; + } + + + /* + * Use the standard method for selecting the boot volume. + */ + if (foundPrimary) + { + for ( bvr = chain; bvr; bvr = bvr->next ) + { + if ( bvr->flags & kBVFlagNativeBoot && bvr->biosdev == gBIOSDev ) bvr1 = bvr; + if ( bvr->flags & kBVFlagPrimary && bvr->biosdev == gBIOSDev ) bvr2 = bvr; + } + //msglog("foundPrimary and flags bvr1=%x bvr2=%x\n", bvr1->flags, bvr2->flags);//foundPrimary and flags bvr1=a bvr2=4b + } + + bvr = bvr2 ? bvr2 : + bvr1 ? bvr1 : chain; + + return bvr; +} + +//========================================================================== + +#define LP '(' +#define RP ')' +int gBIOSDev; + +/*! + This is like boot2's gBootVolume except it is for the internal use of + libsaio to track which volume an unqualified path should be relative to. + This replaces bootInfo->kernDev as the carrier of this information. + */ +static BVRef gRootVolume; + +void setRootVolume(BVRef volume) +{ + gRootVolume = volume; + // Veto non-native FS. Basically that means don't allow the root volume to + // be set to a volume we can't read files from. + if(gRootVolume != NULL && ((gRootVolume->flags & kBVFlagNativeBoot) == 0)) + gRootVolume = NULL; +} + +void setBootGlobals(BVRef chain) +{ + // Record default boot device. + gBootVolume = selectBootVolume(chain); + + // turbo - Save the ORIGINAL boot volume too for loading our mkext + if (!gBIOSBootVolume) gBIOSBootVolume = gBootVolume; + + setRootVolume(gBootVolume); +} + +/*! + Extracts the volume selector from the pathname, returns the selected + BVRef, and sets *outPath to the remainder of the path. + If the path did not include a volume selector then the current volume + is used. When called with a volume selector the current volume + is changed to the selected volume unless the volume selector is + that of a ramdisk. + */ +BVRef getBootVolumeRef( const char * path, const char ** outPath ) +{ + const char * cp; + BVRef bvr = gRootVolume; + int biosdev = gBIOSDev; + + // Search for left parenthesis in the path specification. + + for (cp = path; *cp; cp++) { + if (*cp == LP || *cp == '/') break; + } + + if (*cp != LP) // no left paren found + { + // Path is using the implicit current device so if there is + // no current device, then we must fail. + cp = path; + if ( gRootVolume == NULL ) + return NULL; + } + else if ((cp - path) == 2) // found "xx(" + { + const struct devsw * dp; + const char * xp = path; + int i; + int unit = -1; + int part = -1; + + cp++; + + // Check the 2 character device name pointed by 'xp'. + + for (dp = devsw; dp->name; dp++) + { + if ((xp[0] == dp->name[0]) && (xp[1] == dp->name[1])) + break; // found matching entry + } + if (dp->name == NULL) + { + error("Unknown device '%c%c'\n", xp[0], xp[1]); + return NULL; + } + + // Extract the optional unit number from the specification. + // hd(unit) or hd(unit, part). + + i = 0; + while (*cp >= '0' && *cp <= '9') + { + i = i * 10 + *cp++ - '0'; + unit = i; + } + + // Unit is no longer optional and never really was. + // If the user failed to specify it then the unit number from the previous kernDev + // would have been used which makes little sense anyway. + // For example, if the user did fd()/foobar and the current root device was the + // second hard disk (i.e. unit 1) then fd() would select the second floppy drive! + if(unit == -1) + return NULL; + + // Extract the optional partition number from the specification. + + if (*cp == ',') + part = atoi(++cp); + + // If part is not specified part will be -1 whereas before it would have been + // whatever the last partition was which makes about zero sense if the device + // has been switched. + + // Skip past the right paren. + + for ( ; *cp && *cp != RP; cp++) /* LOOP */; + if (*cp == RP) cp++; + + biosdev = dp->biosdev + unit; + + // turbo - bt(0,0) hook + if (biosdev == 0x101) + { + // zef - use the ramdisk if available and the alias is active. + if (gRAMDiskVolume != NULL && gRAMDiskBTAliased) + bvr = gRAMDiskVolume; + else + bvr = gBIOSBootVolume; + } + else + { + bvr = newBootVolumeRef(biosdev, part); + } + + if(bvr == NULL) + return NULL; + } + else + { + // Bad device specifier, skip past the right paren. + + for ( cp++; *cp && *cp != RP; cp++) /* LOOP */; + if (*cp == RP) cp++; + // If gRootVolume was NULL, then bvr will be NULL as well which + // should be caught by the caller. + } + + // Returns the file path following the device spec. + // e.g. 'hd(1,b)mach_kernel' is reduced to 'mach_kernel'. + + *outPath = cp; + + return bvr; +} + +//========================================================================== +// Function name is a misnomer as scanBootVolumes usually calls diskScanBootVolumes +// which caches the information. So it's only allocated on the first run. +static BVRef newBootVolumeRef( int biosdev, int partno ) +{ + BVRef bvr, bvr1, bvrChain; + + bvr = bvr1 = NULL; + + // Try resolving "rd" and "bt" devices first. +#ifndef OPTION_ROM + if (biosdev == kPseudoBIOSDevRAMDisk) + { + if (gRAMDiskVolume) + bvr1 = gRAMDiskVolume; + } + else +#endif + if (biosdev == kPseudoBIOSDevBooter) + { +#ifndef OPTION_ROM + if (gRAMDiskVolume != NULL && gRAMDiskBTAliased) + bvr1 = gRAMDiskVolume; + else +#endif + bvr1 = gBIOSBootVolume; + } + else + { + // Fetch the volume list from the device. + + scanBootVolumes( biosdev, NULL ); + bvrChain = getBVChainForBIOSDev(biosdev); + + // Look for a perfect match based on device and partition number. + + for ( bvr1 = NULL, bvr = bvrChain; bvr; bvr = bvr->next ) + { + if ( ( bvr->flags & kBVFlagNativeBoot ) == 0 ) continue; + + bvr1 = bvr; + if ( bvr->part_no == partno ) break; + } + } + + return bvr ? bvr : bvr1; +} + +//========================================================================== +// getDeviceDescription() - Extracts unit number and partition number +// from bvr structure into "dw(u,p)" format. +// Returns length of the out string +int getDeviceDescription(BVRef bvr, char *str) +{ + if(!str) + return 0; + + *str = '\0'; + + if (bvr) + { + const struct devsw *dp = devsw; + while(dp->name && bvr->biosdev >= dp->biosdev) + dp++; + + dp--; + if (dp->name) + return sprintf(str, "%s(%d,%d)", dp->name, bvr->biosdev - dp->biosdev, bvr->part_no); + } + + return 0; +} Index: branches/slice/rev749/libsaio/load.c =================================================================== --- branches/slice/rev749/libsaio/load.c (revision 0) +++ branches/slice/rev749/libsaio/load.c (revision 1169) @@ -0,0 +1,343 @@ +/* + * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 2.0 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * load.c - Functions for decoding a Mach-o Kernel. + * + * Copyright (c) 1998-2003 Apple Computer, Inc. + * + */ + +#include +#include +#include + +#include + +static long DecodeSegment(long cmdBase, unsigned int*load_addr, unsigned int *load_size); +static long DecodeUnixThread(long cmdBase, unsigned int *entry); +static long DecodeSymbolTable(long cmdBase); + + +unsigned long gBinaryAddress; +bool gHaveKernelCache; /* XXX aserebln: uninitialized? and only set to true, never to false */ +cpu_type_t archCpuType=CPU_TYPE_I386; + +// Public Functions + +long ThinFatFile(void **binary, unsigned long *length) +{ + unsigned long nfat, swapped, size = 0; + struct fat_header *fhp = (struct fat_header *)*binary; + struct fat_arch *fap = + (struct fat_arch *)((unsigned long)*binary + sizeof(struct fat_header)); + cpu_type_t fapcputype; + uint32_t fapoffset; + uint32_t fapsize; + + if (fhp->magic == FAT_MAGIC) { + nfat = fhp->nfat_arch; + swapped = 0; + } else if (fhp->magic == FAT_CIGAM) { + nfat = OSSwapInt32(fhp->nfat_arch); + swapped = 1; + } else { + return -1; + } + + for (; nfat > 0; nfat--, fap++) { + if (swapped) { + fapcputype = OSSwapInt32(fap->cputype); + fapoffset = OSSwapInt32(fap->offset); + fapsize = OSSwapInt32(fap->size); + } + else + { + fapcputype = fap->cputype; + fapoffset = fap->offset; + fapsize = fap->size; + } + + if (fapcputype == archCpuType) { + *binary = (void *) ((unsigned long)*binary + fapoffset); + size = fapsize; + break; + } + } + + if (length != 0) *length = size; + + return 0; +} + +long DecodeMachO(void *binary, entry_t *rentry, char **raddr, int *rsize) +{ + struct mach_header *mH; + unsigned long ncmds, cmdBase, cmd, cmdsize, cmdstart; + // long headerBase, headerAddr, headerSize; + unsigned int vmaddr = ~0; + unsigned int vmend = 0; + unsigned long cnt; + long ret = -1; + unsigned int entry = 0; + + gBinaryAddress = (unsigned long)binary; + + mH = (struct mach_header *)(gBinaryAddress); + switch (archCpuType) + { + case CPU_TYPE_I386: + if (mH->magic != MH_MAGIC) { + error("Mach-O file has bad magic number\n"); + return -1; + } + cmdstart = (unsigned long)gBinaryAddress + sizeof(struct mach_header); + break; + case CPU_TYPE_X86_64: + if (mH->magic != MH_MAGIC_64 && mH->magic == MH_MAGIC) + return -1; + if (mH->magic != MH_MAGIC_64) { + error("Mach-O file has bad magic number\n"); + return -1; + } + cmdstart = (unsigned long)gBinaryAddress + sizeof(struct mach_header_64); + break; + default: + error("Unknown CPU type\n"); + return -1; + } + + cmdBase = cmdstart; + +#if DEBUG + verbose("magic: %x\n", (unsigned)mH->magic); + verbose("cputype: %x\n", (unsigned)mH->cputype); + verbose("cpusubtype: %x\n", (unsigned)mH->cpusubtype); + verbose("filetype: %x\n", (unsigned)mH->filetype); + verbose("ncmds: %x\n", (unsigned)mH->ncmds); + verbose("sizeofcmds: %x\n", (unsigned)mH->sizeofcmds); + verbose("flags: %x\n", (unsigned)mH->flags); + getc(); +#endif + + ncmds = mH->ncmds; + + for (cnt = 0; cnt < ncmds; cnt++) { + cmd = ((long *)cmdBase)[0]; + cmdsize = ((long *)cmdBase)[1]; + unsigned int load_addr; + unsigned int load_size; + + switch (cmd) { + case LC_SEGMENT_64: + case LC_SEGMENT: + ret = DecodeSegment(cmdBase, &load_addr, &load_size); + if (ret == 0 && load_size != 0 && load_addr >= KERNEL_ADDR) { + vmaddr = min(vmaddr, load_addr); + vmend = max(vmend, load_addr + load_size); + } + break; + + case LC_UNIXTHREAD: + ret = DecodeUnixThread(cmdBase, &entry); + break; + + case LC_SYMTAB: + break; + + default: +#if NOTDEF + verbose("Ignoring cmd type %d.\n", (unsigned)cmd); +#endif + break; + } + + if (ret != 0) return -1; + + cmdBase += cmdsize; + } + + *rentry = (entry_t)( (unsigned long) entry & 0x3fffffff ); + *rsize = vmend - vmaddr; + *raddr = (char *)vmaddr; + + cmdBase = cmdstart; + for (cnt = 0; cnt < ncmds; cnt++) { + cmd = ((long *)cmdBase)[0]; + cmdsize = ((long *)cmdBase)[1]; + + if(cmd==LC_SYMTAB) + if (DecodeSymbolTable(cmdBase)!=0) + return -1; + + cmdBase += cmdsize; + } + + return ret; +} + +// Private Functions + +static long DecodeSegment(long cmdBase, unsigned int *load_addr, unsigned int *load_size) +{ + unsigned long vmaddr, fileaddr; + long vmsize, filesize; + char *segname; + + if (((long *)cmdBase)[0]==LC_SEGMENT_64) + { + struct segment_command_64 *segCmd; + + segCmd = (struct segment_command_64 *)cmdBase; + + vmaddr = (segCmd->vmaddr & 0x3fffffff); + vmsize = segCmd->vmsize; + fileaddr = (gBinaryAddress + segCmd->fileoff); + filesize = segCmd->filesize; + + segname=segCmd->segname; + } + else + { + struct segment_command *segCmd; + + segCmd = (struct segment_command *)cmdBase; + + vmaddr = (segCmd->vmaddr & 0x3fffffff); + vmsize = segCmd->vmsize; + fileaddr = (gBinaryAddress + segCmd->fileoff); + filesize = segCmd->filesize; + + segname=segCmd->segname; + } + + if (vmsize == 0 || filesize == 0) { + *load_addr = ~0; + *load_size = 0; + return 0; + } + +#if DEBUG + verbose("segname: %s, vmaddr: %x, vmsize: %x, fileoff: %x, filesize: %x, nsects: %d, flags: %x.\n", + segCmd->segname, (unsigned)vmaddr, (unsigned)vmsize, (unsigned)fileaddr, (unsigned)filesize, + (unsigned) segCmd->nsects, (unsigned)segCmd->flags); + getc(); +#endif + + if (! ((vmaddr >= KERNEL_ADDR && + (vmaddr + vmsize) <= (KERNEL_ADDR + KERNEL_LEN)) || + (vmaddr >= HIB_ADDR && + (vmaddr + vmsize) <= (HIB_ADDR + HIB_LEN)))) { + stop("Kernel overflows available space"); + } + + if (vmsize && (strcmp(segname, "__PRELINK") == 0)) + gHaveKernelCache = true; + + // Copy from file load area. + if (vmsize>0 && filesize>0) + bcopy((char *)fileaddr, (char *)vmaddr, vmsize>filesize?filesize:vmsize); + + // Zero space at the end of the segment. + if (vmsize > filesize) + bzero((char *)(vmaddr + filesize), vmsize - filesize); + + *load_addr = vmaddr; + *load_size = vmsize; + + return 0; +} + +static long DecodeUnixThread(long cmdBase, unsigned int *entry) +{ + switch (archCpuType) + { + case CPU_TYPE_I386: + { + i386_thread_state_t *i386ThreadState; + + i386ThreadState = (i386_thread_state_t *) + (cmdBase + sizeof(struct thread_command) + 8); + + #if defined(__DARWIN_UNIX03) && __DARWIN_UNIX03 + *entry = i386ThreadState->__eip; + #else + *entry = i386ThreadState->eip; + #endif + return 0; + } + + case CPU_TYPE_X86_64: + { + x86_thread_state64_t *x86_64ThreadState; + + x86_64ThreadState = (x86_thread_state64_t *) + (cmdBase + sizeof(struct thread_command) + 8); + + #if defined(__DARWIN_UNIX03) && __DARWIN_UNIX03 + *entry = x86_64ThreadState->__rip; + #else + *entry = x86_64ThreadState->rip; + #endif + return 0; + } + + default: + error("Unknown CPU type\n"); + return -1; + } +} + +static long DecodeSymbolTable(long cmdBase) +{ + struct symtab_command *symTab, *symTableSave; + long tmpAddr, symsSize, totalSize; + long gSymbolTableAddr; + long gSymbolTableSize; + + symTab = (struct symtab_command *)cmdBase; + +#if DEBUG + verbose("symoff: %x, nsyms: %x, stroff: %x, strsize: %x\n", + symTab->symoff, symTab->nsyms, symTab->stroff, symTab->strsize); + getc (); +#endif + + symsSize = symTab->stroff - symTab->symoff; + totalSize = symsSize + symTab->strsize; + + gSymbolTableSize = totalSize + sizeof(struct symtab_command); + gSymbolTableAddr = AllocateKernelMemory(gSymbolTableSize); + // Add the SymTab to the memory-map. + AllocateMemoryRange("Kernel-__SYMTAB", gSymbolTableAddr, gSymbolTableSize, -1); + + symTableSave = (struct symtab_command *)gSymbolTableAddr; + tmpAddr = gSymbolTableAddr + sizeof(struct symtab_command); + + symTableSave->symoff = tmpAddr; + symTableSave->nsyms = symTab->nsyms; + symTableSave->stroff = tmpAddr + symsSize; + symTableSave->strsize = symTab->strsize; + + bcopy((char *)(gBinaryAddress + symTab->symoff), + (char *)tmpAddr, totalSize); + return 0; +} Index: branches/slice/rev749/libsaio/nbp.c =================================================================== --- branches/slice/rev749/libsaio/nbp.c (revision 0) +++ branches/slice/rev749/libsaio/nbp.c (revision 1169) @@ -0,0 +1,146 @@ +/* + * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 2.0 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +#ifndef OPTION_ROM +#include "libsaio.h" + +/* This NBP code is pretty useless because it just blindly calls INT 2B. + Presumably INT 2B was implemented by some first-stage bootloader that + is long gone. + + One good reason to disable this is that nbpScanBootVolumes always + succeeds. The scanBootVolumes function thus never fails because + it always falls back to NBP. This is a problem because there is + other code in the booter (for example, in open) which needs to + fail instead of attempting to use this NBP which will often + hang the machine. + */ +#ifndef NBP_SUPPORT +#define NBP_SUPPORT 0 +#endif + +#if NBP_SUPPORT + +/* + * Convert zero-based linear address to far pointer. + */ +#define GET_FP(x) ( (((x) & 0xffff0000) << (16 - 4)) | ((x) & 0xffff) ) + +/*========================================================================== + * Issue a command to the network loader. + * + * The 'cmd' command structure should be allocated on the stack to + * ensure that it resides within the addressable range for the + * network loader, which runs in real mode. + */ +static UInt32 nbp(nbpCommandCode_t code, nbpCommand_u * cmd) +{ + loader(code, GET_FP((UInt32) cmd)); + + // Must re-enable the A20 address line, the PXE firmware will + // disable the A20 line control. + // + enableA20(); + + return cmd->header.status; +} + +/*========================================================================== + * Unload Base Code Stack command. + */ +UInt32 nbpUnloadBaseCode() +{ + return nbp(nbpCommandUnloadBaseCode, (nbpCommand_u *) 0); +} + +/*========================================================================== + * TFTP Read File command. + */ +static long NBPLoadFile(CICell ih, char * filePath) +{ + nbpCommandTFTPReadFile_s cmd; + UInt32 ret; + + strcpy((char *)cmd.filename, filePath); + cmd.status = nbpStatusFailed; + cmd.bufferSize = TFTP_LEN; + cmd.buffer = TFTP_ADDR; + + verbose("Loading file: %s\n", filePath); + + ret = nbp(nbpCommandTFTPReadFile, (nbpCommand_u *) &cmd); + + return (ret == nbpStatusSuccess) ? (long)cmd.bufferSize : -1; +} + +/*========================================================================== + * GetDirEntry is not supported. + */ +static long NBPGetDirEntry(CICell ih, char * dirPath, long long * dirIndex, + char ** name, long * flags, long * time, + FinderInfo * finderInfo, long * infoValid) +{ + return -1; +} + +//========================================================================== + +static void NBPGetDescription(CICell ih, char * str, long strMaxLen) +{ + sprintf( str, "Ethernet PXE Client" ); +} + +//========================================================================== + +BVRef nbpScanBootVolumes( int biosdev, int * countPtr ) +{ + static BVRef gNetBVR = NULL; + + if ( countPtr ) *countPtr = 1; + + if ( !gNetBVR ) + { + gNetBVR = malloc( sizeof(*gNetBVR) ); + if ( gNetBVR ) + { + bzero(gNetBVR, sizeof(*gNetBVR)); + gNetBVR->biosdev = biosdev; + gNetBVR->flags = kBVFlagPrimary | kBVFlagNativeBoot; + gNetBVR->description = NBPGetDescription; + gNetBVR->fs_loadfile = NBPLoadFile; + gNetBVR->fs_getdirentry = NBPGetDirEntry; + } + } + return gNetBVR; +} +#else +BVRef nbpScanBootVolumes( int biosdev, int * countPtr ) +{ + return NULL; +} +UInt32 nbpUnloadBaseCode() +{ + return 0; +} +#endif +#endif Index: branches/slice/rev749/libsaio/ntfs.h =================================================================== --- branches/slice/rev749/libsaio/ntfs.h (revision 0) +++ branches/slice/rev749/libsaio/ntfs.h (revision 1169) @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 2.0 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +extern void NTFSGetDescription(CICell ih, char *str, long strMaxLen); +extern bool NTFSProbe (const void *buf); +extern long NTFSGetUUID(CICell ih, char *uuidStr); Index: branches/slice/rev749/libsaio/ufs_byteorder.h =================================================================== --- branches/slice/rev749/libsaio/ufs_byteorder.h (revision 0) +++ branches/slice/rev749/libsaio/ufs_byteorder.h (revision 1169) @@ -0,0 +1,56 @@ +/* + * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 2.0 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1992 NeXT Computer, Inc. + * + * UFS byte swapping routines to make a big endian file system useful on a + * little endian machine. + * + * HISTORY + * + * 8 Jul 1992 Brian Pinkerton at NeXT + * Created. + */ + +#ifndef __LIBSAIO_UFS_BYTEORDER_H +#define __LIBSAIO_UFS_BYTEORDER_H + +#include +#include +#include +#include +#include +#include +#include + +void byte_swap_ints(unsigned int *array, int count); +void byte_swap_shorts(unsigned short *array, int count); +void byte_swap_longlongs(unsigned long long *array, int count); + +void byte_swap_superblock(struct fs *sb); +void byte_swap_dinode_in(struct dinode *di); +void byte_swap_dir_block_in(char *addr, int count); +void byte_swap_inode_in(struct dinode *dc, struct dinode *ic); + +#endif /* !__LIBSAIO_UFS_BYTEORDER_H */ Index: branches/slice/rev749/libsaio/acpi.h =================================================================== --- branches/slice/rev749/libsaio/acpi.h (revision 0) +++ branches/slice/rev749/libsaio/acpi.h (revision 1169) @@ -0,0 +1,153 @@ +#ifndef __LIBSAIO_ACPI_H +#define __LIBSAIO_ACPI_H + +#define ACPI_RANGE_START (0x0E0000) +#define ACPI_RANGE_END (0x0FFFFF) + +#define UINT64_LE_FROM_CHARS(a,b,c,d,e,f,g,h) \ +( ((uint64_t)h << 56) \ +| ((uint64_t)g << 48) \ +| ((uint64_t)f << 40) \ +| ((uint64_t)e << 32) \ +| ((uint64_t)d << 24) \ +| ((uint64_t)c << 16) \ +| ((uint64_t)b << 8) \ +| ((uint64_t)a << 0) \ +) + +#define ACPI_SIGNATURE_UINT64_LE UINT64_LE_FROM_CHARS('R','S','D',' ','P','T','R',' ') + +/* Per ACPI 3.0a spec */ + +// TODO Migrate +struct acpi_2_rsdp { + char Signature[8]; + uint8_t Checksum; + char OEMID[6]; + uint8_t Revision; + uint32_t RsdtAddress; + uint32_t Length; + uint64_t XsdtAddress; + uint8_t ExtendedChecksum; + char Reserved[3]; +} __attribute__((packed)); + +// TODO Migrate +struct acpi_2_rsdt { + char Signature[4]; + uint32_t Length; + uint8_t Revision; + uint8_t Checksum; + char OEMID[6]; + char OEMTableId[8]; + uint32_t OEMRevision; + uint32_t CreatorId; + uint32_t CreatorRevision; +} __attribute__((packed)); + +// TODO Migrate +struct acpi_2_xsdt { + char Signature[4]; + uint32_t Length; + uint8_t Revision; + uint8_t Checksum; + char OEMID[6]; + char OEMTableId[8]; + uint32_t OEMRevision; + uint32_t CreatorId; + uint32_t CreatorRevision; +} __attribute__((packed)); + +// TODO Migrate +struct acpi_2_ssdt { + char Signature[4]; + uint32_t Length; + uint8_t Revision; + uint8_t Checksum; + char OEMID[6]; + char OEMTableId[8]; + uint32_t OEMRevision; + uint32_t CreatorId; + uint32_t CreatorRevision; +} __attribute__((packed)); + +// TODO Migrate +struct acpi_2_dsdt { + char Signature[4]; + uint32_t Length; + uint8_t Revision; + uint8_t Checksum; + char OEMID[6]; + char OEMTableId[8]; + uint32_t OEMRevision; + uint32_t CreatorId; + uint32_t CreatorRevision; +} __attribute__((packed)); + +// TODO Migrate +struct acpi_2_fadt { + char Signature[4]; + uint32_t Length; + uint8_t Revision; + uint8_t Checksum; + char OEMID[6]; + char OEMTableId[8]; + uint32_t OEMRevision; + uint32_t CreatorId; + uint32_t CreatorRevision; + uint32_t FIRMWARE_CTRL; + uint32_t DSDT; + uint8_t Model; // JrCs + uint8_t PM_Profile; // JrCs + uint16_t SCI_Interrupt; + uint32_t SMI_Command_Port; + uint8_t ACPI_Enable; + uint8_t ACPI_Disable; + uint8_t S4BIOS_Command; + uint8_t PState_Control; + uint32_t PM1A_Event_Block_Address; + uint32_t PM1B_Event_Block_Address; + uint32_t PM1A_Control_Block_Address; + uint32_t PM1B_Control_Block_Address; + uint32_t PM2_Control_Block_Address; + uint32_t PM_Timer_Block_Address; + uint32_t GPE0_Block_Address; + uint32_t GPE1_Block_Address; + uint8_t PM1_Event_Block_Length; + uint8_t PM1_Control_Block_Length; + uint8_t PM2_Control_Block_Length; + uint8_t PM_Timer_Block_Length; + uint8_t GPE0_Block_Length; + uint8_t GPE1_Block_Length; + uint8_t GPE1_Base_Offset; + uint8_t CST_Support; + uint16_t C2_Latency; + uint16_t C3_Latency; + uint16_t CPU_Cache_Size; + uint16_t Cache_Flush_Stride; + uint8_t Duty_Cycle_Offset; + uint8_t Duty_Cycle_Width; + uint8_t RTC_Day_Alarm_Index; + uint8_t RTC_Month_Alarm_Index; + uint8_t RTC_Century_Index; + uint16_t Boot_Flags; + uint8_t Reserved0; +/* Begin Asere */ + //Reset Fix + uint32_t Flags; + uint8_t Reset_SpaceID; + uint8_t Reset_BitWidth; + uint8_t Reset_BitOffset; + uint8_t Reset_AccessWidth; + uint64_t Reset_Address; + uint8_t Reset_Value; + uint8_t Reserved[3]; + + uint64_t X_FIRMWARE_CTRL; + uint64_t X_DSDT; +/* End Asere */ + /*We absolutely don't care about theese fields*/ + uint8_t notimp2[96]; +} __attribute__((packed)); + +#endif /* !__LIBSAIO_ACPI_H */ Index: branches/slice/rev749/libsaio/sl.h =================================================================== --- branches/slice/rev749/libsaio/sl.h (revision 0) +++ branches/slice/rev749/libsaio/sl.h (revision 1169) @@ -0,0 +1,67 @@ +/* + * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 2.0 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef __LIBSAIO_SL_H +#define __LIBSAIO_SL_H + +#include +#include +#include +#include "libsaio.h" + +#define SWAP_BE16(x) OSSwapBigToHostInt16(x) +#define SWAP_LE16(x) OSSwapLittleToHostInt16(x) +#define SWAP_BE32(x) OSSwapBigToHostInt32(x) +#define SWAP_LE32(x) OSSwapLittleToHostInt32(x) +#define SWAP_BE64(x) OSSwapBigToHostInt64(x) +#define SWAP_LE64(x) OSSwapLittleToHostInt64(x) + +// File Permissions and Types +enum { + kPermOtherExecute = 1 << 0, + kPermOtherWrite = 1 << 1, + kPermOtherRead = 1 << 2, + kPermGroupExecute = 1 << 3, + kPermGroupWrite = 1 << 4, + kPermGroupRead = 1 << 5, + kPermOwnerExecute = 1 << 6, + kPermOwnerWrite = 1 << 7, + kPermOwnerRead = 1 << 8, + kPermMask = 0x1FF, + kOwnerNotRoot = 1 << 9, + kFileTypeUnknown = 0x0 << 16, + kFileTypeFlat = 0x1 << 16, + kFileTypeDirectory = 0x2 << 16, + kFileTypeLink = 0x3 << 16, + kFileTypeMask = 0x3 << 16 +}; + +#define Seek(c, p) diskSeek(c, p); +#define Read(c, a, l) diskRead(c, a, l); + +extern void * gFSLoadAddress; +extern cpu_type_t archCpuType; +cpu_type_t detectCpuType (); + +#endif /* !__LIBSAIO_SL_H */ Index: branches/slice/rev749/libsaio/platform.c =================================================================== --- branches/slice/rev749/libsaio/platform.c (revision 0) +++ branches/slice/rev749/libsaio/platform.c (revision 1169) @@ -0,0 +1,59 @@ +/* + * platform.c + * + * AsereBLN: cleanup + */ + +#include "libsaio.h" +#include "boot.h" +#include "bootstruct.h" +#include "pci.h" +#include "platform.h" +//#include "cpu.h" +#include "modules.h" +#include "efi.h" + +#ifndef DEBUG_PLATFORM +#define DEBUG_PLATFORM 0 +#endif + +#if DEBUG_PLATFORM +#define DBG(x...) verbose(x) +#else +#define DBG(x...) +#endif + +PlatformInfo_t* Platform; +BLESS_EFI_LOAD_OPTION* BootOrder; +/** Return if a CPU feature specified by feature is activated (true) or not (false) */ +inline bool platformCPUFeature(uint32_t feature) +{ + return (Platform->CPU.Features & feature); +} + +/** scan mem for memory autodection purpose */ +void scan_mem() { + static bool done = false; + if (done) return; + + execute_hook("ScanMemory", NULL, NULL, NULL, NULL); + done = true; +} + +/** + Scan platform hardware information, called by the main entry point (common_boot() ) + _before_ bootConfig xml parsing settings are loaded +*/ +void scan_platform(void) +{ + Platform = malloc(sizeof(PlatformInfo_t)); + memset(Platform, 0, sizeof(PlatformInfo_t)); + gPlatform = (void*)Platform; + BootOrder = malloc(sizeof(BLESS_EFI_LOAD_OPTION)); + memset(BootOrder, 0, sizeof(BLESS_EFI_LOAD_OPTION)); + gBootOrder = (void*)BootOrder; + + build_pci_dt(); + scan_cpu(); //Platform); + //scan_mem(); Rek: called after pci devs init in fake_efi now ... +} Index: branches/slice/rev749/libsaio/cpu.c =================================================================== --- branches/slice/rev749/libsaio/cpu.c (revision 0) +++ branches/slice/rev749/libsaio/cpu.c (revision 1169) @@ -0,0 +1,546 @@ +/* + * Copyright 2008 Islam Ahmed Zaid. All rights reserved. + * AsereBLN: 2009: cleanup and bugfix + */ + +#include "libsaio.h" +#include "platform.h" +//#include "mem.h" +#include "smbios_patcher.h" +#include "cpu.h" + +#ifndef DEBUG_CPU +#define DEBUG_CPU 0 +#endif + +#if DEBUG_CPU +#define DBG(x...) printf(x) +#else +#define DBG(x...) msglog(x) +#endif + +/* + * DFE: Measures the TSC frequency in Hz (64-bit) using the ACPI PM timer + */ +static uint64_t measure_tsc_frequency(void) +{ + uint64_t tscStart; + uint64_t tscEnd; + uint64_t tscDelta = 0xffffffffffffffffULL; + unsigned long pollCount; + uint64_t retval = 0; + int i; + + /* Time how many TSC ticks elapse in 30 msec using the 8254 PIT + * counter 2. We run this loop 3 times to make sure the cache + * is hot and we take the minimum delta from all of the runs. + * That is to say that we're biased towards measuring the minimum + * number of TSC ticks that occur while waiting for the timer to + * expire. That theoretically helps avoid inconsistencies when + * running under a VM if the TSC is not virtualized and the host + * steals time. The TSC is normally virtualized for VMware. + */ + for(i = 0; i < 10; ++i) + { + enable_PIT2(); + set_PIT2_mode0(CALIBRATE_LATCH); + tscStart = rdtsc64(); + pollCount = poll_PIT2_gate(); + tscEnd = rdtsc64(); + /* The poll loop must have run at least a few times for accuracy */ + if(pollCount <= 1) + continue; + /* The TSC must increment at LEAST once every millisecond. We + * should have waited exactly 30 msec so the TSC delta should + * be >= 30. Anything less and the processor is way too slow. + */ + if((tscEnd - tscStart) <= CALIBRATE_TIME_MSEC) + continue; + // tscDelta = min(tscDelta, (tscEnd - tscStart)) + if( (tscEnd - tscStart) < tscDelta ) + tscDelta = tscEnd - tscStart; + } + /* tscDelta is now the least number of TSC ticks the processor made in + * a timespan of 0.03 s (e.g. 30 milliseconds) + * Linux thus divides by 30 which gives the answer in kiloHertz because + * 1 / ms = kHz. But we're xnu and most of the rest of the code uses + * Hz so we need to convert our milliseconds to seconds. Since we're + * dividing by the milliseconds, we simply multiply by 1000. + */ + + /* Unlike linux, we're not limited to 32-bit, but we do need to take care + * that we're going to multiply by 1000 first so we do need at least some + * arithmetic headroom. For now, 32-bit should be enough. + * Also unlike Linux, our compiler can do 64-bit integer arithmetic. + */ + if(tscDelta > (1ULL<<32)) + retval = 0; + else + { + retval = tscDelta * 1000 / 30; + } + disable_PIT2(); + return retval; +} + +/* + * Calculates the FSB and CPU frequencies using specific MSRs for each CPU + * - multi. is read from a specific MSR. In the case of Intel, there is: + * a max multi. (used to calculate the FSB freq.), + * and a current multi. (used to calculate the CPU freq.) + * - fsbFrequency = tscFrequency / multi + * - cpuFrequency = fsbFrequency * multi + */ + +void scan_cpu() //PlatformInfo_t *p) +{ + PlatformInfo_t *p = Platform; + int i = 0; + uint8_t turbo = 0; + uint64_t tscFrequency, fsbFrequency, cpuFrequency; + uint64_t msr; //, flex_ratio; + uint8_t maxcoef, maxdiv, currcoef, currdiv, mindiv; + + maxcoef = maxdiv = currcoef = currdiv = mindiv = 0; + +#if DEBUG_CPU + printf("Enter cpuid_info\n"); + pause(); +#endif + cpuid_update_generic_info(); + +#if DEBUG_CPU + printf("...OK\n"); + pause(); +#endif + +#if OLDMETHOD + /* get cpuid values */ + for( ; i <= 3; i++) + { + do_cpuid(i, p->CPU.CPUID[i]); + } + + do_cpuid2(0x00000004, 0, p->CPU.CPUID[CPUID_4]); + do_cpuid(0x80000000, p->CPU.CPUID[CPUID_80]); + if ((p->CPU.CPUID[CPUID_80][0] & 0x0000000f) >= 1) { + do_cpuid(0x80000001, p->CPU.CPUID[CPUID_81]); + } +#if DEBUG_CPU + { + int i; + DBG("CPUID Raw Values:\n"); + for (i=0; iCPU.CPUID[i][0], p->CPU.CPUID[i][1], + p->CPU.CPUID[i][2], p->CPU.CPUID[i][3]); + } + } +#endif + p->CPU.Vendor = p->CPU.CPUID[CPUID_0][1]; + p->CPU.Signature = p->CPU.CPUID[CPUID_1][0]; + p->CPU.Stepping = bitfield(p->CPU.CPUID[CPUID_1][0], 3, 0); + p->CPU.Model = bitfield(p->CPU.CPUID[CPUID_1][0], 7, 4); + p->CPU.Family = bitfield(p->CPU.CPUID[CPUID_1][0], 11, 8); + p->CPU.ExtModel = bitfield(p->CPU.CPUID[CPUID_1][0], 19, 16); + p->CPU.ExtFamily = bitfield(p->CPU.CPUID[CPUID_1][0], 27, 20); + p->CPU.NoThreads = bitfield(p->CPU.CPUID[CPUID_1][1], 23, 16); + p->CPU.NoCores = bitfield(p->CPU.CPUID[CPUID_4][0], 31, 26) + 1; + + p->CPU.Model += (p->CPU.ExtModel << 4); + + /* get brand string (if supported) */ + /* Copyright: from Apple's XNU cpuid.c */ + if (p->CPU.CPUID[CPUID_80][0] > 0x80000004) { + uint32_t reg[4]; + char str[128], *s; + /* + * The brand string 48 bytes (max), guaranteed to + * be NUL terminated. + */ + do_cpuid(0x80000002, reg); + bcopy((char *)reg, &str[0], 16); + do_cpuid(0x80000003, reg); + bcopy((char *)reg, &str[16], 16); + do_cpuid(0x80000004, reg); + bcopy((char *)reg, &str[32], 16); + for (s = str; *s != '\0'; s++) { + if (*s != ' ') break; + } + + strlcpy(p->CPU.BrandString, s, sizeof(p->CPU.BrandString)); + + if (!strncmp(p->CPU.BrandString, CPU_STRING_UNKNOWN, min(sizeof(p->CPU.BrandString), strlen(CPU_STRING_UNKNOWN) + 1))) { + /* + * This string means we have a firmware-programmable brand string, + * and the firmware couldn't figure out what sort of CPU we have. + */ + p->CPU.BrandString[0] = '\0'; + } + } + + /* setup features */ + p->CPU.Features |= (CPU_FEATURE_MMX | CPU_FEATURE_SSE | CPU_FEATURE_SSE2 | CPU_FEATURE_MSR) & p->CPU.CPUID[CPUID_1][3]; + p->CPU.Features |= (CPU_FEATURE_SSE3 | CPU_FEATURE_SSE41 | CPU_FEATURE_SSE42) & p->CPU.CPUID[CPUID_1][2]; + p->CPU.Features |= (CPU_FEATURE_EM64T) & p->CPU.CPUID[CPUID_81][3]; + + + //if ((CPU_FEATURE_HTT & p->CPU.CPUID[CPUID_1][3]) != 0) { + if (p->CPU.NoThreads > p->CPU.NoCores) { + p->CPU.Features |= CPU_FEATURE_HTT; + } +#else //Slice + p->CPU.Vendor = *(UInt32*)&cpuid_info()->cpuid_vendor; + p->CPU.Signature = cpuid_info()->cpuid_signature; + p->CPU.Stepping = cpuid_info()->cpuid_stepping; + p->CPU.Model = cpuid_info()->cpuid_model; + p->CPU.Family = cpuid_info()->cpuid_family; + p->CPU.ExtModel = cpuid_info()->cpuid_extmodel; + p->CPU.ExtFamily = cpuid_info()->cpuid_extfamily; +// DBG("CPU: Vendor/Model/ExtModel: 0x%x/0x%x/0x%x\n", p->CPU.Vendor, p->CPU.Model, p->CPU.ExtModel); +// DBG("CPU: Family/ExtFamily: 0x%x/0x%x\n", p->CPU.Family, p->CPU.ExtFamily); + + strlcpy(p->CPU.BrandString, cpuid_info()->cpuid_brand_string, sizeof(p->CPU.BrandString)); + DBG("CPU: BrandString %s\n", p->CPU.BrandString); + p->CPU.Features = cpuid_info()->cpuid_features; + p->CPU.NoCores = cpuid_info()->core_count; + p->CPU.NoThreads = cpuid_info()->thread_count; +// DBG("CPU: MaxCoef/CurrCoef: 0x%x/0x%x\n", p->CPU.MaxCoef, p->CPU.CurrCoef); +// DBG("CPU: MaxDiv/CurrDiv: 0x%x/0x%x\n", p->CPU.MaxDiv?2:1, p->CPU.CurrDiv?2:1); +// DBG("CPU: TSCFreq: %dMHz\n", p->CPU.TSCFrequency / 1000000); +// DBG("CPU: FSBFreq: %dMHz\n", p->CPU.FSBFrequency / 1000000); +// DBG("CPU: CPUFreq: %dMHz\n", p->CPU.CPUFrequency / 1000000); +// DBG("CPU: NoCores/NoThreads: %d/%d\n", p->CPU.NoCores, p->CPU.NoThreads); +// DBG("CPU: Features: 0x%08x\n", p->CPU.Features); +#if DEBUG_CPU + pause(); +#endif + +#endif + + tscFrequency = measure_tsc_frequency(); + DBG("measure_tsc_frequency = %dMHz\n", tscFrequency / MEGA); + fsbFrequency = 0; + cpuFrequency = 0; + + if ((p->CPU.Vendor == 0x756E6547 /* Intel */) && + ((p->CPU.Family == 0x06) || + (p->CPU.Family == 0x0f))) + { + if ((p->CPU.Family == 0x06 && p->CPU.Model >= 0x0c) || + (p->CPU.Family == 0x0f && p->CPU.Model >= 0x03)) + { + /* Nehalem CPU model */ + if (p->CPU.Family == 0x06 && (p->CPU.Model == 0x1a || p->CPU.Model == 0x1e || + p->CPU.Model == 0x1f || p->CPU.Model == 0x25 || + p->CPU.Model == 0x19 || p->CPU.Model == 0x2c)) + { + msr = rdmsr64(MSR_PLATFORM_INFO); + DBG("msr(0x%04x): platform_info %08x-%08x\n", MSR_PLATFORM_INFO, + (msr >> 32) & 0xffffffff, msr & 0xffffffff); + mindiv = (msr >> 40) & 0xff; + maxcoef = (msr >> 8) & 0xff; + + msr = rdmsr64(MSR_TURBO_RATIO); + turbo = msr & 0x7f; + //Slice - doesn't work + /* + msr = rdmsr64(MSR_FLEX_RATIO); + DBG("msr(0x%04x): flex_ratio %08x\n", MSR_FLEX_RATIO, msr & 0xffffffff); + if ((msr >> 16) & 0x01) { + flex_ratio = (msr >> 8) & 0xff; + if (currcoef > flex_ratio) { + currcoef = flex_ratio; + } + }*/ + msr = rdmsr64(MSR_IA32_PERF_STATUS); + if (msr) { + currcoef = msr & 0x1f; + } + + if (!currcoef) { + currcoef = maxcoef; + } + + if (currcoef < mindiv) { + currcoef = mindiv; + } + + if (currcoef) { + fsbFrequency = (tscFrequency / currcoef); + } + cpuFrequency = tscFrequency; + } + else //not nehalem + { + //Slice - it is not FSB frequency. It is System Bus Speed: FSB = SBS * 4; + if (p->CPU.Family != 0x0d){ + msr = rdmsr64(MSR_FSB_FREQ); + switch (msr & 7) { + case 0: + fsbFrequency = 266670 * 1000; + break; + case 1: + fsbFrequency = 133330 * 1000; + break; + case 2: + fsbFrequency = 200000 * 1000; + break; + case 3: + fsbFrequency = 166670 * 1000; + break; + case 4: + fsbFrequency = 333330 * 1000; + break; + case 5: + fsbFrequency = 200000 * 1000; + break; + case 6: + fsbFrequency = 400000 * 1000; + break; + default: + fsbFrequency = 0; + break; + } + DBG("msr(0x%04x): MSR_FSB_FREQ %d.%dMHz\n", MSR_FSB_FREQ, + fsbFrequency/MEGA, (fsbFrequency%MEGA)/1000); + } + + msr = rdmsr64(MSR_PLATFORM_INFO); //info only? + uint32_t m2 = msr >> 32; + DBG("msr(0x%04x): platform_info %08x-%08x\n", MSR_PLATFORM_INFO, + m2 & 0xffffffff, msr & 0xffffffff); + turbo = (m2 >> 8) & 0x1f; + + msr = rdmsr64(MSR_IA32_PERF_STATUS); + m2 = msr >> 32; + DBG("msr(0x%04x): MSR_IA32_PERF_STATUS %08x-%08x\n", MSR_IA32_PERF_STATUS, + m2 & 0xffffffff, msr & 0xffffffff); + + currcoef = (msr >> 8) & 0x1f; + mindiv = (msr >> 24) & 0xf; + if (currcoef < mindiv) { + currcoef = mindiv; + } + + /* Non-integer bus ratio for the max-multi*/ + maxdiv = (msr >> 46) & 0x01; + /* Non-integer bus ratio for the current-multi (undocumented)*/ + currdiv = (msr >> 14) & 0x01; + + if ((p->CPU.Family == 0x06 && p->CPU.Model >= 0x0e) || + (p->CPU.Family == 0x0f)) // This will always be model >= 3 + { + /* On these models, maxcoef defines TSC freq */ + maxcoef = (msr >> 40) & 0x1f; + } + else + { + /* On lower models, currcoef defines TSC freq */ + /* XXX */ + maxcoef = currcoef; + } + + if (maxcoef) + { + if (!fsbFrequency) { + if (maxdiv) + { + fsbFrequency = ((tscFrequency * 2) / ((maxcoef * 2) + 1)); + } + else + { + fsbFrequency = (tscFrequency / maxcoef); + } + + } + + if (currdiv) + { + cpuFrequency = (fsbFrequency * ((currcoef * 2) + 1) / 2); + } + else + { + cpuFrequency = (fsbFrequency * currcoef); + } + DBG("max: %d%s current: %d%s\n", maxcoef, maxdiv ? ".5" : "",currcoef, currdiv ? ".5" : ""); + } + } + } + /* Mobile CPU ? */ +//Slice + msr = rdmsr64(MSR_IA32_PLATFORM_ID); + DBG("msr(0x%04x): MSR_IA32_PLATFORM_ID 0x%08x\n", MSR_IA32_PLATFORM_ID, msr & 0xffffffff); //__LINE__ - source line number :) + if (!scanDMI() && msr) { + p->CPU.Mobile = FALSE; + switch (p->CPU.Model) { + case 0x0D: + p->CPU.Mobile = TRUE; // CPU_FEATURE_MOBILE; + break; + case 0x0F: + p->CPU.Mobile = FALSE; // CPU_FEATURE_MOBILE; + break; + case 0x02: + case 0x03: + case 0x04: + case 0x06: + p->CPU.Mobile = (rdmsr64(MSR_P4_EBC_FREQUENCY_ID) && (1 << 21)); + break; + default: + p->CPU.Mobile = (rdmsr64(MSR_IA32_PLATFORM_ID) && (1<<28)); + break; + } + if (p->CPU.Mobile) { + p->CPU.Features |= CPU_FEATURE_MOBILE; + } + } + DBG("CPU is %s\n", p->CPU.Mobile?"Mobile":"Desktop"); + + } +#if 0 + else if((p->CPU.Vendor == 0x68747541 /* AMD */) && (p->CPU.Family == 0x0f)) + { + if(p->CPU.ExtFamily == 0x00 /* K8 */) + { + msr = rdmsr64(K8_FIDVID_STATUS); + currcoef = (msr & 0x3f) / 2 + 4; + currdiv = (msr & 0x01) * 2; + } + else if(p->CPU.ExtFamily >= 0x01 /* K10+ */) + { + msr = rdmsr64(K10_COFVID_STATUS); + if(p->CPU.ExtFamily == 0x01 /* K10 */) + currcoef = (msr & 0x3f) + 0x10; + else /* K11+ */ + currcoef = (msr & 0x3f) + 0x08; + currdiv = (2 << ((msr >> 6) & 0x07)); + } + + if (currcoef) + { + if (currdiv) + { + fsbFrequency = ((tscFrequency * currdiv) / currcoef); + DBG("%d.%d\n", currcoef / currdiv, ((currcoef % currdiv) * 100) / currdiv); + } + else + { + fsbFrequency = (tscFrequency / currcoef); + DBG("%d\n", currcoef); + } + fsbFrequency = (tscFrequency / currcoef); + cpuFrequency = tscFrequency; + } + } +#endif + else if(p->CPU.Vendor == 0x746e6543 && p->CPU.Family == 6) + { + switch (p->CPU.Model) { + case CPU_VIA_NANO: + // NOTE: TSC is constant, irrelevent of speed steping + break; + default: + break; + } + + msr = rdmsr64(MSR_NANO_FCR2); + verbose("MSR_IA32_EBL_CR_POWERON Returns 0x%X 0x%X\n", msr >> 32, msr & 0xffffffff); + + //msr = msr >> 32; + msr |= VIA_ALTERNATIVE_VENDOR_BIT; + //msr = msr << 32; + + verbose("MSR_IA32_EBL_CR_POWERON Returns 0x%X 0x%X\n", msr >> 32, msr & 0xffffffff); + wrmsr64(MSR_NANO_FCR2, msr); + msr = rdmsr64(MSR_NANO_FCR2); + verbose("MSR_IA32_EBL_CR_POWERON Returns 0x%X 0x%X\n", msr >> 32, msr & 0xffffffff); + + + /* get cpuid values */ + for( ; i <= 3; i++) + { + do_cpuid(i, p->CPU.CPUID[i]); + } + //int numcpuid_supported = p->CPU.CPUID[CPUID_0][0]; // max number cpuid call + //int numextcpuid = p->CPU.CPUID[CPUID_80][0]; + //p->CPU.Features = 0; + // bitfield(p->CPU.CPUID[CPUID_1][1], 0, 0) FEATURE_C + + // CPUID_0 -> largest cpuid val in EAX + // CPUID_0 -> rem = vendor string + /* + CPUID_1 EDX: + 0 -> FPU + 1 -> VME + 2 -> DE + 3 -> PSE + 4 -> TSC + 5 -> MSR + 6 -> PAE + 7 -> MCE + 8 -> CX8 + 9 -> APIC + 10 -> Reserved + 11 -> Fast Call + 12 -> MTTR + 13 -> PGE + 14 -> MCA + 15 -> CMOV + 16 -> PAT + 17 -> PSE36 + 18 -> Serial Number + 23 -> MMX + 24 -> FXSR + 25 -> SSE + */ + + //CPUID_80 -> largest excpuid value in EAX + //CPUID_81,EAX -> Signature + //CPUID_80,EDX -> Ext Features + //CPUID_82 -> CPU String + //CPUID_83 -> CPU String + //CPUID_84 -> CPU String + p->CPU.NoThreads = p->CPU.NoCores; + + } + + if (!fsbFrequency) { + fsbFrequency = (DEFAULT_FSB * 1000); + cpuFrequency = tscFrequency; + msglog("CPU: fsb=0 ! using the default value 100MHz !\n"); + } + +/* + p->CPU.Vendor = p->CPU.CPUID[CPUID_0][1]; + p->CPU.Signature = p->CPU.CPUID[CPUID_1][0]; + p->CPU.Stepping = bitfield(p->CPU.CPUID[CPUID_1][0], 3, 0); + p->CPU.Model = bitfield(p->CPU.CPUID[CPUID_1][0], 7, 4); + p->CPU.Family = bitfield(p->CPU.CPUID[CPUID_1][0], 11, 8); + p->CPU.ExtModel = bitfield(p->CPU.CPUID[CPUID_1][0], 19, 16); + p->CPU.ExtFamily = bitfield(p->CPU.CPUID[CPUID_1][0], 27, 20); + p->CPU.NoThreads = bitfield(p->CPU.CPUID[CPUID_1][1], 23, 16); +*/ + + + p->CPU.MaxCoef = turbo; + p->CPU.MaxDiv = maxdiv; + p->CPU.MinCoef = mindiv; + p->CPU.CurrCoef = currcoef; + p->CPU.CurrDiv = currdiv; + p->CPU.TSCFrequency = tscFrequency; + p->CPU.FSBFrequency = fsbFrequency; + p->CPU.CPUFrequency = cpuFrequency; + DBG("CPU: Brand: %s\n", p->CPU.BrandString); + DBG("CPU: Vendor/Model/ExtModel: 0x%x/0x%x/0x%x\n", p->CPU.Vendor, p->CPU.Model, p->CPU.ExtModel); + DBG("CPU: Family/ExtFamily: 0x%x/0x%x\n", p->CPU.Family, p->CPU.ExtFamily); + DBG("CPU: MaxCoef/CurrCoef/Turbo: 0x%x/0x%x/0x%x\n", p->CPU.MaxCoef, p->CPU.CurrCoef, turbo); + DBG("CPU: MaxDiv/CurrDiv: 0x%x/0x%x\n", p->CPU.MaxDiv?2:1, p->CPU.CurrDiv?2:1); + DBG("CPU: TSCFreq: %dMHz\n", p->CPU.TSCFrequency / 1000000); + DBG("CPU: FSBFreq: %dMHz\n", p->CPU.FSBFrequency / 1000000); + DBG("CPU: CPUFreq: %dMHz\n", p->CPU.CPUFrequency / 1000000); + DBG("CPU: NoCores/NoThreads: %d/%d\n", p->CPU.NoCores, p->CPU.NoThreads); + DBG("CPU: Features: 0x%08x\n", p->CPU.Features); +#if DEBUG_CPU + pause(); +#endif +} Index: branches/slice/rev749/libsaio/platform.h =================================================================== --- branches/slice/rev749/libsaio/platform.h (revision 0) +++ branches/slice/rev749/libsaio/platform.h (revision 1169) @@ -0,0 +1,172 @@ +/* + * platform.h + * AsereBLN: reworked and extended + * + */ + +#ifndef __LIBSAIO_PLATFORM_H +#define __LIBSAIO_PLATFORM_H + +#include "libsaio.h" + +extern bool platformCPUFeature(uint32_t); +extern void scan_platform(void); +extern void dumpPhysAddr(const char * title, void * a, int len); +extern void scan_cpu(); + +#define bit(n) (1UL << (n)) +#define bitmask(h,l) ((bit(h)|(bit(h)-1)) & ~(bit(l)-1)) +#define bitfield(x,h,l) (((x) & bitmask(h,l)) >> l) + + +/* CPUID index into cpuid_raw */ +#define CPUID_0 0 +#define CPUID_1 1 +#define CPUID_2 2 +#define CPUID_3 3 +#define CPUID_4 4 +#define CPUID_80 5 +#define CPUID_81 6 +#define CPUID_MAX 7 + +#define CPU_MODEL_PENTIUM_M 0x0D +#define CPU_MODEL_YONAH 0x0E +#define CPU_MODEL_MEROM 0x0F +#define CPU_MODEL_PENRYN 0x17 +#define CPU_MODEL_NEHALEM 0x1A +#define CPU_MODEL_ATOM 0x1C +#define CPU_MODEL_FIELDS 0x1E /* Lynnfield, Clarksfield, Jasper */ +#define CPU_MODEL_DALES 0x1F /* Havendale, Auburndale */ +#define CPU_MODEL_DALES_32NM 0x25 /* Clarkdale, Arrandale */ +#define CPU_MODEL_WESTMERE 0x2C /* Gulftown, Westmere-EP, Westmere-WS */ +#define CPU_MODEL_NEHALEM_EX 0x2E +#define CPU_MODEL_WESTMERE_EX 0x2F + +/* CPU Features */ +// NOTE: Theses are currently mapped to the actual bit in the cpuid value +#define CPU_FEATURE_MMX bit(23) // MMX Instruction Set +#define CPU_FEATURE_SSE bit(25) // SSE Instruction Set +#define CPU_FEATURE_SSE2 bit(26) // SSE2 Instruction Set +#define CPU_FEATURE_SSE3 bit(0) // SSE3 Instruction Set +#define CPU_FEATURE_SSE41 bit(19) // SSE41 Instruction Set +#define CPU_FEATURE_SSE42 bit(20) // SSE42 Instruction Set +#define CPU_FEATURE_EM64T bit(29) // 64Bit Support +#define CPU_FEATURE_HTT bit(28) // HyperThreading +#define CPU_FEATURE_MSR bit(5) // MSR Support + +// NOTE: Determine correct bit for bellow (28 is already in use) +#define CPU_FEATURE_MOBILE bit(1) // Mobile CPU +//Slice - just use Platform->CPU.Mobile +#define MEGA 1000000LL + +/* SMBIOS Memory Types */ +#define SMB_MEM_TYPE_UNDEFINED 0 +#define SMB_MEM_TYPE_OTHER 1 +#define SMB_MEM_TYPE_UNKNOWN 2 +#define SMB_MEM_TYPE_DRAM 3 +#define SMB_MEM_TYPE_EDRAM 4 +#define SMB_MEM_TYPE_VRAM 5 +#define SMB_MEM_TYPE_SRAM 6 +#define SMB_MEM_TYPE_RAM 7 +#define SMB_MEM_TYPE_ROM 8 +#define SMB_MEM_TYPE_FLASH 9 +#define SMB_MEM_TYPE_EEPROM 10 +#define SMB_MEM_TYPE_FEPROM 11 +#define SMB_MEM_TYPE_EPROM 12 +#define SMB_MEM_TYPE_CDRAM 13 +#define SMB_MEM_TYPE_3DRAM 14 +#define SMB_MEM_TYPE_SDRAM 15 +#define SMB_MEM_TYPE_SGRAM 16 +#define SMB_MEM_TYPE_RDRAM 17 +#define SMB_MEM_TYPE_DDR 18 +#define SMB_MEM_TYPE_DDR2 19 +#define SMB_MEM_TYPE_FBDIMM 20 +#define SMB_MEM_TYPE_DDR3 24 // Supported in 10.5.6+ AppleSMBIOS + +/* Memory Configuration Types */ +#define SMB_MEM_CHANNEL_UNKNOWN 0 +#define SMB_MEM_CHANNEL_SINGLE 1 +#define SMB_MEM_CHANNEL_DUAL 2 +#define SMB_MEM_CHANNEL_TRIPLE 3 + +/* Maximum number of ram slots */ +#define MAX_RAM_SLOTS 8 +#define RAM_SLOT_ENUMERATOR {0, 2, 4, 1, 3, 5, 6, 8, 10, 7, 9, 11} + +/* Maximum number of SPD bytes */ +#define MAX_SPD_SIZE 256 + +/* Size of SMBIOS UUID in bytes */ +#define UUID_LEN 16 + +typedef struct _RamSlotInfo_t { + uint32_t ModuleSize; // Size of Module in MB + uint32_t Frequency; // in Mhz + const char* Vendor; + const char* PartNo; + const char* SerialNo; + char* spd; // SPD Dump + bool InUse; + uint8_t Type; + uint8_t BankConnections; // table type 6, see (3.3.7) + uint8_t BankConnCnt; + +} RamSlotInfo_t; + +typedef struct _PlatformInfo_t { + struct PCI { + uint8_t NoDevices; // No of PCI devices + } PCI; + struct CPU { + uint32_t Features; // CPU Features like MMX, SSE2, VT, MobileCPU + uint32_t Vendor; // Vendor + uint32_t Signature; // Signature + uint32_t Stepping; // Stepping + uint32_t Model; // Model + uint32_t ExtModel; // Extended Model + uint32_t Family; // Family + uint32_t ExtFamily; // Extended Family + uint32_t NoCores; // No Cores per Package + uint32_t NoThreads; // Threads per Package + uint8_t MaxCoef; // Max Multiplier + uint8_t MaxDiv; // Possible 0,5 + uint8_t MinCoef; // Min Multiplier + uint8_t CurrCoef; // Current Multiplier + uint8_t CurrDiv; + float MaxRatio; // non-integer ratio + float CurrRatio; + uint64_t TSCFrequency; // TSC Frequency Hz + uint64_t FSBFrequency; // FSB Frequency Hz + uint64_t CPUFrequency; // CPU Frequency Hz + bool Mobile; // Mobile CPU + char BrandString[48]; // 48 Byte Branding String + uint32_t CPUID[CPUID_MAX][4]; // CPUID 0..4, 80..81 Raw Values + } CPU; + + struct RAM { + uint64_t Frequency; // Ram Frequency + uint32_t Divider; // Memory divider + uint8_t CAS; // CAS 1/2/2.5/3/4/5/6/7 + uint8_t TRC; + uint8_t TRP; + uint8_t RAS; + uint8_t Channels; // Channel Configuration Single,Dual or Triple + uint8_t NoSlots; // Maximum no of slots available + uint8_t Type; // Standard SMBIOS v2.5 Memory Type + char BrandString[48]; // Branding String Memory Controller + RamSlotInfo_t DIMM[MAX_RAM_SLOTS]; // Information about each slot + } RAM; + + struct DMI { + int MaxMemorySlots; // number of memory slots polulated by SMBIOS + int CntMemorySlots; // number of memory slots counted + int MemoryModules; // number of memory modules installed + int DIMM[MAX_RAM_SLOTS]; // Information and SPD mapping for each slot + } DMI; + uint8_t Type; // System Type: 1=Desktop, 2=Portable... according ACPI2.0 (FACP: PM_Profile) + uint8_t *UUID; +} PlatformInfo_t; + +extern PlatformInfo_t* Platform; + +#endif /* !__LIBSAIO_PLATFORM_H */ Index: branches/slice/rev749/libsaio/disk.c =================================================================== --- branches/slice/rev749/libsaio/disk.c (revision 0) +++ branches/slice/rev749/libsaio/disk.c (revision 1169) @@ -0,0 +1,2027 @@ +/* + * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 2.0 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Mach Operating System + * Copyright (c) 1990 Carnegie-Mellon University + * Copyright (c) 1989 Carnegie-Mellon University + * All rights reserved. The CMU software License Agreement specifies + * the terms and conditions for use and redistribution. + */ + +/* + * INTEL CORPORATION PROPRIETARY INFORMATION + * + * This software is supplied under the terms of a license agreement or + * nondisclosure agreement with Intel Corporation and may not be copied + * nor disclosed except in accordance with the terms of that agreement. + * + * Copyright 1988, 1989 Intel Corporation + */ + +/* + * Copyright 1993 NeXT Computer, Inc. + * All rights reserved. + */ + +/* Copyright 2007 VMware Inc. + "Preboot" ramdisk support added by David Elliott + GPT support added by David Elliott. Based on IOGUIDPartitionScheme.cpp. + */ + +// Allow UFS_SUPPORT to be overridden with preprocessor option. +#ifndef UFS_SUPPORT +// zef: Disabled UFS support +#define UFS_SUPPORT 0 +#endif + +#include "libsaio.h" +#include "boot.h" +#include "bootstruct.h" +#include "fdisk.h" +#if UFS_SUPPORT +#include "ufs.h" +#endif +#include "hfs.h" +#include "ntfs.h" +#include "msdos.h" +#include "ext2fs.h" + +#include "xml.h" +#include "disk.h" + +#include +#include +#include +typedef struct gpt_hdr gpt_hdr; +typedef struct gpt_ent gpt_ent; + +// For EFI_GUID +#include "efi.h" +#include "efi_tables.h" + +#define BPS 512 /* sector size of the device */ +#define PROBEFS_SIZE BPS * 4 /* buffer size for filesystem probe */ +#define CD_BPS 2048 /* CD-ROM block size */ +#define N_CACHE_SECS (BIOS_LEN / BPS) /* Must be a multiple of 4 for CD-ROMs */ +#define UFS_FRONT_PORCH 0 +#define kAPMSector 2 /* Sector number of Apple partition map */ +#define kAPMCDSector 8 /* Translated sector of Apple partition map on a CD */ + +/* + * IORound and IOTrunc convenience functions, in the spirit + * of vm's round_page() and trunc_page(). + */ +#define IORound(value,multiple) \ +((((value) + (multiple) - 1) / (multiple)) * (multiple)) + +#define IOTrunc(value,multiple) \ +(((value) / (multiple)) * (multiple)); + +/* + * trackbuf points to the start of the track cache. Biosread() + * will store the sectors read from disk to this memory area. + * + * biosbuf points to a sector within the track cache, and is + * updated by Biosread(). + */ +static char * const trackbuf = (char *) ptov(BIOS_ADDR); +static char * biosbuf; + +/* + * Map a disk drive to bootable volumes contained within. + */ +struct DiskBVMap { + int biosdev; // BIOS device number (unique) + BVRef bvr; // chain of boot volumes on the disk + int bvrcnt; // number of boot volumes + struct DiskBVMap * next; // linkage to next mapping +}; + +static struct DiskBVMap * gDiskBVMap = NULL; +static struct disk_blk0 * gBootSector = NULL; + +// Function pointers to be filled in if ramdisks are available: +int (*p_ramdiskReadBytes)( int biosdev, unsigned int blkno, + unsigned int byteoff, + unsigned int byteCount, void * buffer ) = NULL; +int (*p_get_ramdisk_info)(int biosdev, struct driveInfo *dip) = NULL; + + +extern void spinActivityIndicator(int sectors); + +//========================================================================== + +static int getDriveInfo( int biosdev, struct driveInfo *dip ) +{ + static struct driveInfo cached_di; + int cc; + + // Real BIOS devices are 8-bit, so anything above that is for internal use. + // Don't cache ramdisk drive info since it doesn't require several BIOS + // calls and is thus not worth it. + if(biosdev >= 0x100) + { + if(p_get_ramdisk_info != NULL) + cc = (*p_get_ramdisk_info)(biosdev, dip); + else + cc = -1; + if(cc < 0) + { + dip->valid = 0; + return -1; + } + else + return 0; + } + + if ( !cached_di.valid || biosdev != cached_di.biosdev ) + { + cc = get_drive_info(biosdev, &cached_di); + if (cc < 0) { + cached_di.valid = 0; + DEBUG_DISK(("get_drive_info returned error\n")); + return (-1); // BIOS call error + } + } + + bcopy(&cached_di, dip, sizeof(cached_di)); + + return 0; +} + +//========================================================================== +// Maps (E)BIOS return codes to message strings. + +struct NamedValue { + unsigned char value; + const char * name; +}; + +static const char * getNameForValue( const struct NamedValue * nameTable, + unsigned char value ) +{ + const struct NamedValue * np; + + for ( np = nameTable; np->value; np++) + if (np->value == value) + return np->name; + + return NULL; +} + +#define ECC_CORRECTED_ERR 0x11 + +static const struct NamedValue bios_errors[] = { + { 0x10, "Media error" }, + { 0x11, "Corrected ECC error" }, + { 0x20, "Controller or device error" }, + { 0x40, "Seek failed" }, + { 0x80, "Device timeout" }, + { 0xAA, "Drive not ready" }, + { 0x00, 0 } +}; + +static const char * bios_error(int errnum) +{ + static char errorstr[] = "Error 0x00"; + const char * errname; + + errname = getNameForValue( bios_errors, errnum ); + if ( errname ) return errname; + + sprintf(errorstr, "Error 0x%02x", errnum); + return errorstr; // No string, print error code only +} + +//========================================================================== +// Use BIOS INT13 calls to read the sector specified. This function will +// also perform read-ahead to cache a few subsequent sector to the sector +// cache. +// +// Return: +// 0 on success, or an error code from INT13/F2 or INT13/F42 BIOS call. + +static bool cache_valid = false; + +static int Biosread( int biosdev, unsigned long long secno ) +{ + static int xbiosdev, xcyl, xhead; + static unsigned int xsec, xnsecs; + struct driveInfo di; + + int rc = -1; + int cyl, head, sec; + int tries = 0; + int bps, divisor; + + if (getDriveInfo(biosdev, &di) < 0) { + return -1; + } + if (di.no_emulation) { + /* Always assume 2k block size; BIOS may lie about geometry */ + bps = 2048; + } else { + bps = di.di.params.phys_nbps; + if (bps == 0) { + return -1; + } + } + divisor = bps / BPS; + + DEBUG_DISK(("Biosread dev %x sec %d bps %d\n", biosdev, secno, bps)); + + // To read the disk sectors, use EBIOS if we can. Otherwise, + // revert to the standard BIOS calls. + + if ((biosdev >= kBIOSDevTypeHardDrive) && + (di.uses_ebios & EBIOS_FIXED_DISK_ACCESS)) + { + if (cache_valid && + (biosdev == xbiosdev) && + (secno >= xsec) && + ((unsigned int)secno < (xsec + xnsecs))) + { + biosbuf = trackbuf + (BPS * (secno - xsec)); + return 0; + } + + xnsecs = N_CACHE_SECS; + xsec = (secno / divisor) * divisor; + cache_valid = false; + + while ((rc = ebiosread(biosdev, secno / divisor, xnsecs / divisor)) && (++tries < 5)) + { + if (rc == ECC_CORRECTED_ERR) { + /* Ignore corrected ECC errors */ + rc = 0; + break; + } + error(" EBIOS read error: %s\n", bios_error(rc), rc); + error(" Block 0x%x Sectors %d\n", secno, xnsecs); + sleep(1); + } + } + else + { + /* spc = spt * heads */ + int spc = (di.di.params.phys_spt * di.di.params.phys_heads); + cyl = secno / spc; + head = (secno % spc) / di.di.params.phys_spt; + sec = secno % di.di.params.phys_spt; + + if (cache_valid && + (biosdev == xbiosdev) && + (cyl == xcyl) && + (head == xhead) && + ((unsigned int)sec >= xsec) && + ((unsigned int)sec < (xsec + xnsecs))) + { + // this sector is in trackbuf cache + biosbuf = trackbuf + (BPS * (sec - xsec)); + return 0; + } + + // Cache up to a track worth of sectors, but do not cross a + // track boundary. + + xcyl = cyl; + xhead = head; + xsec = sec; + xnsecs = ((unsigned int)(sec + N_CACHE_SECS) > di.di.params.phys_spt) ? (di.di.params.phys_spt - sec) : N_CACHE_SECS; + cache_valid = false; + + while ((rc = biosread(biosdev, cyl, head, sec, xnsecs)) && + (++tries < 5)) + { + if (rc == ECC_CORRECTED_ERR) { + /* Ignore corrected ECC errors */ + rc = 0; + break; + } + error(" BIOS read error: %s\n", bios_error(rc), rc); + error(" Block %d, Cyl %d Head %d Sector %d\n", + secno, cyl, head, sec); + sleep(1); + } + } + + // If the BIOS reported success, mark the sector cache as valid. + + if (rc == 0) { + cache_valid = true; + } + biosbuf = trackbuf + (secno % divisor) * BPS; + xbiosdev = biosdev; + + spinActivityIndicator(xnsecs); + + return rc; +} + +//========================================================================== + +int testBiosread( int biosdev, unsigned long long secno ) +{ + return Biosread(biosdev, secno); +} + +//========================================================================== + +static int readBytes( int biosdev, unsigned long long blkno, + unsigned int byteoff, + unsigned int byteCount, void * buffer ) +{ + // ramdisks require completely different code for reading. + if(p_ramdiskReadBytes != NULL && biosdev >= 0x100) + return (*p_ramdiskReadBytes)(biosdev, blkno, byteoff, byteCount, buffer); + + char * cbuf = (char *) buffer; + int error; + int copy_len; + + DEBUG_DISK(("%s: dev %x block %x [%d] -> 0x%x...", __FUNCTION__, + biosdev, blkno, byteCount, (unsigned)cbuf)); + + for ( ; byteCount; cbuf += copy_len, blkno++ ) + { + error = Biosread( biosdev, blkno ); + if ( error ) + { + DEBUG_DISK(("error\n")); + return (-1); + } + + copy_len = ((byteCount + byteoff) > BPS) ? (BPS - byteoff) : byteCount; + bcopy( biosbuf + byteoff, cbuf, copy_len ); + byteCount -= copy_len; + byteoff = 0; + } + + DEBUG_DISK(("done\n")); + + return 0; +} + +//========================================================================== + +static int isExtendedFDiskPartition( const struct fdisk_part * part ) +{ + static unsigned char extParts[] = + { + 0x05, /* Extended */ + 0x0f, /* Win95 extended */ + 0x85, /* Linux extended */ + }; + + unsigned int i; + + for (i = 0; i < sizeof(extParts)/sizeof(extParts[0]); i++) + { + if (extParts[i] == part->systid) return 1; + } + return 0; +} + +//========================================================================== + +static int getNextFDiskPartition( int biosdev, int * partno, + const struct fdisk_part ** outPart ) +{ + static int sBiosdev = -1; + static int sNextPartNo; + static unsigned int sFirstBase; + static unsigned int sExtBase; + static unsigned int sExtDepth; + static struct fdisk_part * sExtPart; + struct fdisk_part * part; + + if ( sBiosdev != biosdev || *partno < 0 ) + { + // Fetch MBR. + if ( readBootSector( biosdev, DISK_BLK0, 0 ) ) return 0; + + sBiosdev = biosdev; + sNextPartNo = 0; + sFirstBase = 0; + sExtBase = 0; + sExtDepth = 0; + sExtPart = NULL; + } + + while (1) + { + part = NULL; + + if ( sNextPartNo < FDISK_NPART ) + { + part = (struct fdisk_part *) gBootSector->parts[sNextPartNo]; + } + else if ( sExtPart ) + { + unsigned int blkno = sExtPart->relsect + sFirstBase; + + // Save the block offset of the first extended partition. + + if (sExtDepth == 0) { + sFirstBase = blkno; + } + sExtBase = blkno; + + // Load extended partition table. + + if ( readBootSector( biosdev, blkno, 0 ) == 0 ) + { + sNextPartNo = 0; + sExtDepth++; + sExtPart = NULL; + continue; + } + // Fall through to part == NULL + } + + if ( part == NULL ) break; // Reached end of partition chain. + + // Advance to next partition number. + + sNextPartNo++; + + if ( isExtendedFDiskPartition(part) ) + { + sExtPart = part; + continue; + } + + // Skip empty slots. + + if ( part->systid == 0x00 ) + { + continue; + } + + // Change relative offset to an absolute offset. + part->relsect += sExtBase; + + *outPart = part; + *partno = sExtDepth ? (int)(sExtDepth + FDISK_NPART) : sNextPartNo; + + break; + } + + return (part != NULL); +} + +//========================================================================== + +BVRef newFDiskBVRef( int biosdev, int partno, unsigned int blkoff, + const struct fdisk_part * part, + FSInit initFunc, FSLoadFile loadFunc, + FSReadFile readFunc, + FSGetDirEntry getdirFunc, + FSGetFileBlock getBlockFunc, + FSGetUUID getUUIDFunc, + BVGetDescription getDescriptionFunc, + BVFree bvFreeFunc, + int probe, int type, unsigned int bvrFlags ) +{ + BVRef bvr = (BVRef) malloc( sizeof(*bvr) ); + if ( bvr ) + { + bzero(bvr, sizeof(*bvr)); + + bvr->biosdev = biosdev; + bvr->part_no = partno; + bvr->part_boff = blkoff; + bvr->part_type = part->systid; + bvr->fs_loadfile = loadFunc; + bvr->fs_readfile = readFunc; + bvr->fs_getdirentry = getdirFunc; + bvr->fs_getfileblock= getBlockFunc; + bvr->fs_getuuid = getUUIDFunc; + bvr->description = getDescriptionFunc; + bvr->type = type; + bvr->bv_free = bvFreeFunc; + + if ((part->bootid & FDISK_ACTIVE) && (part->systid == FDISK_HFS)) + bvr->flags |= kBVFlagPrimary; + + // Probe the filesystem. + + if ( initFunc ) + { + bvr->flags |= kBVFlagNativeBoot; + + if ( probe && initFunc( bvr ) != 0 ) + { + // filesystem probe failed. + + DEBUG_DISK(("%s: failed probe on dev %x part %d\n", + __FUNCTION__, biosdev, partno)); + + (*bvr->bv_free)(bvr); + bvr = NULL; + } + if ( readBootSector( biosdev, blkoff, (void *)0x7e00 ) == 0 ) + { + bvr->flags |= kBVFlagBootable; + } + } + else if ( readBootSector( biosdev, blkoff, (void *)0x7e00 ) == 0 ) + { + bvr->flags |= kBVFlagForeignBoot; + } + else + { + (*bvr->bv_free)(bvr); + bvr = NULL; + } + } + if (bvr) bvr->flags |= bvrFlags; + return bvr; +} + +//========================================================================== + +BVRef newAPMBVRef( int biosdev, int partno, unsigned int blkoff, + const DPME * part, + FSInit initFunc, FSLoadFile loadFunc, + FSReadFile readFunc, + FSGetDirEntry getdirFunc, + FSGetFileBlock getBlockFunc, + FSGetUUID getUUIDFunc, + BVGetDescription getDescriptionFunc, + BVFree bvFreeFunc, + int probe, int type, unsigned int bvrFlags ) +{ + BVRef bvr = (BVRef) malloc( sizeof(*bvr) ); + if ( bvr ) + { + bzero(bvr, sizeof(*bvr)); + + bvr->biosdev = biosdev; + bvr->part_no = partno; + bvr->part_boff = blkoff; + bvr->fs_loadfile = loadFunc; + bvr->fs_readfile = readFunc; + bvr->fs_getdirentry = getdirFunc; + bvr->fs_getfileblock= getBlockFunc; + bvr->fs_getuuid = getUUIDFunc; + bvr->description = getDescriptionFunc; + bvr->type = type; + bvr->bv_free = bvFreeFunc; + strlcpy(bvr->name, part->dpme_name, DPISTRLEN); + strlcpy(bvr->type_name, part->dpme_type, DPISTRLEN); + + /* + if ( part->bootid & FDISK_ACTIVE ) + bvr->flags |= kBVFlagPrimary; + */ + + // Probe the filesystem. + + if ( initFunc ) + { + bvr->flags |= kBVFlagNativeBoot | kBVFlagBootable | kBVFlagSystemVolume; + + if ( probe && initFunc( bvr ) != 0 ) + { + // filesystem probe failed. + + DEBUG_DISK(("%s: failed probe on dev %x part %d\n", + __FUNCTION__, biosdev, partno)); + + (*bvr->bv_free)(bvr); + bvr = NULL; + } + } + /* + else if ( readBootSector( biosdev, blkoff, (void *)0x7e00 ) == 0 ) + { + bvr->flags |= kBVFlagForeignBoot; + } + */ + else + { + (*bvr->bv_free)(bvr); + bvr = NULL; + } + } + if (bvr) bvr->flags |= bvrFlags; + return bvr; +} + +//========================================================================== + +// HFS+ GUID in LE form +EFI_GUID const GPT_HFS_GUID = { 0x48465300, 0x0000, 0x11AA, 0xAA, 0x11, {0x00, 0x30, 0x65, 0x43, 0xEC, 0xAC } }; +// turbo - also our booter partition +EFI_GUID const GPT_BOOT_GUID = { 0x426F6F74, 0x0000, 0x11AA, 0xAA, 0x11, {0x00, 0x30, 0x65, 0x43, 0xEC, 0xAC } }; +// turbo - or an efi system partition +EFI_GUID const GPT_EFISYS_GUID = { 0xC12A7328, 0xF81F, 0x11D2, 0xBA, 0x4B, {0x00, 0xA0, 0xC9, 0x3E, 0xC9, 0x3B } }; +// zef - basic data partition EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 for foreign OS support +EFI_GUID const GPT_BASICDATA_GUID = { 0xEBD0A0A2, 0xB9E5, 0x4433, 0x87, 0xC0, {0x68, 0xB6, 0xB7, 0x26, 0x99, 0xC7 } }; +EFI_GUID const GPT_BASICDATA2_GUID = { 0xE3C9E316, 0x0B5C, 0x4DB8, 0x81, 0x7D, {0xF9, 0x2D, 0xF0, 0x02, 0x15, 0xAE } }; + + +BVRef newGPTBVRef( int biosdev, int partno, unsigned int blkoff, + const gpt_ent * part, + FSInit initFunc, FSLoadFile loadFunc, + FSReadFile readFunc, + FSGetDirEntry getdirFunc, + FSGetFileBlock getBlockFunc, + FSGetUUID getUUIDFunc, + BVGetDescription getDescriptionFunc, + BVFree bvFreeFunc, + int probe, int type, unsigned int bvrFlags ) +{ + BVRef bvr = (BVRef) malloc( sizeof(*bvr) ); + if ( bvr ) + { + bzero(bvr, sizeof(*bvr)); + + bvr->biosdev = biosdev; + bvr->part_no = partno; + bvr->part_boff = blkoff; + bvr->fs_loadfile = loadFunc; + bvr->fs_readfile = readFunc; + bvr->fs_getdirentry = getdirFunc; + bvr->fs_getfileblock= getBlockFunc; + bvr->fs_getuuid = getUUIDFunc; + bvr->description = getDescriptionFunc; + bvr->type = type; + bvr->bv_free = bvFreeFunc; + // FIXME: UCS-2 -> UTF-8 the name + strlcpy(bvr->name, "----", DPISTRLEN); + if ( (efi_guid_compare(&GPT_BOOT_GUID, (EFI_GUID const*)part->ent_type) == 0) || + (efi_guid_compare(&GPT_HFS_GUID, (EFI_GUID const*)part->ent_type) == 0) ) + strlcpy(bvr->type_name, "GPT HFS+", DPISTRLEN); + else + strlcpy(bvr->type_name, "GPT Unknown", DPISTRLEN); + + /* + if ( part->bootid & FDISK_ACTIVE ) + bvr->flags |= kBVFlagPrimary; + */ + + // Probe the filesystem. + + if ( initFunc ) + { + bvr->flags |= kBVFlagNativeBoot; + + if ( probe && initFunc( bvr ) != 0 ) + { + // filesystem probe failed. + + DEBUG_DISK(("%s: failed probe on dev %x part %d\n", + __FUNCTION__, biosdev, partno)); + + (*bvr->bv_free)(bvr); + bvr = NULL; + } + if ( readBootSector( biosdev, blkoff, (void *)0x7e00 ) == 0 ) + { + bvr->flags |= kBVFlagBootable; + } + } + else if ( readBootSector( biosdev, blkoff, (void *)0x7e00 ) == 0 ) + { + bvr->flags |= kBVFlagForeignBoot; + } + else + { + (*bvr->bv_free)(bvr); + bvr = NULL; + } + } + if (bvr) bvr->flags |= bvrFlags; + return bvr; +} + +//========================================================================== + +/* A note on partition numbers: + * IOKit makes the primary partitions numbers 1-4, and then + * extended partitions are numbered consecutively 5 and up. + * So, for example, if you have two primary partitions and + * one extended partition they will be numbered 1, 2, 5. + */ + +static BVRef diskScanFDiskBootVolumes( int biosdev, int * countPtr ) +{ + const struct fdisk_part * part; + struct DiskBVMap * map; + int partno = -1; + BVRef bvr; +#if UFS_SUPPORT + BVRef booterUFS = NULL; +#endif + int spc; + struct driveInfo di; + boot_drive_info_t *dp; + verbose("diskScanFDiskBootVolumes %d\n", biosdev); + /* Initialize disk info */ + if (getDriveInfo(biosdev, &di) != 0) { + return NULL; + } + dp = &di.di; + spc = (dp->params.phys_spt * dp->params.phys_heads); + if (spc == 0) { + /* This is probably a CD-ROM; punt on the geometry. */ + spc = 1; + } + + do { + // Create a new mapping. + + map = (struct DiskBVMap *) malloc( sizeof(*map) ); + if ( map ) + { + map->biosdev = biosdev; + map->bvr = NULL; + map->bvrcnt = 0; + map->next = gDiskBVMap; + gDiskBVMap = map; + + // Create a record for each partition found on the disk. + + while ( getNextFDiskPartition( biosdev, &partno, &part ) ) + { + DEBUG_DISK(("%s: part %d [%x]\n", __FUNCTION__, + partno, part->systid)); + bvr = 0; + + switch ( part->systid ) + { +#if UFS_SUPPORT + case FDISK_UFS: + bvr = newFDiskBVRef( + biosdev, partno, + part->relsect + UFS_FRONT_PORCH/BPS, + part, + UFSInitPartition, + UFSLoadFile, + UFSReadFile, + UFSGetDirEntry, + UFSGetFileBlock, + UFSGetUUID, + UFSGetDescription, + UFSFree, + 0, + kBIOSDevTypeHardDrive, 0); + break; +#endif + + case FDISK_HFS: + bvr = newFDiskBVRef( + biosdev, partno, + part->relsect, + part, + HFSInitPartition, + HFSLoadFile, + HFSReadFile, + HFSGetDirEntry, + HFSGetFileBlock, + HFSGetUUID, + HFSGetDescription, + HFSFree, + 0, + kBIOSDevTypeHardDrive, 0); + break; + + // turbo - we want the booter type scanned also + case FDISK_BOOTER: + if (part->bootid & FDISK_ACTIVE) + gBIOSBootVolume = newFDiskBVRef( + biosdev, partno, + part->relsect, + part, + HFSInitPartition, + HFSLoadFile, + HFSReadFile, + HFSGetDirEntry, + HFSGetFileBlock, + HFSGetUUID, + HFSGetDescription, + HFSFree, + 0, + kBIOSDevTypeHardDrive, 0); + break; + +#if UFS_SUPPORT + case FDISK_BOOTER: + booterUFS = newFDiskBVRef( + biosdev, partno, + ((part->relsect + spc - 1) / spc) * spc, + part, + UFSInitPartition, + UFSLoadFile, + UFSReadFile, + UFSGetDirEntry, + UFSGetFileBlock, + UFSGetUUID, + UFSGetDescription, + UFSFree, + 0, + kBIOSDevTypeHardDrive, 0); + break; +#endif + + case FDISK_FAT32: + case FDISK_DOS12: + case FDISK_DOS16S: + case FDISK_DOS16B: + case FDISK_SMALLFAT32: + case FDISK_DOS16SLBA: + bvr = newFDiskBVRef( + biosdev, partno, + part->relsect, + part, + MSDOSInitPartition, + MSDOSLoadFile, + MSDOSReadFile, + MSDOSGetDirEntry, + MSDOSGetFileBlock, + MSDOSGetUUID, + MSDOSGetDescription, + MSDOSFree, + 0, + kBIOSDevTypeHardDrive, 0); + break; +#ifndef OPTION_ROM + case FDISK_NTFS: + bvr = newFDiskBVRef( + biosdev, partno, + part->relsect, + part, + 0, 0, 0, 0, 0, + NTFSGetUUID, + NTFSGetDescription, + (BVFree)free, + 0, kBIOSDevTypeHardDrive, 0); + break; + + case FDISK_LINUX: + bvr = newFDiskBVRef( + biosdev, partno, + part->relsect, + part, + 0, 0, 0, 0, 0, 0, + EX2GetDescription, + (BVFree)free, + 0, kBIOSDevTypeHardDrive, 0); + break; +#endif + default: + bvr = newFDiskBVRef( + biosdev, partno, + part->relsect, + part, + 0, 0, 0, 0, 0, 0, 0, + (BVFree)free, + 0, + kBIOSDevTypeHardDrive, 0); + break; + } + + if ( bvr ) + { + bvr->next = map->bvr; + map->bvr = bvr; + map->bvrcnt++; + } + } + +#if UFS_SUPPORT + // Booting from a CD with an UFS filesystem embedded + // in a booter partition. + + if ( booterUFS ) + { + if ( map->bvrcnt == 0 ) + { + map->bvr = booterUFS; + map->bvrcnt++; + } + else free( booterUFS ); + } +#endif + } + } while (0); + + /* + * If no FDisk partition, then we will check for + * an Apple partition map elsewhere. + */ +#if UNUSED + if (map->bvrcnt == 0) { + static struct fdisk_part cdpart; + cdpart.systid = 0xCD; + + /* Let's try assuming we are on a hybrid HFS/ISO9660 CD. */ + bvr = newFDiskBVRef( + biosdev, 0, + 0, + &cdpart, + HFSInitPartition, + HFSLoadFile, + HFSReadFile, + HFSGetDirEntry, + HFSGetFileBlock, + HFSGetUUID, + 0, + kBIOSDevTypeHardDrive); + bvr->next = map->bvr; + map->bvr = bvr; + map->bvrcnt++; + } +#endif + // Actually this should always be true given the above code + if(map == gDiskBVMap) + { + // Don't leave a null map in the chain + if(map->bvrcnt == 0 && map->bvr == NULL) + { + gDiskBVMap = map->next; + free(map); + map = NULL; + } + } + + if (countPtr) *countPtr = map ? map->bvrcnt : 0; + + return map ? map->bvr : NULL; +} + +//========================================================================== + +static BVRef diskScanAPMBootVolumes( int biosdev, int * countPtr ) +{ + struct DiskBVMap * map; + struct Block0 *block0_p; + unsigned int blksize; + unsigned int factor; + void *buffer = malloc(BPS); + + /* Check for alternate block size */ + if (readBytes( biosdev, 0, 0, BPS, buffer ) != 0) { + return NULL; + } + block0_p = buffer; + if (OSSwapBigToHostInt16(block0_p->sbSig) == BLOCK0_SIGNATURE) { + blksize = OSSwapBigToHostInt16(block0_p->sbBlkSize); + if (blksize != BPS) { + free(buffer); + buffer = malloc(blksize); + } + factor = blksize / BPS; + } else { + blksize = BPS; + factor = 1; + } + + do { + // Create a new mapping. + + map = (struct DiskBVMap *) malloc( sizeof(*map) ); + if ( map ) + { + int error; + DPME *dpme_p = (DPME *)buffer; + UInt32 i, npart = UINT_MAX; + BVRef bvr; + + map->biosdev = biosdev; + map->bvr = NULL; + map->bvrcnt = 0; + map->next = gDiskBVMap; + gDiskBVMap = map; + + for (i=0; idpme_signature) != DPME_SIGNATURE) { + break; + } + + if (i==0) { + npart = OSSwapBigToHostInt32(dpme_p->dpme_map_entries); + } + /* + printf("name = %s, %s%s %d -> %d [%d -> %d] {%d}\n", + dpme.dpme_name, dpme.dpme_type, (dpme.dpme_flags & DPME_FLAGS_BOOTABLE) ? "(bootable)" : "", + dpme.dpme_pblock_start, dpme.dpme_pblocks, + dpme.dpme_lblock_start, dpme.dpme_lblocks, + dpme.dpme_boot_block); + */ + + if (strcmp(dpme_p->dpme_type, "Apple_HFS") == 0) { + bvr = newAPMBVRef(biosdev, + i, + OSSwapBigToHostInt32(dpme_p->dpme_pblock_start) * factor, + dpme_p, + HFSInitPartition, + HFSLoadFile, + HFSReadFile, + HFSGetDirEntry, + HFSGetFileBlock, + HFSGetUUID, + HFSGetDescription, + HFSFree, + 0, + kBIOSDevTypeHardDrive, 0); + bvr->next = map->bvr; + map->bvr = bvr; + map->bvrcnt++; + } + } + } + } while (0); + + free(buffer); + + if (countPtr) *countPtr = map ? map->bvrcnt : 0; + + return map ? map->bvr : NULL; +} + +//========================================================================== + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +/* + * Trying to figure out the filsystem type of a given partition. + */ +static int probeFileSystem(int biosdev, unsigned int blkoff) +{ + // detected filesystem type; + int result = -1; + int fatbits; + + // Allocating buffer for 4 sectors. + const void * probeBuffer = malloc(PROBEFS_SIZE); + if (probeBuffer == NULL) + goto exit; + + // Reading first 4 sectors of current partition + int error = readBytes(biosdev, blkoff, 0, PROBEFS_SIZE, (void *)probeBuffer); + if (error) + goto exit; + + if (HFSProbe(probeBuffer)) + result = FDISK_HFS; +#ifndef OPTION_ROM + else if (EX2Probe(probeBuffer)) + result = FDISK_LINUX; + else if (NTFSProbe(probeBuffer)) + result = FDISK_NTFS; +#endif + else if (fatbits=MSDOSProbe(probeBuffer)) + { + switch (fatbits) + { + case 32: + default: + result = FDISK_FAT32; + break; + case 16: + result = FDISK_DOS16B; + break; + case 12: + result = FDISK_DOS12; + break; + } + } + else + // Couldn't detect filesystem type + result = 0; + +exit: + if (probeBuffer != NULL) free((void *)probeBuffer); + return result; +} + +static bool isPartitionUsed(gpt_ent * partition) +{ + // + // Ask whether the given partition is used. + // + + return efi_guid_is_null((EFI_GUID const*)partition->ent_type) ? false : true; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +static BVRef diskScanGPTBootVolumes( int biosdev, int * countPtr ) +{ + struct DiskBVMap * map = NULL; + void *buffer = malloc(BPS); + int error; + if ( error = readBytes( biosdev, /*secno*/0, 0, BPS, buffer ) != 0) { + verbose("Failed to read boot sector from BIOS device %02xh. Error=%d\n", biosdev, error); + goto scanErr; + } + struct REAL_disk_blk0 *fdiskMap = buffer; + if ( OSSwapLittleToHostInt16(fdiskMap->signature) != DISK_SIGNATURE ) + { + verbose("Failed to find boot signature on BIOS device %02xh\n", biosdev); + goto scanErr; + } + + int fdiskID = 0; + unsigned index; + for ( index = 0; index < FDISK_NPART; index++ ) + { + if ( fdiskMap->parts[index].systid ) + { + if ( fdiskMap->parts[index].systid == 0xEE ) + { + // Fail if two 0xEE partitions are present which + // means the FDISK code will wind up parsing it. + if ( fdiskID ) goto scanErr; + + fdiskID = index + 1; + } + } + } + + if ( fdiskID == 0 ) goto scanErr; + verbose("Attempting to read GPT\n"); + + if(readBytes(biosdev, 1, 0, BPS, buffer) != 0) + goto scanErr; + + gpt_hdr *headerMap = buffer; + + // Determine whether the partition header signature is present. + + if ( memcmp(headerMap->hdr_sig, GPT_HDR_SIG, strlen(GPT_HDR_SIG)) ) + { + goto scanErr; + } + + // Determine whether the partition header size is valid. + + UInt32 headerCheck = OSSwapLittleToHostInt32(headerMap->hdr_crc_self); + UInt32 headerSize = OSSwapLittleToHostInt32(headerMap->hdr_size); + + if ( headerSize < offsetof(gpt_hdr, padding) ) + { + goto scanErr; + } + + if ( headerSize > BPS ) + { + goto scanErr; + } + + // Determine whether the partition header checksum is valid. + + headerMap->hdr_crc_self = 0; + + if ( crc32(0, headerMap, headerSize) != headerCheck ) + { + goto scanErr; + } + + // Determine whether the partition entry size is valid. + + UInt64 gptBlock = 0; + UInt32 gptCheck = 0; + UInt32 gptCount = 0; + UInt32 gptID = 0; + gpt_ent * gptMap = 0; + UInt32 gptSize = 0; + + gptBlock = OSSwapLittleToHostInt64(headerMap->hdr_lba_table); + gptCheck = OSSwapLittleToHostInt32(headerMap->hdr_crc_table); + gptCount = OSSwapLittleToHostInt32(headerMap->hdr_entries); + gptSize = OSSwapLittleToHostInt32(headerMap->hdr_entsz); + + if ( gptSize < sizeof(gpt_ent) ) + { + goto scanErr; + } + + // Allocate a buffer large enough to hold one map, rounded to a media block. + free(buffer); + buffer = NULL; + + UInt32 bufferSize = IORound(gptCount * gptSize, BPS); + if(bufferSize == 0) + goto scanErr; + buffer = malloc(bufferSize); + + if(readBytes(biosdev, gptBlock, 0, bufferSize, buffer) != 0) + goto scanErr; + + verbose("Read GPT\n"); + + // Allocate a new map for this BIOS device and insert it into the chain + map = malloc(sizeof(*map)); + map->biosdev = biosdev; + map->bvr = NULL; + map->bvrcnt = 0; + map->next = gDiskBVMap; + gDiskBVMap = map; + + // fdisk like partition type id. + int fsType = 0; + + for(gptID = 1; gptID <= gptCount; ++gptID) + { + BVRef bvr = NULL; + unsigned int bvrFlags = 0; + + // size on disk can be larger than sizeof(gpt_ent) + gptMap = (gpt_ent *) ( buffer + ( (gptID - 1) * gptSize) ); + + // NOTE: EFI_GUID's are in LE and we know we're on an x86. + // The IOGUIDPartitionScheme.cpp code uses byte-based UUIDs, we don't. + + if(isPartitionUsed(gptMap)) + { + char stringuuid[100]; + efi_guid_unparse_upper((EFI_GUID*)gptMap->ent_type, stringuuid); + verbose("Reading GPT partition %d, type %s\n", gptID, stringuuid); + + // Getting fdisk like partition type. + fsType = probeFileSystem(biosdev, gptMap->ent_lba_start); + + if ( (efi_guid_compare(&GPT_BOOT_GUID, (EFI_GUID const*)gptMap->ent_type) == 0) || + (efi_guid_compare(&GPT_HFS_GUID, (EFI_GUID const*)gptMap->ent_type) == 0) ) + { + bvrFlags = (efi_guid_compare(&GPT_BOOT_GUID, (EFI_GUID const*)gptMap->ent_type) == 0) ? kBVFlagBooter : 0; + bvr = newGPTBVRef(biosdev, + gptID, + gptMap->ent_lba_start, + gptMap, + HFSInitPartition, + HFSLoadFile, + HFSReadFile, + HFSGetDirEntry, + HFSGetFileBlock, + HFSGetUUID, + HFSGetDescription, + HFSFree, + 0, + kBIOSDevTypeHardDrive, bvrFlags); + } + + // zef - foreign OS support + if ( (efi_guid_compare(&GPT_BASICDATA_GUID, (EFI_GUID const*)gptMap->ent_type) == 0) || + (efi_guid_compare(&GPT_BASICDATA2_GUID, (EFI_GUID const*)gptMap->ent_type) == 0) ) + { + + switch (fsType) + { +#ifndef OPTION_ROM + case FDISK_NTFS: + bvr = newGPTBVRef(biosdev, gptID, gptMap->ent_lba_start, gptMap, + 0, 0, 0, 0, 0, 0, NTFSGetDescription, + (BVFree)free, 0, kBIOSDevTypeHardDrive, 0); + break; + + case FDISK_LINUX: + bvr = newGPTBVRef(biosdev, gptID, gptMap->ent_lba_start, gptMap, + 0, 0, 0, 0, 0, 0, EX2GetDescription, + (BVFree)free, 0, kBIOSDevTypeHardDrive, 0); + break; +#endif + default: + bvr = newGPTBVRef(biosdev, gptID, gptMap->ent_lba_start, gptMap, + 0, 0, 0, 0, 0, 0, 0, + (BVFree)free, 0, kBIOSDevTypeHardDrive, 0); + break; + } + + } + + // turbo - save our booter partition + // zef - only on original boot device + if ( (efi_guid_compare(&GPT_EFISYS_GUID, (EFI_GUID const*)gptMap->ent_type) == 0) ) + { + switch (fsType) + { + case FDISK_HFS: + if (readBootSector( biosdev, gptMap->ent_lba_start, (void *)0x7e00 ) == 0) + { + bvr = newGPTBVRef(biosdev, gptID, gptMap->ent_lba_start, gptMap, + HFSInitPartition, + HFSLoadFile, + HFSReadFile, + HFSGetDirEntry, + HFSGetFileBlock, + HFSGetUUID, + HFSGetDescription, + HFSFree, + 0, kBIOSDevTypeHardDrive, kBVFlagEFISystem); + } + break; + + case FDISK_FAT32: + if (testFAT32EFIBootSector( biosdev, gptMap->ent_lba_start, (void *)0x7e00 ) == 0) + { + bvr = newGPTBVRef(biosdev, gptID, gptMap->ent_lba_start, gptMap, + MSDOSInitPartition, + MSDOSLoadFile, + MSDOSReadFile, + MSDOSGetDirEntry, + MSDOSGetFileBlock, + MSDOSGetUUID, + MSDOSGetDescription, + MSDOSFree, + 0, kBIOSDevTypeHardDrive, kBVFlagEFISystem); + } + break; + + if (biosdev == gBIOSDev) + gBIOSBootVolume = bvr; + } + } + + if (bvr) + { + // Fixup bvr with the fake fdisk partition type. + if (fsType > 0) bvr->part_type = fsType; + + bvr->next = map->bvr; + map->bvr = bvr; + ++map->bvrcnt; + } + + } + } + +scanErr: + free(buffer); + + if(map) + { + if(countPtr) *countPtr = map->bvrcnt; + return map->bvr; + } + else + { + if(countPtr) *countPtr = 0; + return NULL; + } +} + +//========================================================================== + +static void scanFSLevelBVRSettings(BVRef chain) +{ + BVRef bvr; + char dirSpec[512], fileSpec[512]; + char label[BVSTRLEN]; + int ret; + long flags, time; + int fh, fileSize, error; + + for (bvr = chain; bvr; bvr = bvr->next) + { + ret = -1; + error = 0; + + // + // Check for alternate volume label on boot helper partitions. + // + if (bvr->flags & kBVFlagBooter) + { + sprintf(dirSpec, "hd(%d,%d)/System/Library/CoreServices/", BIOS_DEV_UNIT(bvr), bvr->part_no); + strcpy(fileSpec, ".disk_label.contentDetails"); + ret = GetFileInfo(dirSpec, fileSpec, &flags, &time); + if (!ret) + { + fh = open(strcat(dirSpec, fileSpec), 0); + fileSize = file_size(fh); + if (fileSize > 0 && fileSize < BVSTRLEN) + { + if (read(fh, label, fileSize) != fileSize) + error = -1; + } + else + error = -1; + + close(fh); + + if (!error) + { + label[fileSize] = '\0'; + strcpy(bvr->altlabel, label); + } + } + } + + // + // Check for SystemVersion.plist or ServerVersion.plist + // to determine if a volume hosts an installed system. + // + if (bvr->flags & kBVFlagNativeBoot) + { + sprintf(dirSpec, "hd(%d,%d)/System/Library/CoreServices/", BIOS_DEV_UNIT(bvr), bvr->part_no); + strcpy(fileSpec, "SystemVersion.plist"); + ret = GetFileInfo(dirSpec, fileSpec, &flags, &time); + + if (ret == -1) + { + strcpy(fileSpec, "ServerVersion.plist"); + ret = GetFileInfo(dirSpec, fileSpec, &flags, &time); + } + + if (!ret) + bvr->flags |= kBVFlagSystemVolume; + } + + } +} +#ifndef OPTION_ROM +void rescanBIOSDevice(int biosdev) +{ + struct DiskBVMap *oldMap = diskResetBootVolumes(biosdev); + CacheReset(); + diskFreeMap(oldMap); + oldMap = NULL; + scanBootVolumes(biosdev, 0); +} +#endif + +struct DiskBVMap* diskResetBootVolumes(int biosdev) +{ + struct DiskBVMap * map; + struct DiskBVMap *prevMap = NULL; + for ( map = gDiskBVMap; map; prevMap = map, map = map->next ) { + if ( biosdev == map->biosdev ) { + break; + } + } + if(map != NULL) + { + verbose("Resetting BIOS device %xh\n", biosdev); + // Reset the biosbuf cache + cache_valid = false; + if(map == gDiskBVMap) + gDiskBVMap = map->next; + else if(prevMap != NULL) + prevMap->next = map->next; + else + stop(""); + } + // Return the old map, either to be freed, or reinserted later + return map; +} + +// Frees a DiskBVMap and all of its BootVolume's +void diskFreeMap(struct DiskBVMap *map) +{ + if(map != NULL) + { + while(map->bvr != NULL) + { + BVRef bvr = map->bvr; + map->bvr = bvr->next; + (*bvr->bv_free)(bvr); + } + free(map); + } +} + +BVRef diskScanBootVolumes( int biosdev, int * countPtr ) +{ + struct DiskBVMap * map = NULL; + BVRef bvr; + int count = 0; + + // Find an existing mapping for this device. + + for ( map = gDiskBVMap; map; map = map->next ) { + if ( biosdev == map->biosdev ) { + count = map->bvrcnt; + break; + } + } + + if (map == NULL) { + bvr = diskScanGPTBootVolumes(biosdev, &count); + if (bvr == NULL) { + bvr = diskScanFDiskBootVolumes(biosdev, &count); + } + if (bvr == NULL) { + bvr = diskScanAPMBootVolumes(biosdev, &count); + } + if (bvr) + { + scanFSLevelBVRSettings(bvr); + } + } else { + bvr = map->bvr; + } + if (countPtr) *countPtr += count; + return bvr; +} + +BVRef getBVChainForBIOSDev(int biosdev) +{ + BVRef chain = NULL; + struct DiskBVMap * map = NULL; + + for (map = gDiskBVMap; map; map = map->next) + { + if (map->biosdev == biosdev) + { + chain = map->bvr; + break; + } + } + + return chain; +} + +BVRef newFilteredBVChain(int minBIOSDev, int maxBIOSDev, unsigned int allowFlags, unsigned int denyFlags, int *count) +{ + BVRef chain = NULL; + BVRef bvr = NULL; + BVRef newBVR = NULL; + BVRef prevBVR = NULL; + + struct DiskBVMap * map = NULL; + int bvCount = 0; + + const char *raw = 0; + char* val = 0; + int len; + + getValueForKey(kHidePartition, &raw, &len, &bootInfo->bootConfig); + if(raw) + { + val = XMLDecode(raw); + } + + /* + * Traverse gDISKBVmap to get references for + * individual bvr chains of each drive. + */ + for (map = gDiskBVMap; map; map = map->next) + { + for (bvr = map->bvr; bvr; bvr = bvr->next) + { + /* + * Save the last bvr. + */ + if (newBVR) prevBVR = newBVR; + + /* + * Allocate and copy the matched bvr entry into a new one. + */ + newBVR = (BVRef) malloc(sizeof(*newBVR)); + bcopy(bvr, newBVR, sizeof(*newBVR)); + + /* + * Adjust the new bvr's fields. + */ + newBVR->next = NULL; + newBVR->filtered = true; + + if ( (!allowFlags || newBVR->flags & allowFlags) + && (!denyFlags || !(newBVR->flags & denyFlags) ) + && (newBVR->biosdev >= minBIOSDev && newBVR->biosdev <= maxBIOSDev) + ) + newBVR->visible = true; + + /* Looking for "Hide Partition" entries in 'hd(x,y)|uuid|"label" hd(m,n)|uuid|"label"' format + * to be able to hide foreign partitions from the boot menu. + */ + if ( (newBVR->flags & kBVFlagForeignBoot) ) + { + char *start, *next = val; + long len = 0; + do + { + start = strbreak(next, &next, &len); + if(len && matchVolumeToString(newBVR, start, len) ) + newBVR->visible = false; + } + while ( next && *next ); + } + + /* + * Use the first bvr entry as the starting chain pointer. + */ + if (!chain) + chain = newBVR; + + /* + * Update the previous bvr's link pointer to use the new memory area. + */ + if (prevBVR) + prevBVR->next = newBVR; + + if (newBVR->visible) + bvCount++; + } + } + +#if DEBUG + for (bvr = chain; bvr; bvr = bvr->next) + { + msglog(" bvr: %x, dev: %x, part: %d, flags: %x, vis: %d\n", bvr, bvr->biosdev, bvr->part_no, bvr->flags, bvr->visible); + } + msglog("count: %d\n", bvCount); +// getc(); +#endif + + *count = bvCount; + + free(val); + return chain; +} + +int freeFilteredBVChain(const BVRef chain) +{ + int ret = 1; + BVRef bvr = chain; + BVRef nextBVR = NULL; + + while (bvr) + { + nextBVR = bvr->next; + + if (bvr->filtered) + { + free(bvr); + } + else + { + ret = 0; + break; + } + + bvr = nextBVR; + } + + return ret; +} + +//========================================================================== + +static const struct NamedValue fdiskTypes[] = +{ +#ifndef OPTION_ROM + { FDISK_NTFS, "Windows NTFS" }, +#endif + { FDISK_DOS12, "Windows FAT12" }, + { FDISK_DOS16B, "Windows FAT16" }, + { FDISK_DOS16S, "Windows FAT16" }, + { FDISK_DOS16SLBA, "Windows FAT16" }, + { FDISK_SMALLFAT32, "Windows FAT32" }, + { FDISK_FAT32, "Windows FAT32" }, +#ifndef OPTION_ROM + { FDISK_LINUX, "Linux" }, +#endif + { FDISK_UFS, "Apple UFS" }, + { FDISK_HFS, "Apple HFS" }, + { FDISK_BOOTER, "Apple Boot/UFS" }, + { 0xCD, "CD-ROM" }, + { 0x00, 0 } /* must be last */ +}; + +//========================================================================== + +bool matchVolumeToString( BVRef bvr, const char* match, long matchLen) +{ + char testStr[128]; + + if ( !bvr || !match || !*match) + return 0; + + if ( bvr->biosdev < 0x80 || bvr->biosdev >= 0x100 ) + return 0; + + // Try to match hd(x,y) first. + sprintf(testStr, "hd(%d,%d)", BIOS_DEV_UNIT(bvr), bvr->part_no); + if ( matchLen ? !strncmp(match, testStr, matchLen) : !strcmp(match, testStr) ) + return true; + + // Try to match volume UUID. + if ( bvr->fs_getuuid && bvr->fs_getuuid(bvr, testStr) == 0) + { + if( matchLen ? !strncmp(match, testStr, matchLen) : !strcmp(match, testStr) ) + return true; + } + + // Try to match volume label (always quoted). + if ( bvr->description ) + { + bvr->description(bvr, testStr, sizeof(testStr)-1); + if( matchLen ? !strncmp(match, testStr, matchLen) : !strcmp(match, testStr) ) + return true; + } + + return false; +} + +/* If Rename Partition has defined an alias, then extract it for description purpose + * The format for the rename string is the following: + * hd(x,y)|uuid|"label" "alias";hd(m,n)|uuid|"label" etc; ... + */ + +bool getVolumeLabelAlias(BVRef bvr, char* str, long strMaxLen) +{ + char *aliasList, *entryStart, *entryNext; + + if ( !str || strMaxLen <= 0) + return false; + + aliasList = XMLDecode(getStringForKey(kRenamePartition, &bootInfo->bootConfig)); + if ( !aliasList ) + return false; + + for ( entryStart = entryNext = aliasList; + entryNext && *entryNext; + entryStart = entryNext ) + { + char *volStart, *volEnd, *aliasStart; + long volLen, aliasLen; + + // Delimit current entry + entryNext = strchr(entryStart, ';'); + if ( entryNext ) + { + *entryNext = '\0'; + entryNext++; + } + + volStart = strbreak(entryStart, &volEnd, &volLen); + if(!volLen) + continue; + + aliasStart = strbreak(volEnd, 0, &aliasLen); + if(!aliasLen) + continue; + + if ( matchVolumeToString(bvr, volStart, volLen) ) + { + strncat(str, aliasStart, min(strMaxLen, aliasLen)); + free(aliasList); + + return true; + } + } + + free(aliasList); + return false; +} + +void getBootVolumeDescription( BVRef bvr, char * str, long strMaxLen, bool useDeviceDescription ) +{ + unsigned char type; + char *p = str; + + if(!bvr || !p || strMaxLen <= 0) + return; + + type = (unsigned char) bvr->part_type; + + if (useDeviceDescription) + { + int len = getDeviceDescription(bvr, str); + if(len >= strMaxLen) + return; + + strcpy(str + len, " "); + len++; + strMaxLen -= len; + p += len; + } + + /* See if a partition rename is preferred */ + if(getVolumeLabelAlias(bvr, p, strMaxLen)) { + strncpy(bvr->label, p, strMaxLen); + return; // we're done here no need to seek for real name + } + + // + // Get the volume label using filesystem specific functions + // or use the alternate volume label if available. + // + if (*bvr->altlabel != '\0') + strncpy(p, bvr->altlabel, strMaxLen); + else if (bvr->description) + bvr->description(bvr, p, strMaxLen); + + if (*p == '\0') { + const char * name = getNameForValue( fdiskTypes, type ); + if (name == NULL) { + name = bvr->type_name; + } + if (name == NULL) { + sprintf(p, "TYPE %02x", type); + } else { + strncpy(p, name, strMaxLen); + } + } + + // Set the devices label + sprintf(bvr->label, p); +} + +//========================================================================== +int readBootSector( int biosdev, unsigned int secno, void * buffer ) +{ + struct disk_blk0 * bootSector = (struct disk_blk0 *) buffer; + int error; + + if ( bootSector == NULL ) + { + if ( gBootSector == NULL ) + { + gBootSector = (struct disk_blk0 *) malloc(sizeof(*gBootSector)); + if ( gBootSector == NULL ) return -1; + } + bootSector = gBootSector; + } + + error = readBytes( biosdev, secno, 0, BPS, bootSector ); + if ( error || bootSector->signature != DISK_SIGNATURE ) + return -1; + + return 0; +} + +/* + * Format of boot1f32 block. + */ + +#define BOOT1F32_MAGIC "BOOT " +#define BOOT1F32_MAGICLEN 11 + +struct disk_boot1f32_blk { + unsigned char init[3]; + unsigned char fsheader[87]; + unsigned char magic[BOOT1F32_MAGICLEN]; + unsigned char bootcode[409]; + unsigned short signature; +}; + +int testFAT32EFIBootSector( int biosdev, unsigned int secno, void * buffer ) +{ + struct disk_boot1f32_blk * bootSector = (struct disk_boot1f32_blk *) buffer; + int error; + + if ( bootSector == NULL ) + { + if ( gBootSector == NULL ) + { + gBootSector = (struct disk_blk0 *) malloc(sizeof(*gBootSector)); + if ( gBootSector == NULL ) return -1; + } + bootSector = (struct disk_boot1f32_blk *) gBootSector; + } + + error = readBytes( biosdev, secno, 0, BPS, bootSector ); + if ( error || bootSector->signature != DISK_SIGNATURE + || strncmp((const char *)bootSector->magic, BOOT1F32_MAGIC, BOOT1F32_MAGICLEN) ) + return -1; + + return 0; +} + +//========================================================================== +// Handle seek request from filesystem modules. + +void diskSeek( BVRef bvr, long long position ) +{ + bvr->fs_boff = position / BPS; + bvr->fs_byteoff = position % BPS; +} + +//========================================================================== +// Handle read request from filesystem modules. + +int diskRead( BVRef bvr, long addr, long length ) +{ + return readBytes( bvr->biosdev, + bvr->fs_boff + bvr->part_boff, + bvr->fs_byteoff, + length, + (void *) addr ); +} +#ifndef OPTION_ROM + +int rawDiskRead( BVRef bvr, unsigned int secno, void *buffer, unsigned int len ) +{ + int secs; + unsigned char *cbuf = (unsigned char *)buffer; + unsigned int copy_len; + int rc; + + if ((len & (BPS-1)) != 0) { + error("raw disk read not sector aligned"); + return -1; + } + secno += bvr->part_boff; + + cache_valid = false; + + while (len > 0) { + secs = len / BPS; + if (secs > N_CACHE_SECS) secs = N_CACHE_SECS; + copy_len = secs * BPS; + + //printf("rdr: ebiosread(%d, %d, %d)\n", bvr->biosdev, secno, secs); + if ((rc = ebiosread(bvr->biosdev, secno, secs)) != 0) { + /* Ignore corrected ECC errors */ + if (rc != ECC_CORRECTED_ERR) { + error(" EBIOS read error: %s\n", bios_error(rc), rc); + error(" Block %d Sectors %d\n", secno, secs); + return rc; + } + } + bcopy( trackbuf, cbuf, copy_len ); + len -= copy_len; + cbuf += copy_len; + secno += secs; + spinActivityIndicator(secs); + } + + return 0; +} + +int rawDiskWrite( BVRef bvr, unsigned int secno, void *buffer, unsigned int len ) +{ + int secs; + unsigned char *cbuf = (unsigned char *)buffer; + unsigned int copy_len; + int rc; + + if ((len & (BPS-1)) != 0) { + error("raw disk write not sector aligned"); + return -1; + } + secno += bvr->part_boff; + + cache_valid = false; + + while (len > 0) { + secs = len / BPS; + if (secs > N_CACHE_SECS) secs = N_CACHE_SECS; + copy_len = secs * BPS; + + bcopy( cbuf, trackbuf, copy_len ); + //printf("rdr: ebioswrite(%d, %d, %d)\n", bvr->biosdev, secno, secs); + if ((rc = ebioswrite(bvr->biosdev, secno, secs)) != 0) { + error(" EBIOS write error: %s\n", bios_error(rc), rc); + error(" Block %d Sectors %d\n", secno, secs); + return rc; + } + len -= copy_len; + cbuf += copy_len; + secno += secs; + spinActivityIndicator(secs); + } + + return 0; +} +#endif + +int diskIsCDROM(BVRef bvr) +{ + struct driveInfo di; + + if (getDriveInfo(bvr->biosdev, &di) == 0 && di.no_emulation) { + return 1; + } + return 0; +} + +int biosDevIsCDROM(int biosdev) +{ + struct driveInfo di; + + if (getDriveInfo(biosdev, &di) == 0 && di.no_emulation) + { + return 1; + } + return 0; +} Index: branches/slice/rev749/libsaio/pci_setup.c =================================================================== --- branches/slice/rev749/libsaio/pci_setup.c (revision 0) +++ branches/slice/rev749/libsaio/pci_setup.c (revision 1169) @@ -0,0 +1,29 @@ +#include "libsaio.h" +#include "boot.h" +#include "bootstruct.h" +#include "pci.h" +#include "modules.h" + +#define DEBUG_PCI 0 + +#if DEBUG_PCI +#define DBG(x...) msglog(x) +#else +#define DBG(x...) +#endif + + +void setup_pci_devs(pci_dt_t *pci_dt) +{ + pci_dt_t *current = pci_dt; + + + while (current) + { + execute_hook("PCIDevice", current, NULL, NULL, NULL); + DBG("setup_pci_devs current devID=%08x\n", current->device_id); + setup_pci_devs(current->children); + DBG("setup_pci_devs children devID=%08x\n", current->device_id); + current = current->next; + } +} Index: branches/slice/rev749/libsaio/cpu.h =================================================================== --- branches/slice/rev749/libsaio/cpu.h (revision 0) +++ branches/slice/rev749/libsaio/cpu.h (revision 1169) @@ -0,0 +1,551 @@ +/* + * Copyright 2008 Islam Ahmed Zaid. All rights reserved. + * AsereBLN: 2009: cleanup and bugfix + */ + +#ifndef __LIBSAIO_CPU_H +#define __LIBSAIO_CPU_H + +#include "libsaio.h" + +#define CPU_VIA_C3 0x07 +#define CPU_VIA_C3_Ezra_T 0x08 + +#define CPU_VIA_NANO 0x0F + + + +extern void scan_cpu(); //PlatformInfo_t *); + +#define min(a,b) ((a) < (b) ? (a) : (b)) +#define quad(hi,lo) (((uint64_t)(hi)) << 32 | (lo)) + + +#define bit(n) (1UL << (n)) +#define bitmask(h,l) ((bit(h)|(bit(h)-1)) & ~(bit(l)-1)) +#define bitfield(x,h,l) (((x) & bitmask(h,l)) >> l) + +#define CPUID_VID_INTEL "GenuineIntel" +#define CPUID_VID_AMD "AuthenticAMD" + +#define CPUID_STRING_UNKNOWN "Unknown CPU Typ" + +#define _Bit(n) (1ULL << n) +#define _HBit(n) (1ULL << ((n)+32)) + +/* + * The CPUID_FEATURE_XXX values define 64-bit values + * returned in %ecx:%edx to a CPUID request with %eax of 1: + */ +#define CPUID_FEATURE_FPU _Bit(0) /* Floating point unit on-chip */ +#define CPUID_FEATURE_VME _Bit(1) /* Virtual Mode Extension */ +#define CPUID_FEATURE_DE _Bit(2) /* Debugging Extension */ +#define CPUID_FEATURE_PSE _Bit(3) /* Page Size Extension */ +#define CPUID_FEATURE_TSC _Bit(4) /* Time Stamp Counter */ +#define CPUID_FEATURE_MSR _Bit(5) /* Model Specific Registers */ +#define CPUID_FEATURE_PAE _Bit(6) /* Physical Address Extension */ +#define CPUID_FEATURE_MCE _Bit(7) /* Machine Check Exception */ +#define CPUID_FEATURE_CX8 _Bit(8) /* CMPXCHG8B */ +#define CPUID_FEATURE_APIC _Bit(9) /* On-chip APIC */ +#define CPUID_FEATURE_SEP _Bit(11) /* Fast System Call */ +#define CPUID_FEATURE_MTRR _Bit(12) /* Memory Type Range Register */ +#define CPUID_FEATURE_PGE _Bit(13) /* Page Global Enable */ +#define CPUID_FEATURE_MCA _Bit(14) /* Machine Check Architecture */ +#define CPUID_FEATURE_CMOV _Bit(15) /* Conditional Move Instruction */ +#define CPUID_FEATURE_PAT _Bit(16) /* Page Attribute Table */ +#define CPUID_FEATURE_PSE36 _Bit(17) /* 36-bit Page Size Extension */ +#define CPUID_FEATURE_PSN _Bit(18) /* Processor Serial Number */ +#define CPUID_FEATURE_CLFSH _Bit(19) /* CLFLUSH Instruction supported */ +#define CPUID_FEATURE_DS _Bit(21) /* Debug Store */ +#define CPUID_FEATURE_ACPI _Bit(22) /* Thermal monitor and Clock Ctrl */ +#define CPUID_FEATURE_MMX _Bit(23) /* MMX supported */ +#define CPUID_FEATURE_FXSR _Bit(24) /* Fast floating pt save/restore */ +#define CPUID_FEATURE_SSE _Bit(25) /* Streaming SIMD extensions */ +#define CPUID_FEATURE_SSE2 _Bit(26) /* Streaming SIMD extensions 2 */ +#define CPUID_FEATURE_SS _Bit(27) /* Self-Snoop */ +#define CPUID_FEATURE_HTT _Bit(28) /* Hyper-Threading Technology */ +#define CPUID_FEATURE_TM _Bit(29) /* Thermal Monitor (TM1) */ +#define CPUID_FEATURE_PBE _Bit(31) /* Pend Break Enable */ + +#define CPUID_FEATURE_SSE3 _HBit(0) /* Streaming SIMD extensions 3 */ +#define CPUID_FEATURE_PCLMULQDQ _HBit(1) /* PCLMULQDQ Instruction */ + +#define CPUID_FEATURE_MONITOR _HBit(3) /* Monitor/mwait */ +#define CPUID_FEATURE_DSCPL _HBit(4) /* Debug Store CPL */ +#define CPUID_FEATURE_VMX _HBit(5) /* VMX */ +#define CPUID_FEATURE_SMX _HBit(6) /* SMX */ +#define CPUID_FEATURE_EST _HBit(7) /* Enhanced SpeedsTep (GV3) */ +#define CPUID_FEATURE_TM2 _HBit(8) /* Thermal Monitor 2 */ +#define CPUID_FEATURE_SSSE3 _HBit(9) /* Supplemental SSE3 instructions */ +#define CPUID_FEATURE_CID _HBit(10) /* L1 Context ID */ + +#define CPUID_FEATURE_CX16 _HBit(13) /* CmpXchg16b instruction */ +#define CPUID_FEATURE_xTPR _HBit(14) /* Send Task PRiority msgs */ +#define CPUID_FEATURE_PDCM _HBit(15) /* Perf/Debug Capability MSR */ + +#define CPUID_FEATURE_DCA _HBit(18) /* Direct Cache Access */ +#define CPUID_FEATURE_SSE4_1 _HBit(19) /* Streaming SIMD extensions 4.1 */ +#define CPUID_FEATURE_SSE4_2 _HBit(20) /* Streaming SIMD extensions 4.2 */ +#define CPUID_FEATURE_xAPIC _HBit(21) /* Extended APIC Mode */ +#define CPUID_FEATURE_POPCNT _HBit(23) /* POPCNT instruction */ +#define CPUID_FEATURE_AES _HBit(25) /* AES instructions */ +#define CPUID_FEATURE_VMM _HBit(31) /* VMM (Hypervisor) present */ + +/* + * The CPUID_EXTFEATURE_XXX values define 64-bit values + * returned in %ecx:%edx to a CPUID request with %eax of 0x80000001: + */ +#define CPUID_EXTFEATURE_SYSCALL _Bit(11) /* SYSCALL/sysret */ +#define CPUID_EXTFEATURE_XD _Bit(20) /* eXecute Disable */ +#define CPUID_EXTFEATURE_1GBPAGE _Bit(26) /* 1G-Byte Page support */ +#define CPUID_EXTFEATURE_RDTSCP _Bit(27) /* RDTSCP */ +#define CPUID_EXTFEATURE_EM64T _Bit(29) /* Extended Mem 64 Technology */ + +//#define CPUID_EXTFEATURE_LAHF _HBit(20) /* LAFH/SAHF instructions */ +// New definition with Snow kernel +#define CPUID_EXTFEATURE_LAHF _HBit(0) /* LAHF/SAHF instructions */ +/* + * The CPUID_EXTFEATURE_XXX values define 64-bit values + * returned in %ecx:%edx to a CPUID request with %eax of 0x80000007: + */ +#define CPUID_EXTFEATURE_TSCI _Bit(8) /* TSC Invariant */ + +#define CPUID_CACHE_SIZE 16 /* Number of descriptor values */ + +#define CPUID_MWAIT_EXTENSION _Bit(0) /* enumeration of WMAIT extensions */ +#define CPUID_MWAIT_BREAK _Bit(1) /* interrupts are break events */ + + + + +#define MSR_IA32_PLATFORM_ID 0x0017 +#define MSR_P4_EBC_FREQUENCY_ID 0x002C +#define MSR_CORE_THREAD_COUNT 0x0035 +#define MSR_IA32_PERF_STATUS 0x0198 +#define MSR_IA32_PERF_CONTROL 0x0199 +#define MSR_IA32_EXT_CONFIG 0x00EE +#define MSR_FLEX_RATIO 0x0194 //Slice - not used +#define MSR_FSB_FREQ 0x00CD //Slice - not used +#define MSR_PLATFORM_INFO 0x00CE // for i7 it gives min and max +#define MSR_TURBO_RATIO 0x01AD //Slice - for i7 +#define MSR_IA32_EBL_CR_POWERON 0x002A //Meklort - for VIA +#define K8_FIDVID_STATUS 0xC0010042 +#define K10_COFVID_STATUS 0xC0010071 + +/* Centaur-Hauls/IDT defined MSRs. */ +#define MSR_IDT_FCR1 0x00000107 +#define MSR_IDT_FCR2 0x00000108 +#define MSR_IDT_FCR3 0x00000109 +#define MSR_IDT_FCR4 0x0000010a + +#define MSR_IDT_MCR0 0x00000110 +#define MSR_IDT_MCR1 0x00000111 +#define MSR_IDT_MCR2 0x00000112 +#define MSR_IDT_MCR3 0x00000113 +#define MSR_IDT_MCR4 0x00000114 +#define MSR_IDT_MCR5 0x00000115 +#define MSR_IDT_MCR6 0x00000116 +#define MSR_IDT_MCR7 0x00000117 +#define MSR_IDT_MCR_CTRL 0x00000120 + +/* VIA Nano defined MSTs */ +#define MSR_NANO_FCR1 0x1204 // This MSR contains control bits and family, model, etc. +#define MSR_NANO_FCR2 0x1206 // This MSR contains part of the vendor string +#define MSR_NANO_FCR3 0x1207 // This MSR contains part of the vendor string +#define VIA_ALTERNATIVE_VENDOR_BIT (1 << 8) // This bit in MSR_IDT_FCR1 enables alternative vendor string + +/* VIA Cyrix defined MSRs */ +#define MSR_VIA_FCR 0x00001107 +#define MSR_VIA_LONGHAUL 0x0000110a +#define MSR_VIA_RNG 0x0000110b +#define MSR_VIA_BCR2 0x00001147 + + + +#define DEFAULT_FSB 100000 /* for now, hardcoding 100MHz for old CPUs */ + +// DFE: This constant comes from older xnu: +#define CLKNUM 1193182 /* formerly 1193167 */ + +// DFE: These two constants come from Linux except CLOCK_TICK_RATE replaced with CLKNUM +#define CALIBRATE_TIME_MSEC 30 /* 30 msecs */ +#define CALIBRATE_LATCH ((CLKNUM * CALIBRATE_TIME_MSEC + 1000/2)/1000) + +typedef enum { eax, ebx, ecx, edx } cpuid_register_t; +/* + * Cache ID descriptor structure, used to parse CPUID leaf 2. + * Note: not used in kernel. + */ +typedef enum { Lnone, L1I, L1D, L2U, L3U, LCACHE_MAX } cache_type_t ; +typedef struct { + unsigned char value; /* Descriptor value */ + cache_type_t type; /* Cache type */ + unsigned int size; /* Cache size */ + unsigned int linesize; /* Cache line size */ + const char *description; /* Cache description */ +} cpuid_cache_desc_t; + + +#define CACHE_DESC(value,type,size,linesize,text) \ +{ value, type, size, linesize, text } + +/* Physical CPU info - this is exported out of the kernel (kexts), so be wary of changes */ +typedef struct { + char cpuid_vendor[16]; + char cpuid_brand_string[48]; + const char *cpuid_model_string; + + cpu_type_t cpuid_type; /* this is *not* a cpu_type_t in our */ + uint8_t cpuid_family; + uint8_t cpuid_model; + uint8_t cpuid_extmodel; + uint8_t cpuid_extfamily; + uint8_t cpuid_stepping; + uint64_t cpuid_features; + uint64_t cpuid_extfeatures; + uint32_t cpuid_signature; + uint8_t cpuid_brand; + + uint32_t cache_size[LCACHE_MAX]; + uint32_t cache_linesize; + + uint8_t cache_info[64]; /* list of cache descriptors */ + + uint32_t cpuid_cores_per_package; + uint32_t cpuid_logical_per_package; + uint32_t cache_sharing[LCACHE_MAX]; + uint32_t cache_partitions[LCACHE_MAX]; + + cpu_type_t cpuid_cpu_type; /* */ + cpu_subtype_t cpuid_cpu_subtype; /* */ + + /* Monitor/mwait Leaf: */ + uint32_t cpuid_mwait_linesize_min; + uint32_t cpuid_mwait_linesize_max; + uint32_t cpuid_mwait_extensions; + uint32_t cpuid_mwait_sub_Cstates; + + /* Thermal and Power Management Leaf: */ + boolean_t cpuid_thermal_sensor; + boolean_t cpuid_thermal_dynamic_acceleration; + uint32_t cpuid_thermal_thresholds; + boolean_t cpuid_thermal_ACNT_MCNT; + + /* Architectural Performance Monitoring Leaf: */ + uint8_t cpuid_arch_perf_version; + uint8_t cpuid_arch_perf_number; + uint8_t cpuid_arch_perf_width; + uint8_t cpuid_arch_perf_events_number; + uint32_t cpuid_arch_perf_events; + uint8_t cpuid_arch_perf_fixed_number; + uint8_t cpuid_arch_perf_fixed_width; + + /* Cache details: */ + uint32_t cpuid_cache_linesize; + uint32_t cpuid_cache_L2_associativity; + uint32_t cpuid_cache_size; + + /* Virtual and physical address aize: */ + uint32_t cpuid_address_bits_physical; + uint32_t cpuid_address_bits_virtual; + + uint32_t cpuid_microcode_version; + + /* Numbers of tlbs per processor [i|d, small|large, level0|level1] */ + uint32_t cpuid_tlb[2][2][2]; +#define TLB_INST 0 +#define TLB_DATA 1 +#define TLB_SMALL 0 +#define TLB_LARGE 1 + uint32_t cpuid_stlb; + + uint32_t core_count; + uint32_t thread_count; + + /* Max leaf ids available from CPUID */ + uint32_t cpuid_max_basic; + uint32_t cpuid_max_ext; +} i386_cpu_info_t; + +static i386_cpu_info_t cpuid_cpu_info; + +static i386_cpu_info_t *cpuid_info(void) +{ + return &cpuid_cpu_info; +} + + +static inline uint64_t rdtsc64(void) +{ + uint64_t ret; + __asm__ volatile("rdtsc" : "=A" (ret)); + return ret; +} + +static inline uint64_t rdmsr64(uint32_t msr) +{ + uint64_t ret; + __asm__ volatile("rdmsr" : "=A" (ret) : "c" (msr)); + return ret; +} + +static inline void wrmsr64(uint32_t msr, uint64_t val) +{ + __asm__ volatile("wrmsr" : : "c" (msr), "A" (val)); +} + +static inline void intel_waitforsts(void) { + uint32_t inline_timeout = 100000; + while (rdmsr64(MSR_IA32_PERF_STATUS) & (1 << 21)) { if (!inline_timeout--) break; } +} + +static inline void do_cpuid(uint32_t selector, uint32_t *data) +{ + asm volatile ("cpuid" + : "=a" (data[0]), + "=b" (data[1]), + "=c" (data[2]), + "=d" (data[3]) + : "a" (selector)); +} + +static inline void do_cpuid2(uint32_t selector, uint32_t selector2, uint32_t *data) +{ + asm volatile ("cpuid" + : "=a" (data[0]), + "=b" (data[1]), + "=c" (data[2]), + "=d" (data[3]) + : "a" (selector), "c" (selector2)); +} + +// DFE: enable_PIT2 and disable_PIT2 come from older xnu + +/* + * Enable or disable timer 2. + * Port 0x61 controls timer 2: + * bit 0 gates the clock, + * bit 1 gates output to speaker. + */ +static inline void enable_PIT2(void) +{ + /* Enable gate, disable speaker */ + __asm__ volatile( + " inb $0x61,%%al \n\t" + " and $0xFC,%%al \n\t" /* & ~0x03 */ + " or $1,%%al \n\t" + " outb %%al,$0x61 \n\t" + : : : "%al" ); +} + +static inline void disable_PIT2(void) +{ + /* Disable gate and output to speaker */ + __asm__ volatile( + " inb $0x61,%%al \n\t" + " and $0xFC,%%al \n\t" /* & ~0x03 */ + " outb %%al,$0x61 \n\t" + : : : "%al" ); +} + +// DFE: set_PIT2_mode0, poll_PIT2_gate, and measure_tsc_frequency are +// roughly based on Linux code + +/* Set the 8254 channel 2 to mode 0 with the specified value. + In mode 0, the counter will initially set its gate low when the + timer expires. For this to be useful, you ought to set it high + before calling this function. The enable_PIT2 function does this. + */ +static inline void set_PIT2_mode0(uint16_t value) +{ + __asm__ volatile( + " movb $0xB0,%%al \n\t" + " outb %%al,$0x43 \n\t" + " movb %%dl,%%al \n\t" + " outb %%al,$0x42 \n\t" + " movb %%dh,%%al \n\t" + " outb %%al,$0x42" + : : "d"(value) /*: no clobber */ ); +} + +/* Returns the number of times the loop ran before the PIT2 signaled */ +static inline unsigned long poll_PIT2_gate(void) +{ + unsigned long count = 0; + unsigned char nmi_sc_val; + do { + ++count; + __asm__ volatile( + "inb $0x61,%0" + : "=q"(nmi_sc_val) /*:*/ /* no input */ /*:*/ /* no clobber */); + } while( (nmi_sc_val & 0x20) == 0); + return count; +} + +static void cpuid_update_generic_info() +{ + uint32_t cpuid_reg[4]; + uint32_t max_extid; + char str[128]; + char* p; + i386_cpu_info_t* info_p = cpuid_info(); + + /* Get vendor */ + do_cpuid(0, cpuid_reg); + bcopy((char *)&cpuid_reg[ebx], &info_p->cpuid_vendor[0], 4); /* ug */ + bcopy((char *)&cpuid_reg[ecx], &info_p->cpuid_vendor[8], 4); + bcopy((char *)&cpuid_reg[edx], &info_p->cpuid_vendor[4], 4); + info_p->cpuid_vendor[12] = 0; + + /* Get extended CPUID results */ + do_cpuid(0x80000000, cpuid_reg); + max_extid = cpuid_reg[eax]; + + /* Check to see if we can get the brand string */ + if (max_extid >= 0x80000004) { + /* + * The brand string is up to 48 bytes and is guaranteed to be + * NUL terminated. + */ + do_cpuid(0x80000002, cpuid_reg); + bcopy((char *)cpuid_reg, &str[0], 16); + do_cpuid(0x80000003, cpuid_reg); + bcopy((char *)cpuid_reg, &str[16], 16); + do_cpuid(0x80000004, cpuid_reg); + bcopy((char *)cpuid_reg, &str[32], 16); + for (p = str; *p != '\0'; p++) { + if (*p != ' ') break; + } + strncpy(info_p->cpuid_brand_string, p, + sizeof(info_p->cpuid_brand_string)); + + if (!strncmp(info_p->cpuid_brand_string, CPUID_STRING_UNKNOWN, + min(sizeof(info_p->cpuid_brand_string), + strlen(CPUID_STRING_UNKNOWN) + 1))) { + /* + * This string means we have a firmware-programmable brand string, + * and the firmware couldn't figure out what sort of CPU we have. + */ + info_p->cpuid_brand_string[0] = '\0'; + } + } + + /* Get cache and addressing info */ + if (max_extid >= 0x80000006) { + do_cpuid(0x80000006, cpuid_reg); + info_p->cpuid_cache_linesize = bitfield(cpuid_reg[ecx], 7, 0); + info_p->cpuid_cache_L2_associativity = bitfield(cpuid_reg[ecx], 15, 12); + info_p->cpuid_cache_size = bitfield(cpuid_reg[ecx], 31, 16); + do_cpuid(0x80000008, cpuid_reg); + info_p->cpuid_address_bits_physical = bitfield(cpuid_reg[eax], 7, 0); + info_p->cpuid_address_bits_virtual = bitfield(cpuid_reg[eax], 15, 8); + } + + /* Get processor signature and decode */ + do_cpuid(1, cpuid_reg); + info_p->cpuid_signature = cpuid_reg[eax]; + info_p->cpuid_stepping = bitfield(cpuid_reg[eax], 3, 0); + info_p->cpuid_model = bitfield(cpuid_reg[eax], 7, 4); + info_p->cpuid_family = bitfield(cpuid_reg[eax], 11, 8); + info_p->cpuid_type = bitfield(cpuid_reg[eax], 13, 12); + info_p->cpuid_extmodel = bitfield(cpuid_reg[eax], 19, 16); + info_p->cpuid_extfamily = bitfield(cpuid_reg[eax], 27, 20); + info_p->cpuid_brand = bitfield(cpuid_reg[ebx], 7, 0); + info_p->cpuid_features = quad(cpuid_reg[ecx], cpuid_reg[edx]); + + /* Fold extensions into family/model */ + if (info_p->cpuid_family == 0x0f) { + info_p->cpuid_family += info_p->cpuid_extfamily; + } + if (info_p->cpuid_family == 0x0f || info_p->cpuid_family== 0x06) { + info_p->cpuid_model += (info_p->cpuid_extmodel << 4); + } + + if (info_p->cpuid_features & CPUID_FEATURE_HTT) { + info_p->cpuid_logical_per_package = bitfield(cpuid_reg[ebx], 23, 16); + } else { + info_p->cpuid_logical_per_package = 1; + } + + if (max_extid >= 0x80000001) { + do_cpuid(0x80000001, cpuid_reg); + info_p->cpuid_extfeatures = quad(cpuid_reg[ecx], cpuid_reg[edx]); + } + + if (info_p->cpuid_extfeatures & CPUID_FEATURE_MONITOR) { + + do_cpuid(5, cpuid_reg); + info_p->cpuid_mwait_linesize_min = cpuid_reg[eax]; + info_p->cpuid_mwait_linesize_max = cpuid_reg[ebx]; + info_p->cpuid_mwait_extensions = cpuid_reg[ecx]; + info_p->cpuid_mwait_sub_Cstates = cpuid_reg[edx]; + + do_cpuid(6, cpuid_reg); + info_p->cpuid_thermal_sensor = bitfield(cpuid_reg[eax], 0, 0); + info_p->cpuid_thermal_dynamic_acceleration = + bitfield(cpuid_reg[eax], 1, 1); + info_p->cpuid_thermal_thresholds = bitfield(cpuid_reg[ebx], 3, 0); + info_p->cpuid_thermal_ACNT_MCNT = bitfield(cpuid_reg[ecx], 0, 0); + + do_cpuid(0xa, cpuid_reg); + info_p->cpuid_arch_perf_version = bitfield(cpuid_reg[eax], 7, 0); + info_p->cpuid_arch_perf_number = bitfield(cpuid_reg[eax],15, 8); + info_p->cpuid_arch_perf_width = bitfield(cpuid_reg[eax],23,16); + info_p->cpuid_arch_perf_events_number = bitfield(cpuid_reg[eax],31,24); + info_p->cpuid_arch_perf_events = cpuid_reg[ebx]; + info_p->cpuid_arch_perf_fixed_number = bitfield(cpuid_reg[edx], 4, 0); + info_p->cpuid_arch_perf_fixed_width = bitfield(cpuid_reg[edx],12, 5); + + } + + do_cpuid(4, cpuid_reg); + info_p->cpuid_cores_per_package = bitfield(cpuid_reg[eax], 31, 26) + 1; + + if (info_p->cpuid_cores_per_package == 0) { + info_p->cpuid_cores_per_package = 1; + + } + + switch (info_p->cpuid_model) + { + case 0x1C: + { + //uint64_t msr = rdmsr64(MSR_CORE_THREAD_COUNT); + info_p->core_count = 1; //bitfield((uint32_t)msr, 19, 16); + info_p->thread_count = 2; //bitfield((uint32_t)msr, 15, 0); + } + break; + case 0x19: // some i5 ??? + case 0x1A: // Intel Core i7 LGA1366 (45nm) + case 0x1E: // Intel Core i5, i7 LGA1156 (45nm) + case 0x25: // Intel Core i3, i5, i7 LGA1156 (32nm) + { + uint64_t msr = rdmsr64(MSR_CORE_THREAD_COUNT); + info_p->core_count = bitfield((uint32_t)msr, 31, 16); + info_p->thread_count = bitfield((uint32_t)msr, 15, 0); + } break; + case 0x2C: // Intel Core i7 LGA1366 (32nm) 6 Core + case 0x1F: + case 0x2F: + { + uint64_t msr = rdmsr64(MSR_CORE_THREAD_COUNT); + info_p->core_count = bitfield((uint32_t)msr, 19, 16); + info_p->thread_count = bitfield((uint32_t)msr, 15, 0); + break; + } + + default: + { + do_cpuid(1, cpuid_reg); + info_p->core_count = bitfield(cpuid_reg[1], 23, 16); + } break; + } + if (info_p->core_count == 0) { + info_p->core_count = info_p->cpuid_cores_per_package; + info_p->thread_count = info_p->cpuid_logical_per_package; + } + +} + + +#endif /* !__LIBSAIO_CPU_H */ Index: branches/slice/rev749/libsaio/disk.h =================================================================== --- branches/slice/rev749/libsaio/disk.h (revision 0) +++ branches/slice/rev749/libsaio/disk.h (revision 1169) @@ -0,0 +1,14 @@ +/* + * disk.h + * Chameleon + * + * Created by Daniel Miranda on 27/07/10. + * Copyright 2010 __MyCompanyName__. All rights reserved. + * + */ +#ifndef __LIBSAIO_DISK_H +#define __LIBSAIO_DISK_H + +bool matchVolumeToString( BVRef bvr, const char* match, long strMaxLen); + +#endif /* __LIBSAIO_DISK_H */ \ No newline at end of file Property changes on: branches/slice/rev749/libsaio/disk.h ___________________________________________________________________ Added: svn:executable + Index: branches/slice/rev749/libsaio/cache.c =================================================================== --- branches/slice/rev749/libsaio/cache.c (revision 0) +++ branches/slice/rev749/libsaio/cache.c (revision 1169) @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 2.0 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * cache.c - A simple cache for file systems meta-data. + * + * Copyright (c) 2000 Apple Computer, Inc. + * + * DRI: Josh de Cesare + */ + +#include +// #include + +struct CacheEntry { + CICell ih; + long time; + long long offset; +}; +typedef struct CacheEntry CacheEntry; + +#define kCacheSize (0x100000) +#define kCacheMinBlockSize (0x200) +#define kCacheMaxBlockSize (0x8000) +#define kCacheMaxEntries (kCacheSize / kCacheMinBlockSize) + +static CICell gCacheIH; +static long gCacheBlockSize; +static long gCacheNumEntries; +static long gCacheTime; + +#ifdef __i386__ +static CacheEntry *gCacheEntries; +static char *gCacheBuffer; +#else +static CacheEntry gCacheEntries[kCacheMaxEntries]; +static char gCacheBuffer[kCacheSize]; +#endif + +#if CACHE_STATS +unsigned long gCacheHits; +unsigned long gCacheMisses; +unsigned long gCacheEvicts; +#endif + +void CacheReset() +{ + gCacheIH = NULL; +} + +void CacheInit( CICell ih, long blockSize ) +{ +#ifdef __i386__ + if ((ih == gCacheIH) && (blockSize == gCacheBlockSize)) + return; +#endif + + if ((blockSize < kCacheMinBlockSize) || + (blockSize > kCacheMaxBlockSize)) + return; + + gCacheBlockSize = blockSize; + gCacheNumEntries = kCacheSize / gCacheBlockSize; + gCacheTime = 0; + +#if CACHE_STATS + gCacheHits = 0; + gCacheMisses = 0; + gCacheEvicts = 0; +#endif + + gCacheIH = ih; + +#ifdef __i386__ + if (!gCacheBuffer) gCacheBuffer = (char *) malloc(kCacheSize); + if (!gCacheEntries) gCacheEntries = (CacheEntry *) malloc(kCacheMaxEntries * sizeof(CacheEntry)); + if ( !gCacheBuffer || !gCacheEntries ) + { + gCacheIH = 0; // invalidate cache + return; + } +#endif + + bzero(gCacheEntries, kCacheMaxEntries * sizeof(CacheEntry)); +} + +long CacheRead( CICell ih, char * buffer, long long offset, + long length, long cache ) +{ + long cnt, oldestEntry = 0, oldestTime, loadCache = 0; + CacheEntry *entry; + + // See if the data can be cached. + if (cache && (gCacheIH == ih) && (length == gCacheBlockSize)) { + // Look for the data in the cache. + for (cnt = 0; cnt < gCacheNumEntries; cnt++) { + entry = &gCacheEntries[cnt]; + if ((entry->ih == ih) && (entry->offset == offset)) { + entry->time = ++gCacheTime; + break; + } + } + + // If the data was found copy it to the caller. + if (cnt != gCacheNumEntries) { + bcopy(gCacheBuffer + cnt * gCacheBlockSize, buffer, gCacheBlockSize); +#if CACHE_STATS + gCacheHits++; +#endif + return gCacheBlockSize; + } + + // Could not find the data in the cache. + loadCache = 1; + } + + // Read the data from the disk. + Seek(ih, offset); + Read(ih, (long)buffer, length); +#if CACHE_STATS + if (cache) gCacheMisses++; +#endif + + // Put the data from the disk in the cache if needed. + if (loadCache) { + // Find a free entry. + oldestTime = gCacheTime; + for (cnt = 0; cnt < gCacheNumEntries; cnt++) { + entry = &gCacheEntries[cnt]; + + // Found a free entry. + if (entry->ih == 0) break; + + if (entry->time < oldestTime) { + oldestTime = entry->time; + oldestEntry = cnt; + } + } + + // If no free entry was found, use the oldest. + if (cnt == gCacheNumEntries) { + cnt = oldestEntry; +#if CACHE_STATS + gCacheEvicts++; +#endif + } + + // Copy the data from disk to the new entry. + entry = &gCacheEntries[cnt]; + entry->ih = ih; + entry->time = ++gCacheTime; + entry->offset = offset; + bcopy(buffer, gCacheBuffer + cnt * gCacheBlockSize, gCacheBlockSize); + } + + return length; +} Index: branches/slice/rev749/libsaio/pci.c =================================================================== --- branches/slice/rev749/libsaio/pci.c (revision 0) +++ branches/slice/rev749/libsaio/pci.c (revision 1169) @@ -0,0 +1,208 @@ +/* + * + * Copyright 2008 by Islam M. Ahmed Zaid. All rights reserved. + * + */ + +#include "libsaio.h" +#include "boot.h" +#include "bootstruct.h" +#include "pci.h" +#include "pci_root.h" + +#ifndef DEBUG_PCI +#define DEBUG_PCI 0 +#endif + +#if DEBUG_PCI +#define DBG(x...) verbose(x) +#else +#define DBG(x...) msglog(x) +#endif + +//static +pci_dt_t *root_pci_dev; + + +uint8_t pci_config_read8(uint32_t pci_addr, uint8_t reg) +{ + pci_addr |= reg & ~3; + outl(PCI_ADDR_REG, pci_addr); + return inb(PCI_DATA_REG + (reg & 3)); +} + +uint16_t pci_config_read16(uint32_t pci_addr, uint8_t reg) +{ + pci_addr |= reg & ~3; + outl(PCI_ADDR_REG, pci_addr); + return inw(PCI_DATA_REG + (reg & 2)); +} + +uint32_t pci_config_read32(uint32_t pci_addr, uint8_t reg) +{ + pci_addr |= reg & ~3; + outl(PCI_ADDR_REG, pci_addr); + return inl(PCI_DATA_REG); +} + +void pci_config_write8(uint32_t pci_addr, uint8_t reg, uint8_t data) +{ + pci_addr |= reg & ~3; + outl(PCI_ADDR_REG, pci_addr); + outb(PCI_DATA_REG + (reg & 3), data); +} + +void pci_config_write16(uint32_t pci_addr, uint8_t reg, uint16_t data) +{ + pci_addr |= reg & ~3; + outl(PCI_ADDR_REG, pci_addr); + outw(PCI_DATA_REG + (reg & 2), data); +} + +void pci_config_write32(uint32_t pci_addr, uint8_t reg, uint32_t data) +{ + pci_addr |= reg & ~3; + outl(PCI_ADDR_REG, pci_addr); + outl(PCI_DATA_REG, data); +} + +void scan_pci_bus(pci_dt_t *start, uint8_t bus) +{ + pci_dt_t *new; + pci_dt_t **current = &start->children; + uint32_t id; + uint32_t pci_addr; + uint8_t dev; + uint8_t func; + uint8_t secondary_bus; + uint8_t header_type; + + for (dev = 0; dev < 32; dev++) + { + for (func = 0; func < 8; func++) + { + pci_addr = PCIADDR(bus, dev, func); + id = pci_config_read32(pci_addr, PCI_VENDOR_ID); + if (!id || id == 0xffffffff) + { + continue; + } + new = (pci_dt_t*)malloc(sizeof(pci_dt_t)); + if (!new) + return; + memset(new, 0, sizeof(pci_dt_t)); + + new->dev.addr = pci_addr; + new->vendor_id = id & 0xffff; + new->device_id = (id >> 16) & 0xffff; + new->subsys_id.subsys_id = pci_config_read32(pci_addr, PCI_SUBSYSTEM_VENDOR_ID); + new->subclass = pci_config_read8(pci_addr, PCI_CLASS_PROG); + new->class_id = pci_config_read16(pci_addr, PCI_CLASS_DEVICE); + new->parent = start; + + header_type = pci_config_read8(pci_addr, PCI_HEADER_TYPE); + switch (header_type & 0x7f) + { + case PCI_HEADER_TYPE_BRIDGE: + case PCI_HEADER_TYPE_CARDBUS: + secondary_bus = pci_config_read8(pci_addr, PCI_SECONDARY_BUS); + if (secondary_bus != 0) + { + scan_pci_bus(new, secondary_bus); + } + break; + } + *current = new; + current = &new->next; + + if ((func == 0) && ((header_type & 0x80) == 0)) + { + break; + } + } + } +} + +void enable_pci_devs(void) +{ + uint16_t id; + uint32_t rcba, *fd; + + id = pci_config_read16(PCIADDR(0, 0x00, 0), 0x00); + /* make sure we're on Intel chipset */ + if (id != 0x8086) + return; + rcba = pci_config_read32(PCIADDR(0, 0x1f, 0), 0xf0) & ~1; + fd = (uint32_t *)(rcba + 0x3418); + /* set SMBus Disable (SD) to 0 */ + *fd &= ~0x8; + /* and all devices? */ + //*fd = 0x1; +} + + +void build_pci_dt(void) +{ + root_pci_dev = malloc(sizeof(pci_dt_t)); + + if (!root_pci_dev) + return; + gRootPCIDev = (void*)root_pci_dev; + bzero(root_pci_dev, sizeof(pci_dt_t)); + enable_pci_devs(); + scan_pci_bus(root_pci_dev, 0); +#if 1 //DEBUG_PCI + dump_pci_dt(root_pci_dev->children); + //pause(); +#endif +} + +static char dev_path[256]; +char *get_pci_dev_path(pci_dt_t *pci_dt) +{ + pci_dt_t *current; + pci_dt_t *end; + char tmp[64]; + + dev_path[0] = 0; + end = root_pci_dev; + + int uid = getPciRootUID(); + while (end != pci_dt) + { + current = pci_dt; + while (current->parent != end) + current = current->parent; + end = current; + if (current->parent == root_pci_dev) + { + sprintf(tmp, "PciRoot(0x%x)/Pci(0x%x,0x%x)", uid, + current->dev.bits.dev, current->dev.bits.func); + } + else + { + sprintf(tmp, "/Pci(0x%x,0x%x)", + current->dev.bits.dev, current->dev.bits.func); + } + strcat(dev_path, tmp); + } + return dev_path; +} + +#ifndef OPTION_ROM +void dump_pci_dt(pci_dt_t *pci_dt) +{ + pci_dt_t *current; + + current = pci_dt; + while (current) { + msglog("%02x:%02x.%x [%04x%02x] [%04x:%04x] (subsys [%04x:%04x]):: %s\n", + current->dev.bits.bus, current->dev.bits.dev, current->dev.bits.func, + current->class_id, current->subclass, current->vendor_id, current->device_id, + current->subsys_id.subsys.vendor_id, current->subsys_id.subsys.device_id, + get_pci_dev_path(current)); + dump_pci_dt(current->children); + current = current->next; + } +} +#endif Index: branches/slice/rev749/libsaio/stringTable.c =================================================================== --- branches/slice/rev749/libsaio/stringTable.c (revision 0) +++ branches/slice/rev749/libsaio/stringTable.c (revision 1169) @@ -0,0 +1,855 @@ +/* + * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 2.0 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright 1993 NeXT, Inc. + * All rights reserved. + */ + +#include "bootstruct.h" +#include "libsaio.h" +#include "xml.h" + +extern char *Language; +extern char *LoadableFamilies; + +bool sysConfigValid; + +/* + * Compare a string to a key with quoted characters + */ +static inline int +keyncmp(const char *str, const char *key, int n) +{ + int c; + while (n--) { + c = *key++; + if (c == '\\') { + switch(c = *key++) { + case 'n': + c = '\n'; + break; + case 'r': + c = '\r'; + break; + case 't': + c = '\t'; + break; + default: + break; + } + } else if (c == '\"') { + /* Premature end of key */ + return 1; + } + if (c != *str++) { + return 1; + } + } + return 0; +} + +#if UNUSED + +static void eatThru(char val, const char **table_p) +{ + register const char *table = *table_p; + register bool found = false; + + while (*table && !found) + { + if (*table == '\\') table += 2; + else + { + if (*table == val) found = true; + table++; + } + } + *table_p = table; +} + +/* Remove key and its associated value from the table. */ + +bool +removeKeyFromTable(const char *key, char *table) +{ + register int len; + register char *tab; + char *buf; + + len = strlen(key); + tab = (char *)table; + buf = (char *)malloc(len + 3); + + sprintf(buf, "\"%s\"", key); + len = strlen(buf); + + while(*tab) { + if(strncmp(buf, tab, len) == 0) { + char c; + + while((c = *(tab + len)) != ';') { + if(c == 0) { + len = -1; + goto out; + } + len++; + } + len++; + if(*(tab + len) == '\n') len++; + goto out; + } + tab++; + } + len = -1; +out: + free(buf); + + if(len == -1) return false; + + while((*tab = *(tab + len))) { + tab++; + } + + return true; +} + +char * +newStringFromList( + char **list, + int *size +) +{ + char *begin = *list, *end; + char *newstr; + int newsize = *size; + int bufsize; + + while (*begin && newsize && isspace(*begin)) { + begin++; + newsize--; + } + end = begin; + while (*end && newsize && !isspace(*end)) { + end++; + newsize--; + } + if (begin == end) + return 0; + bufsize = end - begin + 1; + newstr = malloc(bufsize); + strlcpy(newstr, begin, bufsize); + *list = end; + *size = newsize; + return newstr; +} + +#endif + +/* + * compress == compress escaped characters to one character + */ +int stringLength(const char *table, int compress) +{ + int ret = 0; + + while (*table) + { + if (*table == '\\') + { + table += 2; + ret += 1 + (compress ? 0 : 1); + } + else + { + if (*table == '\"') return ret; + ret++; + table++; + } + } + return ret; +} + + +bool getValueForConfigTableKey(config_file_t *config, const char *key, const char **val, int *size) +{ + if (config->dictionary != 0 ) { + // Look up key in XML dictionary + TagPtr value; + value = XMLGetProperty(config->dictionary, key); + if (value != 0) { + if (value->type != kTagTypeString) { + error("Non-string tag '%s' found in config file\n", + key); + return false; + } + *val = value->string; + *size = strlen(value->string); + return true; + } + } else { + + // Legacy plist-style table + + } + + return false; +} + +#if UNUSED + +/* + * Returns a new malloc'ed string if one is found + * in the string table matching 'key'. Also translates + * \n escapes in the string. + */ +char *newStringForStringTableKey( + char *table, + char *key, + config_file_t *config +) +{ + const char *val; + char *newstr, *p; + int size; + + if (getValueForConfigTableKey(config, key, &val, &size)) { + newstr = (char *)malloc(size+1); + for (p = newstr; size; size--, p++, val++) { + if ((*p = *val) == '\\') { + switch (*++val) { + case 'r': + *p = '\r'; + break; + case 'n': + *p = '\n'; + break; + case 't': + *p = '\t'; + break; + default: + *p = *val; + break; + } + size--; + } + } + *p = '\0'; + return newstr; + } else { + return 0; + } +} + +#endif + +char * +newStringForKey(char *key, config_file_t *config) +{ + const char *val; + char *newstr; + int size; + + if (getValueForKey(key, &val, &size, config) && size) { + newstr = (char *)malloc(size + 1); + strlcpy(newstr, val, size + 1); + return newstr; + } else { + return 0; + } +} + +/* parse a command line + * in the form: [ ...] [" >> "${1}/${packagename}/Distribution" + + perl -i -p -e "s/%CHAMELEONVERSION%/${version%%-*}/g" `find "${1}/${packagename}/Resources" -type f` + perl -i -p -e "s/%CHAMELEONREVISION%/${revision}/g" `find "${1}/${packagename}/Resources" -type f` + + stage=${stage/RC/Release Candidate } + stage=${stage/FINAL/2.0 Final} + perl -i -p -e "s/%CHAMELEONSTAGE%/${stage}/g" `find "${1}/${packagename}/Resources" -type f` + + find "${1}/${packagename}" -name '.DS_Store' -delete + pushd "${1}/${packagename}" >/dev/null + xar -c -f "${1%/*}/${packagename// /}-${version}-r${revision}.pkg" --compression none . + popd >/dev/null + + md5=$( md5 "${1%/*}/${packagename// /}-${version}-r${revision}.pkg" | awk {'print $4'} ) + echo "MD5 (${packagename// /}-${version}-r${revision}.pkg) = ${md5}" > "${1%/*}/${packagename// /}-${version}-r${revision}.pkg.md5" +} + +main "${1}" "${2}" "${3}" "${4}" "${5}" + Property changes on: branches/slice/rev749/buildpkg ___________________________________________________________________ Added: svn:executable + Index: branches/slice/rev749/ChamMek.xcodeproj/slice.pbxuser =================================================================== --- branches/slice/rev749/ChamMek.xcodeproj/slice.pbxuser (revision 0) +++ branches/slice/rev749/ChamMek.xcodeproj/slice.pbxuser (revision 1169) @@ -0,0 +1,972 @@ +// !$*UTF8*$! +{ + 08FB7793FE84155DC02AAC07 /* Project object */ = { + activeBuildConfigurationName = Debug; + activeExecutable = 12C26D2E12B0DDF400AF7F4B /* ChamMek */; + activeTarget = 8DD76FA90486AB0100D96B5E /* ChamMek */; + addToTargets = ( + 8DD76FA90486AB0100D96B5E /* ChamMek */, + ); + codeSenseManager = 12C26D3812B0DDFC00AF7F4B /* Code sense */; + executables = ( + 12C26D2E12B0DDF400AF7F4B /* ChamMek */, + ); + perUserDictionary = { + PBXConfiguration.PBXFileTableDataSource3.PBXExecutablesDataSource = { + PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; + PBXFileTableDataSourceColumnSortingKey = PBXExecutablesDataSource_NameID; + PBXFileTableDataSourceColumnWidthsKey = ( + 22, + 300, + 612.58349609375, + ); + PBXFileTableDataSourceColumnsKey = ( + PBXExecutablesDataSource_ActiveFlagID, + PBXExecutablesDataSource_NameID, + PBXExecutablesDataSource_CommentsID, + ); + }; + PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = { + PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; + PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; + PBXFileTableDataSourceColumnWidthsKey = ( + 20, + 725, + 20, + 48, + 43, + 43, + 20, + ); + PBXFileTableDataSourceColumnsKey = ( + PBXFileDataSource_FiletypeID, + PBXFileDataSource_Filename_ColumnID, + PBXFileDataSource_Built_ColumnID, + PBXFileDataSource_ObjectSize_ColumnID, + PBXFileDataSource_Errors_ColumnID, + PBXFileDataSource_Warnings_ColumnID, + PBXFileDataSource_Target_ColumnID, + ); + }; + PBXPerProjectTemplateStateSaveDate = 314271982; + PBXWorkspaceStateSaveDate = 314271982; + }; + perUserProjectItems = { + 120DFB1712BA3A4D00C7EAC8 /* PBXTextBookmark */ = 120DFB1712BA3A4D00C7EAC8 /* PBXTextBookmark */; + 120DFB1812BA3A4D00C7EAC8 /* PBXTextBookmark */ = 120DFB1812BA3A4D00C7EAC8 /* PBXTextBookmark */; + 120DFF6B12BA3BF500C7EAC8 /* PBXTextBookmark */ = 120DFF6B12BA3BF500C7EAC8 /* PBXTextBookmark */; + 12121ED112B261EA00207E55 /* PBXTextBookmark */ = 12121ED112B261EA00207E55 /* PBXTextBookmark */; + 1216139E12B65BB50019961E /* PBXTextBookmark */ = 1216139E12B65BB50019961E /* PBXTextBookmark */; + 121613FF12B65D970019961E /* PBXTextBookmark */ = 121613FF12B65D970019961E /* PBXTextBookmark */; + 124C493212B8D846005AA276 /* PBXTextBookmark */ = 124C493212B8D846005AA276 /* PBXTextBookmark */; + 124C493712B8D846005AA276 /* PBXTextBookmark */ = 124C493712B8D846005AA276 /* PBXTextBookmark */; + 124C494212B8E8C2005AA276 /* PBXTextBookmark */ = 124C494212B8E8C2005AA276 /* PBXTextBookmark */; + 124C494312B8E8C2005AA276 /* PBXTextBookmark */ = 124C494312B8E8C2005AA276 /* PBXTextBookmark */; + 124C494512B8E8C2005AA276 /* PBXTextBookmark */ = 124C494512B8E8C2005AA276 /* PBXTextBookmark */; + 124C494B12B8EA5D005AA276 /* PBXTextBookmark */ = 124C494B12B8EA5D005AA276 /* PBXTextBookmark */; + 1267813012B7B13E00A25CED /* PBXTextBookmark */ = 1267813012B7B13E00A25CED /* PBXTextBookmark */; + 1299A51F12B3C328007ED516 /* PBXTextBookmark */ = 1299A51F12B3C328007ED516 /* PBXTextBookmark */; + 1299A55612B3C4DF007ED516 /* PBXTextBookmark */ = 1299A55612B3C4DF007ED516 /* PBXTextBookmark */; + 12AB04BD12B663F5005A745F /* PBXTextBookmark */ = 12AB04BD12B663F5005A745F /* PBXTextBookmark */; + 12AB04EC12B665EA005A745F /* PBXTextBookmark */ = 12AB04EC12B665EA005A745F /* PBXTextBookmark */; + 12AF764312BA614B003BBFD3 /* PBXTextBookmark */ = 12AF764312BA614B003BBFD3 /* PBXTextBookmark */; + 12B46E6612B75631006C2B9C /* PBXTextBookmark */ = 12B46E6612B75631006C2B9C /* PBXTextBookmark */; + 12B46E6812B75631006C2B9C /* PBXTextBookmark */ = 12B46E6812B75631006C2B9C /* PBXTextBookmark */; + 12B46E6912B75631006C2B9C /* PBXTextBookmark */ = 12B46E6912B75631006C2B9C /* PBXTextBookmark */; + 12B46E6A12B75631006C2B9C /* PBXTextBookmark */ = 12B46E6A12B75631006C2B9C /* PBXTextBookmark */; + 12B90A2012B2A7E200FE287A /* PBXTextBookmark */ = 12B90A2012B2A7E200FE287A /* PBXTextBookmark */; + 12B90A2B12B2A86B00FE287A /* PBXTextBookmark */ = 12B90A2B12B2A86B00FE287A /* PBXTextBookmark */; + 12B90A4D12B2AE1300FE287A /* PBXTextBookmark */ = 12B90A4D12B2AE1300FE287A /* PBXTextBookmark */; + 12B90A4F12B2AE1300FE287A /* PBXTextBookmark */ = 12B90A4F12B2AE1300FE287A /* PBXTextBookmark */; + 12B90A5212B2AE1300FE287A /* PBXTextBookmark */ = 12B90A5212B2AE1300FE287A /* PBXTextBookmark */; + 12B9F42612B29A4A00FE287A /* PBXTextBookmark */ = 12B9F42612B29A4A00FE287A /* PBXTextBookmark */; + 12BF14DA12B3CF8E00D798FE /* PBXTextBookmark */ = 12BF14DA12B3CF8E00D798FE /* PBXTextBookmark */; + 12C7009812B7BCE7006BD382 /* PBXTextBookmark */ = 12C7009812B7BCE7006BD382 /* PBXTextBookmark */; + 12C7009912B7BCE7006BD382 /* PBXTextBookmark */ = 12C7009912B7BCE7006BD382 /* PBXTextBookmark */; + 12C704E512B7BD3E006BD382 /* PBXTextBookmark */ = 12C704E512B7BD3E006BD382 /* PBXTextBookmark */; + 12C7FC4D12B7BCD3006BD382 /* PBXTextBookmark */ = 12C7FC4D12B7BCD3006BD382 /* PBXTextBookmark */; + 12C7FC4E12B7BCD3006BD382 /* PlistBookmark */ = 12C7FC4E12B7BCD3006BD382 /* PlistBookmark */; + 12C8CB6812B5529D003DA1E4 /* PBXTextBookmark */ = 12C8CB6812B5529D003DA1E4 /* PBXTextBookmark */; + 12CC44C812B3947B007E0C76 /* PBXTextBookmark */ = 12CC44C812B3947B007E0C76 /* PBXTextBookmark */; + 12D6232512BA5F380032F367 /* PBXTextBookmark */ = 12D6232512BA5F380032F367 /* PBXTextBookmark */; + 12D6232612BA5F380032F367 /* PBXTextBookmark */ = 12D6232612BA5F380032F367 /* PBXTextBookmark */; + 12E17AE612B2BA9B00607D8E /* PBXTextBookmark */ = 12E17AE612B2BA9B00607D8E /* PBXTextBookmark */; + 12E6FB5712BB458400C2A021 /* PBXTextBookmark */ = 12E6FB5712BB458400C2A021 /* PBXTextBookmark */; + 12EFD98A12B510D9002A1712 /* PBXTextBookmark */ = 12EFD98A12B510D9002A1712 /* PBXTextBookmark */; + 12EFE2FD12B51ED5002A1712 /* PBXTextBookmark */ = 12EFE2FD12B51ED5002A1712 /* PBXTextBookmark */; + 12EFE65A12B547A7002A1712 /* PBXTextBookmark */ = 12EFE65A12B547A7002A1712 /* PBXTextBookmark */; + 12EFE95E12B549B6002A1712 /* PBXTextBookmark */ = 12EFE95E12B549B6002A1712 /* PBXTextBookmark */; + 12FC0E7512BB4B5200E9CFA8 /* PBXTextBookmark */ = 12FC0E7512BB4B5200E9CFA8 /* PBXTextBookmark */; + 12FC0E9412BB65A800E9CFA8 /* PBXTextBookmark */ = 12FC0E9412BB65A800E9CFA8 /* PBXTextBookmark */; + 12FC11AA12BB687A00E9CFA8 /* PBXTextBookmark */ = 12FC11AA12BB687A00E9CFA8 /* PBXTextBookmark */; + 12FC14AE12BB730100E9CFA8 /* PBXTextBookmark */ = 12FC14AE12BB730100E9CFA8 /* PBXTextBookmark */; + }; + sourceControlManager = 12C26D3712B0DDFC00AF7F4B /* Source Control */; + userBuildSettings = { + }; + }; + 12078D9812BA5AF400A1C013 /* fake_efi.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = fake_efi.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/libsaio/fake_efi.c; + sourceTree = ""; + }; + 120DB90712B9F3F1001FDAE1 /* boot.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = boot.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/boot2/boot.c; + sourceTree = ""; + }; + 120DFB0A12BA3A3900C7EAC8 /* Localizable.strings */ = { + isa = PBXFileReference; + lastKnownFileType = text.plist.strings; + name = Localizable.strings; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/package/Resources/Italian.lproj/Localizable.strings; + sourceTree = ""; + }; + 120DFB1712BA3A4D00C7EAC8 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 120DB90712B9F3F1001FDAE1 /* boot.c */; + name = "boot.c: 111"; + rLen = 11; + rLoc = 3102; + rType = 0; + vrLen = 818; + vrLoc = 2630; + }; + 120DFB1812BA3A4D00C7EAC8 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 120DFB0A12BA3A3900C7EAC8 /* Localizable.strings */; + name = "Localizable.strings: 54"; + rLen = 7; + rLoc = 2404; + rType = 0; + vrLen = 980; + vrLoc = 1773; + }; + 120DFB2112BA3A5800C7EAC8 /* Makefile */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.make; + name = Makefile; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/Makefile; + sourceTree = ""; + }; + 120DFF6B12BA3BF500C7EAC8 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 120DFB2112BA3A5800C7EAC8 /* Makefile */; + name = "Makefile: 29"; + rLen = 7; + rLoc = 685; + rType = 0; + vrLen = 881; + vrLoc = 298; + }; + 12121ED112B261EA00207E55 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12C26F9A12B0E98200AF7F4B /* kernel_patcher.h */; + name = "kernel_patcher.h: 19"; + rLen = 4; + rLoc = 393; + rType = 0; + vrLen = 468; + vrLoc = 0; + }; + 1216139E12B65BB50019961E /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12CF89A712B6410100B7BC73 /* pci_setup.c */; + name = "pci_setup.c: 16"; + rLen = 14; + rLoc = 204; + rType = 0; + vrLen = 470; + vrLoc = 80; + }; + 121613A212B65BB50019961E /* pci.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = pci.h; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/libsaio/pci.h; + sourceTree = ""; + }; + 121613FF12B65D970019961E /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 121613A212B65BB50019961E /* pci.h */; + name = "pci.h: 51"; + rLen = 12; + rLoc = 855; + rType = 0; + vrLen = 895; + vrLoc = 563; + }; + 121EA43012B7B9DD002449B3 /* smbios_patcher.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = smbios_patcher.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/libsaio/smbios_patcher.c; + sourceTree = ""; + }; + 124C492812B8C915005AA276 /* Memory.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = Memory.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/Memory/Memory.c; + sourceTree = ""; + }; + 124C492E12B8D82D005AA276 /* gui.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = gui.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/GUI/gui.c; + sourceTree = ""; + }; + 124C493212B8D846005AA276 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12CC44D112B398A2007E0C76 /* platform.c */; + name = "platform.c: 39"; + rLen = 12; + rLoc = 668; + rType = 0; + vrLen = 718; + vrLoc = 323; + }; + 124C493412B8D846005AA276 /* HelloWorld.cpp */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.cpp.cpp; + name = HelloWorld.cpp; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/HelloWorld/HelloWorld.cpp; + sourceTree = ""; + }; + 124C493712B8D846005AA276 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 124C492E12B8D82D005AA276 /* gui.c */; + name = "gui.c: 716"; + rLen = 17; + rLoc = 21684; + rType = 0; + vrLen = 890; + vrLoc = 21338; + }; + 124C494012B8E8BC005AA276 /* GUI_module.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = GUI_module.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/GUI/GUI_module.c; + sourceTree = ""; + }; + 124C494212B8E8C2005AA276 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 124C492812B8C915005AA276 /* Memory.c */; + name = "Memory.c: 44"; + rLen = 8; + rLoc = 900; + rType = 0; + vrLen = 764; + vrLoc = 680; + }; + 124C494312B8E8C2005AA276 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 124C494412B8E8C2005AA276 /* hpet.h */; + name = "hpet.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 306; + vrLoc = 0; + }; + 124C494412B8E8C2005AA276 /* hpet.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = hpet.h; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/HPET/hpet.h; + sourceTree = ""; + }; + 124C494512B8E8C2005AA276 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 124C494612B8E8C2005AA276 /* HPET.c */; + name = "HPET.c: 27"; + rLen = 377; + rLoc = 410; + rType = 0; + vrLen = 554; + vrLoc = 237; + }; + 124C494612B8E8C2005AA276 /* HPET.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = HPET.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/HPET/HPET.c; + sourceTree = ""; + }; + 124C494B12B8EA5D005AA276 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 124C494012B8E8BC005AA276 /* GUI_module.c */; + name = "GUI_module.c: 240"; + rLen = 17; + rLoc = 5650; + rType = 0; + vrLen = 554; + vrLoc = 5486; + }; + 1267813012B7B13E00A25CED /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12B46E6D12B75631006C2B9C /* smbios_patcher.h */; + name = "smbios_patcher.h: 16"; + rLen = 8; + rLoc = 250; + rType = 0; + vrLen = 637; + vrLoc = 0; + }; + 1299A51F12B3C328007ED516 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12CC4AEF12B39FC7007E0C76 /* zutil.h */; + name = "zutil.h: 266"; + rLen = 6; + rLoc = 6791; + rType = 0; + vrLen = 374; + vrLoc = 6561; + }; + 1299A55612B3C4DF007ED516 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 1299A55712B3C4DF007ED516 /* console.c */; + name = "console.c: 185"; + rLen = 35; + rLoc = 3729; + rType = 0; + vrLen = 353; + vrLoc = 3516; + }; + 1299A55712B3C4DF007ED516 /* console.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = console.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/libsaio/console.c; + sourceTree = ""; + }; + 1299A55A12B3C4DF007ED516 /* Symbols.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = Symbols.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/boot2/Symbols.c; + sourceTree = ""; + }; + 129F6EF012B50BB6005A820E /* modules.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = modules.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/boot2/modules.c; + sourceTree = ""; + }; + 12AB04BD12B663F5005A745F /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12B903AB12B2A00E00FE287A /* platform.h */; + name = "platform.h: 169"; + rLen = 25; + rLoc = 5455; + rType = 0; + vrLen = 924; + vrLoc = 4593; + }; + 12AB04BF12B663F5005A745F /* boot.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = boot.h; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/boot2/boot.h; + sourceTree = ""; + }; + 12AB04D712B66471005A745F /* pci.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = pci.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/libsaio/pci.c; + sourceTree = ""; + }; + 12AB04EC12B665EA005A745F /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12AB04D712B66471005A745F /* pci.c */; + name = "pci.c: 150"; + rLen = 11; + rLoc = 3133; + rType = 0; + vrLen = 400; + vrLoc = 3028; + }; + 12AF764312BA614B003BBFD3 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12EFD98D12B510D9002A1712 /* revision */; + name = "revision: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 3; + vrLoc = 0; + }; + 12B46E5E12B75493006C2B9C /* cpu.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = cpu.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/libsaio/cpu.c; + sourceTree = ""; + }; + 12B46E6612B75631006C2B9C /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12BB443912B6694900C7B484 /* spd.c */; + name = "spd.c: 272"; + rLen = 13; + rLoc = 7917; + rType = 0; + vrLen = 742; + vrLoc = 7543; + }; + 12B46E6812B75631006C2B9C /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12AB04BF12B663F5005A745F /* boot.h */; + name = "boot.h: 44"; + rLen = 0; + rLoc = 1396; + rType = 0; + vrLen = 422; + vrLoc = 7282; + }; + 12B46E6912B75631006C2B9C /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12B9FA5512B29AFC00FE287A /* cpu.h */; + name = "cpu.h: 32"; + rLen = 12; + rLoc = 762; + rType = 0; + vrLen = 782; + vrLoc = 517; + }; + 12B46E6A12B75631006C2B9C /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12B46E5E12B75493006C2B9C /* cpu.c */; + name = "cpu.c: 184"; + rLen = 0; + rLoc = 6055; + rType = 0; + vrLen = 685; + vrLoc = 5865; + }; + 12B46E6D12B75631006C2B9C /* smbios_patcher.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = smbios_patcher.h; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/libsaio/smbios_patcher.h; + sourceTree = ""; + }; + 12B903AB12B2A00E00FE287A /* platform.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = platform.h; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/libsaio/platform.h; + sourceTree = ""; + }; + 12B90A0312B2A7A700FE287A /* acpi_patcher.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = acpi_patcher.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/ACPIPatcher/acpi_patcher.c; + sourceTree = ""; + }; + 12B90A2012B2A7E200FE287A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12B90A0312B2A7A700FE287A /* acpi_patcher.c */; + name = "acpi_patcher.c: 115"; + rLen = 22; + rLoc = 2845; + rType = 0; + vrLen = 611; + vrLoc = 2564; + }; + 12B90A2212B2A7E200FE287A /* mem.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = mem.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/Memory/mem.c; + sourceTree = ""; + }; + 12B90A2B12B2A86B00FE287A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12B90A2212B2A7E200FE287A /* mem.c */; + name = "mem.c: 142"; + rLen = 0; + rLoc = 4591; + rType = 0; + vrLen = 688; + vrLoc = 3903; + }; + 12B90A4D12B2AE1300FE287A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12B90A4E12B2AE1300FE287A /* Resolution.c */; + name = "Resolution.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 167; + vrLoc = 0; + }; + 12B90A4E12B2AE1300FE287A /* Resolution.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = Resolution.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/Resolution/Resolution.c; + sourceTree = ""; + }; + 12B90A4F12B2AE1300FE287A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12B90A5012B2AE1300FE287A /* 915resolution.c */; + name = "915resolution.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 363; + vrLoc = 20239; + }; + 12B90A5012B2AE1300FE287A /* 915resolution.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = 915resolution.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/Resolution/915resolution.c; + sourceTree = ""; + }; + 12B90A5212B2AE1300FE287A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12B90A5312B2AE1300FE287A /* edid.h */; + name = "edid.h: 15"; + rLen = 13; + rLoc = 205; + rType = 0; + vrLen = 253; + vrLoc = 0; + }; + 12B90A5312B2AE1300FE287A /* edid.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = edid.h; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/Resolution/edid.h; + sourceTree = ""; + }; + 12B90A5712B2AE1300FE287A /* 915resolution.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = 915resolution.h; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/Resolution/915resolution.h; + sourceTree = ""; + }; + 12B9F40D12B2987800FE287A /* SMBIOS.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = SMBIOS.h; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/libsaio/SMBIOS.h; + sourceTree = ""; + }; + 12B9F42612B29A4A00FE287A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12B9F40D12B2987800FE287A /* SMBIOS.h */; + name = "SMBIOS.h: 140"; + rLen = 20; + rLoc = 5015; + rType = 0; + vrLen = 922; + vrLoc = 4588; + }; + 12B9FA5512B29AFC00FE287A /* cpu.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = cpu.h; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/libsaio/cpu.h; + sourceTree = ""; + }; + 12BB443912B6694900C7B484 /* spd.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = spd.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/Memory/spd.c; + sourceTree = ""; + }; + 12BF14DA12B3CF8E00D798FE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 1299A55A12B3C4DF007ED516 /* Symbols.c */; + name = "Symbols.c: 20"; + rLen = 0; + rLoc = 640; + rType = 0; + vrLen = 665; + vrLoc = 3; + }; + 12C26D2E12B0DDF400AF7F4B /* ChamMek */ = { + isa = PBXExecutable; + activeArgIndices = ( + ); + argumentStrings = ( + ); + autoAttachOnCrash = 1; + breakpointsEnabled = 0; + configStateDict = { + }; + customDataFormattersEnabled = 1; + dataTipCustomDataFormattersEnabled = 1; + dataTipShowTypeColumn = 1; + dataTipSortType = 0; + debuggerPlugin = GDBDebugging; + disassemblyDisplayState = 0; + enableDebugStr = 1; + environmentEntries = ( + ); + executableSystemSymbolLevel = 0; + executableUserSymbolLevel = 0; + libgmallocEnabled = 0; + name = ChamMek; + showTypeColumn = 0; + sourceDirectories = ( + ); + }; + 12C26D3712B0DDFC00AF7F4B /* Source Control */ = { + isa = PBXSourceControlManager; + fallbackIsa = XCSourceControlManager; + isSCMEnabled = 0; + scmConfiguration = { + repositoryNamesForRoots = { + "" = chameleon; + }; + }; + }; + 12C26D3812B0DDFC00AF7F4B /* Code sense */ = { + isa = PBXCodeSenseManager; + indexTemplatePath = ""; + }; + 12C26F9A12B0E98200AF7F4B /* kernel_patcher.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = kernel_patcher.h; + path = /Users/slice/Projects/Chameleons/chameleon/branches/meklort/i386/modules/KernelPatcher/kernel_patcher.h; + sourceTree = ""; + }; + 12C7009812B7BCE7006BD382 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12C7FC5C12B7BCD6006BD382 /* basic_definitions */; + name = "basic_definitions: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1088; + vrLoc = 0; + }; + 12C7009912B7BCE7006BD382 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12C7009A12B7BCE7006BD382 /* __udivmoddi4.c */; + name = "__udivmoddi4.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 444; + vrLoc = 0; + }; + 12C7009A12B7BCE7006BD382 /* __udivmoddi4.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = __udivmoddi4.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/klibc/__udivmoddi4.c; + sourceTree = ""; + }; + 12C7009D12B7BCE7006BD382 /* __moddi3.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = __moddi3.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/klibc/__moddi3.c; + sourceTree = ""; + }; + 12C704E512B7BD3E006BD382 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12C7009D12B7BCE7006BD382 /* __moddi3.c */; + name = "__moddi3.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 395; + vrLoc = 0; + }; + 12C7FC3E12B7BCBA006BD382 /* theme.plist */ = { + isa = PBXFileReference; + lastKnownFileType = text.plist.xml; + name = theme.plist; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/artwork/themes/legacy/theme.plist; + sourceTree = ""; + }; + 12C7FC4D12B7BCD3006BD382 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 121EA43012B7B9DD002449B3 /* smbios_patcher.c */; + name = "smbios_patcher.c: 802"; + rLen = 5; + rLoc = 27589; + rType = 0; + vrLen = 1182; + vrLoc = 27099; + }; + 12C7FC4E12B7BCD3006BD382 /* PlistBookmark */ = { + isa = PlistBookmark; + fRef = 12C7FC3E12B7BCBA006BD382 /* theme.plist */; + fallbackIsa = PBXBookmark; + isK = 0; + kPath = ( + screen_width, + ); + name = /Users/slice/Projects/fakesmc/Chameleon/RC5m/artwork/themes/legacy/theme.plist; + rLen = 0; + rLoc = 9223372036854775808; + }; + 12C7FC5C12B7BCD6006BD382 /* basic_definitions */ = { + isa = PBXFileReference; + lastKnownFileType = text; + name = basic_definitions; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/include/basic_definitions; + sourceTree = ""; + }; + 12C8CB6812B5529D003DA1E4 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12EFE96012B549B6002A1712 /* pci_root.c */; + name = "pci_root.c: 53"; + rLen = 22; + rLoc = 1024; + rType = 0; + vrLen = 657; + vrLoc = 731; + }; + 12CC44C812B3947B007E0C76 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12E17AEA12B2BA9B00607D8E /* saio_types.h */; + name = "saio_types.h: 261"; + rLen = 0; + rLoc = 8455; + rType = 0; + vrLen = 409; + vrLoc = 8182; + }; + 12CC44D112B398A2007E0C76 /* platform.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = platform.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/libsaio/platform.c; + sourceTree = ""; + }; + 12CC4AEF12B39FC7007E0C76 /* zutil.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = zutil.h; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/KextPatcher/zutil.h; + sourceTree = ""; + }; + 12CF89A712B6410100B7BC73 /* pci_setup.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = pci_setup.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/libsaio/pci_setup.c; + sourceTree = ""; + }; + 12D6232512BA5F380032F367 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12078D9812BA5AF400A1C013 /* fake_efi.c */; + name = "fake_efi.c: 523"; + rLen = 6; + rLoc = 21723; + rType = 0; + vrLen = 665; + vrLoc = 21278; + }; + 12D6232612BA5F380032F367 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 124C493412B8D846005AA276 /* HelloWorld.cpp */; + name = "HelloWorld.cpp: 39"; + rLen = 10; + rLoc = 652; + rType = 0; + vrLen = 419; + vrLoc = 398; + }; + 12E17AE612B2BA9B00607D8E /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12B90A5712B2AE1300FE287A /* 915resolution.h */; + name = "915resolution.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 294; + vrLoc = 0; + }; + 12E17AEA12B2BA9B00607D8E /* saio_types.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = saio_types.h; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/libsaio/saio_types.h; + sourceTree = ""; + }; + 12E6FB4712BB438700C2A021 /* Makefile */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.make; + name = Makefile; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/boot2/Makefile; + sourceTree = ""; + }; + 12E6FB5712BB458400C2A021 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12E6FB4712BB438700C2A021 /* Makefile */; + name = "Makefile: 117"; + rLen = 8; + rLoc = 4153; + rType = 0; + vrLen = 857; + vrLoc = 3681; + }; + 12E6FB5B12BB458400C2A021 /* load.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = load.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/libsaio/load.c; + sourceTree = ""; + }; + 12EFD98A12B510D9002A1712 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 129F6EF012B50BB6005A820E /* modules.c */; + name = "modules.c: 927"; + rLen = 14; + rLoc = 22234; + rType = 0; + vrLen = 676; + vrLoc = 21912; + }; + 12EFD98D12B510D9002A1712 /* revision */ = { + isa = PBXFileReference; + lastKnownFileType = text; + name = revision; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/revision; + sourceTree = ""; + }; + 12EFDFC612B51958002A1712 /* nvidia.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = nvidia.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/GraphicsEnabler/nvidia.c; + sourceTree = ""; + }; + 12EFE2FD12B51ED5002A1712 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12EFDFC612B51958002A1712 /* nvidia.c */; + name = "nvidia.c: 712"; + rLen = 38; + rLoc = 23132; + rType = 0; + vrLen = 544; + vrLoc = 22879; + }; + 12EFE30112B51ED5002A1712 /* spd.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = spd.h; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/Memory/spd.h; + sourceTree = ""; + }; + 12EFE65A12B547A7002A1712 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12EFE30112B51ED5002A1712 /* spd.h */; + name = "spd.h: 16"; + rLen = 17; + rLoc = 306; + rType = 0; + vrLen = 533; + vrLoc = 0; + }; + 12EFE94412B548B5002A1712 /* ACPIPatcher.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = ACPIPatcher.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/ACPIPatcher/ACPIPatcher.c; + sourceTree = ""; + }; + 12EFE95E12B549B6002A1712 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12EFE94412B548B5002A1712 /* ACPIPatcher.c */; + name = "ACPIPatcher.c: 37"; + rLen = 22; + rLoc = 940; + rType = 0; + vrLen = 742; + vrLoc = 534; + }; + 12EFE96012B549B6002A1712 /* pci_root.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = pci_root.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/libsaio/pci_root.c; + sourceTree = ""; + }; + 12FC0E7512BB4B5200E9CFA8 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12E6FB5B12BB458400C2A021 /* load.c */; + name = "load.c: 42"; + rLen = 4; + rLoc = 1522; + rType = 0; + vrLen = 697; + vrLoc = 1159; + }; + 12FC0E7812BB4B5200E9CFA8 /* NVRAM.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = NVRAM.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/NVRAM/NVRAM.c; + sourceTree = ""; + }; + 12FC0E9412BB65A800E9CFA8 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12FC0E7812BB4B5200E9CFA8 /* NVRAM.c */; + name = "NVRAM.c: 150"; + rLen = 0; + rLoc = 4870; + rType = 0; + vrLen = 362; + vrLoc = 4873; + }; + 12FC11AA12BB687A00E9CFA8 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12FC11AB12BB687A00E9CFA8 /* drivers.c */; + name = "drivers.c: 77"; + rLen = 8; + rLoc = 2385; + rType = 0; + vrLen = 461; + vrLoc = 2046; + }; + 12FC11AB12BB687A00E9CFA8 /* drivers.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = drivers.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/boot2/drivers.c; + sourceTree = ""; + }; + 12FC14AE12BB730100E9CFA8 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12FC14AF12BB730100E9CFA8 /* drivers.c */; + name = "drivers.c: 77"; + rLen = 8; + rLoc = 2385; + rType = 0; + vrLen = 456; + vrLoc = 2046; + }; + 12FC14AF12BB730100E9CFA8 /* drivers.c */ = { + isa = PBXFileReference; + name = drivers.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/boot2/drivers.c; + sourceTree = ""; + }; + 8DD76FA90486AB0100D96B5E /* ChamMek */ = { + activeExec = 0; + executables = ( + 12C26D2E12B0DDF400AF7F4B /* ChamMek */, + ); + }; +} Index: branches/slice/rev749/ChamMek.xcodeproj/project.pbxproj =================================================================== --- branches/slice/rev749/ChamMek.xcodeproj/project.pbxproj (revision 0) +++ branches/slice/rev749/ChamMek.xcodeproj/project.pbxproj (revision 1169) @@ -0,0 +1,212 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 45; + objects = { + +/* Begin PBXBuildFile section */ + 8DD76FAC0486AB0100D96B5E /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 08FB7796FE84155DC02AAC07 /* main.c */; settings = {ATTRIBUTES = (); }; }; + 8DD76FB00486AB0100D96B5E /* ChamMek.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = C6A0FF2C0290799A04C91782 /* ChamMek.1 */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 8DD76FAF0486AB0100D96B5E /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + 8DD76FB00486AB0100D96B5E /* ChamMek.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 08FB7796FE84155DC02AAC07 /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; + 12C26D3912B0DE0A00AF7F4B /* meklort */ = {isa = PBXFileReference; lastKnownFileType = folder; name = meklort; path = ..; sourceTree = SOURCE_ROOT; }; + 8DD76FB20486AB0100D96B5E /* ChamMek */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ChamMek; sourceTree = BUILT_PRODUCTS_DIR; }; + C6A0FF2C0290799A04C91782 /* ChamMek.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = ChamMek.1; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8DD76FAD0486AB0100D96B5E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 08FB7794FE84155DC02AAC07 /* ChamMek */ = { + isa = PBXGroup; + children = ( + 08FB7795FE84155DC02AAC07 /* Source */, + C6A0FF2B0290797F04C91782 /* Documentation */, + 1AB674ADFE9D54B511CA2CBB /* Products */, + ); + name = ChamMek; + sourceTree = ""; + }; + 08FB7795FE84155DC02AAC07 /* Source */ = { + isa = PBXGroup; + children = ( + 12C26D3912B0DE0A00AF7F4B /* meklort */, + 08FB7796FE84155DC02AAC07 /* main.c */, + ); + name = Source; + sourceTree = ""; + }; + 1AB674ADFE9D54B511CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 8DD76FB20486AB0100D96B5E /* ChamMek */, + ); + name = Products; + sourceTree = ""; + }; + C6A0FF2B0290797F04C91782 /* Documentation */ = { + isa = PBXGroup; + children = ( + C6A0FF2C0290799A04C91782 /* ChamMek.1 */, + ); + name = Documentation; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8DD76FA90486AB0100D96B5E /* ChamMek */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1DEB928508733DD80010E9CD /* Build configuration list for PBXNativeTarget "ChamMek" */; + buildPhases = ( + 8DD76FAB0486AB0100D96B5E /* Sources */, + 8DD76FAD0486AB0100D96B5E /* Frameworks */, + 8DD76FAF0486AB0100D96B5E /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ChamMek; + productInstallPath = "$(HOME)/bin"; + productName = ChamMek; + productReference = 8DD76FB20486AB0100D96B5E /* ChamMek */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 08FB7793FE84155DC02AAC07 /* Project object */ = { + isa = PBXProject; + buildConfigurationList = 1DEB928908733DD80010E9CD /* Build configuration list for PBXProject "ChamMek" */; + compatibilityVersion = "Xcode 3.1"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + ); + mainGroup = 08FB7794FE84155DC02AAC07 /* ChamMek */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8DD76FA90486AB0100D96B5E /* ChamMek */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 8DD76FAB0486AB0100D96B5E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8DD76FAC0486AB0100D96B5E /* main.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 1DEB928608733DD80010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + INSTALL_PATH = /usr/local/bin; + PRODUCT_NAME = ChamMek; + }; + name = Debug; + }; + 1DEB928708733DD80010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = /usr/local/bin; + PRODUCT_NAME = ChamMek; + }; + name = Release; + }; + 1DEB928A08733DD80010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + ONLY_ACTIVE_ARCH = YES; + PREBINDING = NO; + SDKROOT = macosx10.6; + }; + name = Debug; + }; + 1DEB928B08733DD80010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PREBINDING = NO; + SDKROOT = macosx10.6; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1DEB928508733DD80010E9CD /* Build configuration list for PBXNativeTarget "ChamMek" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB928608733DD80010E9CD /* Debug */, + 1DEB928708733DD80010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1DEB928908733DD80010E9CD /* Build configuration list for PBXProject "ChamMek" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB928A08733DD80010E9CD /* Debug */, + 1DEB928B08733DD80010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; +} Index: branches/slice/rev749/ChamMek.xcodeproj/slice.mode1v3 =================================================================== --- branches/slice/rev749/ChamMek.xcodeproj/slice.mode1v3 (revision 0) +++ branches/slice/rev749/ChamMek.xcodeproj/slice.mode1v3 (revision 1169) @@ -0,0 +1,1435 @@ + + + + + ActivePerspectiveName + Project + AllowedModules + + + BundleLoadPath + + MaxInstances + n + Module + PBXSmartGroupTreeModule + Name + Groups and Files Outline View + + + BundleLoadPath + + MaxInstances + n + Module + PBXNavigatorGroup + Name + Editor + + + BundleLoadPath + + MaxInstances + n + Module + XCTaskListModule + Name + Task List + + + BundleLoadPath + + MaxInstances + n + Module + XCDetailModule + Name + File and Smart Group Detail Viewer + + + BundleLoadPath + + MaxInstances + 1 + Module + PBXBuildResultsModule + Name + Detailed Build Results Viewer + + + BundleLoadPath + + MaxInstances + 1 + Module + PBXProjectFindModule + Name + Project Batch Find Tool + + + BundleLoadPath + + MaxInstances + n + Module + XCProjectFormatConflictsModule + Name + Project Format Conflicts List + + + BundleLoadPath + + MaxInstances + n + Module + PBXBookmarksModule + Name + Bookmarks Tool + + + BundleLoadPath + + MaxInstances + n + Module + PBXClassBrowserModule + Name + Class Browser + + + BundleLoadPath + + MaxInstances + n + Module + PBXCVSModule + Name + Source Code Control Tool + + + BundleLoadPath + + MaxInstances + n + Module + PBXDebugBreakpointsModule + Name + Debug Breakpoints Tool + + + BundleLoadPath + + MaxInstances + n + Module + XCDockableInspector + Name + Inspector + + + BundleLoadPath + + MaxInstances + n + Module + PBXOpenQuicklyModule + Name + Open Quickly Tool + + + BundleLoadPath + + MaxInstances + 1 + Module + PBXDebugSessionModule + Name + Debugger + + + BundleLoadPath + + MaxInstances + 1 + Module + PBXDebugCLIModule + Name + Debug Console + + + BundleLoadPath + + MaxInstances + n + Module + XCSnapshotModule + Name + Snapshots Tool + + + BundlePath + /Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources + Description + DefaultDescriptionKey + DockingSystemVisible + + Extension + mode1v3 + FavBarConfig + + PBXProjectModuleGUID + 12C26D3412B0DDFC00AF7F4B + XCBarModuleItemNames + + XCBarModuleItems + + + FirstTimeWindowDisplayed + + Identifier + com.apple.perspectives.project.mode1v3 + MajorVersion + 33 + MinorVersion + 0 + Name + Default + Notifications + + OpenEditors + + PerspectiveWidths + + -1 + -1 + + Perspectives + + + ChosenToolbarItems + + active-combo-popup + action + NSToolbarFlexibleSpaceItem + clean-target + buildOrClean + servicesModulefind + com.apple.ide.PBXToolbarStopButton + get-info + NSToolbarFlexibleSpaceItem + com.apple.pbx.toolbar.searchfield + + ControllerClassBaseName + + IconName + WindowOfProjectWithEditor + Identifier + perspective.project + IsVertical + + Layout + + + ContentConfiguration + + PBXBottomSmartGroupGIDs + + 1C37FBAC04509CD000000102 + 1C37FAAC04509CD000000102 + 1C37FABC05509CD000000102 + 1C37FABC05539CD112110102 + E2644B35053B69B200211256 + 1C37FABC04509CD000100104 + 1CC0EA4004350EF90044410B + 1CC0EA4004350EF90041110B + + PBXProjectModuleGUID + 1CE0B1FE06471DED0097A5F4 + PBXProjectModuleLabel + Files + PBXProjectStructureProvided + yes + PBXSmartGroupTreeModuleColumnData + + PBXSmartGroupTreeModuleColumnWidthsKey + + 22 + 164 + + PBXSmartGroupTreeModuleColumnsKey_v4 + + SCMStatusColumn + MainColumn + + + PBXSmartGroupTreeModuleOutlineStateKey_v7 + + PBXSmartGroupTreeModuleOutlineStateExpansionKey + + 08FB7794FE84155DC02AAC07 + 08FB7795FE84155DC02AAC07 + 12C26D3912B0DE0A00AF7F4B + 1C37FABC05509CD000000102 + + PBXSmartGroupTreeModuleOutlineStateSelectionKey + + + 17 + 2 + 1 + 0 + + + PBXSmartGroupTreeModuleOutlineStateVisibleRectKey + {{0, 0}, {186, 635}} + + PBXTopSmartGroupGIDs + + XCIncludePerspectivesSwitch + + XCSharingToken + com.apple.Xcode.GFSharingToken + + GeometryConfiguration + + Frame + {{0, 0}, {203, 653}} + GroupTreeTableConfiguration + + SCMStatusColumn + 22 + MainColumn + 164 + + RubberWindowFrame + 152 173 1172 694 0 0 1440 878 + + Module + PBXSmartGroupTreeModule + Proportion + 203pt + + + Dock + + + ContentConfiguration + + PBXProjectModuleGUID + 1CE0B20306471E060097A5F4 + PBXProjectModuleLabel + drivers.c + PBXSplitModuleInNavigatorKey + + Split0 + + PBXProjectModuleGUID + 1CE0B20406471E060097A5F4 + PBXProjectModuleLabel + drivers.c + _historyCapacity + 0 + bookmark + 12FC14AE12BB730100E9CFA8 + history + + 12121ED112B261EA00207E55 + 12B9F42612B29A4A00FE287A + 12B90A2012B2A7E200FE287A + 12B90A2B12B2A86B00FE287A + 12B90A4D12B2AE1300FE287A + 12B90A4F12B2AE1300FE287A + 12B90A5212B2AE1300FE287A + 12E17AE612B2BA9B00607D8E + 12CC44C812B3947B007E0C76 + 1299A51F12B3C328007ED516 + 1299A55612B3C4DF007ED516 + 12BF14DA12B3CF8E00D798FE + 12EFD98A12B510D9002A1712 + 12EFE2FD12B51ED5002A1712 + 12EFE65A12B547A7002A1712 + 12EFE95E12B549B6002A1712 + 12C8CB6812B5529D003DA1E4 + 1216139E12B65BB50019961E + 121613FF12B65D970019961E + 12AB04BD12B663F5005A745F + 12AB04EC12B665EA005A745F + 12B46E6612B75631006C2B9C + 12B46E6812B75631006C2B9C + 12B46E6912B75631006C2B9C + 12B46E6A12B75631006C2B9C + 1267813012B7B13E00A25CED + 12C7FC4D12B7BCD3006BD382 + 12C7FC4E12B7BCD3006BD382 + 12C7009812B7BCE7006BD382 + 12C7009912B7BCE7006BD382 + 12C704E512B7BD3E006BD382 + 124C493212B8D846005AA276 + 124C493712B8D846005AA276 + 124C494212B8E8C2005AA276 + 124C494312B8E8C2005AA276 + 124C494512B8E8C2005AA276 + 124C494B12B8EA5D005AA276 + 120DFB1712BA3A4D00C7EAC8 + 120DFB1812BA3A4D00C7EAC8 + 120DFF6B12BA3BF500C7EAC8 + 12D6232512BA5F380032F367 + 12D6232612BA5F380032F367 + 12AF764312BA614B003BBFD3 + 12E6FB5712BB458400C2A021 + 12FC0E7512BB4B5200E9CFA8 + 12FC0E9412BB65A800E9CFA8 + 12FC11AA12BB687A00E9CFA8 + + + SplitCount + 1 + + StatusBarVisibility + + + GeometryConfiguration + + Frame + {{0, 0}, {964, 214}} + RubberWindowFrame + 152 173 1172 694 0 0 1440 878 + + Module + PBXNavigatorGroup + Proportion + 214pt + + + BecomeActive + + ContentConfiguration + + PBXProjectModuleGUID + 1CE0B20506471E060097A5F4 + PBXProjectModuleLabel + Detail + + GeometryConfiguration + + Frame + {{0, 219}, {964, 434}} + RubberWindowFrame + 152 173 1172 694 0 0 1440 878 + + Module + XCDetailModule + Proportion + 434pt + + + Proportion + 964pt + + + Name + Project + ServiceClasses + + XCModuleDock + PBXSmartGroupTreeModule + XCModuleDock + PBXNavigatorGroup + XCDetailModule + + TableOfContents + + 12FC14B012BB730100E9CFA8 + 1CE0B1FE06471DED0097A5F4 + 12FC14B112BB730100E9CFA8 + 1CE0B20306471E060097A5F4 + 1CE0B20506471E060097A5F4 + + ToolbarConfigUserDefaultsMinorVersion + 2 + ToolbarConfiguration + xcode.toolbar.config.defaultV3 + + + ControllerClassBaseName + + IconName + WindowOfProject + Identifier + perspective.morph + IsVertical + 0 + Layout + + + BecomeActive + 1 + ContentConfiguration + + PBXBottomSmartGroupGIDs + + 1C37FBAC04509CD000000102 + 1C37FAAC04509CD000000102 + 1C08E77C0454961000C914BD + 1C37FABC05509CD000000102 + 1C37FABC05539CD112110102 + E2644B35053B69B200211256 + 1C37FABC04509CD000100104 + 1CC0EA4004350EF90044410B + 1CC0EA4004350EF90041110B + + PBXProjectModuleGUID + 11E0B1FE06471DED0097A5F4 + PBXProjectModuleLabel + Files + PBXProjectStructureProvided + yes + PBXSmartGroupTreeModuleColumnData + + PBXSmartGroupTreeModuleColumnWidthsKey + + 186 + + PBXSmartGroupTreeModuleColumnsKey_v4 + + MainColumn + + + PBXSmartGroupTreeModuleOutlineStateKey_v7 + + PBXSmartGroupTreeModuleOutlineStateExpansionKey + + 29B97314FDCFA39411CA2CEA + 1C37FABC05509CD000000102 + + PBXSmartGroupTreeModuleOutlineStateSelectionKey + + + 0 + + + PBXSmartGroupTreeModuleOutlineStateVisibleRectKey + {{0, 0}, {186, 337}} + + PBXTopSmartGroupGIDs + + XCIncludePerspectivesSwitch + 1 + XCSharingToken + com.apple.Xcode.GFSharingToken + + GeometryConfiguration + + Frame + {{0, 0}, {203, 355}} + GroupTreeTableConfiguration + + MainColumn + 186 + + RubberWindowFrame + 373 269 690 397 0 0 1440 878 + + Module + PBXSmartGroupTreeModule + Proportion + 100% + + + Name + Morph + PreferredWidth + 300 + ServiceClasses + + XCModuleDock + PBXSmartGroupTreeModule + + TableOfContents + + 11E0B1FE06471DED0097A5F4 + + ToolbarConfiguration + xcode.toolbar.config.default.shortV3 + + + PerspectivesBarVisible + + ShelfIsVisible + + SourceDescription + file at '/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources/XCPerspectivesSpecificationMode1.xcperspec' + StatusbarIsVisible + + TimeStamp + 0.0 + ToolbarConfigUserDefaultsMinorVersion + 2 + ToolbarDisplayMode + 1 + ToolbarIsVisible + + ToolbarSizeMode + 1 + Type + Perspectives + UpdateMessage + The Default Workspace in this version of Xcode now includes support to hide and show the detail view (what has been referred to as the "Metro-Morph" feature). You must discard your current Default Workspace settings and update to the latest Default Workspace in order to gain this feature. Do you wish to update to the latest Workspace defaults for project '%@'? + WindowJustification + 5 + WindowOrderList + + 12C26D3512B0DDFC00AF7F4B + /Users/slice/Projects/Chameleons/chameleon/branches/slice/ChamMek/ChamMek.xcodeproj + + WindowString + 152 173 1172 694 0 0 1440 878 + WindowToolsV3 + + + FirstTimeWindowDisplayed + + Identifier + windowTool.build + IsVertical + + Layout + + + Dock + + + ContentConfiguration + + PBXProjectModuleGUID + 1CD0528F0623707200166675 + PBXProjectModuleLabel + + StatusBarVisibility + + + GeometryConfiguration + + Frame + {{0, 0}, {500, 218}} + RubberWindowFrame + 347 289 500 500 0 0 1440 878 + + Module + PBXNavigatorGroup + Proportion + 218pt + + + ContentConfiguration + + PBXProjectModuleGUID + XCMainBuildResultsModuleGUID + PBXProjectModuleLabel + Build Results + XCBuildResultsTrigger_Collapse + 1021 + XCBuildResultsTrigger_Open + 1011 + + GeometryConfiguration + + Frame + {{0, 223}, {500, 236}} + RubberWindowFrame + 347 289 500 500 0 0 1440 878 + + Module + PBXBuildResultsModule + Proportion + 236pt + + + Proportion + 459pt + + + Name + Build Results + ServiceClasses + + PBXBuildResultsModule + + StatusbarIsVisible + + TableOfContents + + 12C26D3512B0DDFC00AF7F4B + 12FC14B212BB730100E9CFA8 + 1CD0528F0623707200166675 + XCMainBuildResultsModuleGUID + + ToolbarConfiguration + xcode.toolbar.config.buildV3 + WindowContentMinSize + 486 300 + WindowString + 347 289 500 500 0 0 1440 878 + WindowToolGUID + 12C26D3512B0DDFC00AF7F4B + WindowToolIsVisible + + + + FirstTimeWindowDisplayed + + Identifier + windowTool.debugger + IsVertical + + Layout + + + Dock + + + ContentConfiguration + + Debugger + + HorizontalSplitView + + _collapsingFrameDimension + 0.0 + _indexOfCollapsedView + 0 + _percentageOfCollapsedView + 0.0 + isCollapsed + yes + sizes + + {{0, 0}, {316, 203}} + {{316, 0}, {378, 203}} + + + VerticalSplitView + + _collapsingFrameDimension + 0.0 + _indexOfCollapsedView + 0 + _percentageOfCollapsedView + 0.0 + isCollapsed + yes + sizes + + {{0, 0}, {694, 203}} + {{0, 203}, {694, 178}} + + + + LauncherConfigVersion + 8 + PBXProjectModuleGUID + 1C162984064C10D400B95A72 + PBXProjectModuleLabel + Debug - GLUTExamples (Underwater) + + GeometryConfiguration + + DebugConsoleVisible + None + DebugConsoleWindowFrame + {{200, 200}, {500, 300}} + DebugSTDIOWindowFrame + {{200, 200}, {500, 300}} + Frame + {{0, 0}, {694, 381}} + PBXDebugSessionStackFrameViewKey + + DebugVariablesTableConfiguration + + Name + 120 + Value + 85 + Summary + 148 + + Frame + {{316, 0}, {378, 203}} + RubberWindowFrame + 77 419 694 422 0 0 1440 878 + + RubberWindowFrame + 77 419 694 422 0 0 1440 878 + + Module + PBXDebugSessionModule + Proportion + 381pt + + + Proportion + 381pt + + + Name + Debugger + ServiceClasses + + PBXDebugSessionModule + + StatusbarIsVisible + + TableOfContents + + 1CD10A99069EF8BA00B06720 + 12FC0E7C12BB4B5200E9CFA8 + 1C162984064C10D400B95A72 + 12FC0E7D12BB4B5200E9CFA8 + 12FC0E7E12BB4B5200E9CFA8 + 12FC0E7F12BB4B5200E9CFA8 + 12FC0E8012BB4B5200E9CFA8 + 12FC0E8112BB4B5200E9CFA8 + + ToolbarConfiguration + xcode.toolbar.config.debugV3 + WindowString + 77 419 694 422 0 0 1440 878 + WindowToolGUID + 1CD10A99069EF8BA00B06720 + WindowToolIsVisible + + + + FirstTimeWindowDisplayed + + Identifier + windowTool.find + IsVertical + + Layout + + + Dock + + + Dock + + + BecomeActive + + ContentConfiguration + + PBXProjectModuleGUID + 1CDD528C0622207200134675 + PBXProjectModuleLabel + drivers.c + StatusBarVisibility + + + GeometryConfiguration + + Frame + {{0, 0}, {1079, 456}} + RubberWindowFrame + 297 75 1079 762 0 0 1440 878 + + Module + PBXNavigatorGroup + Proportion + 1079pt + + + Proportion + 456pt + + + ContentConfiguration + + PBXProjectModuleGUID + 1CD0528E0623707200166675 + PBXProjectModuleLabel + Project Find + + GeometryConfiguration + + Frame + {{0, 461}, {1079, 260}} + RubberWindowFrame + 297 75 1079 762 0 0 1440 878 + + Module + PBXProjectFindModule + Proportion + 260pt + + + Proportion + 721pt + + + Name + Project Find + ServiceClasses + + PBXProjectFindModule + + StatusbarIsVisible + + TableOfContents + + 1C530D57069F1CE1000CFCEE + 12FC0E9212BB65A600E9CFA8 + 12FC0E9312BB65A600E9CFA8 + 1CDD528C0622207200134675 + 1CD0528E0623707200166675 + + WindowString + 297 75 1079 762 0 0 1440 878 + WindowToolGUID + 1C530D57069F1CE1000CFCEE + WindowToolIsVisible + + + + Identifier + MENUSEPARATOR + + + Identifier + windowTool.debuggerConsole + Layout + + + Dock + + + BecomeActive + 1 + ContentConfiguration + + PBXProjectModuleGUID + 1C78EAAC065D492600B07095 + PBXProjectModuleLabel + Debugger Console + + GeometryConfiguration + + Frame + {{0, 0}, {650, 250}} + RubberWindowFrame + 516 632 650 250 0 0 1680 1027 + + Module + PBXDebugCLIModule + Proportion + 209pt + + + Proportion + 209pt + + + Name + Debugger Console + ServiceClasses + + PBXDebugCLIModule + + StatusbarIsVisible + 1 + TableOfContents + + 1C78EAAD065D492600B07095 + 1C78EAAE065D492600B07095 + 1C78EAAC065D492600B07095 + + ToolbarConfiguration + xcode.toolbar.config.consoleV3 + WindowString + 650 41 650 250 0 0 1280 1002 + WindowToolGUID + 1C78EAAD065D492600B07095 + WindowToolIsVisible + 0 + + + Identifier + windowTool.snapshots + Layout + + + Dock + + + Module + XCSnapshotModule + Proportion + 100% + + + Proportion + 100% + + + Name + Snapshots + ServiceClasses + + XCSnapshotModule + + StatusbarIsVisible + Yes + ToolbarConfiguration + xcode.toolbar.config.snapshots + WindowString + 315 824 300 550 0 0 1440 878 + WindowToolIsVisible + Yes + + + Identifier + windowTool.scm + Layout + + + Dock + + + ContentConfiguration + + PBXProjectModuleGUID + 1C78EAB2065D492600B07095 + PBXProjectModuleLabel + <No Editor> + PBXSplitModuleInNavigatorKey + + Split0 + + PBXProjectModuleGUID + 1C78EAB3065D492600B07095 + + SplitCount + 1 + + StatusBarVisibility + 1 + + GeometryConfiguration + + Frame + {{0, 0}, {452, 0}} + RubberWindowFrame + 743 379 452 308 0 0 1280 1002 + + Module + PBXNavigatorGroup + Proportion + 0pt + + + BecomeActive + 1 + ContentConfiguration + + PBXProjectModuleGUID + 1CD052920623707200166675 + PBXProjectModuleLabel + SCM + + GeometryConfiguration + + ConsoleFrame + {{0, 259}, {452, 0}} + Frame + {{0, 7}, {452, 259}} + RubberWindowFrame + 743 379 452 308 0 0 1280 1002 + TableConfiguration + + Status + 30 + FileName + 199 + Path + 197.0950012207031 + + TableFrame + {{0, 0}, {452, 250}} + + Module + PBXCVSModule + Proportion + 262pt + + + Proportion + 266pt + + + Name + SCM + ServiceClasses + + PBXCVSModule + + StatusbarIsVisible + 1 + TableOfContents + + 1C78EAB4065D492600B07095 + 1C78EAB5065D492600B07095 + 1C78EAB2065D492600B07095 + 1CD052920623707200166675 + + ToolbarConfiguration + xcode.toolbar.config.scm + WindowString + 743 379 452 308 0 0 1280 1002 + + + Identifier + windowTool.breakpoints + IsVertical + 0 + Layout + + + Dock + + + BecomeActive + 1 + ContentConfiguration + + PBXBottomSmartGroupGIDs + + 1C77FABC04509CD000000102 + + PBXProjectModuleGUID + 1CE0B1FE06471DED0097A5F4 + PBXProjectModuleLabel + Files + PBXProjectStructureProvided + no + PBXSmartGroupTreeModuleColumnData + + PBXSmartGroupTreeModuleColumnWidthsKey + + 168 + + PBXSmartGroupTreeModuleColumnsKey_v4 + + MainColumn + + + PBXSmartGroupTreeModuleOutlineStateKey_v7 + + PBXSmartGroupTreeModuleOutlineStateExpansionKey + + 1C77FABC04509CD000000102 + + PBXSmartGroupTreeModuleOutlineStateSelectionKey + + + 0 + + + PBXSmartGroupTreeModuleOutlineStateVisibleRectKey + {{0, 0}, {168, 350}} + + PBXTopSmartGroupGIDs + + XCIncludePerspectivesSwitch + 0 + + GeometryConfiguration + + Frame + {{0, 0}, {185, 368}} + GroupTreeTableConfiguration + + MainColumn + 168 + + RubberWindowFrame + 315 424 744 409 0 0 1440 878 + + Module + PBXSmartGroupTreeModule + Proportion + 185pt + + + ContentConfiguration + + PBXProjectModuleGUID + 1CA1AED706398EBD00589147 + PBXProjectModuleLabel + Detail + + GeometryConfiguration + + Frame + {{190, 0}, {554, 368}} + RubberWindowFrame + 315 424 744 409 0 0 1440 878 + + Module + XCDetailModule + Proportion + 554pt + + + Proportion + 368pt + + + MajorVersion + 3 + MinorVersion + 0 + Name + Breakpoints + ServiceClasses + + PBXSmartGroupTreeModule + XCDetailModule + + StatusbarIsVisible + 1 + TableOfContents + + 1CDDB66807F98D9800BB5817 + 1CDDB66907F98D9800BB5817 + 1CE0B1FE06471DED0097A5F4 + 1CA1AED706398EBD00589147 + + ToolbarConfiguration + xcode.toolbar.config.breakpointsV3 + WindowString + 315 424 744 409 0 0 1440 878 + WindowToolGUID + 1CDDB66807F98D9800BB5817 + WindowToolIsVisible + 1 + + + Identifier + windowTool.debugAnimator + Layout + + + Dock + + + Module + PBXNavigatorGroup + Proportion + 100% + + + Proportion + 100% + + + Name + Debug Visualizer + ServiceClasses + + PBXNavigatorGroup + + StatusbarIsVisible + 1 + ToolbarConfiguration + xcode.toolbar.config.debugAnimatorV3 + WindowString + 100 100 700 500 0 0 1280 1002 + + + Identifier + windowTool.bookmarks + Layout + + + Dock + + + Module + PBXBookmarksModule + Proportion + 100% + + + Proportion + 100% + + + Name + Bookmarks + ServiceClasses + + PBXBookmarksModule + + StatusbarIsVisible + 0 + WindowString + 538 42 401 187 0 0 1280 1002 + + + Identifier + windowTool.projectFormatConflicts + Layout + + + Dock + + + Module + XCProjectFormatConflictsModule + Proportion + 100% + + + Proportion + 100% + + + Name + Project Format Conflicts + ServiceClasses + + XCProjectFormatConflictsModule + + StatusbarIsVisible + 0 + WindowContentMinSize + 450 300 + WindowString + 50 850 472 307 0 0 1440 877 + + + Identifier + windowTool.classBrowser + Layout + + + Dock + + + BecomeActive + 1 + ContentConfiguration + + OptionsSetName + Hierarchy, all classes + PBXProjectModuleGUID + 1CA6456E063B45B4001379D8 + PBXProjectModuleLabel + Class Browser - NSObject + + GeometryConfiguration + + ClassesFrame + {{0, 0}, {374, 96}} + ClassesTreeTableConfiguration + + PBXClassNameColumnIdentifier + 208 + PBXClassBookColumnIdentifier + 22 + + Frame + {{0, 0}, {630, 331}} + MembersFrame + {{0, 105}, {374, 395}} + MembersTreeTableConfiguration + + PBXMemberTypeIconColumnIdentifier + 22 + PBXMemberNameColumnIdentifier + 216 + PBXMemberTypeColumnIdentifier + 97 + PBXMemberBookColumnIdentifier + 22 + + PBXModuleWindowStatusBarHidden2 + 1 + RubberWindowFrame + 385 179 630 352 0 0 1440 878 + + Module + PBXClassBrowserModule + Proportion + 332pt + + + Proportion + 332pt + + + Name + Class Browser + ServiceClasses + + PBXClassBrowserModule + + StatusbarIsVisible + 0 + TableOfContents + + 1C0AD2AF069F1E9B00FABCE6 + 1C0AD2B0069F1E9B00FABCE6 + 1CA6456E063B45B4001379D8 + + ToolbarConfiguration + xcode.toolbar.config.classbrowser + WindowString + 385 179 630 352 0 0 1440 878 + WindowToolGUID + 1C0AD2AF069F1E9B00FABCE6 + WindowToolIsVisible + 0 + + + Identifier + windowTool.refactoring + IncludeInToolsMenu + 0 + Layout + + + Dock + + + BecomeActive + 1 + GeometryConfiguration + + Frame + {0, 0}, {500, 335} + RubberWindowFrame + {0, 0}, {500, 335} + + Module + XCRefactoringModule + Proportion + 100% + + + Proportion + 100% + + + Name + Refactoring + ServiceClasses + + XCRefactoringModule + + WindowString + 200 200 500 356 0 0 1920 1200 + + + + Index: branches/slice/rev749/APPLE_LICENSE =================================================================== --- branches/slice/rev749/APPLE_LICENSE (revision 0) +++ branches/slice/rev749/APPLE_LICENSE (revision 1169) @@ -0,0 +1,367 @@ +APPLE PUBLIC SOURCE LICENSE +Version 2.0 - August 6, 2003 + +Please read this License carefully before downloading this software. +By downloading or using this software, you are agreeing to be bound by +the terms of this License. If you do not or cannot agree to the terms +of this License, please do not download or use the software. + +1. General; Definitions. This License applies to any program or other +work which Apple Computer, Inc. ("Apple") makes publicly available and +which contains a notice placed by Apple identifying such program or +work as "Original Code" and stating that it is subject to the terms of +this Apple Public Source License version 2.0 ("License"). As used in +this License: + +1.1 "Applicable Patent Rights" mean: (a) in the case where Apple is +the grantor of rights, (i) claims of patents that are now or hereafter +acquired, owned by or assigned to Apple and (ii) that cover subject +matter contained in the Original Code, but only to the extent +necessary to use, reproduce and/or distribute the Original Code +without infringement; and (b) in the case where You are the grantor of +rights, (i) claims of patents that are now or hereafter acquired, +owned by or assigned to You and (ii) that cover subject matter in Your +Modifications, taken alone or in combination with Original Code. + +1.2 "Contributor" means any person or entity that creates or +contributes to the creation of Modifications. + +1.3 "Covered Code" means the Original Code, Modifications, the +combination of Original Code and any Modifications, and/or any +respective portions thereof. + +1.4 "Externally Deploy" means: (a) to sublicense, distribute or +otherwise make Covered Code available, directly or indirectly, to +anyone other than You; and/or (b) to use Covered Code, alone or as +part of a Larger Work, in any way to provide a service, including but +not limited to delivery of content, through electronic communication +with a client other than You. + +1.5 "Larger Work" means a work which combines Covered Code or portions +thereof with code not governed by the terms of this License. + +1.6 "Modifications" mean any addition to, deletion from, and/or change +to, the substance and/or structure of the Original Code, any previous +Modifications, the combination of Original Code and any previous +Modifications, and/or any respective portions thereof. When code is +released as a series of files, a Modification is: (a) any addition to +or deletion from the contents of a file containing Covered Code; +and/or (b) any new file or other representation of computer program +statements that contains any part of Covered Code. + +1.7 "Original Code" means (a) the Source Code of a program or other +work as originally made available by Apple under this License, +including the Source Code of any updates or upgrades to such programs +or works made available by Apple under this License, and that has been +expressly identified by Apple as such in the header file(s) of such +work; and (b) the object code compiled from such Source Code and +originally made available by Apple under this License. + +1.8 "Source Code" means the human readable form of a program or other +work that is suitable for making modifications to it, including all +modules it contains, plus any associated interface definition files, +scripts used to control compilation and installation of an executable +(object code). + +1.9 "You" or "Your" means an individual or a legal entity exercising +rights under this License. For legal entities, "You" or "Your" +includes any entity which controls, is controlled by, or is under +common control with, You, where "control" means (a) the power, direct +or indirect, to cause the direction or management of such entity, +whether by contract or otherwise, or (b) ownership of fifty percent +(50%) or more of the outstanding shares or beneficial ownership of +such entity. + +2. Permitted Uses; Conditions & Restrictions. Subject to the terms +and conditions of this License, Apple hereby grants You, effective on +the date You accept this License and download the Original Code, a +world-wide, royalty-free, non-exclusive license, to the extent of +Apple's Applicable Patent Rights and copyrights covering the Original +Code, to do the following: + +2.1 Unmodified Code. You may use, reproduce, display, perform, +internally distribute within Your organization, and Externally Deploy +verbatim, unmodified copies of the Original Code, for commercial or +non-commercial purposes, provided that in each instance: + +(a) You must retain and reproduce in all copies of Original Code the +copyright and other proprietary notices and disclaimers of Apple as +they appear in the Original Code, and keep intact all notices in the +Original Code that refer to this License; and + +(b) You must include a copy of this License with every copy of Source +Code of Covered Code and documentation You distribute or Externally +Deploy, and You may not offer or impose any terms on such Source Code +that alter or restrict this License or the recipients' rights +hereunder, except as permitted under Section 6. + +2.2 Modified Code. You may modify Covered Code and use, reproduce, +display, perform, internally distribute within Your organization, and +Externally Deploy Your Modifications and Covered Code, for commercial +or non-commercial purposes, provided that in each instance You also +meet all of these conditions: + +(a) You must satisfy all the conditions of Section 2.1 with respect to +the Source Code of the Covered Code; + +(b) You must duplicate, to the extent it does not already exist, the +notice in Exhibit A in each file of the Source Code of all Your +Modifications, and cause the modified files to carry prominent notices +stating that You changed the files and the date of any change; and + +(c) If You Externally Deploy Your Modifications, You must make +Source Code of all Your Externally Deployed Modifications either +available to those to whom You have Externally Deployed Your +Modifications, or publicly available. Source Code of Your Externally +Deployed Modifications must be released under the terms set forth in +this License, including the license grants set forth in Section 3 +below, for as long as you Externally Deploy the Covered Code or twelve +(12) months from the date of initial External Deployment, whichever is +longer. You should preferably distribute the Source Code of Your +Externally Deployed Modifications electronically (e.g. download from a +web site). + +2.3 Distribution of Executable Versions. In addition, if You +Externally Deploy Covered Code (Original Code and/or Modifications) in +object code, executable form only, You must include a prominent +notice, in the code itself as well as in related documentation, +stating that Source Code of the Covered Code is available under the +terms of this License with information on how and where to obtain such +Source Code. + +2.4 Third Party Rights. You expressly acknowledge and agree that +although Apple and each Contributor grants the licenses to their +respective portions of the Covered Code set forth herein, no +assurances are provided by Apple or any Contributor that the Covered +Code does not infringe the patent or other intellectual property +rights of any other entity. Apple and each Contributor disclaim any +liability to You for claims brought by any other entity based on +infringement of intellectual property rights or otherwise. As a +condition to exercising the rights and licenses granted hereunder, You +hereby assume sole responsibility to secure any other intellectual +property rights needed, if any. For example, if a third party patent +license is required to allow You to distribute the Covered Code, it is +Your responsibility to acquire that license before distributing the +Covered Code. + +3. Your Grants. In consideration of, and as a condition to, the +licenses granted to You under this License, You hereby grant to any +person or entity receiving or distributing Covered Code under this +License a non-exclusive, royalty-free, perpetual, irrevocable license, +under Your Applicable Patent Rights and other intellectual property +rights (other than patent) owned or controlled by You, to use, +reproduce, display, perform, modify, sublicense, distribute and +Externally Deploy Your Modifications of the same scope and extent as +Apple's licenses under Sections 2.1 and 2.2 above. + +4. Larger Works. You may create a Larger Work by combining Covered +Code with other code not governed by the terms of this License and +distribute the Larger Work as a single product. In each such instance, +You must make sure the requirements of this License are fulfilled for +the Covered Code or any portion thereof. + +5. Limitations on Patent License. Except as expressly stated in +Section 2, no other patent rights, express or implied, are granted by +Apple herein. Modifications and/or Larger Works may require additional +patent licenses from Apple which Apple may grant in its sole +discretion. + +6. Additional Terms. You may choose to offer, and to charge a fee for, +warranty, support, indemnity or liability obligations and/or other +rights consistent with the scope of the license granted herein +("Additional Terms") to one or more recipients of Covered Code. +However, You may do so only on Your own behalf and as Your sole +responsibility, and not on behalf of Apple or any Contributor. You +must obtain the recipient's agreement that any such Additional Terms +are offered by You alone, and You hereby agree to indemnify, defend +and hold Apple and every Contributor harmless for any liability +incurred by or claims asserted against Apple or such Contributor by +reason of any such Additional Terms. + +7. Versions of the License. Apple may publish revised and/or new +versions of this License from time to time. Each version will be given +a distinguishing version number. Once Original Code has been published +under a particular version of this License, You may continue to use it +under the terms of that version. You may also choose to use such +Original Code under the terms of any subsequent version of this +License published by Apple. No one other than Apple has the right to +modify the terms applicable to Covered Code created under this +License. + +8. NO WARRANTY OR SUPPORT. The Covered Code may contain in whole or in +part pre-release, untested, or not fully tested works. The Covered +Code may contain errors that could cause failures or loss of data, and +may be incomplete or contain inaccuracies. You expressly acknowledge +and agree that use of the Covered Code, or any portion thereof, is at +Your sole and entire risk. THE COVERED CODE IS PROVIDED "AS IS" AND +WITHOUT WARRANTY, UPGRADES OR SUPPORT OF ANY KIND AND APPLE AND +APPLE'S LICENSOR(S) (COLLECTIVELY REFERRED TO AS "APPLE" FOR THE +PURPOSES OF SECTIONS 8 AND 9) AND ALL CONTRIBUTORS EXPRESSLY DISCLAIM +ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, BUT +NOT LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF +MERCHANTABILITY, OF SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR +PURPOSE, OF ACCURACY, OF QUIET ENJOYMENT, AND NONINFRINGEMENT OF THIRD +PARTY RIGHTS. APPLE AND EACH CONTRIBUTOR DOES NOT WARRANT AGAINST +INTERFERENCE WITH YOUR ENJOYMENT OF THE COVERED CODE, THAT THE +FUNCTIONS CONTAINED IN THE COVERED CODE WILL MEET YOUR REQUIREMENTS, +THAT THE OPERATION OF THE COVERED CODE WILL BE UNINTERRUPTED OR +ERROR-FREE, OR THAT DEFECTS IN THE COVERED CODE WILL BE CORRECTED. NO +ORAL OR WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE, AN APPLE +AUTHORIZED REPRESENTATIVE OR ANY CONTRIBUTOR SHALL CREATE A WARRANTY. +You acknowledge that the Covered Code is not intended for use in the +operation of nuclear facilities, aircraft navigation, communication +systems, or air traffic control machines in which case the failure of +the Covered Code could lead to death, personal injury, or severe +physical or environmental damage. + +9. LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO +EVENT SHALL APPLE OR ANY CONTRIBUTOR BE LIABLE FOR ANY INCIDENTAL, +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING +TO THIS LICENSE OR YOUR USE OR INABILITY TO USE THE COVERED CODE, OR +ANY PORTION THEREOF, WHETHER UNDER A THEORY OF CONTRACT, WARRANTY, +TORT (INCLUDING NEGLIGENCE), PRODUCTS LIABILITY OR OTHERWISE, EVEN IF +APPLE OR SUCH CONTRIBUTOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES AND NOTWITHSTANDING THE FAILURE OF ESSENTIAL PURPOSE OF ANY +REMEDY. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF LIABILITY OF +INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT APPLY +TO YOU. In no event shall Apple's total liability to You for all +damages (other than as may be required by applicable law) under this +License exceed the amount of fifty dollars ($50.00). + +10. Trademarks. This License does not grant any rights to use the +trademarks or trade names "Apple", "Apple Computer", "Mac", "Mac OS", +"QuickTime", "QuickTime Streaming Server" or any other trademarks, +service marks, logos or trade names belonging to Apple (collectively +"Apple Marks") or to any trademark, service mark, logo or trade name +belonging to any Contributor. You agree not to use any Apple Marks in +or as part of the name of products derived from the Original Code or +to endorse or promote products derived from the Original Code other +than as expressly permitted by and in strict compliance at all times +with Apple's third party trademark usage guidelines which are posted +at http://www.apple.com/legal/guidelinesfor3rdparties.html. + +11. Ownership. Subject to the licenses granted under this License, +each Contributor retains all rights, title and interest in and to any +Modifications made by such Contributor. Apple retains all rights, +title and interest in and to the Original Code and any Modifications +made by or on behalf of Apple ("Apple Modifications"), and such Apple +Modifications will not be automatically subject to this License. Apple +may, at its sole discretion, choose to license such Apple +Modifications under this License, or on different terms from those +contained in this License or may choose not to license them at all. + +12. Termination. + +12.1 Termination. This License and the rights granted hereunder will +terminate: + +(a) automatically without notice from Apple if You fail to comply with +any term(s) of this License and fail to cure such breach within 30 +days of becoming aware of such breach; + +(b) immediately in the event of the circumstances described in Section +13.5(b); or + +(c) automatically without notice from Apple if You, at any time during +the term of this License, commence an action for patent infringement +against Apple; provided that Apple did not first commence +an action for patent infringement against You in that instance. + +12.2 Effect of Termination. Upon termination, You agree to immediately +stop any further use, reproduction, modification, sublicensing and +distribution of the Covered Code. All sublicenses to the Covered Code +which have been properly granted prior to termination shall survive +any termination of this License. Provisions which, by their nature, +should remain in effect beyond the termination of this License shall +survive, including but not limited to Sections 3, 5, 8, 9, 10, 11, +12.2 and 13. No party will be liable to any other for compensation, +indemnity or damages of any sort solely as a result of terminating +this License in accordance with its terms, and termination of this +License will be without prejudice to any other right or remedy of +any party. + +13. Miscellaneous. + +13.1 Government End Users. The Covered Code is a "commercial item" as +defined in FAR 2.101. Government software and technical data rights in +the Covered Code include only those rights customarily provided to the +public as defined in this License. This customary commercial license +in technical data and software is provided in accordance with FAR +12.211 (Technical Data) and 12.212 (Computer Software) and, for +Department of Defense purchases, DFAR 252.227-7015 (Technical Data -- +Commercial Items) and 227.7202-3 (Rights in Commercial Computer +Software or Computer Software Documentation). Accordingly, all U.S. +Government End Users acquire Covered Code with only those rights set +forth herein. + +13.2 Relationship of Parties. This License will not be construed as +creating an agency, partnership, joint venture or any other form of +legal association between or among You, Apple or any Contributor, and +You will not represent to the contrary, whether expressly, by +implication, appearance or otherwise. + +13.3 Independent Development. Nothing in this License will impair +Apple's right to acquire, license, develop, have others develop for +it, market and/or distribute technology or products that perform the +same or similar functions as, or otherwise compete with, +Modifications, Larger Works, technology or products that You may +develop, produce, market or distribute. + +13.4 Waiver; Construction. Failure by Apple or any Contributor to +enforce any provision of this License will not be deemed a waiver of +future enforcement of that or any other provision. Any law or +regulation which provides that the language of a contract shall be +construed against the drafter will not apply to this License. + +13.5 Severability. (a) If for any reason a court of competent +jurisdiction finds any provision of this License, or portion thereof, +to be unenforceable, that provision of the License will be enforced to +the maximum extent permissible so as to effect the economic benefits +and intent of the parties, and the remainder of this License will +continue in full force and effect. (b) Notwithstanding the foregoing, +if applicable law prohibits or restricts You from fully and/or +specifically complying with Sections 2 and/or 3 or prevents the +enforceability of either of those Sections, this License will +immediately terminate and You must immediately discontinue any use of +the Covered Code and destroy all copies of it that are in your +possession or control. + +13.6 Dispute Resolution. Any litigation or other dispute resolution +between You and Apple relating to this License shall take place in the +Northern District of California, and You and Apple hereby consent to +the personal jurisdiction of, and venue in, the state and federal +courts within that District with respect to this License. The +application of the United Nations Convention on Contracts for the +International Sale of Goods is expressly excluded. + +13.7 Entire Agreement; Governing Law. This License constitutes the +entire agreement between the parties with respect to the subject +matter hereof. This License shall be governed by the laws of the +United States and the State of California, except that body of +California law concerning conflicts of law. + +Where You are located in the province of Quebec, Canada, the following +clause applies: The parties hereby confirm that they have requested +that this License and all related documents be drafted in English. Les +parties ont exige que le present contrat et tous les documents +connexes soient rediges en anglais. + +EXHIBIT A. + +"Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights +Reserved. + +This file contains Original Code and/or Modifications of Original Code +as defined in and that are subject to the Apple Public Source License +Version 2.0 (the 'License'). You may not use this file except in +compliance with the License. Please obtain a copy of the License at +http://www.opensource.apple.com/apsl/ and read it before using this +file. + +The Original Code and all software distributed under the License are +distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER +EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. +Please see the License for the specific language governing rights and +limitations under the License." Index: branches/slice/rev749/ChamMek/ChamMek.xcodeproj/slice.pbxuser =================================================================== --- branches/slice/rev749/ChamMek/ChamMek.xcodeproj/slice.pbxuser (revision 0) +++ branches/slice/rev749/ChamMek/ChamMek.xcodeproj/slice.pbxuser (revision 1169) @@ -0,0 +1,2228 @@ +// !$*UTF8*$! +{ + 08FB7793FE84155DC02AAC07 /* Project object */ = { + activeBuildConfigurationName = Debug; + activeExecutable = 12C26D2E12B0DDF400AF7F4B /* ChamMek */; + activeTarget = 8DD76FA90486AB0100D96B5E /* ChamMek */; + addToTargets = ( + 8DD76FA90486AB0100D96B5E /* ChamMek */, + ); + codeSenseManager = 12C26D3812B0DDFC00AF7F4B /* Code sense */; + executables = ( + 12C26D2E12B0DDF400AF7F4B /* ChamMek */, + ); + perUserDictionary = { + PBXConfiguration.PBXFileTableDataSource3.PBXBookmarksDataSource = { + PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; + PBXFileTableDataSourceColumnSortingKey = PBXBookmarksDataSource_NameID; + PBXFileTableDataSourceColumnWidthsKey = ( + 200, + 200, + 534.58349609375, + ); + PBXFileTableDataSourceColumnsKey = ( + PBXBookmarksDataSource_LocationID, + PBXBookmarksDataSource_NameID, + PBXBookmarksDataSource_CommentsID, + ); + }; + PBXConfiguration.PBXFileTableDataSource3.PBXExecutablesDataSource = { + PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; + PBXFileTableDataSourceColumnSortingKey = PBXExecutablesDataSource_NameID; + PBXFileTableDataSourceColumnWidthsKey = ( + 22, + 300, + 461.58349609375, + ); + PBXFileTableDataSourceColumnsKey = ( + PBXExecutablesDataSource_ActiveFlagID, + PBXExecutablesDataSource_NameID, + PBXExecutablesDataSource_CommentsID, + ); + }; + PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = { + PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; + PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; + PBXFileTableDataSourceColumnWidthsKey = ( + 20, + 512, + 20, + 48, + 43, + 43, + 20, + ); + PBXFileTableDataSourceColumnsKey = ( + PBXFileDataSource_FiletypeID, + PBXFileDataSource_Filename_ColumnID, + PBXFileDataSource_Built_ColumnID, + PBXFileDataSource_ObjectSize_ColumnID, + PBXFileDataSource_Errors_ColumnID, + PBXFileDataSource_Warnings_ColumnID, + PBXFileDataSource_Target_ColumnID, + ); + }; + PBXConfiguration.PBXFileTableDataSource3.PBXFindDataSource = { + PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; + PBXFileTableDataSourceColumnSortingKey = PBXFindDataSource_LocationID; + PBXFileTableDataSourceColumnWidthsKey = ( + 200, + 588, + ); + PBXFileTableDataSourceColumnsKey = ( + PBXFindDataSource_MessageID, + PBXFindDataSource_LocationID, + ); + }; + PBXConfiguration.PBXFileTableDataSource3.PBXSymbolsDataSource = { + PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; + PBXFileTableDataSourceColumnSortingKey = PBXSymbolsDataSource_SymbolNameID; + PBXFileTableDataSourceColumnWidthsKey = ( + 16, + 200, + 50, + 514.20849609375, + ); + PBXFileTableDataSourceColumnsKey = ( + PBXSymbolsDataSource_SymbolTypeIconID, + PBXSymbolsDataSource_SymbolNameID, + PBXSymbolsDataSource_SymbolTypeID, + PBXSymbolsDataSource_ReferenceNameID, + ); + }; + PBXConfiguration.PBXFileTableDataSource3.XCSCMDataSource = { + PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; + PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; + PBXFileTableDataSourceColumnWidthsKey = ( + 20, + 20, + 550, + 20, + 48, + 43, + 43, + 20, + ); + PBXFileTableDataSourceColumnsKey = ( + PBXFileDataSource_SCM_ColumnID, + PBXFileDataSource_FiletypeID, + PBXFileDataSource_Filename_ColumnID, + PBXFileDataSource_Built_ColumnID, + PBXFileDataSource_ObjectSize_ColumnID, + PBXFileDataSource_Errors_ColumnID, + PBXFileDataSource_Warnings_ColumnID, + PBXFileDataSource_Target_ColumnID, + ); + }; + PBXPerProjectTemplateStateSaveDate = 326878013; + PBXWorkspaceStateSaveDate = 326878013; + }; + perUserProjectItems = { + 120DC73B12F5C87900345D09 /* PBXTextBookmark */ = 120DC73B12F5C87900345D09 /* PBXTextBookmark */; + 120DFB1712BA3A4D00C7EAC8 /* PBXTextBookmark */ = 120DFB1712BA3A4D00C7EAC8 /* PBXTextBookmark */; + 120DFB1812BA3A4D00C7EAC8 /* PBXTextBookmark */ = 120DFB1812BA3A4D00C7EAC8 /* PBXTextBookmark */; + 120DFF6B12BA3BF500C7EAC8 /* PBXTextBookmark */ = 120DFF6B12BA3BF500C7EAC8 /* PBXTextBookmark */; + 120FE7891345F8FC00CC4AA2 /* PBXTextBookmark */ = 120FE7891345F8FC00CC4AA2 /* PBXTextBookmark */; + 12106C2B12F480E2008BA484 /* PBXTextBookmark */ = 12106C2B12F480E2008BA484 /* PBXTextBookmark */; + 121114BE12F591340029B6FC /* PBXTextBookmark */ = 121114BE12F591340029B6FC /* PBXTextBookmark */; + 1216139E12B65BB50019961E /* PBXTextBookmark */ = 1216139E12B65BB50019961E /* PBXTextBookmark */; + 121613FF12B65D970019961E /* PBXTextBookmark */ = 121613FF12B65D970019961E /* PBXTextBookmark */; + 1218381312F2EA3F007D1704 /* PBXTextBookmark */ = 1218381312F2EA3F007D1704 /* PBXTextBookmark */; + 1218381412F2EA3F007D1704 /* PBXTextBookmark */ = 1218381412F2EA3F007D1704 /* PBXTextBookmark */; + 1218381612F2EA3F007D1704 /* PBXTextBookmark */ = 1218381612F2EA3F007D1704 /* PBXTextBookmark */; + 1218381812F2EA3F007D1704 /* PBXTextBookmark */ = 1218381812F2EA3F007D1704 /* PBXTextBookmark */; + 1218381A12F2EA3F007D1704 /* PBXTextBookmark */ = 1218381A12F2EA3F007D1704 /* PBXTextBookmark */; + 121DBA96137186C700C733E2 /* PBXTextBookmark */ = 121DBA96137186C700C733E2 /* PBXTextBookmark */; + 121DBAA11371953B00C733E2 /* PBXTextBookmark */ = 121DBAA11371953B00C733E2 /* PBXTextBookmark */; + 121DBAA21371953B00C733E2 /* PBXTextBookmark */ = 121DBAA21371953B00C733E2 /* PBXTextBookmark */; + 121DBAA31371953B00C733E2 /* PBXTextBookmark */ = 121DBAA31371953B00C733E2 /* PBXTextBookmark */; + 121DBAA51371953B00C733E2 /* PBXTextBookmark */ = 121DBAA51371953B00C733E2 /* PBXTextBookmark */; + 121DBAA71371953B00C733E2 /* PBXTextBookmark */ = 121DBAA71371953B00C733E2 /* PBXTextBookmark */; + 121FAA3512F051A200385F21 /* PBXTextBookmark */ = 121FAA3512F051A200385F21 /* PBXTextBookmark */; + 1220CE4112F2BFBF0045986D /* PBXTextBookmark */ = 1220CE4112F2BFBF0045986D /* PBXTextBookmark */; + 1220CE4212F2BFBF0045986D /* PBXTextBookmark */ = 1220CE4212F2BFBF0045986D /* PBXTextBookmark */; + 1221899A134352F700A5656B /* PBXTextBookmark */ = 1221899A134352F700A5656B /* PBXTextBookmark */; + 12218E691343597300A5656B /* PBXTextBookmark */ = 12218E691343597300A5656B /* PBXTextBookmark */; + 1221F71113291A0A0014A9B5 /* PBXTextBookmark */ = 1221F71113291A0A0014A9B5 /* PBXTextBookmark */; + 1221F71213291A0A0014A9B5 /* PBXTextBookmark */ = 1221F71213291A0A0014A9B5 /* PBXTextBookmark */; + 1221F71413291A0A0014A9B5 /* PBXTextBookmark */ = 1221F71413291A0A0014A9B5 /* PBXTextBookmark */; + 1221F71513291A0A0014A9B5 /* PBXTextBookmark */ = 1221F71513291A0A0014A9B5 /* PBXTextBookmark */; + 1221F71613291A0A0014A9B5 /* PBXTextBookmark */ = 1221F71613291A0A0014A9B5 /* PBXTextBookmark */; + 1221F71813291A0A0014A9B5 /* PBXTextBookmark */ = 1221F71813291A0A0014A9B5 /* PBXTextBookmark */; + 1221F71A13291A0A0014A9B5 /* PBXTextBookmark */ = 1221F71A13291A0A0014A9B5 /* PBXTextBookmark */; + 122A869812EC5429004312F4 /* PBXTextBookmark */ = 122A869812EC5429004312F4 /* PBXTextBookmark */; + 122A86C612ECA817004312F4 /* PBXTextBookmark */ = 122A86C612ECA817004312F4 /* PBXTextBookmark */; + 122C56E012F2CB51005FE786 /* PBXTextBookmark */ = 122C56E012F2CB51005FE786 /* PBXTextBookmark */; + 122DBE3512F47E30003C7482 /* PBXTextBookmark */ = 122DBE3512F47E30003C7482 /* PBXTextBookmark */; + 12306DBE12F4AAEE000AAE98 /* PBXTextBookmark */ = 12306DBE12F4AAEE000AAE98 /* PBXTextBookmark */; + 124C493212B8D846005AA276 /* PBXTextBookmark */ = 124C493212B8D846005AA276 /* PBXTextBookmark */; + 124C493712B8D846005AA276 /* PBXTextBookmark */ = 124C493712B8D846005AA276 /* PBXTextBookmark */; + 124C494212B8E8C2005AA276 /* PBXTextBookmark */ = 124C494212B8E8C2005AA276 /* PBXTextBookmark */; + 124C494312B8E8C2005AA276 /* PBXTextBookmark */ = 124C494312B8E8C2005AA276 /* PBXTextBookmark */; + 124C494512B8E8C2005AA276 /* PBXTextBookmark */ = 124C494512B8E8C2005AA276 /* PBXTextBookmark */; + 124C494B12B8EA5D005AA276 /* PBXTextBookmark */ = 124C494B12B8EA5D005AA276 /* PBXTextBookmark */; + 125437C812EF1E99007175C8 /* PBXTextBookmark */ = 125437C812EF1E99007175C8 /* PBXTextBookmark */; + 125437CB12EF1E99007175C8 /* PBXTextBookmark */ = 125437CB12EF1E99007175C8 /* PBXTextBookmark */; + 12569C8612F0115B005A9113 /* PBXTextBookmark */ = 12569C8612F0115B005A9113 /* PBXTextBookmark */; + 125A6C2512F53BCD00535D65 /* PBXTextBookmark */ = 125A6C2512F53BCD00535D65 /* PBXTextBookmark */; + 1267813012B7B13E00A25CED /* PBXTextBookmark */ = 1267813012B7B13E00A25CED /* PBXTextBookmark */; + 12679BA312BE822E00E3637F /* PBXTextBookmark */ = 12679BA312BE822E00E3637F /* PBXTextBookmark */; + 1267A85C12F5771100751FC6 /* PBXTextBookmark */ = 1267A85C12F5771100751FC6 /* PBXTextBookmark */; + 126A6402137BCAAC003C4F2E /* PBXTextBookmark */ = 126A6402137BCAAC003C4F2E /* PBXTextBookmark */; + 126A6408137BCAAE003C4F2E /* PBXTextBookmark */ = 126A6408137BCAAE003C4F2E /* PBXTextBookmark */; + 126A6409137BCAAE003C4F2E /* PBXTextBookmark */ = 126A6409137BCAAE003C4F2E /* PBXTextBookmark */; + 126C766312EEF67F00BDB81E /* PBXTextBookmark */ = 126C766312EEF67F00BDB81E /* PBXTextBookmark */; + 126D84C612F7FA6E000AB776 /* PBXTextBookmark */ = 126D84C612F7FA6E000AB776 /* PBXTextBookmark */; + 12715CDF12EA253100E3013B /* PBXTextBookmark */ = 12715CDF12EA253100E3013B /* PBXTextBookmark */; + 12715CE012EA253100E3013B /* PBXTextBookmark */ = 12715CE012EA253100E3013B /* PBXTextBookmark */; + 128439CE1365B655003A4A52 /* PBXTextBookmark */ = 128439CE1365B655003A4A52 /* PBXTextBookmark */; + 1288318212C3608100EA4CB2 /* PBXTextBookmark */ = 1288318212C3608100EA4CB2 /* PBXTextBookmark */; + 128A9AF412C233CE00600556 /* PBXTextBookmark */ = 128A9AF412C233CE00600556 /* PBXTextBookmark */; + 1299A51F12B3C328007ED516 /* PBXTextBookmark */ = 1299A51F12B3C328007ED516 /* PBXTextBookmark */; + 1299A55612B3C4DF007ED516 /* PBXTextBookmark */ = 1299A55612B3C4DF007ED516 /* PBXTextBookmark */; + 12AB04BD12B663F5005A745F /* PBXTextBookmark */ = 12AB04BD12B663F5005A745F /* PBXTextBookmark */; + 12AB04EC12B665EA005A745F /* PBXTextBookmark */ = 12AB04EC12B665EA005A745F /* PBXTextBookmark */; + 12AF764312BA614B003BBFD3 /* PBXTextBookmark */ = 12AF764312BA614B003BBFD3 /* PBXTextBookmark */; + 12B46E6612B75631006C2B9C /* PBXTextBookmark */ = 12B46E6612B75631006C2B9C /* PBXTextBookmark */; + 12B46E6812B75631006C2B9C /* PBXTextBookmark */ = 12B46E6812B75631006C2B9C /* PBXTextBookmark */; + 12B46E6912B75631006C2B9C /* PBXTextBookmark */ = 12B46E6912B75631006C2B9C /* PBXTextBookmark */; + 12B46E6A12B75631006C2B9C /* PBXTextBookmark */ = 12B46E6A12B75631006C2B9C /* PBXTextBookmark */; + 12B90A2012B2A7E200FE287A /* PBXTextBookmark */ = 12B90A2012B2A7E200FE287A /* PBXTextBookmark */; + 12B90A2B12B2A86B00FE287A /* PBXTextBookmark */ = 12B90A2B12B2A86B00FE287A /* PBXTextBookmark */; + 12B90A4D12B2AE1300FE287A /* PBXTextBookmark */ = 12B90A4D12B2AE1300FE287A /* PBXTextBookmark */; + 12B90A4F12B2AE1300FE287A /* PBXTextBookmark */ = 12B90A4F12B2AE1300FE287A /* PBXTextBookmark */; + 12B90A5212B2AE1300FE287A /* PBXTextBookmark */ = 12B90A5212B2AE1300FE287A /* PBXTextBookmark */; + 12B9F42612B29A4A00FE287A /* PBXTextBookmark */ = 12B9F42612B29A4A00FE287A /* PBXTextBookmark */; + 12BF14DA12B3CF8E00D798FE /* PBXTextBookmark */ = 12BF14DA12B3CF8E00D798FE /* PBXTextBookmark */; + 12C246F412C87C7C007E8339 /* PBXTextBookmark */ = 12C246F412C87C7C007E8339 /* PBXTextBookmark */; + 12C5020712D8B82400EDCC4E /* PBXTextBookmark */ = 12C5020712D8B82400EDCC4E /* PBXTextBookmark */; + 12C7009812B7BCE7006BD382 /* PBXTextBookmark */ = 12C7009812B7BCE7006BD382 /* PBXTextBookmark */; + 12C7009912B7BCE7006BD382 /* PBXTextBookmark */ = 12C7009912B7BCE7006BD382 /* PBXTextBookmark */; + 12C704E512B7BD3E006BD382 /* PBXTextBookmark */ = 12C704E512B7BD3E006BD382 /* PBXTextBookmark */; + 12C7FC4D12B7BCD3006BD382 /* PBXTextBookmark */ = 12C7FC4D12B7BCD3006BD382 /* PBXTextBookmark */; + 12C7FC4E12B7BCD3006BD382 /* PlistBookmark */ = 12C7FC4E12B7BCD3006BD382 /* PlistBookmark */; + 12C8CB6812B5529D003DA1E4 /* PBXTextBookmark */ = 12C8CB6812B5529D003DA1E4 /* PBXTextBookmark */; + 12CC44C812B3947B007E0C76 /* PBXTextBookmark */ = 12CC44C812B3947B007E0C76 /* PBXTextBookmark */; + 12D331A312C61E950093EEDB /* PBXTextBookmark */ = 12D331A312C61E950093EEDB /* PBXTextBookmark */; + 12D3324112C63EB70093EEDB /* PBXTextBookmark */ = 12D3324112C63EB70093EEDB /* PBXTextBookmark */; + 12D3329E12C669090093EEDB /* PBXTextBookmark */ = 12D3329E12C669090093EEDB /* PBXTextBookmark */; + 12D332A512C669090093EEDB /* PBXTextBookmark */ = 12D332A512C669090093EEDB /* PBXTextBookmark */; + 12D332AA12C669090093EEDB /* PBXTextBookmark */ = 12D332AA12C669090093EEDB /* PBXTextBookmark */; + 12D6232512BA5F380032F367 /* PBXTextBookmark */ = 12D6232512BA5F380032F367 /* PBXTextBookmark */; + 12D6232612BA5F380032F367 /* PBXTextBookmark */ = 12D6232612BA5F380032F367 /* PBXTextBookmark */; + 12DA422F12C52DAC009281B3 /* PBXTextBookmark */ = 12DA422F12C52DAC009281B3 /* PBXTextBookmark */; + 12DCD38E12BBA5D600A20635 /* PBXTextBookmark */ = 12DCD38E12BBA5D600A20635 /* PBXTextBookmark */; + 12DFBB1C12F6E9A500E2DA49 /* PBXTextBookmark */ = 12DFBB1C12F6E9A500E2DA49 /* PBXTextBookmark */; + 12DFBB1D12F6E9A500E2DA49 /* PBXTextBookmark */ = 12DFBB1D12F6E9A500E2DA49 /* PBXTextBookmark */; + 12DFBB1F12F6E9A500E2DA49 /* PBXTextBookmark */ = 12DFBB1F12F6E9A500E2DA49 /* PBXTextBookmark */; + 12DFBB2112F6E9A500E2DA49 /* PBXTextBookmark */ = 12DFBB2112F6E9A500E2DA49 /* PBXTextBookmark */; + 12DFBFDA12F7066500E2DA49 /* PBXTextBookmark */ = 12DFBFDA12F7066500E2DA49 /* PBXTextBookmark */; + 12E17AE612B2BA9B00607D8E /* PBXTextBookmark */ = 12E17AE612B2BA9B00607D8E /* PBXTextBookmark */; + 12E6FB5712BB458400C2A021 /* PBXTextBookmark */ = 12E6FB5712BB458400C2A021 /* PBXTextBookmark */; + 12E8842612D8F833004C76C8 /* PBXTextBookmark */ = 12E8842612D8F833004C76C8 /* PBXTextBookmark */; + 12EA3B42131B91D4008D7D68 /* PBXTextBookmark */ = 12EA3B42131B91D4008D7D68 /* PBXTextBookmark */; + 12EFD98A12B510D9002A1712 /* PBXTextBookmark */ = 12EFD98A12B510D9002A1712 /* PBXTextBookmark */; + 12EFE2FD12B51ED5002A1712 /* PBXTextBookmark */ = 12EFE2FD12B51ED5002A1712 /* PBXTextBookmark */; + 12EFE65A12B547A7002A1712 /* PBXTextBookmark */ = 12EFE65A12B547A7002A1712 /* PBXTextBookmark */; + 12EFE95E12B549B6002A1712 /* PBXTextBookmark */ = 12EFE95E12B549B6002A1712 /* PBXTextBookmark */; + 12F7FF0012BB9F3200949DEC /* PBXTextBookmark */ = 12F7FF0012BB9F3200949DEC /* PBXTextBookmark */; + 12FC0E7512BB4B5200E9CFA8 /* PBXTextBookmark */ = 12FC0E7512BB4B5200E9CFA8 /* PBXTextBookmark */; + 12FC0E9412BB65A800E9CFA8 /* PBXTextBookmark */ = 12FC0E9412BB65A800E9CFA8 /* PBXTextBookmark */; + 12FE983612C7CEEB001B1702 /* PBXTextBookmark */ = 12FE983612C7CEEB001B1702 /* PBXTextBookmark */; + 12FE984A12C7E11C001B1702 /* PBXTextBookmark */ = 12FE984A12C7E11C001B1702 /* PBXTextBookmark */; + 12FE987912C7E281001B1702 /* PBXTextBookmark */ = 12FE987912C7E281001B1702 /* PBXTextBookmark */; + 12FE987A12C7E281001B1702 /* PBXTextBookmark */ = 12FE987A12C7E281001B1702 /* PBXTextBookmark */; + }; + sourceControlManager = 12C26D3712B0DDFC00AF7F4B /* Source Control */; + userBuildSettings = { + }; + }; + 08FB7796FE84155DC02AAC07 /* main.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {752, 331}}"; + sepNavSelRange = "{192, 7}"; + sepNavVisRange = "{0, 235}"; + }; + }; + 12078D9812BA5AF400A1C013 /* fake_efi.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = fake_efi.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/libsaio/fake_efi.c; + sourceTree = ""; + }; + 120DB90712B9F3F1001FDAE1 /* boot.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = boot.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/boot2/boot.c; + sourceTree = ""; + }; + 120DC73B12F5C87900345D09 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12164AF212F5C31400CB43B3 /* Makefile */; + name = "Makefile: 4"; + rLen = 6; + rLoc = 105; + rType = 0; + vrLen = 798; + vrLoc = 0; + }; + 120DFB0A12BA3A3900C7EAC8 /* Localizable.strings */ = { + isa = PBXFileReference; + lastKnownFileType = text.plist.strings; + name = Localizable.strings; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/package/Resources/Italian.lproj/Localizable.strings; + sourceTree = ""; + }; + 120DFB1712BA3A4D00C7EAC8 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 120DB90712B9F3F1001FDAE1 /* boot.c */; + name = "boot.c: 111"; + rLen = 11; + rLoc = 3102; + rType = 0; + vrLen = 818; + vrLoc = 2630; + }; + 120DFB1812BA3A4D00C7EAC8 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 120DFB0A12BA3A3900C7EAC8 /* Localizable.strings */; + name = "Localizable.strings: 54"; + rLen = 7; + rLoc = 2404; + rType = 0; + vrLen = 980; + vrLoc = 1773; + }; + 120DFB2112BA3A5800C7EAC8 /* Makefile */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.make; + name = Makefile; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/Makefile; + sourceTree = ""; + }; + 120DFF6B12BA3BF500C7EAC8 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 120DFB2112BA3A5800C7EAC8 /* Makefile */; + name = "Makefile: 29"; + rLen = 7; + rLoc = 685; + rType = 0; + vrLen = 881; + vrLoc = 298; + }; + 120F5CDE12F0087200C64A78 /* CHANGES */ = { + isa = PBXFileReference; + lastKnownFileType = text; + name = CHANGES; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/CHANGES; + sourceTree = ""; + }; + 120FE7891345F8FC00CC4AA2 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12218E6B1343597300A5656B /* cpuid.h */; + name = "cpuid.h: 110"; + rLen = 16; + rLoc = 4965; + rType = 0; + vrLen = 1214; + vrLoc = 4347; + }; + 120FE78D1345F8FC00CC4AA2 /* spd.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = spd.h; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/modules/Memory/spd.h; + sourceTree = ""; + }; + 12106C2B12F480E2008BA484 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 122DBE3A12F47E30003C7482 /* stringTable.c */; + name = "stringTable.c: 602"; + rLen = 12; + rLoc = 11991; + rType = 0; + vrLen = 470; + vrLoc = 11606; + }; + 121114BE12F591340029B6FC /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 1267A85F12F5771100751FC6 /* GUI_module.c */; + name = "GUI_module.c: 150"; + rLen = 6; + rLoc = 3652; + rType = 0; + vrLen = 747; + vrLoc = 3433; + }; + 121217CC12EEF2550055AF66 /* options.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = options.c; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/boot2/options.c; + sourceTree = ""; + }; + 1216139E12B65BB50019961E /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12CF89A712B6410100B7BC73 /* pci_setup.c */; + name = "pci_setup.c: 16"; + rLen = 14; + rLoc = 204; + rType = 0; + vrLen = 470; + vrLoc = 80; + }; + 121613A212B65BB50019961E /* pci.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = pci.h; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/libsaio/pci.h; + sourceTree = ""; + }; + 121613FF12B65D970019961E /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 121613A212B65BB50019961E /* pci.h */; + name = "pci.h: 51"; + rLen = 12; + rLoc = 855; + rType = 0; + vrLen = 895; + vrLoc = 563; + }; + 12164AF212F5C31400CB43B3 /* Makefile */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.make; + name = Makefile; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/modules/GUI/Makefile; + sourceTree = ""; + }; + 1218381312F2EA3F007D1704 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 122C56E412F2CB51005FE786 /* Memory.c */; + name = "Memory.c: 61"; + rLen = 13; + rLoc = 1338; + rType = 0; + vrLen = 758; + vrLoc = 1080; + }; + 1218381412F2EA3F007D1704 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 1218381512F2EA3F007D1704 /* __udivsi3.c */; + name = "__udivsi3.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 234; + vrLoc = 0; + }; + 1218381512F2EA3F007D1704 /* __udivsi3.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = __udivsi3.c; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/modules/klibc/__udivsi3.c; + sourceTree = ""; + }; + 1218381612F2EA3F007D1704 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 1218381712F2EA3F007D1704 /* __udivmodsi4.c */; + name = "__udivmodsi4.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 485; + vrLoc = 0; + }; + 1218381712F2EA3F007D1704 /* __udivmodsi4.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = __udivmodsi4.c; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/modules/klibc/__udivmodsi4.c; + sourceTree = ""; + }; + 1218381812F2EA3F007D1704 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 1218381912F2EA3F007D1704 /* uClibc++.c */; + name = "uClibc++.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 97; + vrLoc = 0; + }; + 1218381912F2EA3F007D1704 /* uClibc++.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = "uClibc++.c"; + path = "/Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/modules/uClibc++/uClibc++.c"; + sourceTree = ""; + }; + 1218381A12F2EA3F007D1704 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 1218381B12F2EA3F007D1704 /* Makefile */; + name = "Makefile: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1158; + vrLoc = 0; + }; + 1218381B12F2EA3F007D1704 /* Makefile */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.make; + name = Makefile; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/modules/klibc/Makefile; + sourceTree = ""; + }; + 121B17F412F2C5DF00259614 /* platform.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = platform.h; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/libsaio/platform.h; + sourceTree = ""; + }; + 121DBA96137186C700C733E2 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 128439D21365B655003A4A52 /* saio_internal.h */; + name = "saio_internal.h: 71"; + rLen = 9; + rLoc = 2652; + rType = 0; + vrLen = 1305; + vrLoc = 1916; + }; + 121DBA98137186C700C733E2 /* graphics.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = graphics.c; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/boot2/graphics.c; + sourceTree = ""; + }; + 121DBA9E137188C200C733E2 /* asm.s */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.asm; + name = asm.s; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/libsaio/asm.s; + sourceTree = ""; + }; + 121DBAA11371953B00C733E2 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 121DBA98137186C700C733E2 /* graphics.c */; + name = "graphics.c: 642"; + rLen = 4; + rLoc = 18270; + rType = 0; + vrLen = 961; + vrLoc = 17789; + }; + 121DBAA21371953B00C733E2 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 121DBA9E137188C200C733E2 /* asm.s */; + name = "asm.s: 261"; + rLen = 12; + rLoc = 7967; + rType = 0; + vrLen = 765; + vrLoc = 7537; + }; + 121DBAA31371953B00C733E2 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 121DBAA41371953B00C733E2 /* biosfn.c */; + name = "biosfn.c: 449"; + rLen = 196; + rLoc = 13069; + rType = 0; + vrLen = 1123; + vrLoc = 10570; + }; + 121DBAA41371953B00C733E2 /* biosfn.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = biosfn.c; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/libsaio/biosfn.c; + sourceTree = ""; + }; + 121DBAA51371953B00C733E2 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 121DBAA61371953B00C733E2 /* bios.s */; + name = "bios.s: 130"; + rLen = 12; + rLoc = 4475; + rType = 0; + vrLen = 842; + vrLoc = 4915; + }; + 121DBAA61371953B00C733E2 /* bios.s */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.asm; + name = bios.s; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/libsaio/bios.s; + sourceTree = ""; + }; + 121DBAA71371953B00C733E2 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 121DBAA81371953B00C733E2 /* Makefile */; + name = "Makefile: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 902; + vrLoc = 0; + }; + 121DBAA81371953B00C733E2 /* Makefile */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.make; + name = Makefile; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/libsaio/Makefile; + sourceTree = ""; + }; + 121DBAAB1371953B00C733E2 /* boot2.s */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.asm; + name = boot2.s; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/boot2/boot2.s; + sourceTree = ""; + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {824, 4485}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{12996, 1077}"; + }; + }; + 121E3B3D12F04EB9007B7E08 /* gui.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = gui.h; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/modules/GUI/gui.h; + sourceTree = ""; + }; + 121E9E4112C6A6F9000B6ED3 /* gma.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = gma.c; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/modules/GraphicsEnabler/gma.c; + sourceTree = ""; + }; + 121EA43012B7B9DD002449B3 /* smbios_patcher.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = smbios_patcher.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/libsaio/smbios_patcher.c; + sourceTree = ""; + }; + 121FAA3512F051A200385F21 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 121E3B3D12F04EB9007B7E08 /* gui.h */; + name = "gui.h: 28"; + rLen = 16; + rLoc = 572; + rType = 0; + vrLen = 887; + vrLoc = 2270; + }; + 1220CE3912F2BF1C0045986D /* dram_controllers.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = dram_controllers.c; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/modules/Memory/dram_controllers.c; + sourceTree = ""; + }; + 1220CE4112F2BFBF0045986D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 1220CE3912F2BF1C0045986D /* dram_controllers.c */; + name = "dram_controllers.c: 162"; + rLen = 13; + rLoc = 3575; + rType = 0; + vrLen = 629; + vrLoc = 3268; + }; + 1220CE4212F2BFBF0045986D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 1220CE4312F2BFBF0045986D /* mem.c */; + name = "mem.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 508; + vrLoc = 0; + }; + 1220CE4312F2BFBF0045986D /* mem.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = mem.c; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/modules/Memory/mem.c; + sourceTree = ""; + }; + 1221899A134352F700A5656B /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 1221F71D13291A0A0014A9B5 /* gui.c */; + name = "gui.c: 745"; + rLen = 13; + rLoc = 22523; + rType = 0; + vrLen = 616; + vrLoc = 176; + }; + 1221899C134352F700A5656B /* smbios_patcher.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = smbios_patcher.c; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/libsaio/smbios_patcher.c; + sourceTree = ""; + }; + 12218E691343597300A5656B /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 1221899C134352F700A5656B /* smbios_patcher.c */; + name = "smbios_patcher.c: 1344"; + rLen = 7; + rLoc = 44953; + rType = 0; + vrLen = 779; + vrLoc = 44243; + }; + 12218E6B1343597300A5656B /* cpuid.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = cpuid.h; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/libsaio/cpuid.h; + sourceTree = ""; + }; + 1221F71113291A0A0014A9B5 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12EA3B46131B91D4008D7D68 /* drivers.c */; + name = "drivers.c: 44"; + rLen = 6; + rLoc = 1443; + rType = 0; + vrLen = 840; + vrLoc = 1094; + }; + 1221F71213291A0A0014A9B5 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 1221F71313291A0A0014A9B5 /* ati5.h */; + name = "ati5.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 833; + vrLoc = 461; + }; + 1221F71313291A0A0014A9B5 /* ati5.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = ati5.h; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/modules/ATI5000Enabler/ati5.h; + sourceTree = ""; + }; + 1221F71413291A0A0014A9B5 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12D331EE12C63CB30093EEDB /* ati5.c */; + name = "ati5.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 679; + vrLoc = 0; + }; + 1221F71513291A0A0014A9B5 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 1267A85612F576AA00751FC6 /* ATIEnabler.c */; + name = "ATIEnabler.c: 22"; + rLen = 5; + rLoc = 428; + rType = 0; + vrLen = 738; + vrLoc = 0; + }; + 1221F71613291A0A0014A9B5 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 1221F71713291A0A0014A9B5 /* appleboot.h */; + name = "appleboot.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1296; + vrLoc = 0; + }; + 1221F71713291A0A0014A9B5 /* appleboot.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = appleboot.h; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/modules/GUI/appleboot.h; + sourceTree = ""; + }; + 1221F71813291A0A0014A9B5 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 1221F71913291A0A0014A9B5 /* graphic_utils.c */; + name = "graphic_utils.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 764; + vrLoc = 0; + }; + 1221F71913291A0A0014A9B5 /* graphic_utils.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = graphic_utils.c; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/modules/GUI/graphic_utils.c; + sourceTree = ""; + }; + 1221F71A13291A0A0014A9B5 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 1221F71B13291A0A0014A9B5 /* graphic_utils.h */; + name = "graphic_utils.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 559; + vrLoc = 0; + }; + 1221F71B13291A0A0014A9B5 /* graphic_utils.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = graphic_utils.h; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/modules/GUI/graphic_utils.h; + sourceTree = ""; + }; + 1221F71D13291A0A0014A9B5 /* gui.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = gui.c; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/modules/GUI/gui.c; + sourceTree = ""; + }; + 122A869812EC5429004312F4 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 122A869912EC5429004312F4 /* disk.h */; + name = "disk.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 294; + vrLoc = 0; + }; + 122A869912EC5429004312F4 /* disk.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = disk.h; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/libsaio/disk.h; + sourceTree = ""; + }; + 122A869C12EC5429004312F4 /* disk.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = disk.c; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/libsaio/disk.c; + sourceTree = ""; + }; + 122A86C612ECA817004312F4 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 122A869C12EC5429004312F4 /* disk.c */; + name = "disk.c: 874"; + rLen = 10; + rLoc = 25878; + rType = 0; + vrLen = 528; + vrLoc = 4718; + }; + 122C56E012F2CB51005FE786 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 121B17F412F2C5DF00259614 /* platform.h */; + name = "platform.h: 89"; + rLen = 0; + rLoc = 2826; + rType = 0; + vrLen = 902; + vrLoc = 2408; + }; + 122C56E412F2CB51005FE786 /* Memory.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = Memory.c; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/modules/Memory/Memory.c; + sourceTree = ""; + }; + 122DBE3512F47E30003C7482 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 125332B012F4563000937C5D /* usb.c */; + name = "usb.c: 379"; + rLen = 0; + rLoc = 10512; + rType = 0; + vrLen = 860; + vrLoc = 9952; + }; + 122DBE3A12F47E30003C7482 /* stringTable.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = stringTable.c; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/libsaio/stringTable.c; + sourceTree = ""; + }; + 12306DB512F4A734000AAE98 /* Symbols.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = Symbols.h; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/sym/i386/Symbols.h; + sourceTree = ""; + }; + 12306DBE12F4AAEE000AAE98 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12306DB512F4A734000AAE98 /* Symbols.h */; + name = "Symbols.h: 698"; + rLen = 8; + rLoc = 38634; + rType = 0; + vrLen = 1295; + vrLoc = 37954; + }; + 1230722412F4BC2E000AAE98 /* bootstruct.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = bootstruct.c; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/libsaio/bootstruct.c; + sourceTree = ""; + }; + 124C492812B8C915005AA276 /* Memory.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = Memory.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/Memory/Memory.c; + sourceTree = ""; + }; + 124C492E12B8D82D005AA276 /* gui.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = gui.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/GUI/gui.c; + sourceTree = ""; + }; + 124C493212B8D846005AA276 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12CC44D112B398A2007E0C76 /* platform.c */; + name = "platform.c: 39"; + rLen = 12; + rLoc = 668; + rType = 0; + vrLen = 718; + vrLoc = 323; + }; + 124C493412B8D846005AA276 /* HelloWorld.cpp */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.cpp.cpp; + name = HelloWorld.cpp; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/HelloWorld/HelloWorld.cpp; + sourceTree = ""; + }; + 124C493712B8D846005AA276 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 124C492E12B8D82D005AA276 /* gui.c */; + name = "gui.c: 716"; + rLen = 17; + rLoc = 21684; + rType = 0; + vrLen = 890; + vrLoc = 21338; + }; + 124C494012B8E8BC005AA276 /* GUI_module.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = GUI_module.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/GUI/GUI_module.c; + sourceTree = ""; + }; + 124C494212B8E8C2005AA276 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 124C492812B8C915005AA276 /* Memory.c */; + name = "Memory.c: 44"; + rLen = 8; + rLoc = 900; + rType = 0; + vrLen = 764; + vrLoc = 680; + }; + 124C494312B8E8C2005AA276 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 124C494412B8E8C2005AA276 /* hpet.h */; + name = "hpet.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 306; + vrLoc = 0; + }; + 124C494412B8E8C2005AA276 /* hpet.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = hpet.h; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/HPET/hpet.h; + sourceTree = ""; + }; + 124C494512B8E8C2005AA276 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 124C494612B8E8C2005AA276 /* HPET.c */; + name = "HPET.c: 27"; + rLen = 377; + rLoc = 410; + rType = 0; + vrLen = 554; + vrLoc = 237; + }; + 124C494612B8E8C2005AA276 /* HPET.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = HPET.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/HPET/HPET.c; + sourceTree = ""; + }; + 124C494B12B8EA5D005AA276 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 124C494012B8E8BC005AA276 /* GUI_module.c */; + name = "GUI_module.c: 240"; + rLen = 17; + rLoc = 5650; + rType = 0; + vrLen = 554; + vrLoc = 5486; + }; + 125332B012F4563000937C5D /* usb.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = usb.c; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/modules/USBFix/usb.c; + sourceTree = ""; + }; + 125437C812EF1E99007175C8 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 125437C912EF1E99007175C8 /* HPET.c */; + name = "HPET.c: 43"; + rLen = 11; + rLoc = 759; + rType = 0; + vrLen = 611; + vrLoc = 286; + }; + 125437C912EF1E99007175C8 /* HPET.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = HPET.c; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/modules/HPET/HPET.c; + sourceTree = ""; + }; + 125437CB12EF1E99007175C8 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 125437CC12EF1E99007175C8 /* modules.h */; + name = "modules.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1151; + vrLoc = 1550; + }; + 125437CC12EF1E99007175C8 /* modules.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = modules.h; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/boot2/modules.h; + sourceTree = ""; + }; + 12569C8612F0115B005A9113 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 120F5CDE12F0087200C64A78 /* CHANGES */; + name = "CHANGES: 9"; + rLen = 13; + rLoc = 339; + rType = 0; + vrLen = 1670; + vrLoc = 0; + }; + 125916AD12F8445300001F4A /* ext2fs.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = ext2fs.c; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/libsaio/ext2fs.c; + sourceTree = ""; + }; + 125A6C2512F53BCD00535D65 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 1230722412F4BC2E000AAE98 /* bootstruct.c */; + name = "bootstruct.c: 38"; + rLen = 29; + rLoc = 1346; + rType = 0; + vrLen = 750; + vrLoc = 1047; + }; + 1267813012B7B13E00A25CED /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12B46E6D12B75631006C2B9C /* smbios_patcher.h */; + name = "smbios_patcher.h: 16"; + rLen = 8; + rLoc = 250; + rType = 0; + vrLen = 637; + vrLoc = 0; + }; + 12679BA312BE822E00E3637F /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12BB721912BE659500B11948 /* nvidia.c */; + name = "nvidia.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 894; + vrLoc = 14871; + }; + 1267A85112F574E500751FC6 /* modules.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = modules.c; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/boot2/modules.c; + sourceTree = ""; + }; + 1267A85612F576AA00751FC6 /* ATIEnabler.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = ATIEnabler.c; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/modules/ATI5000Enabler/ATIEnabler.c; + sourceTree = ""; + }; + 1267A85C12F5771100751FC6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 1267A85112F574E500751FC6 /* modules.c */; + name = "modules.c: 80"; + rLen = 15; + rLoc = 1931; + rType = 0; + vrLen = 804; + vrLoc = 1636; + }; + 1267A85F12F5771100751FC6 /* GUI_module.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = GUI_module.c; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/modules/GUI/GUI_module.c; + sourceTree = ""; + }; + 126A6402137BCAAC003C4F2E /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 126A6403137BCAAC003C4F2E /* fake_efi.c */; + rLen = 18; + rLoc = 9784; + rType = 0; + }; + 126A6403137BCAAC003C4F2E /* fake_efi.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = fake_efi.c; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/libsaio/fake_efi.c; + sourceTree = ""; + }; + 126A6408137BCAAE003C4F2E /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 121DBAAB1371953B00C733E2 /* boot2.s */; + name = "boot2.s: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1077; + vrLoc = 12996; + }; + 126A6409137BCAAE003C4F2E /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 126A640A137BCAAE003C4F2E /* fake_efi.c */; + name = "fake_efi.c: 244"; + rLen = 18; + rLoc = 9784; + rType = 0; + vrLen = 1740; + vrLoc = 9142; + }; + 126A640A137BCAAE003C4F2E /* fake_efi.c */ = { + isa = PBXFileReference; + name = fake_efi.c; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/libsaio/fake_efi.c; + sourceTree = ""; + }; + 126C766312EEF67F00BDB81E /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 121217CC12EEF2550055AF66 /* options.c */; + name = "options.c: 1003"; + rLen = 8; + rLoc = 24793; + rType = 0; + vrLen = 1190; + vrLoc = 24206; + }; + 126D84C612F7FA6E000AB776 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12DFBFDE12F7066500E2DA49 /* boot0.s */; + name = "boot0.s: 784"; + rLen = 0; + rLoc = 22464; + rType = 0; + vrLen = 761; + vrLoc = 22651; + }; + 1271587B12EA1C6400E3013B /* ntfs.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = ntfs.c; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/libsaio/ntfs.c; + sourceTree = ""; + }; + 12715CDF12EA253100E3013B /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 1271587B12EA1C6400E3013B /* ntfs.c */; + name = "ntfs.c: 70"; + rLen = 10; + rLoc = 2053; + rType = 0; + vrLen = 835; + vrLoc = 1675; + }; + 12715CE012EA253100E3013B /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 121E9E4112C6A6F9000B6ED3 /* gma.c */; + name = "gma.c: 130"; + rLen = 9; + rLoc = 4027; + rType = 0; + vrLen = 1331; + vrLoc = 3531; + }; + 128439CE1365B655003A4A52 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 120FE78D1345F8FC00CC4AA2 /* spd.h */; + name = "spd.h: 13"; + rLen = 5; + rLoc = 196; + rType = 0; + vrLen = 779; + vrLoc = 0; + }; + 128439D21365B655003A4A52 /* saio_internal.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = saio_internal.h; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/libsaio/saio_internal.h; + sourceTree = ""; + }; + 1288318212C3608100EA4CB2 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 128A9AF812C233CE00600556 /* Makefile */; + name = "Makefile: 14"; + rLen = 6; + rLoc = 217; + rType = 0; + vrLen = 858; + vrLoc = 0; + }; + 128A97BC12C2336000600556 /* USBFix.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = USBFix.c; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/modules/USBFix/USBFix.c; + sourceTree = ""; + }; + 128A9AF412C233CE00600556 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 128A97BC12C2336000600556 /* USBFix.c */; + name = "USBFix.c: 31"; + rLen = 14; + rLoc = 559; + rType = 0; + vrLen = 454; + vrLoc = 145; + }; + 128A9AF812C233CE00600556 /* Makefile */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.make; + name = Makefile; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/modules/HPET/Makefile; + sourceTree = ""; + }; + 1299A51F12B3C328007ED516 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12CC4AEF12B39FC7007E0C76 /* zutil.h */; + name = "zutil.h: 266"; + rLen = 6; + rLoc = 6791; + rType = 0; + vrLen = 374; + vrLoc = 6561; + }; + 1299A55612B3C4DF007ED516 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 1299A55712B3C4DF007ED516 /* console.c */; + name = "console.c: 185"; + rLen = 35; + rLoc = 3729; + rType = 0; + vrLen = 353; + vrLoc = 3516; + }; + 1299A55712B3C4DF007ED516 /* console.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = console.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/libsaio/console.c; + sourceTree = ""; + }; + 1299A55A12B3C4DF007ED516 /* Symbols.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = Symbols.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/boot2/Symbols.c; + sourceTree = ""; + }; + 129F6EF012B50BB6005A820E /* modules.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = modules.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/boot2/modules.c; + sourceTree = ""; + }; + 12A7377212C854A600769789 /* vbe.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = vbe.c; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/libsaio/vbe.c; + sourceTree = ""; + }; + 12AB04BD12B663F5005A745F /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12B903AB12B2A00E00FE287A /* platform.h */; + name = "platform.h: 169"; + rLen = 25; + rLoc = 5455; + rType = 0; + vrLen = 924; + vrLoc = 4593; + }; + 12AB04BF12B663F5005A745F /* boot.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = boot.h; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/boot2/boot.h; + sourceTree = ""; + }; + 12AB04D712B66471005A745F /* pci.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = pci.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/libsaio/pci.c; + sourceTree = ""; + }; + 12AB04EC12B665EA005A745F /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12AB04D712B66471005A745F /* pci.c */; + name = "pci.c: 150"; + rLen = 11; + rLoc = 3133; + rType = 0; + vrLen = 400; + vrLoc = 3028; + }; + 12AF764312BA614B003BBFD3 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12EFD98D12B510D9002A1712 /* revision */; + name = "revision: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 3; + vrLoc = 0; + }; + 12B46E5E12B75493006C2B9C /* cpu.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = cpu.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/libsaio/cpu.c; + sourceTree = ""; + }; + 12B46E6612B75631006C2B9C /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12BB443912B6694900C7B484 /* spd.c */; + name = "spd.c: 272"; + rLen = 13; + rLoc = 7917; + rType = 0; + vrLen = 742; + vrLoc = 7543; + }; + 12B46E6812B75631006C2B9C /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12AB04BF12B663F5005A745F /* boot.h */; + name = "boot.h: 44"; + rLen = 0; + rLoc = 1396; + rType = 0; + vrLen = 422; + vrLoc = 7282; + }; + 12B46E6912B75631006C2B9C /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12B9FA5512B29AFC00FE287A /* cpu.h */; + name = "cpu.h: 32"; + rLen = 12; + rLoc = 762; + rType = 0; + vrLen = 782; + vrLoc = 517; + }; + 12B46E6A12B75631006C2B9C /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12B46E5E12B75493006C2B9C /* cpu.c */; + name = "cpu.c: 184"; + rLen = 0; + rLoc = 6055; + rType = 0; + vrLen = 685; + vrLoc = 5865; + }; + 12B46E6D12B75631006C2B9C /* smbios_patcher.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = smbios_patcher.h; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/libsaio/smbios_patcher.h; + sourceTree = ""; + }; + 12B903AB12B2A00E00FE287A /* platform.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = platform.h; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/libsaio/platform.h; + sourceTree = ""; + }; + 12B90A0312B2A7A700FE287A /* acpi_patcher.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = acpi_patcher.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/ACPIPatcher/acpi_patcher.c; + sourceTree = ""; + }; + 12B90A2012B2A7E200FE287A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12B90A0312B2A7A700FE287A /* acpi_patcher.c */; + name = "acpi_patcher.c: 115"; + rLen = 22; + rLoc = 2845; + rType = 0; + vrLen = 611; + vrLoc = 2564; + }; + 12B90A2212B2A7E200FE287A /* mem.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = mem.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/Memory/mem.c; + sourceTree = ""; + }; + 12B90A2B12B2A86B00FE287A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12B90A2212B2A7E200FE287A /* mem.c */; + name = "mem.c: 142"; + rLen = 0; + rLoc = 4591; + rType = 0; + vrLen = 688; + vrLoc = 3903; + }; + 12B90A4D12B2AE1300FE287A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12B90A4E12B2AE1300FE287A /* Resolution.c */; + name = "Resolution.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 167; + vrLoc = 0; + }; + 12B90A4E12B2AE1300FE287A /* Resolution.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = Resolution.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/Resolution/Resolution.c; + sourceTree = ""; + }; + 12B90A4F12B2AE1300FE287A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12B90A5012B2AE1300FE287A /* 915resolution.c */; + name = "915resolution.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 363; + vrLoc = 20239; + }; + 12B90A5012B2AE1300FE287A /* 915resolution.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = 915resolution.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/Resolution/915resolution.c; + sourceTree = ""; + }; + 12B90A5212B2AE1300FE287A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12B90A5312B2AE1300FE287A /* edid.h */; + name = "edid.h: 15"; + rLen = 13; + rLoc = 205; + rType = 0; + vrLen = 253; + vrLoc = 0; + }; + 12B90A5312B2AE1300FE287A /* edid.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = edid.h; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/Resolution/edid.h; + sourceTree = ""; + }; + 12B90A5712B2AE1300FE287A /* 915resolution.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = 915resolution.h; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/Resolution/915resolution.h; + sourceTree = ""; + }; + 12B9F40D12B2987800FE287A /* SMBIOS.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = SMBIOS.h; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/libsaio/SMBIOS.h; + sourceTree = ""; + }; + 12B9F42612B29A4A00FE287A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12B9F40D12B2987800FE287A /* SMBIOS.h */; + name = "SMBIOS.h: 140"; + rLen = 20; + rLoc = 5015; + rType = 0; + vrLen = 922; + vrLoc = 4588; + }; + 12B9FA5512B29AFC00FE287A /* cpu.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = cpu.h; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/libsaio/cpu.h; + sourceTree = ""; + }; + 12BB443912B6694900C7B484 /* spd.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = spd.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/Memory/spd.c; + sourceTree = ""; + }; + 12BB721912BE659500B11948 /* nvidia.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = nvidia.c; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/modules/GraphicsEnabler/nvidia.c; + sourceTree = ""; + }; + 12BD8A5312D8EEE10051EE43 /* sys.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = sys.c; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/libsaio/sys.c; + sourceTree = ""; + }; + 12BF14DA12B3CF8E00D798FE /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 1299A55A12B3C4DF007ED516 /* Symbols.c */; + name = "Symbols.c: 20"; + rLen = 0; + rLoc = 640; + rType = 0; + vrLen = 665; + vrLoc = 3; + }; + 12C246F412C87C7C007E8339 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12A7377212C854A600769789 /* vbe.c */; + name = "vbe.c: 245"; + rLen = 7; + rLoc = 7689; + rType = 0; + vrLen = 735; + vrLoc = 7282; + }; + 12C26D2E12B0DDF400AF7F4B /* ChamMek */ = { + isa = PBXExecutable; + activeArgIndices = ( + ); + argumentStrings = ( + ); + autoAttachOnCrash = 1; + breakpointsEnabled = 0; + configStateDict = { + }; + customDataFormattersEnabled = 1; + dataTipCustomDataFormattersEnabled = 1; + dataTipShowTypeColumn = 1; + dataTipSortType = 0; + debuggerPlugin = GDBDebugging; + disassemblyDisplayState = 0; + enableDebugStr = 1; + environmentEntries = ( + ); + executableSystemSymbolLevel = 0; + executableUserSymbolLevel = 0; + libgmallocEnabled = 0; + name = ChamMek; + showTypeColumn = 0; + sourceDirectories = ( + ); + }; + 12C26D3712B0DDFC00AF7F4B /* Source Control */ = { + isa = PBXSourceControlManager; + fallbackIsa = XCSourceControlManager; + isSCMEnabled = 0; + scmConfiguration = { + repositoryNamesForRoots = { + "" = chameleon; + }; + }; + }; + 12C26D3812B0DDFC00AF7F4B /* Code sense */ = { + isa = PBXCodeSenseManager; + indexTemplatePath = ""; + }; + 12C5020712D8B82400EDCC4E /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12D52EA712D7377E00A23AEF /* resume.c */; + name = "resume.c: 114"; + rLen = 15; + rLoc = 2532; + rType = 0; + vrLen = 698; + vrLoc = 2183; + }; + 12C7009812B7BCE7006BD382 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12C7FC5C12B7BCD6006BD382 /* basic_definitions */; + name = "basic_definitions: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1088; + vrLoc = 0; + }; + 12C7009912B7BCE7006BD382 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12C7009A12B7BCE7006BD382 /* __udivmoddi4.c */; + name = "__udivmoddi4.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 444; + vrLoc = 0; + }; + 12C7009A12B7BCE7006BD382 /* __udivmoddi4.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = __udivmoddi4.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/klibc/__udivmoddi4.c; + sourceTree = ""; + }; + 12C7009D12B7BCE7006BD382 /* __moddi3.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = __moddi3.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/klibc/__moddi3.c; + sourceTree = ""; + }; + 12C704E512B7BD3E006BD382 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12C7009D12B7BCE7006BD382 /* __moddi3.c */; + name = "__moddi3.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 395; + vrLoc = 0; + }; + 12C7FC3E12B7BCBA006BD382 /* theme.plist */ = { + isa = PBXFileReference; + lastKnownFileType = text.plist.xml; + name = theme.plist; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/artwork/themes/legacy/theme.plist; + sourceTree = ""; + }; + 12C7FC4D12B7BCD3006BD382 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 121EA43012B7B9DD002449B3 /* smbios_patcher.c */; + name = "smbios_patcher.c: 802"; + rLen = 5; + rLoc = 27589; + rType = 0; + vrLen = 1182; + vrLoc = 27099; + }; + 12C7FC4E12B7BCD3006BD382 /* PlistBookmark */ = { + isa = PlistBookmark; + fRef = 12C7FC3E12B7BCBA006BD382 /* theme.plist */; + fallbackIsa = PBXBookmark; + isK = 0; + kPath = ( + screen_width, + ); + name = /Users/slice/Projects/fakesmc/Chameleon/RC5m/artwork/themes/legacy/theme.plist; + rLen = 0; + rLoc = 9223372036854775808; + }; + 12C7FC5C12B7BCD6006BD382 /* basic_definitions */ = { + isa = PBXFileReference; + lastKnownFileType = text; + name = basic_definitions; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/include/basic_definitions; + sourceTree = ""; + }; + 12C8CB6812B5529D003DA1E4 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12EFE96012B549B6002A1712 /* pci_root.c */; + name = "pci_root.c: 53"; + rLen = 22; + rLoc = 1024; + rType = 0; + vrLen = 657; + vrLoc = 731; + }; + 12CC44C812B3947B007E0C76 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12E17AEA12B2BA9B00607D8E /* saio_types.h */; + name = "saio_types.h: 261"; + rLen = 0; + rLoc = 8455; + rType = 0; + vrLen = 409; + vrLoc = 8182; + }; + 12CC44D112B398A2007E0C76 /* platform.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = platform.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/libsaio/platform.c; + sourceTree = ""; + }; + 12CC4AEF12B39FC7007E0C76 /* zutil.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = zutil.h; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/KextPatcher/zutil.h; + sourceTree = ""; + }; + 12CF89A712B6410100B7BC73 /* pci_setup.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = pci_setup.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/libsaio/pci_setup.c; + sourceTree = ""; + }; + 12D3316C12C61CA80093EEDB /* bootstruct.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = bootstruct.h; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/libsaio/bootstruct.h; + sourceTree = ""; + }; + 12D331A312C61E950093EEDB /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12D3316C12C61CA80093EEDB /* bootstruct.h */; + name = "bootstruct.h: 43"; + rLen = 0; + rLoc = 1435; + rType = 0; + vrLen = 633; + vrLoc = 1150; + }; + 12D331EE12C63CB30093EEDB /* ati5.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = ati5.c; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/modules/ATI5000Enabler/ati5.c; + sourceTree = ""; + }; + 12D3321A12C63DF20093EEDB /* pci.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = pci.h; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/libsaio/pci.h; + sourceTree = ""; + }; + 12D3324112C63EB70093EEDB /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12D3321A12C63DF20093EEDB /* pci.h */; + name = "pci.h: 107"; + rLen = 0; + rLoc = 2409; + rType = 0; + vrLen = 1242; + vrLoc = 3316; + }; + 12D3329E12C669090093EEDB /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12D3329F12C669090093EEDB /* lazydylib1.c */; + name = "lazydylib1.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 216; + vrLoc = 0; + }; + 12D3329F12C669090093EEDB /* lazydylib1.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = lazydylib1.c; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/modules/lazydylib1.c; + sourceTree = ""; + }; + 12D332A512C669090093EEDB /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12D332A612C669090093EEDB /* graphics.h */; + name = "graphics.h: 20"; + rLen = 0; + rLoc = 352; + rType = 0; + vrLen = 962; + vrLoc = 122; + }; + 12D332A612C669090093EEDB /* graphics.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = graphics.h; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/boot2/graphics.h; + sourceTree = ""; + }; + 12D332AA12C669090093EEDB /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12D332AB12C669090093EEDB /* gma.h */; + name = "gma.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 352; + vrLoc = 0; + }; + 12D332AB12C669090093EEDB /* gma.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = gma.h; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/modules/GraphicsEnabler/gma.h; + sourceTree = ""; + }; + 12D52EA712D7377E00A23AEF /* resume.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = resume.c; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/boot2/resume.c; + sourceTree = ""; + }; + 12D6232512BA5F380032F367 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12078D9812BA5AF400A1C013 /* fake_efi.c */; + name = "fake_efi.c: 523"; + rLen = 6; + rLoc = 21723; + rType = 0; + vrLen = 665; + vrLoc = 21278; + }; + 12D6232612BA5F380032F367 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 124C493412B8D846005AA276 /* HelloWorld.cpp */; + name = "HelloWorld.cpp: 39"; + rLen = 10; + rLoc = 652; + rType = 0; + vrLen = 419; + vrLoc = 398; + }; + 12D928BE12C7C8EB00269820 /* Makefile */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.make; + name = Makefile; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/modules/ATI5000Enabler/Makefile; + sourceTree = ""; + }; + 12DA422F12C52DAC009281B3 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12DA423012C52DAC009281B3 /* libsaio.h */; + name = "libsaio.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 801; + vrLoc = 468; + }; + 12DA423012C52DAC009281B3 /* libsaio.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = libsaio.h; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/libsaio/libsaio.h; + sourceTree = ""; + }; + 12DA42EA12C54134009281B3 /* edid.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = edid.c; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/modules/Resolution/edid.c; + sourceTree = ""; + }; + 12DCD38E12BBA5D600A20635 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12F7FF0412BB9F3200949DEC /* ntfs_private.h */; + name = "ntfs_private.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1189; + vrLoc = 0; + }; + 12DFBB1C12F6E9A500E2DA49 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 08FB7796FE84155DC02AAC07 /* main.c */; + name = "main.c: 10"; + rLen = 7; + rLoc = 192; + rType = 0; + vrLen = 235; + vrLoc = 0; + }; + 12DFBB1D12F6E9A500E2DA49 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12DFBB1E12F6E9A500E2DA49 /* acpi.h */; + name = "acpi.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 634; + vrLoc = 0; + }; + 12DFBB1E12F6E9A500E2DA49 /* acpi.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = acpi.h; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/libsaio/acpi.h; + sourceTree = ""; + }; + 12DFBB1F12F6E9A500E2DA49 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12DFBB2012F6E9A500E2DA49 /* kext_patcher.c */; + name = "kext_patcher.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 831; + vrLoc = 4232; + }; + 12DFBB2012F6E9A500E2DA49 /* kext_patcher.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = kext_patcher.c; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/modules/KextPatcher/kext_patcher.c; + sourceTree = ""; + }; + 12DFBB2112F6E9A500E2DA49 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12DFBB2212F6E9A500E2DA49 /* boot.h */; + name = "boot.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 617; + vrLoc = 7802; + }; + 12DFBB2212F6E9A500E2DA49 /* boot.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = boot.h; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/boot2/boot.h; + sourceTree = ""; + }; + 12DFBFD412F7016200E2DA49 /* boot.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = boot.c; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/boot2/boot.c; + sourceTree = ""; + }; + 12DFBFDA12F7066500E2DA49 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12DFBFD412F7016200E2DA49 /* boot.c */; + name = "boot.c: 327"; + rLen = 9; + rLoc = 9603; + rType = 0; + vrLen = 772; + vrLoc = 9218; + }; + 12DFBFDE12F7066500E2DA49 /* boot0.s */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.asm; + name = boot0.s; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/boot0/boot0.s; + sourceTree = ""; + }; + 12E17AE612B2BA9B00607D8E /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12B90A5712B2AE1300FE287A /* 915resolution.h */; + name = "915resolution.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 294; + vrLoc = 0; + }; + 12E17AEA12B2BA9B00607D8E /* saio_types.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = saio_types.h; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/libsaio/saio_types.h; + sourceTree = ""; + }; + 12E6FB4712BB438700C2A021 /* Makefile */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.make; + name = Makefile; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/boot2/Makefile; + sourceTree = ""; + }; + 12E6FB5712BB458400C2A021 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12E6FB4712BB438700C2A021 /* Makefile */; + name = "Makefile: 117"; + rLen = 8; + rLoc = 4153; + rType = 0; + vrLen = 857; + vrLoc = 3681; + }; + 12E6FB5B12BB458400C2A021 /* load.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = load.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/libsaio/load.c; + sourceTree = ""; + }; + 12E8842612D8F833004C76C8 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12BD8A5312D8EEE10051EE43 /* sys.c */; + name = "sys.c: 822"; + rLen = 14; + rLoc = 21356; + rType = 0; + vrLen = 763; + vrLoc = 20973; + }; + 12EA3B42131B91D4008D7D68 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 125916AD12F8445300001F4A /* ext2fs.c */; + name = "ext2fs.c: 2"; + rLen = 4; + rLoc = 7; + rType = 0; + vrLen = 598; + vrLoc = 0; + }; + 12EA3B46131B91D4008D7D68 /* drivers.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = drivers.c; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/boot2/drivers.c; + sourceTree = ""; + }; + 12EFD98A12B510D9002A1712 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 129F6EF012B50BB6005A820E /* modules.c */; + name = "modules.c: 927"; + rLen = 14; + rLoc = 22234; + rType = 0; + vrLen = 676; + vrLoc = 21912; + }; + 12EFD98D12B510D9002A1712 /* revision */ = { + isa = PBXFileReference; + lastKnownFileType = text; + name = revision; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/revision; + sourceTree = ""; + }; + 12EFDFC612B51958002A1712 /* nvidia.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = nvidia.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/GraphicsEnabler/nvidia.c; + sourceTree = ""; + }; + 12EFE2FD12B51ED5002A1712 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12EFDFC612B51958002A1712 /* nvidia.c */; + name = "nvidia.c: 712"; + rLen = 38; + rLoc = 23132; + rType = 0; + vrLen = 544; + vrLoc = 22879; + }; + 12EFE30112B51ED5002A1712 /* spd.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = spd.h; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/Memory/spd.h; + sourceTree = ""; + }; + 12EFE65A12B547A7002A1712 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12EFE30112B51ED5002A1712 /* spd.h */; + name = "spd.h: 16"; + rLen = 17; + rLoc = 306; + rType = 0; + vrLen = 533; + vrLoc = 0; + }; + 12EFE94412B548B5002A1712 /* ACPIPatcher.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = ACPIPatcher.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/ACPIPatcher/ACPIPatcher.c; + sourceTree = ""; + }; + 12EFE95E12B549B6002A1712 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12EFE94412B548B5002A1712 /* ACPIPatcher.c */; + name = "ACPIPatcher.c: 37"; + rLen = 22; + rLoc = 940; + rType = 0; + vrLen = 742; + vrLoc = 534; + }; + 12EFE96012B549B6002A1712 /* pci_root.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = pci_root.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/libsaio/pci_root.c; + sourceTree = ""; + }; + 12F7FF0012BB9F3200949DEC /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12FC25E812BB825300E9CFA8 /* drivers.c */; + name = "drivers.c: 77"; + rLen = 13; + rLoc = 2379; + rType = 0; + vrLen = 570; + vrLoc = 2251; + }; + 12F7FF0412BB9F3200949DEC /* ntfs_private.h */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = ntfs_private.h; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/libsaio/ntfs_private.h; + sourceTree = ""; + }; + 12FC0E7512BB4B5200E9CFA8 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12E6FB5B12BB458400C2A021 /* load.c */; + name = "load.c: 42"; + rLen = 4; + rLoc = 1522; + rType = 0; + vrLen = 697; + vrLoc = 1159; + }; + 12FC0E7812BB4B5200E9CFA8 /* NVRAM.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = NVRAM.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/modules/NVRAM/NVRAM.c; + sourceTree = ""; + }; + 12FC0E9412BB65A800E9CFA8 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12FC0E7812BB4B5200E9CFA8 /* NVRAM.c */; + name = "NVRAM.c: 150"; + rLen = 0; + rLoc = 4870; + rType = 0; + vrLen = 362; + vrLoc = 4873; + }; + 12FC25E812BB825300E9CFA8 /* drivers.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = drivers.c; + path = /Users/slice/Projects/fakesmc/Chameleon/RC5m/i386/boot2/drivers.c; + sourceTree = ""; + }; + 12FE983612C7CEEB001B1702 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12D928BE12C7C8EB00269820 /* Makefile */; + name = "Makefile: 1"; + rLen = 7; + rLoc = 14; + rType = 0; + vrLen = 736; + vrLoc = 0; + }; + 12FE984A12C7E11C001B1702 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12FE984B12C7E11C001B1702 /* Resolution.c */; + name = "Resolution.c: 13"; + rLen = 14; + rLoc = 247; + rType = 0; + vrLen = 236; + vrLoc = 0; + }; + 12FE984B12C7E11C001B1702 /* Resolution.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = Resolution.c; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/modules/Resolution/Resolution.c; + sourceTree = ""; + }; + 12FE985E12C7E1F7001B1702 /* 915resolution.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = 915resolution.c; + path = /Users/slice/Projects/Chameleons/chameleon/branches/slice/i386/modules/Resolution/915resolution.c; + sourceTree = ""; + }; + 12FE987912C7E281001B1702 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12FE985E12C7E1F7001B1702 /* 915resolution.c */; + name = "915resolution.c: 419"; + rLen = 0; + rLoc = 8936; + rType = 0; + vrLen = 670; + vrLoc = 2670; + }; + 12FE987A12C7E281001B1702 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 12DA42EA12C54134009281B3 /* edid.c */; + name = "edid.c: 190"; + rLen = 13; + rLoc = 4618; + rType = 0; + vrLen = 987; + vrLoc = 4129; + }; + 8DD76FA90486AB0100D96B5E /* ChamMek */ = { + activeExec = 0; + executables = ( + 12C26D2E12B0DDF400AF7F4B /* ChamMek */, + ); + }; +} Index: branches/slice/rev749/ChamMek/ChamMek.xcodeproj/project.pbxproj =================================================================== --- branches/slice/rev749/ChamMek/ChamMek.xcodeproj/project.pbxproj (revision 0) +++ branches/slice/rev749/ChamMek/ChamMek.xcodeproj/project.pbxproj (revision 1169) @@ -0,0 +1,212 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 45; + objects = { + +/* Begin PBXBuildFile section */ + 8DD76FAC0486AB0100D96B5E /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 08FB7796FE84155DC02AAC07 /* main.c */; settings = {ATTRIBUTES = (); }; }; + 8DD76FB00486AB0100D96B5E /* ChamMek.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = C6A0FF2C0290799A04C91782 /* ChamMek.1 */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 8DD76FAF0486AB0100D96B5E /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + 8DD76FB00486AB0100D96B5E /* ChamMek.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 08FB7796FE84155DC02AAC07 /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; + 12C26D3912B0DE0A00AF7F4B /* slice */ = {isa = PBXFileReference; lastKnownFileType = folder; name = slice; path = ..; sourceTree = SOURCE_ROOT; }; + 8DD76FB20486AB0100D96B5E /* ChamMek */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ChamMek; sourceTree = BUILT_PRODUCTS_DIR; }; + C6A0FF2C0290799A04C91782 /* ChamMek.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = ChamMek.1; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8DD76FAD0486AB0100D96B5E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 08FB7794FE84155DC02AAC07 /* ChamMek */ = { + isa = PBXGroup; + children = ( + 08FB7795FE84155DC02AAC07 /* Source */, + C6A0FF2B0290797F04C91782 /* Documentation */, + 1AB674ADFE9D54B511CA2CBB /* Products */, + ); + name = ChamMek; + sourceTree = ""; + }; + 08FB7795FE84155DC02AAC07 /* Source */ = { + isa = PBXGroup; + children = ( + 12C26D3912B0DE0A00AF7F4B /* slice */, + 08FB7796FE84155DC02AAC07 /* main.c */, + ); + name = Source; + sourceTree = ""; + }; + 1AB674ADFE9D54B511CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 8DD76FB20486AB0100D96B5E /* ChamMek */, + ); + name = Products; + sourceTree = ""; + }; + C6A0FF2B0290797F04C91782 /* Documentation */ = { + isa = PBXGroup; + children = ( + C6A0FF2C0290799A04C91782 /* ChamMek.1 */, + ); + name = Documentation; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8DD76FA90486AB0100D96B5E /* ChamMek */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1DEB928508733DD80010E9CD /* Build configuration list for PBXNativeTarget "ChamMek" */; + buildPhases = ( + 8DD76FAB0486AB0100D96B5E /* Sources */, + 8DD76FAD0486AB0100D96B5E /* Frameworks */, + 8DD76FAF0486AB0100D96B5E /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ChamMek; + productInstallPath = "$(HOME)/bin"; + productName = ChamMek; + productReference = 8DD76FB20486AB0100D96B5E /* ChamMek */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 08FB7793FE84155DC02AAC07 /* Project object */ = { + isa = PBXProject; + buildConfigurationList = 1DEB928908733DD80010E9CD /* Build configuration list for PBXProject "ChamMek" */; + compatibilityVersion = "Xcode 3.1"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + ); + mainGroup = 08FB7794FE84155DC02AAC07 /* ChamMek */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8DD76FA90486AB0100D96B5E /* ChamMek */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 8DD76FAB0486AB0100D96B5E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8DD76FAC0486AB0100D96B5E /* main.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 1DEB928608733DD80010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + INSTALL_PATH = /usr/local/bin; + PRODUCT_NAME = ChamMek; + }; + name = Debug; + }; + 1DEB928708733DD80010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = /usr/local/bin; + PRODUCT_NAME = ChamMek; + }; + name = Release; + }; + 1DEB928A08733DD80010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + ONLY_ACTIVE_ARCH = YES; + PREBINDING = NO; + SDKROOT = macosx10.6; + }; + name = Debug; + }; + 1DEB928B08733DD80010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PREBINDING = NO; + SDKROOT = macosx10.6; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1DEB928508733DD80010E9CD /* Build configuration list for PBXNativeTarget "ChamMek" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB928608733DD80010E9CD /* Debug */, + 1DEB928708733DD80010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1DEB928908733DD80010E9CD /* Build configuration list for PBXProject "ChamMek" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB928A08733DD80010E9CD /* Debug */, + 1DEB928B08733DD80010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; +} Index: branches/slice/rev749/ChamMek/ChamMek.xcodeproj/slice.mode1v3 =================================================================== --- branches/slice/rev749/ChamMek/ChamMek.xcodeproj/slice.mode1v3 (revision 0) +++ branches/slice/rev749/ChamMek/ChamMek.xcodeproj/slice.mode1v3 (revision 1169) @@ -0,0 +1,1499 @@ + + + + + ActivePerspectiveName + Project + AllowedModules + + + BundleLoadPath + + MaxInstances + n + Module + PBXSmartGroupTreeModule + Name + Groups and Files Outline View + + + BundleLoadPath + + MaxInstances + n + Module + PBXNavigatorGroup + Name + Editor + + + BundleLoadPath + + MaxInstances + n + Module + XCTaskListModule + Name + Task List + + + BundleLoadPath + + MaxInstances + n + Module + XCDetailModule + Name + File and Smart Group Detail Viewer + + + BundleLoadPath + + MaxInstances + 1 + Module + PBXBuildResultsModule + Name + Detailed Build Results Viewer + + + BundleLoadPath + + MaxInstances + 1 + Module + PBXProjectFindModule + Name + Project Batch Find Tool + + + BundleLoadPath + + MaxInstances + n + Module + XCProjectFormatConflictsModule + Name + Project Format Conflicts List + + + BundleLoadPath + + MaxInstances + n + Module + PBXBookmarksModule + Name + Bookmarks Tool + + + BundleLoadPath + + MaxInstances + n + Module + PBXClassBrowserModule + Name + Class Browser + + + BundleLoadPath + + MaxInstances + n + Module + PBXCVSModule + Name + Source Code Control Tool + + + BundleLoadPath + + MaxInstances + n + Module + PBXDebugBreakpointsModule + Name + Debug Breakpoints Tool + + + BundleLoadPath + + MaxInstances + n + Module + XCDockableInspector + Name + Inspector + + + BundleLoadPath + + MaxInstances + n + Module + PBXOpenQuicklyModule + Name + Open Quickly Tool + + + BundleLoadPath + + MaxInstances + 1 + Module + PBXDebugSessionModule + Name + Debugger + + + BundleLoadPath + + MaxInstances + 1 + Module + PBXDebugCLIModule + Name + Debug Console + + + BundleLoadPath + + MaxInstances + n + Module + XCSnapshotModule + Name + Snapshots Tool + + + BundlePath + /Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources + Description + DefaultDescriptionKey + DockingSystemVisible + + Extension + mode1v3 + FavBarConfig + + PBXProjectModuleGUID + 12C26D3412B0DDFC00AF7F4B + XCBarModuleItemNames + + XCBarModuleItems + + + FirstTimeWindowDisplayed + + Identifier + com.apple.perspectives.project.mode1v3 + MajorVersion + 33 + MinorVersion + 0 + Name + Default + Notifications + + OpenEditors + + PerspectiveWidths + + -1 + -1 + + Perspectives + + + ChosenToolbarItems + + active-combo-popup + action + NSToolbarFlexibleSpaceItem + clean-target + buildOrClean + servicesModulefind + com.apple.ide.PBXToolbarStopButton + get-info + NSToolbarFlexibleSpaceItem + com.apple.pbx.toolbar.searchfield + + ControllerClassBaseName + + IconName + WindowOfProjectWithEditor + Identifier + perspective.project + IsVertical + + Layout + + + BecomeActive + + ContentConfiguration + + PBXBottomSmartGroupGIDs + + 1C37FBAC04509CD000000102 + 1C37FAAC04509CD000000102 + 1C37FABC05509CD000000102 + 1C37FABC05539CD112110102 + E2644B35053B69B200211256 + 1C37FABC04509CD000100104 + 1CC0EA4004350EF90044410B + 1CC0EA4004350EF90041110B + + PBXProjectModuleGUID + 1CE0B1FE06471DED0097A5F4 + PBXProjectModuleLabel + Files + PBXProjectStructureProvided + yes + PBXSmartGroupTreeModuleColumnData + + PBXSmartGroupTreeModuleColumnWidthsKey + + 22 + 226 + + PBXSmartGroupTreeModuleColumnsKey_v4 + + SCMStatusColumn + MainColumn + + + PBXSmartGroupTreeModuleOutlineStateKey_v7 + + PBXSmartGroupTreeModuleOutlineStateExpansionKey + + 08FB7794FE84155DC02AAC07 + 08FB7795FE84155DC02AAC07 + 12C26D3912B0DE0A00AF7F4B + 1C37FABC05509CD000000102 + + PBXSmartGroupTreeModuleOutlineStateSelectionKey + + + 35 + + + PBXSmartGroupTreeModuleOutlineStateVisibleRectKey + {{0, 0}, {248, 647}} + + PBXTopSmartGroupGIDs + + XCIncludePerspectivesSwitch + + XCSharingToken + com.apple.Xcode.GFSharingToken + + GeometryConfiguration + + Frame + {{0, 0}, {265, 665}} + GroupTreeTableConfiguration + + SCMStatusColumn + 22 + MainColumn + 226 + + RubberWindowFrame + 364 171 1021 706 0 0 1440 878 + + Module + PBXSmartGroupTreeModule + Proportion + 265pt + + + Dock + + + ContentConfiguration + + PBXProjectModuleGUID + 1CE0B20306471E060097A5F4 + PBXProjectModuleLabel + fake_efi.c + PBXSplitModuleInNavigatorKey + + Split0 + + PBXProjectModuleGUID + 1CE0B20406471E060097A5F4 + PBXProjectModuleLabel + fake_efi.c + _historyCapacity + 0 + bookmark + 126A6409137BCAAE003C4F2E + history + + 12B9F42612B29A4A00FE287A + 12B90A2012B2A7E200FE287A + 12B90A2B12B2A86B00FE287A + 12B90A4D12B2AE1300FE287A + 12B90A4F12B2AE1300FE287A + 12B90A5212B2AE1300FE287A + 12E17AE612B2BA9B00607D8E + 12CC44C812B3947B007E0C76 + 1299A51F12B3C328007ED516 + 1299A55612B3C4DF007ED516 + 12BF14DA12B3CF8E00D798FE + 12EFD98A12B510D9002A1712 + 12EFE2FD12B51ED5002A1712 + 12EFE65A12B547A7002A1712 + 12EFE95E12B549B6002A1712 + 12C8CB6812B5529D003DA1E4 + 1216139E12B65BB50019961E + 121613FF12B65D970019961E + 12AB04BD12B663F5005A745F + 12AB04EC12B665EA005A745F + 12B46E6612B75631006C2B9C + 12B46E6812B75631006C2B9C + 12B46E6912B75631006C2B9C + 12B46E6A12B75631006C2B9C + 1267813012B7B13E00A25CED + 12C7FC4D12B7BCD3006BD382 + 12C7FC4E12B7BCD3006BD382 + 12C7009812B7BCE7006BD382 + 12C7009912B7BCE7006BD382 + 12C704E512B7BD3E006BD382 + 124C493212B8D846005AA276 + 124C493712B8D846005AA276 + 124C494212B8E8C2005AA276 + 124C494312B8E8C2005AA276 + 124C494512B8E8C2005AA276 + 124C494B12B8EA5D005AA276 + 120DFB1712BA3A4D00C7EAC8 + 120DFB1812BA3A4D00C7EAC8 + 120DFF6B12BA3BF500C7EAC8 + 12D6232512BA5F380032F367 + 12D6232612BA5F380032F367 + 12AF764312BA614B003BBFD3 + 12E6FB5712BB458400C2A021 + 12FC0E7512BB4B5200E9CFA8 + 12FC0E9412BB65A800E9CFA8 + 12F7FF0012BB9F3200949DEC + 12DCD38E12BBA5D600A20635 + 12679BA312BE822E00E3637F + 128A9AF412C233CE00600556 + 1288318212C3608100EA4CB2 + 12DA422F12C52DAC009281B3 + 12D331A312C61E950093EEDB + 12D3324112C63EB70093EEDB + 12D3329E12C669090093EEDB + 12D332A512C669090093EEDB + 12D332AA12C669090093EEDB + 12FE983612C7CEEB001B1702 + 12FE984A12C7E11C001B1702 + 12FE987912C7E281001B1702 + 12FE987A12C7E281001B1702 + 12C246F412C87C7C007E8339 + 12C5020712D8B82400EDCC4E + 12E8842612D8F833004C76C8 + 12715CDF12EA253100E3013B + 12715CE012EA253100E3013B + 122A869812EC5429004312F4 + 122A86C612ECA817004312F4 + 126C766312EEF67F00BDB81E + 125437C812EF1E99007175C8 + 125437CB12EF1E99007175C8 + 12569C8612F0115B005A9113 + 121FAA3512F051A200385F21 + 1220CE4112F2BFBF0045986D + 1220CE4212F2BFBF0045986D + 122C56E012F2CB51005FE786 + 1218381312F2EA3F007D1704 + 1218381412F2EA3F007D1704 + 1218381612F2EA3F007D1704 + 1218381812F2EA3F007D1704 + 1218381A12F2EA3F007D1704 + 122DBE3512F47E30003C7482 + 12106C2B12F480E2008BA484 + 12306DBE12F4AAEE000AAE98 + 125A6C2512F53BCD00535D65 + 1267A85C12F5771100751FC6 + 121114BE12F591340029B6FC + 120DC73B12F5C87900345D09 + 12DFBB1C12F6E9A500E2DA49 + 12DFBB1D12F6E9A500E2DA49 + 12DFBB1F12F6E9A500E2DA49 + 12DFBB2112F6E9A500E2DA49 + 12DFBFDA12F7066500E2DA49 + 126D84C612F7FA6E000AB776 + 12EA3B42131B91D4008D7D68 + 1221F71113291A0A0014A9B5 + 1221F71213291A0A0014A9B5 + 1221F71413291A0A0014A9B5 + 1221F71513291A0A0014A9B5 + 1221F71613291A0A0014A9B5 + 1221F71813291A0A0014A9B5 + 1221F71A13291A0A0014A9B5 + 1221899A134352F700A5656B + 12218E691343597300A5656B + 120FE7891345F8FC00CC4AA2 + 128439CE1365B655003A4A52 + 121DBA96137186C700C733E2 + 121DBAA11371953B00C733E2 + 121DBAA21371953B00C733E2 + 121DBAA31371953B00C733E2 + 121DBAA51371953B00C733E2 + 121DBAA71371953B00C733E2 + 126A6408137BCAAE003C4F2E + 126A6402137BCAAC003C4F2E + + + SplitCount + 1 + + StatusBarVisibility + + + GeometryConfiguration + + Frame + {{0, 0}, {751, 444}} + RubberWindowFrame + 364 171 1021 706 0 0 1440 878 + + Module + PBXNavigatorGroup + Proportion + 444pt + + + ContentConfiguration + + PBXProjectModuleGUID + 1CE0B20506471E060097A5F4 + PBXProjectModuleLabel + Detail + + GeometryConfiguration + + Frame + {{0, 449}, {751, 216}} + RubberWindowFrame + 364 171 1021 706 0 0 1440 878 + + Module + XCDetailModule + Proportion + 216pt + + + Proportion + 751pt + + + Name + Project + ServiceClasses + + XCModuleDock + PBXSmartGroupTreeModule + XCModuleDock + PBXNavigatorGroup + XCDetailModule + + TableOfContents + + 126A640B137BCAAE003C4F2E + 1CE0B1FE06471DED0097A5F4 + 126A640C137BCAAE003C4F2E + 1CE0B20306471E060097A5F4 + 1CE0B20506471E060097A5F4 + + ToolbarConfigUserDefaultsMinorVersion + 2 + ToolbarConfiguration + xcode.toolbar.config.defaultV3 + + + ControllerClassBaseName + + IconName + WindowOfProject + Identifier + perspective.morph + IsVertical + 0 + Layout + + + BecomeActive + 1 + ContentConfiguration + + PBXBottomSmartGroupGIDs + + 1C37FBAC04509CD000000102 + 1C37FAAC04509CD000000102 + 1C08E77C0454961000C914BD + 1C37FABC05509CD000000102 + 1C37FABC05539CD112110102 + E2644B35053B69B200211256 + 1C37FABC04509CD000100104 + 1CC0EA4004350EF90044410B + 1CC0EA4004350EF90041110B + + PBXProjectModuleGUID + 11E0B1FE06471DED0097A5F4 + PBXProjectModuleLabel + Files + PBXProjectStructureProvided + yes + PBXSmartGroupTreeModuleColumnData + + PBXSmartGroupTreeModuleColumnWidthsKey + + 186 + + PBXSmartGroupTreeModuleColumnsKey_v4 + + MainColumn + + + PBXSmartGroupTreeModuleOutlineStateKey_v7 + + PBXSmartGroupTreeModuleOutlineStateExpansionKey + + 29B97314FDCFA39411CA2CEA + 1C37FABC05509CD000000102 + + PBXSmartGroupTreeModuleOutlineStateSelectionKey + + + 0 + + + PBXSmartGroupTreeModuleOutlineStateVisibleRectKey + {{0, 0}, {186, 337}} + + PBXTopSmartGroupGIDs + + XCIncludePerspectivesSwitch + 1 + XCSharingToken + com.apple.Xcode.GFSharingToken + + GeometryConfiguration + + Frame + {{0, 0}, {203, 355}} + GroupTreeTableConfiguration + + MainColumn + 186 + + RubberWindowFrame + 373 269 690 397 0 0 1440 878 + + Module + PBXSmartGroupTreeModule + Proportion + 100% + + + Name + Morph + PreferredWidth + 300 + ServiceClasses + + XCModuleDock + PBXSmartGroupTreeModule + + TableOfContents + + 11E0B1FE06471DED0097A5F4 + + ToolbarConfiguration + xcode.toolbar.config.default.shortV3 + + + PerspectivesBarVisible + + ShelfIsVisible + + SourceDescription + file at '/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources/XCPerspectivesSpecificationMode1.xcperspec' + StatusbarIsVisible + + TimeStamp + 0.0 + ToolbarConfigUserDefaultsMinorVersion + 2 + ToolbarDisplayMode + 1 + ToolbarIsVisible + + ToolbarSizeMode + 1 + Type + Perspectives + UpdateMessage + The Default Workspace in this version of Xcode now includes support to hide and show the detail view (what has been referred to as the "Metro-Morph" feature). You must discard your current Default Workspace settings and update to the latest Default Workspace in order to gain this feature. Do you wish to update to the latest Workspace defaults for project '%@'? + WindowJustification + 5 + WindowOrderList + + 1C530D57069F1CE1000CFCEE + 12C26D3512B0DDFC00AF7F4B + /Users/slice/Projects/Chameleons/chameleon/branches/slice/ChamMek/ChamMek.xcodeproj + + WindowString + 364 171 1021 706 0 0 1440 878 + WindowToolsV3 + + + FirstTimeWindowDisplayed + + Identifier + windowTool.build + IsVertical + + Layout + + + Dock + + + ContentConfiguration + + PBXProjectModuleGUID + 1CD0528F0623707200166675 + PBXProjectModuleLabel + + StatusBarVisibility + + + GeometryConfiguration + + Frame + {{0, 0}, {500, 218}} + RubberWindowFrame + 347 289 500 500 0 0 1440 878 + + Module + PBXNavigatorGroup + Proportion + 218pt + + + ContentConfiguration + + PBXProjectModuleGUID + XCMainBuildResultsModuleGUID + PBXProjectModuleLabel + Build Results + XCBuildResultsTrigger_Collapse + 1021 + XCBuildResultsTrigger_Open + 1011 + + GeometryConfiguration + + Frame + {{0, 223}, {500, 236}} + RubberWindowFrame + 347 289 500 500 0 0 1440 878 + + Module + PBXBuildResultsModule + Proportion + 236pt + + + Proportion + 459pt + + + Name + Build Results + ServiceClasses + + PBXBuildResultsModule + + StatusbarIsVisible + + TableOfContents + + 12C26D3512B0DDFC00AF7F4B + 126A6400137BCAAC003C4F2E + 1CD0528F0623707200166675 + XCMainBuildResultsModuleGUID + + ToolbarConfiguration + xcode.toolbar.config.buildV3 + WindowContentMinSize + 486 300 + WindowString + 347 289 500 500 0 0 1440 878 + WindowToolGUID + 12C26D3512B0DDFC00AF7F4B + WindowToolIsVisible + + + + FirstTimeWindowDisplayed + + Identifier + windowTool.debugger + IsVertical + + Layout + + + Dock + + + ContentConfiguration + + Debugger + + HorizontalSplitView + + _collapsingFrameDimension + 0.0 + _indexOfCollapsedView + 0 + _percentageOfCollapsedView + 0.0 + isCollapsed + yes + sizes + + {{0, 0}, {316, 203}} + {{316, 0}, {378, 203}} + + + VerticalSplitView + + _collapsingFrameDimension + 0.0 + _indexOfCollapsedView + 0 + _percentageOfCollapsedView + 0.0 + isCollapsed + yes + sizes + + {{0, 0}, {694, 203}} + {{0, 203}, {694, 178}} + + + + LauncherConfigVersion + 8 + PBXProjectModuleGUID + 1C162984064C10D400B95A72 + PBXProjectModuleLabel + Debug - GLUTExamples (Underwater) + + GeometryConfiguration + + DebugConsoleVisible + None + DebugConsoleWindowFrame + {{200, 200}, {500, 300}} + DebugSTDIOWindowFrame + {{200, 200}, {500, 300}} + Frame + {{0, 0}, {694, 381}} + PBXDebugSessionStackFrameViewKey + + DebugVariablesTableConfiguration + + Name + 120 + Value + 85 + Summary + 148 + + Frame + {{316, 0}, {378, 203}} + RubberWindowFrame + 77 419 694 422 0 0 1440 878 + + RubberWindowFrame + 77 419 694 422 0 0 1440 878 + + Module + PBXDebugSessionModule + Proportion + 381pt + + + Proportion + 381pt + + + Name + Debugger + ServiceClasses + + PBXDebugSessionModule + + StatusbarIsVisible + + TableOfContents + + 1CD10A99069EF8BA00B06720 + 128439B41365B650003A4A52 + 1C162984064C10D400B95A72 + 128439B51365B650003A4A52 + 128439B61365B650003A4A52 + 128439B71365B650003A4A52 + 128439B81365B650003A4A52 + 128439B91365B650003A4A52 + + ToolbarConfiguration + xcode.toolbar.config.debugV3 + WindowString + 77 419 694 422 0 0 1440 878 + WindowToolGUID + 1CD10A99069EF8BA00B06720 + WindowToolIsVisible + + + + FirstTimeWindowDisplayed + + Identifier + windowTool.find + IsVertical + + Layout + + + Dock + + + Dock + + + BecomeActive + + ContentConfiguration + + PBXProjectModuleGUID + 1CDD528C0622207200134675 + PBXProjectModuleLabel + fake_efi.c + StatusBarVisibility + + + GeometryConfiguration + + Frame + {{0, 0}, {1109, 510}} + RubberWindowFrame + 331 55 1109 816 0 0 1440 878 + + Module + PBXNavigatorGroup + Proportion + 1109pt + + + Proportion + 510pt + + + ContentConfiguration + + PBXProjectModuleGUID + 1CD0528E0623707200166675 + PBXProjectModuleLabel + Project Find + + GeometryConfiguration + + Frame + {{0, 515}, {1109, 260}} + RubberWindowFrame + 331 55 1109 816 0 0 1440 878 + + Module + PBXProjectFindModule + Proportion + 260pt + + + Proportion + 775pt + + + Name + Project Find + ServiceClasses + + PBXProjectFindModule + + StatusbarIsVisible + + TableOfContents + + 1C530D57069F1CE1000CFCEE + 126A6406137BCAAC003C4F2E + 126A6407137BCAAC003C4F2E + 1CDD528C0622207200134675 + 1CD0528E0623707200166675 + + WindowString + 331 55 1109 816 0 0 1440 878 + WindowToolGUID + 1C530D57069F1CE1000CFCEE + WindowToolIsVisible + + + + Identifier + MENUSEPARATOR + + + Identifier + windowTool.debuggerConsole + Layout + + + Dock + + + BecomeActive + 1 + ContentConfiguration + + PBXProjectModuleGUID + 1C78EAAC065D492600B07095 + PBXProjectModuleLabel + Debugger Console + + GeometryConfiguration + + Frame + {{0, 0}, {650, 250}} + RubberWindowFrame + 516 632 650 250 0 0 1680 1027 + + Module + PBXDebugCLIModule + Proportion + 209pt + + + Proportion + 209pt + + + Name + Debugger Console + ServiceClasses + + PBXDebugCLIModule + + StatusbarIsVisible + 1 + TableOfContents + + 1C78EAAD065D492600B07095 + 1C78EAAE065D492600B07095 + 1C78EAAC065D492600B07095 + + ToolbarConfiguration + xcode.toolbar.config.consoleV3 + WindowString + 650 41 650 250 0 0 1280 1002 + WindowToolGUID + 1C78EAAD065D492600B07095 + WindowToolIsVisible + 0 + + + Identifier + windowTool.snapshots + Layout + + + Dock + + + Module + XCSnapshotModule + Proportion + 100% + + + Proportion + 100% + + + Name + Snapshots + ServiceClasses + + XCSnapshotModule + + StatusbarIsVisible + Yes + ToolbarConfiguration + xcode.toolbar.config.snapshots + WindowString + 315 824 300 550 0 0 1440 878 + WindowToolIsVisible + Yes + + + Identifier + windowTool.scm + Layout + + + Dock + + + ContentConfiguration + + PBXProjectModuleGUID + 1C78EAB2065D492600B07095 + PBXProjectModuleLabel + <No Editor> + PBXSplitModuleInNavigatorKey + + Split0 + + PBXProjectModuleGUID + 1C78EAB3065D492600B07095 + + SplitCount + 1 + + StatusBarVisibility + 1 + + GeometryConfiguration + + Frame + {{0, 0}, {452, 0}} + RubberWindowFrame + 743 379 452 308 0 0 1280 1002 + + Module + PBXNavigatorGroup + Proportion + 0pt + + + BecomeActive + 1 + ContentConfiguration + + PBXProjectModuleGUID + 1CD052920623707200166675 + PBXProjectModuleLabel + SCM + + GeometryConfiguration + + ConsoleFrame + {{0, 259}, {452, 0}} + Frame + {{0, 7}, {452, 259}} + RubberWindowFrame + 743 379 452 308 0 0 1280 1002 + TableConfiguration + + Status + 30 + FileName + 199 + Path + 197.0950012207031 + + TableFrame + {{0, 0}, {452, 250}} + + Module + PBXCVSModule + Proportion + 262pt + + + Proportion + 266pt + + + Name + SCM + ServiceClasses + + PBXCVSModule + + StatusbarIsVisible + 1 + TableOfContents + + 1C78EAB4065D492600B07095 + 1C78EAB5065D492600B07095 + 1C78EAB2065D492600B07095 + 1CD052920623707200166675 + + ToolbarConfiguration + xcode.toolbar.config.scm + WindowString + 743 379 452 308 0 0 1280 1002 + + + Identifier + windowTool.breakpoints + IsVertical + 0 + Layout + + + Dock + + + BecomeActive + 1 + ContentConfiguration + + PBXBottomSmartGroupGIDs + + 1C77FABC04509CD000000102 + + PBXProjectModuleGUID + 1CE0B1FE06471DED0097A5F4 + PBXProjectModuleLabel + Files + PBXProjectStructureProvided + no + PBXSmartGroupTreeModuleColumnData + + PBXSmartGroupTreeModuleColumnWidthsKey + + 168 + + PBXSmartGroupTreeModuleColumnsKey_v4 + + MainColumn + + + PBXSmartGroupTreeModuleOutlineStateKey_v7 + + PBXSmartGroupTreeModuleOutlineStateExpansionKey + + 1C77FABC04509CD000000102 + + PBXSmartGroupTreeModuleOutlineStateSelectionKey + + + 0 + + + PBXSmartGroupTreeModuleOutlineStateVisibleRectKey + {{0, 0}, {168, 350}} + + PBXTopSmartGroupGIDs + + XCIncludePerspectivesSwitch + 0 + + GeometryConfiguration + + Frame + {{0, 0}, {185, 368}} + GroupTreeTableConfiguration + + MainColumn + 168 + + RubberWindowFrame + 315 424 744 409 0 0 1440 878 + + Module + PBXSmartGroupTreeModule + Proportion + 185pt + + + ContentConfiguration + + PBXProjectModuleGUID + 1CA1AED706398EBD00589147 + PBXProjectModuleLabel + Detail + + GeometryConfiguration + + Frame + {{190, 0}, {554, 368}} + RubberWindowFrame + 315 424 744 409 0 0 1440 878 + + Module + XCDetailModule + Proportion + 554pt + + + Proportion + 368pt + + + MajorVersion + 3 + MinorVersion + 0 + Name + Breakpoints + ServiceClasses + + PBXSmartGroupTreeModule + XCDetailModule + + StatusbarIsVisible + 1 + TableOfContents + + 1CDDB66807F98D9800BB5817 + 1CDDB66907F98D9800BB5817 + 1CE0B1FE06471DED0097A5F4 + 1CA1AED706398EBD00589147 + + ToolbarConfiguration + xcode.toolbar.config.breakpointsV3 + WindowString + 315 424 744 409 0 0 1440 878 + WindowToolGUID + 1CDDB66807F98D9800BB5817 + WindowToolIsVisible + 1 + + + Identifier + windowTool.debugAnimator + Layout + + + Dock + + + Module + PBXNavigatorGroup + Proportion + 100% + + + Proportion + 100% + + + Name + Debug Visualizer + ServiceClasses + + PBXNavigatorGroup + + StatusbarIsVisible + 1 + ToolbarConfiguration + xcode.toolbar.config.debugAnimatorV3 + WindowString + 100 100 700 500 0 0 1280 1002 + + + Identifier + windowTool.bookmarks + Layout + + + Dock + + + Module + PBXBookmarksModule + Proportion + 100% + + + Proportion + 100% + + + Name + Bookmarks + ServiceClasses + + PBXBookmarksModule + + StatusbarIsVisible + 0 + WindowString + 538 42 401 187 0 0 1280 1002 + + + Identifier + windowTool.projectFormatConflicts + Layout + + + Dock + + + Module + XCProjectFormatConflictsModule + Proportion + 100% + + + Proportion + 100% + + + Name + Project Format Conflicts + ServiceClasses + + XCProjectFormatConflictsModule + + StatusbarIsVisible + 0 + WindowContentMinSize + 450 300 + WindowString + 50 850 472 307 0 0 1440 877 + + + Identifier + windowTool.classBrowser + Layout + + + Dock + + + BecomeActive + 1 + ContentConfiguration + + OptionsSetName + Hierarchy, all classes + PBXProjectModuleGUID + 1CA6456E063B45B4001379D8 + PBXProjectModuleLabel + Class Browser - NSObject + + GeometryConfiguration + + ClassesFrame + {{0, 0}, {374, 96}} + ClassesTreeTableConfiguration + + PBXClassNameColumnIdentifier + 208 + PBXClassBookColumnIdentifier + 22 + + Frame + {{0, 0}, {630, 331}} + MembersFrame + {{0, 105}, {374, 395}} + MembersTreeTableConfiguration + + PBXMemberTypeIconColumnIdentifier + 22 + PBXMemberNameColumnIdentifier + 216 + PBXMemberTypeColumnIdentifier + 97 + PBXMemberBookColumnIdentifier + 22 + + PBXModuleWindowStatusBarHidden2 + 1 + RubberWindowFrame + 385 179 630 352 0 0 1440 878 + + Module + PBXClassBrowserModule + Proportion + 332pt + + + Proportion + 332pt + + + Name + Class Browser + ServiceClasses + + PBXClassBrowserModule + + StatusbarIsVisible + 0 + TableOfContents + + 1C0AD2AF069F1E9B00FABCE6 + 1C0AD2B0069F1E9B00FABCE6 + 1CA6456E063B45B4001379D8 + + ToolbarConfiguration + xcode.toolbar.config.classbrowser + WindowString + 385 179 630 352 0 0 1440 878 + WindowToolGUID + 1C0AD2AF069F1E9B00FABCE6 + WindowToolIsVisible + 0 + + + Identifier + windowTool.refactoring + IncludeInToolsMenu + 0 + Layout + + + Dock + + + BecomeActive + 1 + GeometryConfiguration + + Frame + {0, 0}, {500, 335} + RubberWindowFrame + {0, 0}, {500, 335} + + Module + XCRefactoringModule + Proportion + 100% + + + Proportion + 100% + + + Name + Refactoring + ServiceClasses + + XCRefactoringModule + + WindowString + 200 200 500 356 0 0 1920 1200 + + + + Index: branches/slice/rev749/ChamMek/ChamMek.1 =================================================================== --- branches/slice/rev749/ChamMek/ChamMek.1 (revision 0) +++ branches/slice/rev749/ChamMek/ChamMek.1 (revision 1169) @@ -0,0 +1,79 @@ +.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples. +.\"See Also: +.\"man mdoc.samples for a complete listing of options +.\"man mdoc for the short list of editing options +.\"/usr/share/misc/mdoc.template +.Dd 09.12.10 \" DATE +.Dt ChamMek 1 \" Program name and manual section number +.Os Darwin +.Sh NAME \" Section Header - required - don't modify +.Nm ChamMek, +.\" The following lines are read in generating the apropos(man -k) database. Use only key +.\" words here as the database is built based on the words here and in the .ND line. +.Nm Other_name_for_same_program(), +.Nm Yet another name for the same program. +.\" Use .Nm macro to designate other names for the documented program. +.Nd This line parsed for whatis database. +.Sh SYNOPSIS \" Section Header - required - don't modify +.Nm +.Op Fl abcd \" [-abcd] +.Op Fl a Ar path \" [-a path] +.Op Ar file \" [file] +.Op Ar \" [file ...] +.Ar arg0 \" Underlined argument - use .Ar anywhere to underline +arg2 ... \" Arguments +.Sh DESCRIPTION \" Section Header - required - don't modify +Use the .Nm macro to refer to your program throughout the man page like such: +.Nm +Underlining is accomplished with the .Ar macro like this: +.Ar underlined text . +.Pp \" Inserts a space +A list of items with descriptions: +.Bl -tag -width -indent \" Begins a tagged list +.It item a \" Each item preceded by .It macro +Description of item a +.It item b +Description of item b +.El \" Ends the list +.Pp +A list of flags and their descriptions: +.Bl -tag -width -indent \" Differs from above in tag removed +.It Fl a \"-a flag as a list item +Description of -a flag +.It Fl b +Description of -b flag +.El \" Ends the list +.Pp +.\" .Sh ENVIRONMENT \" May not be needed +.\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1 +.\" .It Ev ENV_VAR_1 +.\" Description of ENV_VAR_1 +.\" .It Ev ENV_VAR_2 +.\" Description of ENV_VAR_2 +.\" .El +.Sh FILES \" File used or created by the topic of the man page +.Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact +.It Pa /usr/share/file_name +FILE_1 description +.It Pa /Users/joeuser/Library/really_long_file_name +FILE_2 description +.El \" Ends the list +.\" .Sh DIAGNOSTICS \" May not be needed +.\" .Bl -diag +.\" .It Diagnostic Tag +.\" Diagnostic informtion here. +.\" .It Diagnostic Tag +.\" Diagnostic informtion here. +.\" .El +.Sh SEE ALSO +.\" List links in ascending order by section, alphabetically within a section. +.\" Please do not reference files that do not exist without filing a bug report +.Xr a 1 , +.Xr b 1 , +.Xr c 1 , +.Xr a 2 , +.Xr b 2 , +.Xr a 3 , +.Xr b 3 +.\" .Sh BUGS \" Document known, unremedied bugs +.\" .Sh HISTORY \" Document history if command behaves in a unique manner \ No newline at end of file Index: branches/slice/rev749/ChamMek/main.c =================================================================== --- branches/slice/rev749/ChamMek/main.c (revision 0) +++ branches/slice/rev749/ChamMek/main.c (revision 1169) @@ -0,0 +1,12 @@ +#include + +//do not build this project! +//it is for Search purpose +// Find: something +// Replace by: newOne + +int main (int argc, const char * argv[]) { + // insert code here... + printf("Hello, World!\n"); + return 0; +} Index: branches/slice/rev749/doc/Limits =================================================================== --- branches/slice/rev749/doc/Limits (revision 0) +++ branches/slice/rev749/doc/Limits (revision 1169) @@ -0,0 +1,2 @@ +The memory map and sizes of various things are in libsa/memory.h. + Index: branches/slice/rev749/doc/README =================================================================== --- branches/slice/rev749/doc/README (revision 0) +++ branches/slice/rev749/doc/README (revision 1169) @@ -0,0 +1,173 @@ +/* + * Mach Operating System + * Copyright (c) 1990 Carnegie-Mellon University + * Copyright (c) 1989 Carnegie-Mellon University + * All rights reserved. The CMU software License Agreement specifies + * the terms and conditions for use and redistribution. + */ + + AT386 Protected Mode Bootstrap Loader + ===================================== + +1. Overview of Startup + ------------------- + + After the system is rebooted, the BIOS bootstrap routine reads Sector + 1, Track 0 into memory at location 0000:7C00H. If location 0000:7DFEH + (last two bytes of that sector) contains the value AA55H, the BIOS + bootstrap routine will transfer control to 0000:7C00H. Otherwise, the + boot code in that sector is bad and the boot routine stops. + + For DOS compatibility reason, one extra stage of boot is required if + the boot device is a hard disk. The first sector of the hard disk will + contain the MOS-DOS boot code and a boot record partition table. + When this sector is loaded into 0000:7C00H, it will relocate itself + to somewhere else and then load the first sector of the active + partition into 0000:7C00H. Both UNIX and DOS use the command "fdisk" + to install this first sector into the hard disk and to manipulate + the hard disk partitions. + + + +2. The First Stage Bootstrap Loader + -------------------------------- + + After startup, the first stage boot is loaded at 0000:7C00H. This + first stage boot will load itself and the second stage boot into + memory at location 0000:1000H. For floppy disks, the first cylinder + is reserved as the boot cylinder, and the boot code (first and second) + will be loaded from there. Currently, only double sided, high density + (15 sectors per track) floppies are supported. For hard disks, the + first 29 sectors of the active partition is reserved for boot code + which will be loaded by the first stage boot. All the disk types + recognized by BIOS are supported by this bootstrap loader. + + + +3. The Second Stage Bootstrap Loader + -------------------------------- + + After the boot code is loaded, the control is passed to the second + stage bootstrap loader "boot2()". In order to be able to load the + big kernel image (bigger than 512K or 640K, depends on the memory + configuration), the second stage boot loader will run on the protected + mode. This bootstarp loader does not have any stand alone device + drivers, all the I/O's are through the BIOS calls. Since the first + stage boot code will no longer be used at this moment, the memory + location of the first stage boot code (0000:1000H to 0000:1200H) will + be used as an internal buffer for BIOS calls. Immediately after this + internal buffer is the GDT table for the second stage boot loader. + Since this boot loader needs to switch back and forth between protected + and real mode in order to use BIOS calls, the limit of the boot code + and boot data segments must not be greater than 64K. + + The boot loader loads the kernel image at memory location above 1 MB + to skip the memory hole between 521K/640K and 1MB. After the kernel + is loaded, the boot loader stores the information in the stack and + then passes control to kernel. Currently, the three information passed + fromm the boot loader to the kernel are type of the boot device, size + of the base memory and size of the extended memory. + + +4. The UNIX Startup + ---------------- + + Since the boot loader loads the kernel image at memory location above + 1MB, the kernel has to start as protected mode. In addition, the + link editor description file (vuifile) has to indicate that + the text and data segments start above 1MB. Also, the boot loader + passes the infomation to the kernel through the stack. + + +5. Disk Layout and Bad Block Handling + --------------------------------- + + The System V/386 Release 3.2 (AT) disk layout will be used as the disk + layout for the MACH System on the AT platform. + + This disk layout is as follows: + + * Reserve the first sector of cylinder 0 for the DOS boot record which + contains the master boot code (446 bytes) and the partition table. + (Refer to DOS Technical Reference Manual page 9-6 to 9-10). + + * Reserve the first 29 sectors of the UNIX partition for the first + and the second stage bootstrap. + + * Reserve the 30th sector of the UNIX partition for the pdinfo and + the vtoc tables. + + * Reserve the 31st to the 34th sectors of the UNIX partition for the + bad track and the bad block mapping tables. + + * Reserve up to 253 consecutive tracks when required, beginning with + the 35th sector of the UNIX partition, for alternate tracks. + + * Reserve up to 253 consecutive blocks, beginning with the first + sector after the alternate tracks area, for alternate blocks. + + SEC + 1 + ---------------------------------------------------- + | X | | CYL 0, TRK 0 + ---------------- .......... -------------------- + | .......... | + ---------------- .......... -------------------- + | .......... | + =============================================================== + ^ | BOOTSTRAP | CYL N, TRK M + | ---------------------------------------------------- + | | |30 |31 |32 |33 |34 | + ---------------------------------------------------- --- + U | .......... | ^ + N ---------------- .......... --------------------- | + I | .......... | Alternate Tracks + X ---------------- .......... --------------------- | + | .......... | V + P ---------------------------------------------------- --- + A | .......... | ^ + R ---------------- .......... --------------------- | + T | .......... | Alternate Blocks + I ---------------- .......... -------------------- | + T | .......... | V + I ---------------------------------------------------- --- + O | Unix root partition starts from here | + N ---------------- ----------------- + | | + ---------------------------------------------------- + | | + ---------------------------------------------------- + | | + | --------------------------------------------------- + | | | + | ---------------------------------------------------- + V | | + =============================================================== + | ........ | + --------------- ........ -------------- + | ........ | + ---------------------------------------------------- + + + The bad block handling mechanism is as follows: + + * Use the alternate track in the alternate tracks area if the + track containing the target sector is bad. + + * Use the alternate block in the alternate blocks area if the + target sector is bad. + + + + +6. How to make: + ----------- + + Since the kernel image is loaded above 1 MB, the kernel must start + as protected mode. This means that this bootstrap loader will work + only when the corresponding changes on the kernel startup code are done. + + The make command to generate this bootstrap loader is: + + make -f boot.mk fdboot (floppy boot loader) + make -f boot.mk hdboot (wini boot loader) Index: branches/slice/rev749/CHANGES =================================================================== --- branches/slice/rev749/CHANGES (revision 0) +++ branches/slice/rev749/CHANGES (revision 1169) @@ -0,0 +1,83 @@ +Slice: +rev712 +- correct module system as Meklort did to be Symbols.dylib embedded. +- return acpi_patcher to main sources to exclude obligatory module +- correct modules.c procedure register_hook_callback. +rev692 +- add ATI 5xxx Enabler module on Kabyl's sources (not checked) +- corrections to open standards: EFI, UUID, SMBIOS, ACPI, EDID +- getResolution from BIOS EDID now works +- exclude Intel BIOS from patch, because it has other structure +rev673 +- not agree with claim "Removed obsolete -f option, use -x instead" + -f - ignore kernel cache (rebuild it) + -x - boot with restricted set of drivers (without Graphics card etc.) +- kernelcache location depends on OS vesion. It differs for 10.4, 10.5, 10.6 +- don't need to include headers twice, other cosmetics +- don't need to call getSMBIOS ten times, just global pointer to patched one. +- more correct detect system type Mobile or Desktop based on CPU MSR registers and DMI info. +- write system-type into FACP if incorrect. Sometimes it happen. +- create ACPI2.0 structure for old BIOSes having only ACPI1.0. It is only way to boot SamsungP29 notebook +- place patched DSDT at the ACPI1.0 pointer. It is only way to patch DSDT for SamsungP29 notebook. Nontheless acpi_patcher works for any system +- delete messages like "Loading HFS+ file [xxx]xxx...". No info for user but very slow. +- correct UUID to be LittleEndian as used by ACPI.org, Microsoft, Apple +- some corrections to detect CPU, ATI, NVidia +- other current corrections by Mozo and Meklort +----------------------------------- +- Added Booter Log Dump Tool +- Added Booter message Logging (":/boot-log" ioreg property) +- Removed obsolete -f option, use -x instead +- Removed -x32 option, use arch=i386 instead +- Added automatic SMBusspeed detection for lga1156 core i5/7 cpus +- Added new iMac11,1 sbios default model for lga1156 core i5/17 mobos +- md0 code. Notified xnu when an md ramdisk is specified +- Added rollover image support for selected device icons. + Use device__o.png in theme folder. Credits goes to Blackosx. +- Revisited theme resource embedding. Using the device_ icons are optional with + the exception of device_generic. +- Optimized memory detection speed +- Added displaying source device and partition number for file read operations. +- Increased boot2's maximum size from 383.5k to 447.5k. + Updated stage 1 loaders for handling the new size limit. +- Added alternate format for setting the default partition. The user can specify the selected + volume UUID for the "Default Partition" key. +- Implemented SPD memory automatic detection and injection,seems to work really great ... +- Factorized code to prepare a dynamic memory detection algorithm ... +- Optimized smbios table address search +- Optimized cursor spinout in textmode if no verbose mode is set +- Added ram table structures definitions +- Added getSmbios() a param permitting to select between orig and new smbios entries +- Changed "Default Partition" behaviour to accept only native system volumes or foreign partitions. +- Added NVIDIA new NVCAP customization support and support for ION gfx cards from aserebln +- Added ATI new framebuffers support and new cards from PCEFI10.6 +- improved ACPI file search algo by implementing a cache. +- Nvidia injection fix +- pciroot would not always return correct uuid in autodection mode +- Fixed the hibernation problem in boot2/resume.c +- Fixed all new booter versions with SystemType would override the facp value even if correct, + now keeps the facp value if correct and no override has been done, implemented a best effort algo. + for maximizing the chance to get the most correct value before we decide to use a fixed value (1=desktop) +- Fixed display cosmetics of UUID, now a convert.c file contains all + conversions api, to be completed by function that we should reuse. + +- Fixed SystemType would be always forced to a value, now optionally changed + only if ovveriden +- Kept SystemID as the only option to change manually the system-id + For theses reasons, SystemId from bootConfig and SMUUID from smbiosConfig aer now DEPRECATED. + +- Integrated JrCs fadt patch (kept for RC5 the existing DSDT.aml retry algo that disapeared in his patch, should be more discussed for RC6) +- Added JrCs modified convention name change to coding_standards +- Now malloc (ex. MALLOC in Asere patch) is renamed malloc(size) and is an alias + to safe_malloc(size, file, line) with _FILE_ and _LINE_ prerocessor definitions +- Added a new 'Rename Partition Feature', now permitting to rename partition + like 'System reserved' to a more meaningful name +- Added SystemID option permitting to change the System UUID to a fixed value. +- Added the PciRoot autodetection feature imported from pcefi10.5 +- Added automatic "system-id" injection from dmi bios, also compatible + with SystemID boot option and former SMUUID from smbios,plist +- Added "system-type' automatic injection (1=Desktop) plus override possibility + with the new system-type option in bootConfig +- Added SMserial and SMproductname new options for smbios.plist +- Merged with asere patch, while keeping my fake_efi.c changes, and adding a new + stringForKey() API, also changed the DT__XXXX() set of functions + to handle const char * values instead of char*. Index: branches/slice/rev749/modules/NetbookInstaller/NBI.c =================================================================== --- branches/slice/rev749/modules/NetbookInstaller/NBI.c (revision 0) +++ branches/slice/rev749/modules/NetbookInstaller/NBI.c (revision 1169) @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2009 Evan Lojewski. All rights reserved. + * + */ + +#include +#include +#include + +#include "libsaio.h" + +#include "sl.h" +#include "boot.h" +#include "bootstruct.h" +#include "xml.h" +#include "ramdisk.h" +#include "drivers.h" +#include "modules.h" + +int runNetbookInstaller = 0; + +long NBI_LoadDrivers( char * dirSpec ); +void NBI_md0Ramdisk(); +void NBI_PreBoot_hook(void* arg1, void* arg2, void* arg3, void* arg4); +void NBI_loadBootGraphics(void); + +#ifndef OPTION_ROM +extern long (*LoadExtraDrivers_p)(FileLoadDrivers_t FileLoadDrivers_p); + +extern long NetLoadDrivers(char *dirSpec); +extern long FileLoadDrivers(char *dirSpec, long plugin); +#endif + +extern char gMacOSVersion[]; + + +extern long LoadDriverMKext(char *fileSpec); +extern long LoadDriverPList(char *dirSpec, char *name, long bundleType); + +extern long MatchLibraries( void ); +extern long MatchPersonalities( void ); +extern long LoadMatchedModules( void ); +extern long InitDriverSupport(void); +extern char * gExtensionsSpec; +extern char * gDriverSpec; +extern char * gFileSpec; +extern char * gTempSpec; +extern char * gFileName; + +void NetbookInstaller_start() +{ + //else printf("Unable to locate Extra/SystemVersion.LastPatched.plist\n"); + + register_hook_callback("PreBoot", &NBI_PreBoot_hook); + +} + +void NBI_PreBoot_hook(void* arg1, void* arg2, void* arg3, void* arg4) +{ + bool dummyVal = 0; + config_file_t systemVersion; + + char valid = false; + const char *val; + int len; + const char* gPrevMacOSBuildVersion; + + if (!loadConfigFile("System/Library/CoreServices/SystemVersion.plist", &systemVersion)) + { + valid = true; + } + else if (!loadConfigFile("System/Library/CoreServices/ServerVersion.plist", &systemVersion)) + { + valid = true; + } + + if (valid) + { + if (getValueForKey("ProductBuildVersion", &val, &len, &systemVersion)) + { + + if (!loadConfigFile("Extra/SystemVersion.LastPatched.plist", &systemVersion)) + { + if(getValueForKey("ProductBuildVersion", &gPrevMacOSBuildVersion, &len, &systemVersion)) + { + if(strlen(val) != strlen(gPrevMacOSBuildVersion) || + strcmp(val, gPrevMacOSBuildVersion) != 0 + ) + { + runNetbookInstaller = 1; + } + else + { + // Only allow restore from hibernation if the system hasn't changed, probably a bad idea though + //char* val="/private/var/vm/sleepimage"; + + // Do this first to be sure that root volume is mounted + //ret = GetFileInfo(0, val, &flags, &sleeptime); + + //printf("System version has not changed\n"); + //runNetbookInstaller = 0; + + } + + } + } + } + } + + + + + if (!runNetbookInstaller && getBoolForKey("recovery", &dummyVal, &bootInfo->bootConfig) && dummyVal) + { + if(dummyVal) runNetbookInstaller = 2; + } + + if(runNetbookInstaller) + { + + replace_function("_LoadDrivers", &NBI_LoadDrivers); + if(runNetbookInstaller == 1) + { + replace_function("_md0Ramdisk", &NBI_md0Ramdisk); + } + + // Force arch=i386 + -v + archCpuType = CPU_TYPE_I386; + gVerboseMode = true; + } +} + + +void NBI_md0Ramdisk() +{ + RAMDiskParam ramdiskPtr; + char filename[512]; + int fh = -1; + + // TODO: embed NBI.img in this file + // If runNetbookInstaller is true, then the system has changed states, patch it + sprintf(filename, "%s", "Extra/NetbookInstaller.img");; + fh = open(filename, 0); + + if (fh >= 0) + { + verbose("Enabling ramdisk %s\n", filename); + + ramdiskPtr.size = file_size(fh); + ramdiskPtr.base = AllocateKernelMemory(ramdiskPtr.size); + + if(ramdiskPtr.size && ramdiskPtr.base) + { + // Read new ramdisk image contents in kernel memory. + if (read(fh, (char*) ramdiskPtr.base, ramdiskPtr.size) == ramdiskPtr.size) + { + AllocateMemoryRange("RAMDisk", ramdiskPtr.base, ramdiskPtr.size, kBootDriverTypeInvalid); + Node* node = DT__FindNode("/chosen/memory-map", false); + if(node != NULL) + { + DT__AddProperty(node, "RAMDisk", sizeof(RAMDiskParam), (void*)&ramdiskPtr); + } + else + { + verbose("Unable to notify Mac OS X of the ramdisk %s.\n", filename); + } + } + else + { + verbose("Unable to read md0 image %s.\n", filename); + } + } + else + { + verbose("md0 image %s is empty.\n", filename); + } + + close(fh); + + } +} + + +long NBI_LoadDrivers( char * dirSpec ) +{ + + char dirSpecExtra[1024]; + + if ( InitDriverSupport() != 0 ) + return 0; + +#ifndef OPTION_ROM + // Load extra drivers if a hook has been installed. + if (LoadExtraDrivers_p != NULL) + { + (*LoadExtraDrivers_p)(&FileLoadDrivers); + } + + if ( gBootFileType == kNetworkDeviceType ) + { + if (NetLoadDrivers(dirSpec) != 0) { + error("Could not load drivers from the network\n"); + return -1; + } + } + else +#endif + if ( gBootFileType == kBlockDeviceType ) + { + verbose("Loading Recovery Extensions\n"); + strcpy(dirSpecExtra, "/Extra/RecoveryExtensions/"); + FileLoadDrivers(dirSpecExtra, 0); + + + // TODO: fix this, the order does matter, and it's not correct now. + // Also try to load Extensions from boot helper partitions. + if (gBootVolume->flags & kBVFlagBooter) + { + strcpy(dirSpecExtra, "/com.apple.boot.P/System/Library/"); + if (FileLoadDrivers(dirSpecExtra, 0) != 0) + { + strcpy(dirSpecExtra, "/com.apple.boot.R/System/Library/"); + if (FileLoadDrivers(dirSpecExtra, 0) != 0) + { + strcpy(dirSpecExtra, "/com.apple.boot.S/System/Library/"); + FileLoadDrivers(dirSpecExtra, 0); + } + } + } + + if (gMKextName[0] != '\0') + { + verbose("LoadDrivers: Loading from [%s]\n", gMKextName); + if ( LoadDriverMKext(gMKextName) != 0 ) + { + error("Could not load %s\n", gMKextName); + return -1; + } + } + else + { + strcpy(gExtensionsSpec, dirSpec); + strcat(gExtensionsSpec, "System/Library/"); + FileLoadDrivers(gExtensionsSpec, 0); + } + } + else + { + return 0; + } + + MatchPersonalities(); + + MatchLibraries(); + + LoadMatchedModules(); + + return 0; +} Index: branches/slice/rev749/modules/NetbookInstaller/Makefile =================================================================== --- branches/slice/rev749/modules/NetbookInstaller/Makefile (revision 0) +++ branches/slice/rev749/modules/NetbookInstaller/Makefile (revision 1169) @@ -0,0 +1,43 @@ + +MODULE_NAME = NetbookInstaller +MODULE_VERSION = "1.0.0" +MODULE_COMPAT_VERSION = "1.0.0" +MODULE_START = _$(MODULE_NAME)_start +MODULE_DEPENDENCIES = + +DIR = NetbookInstaller + +MODULE_OBJS = NBI.o + +OPTIM = -Os -Oz +DEBUG = -DNOTHING +#DEBUG = -DDEBUG_HELLO_WORLD=1 +CFLAGS = $(RC_CFLAGS) $(OPTIM) $(MORECPP) -arch i386 -g -Wmost \ + -D__ARCHITECTURE__=\"i386\" -DSAIO_INTERNAL_USER \ + -DRCZ_COMPRESSED_FILE_SUPPORT $(DEBUG) \ + -fno-builtin $(OMIT_FRAME_POINTER_CFLAG) \ + -mpreferred-stack-boundary=2 -fno-align-functions -fno-stack-protector \ + -march=pentium4 -msse2 -mfpmath=sse -msoft-float -fno-common + +DEFINES= +CONFIG = hd +INC = -I. -I.. -I$(SYMROOT) -I$(UTILDIR) -I$(LIBSADIR) -I$(LIBSAIODIR) -I$(BOOT2DIR) +LIBS= + +VPATH = $(OBJROOT):$(SYMROOT) + + + +SFILES = +CFILES = +HFILES = +EXPORTED_HFILES = +INSTALLED_HFILES = +OTHERFILES = Makefile +ALLSRC = $(SFILES) $(CFILES) \ + $(HFILES) $(OTHERFILES) +DIRS_NEEDED = $(OBJROOT) $(SYMROOT) + +all embedtheme optionrom: dylib + +include ../MakeInc.dir \ No newline at end of file Index: branches/slice/rev749/modules/KextPatcher/inftrees.c =================================================================== --- branches/slice/rev749/modules/KextPatcher/inftrees.c (revision 0) +++ branches/slice/rev749/modules/KextPatcher/inftrees.c (revision 1169) @@ -0,0 +1,330 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#define MAXBITS 15 + +const char inflate_copyright[] = + " inflate 1.2.5 Copyright 1995-2010 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work) +codetype type; +unsigned short FAR *lens; +unsigned codes; +code FAR * FAR *table; +unsigned FAR *bits; +unsigned short FAR *work; +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code here; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + int end; /* use base and extra for symbol > end */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 73, 195}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0}; + static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) { /* no symbols to code at all */ + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)1; + here.val = (unsigned short)0; + *(*table)++ = here; /* make a table to force an error */ + *(*table)++ = here; + *bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min < max; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || max != 1)) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked for LENS and DIST tables against + the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in + the initial root table size constants. See the comments in inftrees.h + for more information. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + end = 19; + break; + case LENS: + base = lbase; + base -= 257; + extra = lext; + extra -= 257; + end = 256; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if ((type == LENS && used >= ENOUGH_LENS) || + (type == DISTS && used >= ENOUGH_DISTS)) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + here.bits = (unsigned char)(len - drop); + if ((int)(work[sym]) < end) { + here.op = (unsigned char)0; + here.val = work[sym]; + } + else if ((int)(work[sym]) > end) { + here.op = (unsigned char)(extra[work[sym]]); + here.val = base[work[sym]]; + } + else { + here.op = (unsigned char)(32 + 64); /* end of block */ + here.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + next[(huff >> drop) + fill] = here; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if ((type == LENS && used >= ENOUGH_LENS) || + (type == DISTS && used >= ENOUGH_DISTS)) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } + } + + /* + Fill in rest of table for incomplete codes. This loop is similar to the + loop above in incrementing huff for table indices. It is assumed that + len is equal to curr + drop, so there is no loop needed to increment + through high index bits. When the current sub-table is filled, the loop + drops back to the root table to fill in any remaining entries there. + */ + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)(len - drop); + here.val = (unsigned short)0; + while (huff != 0) { + /* when done with sub-table, drop back to root table */ + if (drop != 0 && (huff & mask) != low) { + drop = 0; + len = root; + next = *table; + here.bits = (unsigned char)len; + } + + /* put invalid code marker in table */ + next[huff >> drop] = here; + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; +} Index: branches/slice/rev749/modules/KextPatcher/kext_patcher.c =================================================================== --- branches/slice/rev749/modules/KextPatcher/kext_patcher.c (revision 0) +++ branches/slice/rev749/modules/KextPatcher/kext_patcher.c (revision 1169) @@ -0,0 +1,823 @@ + /* + * Copyright (c) 2010 Evan Lojewski. All rights reserved. + * + * KextPather + * This is an experimental module that I'm looking into implimenting. + * The main purpose is to replace the need for programs such as + * NetbookInstaller's kext patching routines. THis way, Apple's kexts can be + * patched whe loaded instead. (eg: GMA950 kext, Bluetooth + Wifi kexts) + */ + +#include "libsaio.h" +#include "zlib.h" +#include "kext_patcher.h" +#include "boot.h" +#include "bootstruct.h" +#include "pci.h" +#include "drivers.h" +#include "mkext.h" +#include "modules.h" +#include "hex_editor.h" + + +#define kHDACodec "HDACodec" + + +#ifndef DEBUG_KEXT_PATCHER +#define DEBUG_KEXT_PATCHER 0 +#endif + +#if DEBUG_KEXT_PATCHER +#define DBG(x...) verbose(x) +#else +#define DBG(x...) +#endif + + +bool patch_kext(TagPtr plist, char* plistbuffer, void* start); +bool patch_gma_kexts(TagPtr plist, char* plistbuffer, void* start); +bool patch_bcm_kext(TagPtr plist, char* plistbuffer, void* start); +bool patch_hda_kext(TagPtr plist, char* plistbuffer, void* start); +bool patch_hda_controller(TagPtr plist, char* plistbuffer, void* start); + +int chartohex(char c); + +static void * z_alloc(void *, u_int items, u_int size); +static void z_free(void *, void *ptr); + +uint16_t patch_gma_deviceid = 0; +uint16_t patch_bcm_deviceid = 0; + +// TODO: add detection code +uint16_t patch_hda_codec = 0x00; + +#define NEEDS_PATCHING (patch_bcm_deviceid || patch_gma_deviceid || patch_hda_codec) + +typedef struct z_mem { + uint32_t alloc_size; + uint8_t data[0]; +} z_mem; + +/* + * Space allocation and freeing routines for use by zlib routines. + */ +void * +z_alloc(void * notused __unused, u_int num_items, u_int size) +{ + void * result = NULL; + z_mem * zmem = NULL; + uint32_t total = num_items * size; + uint32_t allocSize = total + sizeof(zmem); + + zmem = (z_mem *)malloc(allocSize); + if (!zmem) { + goto finish; + } + zmem->alloc_size = allocSize; + result = (void *)&(zmem->data); +finish: + return result; +} + +void +z_free(void * notused __unused, void * ptr) +{ + uint32_t * skipper = (uint32_t *)ptr - 1; + z_mem * zmem = (z_mem *)skipper; + free((void *)zmem); + return; +} + + +//unsigned long Adler32( unsigned char * buffer, long length ); + +void KextPatcher_hook(void* current, void* arg2, void* arg3, void* arg4); + +/** + ** KextPatcher_start -> module start + ** Notified the module system that this module will hook into the + ** LoadMatchedModules and LoadDriverMKext functions + **/ +void KextPatcher_start() +{ + // Hooks into the following: + // execute_hook("LoadDriverMKext", (void*)package, (void*) length, NULL, NULL); + // execute_hook("LoadMatchedModules", module, &length, executableAddr, NULL); + + register_hook_callback("PCIDevice", &KextPatcher_hook); + //register_hook_callback("LoadMatchedModules", &kext_loaded); + register_hook_callback("LoadDriverMKext", &mkext_loaded); + +} + +/** + ** kext_loaded -> Called whenever a kext is in read into memory + ** This function will be used to patch kexts ( eg AppleInteIntegratedFramebuffer) + ** and their plists when they are loaded into memmory + **/ +void kext_loaded(void* moduletmp, void* lengthprt, void* executableAddr, void* arg3) +{ + + //ModulePtr module = moduletmp; + //long length = *(long*)lengthprt; + //long length2 = strlen(module->plistAddr); + // *(long*)lengthprt = length2 + 5 * 1024 * 1024; + + //printf("Loading %s, lenght is %d, executable is 0x%X\n", module->plistAddr, length, executableAddr); + //getc(); +} + +/** + ** mkext_loaded -> Called whenever an mkext is in read into memory + ** This function will be used to patch mkext. Matching kexts will be + ** Extracted, modified, and then compressed again. Note: I need to determine + ** what sort of slowdown this will cause and if it's worth implimenting. + **/ + +void mkext_loaded(void* filespec, void* packagetmp, void* lengthtmp, void* arg3) +{ + const char* hda_codec; + int len = 0; + if (getValueForKey(kHDACodec, &hda_codec, &len, &bootInfo->bootConfig)) + { + patch_hda_codec = 0; + int index = 0; + while(len--) + { + patch_hda_codec <<= 4; + patch_hda_codec |= chartohex(hda_codec[index]); + index++; + } + } + + if(!NEEDS_PATCHING) return; // No need to apply a patch, hardware doesn't need it + + int version = 0; + //int length = *((int*)lengthtmp); + mkext_basic_header* package = packagetmp; + + // Verify the MKext. + if (( MKEXT_GET_MAGIC(package) != MKEXT_MAGIC ) || + ( MKEXT_GET_SIGNATURE(package) != MKEXT_SIGN ) || + ( MKEXT_GET_LENGTH(package) > kLoadSize ) || + ( MKEXT_GET_CHECKSUM(package) != + Adler32((unsigned char *)&package->version, MKEXT_GET_LENGTH(package) - 0x10) ) ) + { + msglog("mkext verification failed, do not patch\n"); + return; + // Don't try to patch a b + } + + /* + if(strcmp(filespec, "/System/Library/Caches/com.apple.kext.caches/Startup/Extensions.mkext") == 0) + { + printf("Invalidating mkext %s\n", filespec); + // 10.6 cache folder. Doesn't contain certain extensions we need, so invalidate it. + //package->adler32++; + // NOTE: double check that this is needed + package->magic = 0x00; + return; + }*/ + + + version = MKEXT_GET_VERSION(package); + + if(version == 0x01008000) // mkext1 + { + // mkext1 uses lzss + mkext1_header* package = packagetmp; + int i; + for(i = 0; i < MKEXT_GET_COUNT(package); i++) + { + DBG("Parsing kext %d\n", i); + //mkext_kext* kext = MKEXT1_GET_KEXT(package, i); + // uses decompress_lzss + // TODO: handle kext + + } + } + else if((version & 0xFFFF0000) == 0x02000000) // mkext2 + { + DBG("Mkext2 package located at 0x%X\n", package); + + // mkext2 uses zlib + mkext2_header* package = packagetmp; + z_stream zstream; + bool zstream_inited = false; + int zlib_result; + int plist_offset = MKEXT2_GET_PLIST(package); + + char* plist = malloc(MKEXT2_GET_PLIST_FULLSIZE(package)); + + bzero(&zstream, sizeof(zstream)); + zstream.next_in = (UInt8*)((char*)package + plist_offset); + zstream.avail_in = MKEXT2_GET_PLIST_COMPSIZE(package); + + zstream.next_out = (UInt8*)plist; + zstream.avail_out = MKEXT2_GET_PLIST_FULLSIZE(package); + + zstream.zalloc = z_alloc; + zstream.zfree = z_free; + + zlib_result = inflateInit(&zstream); + if (Z_OK != zlib_result) + { + printf("ZLIB Error: %s\n", zstream.msg); + getc(); + } + else + { + zstream_inited = true; + } + + + zlib_result = inflate(&zstream, Z_FINISH); + if (zstream_inited) inflateEnd(&zstream); + + DBG("Inflated result is %d, in: %d bytes, out: %d bytes\n", zlib_result, zstream.total_in, zstream.total_out); + if (zlib_result == Z_STREAM_END || zlib_result == Z_OK) + { + config_file_t plistData; + config_file_t allDicts; + bzero(&plistData, sizeof(plistData)); + bzero(&allDicts, sizeof(allDicts)); + + XMLParseFile( plist, &plistData.dictionary ); + + int count = 0; + + allDicts.dictionary = XMLGetProperty(plistData.dictionary, kMKEXTInfoDictionariesKey); + //count = XMLTagCount(allDicts.dictionary); + + //DBG("Plist contains %d kexts\n", count); + + + bool patched = false; + for(count = XMLTagCount(allDicts.dictionary); + count > 0; + count--) + { + TagPtr kextEntry = XMLGetElement(allDicts.dictionary, count); + patched |= patch_kext(kextEntry, plist, package); + } + + + if(patched) + { + zstream_inited = false; + // Recompress the plist + bzero(&zstream, sizeof(zstream)); + zstream.next_in = (UInt8*)plist; + zstream.next_out = (UInt8*)package + plist_offset; + zstream.avail_in = MKEXT2_GET_PLIST_FULLSIZE(package); + zstream.avail_out = MKEXT2_GET_PLIST_FULLSIZE(package)<<2; // Give us some extra free space, just in case + zstream.zalloc = Z_NULL; + zstream.zfree = Z_NULL; + zstream.opaque = Z_NULL; + + + zlib_result = deflateInit2(&zstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,15, 8 /* memLevel */, Z_DEFAULT_STRATEGY); + if (Z_OK != zlib_result) { + printf("ZLIB Deflate Error: %s\n", zstream.msg); + getc(); + } + else + { + zstream_inited = true; + } + + zlib_result = deflate(&zstream, Z_FINISH); + + if (zlib_result == Z_STREAM_END) + { + DBG("Deflated result is %d, in: %d bytes, out: %d bytes, full: %d\n", zlib_result, zstream.total_in, zstream.total_out, MKEXT2_GET_PLIST_FULLSIZE(package)); + } + else if (zlib_result == Z_OK) + { + /* deflate filled output buffer, meaning the data doesn't compress. + */ + DBG("Deflated result is %d, in: %d bytes, out: %d bytes, full: %d\n", zlib_result, zstream.total_in, zstream.total_out, MKEXT2_GET_PLIST_FULLSIZE(package)); + + } + else if (zlib_result != Z_STREAM_ERROR) + { + printf("ZLIB Deflate Error: %s\n", zstream.msg); + getc(); + } + + if(zstream.total_out != MKEXT2_GET_PLIST_COMPSIZE(package)) + { + // Update the mkext length + MKEXT2_HDR_CAST(package)->length = MKEXT_SWAP(MKEXT_GET_LENGTH(package) - MKEXT2_GET_PLIST_COMPSIZE(package) + zstream.total_out); + MKEXT2_HDR_CAST(package)->plist_compressed_size = MKEXT_SWAP(zstream.total_out); + *((int*)lengthtmp) -= MKEXT2_GET_PLIST_COMPSIZE(package); + *((int*)lengthtmp) += zstream.total_out; + } + + if (zstream_inited) deflateEnd(&zstream); + + + + // re adler32 the new mkext2 package + MKEXT_HDR_CAST(package)->adler32 = + MKEXT_SWAP(Adler32((unsigned char *)&package->version, + MKEXT_GET_LENGTH(package) - 0x10)); + } + } + else + { + printf("ZLIB Error: %s\n", zstream.msg); + getc(); + } + + //config_file_t mkextPlist; + //ParseXMLFile((char*) plist, &mkextPlist.dictionary); + + + + + + /* int i; + for(i = 0; i < MKEXT_GET_COUNT(package); i++) + { + printf("Parsing kext %d\n", i); + } + */ + + + } + + + DBG("Loading %s, version 0x%x\n", filespec, version); + //getc(); +} + +// FIXME: only handles mkext2 entries +bool patch_kext(TagPtr plist, char* plistbuffer, void* start) +{ + char* bundleID; + + if(XMLGetProperty(plist, kMKEXTExecutableKey) == NULL) return false; // Kext is a plist only kext, don't patch + + bundleID = XMLCastString(XMLGetProperty(plist, kPropCFBundleIdentifier)); + + + if(patch_gma_deviceid && + ( + (strcmp(bundleID, "com.apple.driver.AppleIntelGMA950") == 0) || + (strcmp(bundleID, "com.apple.driver.AppleIntelIntegratedFramebuffer") == 0) + ) + ) + { + if(strcmp(bundleID, "com.apple.driver.AppleIntelIntegratedFramebuffer") == 0 || patch_gma_deviceid == 0x27ae) + { + return patch_gma_kexts(plist, plistbuffer, start); + } + else + { + return patch_gma_kexts(plist, plistbuffer, start); + } + + } + else if(patch_bcm_deviceid && (strcmp(bundleID, "com.apple.driver.AirPortBrcm43xx") == 0)) + { + return patch_bcm_kext(plist, plistbuffer, start); + + } + else if(patch_hda_codec && strcmp(bundleID, "com.apple.driver.AppleHDA") == 0) + { + return patch_hda_kext(plist, plistbuffer, start); + + } + + else if(patch_hda_codec && strcmp(bundleID, "com.apple.driver.AppleHDAController") == 0) + { + return patch_hda_controller(plist, plistbuffer, start); + + } + + return false; +} + +void KextPatcher_hook(void* arg1, void* arg2, void* arg3, void* arg4) +{ + pci_dt_t* current = arg1; + if(current) + { + switch(current->class_id) + { + case PCI_CLASS_DISPLAY_VGA: + if(current->vendor_id == 0x8086 && + ( + current->device_id == 0x27AE || + current->device_id == 0xA001 || + current->device_id == 0xA002 || + current->device_id == 0xA011 || + current->device_id == 0xA012 + + ) + ) + { + patch_gma_deviceid = current->device_id; + } + break; + + case PCI_CLASS_NETWORK_OTHER: + + // Patch BCM43xx + if(current->vendor_id == 0x14E4 && ((current->device_id & 0xFF00) == 0x4300)) + { + patch_bcm_deviceid = current->device_id; + } + break; + } + } +} + + +bool patch_hda_controller(TagPtr plist, char* plistbuffer, void* start) +{ + return false; + // change the PCI class code to match to. Note: A LegacyHDA plist should do this on it's own + // As such, it's disabled + + // TODO: read class code + TagPtr personality; + personality = XMLCastDict(XMLGetProperty(plist, kPropIOKitPersonalities)); + personality = XMLGetProperty(personality, (const char*)"BuiltInHDA"); + TagPtr match_class =XMLCastArray(XMLGetProperty(personality, (const char*)"IOPCIClassMatch")); + + + char* new_str = malloc(sizeof("0xXXXX000&0xFFFE0000")); + sprintf(new_str, "0x04030000&0xFFFE0000"); // todo, pass in actual class id + + + char* orig_string = "0x04020000&0xFFFE0000"; //XMLCastString(match_class); + + verbose("Attemting to replace '%s' with '%s'\n", orig_string, new_str); + + // TODO: verify string doesn't exist first. + + replace_string(orig_string, new_str, plistbuffer + XMLCastStringOffset(match_class), 1024); + + return true; + +} + + +bool patch_hda_kext(TagPtr plist, char* plistbuffer, void* start) +{ + uint16_t find_codec = 0; + int full_size, compressed_size, executable_offset; + void* compressed_data; + mkext2_file_entry* kext; + int zlib_result; + z_stream zstream; + bool zstream_inited = false; + + switch(patch_hda_codec & 0xFF00) + { + case 0x0200: + find_codec = 0x0262; + break; + + case 0x0800: + find_codec = 0x0885; + break; + + case 0x0600: // specificaly the 662 + find_codec = 0x0885; + break; + } + if(!find_codec) return false; // notify caller that we aren't patching the kext + + executable_offset = XMLCastInteger(XMLGetProperty(plist, kMKEXTExecutableKey)); + kext = (void*)((char*)start + executable_offset); + + full_size = MKEXT2_GET_ENTRY_FULLSIZE(kext); + compressed_size = MKEXT2_GET_ENTRY_COMPSIZE(kext); + compressed_data = MKEXT2_GET_ENTRY_DATA(kext); + executable_offset = XMLCastInteger(XMLGetProperty(plist, kMKEXTExecutableKey)); + + + char* executable = malloc(full_size); + + bzero(&zstream, sizeof(zstream)); + zstream.next_in = (UInt8*)compressed_data; + zstream.avail_in = compressed_size; + + zstream.next_out = (UInt8*)executable; + zstream.avail_out = full_size; + + zstream.zalloc = z_alloc; + zstream.zfree = z_free; + + zlib_result = inflateInit(&zstream); + if (Z_OK != zlib_result) + { + printf("ZLIB Inflate Error: %s\n", zstream.msg); + getc(); + } + else + { + zstream_inited = true; + } + + + zlib_result = inflate(&zstream, Z_FINISH); + + DBG("Inflated result is %d, in: %d bytes, out: %d bytes, full: %d\n", zlib_result, zstream.total_in, zstream.total_out, full_size); + + //int times = + replace_word(0x10EC0000 | (find_codec), 0x10EC0000 | (patch_hda_codec), executable, zstream.total_out); + if (zstream_inited) inflateEnd(&zstream); + + + zstream.next_in = (UInt8*)executable; + zstream.next_out = (UInt8*)compressed_data; + + zstream.avail_in = full_size; + zstream.avail_out = compressed_size<<1; + zstream.zalloc = Z_NULL; + zstream.zfree = Z_NULL; + zstream.opaque = Z_NULL; + + + + // Recompress the executable + zlib_result = deflateInit2(&zstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,15, 8 /* memLevel */, Z_DEFAULT_STRATEGY); + if (Z_OK != zlib_result) { + printf("ZLIB Deflate Error: %s\n", zstream.msg); + getc(); + } + else + { + zstream_inited = true; + } + + zlib_result = deflate(&zstream, Z_FINISH); + + if (zlib_result == Z_STREAM_END) + { + DBG("Deflated result is %d, avail: %d bytes, out: %d bytes, full: %d\n", zlib_result, compressed_size, zstream.total_out, full_size); + } + else if (zlib_result == Z_OK) + { + /* deflate filled output buffer, meaning the data doesn't compress. + */ + DBG("Buffer FULL: deflated result is %d, avail: %d bytes, out: %d bytes, full: %d\n", zlib_result, compressed_size, zstream.total_out, full_size); + printf("Unable to patch AppleHDA\n"); + + } + else if (zlib_result != Z_STREAM_ERROR) + { + printf("AppleHDA: ZLIB Deflate Error: %s\n", zstream.msg); + getc(); + } + + if (zstream_inited) deflateEnd(&zstream); + + if(zstream.total_out < compressed_size) kext->compressed_size = MKEXT_SWAP(zstream.total_out); + + + free(executable); + + return true; + +} + +bool patch_bcm_kext(TagPtr plist, char* plistbuffer, void* start) +{ + TagPtr personality; + personality = XMLCastDict(XMLGetProperty(plist, kPropIOKitPersonalities)); + personality = XMLGetProperty(personality, (const char*)"Broadcom 802.11 PCI"); + TagPtr match_names =XMLCastArray(XMLGetProperty(personality, (const char*)"IONameMatch")); + + + char* new_str = malloc(sizeof("pci14e4,xxxx")); + sprintf(new_str, "pci14e4,%02x", patch_bcm_deviceid); + + // Check to see if we *really* need to modify the plist, if not, return false + // so that *if* this were going ot be the only modified kext, the repacking code + // won't need to be executed. + int count = XMLTagCount(match_names); + while(count) + { + count--; + TagPtr replace = XMLGetElement(match_names, count); // Modify the second entry + char* orig_string = XMLCastString(replace); + if(strcmp(orig_string, new_str) == 0) return false; + } + + + TagPtr replace = XMLGetElement(match_names, 1); // Modify the second entry + char* orig_string = XMLCastString(replace); + + + // TODO: verify string doesn't exist first. + + replace_string(orig_string, new_str, plistbuffer + XMLCastStringOffset(replace), 10240); + + return true; +} + +bool patch_gma_kexts(TagPtr plist, char* plistbuffer, void* start) +{ + // TODO: clean up this function / split into two / etc + int exeutable_offset, full_size, compressed_size; + TagPtr personality; + long offset; + int zlib_result; + z_stream zstream; + bool zstream_inited = false; + mkext2_file_entry* kext; + void* compressed_data; + + exeutable_offset = XMLCastInteger(XMLGetProperty(plist, kMKEXTExecutableKey)); + kext = (void*)((char*)start + exeutable_offset); + + full_size = MKEXT2_GET_ENTRY_FULLSIZE(kext); + compressed_size = MKEXT2_GET_ENTRY_COMPSIZE(kext); + compressed_data = MKEXT2_GET_ENTRY_DATA(kext); + + personality = XMLCastDict(XMLGetProperty(plist, kPropIOKitPersonalities)); + + + + char* executable = malloc(full_size); + + bzero(&zstream, sizeof(zstream)); + zstream.next_in = (UInt8*)compressed_data; + zstream.avail_in = compressed_size; + + zstream.next_out = (UInt8*)executable; + zstream.avail_out = full_size; + + zstream.zalloc = z_alloc; + zstream.zfree = z_free; + + zlib_result = inflateInit(&zstream); + if (Z_OK != zlib_result) + { + printf("ZLIB Inflate Error: %s\n", zstream.msg); + getc(); + } + else + { + zstream_inited = true; + } + + + zlib_result = inflate(&zstream, Z_FINISH); + + DBG("Inflated result is %d, in: %d bytes, out: %d bytes, full: %d\n", zlib_result, zstream.total_in, zstream.total_out, full_size); + + char* newstring = malloc(sizeof("0x00008086")); + sprintf(newstring, "0x%04x", 0x8086 | (patch_gma_deviceid << 16)); + + + if(XMLGetProperty(personality, (const char*)"Intel915")) + { + verbose("Patching AppleIntelGMA950.kext\n"); + //getc(); + + personality = XMLGetProperty(personality, (const char*)"Intel915"); + // IOAccelerator kext + + offset = XMLCastStringOffset(XMLGetProperty(personality, (const char*)"IOPCIPrimaryMatch")); + replace_string("0x27A28086", newstring, plistbuffer + offset, 10240); + replace_word(0x27A28086, 0x8086 | (patch_gma_deviceid << 16), executable, zstream.total_out); + + } + else if(XMLGetProperty(personality, (const char*)"AppleIntelIntegratedFramebuffer")) + { + verbose("Patching AppleIntelIntegratedFramebuffer\n"); + //getc(); + + personality = XMLGetProperty(personality, (const char*)"AppleIntelIntegratedFramebuffer"); + // Framebuffer Kext + + if((patch_gma_deviceid & 0xFF00) == 0xA000) // GMA3150 + { + // Cursor corruption fix. + // This patch changes the cursor address from + // a physical address (used in the gma950) to an offset (used in the gma3150). + //s {0x8b, 0x55, 0x08, 0x83, 0xba, 0xb0, 0x00, 0x00, 0x00, 0x01, 0x7e, 0x36, 0x89, 0x04, 0x24, 0xe8, 0x6b, 0xbc, 0xff, 0xff}; + char find_bytes[] = {0x8b, 0x55, 0x08, 0x83, 0xba, 0xb0, 0x00, 0x00, 0x00, 0x01, 0x7e, 0x36, 0x89, 0x04, 0x24, 0xe8/*, 0x32, 0xbb, 0xff, 0xff*/}; // getPhysicalAddress() and more + char new_bytes[] = {0xb8, 0x00, 0x00, 0x00, 0x02, 0xEB, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // jump past getPhysicalAddress binding. NOTE: last six bytes are unusable + replace_bytes(find_bytes, sizeof(find_bytes), new_bytes, sizeof(new_bytes), executable, zstream.total_out); + + + } + offset = XMLCastStringOffset(XMLGetProperty(personality, (const char*)"IOPCIPrimaryMatch")); + replace_string("0x27A28086", newstring, plistbuffer + offset, 10240); + replace_word(0x27A28086, 0x8086 | (patch_gma_deviceid << 16), executable, zstream.total_out); + + } + else if(XMLGetProperty(personality, (const char*)"Intel965")) + { + verbose("Patching AppleIntelGMAX3100.kext\n"); + + personality = XMLGetProperty(personality, (const char*)"Intel965"); + + offset = XMLCastStringOffset(XMLGetProperty(personality, (const char*)"IOPCIPrimaryMatch")); + + //printf("Intel965\n"); + //printf("Replacing %c%c%c%c\n", (plistbuffer + offset)[0], (plistbuffer + offset)[1], (plistbuffer + offset)[2], (plistbuffer + offset)[3]); + //getc(); + + + //return true; + + replace_string("0x2a028086", newstring, plistbuffer + offset, 10240); + //replace_word(0x2A028086, 0x8086 | (patch_gma_deviceid << 16), executable, zstream.total_out); + } + else if(XMLGetProperty(personality, (const char*)"AppleIntelGMAX3100FB")) + { + verbose("Patching AppleIntelGMAX3100FB.kext\n"); + //getc(); + personality = XMLGetProperty(personality, (const char*)"AppleIntelGMAX3100FB"); + + offset = XMLCastStringOffset(XMLGetProperty(personality, (const char*)"IOPCIPrimaryMatch")); + replace_string("0x2A028086", newstring, plistbuffer + offset, 10240); + replace_word(0x2A028086, 0x8086 | (patch_gma_deviceid << 16), executable, zstream.total_out); + } + else + { + return false; + } + + + if (zstream_inited) inflateEnd(&zstream); + + + zstream.next_in = (UInt8*)executable; + zstream.next_out = (UInt8*)compressed_data; + + zstream.avail_in = full_size; + zstream.avail_out = compressed_size; + zstream.zalloc = Z_NULL; + zstream.zfree = Z_NULL; + zstream.opaque = Z_NULL; + + + + // Recompress the eecutable + zlib_result = deflateInit2(&zstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,15, 8 /* memLevel */, Z_DEFAULT_STRATEGY); + if (Z_OK != zlib_result) { + printf("ZLIB Deflate Error: %s\n", zstream.msg); + getc(); + } + else + { + zstream_inited = true; + } + + zlib_result = deflate(&zstream, Z_FINISH); + + if (zlib_result == Z_STREAM_END) + { + DBG("Deflated result is %d, avail: %d bytes, out: %d bytes, full: %d\n", zlib_result, compressed_size, zstream.total_out, full_size); + } + else if (zlib_result == Z_OK) + { + /* deflate filled output buffer, meaning the data doesn't compress. + */ + printf("Deflated result is %d, in: %d bytes, out: %d bytes, full: %d\n", zlib_result, zstream.total_in, zstream.total_out, full_size); + printf("ERROR: Unable to compress patched kext, not enough room.\n"); + pause(); + + } + else if (zlib_result != Z_STREAM_ERROR) + { + printf("ZLIB Deflate Error: %s\n", zstream.msg); + getc(); + } + if(zstream.total_out < compressed_size) kext->compressed_size = MKEXT_SWAP(zstream.total_out); + + + + + if (zstream_inited) deflateEnd(&zstream); + + free(executable); + + return true; +} + +int chartohex(char c) +{ + if(c <= '9' && c >= '0') + { + return c - '0'; // c is between 0 and 9 + } + else if(c <= 'F' && c >= 'A') + { + return c - 'A' + 10; // c = 10 - 15; + } + else if(c <= 'f' && c >= 'a') + { + return c - 'a' + 10; // c = 10 - 15; + } + return 0; +} \ No newline at end of file Index: branches/slice/rev749/modules/KextPatcher/include/hex_editor.h =================================================================== --- branches/slice/rev749/modules/KextPatcher/include/hex_editor.h (revision 0) +++ branches/slice/rev749/modules/KextPatcher/include/hex_editor.h (revision 1169) @@ -0,0 +1,17 @@ +/* + * hex_editor.h + * + * + * Created by Meklort on 10/19/10. + * Copyright 2010 Evan Lojewski. All rights reserved. + * + */ +#ifndef H_HEX_EDITOR +#define H_HEX_EDITOR +#include "libsaio.h" + +int replace_patern(char* pattern, char* repalcement, char* buffer, long buffer_size); +int replace_word(uint32_t pattern, uint32_t repalcement, char* buffer, long buffer_size); +void replace_string(char* find, char* replace, char* string, int length); +void replace_bytes(char* find, int find_size, char* replace, int replace_size, char* exec, int length); +#endif /* H_HEX_EDITOR */ \ No newline at end of file Index: branches/slice/rev749/modules/KextPatcher/include/inffast.h =================================================================== --- branches/slice/rev749/modules/KextPatcher/include/inffast.h (revision 0) +++ branches/slice/rev749/modules/KextPatcher/include/inffast.h (revision 1169) @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start)); Index: branches/slice/rev749/modules/KextPatcher/include/inffixed.h =================================================================== --- branches/slice/rev749/modules/KextPatcher/include/inffixed.h (revision 0) +++ branches/slice/rev749/modules/KextPatcher/include/inffixed.h (revision 1169) @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. It + is part of the implementation of the compression library and + is subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; Index: branches/slice/rev749/modules/KextPatcher/include/inftrees.h =================================================================== --- branches/slice/rev749/modules/KextPatcher/include/inftrees.h (revision 0) +++ branches/slice/rev749/modules/KextPatcher/include/inftrees.h (revision 1169) @@ -0,0 +1,62 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2005, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of the dynamic table. The maximum number of code structures is + 1444, which is the sum of 852 for literal/length codes and 592 for distance + codes. These values were found by exhaustive searches using the program + examples/enough.c found in the zlib distribtution. The arguments to that + program are the number of symbols, the initial root table size, and the + maximum bit length of a code. "enough 286 9 15" for literal/length codes + returns returns 852, and "enough 30 6 15" for distance codes returns 592. + The initial root table size (9 or 6) is found in the fifth argument of the + inflate_table() calls in inflate.c and infback.c. If the root table size is + changed, then these maximum sizes would be need to be recalculated and + updated. */ +#define ENOUGH_LENS 852 +#define ENOUGH_DISTS 592 +#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) + +/* Type of code to build for inflate_table() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); Index: branches/slice/rev749/modules/KextPatcher/include/zconf.h =================================================================== --- branches/slice/rev749/modules/KextPatcher/include/zconf.h (revision 0) +++ branches/slice/rev749/modules/KextPatcher/include/zconf.h (revision 1169) @@ -0,0 +1,428 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2010 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ + +/* all linked symbols */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzgetc z_gzgetc +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzwrite z_gzwrite +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetHeader z_inflateGetHeader +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# define uncompress z_uncompress +# define zError z_zError +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# define gzFile z_gzFile +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#ifdef STDC +//# include /* for off_t */ +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +//# include /* for SEEK_* and off_t */ +# ifdef VMS +//# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +#endif + +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 +# define z_off64_t off64_t +#else +# define z_off64_t z_off_t +#endif + +#if defined(__OS400__) +# define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ Index: branches/slice/rev749/modules/KextPatcher/include/zlib.h =================================================================== --- branches/slice/rev749/modules/KextPatcher/include/zlib.h (revision 0) +++ branches/slice/rev749/modules/KextPatcher/include/zlib.h (revision 1169) @@ -0,0 +1,1613 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.5, April 19th, 2010 + + Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.5" +#define ZLIB_VERNUM 0x1250 +#define ZLIB_VER_MAJOR 1 +#define ZLIB_VER_MINOR 2 +#define ZLIB_VER_REVISION 5 +#define ZLIB_VER_SUBREVISION 0 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed data. + This version of the library supports only one compression method (deflation) + but other algorithms will be added later and will have the same stream + interface. + + Compression can be done in a single step if the buffers are large enough, + or can be done by repeated calls of the compression function. In the latter + case, the application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip streams in memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never crash + even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has dropped + to zero. It must update next_out and avail_out when avail_out has dropped + to zero. The application must initialize zalloc, zfree and opaque before + calling the init function. All other fields are set by the compression + library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this if + the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers + returned by zalloc for objects of exactly 65536 bytes *must* have their + offset normalized to zero. The default allocation function provided by this + library ensures this (see zutil.c). To reduce memory requirements and avoid + any allocation of 64K objects, at the expense of compression ratio, compile + the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or progress + reports. After compression, total_in holds the total size of the + uncompressed data and may be saved for use in the decompressor (particularly + if the decompressor wants to decompress everything in a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +#define Z_TREES 6 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is not + compatible with the zlib.h header file used by the application. This check + is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. If + zalloc and zfree are set to Z_NULL, deflateInit updates them to use default + allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at all + (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION + requests a default compromise between speed and compression (currently + equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if level is not a valid compression level, or + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). msg is set to null + if there is no error message. deflateInit does not perform any compression: + this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). Some + output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating avail_in or avail_out accordingly; avail_out should + never be zero before the call. The application can consume the compressed + output when it wants, for example when the output buffer is full (avail_out + == 0), or after each call of deflate(). If deflate returns Z_OK and with + zero avail_out, it must be called again after making room in the output + buffer because there might be more output pending. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumulate before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In + particular avail_in is zero after the call if enough output space has been + provided before the call.) Flushing may degrade compression for some + compression algorithms and so it should be used only when necessary. This + completes the current deflate block and follows it with an empty stored block + that is three bits plus filler bits to the next byte, followed by four bytes + (00 00 ff ff). + + If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the + output buffer, but the output is not aligned to a byte boundary. All of the + input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. + This completes the current deflate block and follows it with an empty fixed + codes block that is 10 bits long. This assures that enough bytes are output + in order for the decompressor to finish the block before the empty fixed code + block. + + If flush is set to Z_BLOCK, a deflate block is completed and emitted, as + for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to + seven bits of the current block are held to be written as the next byte after + the next deflate block is completed. In this case, the decompressor may not + be provided enough bits at this point in order to complete decompression of + the data provided so far to the compressor. It may need to wait for the next + block to be emitted. This is for advanced applications that need to control + the emission of deflate blocks. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there was + enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the stream + are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least the + value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered + binary. This field is only for information purposes and does not affect the + compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, msg + may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the + exact value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit() does not process any header information -- that is deferred + until inflate() is called. +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing will + resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there is + no more input data or no more space in the output buffer (see below about + the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating the next_* and avail_* values accordingly. The + application can consume the uncompressed output when it wants, for example + when the output buffer is full (avail_out == 0), or after each call of + inflate(). If inflate returns Z_OK and with zero avail_out, it must be + called again after making room in the output buffer because there might be + more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, + Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() + stop if and when it gets to the next deflate block boundary. When decoding + the zlib or gzip format, this will cause inflate() to return immediately + after the header and before the first block. When doing a raw inflate, + inflate() will go ahead and process the first block, and will return when it + gets to the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 if + inflate() is currently decoding the last block in the deflate stream, plus + 128 if inflate() returned immediately after decoding an end-of-block code or + decoding the complete header up to just before the first byte of the deflate + stream. The end-of-block will not be indicated until all of the uncompressed + data from that block has been written to strm->next_out. The number of + unused bits may in general be greater than seven, except when bit 7 of + data_type is set, in which case the number of unused bits will be less than + eight. data_type is set as noted here every time inflate() returns for all + flush options, and so can be used to determine the amount of currently + consumed input in bits. + + The Z_TREES option behaves as Z_BLOCK does, but it also returns when the + end of each deflate block header is reached, before any actual data in that + block is decoded. This allows the caller to determine the length of the + deflate block header for later use in random access within a deflate block. + 256 is added to the value of strm->data_type when inflate() returns + immediately after reaching the end of the deflate block header. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step (a + single call of inflate), the parameter flush should be set to Z_FINISH. In + this case all pending input is processed and all pending output is flushed; + avail_out must be large enough to hold all the uncompressed data. (The size + of the uncompressed data may have been saved by the compressor for this + purpose.) The next operation on this stream must be inflateEnd to deallocate + the decompression state. The use of Z_FINISH is never required, but can be + used to inform inflate that a faster approach may be used for the single + inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK or Z_TREES is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() can decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically, if requested when + initializing with inflateInit2(). Any information contained in the gzip + header is not retained, so applications that need that information should + instead use raw inflate, see inflateInit2() below, or inflateBack() and + perform their own processing of the gzip header and trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may + then call inflateSync() to look for a good compression block if a partial + recovery of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by the + caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), no + header crc, and the operating system will be set to 255 (unknown). If a + gzip stream is being written, strm->adler is a crc32 instead of an adler32. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but is + slow and reduces compression ratio; memLevel=9 uses maximum memory for + optimal speed. The default value is 8. See zconf.h for total memory usage + as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as + fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The + strategy parameter only affects the compression ratio but not the + correctness of the compressed output even if it is not set appropriately. + Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler + decoder for special applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid + method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is + incompatible with the version assumed by the caller (ZLIB_VERSION). msg is + set to null if there is no error message. deflateInit2 does not perform any + compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any call + of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size + provided in deflateInit or deflateInit2. Thus the strings most likely to be + useful should be put at the end of the dictionary, not at the front. In + addition, the current implementation of deflate will use at most the window + size minus 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and can + consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. The + stream will keep the same compression level and any other attributes that + may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different strategy. + If the compression level is changed, the input available so far is + compressed with the old level (and may be flushed); the new level will take + effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to be + compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if + strm->avail_out was zero. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() or + deflateInit2(), and after deflateSetHeader(), if used. This would be used + to allocate an output buffer for deflation in a single pass, and so would be + called before deflate(). +*/ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the bits + leftover from a previous deflate stream when appending to it. As such, this + function can only be used for raw deflate, and must be used before the first + deflate() call after a deflateInit2() or deflateReset(). bits must be less + than or equal to 16, and that many of the least significant bits of value + will be inserted in the output. + + deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be zero to request that inflate use the window size in + the zlib header of the compressed stream. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a + crc32 instead of an adler32. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit2 does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit2() does not process any header information -- that is + deferred until inflate() is called. +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called + immediately after inflateInit2() or inflateReset() and before any call of + inflate() to set the dictionary. The application must insure that the + dictionary that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been + found, or Z_STREAM_ERROR if the stream structure was inconsistent. In the + success case, the application may save the current current value of total_in + which indicates where valid compressed data was found. In the error case, + the application may repeatedly call inflateSync, providing more input each + time, until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. The + stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, + int windowBits)); +/* + This function is the same as inflateReset, but it also permits changing + the wrap and window size requests. The windowBits parameter is interpreted + the same as it is for inflateInit2. + + inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL), or if + the windowBits parameter is invalid. +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + If bits is negative, then the input stream bit buffer is emptied. Then + inflatePrime() can be called again to put bits in the buffer. This is used + to clear out bits leftover after feeding inflate a block description prior + to feeding inflate codes. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); +/* + This function returns two values, one in the lower 16 bits of the return + value, and the other in the remaining upper bits, obtained by shifting the + return value down 16 bits. If the upper value is -1 and the lower value is + zero, then inflate() is currently decoding information outside of a block. + If the upper value is -1 and the lower value is non-zero, then inflate is in + the middle of a stored block, with the lower value equaling the number of + bytes from the input remaining to copy. If the upper value is not -1, then + it is the number of bits back from the current bit position in the input of + the code (literal or length/distance pair) currently being processed. In + that case the lower value is the number of bytes already emitted for that + code. + + A code is being processed if inflate is waiting for more input to complete + decoding of the code, or if it has completed decoding but is waiting for + more output space to write the literal or match data. + + inflateMark() is used to mark locations in the input data for random + access, which may be at bit positions, and to note those cases where the + output of a code may span boundaries of random access blocks. The current + location in the input stream can be determined from avail_in and data_type + as noted in the description for the Z_BLOCK flush parameter for inflate. + + inflateMark returns the value noted above or -1 << 16 if the provided + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be + used to force inflate() to return immediately after header processing is + complete and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When any + of extra, name, or comment are not Z_NULL and the respective field is not + present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the paramaters are invalid, Z_MEM_ERROR if the internal state could not be + allocated, or Z_VERSION_ERROR if the version of the library does not match + the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free the + allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects only + the raw deflate stream to decompress. This is different from the normal + behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format error + in the deflate stream (in which case strm->msg is set to indicate the nature + of the error), or Z_STREAM_ERROR if the stream was not properly initialized. + In the case of Z_BUF_ERROR, an input or output error can be distinguished + using strm->next_in which will be Z_NULL only if in() returned an error. If + strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning + non-zero. (in() will always be called before out(), so strm->next_in is + assured to be defined if out() returns non-zero.) Note that inflateBack() + cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the basic + stream-oriented functions. To simplify the interface, some default options + are assumed (compression level and memory usage, standard memory allocation + functions). The source code of these utility functions can be modified if + you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before a + compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) Upon exit, destLen + is the actual size of the uncompressed buffer. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. +*/ + + + /* gzip file access functions */ + +/* + This library supports reading and writing files in gzip (.gz) format with + an interface similar to that of stdio, using the functions that start with + "gz". The gzip format is different from the zlib format. gzip is a gzip + wrapper, documented in RFC 1952, wrapped around a deflate stream. +*/ + +typedef voidp gzFile; /* opaque gzip file descriptor */ + +/* +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); + + Opens a gzip (.gz) file for reading or writing. The mode parameter is as + in fopen ("rb" or "wb") but can also include a compression level ("wb9") or + a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only + compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' + for fixed code compression as in "wb9F". (See the description of + deflateInit2 for more information about the strategy parameter.) Also "a" + can be used instead of "w" to request that the gzip stream that will be + written be appended to the file. "+" will result in an error, since reading + and writing to the same gzip file is not supported. + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened, if there was + insufficient memory to allocate the gzFile state, or if an invalid mode was + specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). + errno can be checked to determine if the reason gzopen failed was that the + file could not be opened. +*/ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen associates a gzFile with the file descriptor fd. File descriptors + are obtained from calls like open, dup, creat, pipe or fileno (if the file + has been previously opened with fopen). The mode parameter is as in gzopen. + + The next call of gzclose on the returned gzFile will also close the file + descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor + fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, + mode);. The duplicated descriptor should be saved to avoid a leak, since + gzdopen does not close fd if it fails. + + gzdopen returns NULL if there was insufficient memory to allocate the + gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not + provided, or '+' was provided), or if fd is -1. The file descriptor is not + used until the next gz* read, write, seek, or close operation, so gzdopen + will not detect if fd is invalid (unless fd is -1). +*/ + +ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); +/* + Set the internal buffer size used by this library's functions. The + default buffer size is 8192 bytes. This function must be called after + gzopen() or gzdopen(), and before any other calls that read or write the + file. The buffer memory allocation is always deferred to the first read or + write. Two buffers are allocated, either both of the specified size when + writing, or one of the specified size and the other twice that size when + reading. A larger buffer size of, for example, 64K or 128K bytes will + noticeably increase the speed of decompression (reading). + + The new buffer size also affects the maximum length for gzprintf(). + + gzbuffer() returns 0 on success, or -1 on failure, such as being called + too late. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. If + the input file was not in gzip format, gzread copies the given number of + bytes into the buffer. + + After reaching the end of a gzip stream in the input, gzread will continue + to read, looking for another gzip stream, or failing that, reading the rest + of the input file directly without decompression. The entire input file + will be read if gzread is called until it returns less than the requested + len. + + gzread returns the number of uncompressed bytes actually read, less than + len for end of file, or -1 for error. +*/ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes written or 0 in case of + error. +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the arguments to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written, or 0 in case of error. The number of + uncompressed bytes written is limited to 8191, or one less than the buffer + size given to gzbuffer(). The caller should assure that this limit is not + exceeded. If it is exceeded, then gzprintf() will return an error (0) with + nothing written. In this case, there may also be a buffer overflow with + unpredictable consequences, which is possible only if zlib was compiled with + the insecure functions sprintf() or vsprintf() because the secure snprintf() + or vsnprintf() functions were not available. This can be determined using + zlibCompileFlags(). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or a + newline character is read and transferred to buf, or an end-of-file + condition is encountered. If any characters are read or if len == 1, the + string is terminated with a null character. If no characters are read due + to an end-of-file or len < 1, then the buffer is left untouched. + + gzgets returns buf which is a null-terminated string, or it returns NULL + for end-of-file or in case of error. If there was an error, the contents at + buf are indeterminate. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. gzputc + returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte or -1 + in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read as the first character + on the next read. At least one character of push-back is allowed. + gzungetc() returns the character pushed, or -1 on failure. gzungetc() will + fail if c is -1, and may fail if a character has been pushed but not read + yet. If gzungetc is used immediately after gzopen or gzdopen, at least the + output buffer size of pushed characters is allowed. (See gzbuffer above.) + The pushed character will be discarded if the stream is repositioned with + gzseek() or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter flush + is as in the deflate() function. The return value is the zlib error number + (see function gzerror below). gzflush is only permitted when writing. + + If the flush parameter is Z_FINISH, the remaining data is written and the + gzip stream is completed in the output. If gzwrite() is called again, a new + gzip stream will be started in the output. gzread() is able to read such + concatented gzip streams. + + gzflush should be called only when strictly necessary because it will + degrade compression if called too often. +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); + + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); + + Returns the starting position for the next gzread or gzwrite on the given + compressed file. This position represents a number of bytes in the + uncompressed data stream, and is zero when starting, even if appending or + reading a gzip stream from the middle of a file using gzdopen(). + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); + + Returns the current offset in the file being read or written. This offset + includes the count of bytes that precede the gzip stream, for example when + appending or when using gzdopen() for reading. When reading, the offset + does not include as yet unused buffered input. This information can be used + for a progress indicator. On error, gzoffset() returns -1. +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns true (1) if the end-of-file indicator has been set while reading, + false (0) otherwise. Note that the end-of-file indicator is set only if the + read tried to go past the end of the input, but came up short. Therefore, + just like feof(), gzeof() may return false even if there is no more data to + read, in the event that the last read request was for the exact number of + bytes remaining in the input file. This will happen if the input file size + is an exact multiple of the buffer size. + + If gzeof() returns true, then the read functions will return no more data, + unless the end-of-file indicator is reset by gzclearerr() and the input file + has grown since the previous end of file was detected. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns true (1) if file is being copied directly while reading, or false + (0) if file is a gzip stream being decompressed. This state can change from + false to true while reading the input file if the end of a gzip stream is + reached, but is followed by data that is not another gzip stream. + + If the input file is empty, gzdirect() will return true, since the input + does not contain a gzip stream. + + If gzdirect() is used immediately after gzopen() or gzdopen() it will + cause buffers to be allocated to allow reading the file to determine if it + is a gzip file. Therefore if gzbuffer() is used, it should be called before + gzdirect(). +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file and + deallocates the (de)compression state. Note that once file is closed, you + cannot call gzerror with file, since its structures have been deallocated. + gzclose must not be called more than once on the same file, just as free + must not be called more than once on the same allocation. + + gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a + file operation error, or Z_OK on success. +*/ + +ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); +ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); +/* + Same as gzclose(), but gzclose_r() is only for use when reading, and + gzclose_w() is only for use when writing or appending. The advantage to + using these instead of gzclose() is that they avoid linking in zlib + compression or decompression code that is not used when only reading or only + writing respectively. If gzclose() is used, then both compression and + decompression code will be included the application when linking to a static + zlib library. +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the given + compressed file. errnum is set to zlib error number. If an error occurred + in the file system and not in the compression library, errnum is set to + Z_ERRNO and the application may consult errno to get the exact error code. + + The application must not modify the returned string. Future calls to + this function may invalidate the previously returned string. If file is + closed, then the string previously returned by gzerror will no longer be + available. + + gzerror() should be used to distinguish errors from end-of-file for those + functions above that do not distinguish those cases in their return values. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the compression + library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is Z_NULL, this function returns the + required initial value for the checksum. + + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. + + Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +/* +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); + + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is Z_NULL, this function returns the required + initial value for the for the crc. Pre- and post-conditioning (one's + complement) is performed within this function so it shouldn't be done by the + application. + + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + +/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or + * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if + * both are true, the application gets the *64 functions, and the regular + * functions are changed to 64 bits) -- in case these are set on systems + * without large file support, _LFS64_LARGEFILE must also be true + */ +#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); +#endif + +#if !defined(ZLIB_INTERNAL) && _FILE_OFFSET_BITS-0 == 64 && _LFS64_LARGEFILE-0 +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# ifdef _LARGEFILE64_SOURCE + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +# endif +#else + ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); +#endif + +/* hack for buggy compilers */ +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; +#endif + +/* undocumented functions */ +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); +ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ Index: branches/slice/rev749/modules/KextPatcher/include/inflate.h =================================================================== --- branches/slice/rev749/modules/KextPatcher/include/inflate.h (revision 0) +++ branches/slice/rev749/modules/KextPatcher/include/inflate.h (revision 1169) @@ -0,0 +1,122 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2009 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD, /* i: waiting for magic header */ + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY_, /* i/o: same as COPY below, but only first time in */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN_, /* i: same as LEN below, but only first time in */ + LEN, /* i: waiting for length/lit/eob code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ + LENGTH, /* i: waiting for 32-bit length (gzip) */ + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to BAD or MEM on error -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) or (raw) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT -> + HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + (raw) -> TYPEDO + Read deflate blocks: + TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK + STORED -> COPY_ -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN_ + LEN_ -> LEN + Read deflate codes in fixed or dynamic block: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* state maintained between inflate() calls. Approximately 10K bytes. */ +struct inflate_state { + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + gz_headerp head; /* where to save gzip header information */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ + int sane; /* if false, allow invalid distance too far */ + int back; /* bits back of last unprocessed length/lit */ + unsigned was; /* initial length of match */ +}; Index: branches/slice/rev749/modules/KextPatcher/include/trees.h =================================================================== --- branches/slice/rev749/modules/KextPatcher/include/trees.h (revision 0) +++ branches/slice/rev749/modules/KextPatcher/include/trees.h (revision 1169) @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + Index: branches/slice/rev749/modules/KextPatcher/include/deflate.h =================================================================== --- branches/slice/rev749/modules/KextPatcher/include/deflate.h (revision 0) +++ branches/slice/rev749/modules/KextPatcher/include/deflate.h (revision 1169) @@ -0,0 +1,342 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2010 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef DEFLATE_H +#define DEFLATE_H + +#include "zutil.h" + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer creation by deflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip encoding + should be left enabled. */ +#ifndef NO_GZIP +# define GZIP +#endif + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define EXTRA_STATE 69 +#define NAME_STATE 73 +#define COMMENT_STATE 91 +#define HCRC_STATE 103 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + uInt pending; /* nb of bytes in the pending buffer */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + gz_headerp gzhead; /* gzip header information to write */ + uInt gzindex; /* where in extra, name, or comment */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to supress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + + ulg high_water; + /* High water mark offset in window for initialized bytes -- bytes above + * this are set to zero in order to avoid memory check warnings when + * longest match routines access bytes past the input. This is then + * updated to the new high water mark. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + +#define WIN_INIT MAX_MATCH +/* Number of bytes after end of data in window to initialize in order to avoid + memory checker errors from longest match routines */ + + /* in trees.c */ +void ZLIB_INTERNAL _tr_init OF((deflate_state *s)); +int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf, + ulg stored_len, int last)); +void ZLIB_INTERNAL _tr_align OF((deflate_state *s)); +void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, + ulg stored_len, int last)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch ZLIB_INTERNAL _length_code[]; + extern uch ZLIB_INTERNAL _dist_code[]; +#else + extern const uch ZLIB_INTERNAL _length_code[]; + extern const uch ZLIB_INTERNAL _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif /* DEFLATE_H */ Index: branches/slice/rev749/modules/KextPatcher/include/zutil.h =================================================================== --- branches/slice/rev749/modules/KextPatcher/include/zutil.h (revision 0) +++ branches/slice/rev749/modules/KextPatcher/include/zutil.h (revision 1169) @@ -0,0 +1,275 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2010 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ) +# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) +#else +# define ZLIB_INTERNAL +#endif + +#include "libsaio.h" +#include "zlib.h" + +#ifdef STDC +# if !(defined(_WIN32_WCE) && defined(_MSC_VER)) +# include +# endif +//# include +//# include +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = (char*)ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) +# define OS_CODE 0x00 +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +# ifdef M_I86 +//# include +# endif +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#ifdef WIN32 +# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ +# define OS_CODE 0x0b +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0f +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef _PTRDIFF_T_DEFINED + typedef int ptrdiff_t; +# define _PTRDIFF_T_DEFINED +# endif +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif +#endif + +#if defined(__BORLANDC__) + #pragma warn -8004 + #pragma warn -8008 + #pragma warn -8066 +#endif + +/* provide prototypes for these when building zlib without LFS */ +#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#if defined(__CYGWIN__) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#ifndef HAVE_VSNPRINTF +# ifdef MSDOS + /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), + but for now we just assume it doesn't. */ +# define NO_vsnprintf +# endif +# ifdef __TURBOC__ +# define NO_vsnprintf +# endif +# ifdef WIN32 + /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 ) +# define vsnprintf _vsnprintf +# endif +# endif +# endif +# ifdef __SASC +# define NO_vsnprintf +# endif +#endif +#ifdef VMS +# define NO_vsnprintf +#endif + +#if defined(pyr) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include + extern int ZLIB_INTERNAL z_verbose; + extern void ZLIB_INTERNAL z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + +voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, + unsigned size)); +void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* ZUTIL_H */ Index: branches/slice/rev749/modules/KextPatcher/include/mkext.h =================================================================== --- branches/slice/rev749/modules/KextPatcher/include/mkext.h (revision 0) +++ branches/slice/rev749/modules/KextPatcher/include/mkext.h (revision 1169) @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2008 Apple Inc. All rights reserved. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ + */ + +#ifndef _MKEXT_H_ +#define _MKEXT_H_ 1 + +#include +#include + +#include + +/********************************************************************* +* Mkext File Format +* +* ALL BINARY VALUES ARE BIG-ENDIAN. +*********************************************************************/ +#if PRAGMA_MARK +#pragma mark Constants +#endif + +#define MKEXT_MAGIC 0x4D4B5854 /* 'MKXT' */ +#define MKEXT_SIGN 0x4D4F5358 /* 'MOSX' */ + +#define MKEXT_EXTN ".mkext" + +#define MKEXT_VERS_1 (0x01008000) + +// Used during development/bringup: v 2.0d1 +#define MKEXT_VERS_2 (0x02002001) +// xxx - Will use this when format is final +// #define MKEXT_VERS_2 (0x02008000) + +#if PRAGMA_MARK +#pragma mark Core Header +#endif +/********************************************************************* +* Core Header +* +* All versions of mkext files have this basic header: +* +* - magic & signature - always 'MKXT' and 'MOSX' as defined above. +* - length - the length of the whole file +* - adler32 - checksum from &version to end of file +* - version - a 'vers' style value +* - numkexts - how many kexts are in the archive (only needed in v.1) +* - cputype & cpusubtype - in version 1 could be CPU_TYPE_ANY +* and CPU_SUBTYPE_MULTIPLE if the archive contained fat kexts; +* version 2 does not allow this and all kexts must be of a single +* arch. For either version, mkexts of specific arches can be +* embedded in a fat Mach-O file to combine them. +*********************************************************************/ + +#define MKEXT_HEADER_CORE \ + uint32_t magic; \ + uint32_t signature; \ + uint32_t length; \ + uint32_t adler32; \ + uint32_t version; \ + uint32_t numkexts; \ + cpu_type_t cputype; \ + cpu_subtype_t cpusubtype; + +typedef struct mkext_basic_header { + MKEXT_HEADER_CORE +} mkext_basic_header; + +#define MKEXT_HDR_CAST(hdr) ((mkext_basic_header *)(hdr)) + +#define MKEXT_SWAP(num) OSSwapBigToHostInt32((uint32_t)(num)) + +#define MKEXT_GET_MAGIC(hdr) (MKEXT_SWAP(MKEXT_HDR_CAST(hdr)->magic)) +#define MKEXT_GET_SIGNATURE(hdr) (MKEXT_SWAP(MKEXT_HDR_CAST(hdr)->signature)) +#define MKEXT_GET_LENGTH(hdr) (MKEXT_SWAP(MKEXT_HDR_CAST(hdr)->length)) +#define MKEXT_GET_CHECKSUM(hdr) (MKEXT_SWAP(MKEXT_HDR_CAST(hdr)->adler32)) +#define MKEXT_GET_VERSION(hdr) (MKEXT_SWAP(MKEXT_HDR_CAST(hdr)->version)) +#define MKEXT_GET_COUNT(hdr) (MKEXT_SWAP(MKEXT_HDR_CAST(hdr)->numkexts)) +#define MKEXT_GET_CPUTYPE(hdr) (MKEXT_SWAP(MKEXT_HDR_CAST(hdr)->cputype)) +#define MKEXT_GET_CPUSUBTYPE(hdr) (MKEXT_SWAP(MKEXT_HDR_CAST(hdr)->cpusubtype)) + +#if PRAGMA_MARK +#pragma mark Mkext Version 2 Format Definitions +#endif +/********************************************************************* +* Mkext Version 2 Format Definitions +* +* The version field here will be some variant of 0x0200....; that is +* the major version byte will be 0x02. +* +* Version 2 uses zlib for compression, not the lzss compressor used +* by version 1. +* +* In version 2, all executable & resource files are stored in sequence +* followed by the combined info dictionaries of all kexts at the end. +* This XML plist should be nul-terminated and stored at a page-aligned +* offset in the file so that kernel code can unmap it as soon as it's +* parsed. +* +* The info dict for each kext will have inserted into it these +* additional properties: +* +* - _MKEXTBundlePath (string) - full path to the original bundle, +* relative to volume. +* - _MKEXTExecutable (integer) - offset to the executable entry. +* - _MKEXTResources (dict) - keyed by filename, values integer offsets +* to file entries. +* +* Mkext2 buffers are used to send load requests to the kernel. When +* this is done, the plist will contain an _MKEXTLoadRequest dictionary +* whose keys are the bundle IDs to load, and whose values are +* dictionaries of flags: +* +* - "Load Kext" - boolean, whether to load the kext or not (default true). +* May be used to send just personalities for already-loaded kexts, +* but we do have a mechanism to do that from userland already. +* - "Start Kext" - boolean, whether to start the kext or not +* (used when debugging). Defaults to true. +* - "Add Personalities" - boolean, whether to send personalities to +* the IOCatalogue (used when debugging). Defaults to true. +* - "Disable Autounload" - boolean, whether to prevent the reaper +* thread from unloading the kext, so the dev. has time to set up +* the debug session. (Predefined window, or maybe this will be a +* number of seconds to wait.) Defaults to false. +*********************************************************************/ +#define kMKEXTInfoDictionariesKey "_MKEXTInfoDictionaries" + +#define kMKEXTBundlePathKey "_MKEXTBundlePath" +#define kMKEXTExecutableKey "_MKEXTExecutable" + +#define kMKEXTLoadRequestKey "_MKEXTLoadRequest" +#define kMKEXTLoadRequestLoadKey "Load Kext" +#define kMKEXTLoadRequestStartKey "Start Kext" +#define kMKEXTLoadRequestAddPersonalitiesKey "Add Personalities" +#define kMKEXTLoadRequestDisableAutounloadKey "Disable Autounload" + +typedef struct mkext2_file_entry { + uint32_t compressed_size; // if zero, file is not compressed + uint32_t full_size; // full size of data w/o this struct + uint8_t data[0]; // data is inline to this struct +} mkext2_file_entry; + +typedef struct mkext2_header { + MKEXT_HEADER_CORE + uint32_t plist_offset; + uint32_t plist_compressed_size; + uint32_t plist_full_size; +} mkext2_header; + +#define MKEXT2_GET_ENTRY_COMPSIZE(ptr) MKEXT_SWAP((ptr)->compressed_size) +#define MKEXT2_GET_ENTRY_FULLSIZE(ptr) MKEXT_SWAP((ptr)->full_size) +#define MKEXT2_GET_ENTRY_DATA(ptr) ((ptr)->data) + +#define MKEXT2_HDR_CAST(hdr) ((mkext2_header *)(hdr)) +#define MKEXT2_GET_PLIST(hdr) MKEXT_SWAP(MKEXT2_HDR_CAST(hdr)->plist_offset) +#define MKEXT2_GET_PLIST_COMPSIZE(hdr) MKEXT_SWAP(MKEXT2_HDR_CAST(hdr)->plist_compressed_size) +#define MKEXT2_GET_PLIST_FULLSIZE(hdr) MKEXT_SWAP(MKEXT2_HDR_CAST(hdr)->plist_full_size) + +#if PRAGMA_MARK +#pragma mark Mkext Version 1 Format Definitions +#endif +/********************************************************************* +* Mkext Version 1 Format Definitions +* +* The original mkext format has version 0x01008000 ("1.0"). +* +* In version 1, plists were not nul-terminated, so it's up to the +* reader to add that '\0' on the end if it's needed. +* +* Original bad names preserved for source compatibility. +*********************************************************************/ + +// If all fields are 0 then this file slot is empty +// If compsize is zero then the file isn't compressed. +typedef struct mkext_file { + uint32_t offset; // 4 bytes + uint32_t compsize; // 4 bytes + uint32_t realsize; // 4 bytes + uint32_t modifiedsecs; // 4 bytes; cast to time_t to use +} mkext_file; + +// The plist file entry is mandatory, but module may be empty +typedef struct mkext_kext { + mkext_file plist; // 16 bytes + mkext_file module; // 16 bytes +} mkext_kext; + +typedef struct mkext_header { + MKEXT_HEADER_CORE + mkext_kext kext[1]; // 32 bytes/entry +} mkext_header; + +typedef mkext_header mkext1_header; + +#define MKEXT1_ENTRY_CAST(ptr) ((mkext_file *)(ptr)) +#define MKEXT1_GET_ENTRY_OFFSET(ptr) (MKEXT_SWAP(MKEXT1_ENTRY_CAST(ptr)->offset)) +#define MKEXT1_GET_ENTRY_COMPSIZE(ptr) (MKEXT_SWAP(MKEXT1_ENTRY_CAST(ptr)->compsize)) +#define MKEXT1_GET_ENTRY_FULLSIZE(ptr) (MKEXT_SWAP(MKEXT1_ENTRY_CAST(ptr)->realsize)) +#define MKEXT1_GET_ENTRY_MODTIME(ptr) ((time_t)MKEXT_SWAP(MKEXT1_ENTRY_CAST(ptr)->modifiedsecs)) +#define MKEXT1_ENTRY_EXISTS(ptr) (MKEXT1_GET_ENTRY_OFFSET(ptr) || \ + MKEXT1_GET_ENTRY_FULLSIZE(ptr) || \ + MKEXT_GET_ENTRY_COMPSIZE(ptr) || \ + MKEXT_GET_ENTRY_COMPSIZE(ptr)) + +#define MKEXT1_GET_KEXT(hdr, i) ((mkext_kext *)&(MKEXT1_HDR_CAST(hdr)->kext[(i)])) +#define MKEXT1_GET_KEXT_PLIST(hdr, i) (MKEXT1_ENTRY_CAST(&(MKEXT1_GET_KEXT((hdr), (i))->plist))) +#define MKEXT1_GET_KEXT_EXEC(hdr, i) (MKEXT1_ENTRY_CAST(&(MKEXT1_GET_KEXT((hdr), (i))->module) + +#define MKEXT1_HDR_CAST(hdr) ((mkext1_header *)(hdr)) + +#endif /* _MKEXT_H_ */ Index: branches/slice/rev749/modules/KextPatcher/inflate.c =================================================================== --- branches/slice/rev749/modules/KextPatcher/inflate.c (revision 0) +++ branches/slice/rev749/modules/KextPatcher/inflate.c (revision 1169) @@ -0,0 +1,1480 @@ +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * Change history: + * + * 1.2.beta0 24 Nov 2002 + * - First version -- complete rewrite of inflate to simplify code, avoid + * creation of window when not needed, minimize use of window when it is + * needed, make inffast.c even faster, implement gzip decoding, and to + * improve code readability and style over the previous zlib inflate code + * + * 1.2.beta1 25 Nov 2002 + * - Use pointers for available input and output checking in inffast.c + * - Remove input and output counters in inffast.c + * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 + * - Remove unnecessary second byte pull from length extra in inffast.c + * - Unroll direct copy to three copies per loop in inffast.c + * + * 1.2.beta2 4 Dec 2002 + * - Change external routine names to reduce potential conflicts + * - Correct filename to inffixed.h for fixed tables in inflate.c + * - Make hbuf[] unsigned char to match parameter type in inflate.c + * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) + * to avoid negation problem on Alphas (64 bit) in inflate.c + * + * 1.2.beta3 22 Dec 2002 + * - Add comments on state->bits assertion in inffast.c + * - Add comments on op field in inftrees.h + * - Fix bug in reuse of allocated window after inflateReset() + * - Remove bit fields--back to byte structure for speed + * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths + * - Change post-increments to pre-increments in inflate_fast(), PPC biased? + * - Add compile time option, POSTINC, to use post-increments instead (Intel?) + * - Make MATCH copy in inflate() much faster for when inflate_fast() not used + * - Use local copies of stream next and avail values, as well as local bit + * buffer and bit count in inflate()--for speed when inflate_fast() not used + * + * 1.2.beta4 1 Jan 2003 + * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings + * - Move a comment on output buffer sizes from inffast.c to inflate.c + * - Add comments in inffast.c to introduce the inflate_fast() routine + * - Rearrange window copies in inflate_fast() for speed and simplification + * - Unroll last copy for window match in inflate_fast() + * - Use local copies of window variables in inflate_fast() for speed + * - Pull out common wnext == 0 case for speed in inflate_fast() + * - Make op and len in inflate_fast() unsigned for consistency + * - Add FAR to lcode and dcode declarations in inflate_fast() + * - Simplified bad distance check in inflate_fast() + * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new + * source file infback.c to provide a call-back interface to inflate for + * programs like gzip and unzip -- uses window as output buffer to avoid + * window copying + * + * 1.2.beta5 1 Jan 2003 + * - Improved inflateBack() interface to allow the caller to provide initial + * input in strm. + * - Fixed stored blocks bug in inflateBack() + * + * 1.2.beta6 4 Jan 2003 + * - Added comments in inffast.c on effectiveness of POSTINC + * - Typecasting all around to reduce compiler warnings + * - Changed loops from while (1) or do {} while (1) to for (;;), again to + * make compilers happy + * - Changed type of window in inflateBackInit() to unsigned char * + * + * 1.2.beta7 27 Jan 2003 + * - Changed many types to unsigned or unsigned short to avoid warnings + * - Added inflateCopy() function + * + * 1.2.0 9 Mar 2003 + * - Changed inflateBack() interface to provide separate opaque descriptors + * for the in() and out() functions + * - Changed inflateBack() argument and in_func typedef to swap the length + * and buffer address return values for the input function + * - Check next_in and next_out for Z_NULL on entry to inflate() + * + * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef MAKEFIXED +# ifndef BUILDFIXED +# define BUILDFIXED +# endif +#endif + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); +local int updatewindow OF((z_streamp strm, unsigned out)); +#ifdef BUILDFIXED + void makefixed OF((void)); +#endif +local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, + unsigned len)); + +int ZEXPORT inflateReset(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = Z_NULL; + strm->adler = 1; /* to support ill-conceived Java test suite */ + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->dmax = 32768U; + state->head = Z_NULL; + state->wsize = 0; + state->whave = 0; + state->wnext = 0; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + state->sane = 1; + state->back = -1; + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +int ZEXPORT inflateReset2(strm, windowBits) +z_streamp strm; +int windowBits; +{ + int wrap; + struct inflate_state FAR *state; + + /* get the state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* extract wrap request from windowBits parameter */ + if (windowBits < 0) { + wrap = 0; + windowBits = -windowBits; + } + else { + wrap = (windowBits >> 4) + 1; +#ifdef GUNZIP + if (windowBits < 48) + windowBits &= 15; +#endif + } + + /* set number of window bits, free window if different */ + if (windowBits && (windowBits < 8 || windowBits > 15)) + return Z_STREAM_ERROR; + if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) { + ZFREE(strm, state->window); + state->window = Z_NULL; + } + + /* update state and reset the rest of it */ + state->wrap = wrap; + state->wbits = (unsigned)windowBits; + return inflateReset(strm); +} + +int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) +z_streamp strm; +int windowBits; +const char *version; +int stream_size; +{ + int ret; + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL) return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *) + ZALLOC(strm, 1, sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + state->window = Z_NULL; + ret = inflateReset2(strm, windowBits); + if (ret != Z_OK) { + ZFREE(strm, state); + strm->state = Z_NULL; + } + return ret; +} + +int ZEXPORT inflateInit_(strm, version, stream_size) +z_streamp strm; +const char *version; +int stream_size; +{ + return inflateInit2_(strm, DEF_WBITS, version, stream_size); +} + +int ZEXPORT inflatePrime(strm, bits, value) +z_streamp strm; +int bits; +int value; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (bits < 0) { + state->hold = 0; + state->bits = 0; + return Z_OK; + } + if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; + value &= (1L << bits) - 1; + state->hold += value << state->bits; + state->bits += bits; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +#ifdef MAKEFIXED +#include + +/* + Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also + defines BUILDFIXED, so the tables are built on the fly. makefixed() writes + those tables to stdout, which would be piped to inffixed.h. A small program + can simply call makefixed to do this: + + void makefixed(void); + + int main(void) + { + makefixed(); + return 0; + } + + Then that can be linked with zlib built with MAKEFIXED defined and run: + + a.out > inffixed.h + */ +void makefixed() +{ + unsigned low, size; + struct inflate_state state; + + fixedtables(&state); + puts(" /* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits, + state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +local int updatewindow(strm, out) +z_streamp strm; +unsigned out; +{ + struct inflate_state FAR *state; + unsigned copy, dist; + + state = (struct inflate_state FAR *)strm->state; + + /* if it hasn't been done already, allocate space for the window */ + if (state->window == Z_NULL) { + state->window = (unsigned char FAR *) + ZALLOC(strm, 1U << state->wbits, + sizeof(unsigned char)); + if (state->window == Z_NULL) return 1; + } + + /* if window not in use yet, initialize */ + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->wnext = 0; + state->whave = 0; + } + + /* copy state->wsize or less output bytes into the circular window */ + copy = out - strm->avail_out; + if (copy >= state->wsize) { + zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); + state->wnext = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->wnext; + if (dist > copy) dist = copy; + zmemcpy(state->window + state->wnext, strm->next_out - copy, dist); + copy -= dist; + if (copy) { + zmemcpy(state->window, strm->next_out - copy, copy); + state->wnext = copy; + state->whave = state->wsize; + } + else { + state->wnext += dist; + if (state->wnext == state->wsize) state->wnext = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } + return 0; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE(check, buf, len) \ + (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) +#else +# define UPDATE(check, buf, len) adler32(check, buf, len) +#endif + +/* check macros for header crc */ +#ifdef GUNZIP +# define CRC2(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = crc32(check, hbuf, 2); \ + } while (0) + +# define CRC4(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = crc32(check, hbuf, 4); \ + } while (0) +#endif + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Reverse the bytes in a 32-bit value */ +#define REVERSE(q) \ + ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; + break; + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int ZEXPORT inflate(strm, flush) +z_streamp strm; +int flush; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code here; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ +#ifdef GUNZIP + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ +#endif + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state FAR *)strm->state; + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); +#ifdef GUNZIP + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + state->check = crc32(0L, Z_NULL, 0); + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + state->flags = 0; /* expect zlib header */ + if (state->head != Z_NULL) + state->head->done = -1; + if (!(state->wrap & 1) || /* check if zlib header allowed */ +#else + if ( +#endif + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + len = BITS(4) + 8; + if (state->wbits == 0) + state->wbits = len; + else if (len > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + state->dmax = 1U << len; + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; +#ifdef GUNZIP + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + if (state->flags & 0xe000) { + strm->msg = (char *)"unknown header flags set"; + state->mode = BAD; + break; + } + if (state->head != Z_NULL) + state->head->text = (int)((hold >> 8) & 1); + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + case TIME: + NEEDBITS(32); + if (state->head != Z_NULL) + state->head->time = hold; + if (state->flags & 0x0200) CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + case OS: + NEEDBITS(16); + if (state->head != Z_NULL) { + state->head->xflags = (int)(hold & 0xff); + state->head->os = (int)(hold >> 8); + } + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (unsigned)(hold); + if (state->head != Z_NULL) + state->head->extra_len = (unsigned)hold; + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + } + else if (state->head != Z_NULL) + state->head->extra = Z_NULL; + state->mode = EXTRA; + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) copy = have; + if (copy) { + if (state->head != Z_NULL && + state->head->extra != Z_NULL) { + len = state->head->extra_len - state->length; + zmemcpy(state->head->extra + len, next, + len + copy > state->head->extra_max ? + state->head->extra_max - len : copy); + } + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) goto inf_leave; + } + state->length = 0; + state->mode = NAME; + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->name != Z_NULL && + state->length < state->head->name_max) + state->head->name[state->length++] = len; + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->name = Z_NULL; + state->length = 0; + state->mode = COMMENT; + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->comment != Z_NULL && + state->length < state->head->comm_max) + state->head->comment[state->length++] = len; + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->comment = Z_NULL; + state->mode = HCRC; + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if (hold != (state->check & 0xffff)) { + strm->msg = (char *)"header crc mismatch"; + state->mode = BAD; + break; + } + INITBITS(); + } + if (state->head != Z_NULL) { + state->head->hcrc = (int)((state->flags >> 9) & 1); + state->head->done = 1; + } + strm->adler = state->check = crc32(0L, Z_NULL, 0); + state->mode = TYPE; + break; +#endif + case DICTID: + NEEDBITS(32); + strm->adler = state->check = REVERSE(hold); + INITBITS(); + state->mode = DICT; + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = TYPE; + case TYPE: + if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN_; /* decode codes */ + if (flush == Z_TREES) { + DROPBITS(2); + goto inf_leave; + } + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + state->mode = COPY_; + if (flush == Z_TREES) goto inf_leave; + case COPY_: + state->mode = COPY; + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.val < 16) { + NEEDBITS(here.bits); + DROPBITS(here.bits); + state->lens[state->have++] = here.val; + } + else { + if (here.val == 16) { + NEEDBITS(here.bits + 2); + DROPBITS(here.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (here.val == 17) { + NEEDBITS(here.bits + 3); + DROPBITS(here.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(here.bits + 7); + DROPBITS(here.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* check for end-of-block code (better have one) */ + if (state->lens[256] == 0) { + strm->msg = (char *)"invalid code -- missing end-of-block"; + state->mode = BAD; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN_; + if (flush == Z_TREES) goto inf_leave; + case LEN_: + state->mode = LEN; + case LEN: + if (have >= 6 && left >= 258) { + RESTORE(); + inflate_fast(strm, out); + LOAD(); + if (state->mode == TYPE) + state->back = -1; + break; + } + state->back = 0; + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.op && (here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + state->length = (unsigned)here.val; + if ((int)(here.op) == 0) { + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + state->mode = LIT; + break; + } + if (here.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->back = -1; + state->mode = TYPE; + break; + } + if (here.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(here.op) & 15; + state->mode = LENEXT; + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->was = state->length; + state->mode = DIST; + case DIST: + for (;;) { + here = state->distcode[BITS(state->distbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if ((here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + if (here.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)here.val; + state->extra = (unsigned)(here.op) & 15; + state->mode = DISTEXT; + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } +#ifdef INFLATE_STRICT + if (state->offset > state->dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->whave) { + if (state->sane) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + Trace((stderr, "inflate.c too far\n")); + copy -= state->whave; + if (copy > state->length) copy = state->length; + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = 0; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; +#endif + } + if (copy > state->wnext) { + copy -= state->wnext; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->wnext - copy); + if (copy > state->length) copy = state->length; + } + else { /* copy from output */ + from = put - state->offset; + copy = state->length; + } + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = *from++; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if (out) + strm->adler = state->check = + UPDATE(state->check, put - out, out); + out = left; + if (( +#ifdef GUNZIP + state->flags ? hold : +#endif + REVERSE(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } +#ifdef GUNZIP + state->mode = LENGTH; + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if (hold != (state->total & 0xffffffffUL)) { + strm->msg = (char *)"incorrect length check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } +#endif + state->mode = DONE; + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + inf_leave: + RESTORE(); + if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) + if (updatewindow(strm, out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if (state->wrap && out) + strm->adler = state->check = + UPDATE(state->check, strm->next_out - out, out); + strm->data_type = state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0) + + (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; +} + +int ZEXPORT inflateEnd(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->window != Z_NULL) ZFREE(strm, state->window); + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + +int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) +z_streamp strm; +const Bytef *dictionary; +uInt dictLength; +{ + struct inflate_state FAR *state; + unsigned long id; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->wrap != 0 && state->mode != DICT) + return Z_STREAM_ERROR; + + /* check for correct dictionary id */ + if (state->mode == DICT) { + id = adler32(0L, Z_NULL, 0); + id = adler32(id, dictionary, dictLength); + if (id != state->check) + return Z_DATA_ERROR; + } + + /* copy dictionary to window */ + if (updatewindow(strm, strm->avail_out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + if (dictLength > state->wsize) { + zmemcpy(state->window, dictionary + dictLength - state->wsize, + state->wsize); + state->whave = state->wsize; + } + else { + zmemcpy(state->window + state->wsize - dictLength, dictionary, + dictLength); + state->whave = dictLength; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +int ZEXPORT inflateGetHeader(strm, head) +z_streamp strm; +gz_headerp head; +{ + struct inflate_state FAR *state; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; + + /* save header structure */ + state->head = head; + head->done = 0; + return Z_OK; +} + +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +local unsigned syncsearch(have, buf, len) +unsigned FAR *have; +unsigned char FAR *buf; +unsigned len; +{ + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} + +int ZEXPORT inflateSync(strm) +z_streamp strm; +{ + unsigned len; /* number of bytes to look at or looked at */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state FAR *state; + + /* check parameters */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + in = strm->total_in; out = strm->total_out; + inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->mode = TYPE; + return Z_OK; +} + +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + return state->mode == STORED && state->bits == 0; +} + +int ZEXPORT inflateCopy(dest, source) +z_streamp dest; +z_streamp source; +{ + struct inflate_state FAR *state; + struct inflate_state FAR *copy; + unsigned char FAR *window; + unsigned wsize; + + /* check input */ + if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || + source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)source->state; + + /* allocate space */ + copy = (struct inflate_state FAR *) + ZALLOC(source, 1, sizeof(struct inflate_state)); + if (copy == Z_NULL) return Z_MEM_ERROR; + window = Z_NULL; + if (state->window != Z_NULL) { + window = (unsigned char FAR *) + ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); + if (window == Z_NULL) { + ZFREE(source, copy); + return Z_MEM_ERROR; + } + } + + /* copy state */ + zmemcpy(dest, source, sizeof(z_stream)); + zmemcpy(copy, state, sizeof(struct inflate_state)); + if (state->lencode >= state->codes && + state->lencode <= state->codes + ENOUGH - 1) { + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + } + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) { + wsize = 1U << state->wbits; + zmemcpy(window, state->window, wsize); + } + copy->window = window; + dest->state = (struct internal_state FAR *)copy; + return Z_OK; +} + +int ZEXPORT inflateUndermine(strm, subvert) +z_streamp strm; +int subvert; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + state->sane = !subvert; +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + return Z_OK; +#else + state->sane = 1; + return Z_DATA_ERROR; +#endif +} + +long ZEXPORT inflateMark(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return -1L << 16; + state = (struct inflate_state FAR *)strm->state; + return ((long)(state->back) << 16) + + (state->mode == COPY ? state->length : + (state->mode == MATCH ? state->was - state->length : 0)); +} Index: branches/slice/rev749/modules/KextPatcher/trees.c =================================================================== --- branches/slice/rev749/modules/KextPatcher/trees.c (revision 0) +++ branches/slice/rev749/modules/KextPatcher/trees.c (revision 1169) @@ -0,0 +1,1244 @@ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1995-2010 Jean-loup Gailly + * detect_data_type() function provided freely by Cosmin Truta, 2006 + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in a compressed form which is itself + * a Huffman encoding of the lengths of all the code strings (in + * ascending order by source values). The actual code strings are + * reconstructed from the lengths in the inflate process, as described + * in the deflate specification. + * + * REFERENCES + * + * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + */ + +/* @(#) $Id$ */ + +/* #define GEN_TREES_H */ + +#include "deflate.h" + +#ifdef DEBUG +# include +#endif + +/* =========================================================================== + * Constants + */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +local const int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +local const uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +#define Buf_size (8 * 2*sizeof(char)) +/* Number of bits used within bi_buf. (bi_buf might be implemented on + * more than 16 bits on some systems.) + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ + +#if defined(GEN_TREES_H) || !defined(STDC) +/* non ANSI compilers may not accept trees.h */ + +local ct_data static_ltree[L_CODES+2]; +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +local ct_data static_dtree[D_CODES]; +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +uch _dist_code[DIST_CODE_LEN]; +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +uch _length_code[MAX_MATCH-MIN_MATCH+1]; +/* length code for each normalized match length (0 == MIN_MATCH) */ + +local int base_length[LENGTH_CODES]; +/* First normalized length for each code (0 = MIN_MATCH) */ + +local int base_dist[D_CODES]; +/* First normalized distance for each code (0 = distance of 1) */ + +#else +# include "trees.h" +#endif /* GEN_TREES_H */ + +struct static_tree_desc_s { + const ct_data *static_tree; /* static tree or NULL */ + const intf *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ +}; + +local static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +local static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +local static_tree_desc static_bl_desc = +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +/* =========================================================================== + * Local (static) routines in this file. + */ + +local void tr_static_init OF((void)); +local void init_block OF((deflate_state *s)); +local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); +local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); +local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); +local void build_tree OF((deflate_state *s, tree_desc *desc)); +local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local int build_bl_tree OF((deflate_state *s)); +local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, + int blcodes)); +local void compress_block OF((deflate_state *s, ct_data *ltree, + ct_data *dtree)); +local int detect_data_type OF((deflate_state *s)); +local unsigned bi_reverse OF((unsigned value, int length)); +local void bi_windup OF((deflate_state *s)); +local void bi_flush OF((deflate_state *s)); +local void copy_block OF((deflate_state *s, charf *buf, unsigned len, + int header)); + +#ifdef GEN_TREES_H +local void gen_trees_header OF((void)); +#endif + +#ifndef DEBUG +# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* DEBUG */ +# define send_code(s, c, tree) \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } +#endif + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +#ifdef DEBUG +local void send_bits OF((deflate_state *s, int value, int length)); + +local void send_bits(s, value, length) + deflate_state *s; + int value; /* value to send */ + int length; /* number of bits */ +{ + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; + + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (ush)value << s->bi_valid; + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= (ush)value << s->bi_valid; + s->bi_valid += length; + } +} +#else /* !DEBUG */ + +#define send_bits(s, value, length) \ +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = value;\ + s->bi_buf |= (ush)val << s->bi_valid;\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf |= (ush)(value) << s->bi_valid;\ + s->bi_valid += len;\ + }\ +} +#endif /* DEBUG */ + + +/* the arguments must not have side effects */ + +/* =========================================================================== + * Initialize the various 'constant' tables. + */ +local void tr_static_init() +{ +#if defined(GEN_TREES_H) || !defined(STDC) + static int static_init_done = 0; + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + if (static_init_done) return; + + /* For some embedded targets, global variables are not initialized: */ +#ifdef NO_INIT_GLOBAL_POINTERS + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; +#endif + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1< dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + _dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse((unsigned)n, 5); + } + static_init_done = 1; + +# ifdef GEN_TREES_H + gen_trees_header(); +# endif +#endif /* defined(GEN_TREES_H) || !defined(STDC) */ +} + +/* =========================================================================== + * Genererate the file trees.h describing the static trees. + */ +#ifdef GEN_TREES_H +# ifndef DEBUG +# include +# endif + +# define SEPARATOR(i, last, width) \ + ((i) == (last)? "\n};\n\n" : \ + ((i) % (width) == (width)-1 ? ",\n" : ", ")) + +void gen_trees_header() +{ + FILE *header = fopen("trees.h", "w"); + int i; + + Assert (header != NULL, "Can't open trees.h"); + fprintf(header, + "/* header created automatically with -DGEN_TREES_H */\n\n"); + + fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); + for (i = 0; i < L_CODES+2; i++) { + fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, + static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); + } + + fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, + static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); + } + + fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n"); + for (i = 0; i < DIST_CODE_LEN; i++) { + fprintf(header, "%2u%s", _dist_code[i], + SEPARATOR(i, DIST_CODE_LEN-1, 20)); + } + + fprintf(header, + "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); + for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { + fprintf(header, "%2u%s", _length_code[i], + SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + } + + fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); + for (i = 0; i < LENGTH_CODES; i++) { + fprintf(header, "%1u%s", base_length[i], + SEPARATOR(i, LENGTH_CODES-1, 20)); + } + + fprintf(header, "local const int base_dist[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "%5u%s", base_dist[i], + SEPARATOR(i, D_CODES-1, 10)); + } + + fclose(header); +} +#endif /* GEN_TREES_H */ + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +void ZLIB_INTERNAL _tr_init(s) + deflate_state *s; +{ + tr_static_init(); + + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; + s->last_eob_len = 8; /* enough lookahead for inflate */ +#ifdef DEBUG + s->compressed_len = 0L; + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(s) + deflate_state *s; +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =========================================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +local void pqdownheap(s, tree, k) + deflate_state *s; + ct_data *tree; /* the tree to restore */ + int k; /* node to move down */ +{ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +local void gen_bitlen(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const intf *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (bits + xbits); + if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; + + Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if ((unsigned) tree[m].Len != (unsigned) bits) { + Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((long)bits - (long)tree[m].Len) + *(long)tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +local void gen_codes (tree, max_code, bl_count) + ct_data *tree; /* the tree to decorate */ + int max_code; /* largest code with non zero frequency */ + ushf *bl_count; /* number of codes at each bit length */ +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + ush code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits-1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s->heap_len = 0, s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; if (stree) s->static_len -= stree[node].Len; + /* node is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? + s->depth[n] : s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code, s->bl_count); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +local void scan_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +local void send_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +local int build_bl_tree(s) + deflate_state *s; +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += 3*(max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len, s->static_len)); + + return max_blindex; +} + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +local void send_all_trees(s, lcodes, dcodes, blcodes) + deflate_state *s; + int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + +/* =========================================================================== + * Send a stored block + */ +void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last) + deflate_state *s; + charf *buf; /* input block */ + ulg stored_len; /* length of input block */ + int last; /* one if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK<<1)+last, 3); /* send block type */ +#ifdef DEBUG + s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; + s->compressed_len += (stored_len + 4) << 3; +#endif + copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ +} + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + * The current inflate code requires 9 bits of lookahead. If the + * last two codes for the previous block (real code plus EOB) were coded + * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + * the last real code. In this case we send two empty static blocks instead + * of one. (There are no problems if the previous block is stored or fixed.) + * To simplify the code, we assume the worst case of last real code encoded + * on one bit only. + */ +void ZLIB_INTERNAL _tr_align(s) + deflate_state *s; +{ + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ +#endif + bi_flush(s); + /* Of the 10 bits for the empty block, we have already sent + * (10 - bi_valid) bits. The lookahead for the last real code (before + * the EOB of the previous block) was thus at least one plus the length + * of the EOB plus what we have just sent of the empty static block. + */ + if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; +#endif + bi_flush(s); + } + s->last_eob_len = 7; +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ +void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) + deflate_state *s; + charf *buf; /* input block, or NULL if too old */ + ulg stored_len; /* length of input block */ + int last; /* one if this is the last block for a file */ +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s->level > 0) { + + /* Check if the file is binary or text */ + if (s->strm->data_type == Z_UNKNOWN) + s->strm->data_type = detect_data_type(s); + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute the block lengths in bytes. */ + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->last_lit)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + } else { + Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + +#ifdef FORCE_STORED + if (buf != (char*)0) { /* force stored block */ +#else + if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* 4: two words for the lengths */ +#endif + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, last); + +#ifdef FORCE_STATIC + } else if (static_lenb >= 0) { /* force static trees */ +#else + } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { +#endif + send_bits(s, (STATIC_TREES<<1)+last, 3); + compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->static_len; +#endif + } else { + send_bits(s, (DYN_TREES<<1)+last, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->opt_len; +#endif + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (last) { + bi_windup(s); +#ifdef DEBUG + s->compressed_len += 7; /* align on byte boundary */ +#endif + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + s->compressed_len-7*last)); +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +int ZLIB_INTERNAL _tr_tally (s, dist, lc) + deflate_state *s; + unsigned dist; /* distance of matched string */ + unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } + +#ifdef TRUNCATE_BLOCK + /* Try to guess if it is profitable to stop the current block here */ + if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)((long)s->strstart - s->block_start); + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + s->last_lit, in_length, out_length, + 100L - out_length*100L/in_length)); + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } +#endif + return (s->last_lit == s->lit_bufsize-1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(s, ltree, dtree) + deflate_state *s; + ct_data *ltree; /* literal tree */ + ct_data *dtree; /* distance tree */ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, + "pendingBuf overflow"); + + } while (lx < s->last_lit); + + send_code(s, END_BLOCK, ltree); + s->last_eob_len = ltree[END_BLOCK].Len; +} + +/* =========================================================================== + * Check if the data type is TEXT or BINARY, using the following algorithm: + * - TEXT if the two conditions below are satisfied: + * a) There are no non-portable control characters belonging to the + * "black list" (0..6, 14..25, 28..31). + * b) There is at least one printable character belonging to the + * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). + * - BINARY otherwise. + * - The following partially-portable control characters form a + * "gray list" that is ignored in this detection algorithm: + * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). + * IN assertion: the fields Freq of dyn_ltree are set. + */ +local int detect_data_type(s) + deflate_state *s; +{ + /* black_mask is the bit mask of black-listed bytes + * set bits 0..6, 14..25, and 28..31 + * 0xf3ffc07f = binary 11110011111111111100000001111111 + */ + unsigned long black_mask = 0xf3ffc07fUL; + int n; + + /* Check for non-textual ("black-listed") bytes. */ + for (n = 0; n <= 31; n++, black_mask >>= 1) + if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0)) + return Z_BINARY; + + /* Check for textual ("white-listed") bytes. */ + if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0 + || s->dyn_ltree[13].Freq != 0) + return Z_TEXT; + for (n = 32; n < LITERALS; n++) + if (s->dyn_ltree[n].Freq != 0) + return Z_TEXT; + + /* There are no "black-listed" or "white-listed" bytes: + * this stream either is empty or has tolerated ("gray-listed") bytes only. + */ + return Z_BINARY; +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +local unsigned bi_reverse(code, len) + unsigned code; /* the value to invert */ + int len; /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +local void bi_flush(s) + deflate_state *s; +{ + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +local void bi_windup(s) + deflate_state *s; +{ + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef DEBUG + s->bits_sent = (s->bits_sent+7) & ~7; +#endif +} + +/* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ +local void copy_block(s, buf, len, header) + deflate_state *s; + charf *buf; /* the input data */ + unsigned len; /* its length */ + int header; /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + s->last_eob_len = 8; /* enough lookahead for inflate */ + + if (header) { + put_short(s, (ush)len); + put_short(s, (ush)~len); +#ifdef DEBUG + s->bits_sent += 2*16; +#endif + } +#ifdef DEBUG + s->bits_sent += (ulg)len<<3; +#endif + while (len--) { + put_byte(s, *buf++); + } +} Index: branches/slice/rev749/modules/KextPatcher/deflate.c =================================================================== --- branches/slice/rev749/modules/KextPatcher/deflate.c (revision 0) +++ branches/slice/rev749/modules/KextPatcher/deflate.c (revision 1169) @@ -0,0 +1,1834 @@ +/* deflate.c -- compress data using the deflation algorithm + * Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process depends on being able to identify portions + * of the input text which are identical to earlier input (within a + * sliding window trailing behind the input currently being processed). + * + * The most straightforward technique turns out to be the fastest for + * most input files: try all possible matches and select the longest. + * The key feature of this algorithm is that insertions into the string + * dictionary are very simple and thus fast, and deletions are avoided + * completely. Insertions are performed at each input character, whereas + * string matches are performed only when the previous match ends. So it + * is preferable to spend more time in matches to allow very fast string + * insertions and avoid deletions. The matching algorithm for small + * strings is inspired from that of Rabin & Karp. A brute force approach + * is used to find longer strings when a small match has been found. + * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + * (by Leonid Broukhis). + * A previous version of this file used a more sophisticated algorithm + * (by Fiala and Greene) which is guaranteed to run in linear amortized + * time, but has a larger average cost, uses more memory and is patented. + * However the F&G algorithm may be faster for some highly redundant + * files if the parameter max_chain_length (described below) is too large. + * + * ACKNOWLEDGEMENTS + * + * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + * I found it in 'freeze' written by Leonid Broukhis. + * Thanks to many people for bug reports and testing. + * + * REFERENCES + * + * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". + * Available in http://www.ietf.org/rfc/rfc1951.txt + * + * A description of the Rabin and Karp algorithm is given in the book + * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + * + * Fiala,E.R., and Greene,D.H. + * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + * + */ + +/* @(#) $Id$ */ + +#include "deflate.h" + +const char deflate_copyright[] = + " deflate 1.2.5 Copyright 1995-2010 Jean-loup Gailly and Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* =========================================================================== + * Function prototypes. + */ +typedef enum { + need_more, /* block not completed, need more input or more output */ + block_done, /* block flush performed */ + finish_started, /* finish started, need only more output at next deflate */ + finish_done /* finish done, accept no more input or output */ +} block_state; + +typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +/* Compression function. Returns the block state after the call. */ + +local void fill_window OF((deflate_state *s)); +local block_state deflate_stored OF((deflate_state *s, int flush)); +local block_state deflate_fast OF((deflate_state *s, int flush)); +#ifndef FASTEST +local block_state deflate_slow OF((deflate_state *s, int flush)); +#endif +local block_state deflate_rle OF((deflate_state *s, int flush)); +local block_state deflate_huff OF((deflate_state *s, int flush)); +local void lm_init OF((deflate_state *s)); +local void putShortMSB OF((deflate_state *s, uInt b)); +local void flush_pending OF((z_streamp strm)); +local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +#ifdef ASMV + void match_init OF((void)); /* asm code initialization */ + uInt longest_match OF((deflate_state *s, IPos cur_match)); +#else +local uInt longest_match OF((deflate_state *s, IPos cur_match)); +#endif + +#ifdef DEBUG +local void check_match OF((deflate_state *s, IPos start, IPos match, + int length)); +#endif + +/* =========================================================================== + * Local data + */ + +#define NIL 0 +/* Tail of hash chains */ + +#ifndef TOO_FAR +# define TOO_FAR 4096 +#endif +/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +typedef struct config_s { + ush good_length; /* reduce lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ + ush nice_length; /* quit search above this match length */ + ush max_chain; + compress_func func; +} config; + +#ifdef FASTEST +local const config configuration_table[2] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ +#else +local const config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8, deflate_fast}, +/* 3 */ {4, 6, 32, 32, deflate_fast}, + +/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32, deflate_slow}, +/* 6 */ {8, 16, 128, 128, deflate_slow}, +/* 7 */ {8, 32, 128, 256, deflate_slow}, +/* 8 */ {32, 128, 258, 1024, deflate_slow}, +/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ +#endif + +/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. + */ + +#define EQUAL 0 +/* result of memcmp for equal strings */ + +#ifndef NO_DUMMY_DECL +struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ +#endif + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * input characters, so that a running hash key can be computed from the + * previous key instead of complete recalculation each time. + */ +#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) + + +/* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * If this file is compiled with -DFASTEST, the compression level is forced + * to 1, and no hash chains are maintained. + * IN assertion: all calls to to INSERT_STRING are made with consecutive + * input characters and the first MIN_MATCH bytes of str are valid + * (except for the last MIN_MATCH-1 bytes of the input file). + */ +#ifdef FASTEST +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#else +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#endif + +/* =========================================================================== + * Initialize the hash table (avoiding 64K overflow for 16 bit systems). + * prev[] will be initialized on the fly. + */ +#define CLEAR_HASH(s) \ + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + +/* ========================================================================= */ +int ZEXPORT deflateInit_(strm, level, version, stream_size) + z_streamp strm; + int level; + const char *version; + int stream_size; +{ + return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); + /* To do: ignore strm->next_in if we use it as window */ +} + +/* ========================================================================= */ +int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + version, stream_size) + z_streamp strm; + int level; + int method; + int windowBits; + int memLevel; + int strategy; + const char *version; + int stream_size; +{ + deflate_state *s; + int wrap = 1; + static const char my_version[] = ZLIB_VERSION; + + ushf *overlay; + /* We overlay pending_buf and d_buf+l_buf. This works since the average + * output size for (length,distance) codes is <= 24 bits. + */ + + if (version == Z_NULL || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; + } + if (strm == Z_NULL) return Z_STREAM_ERROR; + + strm->msg = Z_NULL; + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } +#ifdef GZIP + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } +#endif + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_FIXED) { + return Z_STREAM_ERROR; + } + if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state FAR *)s; + s->strm = strm; + + s->wrap = wrap; + s->gzhead = Z_NULL; + s->w_bits = windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + + s->hash_bits = memLevel + 7; + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + + s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->high_water = 0; /* nothing written to s->window yet */ + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + s->pending_buf = (uchf *) overlay; + s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { + s->status = FINISH_STATE; + strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); + deflateEnd (strm); + return Z_MEM_ERROR; + } + s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; + + return deflateReset(strm); +} + +/* ========================================================================= */ +int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) + z_streamp strm; + const Bytef *dictionary; + uInt dictLength; +{ + deflate_state *s; + uInt length = dictLength; + uInt n; + IPos hash_head = 0; + + if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || + strm->state->wrap == 2 || + (strm->state->wrap == 1 && strm->state->status != INIT_STATE)) + return Z_STREAM_ERROR; + + s = strm->state; + if (s->wrap) + strm->adler = adler32(strm->adler, dictionary, dictLength); + + if (length < MIN_MATCH) return Z_OK; + if (length > s->w_size) { + length = s->w_size; + dictionary += dictLength - length; /* use the tail of the dictionary */ + } + zmemcpy(s->window, dictionary, length); + s->strstart = length; + s->block_start = (long)length; + + /* Insert all strings in the hash table (except for the last two bytes). + * s->lookahead stays null, so s->ins_h will be recomputed at the next + * call of fill_window. + */ + s->ins_h = s->window[0]; + UPDATE_HASH(s, s->ins_h, s->window[1]); + for (n = 0; n <= length - MIN_MATCH; n++) { + INSERT_STRING(s, n, hash_head); + } + if (hash_head) hash_head = 0; /* to make compiler happy */ + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateReset (strm) + z_streamp strm; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { + return Z_STREAM_ERROR; + } + + strm->total_in = strm->total_out = 0; + strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ + strm->data_type = Z_UNKNOWN; + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + if (s->wrap < 0) { + s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ + } + s->status = s->wrap ? INIT_STATE : BUSY_STATE; + strm->adler = +#ifdef GZIP + s->wrap == 2 ? crc32(0L, Z_NULL, 0) : +#endif + adler32(0L, Z_NULL, 0); + s->last_flush = Z_NO_FLUSH; + + _tr_init(s); + lm_init(s); + + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateSetHeader (strm, head) + z_streamp strm; + gz_headerp head; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (strm->state->wrap != 2) return Z_STREAM_ERROR; + strm->state->gzhead = head; + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflatePrime (strm, bits, value) + z_streamp strm; + int bits; + int value; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + strm->state->bi_valid = bits; + strm->state->bi_buf = (ush)(value & ((1 << bits) - 1)); + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateParams(strm, level, strategy) + z_streamp strm; + int level; + int strategy; +{ + deflate_state *s; + compress_func func; + int err = Z_OK; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { + return Z_STREAM_ERROR; + } + func = configuration_table[s->level].func; + + if ((strategy != s->strategy || func != configuration_table[level].func) && + strm->total_in != 0) { + /* Flush the last buffer: */ + err = deflate(strm, Z_BLOCK); + } + if (s->level != level) { + s->level = level; + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + } + s->strategy = strategy; + return err; +} + +/* ========================================================================= */ +int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain) + z_streamp strm; + int good_length; + int max_lazy; + int nice_length; + int max_chain; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + s->good_match = good_length; + s->max_lazy_match = max_lazy; + s->nice_match = nice_length; + s->max_chain_length = max_chain; + return Z_OK; +} + +/* ========================================================================= + * For the default windowBits of 15 and memLevel of 8, this function returns + * a close to exact, as well as small, upper bound on the compressed size. + * They are coded as constants here for a reason--if the #define's are + * changed, then this function needs to be changed as well. The return + * value for 15 and 8 only works for those exact settings. + * + * For any setting other than those defaults for windowBits and memLevel, + * the value returned is a conservative worst case for the maximum expansion + * resulting from using fixed blocks instead of stored blocks, which deflate + * can emit on compressed data for some combinations of the parameters. + * + * This function could be more sophisticated to provide closer upper bounds for + * every combination of windowBits and memLevel. But even the conservative + * upper bound of about 14% expansion does not seem onerous for output buffer + * allocation. + */ +uLong ZEXPORT deflateBound(strm, sourceLen) + z_streamp strm; + uLong sourceLen; +{ + deflate_state *s; + uLong complen, wraplen; + Bytef *str; + + /* conservative upper bound for compressed data */ + complen = sourceLen + + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5; + + /* if can't get parameters, return conservative bound plus zlib wrapper */ + if (strm == Z_NULL || strm->state == Z_NULL) + return complen + 6; + + /* compute wrapper length */ + s = strm->state; + switch (s->wrap) { + case 0: /* raw deflate */ + wraplen = 0; + break; + case 1: /* zlib wrapper */ + wraplen = 6 + (s->strstart ? 4 : 0); + break; + case 2: /* gzip wrapper */ + wraplen = 18; + if (s->gzhead != Z_NULL) { /* user-supplied gzip header */ + if (s->gzhead->extra != Z_NULL) + wraplen += 2 + s->gzhead->extra_len; + str = s->gzhead->name; + if (str != Z_NULL) + do { + wraplen++; + } while (*str++); + str = s->gzhead->comment; + if (str != Z_NULL) + do { + wraplen++; + } while (*str++); + if (s->gzhead->hcrc) + wraplen += 2; + } + break; + default: /* for compiler happiness */ + wraplen = 6; + } + + /* if not default parameters, return conservative bound */ + if (s->w_bits != 15 || s->hash_bits != 8 + 7) + return complen + wraplen; + + /* default settings: return tight bound for that case */ + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + + (sourceLen >> 25) + 13 - 6 + wraplen; +} + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +local void putShortMSB (s, b) + deflate_state *s; + uInt b; +{ + put_byte(s, (Byte)(b >> 8)); + put_byte(s, (Byte)(b & 0xff)); +} + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->next_out buffer and copying into it. + * (See also read_buf()). + */ +local void flush_pending(strm) + z_streamp strm; +{ + unsigned len = strm->state->pending; + + if (len > strm->avail_out) len = strm->avail_out; + if (len == 0) return; + + zmemcpy(strm->next_out, strm->state->pending_out, len); + strm->next_out += len; + strm->state->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + strm->state->pending -= len; + if (strm->state->pending == 0) { + strm->state->pending_out = strm->state->pending_buf; + } +} + +/* ========================================================================= */ +int ZEXPORT deflate (strm, flush) + z_streamp strm; + int flush; +{ + int old_flush; /* value of flush param for previous deflate call */ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + flush > Z_BLOCK || flush < 0) { + return Z_STREAM_ERROR; + } + s = strm->state; + + if (strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0) || + (s->status == FINISH_STATE && flush != Z_FINISH)) { + ERR_RETURN(strm, Z_STREAM_ERROR); + } + if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); + + s->strm = strm; /* just in case */ + old_flush = s->last_flush; + s->last_flush = flush; + + /* Write the header */ + if (s->status == INIT_STATE) { +#ifdef GZIP + if (s->wrap == 2) { + strm->adler = crc32(0L, Z_NULL, 0); + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + if (s->gzhead == Z_NULL) { + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, OS_CODE); + s->status = BUSY_STATE; + } + else { + put_byte(s, (s->gzhead->text ? 1 : 0) + + (s->gzhead->hcrc ? 2 : 0) + + (s->gzhead->extra == Z_NULL ? 0 : 4) + + (s->gzhead->name == Z_NULL ? 0 : 8) + + (s->gzhead->comment == Z_NULL ? 0 : 16) + ); + put_byte(s, (Byte)(s->gzhead->time & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, s->gzhead->os & 0xff); + if (s->gzhead->extra != Z_NULL) { + put_byte(s, s->gzhead->extra_len & 0xff); + put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); + } + if (s->gzhead->hcrc) + strm->adler = crc32(strm->adler, s->pending_buf, + s->pending); + s->gzindex = 0; + s->status = EXTRA_STATE; + } + } + else +#endif + { + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags; + + if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) + level_flags = 0; + else if (s->level < 6) + level_flags = 1; + else if (s->level == 6) + level_flags = 2; + else + level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + s->status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = adler32(0L, Z_NULL, 0); + } + } +#ifdef GZIP + if (s->status == EXTRA_STATE) { + if (s->gzhead->extra != Z_NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + + while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) + break; + } + put_byte(s, s->gzhead->extra[s->gzindex]); + s->gzindex++; + } + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (s->gzindex == s->gzhead->extra_len) { + s->gzindex = 0; + s->status = NAME_STATE; + } + } + else + s->status = NAME_STATE; + } + if (s->status == NAME_STATE) { + if (s->gzhead->name != Z_NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + int val; + + do { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) { + val = 1; + break; + } + } + val = s->gzhead->name[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (val == 0) { + s->gzindex = 0; + s->status = COMMENT_STATE; + } + } + else + s->status = COMMENT_STATE; + } + if (s->status == COMMENT_STATE) { + if (s->gzhead->comment != Z_NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + int val; + + do { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) { + val = 1; + break; + } + } + val = s->gzhead->comment[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (val == 0) + s->status = HCRC_STATE; + } + else + s->status = HCRC_STATE; + } + if (s->status == HCRC_STATE) { + if (s->gzhead->hcrc) { + if (s->pending + 2 > s->pending_buf_size) + flush_pending(strm); + if (s->pending + 2 <= s->pending_buf_size) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + strm->adler = crc32(0L, Z_NULL, 0); + s->status = BUSY_STATE; + } + } + else + s->status = BUSY_STATE; + } +#endif + + /* Flush as much pending output as possible */ + if (s->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s->last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm->avail_in == 0 && flush <= old_flush && + flush != Z_FINISH) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm->avail_in != 0 || s->lookahead != 0 || + (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { + block_state bstate; + + bstate = s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : + (s->strategy == Z_RLE ? deflate_rle(s, flush) : + (*(configuration_table[s->level].func))(s, flush)); + + if (bstate == finish_started || bstate == finish_done) { + s->status = FINISH_STATE; + } + if (bstate == need_more || bstate == finish_started) { + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate == block_done) { + if (flush == Z_PARTIAL_FLUSH) { + _tr_align(s); + } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ + _tr_stored_block(s, (char*)0, 0L, 0); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush == Z_FULL_FLUSH) { + CLEAR_HASH(s); /* forget history */ + if (s->lookahead == 0) { + s->strstart = 0; + s->block_start = 0L; + } + } + } + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + Assert(strm->avail_out > 0, "bug2"); + + if (flush != Z_FINISH) return Z_OK; + if (s->wrap <= 0) return Z_STREAM_END; + + /* Write the trailer */ +#ifdef GZIP + if (s->wrap == 2) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); + put_byte(s, (Byte)(strm->total_in & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); + } + else +#endif + { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ + return s->pending != 0 ? Z_OK : Z_STREAM_END; +} + +/* ========================================================================= */ +int ZEXPORT deflateEnd (strm) + z_streamp strm; +{ + int status; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + + status = strm->state->status; + if (status != INIT_STATE && + status != EXTRA_STATE && + status != NAME_STATE && + status != COMMENT_STATE && + status != HCRC_STATE && + status != BUSY_STATE && + status != FINISH_STATE) { + return Z_STREAM_ERROR; + } + + /* Deallocate in reverse order of allocations: */ + TRY_FREE(strm, strm->state->pending_buf); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->prev); + TRY_FREE(strm, strm->state->window); + + ZFREE(strm, strm->state); + strm->state = Z_NULL; + + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; +} + +/* ========================================================================= + * Copy the source state to the destination state. + * To simplify the source, this is not supported for 16-bit MSDOS (which + * doesn't have enough memory anyway to duplicate compression states). + */ +int ZEXPORT deflateCopy (dest, source) + z_streamp dest; + z_streamp source; +{ +#ifdef MAXSEG_64K + return Z_STREAM_ERROR; +#else + deflate_state *ds; + deflate_state *ss; + ushf *overlay; + + + if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { + return Z_STREAM_ERROR; + } + + ss = source->state; + + zmemcpy(dest, source, sizeof(z_stream)); + + ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); + if (ds == Z_NULL) return Z_MEM_ERROR; + dest->state = (struct internal_state FAR *) ds; + zmemcpy(ds, ss, sizeof(deflate_state)); + ds->strm = dest; + + ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); + ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); + ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); + overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); + ds->pending_buf = (uchf *) overlay; + + if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || + ds->pending_buf == Z_NULL) { + deflateEnd (dest); + return Z_MEM_ERROR; + } + /* following zmemcpy do not work for 16-bit MSDOS */ + zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); + zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); + ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); + ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; + ds->bl_desc.dyn_tree = ds->bl_tree; + + return Z_OK; +#endif /* MAXSEG_64K */ +} + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +local int read_buf(strm, buf, size) + z_streamp strm; + Bytef *buf; + unsigned size; +{ + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + if (strm->state->wrap == 1) { + strm->adler = adler32(strm->adler, strm->next_in, len); + } +#ifdef GZIP + else if (strm->state->wrap == 2) { + strm->adler = crc32(strm->adler, strm->next_in, len); + } +#endif + zmemcpy(buf, strm->next_in, len); + strm->next_in += len; + strm->total_in += len; + + return (int)len; +} + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +local void lm_init (s) + deflate_state *s; +{ + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; +#ifndef FASTEST +#ifdef ASMV + match_init(); /* initialize the asm code */ +#endif +#endif +} + +#ifndef FASTEST +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +#ifndef ASMV +/* For 80x86 and 680x0, an optimized version will be provided in match.asm or + * match.S. The code will be functionally equivalent. + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + int best_len = s->prev_length; /* best match length so far */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + Posf *prev = s->prev; + uInt wmask = s->w_mask; + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ushf*)scan; + register ush scan_end = *(ushf*)(scan+best_len-1); +#else + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2. Note that the checks below + * for insufficient lookahead only occur occasionally for performance + * reasons. Therefore uninitialized memory will be accessed, and + * conditional jumps will be made that depend on those values. + * However the length of the match is limited to the lookahead, so + * the output of deflate is not affected by the uninitialized values. + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ushf*)(match+best_len-1) != scan_end || + *(ushf*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ushf*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); + + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; + return s->lookahead; +} +#endif /* ASMV */ + +#else /* FASTEST */ + +/* --------------------------------------------------------------------------- + * Optimized version for FASTEST only + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + Assert(cur_match < s->strstart, "no future"); + + match = s->window + cur_match; + + /* Return failure if the match length is less than 2: + */ + if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match += 2; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + + if (len < MIN_MATCH) return MIN_MATCH - 1; + + s->match_start = cur_match; + return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; +} + +#endif /* FASTEST */ + +#ifdef DEBUG +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +local void check_match(s, start, match, length) + deflate_state *s; + IPos start, match; + int length; +{ + /* check that the match is indeed a match */ + if (zmemcmp(s->window + match, + s->window + start, length) != EQUAL) { + fprintf(stderr, " start %u, match %u, length %d\n", + start, match, length); + do { + fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start-match, length); + do { putc(s->window[start++], stderr); } while (--length != 0); + } +} +#else +# define check_match(s, start, match, length) +#endif /* DEBUG */ + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +local void fill_window(s) + deflate_state *s; +{ + register unsigned n, m; + register Posf *p; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (sizeof(int) <= 2) { + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if + * strstart == 0 && lookahead == 1 (input done a byte at time) + */ + more--; + } + } + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s->strstart >= wsize+MAX_DIST(s)) { + + zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + } while (--n); + + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif + more += wsize; + } + if (s->strm->avail_in == 0) return; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead >= MIN_MATCH) { + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); + + /* If the WIN_INIT bytes after the end of the current data have never been + * written, then zero those bytes in order to avoid memory check reports of + * the use of uninitialized (or uninitialised as Julian writes) bytes by + * the longest match routines. Update the high water mark for the next + * time through here. WIN_INIT is set to MAX_MATCH since the longest match + * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. + */ + if (s->high_water < s->window_size) { + ulg curr = s->strstart + (ulg)(s->lookahead); + ulg init; + + if (s->high_water < curr) { + /* Previous high water mark below current data -- zero WIN_INIT + * bytes or up to end of window, whichever is less. + */ + init = s->window_size - curr; + if (init > WIN_INIT) + init = WIN_INIT; + zmemzero(s->window + curr, (unsigned)init); + s->high_water = curr + init; + } + else if (s->high_water < (ulg)curr + WIN_INIT) { + /* High water mark at or above current data, but below current data + * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up + * to end of window, whichever is less. + */ + init = (ulg)curr + WIN_INIT - s->high_water; + if (init > s->window_size - s->high_water) + init = s->window_size - s->high_water; + zmemzero(s->window + s->high_water, (unsigned)init); + s->high_water += init; + } + } +} + +/* =========================================================================== + * Flush the current block, with given end-of-file flag. + * IN assertion: strstart is set to the end of the current match. + */ +#define FLUSH_BLOCK_ONLY(s, last) { \ + _tr_flush_block(s, (s->block_start >= 0L ? \ + (charf *)&s->window[(unsigned)s->block_start] : \ + (charf *)Z_NULL), \ + (ulg)((long)s->strstart - s->block_start), \ + (last)); \ + s->block_start = s->strstart; \ + flush_pending(s->strm); \ + Tracev((stderr,"[FLUSH]")); \ +} + +/* Same but force premature exit if necessary. */ +#define FLUSH_BLOCK(s, last) { \ + FLUSH_BLOCK_ONLY(s, last); \ + if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \ +} + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ +local block_state deflate_stored(s, flush) + deflate_state *s; + int flush; +{ + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + ulg max_block_size = 0xffff; + ulg max_start; + + if (max_block_size > s->pending_buf_size - 5) { + max_block_size = s->pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (;;) { + /* Fill the window as much as possible: */ + if (s->lookahead <= 1) { + + Assert(s->strstart < s->w_size+MAX_DIST(s) || + s->block_start >= (long)s->w_size, "slide too late"); + + fill_window(s); + if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; + + if (s->lookahead == 0) break; /* flush the current block */ + } + Assert(s->block_start >= 0L, "block gone"); + + s->strstart += s->lookahead; + s->lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + max_start = s->block_start + max_block_size; + if (s->strstart == 0 || (ulg)s->strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s->lookahead = (uInt)(s->strstart - max_start); + s->strstart = (uInt)max_start; + FLUSH_BLOCK(s, 0); + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { + FLUSH_BLOCK(s, 0); + } + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +local block_state deflate_fast(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head; /* head of the hash chain */ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = NIL; + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s->match_length = longest_match (s, hash_head); + /* longest_match() sets match_start */ + } + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->match_start, s->match_length); + + _tr_tally_dist(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ +#ifndef FASTEST + if (s->match_length <= s->max_insert_length && + s->lookahead >= MIN_MATCH) { + s->match_length--; /* string at strstart already in table */ + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s->match_length != 0); + s->strstart++; + } else +#endif + { + s->strstart += s->match_length; + s->match_length = 0; + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +#ifndef FASTEST +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +local block_state deflate_slow(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = NIL; + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; + + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s->match_length = longest_match (s, hash_head); + /* longest_match() sets match_start */ + + if (s->match_length <= 5 && (s->strategy == Z_FILTERED +#if TOO_FAR <= 32767 + || (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR) +#endif + )) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s->match_length = MIN_MATCH-1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + check_match(s, s->strstart-1, s->prev_match, s->prev_length); + + _tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { + INSERT_STRING(s, s->strstart, hash_head); + } + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; + + if (bflush) FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + if (bflush) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return need_more; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + s->match_available = 0; + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} +#endif /* FASTEST */ + +/* =========================================================================== + * For Z_RLE, simply look for runs of bytes, generate matches only of distance + * one. Do not maintain a hash table. (It will be regenerated if this run of + * deflate switches away from Z_RLE.) + */ +local block_state deflate_rle(s, flush) + deflate_state *s; + int flush; +{ + int bflush; /* set if current block must be flushed */ + uInt prev; /* byte at distance one to match */ + Bytef *scan, *strend; /* scan goes up to strend for length of run */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the longest encodable run. + */ + if (s->lookahead < MAX_MATCH) { + fill_window(s); + if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* See how many times the previous byte repeats */ + s->match_length = 0; + if (s->lookahead >= MIN_MATCH && s->strstart > 0) { + scan = s->window + s->strstart - 1; + prev = *scan; + if (prev == *++scan && prev == *++scan && prev == *++scan) { + strend = s->window + s->strstart + MAX_MATCH; + do { + } while (prev == *++scan && prev == *++scan && + prev == *++scan && prev == *++scan && + prev == *++scan && prev == *++scan && + prev == *++scan && prev == *++scan && + scan < strend); + s->match_length = MAX_MATCH - (int)(strend - scan); + if (s->match_length > s->lookahead) + s->match_length = s->lookahead; + } + } + + /* Emit match if have run of MIN_MATCH or longer, else emit literal */ + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->strstart - 1, s->match_length); + + _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + s->strstart += s->match_length; + s->match_length = 0; + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. + * (It will be regenerated if this run of deflate switches away from Huffman.) + */ +local block_state deflate_huff(s, flush) + deflate_state *s; + int flush; +{ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we have a literal to write. */ + if (s->lookahead == 0) { + fill_window(s); + if (s->lookahead == 0) { + if (flush == Z_NO_FLUSH) + return need_more; + break; /* flush the current block */ + } + } + + /* Output a literal byte */ + s->match_length = 0; + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} Index: branches/slice/rev749/modules/KextPatcher/kext_patcher.h =================================================================== --- branches/slice/rev749/modules/KextPatcher/kext_patcher.h (revision 0) +++ branches/slice/rev749/modules/KextPatcher/kext_patcher.h (revision 1169) @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2009 Evan Lojewski. All rights reserved. + * + */ +#ifndef __BOOT2_KERNEL_PATCHER_H +#define __BOOT2_KERNEL_PATCHER_H + + +void KextPatcher_start(); + +void kext_loaded(void* module, void* length, void* executableAddr, void* arg3); +void mkext_loaded(void* filespec, void* package, void* lenght, void* arg3); + + +#endif /* !__BOOT2_KERNEL_PATCHER_H */ Index: branches/slice/rev749/modules/KextPatcher/zutil.c =================================================================== --- branches/slice/rev749/modules/KextPatcher/zutil.c (revision 0) +++ branches/slice/rev749/modules/KextPatcher/zutil.c (revision 1169) @@ -0,0 +1,320 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2005, 2010 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" + +extern void *calloc(size_t nmemb, size_t size); + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +const char * const z_errmsg[10] = { +"need dictionary", /* Z_NEED_DICT 2 */ +"stream end", /* Z_STREAM_END 1 */ +"", /* Z_OK 0 */ +"file error", /* Z_ERRNO (-1) */ +"stream error", /* Z_STREAM_ERROR (-2) */ +"data error", /* Z_DATA_ERROR (-3) */ +"insufficient memory", /* Z_MEM_ERROR (-4) */ +"buffer error", /* Z_BUF_ERROR (-5) */ +"incompatible version",/* Z_VERSION_ERROR (-6) */ +""}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +uLong ZEXPORT zlibCompileFlags() +{ + uLong flags; + + flags = 0; + switch ((int)(sizeof(uInt))) { + case 2: break; + case 4: flags += 1; break; + case 8: flags += 2; break; + default: flags += 3; + } + switch ((int)(sizeof(uLong))) { + case 2: break; + case 4: flags += 1 << 2; break; + case 8: flags += 2 << 2; break; + default: flags += 3 << 2; + } + switch ((int)(sizeof(voidpf))) { + case 2: break; + case 4: flags += 1 << 4; break; + case 8: flags += 2 << 4; break; + default: flags += 3 << 4; + } + switch ((int)(sizeof(z_off_t))) { + case 2: break; + case 4: flags += 1 << 6; break; + case 8: flags += 2 << 6; break; + default: flags += 3 << 6; + } +#ifdef DEBUG + flags += 1 << 8; +#endif +#if defined(ASMV) || defined(ASMINF) + flags += 1 << 9; +#endif +#ifdef ZLIB_WINAPI + flags += 1 << 10; +#endif +#ifdef BUILDFIXED + flags += 1 << 12; +#endif +#ifdef DYNAMIC_CRC_TABLE + flags += 1 << 13; +#endif +#ifdef NO_GZCOMPRESS + flags += 1L << 16; +#endif +#ifdef NO_GZIP + flags += 1L << 17; +#endif +#ifdef PKZIP_BUG_WORKAROUND + flags += 1L << 20; +#endif +#ifdef FASTEST + flags += 1L << 21; +#endif +#ifdef STDC +# ifdef NO_vsnprintf + flags += 1L << 25; +# ifdef HAS_vsprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_vsnprintf_void + flags += 1L << 26; +# endif +# endif +#else + flags += 1L << 24; +# ifdef NO_snprintf + flags += 1L << 25; +# ifdef HAS_sprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_snprintf_void + flags += 1L << 26; +# endif +# endif +#endif + return flags; +} + +#ifdef DEBUG + +# ifndef verbose +# define verbose 0 +# endif +int ZLIB_INTERNAL z_verbose = verbose; + +void ZLIB_INTERNAL z_error (m) + char *m; +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + +#if defined(_WIN32_WCE) + /* The Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. + */ + int errno = 0; +#endif + +#ifndef HAVE_MEMCPY + +void ZLIB_INTERNAL zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int ZLIB_INTERNAL zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void ZLIB_INTERNAL zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + + +#ifdef SYS16BIT + +#ifdef __TURBOC__ +/* Turbo C in 16-bit mode */ + +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf = opaque; /* just to make some compilers happy */ + ulg bsize = (ulg)items*size; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) +{ + int n; + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + ptr = opaque; /* just to make some compilers happy */ + Assert(0, "zcfree: ptr not found"); +} + +#endif /* __TURBOC__ */ + + +#ifdef M_I86 +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + return _halloc((long)items, size); +} + +void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + _hfree(ptr); +} + +#endif /* M_I86 */ + +#endif /* SYS16BIT */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +//extern voidp malloc OF((uInt size)); +//extern voidp calloc OF((uInt items, uInt size)); +//extern void free OF((voidpf ptr)); +#endif + +voidpf ZLIB_INTERNAL zcalloc (opaque, items, size) + voidpf opaque; + unsigned items; + unsigned size; +{ + if (opaque) items += size - size; /* make compiler happy */ + return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : + (voidpf)calloc(items, size); +} + +void ZLIB_INTERNAL zcfree (opaque, ptr) + voidpf opaque; + voidpf ptr; +{ + free(ptr); + if (opaque) return; /* make compiler happy */ +} + +#endif /* MY_ZCALLOC */ Index: branches/slice/rev749/modules/KextPatcher/hex_editor.c =================================================================== --- branches/slice/rev749/modules/KextPatcher/hex_editor.c (revision 0) +++ branches/slice/rev749/modules/KextPatcher/hex_editor.c (revision 1169) @@ -0,0 +1,119 @@ +/* + * hex_editor.c + * + * + * Created by Meklort on 10/19/10. + * Copyright 2010 Evan Lojewski. All rights reserved. + * + */ + +#include "hex_editor.h" + +int replace_patern(char* pattern, char* replacement, char* buffer, long buffer_size) +{ + long index = 0; + int num_replaced = 0; + // NOTE: patehrn and replacement are null terminated. This may change later + // If I need to replace null bytes + + if(!pattern || + !replacement || + !buffer || + strlen(pattern) != strlen(replacement) + ) return 0; + + + while(index < buffer_size - strlen(pattern)) + { + bool located = true; + int i = 0; + while(located && i < strlen(pattern)) + { + if(pattern[i] != buffer[i + index]) located = false; + i++; + } + + if(located) + { + printf("Located patern\n"); + index += strlen(pattern) - 1; + num_replaced++; + } + + index++; + } + + return num_replaced; +} + + +int replace_word(uint32_t pattern, uint32_t repalcement, char* buffer, long buffer_size) +{ + int num_replaced = 0; + char* tmp = buffer; + + if(!buffer || !buffer_size) return 0; + + + while(tmp < buffer + buffer_size - sizeof(uint32_t)) + { + + uint32_t* current= (uint32_t*)tmp; + + if(*current == pattern) + { + *current = repalcement; + num_replaced++; + tmp += 4; + } + else + { + tmp++; + } + } + + return num_replaced; +} + +void replace_string(char* find, char* replace, char* string, int length) +{ + if(!find || + !replace || + !string || + !length || + strlen(find) != strlen(replace)) return; + + char* str = string; + while(length && strncmp(str, find, strlen(find)-1)) + { + length--; + str++; + } + strncpy(str, replace, strlen(replace)); // don't copy the null char +} + +void replace_bytes(char* find, int find_size, char* replace, int replace_size, char* exec, int length) +{ + if(!find || + !replace || + !exec || + !length || + find_size > replace_size) // Allow find_size to be less than replace_size. Will overwrite bytes including and *after* located pattern + return; + + char* search = exec; + + + while(memcmp(search, find, find_size) != 0 + && ((search - exec) < length)) + { + search++; + } + + if((search - exec) < length) + { + // Mem found, replace it + memcpy(search, replace, replace_size); + } +} + Index: branches/slice/rev749/modules/KextPatcher/inffast.c =================================================================== --- branches/slice/rev749/modules/KextPatcher/inffast.c (revision 0) +++ branches/slice/rev749/modules/KextPatcher/inffast.c (revision 1169) @@ -0,0 +1,340 @@ +/* inffast.c -- fast decoding + * Copyright (C) 1995-2008, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifndef ASMINF + +/* Allow machine dependent optimization for post-increment or pre-increment. + Based on testing to date, + Pre-increment preferred for: + - PowerPC G3 (Adler) + - MIPS R5000 (Randers-Pehrson) + Post-increment preferred for: + - none + No measurable difference: + - Pentium III (Anderson) + - M68060 (Nikl) + */ +#ifdef POSTINC +# define OFF 0 +# define PUP(a) *(a)++ +#else +# define OFF 1 +# define PUP(a) *++(a) +#endif + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void ZLIB_INTERNAL inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + unsigned char FAR *in; /* local strm->next_in */ + unsigned char FAR *last; /* while in < last, enough input available */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ +#ifdef INFLATE_STRICT + unsigned dmax; /* maximum distance from zlib header */ +#endif + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ + unsigned long hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const FAR *lcode; /* local strm->lencode */ + code const FAR *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code here; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char FAR *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + in = strm->next_in - OFF; + last = in + (strm->avail_in - 5); + out = strm->next_out - OFF; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); +#ifdef INFLATE_STRICT + dmax = state->dmax; +#endif + wsize = state->wsize; + whave = state->whave; + wnext = state->wnext; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + here = lcode[hold & lmask]; + dolen: + op = (unsigned)(here.bits); + hold >>= op; + bits -= op; + op = (unsigned)(here.op); + if (op == 0) { /* literal */ + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + PUP(out) = (unsigned char)(here.val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(here.val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + here = dcode[hold & dmask]; + dodist: + op = (unsigned)(here.bits); + hold >>= op; + bits -= op; + op = (unsigned)(here.op); + if (op & 16) { /* distance base */ + dist = (unsigned)(here.val); + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + } + dist += (unsigned)hold & ((1U << op) - 1); +#ifdef INFLATE_STRICT + if (dist > dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + hold >>= op; + bits -= op; + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + if (state->sane) { + strm->msg = + (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + if (len <= op - whave) { + do { + PUP(out) = 0; + } while (--len); + continue; + } + len -= op - whave; + do { + PUP(out) = 0; + } while (--op > whave); + if (op == 0) { + from = out - dist; + do { + PUP(out) = PUP(from); + } while (--len); + continue; + } +#endif + } + from = window - OFF; + if (wnext == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + else if (wnext < op) { /* wrap around window */ + from += wsize + wnext - op; + op -= wnext; + if (op < len) { /* some from end of window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = window - OFF; + if (wnext < len) { /* some from start of window */ + op = wnext; + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + } + else { /* contiguous in window */ + from += wnext - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + else { + from = out - dist; /* copy direct from output */ + do { /* minimum length is three */ + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } while (len > 2); + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + here = dcode[here.val + (hold & ((1U << op) - 1))]; + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + here = lcode[here.val + (hold & ((1U << op) - 1))]; + goto dolen; + } + else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in + OFF; + strm->next_out = out + OFF; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); + state->hold = hold; + state->bits = bits; + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and wnext == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */ Index: branches/slice/rev749/modules/KextPatcher/Makefile =================================================================== --- branches/slice/rev749/modules/KextPatcher/Makefile (revision 0) +++ branches/slice/rev749/modules/KextPatcher/Makefile (revision 1169) @@ -0,0 +1,42 @@ +MODULE_NAME = KextPatcher +MODULE_VERSION = "1.0.0" +MODULE_COMPAT_VERSION = "1.0.0" +MODULE_START = _$(MODULE_NAME)_start +MODULE_DEPENDENCIES = + +DIR = KextPatcher + +MODULE_OBJS = kext_patcher.o inflate.o deflate.o zutil.o inftrees.o inffast.o adler32.o hex_editor.o trees.o + +OPTIM = -Os -Oz +DEBUG = -DNOTHING +#DEBUG = -DDEBUG_HELLO_WORLD=1 +CFLAGS = $(RC_CFLAGS) $(OPTIM) $(MORECPP) -arch i386 -g -Wmost \ + -D__ARCHITECTURE__=\"i386\" -DSAIO_INTERNAL_USER \ + -DRCZ_COMPRESSED_FILE_SUPPORT $(DEBUG) \ + -fno-builtin $(OMIT_FRAME_POINTER_CFLAG) \ + -mpreferred-stack-boundary=2 -fno-align-functions -fno-stack-protector \ + -march=pentium4 -msse2 -mfpmath=sse -msoft-float -fno-common + +DEFINES= +CONFIG = hd +INC = -I. -I.. -I$(SYMROOT) -I$(UTILDIR) -I$(LIBSADIR) -I$(LIBSAIODIR) -I$(BOOT2DIR) +LIBS= + +VPATH = $(OBJROOT):$(SYMROOT) + + + +SFILES = +CFILES = +HFILES = +EXPORTED_HFILES = +INSTALLED_HFILES = +OTHERFILES = Makefile +ALLSRC = $(SFILES) $(CFILES) \ + $(HFILES) $(OTHERFILES) +DIRS_NEEDED = $(OBJROOT) $(SYMROOT) + +all embedtheme optionrom: dylib + +include ../MakeInc.dir \ No newline at end of file Index: branches/slice/rev749/modules/KextPatcher/adler32.c =================================================================== --- branches/slice/rev749/modules/KextPatcher/adler32.c (revision 0) +++ branches/slice/rev749/modules/KextPatcher/adler32.c (revision 1169) @@ -0,0 +1,169 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2007 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" + +#define local static + +local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2); + +#define BASE 65521UL /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +/* use NO_DIVIDE if your processor does not do division in hardware */ +#ifdef NO_DIVIDE +# define MOD(a) \ + do { \ + if (a >= (BASE << 16)) a -= (BASE << 16); \ + if (a >= (BASE << 15)) a -= (BASE << 15); \ + if (a >= (BASE << 14)) a -= (BASE << 14); \ + if (a >= (BASE << 13)) a -= (BASE << 13); \ + if (a >= (BASE << 12)) a -= (BASE << 12); \ + if (a >= (BASE << 11)) a -= (BASE << 11); \ + if (a >= (BASE << 10)) a -= (BASE << 10); \ + if (a >= (BASE << 9)) a -= (BASE << 9); \ + if (a >= (BASE << 8)) a -= (BASE << 8); \ + if (a >= (BASE << 7)) a -= (BASE << 7); \ + if (a >= (BASE << 6)) a -= (BASE << 6); \ + if (a >= (BASE << 5)) a -= (BASE << 5); \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +# define MOD4(a) \ + do { \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +#else +# define MOD(a) a %= BASE +# define MOD4(a) a %= BASE +#endif + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + unsigned long sum2; + unsigned n; + + /* split Adler-32 into component sums */ + sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; + + /* in case user likes doing a byte at a time, keep it fast */ + if (len == 1) { + adler += buf[0]; + if (adler >= BASE) + adler -= BASE; + sum2 += adler; + if (sum2 >= BASE) + sum2 -= BASE; + return adler | (sum2 << 16); + } + + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (buf == Z_NULL) + return 1L; + + /* in case short lengths are provided, keep it somewhat fast */ + if (len < 16) { + while (len--) { + adler += *buf++; + sum2 += adler; + } + if (adler >= BASE) + adler -= BASE; + MOD4(sum2); /* only added so many BASE's */ + return adler | (sum2 << 16); + } + + /* do length NMAX blocks -- requires just one modulo operation */ + while (len >= NMAX) { + len -= NMAX; + n = NMAX / 16; /* NMAX is divisible by 16 */ + do { + DO16(buf); /* 16 sums unrolled */ + buf += 16; + } while (--n); + MOD(adler); + MOD(sum2); + } + + /* do remaining bytes (less than NMAX, still just one modulo) */ + if (len) { /* avoid modulos if none remaining */ + while (len >= 16) { + len -= 16; + DO16(buf); + buf += 16; + } + while (len--) { + adler += *buf++; + sum2 += adler; + } + MOD(adler); + MOD(sum2); + } + + /* return recombined sums */ + return adler | (sum2 << 16); +} + +/* ========================================================================= */ +local uLong adler32_combine_(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off64_t len2; +{ + unsigned long sum1; + unsigned long sum2; + unsigned rem; + + /* the derivation of this formula is left as an exercise for the reader */ + rem = (unsigned)(len2 % BASE); + sum1 = adler1 & 0xffff; + sum2 = rem * sum1; + MOD(sum2); + sum1 += (adler2 & 0xffff) + BASE - 1; + sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; + if (sum1 >= BASE) sum1 -= BASE; + if (sum1 >= BASE) sum1 -= BASE; + if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1); + if (sum2 >= BASE) sum2 -= BASE; + return sum1 | (sum2 << 16); +} + +/* ========================================================================= */ +uLong ZEXPORT adler32_combine(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off_t len2; +{ + return adler32_combine_(adler1, adler2, len2); +} + +uLong ZEXPORT adler32_combine64(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off64_t len2; +{ + return adler32_combine_(adler1, adler2, len2); +} Index: branches/slice/rev749/modules/NVRAM/NVRAM.c =================================================================== --- branches/slice/rev749/modules/NVRAM/NVRAM.c (revision 0) +++ branches/slice/rev749/modules/NVRAM/NVRAM.c (revision 1169) @@ -0,0 +1,299 @@ +/* + * Template by (c) 2009 Evan Lojewski. All rights reserved. + * + * NVRAM module by Slice 2010. + */ + +#include "libsaio.h" +#include "modules.h" +#include "boot.h" +#include "bootstruct.h" +#include "pci.h" +#include "efi.h" +#include "smbios_patcher.h" +#include "xml.h" + +#ifndef DEBUG_NVRAM +#define DEBUG_NVRAM 0 +#endif + +#if DEBUG_NVRAM +#define DBG(x...) printf(x) +#else +#define DBG(x...) msglog(x) +#endif + +/*static const char const FIRMWARE_REVISION_PROP[] = "firmware-revision"; +static const char const FIRMWARE_ABI_PROP[] = "firmware-abi"; +static const char const FIRMWARE_VENDOR_PROP[] = "firmware-vendor"; +static const char const FIRMWARE_ABI_32_PROP_VALUE[] = "EFI32"; +static const char const FIRMWARE_ABI_64_PROP_VALUE[] = "EFI64"; +static const char const SYSTEM_ID_PROP[] = "system-id"; +static const char const SYSTEM_SERIAL_PROP[] = "SystemSerialNumber"; +static const char const SYSTEM_TYPE_PROP[] = "system-type"; +static const char const MODEL_PROP[] = "Model"; + */ +const char PLATFORM_UUID[] = "platform-uuid"; +//EFI_UINT32 const FIRMWARE_FEATURE_MASK = 0x000003FF; +EFI_UINT32 const STATIC_ZERO = 0; + +#define kBL_GLOBAL_NVRAM_GUID "8BE4DF61-93CA-11D2-AA0D-00E098032B8C" + +// Check if a system supports CSM legacy mode +#define kBL_APPLE_VENDOR_NVRAM_GUID "4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14" +#define UUID_LEN 16 + +extern EFI_GUID* getSystemID(); +void NVRAM_hook(void* arg1, void* arg2, void* arg3, void* arg4); +void NVRAM_start(void); + +typedef struct { + char Name[32]; + char Value[512]; +} variables; +int readNVRAM(variables* v); + + +void NVRAM_hook(void* arg1, void* arg2, void* arg3, void* arg4); +/* +void NVRAM_start_hook(void* arg1, void* arg2, void* arg3, void* arg4) +{ + msglog("NVRAM started with ExecKernel\n"); + +} +*/ + +void NVRAM_start() +{ +// register_hook_callback("ExecKernel", &NVRAM_start_hook); + // register_hook_callback("Kernel Start", &NVRAM_hook); + register_hook_callback("ModulesLoaded", &NVRAM_hook); +} + +void NVRAM_hook(void* arg1, void* arg2, void* arg3, void* arg4) +{ + char bootName[128]; + variables* var; + char* ffName; + uint8_t * FirmwareFeatures; + EFI_UINT32* FirmwareFeaturesMask; + char* ffmName; + char* boName; + char* bnName; + EFI_GUID* ret = 0; + uint16_t bootOptionNumber = 0; + int i, j; + +// BLESS_EFI_LOAD_OPTION* NextBoot =(BLESS_EFI_LOAD_OPTION*)gBootOrder; + + DBG("NVRAM started with ModulesLoaded\n"); + + //Slice create /options node -> /fakenvram + // I need to use fakenvram until I know what is happen +// bool UseNVRAM = FALSE; + bool ClearNVRAM = FALSE; + const char* buff; +// TagPtr dictionary; + int cnt; + var = malloc(sizeof(variables)+1); + ClearNVRAM = getValueForKey(kClearNVRAM, &buff, &cnt, &bootInfo->bootConfig); + if (!ClearNVRAM) { + readNVRAM(var); + } + + for (i=0; i<32; i++) { + if (var[i].Name[0] == 0) { + break; + } + if (strcmp(var[i].Name, "efi-boot-device")==0) { + //XMLParseFile(var[i].Value, &dictionary); + //buff = XMLGetProperty(dictionary, "BLLastBSDName")->string; + verbose("Required boot device is %s\n", var[i].Value); + //NextBoot->FilePathListLength = 1; + //strcpy(NextBoot->Description, buff); + break; + } + } + + Node* optionsNode = DT__FindNode("/options", true); //"/fakenvram" + ffName = malloc(sizeof(PLATFORM_UUID)+1); + strcpy(ffName, PLATFORM_UUID); + ret = getSystemID(); + DT__AddProperty(optionsNode, ffName, UUID_LEN, (EFI_UINT32*) ret); + + // this information can be obtained from DMI Type 0 + SMBByte* p = (SMBByte*)FindFirstDmiTableOfType(0, 0x18); + FirmwareFeatures = malloc(sizeof(SMBByte)); + //TODO - the bufferFF must be composed from bits p[0x12] and [0x13]. Datasheet needed + *FirmwareFeatures = ((p[19] >> 1) & 1) //USB Legacy is supported + | ((p[18] >> 14) & 2) //Boot from CD is supported + | 0x14; //default for bless (GUID partition) + + sprintf(bootName, "%s:FirmwareFeatures", kBL_APPLE_VENDOR_NVRAM_GUID); + ffName = malloc(sizeof(bootName)+1); + strcpy(ffName, bootName); + DT__AddProperty(optionsNode, ffName, sizeof(uint32_t), (char *)FirmwareFeatures); //legacy support + + sprintf(bootName, "%s:FirmwareFeaturesMask", kBL_APPLE_VENDOR_NVRAM_GUID); + FirmwareFeaturesMask = malloc(sizeof(EFI_UINT32)); + *FirmwareFeaturesMask = (EFI_UINT32)0x3ff; + ffmName = malloc(sizeof(bootName)+1); + strcpy(ffmName, bootName); + DT__AddProperty(optionsNode, ffmName, sizeof(uint32_t), (EFI_UINT32*)FirmwareFeaturesMask); + + //TODO - check, validate and fill by bvr structure. + //here I am not sure what is BootOrder: node or property? + //Node* bootNode = DT__AddChild(optionsNode, kBL_GLOBAL_NVRAM_GUID ":BootOrder"); + sprintf(bootName, "%s:BootOrder", kBL_GLOBAL_NVRAM_GUID); + boName = malloc(sizeof(bootName)+1); + strcpy(boName, bootName); + DT__AddProperty(optionsNode, boName, sizeof(uint32_t), (EFI_UINT32*)&STATIC_ZERO); + + sprintf(bootName, "%s:Boot%04hx", kBL_GLOBAL_NVRAM_GUID, bootOptionNumber); + bnName = malloc(sizeof(bootName)+1); + strcpy(bnName, bootName); + DT__AddProperty(optionsNode, bnName, sizeof(uint32_t), (EFI_UINT32*)&STATIC_ZERO); + + + //can we add here boot-properties? + // optionsNode = DT__FindNode("chosen", true); +#if 1 //NOTYET + int lbC = 0; + while(((char*)&bootInfo->bootConfig)[lbC++]); + if (lbC > sizeof(bootInfo->bootConfig)) lbC = sizeof(bootInfo->bootConfig); + DT__AddProperty(optionsNode, "boot-args", lbC, (char*)&bootInfo->bootConfig); +#endif + //TODO - BootCamp emulation? + /* + romNode = DT__FindNode("/rom", true); + DT__AddProperty(romNode, "fv-main-address"... //provided by AppleSMBIOS + DT__AddProperty(romNode, "fv-main-size"... + "IOEFIDevicePathType" -> "MediaFirmwareVolumeFilePath" + "Guid" -> "2B0585EB-D8B8-49A9-8B8C-E21B01AEF2B7" + + */ + // + + for (i=0; i<32; i++) { + DBG("NVRAM get a name %s\n", var[i].Name); + if (var[i].Name[0]) { + if (isdigit(var[i].Name[0])) { + msglog(" ...it is digit...\n"); + continue; + } + j=0; + while (var[i].Value[j++]); + DT__AddProperty(optionsNode, var[i].Name, j,&var[i].Value); +#if 1 //DEBUG_NVRAM + DBG("NVRAM add name=%s value=%s length=%d\n", var[i].Name, var[i].Value, j); +#endif + } else { + break; + } + + } + //Serialization? + bnName[0] = bnName[1] = 0; + DT__AddProperty(optionsNode, bnName, sizeof(uint32_t), (EFI_UINT32*)&STATIC_ZERO); +} + +const char NVRAM_INF[] = "nvram.inf"; +int readNVRAM(variables* var) +{ + int fd, fsize; + char* nvr = 0; + DBG("Start NVRAM reading\n"); + if ((fd = open(NVRAM_INF, 0)) < 0) { + DBG("[ERROR] open NVRAM failed\n"); + return -1; + } + fsize = file_size(fd); + if (!fsize) { + DBG(" zero NVRAM file\n"); + close (fd); + return -1; + } + if ((nvr = malloc(fsize)) == NULL) { + DBG("[ERROR] alloc NVRAM memory failed\n"); + close (fd); + return -1; + } + if (read (fd, nvr, fsize) != fsize) { + DBG("[ERROR] read %s failed\n", NVRAM_INF); + close (fd); + return -1; + } + close (fd); +/* if ((var = malloc(fsize)) == NULL) { + DBG("[ERROR] alloc VAR memory failed\n"); + return -1; + }*/ + int i = 0; + char * onvr = nvr; + bool skipGUID; + while (*nvr) { + int j = 0; + skipGUID = false; + DBG("Name[%d]:", i); + while (*nvr != 9) { +// DBG("%c", *nvr); + if (*nvr == 4) { + skipGUID = true; //TODO this is GUID + nvr++; + } else + var[i].Name[j++] = *nvr++; + } + DBG("\n"); + nvr++; //skip \09 + var[i].Name[j] = 0; //end of c-string + if (skipGUID) { + //TODO this is GUID + DBG("skip GUID\n"); + while (*nvr++ != 0x0A) {} + i--; + } else { + + j = 0; + unsigned char c; + while (*nvr != 0x0A) { + c = *nvr++; + if (c == 0x25) { //TODO this is hex + int k1=*nvr++; + if ((k1 >= 0x30) && (k1 <= 0x39)) { + k1 = k1 - 0x30; + } + if ((k1 > 0x60) && (k1 <= 0x66)) { + k1 = k1 - 0x60 + 10; + } + int k2=*nvr++; + if ((k2 >= 0x30) && (k2 <= 0x39)) { + k2 = k2 - 0x30; + } + if ((k2 > 0x60) && (k2 <= 0x66)) { + k2 = k2 - 0x60 + 10; + } + c = (k1 << 4) + k2; + //break; + } + var[i].Value[j++] = c; + } + nvr++; + DBG("Value[%d]:", i); + int m; + for (m=0; m fsize) { + DBG("end of buffer\n"); + break; + } + } + var[i].Name[0]=0; + var[i].Name[1]=0; + + return 0; +} \ No newline at end of file Index: branches/slice/rev749/modules/NVRAM/Makefile =================================================================== --- branches/slice/rev749/modules/NVRAM/Makefile (revision 0) +++ branches/slice/rev749/modules/NVRAM/Makefile (revision 1169) @@ -0,0 +1,44 @@ + +MODULE_NAME = NVRAM +MODULE_VERSION = "1.0.0" +MODULE_COMPAT_VERSION = "1.0.0" +MODULE_START = _$(MODULE_NAME)_start +MODULE_DEPENDENCIES = + +DIR = NVRAM + +MODULE_OBJS = NVRAM.o + +OPTIM = -Os -Oz +DEBUG = -DNOTHING +#DEBUG = -DDEBUG_HELLO_WORLD=1 +CFLAGS = $(RC_CFLAGS) $(OPTIM) $(MORECPP) -arch i386 -g -Wmost \ + -D__ARCHITECTURE__=\"i386\" -DSAIO_INTERNAL_USER \ + -DRCZ_COMPRESSED_FILE_SUPPORT $(DEBUG) \ + -fno-builtin $(OMIT_FRAME_POINTER_CFLAG) \ + -mpreferred-stack-boundary=2 -fno-align-functions -fno-stack-protector \ + -march=pentium4 -msse2 -mfpmath=sse -msoft-float -fno-common + +DEFINES= +CONFIG = hd +INC = -I. -I.. -I$(SYMROOT) -I$(UTILDIR) -I$(LIBSADIR) -I$(LIBSAIODIR) -I$(BOOT2DIR) +LIBS= + +VPATH = $(OBJROOT):$(SYMROOT) + + + +SFILES = +CFILES = +HFILES = +EXPORTED_HFILES = +INSTALLED_HFILES = +OTHERFILES = Makefile +ALLSRC = $(SFILES) $(CFILES) \ + $(HFILES) $(OTHERFILES) +DIRS_NEEDED = $(OBJROOT) $(SYMROOT) + +all embedtheme optionrom: dylib + + +include ../MakeInc.dir \ No newline at end of file Index: branches/slice/rev749/modules/include/modules =================================================================== --- branches/slice/rev749/modules/include/modules (revision 0) +++ branches/slice/rev749/modules/include/modules (revision 1169) @@ -0,0 +1,104 @@ +extern "C" { +/* + * Module Loading functionality + * Copyright 2009 Evan Lojewski. All rights reserved. + * + */ + +#include +#include + + +// There is a bug with the module system / rebasing / binding +// that causes static variables to be incorrectly rebased or bound +// Disable static variables for the moment +// #define static + +#ifndef __BOOT_MODULES_H +#define __BOOT_MODULES_H + +#define SYMBOLS_MODULE "Symbols.dylib" + +#define SYMBOL_LOOKUP_SYMBOL "_lookup_symbol" +#define STUB_ENTRY_SIZE 6 + +#define SECT_NON_LAZY_SYMBOL_PTR "__nl_symbol_ptr" +#define SECT_SYMBOL_STUBS "__symbol_stub" + + +#define VALID_FUNCTION(__x__) (__x__ && (void*)__x__ != (void*)0xFFFFFFFF) + +extern unsigned long long textAddress; +extern unsigned long long textSection; + + +typedef struct symbolList_t +{ + char* symbol; + unsigned int addr; + struct symbolList_t* next; +} symbolList_t; + +typedef struct moduleList_t +{ + char* module; + unsigned int version; + unsigned int compat; + struct moduleList_t* next; +} moduleList_t; + +typedef struct callbackList_t +{ + void(*callback)(void*, void*, void*, void*); + struct callbackList_t* next; +} callbackList_t; + +typedef struct moduleHook_t +{ + const char* name; + callbackList_t* callbacks; + struct moduleHook_t* next; +} moduleHook_t; + + + +int init_module_system(); +void load_all_modules(); + +/* + * Modules Interface + * execute_hook + * Exexutes a registered hook. All callbaks are + * called in the same order that they were added + * + * register_hook_callback + * registers a void function to be executed when a + * hook is executed. + */ +int execute_hook(const char* name, void*, void*, void*, void*); +void register_hook_callback(const char* name, void(*callback)(void*, void*, void*, void*)); + + +int load_module(char* module); +int is_module_loaded(const char* name); +void module_loaded(const char* name/*, uint32_t version, uint32_t compat*/); + +long long add_symbol(char* symbol, long long addr, char is64); + +void* parse_mach(void* binary, + int(*dylib_loader)(char*), + long long(*symbol_handler)(char*, long long, char) + ); + +unsigned int handle_symtable(uint32_t base, struct symtab_command* symtabCommand, + long long(*symbol_handler)(char*, long long, char), + char is64); + +unsigned int lookup_all_symbols(const char* name); + +int replace_function(const char* symbol, void* newAddress); + +//extern unsigned int (*lookup_symbol)(const char*); + +#endif /* __BOOT_MODULES_H */ +} \ No newline at end of file Index: branches/slice/rev749/modules/include/types.h =================================================================== --- branches/slice/rev749/modules/include/types.h (revision 0) +++ branches/slice/rev749/modules/include/types.h (revision 1169) @@ -0,0 +1,16 @@ +#ifndef _TYPES_H_ +#define _TYPES_H_ + +typedef unsigned char UInt8; +typedef signed char SInt8; + +typedef unsigned short UInt16; +typedef signed short SInt16; + +typedef unsigned int UInt32; +typedef signed int SInt32; + +typedef unsigned long long UInt64; +typedef signed long long SInt64; + +#endif /* _TYPES_H_ */ \ No newline at end of file Index: branches/slice/rev749/modules/klibc/strndup.c =================================================================== --- branches/slice/rev749/modules/klibc/strndup.c (revision 0) +++ branches/slice/rev749/modules/klibc/strndup.c (revision 1169) @@ -0,0 +1,16 @@ +/* + * strndup.c + */ + +#include "libsaio.h" + +char *strndup(const char *s, size_t n) +{ + int l = n > strlen(s) ? strlen(s) + 1 : n + 1; + char *d = malloc(l); + + if (d) + memcpy(d, s, l); + d[n] = '\0'; + return d; +} Index: branches/slice/rev749/modules/klibc/sha1hash.c =================================================================== --- branches/slice/rev749/modules/klibc/sha1hash.c (revision 0) +++ branches/slice/rev749/modules/klibc/sha1hash.c (revision 1169) @@ -0,0 +1,319 @@ +/* +SHA-1 in C +By Steve Reid +100% Public Domain + +----------------- +Modified 7/98 +By James H. Brown +Still 100% Public Domain + +Corrected a problem which generated improper hash values on 16 bit machines +Routine SHA1Update changed from + void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int +len) +to + void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned +long len) + +The 'len' parameter was declared an int which works fine on 32 bit machines. +However, on 16 bit machines an int is too small for the shifts being done +against +it. This caused the hash function to generate incorrect values if len was +greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update(). + +Since the file IO in main() reads 16K at a time, any file 8K or larger would +be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million +"a"s). + +I also changed the declaration of variables i & j in SHA1Update to +unsigned long from unsigned int for the same reason. + +These changes should make no difference to any 32 bit implementations since +an +int and a long are the same size in those environments. + +-- +I also corrected a few compiler warnings generated by Borland C. +1. Added #include for exit() prototype +2. Removed unused variable 'j' in SHA1Final +3. Changed exit(0) to return(0) at end of main. + +ALL changes I made can be located by searching for comments containing 'JHB' +----------------- +Modified 8/98 +By Steve Reid +Still 100% public domain + +1- Removed #include and used return() instead of exit() +2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall) +3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net + +----------------- +Modified 4/01 +By Saul Kravitz +Still 100% PD +Modified to run on Compaq Alpha hardware. + +----------------- +Modified 2/03 +By H. Peter Anvin +Still 100% PD +Modified to run on any hardware with and +Changed the driver program + +*/ + +/* +Test Vectors (from FIPS PUB 180-1) +"abc" + A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D +"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 +A million repetitions of "a" + 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F +*/ + +/* #define SHA1HANDSOFF */ + +#include +#include +#include +#include /* For htonl/ntohl/htons/ntohs */ + +/* #include */ /* prototype for exit() - JHB */ +/* Using return() instead of exit() - SWR */ + +typedef struct { + uint32_t state[5]; + uint32_t count[2]; + unsigned char buffer[64]; +} SHA1_CTX; + +void SHA1Transform(uint32_t state[5], unsigned char buffer[64]); +void SHA1Init(SHA1_CTX* context); +void SHA1Update(SHA1_CTX* context, unsigned char* data, uint32_t len); /* +JHB */ +void SHA1Final(unsigned char digest[20], SHA1_CTX* context); + +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +/* blk0() and blk() perform the initial expand. */ +/* I got the idea of expanding during the round function from SSLeay */ +#define blk0(i) (block->l[i] = ntohl(block->l[i])) +#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ + ^block->l[(i+2)&15]^block->l[i&15],1)) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); +#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); +#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); + + +#ifdef VERBOSE /* SAK */ +void SHAPrintContext(SHA1_CTX *context, char *msg){ + verbose("%s (%d,%d) %x %x %x %x %x\n", + msg, + context->count[0], context->count[1], + context->state[0], + context->state[1], + context->state[2], + context->state[3], + context->state[4]); +} +#endif + +/* Hash a single 512-bit block. This is the core of the algorithm. */ + +void SHA1Transform(uint32_t state[5], unsigned char buffer[64]) +{ +uint32_t a, b, c, d, e; +typedef union { + unsigned char c[64]; + uint32_t l[16]; +} CHAR64LONG16; +CHAR64LONG16* block; +#ifdef SHA1HANDSOFF +static unsigned char workspace[64]; + block = (CHAR64LONG16*)workspace; + memcpy(block, buffer, 64); +#else + block = (CHAR64LONG16*)buffer; +#endif + /* Copy context->state[] to working vars */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); + R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); + R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); + R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + /* Wipe variables */ + a = b = c = d = e = 0; +} + + +/* SHA1Init - Initialize new context */ + +void SHA1Init(SHA1_CTX* context) +{ + /* SHA1 initialization constants */ + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; + context->state[4] = 0xC3D2E1F0; + context->count[0] = context->count[1] = 0; +} + + +/* Run your data through this. */ + +void SHA1Update(SHA1_CTX* context, unsigned char* data, uint32_t len) /* +JHB */ +{ +uint32_t i, j; /* JHB */ + +#ifdef VERBOSE + SHAPrintContext(context, "before"); +#endif + j = (context->count[0] >> 3) & 63; + if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++; + context->count[1] += (len >> 29); + if ((j + len) > 63) { + memcpy(&context->buffer[j], data, (i = 64-j)); + SHA1Transform(context->state, context->buffer); + for ( ; i + 63 < len; i += 64) { + SHA1Transform(context->state, &data[i]); + } + j = 0; + } + else i = 0; + memcpy(&context->buffer[j], &data[i], len - i); +#ifdef VERBOSE + SHAPrintContext(context, "after "); +#endif +} + + +/* Add padding and return the message digest. */ + +void SHA1Final(unsigned char digest[20], SHA1_CTX* context) +{ +uint32_t i; /* JHB */ +unsigned char finalcount[8]; + + for (i = 0; i < 8; i++) { + finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] + >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ + } + SHA1Update(context, (unsigned char *)"\200", 1); + while ((context->count[0] & 504) != 448) { + SHA1Update(context, (unsigned char *)"\0", 1); + } + SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() +*/ + for (i = 0; i < 20; i++) { + digest[i] = (unsigned char) + ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); + } + /* Wipe variables */ + i = 0; /* JHB */ + memset(context->buffer, 0, 64); + memset(context->state, 0, 20); + memset(context->count, 0, 8); + memset(finalcount, 0, 8); /* SWR */ +#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */ + SHA1Transform(context->state, context->buffer); +#endif +} + +/*************************************************************/ + +/* This is not quite the MIME base64 algorithm: it uses _ instead of /, + and instead of padding the output with = characters we just make the + output shorter. */ +char *mybase64(uint8_t digest[20]) +{ + static const char charz[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; + uint8_t input[21]; + static char output[28]; + int i, j; + uint8_t *p; + char *q; + uint32_t bv; + + memcpy(input, digest, 20); + input[20] = 0; /* Pad to multiple of 3 bytes */ + + p = input; q = output; + for ( i = 0 ; i < 7 ; i++ ) { + bv = (p[0] << 16) | (p[1] << 8) | p[2]; + p += 3; + for ( j = 0 ; j < 4 ; j++ ) { + *q++ = charz[(bv >> 18) & 0x3f]; + bv <<= 6; + } + } + *--q = '\0'; /* The last character is not significant */ + return output; +} + +#if 0 +int main(int argc, char** argv) +{ + int i; + SHA1_CTX context; + uint8_t digest[20], buffer[16384]; + FILE* file; + + if (argc < 2) { + file = stdin; + } + else { + if (!(file = fopen(argv[1], "rb"))) { + fputs("Unable to open file.", stderr); + return(-1); + } + } + SHA1Init(&context); + while (!feof(file)) { /* note: what if ferror(file) */ + i = fread(buffer, 1, 16384, file); + SHA1Update(&context, buffer, i); + } + SHA1Final(digest, &context); + fclose(file); + + puts(mybase64(digest)); + + return 0; +} +#endif Index: branches/slice/rev749/modules/klibc/strtox.c =================================================================== --- branches/slice/rev749/modules/klibc/strtox.c (revision 0) +++ branches/slice/rev749/modules/klibc/strtox.c (revision 1169) @@ -0,0 +1,16 @@ +/* + * strtox.c + * + * strto...() functions, by macro definition + */ + +#include +#include +#include + +extern uintmax_t strntoumax(const char *nptr, char **endptr, int base, size_t n); + +TYPE NAME(const char *nptr, char **endptr, int base) +{ + return (TYPE) strntoumax(nptr, endptr, base, ~(size_t) 0); +} Index: branches/slice/rev749/modules/klibc/__clzsi2.c =================================================================== --- branches/slice/rev749/modules/klibc/__clzsi2.c (revision 0) +++ branches/slice/rev749/modules/klibc/__clzsi2.c (revision 1169) @@ -0,0 +1,36 @@ +/* + * libgcc/__clzsi2.c + * + * Returns the leading number of 0 bits in the argument + */ + +#include +#include + +uint32_t __clzsi2(uint32_t v) +{ + int p = 31; + + if (v & 0xffff0000) { + p -= 16; + v >>= 16; + } + if (v & 0xff00) { + p -= 8; + v >>= 8; + } + if (v & 0xf0) { + p -= 4; + v >>= 4; + } + if (v & 0xc) { + p -= 2; + v >>= 2; + } + if (v & 0x2) { + p -= 1; + v >>= 1; + } + + return p; +} Index: branches/slice/rev749/modules/klibc/strcasecmp.c =================================================================== --- branches/slice/rev749/modules/klibc/strcasecmp.c (revision 0) +++ branches/slice/rev749/modules/klibc/strcasecmp.c (revision 1169) @@ -0,0 +1,24 @@ +/* + * strcasecmp.c + */ + +#include +#include + +int strcasecmp(const char *s1, const char *s2) +{ + const unsigned char *c1 = (const unsigned char *)s1; + const unsigned char *c2 = (const unsigned char *)s2; + unsigned char ch; + int d = 0; + + while (1) { + /* toupper() expects an unsigned char (implicitly cast to int) + as input, and returns an int, which is exactly what we want. */ + d = toupper(ch = *c1++) - toupper(*c2++); + if (d || !ch) + break; + } + + return d; +} Index: branches/slice/rev749/modules/klibc/__udivdi3.c =================================================================== --- branches/slice/rev749/modules/klibc/__udivdi3.c (revision 0) +++ branches/slice/rev749/modules/klibc/__udivdi3.c (revision 1169) @@ -0,0 +1,13 @@ +/* + * arch/i386/libgcc/__divdi3.c + */ + +#include +#include + +extern uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t * rem); + +uint64_t __udivdi3(uint64_t num, uint64_t den) +{ + return __udivmoddi4(num, den, NULL); +} Index: branches/slice/rev749/modules/klibc/memmove.c =================================================================== --- branches/slice/rev749/modules/klibc/memmove.c (revision 0) +++ branches/slice/rev749/modules/klibc/memmove.c (revision 1169) @@ -0,0 +1,36 @@ +/* + * memmove.c + */ + +#include "libsaio.h" + +void *memmove(void *dst, const void *src, size_t n) +{ + const char *p = src; + char *q = dst; +#if defined(__i386__) || defined(__x86_64__) + if (q < p) { + asm volatile("cld; rep; movsb" + : "+c" (n), "+S"(p), "+D"(q)); + } else { + p += (n - 1); + q += (n - 1); + asm volatile("std; rep; movsb; cld" + : "+c" (n), "+S"(p), "+D"(q)); + } +#else + if (q < p) { + while (n--) { + *q++ = *p++; + } + } else { + p += n; + q += n; + while (n--) { + *--q = *--p; + } + } +#endif + + return dst; +} Index: branches/slice/rev749/modules/klibc/strtotimespec.c =================================================================== --- branches/slice/rev749/modules/klibc/strtotimespec.c (revision 0) +++ branches/slice/rev749/modules/klibc/strtotimespec.c (revision 1169) @@ -0,0 +1,5 @@ +#define NAME strtotimespec +#define TIMEX struct timespec +#define FSEC tv_nsec +#define DECIMALS 9 +#include "strtotimex.c" Index: branches/slice/rev749/modules/klibc/limits.h =================================================================== --- branches/slice/rev749/modules/klibc/limits.h (revision 0) +++ branches/slice/rev749/modules/klibc/limits.h (revision 1169) @@ -0,0 +1,6 @@ + +#define CHAR_BIT 8 + +#define UCHAR_MAX 255u +#define INT_MAX 2147483647 +#define UINT_MAX 4294967295u \ No newline at end of file Index: branches/slice/rev749/modules/klibc/onexit.c =================================================================== --- branches/slice/rev749/modules/klibc/onexit.c (revision 0) +++ branches/slice/rev749/modules/klibc/onexit.c (revision 1169) @@ -0,0 +1,22 @@ +/* + * onexit.c + */ + +#include "libsaio.h" +#include "atexit.h" + +int on_exit(void (*fctn) (int, void *), void *arg) +{ + struct atexit *as = malloc(sizeof(struct atexit)); + + if (!as) + return -1; + + as->fctn = fctn; + as->arg = arg; + + as->next = __atexit_list; + __atexit_list = as; + + return 0; +} Index: branches/slice/rev749/modules/klibc/exit.c =================================================================== --- branches/slice/rev749/modules/klibc/exit.c (revision 0) +++ branches/slice/rev749/modules/klibc/exit.c (revision 1169) @@ -0,0 +1,30 @@ +/* + * exit.c + * + * exit(), including the handling of the atexit chain. + */ + +#include +#include +#include +#include "atexit.h" + +/* Link chain for atexit/on_exit */ +struct atexit *__atexit_list; + +void exit(int rv) +{ + struct atexit *ap; + + for (ap = __atexit_list; ap; ap = ap->next) { + /* This assumes extra args are harmless. They should + be in all normal C ABIs, but if an architecture has + some particularly bizarre ABI this might be worth + watching out for. */ + ap->fctn(rv, ap->arg); + } + + /* Handle any library destructors if we ever start using them... */ + + _exit(rv); +} Index: branches/slice/rev749/modules/klibc/jrand48.c =================================================================== --- branches/slice/rev749/modules/klibc/jrand48.c (revision 0) +++ branches/slice/rev749/modules/klibc/jrand48.c (revision 1169) @@ -0,0 +1,24 @@ +/* + * jrand48.c + */ + +#include +#include + +long jrand48(unsigned short xsubi[3]) +{ + uint64_t x; + + /* The xsubi[] array is littleendian by spec */ + x = (uint64_t) (uint16_t) xsubi[0] + + ((uint64_t) (uint16_t) xsubi[1] << 16) + + ((uint64_t) (uint16_t) xsubi[2] << 32); + + x = (0x5deece66dULL * x) + 0xb; + + xsubi[0] = (unsigned short)(uint16_t) x; + xsubi[1] = (unsigned short)(uint16_t) (x >> 16); + xsubi[2] = (unsigned short)(uint16_t) (x >> 32); + + return (long)(int32_t) (x >> 16); +} Index: branches/slice/rev749/modules/klibc/memchr.c =================================================================== --- branches/slice/rev749/modules/klibc/memchr.c (revision 0) +++ branches/slice/rev749/modules/klibc/memchr.c (revision 1169) @@ -0,0 +1,19 @@ +/* + * memchr.c + */ + +#include +#include + +void *memchr(const void *s, int c, size_t n) +{ + const unsigned char *sp = s; + + while (n--) { + if (*sp == (unsigned char)c) + return (void *)sp; + sp++; + } + + return NULL; +} Index: branches/slice/rev749/modules/klibc/lrand48.c =================================================================== --- branches/slice/rev749/modules/klibc/lrand48.c (revision 0) +++ branches/slice/rev749/modules/klibc/lrand48.c (revision 1169) @@ -0,0 +1,13 @@ +/* + * lrand48.c + */ + +#include +#include + +extern unsigned short __rand48_seed[3]; /* Common with mrand48.c, srand48.c */ + +long lrand48(void) +{ + return (uint32_t) jrand48(__rand48_seed) >> 1; +} Index: branches/slice/rev749/modules/klibc/mrand48.c =================================================================== --- branches/slice/rev749/modules/klibc/mrand48.c (revision 0) +++ branches/slice/rev749/modules/klibc/mrand48.c (revision 1169) @@ -0,0 +1,13 @@ +/* + * mrand48.c + */ + +#include +#include + +extern unsigned short __rand48_seed[3]; /* Common with lrand48.c, srand48.c */ + +long mrand48(void) +{ + return jrand48(__rand48_seed); +} Index: branches/slice/rev749/modules/klibc/nrand48.c =================================================================== --- branches/slice/rev749/modules/klibc/nrand48.c (revision 0) +++ branches/slice/rev749/modules/klibc/nrand48.c (revision 1169) @@ -0,0 +1,11 @@ +/* + * nrand48.c + */ + +#include +#include + +long nrand48(unsigned short xsubi[3]) +{ + return (long)((uint32_t) jrand48(xsubi) >> 1); +} Index: branches/slice/rev749/modules/klibc/srand48.c =================================================================== --- branches/slice/rev749/modules/klibc/srand48.c (revision 0) +++ branches/slice/rev749/modules/klibc/srand48.c (revision 1169) @@ -0,0 +1,15 @@ +/* + * srand48.c + */ + +#include +#include + +extern unsigned short __rand48_seed[3]; /* Common with mrand48.c, lrand48.c */ + +void srand48(long seedval) +{ + __rand48_seed[0] = 0x330e; + __rand48_seed[1] = (unsigned short)seedval; + __rand48_seed[2] = (unsigned short)((uint32_t) seedval >> 16); +} Index: branches/slice/rev749/modules/klibc/__udivsi3.c =================================================================== --- branches/slice/rev749/modules/klibc/__udivsi3.c (revision 0) +++ branches/slice/rev749/modules/klibc/__udivsi3.c (revision 1169) @@ -0,0 +1,13 @@ +/* + * libgcc/__divsi3.c + */ + +#include +#include + +extern uint32_t __udivmodsi4(uint32_t num, uint32_t den, uint32_t * rem); + +uint32_t __udivsi3(uint32_t num, uint32_t den) +{ + return __udivmodsi4(num, den, NULL); +} Index: branches/slice/rev749/modules/klibc/klibc.c =================================================================== --- branches/slice/rev749/modules/klibc/klibc.c (revision 0) +++ branches/slice/rev749/modules/klibc/klibc.c (revision 1169) @@ -0,0 +1,36 @@ +/* + * klibc.c + * + * glue + initialization + */ + +#include "libsaio.h" + +int _DefaultRuneLocale; // todo: fixme + +void klibc_start() +{ +} + +void _exit() +{ +} + +char __toupper(char c) +{ + return ((c) & ~32); +} + +void __divide_error() +{ + stop("Divide by 0\n"); +} + +// hack +int +__maskrune(int _c, unsigned long _f) +{ + return 0; + //return ((_c < 0 || _c >= _CACHED_RUNES) ? ___runetype(_c) : + // _CurrentRuneLocale->__runetype[_c]) & _f; +} Index: branches/slice/rev749/modules/klibc/__ashldi3.c =================================================================== --- branches/slice/rev749/modules/klibc/__ashldi3.c (revision 0) +++ branches/slice/rev749/modules/klibc/__ashldi3.c (revision 1169) @@ -0,0 +1,23 @@ +/* + * libgcc/__ashldi3.c + */ + +#include +#include + +uint64_t __ashldi3(uint64_t v, int cnt) +{ + int c = cnt & 31; + uint32_t vl = (uint32_t) v; + uint32_t vh = (uint32_t) (v >> 32); + + if (cnt & 32) { + vh = (vl << c); + vl = 0; + } else { + vh = (vh << c) + (vl >> (32 - c)); + vl = (vl << c); + } + + return ((uint64_t) vh << 32) + vl; +} Index: branches/slice/rev749/modules/klibc/Makefile =================================================================== --- branches/slice/rev749/modules/klibc/Makefile (revision 0) +++ branches/slice/rev749/modules/klibc/Makefile (revision 1169) @@ -0,0 +1,64 @@ +MODULE_NAME = klibc +MODULE_VERSION = "1.5.20" +MODULE_COMPAT_VERSION = "1.5.20" +MODULE_START = _$(MODULE_NAME)_start +MODULE_DEPENDENCIES = + +DIR = klibc + +MODULE_OBJS = klibc.o \ + __ashldi3.o __ashrdi3.o __clzsi2.o __divdi3.o __divsi3.o \ + __lshrdi3.o __moddi3.o __modsi3.o __udivdi3.o \ + __udivmoddi4.o __udivmodsi4.o __udivsi3.o \ + __umoddi3.o __umodsi3.o \ + strntoumax.o strntoimax.o atoi.o atol.o atoll.o \ + strcasecmp.o strncasecmp.o strdup.o strlcat.o strndup.o strnlen.o \ + strsep.o strtoimax.o strtok_r.o strtok.o strtol.o strtoll.o strtotimespec.o strtotimeval.o \ + strtoul.o strtoull.o strtoumax.o strxspn.o strpbrk.o \ + bsearch.o calloc.o \ + jrand48.o lrand48.o mrand48.o srand48.o nrand48.o seed48.o \ + memccpy.o memchr.o memmem.o memmove.o memrchr.o memswap.o \ + qsort.o sha1hash.o onexit.o atexit.o exit.o \ + snprintf.o vsnprintf.o sscanf.o vsscanf.o\ + +OPTIM = -Os -Oz +DEBUG = -DNOTHING +#DEBUG = -DDEBUG_HELLO_WORLD=1 +CFLAGS = $(RC_CFLAGS) $(OPTIM) $(MORECPP) -arch i386 -g -Wmost \ + -D__ARCHITECTURE__=\"i386\" -DSAIO_INTERNAL_USER \ + -DRCZ_COMPRESSED_FILE_SUPPORT $(DEBUG) \ + -fno-builtin $(OMIT_FRAME_POINTER_CFLAG) \ + -mpreferred-stack-boundary=2 -fno-align-functions -fno-stack-protector \ + -march=pentium4 -msse2 -mfpmath=sse -msoft-float -fno-common + +DEFINES= +CONFIG = hd +INC = -I. -I.. -I$(SYMROOT) -I$(UTILDIR) -I$(LIBSADIR) -I$(LIBSAIODIR) -I$(BOOT2DIR) +ifneq "" "$(wildcard /bin/mkdirs)" + MKDIRS = /bin/mkdirs +else + MKDIRS = /bin/mkdir -p +endif +AS = as +LD = ld +# LIBS= -lc_static +LIBS= + +VPATH = $(OBJROOT):$(SYMROOT) + + + + +SFILES = +CFILES = +HFILES = +EXPORTED_HFILES = +INSTALLED_HFILES = +OTHERFILES = Makefile +ALLSRC = $(SFILES) $(CFILES) \ + $(HFILES) $(OTHERFILES) +DIRS_NEEDED = $(OBJROOT) $(SYMROOT) + +all embedtheme optionrom: dylib + +include ../MakeInc.dir \ No newline at end of file Index: branches/slice/rev749/modules/klibc/strtotimeval.c =================================================================== --- branches/slice/rev749/modules/klibc/strtotimeval.c (revision 0) +++ branches/slice/rev749/modules/klibc/strtotimeval.c (revision 1169) @@ -0,0 +1,5 @@ +#define NAME strtotimeval +#define TIMEX struct timeval +#define FSEC tv_usec +#define DECIMALS 6 +#include "strtotimex.c" Index: branches/slice/rev749/modules/klibc/memrchr.c =================================================================== --- branches/slice/rev749/modules/klibc/memrchr.c (revision 0) +++ branches/slice/rev749/modules/klibc/memrchr.c (revision 1169) @@ -0,0 +1,19 @@ +/* + * memrchr.c + */ + +#include +#include + +void *memrchr(const void *s, int c, size_t n) +{ + const unsigned char *sp = (const unsigned char *)s + n - 1; + + while (n--) { + if (*sp == (unsigned char)c) + return (void *)sp; + sp--; + } + + return NULL; +} Index: branches/slice/rev749/modules/klibc/__umoddi3.c =================================================================== --- branches/slice/rev749/modules/klibc/__umoddi3.c (revision 0) +++ branches/slice/rev749/modules/klibc/__umoddi3.c (revision 1169) @@ -0,0 +1,16 @@ +/* + * arch/i386/libgcc/__umoddi3.c + */ + +#include +#include + +extern uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t * rem); + +uint64_t __umoddi3(uint64_t num, uint64_t den) +{ + uint64_t v; + + (void)__udivmoddi4(num, den, &v); + return v; +} Index: branches/slice/rev749/modules/klibc/memswap.c =================================================================== --- branches/slice/rev749/modules/klibc/memswap.c (revision 0) +++ branches/slice/rev749/modules/klibc/memswap.c (revision 1169) @@ -0,0 +1,24 @@ +/* + * memswap() + * + * Swaps the contents of two nonoverlapping memory areas. + * This really could be done faster... + */ + +#include + +void memswap(void *m1, void *m2, size_t n) +{ + char *p = m1; + char *q = m2; + char tmp; + + while (n--) { + tmp = *p; + *p = *q; + *q = tmp; + + p++; + q++; + } +} Index: branches/slice/rev749/modules/klibc/atoll.c =================================================================== --- branches/slice/rev749/modules/klibc/atoll.c (revision 0) +++ branches/slice/rev749/modules/klibc/atoll.c (revision 1169) @@ -0,0 +1,3 @@ +#define TYPE long long +#define NAME atoll +#include "atox.c" Index: branches/slice/rev749/modules/klibc/strlcat.c =================================================================== --- branches/slice/rev749/modules/klibc/strlcat.c (revision 0) +++ branches/slice/rev749/modules/klibc/strlcat.c (revision 1169) @@ -0,0 +1,30 @@ +/* + * strlcat.c + */ + +#include + +size_t strlcat(char *dst, const char *src, size_t size) +{ + size_t bytes = 0; + char *q = dst; + const char *p = src; + char ch; + + while (bytes < size && *q) { + q++; + bytes++; + } + if (bytes == size) + return (bytes + strlen(src)); + + while ((ch = *p++)) { + if (bytes + 1 < size) + *q++ = ch; + + bytes++; + } + + *q = '\0'; + return bytes; +} Index: branches/slice/rev749/modules/klibc/memmem.c =================================================================== --- branches/slice/rev749/modules/klibc/memmem.c (revision 0) +++ branches/slice/rev749/modules/klibc/memmem.c (revision 1169) @@ -0,0 +1,52 @@ +/* + * memmem.c + * + * Find a byte string inside a longer byte string + * + * This uses the "Not So Naive" algorithm, a very simple but + * usually effective algorithm, see: + * + * http://www-igm.univ-mlv.fr/~lecroq/string/ + */ + +#include + +void *memmem(const void *haystack, size_t n, const void *needle, size_t m) +{ + const unsigned char *y = (const unsigned char *)haystack; + const unsigned char *x = (const unsigned char *)needle; + + size_t j, k, l; + + if (m > n || !m || !n) + return NULL; + + if (1 != m) { + if (x[0] == x[1]) { + k = 2; + l = 1; + } else { + k = 1; + l = 2; + } + + j = 0; + while (j <= n - m) { + if (x[1] != y[j + 1]) { + j += k; + } else { + if (!memcmp(x + 2, y + j + 2, m - 2) + && x[0] == y[j]) + return (void *)&y[j]; + j += l; + } + } + } else + do { + if (*y == *x) + return (void *)y; + y++; + } while (--n); + + return NULL; +} Index: branches/slice/rev749/modules/klibc/strsep.c =================================================================== --- branches/slice/rev749/modules/klibc/strsep.c (revision 0) +++ branches/slice/rev749/modules/klibc/strsep.c (revision 1169) @@ -0,0 +1,21 @@ +/* + * strsep.c + */ + +#include + +char *strsep(char **stringp, const char *delim) +{ + char *s = *stringp; + char *e; + + if (!s) + return NULL; + + e = strpbrk(s, delim); + if (e) + *e++ = '\0'; + + *stringp = e; + return s; +} Index: branches/slice/rev749/modules/klibc/strdup.c =================================================================== --- branches/slice/rev749/modules/klibc/strdup.c (revision 0) +++ branches/slice/rev749/modules/klibc/strdup.c (revision 1169) @@ -0,0 +1,16 @@ +/* + * strdup.c + */ + +#include "libsaio.h" + +char *strdup(const char *s) +{ + int l = strlen(s) + 1; + char *d = malloc(l); + + if (d) + memcpy(d, s, l); + + return d; +} Index: branches/slice/rev749/modules/klibc/__umodsi3.c =================================================================== --- branches/slice/rev749/modules/klibc/__umodsi3.c (revision 0) +++ branches/slice/rev749/modules/klibc/__umodsi3.c (revision 1169) @@ -0,0 +1,16 @@ +/* + * libgcc/__umodsi3.c + */ + +#include +#include + +extern uint32_t __udivmodsi4(uint32_t num, uint32_t den, uint32_t * rem); + +uint32_t __umodsi3(uint32_t num, uint32_t den) +{ + uint32_t v; + + (void)__udivmodsi4(num, den, &v); + return v; +} Index: branches/slice/rev749/modules/klibc/strtotimex.c =================================================================== --- branches/slice/rev749/modules/klibc/strtotimex.c (revision 0) +++ branches/slice/rev749/modules/klibc/strtotimex.c (revision 1169) @@ -0,0 +1,42 @@ +/* + * strtotimex.c + * + * Nonstandard function which takes a string and converts it to a + * struct timespec/timeval. Returns a pointer to the first non-numeric + * character in the string. + * + */ + +#include +#include +#include +#include +#include + +uintmax_t strntoumax(const char *nptr, char **endptr, int base, size_t n); + +char *NAME(const char *str, TIMEX * ts) +{ + int n; + char *s, *s0; + __typeof__(ts->FSEC) fs; /* Fractional seconds */ + + ts->tv_sec = strntoumax(str, &s, 10, ~(size_t) 0); + fs = 0; + + if (*s == '.') { + s0 = s + 1; + + fs = strntoumax(s0, &s, 10, DECIMALS); + n = s - s0; + + while (isdigit(*s)) + s++; + + for (; n < DECIMALS; n++) + fs *= 10; + } + + ts->FSEC = fs; + return s; +} Index: branches/slice/rev749/modules/klibc/strtok.c =================================================================== --- branches/slice/rev749/modules/klibc/strtok.c (revision 0) +++ branches/slice/rev749/modules/klibc/strtok.c (revision 1169) @@ -0,0 +1,12 @@ +/* + * strtok.c + */ + +#include + +char *strtok(char *s, const char *delim) +{ + static char *holder; + + return strtok_r(s, delim, &holder); +} Index: branches/slice/rev749/modules/klibc/vsnprintf.c =================================================================== --- branches/slice/rev749/modules/klibc/vsnprintf.c (revision 0) +++ branches/slice/rev749/modules/klibc/vsnprintf.c (revision 1169) @@ -0,0 +1,483 @@ +/* + * vsnprintf.c + * + * vsnprintf(), from which the rest of the printf() + * family is built + */ + +#include "libsaio.h" +#include "limits.h" +enum flags { + FL_ZERO = 0x01, /* Zero modifier */ + FL_MINUS = 0x02, /* Minus modifier */ + FL_PLUS = 0x04, /* Plus modifier */ + FL_TICK = 0x08, /* ' modifier */ + FL_SPACE = 0x10, /* Space modifier */ + FL_HASH = 0x20, /* # modifier */ + FL_SIGNED = 0x40, /* Number is signed */ + FL_UPPER = 0x80 /* Upper case digits */ +}; + +/* These may have to be adjusted on certain implementations */ +enum ranks { + rank_char = -2, + rank_short = -1, + rank_int = 0, + rank_long = 1, + rank_longlong = 2 +}; + +#define MIN_RANK rank_char +#define MAX_RANK rank_longlong + +#define INTMAX_RANK rank_longlong +#define SIZE_T_RANK rank_long +#define PTRDIFF_T_RANK rank_long + +#define EMIT(x) ({ if (o nchars) { + while (width > nchars) { + EMIT(' '); + width--; + } + } + + /* Emit nondigits */ + if (minus) + EMIT('-'); + else if (flags & FL_PLUS) + EMIT('+'); + else if (flags & FL_SPACE) + EMIT(' '); + + if ((flags & FL_HASH) && base == 16) { + EMIT('0'); + EMIT((flags & FL_UPPER) ? 'X' : 'x'); + } + + /* Emit zero padding */ + if ((flags & (FL_MINUS | FL_ZERO)) == FL_ZERO && width > ndigits) { + while (width > nchars) { + EMIT('0'); + width--; + } + } + + /* Generate the number. This is done from right to left. */ + q += ndigits; /* Advance the pointer to end of number */ + o += ndigits; + qq = q; + oo = o; /* Temporary values */ + + b4tick = tickskip; + while (ndigits > 0) { + if (!b4tick--) { + qq--; + oo--; + ndigits--; + if (oo < n) + *qq = '_'; + b4tick = tickskip - 1; + } + qq--; + oo--; + ndigits--; + if (oo < n) + *qq = digits[val % base]; + val /= base; + } + + /* Emit late space padding */ + while ((flags & FL_MINUS) && width > nchars) { + EMIT(' '); + width--; + } + + return o; +} + +int vsnprintf(char *buffer, size_t n, const char *format, va_list ap) +{ + const char *p = format; + char ch; + char *q = buffer; + size_t o = 0; /* Number of characters output */ + uintmax_t val = 0; + int rank = rank_int; /* Default rank */ + int width = 0; + int prec = -1; + int base; + size_t sz; + enum flags flags = 0; + enum { + st_normal, /* Ground state */ + st_flags, /* Special flags */ + st_width, /* Field width */ + st_prec, /* Field precision */ + st_modifiers /* Length or conversion modifiers */ + } state = st_normal; + const char *sarg; /* %s string argument */ + char carg; /* %c char argument */ + int slen; /* String length */ + + while ((ch = *p++)) { + switch (state) { + case st_normal: + if (ch == '%') { + state = st_flags; + flags = 0; + rank = rank_int; + width = 0; + prec = -1; + } else { + EMIT(ch); + } + break; + + case st_flags: + switch (ch) { + case '-': + flags |= FL_MINUS; + break; + case '+': + flags |= FL_PLUS; + break; + case '\'': + flags |= FL_TICK; + break; + case ' ': + flags |= FL_SPACE; + break; + case '#': + flags |= FL_HASH; + break; + case '0': + flags |= FL_ZERO; + break; + default: + state = st_width; + p--; /* Process this character again */ + break; + } + break; + + case st_width: + if (ch >= '0' && ch <= '9') { + width = width * 10 + (ch - '0'); + } else if (ch == '*') { + width = va_arg(ap, int); + if (width < 0) { + width = -width; + flags |= FL_MINUS; + } + } else if (ch == '.') { + prec = 0; /* Precision given */ + state = st_prec; + } else { + state = st_modifiers; + p--; /* Process this character again */ + } + break; + + case st_prec: + if (ch >= '0' && ch <= '9') { + prec = prec * 10 + (ch - '0'); + } else if (ch == '*') { + prec = va_arg(ap, int); + if (prec < 0) + prec = -1; + } else { + state = st_modifiers; + p--; /* Process this character again */ + } + break; + + case st_modifiers: + switch (ch) { + /* Length modifiers - nonterminal sequences */ + case 'h': + rank--; /* Shorter rank */ + break; + case 'l': + rank++; /* Longer rank */ + break; + case 'j': + rank = INTMAX_RANK; + break; + case 'z': + rank = SIZE_T_RANK; + break; + case 't': + rank = PTRDIFF_T_RANK; + break; + case 'L': + case 'q': + rank += 2; + break; + default: + /* Output modifiers - terminal sequences */ + + /* Next state will be normal */ + state = st_normal; + + /* Canonicalize rank */ + if (rank < MIN_RANK) + rank = MIN_RANK; + else if (rank > MAX_RANK) + rank = MAX_RANK; + + switch (ch) { + case 'P': /* Upper case pointer */ + flags |= FL_UPPER; + /* fall through */ + case 'p': /* Pointer */ + base = 16; + prec = (CHAR_BIT*sizeof(void *)+3)/4; + flags |= FL_HASH; + val = (uintmax_t)(uintptr_t) + va_arg(ap, void *); + goto is_integer; + + case 'd': /* Signed decimal output */ + case 'i': + base = 10; + flags |= FL_SIGNED; + switch (rank) { + case rank_char: + /* Yes, all these casts are + needed... */ + val = (uintmax_t)(intmax_t) + (signed char) + va_arg(ap, signed int); + break; + case rank_short: + val = (uintmax_t)(intmax_t) + (signed short) + va_arg(ap, signed int); + break; + case rank_int: + val = (uintmax_t)(intmax_t) + va_arg(ap, signed int); + break; + case rank_long: + val = (uintmax_t)(intmax_t) + va_arg(ap, signed long); + break; + case rank_longlong: + val = (uintmax_t)(intmax_t) + va_arg(ap, + signed long long); + break; + } + goto is_integer; + case 'o': /* Octal */ + base = 8; + goto is_unsigned; + case 'u': /* Unsigned decimal */ + base = 10; + goto is_unsigned; + case 'X': /* Upper case hexadecimal */ + flags |= FL_UPPER; + /* fall through */ + case 'x': /* Hexadecimal */ + base = 16; + goto is_unsigned; + + is_unsigned: + switch (rank) { + case rank_char: + val = (uintmax_t) + (unsigned char) + va_arg(ap, unsigned + int); + break; + case rank_short: + val = (uintmax_t) + (unsigned short) + va_arg(ap, unsigned + int); + break; + case rank_int: + val = (uintmax_t) + va_arg(ap, unsigned + int); + break; + case rank_long: + val = (uintmax_t) + va_arg(ap, unsigned + long); + break; + case rank_longlong: + val = (uintmax_t) + va_arg(ap, unsigned + long long); + break; + } + /* fall through */ + + is_integer: + sz = format_int(q, (o < n) ? n - o : 0, + val, flags, base, + width, prec); + q += sz; + o += sz; + break; + + case 'c': /* Character */ + carg = (char)va_arg(ap, int); + sarg = &carg; + slen = 1; + goto is_string; + case 's': /* String */ + sarg = va_arg(ap, const char *); + sarg = sarg ? sarg : "(null)"; + slen = strlen(sarg); + goto is_string; + + is_string: + { + char sch; + int i; + + if (prec != -1 && slen > prec) + slen = prec; + + if (width > slen + && !(flags & FL_MINUS)) { + char pad = + (flags & FL_ZERO) ? + '0' : ' '; + while (width > slen) { + EMIT(pad); + width--; + } + } + for (i = slen; i; i--) { + sch = *sarg++; + EMIT(sch); + } + if (width > slen + && (flags & FL_MINUS)) { + while (width > slen) { + EMIT(' '); + width--; + } + } + } + break; + + case 'n': + { + /* Output the number of + characters written */ + + switch (rank) { + case rank_char: + *va_arg(ap, + signed char *) + = o; + break; + case rank_short: + *va_arg(ap, + signed short *) + = o; + break; + case rank_int: + *va_arg(ap, + signed int *) + = o; + break; + case rank_long: + *va_arg(ap, + signed long *) + = o; + break; + case rank_longlong: + *va_arg(ap, + signed long long *) + = o; + break; + } + } + break; + + default: /* Anything else, including % */ + EMIT(ch); + break; + } + } + } + } + + /* Null-terminate the string */ + if (o < n) + *q = '\0'; /* No overflow */ + else if (n > 0) + buffer[n - 1] = '\0'; /* Overflow - terminate at end of buffer */ + + return o; +} Index: branches/slice/rev749/modules/klibc/strtoimax.c =================================================================== --- branches/slice/rev749/modules/klibc/strtoimax.c (revision 0) +++ branches/slice/rev749/modules/klibc/strtoimax.c (revision 1169) @@ -0,0 +1,3 @@ +#define TYPE intmax_t +#define NAME strtoimax +#include "strtox.c" Index: branches/slice/rev749/modules/klibc/atexit.c =================================================================== --- branches/slice/rev749/modules/klibc/atexit.c (revision 0) +++ branches/slice/rev749/modules/klibc/atexit.c (revision 1169) @@ -0,0 +1,16 @@ +/* + * atexit.c + */ + +#include + +int atexit(void (*fctn) (void)) +{ + return 0; +} + +int __cxa_atexit(void (*fctn) (void)) +{ + return 0; + //return on_exit((void (*)(int, void *))fctn, NULL); +} Index: branches/slice/rev749/modules/klibc/atol.c =================================================================== --- branches/slice/rev749/modules/klibc/atol.c (revision 0) +++ branches/slice/rev749/modules/klibc/atol.c (revision 1169) @@ -0,0 +1,3 @@ +#define TYPE long +#define NAME atol +#include "atox.c" Index: branches/slice/rev749/modules/klibc/vsscanf.c =================================================================== --- branches/slice/rev749/modules/klibc/vsscanf.c (revision 0) +++ branches/slice/rev749/modules/klibc/vsscanf.c (revision 1169) @@ -0,0 +1,395 @@ +/* + * vsscanf.c + * + * vsscanf(), from which the rest of the scanf() + * family is built + */ + +#include "libsaio.h" +#include "limits.h" +extern uintmax_t strntoumax(const char *nptr, char **endptr, int base, size_t n); + +#ifndef LONG_BIT +#define LONG_BIT (CHAR_BIT*sizeof(long)) +#endif + +enum flags { + FL_SPLAT = 0x01, /* Drop the value, do not assign */ + FL_INV = 0x02, /* Character-set with inverse */ + FL_WIDTH = 0x04, /* Field width specified */ + FL_MINUS = 0x08, /* Negative number */ +}; + +enum ranks { + rank_char = -2, + rank_short = -1, + rank_int = 0, + rank_long = 1, + rank_longlong = 2, + rank_ptr = INT_MAX /* Special value used for pointers */ +}; + +#define MIN_RANK rank_char +#define MAX_RANK rank_longlong + +#define INTMAX_RANK rank_longlong +#define SIZE_T_RANK rank_long +#define PTRDIFF_T_RANK rank_long + +enum bail { + bail_none = 0, /* No error condition */ + bail_eof, /* Hit EOF */ + bail_err /* Conversion mismatch */ +}; + +static inline const char *skipspace(const char *p) +{ + while (isspace((unsigned char)*p)) + p++; + return p; +} + +#undef set_bit +static inline void set_bit(unsigned long *bitmap, unsigned int bit) +{ + bitmap[bit / LONG_BIT] |= 1UL << (bit % LONG_BIT); +} + +#undef test_bit +static inline int test_bit(unsigned long *bitmap, unsigned int bit) +{ + return (int)(bitmap[bit / LONG_BIT] >> (bit % LONG_BIT)) & 1; +} + +int vsscanf(const char *buffer, const char *format, va_list ap) +{ + const char *p = format; + char ch; + unsigned char uc; + const char *q = buffer; + const char *qq; + uintmax_t val = 0; + int rank = rank_int; /* Default rank */ + unsigned int width = UINT_MAX; + int base; + enum flags flags = 0; + enum { + st_normal, /* Ground state */ + st_flags, /* Special flags */ + st_width, /* Field width */ + st_modifiers, /* Length or conversion modifiers */ + st_match_init, /* Initial state of %[ sequence */ + st_match, /* Main state of %[ sequence */ + st_match_range, /* After - in a %[ sequence */ + } state = st_normal; + char *sarg = NULL; /* %s %c or %[ string argument */ + enum bail bail = bail_none; + int sign; + int converted = 0; /* Successful conversions */ + unsigned long matchmap[((1 << CHAR_BIT) + (LONG_BIT - 1)) / LONG_BIT]; + int matchinv = 0; /* Is match map inverted? */ + unsigned char range_start = 0; + + while ((ch = *p++) && !bail) { + switch (state) { + case st_normal: + if (ch == '%') { + state = st_flags; + flags = 0; + rank = rank_int; + width = UINT_MAX; + } else if (isspace((unsigned char)ch)) { + q = skipspace(q); + } else { + if (*q == ch) + q++; + else + bail = bail_err; /* Match failure */ + } + break; + + case st_flags: + switch (ch) { + case '*': + flags |= FL_SPLAT; + break; + case '0'...'9': + width = (ch - '0'); + state = st_width; + flags |= FL_WIDTH; + break; + default: + state = st_modifiers; + p--; /* Process this character again */ + break; + } + break; + + case st_width: + if (ch >= '0' && ch <= '9') { + width = width * 10 + (ch - '0'); + } else { + state = st_modifiers; + p--; /* Process this character again */ + } + break; + + case st_modifiers: + switch (ch) { + /* Length modifiers - nonterminal sequences */ + case 'h': + rank--; /* Shorter rank */ + break; + case 'l': + rank++; /* Longer rank */ + break; + case 'j': + rank = INTMAX_RANK; + break; + case 'z': + rank = SIZE_T_RANK; + break; + case 't': + rank = PTRDIFF_T_RANK; + break; + case 'L': + case 'q': + rank = rank_longlong; /* long double/long long */ + break; + + default: + /* Output modifiers - terminal sequences */ + /* Next state will be normal */ + state = st_normal; + + /* Canonicalize rank */ + if (rank < MIN_RANK) + rank = MIN_RANK; + else if (rank > MAX_RANK) + rank = MAX_RANK; + + switch (ch) { + case 'P': /* Upper case pointer */ + case 'p': /* Pointer */ + rank = rank_ptr; + base = 0; + sign = 0; + goto scan_int; + + case 'i': /* Base-independent integer */ + base = 0; + sign = 1; + goto scan_int; + + case 'd': /* Decimal integer */ + base = 10; + sign = 1; + goto scan_int; + + case 'o': /* Octal integer */ + base = 8; + sign = 0; + goto scan_int; + + case 'u': /* Unsigned decimal integer */ + base = 10; + sign = 0; + goto scan_int; + + case 'x': /* Hexadecimal integer */ + case 'X': + base = 16; + sign = 0; + goto scan_int; + + case 'n': /* # of characters consumed */ + val = (q - buffer); + goto set_integer; + + scan_int: + q = skipspace(q); + if (!*q) { + bail = bail_eof; + break; + } + val = + strntoumax(q, (char **)&qq, base, + width); + if (qq == q) { + bail = bail_err; + break; + } + q = qq; + if (!(flags & FL_SPLAT)) + converted++; + /* fall through */ + + set_integer: + if (!(flags & FL_SPLAT)) { + switch (rank) { + case rank_char: + *va_arg(ap, + unsigned char *) + = val; + break; + case rank_short: + *va_arg(ap, + unsigned short + *) = val; + break; + case rank_int: + *va_arg(ap, + unsigned int *) + = val; + break; + case rank_long: + *va_arg(ap, + unsigned long *) + = val; + break; + case rank_longlong: + *va_arg(ap, + unsigned long + long *) = val; + break; + case rank_ptr: + *va_arg(ap, void **) = + (void *) + (uintptr_t)val; + break; + } + } + break; + + case 'c': /* Character */ + /* Default width == 1 */ + width = (flags & FL_WIDTH) ? width : 1; + if (flags & FL_SPLAT) { + while (width--) { + if (!*q) { + bail = bail_eof; + break; + } + } + } else { + sarg = va_arg(ap, char *); + while (width--) { + if (!*q) { + bail = bail_eof; + break; + } + *sarg++ = *q++; + } + if (!bail) + converted++; + } + break; + + case 's': /* String */ + uc = 1; /* Anything nonzero */ + if (flags & FL_SPLAT) { + while (width-- && (uc = *q) && + !isspace(uc)) { + q++; + } + } else { + char *sp; + sp = sarg = va_arg(ap, char *); + while (width-- && (uc = *q) && + !isspace(uc)) { + *sp++ = uc; + q++; + } + if (sarg != sp) { + /* Terminate output */ + *sp = '\0'; + converted++; + } + } + if (!uc) + bail = bail_eof; + break; + + case '[': /* Character range */ + sarg = (flags & FL_SPLAT) ? NULL + : va_arg(ap, char *); + state = st_match_init; + matchinv = 0; + memset(matchmap, 0, sizeof matchmap); + break; + + case '%': /* %% sequence */ + if (*q == '%') + q++; + else + bail = bail_err; + break; + + default: /* Anything else */ + /* Unknown sequence */ + bail = bail_err; + break; + } + } + break; + + case st_match_init: /* Initial state for %[ match */ + if (ch == '^' && !(flags & FL_INV)) { + matchinv = 1; + } else { + set_bit(matchmap, (unsigned char)ch); + state = st_match; + } + break; + + case st_match: /* Main state for %[ match */ + if (ch == ']') { + goto match_run; + } else if (ch == '-') { + range_start = (unsigned char)ch; + state = st_match_range; + } else { + set_bit(matchmap, (unsigned char)ch); + } + break; + + case st_match_range: /* %[ match after - */ + if (ch == ']') { + /* - was last character */ + set_bit(matchmap, (unsigned char)'-'); + goto match_run; + } else { + int i; + for (i = range_start; i < (unsigned char)ch; + i++) + set_bit(matchmap, i); + state = st_match; + } + break; + + match_run: /* Match expression finished */ + qq = q; + uc = 1; /* Anything nonzero */ + while (width && (uc = *q) + && test_bit(matchmap, uc)^matchinv) { + if (sarg) + *sarg++ = uc; + q++; + } + if (q != qq && sarg) { + *sarg = '\0'; + converted++; + } else { + bail = bail_err; + } + if (!uc) + bail = bail_eof; + break; + } + } + + if (bail == bail_eof && !converted) + converted = -1; /* Return EOF (-1) */ + + return converted; +} Index: branches/slice/rev749/modules/klibc/atexit.h =================================================================== --- branches/slice/rev749/modules/klibc/atexit.h (revision 0) +++ branches/slice/rev749/modules/klibc/atexit.h (revision 1169) @@ -0,0 +1,18 @@ +/* + * atexit.h + * + * atexit()/on_exit() internal definitions + */ + +#ifndef ATEXIT_H +#define ATEXIT_H + +struct atexit { + void (*fctn) (int, void *); + void *arg; /* on_exit() parameter */ + struct atexit *next; +}; + +extern struct atexit *__atexit_list; + +#endif /* ATEXIT_H */ Index: branches/slice/rev749/modules/klibc/snprintf.c =================================================================== --- branches/slice/rev749/modules/klibc/snprintf.c (revision 0) +++ branches/slice/rev749/modules/klibc/snprintf.c (revision 1169) @@ -0,0 +1,17 @@ +/* + * snprintf.c + */ + +#include "libsaio.h" +extern int vsnprintf(char *buffer, size_t n, const char *format, va_list ap); + +int snprintf(char *buffer, size_t n, const char *format, ...) +{ + va_list ap; + int rv; + + va_start(ap, format); + rv = vsnprintf(buffer, n, format, ap); + va_end(ap); + return rv; +} Index: branches/slice/rev749/modules/klibc/strtoumax.c =================================================================== --- branches/slice/rev749/modules/klibc/strtoumax.c (revision 0) +++ branches/slice/rev749/modules/klibc/strtoumax.c (revision 1169) @@ -0,0 +1,3 @@ +#define TYPE uintmax_t +#define NAME strtoumax +#include "strtox.c" Index: branches/slice/rev749/modules/klibc/bsearch.c =================================================================== --- branches/slice/rev749/modules/klibc/bsearch.c (revision 0) +++ branches/slice/rev749/modules/klibc/bsearch.c (revision 1169) @@ -0,0 +1,26 @@ +/* + * bsearch.c + */ + +#include + +void *bsearch(const void *key, const void *base, size_t nmemb, + size_t size, int (*cmp) (const void *, const void *)) +{ + while (nmemb) { + size_t mididx = nmemb / 2; + const void *midobj = base + mididx * size; + int diff = cmp(key, midobj); + + if (diff == 0) + return (void *)midobj; + + if (diff > 0) { + base = midobj + size; + nmemb -= mididx + 1; + } else + nmemb = mididx; + } + + return NULL; +} Index: branches/slice/rev749/modules/klibc/strntoimax.c =================================================================== --- branches/slice/rev749/modules/klibc/strntoimax.c (revision 0) +++ branches/slice/rev749/modules/klibc/strntoimax.c (revision 1169) @@ -0,0 +1,15 @@ +/* + * strntoimax.c + * + * strntoimax() + */ + +#include +#include + +extern uintmax_t strntoumax(const char *nptr, char **endptr, int base, size_t n); + +intmax_t strntoimax(const char *nptr, char **endptr, int base, size_t n) +{ + return (intmax_t) strntoumax(nptr, endptr, base, n); +} Index: branches/slice/rev749/modules/klibc/atox.c =================================================================== --- branches/slice/rev749/modules/klibc/atox.c (revision 0) +++ branches/slice/rev749/modules/klibc/atox.c (revision 1169) @@ -0,0 +1,16 @@ +/* + * atox.c + * + * atoi(), atol(), atoll() + */ + +#include +#include +#include + +extern uintmax_t strntoumax(const char *nptr, char **endptr, int base, size_t n); + +TYPE NAME(const char *nptr) +{ + return (TYPE) strntoumax(nptr, (char **)NULL, 10, ~(size_t) 0); +} Index: branches/slice/rev749/modules/klibc/strtoul.c =================================================================== --- branches/slice/rev749/modules/klibc/strtoul.c (revision 0) +++ branches/slice/rev749/modules/klibc/strtoul.c (revision 1169) @@ -0,0 +1,3 @@ +#define TYPE unsigned long +#define NAME strtoul +#include "strtox.c" Index: branches/slice/rev749/modules/klibc/sscanf.c =================================================================== --- branches/slice/rev749/modules/klibc/sscanf.c (revision 0) +++ branches/slice/rev749/modules/klibc/sscanf.c (revision 1169) @@ -0,0 +1,17 @@ +/* + * sscanf() + */ + +#include "libsaio.h" +extern int vsscanf(const char *buffer, const char *format, va_list ap); +int sscanf(const char *str, const char *format, ...) +{ + va_list ap; + int rv; + + va_start(ap, format); + rv = vsscanf(str, format, ap); + va_end(ap); + + return rv; +} Index: branches/slice/rev749/modules/klibc/__divdi3.c =================================================================== --- branches/slice/rev749/modules/klibc/__divdi3.c (revision 0) +++ branches/slice/rev749/modules/klibc/__divdi3.c (revision 1169) @@ -0,0 +1,29 @@ +/* + * arch/i386/libgcc/__divdi3.c + */ + +#include +#include + +extern uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t * rem); + +int64_t __divdi3(int64_t num, int64_t den) +{ + int minus = 0; + int64_t v; + + if (num < 0) { + num = -num; + minus = 1; + } + if (den < 0) { + den = -den; + minus ^= 1; + } + + v = __udivmoddi4(num, den, NULL); + if (minus) + v = -v; + + return v; +} Index: branches/slice/rev749/modules/klibc/strncasecmp.c =================================================================== --- branches/slice/rev749/modules/klibc/strncasecmp.c (revision 0) +++ branches/slice/rev749/modules/klibc/strncasecmp.c (revision 1169) @@ -0,0 +1,24 @@ +/* + * strncasecmp.c + */ + +#include +#include + +int strncasecmp(const char *s1, const char *s2, size_t n) +{ + const unsigned char *c1 = (const unsigned char *)s1; + const unsigned char *c2 = (const unsigned char *)s2; + unsigned char ch; + int d = 0; + + while (n--) { + /* toupper() expects an unsigned char (implicitly cast to int) + as input, and returns an int, which is exactly what we want. */ + d = toupper(ch = *c1++) - toupper(*c2++); + if (d || !ch) + break; + } + + return d; +} Index: branches/slice/rev749/modules/klibc/strntoumax.c =================================================================== --- branches/slice/rev749/modules/klibc/strntoumax.c (revision 0) +++ branches/slice/rev749/modules/klibc/strntoumax.c (revision 1169) @@ -0,0 +1,73 @@ +/* + * strntoumax.c + * + * The strntoumax() function and associated + */ +#include "libsaio.h" + +static inline int digitval(int ch) +{ + if (ch >= '0' && ch <= '9') { + return ch - '0'; + } else if (ch >= 'A' && ch <= 'Z') { + return ch - 'A' + 10; + } else if (ch >= 'a' && ch <= 'z') { + return ch - 'a' + 10; + } else { + return -1; + } +} + +uintmax_t strntoumax(const char *nptr, char **endptr, int base, size_t n) +{ + int minus = 0; + uintmax_t v = 0; + int d; + + while (n && isspace((unsigned char)*nptr)) { + nptr++; + n--; + } + + /* Single optional + or - */ + if (n) { + char c = *nptr; + if (c == '-' || c == '+') { + minus = (c == '-'); + nptr++; + n--; + } + } + + if (base == 0) { + if (n >= 2 && nptr[0] == '0' && + (nptr[1] == 'x' || nptr[1] == 'X')) { + n -= 2; + nptr += 2; + base = 16; + } else if (n >= 1 && nptr[0] == '0') { + n--; + nptr++; + base = 8; + } else { + base = 10; + } + } else if (base == 16) { + if (n >= 2 && nptr[0] == '0' && + (nptr[1] == 'x' || nptr[1] == 'X')) { + n -= 2; + nptr += 2; + } + } + + while (n && (d = digitval(*nptr)) >= 0 && d < base) { + v = v * base + d; + n--; + nptr++; + } + + if (endptr) + *endptr = (char *)nptr; + + return minus ? -v : v; +} Index: branches/slice/rev749/modules/klibc/strpbrk.c =================================================================== --- branches/slice/rev749/modules/klibc/strpbrk.c (revision 0) +++ branches/slice/rev749/modules/klibc/strpbrk.c (revision 1169) @@ -0,0 +1,14 @@ +/* + * strpbrk + */ + +#include + +#include "strxspn.h" + +char *strpbrk(const char *s, const char *accept) +{ + const char *ss = s + __strxspn(s, accept, 1); + + return *ss ? (char *)ss : NULL; +} Index: branches/slice/rev749/modules/klibc/strtoull.c =================================================================== --- branches/slice/rev749/modules/klibc/strtoull.c (revision 0) +++ branches/slice/rev749/modules/klibc/strtoull.c (revision 1169) @@ -0,0 +1,3 @@ +#define TYPE unsigned long long +#define NAME strtoull +#include "strtox.c" Index: branches/slice/rev749/modules/klibc/__ashrdi3.c =================================================================== --- branches/slice/rev749/modules/klibc/__ashrdi3.c (revision 0) +++ branches/slice/rev749/modules/klibc/__ashrdi3.c (revision 1169) @@ -0,0 +1,23 @@ +/* + * libgcc/__ashrdi3.c + */ + +#include +#include + +uint64_t __ashrdi3(uint64_t v, int cnt) +{ + int c = cnt & 31; + uint32_t vl = (uint32_t) v; + uint32_t vh = (uint32_t) (v >> 32); + + if (cnt & 32) { + vl = ((int32_t) vh >> c); + vh = (int32_t) vh >> 31; + } else { + vl = (vl >> c) + (vh << (32 - c)); + vh = ((int32_t) vh >> c); + } + + return ((uint64_t) vh << 32) + vl; +} Index: branches/slice/rev749/modules/klibc/seed48.c =================================================================== --- branches/slice/rev749/modules/klibc/seed48.c (revision 0) +++ branches/slice/rev749/modules/klibc/seed48.c (revision 1169) @@ -0,0 +1,16 @@ +/* + * seed48.c + */ + +#include "libsaio.h" + +unsigned short __rand48_seed[3]; + +unsigned short *seed48(const unsigned short xsubi[3]) +{ + static unsigned short oldseed[3]; + memcpy(oldseed, __rand48_seed, sizeof __rand48_seed); + memcpy(__rand48_seed, xsubi, sizeof __rand48_seed); + + return oldseed; +} Index: branches/slice/rev749/modules/klibc/__divsi3.c =================================================================== --- branches/slice/rev749/modules/klibc/__divsi3.c (revision 0) +++ branches/slice/rev749/modules/klibc/__divsi3.c (revision 1169) @@ -0,0 +1,29 @@ +/* + * libgcc/__divsi3.c + */ + +#include +#include + +extern uint32_t __udivmodsi4(uint32_t num, uint32_t den, uint32_t * rem); + +int32_t __divsi3(int32_t num, int32_t den) +{ + int minus = 0; + int32_t v; + + if (num < 0) { + num = -num; + minus = 1; + } + if (den < 0) { + den = -den; + minus ^= 1; + } + + v = __udivmodsi4(num, den, NULL); + if (minus) + v = -v; + + return v; +} Index: branches/slice/rev749/modules/klibc/LICENSE =================================================================== --- branches/slice/rev749/modules/klibc/LICENSE (revision 0) +++ branches/slice/rev749/modules/klibc/LICENSE (revision 1169) @@ -0,0 +1,73 @@ +This license applies to all files in directory and its subdirectories, +unless otherwise noted in individual files. + + +Some files are derived from files derived from the include/ directory +of the Linux kernel, and are licensed under the terms of the GNU +General Public License, version 2, as released by the Free Software +Foundation, Inc.; incorporated herein by reference. + + ----- + +Some files are derived from files copyrighted by the Regents of The +University of California, and are available under the following +license: + +Note: The advertising clause in the license appearing on BSD Unix +files was officially rescinded by the Director of the Office of +Technology Licensing of the University of California on July 22 +1999. He states that clause 3 is "hereby deleted in its entirety." + + * Copyright (c) + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + + ----- + +For all remaining files, the following license applies: + + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * Any copyright notice(s) and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Index: branches/slice/rev749/modules/klibc/strtoll.c =================================================================== --- branches/slice/rev749/modules/klibc/strtoll.c (revision 0) +++ branches/slice/rev749/modules/klibc/strtoll.c (revision 1169) @@ -0,0 +1,3 @@ +#define TYPE signed long long +#define NAME strtoll +#include "strtox.c" Index: branches/slice/rev749/modules/klibc/version =================================================================== --- branches/slice/rev749/modules/klibc/version (revision 0) +++ branches/slice/rev749/modules/klibc/version (revision 1169) @@ -0,0 +1 @@ +1.5.20 Index: branches/slice/rev749/modules/klibc/__lshrdi3.c =================================================================== --- branches/slice/rev749/modules/klibc/__lshrdi3.c (revision 0) +++ branches/slice/rev749/modules/klibc/__lshrdi3.c (revision 1169) @@ -0,0 +1,23 @@ +/* + * libgcc/__lshrdi3.c + */ + +#include +#include + +uint64_t __lshrdi3(uint64_t v, int cnt) +{ + int c = cnt & 31; + uint32_t vl = (uint32_t) v; + uint32_t vh = (uint32_t) (v >> 32); + + if (cnt & 32) { + vl = (vh >> c); + vh = 0; + } else { + vl = (vl >> c) + (vh << (32 - c)); + vh = (vh >> c); + } + + return ((uint64_t) vh << 32) + vl; +} Index: branches/slice/rev749/modules/klibc/__udivmoddi4.c =================================================================== --- branches/slice/rev749/modules/klibc/__udivmoddi4.c (revision 0) +++ branches/slice/rev749/modules/klibc/__udivmoddi4.c (revision 1169) @@ -0,0 +1,33 @@ +#include "libsaio.h" + +extern void __divide_error(); + +uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t * rem_p) +{ + uint64_t quot = 0, qbit = 1; + + if (den == 0) { + __divide_error(); + return 0; /* If trap returns... */ + } + + /* Left-justify denominator and count shift */ + while ((int64_t) den >= 0) { + den <<= 1; + qbit <<= 1; + } + + while (qbit) { + if (den <= num) { + num -= den; + quot += qbit; + } + den >>= 1; + qbit >>= 1; + } + + if (rem_p) + *rem_p = num; + + return quot; +} Index: branches/slice/rev749/modules/klibc/strtok_r.c =================================================================== --- branches/slice/rev749/modules/klibc/strtok_r.c (revision 0) +++ branches/slice/rev749/modules/klibc/strtok_r.c (revision 1169) @@ -0,0 +1,13 @@ +#include + +char *strtok_r(char *s, const char *delim, char **holder) +{ + if (s) + *holder = s; + + do { + s = strsep(holder, delim); + } while (s && !*s); + + return s; +} Index: branches/slice/rev749/modules/klibc/qsort.c =================================================================== --- branches/slice/rev749/modules/klibc/qsort.c (revision 0) +++ branches/slice/rev749/modules/klibc/qsort.c (revision 1169) @@ -0,0 +1,48 @@ +/* + * qsort.c + * + * This is actually combsort. It's an O(n log n) algorithm with + * simplicity/small code size being its main virtue. + */ + +#include +#include +#include + +extern void memswap(void *m1, void *m2, size_t n); + +static inline size_t newgap(size_t gap) +{ + gap = (gap * 10) / 13; + if (gap == 9 || gap == 10) + gap = 11; + + if (gap < 1) + gap = 1; + return gap; +} + +void qsort(void *base, size_t nmemb, size_t size, + int (*compar) (const void *, const void *)) +{ + size_t gap = nmemb; + size_t i, j; + char *p1, *p2; + int swapped; + + if (!nmemb) + return; + + do { + gap = newgap(gap); + swapped = 0; + + for (i = 0, p1 = base; i < nmemb - gap; i++, p1 += size) { + j = i + gap; + if (compar(p1, p2 = (char *)base + j * size) > 0) { + memswap(p1, p2, size); + swapped = 1; + } + } + } while (gap > 1 || swapped); +} Index: branches/slice/rev749/modules/klibc/__moddi3.c =================================================================== --- branches/slice/rev749/modules/klibc/__moddi3.c (revision 0) +++ branches/slice/rev749/modules/klibc/__moddi3.c (revision 1169) @@ -0,0 +1,29 @@ +/* + * arch/i386/libgcc/__moddi3.c + */ + +#include +#include + +extern uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t * rem); + +int64_t __moddi3(int64_t num, int64_t den) +{ + int minus = 0; + int64_t v; + + if (num < 0) { + num = -num; + minus = 1; + } + if (den < 0) { + den = -den; + minus ^= 1; + } + + (void)__udivmoddi4(num, den, (uint64_t *) & v); + if (minus) + v = -v; + + return v; +} Index: branches/slice/rev749/modules/klibc/strxspn.c =================================================================== --- branches/slice/rev749/modules/klibc/strxspn.c (revision 0) +++ branches/slice/rev749/modules/klibc/strxspn.c (revision 1169) @@ -0,0 +1,26 @@ +/* + * strpbrk + */ + +#include +#include "strxspn.h" + +size_t __strxspn(const char *s, const char *map, int parity) +{ + char matchmap[UCHAR_MAX + 1]; + size_t n = 0; + + /* Create bitmap */ + memset(matchmap, 0, sizeof matchmap); + while (*map) + matchmap[(unsigned char)*map++] = 1; + + /* Make sure the null character never matches */ + matchmap[0] = parity; + + /* Calculate span length */ + while (matchmap[(unsigned char)*s++] ^ parity) + n++; + + return n; +} Index: branches/slice/rev749/modules/klibc/strnlen.c =================================================================== --- branches/slice/rev749/modules/klibc/strnlen.c (revision 0) +++ branches/slice/rev749/modules/klibc/strnlen.c (revision 1169) @@ -0,0 +1,18 @@ +/* + * strnlen() + */ + +#include + +size_t strnlen(const char *s, size_t maxlen) +{ + const char *ss = s; + + /* Important: the maxlen test must precede the reference through ss; + since the byte beyond the maximum may segfault */ + while ((maxlen > 0) && *ss) { + ss++; + maxlen--; + } + return ss - s; +} Index: branches/slice/rev749/modules/klibc/__udivmodsi4.c =================================================================== --- branches/slice/rev749/modules/klibc/__udivmodsi4.c (revision 0) +++ branches/slice/rev749/modules/klibc/__udivmodsi4.c (revision 1169) @@ -0,0 +1,31 @@ +#include "libsaio.h" +extern void __divide_error(); +uint32_t __udivmodsi4(uint32_t num, uint32_t den, uint32_t * rem_p) +{ + uint32_t quot = 0, qbit = 1; + + if (den == 0) { + __divide_error(); + return 0; /* If trap returns... */ + } + + /* Left-justify denominator and count shift */ + while ((int32_t) den >= 0) { + den <<= 1; + qbit <<= 1; + } + + while (qbit) { + if (den <= num) { + num -= den; + quot += qbit; + } + den >>= 1; + qbit >>= 1; + } + + if (rem_p) + *rem_p = num; + + return quot; +} Index: branches/slice/rev749/modules/klibc/strxspn.h =================================================================== --- branches/slice/rev749/modules/klibc/strxspn.h (revision 0) +++ branches/slice/rev749/modules/klibc/strxspn.h (revision 1169) @@ -0,0 +1,13 @@ +/* + * strxspn.h + */ + +#ifndef STRXSPN_H +#define STRXSPN_H + +#include +#include + +extern size_t __strxspn(const char *s, const char *map, int parity); + +#endif Index: branches/slice/rev749/modules/klibc/strtol.c =================================================================== --- branches/slice/rev749/modules/klibc/strtol.c (revision 0) +++ branches/slice/rev749/modules/klibc/strtol.c (revision 1169) @@ -0,0 +1,3 @@ +#define TYPE signed long +#define NAME strtol +#include "strtox.c" Index: branches/slice/rev749/modules/klibc/__modsi3.c =================================================================== --- branches/slice/rev749/modules/klibc/__modsi3.c (revision 0) +++ branches/slice/rev749/modules/klibc/__modsi3.c (revision 1169) @@ -0,0 +1,29 @@ +/* + * libgcc/__modsi3.c + */ + +#include +#include + +extern uint32_t __udivmodsi4(uint32_t num, uint32_t den, uint32_t * rem); + +int32_t __modsi3(int32_t num, int32_t den) +{ + int minus = 0; + int32_t v; + + if (num < 0) { + num = -num; + minus = 1; + } + if (den < 0) { + den = -den; + minus ^= 1; + } + + (void)__udivmodsi4(num, den, (uint32_t *) & v); + if (minus) + v = -v; + + return v; +} Index: branches/slice/rev749/modules/klibc/atoi.c =================================================================== --- branches/slice/rev749/modules/klibc/atoi.c (revision 0) +++ branches/slice/rev749/modules/klibc/atoi.c (revision 1169) @@ -0,0 +1,3 @@ +#define TYPE int +#define NAME atoi +#include "atox.c" Index: branches/slice/rev749/modules/klibc/calloc.c =================================================================== --- branches/slice/rev749/modules/klibc/calloc.c (revision 0) +++ branches/slice/rev749/modules/klibc/calloc.c (revision 1169) @@ -0,0 +1,18 @@ +/* + * calloc.c + */ + +#include "libsaio.h" +/* FIXME: This should look for multiplication overflow */ + +void *calloc(size_t nmemb, size_t size) +{ + void *ptr; + + size *= nmemb; + ptr = malloc(size); + if (ptr) + memset(ptr, 0, size); + + return ptr; +} Index: branches/slice/rev749/modules/klibc/memccpy.c =================================================================== --- branches/slice/rev749/modules/klibc/memccpy.c (revision 0) +++ branches/slice/rev749/modules/klibc/memccpy.c (revision 1169) @@ -0,0 +1,23 @@ +/* + * memccpy.c + * + * memccpy() + */ + +#include +#include + +void *memccpy(void *dst, const void *src, int c, size_t n) +{ + char *q = dst; + const char *p = src; + char ch; + + while (n--) { + *q++ = ch = *p++; + if (ch == (char)c) + return q; + } + + return NULL; /* No instance of "c" found */ +} Index: branches/slice/rev749/modules/GUI/picopng.c =================================================================== --- branches/slice/rev749/modules/GUI/picopng.c (revision 0) +++ branches/slice/rev749/modules/GUI/picopng.c (revision 1169) @@ -0,0 +1,1237 @@ +// picoPNG version 20080503 (cleaned up and ported to c by kaitek) +// Copyright (c) 2005-2008 Lode Vandevenne +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +#include "libsa.h" +#include "picopng.h" + +/* sys.c */ +int open_bvdev(const char *bvd, const char *path, int flags); +int read(int fdesc, char * buf, int count); +int close(int fdesc); +int file_size(int fdesc); +/*************************************************************************************************/ + +typedef struct png_alloc_node { + struct png_alloc_node *prev, *next; + void *addr; + size_t size; +} png_alloc_node_t; + +png_alloc_node_t *png_alloc_head = NULL; +png_alloc_node_t *png_alloc_tail = NULL; + +png_alloc_node_t *png_alloc_find_node(void *addr) +{ + png_alloc_node_t *node; + for (node = png_alloc_head; node; node = node->next) + if (node->addr == addr) + break; + return node; +} + +void png_alloc_add_node(void *addr, size_t size) +{ + png_alloc_node_t *node; + if (png_alloc_find_node(addr)) + return; + node = malloc(sizeof (png_alloc_node_t)); + node->addr = addr; + node->size = size; + node->prev = png_alloc_tail; + node->next = NULL; + png_alloc_tail = node; + if (node->prev) + node->prev->next = node; + if (!png_alloc_head) + png_alloc_head = node; +} + +void png_alloc_remove_node(png_alloc_node_t *node) +{ + if (node->prev) + node->prev->next = node->next; + if (node->next) + node->next->prev = node->prev; + if (node == png_alloc_head) + png_alloc_head = node->next; + if (node == png_alloc_tail) + png_alloc_tail = node->prev; + node->prev = node->next = node->addr = NULL; + free(node); +} + +void *png_alloc_malloc(size_t size) +{ + void *addr = malloc(size); + png_alloc_add_node(addr, size); + return addr; +} + +void *png_alloc_realloc(void *addr, size_t size) +{ + void *new_addr; + if (!addr) + return png_alloc_malloc(size); + new_addr = realloc(addr, size); + if (new_addr != addr) { + png_alloc_node_t *old_node; + old_node = png_alloc_find_node(addr); + png_alloc_remove_node(old_node); + png_alloc_add_node(new_addr, size); + } + return new_addr; +} + +void png_alloc_free(void *addr) +{ + png_alloc_node_t *node = png_alloc_find_node(addr); + if (!node) + return; + png_alloc_remove_node(node); + free(addr); +} + +void png_alloc_free_all() +{ + while (png_alloc_tail) { + void *addr = png_alloc_tail->addr; + png_alloc_remove_node(png_alloc_tail); + free(addr); + } +} + +/*************************************************************************************************/ + +__unused void vector32_cleanup(vector32_t *p) +{ + p->size = p->allocsize = 0; + if (p->data) + png_alloc_free(p->data); + p->data = NULL; +} + +uint32_t vector32_resize(vector32_t *p, size_t size) +{ // returns 1 if success, 0 if failure ==> nothing done + if (size * sizeof (uint32_t) > p->allocsize) { + size_t newsize = size * sizeof (uint32_t) * 2; + void *data = png_alloc_realloc(p->data, newsize); + if (data) { + p->allocsize = newsize; + p->data = (uint32_t *) data; + p->size = size; + } else + return 0; + } else + p->size = size; + return 1; +} + +uint32_t vector32_resizev(vector32_t *p, size_t size, uint32_t value) +{ // resize and give all new elements the value + size_t oldsize = p->size, i; + if (!vector32_resize(p, size)) + return 0; + for (i = oldsize; i < size; i++) + p->data[i] = value; + return 1; +} + +void vector32_init(vector32_t *p) +{ + p->data = NULL; + p->size = p->allocsize = 0; +} + +vector32_t *vector32_new(size_t size, uint32_t value) +{ + vector32_t *p = png_alloc_malloc(sizeof (vector32_t)); + vector32_init(p); + if (size && !vector32_resizev(p, size, value)) + return NULL; + return p; +} + +/*************************************************************************************************/ + +__unused void vector8_cleanup(vector8_t *p) +{ + p->size = p->allocsize = 0; + if (p->data) + png_alloc_free(p->data); + p->data = NULL; +} + +uint32_t vector8_resize(vector8_t *p, size_t size) +{ // returns 1 if success, 0 if failure ==> nothing done + // xxx: the use of sizeof uint32_t here seems like a bug (this descends from the lodepng vector + // compatibility functions which do the same). without this there is corruption in certain cases, + // so this was probably done to cover up allocation bug(s) in the original picopng code! + if (size * sizeof (uint32_t) > p->allocsize) { + size_t newsize = size * sizeof (uint32_t) * 2; + void *data = png_alloc_realloc(p->data, newsize); + if (data) { + p->allocsize = newsize; + p->data = (uint8_t *) data; + p->size = size; + } else + return 0; // error: not enough memory + } else + p->size = size; + return 1; +} + +uint32_t vector8_resizev(vector8_t *p, size_t size, uint8_t value) +{ // resize and give all new elements the value + size_t oldsize = p->size, i; + if (!vector8_resize(p, size)) + return 0; + for (i = oldsize; i < size; i++) + p->data[i] = value; + return 1; +} + +void vector8_init(vector8_t *p) +{ + p->data = NULL; + p->size = p->allocsize = 0; +} + +vector8_t *vector8_new(size_t size, uint8_t value) +{ + vector8_t *p = png_alloc_malloc(sizeof (vector8_t)); + vector8_init(p); + if (size && !vector8_resizev(p, size, value)) + return NULL; + return p; +} + +vector8_t *vector8_copy(vector8_t *p) +{ + vector8_t *q = vector8_new(p->size, 0); + uint32_t n; + for (n = 0; n < q->size; n++) + q->data[n] = p->data[n]; + return q; +} + +/*************************************************************************************************/ + +const uint32_t LENBASE[29] = { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, + 59, 67, 83, 99, 115, 131, 163, 195, 227, 258 }; +const uint32_t LENEXTRA[29] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, + 4, 5, 5, 5, 5, 0 }; +const uint32_t DISTBASE[30] = { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, + 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577 }; +const uint32_t DISTEXTRA[30] = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, + 10, 10, 11, 11, 12, 12, 13, 13 }; +// code length code lengths +const uint32_t CLCL[19] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; + +/*************************************************************************************************/ + +typedef struct { + // 2D representation of a huffman tree: The one dimension is "0" or "1", the other contains all + // nodes and leaves of the tree. + vector32_t *tree2d; +} HuffmanTree; + +HuffmanTree *HuffmanTree_new() +{ + HuffmanTree *tree = png_alloc_malloc(sizeof (HuffmanTree)); + tree->tree2d = NULL; + return tree; +} + +int HuffmanTree_makeFromLengths(HuffmanTree *tree, const vector32_t *bitlen, uint32_t maxbitlen) +{ // make tree given the lengths + uint32_t bits, n, i; + uint32_t numcodes = (uint32_t) bitlen->size, treepos = 0, nodefilled = 0; + vector32_t *tree1d, *blcount, *nextcode; + tree1d = vector32_new(numcodes, 0); + blcount = vector32_new(maxbitlen + 1, 0); + nextcode = vector32_new(maxbitlen + 1, 0); + for (bits = 0; bits < numcodes; bits++) + blcount->data[bitlen->data[bits]]++; // count number of instances of each code length + for (bits = 1; bits <= maxbitlen; bits++) + nextcode->data[bits] = (nextcode->data[bits - 1] + blcount->data[bits - 1]) << 1; + for (n = 0; n < numcodes; n++) + if (bitlen->data[n] != 0) + tree1d->data[n] = nextcode->data[bitlen->data[n]]++; // generate all the codes + // 0x7fff here means the tree2d isn't filled there yet + vector32_t *tree2d = vector32_new(numcodes * 2, 0x7fff); + tree->tree2d = tree2d; + for (n = 0; n < numcodes; n++) // the codes + for (i = 0; i < bitlen->data[n]; i++) { // the bits for this code + uint32_t bit = (tree1d->data[n] >> (bitlen->data[n] - i - 1)) & 1; + if (treepos > numcodes - 2) + return 55; + if (tree2d->data[2 * treepos + bit] == 0x7fff) { // not yet filled in + if (i + 1 == bitlen->data[n]) { // last bit + tree2d->data[2 * treepos + bit] = n; + treepos = 0; + } else { // addresses are encoded as values > numcodes + tree2d->data[2 * treepos + bit] = ++nodefilled + numcodes; + treepos = nodefilled; + } + } else // subtract numcodes from address to get address value + treepos = tree2d->data[2 * treepos + bit] - numcodes; + } + return 0; +} + +int HuffmanTree_decode(const HuffmanTree *tree, bool *decoded, uint32_t *result, size_t *treepos, + uint32_t bit) +{ // Decodes a symbol from the tree + const vector32_t *tree2d = tree->tree2d; + uint32_t numcodes = (uint32_t) tree2d->size / 2; + if (*treepos >= numcodes) + return 11; // error: you appeared outside the codetree + *result = tree2d->data[2 * (*treepos) + bit]; + *decoded = (*result < numcodes); + *treepos = *decoded ? 0 : *result - numcodes; + return 0; +} + +/*************************************************************************************************/ + +int Inflator_error; + +uint32_t Zlib_readBitFromStream(size_t *bitp, const uint8_t *bits) +{ + uint32_t result = (bits[*bitp >> 3] >> (*bitp & 0x7)) & 1; + (*bitp)++; + return result; +} + +uint32_t Zlib_readBitsFromStream(size_t *bitp, const uint8_t *bits, size_t nbits) +{ + uint32_t i, result = 0; + for (i = 0; i < nbits; i++) + result += (Zlib_readBitFromStream(bitp, bits)) << i; + return result; +} + +void Inflator_generateFixedTrees(HuffmanTree *tree, HuffmanTree *treeD) +{ // get the tree of a deflated block with fixed tree + size_t i; + vector32_t *bitlen, *bitlenD; + bitlen = vector32_new(288, 8); + bitlenD = vector32_new(32, 5); + for (i = 144; i <= 255; i++) + bitlen->data[i] = 9; + for (i = 256; i <= 279; i++) + bitlen->data[i] = 7; + HuffmanTree_makeFromLengths(tree, bitlen, 15); + HuffmanTree_makeFromLengths(treeD, bitlenD, 15); +} + +uint32_t Inflator_huffmanDecodeSymbol(const uint8_t *in, size_t *bp, const HuffmanTree *codetree, + size_t inlength) +{ // decode a single symbol from given list of bits with given code tree. returns the symbol + bool decoded = false; + uint32_t ct = 0; + size_t treepos = 0; + for (;;) { + if ((*bp & 0x07) == 0 && (*bp >> 3) > inlength) { + Inflator_error = 10; // error: end reached without endcode + return 0; + } + Inflator_error = HuffmanTree_decode(codetree, &decoded, &ct, &treepos, + Zlib_readBitFromStream(bp, in)); + if (Inflator_error) + return 0; // stop, an error happened + if (decoded) + return ct; + } +} + +void Inflator_getTreeInflateDynamic(HuffmanTree *tree, HuffmanTree *treeD, const uint8_t *in, + size_t *bp, size_t inlength) +{ // get the tree of a deflated block with dynamic tree, the tree itself is also Huffman + // compressed with a known tree + size_t i, n; + HuffmanTree *codelengthcodetree = HuffmanTree_new(); // the code tree for code length codes + vector32_t *bitlen, *bitlenD; + bitlen = vector32_new(288, 0); + bitlenD = vector32_new(32, 0); + if (*bp >> 3 >= inlength - 2) { + Inflator_error = 49; // the bit pointer is or will go past the memory + return; + } + size_t HLIT = Zlib_readBitsFromStream(bp, in, 5) + 257; // number of literal/length codes + 257 + size_t HDIST = Zlib_readBitsFromStream(bp, in, 5) + 1; // number of dist codes + 1 + size_t HCLEN = Zlib_readBitsFromStream(bp, in, 4) + 4; // number of code length codes + 4 + vector32_t *codelengthcode; // lengths of tree to decode the lengths of the dynamic tree + codelengthcode = vector32_new(19, 0); + for (i = 0; i < 19; i++) + codelengthcode->data[CLCL[i]] = (i < HCLEN) ? Zlib_readBitsFromStream(bp, in, 3) : 0; + Inflator_error = HuffmanTree_makeFromLengths(codelengthcodetree, codelengthcode, 7); + if (Inflator_error) + return; + size_t replength; + for (i = 0; i < HLIT + HDIST; ) { + uint32_t code = Inflator_huffmanDecodeSymbol(in, bp, codelengthcodetree, inlength); + if (Inflator_error) + return; + if (code <= 15) { // a length code + if (i < HLIT) + bitlen->data[i++] = code; + else + bitlenD->data[i++ - HLIT] = code; + } else if (code == 16) { // repeat previous + if (*bp >> 3 >= inlength) { + Inflator_error = 50; // error, bit pointer jumps past memory + return; + } + replength = 3 + Zlib_readBitsFromStream(bp, in, 2); + uint32_t value; // set value to the previous code + if ((i - 1) < HLIT) + value = bitlen->data[i - 1]; + else + value = bitlenD->data[i - HLIT - 1]; + for (n = 0; n < replength; n++) { // repeat this value in the next lengths + if (i >= HLIT + HDIST) { + Inflator_error = 13; // error: i is larger than the amount of codes + return; + } + if (i < HLIT) + bitlen->data[i++] = value; + else + bitlenD->data[i++ - HLIT] = value; + } + } else if (code == 17) { // repeat "0" 3-10 times + if (*bp >> 3 >= inlength) { + Inflator_error = 50; // error, bit pointer jumps past memory + return; + } + replength = 3 + Zlib_readBitsFromStream(bp, in, 3); + for (n = 0; n < replength; n++) { // repeat this value in the next lengths + if (i >= HLIT + HDIST) { + Inflator_error = 14; // error: i is larger than the amount of codes + return; + } + if (i < HLIT) + bitlen->data[i++] = 0; + else + bitlenD->data[i++ - HLIT] = 0; + } + } else if (code == 18) { // repeat "0" 11-138 times + if (*bp >> 3 >= inlength) { + Inflator_error = 50; // error, bit pointer jumps past memory + return; + } + replength = 11 + Zlib_readBitsFromStream(bp, in, 7); + for (n = 0; n < replength; n++) { // repeat this value in the next lengths + if (i >= HLIT + HDIST) { + Inflator_error = 15; // error: i is larger than the amount of codes + return; + } + if (i < HLIT) + bitlen->data[i++] = 0; + else + bitlenD->data[i++ - HLIT] = 0; + } + } else { + Inflator_error = 16; // error: an nonexitent code appeared. This can never happen. + return; + } + } + if (bitlen->data[256] == 0) { + Inflator_error = 64; // the length of the end code 256 must be larger than 0 + return; + } + // now we've finally got HLIT and HDIST, so generate the code trees, and the function is done + Inflator_error = HuffmanTree_makeFromLengths(tree, bitlen, 15); + if (Inflator_error) + return; + Inflator_error = HuffmanTree_makeFromLengths(treeD, bitlenD, 15); + if (Inflator_error) + return; +} + +void Inflator_inflateHuffmanBlock(vector8_t *out, const uint8_t *in, size_t *bp, size_t *pos, + size_t inlength, uint32_t btype) +{ + HuffmanTree *codetree, *codetreeD; // the code tree for Huffman codes, dist codes + codetree = HuffmanTree_new(); + codetreeD = HuffmanTree_new(); + if (btype == 1) + Inflator_generateFixedTrees(codetree, codetreeD); + else if (btype == 2) { + Inflator_getTreeInflateDynamic(codetree, codetreeD, in, bp, inlength); + if (Inflator_error) + return; + } + for (;;) { + uint32_t code = Inflator_huffmanDecodeSymbol(in, bp, codetree, inlength); + if (Inflator_error) + return; + if (code == 256) // end code + return; + else if (code <= 255) { // literal symbol + if (*pos >= out->size) + vector8_resize(out, (*pos + 1) * 2); // reserve more room + out->data[(*pos)++] = (uint8_t) code; + } else if (code >= 257 && code <= 285) { // length code + size_t length = LENBASE[code - 257], numextrabits = LENEXTRA[code - 257]; + if ((*bp >> 3) >= inlength) { + Inflator_error = 51; // error, bit pointer will jump past memory + return; + } + length += Zlib_readBitsFromStream(bp, in, numextrabits); + uint32_t codeD = Inflator_huffmanDecodeSymbol(in, bp, codetreeD, inlength); + if (Inflator_error) + return; + if (codeD > 29) { + Inflator_error = 18; // error: invalid dist code (30-31 are never used) + return; + } + uint32_t dist = DISTBASE[codeD], numextrabitsD = DISTEXTRA[codeD]; + if ((*bp >> 3) >= inlength) { + Inflator_error = 51; // error, bit pointer will jump past memory + return; + } + dist += Zlib_readBitsFromStream(bp, in, numextrabitsD); + size_t start = *pos, back = start - dist; // backwards + if (*pos + length >= out->size) + vector8_resize(out, (*pos + length) * 2); // reserve more room + size_t i; + for (i = 0; i < length; i++) { + out->data[(*pos)++] = out->data[back++]; + if (back >= start) + back = start - dist; + } + } + } +} + +void Inflator_inflateNoCompression(vector8_t *out, const uint8_t *in, size_t *bp, size_t *pos, + size_t inlength) +{ + while ((*bp & 0x7) != 0) + (*bp)++; // go to first boundary of byte + size_t p = *bp / 8; + if (p >= inlength - 4) { + Inflator_error = 52; // error, bit pointer will jump past memory + return; + } + uint32_t LEN = in[p] + 256 * in[p + 1], NLEN = in[p + 2] + 256 * in[p + 3]; + p += 4; + if (LEN + NLEN != 65535) { + Inflator_error = 21; // error: NLEN is not one's complement of LEN + return; + } + if (*pos + LEN >= out->size) + vector8_resize(out, *pos + LEN); + if (p + LEN > inlength) { + Inflator_error = 23; // error: reading outside of in buffer + return; + } + uint32_t n; + for (n = 0; n < LEN; n++) + out->data[(*pos)++] = in[p++]; // read LEN bytes of literal data + *bp = p * 8; +} + +void Inflator_inflate(vector8_t *out, const vector8_t *in, size_t inpos) +{ + size_t bp = 0, pos = 0; // bit pointer and byte pointer + Inflator_error = 0; + uint32_t BFINAL = 0; + while (!BFINAL && !Inflator_error) { + if (bp >> 3 >= in->size) { + Inflator_error = 52; // error, bit pointer will jump past memory + return; + } + BFINAL = Zlib_readBitFromStream(&bp, &in->data[inpos]); + uint32_t BTYPE = Zlib_readBitFromStream(&bp, &in->data[inpos]); + BTYPE += 2 * Zlib_readBitFromStream(&bp, &in->data[inpos]); + if (BTYPE == 3) { + Inflator_error = 20; // error: invalid BTYPE + return; + } + else if (BTYPE == 0) + Inflator_inflateNoCompression(out, &in->data[inpos], &bp, &pos, in->size); + else + Inflator_inflateHuffmanBlock(out, &in->data[inpos], &bp, &pos, in->size, BTYPE); + } + if (!Inflator_error) + vector8_resize(out, pos); // Only now we know the true size of out, resize it to that +} + +/*************************************************************************************************/ + +int Zlib_decompress(vector8_t *out, const vector8_t *in) // returns error value +{ + if (in->size < 2) + return 53; // error, size of zlib data too small + if ((in->data[0] * 256 + in->data[1]) % 31 != 0) + // error: 256 * in->data[0] + in->data[1] must be a multiple of 31, the FCHECK value is + // supposed to be made that way + return 24; + uint32_t CM = in->data[0] & 15, CINFO = (in->data[0] >> 4) & 15, FDICT = (in->data[1] >> 5) & 1; + if (CM != 8 || CINFO > 7) + // error: only compression method 8: inflate with sliding window of 32k is supported by + // the PNG spec + return 25; + if (FDICT != 0) + // error: the specification of PNG says about the zlib stream: "The additional flags shall + // not specify a preset dictionary." + return 26; + Inflator_inflate(out, in, 2); + return Inflator_error; // note: adler32 checksum was skipped and ignored +} + +/*************************************************************************************************/ + +#define PNG_SIGNATURE 0x0a1a0a0d474e5089ull + +#define CHUNK_IHDR 0x52444849 +#define CHUNK_IDAT 0x54414449 +#define CHUNK_IEND 0x444e4549 +#define CHUNK_PLTE 0x45544c50 +#define CHUNK_tRNS 0x534e5274 + +int PNG_error; + +uint32_t PNG_readBitFromReversedStream(size_t *bitp, const uint8_t *bits) +{ + uint32_t result = (bits[*bitp >> 3] >> (7 - (*bitp & 0x7))) & 1; + (*bitp)++; + return result; +} + +uint32_t PNG_readBitsFromReversedStream(size_t *bitp, const uint8_t *bits, uint32_t nbits) +{ + uint32_t i, result = 0; + for (i = nbits - 1; i < nbits; i--) + result += ((PNG_readBitFromReversedStream(bitp, bits)) << i); + return result; +} + +void PNG_setBitOfReversedStream(size_t *bitp, uint8_t *bits, uint32_t bit) +{ + bits[*bitp >> 3] |= (bit << (7 - (*bitp & 0x7))); + (*bitp)++; +} + +uint32_t PNG_read32bitInt(const uint8_t *buffer) +{ + return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]; +} + +int PNG_checkColorValidity(uint32_t colorType, uint32_t bd) // return type is a LodePNG error code +{ + if ((colorType == 2 || colorType == 4 || colorType == 6)) { + if (!(bd == 8 || bd == 16)) + return 37; + else + return 0; + } else if (colorType == 0) { + if (!(bd == 1 || bd == 2 || bd == 4 || bd == 8 || bd == 16)) + return 37; + else + return 0; + } else if (colorType == 3) { + if (!(bd == 1 || bd == 2 || bd == 4 || bd == 8)) + return 37; + else + return 0; + } else + return 31; // nonexistent color type +} + +uint32_t PNG_getBpp(const PNG_info_t *info) +{ + uint32_t bitDepth, colorType; + bitDepth = info->bitDepth; + colorType = info->colorType; + if (colorType == 2) + return (3 * bitDepth); + else if (colorType >= 4) + return (colorType - 2) * bitDepth; + else + return bitDepth; +} + +void PNG_readPngHeader(PNG_info_t *info, const uint8_t *in, size_t inlength) +{ // read the information from the header and store it in the Info + if (inlength < 29) { + PNG_error = 27; // error: the data length is smaller than the length of the header + return; + } + if (*(uint64_t *) in != PNG_SIGNATURE) { + PNG_error = 28; // no PNG signature + return; + } + if (*(uint32_t *) &in[12] != CHUNK_IHDR) { + PNG_error = 29; // error: it doesn't start with a IHDR chunk! + return; + } + info->width = PNG_read32bitInt(&in[16]); + info->height = PNG_read32bitInt(&in[20]); + info->bitDepth = in[24]; + info->colorType = in[25]; + info->compressionMethod = in[26]; + if (in[26] != 0) { + PNG_error = 32; // error: only compression method 0 is allowed in the specification + return; + } + info->filterMethod = in[27]; + if (in[27] != 0) { + PNG_error = 33; // error: only filter method 0 is allowed in the specification + return; + } + info->interlaceMethod = in[28]; + if (in[28] > 1) { + PNG_error = 34; // error: only interlace methods 0 and 1 exist in the specification + return; + } + PNG_error = PNG_checkColorValidity(info->colorType, info->bitDepth); +} + +int PNG_paethPredictor(int a, int b, int c) // Paeth predicter, used by PNG filter type 4 +{ + int p, pa, pb, pc; + p = a + b - c; + pa = p > a ? (p - a) : (a - p); + pb = p > b ? (p - b) : (b - p); + pc = p > c ? (p - c) : (c - p); + return (pa <= pb && pa <= pc) ? a : (pb <= pc ? b : c); +} + +void PNG_unFilterScanline(uint8_t *recon, const uint8_t *scanline, const uint8_t *precon, + size_t bytewidth, uint32_t filterType, size_t length) +{ + size_t i; + switch (filterType) { + case 0: + for (i = 0; i < length; i++) + recon[i] = scanline[i]; + break; + case 1: + for (i = 0; i < bytewidth; i++) + recon[i] = scanline[i]; + for (i = bytewidth; i < length; i++) + recon[i] = scanline[i] + recon[i - bytewidth]; + break; + case 2: + if (precon) + for (i = 0; i < length; i++) + recon[i] = scanline[i] + precon[i]; + else + for (i = 0; i < length; i++) + recon[i] = scanline[i]; + break; + case 3: + if (precon) { + for (i = 0; i < bytewidth; i++) + recon[i] = scanline[i] + precon[i] / 2; + for (i = bytewidth; i < length; i++) + recon[i] = scanline[i] + ((recon[i - bytewidth] + precon[i]) / 2); + } else { + for (i = 0; i < bytewidth; i++) + recon[i] = scanline[i]; + for (i = bytewidth; i < length; i++) + recon[i] = scanline[i] + recon[i - bytewidth] / 2; + } + break; + case 4: + if (precon) { + for (i = 0; i < bytewidth; i++) + recon[i] = (uint8_t) (scanline[i] + PNG_paethPredictor(0, precon[i], 0)); + for (i = bytewidth; i < length; i++) + recon[i] = (uint8_t) (scanline[i] + PNG_paethPredictor(recon[i - bytewidth], + precon[i], precon[i - bytewidth])); + } else { + for (i = 0; i < bytewidth; i++) + recon[i] = scanline[i]; + for (i = bytewidth; i < length; i++) + recon[i] = (uint8_t) (scanline[i] + PNG_paethPredictor(recon[i - bytewidth], 0, 0)); + } + break; + default: + PNG_error = 36; // error: nonexistent filter type given + return; + } +} + +void PNG_adam7Pass(uint8_t *out, uint8_t *linen, uint8_t *lineo, const uint8_t *in, uint32_t w, + size_t passleft, size_t passtop, size_t spacex, size_t spacey, size_t passw, size_t passh, + uint32_t bpp) +{ // filter and reposition the pixels into the output when the image is Adam7 interlaced. This + // function can only do it after the full image is already decoded. The out buffer must have + // the correct allocated memory size already. + if (passw == 0) + return; + size_t bytewidth = (bpp + 7) / 8, linelength = 1 + ((bpp * passw + 7) / 8); + uint32_t y; + for (y = 0; y < passh; y++) { + size_t i, b; + uint8_t filterType = in[y * linelength], *prevline = (y == 0) ? 0 : lineo; + PNG_unFilterScanline(linen, &in[y * linelength + 1], prevline, bytewidth, filterType, + (w * bpp + 7) / 8); + if (PNG_error) + return; + if (bpp >= 8) + for (i = 0; i < passw; i++) + for (b = 0; b < bytewidth; b++) // b = current byte of this pixel + out[bytewidth * w * (passtop + spacey * y) + bytewidth * + (passleft + spacex * i) + b] = linen[bytewidth * i + b]; + else + for (i = 0; i < passw; i++) { + size_t obp, bp; + obp = bpp * w * (passtop + spacey * y) + bpp * (passleft + spacex * i); + bp = i * bpp; + for (b = 0; b < bpp; b++) + PNG_setBitOfReversedStream(&obp, out, PNG_readBitFromReversedStream(&bp, linen)); + } + uint8_t *temp = linen; + linen = lineo; + lineo = temp; // swap the two buffer pointers "line old" and "line new" + } +} + +int PNG_convert(const PNG_info_t *info, vector8_t *out, const uint8_t *in) +{ // converts from any color type to 32-bit. return value = LodePNG error code + size_t i, c; + uint32_t bitDepth, colorType; + bitDepth = info->bitDepth; + colorType = info->colorType; + size_t numpixels = info->width * info->height, bp = 0; + vector8_resize(out, numpixels * 4); + uint8_t *out_data = out->size ? out->data : 0; + if (bitDepth == 8 && colorType == 0) // greyscale + for (i = 0; i < numpixels; i++) { + out_data[4 * i + 0] = out_data[4 * i + 1] = out_data[4 * i + 2] = in[i]; + out_data[4 * i + 3] = (info->key_defined && (in[i] == info->key_r)) ? 0 : 255; + } + else if (bitDepth == 8 && colorType == 2) // RGB color + for (i = 0; i < numpixels; i++) { + for (c = 0; c < 3; c++) + out_data[4 * i + c] = in[3 * i + c]; + out_data[4 * i + 3] = (info->key_defined && (in[3 * i + 0] == info->key_r) && + (in[3 * i + 1] == info->key_g) && (in[3 * i + 2] == info->key_b)) ? 0 : 255; + } + else if (bitDepth == 8 && colorType == 3) // indexed color (palette) + for (i = 0; i < numpixels; i++) { + if (4U * in[i] >= info->palette->size) + return 46; + for (c = 0; c < 4; c++) // get rgb colors from the palette + out_data[4 * i + c] = info->palette->data[4 * in[i] + c]; + } + else if (bitDepth == 8 && colorType == 4) // greyscale with alpha + for (i = 0; i < numpixels; i++) { + out_data[4 * i + 0] = out_data[4 * i + 1] = out_data[4 * i + 2] = in[2 * i + 0]; + out_data[4 * i + 3] = in[2 * i + 1]; + } + else if (bitDepth == 8 && colorType == 6) + for (i = 0; i < numpixels; i++) + for (c = 0; c < 4; c++) + out_data[4 * i + c] = in[4 * i + c]; // RGB with alpha + else if (bitDepth == 16 && colorType == 0) // greyscale + for (i = 0; i < numpixels; i++) { + out_data[4 * i + 0] = out_data[4 * i + 1] = out_data[4 * i + 2] = in[2 * i]; + out_data[4 * i + 3] = (info->key_defined && (256U * in[i] + in[i + 1] == info->key_r)) + ? 0 : 255; + } + else if (bitDepth == 16 && colorType == 2) // RGB color + for (i = 0; i < numpixels; i++) { + for (c = 0; c < 3; c++) + out_data[4 * i + c] = in[6 * i + 2 * c]; + out_data[4 * i + 3] = (info->key_defined && + (256U * in[6 * i + 0] + in[6 * i + 1] == info->key_r) && + (256U * in[6 * i + 2] + in[6 * i + 3] == info->key_g) && + (256U * in[6 * i + 4] + in[6 * i + 5] == info->key_b)) ? 0 : 255; + } + else if (bitDepth == 16 && colorType == 4) // greyscale with alpha + for (i = 0; i < numpixels; i++) { + out_data[4 * i + 0] = out_data[4 * i + 1] = out_data[4 * i + 2] = in[4 * i]; // msb + out_data[4 * i + 3] = in[4 * i + 2]; + } + else if (bitDepth == 16 && colorType == 6) + for (i = 0; i < numpixels; i++) + for (c = 0; c < 4; c++) + out_data[4 * i + c] = in[8 * i + 2 * c]; // RGB with alpha + else if (bitDepth < 8 && colorType == 0) // greyscale + for (i = 0; i < numpixels; i++) { + uint32_t value = (PNG_readBitsFromReversedStream(&bp, in, bitDepth) * 255) / + ((1 << bitDepth) - 1); // scale value from 0 to 255 + out_data[4 * i + 0] = out_data[4 * i + 1] = out_data[4 * i + 2] = (uint8_t) value; + out_data[4 * i + 3] = (info->key_defined && value && + (((1U << bitDepth) - 1U) == info->key_r) && ((1U << bitDepth) - 1U)) ? 0 : 255; + } + else if (bitDepth < 8 && colorType == 3) // palette + for (i = 0; i < numpixels; i++) { + uint32_t value = PNG_readBitsFromReversedStream(&bp, in, bitDepth); + if (4 * value >= info->palette->size) + return 47; + for (c = 0; c < 4; c++) // get rgb colors from the palette + out_data[4 * i + c] = info->palette->data[4 * value + c]; + } + return 0; +} + +PNG_info_t *PNG_info_new() +{ + PNG_info_t *info = png_alloc_malloc(sizeof (PNG_info_t)); + uint32_t i; + for (i = 0; i < sizeof (PNG_info_t); i++) + ((uint8_t *) info)[i] = 0; + info->palette = vector8_new(0, 0); + info->image = vector8_new(0, 0); + return info; +} + +PNG_info_t *PNG_decode(const uint8_t *in, uint32_t size) +{ + PNG_info_t *info; + PNG_error = 0; + if (size == 0 || in == 0) { + PNG_error = 48; // the given data is empty + return NULL; + } + info = PNG_info_new(); + PNG_readPngHeader(info, in, size); + if (PNG_error) + return NULL; + size_t pos = 33; // first byte of the first chunk after the header + vector8_t *idat = NULL; // the data from idat chunks + bool IEND = false, known_type = true; + info->key_defined = false; + // loop through the chunks, ignoring unknown chunks and stopping at IEND chunk. IDAT data is + // put at the start of the in buffer + while (!IEND) { + size_t i, j; + if (pos + 8 >= size) { + PNG_error = 30; // error: size of the in buffer too small to contain next chunk + return NULL; + } + size_t chunkLength = PNG_read32bitInt(&in[pos]); + pos += 4; + if (chunkLength > 0x7fffffff) { + PNG_error = 63; + return NULL; + } + if (pos + chunkLength >= size) { + PNG_error = 35; // error: size of the in buffer too small to contain next chunk + return NULL; + } + uint32_t chunkType = *(uint32_t *) &in[pos]; + if (chunkType == CHUNK_IDAT) { // IDAT: compressed image data chunk + size_t offset = 0; + if (idat) { + offset = idat->size; + vector8_resize(idat, offset + chunkLength); + } else + idat = vector8_new(chunkLength, 0); + for (i = 0; i < chunkLength; i++) + idat->data[offset + i] = in[pos + 4 + i]; + pos += (4 + chunkLength); + } else if (chunkType == CHUNK_IEND) { // IEND + pos += 4; + IEND = true; + } else if (chunkType == CHUNK_PLTE) { // PLTE: palette chunk + pos += 4; // go after the 4 letters + vector8_resize(info->palette, 4 * (chunkLength / 3)); + if (info->palette->size > (4 * 256)) { + PNG_error = 38; // error: palette too big + return NULL; + } + for (i = 0; i < info->palette->size; i += 4) { + for (j = 0; j < 3; j++) + info->palette->data[i + j] = in[pos++]; // RGB + info->palette->data[i + 3] = 255; // alpha + } + } else if (chunkType == CHUNK_tRNS) { // tRNS: palette transparency chunk + pos += 4; // go after the 4 letters + if (info->colorType == 3) { + if (4 * chunkLength > info->palette->size) { + PNG_error = 39; // error: more alpha values given than there are palette entries + return NULL; + } + for (i = 0; i < chunkLength; i++) + info->palette->data[4 * i + 3] = in[pos++]; + } else if (info->colorType == 0) { + if (chunkLength != 2) { + PNG_error = 40; // error: this chunk must be 2 bytes for greyscale image + return NULL; + } + info->key_defined = true; + info->key_r = info->key_g = info->key_b = 256 * in[pos] + in[pos + 1]; + pos += 2; + } else if (info->colorType == 2) { + if (chunkLength != 6) { + PNG_error = 41; // error: this chunk must be 6 bytes for RGB image + return NULL; + } + info->key_defined = true; + info->key_r = 256 * in[pos] + in[pos + 1]; + pos += 2; + info->key_g = 256 * in[pos] + in[pos + 1]; + pos += 2; + info->key_b = 256 * in[pos] + in[pos + 1]; + pos += 2; + } else { + PNG_error = 42; // error: tRNS chunk not allowed for other color models + return NULL; + } + } else { // it's not an implemented chunk type, so ignore it: skip over the data + if (!(in[pos + 0] & 32)) { + // error: unknown critical chunk (5th bit of first byte of chunk type is 0) + PNG_error = 69; + return NULL; + } + pos += (chunkLength + 4); // skip 4 letters and uninterpreted data of unimplemented chunk + known_type = false; + } + pos += 4; // step over CRC (which is ignored) + } + uint32_t bpp = PNG_getBpp(info); + vector8_t *scanlines; // now the out buffer will be filled + scanlines = vector8_new(((info->width * (info->height * bpp + 7)) / 8) + info->height, 0); + PNG_error = Zlib_decompress(scanlines, idat); + if (PNG_error) + return NULL; // stop if the zlib decompressor returned an error + size_t bytewidth = (bpp + 7) / 8, outlength = (info->height * info->width * bpp + 7) / 8; + vector8_resize(info->image, outlength); // time to fill the out buffer + uint8_t *out_data = outlength ? info->image->data : 0; + if (info->interlaceMethod == 0) { // no interlace, just filter + size_t y, obp, bp; + size_t linestart, linelength; + linestart = 0; + // length in bytes of a scanline, excluding the filtertype byte + linelength = (info->width * bpp + 7) / 8; + if (bpp >= 8) // byte per byte + for (y = 0; y < info->height; y++) { + uint32_t filterType = scanlines->data[linestart]; + const uint8_t *prevline; + prevline = (y == 0) ? 0 : &out_data[(y - 1) * info->width * bytewidth]; + PNG_unFilterScanline(&out_data[linestart - y], &scanlines->data[linestart + 1], + prevline, bytewidth, filterType, linelength); + if (PNG_error) + return NULL; + linestart += (1 + linelength); // go to start of next scanline + } else { // less than 8 bits per pixel, so fill it up bit per bit + vector8_t *templine; // only used if bpp < 8 + templine = vector8_new((info->width * bpp + 7) >> 3, 0); + for (y = 0, obp = 0; y < info->height; y++) { + uint32_t filterType = scanlines->data[linestart]; + const uint8_t *prevline; + prevline = (y == 0) ? 0 : &out_data[(y - 1) * info->width * bytewidth]; + PNG_unFilterScanline(templine->data, &scanlines->data[linestart + 1], prevline, + bytewidth, filterType, linelength); + if (PNG_error) + return NULL; + for (bp = 0; bp < info->width * bpp;) + PNG_setBitOfReversedStream(&obp, out_data, PNG_readBitFromReversedStream(&bp, + templine->data)); + linestart += (1 + linelength); // go to start of next scanline + } + } + } else { // interlaceMethod is 1 (Adam7) + int i; + size_t passw[7] = { + (info->width + 7) / 8, (info->width + 3) / 8, (info->width + 3) / 4, + (info->width + 1) / 4, (info->width + 1) / 2, (info->width + 0) / 2, + (info->width + 0) / 1 + }; + size_t passh[7] = { + (info->height + 7) / 8, (info->height + 7) / 8, (info->height + 3) / 8, + (info->height + 3) / 4, (info->height + 1) / 4, (info->height + 1) / 2, + (info->height + 0) / 2 + }; + size_t passstart[7] = { 0 }; + size_t pattern[28] = { 0, 4, 0, 2, 0, 1, 0, 0, 0, 4, 0, 2, 0, 1, 8, 8, 4, 4, 2, 2, 1, 8, 8, + 8, 4, 4, 2, 2 }; // values for the adam7 passes + for (i = 0; i < 6; i++) + passstart[i + 1] = passstart[i] + passh[i] * ((passw[i] ? 1 : 0) + (passw[i] * bpp + 7) / 8); + vector8_t *scanlineo, *scanlinen; // "old" and "new" scanline + scanlineo = vector8_new((info->width * bpp + 7) / 8, 0); + scanlinen = vector8_new((info->width * bpp + 7) / 8, 0); + for (i = 0; i < 7; i++) + PNG_adam7Pass(out_data, scanlinen->data, scanlineo->data, &scanlines->data[passstart[i]], + info->width, pattern[i], pattern[i + 7], pattern[i + 14], pattern[i + 21], + passw[i], passh[i], bpp); + } + if (info->colorType != 6 || info->bitDepth != 8) { // conversion needed + vector8_t *copy = vector8_copy(info->image); // xxx: is this copy necessary? + PNG_error = PNG_convert(info, info->image, copy->data); + } + return info; +} + +/*************************************************************************************************/ + +#ifdef TEST + +#include +#include + +int main(int argc, char **argv) +{ + char *fname = (argc > 1) ? argv[1] : "test.png"; + PNG_info_t *info; + struct stat statbuf; + uint32_t insize, outsize; + FILE *infp, *outfp; + uint8_t *inbuf; + uint32_t n; + + if (stat(fname, &statbuf) != 0) { + perror("stat"); + return 1; + } else if (!statbuf.st_size) { + printf("file empty\n"); + return 1; + } + insize = (uint32_t) statbuf.st_size; + inbuf = malloc(insize); + infp = fopen(fname, "rb"); + if (!infp) { + perror("fopen"); + return 1; + } else if (fread(inbuf, 1, insize, infp) != insize) { + perror("fread"); + return 1; + } + fclose(infp); + + printf("input file: %s (size: %d)\n", fname, insize); + + info = PNG_decode(inbuf, insize); + free(inbuf); + printf("PNG_error: %d\n", PNG_error); + if (PNG_error != 0) + return 1; + + printf("width: %d, height: %d\nfirst 16 bytes: ", info->width, info->height); + for (n = 0; n < 16; n++) + printf("%02x ", info->image->data[n]); + printf("\n"); + + outsize = info->width * info->height * 4; + printf("image size: %d\n", outsize); + if (outsize != info->image->size) { + printf("error: image size doesn't match dimensions\n"); + return 1; + } + outfp = fopen("out.bin", "wb"); + if (!outfp) { + perror("fopen"); + return 1; + } else if (fwrite(info->image->data, 1, outsize, outfp) != outsize) { + perror("fwrite"); + return 1; + } + fclose(outfp); + +#ifdef ALLOC_DEBUG + png_alloc_node_t *node; + for (node = png_alloc_head, n = 1; node; node = node->next, n++) + printf("node %d (%p) addr = %p, size = %ld\n", n, node, node->addr, node->size); +#endif + png_alloc_free_all(); // also frees info and image data from PNG_decode + + return 0; +} + +#endif + + +int loadPngImage(const char *filename, uint16_t *width, uint16_t *height, + uint8_t **imageData) +{ + uint8_t *pngData = NULL; + int pngFile = 0, pngSize; + PNG_info_t *info; + int error = 0; + + pngFile = open_bvdev("bt(0,0)", filename, 0); + if (pngFile == -1) { + error = -1; + goto failed; + } + pngSize = file_size(pngFile); + if (!pngSize) { + error = -1; + goto failed; + } + pngData = malloc(pngSize); + if (read(pngFile, (char *) pngData, pngSize) != pngSize) { + error = -1; + goto failed; + } + + PNG_error = -1; + info = PNG_decode(pngData, pngSize); + if (PNG_error != 0) { + error = PNG_error; + goto failed; + } else if ((info->width > 0xffff) || (info->height > 0xffff)) { + error = -1; + goto failed; + } else if ((info->width * info->height * 4) != info->image->size) { + error = -1; + goto failed; + } + uint8_t *result = malloc(info->width*4*info->height); + *width = info->width; + *height = info->height; + memcpy(result, info->image->data, info->width*4*info->height); + *imageData = result; + +failed: + png_alloc_free_all(); + if (pngData) + free(pngData); + if (pngFile != -1) + close(pngFile); + + return error; +} + +int loadEmbeddedPngImage(uint8_t *pngData, int pngSize, uint16_t *width, uint16_t *height, uint8_t **imageData) { + PNG_info_t *info; + int error = 0; + + PNG_error = -1; + info = PNG_decode(pngData, pngSize); + if (PNG_error != 0) { + error = PNG_error; + goto failed; + } else if ((info->width > 0xffff) || (info->height > 0xffff)) { + error = -1; + goto failed; + } else if ((info->width * info->height * 4) != info->image->size) { + error = -1; + goto failed; + } + uint8_t *result = malloc(info->width*4*info->height); + *width = info->width; + *height = info->height; + memcpy(result, info->image->data, info->width*4*info->height); + *imageData = result; + +failed: + png_alloc_free_all(); + + return error; +} + Index: branches/slice/rev749/modules/GUI/graphic_utils.h =================================================================== --- branches/slice/rev749/modules/GUI/graphic_utils.h (revision 0) +++ branches/slice/rev749/modules/GUI/graphic_utils.h (revision 1169) @@ -0,0 +1,64 @@ + /* Graphic utility functions and data types + * Prashant Vaibhav (C) 12/12/2008 + * Chameleon + */ + +// Everything here is 32 bits per pixel non-premultiplied ARGB format +// + +#ifndef GRAPHIC_UTILS_H +#define GRAPHIC_UTILS_H + +#include "boot.h" + + +char *getVBEInfoString(); + + +typedef union { + struct { + uint8_t b; + uint8_t g; + uint8_t r; + uint8_t a; + } ch; + uint8_t channel[4]; + uint32_t value; +} pixel_t; + +typedef struct { + uint16_t height; + uint16_t width; + pixel_t* pixels; +} pixmap_t; + +typedef struct { + uint32_t x; + uint32_t y; +} position_t; + +// Blends the given pixmap into the given background at the given position +// Uses the alpha channels to blend, and preserves the final alpha (so the +// resultant pixmap can be blended again with another background). +// ported from www.stereopsis.com/doubleblend.html +void blend( const pixmap_t *blendThis, // Source image + pixmap_t *blendInto, // Dest image + const position_t position); // Where to place the source image +// Returns the topleft co-ordinate where if you put the 'toCenter' pixmap, +// it is centered in the background. +position_t centeredIn( const pixmap_t *background, const pixmap_t *toCenter ); + +// Returns the topleft co-ordinate where if you put the given pixmap, its +// center will coincide with the th given center. +position_t centeredAt( const pixmap_t *pixmap, const position_t center ); + +// Utility function returns a position_t struct given the x and y coords as uint16 +position_t pos(const uint16_t x, const uint16_t y); + +// Flips the R and B components of all pixels in the given pixmap +void flipRB(pixmap_t *p); + +// Utility function to get pixel at (x,y) in a pixmap +#define pixel(p,x,y) ((p)->pixels[(x) + (y) * (p)->width]) + +#endif//GRAPHIC_UTILS_H Index: branches/slice/rev749/modules/GUI/gui.c =================================================================== --- branches/slice/rev749/modules/GUI/gui.c (revision 0) +++ branches/slice/rev749/modules/GUI/gui.c (revision 1169) @@ -0,0 +1,2097 @@ +/* + * gui.c + * + * + * Created by Jasmin Fazlic on 18.12.08. + * Copyright 2008/09 Jasmin Fazlic All rights reserved. + * Copyright 2008/09 iNDi All rights reserved. + * + */ + +#include "gui.h" +#include "appleboot.h" +#include "vers.h" +#include "modules.h" +#include "edid.h" + +#ifndef DEBUG_GUI +#define DEBUG_GUI 0 +#endif + +#if DEBUG_GUI +#define DBG(x...) verbose(x) //;getc() +#else +#define DBG(x...) msglog(x) +#endif + + + +gui_t gui; // gui structure +font_t font_small; +font_t font_console; + + +#define IMG_REQUIRED -1 +#define THEME_NAME_DEFAULT "Default" +const char* def_theme_name = THEME_NAME_DEFAULT; +char *theme_name; + +#ifdef EMBED_THEME +#include "art.h" +#endif + +#define LOADPNG(img, alt_img) if (loadThemeImage(#img, alt_img) != 0) { return 1; } + +#define MIN(x, y) ((x) < (y) ? (x) : (y)) +#define MAX(x, y) ((x) > (y) ? (x) : (y)) + +#define VIDEO(x) (bootArgs->Video.v_ ## x) + +#define vram VIDEO(baseAddr) + +int lasttime = 0; // we need this for animating maybe + +extern int gDeviceCount; + + +/* + * ATTENTION: the enum and the following array images[] MUST match !!! + */ +enum { + iBackground = 0, + iLogo, + + iDeviceGeneric, + iDeviceGeneric_o, + iDeviceHFS, + iDeviceHFS_o, + iDeviceHFSRAID, + iDeviceHFSRAID_o, + iDeviceEXT3, + iDeviceEXT3_o, + iDeviceFAT, + iDeviceFAT_o, + iDeviceFAT16, + iDeviceFAT16_o, + iDeviceFAT32, + iDeviceFAT32_o, + iDeviceNTFS, + iDeviceNTFS_o, + iDeviceCDROM, + iDeviceCDROM_o, + + iSelection, + iDeviceScrollPrev, + iDeviceScrollNext, + + iMenuBoot, + iMenuVerbose, + iMenuIgnoreCaches, + iMenuSingleUser, + iMenuMemoryInfo, + iMenuVideoInfo, + iMenuHelp, + iMenuVerboseDisabled, + iMenuIgnoreCachesDisabled, + iMenuSingleUserDisabled, + iMenuSelection, + + iProgressBar, + iProgressBarBackground, + + iTextScrollPrev, + iTextScrollNext, + + iFontConsole, + iFontSmall, +}; + +image_t images[] = { + {.name = "background", .image = NULL}, + {.name = "logo", .image = NULL}, + + {.name = "device_generic", .image = NULL}, + {.name = "device_generic_o", .image = NULL}, + {.name = "device_hfsplus", .image = NULL}, + {.name = "device_hfsplus_o", .image = NULL}, + {.name = "device_hfsraid", .image = NULL}, + {.name = "device_hfsraid_o", .image = NULL}, + {.name = "device_ext3", .image = NULL}, + {.name = "device_ext3_o", .image = NULL}, + {.name = "device_fat", .image = NULL}, + {.name = "device_fat_o", .image = NULL}, + {.name = "device_fat16", .image = NULL}, + {.name = "device_fat16_o", .image = NULL}, + {.name = "device_fat32", .image = NULL}, + {.name = "device_fat32_o", .image = NULL}, + {.name = "device_ntfs", .image = NULL}, + {.name = "device_ntfs_o", .image = NULL}, + {.name = "device_cdrom", .image = NULL}, + {.name = "device_cdrom_o", .image = NULL}, + + {.name = "device_selection", .image = NULL}, + {.name = "device_scroll_prev", .image = NULL}, + {.name = "device_scroll_next", .image = NULL}, + + {.name = "menu_boot", .image = NULL}, + {.name = "menu_verbose", .image = NULL}, + {.name = "menu_ignore_caches", .image = NULL}, + {.name = "menu_single_user", .image = NULL}, + {.name = "menu_memory_info", .image = NULL}, + {.name = "menu_video_info", .image = NULL}, + {.name = "menu_help", .image = NULL}, + {.name = "menu_verbose_disabled", .image = NULL}, + {.name = "menu_ignore_caches_disabled", .image = NULL}, + {.name = "menu_single_user_disabled", .image = NULL}, + {.name = "menu_selection", .image = NULL}, + + {.name = "progress_bar", .image = NULL}, + {.name = "progress_bar_background", .image = NULL}, + + {.name = "text_scroll_prev", .image = NULL}, + {.name = "text_scroll_next", .image = NULL}, + + {.name = "font_console", .image = NULL}, + {.name = "font_small", .image = NULL}, +}; + +int imageCnt = 0; + +extern int gDeviceCount; +extern int selectIndex; + +char prompt[BOOT_STRING_LEN]; + +int prompt_pos=0; + +char prompt_text[] = "boot: "; + +menuitem_t infoMenuItems[] = +{ + { .text = "Boot" }, + { .text = "Boot Verbose" }, + { .text = "Boot Ignore Caches" }, +// { .text = "Boot Safe Mode" }, + { .text = "Boot Single User" }, + { .text = "Memory Info" }, + { .text = "Video Info" }, + { .text = "Help" } +}; + +int initFont(font_t *font, image_t *image); +void colorFont(font_t *font, uint32_t color); +void makeRoundedCorners(pixmap_t *p); + +int infoMenuSelection = 0; +int infoMenuItemsCount = sizeof(infoMenuItems)/sizeof(infoMenuItems[0]); + +bool infoMenuNativeBoot = false; + +unsigned long screen_params[4] = {DEFAULT_SCREEN_WIDTH, DEFAULT_SCREEN_HEIGHT, 32, 0}; // here we store the used screen resolution + +int getImageIndexByName(const char *name) +{ + int i; + for (i = 0; i < sizeof(images) / sizeof(images[0]); i++) + { + if (strcmp(name, images[i].name) == 0) + return i; // found the name + } + return -1; +} + +#ifdef EMBED_THEME +static int getEmbeddedImageIndexByName(const char *name) +{ + int upperLimit = sizeof(embeddedImages) / sizeof(embeddedImages[0]) - 1; + int lowerLimit = 0; + int compareIndex = (upperLimit - lowerLimit) >> 1; // Midpoint + int result; + + // NOTE: This algorithm assumes that the embeddedImages is sorted. + // This is currently done using the make file. If the array is every + // manualy generated, this *will* fail to work properly. + while((result = strcmp(name, embeddedImages[compareIndex].name)) != 0) + { + if(result > 0) // We need to search a HIGHER index + { + if(compareIndex != lowerLimit) + { + lowerLimit = compareIndex; + } + else + { + return -1; + } + compareIndex = (upperLimit + lowerLimit + 1) >> 1; // Midpoint, round up + } + else // We Need to search a LOWER index + { + if(compareIndex != upperLimit) + { + upperLimit = compareIndex; + } + else + { + return -1; + } + compareIndex = (upperLimit + lowerLimit) >> 1; // Midpoint, round down + } + } + return compareIndex; +} +#endif + +static int loadThemeImage(const char *image, int alt_image) +{ + char dirspec[256]; + int i; +#ifdef EMBED_THEME + int e; +#endif + uint16_t width; + uint16_t height; + uint8_t *imagedata; + if ((strlen(image) + strlen(theme_name) + 20 ) > sizeof(dirspec)) { + return 1; + } + + if ((i = getImageIndexByName(image)) >= 0) + { + if (images[i].image == NULL) { + images[i].image = malloc(sizeof(pixmap_t)); + } + sprintf(dirspec, "/Extra/Themes/%s/%s.png", theme_name, image); + + width = 0; + height = 0; + imagedata = NULL; + if ((loadPngImage(dirspec, &width, &height, &imagedata)) == 0) + { + images[i].image->width = width; + images[i].image->height = height; + images[i].image->pixels = (pixel_t *)imagedata; + flipRB(images[i].image); + return 0; + } +#ifdef EMBED_THEME + else if ((e = getEmbeddedImageIndexByName(image)) >= 0) + { + unsigned char *embed_data; + unsigned int embed_size; + embed_data = embeddedImages[e].pngdata; + embed_size = *embeddedImages[e].length; + + if (loadEmbeddedPngImage(embed_data, embed_size, &width, &height, &imagedata) == 0) + { + images[i].image->width = width; + images[i].image->height = height; + images[i].image->pixels = (pixel_t *)imagedata; + flipRB(images[i].image); + return 0; + } + + return 0; + } +#endif + else if (alt_image != IMG_REQUIRED && images[alt_image].image->pixels != NULL) + { + // Using the passed alternate image for non-mandatory images. + // We don't clone the already existing pixmap, but using its properties instead! + images[i].image->width = images[alt_image].image->width; + images[i].image->height = images[alt_image].image->height; + images[i].image->pixels = images[alt_image].image->pixels; + return 0; + } + else + { +#ifndef EMBED_THEME + printf("ERROR: GUI: could not open '%s/%s.png'!\n", theme_name, image); + sleep(2); +#endif + return 1; + } + } + + return 1; +} + +static int loadGraphics(void) +{ + LOADPNG(background, IMG_REQUIRED); + LOADPNG(logo, IMG_REQUIRED); + + LOADPNG(device_generic, IMG_REQUIRED); + LOADPNG(device_generic_o, iDeviceGeneric); + LOADPNG(device_hfsplus, iDeviceGeneric); + LOADPNG(device_hfsplus_o, iDeviceHFS); + LOADPNG(device_hfsraid, iDeviceGeneric); + LOADPNG(device_hfsraid_o, iDeviceHFSRAID); + LOADPNG(device_ext3, iDeviceGeneric); + LOADPNG(device_ext3_o, iDeviceEXT3); + LOADPNG(device_fat, iDeviceGeneric); + LOADPNG(device_fat_o, iDeviceFAT); + LOADPNG(device_fat16, iDeviceFAT); + LOADPNG(device_fat16_o, iDeviceFAT_o); + LOADPNG(device_fat32, iDeviceFAT); + LOADPNG(device_fat32_o, iDeviceFAT_o); + LOADPNG(device_ntfs, iDeviceGeneric); + LOADPNG(device_ntfs_o, iDeviceNTFS); + LOADPNG(device_cdrom, iDeviceGeneric); + LOADPNG(device_cdrom_o, iDeviceCDROM); + + LOADPNG(device_selection, IMG_REQUIRED); + LOADPNG(device_scroll_prev, IMG_REQUIRED); + LOADPNG(device_scroll_next, IMG_REQUIRED); + + LOADPNG(menu_boot, IMG_REQUIRED); + LOADPNG(menu_verbose, IMG_REQUIRED); + LOADPNG(menu_ignore_caches, IMG_REQUIRED); + LOADPNG(menu_single_user, IMG_REQUIRED); + LOADPNG(menu_memory_info, IMG_REQUIRED); + LOADPNG(menu_video_info, IMG_REQUIRED); + LOADPNG(menu_help, IMG_REQUIRED); + LOADPNG(menu_verbose_disabled, IMG_REQUIRED); + LOADPNG(menu_ignore_caches_disabled, IMG_REQUIRED); + LOADPNG(menu_single_user_disabled, IMG_REQUIRED); + LOADPNG(menu_selection, IMG_REQUIRED); + + LOADPNG(progress_bar, IMG_REQUIRED); + LOADPNG(progress_bar_background, IMG_REQUIRED); + + LOADPNG(text_scroll_prev, IMG_REQUIRED); + LOADPNG(text_scroll_next, IMG_REQUIRED); + + LOADPNG(font_console, IMG_REQUIRED); + LOADPNG(font_small, IMG_REQUIRED); + + initFont( &font_console, &images[iFontConsole]); + initFont( &font_small, &images[iFontSmall]); + + return 0; +} + +pixmap_t *getCroppedPixmapAtPosition( pixmap_t *from, position_t pos, uint16_t width, uint16_t height ) +{ + + pixmap_t *cropped = malloc( sizeof( pixmap_t ) ); + if( !cropped ) + return 0; + cropped->pixels = malloc( width * height * 4 ); + if ( !cropped->pixels ) + return 0; + + cropped->width = width; + cropped->height = height; + + int destx = 0, desty = 0; + int srcx = pos.x, srcy = pos.y; + + for( ; desty < height; desty++, srcy++) + { + for( destx = 0, srcx = pos.x; destx < width; destx++, srcx++ ) + { + pixel( cropped, destx, desty ).value = pixel( from, srcx, srcy ).value; + } + } + return cropped; +} + +int createBackBuffer( window_t *window ) +{ + gui.backbuffer = malloc(sizeof(pixmap_t)); + if(!gui.backbuffer) + return 1; + + gui.backbuffer->pixels = malloc( window->width * window->height * 4 ); + if(!gui.backbuffer->pixels) + { + free(gui.backbuffer); + gui.backbuffer = 0; + return 1; + } + + gui.backbuffer->width = gui.screen.width; + gui.backbuffer->height = gui.screen.height; +// gui.backbuffer->width = window->width; +// gui.backbuffer->height = window->height; + + return 0; +} + +int createWindowBuffer( window_t *window ) +{ + window->pixmap = malloc(sizeof(pixmap_t)); + if(!window->pixmap) + return 1; + + window->pixmap->pixels = malloc( window->width * window->height * 4 ); + if(!window->pixmap->pixels) + { + free(window->pixmap); + window->pixmap = 0; + return 1; + } + + window->pixmap->width = window->width; + window->pixmap->height = window->height; + + return 0; +} + +int freeWindowBuffer( window_t *window ) +{ + if (window->pixmap && window->pixmap->pixels) + { + free(window->pixmap->pixels); + free(window->pixmap); + return 0; + } + + return 1; +} + +void fillPixmapWithColor(pixmap_t *pm, uint32_t color) +{ + int x,y; + + // fill with given color AARRGGBB + for( x=0; x < pm->width; x++ ) + for( y=0; y< pm->height; y++) + pixel(pm,x,y).value = color; +} + +void drawBackground() +{ + // reset text cursor + gui.screen.cursor.x = gui.screen.hborder; + gui.screen.cursor.y = gui.screen.vborder; + + fillPixmapWithColor( gui.screen.pixmap, gui.screen.bgcolor); + + // draw background.png into background buffer + blend( images[iBackground].image, gui.screen.pixmap, gui.background.pos ); + + // draw logo.png into background buffer + if (gui.logo.draw) + { + blend( images[iLogo].image, gui.screen.pixmap, gui.logo.pos); + } + + memcpy( gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4 ); +} + +void setupDeviceList(config_file_t *theme) +{ + unsigned int pixel; + int alpha; // transparency level 0 (obligue) - 255 (transparent) + uint32_t color; // color value formatted RRGGBB + int val, len; + const char *string; + + if(getIntForKey("devices_max_visible", &val, theme )) + gui.maxdevices = MIN( val, gDeviceCount ); + + if(getIntForKey("devices_iconspacing", &val, theme )) + gui.devicelist.iconspacing = val; + + // check layout for horizontal or vertical + gui.layout = HorizontalLayout; + if(getValueForKey( "devices_layout", &string, &len, theme)) { + if (!strcmp (string, "vertical")) { + gui.layout = VerticalLayout; + } + } + + switch (gui.layout) { + case VerticalLayout: + gui.devicelist.height = ((images[iSelection].image->height + font_console.chars[0]->height + gui.devicelist.iconspacing) * MIN(gui.maxdevices, gDeviceCount) + (images[iDeviceScrollPrev].image->height + images[iDeviceScrollNext].image->height) + gui.devicelist.iconspacing); + gui.devicelist.width = (images[iSelection].image->width + gui.devicelist.iconspacing); + + if(getDimensionForKey("devices_pos_x", &pixel, theme, gui.screen.width , images[iSelection].image->width ) ) + gui.devicelist.pos.x = pixel; + + if(getDimensionForKey("devices_pos_y", &pixel, theme, gui.screen.height , gui.devicelist.height ) ) + gui.devicelist.pos.y = pixel; + break; + + case HorizontalLayout: + default: + gui.devicelist.width = ((images[iSelection].image->width + gui.devicelist.iconspacing) * MIN(gui.maxdevices, gDeviceCount) + (images[iDeviceScrollPrev].image->width + images[iDeviceScrollNext].image->width) + gui.devicelist.iconspacing); + gui.devicelist.height = (images[iSelection].image->height + font_console.chars[0]->height + gui.devicelist.iconspacing); + + if(getDimensionForKey("devices_pos_x", &pixel, theme, gui.screen.width , gui.devicelist.width ) ) + gui.devicelist.pos.x = pixel; + else + gui.devicelist.pos.x = ( gui.screen.width - gui.devicelist.width ) / 2; + + if(getDimensionForKey("devices_pos_y", &pixel, theme, gui.screen.height , images[iSelection].image->height ) ) + gui.devicelist.pos.y = pixel; + else + gui.devicelist.pos.y = ( gui.screen.height - gui.devicelist.height ) / 2; + break; + } + + if(getColorForKey("devices_bgcolor", &color, theme)) + gui.devicelist.bgcolor = (color & 0x00FFFFFF); + + if(getIntForKey("devices_transparency", &alpha, theme)) + gui.devicelist.bgcolor = gui.devicelist.bgcolor | (( 255 - ( alpha & 0xFF) ) << 24); + + if (gui.devicelist.pixmap) + { + freeWindowBuffer(&gui.devicelist); + createWindowBuffer(&gui.devicelist); + } +} + +void loadThemeValues(config_file_t *theme) +{ + unsigned int screen_width = gui.screen.width; + unsigned int screen_height = gui.screen.height; + unsigned int pixel; + int alpha; // transparency level 0 (obligue) - 255 (transparent) + uint32_t color; // color value formatted RRGGBB + int val; + + /* + * Parse screen parameters + */ + if(getColorForKey("screen_bgcolor", &color, theme )) + gui.screen.bgcolor = (color & 0x00FFFFFF); + + if(getIntForKey("screen_textmargin_h", &val, theme)) + gui.screen.hborder = MIN( gui.screen.width , val ); + + if(getIntForKey("screen_textmargin_v", &val, theme)) + gui.screen.vborder = MIN( gui.screen.height , val ); + + /* + * Parse background parameters + */ + if(getDimensionForKey("background_pos_x", &pixel, theme, screen_width , images[iBackground].image->width ) ) + gui.background.pos.x = pixel; + + if(getDimensionForKey("background_pos_y", &pixel, theme, screen_height , images[iBackground].image->height ) ) + gui.background.pos.y = pixel; + + /* + * Parse logo parameters + */ + if(getDimensionForKey("logo_pos_x", &pixel, theme, screen_width , images[iLogo].image->width ) ) + gui.logo.pos.x = pixel; + + if(getDimensionForKey("logo_pos_y", &pixel, theme, screen_height , images[iLogo].image->height ) ) + gui.logo.pos.y = pixel; + + /* + * Parse progress bar parameters + */ + if(getDimensionForKey("progressbar_pos_x", &pixel, theme, screen_width , 0 ) ) + gui.progressbar.pos.x = pixel; + + if(getDimensionForKey("progressbar_pos_y", &pixel, theme, screen_height , 0 ) ) + gui.progressbar.pos.y = pixel; + + /* + * Parse countdown text parameters + */ + if(getDimensionForKey("countdown_pos_x", &pixel, theme, screen_width , 0 ) ) + gui.countdown.pos.x = pixel; + + if(getDimensionForKey("countdown_pos_y", &pixel, theme, screen_height , 0 ) ) + gui.countdown.pos.y = pixel; + + /* + * Parse devicelist parameters + */ + setupDeviceList(theme); + + /* + * Parse infobox parameters + */ + if(getIntForKey("infobox_width", &val, theme)) + gui.infobox.width = MIN( screen_width , val ); + + if(getIntForKey("infobox_height", &val, theme)) + gui.infobox.height = MIN( screen_height , val ); + + if(getDimensionForKey("infobox_pos_x", &pixel, theme, screen_width , gui.infobox.width ) ) + gui.infobox.pos.x = pixel; + + if(getDimensionForKey("infobox_pos_y", &pixel, theme, screen_height , gui.infobox.height ) ) + gui.infobox.pos.y = pixel; + + if(getIntForKey("infobox_textmargin_h", &val, theme)) + gui.infobox.hborder = MIN( gui.infobox.width , val ); + + if(getIntForKey("infobox_textmargin_v", &val, theme)) + gui.infobox.vborder = MIN( gui.infobox.height , val ); + + if(getColorForKey("infobox_bgcolor", &color, theme)) + gui.infobox.bgcolor = (color & 0x00FFFFFF); + + if(getIntForKey("infobox_transparency", &alpha, theme)) + gui.infobox.bgcolor = gui.infobox.bgcolor | (( 255 - ( alpha & 0xFF) ) << 24); + + /* + * Parse menu parameters + */ + if(getDimensionForKey("menu_width", &pixel, theme, gui.screen.width , 0 ) ) + gui.menu.width = pixel; + else + gui.menu.width = images[iMenuSelection].image->width; + + if(getDimensionForKey("menu_height", &pixel, theme, gui.screen.height , 0 ) ) + gui.menu.height = pixel; + else + gui.menu.height = (infoMenuItemsCount) * images[iMenuSelection].image->height; + + if(getDimensionForKey("menu_pos_x", &pixel, theme, screen_width , gui.menu.width ) ) + gui.menu.pos.x = pixel; + + if(getDimensionForKey("menu_pos_y", &pixel, theme, screen_height , gui.menu.height ) ) + gui.menu.pos.y = pixel; + + if(getIntForKey("menu_textmargin_h", &val, theme)) + gui.menu.hborder = MIN( gui.menu.width , val ); + + if(getIntForKey("menu_textmargin_v", &val, theme)) + gui.menu.vborder = MIN( gui.menu.height , val ); + + if(getColorForKey("menu_bgcolor", &color, theme)) + gui.menu.bgcolor = (color & 0x00FFFFFF); + + if(getIntForKey("menu_transparency", &alpha, theme)) + gui.menu.bgcolor = gui.menu.bgcolor | (( 255 - ( alpha & 0xFF) ) << 24); + + /* + * Parse bootprompt parameters + */ + if(getDimensionForKey("bootprompt_width", &pixel, theme, screen_width , 0 ) ) + gui.bootprompt.width = pixel; + + if(getIntForKey("bootprompt_height", &val, theme)) + gui.bootprompt.height = MIN( screen_height , val ); + + if(getDimensionForKey("bootprompt_pos_x", &pixel, theme, screen_width , gui.bootprompt.width ) ) + gui.bootprompt.pos.x = pixel; + + if(getDimensionForKey("bootprompt_pos_y", &pixel, theme, screen_height , gui.bootprompt.height ) ) + gui.bootprompt.pos.y = pixel; + + if(getIntForKey("bootprompt_textmargin_h", &val, theme)) + gui.bootprompt.hborder = MIN( gui.bootprompt.width , val ); + + if(getIntForKey("bootprompt_textmargin_v", &val, theme)) + gui.bootprompt.vborder = MIN( gui.bootprompt.height , val ); + + if(getColorForKey("bootprompt_bgcolor", &color, theme)) + gui.bootprompt.bgcolor = (color & 0x00FFFFFF); + + if(getIntForKey("bootprompt_transparency", &alpha, theme)) + gui.bootprompt.bgcolor = gui.bootprompt.bgcolor | (( 255 - ( alpha & 0xFF) ) << 24); + + if(getColorForKey("font_small_color", &color, theme)) + gui.screen.font_small_color = (color & 0x00FFFFFF); + + if(getColorForKey("font_console_color", &color, theme)) + gui.screen.font_console_color = (color & 0x00FFFFFF); +} + +int initGUI(void) +{ + int val; + int len; + char* dirspec; //[256]; + dirspec = (char*)malloc(256); + theme_name = (char*)malloc(64); +// msglog("initGUI\n"); + sprintf(theme_name, THEME_NAME_DEFAULT); +// msglog("theme_name = %s\n",theme_name); + if(getValueForKey( "Theme", &def_theme_name, &len, &bootInfo->bootConfig )) + { + sprintf(theme_name, def_theme_name); + } + if ((strlen(theme_name) + 27) > sizeof(dirspec)) { +// msglog("theme_name=%s len=%d\n", theme_name, strlen(theme_name)); + sprintf(theme_name, THEME_NAME_DEFAULT); +// return 1; + } +// msglog(" stop before theme.plist\n"); +// return 1; + + sprintf(dirspec, "/Extra/Themes/%s/theme.plist", theme_name); +// msglog("theme_name=%s dirspec=%s\n",theme_name, dirspec); +// msglog("Address loadConfigFile=%x bootInfo=%x\n", &loadConfigFile, &bootInfo); +// return 1; + if (loadConfigFile(dirspec, &bootInfo->themeConfig) != 0) { +#ifdef EMBED_THEME + config_file_t *config; + DBG("Attention! EMBED_THEME!\n"); + config = &bootInfo->themeConfig; + if (ParseXMLFile((char *)__theme_plist, &config->dictionary) != 0) { + return 1; + } +#else + msglog(" GUI from themeConfig failed\n"); + return 1; +#endif + } +// msglog(" stop before Resolution.dylib\n"); +// return 1; + if(is_module_loaded("Resolution.dylib")) + { + getResolution(&screen_params[0], &screen_params[1], &screen_params[2]); + gDualLink =((screen_params[0] * screen_params[1]) > (1<<20))?1:0; + msglog("GUI module screen width=%d height=%d\n",(int)screen_params[0], (int)screen_params[1]); + } + if (((int)screen_params[0]<800) || ((int)screen_params[1]<600)) + { + if (getIntForKey("screen_width", &val, &bootInfo->themeConfig) && val > 0) + { + screen_params[0] = val; + } + if (getIntForKey("screen_height", &val, &bootInfo->themeConfig) && val > 0) + { + screen_params[1] = val; + } + msglog("GUI theme screen width=%d height=%d\n",screen_params[0], screen_params[1]); + } + if (((int)screen_params[0]<800) || ((int)screen_params[1]<600)) + { + screen_params[0] = DEFAULT_SCREEN_WIDTH; + screen_params[1] = DEFAULT_SCREEN_HEIGHT; + msglog("GUI default screen width=%d height=%d\n",screen_params[0], screen_params[1]); + } + if (((int)screen_params[0]>4000) || ((int)screen_params[1]>4000)) + { + screen_params[0] = DEFAULT_SCREEN_WIDTH; + screen_params[1] = DEFAULT_SCREEN_HEIGHT; + msglog("GUI MAX VESA screen width=%d height=%d\n",screen_params[0], screen_params[1]); + } + screen_params[2] = 32; + // Initalizing GUI structure. + bzero(&gui, sizeof(gui_t)); + + // find best matching vesa mode for our requested width & height + int modeV = getGraphicModeParams(screen_params); + msglog("GUI: set mode %d: %dx%dx%d\n", modeV, screen_params[0], screen_params[1], screen_params[2]); + + // set our screen structure with the mode width & height + gui.screen.width = screen_params[0]; + gui.screen.height = screen_params[1]; + + // load graphics otherwise fail and return + if (loadGraphics() == 0) { + loadThemeValues(&bootInfo->themeConfig); + colorFont(&font_small, gui.screen.font_small_color); + colorFont(&font_console, gui.screen.font_console_color); + + // create the screen & window buffers + if (createBackBuffer(&gui.screen) == 0) + { + if (createWindowBuffer(&gui.screen) == 0) + { + if (createWindowBuffer(&gui.devicelist) == 0) + { + if (createWindowBuffer(&gui.bootprompt) == 0) + { + if (createWindowBuffer(&gui.infobox) == 0) + { + if (createWindowBuffer(&gui.menu) == 0) + { + gui.logo.draw = true; + drawBackground(); + // lets copy the screen into the back buffer + memcpy( gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4 ); + setVideoMode( GRAPHICS_MODE, 0 ); + gui.initialised = true; + return 0; + } + } + } + } + } + } + } + return 1; +} + +void drawDeviceIcon(BVRef device, pixmap_t *buffer, position_t p, bool isSelected) +{ + int devicetype; + + if( diskIsCDROM(device) ) + devicetype = iDeviceCDROM; // Use CDROM icon + else + { + switch (device->part_type) + { + case kPartitionTypeHFS: + + // Use HFS or HFSRAID icon depending on bvr flags. + devicetype = (device->flags & kBVFlagBooter) ? iDeviceHFSRAID : iDeviceHFS; + break; + + case kPartitionTypeHPFS: + devicetype = iDeviceNTFS; // Use HPFS / NTFS icon + break; + + case kPartitionTypeFAT16: + devicetype = iDeviceFAT16; // Use FAT16 icon + break; + + case kPartitionTypeFAT32: + devicetype = iDeviceFAT32; // Use FAT32 icon + break; + + case kPartitionTypeEXT3: + devicetype = iDeviceEXT3; // Use EXT2/3 icon + break; + + default: + devicetype = iDeviceGeneric; // Use Generic icon + break; + } + } + + // Draw the selection image and use the next (device_*_o) image for the selected item. + if (isSelected) + { + blend(images[iSelection].image, buffer, centeredAt(images[iSelection].image, p)); + devicetype++; // select override image + } + + // draw icon + blend( images[devicetype].image, buffer, centeredAt( images[devicetype].image, p )); + + p.y += (images[iSelection].image->height / 2) + font_console.chars[0]->height; + + // draw volume label + drawStrCenteredAt( device->label, &font_small, buffer, p); + +} + +void drawDeviceList (int start, int end, int selection) +{ + int i; + position_t p, p_prev, p_next; + + //uint8_t maxDevices = MIN( gui.maxdevices, menucount ); + + fillPixmapWithColor( gui.devicelist.pixmap, gui.devicelist.bgcolor); + + makeRoundedCorners( gui.devicelist.pixmap); + + switch (gui.layout) + { + + case VerticalLayout: + p.x = (gui.devicelist.width /2); + p.y = ( ( images[iSelection].image->height / 2 ) + images[iDeviceScrollPrev].image->height + gui.devicelist.iconspacing ); + + // place scroll indicators at top & bottom edges + p_prev = pos ( gui.devicelist.width / 2 , gui.devicelist.iconspacing ); + p_next = pos ( p_prev.x, gui.devicelist.height - gui.devicelist.iconspacing ); + + break; + + default: // use Horizontal layout as the default + + case HorizontalLayout: + p.x = (gui.devicelist.width - ( gui.devicelist.width / gui.maxdevices ) * gui.maxdevices ) / 2 + ( images[iSelection].image->width / 2) + images[iDeviceScrollPrev].image->width + gui.devicelist.iconspacing; + p.y = ((gui.devicelist.height - font_console.chars[0]->height ) - images[iSelection].image->height) / 2 + ( images[iSelection].image->height / 2 ); + + // place scroll indicators at left & right edges + p_prev = pos ( images[iDeviceScrollPrev].image->width / 2 + gui.devicelist.iconspacing / 2, gui.devicelist.height / 2 ); + p_next = pos ( gui.devicelist.width - ( images[iDeviceScrollNext].image->width / 2 + gui.devicelist.iconspacing / 2), gui.devicelist.height / 2 ); + + break; + + } + + // draw visible device icons + for (i = 0; i < gui.maxdevices; i++) + { + BVRef param = menuItems[start + i].param; + + bool isSelected = ((start + i) == selection) ? true : false; + if (isSelected) + { + if (param->flags & kBVFlagNativeBoot) + { + infoMenuNativeBoot = true; + } + else + { + infoMenuNativeBoot = false; + if(infoMenuSelection >= INFOMENU_NATIVEBOOT_START && infoMenuSelection <= INFOMENU_NATIVEBOOT_END) + infoMenuSelection = 0; + } + + if(gui.menu.draw) + drawInfoMenuItems(); + +#if DEBUG + gui.debug.cursor = pos( 10, 100); + dprintf( &gui.screen, "label %s\n", param->label ); + dprintf( &gui.screen, "biosdev 0x%x\n", param->biosdev ); + dprintf( &gui.screen, "width %d\n", gui.screen.width); + dprintf( &gui.screen, "height %d\n", gui.screen.height); + dprintf( &gui.screen, "type 0x%x\n", param->type ); + dprintf( &gui.screen, "flags 0x%x\n", param->flags ); + dprintf( &gui.screen, "part_no %d\n", param->part_no ); + dprintf( &gui.screen, "part_boff 0x%x\n", param->part_boff ); + dprintf( &gui.screen, "part_type 0x%x\n", param->part_type ); + dprintf( &gui.screen, "bps 0x%x\n", param->bps ); + dprintf( &gui.screen, "name %s\n", param->name ); + dprintf( &gui.screen, "type_name %s\n", param->type_name ); + dprintf( &gui.screen, "modtime %d\n", param->modTime ); +#endif + } + + drawDeviceIcon( param, gui.devicelist.pixmap, p, isSelected); + + if (gui.layout == HorizontalLayout) + { + p.x += images[iSelection].image->width + gui.devicelist.iconspacing; + } + if (gui.layout == VerticalLayout) + { + p.y += ( images[iSelection].image->height + font_console.chars[0]->height + gui.devicelist.iconspacing ); + } + } + + // draw prev indicator + if(start) + blend( images[iDeviceScrollPrev].image, gui.devicelist.pixmap, centeredAt( images[iDeviceScrollPrev].image, p_prev ) ); + + // draw next indicator + if( end < gDeviceCount - 1 ) + blend( images[iDeviceScrollNext].image, gui.devicelist.pixmap, centeredAt( images[iDeviceScrollNext].image, p_next ) ); + + gui.redraw = true; + + updateVRAM(); + +} + +void clearGraphicBootPrompt() +{ + // clear text buffer + prompt[0] = '\0'; + prompt_pos=0; + + + if( gui.bootprompt.draw == true ) + { + gui.bootprompt.draw = false; + gui.redraw = true; + // this causes extra frames to be drawn + //updateVRAM(); + } + + return; +} + +void updateGraphicBootPrompt(int key) +{ + if ( key == kBackspaceKey ) + prompt[--prompt_pos] = '\0'; + else + { + prompt[prompt_pos] = key; + prompt_pos++; + prompt[prompt_pos] = '\0'; + } + + fillPixmapWithColor( gui.bootprompt.pixmap, gui.bootprompt.bgcolor); + + makeRoundedCorners( gui.bootprompt.pixmap); + + position_t p_text = pos( gui.bootprompt.hborder , ( ( gui.bootprompt.height - font_console.chars[0]->height) ) / 2 ); + + // print the boot prompt text + drawStr(prompt_text, &font_console, gui.bootprompt.pixmap, p_text); + + // get the position of the end of the boot prompt text to display user input + position_t p_prompt = pos( p_text.x + ( ( strlen(prompt_text) ) * font_console.chars[0]->width ), p_text.y ); + + // calculate the position of the cursor + int offset = ( prompt_pos - ( ( gui.bootprompt.width / font_console.chars[0]->width ) - strlen(prompt_text) - 2 ) ); + + if ( offset < 0) + offset = 0; + + drawStr( prompt+offset, &font_console, gui.bootprompt.pixmap, p_prompt); + + gui.menu.draw = false; + gui.bootprompt.draw = true; + gui.redraw = true; + + updateVRAM(); + + return; +} + +inline +void vramwrite (void *data, int width, int height) +{ + if (VIDEO (depth) == 32 && VIDEO (rowBytes) == gui.backbuffer->width * 4) + memcpy((uint8_t *)vram, gui.backbuffer->pixels, VIDEO (rowBytes)*VIDEO (height)); + else + { + uint32_t r, g, b; + int i, j; + for (i = 0; i < VIDEO (height); i++) + for (j = 0; j < VIDEO (width); j++) + { + b = ((uint8_t *) data)[4*i*width + 4*j]; + g = ((uint8_t *) data)[4*i*width + 4*j + 1]; + r = ((uint8_t *) data)[4*i*width + 4*j + 2]; + switch (VIDEO (depth)) + { + case 32: + *(uint32_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*4) = (b&0xff) | ((g&0xff)<<8) | ((r&0xff)<<16); + break; + case 24: + *(uint32_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*3) = ((*(uint32_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*3))&0xff000000) + | (b&0xff) | ((g&0xff)<<8) | ((r&0xff)<<16); + break; + case 16: + // Somehow 16-bit is always 15-bits really + // *(uint16_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*2) = ((b&0xf8)>>3) | ((g&0xfc)<<3) | ((r&0xf8)<<8); + // break; + case 15: + *(uint16_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*2) = ((b&0xf8)>>3) | ((g&0xf8)<<2) | ((r&0xf8)<<7); + break; + } + } + } +} + +void updateVRAM() +{ + if (gui.redraw) + { + if (gui.devicelist.draw) + blend( gui.devicelist.pixmap, gui.backbuffer, gui.devicelist.pos ); + + if (gui.bootprompt.draw) + blend( gui.bootprompt.pixmap, gui.backbuffer, gui.bootprompt.pos ); + + if (gui.menu.draw) + blend( gui.menu.pixmap, gui.backbuffer, gui.menu.pos ); + + if (gui.infobox.draw) + blend( gui.infobox.pixmap, gui.backbuffer, gui.infobox.pos ); + } + + vramwrite ( gui.backbuffer->pixels, gui.backbuffer->width, gui.backbuffer->height ); + + if (gui.redraw) + { + memcpy( gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4 ); + gui.redraw = false; + } +} + +struct putc_info { + char * str; + char * last_str; +}; + +static void +sputc(int c, struct putc_info * pi) +{ + if (pi->last_str) + if (pi->str == pi->last_str) { + *(pi->str) = '\0'; + return; + } + *(pi->str)++ = c; +} + +int gprintf( window_t * window, const char * fmt, ...) +{ + char *formattedtext; + + va_list ap; + + struct putc_info pi; + + if ((formattedtext = malloc(1024)) != NULL) { + // format the text + va_start(ap, fmt); + pi.str = formattedtext; + pi.last_str = 0; + prf(fmt, ap, sputc, &pi); + *pi.str = '\0'; + va_end(ap); + + position_t origin, cursor, bounds; + + int i; + int character; + + origin.x = MAX( window->cursor.x, window->hborder ); + origin.y = MAX( window->cursor.y, window->vborder ); + + bounds.x = ( window->width - window->hborder ); + bounds.y = ( window->height - window->vborder ); + + cursor = origin; + + font_t *font = &font_console; + + for( i=0; i< strlen(formattedtext); i++ ) + { + character = formattedtext[i]; + + character -= 32; + + // newline ? + if( formattedtext[i] == '\n' ) + { + cursor.x = window->hborder; + cursor.y += font->height; + + if ( cursor.y > bounds.y ) + cursor.y = origin.y; + + continue; + } + + // tab ? + if( formattedtext[i] == '\t' ) + cursor.x += ( font->chars[0]->width * 5 ); + + // draw the character + if( font->chars[character]) + blend(font->chars[character], window->pixmap, cursor); + + cursor.x += font->chars[character]->width; + + // check x pos and do newline + if ( cursor.x > bounds.x ) + { + cursor.x = origin.x; + cursor.y += font->height; + } + + // check y pos and reset to origin.y + if ( cursor.y > bounds.y ) + cursor.y = origin.y; + } + + // update cursor postition + window->cursor = cursor; + + free(formattedtext); + + return 0; + + } + return 1; +} + +int dprintf( window_t * window, const char * fmt, ...) +{ + char *formattedtext; + + va_list ap; + + //window = &gui.debug; + + struct putc_info pi; + + if ((formattedtext = malloc(1024)) != NULL) { + // format the text + va_start(ap, fmt); + pi.str = formattedtext; + pi.last_str = 0; + prf(fmt, ap, sputc, &pi); + *pi.str = '\0'; + va_end(ap); + + position_t origin, cursor, bounds; + + int i; + int character; + + origin.x = MAX( gui.debug.cursor.x, window->hborder ); + origin.y = MAX( gui.debug.cursor.y, window->vborder ); + + bounds.x = ( window->width - window->hborder ); + bounds.y = ( window->height - window->vborder ); + + cursor = origin; + + font_t *font = &font_console; + + for( i=0; i< strlen(formattedtext); i++ ) + { + character = formattedtext[i]; + + character -= 32; + + // newline ? + if( formattedtext[i] == '\n' ) + { + cursor.x = window->hborder; + cursor.y += font->height; + + if ( cursor.y > bounds.y ) + cursor.y = origin.y; + + continue; + } + + // tab ? + if( formattedtext[i] == '\t' ) + cursor.x += ( font->chars[0]->width * 5 ); + + // draw the character + if( font->chars[character]) + blend(font->chars[character], gui.backbuffer, cursor); + + cursor.x += font->chars[character]->width; + + // check x pos and do newline + if ( cursor.x > bounds.x ) + { + cursor.x = origin.x; + cursor.y += font->height; + } + + // check y pos and reset to origin.y + if ( cursor.y > bounds.y ) + cursor.y = origin.y; + } + + // update cursor postition + gui.debug.cursor = cursor; + + free(formattedtext); + + return 0; + + } + return 1; +} + +int vprf(const char * fmt, va_list ap) +{ + int i; + int character; + + char *formattedtext; + window_t *window = &gui.screen; + struct putc_info pi; + + position_t origin, cursor, bounds; + font_t *font = &font_console; + + if ((formattedtext = malloc(1024)) != NULL) { + // format the text + pi.str = formattedtext; + pi.last_str = 0; + prf(fmt, ap, sputc, &pi); + *pi.str = '\0'; + + origin.x = MAX( window->cursor.x, window->hborder ); + origin.y = MAX( window->cursor.y, window->vborder ); + bounds.x = ( window->width - ( window->hborder * 2 ) ); + bounds.y = ( window->height - ( window->vborder * 2 ) ); + cursor = origin; + + for( i=0; i< strlen(formattedtext); i++ ) + { + character = formattedtext[i]; + character -= 32; + + // newline ? + if( formattedtext[i] == '\n' ) + { + cursor.x = window->hborder; + cursor.y += font->height; + if ( cursor.y > bounds.y ) + { + gui.redraw = true; + updateVRAM(); + cursor.y = window->vborder; + } + window->cursor.y = cursor.y; + continue; + } + + // tab ? + if( formattedtext[i] == '\t' ) + { + cursor.x = ( cursor.x / ( font->chars[0]->width * 8 ) + 1 ) * ( font->chars[0]->width * 8 ); + continue; + } + cursor.x += font->chars[character]->width; + + // check x pos and do newline + if ( cursor.x > bounds.x ) + { + cursor.x = origin.x; + cursor.y += font->height; + } + + // check y pos and reset to origin.y + if ( cursor.y > ( bounds.y + font->chars[0]->height) ) + { + gui.redraw = true; + updateVRAM(); + cursor.y = window->vborder; + } + // draw the character + if( font->chars[character]) + blend(font->chars[character], gui.backbuffer, cursor); + } + // save cursor postition + window->cursor.x = cursor.x; + updateVRAM(); + free(formattedtext); + return 0; + } + return 1; +} + +void drawStr(char *ch, font_t *font, pixmap_t *blendInto, position_t p) +{ + int i=0; + int y=0; // we need this to support multilines '\n' + int x=0; + + for(i=0;iheight; + continue; + } + + // tab ? + if( ch[i] == '\t' ) + x+=(font->chars[0]->width*5); + + if(font->chars[cha]) + blend(font->chars[cha], blendInto, pos(p.x+x, p.y+y)); + + x += font->chars[cha]->width; + } +} + +void drawStrCenteredAt(char *text, font_t *font, pixmap_t *blendInto, position_t p) +{ + int i = 0; + int width = 0; + + // calculate the width in pixels + for(i=0;ichars[text[i]-32]->width; + + p.x = ( p.x - ( width / 2 ) ); + p.y = ( p.y - ( font->height / 2 ) ); + + if ( p.x == -6 ) + { + p.x = 0; + } + + for(i=0;ichars[cha]) + { + blend(font->chars[cha], blendInto, p); + p.x += font->chars[cha]->width; + } + } + +} + +int initFont(font_t *font, image_t *data) +{ + unsigned int x = 0, y = 0, x2 = 0, x3 = 0; + + int start = 0, end = 0, count = 0, space = 0; + + bool monospaced = false; + + font->height = data->image->height; + + for( x = 0; x < data->image->width; x++) + { + start = end; + + // if the pixel is red we've reached the end of the char + if( pixel( data->image, x, 0 ).value == 0xFFFF0000) + { + end = x + 1; + + if( (font->chars[count] = malloc(sizeof(pixmap_t)) ) ) + { + font->chars[count]->width = ( end - start) - 1; + font->chars[count]->height = font->height; + + if ( ( font->chars[count]->pixels = malloc( font->chars[count]->width * data->image->height * 4) ) ) + { + space += ( font->chars[count]->width * data->image->height * 4 ); + // we skip the first line because there are just the red pixels for the char width + for( y = 1; y< (font->height); y++) + { + for( x2 = start, x3 = 0; x2 < end; x2++, x3++) + { + pixel( font->chars[count], x3, y ) = pixel( data->image, x2, y ); + } + } + + // check if font is monospaced + if( ( count > 0 ) && ( font->width != font->chars[count]->width ) ) + monospaced = true; + + font->width = font->chars[count]->width; + + count++; + } + } + } + } + + if(monospaced) + font->width = 0; + + return 0; +} + +void colorFont(font_t *font, uint32_t color) +{ + if( !color ) + return; + + int x, y, width, height; + int count = 0; + pixel_t *buff; + + while( font->chars[count++] ) + { + width = font->chars[count-1]->width; + height = font->chars[count-1]->height; + for( y = 0; y < height; y++ ) + { + for( x = 0; x < width; x++ ) + { + buff = &(pixel( font->chars[count-1], x, y )); + if( buff->ch.a ) + { + buff->ch.r = (color & 0xFFFF0000) >> 16; + buff->ch.g = (color & 0xFF00FF00) >> 8; + buff->ch.b = (color & 0xFF0000FF); + } + } + } + } +} + +void makeRoundedCorners(pixmap_t *p) +{ + int x,y; + int width=p->width-1; + int height=p->height-1; + + // 10px rounded corner alpha values + uint8_t roundedCorner[10][10] = + { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0xC0, 0xFF}, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF}, + { 0x00, 0x00, 0x00, 0x40, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + { 0x00, 0x00, 0x40, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + { 0x00, 0x40, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + { 0x00, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + { 0x40, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + { 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + { 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + { 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} + }; + + uint8_t alpha=0; + + for( y=0; y<10; y++) + { + for( x=0; x<10; x++) + { + // skip if the pixel should be visible + if(roundedCorner[y][x] != 0xFF) + { + alpha = ( roundedCorner[y][x] ? (uint8_t) (roundedCorner[y][x] * pixel(p, x, y).ch.a) / 255 : 0 ); + // Upper left corner + pixel(p, x, y).ch.a = alpha; + + // upper right corner + pixel(p, width-x,y).ch.a = alpha; + + // lower left corner + pixel(p, x, height-y).ch.a = alpha; + + // lower right corner + pixel(p, width-x, height-y).ch.a = alpha; + } + } + } +} + +void showInfoBox(char *title, char *text) +{ + int i, key, lines, visiblelines; + + int currentline=0; + int cnt=0; + int offset=0; + + if( !title || !text ) + return; + + position_t pos_title = pos ( gui.infobox.vborder, gui.infobox.vborder ); + + // calculate number of lines in the title + for ( i = 0, lines = 1; iwidth - ( gui.infobox.vborder / 2) ), pos_text.y ); + + // draw prev indicator + if(offset) + { + blend( images[iTextScrollPrev].image, gui.infobox.pixmap, centeredAt( images[iTextScrollPrev].image, pos_indicator )); + } + + // draw next indicator + if( lines > ( currentline + visiblelines ) ) + { + pos_indicator.y = ( gui.infobox.height - ( ( images[iTextScrollNext].image->width + gui.infobox.vborder ) / 2 ) ); + blend( images[iTextScrollNext].image, gui.infobox.pixmap, centeredAt( images[iTextScrollNext].image, pos_indicator ) ); + } + + gui.bootprompt.draw = false; + gui.infobox.draw = true; + gui.redraw = true; + + updateVRAM(); + + key = getc(); + + if( key == kUpArrowkey ) + if( currentline > 0 ) + currentline--; + + if( key == kDownArrowkey ) + if( lines > ( currentline + visiblelines ) ) + currentline++; + + if( key == kEscapeKey || key == 'q' || key == 'Q') + { + gui.infobox.draw = false; + gui.redraw = true; + updateVRAM(); + break; + } + } +} + +void animateProgressBar() +{ + int y; + + if( time18() > lasttime) + { + lasttime = time18(); + + pixmap_t *buffBar = images[iProgressBar].image; + + uint32_t buff = buffBar->pixels[0].value; + + memcpy( buffBar->pixels, buffBar->pixels + 1, ( (buffBar->width*buffBar->height) - 1 ) * 4 ); + + for( y = buffBar->height - 1; y > 0; y--) + pixel(buffBar, buffBar->width - 1, y) = pixel(buffBar, buffBar->width - 1, y - 1); + + pixel(buffBar, buffBar->width-1, 0).value = buff; + } +} + +void drawProgressBar(pixmap_t *blendInto, uint16_t width, position_t p, uint8_t progress) +{ + if(progress>100) + return; + + p.x = ( p.x - ( width / 2 ) ); + + int todraw = (width * progress) / 100; + + pixmap_t *buff = images[iProgressBar].image; + pixmap_t *buffBG = images[iProgressBarBackground].image; + if(!buff || !buffBG) + return; + + pixmap_t progressbar; + progressbar.pixels=malloc(width * 4 * buff->height); + if(!progressbar.pixels) + return; + + progressbar.width = width; + progressbar.height = buff->height; + + int x=0,x2=0,y=0; + + for(y=0; yheight; y++) + { + for(x=0; xwidth-1)) x2=0; + pixel(&progressbar, x,y).value = pixel(buff, x2,y).value; + } + x2=0; + } + + for(y=0; yheight; y++) + { + for(x=todraw, x2 = 0; x < width - 1; x++, x2++) + { + if(x2 == (buffBG->width -2 )) x2 = 0; + pixel(&progressbar, x,y).value = pixel(buffBG, x2,y).value; + } + if(progress < 100) + pixel(&progressbar, width - 1, y).value = pixel(buffBG, buffBG->width - 1, y).value; + if(progress == 0) + pixel(&progressbar, 0, y).value = pixel(buffBG, buffBG->width - 1, y).value; + x2=0; + } + + blend(&progressbar, blendInto, p); + animateProgressBar(); + free(progressbar.pixels); +} + +void drawInfoMenuItems() +{ + int i,n; + + position_t position; + + pixmap_t *selection = images[iMenuSelection].image; + + pixmap_t *pbuff; + + fillPixmapWithColor(gui.menu.pixmap, gui.menu.bgcolor); + + makeRoundedCorners(gui.menu.pixmap); + + uint8_t offset = infoMenuNativeBoot ? 0 : infoMenuItemsCount - 1; + + position = pos(0,0); + + for ( i = 0, n = iMenuBoot; i < infoMenuItemsCount; i++, n++) + { + if (i == infoMenuSelection) + { + blend(selection, gui.menu.pixmap, position); + } + + pbuff = images[n].image; + if (offset && i >= INFOMENU_NATIVEBOOT_START && i <= INFOMENU_NATIVEBOOT_END) + { + blend( images[n + (iMenuHelp - iMenuBoot)].image , gui.menu.pixmap, + pos((position.x + (gui.menu.hborder / 2)), position.y + ((selection->height - pbuff->height) / 2))); + } + else + { + blend( pbuff, gui.menu.pixmap, + pos((position.x + (gui.menu.hborder / 2)), position.y + ((selection->height - pbuff->height) / 2))); + } + + drawStr(infoMenuItems[i].text, &font_console, gui.menu.pixmap, + pos(position.x + (pbuff->width + gui.menu.hborder), + position.y + ((selection->height - font_console.height) / 2))); + position.y += images[iMenuSelection].image->height; + + } + + gui.redraw = true; +} + +int drawInfoMenu() +{ + drawInfoMenuItems(); + + gui.menu.draw = true; + + updateVRAM(); + + return 1; +} + +int updateInfoMenu(int key) +{ + switch (key) + { + + case kUpArrowkey: // up arrow + if (infoMenuSelection > 0) + { + if(!infoMenuNativeBoot && infoMenuSelection == INFOMENU_NATIVEBOOT_END + 1) + { + infoMenuSelection -= 4; + } + else + { + infoMenuSelection--; + } + drawInfoMenuItems(); + updateVRAM(); + + } + else + { + + gui.menu.draw = false; + gui.redraw = true; + + updateVRAM(); + + return CLOSE_INFO_MENU; + } + break; + + case kDownArrowkey: // down arrow + if (infoMenuSelection < infoMenuItemsCount - 1) + { + if(!infoMenuNativeBoot && infoMenuSelection == INFOMENU_NATIVEBOOT_START - 1) + infoMenuSelection += 4; + else + infoMenuSelection++; + drawInfoMenuItems(); + updateVRAM(); + } + break; + + case kReturnKey: + key = 0; + if( infoMenuSelection == MENU_SHOW_MEMORY_INFO ) + showInfoBox( "Memory Info. Press q to quit.\n", getMemoryInfoString()); + + else if( infoMenuSelection == MENU_SHOW_VIDEO_INFO ) + showInfoBox( getVBEInfoString(), getVBEModeInfoString() ); + + else if( infoMenuSelection == MENU_SHOW_HELP ) + showHelp(); + + else + { + int buff = infoMenuSelection; + infoMenuSelection = 0; + return buff; + } + break; + } + return DO_NOT_BOOT; +} + +uint16_t bootImageWidth = 0; +uint16_t bootImageHeight = 0; +uint8_t *bootImageData = NULL; +char usePngImage = 0; + +//========================================================================== +// loadBootGraphics +void loadBootGraphics(void) +{ + if (bootImageData != NULL) { + return; + } + + char dirspec[256]; + + if ((strlen(theme_name) + 24) > sizeof(dirspec)) { + usePngImage = 0; + return; + } + sprintf(dirspec, "/Extra/Themes/%s/boot.png", theme_name); + if (loadPngImage(dirspec, &bootImageWidth, &bootImageHeight, &bootImageData) != 0) { +#ifdef EMBED_THEME + if ((loadEmbeddedPngImage(__boot_png, __boot_png_len, &bootImageWidth, &bootImageHeight, &bootImageData)) != 0) +#endif + usePngImage = 0; + } +} + +//========================================================================== +// drawBootGraphics +void drawBootGraphics(void) +{ + int pos; + int length; + const char *dummyVal; + int oldScreenWidth, oldScreenHeight; + uint16_t x, y; + bool legacy_logo = false; + if (getBoolForKey("Legacy Logo", &legacy_logo, &bootInfo->bootConfig) && !legacy_logo) + { + usePngImage = 1; + } + + if (usePngImage && bootImageData == NULL) { + loadBootGraphics(); + } +//Slice - attention! +// getResolution already done! + // parse screen size parameters + if(is_module_loaded("Resolution.dylib")) + { + getResolution(&screen_params[0], &screen_params[1], &screen_params[2]); + } + else + { + if (getIntForKey("boot_width", &pos, &bootInfo->themeConfig) && pos > 0) + { + screen_params[0] = pos; + } else { + screen_params[0] = DEFAULT_SCREEN_WIDTH; + } + if (getIntForKey("boot_height", &pos, &bootInfo->themeConfig) && pos > 0) + { + screen_params[1] = pos; + } else + { + screen_params[1] = DEFAULT_SCREEN_HEIGHT; + } + } + msglog("boot_width=%d boot_height=%d\n", screen_params[0], screen_params[1]); + // Save current screen resolution. // for a what? + + oldScreenWidth = gui.screen.width; + oldScreenHeight = gui.screen.height; + + gui.screen.width = screen_params[0]; + gui.screen.height = screen_params[1]; + + // find best matching vesa mode for our requested width & height + getGraphicModeParams(screen_params); + + // Set graphics mode if the booter was in text mode or the screen resolution has changed. + if (bootArgs->Video.v_display == VGA_TEXT_MODE + || (screen_params[0] != oldScreenWidth && screen_params[1] != oldScreenHeight) ) + { + setVideoMode(GRAPHICS_MODE, 0); + } + + if (getValueForKey("-checkers", &dummyVal, &length, &bootInfo->bootConfig)) { + drawCheckerBoard(); + } else { + // Fill the background to 75% grey (same as BootX). + drawColorRectangle(0, 0, screen_params[0], screen_params[1], 0x01); + } + if ((bootImageData) && (usePngImage)) { + x = (screen_params[0] - MIN(bootImageWidth, screen_params[0])) / 2; + y = (screen_params[1] - MIN(bootImageHeight, screen_params[1])) / 2; + + // Draw the image in the center of the display. + blendImage(x, y, bootImageWidth, bootImageHeight, bootImageData); + } else { + uint8_t *appleBootPict; + bootImageData = NULL; + bootImageWidth = kAppleBootWidth; + bootImageHeight = kAppleBootHeight; + + // Prepare the data for the default Apple boot image. + appleBootPict = (uint8_t *) decodeRLE(gAppleBootPictRLE, kAppleBootRLEBlocks, bootImageWidth * bootImageHeight); + if (appleBootPict) { + convertImage(bootImageWidth, bootImageHeight, appleBootPict, &bootImageData); + if (bootImageData) { + x = (screen_params[0] - MIN(kAppleBootWidth, screen_params[0])) / 2; + y = (screen_params[1] - MIN(kAppleBootHeight, screen_params[1])) / 2; + drawDataRectangle(x, y, kAppleBootWidth, kAppleBootHeight, bootImageData); + free(bootImageData); + } + free(appleBootPict); + } + } +} + +int GUI_initGraphicsMode () +{ + unsigned long params[4]; + int count; + + params[3] = 0; + count = getNumberArrayFromProperty( kGraphicsModeKey, params, 4 ); + + // Try to find a resolution if "Graphics Mode" setting is not available. + if ( count < 3 ) + { + // Use the default resolution if we don't have an initialized GUI. + if (gui.screen.width == 0 || gui.screen.height == 0) + { + gui.screen.width = DEFAULT_SCREEN_WIDTH; + gui.screen.height = DEFAULT_SCREEN_HEIGHT; + } + + params[0] = gui.screen.width; + params[1] = gui.screen.height; + params[2] = 32; + } + + // Map from pixel format to bits per pixel. + + if ( params[2] == 256 ) params[2] = 8; + if ( params[2] == 555 ) params[2] = 16; + if ( params[2] == 888 ) params[2] = 32; + + return setVESAGraphicsMode( params[0], params[1], params[2], params[3] ); +} + + +int GUI_countdown( const char * msg, int row, int timeout ) +{ + unsigned long time; + int ch = 0; + int col = strlen(msg) + 1; + + flushKeyboardBuffer(); + + if( bootArgs->Video.v_display == VGA_TEXT_MODE ) + { + moveCursor( 0, row ); + printf(msg); + + } else { + + position_t p = pos( gui.screen.width / 2 + 1 , ( gui.devicelist.pos.y + 3 ) + ( ( gui.devicelist.height - gui.devicelist.iconspacing ) / 2 ) ); + + char dummy[80]; + getBootVolumeDescription( gBootVolume, dummy, sizeof(dummy) - 1, true ); + drawDeviceIcon( gBootVolume, gui.screen.pixmap, p, true ); + drawStrCenteredAt( (char *) msg, &font_small, gui.screen.pixmap, gui.countdown.pos ); + + // make this screen the new background + memcpy( gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4 ); + + } + + int multi_buff = 18 * (timeout); + int multi = ++multi_buff; + + int lasttime=0; + + for ( time = time18(), timeout++; timeout > 0; ) + { + if( time18() > lasttime) + { + multi--; + lasttime=time18(); + } + + if (ch = readKeyboardStatus()) + break; + + // Count can be interrupted by holding down shift, + // control or alt key + if ( ( readKeyboardShiftFlags() & 0x0F ) != 0 ) + { + ch = 1; + break; + } + + if ( time18() >= time ) + { + time += 18; + timeout--; + + if( bootArgs->Video.v_display == VGA_TEXT_MODE ) + { + moveCursor( col, row ); + printf("(%d) ", timeout); + } + } + + if( bootArgs->Video.v_display == GRAPHICS_MODE ) + { + drawProgressBar( gui.screen.pixmap, 100, gui.progressbar.pos , ( multi * 100 / multi_buff ) ); + gui.redraw = true; + updateVRAM(); + } + + } + + flushKeyboardBuffer(); + + return ch; +} + Index: branches/slice/rev749/modules/GUI/picopng.h =================================================================== --- branches/slice/rev749/modules/GUI/picopng.h (revision 0) +++ branches/slice/rev749/modules/GUI/picopng.h (revision 1169) @@ -0,0 +1,39 @@ +#ifndef _PICOPNG_H +#define _PICOPNG_H + +#include + +typedef struct { + uint32_t *data; + size_t size; + size_t allocsize; +} vector32_t; + +typedef struct { + uint8_t *data; + size_t size; + size_t allocsize; +} vector8_t; + +typedef struct { + uint32_t width, height; + uint32_t colorType, bitDepth; + uint32_t compressionMethod, filterMethod, interlaceMethod; + uint32_t key_r, key_g, key_b; + bool key_defined; // is a transparent color key given? + vector8_t *palette; + vector8_t *image; +} PNG_info_t; + +PNG_info_t *PNG_decode(const uint8_t *in, uint32_t size); +void png_alloc_free_all(); + +extern int PNG_error; + + +int loadPngImage(const char *filename, uint16_t *width, uint16_t *height, + uint8_t **imageData); +int loadEmbeddedPngImage(uint8_t *pngData, int pngSize, uint16_t *width, uint16_t *height, uint8_t **imageData); + + +#endif Index: branches/slice/rev749/modules/GUI/GUI_module.c =================================================================== --- branches/slice/rev749/modules/GUI/GUI_module.c (revision 0) +++ branches/slice/rev749/modules/GUI/GUI_module.c (revision 1169) @@ -0,0 +1,1114 @@ +/* + * Copyright (c) 2009 Evan Lojewski. All rights reserved. + * + */ + +#include "libsaio.h" +#include "options.h" +#include "graphic_utils.h" +#include "ramdisk.h" +#include "embedded.h" + +#include "picopng.h" +#include "gui.h" + +#include "modules.h" + +/* Kabyl: BooterLog */ +#define BOOTER_LOG_SIZE (64 * 1024) +#define SAFE_LOG_SIZE 80 + +#ifndef DEBUG_GUI +#define DEBUG_GUI 0 +#endif + +#if DEBUG_GUI +#define DBG(x...) GUI_verbose(x) +#else +#define DBG(x...) +#endif + + + +bool useGUI; + +//void GUI_Kernel_Start_hook(void* kernelEntry, void* arg2, void* arg3, void* arg4); +void GUI_PreBoot_hook(void* arg1, void* arg2, void* arg3, void* arg4); +void GUI_ModulesLoaded_hook(void* arg1, void* arg2, void* arg3, void* arg4); + +int GUI_getBootOptions(bool firstRun); + +static void GUI_updateBootArgs( int key ); +void GUI_clearBootArgs(void); +static void GUI_showBootPrompt(int row, bool visible); +static void GUI_showMenu( const MenuItem * items, int count, int selection, int row, int height ); +static int GUI_updateMenu( int key, void ** paramPtr ); +static void GUI_showHelp(void); + +int GUI_printf(const char * fmt, ...); +int GUI_verbose(const char * fmt, ...); +int GUI_error(const char * fmt, ...); +void GUI_stop(const char * fmt, ...); + + +/* console.c */ +struct putc_info { + char * str; + char * last_str; +}; +void sputc(int c, struct putc_info * pi); +extern char *msgbuf; +extern char *cursor; + + + + +char GUI_bootRescanPrompt[] = +"Press Enter to start up Darwin/x86 with no options, or you can:\n" +" Press F5 after you swapped the media. The drive will be rescanned.\n" +" Type -v and press Enter to start up with diagnostic messages\n" +" Type ? and press Enter to learn about advanced startup options\n\n" +"boot: "; + + + +/** + ** The kernel is about to start, draw the boot graphics if we are not in + ** verbose mode. + **/ +void GUI_ExecKernel_hook(void* kernelEntry, void* arg2, void* arg3, void* arg4) +{ + if(!gVerboseMode) + { + // Note: shouldn't be needed, but just in case + drawBootGraphics(); + } + else if(!useGUI) + { + setVideoMode( GRAPHICS_MODE, 0 ); //Slice - Why GRAPHICS_MODE if gVerboseMode? +// DBG("GUI set GRAPHICS_MODE\n"); + } +} + +/** + ** A boot option has been selected, disable the graphical elements on screen. + **/ +void GUI_PreBoot_hook(void* arg1, void* arg2, void* arg3, void* arg4) +{ + // Turn off any GUI elements + if( useGUI ) + { + gui.devicelist.draw = false; + gui.bootprompt.draw = false; + gui.menu.draw = false; + gui.infobox.draw = false; + gui.logo.draw = false; + drawBackground(); + //updateVRAM(); + + if(!gVerboseMode) + { + // Disable outputs, they will still show in the boot log. + replace_function("_printf", &GUI_verbose); +// drawBootGraphics(); + } + + } +} + +void GUI_ModulesLoaded_hook(void* kernelEntry, void* arg2, void* arg3, void* arg4) +{ + // Start the gui + useGUI = true; + // Override useGUI default + getBoolForKey(kGUIKey, &useGUI, &bootInfo->bootConfig); + if (useGUI && initGUI()) + { + // initGUI() returned with an error, disabling GUI. + useGUI = false; + } + else if(useGUI) + { + replace_function("_initGraphicsMode", &GUI_initGraphicsMode); + replace_function("_getBootOptions", &GUI_getBootOptions); + replace_function("_clearBootArgs", &GUI_clearBootArgs); + replace_function("_showHelp", &GUI_showHelp); + + replace_function("_printf", &GUI_printf); + replace_function("_verbose", &GUI_verbose); + replace_function("_error", &GUI_error); + replace_function("_stop", &GUI_stop); + + setVideoMode( GRAPHICS_MODE, 0 ); + drawBackground(); + + } +// DBG("GUI loaded\n"); +} + +/** + ** Module startup code. Replace console only print functions as well as + ** replace various menu functions. Finaly, initialize the gui and hook + ** into important events. + **/ +void GUI_start() +{ + // Hoot for the boot screen + //ExecKernel register_hook_callback("Kernel Start", &GUI_Kernel_Start_hook); + register_hook_callback("ExecKernel", &GUI_ExecKernel_hook); + register_hook_callback("PreBoot", &GUI_PreBoot_hook); + register_hook_callback("ModulesLoaded", &GUI_ModulesLoaded_hook); +} + +/** + ** Overriden chameleon function. Draws the updated menu. + **/ +static int GUI_updateMenu( int key, void ** paramPtr ) +{ + int moved = 0; + + union { + struct { + unsigned int + selectionUp : 1, + selectionDown : 1, + scrollUp : 1, + scrollDown : 1; + } f; + unsigned int w; + } draw = {{0}}; + + if ( gMenuItems == NULL ) + return 0; + + if( bootArgs->Video.v_display == GRAPHICS_MODE ) + { + int res; + + // set navigation keys for horizontal layout as defaults + int previous = 0x4B00; // left arrow + int subsequent = 0x4D00; // right arrow + int menu = 0x5000; // down arrow + + if ( gui.layout == VerticalLayout ) + { + // set navigation keys for vertical layout + previous = 0x4800; // up arrow + subsequent = 0x5000; // down arrow + menu = 0x4B00; // right arrow + } + + if ( key == previous ) + { + if ( gMenuSelection > gMenuTop ) + draw.f.selectionUp = 1; + else if ( gMenuTop > 0 ) + draw.f.scrollDown = 1; + + } + + else if ( key == subsequent ) + { + if ( gMenuSelection != gMenuBottom) + draw.f.selectionDown = 1; + else if ( gMenuBottom < ( gMenuItemCount - 1 ) ) + draw.f.scrollUp = 1; + } + + else if ( key == menu ) + { + if ( gui.menu.draw ) + updateInfoMenu(key); + else + drawInfoMenu(); + } + + else if ( gui.menu.draw ) + { + res = updateInfoMenu(key); + + if ( res == CLOSE_INFO_MENU ) + gui.menu.draw = false; + else + { + shouldboot = ( res != DO_NOT_BOOT ); + + if ( shouldboot ) + gui.menu.draw = false; + + switch (res) + { + case BOOT_NORMAL: + gVerboseMode = false; + gBootMode = kBootModeNormal; + break; + + case BOOT_VERBOSE: + gVerboseMode = true; + gBootMode = kBootModeNormal; + addBootArg(kVerboseModeFlag); + break; + + case BOOT_IGNORECACHE: + gVerboseMode = false; + gBootMode = kBootModeNormal; + addBootArg(kIgnoreCachesFlag); + break; + +/* + case BOOT_SAFEMODE: + gVerboseMode = true; + gBootMode = kBootModeNormal; + addBootArg(kSafeModeFlag); + break; +*/ + + case BOOT_SINGLEUSER: + gVerboseMode = true; + gBootMode = kBootModeNormal; + addBootArg(kSingleUserModeFlag); + break; + } + + } + + } + + } else { + switch ( key ) + { + case 0x4800: // Up Arrow + if ( gMenuSelection != gMenuTop ) + { + draw.f.selectionUp = 1; + } + else if ( gMenuTop > 0 ) + { + draw.f.scrollDown = 1; + } + break; + + case 0x5000: // Down Arrow + if ( gMenuSelection != gMenuBottom ) + { + draw.f.selectionDown = 1; + } + else if ( gMenuBottom < (gMenuItemCount - 1) ) + { + draw.f.scrollUp = 1; + } + break; + } + } + + if ( draw.w ) + { + if ( draw.f.scrollUp ) + { + scollPage(0, gMenuRow, 40, gMenuRow + gMenuHeight - 1, 0x07, 1, 1); + gMenuTop++; gMenuBottom++; + gMenuStart++; gMenuEnd++; + draw.f.selectionDown = 1; + } + + if ( draw.f.scrollDown ) + { + scollPage(0, gMenuRow, 40, gMenuRow + gMenuHeight - 1, 0x07, 1, -1); + gMenuTop--; gMenuBottom--; + gMenuStart--; gMenuEnd--; + draw.f.selectionUp = 1; + } + + if ( draw.f.selectionUp || draw.f.selectionDown ) + { + + CursorState cursorState; + + // Set cursor at current position, and clear inverse video. + + if( bootArgs->Video.v_display == VGA_TEXT_MODE ) + { + changeCursor( 0, (gMenuRow + gMenuSelection - gMenuTop), kCursorTypeHidden, &cursorState ); + printMenuItem( &gMenuItems[gMenuSelection], 0 ); + } + + if ( draw.f.selectionUp ) + { + gMenuSelection--; + if(( gMenuSelection - gMenuStart) == -1 ) + { + gMenuStart--; + gMenuEnd--; + } + + } else { + gMenuSelection++; + if(( gMenuSelection - ( gui.maxdevices - 1) - gMenuStart) > 0 ) + { + gMenuStart++; + gMenuEnd++; + } + } + + if( bootArgs->Video.v_display == VGA_TEXT_MODE ) + { + moveCursor( 0, gMenuRow + gMenuSelection - gMenuTop ); + printMenuItem( &gMenuItems[gMenuSelection], 1 ); + restoreCursor( &cursorState ); + + } + else + { + drawDeviceList (gMenuStart, gMenuEnd, gMenuSelection); + } + + } + + *paramPtr = gMenuItems[gMenuSelection].param; + moved = 1; + } + + return moved; +} + + +static void GUI_showMenu( const MenuItem * items, int count, + int selection, int row, int height ) +{ + int i; + CursorState cursorState; + + if ( items == NULL || count == 0 ) + return; + + // head and tail points to the start and the end of the list. + // top and bottom points to the first and last visible items + // in the menu window. + + gMenuItems = items; + gMenuRow = row; + gMenuHeight = height; + gMenuItemCount = count; + gMenuTop = 0; + gMenuBottom = min( count, height ) - 1; + gMenuSelection = selection; + + gMenuStart = 0; + gMenuEnd = min( count, gui.maxdevices ) - 1; + + // If the selected item is not visible, shift the list down. + + if ( gMenuSelection > gMenuBottom ) + { + gMenuTop += ( gMenuSelection - gMenuBottom ); + gMenuBottom = gMenuSelection; + } + + if ( gMenuSelection > gMenuEnd ) + { + gMenuStart += ( gMenuSelection - gMenuEnd ); + gMenuEnd = gMenuSelection; + } + + // Draw the visible items. + + if( bootArgs->Video.v_display == GRAPHICS_MODE ) + { + drawDeviceList(gMenuStart, gMenuEnd, gMenuSelection); + } + else + { + + changeCursor( 0, row, kCursorTypeHidden, &cursorState ); + + for ( i = gMenuTop; i <= gMenuBottom; i++ ) + { + printMenuItem( &items[i], (i == gMenuSelection) ); + } + + restoreCursor( &cursorState ); + } +} + + +static void GUI_updateBootArgs( int key ) +{ + key &= kASCIIKeyMask; + + switch ( key ) + { + case kBackspaceKey: + if ( gBootArgsPtr > gBootArgs ) + { + int x, y, t; + getCursorPositionAndType( &x, &y, &t ); + if ( x == 0 && y ) + { + x = 80; y--; + } + if (x) + x--; + if( bootArgs->Video.v_display == VGA_TEXT_MODE ) + { + setCursorPosition( x, y, 0 ); + putca(' ', 0x07, 1); + } else + { + updateGraphicBootPrompt(kBackspaceKey); + } + + *gBootArgsPtr-- = '\0'; + } + + break; + + default: + if ( key >= ' ' && gBootArgsPtr < gBootArgsEnd) + { + if( bootArgs->Video.v_display == VGA_TEXT_MODE ) + { + putchar(key); // echo to screen + } + else + { + updateGraphicBootPrompt(key); + } + *gBootArgsPtr++ = key; + } + + break; + } +} + + +static void GUI_showBootPrompt(int row, bool visible) +{ + extern char bootPrompt[]; + + if( bootArgs->Video.v_display == VGA_TEXT_MODE ) + { + changeCursor( 0, row, kCursorTypeUnderline, 0 ); + clearScreenRows( row, kScreenLastRow ); + } + + clearBootArgs(); + + if (visible) + { + if (bootArgs->Video.v_display == VGA_TEXT_MODE) + { + if (gEnableCDROMRescan) + { + printf( GUI_bootRescanPrompt ); + } + else + { + printf( bootPrompt ); + } + } + } + else + { + if (bootArgs->Video.v_display == GRAPHICS_MODE) + { + clearGraphicBootPrompt(); + } + else + { + printf("Press Enter to start up the foreign OS. "); + } + } +} + + +void GUI_clearBootArgs(void) +{ + gBootArgsPtr = gBootArgs; + memset(gBootArgs, '\0', BOOT_STRING_LEN); + + if (bootArgs->Video.v_display == GRAPHICS_MODE) + { + clearGraphicBootPrompt(); + } +} + + +int GUI_getBootOptions(bool firstRun) +{ + int i; + int key; + int nextRow; + int timeout; + int bvCount; + BVRef bvr; + BVRef menuBVR; + bool showPrompt, newShowPrompt, isCDROM; + + // Initialize default menu selection entry. + gBootVolume = menuBVR = selectBootVolume(bvChain); + + if (biosDevIsCDROM(gBIOSDev)) + { + isCDROM = true; + DBG("GUI gBIOSDev is CDROM\n"); + } + else + { + isCDROM = false; + } + + // ensure we're in graphics mode if gui is setup + if (gui.initialised && bootArgs->Video.v_display == VGA_TEXT_MODE) + { + setVideoMode(GRAPHICS_MODE, 0); + } + + // Clear command line boot arguments + clearBootArgs(); + + // Allow user to override default timeout. + if (!getIntForKey(kTimeoutKey, &timeout, &bootInfo->bootConfig)) + { + /* If there is no timeout key in the file use the default timeout + which is different for CDs vs. hard disks. However, if not booting + a CD and no config file could be loaded set the timeout + to zero which causes the menu to display immediately. + This way, if no partitions can be found, that is the disk is unpartitioned + or simply cannot be read) then an empty menu is displayed. + If some partitions are found, for example a Windows partition, then + these will be displayed in the menu as foreign partitions. + */ + if (isCDROM) + { + timeout = kCDBootTimeout; + } + else + { + timeout = sysConfigValid ? kBootTimeout : 0; + } + } + + if (timeout < 0) + { + gBootMode |= kBootModeQuiet; + } + + // If the user is holding down a modifier key, enter safe mode. + if ((readKeyboardShiftFlags() & 0x0F) != 0) + { + + //gBootMode |= kBootModeSafe; + } + + // Checking user pressed keys + bool f8press = false, spress = false, vpress = false; + while (readKeyboardStatus()) + { + key = bgetc (); + if (key == 0x4200) f8press = true; + if ((key & 0xff) == 's' || (key & 0xff) == 'S') spress = true; + if ((key & 0xff) == 'v' || (key & 0xff) == 'V') vpress = true; + } + // If user typed F8, abort quiet mode, and display the menu. + if (f8press) + { + gBootMode &= ~kBootModeQuiet; + timeout = 0; + } + // If user typed 'v' or 'V', boot in verbose mode. + if ((gBootMode & kBootModeQuiet) && firstRun && vpress) + { + addBootArg(kVerboseModeFlag); + } + // If user typed 's' or 'S', boot in single user mode. + if ((gBootMode & kBootModeQuiet) && firstRun && spress) + { + addBootArg(kSingleUserModeFlag); + } + + if (bootArgs->Video.v_display == VGA_TEXT_MODE) + { + setCursorPosition(0, 0, 0); + clearScreenRows(0, kScreenLastRow); + if (!(gBootMode & kBootModeQuiet)) + { + // Display banner and show hardware info. + printf(bootBanner, (bootInfo->convmem + bootInfo->extmem) / 1024); + printf(getVBEInfoString()); + } + changeCursor(0, kMenuTopRow, kCursorTypeUnderline, 0); + msglog("GUI_Scanning device %x...", gBIOSDev); + } + + // When booting from CD, default to hard drive boot when possible. + if (isCDROM && firstRun) + { + const char *val; + char *prompt = NULL; + char *name = NULL; + int cnt; + int optionKey; + + if (getValueForKey(kCDROMPromptKey, &val, &cnt, &bootInfo->bootConfig)) + { + prompt = malloc(cnt + 1); + strncat(prompt, val, cnt); + } + else + { + name = malloc(80); + getBootVolumeDescription(gBootVolume, name, 79, false); + prompt = malloc(256); + sprintf(prompt, "Press any key to start up from %s, or press F8 to enter startup options.", name); + free(name); + } + + if (getIntForKey( kCDROMOptionKey, &optionKey, &bootInfo->bootConfig )) + { + // The key specified is a special key. + } + else + { + // Default to F8. + optionKey = 0x4200; + } + + // If the timeout is zero then it must have been set above due to the + // early catch of F8 which means the user wants to set boot options + // which we ought to interpret as meaning he wants to boot the CD. + if (timeout != 0) { + key = GUI_countdown(prompt, kMenuTopRow, timeout); + } + else + { + key = optionKey; + } + + if (prompt != NULL) + { + free(prompt); + } + + clearScreenRows( kMenuTopRow, kMenuTopRow + 2 ); + + // Hit the option key ? + if (key == optionKey) + { + gBootMode &= ~kBootModeQuiet; + timeout = 0; + } + else + { + key = key & 0xFF; + + // Try booting hard disk if user pressed 'h' + if (biosDevIsCDROM(gBIOSDev) && key == 'h') + { + BVRef bvr; + + // Look at partitions hosting OS X other than the CD-ROM + for (bvr = bvChain; bvr; bvr=bvr->next) + { + if ((bvr->flags & kBVFlagSystemVolume) && bvr->biosdev != gBIOSDev) + { + gBootVolume = bvr; + } + } + } + goto done; + } + } + + if (gBootMode & kBootModeQuiet) + { + // No input allowed from user. + goto done; + } + + if (firstRun && timeout > 0 && GUI_countdown("Press any key to enter startup options.", kMenuTopRow, timeout) == 0) + { + // If the user is holding down a modifier key, + // enter safe mode. + if ((readKeyboardShiftFlags() & 0x0F) != 0) + { + gBootMode |= kBootModeSafe; + } + goto done; + } + + if (gDeviceCount) + { + // Allocate memory for an array of menu items. + menuItems = malloc(sizeof(MenuItem) * gDeviceCount); + if (menuItems == NULL) + { + goto done; + } + + // Associate a menu item for each BVRef. + for (bvr=bvChain, i=gDeviceCount-1, selectIndex=0; bvr; bvr=bvr->next) + { +// DBG("GUI menu for device %d\n", bvr->biosdev); + if (bvr->visible) + { + getBootVolumeDescription(bvr, menuItems[i].name, sizeof(menuItems[i].name) - 1, true); + menuItems[i].param = (void *) bvr; + if (bvr == menuBVR) + { + selectIndex = i; + } + i--; + } + } + } + + if (bootArgs->Video.v_display == GRAPHICS_MODE) + { + // redraw the background buffer + gui.logo.draw = true; + drawBackground(); + gui.devicelist.draw = true; + gui.redraw = true; + if (!(gBootMode & kBootModeQuiet)) + { + bool showBootBanner = false; + + // Check if "Boot Banner"=N switch is present in config file. + if (getBoolForKey(kBootBannerKey, &showBootBanner, &bootInfo->bootConfig) && showBootBanner) + { + // Display banner and show hardware info. + gprintf(&gui.screen, bootBanner + 1, (bootInfo->convmem + bootInfo->extmem) / 1024); + } + + // redraw background + memcpy(gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4); + } + } + else + { + // Clear screen and hide the blinking cursor. + clearScreenRows(kMenuTopRow, kMenuTopRow + 2); + changeCursor(0, kMenuTopRow, kCursorTypeHidden, 0); + } + + nextRow = kMenuTopRow; + showPrompt = true; + + if (gDeviceCount) + { + if( bootArgs->Video.v_display == VGA_TEXT_MODE ) + { + printf("Use \30\31 keys to select the startup volume."); + } + GUI_showMenu( menuItems, gDeviceCount, selectIndex, kMenuTopRow + 2, kMenuMaxItems ); + nextRow += min( gDeviceCount, kMenuMaxItems ) + 3; + } + + // Show the boot prompt. + showPrompt = (gDeviceCount == 0) || (menuBVR->flags & kBVFlagNativeBoot); + GUI_showBootPrompt( nextRow, showPrompt ); + + do { + if (bootArgs->Video.v_display == GRAPHICS_MODE) + { + // redraw background + memcpy( gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4 ); + // reset cursor co-ords + gui.debug.cursor = pos( gui.screen.width - 160 , 10 ); + } + key = getc(); + GUI_updateMenu( key, (void **) &menuBVR ); + newShowPrompt = (gDeviceCount == 0) || (menuBVR->flags & kBVFlagNativeBoot); + + if (newShowPrompt != showPrompt) + { + showPrompt = newShowPrompt; + GUI_showBootPrompt( nextRow, showPrompt ); + } + + if (showPrompt) + { + GUI_updateBootArgs(key); + } + + switch (key) + { + case kReturnKey: + if (gui.menu.draw) + { + key=0; + break; + } + if (*gBootArgs == '?') + { + char * argPtr = gBootArgs; + + // Skip the leading "?" character. + argPtr++; + getNextArg(&argPtr, booterCommand); + getNextArg(&argPtr, booterParam); + + /* + * TODO: this needs to be refactored. + */ + if (strcmp( booterCommand, "video" ) == 0) + { + if (bootArgs->Video.v_display == GRAPHICS_MODE) + { + showInfoBox(getVBEInfoString(), getVBEModeInfoString()); + } + else + { + printVBEModeInfo(); + } + } + else if ( strcmp( booterCommand, "memory" ) == 0) + { + if (bootArgs->Video.v_display == GRAPHICS_MODE ) + { + showInfoBox("Memory Map", getMemoryInfoString()); + } + else + { + printMemoryInfo(); + } + } + else if (strcmp(booterCommand, "lspci") == 0) + { + lspci(); + } + else if (strcmp(booterCommand, "more") == 0) + { + showTextFile(booterParam); + } + else if (strcmp(booterCommand, "rd") == 0) + { + processRAMDiskCommand(&argPtr, booterParam); + } + else if (strcmp(booterCommand, "norescan") == 0) + { + if (gEnableCDROMRescan) + { + gEnableCDROMRescan = false; + break; + } + } + else + { + showHelp(); + } + key = 0; + GUI_showBootPrompt(nextRow, showPrompt); + break; + } + gBootVolume = menuBVR; + setRootVolume(menuBVR); + gBIOSDev = menuBVR->biosdev; + break; + + case kEscapeKey: + clearBootArgs(); + break; + + case kF5Key: + // New behavior: + // Clear gBootVolume to restart the loop + // if the user enabled rescanning the optical drive. + // Otherwise boot the default boot volume. + if (gEnableCDROMRescan) + { + gBootVolume = NULL; + clearBootArgs(); + } + break; + + case kF10Key: + gScanSingleDrive = false; + scanDisks(gBIOSDev, &bvCount); + gBootVolume = NULL; + clearBootArgs(); + key = 0; + break; + + case kTabKey: + // New behavior: + // Switch between text & graphic interfaces + // Only Permitted if started in graphics interface + if (useGUI) + { + if (bootArgs->Video.v_display == GRAPHICS_MODE) + { + setVideoMode(VGA_TEXT_MODE, 0); + + setCursorPosition(0, 0, 0); + clearScreenRows(0, kScreenLastRow); + + // Display banner and show hardware info. + printf(bootBanner, (bootInfo->convmem + bootInfo->extmem) / 1024); + printf(getVBEInfoString()); + + clearScreenRows(kMenuTopRow, kMenuTopRow + 2); + changeCursor(0, kMenuTopRow, kCursorTypeHidden, 0); + + nextRow = kMenuTopRow; + showPrompt = true; + + if (gDeviceCount) + { + printf("Use \30\31 keys to select the startup volume."); + GUI_showMenu(menuItems, gDeviceCount, selectIndex, kMenuTopRow + 2, kMenuMaxItems); + nextRow += min(gDeviceCount, kMenuMaxItems) + 3; + } + + showPrompt = (gDeviceCount == 0) || (menuBVR->flags & kBVFlagNativeBoot); + GUI_showBootPrompt(nextRow, showPrompt); + //changeCursor( 0, kMenuTopRow, kCursorTypeUnderline, 0 ); + } + else + { + gui.redraw = true; + setVideoMode(GRAPHICS_MODE, 0); + updateVRAM(); + } + } + key = 0; + break; + + default: + key = 0; + break; + } + } while (0 == key); + +done: + if (bootArgs->Video.v_display == VGA_TEXT_MODE) + { + clearScreenRows(kMenuTopRow, kScreenLastRow); + changeCursor(0, kMenuTopRow, kCursorTypeUnderline, 0); + } + shouldboot = false; + gui.menu.draw = false; + if (menuItems) + { + free(menuItems); + menuItems = NULL; + } + return 0; +} + + + +int GUI_error(const char * fmt, ...) +{ + va_list ap; + gErrors = true; + va_start(ap, fmt); + + if (bootArgs->Video.v_display == VGA_TEXT_MODE) + { + prf(fmt, ap, putchar, 0); + } + else + { + vprf(fmt, ap); + } + + va_end(ap); + return(0); +} + +int GUI_verbose(const char * fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + if (gVerboseMode) + { + if (bootArgs->Video.v_display == VGA_TEXT_MODE) + { + prf(fmt, ap, putchar, 0); + } + else + { + vprf(fmt, ap); + } + } + + /* Kabyl: BooterLog */ + struct putc_info pi; + + if (!msgbuf) + return 0; + + if (((cursor - msgbuf) > (BOOTER_LOG_SIZE - SAFE_LOG_SIZE))) + return 0; + pi.str = cursor; + pi.last_str = 0; + prf(fmt, ap, sputc, &pi); + cursor += strlen((char *)cursor); + + + va_end(ap); + return(0); +} + +int GUI_printf(const char * fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + if (bootArgs->Video.v_display == VGA_TEXT_MODE) + { + prf(fmt, ap, putchar, 0); + } + else + { + vprf(fmt, ap); + } + + /* Kabyl: BooterLog */ + struct putc_info pi; + + if (!msgbuf) + return 0; + + if (((cursor - msgbuf) > (BOOTER_LOG_SIZE - SAFE_LOG_SIZE))) + return 0; + pi.str = cursor; + pi.last_str = 0; + prf(fmt, ap, sputc, &pi); + cursor += strlen((char *)cursor); + + va_end(ap); + return 0; +} + +void GUI_stop(const char * fmt, ...) +{ + va_list ap; + + printf("\n"); + va_start(ap, fmt); + + if (bootArgs->Video.v_display == VGA_TEXT_MODE) + { + prf(fmt, ap, putchar, 0); + } + else + { + vprf(fmt, ap); + } + va_end(ap); + + printf("\nThis is a non recoverable error! System HALTED!!!"); + halt(); + while (1); +} + +void GUI_showHelp(void) +{ + if (bootArgs->Video.v_display == GRAPHICS_MODE) { + showInfoBox("Help. Press q to quit.\n", (char *)BootHelp_txt); + } else { + showTextBuffer((char *)BootHelp_txt, BootHelp_txt_len); + } +} Index: branches/slice/rev749/modules/GUI/gui.h =================================================================== --- branches/slice/rev749/modules/GUI/gui.h (revision 0) +++ branches/slice/rev749/modules/GUI/gui.h (revision 1169) @@ -0,0 +1,154 @@ +/* + * gui.h + * + * + * Created by Jasmin Fazlic on 18.12.08. + * Copyright 2008/09 Jasmin Fazlic All rights reserved. + * Copyright 2008/09 iNDi All rights reserved. + * + */ + +#include "boot.h" +#include "bootstruct.h" +#include "graphics.h" +#include "graphic_utils.h" +#include "picopng.h" +#include "options.h" + +#ifndef __BOOT2_GUI_H +#define __BOOT2_GUI_H + +void showTextBuffer(char *buf, int size); +int GUI_initGraphicsMode (); +int GUI_countdown( const char * msg, int row, int timeout ); +#define CHARACTERS_COUNT 223 + +#define BOOT_NORMAL 0 +#define BOOT_VERBOSE 1 +#define BOOT_IGNORECACHE 2 +#define BOOT_SAFEMODE 6 +#define BOOT_SINGLEUSER 3 +#define DO_NOT_BOOT 4 +#define CLOSE_INFO_MENU 5 + +#define INFOMENU_NATIVEBOOT_START 1 +#define INFOMENU_NATIVEBOOT_END 3 + +#define MENU_SHOW_MEMORY_INFO 4 +#define MENU_SHOW_VIDEO_INFO 5 +#define MENU_SHOW_HELP 6 + +enum { + HorizontalLayout = 0, + VerticalLayout = 1, +}; + + +/* + * Menu item structure. + */ + +typedef struct { + position_t pos; + char *text; + bool enabled; + bool expandable; +} menuitem_t; + +/* + * Image structure. + */ +typedef struct { + pixmap_t *image; + char name[32]; +} image_t; + +/* + * Font structure. + */ +typedef struct { + uint16_t height; // Font Height + uint16_t width; // Font Width for monospace font only + pixmap_t *chars[CHARACTERS_COUNT]; +} font_t; + +/* + * Window structure. + */ +typedef struct +{ + position_t pos; // X,Y Position of window on screen + pixmap_t *pixmap; // Buffer + uint16_t width; // Width + uint16_t height; // Height + uint16_t hborder; // Horizontal border + uint16_t vborder; // Vertical border + uint16_t iconspacing; // Icon spacing + position_t cursor; // Text Cursor X,Y Position will be multiples of font width & height + uint32_t bgcolor; // Background color AARRGGBB + uint32_t fgcolor; // Foreground color AARRGGBB + uint32_t font_small_color; // Color for small font AARRGGBB + uint32_t font_console_color; // Color for consle font AARRGGBB + bool draw; // Draw flag +} window_t; + +/* + * gui structure + */ +typedef struct +{ + uint8_t maxdevices; // + uint8_t layout; // Horizontal or Vertical layout + + pixmap_t *backbuffer; // Off screen buffer + + window_t screen; // + window_t background; // Position of background graphic within screen + window_t logo; // Logo + window_t bootprompt; // Bootprompt Window + window_t devicelist; // Devicelist Window + window_t infobox; // Infobox Window + window_t menu; // Menu + + window_t progressbar; // Progress bar + window_t countdown; // Countdown text + + window_t debug; // Debug + + bool initialised; // Initialised + bool redraw; // Redraw flag +} gui_t; + + +extern gui_t gui; // gui structure + + +int initGUI(); +void drawBootGraphics(void); +void drawBackground(); + +void setupDeviceList(config_file_t *theme); +void drawDeviceIcon(BVRef device, pixmap_t *buffer, position_t p, bool isSelected); +void drawDeviceList(int start, int end, int selection); +void drawProgressBar(pixmap_t *blendInto, uint16_t width, position_t p, uint8_t progress); + +void showInfoBox(char *title, char *text); + +int dprintf( window_t * window, const char * fmt, ...); +int gprintf( window_t * window, const char * fmt, ...); +int vprf(const char * fmt, va_list ap); + +int drawInfoMenu(); +int updateInfoMenu(int key); +void drawInfoMenuItems(); + +void showGraphicBootPrompt(); +void clearGraphicBootPrompt(); +void updateGraphicBootPrompt(int key); + +void updateVRAM(); + +void drawStr(char *ch, font_t *font, pixmap_t *blendInto, position_t p); +void drawStrCenteredAt(char *ch, font_t *font, pixmap_t *blendInto, position_t p); + +#endif /* !__BOOT2_GUI_H */ Index: branches/slice/rev749/modules/GUI/appleboot.h =================================================================== --- branches/slice/rev749/modules/GUI/appleboot.h (revision 0) +++ branches/slice/rev749/modules/GUI/appleboot.h (revision 1169) @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 2.0 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * appleboot.h - Apple logo shown durring boot + * + * Copyright (c) 2002 Apple Computer, Inc. + * + * DRI: Josh de Cesare + */ + +#define kAppleBootWidth (128) +#define kAppleBootHeight (128) +#define kAppleBootOffset (0) +#define kAppleBootFrames (1) +#define kAppleBootFPS (0) +#define kAppleBootRLEBlocks (686) + +// The original data was 16K in size (128x128) and would make the booter +// cross a 64K segment boundary. boot0 cannot load more than 127 sectors +// without changes. To eiminate that complexity, the data was run length +// encoded to save space. The reduced size is 1372 bytes. + +const unsigned char gAppleBootPictRLE[] = +{ + 0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0x50, 0x01, 0x01, 0x02, 0x01, 0x17, + 0x01, 0x34, 0x01, 0x47, 0x03, 0x50, 0x01, 0x13, 0x76, 0x01, 0x01, 0x03, + 0x01, 0x20, 0x01, 0x40, 0x06, 0x50, 0x01, 0x13, 0x75, 0x01, 0x01, 0x1a, + 0x01, 0x42, 0x07, 0x50, 0x01, 0xfa, 0x01, 0x0a, 0x73, 0x01, 0x01, 0x07, + 0x01, 0x34, 0x09, 0x50, 0x01, 0x43, 0x01, 0x02, 0x72, 0x01, 0x01, 0x0e, + 0x01, 0x43, 0x0a, 0x50, 0x01, 0x36, 0x72, 0x01, 0x01, 0x14, 0x01, 0x4a, + 0x0b, 0x50, 0x01, 0x20, 0x71, 0x01, 0x01, 0x12, 0x01, 0x4b, 0x0b, 0x50, + 0x01, 0x4d, 0x01, 0x0b, 0x70, 0x01, 0x01, 0x0b, 0x01, 0x48, 0x0c, 0x50, + 0x01, 0xf9, 0x70, 0x01, 0x01, 0x03, 0x01, 0x3e, 0x0d, 0x50, 0x01, 0x1f, + 0x70, 0x01, 0x01, 0x2f, 0x0d, 0x50, 0x01, 0x48, 0x01, 0x06, 0x6f, 0x01, + 0x01, 0x15, 0x01, 0x4f, 0x0d, 0x50, 0x01, 0x27, 0x6f, 0x01, 0x01, 0x02, + 0x01, 0x3f, 0x0d, 0x50, 0x01, 0x45, 0x01, 0xf7, 0x6f, 0x01, 0x01, 0x1d, + 0x0e, 0x50, 0x01, 0x19, 0x6f, 0x01, 0x01, 0x02, 0x01, 0x40, 0x0d, 0x50, + 0x01, 0x2f, 0x70, 0x01, 0x01, 0x15, 0x0d, 0x50, 0x01, 0x3b, 0x01, 0x03, + 0x70, 0x01, 0x01, 0x34, 0x0c, 0x50, 0x01, 0x3f, 0x01, 0x07, 0x70, 0x01, + 0x01, 0xf7, 0x01, 0x47, 0x0b, 0x50, 0x01, 0xf9, 0x01, 0x07, 0x71, 0x01, + 0x01, 0x14, 0x0b, 0x50, 0x01, 0x36, 0x01, 0xf7, 0x72, 0x01, 0x01, 0x24, + 0x09, 0x50, 0x01, 0x4d, 0x01, 0x28, 0x74, 0x01, 0x01, 0x33, 0x08, 0x50, + 0x01, 0x3f, 0x01, 0x14, 0x75, 0x01, 0x01, 0x3a, 0x06, 0x50, 0x01, 0x41, + 0x01, 0x1f, 0x01, 0x02, 0x76, 0x01, 0x01, 0x3a, 0x03, 0x50, 0x01, 0x48, + 0x01, 0x35, 0x01, 0x17, 0x01, 0x02, 0x78, 0x01, 0x01, 0x15, 0x01, 0x33, + 0x01, 0x27, 0x01, 0x15, 0x01, 0xf7, 0x67, 0x01, 0x01, 0x02, 0x01, 0x08, + 0x01, 0x0e, 0x01, 0x13, 0x01, 0x14, 0x01, 0x12, 0x01, 0x0d, 0x01, 0x06, + 0x01, 0x02, 0x1c, 0x01, 0x01, 0x04, 0x01, 0x0b, 0x01, 0x12, 0x01, 0x17, + 0x01, 0x19, 0x01, 0x15, 0x01, 0x11, 0x01, 0x08, 0x01, 0x02, 0x4e, 0x01, + 0x01, 0x02, 0x01, 0x11, 0x01, 0x26, 0x01, 0x39, 0x01, 0x44, 0x01, 0x4c, + 0x01, 0x4f, 0x02, 0x50, 0x01, 0x4f, 0x01, 0x4d, 0x01, 0x4a, 0x01, 0x3f, + 0x01, 0x31, 0x01, 0x19, 0x01, 0xf7, 0x15, 0x01, 0x01, 0x0b, 0x01, 0x1c, + 0x01, 0x2e, 0x01, 0xf9, 0x01, 0x46, 0x01, 0x4d, 0x04, 0x50, 0x01, 0x4f, + 0x01, 0x4b, 0x01, 0x42, 0x01, 0x34, 0x01, 0x1f, 0x01, 0x0a, 0x49, 0x01, + 0x01, 0xf7, 0x01, 0x21, 0x01, 0x3f, 0x01, 0x4f, 0x0d, 0x50, 0x01, 0x47, + 0x01, 0x2d, 0x01, 0x0d, 0x10, 0x01, 0x01, 0x0d, 0x01, 0x25, 0x01, 0x3d, + 0x01, 0xfa, 0x0e, 0x50, 0x01, 0x4c, 0x01, 0x37, 0x01, 0x15, 0x45, 0x01, + 0x01, 0x04, 0x01, 0x25, 0x01, 0x45, 0x12, 0x50, 0x01, 0x4d, 0x01, 0x39, + 0x01, 0x19, 0x01, 0x02, 0x0a, 0x01, 0x01, 0x09, 0x01, 0x21, 0x01, 0xf9, + 0x01, 0x4d, 0x14, 0x50, 0x01, 0xf9, 0x01, 0x15, 0x42, 0x01, 0x01, 0x17, + 0x01, 0x42, 0x17, 0x50, 0x01, 0x42, 0x01, 0x27, 0x01, 0x0e, 0x01, 0x02, + 0x03, 0x01, 0x01, 0x02, 0x01, 0x0b, 0x01, 0x1f, 0x01, 0x38, 0x01, 0x4b, + 0x19, 0x50, 0x01, 0x33, 0x01, 0x06, 0x3e, 0x01, 0x01, 0x03, 0x01, 0x2e, + 0x1b, 0x50, 0x01, 0x4d, 0x01, 0x43, 0x01, 0x3a, 0x01, 0x37, 0x01, 0x3a, + 0x01, 0x42, 0x01, 0x4d, 0x1d, 0x50, 0x01, 0x42, 0x01, 0x0e, 0x3c, 0x01, + 0x01, 0x0a, 0x01, 0xf9, 0x41, 0x50, 0x01, 0x48, 0x01, 0x13, 0x3a, 0x01, + 0x01, 0x0d, 0x01, 0x45, 0x43, 0x50, 0x01, 0x4b, 0x01, 0x12, 0x38, 0x01, + 0x01, 0x10, 0x01, 0x48, 0x45, 0x50, 0x01, 0x48, 0x01, 0x0b, 0x36, 0x01, + 0x01, 0x0c, 0x01, 0x48, 0x47, 0x50, 0x01, 0x3d, 0x01, 0x03, 0x34, 0x01, + 0x01, 0x07, 0x01, 0x42, 0x49, 0x50, 0x01, 0x21, 0x34, 0x01, 0x01, 0x37, + 0x49, 0x50, 0x01, 0x42, 0x01, 0x12, 0x33, 0x01, 0x01, 0x22, 0x49, 0x50, + 0x01, 0x34, 0x01, 0xf7, 0x33, 0x01, 0x01, 0x0b, 0x01, 0x4b, 0x48, 0x50, + 0x01, 0x2c, 0x35, 0x01, 0x01, 0x36, 0x48, 0x50, 0x01, 0x29, 0x35, 0x01, + 0x01, 0x11, 0x01, 0x4f, 0x47, 0x50, 0x01, 0x2e, 0x36, 0x01, 0x01, 0x36, + 0x47, 0x50, 0x01, 0x3a, 0x01, 0x02, 0x35, 0x01, 0x01, 0x0b, 0x01, 0xfa, + 0x46, 0x50, 0x01, 0x46, 0x01, 0x08, 0x36, 0x01, 0x01, 0x26, 0x46, 0x50, + 0x01, 0x4e, 0x01, 0x15, 0x36, 0x01, 0x01, 0x02, 0x01, 0x40, 0x46, 0x50, + 0x01, 0x31, 0x37, 0x01, 0x01, 0x0e, 0x01, 0x4e, 0x45, 0x50, 0x01, 0x49, + 0x01, 0x08, 0x37, 0x01, 0x01, 0x25, 0x46, 0x50, 0x01, 0x29, 0x38, 0x01, + 0x01, 0x39, 0x45, 0x50, 0x01, 0x4c, 0x01, 0x0a, 0x37, 0x01, 0x01, 0xf7, + 0x01, 0x47, 0x45, 0x50, 0x01, 0x3a, 0x38, 0x01, 0x01, 0x10, 0x01, 0x4f, + 0x45, 0x50, 0x01, 0x22, 0x38, 0x01, 0x01, 0x1d, 0x46, 0x50, 0x01, 0x12, + 0x38, 0x01, 0x01, 0x29, 0x45, 0x50, 0x01, 0x4b, 0x01, 0x07, 0x38, 0x01, + 0x01, 0x36, 0x45, 0x50, 0x01, 0x42, 0x01, 0x02, 0x38, 0x01, 0x01, 0xf9, + 0x45, 0x50, 0x01, 0x3e, 0x39, 0x01, 0x01, 0x42, 0x45, 0x50, 0x01, 0x3c, + 0x39, 0x01, 0x01, 0x46, 0x45, 0x50, 0x01, 0x3b, 0x39, 0x01, 0x01, 0x48, + 0x45, 0x50, 0x01, 0xf9, 0x39, 0x01, 0x01, 0x48, 0x45, 0x50, 0x01, 0x3f, + 0x01, 0x02, 0x38, 0x01, 0x01, 0x46, 0x45, 0x50, 0x01, 0x48, 0x01, 0xf7, + 0x38, 0x01, 0x01, 0x43, 0x45, 0x50, 0x01, 0x4e, 0x01, 0x0e, 0x38, 0x01, + 0x01, 0x3f, 0x46, 0x50, 0x01, 0x1c, 0x38, 0x01, 0x01, 0x3a, 0x46, 0x50, + 0x01, 0x33, 0x38, 0x01, 0x01, 0x34, 0x46, 0x50, 0x01, 0x46, 0x01, 0x04, + 0x37, 0x01, 0x01, 0x2c, 0x47, 0x50, 0x01, 0x19, 0x37, 0x01, 0x01, 0x1f, + 0x47, 0x50, 0x01, 0x3a, 0x37, 0x01, 0x01, 0x15, 0x47, 0x50, 0x01, 0x4e, + 0x01, 0x11, 0x36, 0x01, 0x01, 0x0a, 0x01, 0xfa, 0x47, 0x50, 0x01, 0x37, + 0x36, 0x01, 0x01, 0x02, 0x01, 0x42, 0x47, 0x50, 0x01, 0x4f, 0x01, 0x15, + 0x36, 0x01, 0x01, 0x37, 0x48, 0x50, 0x01, 0x42, 0x01, 0x04, 0x35, 0x01, + 0x01, 0x25, 0x49, 0x50, 0x01, 0x2c, 0x35, 0x01, 0x01, 0x13, 0x49, 0x50, + 0x01, 0x4e, 0x01, 0x15, 0x34, 0x01, 0x01, 0xf7, 0x01, 0x47, 0x49, 0x50, + 0x01, 0x48, 0x01, 0x0b, 0x34, 0x01, 0x01, 0x37, 0x4a, 0x50, 0x01, 0x44, + 0x01, 0x0a, 0x33, 0x01, 0x01, 0x1f, 0x4b, 0x50, 0x01, 0x44, 0x01, 0x0d, + 0x32, 0x01, 0x01, 0x0a, 0x01, 0xfa, 0x4b, 0x50, 0x01, 0x48, 0x01, 0x17, + 0x32, 0x01, 0x01, 0x3a, 0x4c, 0x50, 0x01, 0x4f, 0x01, 0x2c, 0x01, 0x04, + 0x30, 0x01, 0x01, 0x1f, 0x4e, 0x50, 0x01, 0x41, 0x01, 0x19, 0x2f, 0x01, + 0x01, 0x07, 0x01, 0x4a, 0x4e, 0x50, 0x01, 0x44, 0x30, 0x01, 0x01, 0x33, + 0x4e, 0x50, 0x01, 0x36, 0x30, 0x01, 0x01, 0x14, 0x4e, 0x50, 0x01, 0x1f, + 0x30, 0x01, 0x01, 0x02, 0x01, 0x3f, 0x4c, 0x50, 0x01, 0x4d, 0x01, 0x0b, + 0x31, 0x01, 0x01, 0x1e, 0x4c, 0x50, 0x01, 0x3c, 0x32, 0x01, 0x01, 0x04, + 0x01, 0x44, 0x4b, 0x50, 0x01, 0x20, 0x33, 0x01, 0x01, 0x20, 0x4a, 0x50, + 0x01, 0x4a, 0x01, 0x07, 0x33, 0x01, 0x01, 0x04, 0x01, 0x43, 0x49, 0x50, + 0x01, 0x30, 0x35, 0x01, 0x01, 0x1c, 0x48, 0x50, 0x01, 0x4d, 0x01, 0x0e, + 0x35, 0x01, 0x01, 0x02, 0x01, 0x3e, 0x47, 0x50, 0x01, 0x36, 0x37, 0x01, + 0x01, 0x14, 0x01, 0x4f, 0x45, 0x50, 0x01, 0x4d, 0x01, 0x0e, 0x38, 0x01, + 0x01, 0x32, 0x45, 0x50, 0x01, 0x33, 0x39, 0x01, 0x01, 0x07, 0x01, 0x47, + 0x43, 0x50, 0x01, 0x4b, 0x01, 0x0b, 0x3a, 0x01, 0x01, 0x1c, 0x43, 0x50, + 0x01, 0x26, 0x3c, 0x01, 0x01, 0x37, 0x41, 0x50, 0x01, 0x41, 0x01, 0x04, + 0x3c, 0x01, 0x01, 0x08, 0x01, 0x48, 0x3f, 0x50, 0x01, 0x4e, 0x01, 0x13, + 0x3e, 0x01, 0x01, 0x19, 0x3f, 0x50, 0x01, 0x2d, 0x40, 0x01, 0x01, 0x2e, + 0x3d, 0x50, 0x01, 0x3f, 0x01, 0x03, 0x40, 0x01, 0x01, 0x03, 0x01, 0xf9, + 0x3b, 0x50, 0x01, 0x4a, 0x01, 0x0d, 0x42, 0x01, 0x01, 0x09, 0x01, 0x46, + 0x39, 0x50, 0x01, 0x4e, 0x01, 0x19, 0x44, 0x01, 0x01, 0x11, 0x01, 0x4b, + 0x38, 0x50, 0x01, 0x25, 0x46, 0x01, 0x01, 0x17, 0x01, 0x4d, 0x36, 0x50, + 0x01, 0x2e, 0x48, 0x01, 0x01, 0x1b, 0x01, 0x4d, 0x34, 0x50, 0x01, 0x31, + 0x4a, 0x01, 0x01, 0x17, 0x01, 0x4a, 0x14, 0x50, 0x01, 0x4d, 0x01, 0x44, + 0x01, 0x3b, 0x01, 0x34, 0x01, 0x2e, 0x01, 0x2c, 0x01, 0x2e, 0x01, 0x35, + 0x01, 0x3e, 0x01, 0x4a, 0x14, 0x50, 0x01, 0x2e, 0x4c, 0x01, 0x01, 0x0e, + 0x01, 0x41, 0x10, 0x50, 0x01, 0x4a, 0x01, 0x37, 0x01, 0x1f, 0x01, 0x0c, + 0x01, 0x03, 0x07, 0x01, 0x01, 0x06, 0x01, 0x15, 0x01, 0x2d, 0x01, 0x41, + 0x0f, 0x50, 0x01, 0x4a, 0x01, 0x1f, 0x4e, 0x01, 0x01, 0xf7, 0x01, 0x2e, + 0x01, 0xfa, 0x0b, 0x50, 0x01, 0x4f, 0x01, 0xf9, 0x01, 0x1e, 0x01, 0x07, + 0x0e, 0x01, 0x01, 0x02, 0x01, 0x14, 0x01, 0x31, 0x01, 0x48, 0x0b, 0x50, + 0x01, 0x37, 0x01, 0x0c, 0x51, 0x01, 0x01, 0x0d, 0x01, 0x2f, 0x01, 0x45, + 0x01, 0x4f, 0x05, 0x50, 0x01, 0x4f, 0x01, 0x43, 0x01, 0x2e, 0x01, 0x11, + 0x14, 0x01, 0x01, 0x07, 0x01, 0x1f, 0x01, 0x3c, 0x01, 0x4c, 0x04, 0x50, + 0x01, 0x4f, 0x01, 0x46, 0x01, 0x33, 0x01, 0x13, 0x55, 0x01, 0x01, 0x04, + 0x01, 0x12, 0x01, 0x1f, 0x01, 0x26, 0x01, 0x28, 0x01, 0x26, 0x01, 0x1e, + 0x01, 0x10, 0x01, 0x02, 0x19, 0x01, 0x01, 0x09, 0x01, 0x16, 0x01, 0x1e, + 0x01, 0x1f, 0x01, 0x1c, 0x01, 0x11, 0x01, 0x04, 0xff, 0x01, 0xff, 0x01, + 0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01, + 0xff, 0x01, 0xb3, 0x01 +}; Index: branches/slice/rev749/modules/GUI/Makefile =================================================================== --- branches/slice/rev749/modules/GUI/Makefile (revision 0) +++ branches/slice/rev749/modules/GUI/Makefile (revision 1169) @@ -0,0 +1,72 @@ +MODULE_NAME = GUI +MODULE_VERSION = "1.0.0" +MODULE_COMPAT_VERSION = "1.0.0" +MODULE_START = _$(MODULE_NAME)_start +MODULE_DEPENDENCIES = Resolution + +DIR = GUI + +MODULE_OBJS = GUI_module.o gui.o picopng.o graphic_utils.o + +THEME = embed +THEMEDIR = ../../../artwork/themes/$(THEME) + +OPTIM = -Os -Oz +DEBUG = -DNOTHING +#DEBUG = -DDEBUG_HELLO_WORLD=1 +CFLAGS = $(RC_CFLAGS) $(OPTIM) $(MORECPP) -arch i386 -g -Wmost \ + -D__ARCHITECTURE__=\"i386\" -DSAIO_INTERNAL_USER \ + -DRCZ_COMPRESSED_FILE_SUPPORT $(DEBUG) \ + -fno-builtin $(OMIT_FRAME_POINTER_CFLAG) \ + -mpreferred-stack-boundary=2 -fno-align-functions -fno-stack-protector \ + -march=pentium4 -msse2 -mfpmath=sse -msoft-float -fno-common + +DEFINES= +CONFIG = hd +INC = -I. -I.. -I$(SYMROOT) -I$(UTILDIR) -I$(LIBSADIR) -I$(LIBSAIODIR) -I$(BOOT2DIR) +LIBS= + +VPATH = $(OBJROOT):$(SYMROOT) + +SFILES = +CFILES = +HFILES = appleboot.h +EXPORTED_HFILES = +INSTALLED_HFILES = +OTHERFILES = Makefile +ALLSRC = $(SFILES) $(CFILES) \ + $(HFILES) $(OTHERFILES) +DIRS_NEEDED = $(OBJROOT) $(SYMROOT) + +all optionrom: dylib + +embedtheme: CFLAGS += -DEMBED_THEME +embedtheme: art.h all + +art.h: + @if [ "$(PNGCRUSH)" ]; then \ + echo "optimizing art files ...\n$(PNGCRUSH) $(PNGOPTIONS) artwork/$(THEME)"; \ + cd $(THEMEDIR) && find . -name '*.png' -exec $(PNGCRUSH) -q $(PNGOPTIONS) -d $(SYMROOT)/embed {} \;; \ + cp theme.plist $(SYMROOT)/embed; \ + else \ + cp -R $(THEMEDIR) $(SYMROOT)/embed; \ + fi; + @echo "#ifndef __BOOT2_ART_H" >> $(SYMROOT)/art.h + @echo "#define __BOOT2_ART_H" >> $(SYMROOT)/art.h + @cd $(SYMROOT)/embed && find . -name 'theme.plist' -exec xxd -i >> $(SYMROOT)/art.h {} \; + @cd $(SYMROOT)/embed && find . -name '*.png' -exec xxd -i >> $(SYMROOT)/art.h {} \; + + @echo "typedef struct {" >> $(SYMROOT)/art.h + @echo " char name[32];" >> $(SYMROOT)/art.h + @echo " unsigned char *pngdata;" >> $(SYMROOT)/art.h + @echo " unsigned int *length;" >> $(SYMROOT)/art.h + @echo "} embeddedpng_t;" >> $(SYMROOT)/art.h + @echo "" >> $(SYMROOT)/art.h + @echo "embeddedpng_t embeddedImages[] = {" >> $(SYMROOT)/art.h + @cd $(SYMROOT)/embed && find . -name '*.png' | sort | cut -f 2 -d '/' | cut -f 1 -d '.' | \ + awk '{ printf "\t{.name = \"%s\", .pngdata = __%s_png, .length = &__%s_png_len},\n", $$1, $$1, $$1 }' >> $(SYMROOT)/art.h + @echo "};" >> $(SYMROOT)/art.h + + @echo "#endif /* !__BOOT2_ART_H */" >> $(SYMROOT)/art.h ;\ + +include ../MakeInc.dir \ No newline at end of file Index: branches/slice/rev749/modules/GUI/graphic_utils.c =================================================================== --- branches/slice/rev749/modules/GUI/graphic_utils.c (revision 0) +++ branches/slice/rev749/modules/GUI/graphic_utils.c (revision 1169) @@ -0,0 +1,439 @@ + +/* Graphic utility functions and data types + * Prashant Vaibhav (C) 12/12/2008 + * Chameleon + */ +#include "boot.h" +#include "graphic_utils.h" +#include "graphics.h" +#include "vbe.h" +#include "gui.h" + +#define VIDEO(x) (bootArgs->Video.v_ ## x) + +#define MIN(x, y) ((x) < (y) ? (x) : (y)) + + + +int +convertImage( unsigned short width, + unsigned short height, + const unsigned char *imageData, + unsigned char **newImageData ) +{ + int cnt; + unsigned char *img = 0; + unsigned short *img16; + unsigned long *img32; + + switch ( VIDEO(depth) ) { + case 16 : + img16 = malloc(width * height * 2); + if ( !img16 ) break; + for (cnt = 0; cnt < (width * height); cnt++) + img16[cnt] = lookUpCLUTIndex(imageData[cnt], 16); + img = (unsigned char *)img16; + break; + + case 32 : + img32 = malloc(width * height * 4); + if ( !img32 ) break; + for (cnt = 0; cnt < (width * height); cnt++) + img32[cnt] = lookUpCLUTIndex(imageData[cnt], 32); + img = (unsigned char *)img32; + break; + + default : + img = malloc(width * height); + bcopy(imageData, img, width * height); + break; + } + *newImageData = img; + return 0; +} + + +//========================================================================== +// +void +printVBEModeInfo() +{ + VBEInfoBlock vbeInfo; + unsigned short * modePtr; + VBEModeInfoBlock modeInfo; + int err; + int line; + + bzero( &vbeInfo, sizeof(vbeInfo) ); + strcpy( (char*)&vbeInfo, "VBE2" ); + err = getVBEInfo( &vbeInfo ); + if ( err != errSuccess ) + return; + + line = 0; + + // Activate and clear page 1 + setActiveDisplayPage(1); + clearScreenRows(0, 24); + setCursorPosition( 0, 0, 1 ); + + printf("Video modes supported:\n", VBEDecodeFP(const char *, vbeInfo.OEMStringPtr)); + + // Loop through the mode list, and find the matching mode. + + for ( modePtr = VBEDecodeFP( unsigned short *, vbeInfo.VideoModePtr ); + *modePtr != modeEndOfList; modePtr++ ) + { + // Get mode information. + + bzero( &modeInfo, sizeof(modeInfo) ); + err = getVBEModeInfo( *modePtr, &modeInfo ); + if ( err != errSuccess ) + { + continue; + } + + printf("Mode %x: %dx%dx%d mm:%d attr:%x\n", + *modePtr, modeInfo.XResolution, modeInfo.YResolution, + modeInfo.BitsPerPixel, modeInfo.MemoryModel, + modeInfo.ModeAttributes); + + if (line++ >= 20) { + pause(); + line = 0; + clearScreenRows(0, 24); + setCursorPosition( 0, 0, 1 ); + } + } + if (line != 0) { + pause(); + } + setActiveDisplayPage(0); +} + + + +char *getVBEModeInfoString() +{ + VBEInfoBlock vbeInfo; + unsigned short * modePtr; + VBEModeInfoBlock modeInfo; + int err; + + bzero( &vbeInfo, sizeof(vbeInfo) ); + strcpy( (char*)&vbeInfo, "VBE2" ); + err = getVBEInfo( &vbeInfo ); + if ( err != errSuccess ) + return 0; + + char *buff=malloc(sizeof(char)*3072); + if(!buff) return 0; + + // Loop through the mode list, and find the matching mode. + for ( modePtr = VBEDecodeFP( unsigned short *, vbeInfo.VideoModePtr ); + *modePtr != modeEndOfList; modePtr++ ) + { + // Get mode information. + + bzero( &modeInfo, sizeof(modeInfo) ); + err = getVBEModeInfo( *modePtr, &modeInfo ); + if ( err != errSuccess ) + { + continue; + } + + sprintf(buff+strlen(buff), "Mode %x: %dx%dx%d mm:%d attr:%x\n", + *modePtr, modeInfo.XResolution, modeInfo.YResolution, + modeInfo.BitsPerPixel, modeInfo.MemoryModel, + modeInfo.ModeAttributes); + + } + return buff; +} + + +void blendImage(uint16_t x, uint16_t y, uint16_t width, uint16_t height, + uint8_t *data) +{ + uint16_t drawWidth; + uint8_t *vram = (uint8_t *) VIDEO(baseAddr) + VIDEO(rowBytes) * y + 4 * x; + + drawWidth = MIN(width, VIDEO(width) - x); + height = MIN(height, VIDEO(height) - y); + while (height--) { + switch (VIDEO (depth)) + { + case 32: /* Optimized version*/ + { + uint32_t s; uint32_t* d; // Source (img) and destination (bkgd) pixels + uint32_t a; // Alpha + uint32_t dstrb, dstg, srcrb, srcg, drb, dg, rb, g, tempB; // Intermediate variables + uint16_t pos; + + for (pos = 0; pos < drawWidth * 4; pos += 4) { + // Fast pseudo-vector alpha blending, adapted from: http://www.stereopsis.com/doubleblend.html + s = *((uint32_t*) (data + pos)); + d = (uint32_t*) (vram + pos); + + // Flip B and R in source + // TODO: use XCHG and inline assembly to do this in a faster, saner way + tempB = (s & 0xFF0000); // save B + s = (s & 0xFF00FFFF) | ((s & 0xFF) << 16); // put R in B + s = (s & 0xFFFFFF00) | (tempB >> 16); // put B in R + + a = (s >> 24) + 1; + + dstrb = *d & 0xFF00FF; dstg = *d & 0xFF00; + srcrb = s & 0xFF00FF; srcg = s & 0xFF00; + + drb = srcrb - dstrb; + dg = srcg - dstg; + drb *= a; dg *= a; + drb >>= 8; dg >>= 8; + + rb = (drb + dstrb) & 0xFF00FF; + g = (dg + dstg) & 0xFF00; + + *d = rb | g; + } + } + break; + + default: /*Universal version*/ + { + uint32_t s; + uint32_t a; // Alpha + uint32_t dr, dg, db, sr, sg, sb; // Intermediate variables + uint16_t pos; + int bpp = (VIDEO (depth) + 7)/8; + + for (pos = 0; pos < drawWidth; pos ++) { + // Fast pseudo-vector alpha blending, adapted from: http://www.stereopsis.com/doubleblend.html + s = *((uint32_t*) (data + 4*pos)); + + sb = (s & 0xFF0000) >> 16; + sg = (s & 0xFF00) >> 8; + sr = (s & 0xFF); + + a = (s >> 24) + 1; + + switch (VIDEO (depth)) + { + case 24: + db = ((*(uint32_t *)(vram + bpp*pos))&0xff); + dg = ((*(uint32_t *)(vram + bpp*pos))&0xff00)>>8; + dr = ((*(uint32_t *)(vram + bpp*pos))&0xff0000)>>16; + break; + case 16://16-bit seems to be 15-bit + /* db = ((*(uint16_t *)(vram + bpp*pos))&0x1f)<<3; + dg = ((*(uint16_t *)(vram + bpp*pos))&0x07e0)>>3; + dr = ((*(uint16_t *)(vram + bpp*pos))&0xf800)>>8; + break; */ + case 15: + db = ((*(uint16_t *)(vram + bpp*pos))&0x1f)<<3; + dg = ((*(uint16_t *)(vram + bpp*pos))&0x03e0)>>2; + dr = ((*(uint16_t *)(vram + bpp*pos))&0x7c00)>>7; + break; + default: + return; + } + + dr = (((sr - dr) * a) >> 8) + dr; + dg = (((sg - dg) * a) >> 8) + dg; + db = (((sb - db) * a) >> 8) + db; + switch (VIDEO (depth)) + { + case 24: + *(uint32_t *)(vram + bpp*pos) = (*(uint32_t *)(vram + bpp*pos) &0xff000000) + | (db&0xff) | ((dg&0xff)<<8) | ((dr&0xff)<<16); + break; + case 16: + // *(uint16_t *)(vram + bpp*pos) = ((db&0xf8)>>3) | ((dg&0xfc)<<3) | ((dr&0xf8)<<8); + // break; + case 15: + *(uint16_t *)(vram + bpp*pos) = ((db&0xf8)>>3) | ((dg&0xf8)<<2) | ((dr&0xf8)<<7); + break; + } + + } + } + break; + } + vram += VIDEO(rowBytes); + data += width * 4; + } +} + +void drawCheckerBoard() +{ + uint32_t *vram = (uint32_t *) VIDEO(baseAddr); + uint16_t x, y; + uint8_t color; + + for (y = 0; y < VIDEO(height); y++, vram += VIDEO(width)) { + for (x = 0; x < VIDEO(width); x++) { + color = 204 + 51 * (((x / 8) % 2) == ((y / 8) % 2)); + vram[x] = (color << 16) | (color << 8) | color; + } + } +} + + +//========================================================================== +// drawDataRectangle + +void drawDataRectangle( unsigned short x, + unsigned short y, + unsigned short width, + unsigned short height, + unsigned char * data ) +{ + unsigned short drawWidth; + long pixelBytes = VIDEO(depth) / 8; + unsigned char * vram = (unsigned char *) VIDEO(baseAddr) + + VIDEO(rowBytes) * y + pixelBytes * x; + + drawWidth = MIN(width, VIDEO(width) - x); + height = MIN(height, VIDEO(height) - y); + while ( height-- ) { + bcopy( data, vram, drawWidth * pixelBytes ); + vram += VIDEO(rowBytes); + data += width * pixelBytes; + } +} + + + +unsigned short getGraphicModeParams(unsigned long params[]) { + + params[3] = 0; + + VBEModeInfoBlock minfo; + + unsigned short vesaVersion; + unsigned short mode = modeEndOfList; + + getNumberArrayFromProperty( kGraphicsModeKey, params, 4); + + mode = getVESAModeWithProperties( params[0], params[1], params[2], + maColorModeBit | + maModeIsSupportedBit | + maGraphicsModeBit | + maLinearFrameBufferAvailBit, + 0, + &minfo, &vesaVersion ); + + params[0] = minfo.XResolution; + params[1] = minfo.YResolution; + params[2] = 32; + return mode; +} + + +//========================================================================== +// getVBEInfoString + +char *getVBEInfoString() +{ + VBEInfoBlock vbeInfo; + int err, small; + char *buff = malloc(sizeof(char)*256); + if(!buff) return 0; + + bzero( &vbeInfo, sizeof(vbeInfo) ); + strcpy( (char*)&vbeInfo, "VBE2" ); + err = getVBEInfo( &vbeInfo ); + if (err != errSuccess) + return 0; + + if ( strncmp( (char *)vbeInfo.VESASignature, "VESA", 4 ) ) + return 0; + + small = (vbeInfo.TotalMemory < 16); + + sprintf(buff, "VESA v%d.%d %d%s (%s)\n", + vbeInfo.VESAVersion >> 8, + vbeInfo.VESAVersion & 0xf, + small ? (vbeInfo.TotalMemory * 64) : (vbeInfo.TotalMemory / 16), + small ? "KB" : "MB", + VBEDecodeFP(const char *, vbeInfo.OEMStringPtr) ); + + return buff; +} + + +void blend( const pixmap_t *blendThis, // Source image + pixmap_t *blendInto, // Dest image + const position_t position) // Where to place the source image +{ + uint16_t sx, sy, dx, dy; + uint32_t dstrb, dstag, srcrb, srcag, drb, dag, rb, ag, alpha; + + uint16_t width = (blendThis->width + position.x < blendInto->width) ? blendThis->width: blendInto->width-position.x; + uint16_t height = (blendThis->height + position.y < blendInto->height) ? blendThis->height: blendInto->height-position.y; + + for (dy = position.y, sy = 0; sy < height; dy++, sy++) + { + for (dx = position.x, sx = 0; sx < width; dx++, sx++) + { + alpha = (pixel(blendThis, sx, sy).ch.a); + + /* Skip blending for fully transparent pixel */ + if (alpha == 0) continue; + + /* For fully opaque pixel, there is no need to interpolate */ + if (alpha == 255) + { + pixel(blendInto, dx, dy).value = pixel(blendThis, sx, sy).value; + continue; + } + + /* For semi-transparent pixels, do a full blend */ + //alpha++ + /* This is needed to spread the alpha over [0..256] instead of [0..255] + Boundary conditions were handled above */ + dstrb = pixel(blendInto, dx, dy).value & 0xFF00FF; + dstag = (pixel(blendInto, dx, dy).value >> 8) & 0xFF00FF; + srcrb = pixel(blendThis, sx, sy).value & 0xFF00FF; + srcag = (pixel(blendThis, sx, sy).value >> 8) & 0xFF00FF; + drb = srcrb - dstrb; + dag = srcag - dstag; + drb *= alpha; dag *= alpha; + drb >>= 8; dag >>= 8; + rb = (drb + dstrb) & 0x00FF00FF; + ag = ((dag + dstag) << 8) & 0xFF00FF00; + pixel(blendInto, dx, dy).value = (rb | ag); + } + } +} + +position_t centeredIn( const pixmap_t *background, const pixmap_t *toCenter ) +{ + position_t centered; + centered.x = ( background->width - toCenter->width ) / 2; + centered.y = ( background->height - toCenter->height ) / 2; + return centered; +} + +position_t centeredAt( const pixmap_t *pixmap, const position_t center ) +{ + position_t topleft; + topleft.x = center.x - (pixmap->width / 2); + topleft.y = center.y - (pixmap->height / 2); + return topleft; +} + +position_t pos(const uint16_t x, const uint16_t y) { position_t p; p.x = x; p.y = y; return p; } + +void flipRB(pixmap_t *p) +{ + //if(testForQemu()) return; + + uint32_t x; + register uint8_t tempB; + for (x = 0; x < (p->height) * (p->width) ; x++) { + tempB = (p->pixels[x]).ch.b; + (p->pixels[x]).ch.b = (p->pixels[x]).ch.r; + (p->pixels[x]).ch.r = tempB; + } +} Index: branches/slice/rev749/modules/MakeInc.dir =================================================================== --- branches/slice/rev749/modules/MakeInc.dir (revision 0) +++ branches/slice/rev749/modules/MakeInc.dir (revision 1169) @@ -0,0 +1,83 @@ +include ../../MakePaths.dir +include ../../MakeInc.dir + +OBJROOT=../../../obj/i386/modules/$(DIR) +SYMROOT=../../../sym/i386/modules/ +DSTROOT=../../../dst/i386/modules/ + + +UTILDIR = ../../util +LIBSADIR = ../../libsa +LIBSAIODIR = ../../libsaio +BOOT2DIR = ../../boot2 + +INSTALLDIR = $(DSTROOT)/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders/standalone + +dylib: ${MODULE_OBJS} dylib_final + +HAVE_MODULES := $(wildcard $(SYMROOT)/*.dylib) +##IS_CPP_MODULE = $(shell nm $(OBJROOT)/*.o | grep " __Z") + +ifneq ($(strip $(HAVE_MODULES)),) +#### Other modules Exist #### +dylib_final: + @rm -rf $(SYMROOT)/$(MODULE_NAME).dylib #ensure module doesn't link with old version of self + @### Ugly hack, remove the c++ module if this module shouldn't link with it. Needed due to LD behavoir + @echo "\t[LD] $(MODULE_NAME).dylib" + @if [ -f "$(SYMROOT)/uClibc++.dylib" ]; then if [ x"$(shell nm $(OBJROOT)/*.o 2>/dev/null | grep " __Z")" == x"" ]; then mv $(SYMROOT)/uClibc++.dylib $(SYMROOT)/../uClibc++.dylib; fi; fi; + + @ld -arch i386 \ + -alias $(MODULE_START) start \ + -dylib -read_only_relocs suppress \ + -S -x -Z -dead_strip_dylibs \ + -no_uuid \ + -current_version $(MODULE_VERSION) -compatibility_version $(MODULE_COMPAT_VERSION) \ + -final_output $(MODULE_NAME) \ + -L$(OBJROOT)/ \ + -L$(OBJROOT)/../ \ + -L$(SYMROOT)/ \ + $(OBJROOT)/*.o \ + -weak_library $(OBJROOT)/../../boot2/Symbols_LINKER_ONLY.dylib \ + -weak_library $(SYMROOT)/*.dylib \ + -o $(SYMROOT)/$(MODULE_NAME).dylib + + @cp -rf include/* ../module_includes/ &> /dev/null || true + + @if [ -f "$(SYMROOT)/../uClibc++.dylib" ]; then if [ x"$(shell nm $(OBJROOT)/*.o 2>/dev/null | grep " __Z")" == x"" ]; then mv $(SYMROOT)/../uClibc++.dylib $(SYMROOT)/uClibc++.dylib; fi; fi; + +else + +#### This is the first module #### +dylib_final: + @rm -rf $(SYMROOT)/$(MODULE_NAME).dylib #ensure module doesn't link with old version of self + @echo "\t[LD] $(MODULE_NAME).dylib" + @ld -arch i386 \ + -alias $(MODULE_START) start \ + -dylib -read_only_relocs suppress \ + -S -x -Z -dead_strip_dylibs \ + -no_uuid \ + -current_version $(MODULE_VERSION) -compatibility_version $(MODULE_COMPAT_VERSION) \ + -final_output $(MODULE_NAME) \ + -L$(OBJROOT)/ \ + -L$(OBJROOT)/../ \ + -L$(SYMROOT)/ \ + $(OBJROOT)/*.o \ + -weak_library $(OBJROOT)/../../boot2/Symbols_LINKER_ONLY.dylib \ + -o $(SYMROOT)/$(MODULE_NAME).dylib + + @cp -rf include/* ../module_includes/ &> /dev/null || true +endif + +%.o: %.c + @echo "\t[CC] $<" + @$(CC) $(CPPFLAGS) $(CFLAGS) -I../include/ -Iinclude/ -I../module_includes/ -D__KLIBC__ $(DEFINES) -c "$<" $(INC) -o "$(OBJROOT)/$@" + +%.o: %.cpp + @echo "\t[CPP] $<" + @$(CPP) $(CPPFLAGS) $(CFLAGS) -I../include/ -Iinclude/ -I../module_includes/ -D__KLIBC__ $(DEFINES) -c "$<" $(INC) -o "$(OBJROOT)/$@" + + + + +# dependencies +#-include $(OBJROOT)/Makedep Index: branches/slice/rev749/modules/uClibc++/exception.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/exception.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/exception.cpp (revision 1169) @@ -0,0 +1,87 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include +#include +#include +#include + +//We can't do this yet because gcc is too stupid to be able to handle +//different implementations of exception class. + +//#undef __UCLIBCXX_EXCEPTION_SUPPORT__ + +#ifdef __UCLIBCXX_EXCEPTION_SUPPORT__ + +namespace std{ + _UCXXEXPORT static const char * __std_exception_what_value = "exception"; + + //We are providing our own versions to be sneaky + + + _UCXXEXPORT exception::~exception() throw(){ + //Empty function + } + + _UCXXEXPORT const char* exception::what() const throw(){ + return __std_exception_what_value; + } + + _UCXXEXPORT bad_exception::~bad_exception() throw(){ + + } + +} +#else +namespace std{ + _UCXXEXPORT exception::~exception() { + abort(); + } + + _UCXXEXPORT const char* exception::what() const { + abort(); + } + + _UCXXEXPORT bad_exception::~bad_exception() { + abort(); + } + +} +#endif + +void +std::terminate() +{ +#ifdef __UCLIBCXX_EXCEPTION_SUPPORT__ + try + { +#endif // __UCLIBCXX_EXCEPTION_SUPPORT__ + (*std::terminate_handler())(); + // handler should not return + abort (); +#ifdef __UCLIBCXX_EXCEPTION_SUPPORT__ + } + catch (...) + { + // handler should not throw exception + abort (); + } +#endif // __UCLIBCXX_EXCEPTION_SUPPORT__ +} Index: branches/slice/rev749/modules/uClibc++/locale.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/locale.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/locale.cpp (revision 1169) @@ -0,0 +1,29 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include +#include + +namespace std{ + +} + Index: branches/slice/rev749/modules/uClibc++/eh_globals.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/eh_globals.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/eh_globals.cpp (revision 1169) @@ -0,0 +1,44 @@ +/* Copyright (C) 2006 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation, version 2.1 + of the License. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include + +//This is a system-specific header which does all of the error-handling management +#include + +//The following functionality is derived from reading of the GNU libstdc++ code and making it...simple + + +namespace __cxxabiv1{ +#ifdef __UCLIBCXX_EXCEPTION_SUPPORT__ + +static __UCLIBCXX_TLS __cxa_eh_globals eh_globals; + +extern "C" __cxa_eh_globals* __cxa_get_globals() throw(){ + return &eh_globals; +} + +extern "C" __cxa_eh_globals* __cxa_get_globals_fast() throw(){ + return &eh_globals; +} +#endif + +} Index: branches/slice/rev749/modules/uClibc++/del_op.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/del_op.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/del_op.cpp (revision 1169) @@ -0,0 +1,26 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include + +_UCXXEXPORT void operator delete(void* ptr) throw(){ + free(ptr); +} Index: branches/slice/rev749/modules/uClibc++/numeric.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/numeric.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/numeric.cpp (revision 1169) @@ -0,0 +1,27 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include + +namespace std{ + + +} + + Index: branches/slice/rev749/modules/uClibc++/vector.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/vector.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/vector.cpp (revision 1169) @@ -0,0 +1,83 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#define __UCLIBCXX_COMPILE_VECTOR__ 1 + + +#include + +namespace std{ + + +#ifdef __UCLIBCXX_EXPAND_VECTOR_BASIC__ + +#ifdef __UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ + + template _UCXXEXPORT vector >::vector(const allocator& al); + template _UCXXEXPORT vector >::vector(size_type n, const char & value, const allocator & al); + + template _UCXXEXPORT vector >::~vector(); + template _UCXXEXPORT vector >::~vector(); + +#endif //__UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ + + template _UCXXEXPORT void vector >::reserve(size_type n); + template _UCXXEXPORT void vector >::reserve(size_type n); + template _UCXXEXPORT void vector >::reserve(size_type n); + template _UCXXEXPORT void vector >::reserve(size_type n); + template _UCXXEXPORT void vector >::reserve(size_type n); + template _UCXXEXPORT void vector >::reserve(size_type n); + template _UCXXEXPORT void vector >::reserve(size_type n); + template _UCXXEXPORT void vector >::reserve(size_type n); + template _UCXXEXPORT void vector >::reserve(size_type n); + template _UCXXEXPORT void vector >::reserve(size_type n); + template _UCXXEXPORT void vector >::reserve(size_type n); + + template _UCXXEXPORT void vector >::resize(size_type sz, const char & c); + template _UCXXEXPORT void vector >::resize(size_type sz, const unsigned char & c); + template _UCXXEXPORT void vector >::resize(size_type sz, const short & c); + template _UCXXEXPORT void vector > + ::resize(size_type sz, const unsigned short int & c); + template _UCXXEXPORT void vector >::resize(size_type sz, const int & c); + template _UCXXEXPORT void vector >::resize(size_type sz, const unsigned int & c); + template _UCXXEXPORT void vector >::resize(size_type sz, const long int & c); + template _UCXXEXPORT void vector >:: + resize(size_type sz, const unsigned long int & c); + template _UCXXEXPORT void vector >::resize(size_type sz, const float & c); + template _UCXXEXPORT void vector >::resize(size_type sz, const double & c); + template _UCXXEXPORT void vector >::resize(size_type sz, const bool & c); + +#elif defined __UCLIBCXX_EXPAND_STRING_CHAR__ + + +#ifdef __UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ + template _UCXXEXPORT vector >::vector(const allocator& al); + template _UCXXEXPORT vector >::vector(size_type n, const char & value, const allocator & al); + template _UCXXEXPORT vector >::~vector(); +#endif // __UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ + + template _UCXXEXPORT void vector >::reserve(size_type n); + template _UCXXEXPORT void vector >::resize(size_type sz, const char & c); + +#endif + + + + +} Index: branches/slice/rev749/modules/uClibc++/deque.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/deque.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/deque.cpp (revision 1169) @@ -0,0 +1,42 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include + + +namespace std{ + + + + + + + + + + + + + + +} + + + + Index: branches/slice/rev749/modules/uClibc++/stdexcept.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/stdexcept.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/stdexcept.cpp (revision 1169) @@ -0,0 +1,63 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include + +#ifdef __UCLIBCXX_EXCEPTION_SUPPORT__ + +namespace std{ + + _UCXXEXPORT logic_error::logic_error() throw() : mstring(){ + + } + + _UCXXEXPORT logic_error::logic_error(const string& what_arg) : mstring(what_arg){ + + } + + _UCXXEXPORT const char * logic_error::what() const throw(){ + return mstring.c_str(); + } + + + _UCXXEXPORT out_of_range::out_of_range() : logic_error(){ + + } + + _UCXXEXPORT out_of_range::out_of_range(const string & what_arg) : logic_error(what_arg) { + + } + + _UCXXEXPORT runtime_error::runtime_error() : mstring(){ + + } + + _UCXXEXPORT runtime_error::runtime_error(const string& what_arg) : mstring(what_arg){ + + } + + _UCXXEXPORT const char * runtime_error::what() const throw(){ + return mstring.c_str(); + } + +} + +#endif + Index: branches/slice/rev749/modules/uClibc++/utility.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/utility.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/utility.cpp (revision 1169) @@ -0,0 +1,30 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + + +#include + + +namespace std{ + + + +} + + Index: branches/slice/rev749/modules/uClibc++/eh_alloc.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/eh_alloc.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/eh_alloc.cpp (revision 1169) @@ -0,0 +1,46 @@ +/* Copyright (C) 2006 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation, version 2.1 + of the License. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include + +//This is a system-specific header which does all of the error-handling management +#include + +namespace __cxxabiv1{ + +#ifdef __UCLIBCXX_EXCEPTION_SUPPORT__ +extern "C" void * __cxa_allocate_exception(std::size_t thrown_size) throw(){ + void *retval; + //The sizeof crap is required by Itanium ABI because we need to provide space for + //accounting information which is implementaion (gcc) specified + retval = malloc (thrown_size + sizeof(__cxa_exception)); + if(0 == retval){ + std::terminate(); + } + memset (retval, 0, sizeof(__cxa_exception)); + return (void *)((unsigned char *)retval + sizeof(__cxa_exception)); +} + +extern "C" void __cxa_free_exception(void *vptr) throw(){ + free( (char *)(vptr) - sizeof(__cxa_exception) ); +} +#endif +} Index: branches/slice/rev749/modules/uClibc++/list.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/list.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/list.cpp (revision 1169) @@ -0,0 +1,29 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include + +namespace std{ + + + + +} + + Index: branches/slice/rev749/modules/uClibc++/map.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/map.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/map.cpp (revision 1169) @@ -0,0 +1,33 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include + +namespace std{ + + + + + + + + + + +} Index: branches/slice/rev749/modules/uClibc++/new_opvnt.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/new_opvnt.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/new_opvnt.cpp (revision 1169) @@ -0,0 +1,31 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include +#include +#include +extern "C" { +#include "libsaio.h" +}; +#ifndef NO_NOTHROW +_UCXXEXPORT void* operator new[](std::size_t numBytes, const std::nothrow_t& ) throw(){ + return malloc(numBytes); +} +#endif Index: branches/slice/rev749/modules/uClibc++/queue.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/queue.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/queue.cpp (revision 1169) @@ -0,0 +1,27 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include + + +namespace std{ + + + + +} Index: branches/slice/rev749/modules/uClibc++/del_opv.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/del_opv.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/del_opv.cpp (revision 1169) @@ -0,0 +1,26 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include + +_UCXXEXPORT void operator delete[](void * ptr) throw(){ + free(ptr); +} Index: branches/slice/rev749/modules/uClibc++/streambuf.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/streambuf.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/streambuf.cpp (revision 1169) @@ -0,0 +1,49 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#define __UCLIBCXX_COMPILE_STREAMBUF__ 1 + +#include + +namespace std{ + +#ifdef __UCLIBCXX_EXPAND_STREAMBUF_CHAR__ + +#ifdef __UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ + + template _UCXXEXPORT streambuf::basic_streambuf(); + template _UCXXEXPORT streambuf::~basic_streambuf(); + +#endif + + template _UCXXEXPORT locale streambuf::pubimbue(const locale &loc); + template _UCXXEXPORT streamsize streambuf::in_avail(); + template _UCXXEXPORT streambuf::int_type streambuf::sbumpc(); + template _UCXXEXPORT streambuf::int_type streambuf::snextc(); + template _UCXXEXPORT streambuf::int_type streambuf::sgetc(); + template _UCXXEXPORT streambuf::int_type streambuf::sputbackc(char_type c); + template _UCXXEXPORT streambuf::int_type streambuf::sungetc(); + template _UCXXEXPORT streambuf::int_type streambuf::sputc(char_type c); + +#endif + + +} + + Index: branches/slice/rev749/modules/uClibc++/iterator.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/iterator.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/iterator.cpp (revision 1169) @@ -0,0 +1,28 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include + +namespace std{ + + + +} + + Index: branches/slice/rev749/modules/uClibc++/new_opnt.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/new_opnt.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/new_opnt.cpp (revision 1169) @@ -0,0 +1,31 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include +#include +#include +extern "C" { +#include "libsaio.h" +}; +#ifndef NO_NOTHROW +_UCXXEXPORT void* operator new(std::size_t numBytes, const std::nothrow_t& ) throw(){ + return malloc(numBytes); +} +#endif Index: branches/slice/rev749/modules/uClibc++/bitset.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/bitset.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/bitset.cpp (revision 1169) @@ -0,0 +1,26 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include + +namespace std{ + + + +} Index: branches/slice/rev749/modules/uClibc++/ios.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/ios.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/ios.cpp (revision 1169) @@ -0,0 +1,189 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#define __UCLIBCXX_COMPILE_IOS__ 1 + +#include +#include +#include +#include +#include + +namespace std{ + + +#ifdef __UCLIBCXX_SUPPORT_CDIR__ + _UCXXLOCAL int ios_base::Init::init_cnt = 0; //Needed to ensure the static value is created + +//Create buffers first +#if __UCLIBCXX_SUPPORT_COUT__ + _UCXXEXPORT filebuf _cout_filebuf; +#endif +#if __UCLIBCXX_SUPPORT_CIN__ + _UCXXEXPORT filebuf _cin_filebuf; +#endif +#if __UCLIBCXX_SUPPORT_CERR__ + _UCXXEXPORT filebuf _cerr_filebuf; +#endif +#if __UCLIBCXX_SUPPORT_CLOG__ + _UCXXEXPORT filebuf _clog_filebuf; +#endif +#ifdef __UCLIBCXX_SUPPORT_WCOUT__ + _UCXXEXPORT wfilebuf _wcout_filebuf; +#endif +#ifdef __UCLIBCXX_SUPPORT_WCIN__ + _UCXXEXPORT wfilebuf _wcin_filebuf; +#endif +#ifdef __UCLIBCXX_SUPPORT_WCERR__ + _UCXXEXPORT wfilebuf _wcerr_filebuf; +#endif +#ifdef __UCLIBCXX_SUPPORT_WCLOG__ + _UCXXEXPORT wfilebuf _wclog_filebuf; +#endif + +//Then create streams +#if __UCLIBCXX_SUPPORT_COUT__ + _UCXXEXPORT ostream cout(&_cout_filebuf); +#endif +#if __UCLIBCXX_SUPPORT_CIN__ + _UCXXEXPORT istream cin(&_cin_filebuf); +#endif +#if __UCLIBCXX_SUPPORT_CERR__ + _UCXXEXPORT ostream cerr(&_cerr_filebuf); +#endif +#if __UCLIBCXX_SUPPORT_CLOG__ + _UCXXEXPORT ostream clog(&_clog_filebuf); +#endif +#ifdef __UCLIBCXX_SUPPORT_WCOUT__ + _UCXXEXPORT wostream wcout(&_wcout_filebuf); +#endif +#ifdef __UCLIBCXX_SUPPORT_WCIN__ + _UCXXEXPORT wistream wcin(&_wcin_filebuf); +#endif +#ifdef __UCLIBCXX_SUPPORT_WCERR__ + _UCXXEXPORT wostream wcerr(&_wcerr_filebuf); +#endif +#ifdef __UCLIBCXX_SUPPORT_WCLOG__ + _UCXXEXPORT wostream wclog(&_wclog_filebuf); +#endif + + + _UCXXEXPORT ios_base::Init::Init(){ + if(init_cnt == 0){ //Need to construct cout et al +#if __UCLIBCXX_SUPPORT_COUT__ + _cout_filebuf.fp = stdout; + _cout_filebuf.openedFor = ios_base::out; +#endif +#if __UCLIBCXX_SUPPORT_CERR__ + _cerr_filebuf.fp = stderr; + _cerr_filebuf.openedFor = ios_base::out; + cerr.mformat |= ios_base::unitbuf; +#endif +#if __UCLIBCXX_SUPPORT_CLOG__ + _clog_filebuf.fp = stderr; + _clog_filebuf.openedFor = ios_base::out; +#endif +#if __UCLIBCXX_SUPPORT_CIN__ + _cin_filebuf.fp = stdin; + _cin_filebuf.openedFor = ios_base::in; + +#if __UCLIBCXX_SUPPORT_COUT__ + cin.tie(&cout); +#endif + +#endif +#ifdef __UCLIBCXX_SUPPORT_WCOUT__ + _wcout_filebuf.fp = stdout; + _wcout_filebuf.openedFor = ios_base::out; +#endif +#ifdef __UCLIBCXX_SUPPORT_WCERR__ + _wcerr_filebuf.fp = stderr; + _wcerr_filebuf.openedFor = ios_base::out; + wcerr.mformat |= ios_base::unitbuf; +#endif +#ifdef __UCLIBCXX_SUPPORT_WCLOG__ + _wclog_filebuf.fp = stderr; + _wclog_filebuf.openedFor = ios_base::out; +#endif +#ifdef __UCLIBCXX_SUPPORT_WCIN__ + _wcin_filebuf.fp = stdin; + _wcin_filebuf.openedFor = ios_base::in; + +#ifdef __UCLIBCXX_SUPPORT_WCOUT__ + wcin.tie(&wcout); +#endif + +#endif + } + init_cnt++; + } + + _UCXXEXPORT ios_base::Init::~Init(){ + --init_cnt; + if(init_cnt==0){ + + } + } +#endif + + +#ifdef __UCLIBCXX_EXPAND_IOS_CHAR__ + + template _UCXXEXPORT void basic_ios >::clear(iostate state); + template _UCXXEXPORT void basic_ios >::setstate(iostate state); + +#endif + + + _UCXXEXPORT ios_base::fmtflags ios_base::flags(fmtflags fmtfl){ + fmtflags temp = mformat; + mformat = fmtfl; + return temp; + } + + _UCXXEXPORT ios_base::fmtflags ios_base::setf(fmtflags fmtfl){ + return flags(flags() | fmtfl); + } + + _UCXXEXPORT ios_base::fmtflags ios_base::setf(fmtflags fmtfl, fmtflags mask ){ + return flags( (flags()& ~mask) | (fmtfl & mask)); + } + + _UCXXEXPORT streamsize ios_base::precision(streamsize prec){ + streamsize temp = mprecision; + mprecision = prec; + return temp; + } + + _UCXXEXPORT streamsize ios_base::width(streamsize wide){ + streamsize temp = mwidth; + mwidth = wide; + return temp; + } + + _UCXXEXPORT locale ios_base::imbue(const locale& loc){ + locale retval = mLocale; + mLocale = loc; + return retval; + } + +} + + + Index: branches/slice/rev749/modules/uClibc++/set.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/set.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/set.cpp (revision 1169) @@ -0,0 +1,33 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include + +namespace std{ + + + + + + + + + + +} Index: branches/slice/rev749/modules/uClibc++/abi.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/abi.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/abi.cpp (revision 1169) @@ -0,0 +1,39 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc C++ Library. This library is free + software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) + any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this library; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. +*/ + +#include +#include +#include + +/* This file implements a number of the language support features + * needed to deal with the C++ abi, as originally documented in the + * Itanium C++ ABI, though now industry standard + */ + +extern "C" { + + /* This function is called in the event that a non-overidden + * pure virtual function is called. The compiler should never + * let that happen. We get to choose what to do - we will abort + */ + void __cxa_pure_virtual (){ + abort(); + } + +} Index: branches/slice/rev749/modules/uClibc++/Makefile =================================================================== --- branches/slice/rev749/modules/uClibc++/Makefile (revision 0) +++ branches/slice/rev749/modules/uClibc++/Makefile (revision 1169) @@ -0,0 +1,58 @@ + +MODULE_NAME = uClibc++ +MODULE_VERSION = "0.2.2" +MODULE_COMPAT_VERSION = "0.2.2" +MODULE_START = _uClibcxx_start +MODULE_DEPENDENCIES = + +DIR = uClibc++ +# sstream.o fstream.o +MODULE_OBJS = uClibc++.o abi.o algorithm.o associative_base.o bitset.o \ + complex.o del_op.o del_opnt.o del_opv.o del_opvnt.o \ + deque.o eh_alloc.o eh_globals.o exception.o \ + func_exception.o iomanip.o char_traits.o \ + iterator.o limits.o list.o locale.o \ + map.o new_handler.o new_op.o new_opnt.o new_opv.o \ + new_opvnt.o numeric.o queue.o set.o \ + stack.o stdexcept.o streambuf.o string.o typeinfo.o \ + utility.o valarray.o vector.o support.o \ + ios.o iostream.o istream.o ostream.o + +OPTIM = -Os -Oz +DEBUG = -DNOTHING +#DEBUG = -DDEBUG_HELLO_WORLD=1 +CFLAGS = $(RC_CFLAGS) $(OPTIM) $(MORECPP) -arch i386 -g -Wmost \ + -D__ARCHITECTURE__=\"i386\" -DSAIO_INTERNAL_USER \ + -DRCZ_COMPRESSED_FILE_SUPPORT $(DEBUG) \ + -fno-builtin $(OMIT_FRAME_POINTER_CFLAG) \ + -mpreferred-stack-boundary=2 -fno-align-functions -fno-stack-protector \ + -march=pentium4 -msse2 -mfpmath=sse -msoft-float -fno-common + +DEFINES= +CONFIG = hd +INC = -I. -I.. -I$(SYMROOT) -I$(UTILDIR) -I$(LIBSADIR) -I$(LIBSAIODIR) -I$(BOOT2DIR) -Iinclude +ifneq "" "$(wildcard /bin/mkdirs)" + MKDIRS = /bin/mkdirs +else + MKDIRS = /bin/mkdir -p +endif +AS = as +LD = ld +# LIBS= -lc_static +LIBS= + +VPATH = $(OBJROOT):$(SYMROOT) + +SFILES = +CFILES = +HFILES = +EXPORTED_HFILES = +INSTALLED_HFILES = +OTHERFILES = Makefile +ALLSRC = $(SFILES) $(CFILES) \ + $(HFILES) $(OTHERFILES) +DIRS_NEEDED = $(OBJROOT) $(SYMROOT) + +all embedtheme optionrom: dylib + +include ../MakeInc.dir \ No newline at end of file Index: branches/slice/rev749/modules/uClibc++/fstream.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/fstream.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/fstream.cpp (revision 1169) @@ -0,0 +1,174 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#define __UCLIBCXX_COMPILE_FSTREAM__ 1 + +#include + +namespace std{ + +#ifdef __UCLIBCXX_EXPAND_FSTREAM_CHAR__ + +#ifdef __UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ + + template _UCXXEXPORT filebuf::basic_filebuf(); + template _UCXXEXPORT filebuf::~basic_filebuf(); + +#endif //__UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ + + template _UCXXEXPORT filebuf::int_type filebuf::pbackfail(filebuf::int_type c); + template _UCXXEXPORT filebuf * filebuf::open(const char* s, ios_base::openmode mode); + template _UCXXEXPORT filebuf * filebuf::close(); + template _UCXXEXPORT filebuf::int_type filebuf::overflow(filebuf::int_type); + template _UCXXEXPORT filebuf::int_type filebuf::underflow (); + template _UCXXEXPORT streamsize filebuf::xsputn(const char* s, streamsize n); + + template _UCXXEXPORT basic_streambuf >* + filebuf::setbuf(char * s, streamsize n); + + +#ifdef __UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ + + template _UCXXEXPORT basic_ofstream >::basic_ofstream(); + template _UCXXEXPORT basic_ofstream >::basic_ofstream(const char* s, ios_base::openmode mode); + template _UCXXEXPORT basic_ofstream >::~basic_ofstream(); + + template _UCXXEXPORT basic_ifstream >::basic_ifstream(); + template _UCXXEXPORT basic_ifstream >::basic_ifstream(const char* s, ios_base::openmode mode); + template _UCXXEXPORT basic_ifstream >::~basic_ifstream(); + +#endif //__UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ + + +#endif + + + +#ifdef __UCLIBCXX_HAS_WCHAR__ + +template <> _UCXXEXPORT basic_filebuf >::int_type + basic_filebuf >::overflow(int_type c) +{ + typedef basic_streambuf > wstreambuf; + typedef char_traits wtraits; + + if(is_open() == false){ + //Can't do much + return wtraits::eof(); + } + + mbstate_t ps = { 0 }; + char out_array[8]; + size_t out_size; + + + if( wstreambuf::pbase() != 0 ){ + + //Write all possible character from the existing array first + size_t chars_written = 0; + while(wstreambuf::pbase() && (wstreambuf::pbase() + chars_written !=wstreambuf::pptr()) ){ + out_size = wcrtomb(out_array, wstreambuf::pbase()[chars_written], &ps); + if(out_size == (size_t)(-1) || fwrite(out_array, out_size, 1, fp) == 0){ + break; + } + ++chars_written; + } + + if( wstreambuf::pbase() + chars_written == wstreambuf::pptr() ){ + wstreambuf::pbump(-chars_written); + }else{ + //Shuffle data back into order + size_t chars_left = wstreambuf::pptr() - wstreambuf::pbase() - chars_written; + for(size_t i = 0; i < chars_left; ++i){ + wstreambuf::pbase()[i] = (wstreambuf::pptr() - chars_written)[i]; + } + return wtraits::eof(); + } + } + + if( !wtraits::eq_int_type(c, wtraits::eof()) ){ + out_size = wcrtomb(out_array, c, &ps); + if(out_size == (size_t)(-1) || fwrite(out_array, out_size, 1, fp) == 0){ + return wtraits::eof(); + } + return c; + } + + return wtraits::not_eof(c); +} + + +template <> _UCXXEXPORT basic_filebuf >::int_type + basic_filebuf >::underflow() +{ + /*Some variables used internally: + Buffer pointers: + + charT * mgbeg; + charT * mgnext; + charT * mgend; + + eback() returns mgbeg + gptr() returns mgnext + egptr() returns mgend + + gbump(int n) mgnext+=n + */ + + typedef char_traits traits; + typedef basic_streambuf wstreambuf; + + + if(wstreambuf::eback() == wstreambuf::gptr() && 0 != wstreambuf::eback()){ //Buffer is full + return traits::to_int_type(*wstreambuf::gptr()); + } + + size_t in_size; + + wchar_t c = 0; + wint_t wi = 0; + in_size = 0; + + wi = fgetwc(fp); + if(WEOF == wi){ + fprintf(stderr, "WEOF returned by fgetwc\n"); + return traits::eof(); + } + + c = traits::to_char_type(wi); + + if(wstreambuf::eback() == 0){ + return traits::to_int_type(c); + } + + for(wchar_t * i = wstreambuf::gptr(); i < wstreambuf::egptr(); ++i){ + *(i-1) = *i; + } + + *(wstreambuf::egptr()-1) = c; + + wstreambuf::mgnext -= 1; + + return traits::to_int_type(*wstreambuf::gptr()); +} + +#endif // __UCLIBCXX_HAS_WCHAR__ + + +} Index: branches/slice/rev749/modules/uClibc++/limits.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/limits.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/limits.cpp (revision 1169) @@ -0,0 +1,25 @@ +/* Copyright (C) 2006 Garrett A. Kajmowicz + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include + +namespace std{ + + +} Index: branches/slice/rev749/modules/uClibc++/include/iostream =================================================================== --- branches/slice/rev749/modules/uClibc++/include/iostream (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/iostream (revision 1169) @@ -0,0 +1,101 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include + +#ifndef __HEADER_STD_IOSTREAM +#define __HEADER_STD_IOSTREAM 1 + +#include +#include +#include +#include +#include +#include + +#pragma GCC visibility push(default) + +namespace std{ +#ifdef __UCLIBCXX_SUPPORT_CIN__ + extern istream cin; +#endif +#ifdef __UCLIBCXX_SUPPORT_COUT__ + extern ostream cout; +#endif +#ifdef __UCLIBCXX_SUPPORT_CERR__ + extern ostream cerr; +#endif +#ifdef __UCLIBCXX_SUPPORT_CLOG__ + extern ostream clog; +#endif +#ifdef __UCLIBCXX_SUPPORT_WCIN__ + extern wistream wcin; +#endif +#ifdef __UCLIBCXX_SUPPORT_WCOUT__ + extern wostream wcout; +#endif +#ifdef __UCLIBCXX_SUPPORT_WCERR__ + extern wostream wcerr; +#endif +#ifdef __UCLIBCXX_SUPPORT_WCLOG__ + extern wostream wclog; +#endif + + + template class _UCXXEXPORT basic_iostream : + public basic_istream, public basic_ostream + { + public: + // constructor/destructor + explicit _UCXXEXPORT basic_iostream(basic_streambuf* sb); + virtual _UCXXEXPORT ~basic_iostream(); //Below + }; + + template _UCXXEXPORT + basic_iostream:: basic_iostream(basic_streambuf* sb) + : basic_ios(sb), basic_istream(sb), basic_ostream(sb) + { + return; + } + + + template _UCXXEXPORT basic_iostream::~basic_iostream(){ + return; + } + + +#ifdef __UCLIBCXX_EXPAND_OSTREAM_CHAR__ +#ifdef __UCLIBCXX_EXPAND_ISTREAM_CHAR__ +#ifndef __UCLIBCXX_COMPILE_IOSTREAM__ + + template <> _UCXXEXPORT basic_iostream >:: + basic_iostream(basic_streambuf >* sb); + template <> _UCXXEXPORT basic_iostream >::~basic_iostream(); + +#endif +#endif +#endif + + + +} + +#pragma GCC visibility pop + +#endif Index: branches/slice/rev749/modules/uClibc++/include/cstdio =================================================================== --- branches/slice/rev749/modules/uClibc++/include/cstdio (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/cstdio (revision 1169) @@ -0,0 +1,75 @@ +/* Copyright (C) 2006 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation version 2.1 + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include + +#ifndef __HEADER_CSTDIO +#define __HEADER_CSTDIO 1 + + +namespace std{ + using ::FILE; + using ::fpos_t; + + using ::clearerr; + using ::fclose; + using ::feof; + using ::ferror; + using ::fflush; + using ::fgetc; + using ::fgetpos; + using ::fgets; + using ::fopen; + using ::fprintf; + using ::fputc; + using ::fputs; + using ::fread; + using ::freopen; + using ::fscanf; + using ::fseek; + using ::fsetpos; + using ::ftell; + using ::fwrite; + using ::getc; + using ::getchar; + using ::gets; + using ::perror; + using ::printf; + using ::putc; + using ::putchar; + using ::puts; + using ::remove; + using ::rename; + using ::rewind; + using ::scanf; + using ::setbuf; + using ::setvbuf; + using ::sprintf; + using ::sscanf; + using ::tmpfile; + using ::tmpnam; + using ::ungetc; + using ::vfprintf; + using ::vprintf; + using ::vsprintf; +} + + + +#endif + Index: branches/slice/rev749/modules/uClibc++/include/cstdarg =================================================================== --- branches/slice/rev749/modules/uClibc++/include/cstdarg (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/cstdarg (revision 1169) @@ -0,0 +1,60 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 1997, 1998, 1999, 2000, 2002 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// +// ISO C++ 14882: 20.4.6 C library +// + +/** @file cstdarg + * This is a Standard C++ Library file. You should @c #include this file + * in your programs, rather than any of the "*.h" implementation files. + * + * This is the C++ version of the Standard C Library header @c stdarg.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std. + */ + +#ifndef _CPP_CSTDARG +#define _CPP_CSTDARG 1 + +#pragma GCC system_header + +#include + +// Adhere to section 17.4.1.2 clause 5 of ISO 14882:1998 +#ifndef va_end +#define va_end(ap) va_end (ap) +#endif + +namespace std +{ + using ::va_list; +} + +#endif Index: branches/slice/rev749/modules/uClibc++/include/map.old =================================================================== --- branches/slice/rev749/modules/uClibc++/include/map.old (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/map.old (revision 1169) @@ -0,0 +1,1163 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + + +#include +#include +#include +#include +#include + + +#ifndef __STD_HEADER_MAP +#define __STD_HEADER_MAP + +#pragma GCC visibility push(default) + +namespace std{ + + +template, class Allocator = allocator > class __base_map; +template, class Allocator = allocator > class map; +template, class Allocator = allocator > class multimap; + +template class __map_iter; +template class __map_citer; + +/* The code for the map containers is split up into two classes. + * The first class, __base_map holds all of the data and does much of the iterator-based + * work. Then the classes map and multimap inherit from there. This was done to reduce + * the redundancy of code (And thus errors which might crop up), as well as possibly + * reducing the size of binaries if both map and multimap are used, along with the same + * template parameters. + */ + + + +//All base classes first (__base_map, iterators, value_compare) and it's associated code + + +template class _UCXXEXPORT __base_map{ + +protected: + friend class __map_iter; + friend class __map_citer; + +public: + typedef __base_map map_type; + typedef Key key_type; + typedef T mapped_type; + typedef pair value_type; + typedef Compare key_compare; + typedef Allocator allocator_type; + typedef typename Allocator::reference reference; + typedef typename Allocator::const_reference const_reference; + typedef __map_iter iterator; + typedef __map_citer const_iterator; + typedef typename Allocator::size_type size_type; + typedef typename Allocator::difference_type difference_type; + typedef typename Allocator::pointer pointer; + typedef typename Allocator::const_pointer const_pointer; + typedef typename std::reverse_iterator reverse_iterator; + typedef typename std::reverse_iterator const_reverse_iterator; + + class value_compare; + + explicit __base_map(const Compare& comp = Compare(), const Allocator& al = Allocator()); + __base_map(const map_type& x); + ~__base_map(); + + iterator begin(); + const_iterator begin() const; + iterator end(); + const_iterator end() const; + reverse_iterator rbegin(); + const_reverse_iterator rbegin() const; + reverse_iterator rend(); + const_reverse_iterator rend() const; + + bool empty() const; + size_type size() const; + size_type max_size() const; + + iterator lower_bound(const key_type& x); + const_iterator lower_bound(const key_type& x) const; + + void swap(map_type & x); + void clear(); + + key_compare key_comp() const; +// value_compare value_comp() const; + +protected: + + deque, allocator > > data; + Compare c; + +}; + + + //Implementations + + template class _UCXXEXPORT __map_citer + : public std::iterator< + bidirectional_iterator_tag, + std::pair, + typename Allocator::difference_type, + std::pair*, + std::pair& + > + { + protected: + typedef __base_map Map; + + friend class __base_map; + friend class __base_map::iterator; + + friend class map; + friend class multimap; + + typename Map::size_type element; + const Map * container; + public: + __map_citer() : element(0), container(0) { } + __map_citer(const typename Map::const_iterator & m) + : element(m.element), container(m.container) { } + __map_citer(typename Map::size_type e, const Map * const c) + : element(e), container(c) { } + ~__map_citer() { } + + typename Map::value_type operator*() const{ + return container->data[element]; + } + const typename Map::value_type * operator->() const{ + return &(container->data[element]); + } + __map_citer & operator=(const typename Map::const_iterator & m){ + element = m.element; + container = m.container; + return *this; + } + bool operator==(const typename Map::const_iterator & m) const { + return (m.element == element && m.container == container); + } + bool operator!=(const typename Map::const_iterator & m) const { + return (m.element != element || m.container != container); + } + __map_citer & operator++(){ + ++element; + return *this; + } + __map_citer operator++(int){ + __map_citer temp(*this); + ++element; + return temp; + } + __map_citer & operator--(){ + --element; + return *this; + } + __map_citer operator--(int){ + __map_citer temp(*this); + --element; + return temp; + } + + }; + + + template class _UCXXEXPORT __map_iter + : public std::iterator< + bidirectional_iterator_tag, + std::pair, + typename Allocator::difference_type, + std::pair*, + std::pair& + > + { + protected: + typedef class __base_map Map; + + //FIXME - Find a way to use template parameters or something. This will do for now + friend class __base_map; + friend class __base_map::const_iterator; + + friend class map; + friend class multimap; + + typename Map::size_type element; + Map * container; + public: + __map_iter() : element(0), container(0) { } + __map_iter(const typename Map::iterator & m) + : element(m.element), container(m.container) { } + __map_iter(typename Map::size_type e, Map * c) + : element(e), container(c) { } + ~__map_iter() { } + + typename Map::value_type & operator*(){ + return container->data[element]; + } + const typename Map::value_type & operator*() const{ + return container->data[element]; + } + typename Map::value_type * operator->(){ + return &(container->data[element]); + } + __map_iter & operator=(const typename Map::iterator & m){ + element = m.element; + container = m.container; + return *this; + } + bool operator==(const typename Map::iterator & m) const { + return (m.element == element && m.container == container); + } + bool operator!=(const typename Map::iterator & m) const { + return (m.element != element || m.container != container); + } + bool operator==(const typename Map::const_iterator & m) const { + return (m.element == element && m.container == container); + } + bool operator!=(const typename Map::const_iterator & m) const { + return (m.element != element || m.container != container); + } + __map_iter & operator++(){ + ++element; + return *this; + } + __map_iter operator++(int){ + __map_iter temp(*this); + ++element; + return temp; + } + __map_iter & operator--(){ + --element; + return *this; + } + __map_iter operator--(int){ + __map_iter temp(*this); + --element; + return temp; + } + + operator typename Map::const_iterator() const{ + return typename Map::const_iterator(element, container); + } + + }; + + + //Compare the keys of the two items + template class _UCXXEXPORT + __base_map::value_compare : public binary_function< + typename map::value_type, + typename map::value_type, + bool> + { + friend class __base_map; + protected: + Compare comp; + value_compare(Compare c) : comp(c) { } + ~value_compare() { } + public: + bool operator()(const value_type& x, const value_type& y) const { + return comp(x.first, y.first); + } + }; + + template + __base_map::__base_map(const Compare& comp, const Allocator&) + : data(), c(comp) + { + + } + + template + __base_map::__base_map(const __base_map& x) + : data(x.data), c(x.c) + { + + } + + template + __base_map::~__base_map() + { + + } + + + template + typename __base_map::iterator + __base_map::begin() + { + return iterator(0, this); + } + + template + typename __base_map::const_iterator + __base_map::begin() const + { + return const_iterator(0, this); + + } + + template + typename __base_map::iterator + __base_map::end() + { + return iterator(data.size(), this); + } + + template + typename __base_map::const_iterator + __base_map::end() const + { + return const_iterator(data.size(), this); + } + + template + typename __base_map::reverse_iterator + __base_map::rbegin() + { + return reverse_iterator(end()); + } + + template + typename __base_map::const_reverse_iterator + __base_map::rbegin() const + { + return const_reverse_iterator(end()); + } + + template + typename __base_map::reverse_iterator + __base_map::rend() + { + return reverse_iterator(begin()); + } + + template + typename __base_map::const_reverse_iterator + __base_map::rend() const + { + return const_reverse_iterator(begin()); + } + + template + bool __base_map::empty() const + { + return (data.size() == 0); + } + + template + typename __base_map::size_type + __base_map::size() const + { + return data.size(); + } + + template + typename __base_map::size_type + __base_map::max_size() const + { + return data.max_size(); + } + + template + typename __base_map::iterator + __base_map::lower_bound(const key_type &x) + { + size_type low = 0; + size_type high = data.size(); + + while (low < high) { + size_type i = (low + high) / 2; + if( c(data[i].first, x) ){ + low = i + 1; + }else{ + high = i; + } + } + + return iterator(low, this); + } + + template + typename __base_map::const_iterator + __base_map::lower_bound(const key_type &x) const + { + size_type low = 0; + size_type high = data.size(); + + while (low < high) { + size_type i = (low + high) / 2; + if( c(data[i].first, x) ){ + low = i + 1; + }else{ + high = i; + } + } + + return const_iterator(low, this); + } + + template + void __base_map::swap(__base_map& m) + { + Compare n = c; + c = m.c; + m.c = n; + + data.swap(m.data); + } + + + template + void __base_map::clear() + { + data.clear(); + } + + + template + typename __base_map::key_compare + __base_map::key_comp() const + { + return c; + } + +// value_compare value_comp() const; + + + + + +/* This is the implementation for the map container. As noted above, it deviates + * from ISO spec by deriving from a base class in order to reduce code redundancy. + * More code could be reduced by convirting to virtual functions (thus allowing + * much of the erase and insert code to be duplicated), but that would deviate from + * the specifications too much to be worth the risk. + */ + + + + + +//Implementation of map + + +template class _UCXXEXPORT map + : public __base_map +{ + //Default value of allocator does not meet C++ standard specs, but it works for this library + //Deal with it +public: + + typedef __base_map base; + typedef typename base::key_type key_type; + typedef typename base::mapped_type mapped_type; + typedef typename base::value_type value_type; + typedef typename base::key_compare key_compare; + typedef typename base::allocator_type allocator_type; + typedef typename base::reference reference; + typedef typename base::const_reference const_reference; + typedef typename base::iterator iterator; + typedef typename base::const_iterator const_iterator; + typedef typename base::size_type size_type; + typedef typename base::difference_type difference_type; + typedef typename base::pointer pointer; + typedef typename base::const_pointer const_pointer; + typedef typename base::reverse_iterator reverse_iterator; + typedef typename base::const_reverse_iterator const_reverse_iterator; + + using base::value_compare; + + explicit map(const Compare& comp = Compare(), const Allocator& al = Allocator()) + : base(comp, al) { } + + template map(InputIterator first, InputIterator last, + const Compare& comp = Compare(), const Allocator& = Allocator()); + + map(const map& x) : base(x) { } + ~map() { } + + map& operator=(const map& x); + + reference operator[](const key_type& k); + + pair insert(const value_type& x); + iterator insert(iterator position, const value_type& x); + + template void insert(InputIterator first, InputIterator last); + void erase(iterator position); + size_type erase(const key_type& x); + void erase(iterator first, iterator last); + + using base::begin; + using base::end; + using base::rbegin; + using base::rend; + + using base::empty; + using base::size; + using base::max_size; + + iterator find(const key_type& x); + const_iterator find(const key_type& x) const; + size_type count(const key_type& x) const; + iterator upper_bound(const key_type& x); + const_iterator upper_bound(const key_type& x) const; + pair equal_range(const key_type& x); + pair equal_range(const key_type& x) const; + +protected: + friend class base::iterator; + friend class base::const_iterator; + + friend bool operator==(const map& x, const map& y); + + using base::data; + using base::c; + +}; + + + template template + map:: + map(InputIterator first, InputIterator last, const Compare& comp, const Allocator& al) + : base(comp, al) + { + while(first !=last){ + insert(*first); + ++first; + } + } + + template + map::map& + map::operator=(const map& x) + { + if( &x == this){ + return *this; + } + c = x.c; + data = x.data; + return *this; + } + + + template + typename map::reference + map::operator[](const key_type & k) + { +/* iterator i = lower_bound(k); + if( !c( i->first, k) && !c(k, i->first) ){ + return i->second; + } + pair t; + t.first = k; + t.second = T(); + return insert(t).first->second; +*/ + //This is from the spec and is quite ugly. + return (*((insert(make_pair(k, T()))).first)).second; + } + + template + pair::iterator, bool> + map::insert(const value_type& x) + { + pair::iterator, bool> retval; + + //Either set is empty or element to insert goes at the begining + if(data.size() == 0 || c(x.first, data[0].first) ){ + data.push_front(x); + retval.first = begin(); + retval.second = true; + return retval; + } + + //Element to insert goes at the end + if( c(data[data.size() - 1].first, x.first) ){ + data.push_back(x); + retval.first = end(); + --retval.first; + retval.second = true; + return retval; + } + + retval.first = __base_map::lower_bound(x.first); + + //No match - this should never happen + if(retval.first == end()){ + retval.second = false; + return retval; + } + + //If we have an exact match + if( !c( retval.first->first, x.first) && !c(x.first, retval.first->first ) ){ + retval.second = false; + return retval; + } + + typename deque, allocator > >::iterator q(&data, retval.first.element); + data.insert(q, x); + + retval.first = __base_map::lower_bound(x.first); //Need to refind because insert can move data around + retval.second = true; + + return retval; + } + + + template + typename map::iterator + map::insert(iterator, const value_type& x) + { + //Just reusing code. It's hard to make improvements over existing algo. + //We aren't using the iterator parameter, but it's only a hint and not required to be used. + insert(x); + return find(x.first); + } + + template + template void + map::insert(InputIterator first, InputIterator last) + { + while(first !=last){ + insert(*first); + ++first; + } + } + + template void + map::erase(iterator position) + { + //Create a deque iterator from position information and then + //Use built in erase feature because it is handy. + typename deque, allocator > >::iterator pos(&data, position.element); + data.erase(pos); + } + + template + typename map::size_type + map::erase(const key_type& x) + { + typename map::iterator i = find(x); + if(i!=end()){ + erase(i); + return 1; + } + return 0; + } + + template + void map::erase(iterator first, iterator last) + { + typename deque, allocator > >::iterator f(&data, first.element); + typename deque, allocator > >::iterator l(&data, last.element); + data.erase(f, l); + } + + template + typename map::iterator + map:: + find(const typename map::key_type& x) + { + if(data.size() == 0){ + return end(); + } + + iterator retval = __base_map::lower_bound(x); + + if(retval == end()){ + return retval; + } + + //Make sure we have an exact match.... + if(!c( retval->first, x) && !c(x, retval->first )){ + return retval; + } + return end(); + + } + + template + typename map::const_iterator + map::find(const key_type& x) const + { + if(data.size() == 0){ + return end(); + } + + const_iterator retval = __base_map::lower_bound(x); + + if(retval == end()){ + return retval; + } + + //Make sure we have an exact match.... + if(!c( retval->first, x) && !c(x, retval->first )){ + return retval; + } + return end(); + + } + + template + typename map::size_type + map::count(const typename map::key_type& x) const + { + if( find(x) == end()){ + return 0; + } + return 1; + } + + template + typename map::iterator + map::upper_bound(const key_type& x) + { + typename map::iterator i = __base_map::lower_bound(x); + if( i != end() && !c(x, i->first) ){ + ++i; + } + return i; + } + + template + typename map::const_iterator + map::upper_bound(const key_type& x) const + { + typename map::const_iterator i = __base_map::lower_bound(x); + if(i != end() && !c(x, i->first)){ + ++i; + } + return i; + } + + + template + pair< typename map::iterator, + typename map::iterator + > map::equal_range(const key_type& x) + { + pair< typename map::iterator, + typename map::iterator + > retval; + retval.first = __base_map::lower_bound(x); + retval.second = upper_bound(x); + return retval; + } + + template + pair< typename map::const_iterator, + typename map::const_iterator + > map::equal_range(const key_type& x) const + { + pair< typename map::const_iterator, + typename map::const_iterator + > retval; + retval.first = __base_map::lower_bound(x); + retval.second = upper_bound(x); + return retval; + } + + template bool operator== + (const map& x, const map& y) + { + if(x.c == y.c && x.data == y.data){ + return true; + } + return false; + } + + + +//Implementation of multimap + + +template class _UCXXEXPORT multimap + : public __base_map +{ + //Default value of allocator does not meet C++ standard specs, but it works for this library + //Deal with it +public: + + typedef __base_map base; + typedef typename base::key_type key_type; + typedef typename base::mapped_type mapped_type; + typedef typename base::value_type value_type; + typedef typename base::key_compare key_compare; + typedef typename base::allocator_type allocator_type; + typedef typename base::reference reference; + typedef typename base::const_reference const_reference; + typedef typename base::iterator iterator; + typedef typename base::const_iterator const_iterator; + typedef typename base::size_type size_type; + typedef typename base::difference_type difference_type; + typedef typename base::pointer pointer; + typedef typename base::const_pointer const_pointer; + typedef typename base::reverse_iterator reverse_iterator; + typedef typename base::const_reverse_iterator const_reverse_iterator; + + explicit multimap(const Compare& comp = Compare(), const Allocator& al = Allocator()) + : base(comp, al) { } + + template multimap(InputIterator first, InputIterator last, + const Compare& comp = Compare(), const Allocator& = Allocator()); + + multimap(const multimap& x) : base(x) { } + ~multimap() { } + + multimap& operator=(const multimap& x); + + iterator insert(const value_type& x); + iterator insert(iterator position, const value_type& x); + template void insert(InputIterator first, InputIterator last); + + void erase(iterator position); + size_type erase(const key_type& x); + void erase(iterator first, iterator last); + + using base::begin; + using base::end; + using base::rbegin; + using base::rend; + + using base::empty; + using base::size; + using base::max_size; + + iterator find(const key_type& x); + const_iterator find(const key_type& x) const; + size_type count(const key_type& x) const; + iterator upper_bound(const key_type& x); + const_iterator upper_bound(const key_type& x) const; + pair equal_range(const key_type& x); + pair equal_range(const key_type& x) const; + +protected: + friend class base::iterator; + friend class base::const_iterator; + + using base::data; + using base::c; + +}; + + + + template template + multimap:: + multimap(InputIterator first, InputIterator last, const Compare& comp, const Allocator& al) + : base(comp, al) + { + while(first !=last){ + insert(*first); + ++first; + } + } + + template + multimap::multimap& + multimap::operator=(const multimap& x) + { + if( &x == this){ + return *this; + } + c = x.c; + data = x.data; + return *this; + } + + + template + typename multimap::iterator + multimap::insert(const value_type &x) + { + iterator retval; + + //Either set is empty or element to insert goes at the begining + if(data.size() == 0 || c(x.first, data[0].first) ){ + data.push_front(x); + return begin(); + } + + //Element to insert goes at the end + if( c(data[data.size() - 1].first, x.first) ){ + data.push_back(x); + return end(); + } + + retval = __base_map::lower_bound(x.first); + + //No match - this should never happen + if(retval == end()){ + return retval; + } + + if( !c(x.first, retval->first) ){ + ++retval; + } + + typename deque, allocator > >::iterator q(&data, retval.element); + data.insert(q, x); + + return retval; + } + + + template + typename multimap::iterator + multimap::insert(iterator position, const value_type& x) + { + + //Inserting at begining + if(position == begin() && !c(position->first, x.first) ){ + data.push_front(x); + return position; + } + //Inserting at end + if(position == end() && !c(x.first, data[data.size() - 1].first) ){ + data.push_back(x); + return position; + } + + //Inserting in middle + iterator temp = position; + --temp; + if( !c(position->first, x.first) && !c(x.first, temp->first) ){ + typename deque, allocator > >::iterator q(&data, position.element); + data.insert(q, x); + return position; + } + + return insert(x); + } + + template + template void + multimap::insert(InputIterator first, InputIterator last) + { + while(first !=last){ + insert(*first); + ++first; + } + } + + + + template void + multimap::erase(iterator position) + { + //Create a deque iterator from position information and then + //Use built in erase feature because it is handy. + typename deque, allocator > >::iterator pos(&data, position.element); + data.erase(pos); + } + + template + typename multimap::size_type + multimap::erase(const key_type& x) + { + typename multimap::iterator f = __base_map::lower_bound(x); + typename multimap::iterator l = upper_bound(x); + size_type t = l.element - f.element; + erase(f, l); + return t; + } + + + + template + void multimap::erase(iterator first, iterator last) + { + typename deque, allocator > >::iterator f(&data, first.element); + typename deque, allocator > >::iterator l(&data, last.element); + data.erase(f, l); + } + + + template + typename multimap::iterator + multimap::find(const key_type& x) + { + if(data.size() == 0){ + return end(); + } + + iterator retval = __base_map::lower_bound(x); + + if(retval == end()){ + return retval; + } + + if( c(x, retval->first) || c(retval->first, x) ){ + return end(); + } + + while( retval.element > 0 && !c(retval->first, x) && !c(x, retval->first) ){ + --retval; + } + if( c(retval->first, x)){ + ++retval; + } + + return retval; + } + + + template + typename multimap::const_iterator + multimap::find(const key_type& x) const + { + if(data.size() == 0){ + return end(); + } + const_iterator retval = __base_map::lower_bound(x); + + if(retval == end()){ + return retval; + } + + if( c(x, retval->first) || c(retval->first, x) ){ + return end(); + } + + while( retval.element > 0 && !c(retval->first, x) && !c(x, retval->first) ){ + --retval; + } + if( c(retval->first, x)){ + ++retval; + } + + + return retval; + } + + + template + typename multimap::size_type + multimap:: + count(const typename multimap::key_type& x) const + { + pair< typename multimap::const_iterator, + typename multimap::const_iterator + > temp = equal_range(x); + + return temp.second.element - temp.first.element; + } + + template + typename multimap::iterator + multimap::upper_bound(const key_type& x) + { + typename multimap::iterator i = __base_map::lower_bound(x); + + while(i != end() && !c(x, i->first)){ + ++i; + } + return i; + } + + template + typename multimap::const_iterator + multimap::upper_bound(const key_type& x) const + { + typename multimap::const_iterator i = __base_map::lower_bound(x); + + while(i != end() && !c(x, i->first)){ + ++i; + } + return i; + } + + + template + pair< typename multimap::iterator, + typename multimap::iterator + > multimap::equal_range(const key_type& x) + { + pair< typename multimap::iterator, + typename multimap::iterator + > retval; + retval.first = __base_map::lower_bound(x); + retval.second = upper_bound(x); + return retval; + } + + template + pair< typename multimap::const_iterator, + typename multimap::const_iterator + > multimap::equal_range(const key_type& x) const + { + pair< typename multimap::const_iterator, + typename multimap::const_iterator + > retval; + retval.first = __base_map::lower_bound(x); + retval.second = upper_bound(x); + return retval; + } + + + + + +/* Non-member functions. These are at the end because they are not associated with any + particular class. These will be implemented as I figure out exactly what all of + them are supposed to do, and I have time. + */ + + template _UCXXEXPORT bool operator< + (const map& x, const map& y); + template _UCXXEXPORT bool operator!= + (const map& x, const map& y); + template _UCXXEXPORT bool operator> + (const map& x, const map& y); + template _UCXXEXPORT bool operator>= + (const map& x, const map& y); + template _UCXXEXPORT bool operator<= + (const map& x, const map& y); + template _UCXXEXPORT void swap + (map& x, map& y); + + + template _UCXXEXPORT bool operator== + (const multimap& x, const multimap& y); + template _UCXXEXPORT bool operator< + (const multimap& x, const multimap& y); + template _UCXXEXPORT bool operator!= + (const multimap& x, const multimap& y); + template _UCXXEXPORT bool operator> + (const multimap& x, const multimap& y); + template _UCXXEXPORT bool operator>= + (const multimap& x, const multimap& y); + template _UCXXEXPORT bool operator<= + (const multimap& x, const multimap& y); + template _UCXXEXPORT void swap + (multimap& x, multimap& y); + +} + +#pragma GCC visibility pop + +#endif + + Index: branches/slice/rev749/modules/uClibc++/include/unwind-cxx.h =================================================================== --- branches/slice/rev749/modules/uClibc++/include/unwind-cxx.h (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/unwind-cxx.h (revision 1169) @@ -0,0 +1,182 @@ +// -*- C++ -*- Exception handling and frame unwind runtime interface routines. +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This file is part of GCC. +// +// GCC is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// GCC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING. If not, write to +// the Free Software Foundation, 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// This is derived from the C++ ABI for IA-64. Where we diverge +// for cross-architecture compatibility are noted with "@@@". + +#ifndef _UNWIND_CXX_H +#define _UNWIND_CXX_H 1 + +// Level 2: C++ ABI + +#include +#include +#include +#include "unwind.h" + +#pragma GCC visibility push(default) + +namespace __cxxabiv1 +{ + +#ifdef __UCLIBCXX_EXCEPTION_SUPPORT__ + +// A C++ exception object consists of a header, which is a wrapper around +// an unwind object header with additional C++ specific information, +// followed by the exception object itself. + +struct __cxa_exception +{ + // Manage the exception object itself. + std::type_info *exceptionType; + void (*exceptionDestructor)(void *); + + // The C++ standard has entertaining rules wrt calling set_terminate + // and set_unexpected in the middle of the exception cleanup process. + std::unexpected_handler unexpectedHandler; + std::terminate_handler terminateHandler; + + // The caught exception stack threads through here. + __cxa_exception *nextException; + + // How many nested handlers have caught this exception. A negated + // value is a signal that this object has been rethrown. + int handlerCount; + + // Cache parsed handler data from the personality routine Phase 1 + // for Phase 2 and __cxa_call_unexpected. + int handlerSwitchValue; + const unsigned char *actionRecord; + const unsigned char *languageSpecificData; + _Unwind_Ptr catchTemp; + void *adjustedPtr; + + // The generic exception header. Must be last. + _Unwind_Exception unwindHeader; +}; + + // Each thread in a C++ program has access to a __cxa_eh_globals object. +struct __cxa_eh_globals +{ + __cxa_exception *caughtExceptions; + unsigned int uncaughtExceptions; +}; + + +// The __cxa_eh_globals for the current thread can be obtained by using +// either of the following functions. The "fast" version assumes at least +// one prior call of __cxa_get_globals has been made from the current +// thread, so no initialization is necessary. +extern "C" __cxa_eh_globals *__cxa_get_globals () throw(); +extern "C" __cxa_eh_globals *__cxa_get_globals_fast () throw(); +#endif + +#ifdef __UCLIBCXX_EXCEPTION_SUPPORT__ +// Allocate memory for the exception plus the thown object. +extern "C" void *__cxa_allocate_exception(std::size_t thrown_size) throw(); + +// Free the space allocated for the exception. +extern "C" void __cxa_free_exception(void *thrown_exception) throw(); + +// Throw the exception. +extern "C" void __cxa_throw (void *thrown_exception, + std::type_info *tinfo, + void (*dest) (void *)) + __attribute__((noreturn)); + +// Used to implement exception handlers. +extern "C" void *__cxa_begin_catch (void *) throw(); +extern "C" void __cxa_end_catch (); +extern "C" void __cxa_rethrow () __attribute__((noreturn)); +#endif + +// These facilitate code generation for recurring situations. +extern "C" void __cxa_bad_cast (); +extern "C" void __cxa_bad_typeid (); + +// @@@ These are not directly specified by the IA-64 C++ ABI. + +// Handles re-checking the exception specification if unexpectedHandler +// throws, and if bad_exception needs to be thrown. Called from the +// compiler. +extern "C" void __cxa_call_unexpected (void *) __attribute__((noreturn)); + +// Invokes given handler, dying appropriately if the user handler was +// so inconsiderate as to return. +extern void __terminate(std::terminate_handler) __attribute__((noreturn)); +extern void __unexpected(std::unexpected_handler) __attribute__((noreturn)); + +// The current installed user handlers. +extern std::terminate_handler __terminate_handler; +extern std::unexpected_handler __unexpected_handler; + +// These are explicitly GNU C++ specific. + +// This is the exception class we report -- "GNUCC++\0". +const _Unwind_Exception_Class __gxx_exception_class += ((((((((_Unwind_Exception_Class) 'G' + << 8 | (_Unwind_Exception_Class) 'N') + << 8 | (_Unwind_Exception_Class) 'U') + << 8 | (_Unwind_Exception_Class) 'C') + << 8 | (_Unwind_Exception_Class) 'C') + << 8 | (_Unwind_Exception_Class) '+') + << 8 | (_Unwind_Exception_Class) '+') + << 8 | (_Unwind_Exception_Class) '\0'); + +// GNU C++ personality routine, Version 0. +extern "C" _Unwind_Reason_Code __gxx_personality_v0 + (int, _Unwind_Action, _Unwind_Exception_Class, + struct _Unwind_Exception *, struct _Unwind_Context *); + +// GNU C++ sjlj personality routine, Version 0. +extern "C" _Unwind_Reason_Code __gxx_personality_sj0 + (int, _Unwind_Action, _Unwind_Exception_Class, + struct _Unwind_Exception *, struct _Unwind_Context *); + + +#ifdef __UCLIBCXX_EXCEPTION_SUPPORT__ +// Acquire the C++ exception header from the C++ object. +static inline __cxa_exception * +__get_exception_header_from_obj (void *ptr) +{ + return reinterpret_cast<__cxa_exception *>(ptr) - 1; +} + +// Acquire the C++ exception header from the generic exception header. +static inline __cxa_exception * +__get_exception_header_from_ue (_Unwind_Exception *exc) +{ + return reinterpret_cast<__cxa_exception *>(exc + 1) - 1; +} +#endif +} /* namespace __cxxabiv1 */ + +#pragma GCC visibility pop + +#endif // _UNWIND_CXX_H Index: branches/slice/rev749/modules/uClibc++/include/iomanip =================================================================== --- branches/slice/rev749/modules/uClibc++/include/iomanip (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/iomanip (revision 1169) @@ -0,0 +1,170 @@ +/* Copyright (C) 2005 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include + +#ifndef __STD_IOMANIP +#define __STD_IOMANIP 1 + +#pragma GCC visibility push(default) + +namespace std{ + +// These are the helper classes which we are going to be using to +// hold the required data + +class _UCXXEXPORT __resetiosflags{ +public: + ios_base::fmtflags m; + _UCXXEXPORT __resetiosflags(ios_base::fmtflags mask) : m(mask){ } +}; + +class _UCXXEXPORT __setiosflags{ +public: + ios_base::fmtflags m; + _UCXXEXPORT __setiosflags(ios_base::fmtflags mask) : m(mask){ } +}; + +class _UCXXEXPORT __setbase{ +public: + int base; + _UCXXEXPORT __setbase(int b) : base(b){ } +}; + +class _UCXXEXPORT __setfill{ +public: + int character; + _UCXXEXPORT __setfill(int c): character(c){ } +}; + +class _UCXXEXPORT __setprecision{ +public: + int digits; + _UCXXEXPORT __setprecision(int n): digits(n) { } +}; + +class _UCXXEXPORT __setw{ +public: + int width; + _UCXXEXPORT __setw(int n): width(n) { } +}; + + +//Actual manipulator functions + +inline __resetiosflags resetiosflags(ios_base::fmtflags mask){ + return __resetiosflags(mask); +} + +inline __setiosflags setiosflags(ios_base::fmtflags mask){ + return __setiosflags(mask); +} + +inline __setbase setbase(int b){ + return __setbase(b); +} + +inline __setfill setfill(int c){ + return __setfill(c); +} + +inline __setprecision setprecision(int n){ + return __setprecision(n); +} + +inline __setw setw(int n){ + return __setw(n); +} + + +//How to handle interaction with [i|o]stream classes + +template _UCXXEXPORT basic_ostream& + operator<<(basic_ostream& os, const __resetiosflags s) +{ + os.setf(ios_base::fmtflags(0),s.m); + return os; +} + +template _UCXXEXPORT basic_istream& + operator>>(basic_istream& is, const __resetiosflags s) +{ + is.setf(ios_base::fmtflags(0),s.m); + return is; +} + +template _UCXXEXPORT basic_ostream& + operator<<(basic_ostream& os, const __setiosflags s) +{ + os.setf(s.m); + return os; +} + +template _UCXXEXPORT basic_ostream& + operator<<(basic_ostream& os, const __setbase s) +{ + ios_base::fmtflags f(0); + switch(s.base){ + case 8: + f = ios_base::oct; + break; + case 10: + f = ios_base::dec; + break; + case 16: + f = ios_base::hex; + break; + default: + break; + + } + os.setf(f, ios_base::basefield); + return os; +} + +template _UCXXEXPORT basic_ostream& + operator<<(basic_ostream& os, const __setfill s) +{ + os.fill(s.character); + return os; +} + +template _UCXXEXPORT basic_ostream& + operator<<(basic_ostream& os, const __setprecision s) +{ + os.precision(s.digits); + return os; +} + +template _UCXXEXPORT basic_ostream& + operator<<(basic_ostream& os, const __setw s) +{ + os.width(s.width); + return os; +} + + + +} + +#pragma GCC visibility pop + +#endif + Index: branches/slice/rev749/modules/uClibc++/include/numeric =================================================================== --- branches/slice/rev749/modules/uClibc++/include/numeric (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/numeric (revision 1169) @@ -0,0 +1,161 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include + +#ifndef __STD_NUMERIC_HEADER +#define __STD_NUMERIC_HEADER 1 + +#pragma GCC visibility push(default) + +namespace std{ + template _UCXXEXPORT + T accumulate(InputIterator first, InputIterator last, T init) + { + while(first != last){ + init = init + *first; + ++first; + } + return init; + } + + template _UCXXEXPORT + T accumulate(InputIterator first, InputIterator last, T init, BinaryOperation binary_op) + { + while(first != last){ + init = binary_op(init, *first); + ++first; + } + return init; + } + + + template _UCXXEXPORT + T inner_product(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, T init) + { + while(first1 != last1){ + init = init + *first1 * *first2; + ++first1; + ++first2; + } + return init; + } + + template _UCXXEXPORT + T inner_product(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, T init, + BinaryOperation1 binary_op1, + BinaryOperation2 binary_op2) + { + while(first1 != last1){ + init = binary_op1(init, binary_op2(*first1, *first2)); + ++first1; + ++first2; + } + return init; + } + + template _UCXXEXPORT + OutputIterator partial_sum(InputIterator first, InputIterator last, + OutputIterator result) + { + OutputIterator temp(result); + *result = *first; + ++first; + ++result; + + while(first != last){ + *result = *first + *temp; + temp = result; + ++first; + ++result; + } + return result; + } + + + template _UCXXEXPORT + OutputIterator partial_sum(InputIterator first, InputIterator last, + OutputIterator result, BinaryOperation binary_op) + { + OutputIterator temp(result); + *result = *first; + ++first; + ++result; + + while(first != last){ + *result = binary_op(*first, *temp); + temp = result; + ++first; + ++result; + } + return result; + } + + + template _UCXXEXPORT + OutputIterator + adjacent_difference(InputIterator first, InputIterator last, + OutputIterator result) + { + OutputIterator temp(first); + *result = *first; + ++first; + ++result; + + while(first != last){ + *result = *first - *temp; + temp = first; + ++first; + ++result; + } + + return result; + } + + + template _UCXXEXPORT + OutputIterator + adjacent_difference(InputIterator first, InputIterator last, + OutputIterator result, BinaryOperation binary_op) + { + OutputIterator temp(first); + *result = *first; + ++first; + ++result; + + while(first != last){ + *result = binary_op(*first, *temp); + temp = first; + ++first; + ++result; + } + + return result; + } + +} + +#pragma GCC visibility pop + +#endif + Index: branches/slice/rev749/modules/uClibc++/include/utility =================================================================== --- branches/slice/rev749/modules/uClibc++/include/utility (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/utility (revision 1169) @@ -0,0 +1,88 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + + +#include + + +#ifndef __STD_HEADER_UTILITY +#define __STD_HEADER_UTILITY 1 + +#pragma GCC visibility push(default) + +namespace std{ + + namespace rel_ops { + template inline bool operator!=(const T& x, const T& y){ + return !(x == y); + } + + template inline bool operator> (const T& x, const T& y){ + return ( y < x); + } + + template inline bool operator<=(const T& x, const T& y){ + return !( y < x ); + } + + template inline bool operator>=(const T& x, const T& y){ + return !(x < y); + } + } + + template struct _UCXXEXPORT pair { + typedef T1 first_type; + typedef T2 second_type; + + T1 first; + T2 second; + pair() : first(), second() { } + pair(const T1& x, const T2& y) : first(x), second(y) { } + template pair(const pair &p) : first(p.first), second(p.second) { } + }; + + template bool operator==(const pair& x, const pair& y){ + using namespace rel_ops; + return (x.first == y.first && x.second==y.second); + } + template bool operator< (const pair& x, const pair& y){ + return x.first < y.first || (!(y.first < x.first) && x.second < y.second); + } + template bool operator!=(const pair& x, const pair& y){ + return !(x == y); + } + template bool operator> (const pair& x, const pair& y){ + return y < x; + } + template bool operator>=(const pair& x, const pair& y){ + return !(x < y); + } + template bool operator<=(const pair& x, const pair& y){ + return !(y < x); + } + template pair make_pair(const T1& x, const T2& y){ + return pair(x, y); + } + + +} + +#pragma GCC visibility pop + +#endif //__STD_HEADER_UTILITY Index: branches/slice/rev749/modules/uClibc++/include/cwchar =================================================================== --- branches/slice/rev749/modules/uClibc++/include/cwchar (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/cwchar (revision 1169) @@ -0,0 +1,86 @@ +/* Copyright (C) 2006 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation version 2.1 + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include + +#ifndef __HEADER_CWCHAR +#define __HEADER_CWCHAR 1 + + +namespace std{ + using ::mbstate_t; + using ::wint_t; + + using ::btowc; + using ::fgetwc; + using ::fgetws; + using ::fputwc; + using ::fputws; + using ::fwide; + using ::fwprintf; + using ::fwscanf; + using ::getwc; + using ::getwchar; + using ::mbrlen; + using ::mbrtowc; + using ::mbsinit; + using ::mbsrtowcs; + using ::putwc; + using ::putwchar; + using ::swprintf; + using ::swscanf; + using ::ungetwc; + using ::vfwprintf; + using ::vswprintf; + using ::vwprintf; + using ::wcrtomb; + using ::wcscat; + using ::wcschr; + using ::wcscmp; + using ::wcscoll; + using ::wcscpy; + using ::wcscspn; + using ::wcsftime; + using ::wcslen; + using ::wcsncat; + using ::wcsncmp; + using ::wcsncpy; + using ::wcspbrk; + using ::wcsrchr; + using ::wcsrtombs; + using ::wcsspn; + using ::wcsstr; + using ::wcstod; + using ::wcstok; + using ::wcstol; + using ::wcstoul; + using ::wcsxfrm; + using ::wctob; + using ::wmemchr; + using ::wmemcmp; + using ::wmemcpy; + using ::wmemmove; + using ::wmemset; + using ::wprintf; + using ::wscanf; +} + + + +#endif + Index: branches/slice/rev749/modules/uClibc++/include/type_traits =================================================================== --- branches/slice/rev749/modules/uClibc++/include/type_traits (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/type_traits (revision 1169) @@ -0,0 +1,92 @@ +/* Copyright (C) 2005 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include +#include + +#ifndef __HEADER_TYPE_TRAITS +#define __HEADER_TYPE_TRAITS 1 + +#pragma GCC visibility push(default) + +namespace std{ + + struct _UCXXEXPORT __true_type{}; + struct _UCXXEXPORT __false_type{}; + + template class _UCXXEXPORT __is_integer{ + public: + typedef __false_type value; + }; + + template <> class _UCXXEXPORT __is_integer { + public: + typedef __true_type value; + }; + + template <> class _UCXXEXPORT __is_integer { + public: + typedef __true_type value; + }; + + template <> class _UCXXEXPORT __is_integer { + public: + typedef __true_type value; + }; + + template <> class _UCXXEXPORT __is_integer { + public: + typedef __true_type value; + }; + + template <> class _UCXXEXPORT __is_integer { + public: + typedef __true_type value; + }; + + template <> class _UCXXEXPORT __is_integer { + public: + typedef __true_type value; + }; + + template <> class _UCXXEXPORT __is_integer { + public: + typedef __true_type value; + }; + + template <> class _UCXXEXPORT __is_integer { + public: + typedef __true_type value; + }; + + template <> class _UCXXEXPORT __is_integer { + public: + typedef __true_type value; + }; + + + +} + +#pragma GCC visibility pop + +#endif + Index: branches/slice/rev749/modules/uClibc++/include/memory =================================================================== --- branches/slice/rev749/modules/uClibc++/include/memory (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/memory (revision 1169) @@ -0,0 +1,196 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include +#include +#include + +#ifndef HEADER_STD_MEMORY +#define HEADER_STD_MEMORY 1 + +#pragma GCC visibility push(default) + +namespace std{ + +template class allocator; + // Specialize for void: + +template <> class _UCXXEXPORT allocator { +public: + typedef void* pointer; + typedef const void* const_pointer; + typedef void value_type; + template struct rebind { typedef allocator other; }; +}; + +template class _UCXXEXPORT allocator{ +public: + typedef T value_type; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + + typedef T* pointer; + typedef const T* const_pointer; + + typedef T& reference; + typedef const T& const_reference; + + pointer address(reference r) const { return &r; } + const_pointer address(const_reference r) const { return &r; } + + allocator() throw(){} + template allocator(const allocator& ) throw(); + ~allocator() throw(){} + + //Space for n Ts + pointer allocate(size_type n, typename allocator::const_pointer = 0){ + return (T*)(::operator new( n * sizeof(T) )); + } + void deallocate(pointer p, size_type){ + ::operator delete(p); + } + + //Use placement new to engage the constructor + void construct(pointer p, const T& val) { new((void*)p) T(val); } + void destroy(pointer p){ ((T*)p)->~T(); } //Call destructor + + size_type max_size() const throw(); + template struct rebind { typedef allocator other; }; + +}; + +template class _UCXXEXPORT raw_storage_iterator + : public iterator +{ + Out p; + +public: + explicit raw_storage_iterator(Out pp) : p (pp) { } + raw_storage_iterator & operator*() { return *this; } + raw_storage_iterator & operator=(const T& val) { + T* pp = &*p; + new(pp) T(val); + return *this; + } + + raw_storage_iterator & operator++() { ++p; return *this; } + raw_storage_iterator operator++(int) { + raw_storage_iterator t = *this; + ++p; + return t; + } +}; + +template _UCXXEXPORT pair get_temporary_buffer(ptrdiff_t n){ + pair retval; + retval.first = static_cast(malloc(n * sizeof(T))); + if(retval.first == 0){ + retval.second = 0; + }else{ + retval.second = n; + } + return retval; +} + +template _UCXXEXPORT void return_temporary_buffer(T* p){ + free(p); +} + + +template class _UCXXEXPORT auto_ptr{ + +private: + T * object; + template struct auto_ptr_ref{ + Y * p; + }; + +public: + + typedef T element_type; + + explicit auto_ptr(T* p =0) throw() : object(p){ } + auto_ptr(auto_ptr& p) throw() : object(p.release()){ } + auto_ptr(auto_ptr_ref r) throw() : object(r.p){ + r.p = 0; + } + template auto_ptr(auto_ptr& p) throw() : object(p.release()){ } + auto_ptr& operator=(auto_ptr& p) throw(){ + if(&p == this){ + return *this; + } + delete object; + object = p.release(); + return *this; + } + template auto_ptr& operator=(auto_ptr& p) throw(){ + if(&p == this){ + return *this; + } + delete object; + object = p.release(); + return *this; + } + ~auto_ptr(){ + delete object; + } + + T& operator*() const throw(){ + return *object; + } + T* operator->() const throw(){ + return object; + } + T* get() const throw(){ + return object; + } + T* release() throw(){ + T * temp(object); + object = 0; + return temp; + } + void reset(T * p=0) throw(){ + if(p != object){ + delete object; + object = p; + } + } + template operator auto_ptr_ref() throw(){ + auto_ptr_ref retval; + retval.p = object; + object = 0; + return retval; + } + template operator auto_ptr() throw(){ + auto_ptr retval(object); + object = 0; + return retval; + } + +}; + +} //namespace std + +#pragma GCC visibility pop + +#endif + Index: branches/slice/rev749/modules/uClibc++/include/set.old =================================================================== --- branches/slice/rev749/modules/uClibc++/include/set.old (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/set.old (revision 1169) @@ -0,0 +1,1535 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + + +#include +#include +#include +#include +#include + + +#ifndef __STD_HEADER_SET +#define __STD_HEADER_SET + +#pragma GCC visibility push(default) + +namespace std{ + + +template, class Allocator = allocator > class __base_set; +template, class Allocator = allocator > class set; +template, class Allocator = allocator > class multiset; + +template class __set_iter; +template class __set_citer; + +template bool operator== + (const set& x, const set& y); + +template bool operator== + (const multiset& x, const multiset& y); + + + +/* The code for the set containers is split up into two classes. + * The first class, __base_set holds all of the data and does much of the iterator-based + * work. Then the classes set and multiset inherit from there. This was done to reduce + * the redundancy of code (And thus errors which might crop up), as well as possibly + * reducing the size of binaries if both set and multiset are used, along with the same + * template parameters. + */ + + + +//All base classes first (__base_set, iterators, value_compare) and it's associated code + + +template class _UCXXEXPORT __base_set{ + +protected: + friend class __set_iter; + friend class __set_citer; + friend bool operator==<>(const set& x, const set& y); + friend bool operator==<>(const multiset& x, const multiset& y); + +public: + typedef __base_set set_type; + typedef Key key_type; + typedef Key value_type; + typedef Compare key_compare; + typedef Allocator allocator_type; + typedef typename Allocator::reference reference; + typedef typename Allocator::const_reference const_reference; + typedef __set_iter iterator; + typedef __set_citer const_iterator; + typedef typename Allocator::size_type size_type; + typedef typename Allocator::difference_type difference_type; + typedef typename Allocator::pointer pointer; + typedef typename Allocator::const_pointer const_pointer; + typedef typename std::reverse_iterator reverse_iterator; + typedef typename std::reverse_iterator const_reverse_iterator; + + class value_compare; + + explicit __base_set(const Compare& comp = Compare(), const Allocator& al = Allocator()); + __base_set(const set_type& x); + ~__base_set(); + + iterator begin(); + const_iterator begin() const; + iterator end(); + const_iterator end() const; + reverse_iterator rbegin(); + const_reverse_iterator rbegin() const; + reverse_iterator rend(); + const_reverse_iterator rend() const; + + bool empty() const; + size_type size() const; + size_type max_size() const; + + void swap(set_type & x); + void clear(); + + key_compare key_comp() const; + +protected: + + deque > data; + Compare c; + +}; + + + //Implementations + + template class _UCXXEXPORT __set_citer + : public std::iterator< + bidirectional_iterator_tag, + Key, + typename Allocator::difference_type, + typename Allocator::pointer, + typename Allocator::reference + > + { + protected: + typedef class __base_set Set; + + friend class __base_set; + friend class __base_set::iterator; + + friend class set; + friend class multiset; + + typename Set::size_type element; + const Set * container; + public: + __set_citer() : element(0), container(0) { } + __set_citer(const typename Set::const_iterator & m) + : element(m.element), container(m.container) { } + __set_citer(typename Set::size_type e, const Set * const c) + : element(e), container(c) { } + ~__set_citer() { } + + typename Set::value_type operator*(){ + return container->data[element]; + } + const typename Set::value_type * operator->() const{ + return &(container->data[element]); + } + __set_citer & operator=(const typename Set::const_iterator & m){ + element = m.element; + container = m.container; + return *this; + } + bool operator==(const typename Set::const_iterator & m) const { + return (m.element == element && m.container == container); + } + bool operator!=(const typename Set::const_iterator & m) const { + return (m.element != element || m.container != container); + } + __set_citer & operator++(){ + ++element; + return *this; + } + __set_citer operator++(int){ + __set_citer temp(*this); + ++element; + return temp; + } + __set_citer & operator--(){ + --element; + return *this; + } + __set_citer operator--(int){ + __set_citer temp(*this); + --element; + return temp; + } + + }; + + template class _UCXXEXPORT __set_iter + : public std::iterator< + bidirectional_iterator_tag, + Key, + typename Allocator::difference_type, + typename Allocator::pointer, + typename Allocator::reference + > + { + protected: + typedef __base_set Set; + + //FIXME - Find a way to use template parameters or something. This will do for now + friend class __base_set; + friend class __base_set::const_iterator; + + friend class set; + friend class multiset; + + typename Set::size_type element; + Set * container; + public: + __set_iter() : element(0), container(0) { } + __set_iter(const typename Set::iterator & m) + : element(m.element), container(m.container) { } + __set_iter(typename Set::size_type e, Set * c) + : element(e), container(c) { } + ~__set_iter() { } + + typename Set::value_type & operator*(){ + return container->data[element]; + } + const typename Set::value_type & operator*() const{ + return container->data[element]; + } + typename Set::value_type * operator->(){ + return &(container->data[element]); + } + __set_iter & operator=(const typename Set::iterator & m){ + element = m.element; + container = m.container; + return *this; + } + bool operator==(const typename Set::iterator & m) const { + return (m.element == element && m.container == container); + } + bool operator!=(const typename Set::iterator & m) const { + return (m.element != element || m.container != container); + } + bool operator==(const typename Set::const_iterator & m) const { + return (m.element == element && m.container == container); + } + bool operator!=(const typename Set::const_iterator & m) const { + return (m.element != element || m.container != container); + } + __set_iter & operator++(){ + ++element; + return *this; + } + __set_iter operator++(int){ + __set_iter temp(*this); + ++element; + return temp; + } + __set_iter & operator--(){ + --element; + return *this; + } + __set_iter operator--(int){ + __set_iter temp(*this); + --element; + return temp; + } + + //Conversion operator + operator typename Set::const_iterator () const + { + typename Set::const_iterator retval(element, container); +// return typename Set::const_iterator(element, container); + return retval; + } + }; + + + + //Compare the keys of the two items + template class _UCXXEXPORT + __base_set::value_compare : public binary_function< + typename set::value_type, + typename set::value_type, + bool> + { + friend class __base_set; + protected: + Compare comp; + value_compare(Compare c) : comp(c) { } + ~value_compare() { } + public: + bool operator()(const value_type& x, const value_type& y) const { + return comp(x, y); + } + }; + + template + __base_set::__base_set(const Compare& comp, const Allocator&) + : data(), c(comp) + { + + } + + template + __base_set::__base_set(const __base_set& x) + : data(x.data), c(x.c) + { + + } + + template + __base_set::~__base_set() + { + + } + + template + typename __base_set::iterator + __base_set::begin() + { + return iterator(0, this); + } + + template + typename __base_set::const_iterator + __base_set::begin() const + { + return const_iterator(0, this); + + } + + template + typename __base_set::iterator + __base_set::end() + { + return iterator(data.size(), this); + } + + template + typename __base_set::const_iterator + __base_set::end() const + { + return const_iterator(data.size(), this); + } + + template + typename __base_set::reverse_iterator + __base_set::rbegin() + { + return reverse_iterator(end()); + } + + template + typename __base_set::const_reverse_iterator + __base_set::rbegin() const + { + return const_reverse_iterator(end()); + } + + template + typename __base_set::reverse_iterator + __base_set::rend() + { + return reverse_iterator(begin()); + } + + template + typename __base_set::const_reverse_iterator + __base_set::rend() const + { + return const_reverse_iterator(begin()); + } + + template + bool __base_set::empty() const + { + return (data.size() == 0); + } + + template + typename __base_set::size_type + __base_set::size() const + { + return data.size(); + } + + template + typename __base_set::size_type + __base_set::max_size() const + { + return data.max_size(); + } + + + template + void __base_set::swap(__base_set& m) + { + Compare n = c; + c = m.c; + m.c = n; + + data.swap(m.data); + } + + + template + void __base_set::clear() + { + data.clear(); + } + + + template + typename __base_set::key_compare + __base_set::key_comp() const + { + return c; + } + +// value_compare value_comp() const; + + + +/* This is the implementation for the set container. As noted above, it deviates + * from ISO spec by deriving from a base class in order to reduce code redundancy. + * More code could be reduced by convirting to virtual functions (thus allowing + * much of the erase and insert code to be duplicated), but that would deviate from + * the specifications too much to be worth the risk. + */ + + + + + +//Implementation of set + + +template class _UCXXEXPORT set + : public __base_set +{ + //Default value of allocator does not meet C++ standard specs, but it works for this library + //Deal with it +public: + + typedef __base_set base; + typedef typename base::key_type key_type; + typedef typename base::value_type value_type; + typedef typename base::key_compare key_compare; + typedef typename base::allocator_type allocator_type; + typedef typename base::reference reference; + typedef typename base::const_reference const_reference; + typedef typename base::iterator iterator; + typedef typename base::const_iterator const_iterator; + typedef typename base::size_type size_type; + typedef typename base::difference_type difference_type; + typedef typename base::pointer pointer; + typedef typename base::const_pointer const_pointer; + typedef typename base::reverse_iterator reverse_iterator; + typedef typename base::const_reverse_iterator const_reverse_iterator; + + using base::value_compare; + + explicit set(const Compare& comp = Compare(), const Allocator& al = Allocator()) + : base(comp, al) { } + + template set(InputIterator first, InputIterator last, + const Compare& comp = Compare(), const Allocator& = Allocator()); + + set(const set& x) : base(x) { } + ~set() { } + + set& operator=(const set& x); + + pair insert(const value_type& x); + iterator insert(iterator position, const value_type& x); + + template void insert(InputIterator first, InputIterator last); + void erase(iterator position); + size_type erase(const key_type& x); + void erase(iterator first, iterator last); + + using base::begin; + using base::end; + using base::rbegin; + using base::rend; + + using base::empty; + using base::size; + using base::max_size; + + iterator find(const key_type& x); + const_iterator find(const key_type& x) const; + size_type count(const key_type& x) const; + iterator lower_bound(const key_type& x); + const_iterator lower_bound(const key_type& x) const; + iterator upper_bound(const key_type& x); + const_iterator upper_bound(const key_type& x) const; + pair equal_range(const key_type& x); + pair equal_range(const key_type& x) const; + +protected: + friend class base::iterator; + friend class base::const_iterator; + + iterator ifind(const key_type& x); //Core find functionality + const_iterator ifind(const key_type& x) const; //Core find functionality + + using base::data; + using base::c; + +}; + + + template template + set:: + set(InputIterator first, InputIterator last, const Compare& comp, const Allocator& al) + : base(comp, al) + { + while(first !=last){ + insert(*first); + ++first; + } + } + + template + typename set::iterator + set::ifind(const key_type &x) + { + /* This function is not from the standard. It is an internal + * utility function which returns an iterator to either the + * first matching element, or to the element before which + * an insert should be performed. Will not indicate if the + *insert should be performed before the first element + */ + + if(data.size() == 0){ + return end(); + } + + if(data.size() == 1){ + if( c(data[0], x) ){ + return end(); + } + return begin(); + } + + size_type low; + size_type high; + size_type i; + + low = 0; + high = data.size() - 1; + + //This algorithm assumes no duplicates in stored information + while(( high - low) > 1){ + i = low + ((high - low) /2); + if( c(x, data[i]) ){ + high = i; + }else{ + low = i; + } + } + + if( c(data[low], x) ){ // k >=high + i = high; + }else{ + i = low; + } + + return iterator(i, this); + } + + template + typename set::const_iterator + set::ifind(const key_type &x) const + { + /* This function is not from the standard. It is an internal + * utility function which returns an iterator to either the + * first matching element, or to the element before which + * an insert should be performed. Will not indicate if the + *insert should be performed before the first element + */ + + if(data.size() == 0){ + return end(); + } + + if(data.size() == 1){ + if( c(data[0], x) ){ + return end(); + } + return begin(); + } + + size_type low; + size_type high; + size_type i; + + low = 0; + high = data.size() - 1; + + //This algorithm assumes no duplicates in stored information + while(( high - low) > 1){ + i = low + ((high - low) /2); + if( c(x, data[i]) ){ + high = i; + }else{ + low = i; + } + } + + if( c(data[low], x) ){ // k >=high + i = high; + }else{ + i = low; + } + + return const_iterator(i, this); + } + + + template + set::set& + set::operator=(const set& x) + { + if( &x == this){ + return *this; + } + c = x.c; + data = x.data; + return *this; + } + + + template + pair::iterator, bool> + set::insert(const value_type& x) + { + pair::iterator, bool> retval; + + //Either set is empty or element to insert goes at the begining + if(data.size() == 0 || c(x, data[0]) ){ + data.push_front(x); + retval.first = begin(); + retval.second = true; + return retval; + } + + //Element to insert goes at the end + if( c(data[data.size() - 1], x) ){ + data.push_back(x); + retval.first = end(); + --retval.first; + retval.second = true; + return retval; + } + + retval.first = ifind(x); + + //No match - this should never happen + if(retval.first == end()){ + retval.second = false; + return retval; + } + + //If we have an exact match + if( !c( *(retval.first), x) && !c(x, *(retval.first) ) ){ + retval.second = false; + return retval; + } + + typename deque >::iterator q(&data, retval.first.element); + data.insert(q, x); + + retval.first = ifind(x); //Need to refind because insert can move data around + retval.second = true; + + return retval; + } + + + template + typename set::iterator + set::insert(iterator position, const value_type& x) + { + //Just reusing code. It's hard to make improvements over existing algo. + insert(x); + return find(x); + } + + template + template void + set::insert(InputIterator first, InputIterator last) + { + while(first !=last){ + insert(*first); + ++first; + } + } + + template void + set::erase(iterator position) + { + //Create a deque iterator from position information and then + //Use built in erase feature because it is handy. + typename deque >::iterator pos(&data, position.element); + data.erase(pos); + } + + template + typename set::size_type + set::erase(const key_type& x) + { + typename set::iterator i = find(x); + if(i!=end()){ + erase(i); + return 1; + } + return 0; + } + + template + void set::erase(iterator first, iterator last) + { + typename deque >::iterator f(&data, first.element); + typename deque >::iterator l(&data, last.element); + data.erase(f, l); + } + + template + typename set::iterator + set:: + find(const typename set::key_type& x) + { + if(data.size() == 0){ + return end(); + } + + iterator retval = ifind(x); + + if(retval == end()){ + return retval; + } + + //Make sure we have an exact match.... + if(!c( *retval, x) && !c(x, *retval )){ + return retval; + } + return end(); + + } + + template + typename set::const_iterator + set::find(const key_type& x) const + { + if(data.size() == 0){ + return end(); + } + + const_iterator retval = ifind(x); + + if(retval == end()){ + return retval; + } + + //Make sure we have an exact match.... + if(!c( *retval, x) && !c(x, *retval )){ + return retval; + } + return end(); + + } + + template + typename set::size_type + set::count(const typename set::key_type& x) const + { + if( find(x) == end()){ + return 0; + } + return 1; + } + + template + typename set::iterator + set::lower_bound(const key_type& x) + { + return find(x); + } + + template + typename set::const_iterator + set::lower_bound(const key_type& x) const + { + return find(x); + } + + template + typename set::iterator + set::upper_bound(const key_type& x) + { + typename set::iterator i = find(x); + if(i != end()){ + ++i; + } + return i; + } + + template + typename set::const_iterator + set::upper_bound(const key_type& x) const + { + typename set::const_iterator i = find(x); + if(i != end()){ + ++i; + } + return i; + } + + + template + pair< typename set::iterator, + typename set::iterator + > set::equal_range(const key_type& x) + { + pair< typename set::iterator, + typename set::iterator + > retval; + retval.first = lower_bound(x); + retval.second = upper_bound(x); + return retval; + } + + template + pair< typename set::const_iterator, + typename set::const_iterator + > set::equal_range(const key_type& x) const + { + pair< typename set::const_iterator, + typename set::const_iterator + > retval; + retval.first = lower_bound(x); + retval.second = upper_bound(x); + return retval; + } + + template bool operator== + (const set& x, const set& y) + { + if(x.data == y.data){ + return true; + } + return false; + } + + + +//Implementation of multiset + + +template class _UCXXEXPORT multiset + : public __base_set +{ + //Default value of allocator does not meet C++ standard specs, but it works for this library + //Deal with it +public: + + typedef __base_set base; + typedef typename base::key_type key_type; + typedef typename base::value_type value_type; + typedef typename base::key_compare key_compare; + typedef typename base::allocator_type allocator_type; + typedef typename base::reference reference; + typedef typename base::const_reference const_reference; + typedef typename base::iterator iterator; + typedef typename base::const_iterator const_iterator; + typedef typename base::size_type size_type; + typedef typename base::difference_type difference_type; + typedef typename base::pointer pointer; + typedef typename base::const_pointer const_pointer; + typedef typename base::reverse_iterator reverse_iterator; + typedef typename base::const_reverse_iterator const_reverse_iterator; + + explicit multiset(const Compare& comp = Compare(), const Allocator& al = Allocator()) + : base(comp, al) { } + + template multiset(InputIterator first, InputIterator last, + const Compare& comp = Compare(), const Allocator& = Allocator()); + + multiset(const multiset& x) : base(x) { } + ~multiset() { } + + multiset& operator=(const multiset& x); + + iterator insert(const value_type& x); + iterator insert(iterator position, const value_type& x); + template void insert(InputIterator first, InputIterator last); + + void erase(iterator position); + size_type erase(const key_type& x); + void erase(iterator first, iterator last); + + using base::begin; + using base::end; + using base::rbegin; + using base::rend; + + using base::empty; + using base::size; + using base::max_size; + + iterator find(const key_type& x); + const_iterator find(const key_type& x) const; + size_type count(const key_type& x) const; + iterator lower_bound(const key_type& x); + const_iterator lower_bound(const key_type& x) const; + iterator upper_bound(const key_type& x); + const_iterator upper_bound(const key_type& x) const; + pair equal_range(const key_type& x); + pair equal_range(const key_type& x) const; + +protected: + friend class base::iterator; + friend class base::const_iterator; + + iterator ifind(const key_type& x); //Core find functionality + const_iterator ifind(const key_type& x) const; //Core find functionality + + using base::data; + using base::c; + +}; + + + + template template + multiset:: + multiset(InputIterator first, InputIterator last, const Compare& comp, const Allocator& al) + : base(comp, al) + { + while(first !=last){ + insert(*first); + ++first; + } + } + + + template + typename multiset::iterator + multiset::ifind(const key_type &x) + { + /* This function is not from the standard. It is an internal + * utility function which returns an iterator to either the + * first matching element, or to the element before which + * an insert should be performed. end() for error. + */ + + if(data.size() == 0){ + return end(); + } + + //Before the first element + if( c(x, data[0]) ){ + return begin(); + } + + + //Element is larger than all known elemenst + if( c( data[data.size()-1], x) ){ + return end(); + } + + //Or if it is the last element + if( !c(x, data[size()-1]) ){ + return iterator(data.size()-1, this); + } + + size_type low; + size_type high; + size_type i=0; + + low = 0; + high = data.size() - 1; + + //This algorithm will accept duplicates in keys + + while( c(data[i+1], x) || c(x, data[i]) || !c(x, data[i+1]) ){ + i = low + ((high - low) /2); + if( c( x, data[i]) ){ + high = i; + }else{ + low = i; + } + } + + if( c(data[i], x) ){ // k >=high + ++i; + } + + return iterator(i, this); + } + + template + typename multiset::const_iterator + multiset::ifind(const key_type &x) const + { + /* This function is not from the standard. It is an internal + * utility function which returns an iterator to either the + * first matching element, or to the element before which + * an insert should be performed. end() for error. + */ + + if(data.size() == 0){ + return end(); + } + + //Before the first element + if( c(x, data[0]) ){ + return begin(); + } + + + //Element is larger than all known elemenst + if( c( data[data.size()-1], x) ){ + return end(); + } + + //Or if it is the last element + if( !c(x, data[size()-1]) ){ + return const_iterator(data.size()-1, this); + } + + size_type low; + size_type high; + size_type i=0; + + low = 0; + high = data.size() - 1; + + //This algorithm will accept duplicates in keys + + while( c(data[i+1], x) || c(x, data[i]) || !c(x, data[i+1]) ){ + i = low + ((high - low) /2); + if( c( x, data[i]) ){ + high = i; + }else{ + low = i; + } + } + + if( c(data[i], x) ){ // k >=high + ++i; + } + + return const_iterator(i, this); + } + + + template + typename multiset::iterator + multiset::insert(const value_type &x) + { + iterator retval; + + //Either set is empty or element to insert goes at the begining + if(data.size() == 0 || c(x, data[0]) ){ + data.push_front(x); + return begin(); + } + + //Element to insert goes at the end + if( c(data[data.size() - 1], x) ){ + data.push_back(x); + return end(); + } + + retval = ifind(x); + + //No match - this should never happen + if(retval == end()){ + return retval; + } + + if( !c(x, *retval) ){ + ++retval; + } + + typename deque >::iterator q(&data, retval.element); + data.insert(q, x); + + return retval; + } + + + template + typename multiset::iterator + multiset::insert(iterator position, const value_type& x) + { + + //Inserting at begining + if(position == begin() && !c(*position, x) ){ + data.push_front(x); + return position; + } + //Inserting at end + if(position == end() && !c(x, data[data.size() - 1]) ){ + data.push_back(x); + return position; + } + + //Inserting in middle + iterator temp = position; + --temp; + if( !c( *position, x) && !c(x, *temp) ){ + typename deque >::iterator q(&data, position.element); + data.insert(q, x); + return position; + } + + return insert(x); + } + + template + template void + multiset::insert(InputIterator first, InputIterator last) + { + while(first !=last){ + insert(*first); + ++first; + } + } + + + template void + multiset::erase(iterator position) + { + //Create a deque iterator from position information and then + //Use built in erase feature because it is handy. + typename deque >::iterator pos(&data, position.element); + data.erase(pos); + } + + + template + typename multiset::size_type + multiset::erase(const key_type& x) + { + typename multiset::iterator f = lower_bound(x); + typename multiset::iterator l = upper_bound(x); + size_type t = l.element - f.element; + erase(f, l); + return t; + } + + + template + void multiset::erase(iterator first, iterator last) + { + typename deque >::iterator f(&data, first.element); + typename deque >::iterator l(&data, last.element); + data.erase(f, l); + } + + + template + typename multiset::iterator + multiset::find(const key_type& x) + { + if(data.size() == 0){ + return end(); + } + + iterator retval = ifind(x); + + if( c(x, *retval) || c(*retval, x) ){ + return end(); + } + + return retval; + } + + + template + typename multiset::const_iterator + multiset::find(const key_type& x) const + { + if(data.size() == 0){ + return end(); + } + const_iterator retval = ifind(x); + + if( c(x, *retval) || c(*retval, x) ){ + return end(); + } + + return retval; + } + + + template + typename multiset::size_type + multiset:: + count(const typename multiset::key_type& x) const + { + pair< typename multiset::const_iterator, + typename multiset::const_iterator + > temp = equal_range(x); + + return temp.second.element - temp.first.element; + } + + + template + typename multiset::iterator + multiset::lower_bound(const key_type& x) + { + //FIXME - linear search - can we do any better? + typename multiset::iterator i = find(x); + if(i == end()){ + return i; + } + while( i.element > 0 && !c( *i, x) && !c(x, *i) ){ + --i; + } + if( c(*i, x)){ + ++i; + } + return i; + } + + template + typename multiset::const_iterator + multiset::lower_bound(const key_type& x) const + { + //FIXME - linear search - can we do any better? + typename multiset::const_iterator i = find(x); + if(i == end()){ + return i; + } + while( i.element >0 && !c( *i, x) && !c(x, *i) ){ + --i; + } + if( c( *i, x)){ + ++i; + } + return i; + } + + template + typename multiset::iterator + multiset::upper_bound(const key_type& x) + { + typename multiset::iterator i = find(x); + if(i != end()){ + ++i; + } + return i; + } + + template + typename multiset::const_iterator + multiset::upper_bound(const key_type& x) const + { + typename multiset::const_iterator i = find(x); + if(i != end()){ + ++i; + } + return i; + } + + + template + pair< typename multiset::iterator, + typename multiset::iterator + > multiset::equal_range(const key_type& x) + { + pair< typename multiset::iterator, + typename multiset::iterator + > retval; + retval.first = lower_bound(x); + retval.second = upper_bound(x); + return retval; + } + + template + pair< typename multiset::const_iterator, + typename multiset::const_iterator + > multiset::equal_range(const key_type& x) const + { + pair< typename multiset::const_iterator, + typename multiset::const_iterator + > retval; + retval.first = lower_bound(x); + retval.second = upper_bound(x); + return retval; + } + + + + +/* Non-member functions. These are at the end because they are not associated with any + particular class. These will be implemented as I figure out exactly what all of + them are supposed to do, and I have time. + */ + + template _UCXXEXPORT bool operator< + (const set& x, const set& y) + { + typename set::const_iterator first1 = x.begin(); + typename set::const_iterator first2 = y.begin(); + typename set::const_iterator last1 = x.end(); + typename set::const_iterator last2 = y.end(); + + while(first1 != last1 && first2 != last2){ + if( *first1 < *first2 ){ + return true; + } + if( *first2 < *first1 ){ + return false; + } + ++first1; + ++first2; + } + return first1==last1 && first2 != last2; + } + + template _UCXXEXPORT bool operator!= + (const set& x, const set& y) + { + typename set::const_iterator first1 = x.begin(); + typename set::const_iterator first2 = y.begin(); + typename set::const_iterator last1 = x.end(); + typename set::const_iterator last2 = y.end(); + + while(first1 != last1 && first2 != last2){ + if( *first1 != *first2 ){ + return true; + } + ++first1; + ++first2; + } + return first1!=last1 || first2 != last2; + } + + template _UCXXEXPORT bool operator> + (const set& x, const set& y) + { + typename set::const_iterator first1 = x.begin(); + typename set::const_iterator first2 = y.begin(); + typename set::const_iterator last1 = x.end(); + typename set::const_iterator last2 = y.end(); + + while(first1 != last1 && first2 != last2){ + if( *first1 > *first2 ){ + return true; + } + if( *first2 > *first1 ){ + return false; + } + ++first1; + ++first2; + } + return first1!=last1 && first2 == last2; + } + + template _UCXXEXPORT bool operator>= + (const set& x, const set& y) + { + typename set::const_iterator first1 = x.begin(); + typename set::const_iterator first2 = y.begin(); + typename set::const_iterator last1 = x.end(); + typename set::const_iterator last2 = y.end(); + + while(first1 != last1 && first2 != last2){ + if( *first1 > *first2 ){ + return true; + } + if( *first2 > *first1 ){ + return false; + } + ++first1; + ++first2; + } + return first1!=last1; + } + + template _UCXXEXPORT bool operator<= + (const set& x, const set& y) + { + typename set::const_iterator first1 = x.begin(); + typename set::const_iterator first2 = y.begin(); + typename set::const_iterator last1 = x.end(); + typename set::const_iterator last2 = y.end(); + + while(first1 != last1 && first2 != last2){ + if( *first1 < *first2 ){ + return true; + } + if( *first2 < *first1 ){ + return false; + } + ++first1; + ++first2; + } + return first2!=last2; + } + template _UCXXEXPORT void swap + (set& x, set& y) + { + x.swap(y); + } + + + template _UCXXEXPORT bool operator== + (const multiset& x, const multiset& y) + { + if(x.data == y.data){ + return true; + } + return false; + } + + template _UCXXEXPORT bool operator< + (const multiset& x, const multiset& y) + { + typename multiset::const_iterator first1 = x.begin(); + typename multiset::const_iterator first2 = y.begin(); + typename multiset::const_iterator last1 = x.end(); + typename multiset::const_iterator last2 = y.end(); + + while(first1 != last1 && first2 != last2){ + if( *first1 < *first2 ){ + return true; + } + if( *first2 < *first1 ){ + return false; + } + ++first1; + ++first2; + } + return first1==last1 && first2 != last2; + } + + template _UCXXEXPORT bool operator!= + (const multiset& x, const multiset& y) + { + typename multiset::const_iterator first1 = x.begin(); + typename multiset::const_iterator first2 = y.begin(); + typename multiset::const_iterator last1 = x.end(); + typename multiset::const_iterator last2 = y.end(); + + while(first1 != last1 && first2 != last2){ + if( *first1 != *first2 ){ + return true; + } + ++first1; + ++first2; + } + return first1!=last1 || first2 != last2; + } + + template _UCXXEXPORT bool operator> + (const multiset& x, const multiset& y) + { + typename multiset::const_iterator first1 = x.begin(); + typename multiset::const_iterator first2 = y.begin(); + typename multiset::const_iterator last1 = x.end(); + typename multiset::const_iterator last2 = y.end(); + + while(first1 != last1 && first2 != last2){ + if( *first1 > *first2 ){ + return true; + } + if( *first2 > *first1 ){ + return false; + } + ++first1; + ++first2; + } + return first1!=last1 && first2 == last2; + } + + template _UCXXEXPORT bool operator>= + (const multiset& x, const multiset& y) + { + typename multiset::const_iterator first1 = x.begin(); + typename multiset::const_iterator first2 = y.begin(); + typename multiset::const_iterator last1 = x.end(); + typename multiset::const_iterator last2 = y.end(); + + while(first1 != last1 && first2 != last2){ + if( *first1 > *first2 ){ + return true; + } + if( *first2 > *first1 ){ + return false; + } + ++first1; + ++first2; + } + return first1!=last1; + } + + template _UCXXEXPORT bool operator<= + (const multiset& x, const multiset& y) + { + typename multiset::const_iterator first1 = x.begin(); + typename multiset::const_iterator first2 = y.begin(); + typename multiset::const_iterator last1 = x.end(); + typename multiset::const_iterator last2 = y.end(); + + while(first1 != last1 && first2 != last2){ + if( *first1 < *first2 ){ + return true; + } + if( *first2 < *first1 ){ + return false; + } + ++first1; + ++first2; + } + return first2!=last2; + } + + template _UCXXEXPORT void swap + (multiset& x, multiset& y) + { + x.swap(y); + } + + + +} + +#pragma GCC visibility pop + +#endif + + Index: branches/slice/rev749/modules/uClibc++/include/cstddef =================================================================== --- branches/slice/rev749/modules/uClibc++/include/cstddef (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/cstddef (revision 1169) @@ -0,0 +1,58 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 1997, 1998, 1999, 2000, 2002 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// +// ISO C++ 14882: 18.1 Types +// + +/** @file cstddef + * This is a Standard C++ Library file. You should @c #include this file + * in your programs, rather than any of the "*.h" implementation files. + * + * This is the C++ version of the Standard C Library header @c stddef.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std. + */ + +#ifndef _CPP_CSTDDEF +#define _CPP_CSTDDEF 1 + +#ifdef __GCC__ +#pragma GCC system_header +#endif + +#include + +namespace std +{ + using ::ptrdiff_t; + using ::size_t; +} + +#endif Index: branches/slice/rev749/modules/uClibc++/include/Makefile =================================================================== --- branches/slice/rev749/modules/uClibc++/include/Makefile (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/Makefile (revision 1169) @@ -0,0 +1,13 @@ +TOPDIR=../ +include $(TOPDIR)Rules.mak + +all: + +clean: + +distclean: + +HEADERS = $(filter-out .svn CVS Makefile,$(wildcard *)) +install: + $(INSTALL) -d $(PREFIX)$(UCLIBCXX_RUNTIME_INCLUDEDIR) + $(INSTALL) -m 644 $(HEADERS) $(PREFIX)$(UCLIBCXX_RUNTIME_INCLUDEDIR) Index: branches/slice/rev749/modules/uClibc++/include/map =================================================================== --- branches/slice/rev749/modules/uClibc++/include/map (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/map (revision 1169) @@ -0,0 +1,261 @@ +/* Copyright (C) 2004-2007 Garrett A. Kajmowicz + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + + +#include +#include +#include +#include +#include +#include + + +#ifndef __STD_HEADER_MAP +#define __STD_HEADER_MAP + +#pragma GCC visibility push(default) + +namespace std{ + + +template, class Allocator = allocator > class map; +template, class Allocator = allocator > class multimap; + + + //Compare the keys of the two items +/* template class _UCXXEXPORT + __base_map::value_compare : public binary_function< + typename map::value_type, + typename map::value_type, + bool> + { + friend class __base_map; + protected: + Compare comp; + value_compare(Compare c) : comp(c) { } + ~value_compare() { } + public: + bool operator()(const value_type& x, const value_type& y) const { + return comp(x.first, y.first); + } + }; +*/ + +// value_compare value_comp() const; + + + +/* This is the implementation for the map container. As noted above, it deviates + * from ISO spec by deriving from a base class in order to reduce code redundancy. + * More code could be reduced by convirting to virtual functions (thus allowing + * much of the erase and insert code to be duplicated), but that would deviate from + * the specifications too much to be worth the risk. + */ + + + +//Implementation of map + + +template class _UCXXEXPORT map + : public __single_associative, Compare, Allocator> +{ + //Default value of allocator does not meet C++ standard specs, but it works for this library + //Deal with it + +public: + + typedef __single_associative, Compare, Allocator> base; + typedef T mapped_type; + typedef typename base::key_type key_type; + typedef typename base::value_type value_type; + typedef typename base::key_compare key_compare; + typedef typename base::allocator_type allocator_type; + typedef typename base::reference reference; + typedef typename base::const_reference const_reference; + typedef typename base::iterator iterator; + typedef typename base::const_iterator const_iterator; + typedef typename base::size_type size_type; + typedef typename base::difference_type difference_type; + typedef typename base::pointer pointer; + typedef typename base::const_pointer const_pointer; + typedef typename base::reverse_iterator reverse_iterator; + typedef typename base::const_reverse_iterator const_reverse_iterator; + + static const key_type v_t_k(const value_type v){ + return v.first; + } + +// using base::value_compare; + + explicit map(const Compare& comp = Compare(), const Allocator& al = Allocator()) + : base(comp, al, v_t_k) { } + + template map(InputIterator first, InputIterator last, + const Compare& comp = Compare(), const Allocator& al = Allocator()) + : base(first, last, comp, al, v_t_k) { } + + map(const map& x) : base(x) { } + ~map() { } + + using base::operator=; + using base::operator==; + using base::operator!=; + + using base::insert; + using base::erase; + + using base::begin; + using base::end; + using base::rbegin; + using base::rend; + + using base::empty; + using base::size; + using base::max_size; + + using base::find; + using base::count; + using base::lower_bound; + using base::upper_bound; + using base::equal_range; + + reference operator[](const key_type& k){ + //This is from the spec and is quite ugly. + return (*((insert(make_pair(k, T()))).first)).second; + } + +protected: + using base::backing; +}; + + +//Implementation of multimap + + +template class _UCXXEXPORT multimap + : public __multi_associative, Compare, Allocator> + +{ + //Default value of allocator does not meet C++ standard specs, but it works for this library + //Deal with it +public: + + typedef __multi_associative, Compare, Allocator> base; + typedef T mapped_type; + typedef typename base::key_type key_type; + typedef typename base::value_type value_type; + typedef typename base::key_compare key_compare; + typedef typename base::allocator_type allocator_type; + typedef typename base::reference reference; + typedef typename base::const_reference const_reference; + typedef typename base::iterator iterator; + typedef typename base::const_iterator const_iterator; + typedef typename base::size_type size_type; + typedef typename base::difference_type difference_type; + typedef typename base::pointer pointer; + typedef typename base::const_pointer const_pointer; + typedef typename base::reverse_iterator reverse_iterator; + typedef typename base::const_reverse_iterator const_reverse_iterator; + + static const key_type v_t_k(const value_type v){ + return v.first; + } + + explicit multimap(const Compare& comp = Compare(), const Allocator& al = Allocator()) + : base(comp, al, v_t_k) { } + + template multimap(InputIterator first, InputIterator last, + const Compare& comp = Compare(), const Allocator& al = Allocator()) + : base(first, last, comp, al, v_t_k) { } + + + multimap(const multimap& x) : base(x) { } + ~multimap() { } + + using base::operator=; + using base::operator==; + using base::operator!=; + + using base::insert; + using base::erase; + + using base::begin; + using base::end; + using base::rbegin; + using base::rend; + + using base::empty; + using base::size; + using base::max_size; + + using base::find; + using base::count; + using base::lower_bound; + using base::upper_bound; + using base::equal_range; + +protected: + + using base::c; + +}; + + +/* Non-member functions. These are at the end because they are not associated with any + particular class. These will be implemented as I figure out exactly what all of + them are supposed to do, and I have time. + */ + + template _UCXXEXPORT bool operator< + (const map& x, const map& y); + template _UCXXEXPORT bool operator!= + (const map& x, const map& y); + template _UCXXEXPORT bool operator> + (const map& x, const map& y); + template _UCXXEXPORT bool operator>= + (const map& x, const map& y); + template _UCXXEXPORT bool operator<= + (const map& x, const map& y); + template _UCXXEXPORT void swap + (map& x, map& y); + + + template _UCXXEXPORT bool operator== + (const multimap& x, const multimap& y); + template _UCXXEXPORT bool operator< + (const multimap& x, const multimap& y); + template _UCXXEXPORT bool operator!= + (const multimap& x, const multimap& y); + template _UCXXEXPORT bool operator> + (const multimap& x, const multimap& y); + template _UCXXEXPORT bool operator>= + (const multimap& x, const multimap& y); + template _UCXXEXPORT bool operator<= + (const multimap& x, const multimap& y); + template _UCXXEXPORT void swap + (multimap& x, multimap& y); + +} + +#pragma GCC visibility pop + +#endif + + Index: branches/slice/rev749/modules/uClibc++/include/cstdlib =================================================================== --- branches/slice/rev749/modules/uClibc++/include/cstdlib (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/cstdlib (revision 1169) @@ -0,0 +1,71 @@ +/* Copyright (C) 2005 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include + +#ifndef __HEADER_CSTDLIB +#define __HEADER_CSTDLIB 1 + + +namespace std{ + using ::abort; + using ::abs; + using ::atexit; + using ::atol; + using ::atof; + using ::atoi; + using ::bsearch; + using ::calloc; + using ::div; + using ::exit; + using ::free; + using ::getenv; + using ::labs; + using ::ldiv; + using ::malloc; + using ::qsort; + using ::rand; + using ::realloc; + using ::srand; + using ::strtod; + using ::strtol; + using ::strtoul; + using ::system; +#ifdef __UCLIBCXX_HAS_WCHAR__ + using ::mblen; + using ::mbstowcs; + using ::mbtowc; + using ::wctomb; + using ::wcstombs; +#endif + + inline long abs(long i){ + return labs(i); + } + + inline ldiv_t div(long i, long j){ + return ldiv(i, j); + } + +} + + + +#endif + Index: branches/slice/rev749/modules/uClibc++/include/cctype =================================================================== --- branches/slice/rev749/modules/uClibc++/include/cctype (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/cctype (revision 1169) @@ -0,0 +1,37 @@ +/* Copyright (C) 2006 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include + +namespace std{ + + using ::isalnum; + using ::isalpha; + using ::iscntrl; + using ::isdigit; + using ::isgraph; + using ::islower; + using ::isprint; + using ::ispunct; + using ::isspace; + using ::isupper; + using ::isxdigit; + using ::tolower; + using ::toupper; + +} Index: branches/slice/rev749/modules/uClibc++/include/iterator =================================================================== --- branches/slice/rev749/modules/uClibc++/include/iterator (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/iterator (revision 1169) @@ -0,0 +1,229 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include +#include + + + +#ifndef __STD_HEADER_ITERATOR +#define __STD_HEADER_ITERATOR 1 + +#pragma GCC visibility push(default) + +namespace std{ + + // subclause _lib.stream.iterators_, stream iterators: + template , class Distance = ptrdiff_t> class istream_iterator; + template bool + operator==(const istream_iterator& x, const istream_iterator& y); + template bool + operator!=(const istream_iterator& x, const istream_iterator& y); + template > class ostream_iterator; + template > class istreambuf_iterator; + template bool + operator==(const istreambuf_iterator& a, const istreambuf_iterator& b); + template bool + operator!=(const istreambuf_iterator& a, const istreambuf_iterator& b); + template > class ostreambuf_iterator; + + + template < class T, class charT, class traits, class Distance > class _UCXXEXPORT istream_iterator + : public iterator + { + public: + typedef charT char_type; + typedef traits traits_type; + typedef basic_istream istream_type; + istream_iterator() : in_stream(0), value(0) {} + istream_iterator(istream_type& s) : in_stream(&s), value() { + *in_stream >> value; + } + istream_iterator(const istream_iterator& x) + : in_stream(x.in_stream), value(x.value) + { } + ~istream_iterator() { } + const T& operator*() const{ + return value; + } + const T* operator->() const{ + return &value; + } + istream_iterator& operator++() { + *in_stream >> value; + return *this; + } + istream_iterator operator++(int){ + istream_iterator tmp = *this; + *in_stream >> value; + return (tmp); + } + bool m_equal(const istream_iterator& x) const{ + return (in_stream == x.in_stream); + } + private: + basic_istream* in_stream; + T value; + }; + + template _UCXXEXPORT + bool operator==(const istream_iterator& x, + const istream_iterator& y) + { + return x.m_equal(y); + } + + template _UCXXEXPORT + bool operator!=(const istream_iterator& x, + const istream_iterator& y) + { + return !(x == y); + } + + template class _UCXXEXPORT ostream_iterator + : public iterator + { + public: + typedef charT char_type; + typedef traits traits_type; + typedef basic_ostream ostream_type; + + ostream_iterator(ostream_type& s) : out_stream(&s), delim(0) { } + ostream_iterator(ostream_type& s, const charT* delimiter) : out_stream(&s), delim(delimiter) { } + ostream_iterator(const ostream_iterator& x) : out_stream(x.out_stream), delim(x.delim) { } + ~ostream_iterator() { } + ostream_iterator& operator=(const T& value){ + *out_stream << value; + if(delim != 0){ + *out_stream << delim; + } + return (*this); + } + ostream_iterator& operator*(){ return *this; } + ostream_iterator& operator++() { return *this; } + ostream_iterator operator++(int) { return *this; } + private: + basic_ostream* out_stream; + const char* delim; + }; + + template class _UCXXEXPORT istreambuf_iterator : + public iterator + { + public: + typedef charT char_type; + typedef traits traits_type; + typedef typename traits::int_type int_type; + typedef basic_streambuf streambuf_type; + typedef basic_istream istream_type; + + class _UCXXEXPORT proxy{ + charT val; + basic_streambuf * buf; + + proxy(charT v, basic_streambuf * b) : val(v), buf(b) { } + public: + charT operator*() { return val; } + }; + + istreambuf_iterator() throw() : sbuf(0) { } + istreambuf_iterator(istream_type& s) throw() : sbuf(s.rdbuf()) { } + istreambuf_iterator(streambuf_type* s) throw() : sbuf(s) { } + istreambuf_iterator(const proxy& p) throw() : sbuf(&p.buf) { } + + charT operator*() const{ + return sbuf->sgetc(); + } + istreambuf_iterator& operator++(){ + sbuf->sbumpc(); + return *this; + } + proxy operator++(int){ + istreambuf_iterator tmp = *this; + sbuf->sbumpc(); + return(tmp); + } + + bool equal(const istreambuf_iterator& b) const{ + return sbuf == b.sbuf || is_eof() && b.is_eof(); + } + private: + streambuf_type* sbuf; + inline bool is_eof() const{ + return sbuf == 0 || sbuf->sgetc() == traits_type::eof(); + } + }; + + template _UCXXEXPORT bool + operator==(const istreambuf_iterator& a, + const istreambuf_iterator& b) + { + return a.equal(b); + } + + template bool _UCXXEXPORT + operator!=(const istreambuf_iterator& a, + const istreambuf_iterator& b) + { + return !a.equal(b); + } + + template class _UCXXEXPORT ostreambuf_iterator + : iterator + { + public: + typedef charT char_type; + typedef traits traits_type; + typedef basic_streambuf streambuf_type; + typedef basic_ostream ostream_type; + public: + ostreambuf_iterator(ostream_type& s) throw() : sbuf(s.rdbuf()), f(false) { } + ostreambuf_iterator(streambuf_type* s) throw() : sbuf(s), f(false) { } + ostreambuf_iterator& operator=(charT c){ + if(failed() == false){ + if(sbuf->sputc(c) == traits::eof()){ + f = true; + } + } + return *this; + } + ostreambuf_iterator& operator*(){ + return *this; + } + ostreambuf_iterator& operator++() { return *this; } + ostreambuf_iterator operator++(int) { return *this; } + bool failed() const throw(){ + return f; + } + + private: + streambuf_type* sbuf; + bool f; + }; + +} + +#pragma GCC visibility pop + +#endif + + Index: branches/slice/rev749/modules/uClibc++/include/bitset =================================================================== --- branches/slice/rev749/modules/uClibc++/include/bitset (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/bitset (revision 1169) @@ -0,0 +1,423 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include +#include +#include + +#ifndef __STD_BITSET_HEADER +#define __STD_BITSET_HEADER 1 + +#pragma GCC visibility push(default) + +namespace std{ + template class bitset; + + + template bitset operator&(const bitset&, const bitset&); + template bitset operator|(const bitset&, const bitset&); + template bitset operator^(const bitset&, const bitset&); + template basic_istream& + operator>>(basic_istream& is, bitset& x); + + template basic_ostream& + operator<<(basic_ostream& os, const bitset& x); + + //Actual Code + + + template class _UCXXEXPORT bitset { + private: + //Number of characters allocated to hold the bits + static const size_t WORD_SIZE = CHAR_BIT; //Use int maybe? + static const size_t num_bytes = (N + WORD_SIZE - 1) / WORD_SIZE; + + //From the bit number, figure out which byte we are working with + size_t byte_num(size_t bit_num) const{ + if(WORD_SIZE == 8){ + return (bit_num >> 3); + } + if(WORD_SIZE == 16){ + return (bit_num >> 4); + } + if(WORD_SIZE == 32){ + return (bit_num >> 5); + } + if(WORD_SIZE == 64){ + return (bit_num >> 6); + } + return bit_num / WORD_SIZE; + } + //From the bit number, figure out which bit inside the byte we need + size_t bit_num(const size_t bit_num) const{ + return bit_num % WORD_SIZE; + } + + + //Point to the actual data + char data[num_bytes]; + public: + + class _UCXXEXPORT reference { + friend class bitset; + reference() : bit_num(0), parent(0) { } + size_t bit_num; + bitset * parent; + public: + ~reference() { } + reference& operator=(bool x){ // for b[i] = x; + parent->set(bit_num, x); + return *this; + } + reference& operator=(const reference& x){ // for b[i] = b[j]; + parent->set(bit_num, x); + return *this; + } + bool operator~() const{ // flips the bit + return !parent->test(bit_num); + } + operator bool() const{ // for x = b[i]; + return parent->test(bit_num); + } + reference& flip(){ // for b[i].flip(); + parent->flip(bit_num); + return *this; + } + }; + + bitset(){ + reset(); + } + bitset(unsigned long val){ + reset(); + size_t count = sizeof(val) * CHAR_BIT; + if(count > N){ + count = N; + } + for(size_t i = 0; i < count; ++i){ + set(i, ((val >> i) & 1)); + } + } + + bitset(const bitset & val){ + for(size_t i = 0; i < num_bytes; ++i){ + data[i] = val.data[i]; + } + } + + template _UCXXEXPORT + explicit bitset( + const basic_string& str, + typename basic_string::size_type pos = 0, + typename basic_string::size_type n = + basic_string::npos + + ){ + reset(); + if(n > str.length()){ + n = str.length(); + } + size_t width = n; + if (width + pos > str.length()){ + width = str.length() - pos; + } + + for(size_t i = 0; i < width; ++i){ + switch(str[pos + width - i - 1]){ + case '0': + break; + case '1': + set(i); + break; + default: + __throw_invalid_argument(); + } + } + } + + bitset& operator&=(const bitset& rhs){ + for(size_t i =0; i < num_bytes; ++i){ + data[i] &= rhs.data[i]; + } + return *this; + } + + bitset& operator|=(const bitset& rhs){ + for(size_t i =0; i < num_bytes; ++i){ + data[i] |= rhs.data[i]; + } + return *this; + } + bitset& operator^=(const bitset& rhs){ + for(size_t i=0; i < num_bytes; ++i){ + data[i] ^= rhs.data[i]; + } + return *this; + } + + bitset& operator<<=(size_t pos){ + for(size_t i = N-1; i >=pos; --i){ + set(i, test(i - pos)); + } + for(size_t i = 0; i < pos; ++i){ + reset(i); + } + return *this; + } + + bitset& operator>>=(size_t pos){ + for(size_t i = 0; i < (N - pos); ++i){ + set(i, test(i + pos)); + } + for(size_t i = pos; i > 0; --i){ + reset(N - i); + } + return *this; + } + + bitset& set(){ + size_t i; + for(i = 0; i < N ; ++i){ + data[byte_num(i)] |= (1<& set(size_t pos, int val = true){ + if(val == true){ + data[byte_num(pos)] |= (1<& reset(){ + for(size_t i = 0; i <= num_bytes; ++i){ + data[i] = 0; + } + return *this; + } + bitset& reset(size_t pos){ + data[byte_num(pos)] &= ~(1< operator~() const{ + bitset retval(*this); + retval.flip(); + return retval; + } + + bitset& flip(){ + for(size_t i = 0; i <= num_bytes; ++i){ + data[i] = ~data[i]; + } + return *this; + } + bitset& flip(size_t pos){ + char temp = data[byte_num(pos)] & (1 << bit_num(pos)); + if(temp == 0){ //Bit was 0 + data[byte_num(pos)] |= (1 << bit_num(pos)); + }else{ //Bit was 1 + data[byte_num(pos)] &= ~(1< sizeof(unsigned long) * CHAR_BIT){ + __throw_overflow_error(); + } + unsigned long retval = 0; + size_t count = N; + for(size_t i = count; i > 0; --i){ + if(test(i)){ + retval +=1; + } + retval<<=1; + } + if(test(0)){ + retval +=1; + } + return retval; + } + + template + basic_string to_string() const + { + basic_string retval; + retval.reserve(N); + for(size_t i = N ; i > 0; --i){ + if(test(i-1) == true){ + retval.append("1"); + }else{ + retval.append("0"); + } + } + return retval; + } + + + size_t count() const{ + size_t retval = 0; + for(size_t i =0; i < N; ++i){ + if(test(i)){ + ++retval; + } + } + return retval; + } + size_t size() const{ + return N; + } + + bitset& operator=(const bitset & rhs){ + if(&rhs == this){ + return *this; + } + for(size_t i = 0; i <= byte_num(N); ++i){ + data[i] = rhs.data[i]; + } + return *this; + } + + + bool operator==(const bitset& rhs) const{ + for(size_t i =0; i< N; ++i){ + if(test(i) != rhs.test(i)){ + return false; + } + } + return true; + } + + bool operator!=(const bitset& rhs) const{ + for(size_t i =0; i< N; ++i){ + if(test(i) != rhs.test(i)){ + return true; + } + } + return false; + } + + bool test(size_t pos) const{ + return (data[byte_num(pos)] & (1< operator<<(size_t pos) const{ + bitset retval(*this); + retval<<=pos; + return retval; + } + bitset operator>>(size_t pos) const{ + bitset retval(*this); + retval>>=pos; + return retval; + } + }; + + //Non-member functions + + + template _UCXXEXPORT bitset operator&(const bitset& lhs, const bitset& rhs){ + bitset retval(lhs); + retval &= rhs; + return retval; + } + + template _UCXXEXPORT bitset operator|(const bitset& lhs, const bitset& rhs){ + bitset retval(lhs); + retval |= rhs; + return retval; + } + + template _UCXXEXPORT bitset operator^(const bitset& lhs, const bitset& rhs){ + bitset retval(lhs); + retval ^= rhs; + return retval; + } + + template _UCXXEXPORT basic_istream& + operator>>(basic_istream& is, bitset& x) + { + string s; + charT c; + for(size_t i = 0; i < N; ++i){ + is.get(c); + if(!is.good()){ + break; + } + if(c != '1' && c !='0'){ + is.putback(c); + break; + } + s+=c; + } + bitset temp(s); + x = temp; + + return is; + } + + template _UCXXEXPORT basic_ostream& + operator<<(basic_ostream& os, const bitset& x) + { + for(size_t i = N ; i > 0; --i){ + if(x.test(i-1) == true){ + os << "1"; + }else{ + os << "0"; + } + } + return os; + } + + + + +} + +#pragma GCC visibility pop + +#endif + Index: branches/slice/rev749/modules/uClibc++/include/set =================================================================== --- branches/slice/rev749/modules/uClibc++/include/set (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/set (revision 1169) @@ -0,0 +1,407 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + + +#include +#include +#include +#include +#include +#include + +#ifndef __STD_HEADER_SET +#define __STD_HEADER_SET + +#pragma GCC visibility push(default) + +namespace std{ + + +template, class Allocator = allocator > class set; +template, class Allocator = allocator > class multiset; + + +/* This is the implementation for the set container. As noted above, it deviates + * from ISO spec by deriving from a base class in order to reduce code redundancy. + * More code could be reduced by convirting to virtual functions (thus allowing + * much of the erase and insert code to be duplicated), but that would deviate from + * the specifications too much to be worth the risk. + */ + + +//Implementation of set + + +template class _UCXXEXPORT set + : public __single_associative +{ + //Default value of allocator does not meet C++ standard specs, but it works for this library + //Deal with it +public: + + typedef __single_associative base; + typedef typename base::key_type key_type; + typedef typename base::value_type value_type; + typedef typename base::key_compare key_compare; + typedef typename base::allocator_type allocator_type; + typedef typename base::reference reference; + typedef typename base::const_reference const_reference; + typedef typename base::iterator iterator; + typedef typename base::const_iterator const_iterator; + typedef typename base::size_type size_type; + typedef typename base::difference_type difference_type; + typedef typename base::pointer pointer; + typedef typename base::const_pointer const_pointer; + typedef typename base::reverse_iterator reverse_iterator; + typedef typename base::const_reverse_iterator const_reverse_iterator; + +// using base::value_compare; + + static const key_type v_t_k(const value_type v){ + return v; + } + + explicit set(const Compare& comp = Compare(), const Allocator& al = Allocator()) + : base(comp, al, v_t_k) { } + + template set(InputIterator first, InputIterator last, + const Compare& comp = Compare(), const Allocator& al = Allocator()) + : base(first, last, comp, al, v_t_k) { } + + set(const set& x) : base(x) { } + ~set() { } + + using base::operator=; + using base::operator==; + using base::operator!=; + + using base::insert; + using base::erase; + + using base::begin; + using base::end; + using base::rbegin; + using base::rend; + + using base::empty; + using base::size; + using base::max_size; + + + using base::find; + using base::count; + using base::lower_bound; + using base::upper_bound; + using base::equal_range; + +protected: + +}; + + +//Implementation of multiset + + +template class _UCXXEXPORT multiset + : public __multi_associative +{ + //Default value of allocator does not meet C++ standard specs, but it works for this library + //Deal with it +public: + + typedef __multi_associative base; + typedef typename base::key_type key_type; + typedef typename base::value_type value_type; + typedef typename base::key_compare key_compare; + typedef typename base::allocator_type allocator_type; + typedef typename base::reference reference; + typedef typename base::const_reference const_reference; + typedef typename base::iterator iterator; + typedef typename base::const_iterator const_iterator; + typedef typename base::size_type size_type; + typedef typename base::difference_type difference_type; + typedef typename base::pointer pointer; + typedef typename base::const_pointer const_pointer; + typedef typename base::reverse_iterator reverse_iterator; + typedef typename base::const_reverse_iterator const_reverse_iterator; + + static const key_type v_t_k(const value_type v){ + return v; + } + + explicit multiset(const Compare& comp = Compare(), const Allocator& al = Allocator()) + : base(comp, al, v_t_k) { } + + template multiset(InputIterator first, InputIterator last, + const Compare& comp = Compare(), const Allocator& al = Allocator()) + : base(first, last, comp, al, v_t_k) { } + + + multiset(const multiset& x) : base(x) { } + ~multiset() { } + + using base::operator=; + using base::operator==; + using base::operator!=; + + using base::insert; + using base::erase; + + using base::begin; + using base::end; + using base::rbegin; + using base::rend; + + using base::empty; + using base::size; + using base::max_size; + + using base::find; + using base::count; + using base::lower_bound; + using base::upper_bound; + using base::equal_range; + + +protected: + +}; + + +/* Non-member functions. These are at the end because they are not associated with any + particular class. These will be implemented as I figure out exactly what all of + them are supposed to do, and I have time. + */ + + template _UCXXEXPORT bool operator< + (const set& x, const set& y) + { + typename set::const_iterator first1 = x.begin(); + typename set::const_iterator first2 = y.begin(); + typename set::const_iterator last1 = x.end(); + typename set::const_iterator last2 = y.end(); + + while(first1 != last1 && first2 != last2){ + if( *first1 < *first2 ){ + return true; + } + if( *first2 < *first1 ){ + return false; + } + ++first1; + ++first2; + } + return first1==last1 && first2 != last2; + } + + template _UCXXEXPORT bool operator> + (const set& x, const set& y) + { + typename set::const_iterator first1 = x.begin(); + typename set::const_iterator first2 = y.begin(); + typename set::const_iterator last1 = x.end(); + typename set::const_iterator last2 = y.end(); + + while(first1 != last1 && first2 != last2){ + if( *first1 > *first2 ){ + return true; + } + if( *first2 > *first1 ){ + return false; + } + ++first1; + ++first2; + } + return first1!=last1 && first2 == last2; + } + + template _UCXXEXPORT bool operator>= + (const set& x, const set& y) + { + typename set::const_iterator first1 = x.begin(); + typename set::const_iterator first2 = y.begin(); + typename set::const_iterator last1 = x.end(); + typename set::const_iterator last2 = y.end(); + + while(first1 != last1 && first2 != last2){ + if( *first1 > *first2 ){ + return true; + } + if( *first2 > *first1 ){ + return false; + } + ++first1; + ++first2; + } + return first1!=last1; + } + + template _UCXXEXPORT bool operator<= + (const set& x, const set& y) + { + typename set::const_iterator first1 = x.begin(); + typename set::const_iterator first2 = y.begin(); + typename set::const_iterator last1 = x.end(); + typename set::const_iterator last2 = y.end(); + + while(first1 != last1 && first2 != last2){ + if( *first1 < *first2 ){ + return true; + } + if( *first2 < *first1 ){ + return false; + } + ++first1; + ++first2; + } + return first2!=last2; + } + template _UCXXEXPORT void swap + (set& x, set& y) + { + x.swap(y); + } + + + template _UCXXEXPORT bool operator== + (const multiset& x, const multiset& y) + { + if(x.data == y.data){ + return true; + } + return false; + } + + template _UCXXEXPORT bool operator< + (const multiset& x, const multiset& y) + { + typename multiset::const_iterator first1 = x.begin(); + typename multiset::const_iterator first2 = y.begin(); + typename multiset::const_iterator last1 = x.end(); + typename multiset::const_iterator last2 = y.end(); + + while(first1 != last1 && first2 != last2){ + if( *first1 < *first2 ){ + return true; + } + if( *first2 < *first1 ){ + return false; + } + ++first1; + ++first2; + } + return first1==last1 && first2 != last2; + } + + template _UCXXEXPORT bool operator!= + (const multiset& x, const multiset& y) + { + typename multiset::const_iterator first1 = x.begin(); + typename multiset::const_iterator first2 = y.begin(); + typename multiset::const_iterator last1 = x.end(); + typename multiset::const_iterator last2 = y.end(); + + while(first1 != last1 && first2 != last2){ + if( *first1 != *first2 ){ + return true; + } + ++first1; + ++first2; + } + return first1!=last1 || first2 != last2; + } + + template _UCXXEXPORT bool operator> + (const multiset& x, const multiset& y) + { + typename multiset::const_iterator first1 = x.begin(); + typename multiset::const_iterator first2 = y.begin(); + typename multiset::const_iterator last1 = x.end(); + typename multiset::const_iterator last2 = y.end(); + + while(first1 != last1 && first2 != last2){ + if( *first1 > *first2 ){ + return true; + } + if( *first2 > *first1 ){ + return false; + } + ++first1; + ++first2; + } + return first1!=last1 && first2 == last2; + } + + template _UCXXEXPORT bool operator>= + (const multiset& x, const multiset& y) + { + typename multiset::const_iterator first1 = x.begin(); + typename multiset::const_iterator first2 = y.begin(); + typename multiset::const_iterator last1 = x.end(); + typename multiset::const_iterator last2 = y.end(); + + while(first1 != last1 && first2 != last2){ + if( *first1 > *first2 ){ + return true; + } + if( *first2 > *first1 ){ + return false; + } + ++first1; + ++first2; + } + return first1!=last1; + } + + template _UCXXEXPORT bool operator<= + (const multiset& x, const multiset& y) + { + typename multiset::const_iterator first1 = x.begin(); + typename multiset::const_iterator first2 = y.begin(); + typename multiset::const_iterator last1 = x.end(); + typename multiset::const_iterator last2 = y.end(); + + while(first1 != last1 && first2 != last2){ + if( *first1 < *first2 ){ + return true; + } + if( *first2 < *first1 ){ + return false; + } + ++first1; + ++first2; + } + return first2!=last2; + } + + template _UCXXEXPORT void swap + (multiset& x, multiset& y) + { + x.swap(y); + } + + + +} + +#pragma GCC visibility pop + +#endif + + Index: branches/slice/rev749/modules/uClibc++/include/iosfwd =================================================================== --- branches/slice/rev749/modules/uClibc++/include/iosfwd (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/iosfwd (revision 1169) @@ -0,0 +1,114 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include + + +#ifndef __HEADER_STD_IOSFWD +#define __HEADER_STD_IOSFWD 1 + +#pragma GCC visibility push(default) + +namespace std { + class ios_base; + template<> class char_traits; + +#ifdef __UCLIBCXX_HAS_WCHAR__ + template<> class char_traits; +#endif + + template > class basic_ios; + + template > class basic_streambuf; + template > class basic_istream; + template > class basic_ostream; + template > class basic_iostream; + + template , + class Allocator = allocator > class basic_stringbuf; + + template , + class Allocator = allocator > class basic_istringstream; + + template , + class Allocator = allocator > class basic_ostringstream; + + template , + class Allocator = allocator > class basic_stringstream; + + template > class basic_filebuf; + + template > class basic_ifstream; + + template > class basic_ofstream; + + template > class basic_fstream; + + template > class basic_istreambuf_iterator; + + template > class basic_ostreambuf_iterator; + + typedef basic_ios ios; +#ifdef __UCLIBCXX_HAS_WCHAR__ + typedef basic_ios wios; +#endif + + typedef basic_streambuf streambuf; + typedef basic_istream istream; + typedef basic_ostream ostream; + typedef basic_iostream iostream; + + typedef basic_stringbuf stringbuf; + typedef basic_istringstream istringstream; + typedef basic_ostringstream ostringstream; + typedef basic_stringstream stringstream; + + typedef basic_filebuf filebuf; + typedef basic_ifstream ifstream; + typedef basic_ofstream ofstream; + typedef basic_fstream fstream; +#ifdef __UCLIBCXX_HAS_WCHAR__ + typedef basic_streambuf wstreambuf; + typedef basic_istream wistream; + typedef basic_ostream wostream; + typedef basic_iostream wiostream; + + typedef basic_stringbuf wstringbuf; + typedef basic_istringstream wistringstream; + typedef basic_ostringstream wostringstream; + typedef basic_stringstream wstringstream; + + typedef basic_filebuf wfilebuf; + typedef basic_ifstream wifstream; + typedef basic_ofstream wofstream; + typedef basic_fstream wfstream; +#endif + + template class fpos; + typedef fpos::state_type> streampos; +#ifdef __UCLIBCXX_HAS_WCHAR__ + typedef fpos::state_type> wstreampos; +#endif +} + +#pragma GCC visibility pop + +#endif Index: branches/slice/rev749/modules/uClibc++/include/cmath =================================================================== --- branches/slice/rev749/modules/uClibc++/include/cmath (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/cmath (revision 1169) @@ -0,0 +1,205 @@ +/* Copyright (C) 2006 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include + +#ifndef __STD_HEADER_CMATH +#define __STD_HEADER_CMATH 1 + +namespace std{ + using ::acos; + using ::asin; + using ::atan; + using ::atan2; + using ::ceil; + using ::cos; + using ::cosh; + using ::exp; + using ::fabs; + using ::floor; + using ::fmod; + using ::frexp; + using ::ldexp; + using ::log; + using ::log10; + using ::modf; + using ::pow; + using ::sin; + using ::sinh; + using ::sqrt; + using ::tan; + using ::tanh; + + inline float abs (float x){ + return fabsf(x); + } + inline float acos (float x){ + return acosf(x); + } + inline float asin (float x){ + return asinf(x); + } + inline float atan (float x){ + return atanf(x); + } + inline float atan2(float y, float x){ + return atan2f(y, x); + } + inline float ceil (float x){ + return ceilf(x); + } + inline float cos (float x){ + return cosf(x); + } + inline float cosh (float x){ + return coshf(x); + } + inline float exp (float x){ + return expf(x); + } + inline float fabs (float x){ + return fabsf(x); + } + inline float floor(float x){ + return floorf(x); + } + inline float fmod (float x, float y){ + return fmodf(x, y); + } + inline float frexp(float x, int* exp){ + return frexpf(x, exp); + } + inline float ldexp(float x, int exp){ + return ldexpf(x, exp); + } + inline float log (float x){ + return logf(x); + } + inline float log10(float x){ + return log10f(x); + } + inline float modf (float x, float* inptr){ + return modff(x, inptr); + } + inline float pow (float x, float y){ + return powf(x, y); + } + inline float pow (float x, int y){ + return pow((double)x, (double)y); + } + inline float sin (float x){ + return sinf(x); + } + inline float sinh (float x){ + return sinhf(x); + } + inline float sqrt (float x){ + return sqrtf(x); + } + inline float tan (float x){ + return tanf(x); + } + inline float tanh (float x){ + return tanhf(x); + } + inline double abs(double x){ + return fabs(x); + } + inline double pow(double x, int y){ + return pow((double)x, (double)y); + } + +#ifdef __UCLIBCXX_HAS_LONG_DOUBLE__ + inline long double abs (long double x){ + return fabsl(x); + } + inline long double acos (long double x){ + return acosl(x); + } + inline long double asin (long double x){ + return asinl(x); + } + inline long double atan (long double x){ + return atanl(x); + } + inline long double atan2(long double y, long double x){ + return atan2l(y, x); + } + inline long double ceil (long double x){ + return ceill(x); + } + inline long double cos (long double x){ + return cosl(x); + } + inline long double cosh (long double x){ + return coshl(x); + } + inline long double exp (long double x){ + return expl(x); + } + inline long double fabs (long double x){ + return fabsl(x); + } + inline long double floor(long double x){ + return floorl(x); + } + inline long double frexp(long double x, int* exp){ + return frexpl(x, exp); + } + inline long double fmod (long double x, long double y){ + return fmodl(x, y); + } + inline long double ldexp(long double x, int y){ + return ldexpl(x, y); + } + inline long double log (long double x){ + return logl(x); + } + inline long double log10(long double x){ + return log10l(x); + } + inline long double modf (long double x, long double* iptr){ + return modfl(x, iptr); + } + inline long double pow (long double x, long double y){ + return powl(x, y); + } + inline long double pow (long double x, int y){ + return powl(x, (long double)y ); + } + inline long double sin (long double x){ + return sinl(x); + } + inline long double sinh (long double x){ + return sinhl(x); + } + inline long double sqrt (long double x){ + return sqrtl(x); + } + inline long double tan (long double x){ + return tanl(x); + } + inline long double tanh (long double x){ + return tanhl(x); + } +#endif // __UCLIBCXX_HAS_LONG_DOUBLE__ +} + +#endif //__STD_HEADER_CMATH + Index: branches/slice/rev749/modules/uClibc++/include/system_configuration.h =================================================================== --- branches/slice/rev749/modules/uClibc++/include/system_configuration.h (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/system_configuration.h (revision 1169) @@ -0,0 +1,59 @@ +/* + * Automatically generated C config: don't edit + */ +/* + * Version Number + */ +#define __UCLIBCXX_MAJOR__ 0 +#define __UCLIBCXX_MINOR__ 2 +#define __UCLIBCXX_SUBLEVEL__ 2 + +/* + * Target Features and Options + */ +#define __UCLIBCXX_HAS_FLOATS__ 1 +#undef __UCLIBCXX_HAS_LONG_DOUBLE__ +#undef __UCLIBCXX_HAS_TLS__ +#define __WARNINGS__ "-Wall" +#define __BUILD_EXTRA_LIBRARIES__ "" +#define __HAVE_DOT_CONFIG__ 1 + +/* + * String and I/O Stream Support + */ +#undef __UCLIBCXX_HAS_WCHAR__ +#define __UCLIBCXX_IOSTREAM_BUFSIZE__ 32 +#define __UCLIBCXX_HAS_LFS__ 1 +#define __UCLIBCXX_SUPPORT_CDIR__ 0 +#define __UCLIBCXX_SUPPORT_CIN__ 0 +#define __UCLIBCXX_SUPPORT_COUT__ 0 +#define __UCLIBCXX_SUPPORT_CERR__ 0 +#undef __UCLIBCXX_SUPPORT_CLOG__ + +/* + * STL and Code Expansion + */ +#define __UCLIBCXX_STL_BUFFER_SIZE__ 32 +#define __UCLIBCXX_CODE_EXPANSION__ 1 +#undef __UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ +#define __UCLIBCXX_EXPAND_STRING_CHAR__ 1 +#define __UCLIBCXX_EXPAND_VECTOR_BASIC__ 1 +#define __UCLIBCXX_EXPAND_IOS_CHAR__ 1 +#define __UCLIBCXX_EXPAND_STREAMBUF_CHAR__ 1 +#define __UCLIBCXX_EXPAND_ISTREAM_CHAR__ 1 +#define __UCLIBCXX_EXPAND_OSTREAM_CHAR__ 1 +#define __UCLIBCXX_EXPAND_FSTREAM_CHAR__ 1 +#define __UCLIBCXX_EXPAND_SSTREAM_CHAR__ 1 + +/* + * Library Installation Options + */ +#define __UCLIBCXX_RUNTIME_PREFIX__ "." +#define __UCLIBCXX_RUNTIME_INCLUDE_SUBDIR__ "/include" +#define __UCLIBCXX_RUNTIME_LIB_SUBDIR__ "/lib" +#define __UCLIBCXX_RUNTIME_BIN_SUBDIR__ "/bin" +#undef __UCLIBCXX_EXCEPTION_SUPPORT__ +#define __BUILD_STATIC_LIB__ 1 +#define __BUILD_ONLY_STATIC_LIB__ 1 +#undef __DODEBUG__ + Index: branches/slice/rev749/modules/uClibc++/include/limits =================================================================== --- branches/slice/rev749/modules/uClibc++/include/limits (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/limits (revision 1169) @@ -0,0 +1,615 @@ +/* Copyright (C) 2006 Garrett A. Kajmowicz + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include + +#ifndef __STD_HEADER_LIMITS +#define __STD_HEADER_LIMITS 1 + +//#warning limits header is nowhere complete or accurate + +#pragma GCC visibility push(default) + +namespace std{ + +enum float_round_style{ + round_indeterminate =-1, + round_toward_zero = 0, + round_to_nearest = 1, + round_toward_infinity = 2, + round_toward_neg_infinity = 3 +}; + +template struct __bits_to_base_10{ + static const int size = -1; +}; +template <> struct __bits_to_base_10<7>{ + static const int size = 2; +}; +template <> struct __bits_to_base_10<8>{ + static const int size = 2; +}; +template <> struct __bits_to_base_10<9>{ + static const int size = 2; +}; +template <> struct __bits_to_base_10<10>{ + static const int size = 3; +}; +template <> struct __bits_to_base_10<15>{ + static const int size = 4; +}; +template <> struct __bits_to_base_10<16>{ + static const int size = 4; +}; +template <> struct __bits_to_base_10<17>{ + static const int size = 5; +}; +template <> struct __bits_to_base_10<18>{ + static const int size = 5; +}; +template <> struct __bits_to_base_10<31>{ + static const int size = 9; +}; +template <> struct __bits_to_base_10<32>{ + static const int size = 9; +}; +template <> struct __bits_to_base_10<35>{ + static const int size = 10; +}; +template <> struct __bits_to_base_10<36>{ + static const int size = 10; +}; +template <> struct __bits_to_base_10<63>{ + static const int size = 18; +}; +template <> struct __bits_to_base_10<64>{ + static const int size = 19; +}; +template <> struct __bits_to_base_10<71>{ + static const int size = 21; +}; +template <> struct __bits_to_base_10<72>{ + static const int size = 21; +}; +template <> struct __bits_to_base_10<79>{ + static const int size = 23; +}; +template <> struct __bits_to_base_10<80>{ + static const int size = 24; +}; +template <> struct __bits_to_base_10<127>{ + static const int size = 38; +}; +template <> struct __bits_to_base_10<128>{ + static const int size = 38; +}; + + + + + + +template class numeric_limits { +public: + // General -- meaningful for all specializations. + + static const bool is_specialized = false; + static T min(); + static T max(); + static const int radix; + static const int digits; + static const int digits10; + static const bool is_signed; + static const bool is_integer; + static const bool is_exact; + static const bool traps; + static const bool is_modulo; + static const bool is_bounded; + + // Floating point specific. + + static T epsilon(); + static T round_error(); + static const int min_exponent10; + static const int max_exponent10; + static const int min_exponent; + + static const int max_exponent; + static const bool has_infinity; + static const bool has_quiet_NaN; + static const bool has_signaling_NaN; + static const bool is_iec559; + static const bool has_denorm; + static const bool tinyness_before; + static const float_round_style round_style; + static T denorm_min(); + static T infinity(); + static T quiet_NaN(); + static T signaling_NaN(); +}; + +template <> class numeric_limits { +public: + typedef unsigned char T; + // General -- meaningful for all specializations. + static const bool is_specialized = true; + static T min(){ + return 0; + } + static T max(){ + return UCHAR_MAX; + } + static const int radix = 2; + static const int digits = CHAR_BIT; + static const int digits10 = __bits_to_base_10::size; + static const bool is_signed = false; + static const bool is_integer = true; + static const bool is_exact = true; + static const bool traps = false; + static const bool is_modulo = true; + static const bool is_bounded = true; + + // Floating point specific. + + static T epsilon(){ + return 0; + } + static T round_error(){ + return 0; + } + static const int min_exponent10 = 0; + static const int max_exponent10 = 0; + static const int min_exponent = 0; + + static const int max_exponent = 0; + static const bool has_infinity = false; + static const bool has_quiet_NaN = false; + static const bool has_signaling_NaN = false; + static const bool is_iec559 = false; + static const bool has_denorm = false; + static const bool tinyness_before = false; + static const float_round_style round_style = round_indeterminate; + static T denorm_min(); + static T infinity(); + static T quiet_NaN(); + static T signaling_NaN(); +}; + +template <> class numeric_limits { +public: + typedef signed char T; + // General -- meaningful for all specializations. + static const bool is_specialized = true; + static T min(){ + return SCHAR_MIN; + } + static T max(){ + return SCHAR_MAX; + } + static const int radix = 2; + static const int digits = CHAR_BIT - 1; + static const int digits10 = __bits_to_base_10::size; + static const bool is_signed = true; + static const bool is_integer = true; + static const bool is_exact = true; + static const bool traps = false; + static const bool is_modulo = true; + static const bool is_bounded = true; + + // Floating point specific. + + static T epsilon(){ + return 0; + } + static T round_error(){ + return 0; + } + static const int min_exponent10 = 0; + static const int max_exponent10 = 0; + static const int min_exponent = 0; + + static const int max_exponent = 0; + static const bool has_infinity = false; + static const bool has_quiet_NaN = false; + static const bool has_signaling_NaN = false; + static const bool is_iec559 = false; + static const bool has_denorm = false; + static const bool tinyness_before = false; + static const float_round_style round_style = round_indeterminate; + static T denorm_min(); + static T infinity(); + static T quiet_NaN(); + static T signaling_NaN(); +}; + +template <> class numeric_limits { +public: + typedef char T; + // General -- meaningful for all specializations. + static const bool is_specialized = true; + static T min(){ + return CHAR_MIN; + } + static T max(){ + return CHAR_MAX; + } + static const int radix = 2; + static const int digits = (CHAR_MIN != 0) ? CHAR_BIT - 1 : CHAR_BIT; + static const int digits10 = __bits_to_base_10::size; + static const bool is_signed = (CHAR_MIN != 0); + static const bool is_integer = true; + static const bool is_exact = true; + static const bool traps = false; + static const bool is_modulo = true; + static const bool is_bounded = true; + + // Floating point specific. + + static T epsilon(){ + return 0; + } + static T round_error(){ + return 0; + } + static const int min_exponent10 = 0; + static const int max_exponent10 = 0; + static const int min_exponent = 0; + + static const int max_exponent = 0; + static const bool has_infinity = false; + static const bool has_quiet_NaN = false; + static const bool has_signaling_NaN = false; + static const bool is_iec559 = false; + static const bool has_denorm = false; + static const bool tinyness_before = false; + static const float_round_style round_style = round_indeterminate; + static T denorm_min(); + static T infinity(); + static T quiet_NaN(); + static T signaling_NaN(); +}; + +template <> class numeric_limits { +public: + typedef unsigned short T; + // General -- meaningful for all specializations. + static const bool is_specialized = true; + static T min(){ + return 0; + } + static T max(){ + return USHRT_MAX; + } + static const int radix = 2; + static const int digits = CHAR_BIT * sizeof(T); + static const int digits10 = __bits_to_base_10::size; + static const bool is_signed = false; + static const bool is_integer = true; + static const bool is_exact = true; + static const bool traps = false; + static const bool is_modulo = true; + static const bool is_bounded = true; + + // Floating point specific. + + static T epsilon(){ + return 0; + } + static T round_error(){ + return 0; + } + static const int min_exponent10 = 0; + static const int max_exponent10 = 0; + static const int min_exponent = 0; + + static const int max_exponent = 0; + static const bool has_infinity = false; + static const bool has_quiet_NaN = false; + static const bool has_signaling_NaN = false; + static const bool is_iec559 = false; + static const bool has_denorm = false; + static const bool tinyness_before = false; + static const float_round_style round_style = round_indeterminate; + static T denorm_min(); + static T infinity(); + static T quiet_NaN(); + static T signaling_NaN(); +}; + +template <> class numeric_limits { +public: + typedef signed short T; + // General -- meaningful for all specializations. + static const bool is_specialized = true; + static T min(){ + return SHRT_MIN; + } + static T max(){ + return SHRT_MAX; + } + static const int radix = 2; + static const int digits = CHAR_BIT * sizeof(T); + static const int digits10 = __bits_to_base_10::size; + static const bool is_signed = true; + static const bool is_integer = true; + static const bool is_exact = true; + static const bool traps = false; + static const bool is_modulo = true; + static const bool is_bounded = true; + + // Floating point specific. + + static T epsilon(){ + return 0; + } + static T round_error(){ + return 0; + } + static const int min_exponent10 = 0; + static const int max_exponent10 = 0; + static const int min_exponent = 0; + + static const int max_exponent = 0; + static const bool has_infinity = false; + static const bool has_quiet_NaN = false; + static const bool has_signaling_NaN = false; + static const bool is_iec559 = false; + static const bool has_denorm = false; + static const bool tinyness_before = false; + static const float_round_style round_style = round_indeterminate; + static T denorm_min(); + static T infinity(); + static T quiet_NaN(); + static T signaling_NaN(); +}; + +template <> class numeric_limits { +public: + typedef unsigned int T; + // General -- meaningful for all specializations. + static const bool is_specialized = true; + static T min(){ + return 0; + } + static T max(){ + return UINT_MAX; + } + static const int radix = 2; + static const int digits = CHAR_BIT * sizeof(T); + static const int digits10 = __bits_to_base_10::size; + static const bool is_signed = false; + static const bool is_integer = true; + static const bool is_exact = true; + static const bool traps = false; + static const bool is_modulo = true; + static const bool is_bounded = true; + + // Floating point specific. + + static T epsilon(){ + return 0; + } + static T round_error(){ + return 0; + } + static const int min_exponent10 = 0; + static const int max_exponent10 = 0; + static const int min_exponent = 0; + + static const int max_exponent = 0; + static const bool has_infinity = false; + static const bool has_quiet_NaN = false; + static const bool has_signaling_NaN = false; + static const bool is_iec559 = false; + static const bool has_denorm = false; + static const bool tinyness_before = false; + static const float_round_style round_style = round_indeterminate; + static T denorm_min(); + static T infinity(); + static T quiet_NaN(); + static T signaling_NaN(); +}; + +template <> class numeric_limits { +public: + typedef signed int T; + // General -- meaningful for all specializations. + static const bool is_specialized = true; + static T min(){ + return INT_MIN; + } + static T max(){ + return INT_MAX; + } + static const int radix = 2; + static const int digits = CHAR_BIT * sizeof(T); + static const int digits10 = __bits_to_base_10::size; + static const bool is_signed = true; + static const bool is_integer = true; + static const bool is_exact = true; + static const bool traps = false; + static const bool is_modulo = true; + static const bool is_bounded = true; + + // Floating point specific. + + static T epsilon(){ + return 0; + } + static T round_error(){ + return 0; + } + static const int min_exponent10 = 0; + static const int max_exponent10 = 0; + static const int min_exponent = 0; + + static const int max_exponent = 0; + static const bool has_infinity = false; + static const bool has_quiet_NaN = false; + static const bool has_signaling_NaN = false; + static const bool is_iec559 = false; + static const bool has_denorm = false; + static const bool tinyness_before = false; + static const float_round_style round_style = round_indeterminate; + static T denorm_min(); + static T infinity(); + static T quiet_NaN(); + static T signaling_NaN(); +}; + +template <> class numeric_limits { +public: + typedef unsigned long int T; + // General -- meaningful for all specializations. + static const bool is_specialized = true; + static T min(){ + return 0; + } + static T max(){ + return ULONG_MAX; + } + static const int radix = 2; + static const int digits = CHAR_BIT * sizeof(T); + static const int digits10 = __bits_to_base_10::size; + static const bool is_signed = false; + static const bool is_integer = true; + static const bool is_exact = true; + static const bool traps = false; + static const bool is_modulo = true; + static const bool is_bounded = true; + + // Floating point specific. + + static T epsilon(){ + return 0; + } + static T round_error(){ + return 0; + } + static const int min_exponent10 = 0; + static const int max_exponent10 = 0; + static const int min_exponent = 0; + + static const int max_exponent = 0; + static const bool has_infinity = false; + static const bool has_quiet_NaN = false; + static const bool has_signaling_NaN = false; + static const bool is_iec559 = false; + static const bool has_denorm = false; + static const bool tinyness_before = false; + static const float_round_style round_style = round_indeterminate; + static T denorm_min(); + static T infinity(); + static T quiet_NaN(); + static T signaling_NaN(); +}; + +template <> class numeric_limits { +public: + typedef signed long int T; + // General -- meaningful for all specializations. + static const bool is_specialized = true; + static T min(){ + return LONG_MIN; + } + static T max(){ + return LONG_MAX; + } + static const int radix = 2; + static const int digits = CHAR_BIT * sizeof(T); + static const int digits10 = __bits_to_base_10::size; + static const bool is_signed = true; + static const bool is_integer = true; + static const bool is_exact = true; + static const bool traps = false; + static const bool is_modulo = true; + static const bool is_bounded = true; + + // Floating point specific. + + static T epsilon(){ + return 0; + } + static T round_error(){ + return 0; + } + static const int min_exponent10 = 0; + static const int max_exponent10 = 0; + static const int min_exponent = 0; + + static const int max_exponent = 0; + static const bool has_infinity = false; + static const bool has_quiet_NaN = false; + static const bool has_signaling_NaN = false; + static const bool is_iec559 = false; + static const bool has_denorm = false; + static const bool tinyness_before = false; + static const float_round_style round_style = round_indeterminate; + static T denorm_min(); + static T infinity(); + static T quiet_NaN(); + static T signaling_NaN(); +}; + +template <> class numeric_limits { + typedef double numeric_type; + + static const bool is_specialized = true; + static numeric_type min () { return __DBL_MIN__; } + static numeric_type max () { return __DBL_MAX__; } + static const int radix = __FLT_RADIX__; + static const int digits = __DBL_MANT_DIG__; + static const int digits10 = __DBL_DIG__; + static const bool is_signed = true; + static const bool is_integer = false; + static const bool is_exact = false; + static const bool traps = false; // this is a guess + static const bool is_modulo = false; + static const bool is_bounded = true; + + // Floating point specific. + + static numeric_type epsilon () { return __DBL_EPSILON__; } + static numeric_type round_error () { return 0.5; } + static const int min_exponent10 = -1; //How do I properly get this? + static const int max_exponent10 = -1; //How do I properly get this? + static const int min_exponent = -1; //How do I properly get this? + static const int max_exponent = -1; //How do I properly get this? + static const bool has_infinity = false; //I don't know, so until I can find out, I'm saying no + static const bool has_quiet_NaN = false; //I don't know, so until I can find out, I'm saying no + static const bool has_signaling_NaN = false; //I don't know, so until I can find out, I'm saying no + static const bool has_denorm = false; //I don't know, so until I can find out, I'm saying no + + static const bool is_iec559 = false; //I don't know, so until I can find out, I'm saying no + static const bool tinyness_before = false; // more questions + static const float_round_style round_style = round_to_nearest; // more questions + static numeric_type denorm_min () { return -1; } //How do I properly get this? + static numeric_type infinity () { return -1; } //How do I properly get this? + static numeric_type quiet_NaN () { return -1; } //How do I properly get this? + static numeric_type signaling_NaN () { return -1; } //How do I properly get this? +}; + + + + + +} + +#pragma GCC visibility pop + +#endif Index: branches/slice/rev749/modules/uClibc++/include/functional =================================================================== --- branches/slice/rev749/modules/uClibc++/include/functional (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/functional (revision 1169) @@ -0,0 +1,439 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + This file is part of the uClibc++ Library. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#ifndef __STD_HEADER_FUNCTIONAL +#define __STD_HEADER_FUNCTIONAL 1 + +#include + +#pragma GCC visibility push(default) + +namespace std{ + + template struct unary_function; + template struct binary_function; + + template struct plus; + template struct minus; + template struct multiplies; + template struct divides; + template struct modulus; + template struct negate; + + template struct equal_to; + template struct not_equal_to; + template struct greater; + template struct less; + template struct greater_equal; + template struct less_equal; + + template struct logical_and; + template struct logical_or; + template struct logical_not; + + template struct unary_negate; + template unary_negate not1(const Predicate&); + template struct binary_negate; + template binary_negate not2(const Predicate&); + + + template class binder1st; + template binder1st bind1st(const Operation&, const T&); + template class binder2nd; + template binder2nd bind2nd(const Operation&, const T&); + + template class pointer_to_unary_function; + template pointer_to_unary_function ptr_fun(Result (*)(Arg)); + template class pointer_to_binary_function; + template + pointer_to_binary_function ptr_fun(Result (*)(Arg1,Arg2)); + + template class mem_fun_t; + template class mem_fun1_t; + template class const_mem_fun_t; + template class const_mem_fun1_t; + template mem_fun_t mem_fun(S (T::*f)()); + template mem_fun1_t mem_fun(S (T::*f)(A)); + template class mem_fun_ref_t; + template class mem_fun1_ref_t; + template mem_fun_ref_t mem_fun_ref(S (T::*f)()); + template mem_fun1_ref_t mem_fun1_ref(S (T::*f)(A)); + + //Implementation + + template struct _UCXXEXPORT unary_function{ + typedef Arg argument_type; + typedef Result result_type; + }; + + + template struct _UCXXEXPORT binary_function{ + typedef Arg1 first_argument_type; + typedef Arg2 second_argument_type; + typedef Result result_type; + }; + + template struct _UCXXEXPORT plus : binary_function{ + T operator()(const T& x, const T& y) const{ + return x + y; + } + }; + + template struct _UCXXEXPORT minus : binary_function{ + T operator()(const T& x, const T& y) const{ + return x - y; + } + }; + + template struct _UCXXEXPORT multiplies : binary_function{ + T operator()(const T& x, const T& y) const{ + return x * y; + } + }; + + template struct _UCXXEXPORT divides : binary_function{ + T operator()(const T& x, const T& y) const{ + return x / y; + } + }; + + template struct _UCXXEXPORT modulus : binary_function{ + T operator()(const T& x, const T& y) const{ + return x % y; + } + }; + + template struct _UCXXEXPORT negate : unary_function{ + T operator()(const T& x) const{ + return -x; + } + }; + + template struct _UCXXEXPORT equal_to : binary_function{ + bool operator()(const T& x, const T& y) const{ + return (x == y); + } + }; + + template struct _UCXXEXPORT not_equal_to : binary_function{ + bool operator()(const T& x, const T& y) const{ + return (x != y); + } + }; + + template struct _UCXXEXPORT greater : binary_function{ + bool operator()(const T& x, const T& y) const{ + return (x > y); + } + }; + + template struct _UCXXEXPORT less : binary_function{ + bool operator()(const T& x, const T& y) const{ + return (x < y); + } + }; + + template struct _UCXXEXPORT greater_equal : binary_function{ + bool operator()(const T& x, const T& y) const{ + return (x >= y); + } + }; + + template struct _UCXXEXPORT less_equal : binary_function{ + bool operator()(const T& x, const T& y) const{ + return (x <= y); + } + }; + + template struct _UCXXEXPORT logical_and : binary_function { + bool operator()(const T& x, const T& y) const{ + return (x && y); + } + }; + + template struct _UCXXEXPORT logical_or : binary_function { + bool operator()(const T& x, const T& y) const{ + return (x || y); + } + }; + + template struct _UCXXEXPORT logical_not : unary_function { + bool operator()(const T& x) const{ + return !x; + } + }; + + template class _UCXXEXPORT unary_negate + : public unary_function + { + public: + explicit unary_negate(const Predicate& pred) : p(pred) { } + bool operator()(const typename Predicate::argument_type& x) const{ + return !p(x); + } + private: + Predicate p; + }; + + + template _UCXXEXPORT unary_negate not1(const Predicate& pred){ + return unary_negate(pred); + } + + + template class _UCXXEXPORT binary_negate : public + binary_function + { + public: + explicit binary_negate(const Predicate& pred) : p(pred) { } + bool operator()(const typename Predicate::first_argument_type& x, + const typename Predicate::second_argument_type& y) const + { + return !p(x, y); + } + private: + Predicate p; + }; + + + template _UCXXEXPORT binary_negate not2(const Predicate& pred){ + return binary_negate(pred); + } + + + template class _UCXXEXPORT binder1st + : public unary_function + { + protected: + Operation op; + typename Operation::first_argument_type value; + public: + binder1st(const Operation& x, const typename Operation::first_argument_type& y) : op(x), value(y){ } + typename Operation::result_type operator()(const typename Operation::second_argument_type& x) const{ + return op(value,x); + } + }; + + + template _UCXXEXPORT binder1st bind1st(const Operation& op, const T& x){ + return binder1st(op, typename Operation::first_argument_type(x)); + } + + + template class _UCXXEXPORT binder2nd + : public unary_function + { + protected: + Operation op; + typename Operation::second_argument_type value; + public: + binder2nd(const Operation& x, const typename Operation::second_argument_type& y) : op(x), value(y) { } + typename Operation::result_type operator()(const typename Operation::first_argument_type& x) const{ + return op(x,value); + } + }; + + + template _UCXXEXPORT + binder2nd bind2nd(const Operation& op, const T& x) + { + return binder2nd(op, typename Operation::second_argument_type(x)); + } + + + template class _UCXXEXPORT + pointer_to_unary_function : public unary_function + { + protected: + Result (*func)(Arg); + public: + explicit pointer_to_unary_function(Result (*f)(Arg)) : func(f) { } + Result operator()(Arg x) const{ + return func(x); + } + }; + + + template _UCXXEXPORT pointer_to_unary_function ptr_fun(Result (*f)(Arg)){ + return pointer_to_unary_function(f); + } + + + template class _UCXXEXPORT + pointer_to_binary_function : public binary_function + { + protected: + Result (*func)(Arg1, Arg2); + public: + explicit pointer_to_binary_function(Result (*f)(Arg1, Arg2)) : func(f) { } + Result operator()(Arg1 x, Arg2 y) const{ + return func(x, y); + } + }; + + template _UCXXEXPORT + pointer_to_binary_function ptr_fun(Result (*f)(Arg1, Arg2)) + { + return pointer_to_binary_function(f); + } + + + template class _UCXXEXPORT mem_fun_t + : public unary_function + { + public: + explicit mem_fun_t(S (T::*p)()) : m(p) { } + S operator()(T* p) const { return (p->*m)(); } + private: + S (T::*m)(); + }; + + + template class _UCXXEXPORT mem_fun1_t + : public binary_function + { + public: + explicit mem_fun1_t(S (T::*p)(A)) : m(p) { } + S operator()(T* p, A x) const { return (p->*m)(x); } + private: + S (T::*m)(A); + }; + + + template class _UCXXEXPORT const_mem_fun_t + : public unary_function + { + public: + explicit const_mem_fun_t(S (T::*p)() const) : m(p) { } + S operator()(const T* p) const { return (p->*m)(); } + private: + S (T::*m)() const; + }; + + + template class _UCXXEXPORT const_mem_fun1_t + : public binary_function + { + public: + explicit const_mem_fun1_t(S (T::*p)(A) const) : m(p) { } + S operator()(const T* p, A x) const { return (p->*m)(x); } + private: + S (T::*m)(A) const; + }; + + + template _UCXXEXPORT mem_fun_t mem_fun(S (T::*f)()){ + return mem_fun_t(f); + } + + template _UCXXEXPORT const_mem_fun_t mem_fun(S (T::*f)() const){ + return const_mem_fun_t(f); + } + + template _UCXXEXPORT mem_fun1_t mem_fun(S (T::*f)(A)){ + return mem_fun1_t(f); + } + + template _UCXXEXPORT const_mem_fun1_t mem_fun(S (T::*f)(A) const){ + return const_mem_fun1_t(f); + } + + template class _UCXXEXPORT mem_fun_ref_t + : public unary_function + { + public: + explicit mem_fun_ref_t(S (T::*p)()) : mf(p) { } + S operator()(T& p) { return (p.*mf)(); } + private: + S (T::*mf)(); + }; + + template class _UCXXEXPORT mem_fun1_ref_t + : public binary_function + { + public: + explicit mem_fun1_ref_t(S (T::*p)(A)) : mf(p) { } + S operator()(T& p, A x) { return (p.*mf)(x); } + private: + S (T::*mf)(A); + }; + + template _UCXXEXPORT mem_fun_ref_t mem_fun_ref(S (T::*f)()){ + return mem_fun_ref_t(f); + } + + template _UCXXEXPORT mem_fun1_ref_t mem_fun1_ref(S (T::*f)(A)){ + return mem_fun1_ref_t(f); + } + + +} + + +//These are SGI extensions which are checked for by some conformance checks. They +// are *NOT* part of the C++ standard, however + +template class _UCXXEXPORT unary_compose : + public std::unary_function +{ +protected: + Op1 mf1; + Op2 mf2; +public: + unary_compose(const Op1& x, const Op2& y) : mf1(x), mf2(y) { } + typename Op1::result_type operator()(const typename Op2::argument_type& x) const { + return mf1(mf2(x)); + } +}; + +template _UCXXEXPORT +inline unary_compose +compose1(const Op1& fn1, const Op2& fn2){ + return unary_compose(fn1, fn2); +} + +template class _UCXXEXPORT binary_compose : + public std::unary_function +{ +protected: + Op1 mf1; + Op2 mf2; + Op3 mf3; +public: + binary_compose(const Op1 & x, const Op2 & y, const Op3 & z) + : mf1(x), mf2(y), mf3(z){ } + typename Op1::result_type operator()(const typename Op2::argument_type & x) const { + return mf1(mf2(x), mf3(x)); + } +}; + +template inline _UCXXEXPORT binary_compose +compose2(const Op1 & fn1, const Op2 & fn2, const Op3 & fn3){ + return binary_compose(fn1, fn2, fn3); +} + +#pragma GCC visibility pop + +#endif + + + Index: branches/slice/rev749/modules/uClibc++/include/types =================================================================== --- branches/slice/rev749/modules/uClibc++/include/types (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/types (revision 1169) @@ -0,0 +1,3 @@ +extern "C" { + #include "types.h" +} \ No newline at end of file Index: branches/slice/rev749/modules/uClibc++/include/istream =================================================================== --- branches/slice/rev749/modules/uClibc++/include/istream (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/istream (revision 1169) @@ -0,0 +1,601 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc C++ Library. This library is free + software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) + any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this library; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. +*/ + +#include +#include +#include +#include +#include + +#ifndef __STD_HEADER_ISTREAM +#define __STD_HEADER_ISTREAM 1 + +#pragma GCC visibility push(default) + +namespace std{ + + typedef basic_istream istream; + +#ifdef __UCLIBCXX_HAS_WCHAR__ + typedef basic_istream wistream; +#endif + + template basic_istream& ws(basic_istream& is); + + template class _UCXXEXPORT basic_istream : + virtual public basic_ios + { + public: + + typedef charT char_type; + typedef typename traits::int_type int_type; + typedef typename traits::pos_type pos_type; + typedef typename traits::off_type off_type; + typedef basic_streambuf streambuf_type; + typedef traits traits_type; + + explicit basic_istream(basic_streambuf* sb) + : basic_ios(sb), count_last_ufmt_input(0) + { + basic_ios::init(sb); + } + virtual ~basic_istream() { } + + class sentry; + + basic_istream& operator>>(basic_istream& (*pf)(basic_istream&)); + basic_istream& operator>>(basic_ios& (*pf)(basic_ios&)); + basic_istream& operator>>(ios_base& (*pf)(ios_base&)); + basic_istream& operator>>(bool& n); + basic_istream& operator>>(short& n); + basic_istream& operator>>(unsigned short& n); + basic_istream& operator>>(int& n); + basic_istream& operator>>(unsigned int& n); + basic_istream& operator>>(long& n); + basic_istream& operator>>(unsigned long& n); + basic_istream& operator>>(void*& p); + basic_istream& operator>>(basic_streambuf* sb); + +#ifdef __UCLIBCXX_HAS_FLOATS__ + basic_istream& operator>>(float& f); + basic_istream& operator>>(double& f); + basic_istream& operator>>(long double& f); +#endif + + _UCXXEXPORT streamsize gcount() const{ + return count_last_ufmt_input; + } + + _UCXXEXPORT int_type get(); //below + _UCXXEXPORT basic_istream& get(char_type& c); //Below + + _UCXXEXPORT basic_istream& get(char_type* s, streamsize n){ + return get(s, n, basic_ios::widen('\n')); + } + + _UCXXEXPORT basic_istream& get(char_type* s, streamsize n, char_type delim){ + sentry(*this, true); + streamsize i = 0; + int_type c; + for(i=0;i::mstreambuf->sgetc(); + basic_ios::mstreambuf->sbumpc(); + if(c == traits::eof() ){ + if(i==0){ + basic_ios::setstate(ios_base::failbit); + }else{ + basic_ios::setstate(ios_base::eofbit); + } + break; + } + if(c == delim){ + if(i==0){ + basic_ios::setstate(ios_base::failbit); + } + basic_ios::mstreambuf->sputbackc(c); + break; + } + s[i] = c; + } + s[i] = traits::eos(); + count_last_ufmt_input = i; + return *this; + } + + _UCXXEXPORT basic_istream& get(basic_streambuf& sb){ + return get(sb, basic_ios::widen('\n')); + } + + _UCXXEXPORT basic_istream& get(basic_streambuf& sb, char_type delim){ + sentry(*this, true); + streamsize i = 0; + int_type c; + while(1){ //We will exit internally based upon error conditions + c = basic_ios::mstreambuf->sgetc(); + if(c == traits::eof()){ + if(i==0){ + basic_ios::setstate(ios_base::failbit); + }else{ + basic_ios::setstate(ios_base::eofbit); + } + count_last_ufmt_input = i; + return *this; + } + if(c == delim){ + if(i==0){ + basic_ios::setstate(ios_base::failbit); + } + count_last_ufmt_input = i; + return *this; + } + if(sb.sputc(c) != c){ //Error doing output + count_last_ufmt_input = i; + return *this; + } + ++i; + basic_ios::mstreambuf->sbumpc(); + } + } + + _UCXXEXPORT basic_istream& getline(char_type* s, streamsize n){ + return getline(s, n, basic_ios::widen('\n')); + } + + _UCXXEXPORT basic_istream& getline(char_type* s, streamsize n, char_type delim){ + sentry(*this, true); + streamsize i = 0; + int_type c; + for(i=0;i::mstreambuf->sgetc(); + if(c == traits::eof() ){ + if( basic_ios::eof() ){ + basic_ios::setstate(ios_base::failbit); + }else{ + basic_ios::setstate(ios_base::eofbit); + } + count_last_ufmt_input = i; + s[i] = traits::eos(); + return *this; + } + if(basic_ios::mstreambuf->sbumpc()==traits::eof() ){ + basic_ios::setstate(ios_base::eofbit); + } + if(c == delim){ + count_last_ufmt_input = i+1; + s[i] = traits::eos(); + return *this; + } + s[i] = c; + } + s[n-1] = traits::eos(); + return *this; + } + + _UCXXEXPORT basic_istream& ignore (streamsize n = 1, int_type delim = traits::eof()){ + sentry(*this, true); + streamsize i; + int_type c; + for(i=0;i::mstreambuf->sgetc(); + if(c == traits::eof()){ + basic_ios::setstate(ios_base::eofbit); + return *this; + } + basic_ios::mstreambuf->sbumpc(); + if(c == delim){ + return *this; + } + } + return *this; + } + + _UCXXEXPORT int_type peek(){ + if(basic_ios::good() == false){ + return traits::eof(); + }else{ + int_type c = basic_ios::mstreambuf->sgetc(); + if(c == traits::eof()){ + basic_ios::setstate(ios_base::eofbit); + } + return basic_ios::mstreambuf->sgetc(); + } + } + + _UCXXEXPORT basic_istream& read (char_type* s, streamsize n){ + sentry(*this, true); + streamsize i; + int_type c; + for(i=0;i::mstreambuf->sgetc(); + + if(c == traits::eof()){ + basic_ios::setstate(ios_base::failbit); + basic_ios::setstate(ios_base::eofbit); + count_last_ufmt_input = i; + return *this; + } + basic_ios::mstreambuf->sbumpc(); + s[i] = c; + } + count_last_ufmt_input = n; + return *this; + } + + _UCXXEXPORT streamsize readsome(char_type* s, streamsize n){ + sentry(*this, true); + if(!basic_ios::good()){ + count_last_ufmt_input = 0; + basic_ios::setstate(ios_base::failbit); + return 0; + } + + if( basic_ios::mstreambuf->in_avail() == -1){ + count_last_ufmt_input=0; + basic_ios::setstate(ios_base::eofbit); + return 0; + } + + if(n > basic_ios::mstreambuf->in_avail() ){ + n = basic_ios::mstreambuf->in_avail(); + } + + streamsize i; + int_type c; + + for(i=0;i::mstreambuf->sgetc(); + basic_ios::mstreambuf->sbumpc(); + s[i] = c; + } + count_last_ufmt_input = n; + return n; + } + + _UCXXEXPORT basic_istream& putback(char_type c){ + sentry(*this, true); + if(!basic_ios::good()){ + basic_ios::setstate(ios_base::failbit); + return *this; + } + if(basic_ios::mstreambuf == 0){ + basic_ios::setstate(ios_base::badbit); + return *this; + } + if(basic_ios::mstreambuf->sputbackc(c) == traits::eof()){ + basic_ios::setstate(ios_base::badbit); + return *this; + } + return *this; + } + + _UCXXEXPORT basic_istream& unget(){ + sentry(*this, true); + if(!basic_ios::good()){ + basic_ios::setstate(ios_base::failbit); + return *this; + } + if(basic_ios::mstreambuf == 0){ + basic_ios::setstate(ios_base::failbit); + return *this; + } + if(basic_ios::mstreambuf->sungetc() == traits::eof()){ + basic_ios::setstate(ios_base::failbit); + } + return *this; + } + + _UCXXEXPORT int sync(){ + sentry(*this, true); + if(basic_ios::mstreambuf == 0){ + return -1; + } + if(basic_ios::mstreambuf->pubsync() == -1){ + basic_ios::setstate(ios_base::badbit); + return traits::eof(); + } + return 0; + } + + _UCXXEXPORT pos_type tellg(){ + if(basic_ios::fail() !=false){ + return pos_type(-1); + } + return basic_ios::mstreambuf->pubseekoff(0, ios_base::cur, ios_base::in); + } + + _UCXXEXPORT basic_istream& seekg(pos_type pos){ + if(basic_ios::fail() !=true){ + basic_ios::mstreambuf->pubseekpos(pos); + } + return *this; + } + + _UCXXEXPORT basic_istream& seekg(off_type off, ios_base::seekdir dir){ + if(basic_ios::fail() !=true){ + basic_ios::mstreambuf->pubseekoff(off, dir); + } + return *this; + } + + protected: + _UCXXEXPORT basic_istream(const basic_istream &): basic_ios() { } + _UCXXEXPORT basic_istream & operator=(const basic_istream &){ return *this; } + streamsize count_last_ufmt_input; + + }; + + template > class _UCXXEXPORT basic_istream::sentry { + bool ok; + public: + explicit _UCXXEXPORT sentry(basic_istream& os, bool noskipws = false){ + if(os.good() !=0){ //Prepare for output + } + + //Flush any tied buffer + if(os.tie() != 0){ + os.tie()->flush(); + } + if(!noskipws){ + __skipws(os); + } + + ok = true; + } + _UCXXEXPORT ~sentry() { } + _UCXXEXPORT operator bool() { + return ok; + } + }; + + //Template implementations of basic_istream functions which may be partially specialized + //For code reduction + + template + _UCXXEXPORT typename basic_istream::int_type basic_istream::get(){ + sentry(*this, true); + int_type retval = basic_ios::mstreambuf->sgetc(); + if(retval == traits::eof()){ + count_last_ufmt_input = 0; + basic_ios::setstate(ios_base::eofbit); + }else{ + count_last_ufmt_input = 1; + basic_ios::mstreambuf->sbumpc(); + } + return retval; + } + + template + _UCXXEXPORT basic_istream& basic_istream::get(char_type& c){ + sentry(*this, true); + int_type retval = basic_ios::mstreambuf->sgetc(); + if(retval == traits::eof()){ + count_last_ufmt_input = 0; + basic_ios::setstate(ios_base::eofbit); + basic_ios::setstate(ios_base::failbit); + }else{ + count_last_ufmt_input = 1; + c = traits::to_char_type(retval); + basic_ios::mstreambuf->sbumpc(); + } + return *this; + } + + + template _UCXXEXPORT basic_istream& + basic_istream::operator>>(bool& n) + { + sentry(*this); + __istream_readin::readin(*this, n); + return *this; + } + + template _UCXXEXPORT basic_istream& + basic_istream::operator>>(short& n) + { + sentry(*this); + __istream_readin::readin(*this, n); + return *this; + } + + template _UCXXEXPORT basic_istream& + basic_istream::operator>>(unsigned short& n) + { + sentry(*this); + __istream_readin::readin(*this, n); + return *this; + } + + template _UCXXEXPORT basic_istream& basic_istream::operator>>(int& n){ + sentry(*this); + __istream_readin::readin(*this, n); + return *this; + } + + template _UCXXEXPORT basic_istream& basic_istream::operator>>(unsigned int& n){ + sentry(*this); + __istream_readin::readin(*this, n); + return *this; + } + + template _UCXXEXPORT basic_istream& basic_istream::operator>>(long int& n){ + sentry(*this); + __istream_readin::readin(*this, n); + return *this; + } + + template _UCXXEXPORT basic_istream& + basic_istream::operator>>(unsigned long int& n) + { + sentry(*this); + __istream_readin::readin(*this, n); + return *this; + } + +#ifdef __UCLIBCXX_HAS_FLOATS__ + template _UCXXEXPORT basic_istream& + basic_istream::operator>>(float& n) + { + sentry(*this); + __istream_readin::readin(*this, n); + return *this; + } + template _UCXXEXPORT basic_istream& + basic_istream::operator>>(double& n) + { + sentry(*this); + __istream_readin::readin(*this, n); + return *this; + } + template _UCXXEXPORT basic_istream& + basic_istream::operator>>(long double& n) + { + sentry(*this); + __istream_readin::readin(*this, n); + return *this; + } +#endif + template _UCXXEXPORT basic_istream& + basic_istream::operator>>(void *& n) + { + sentry(*this); + __istream_readin::readin(*this, n); + return *this; + } + + template _UCXXEXPORT basic_istream& + operator>>(basic_istream& is, charT& c) + { + typename basic_istream::sentry s(is); + is.get(c); + return is; + } + + template _UCXXEXPORT basic_istream& + operator>>(basic_istream& is, unsigned char& c) + { + typename basic_istream::sentry s(is); + char b; + is.get(b); + c = b; + return is; + } + template _UCXXEXPORT basic_istream& + operator>>(basic_istream& is, signed char& c) + { + typename basic_istream::sentry s(is); + is.get(c); + return is; + } + + template _UCXXEXPORT basic_istream& + operator>>(basic_istream& is, charT* c) + { + typename basic_istream::sentry s(is); + int n = is.width(); + if(n == 0){ + n = __STRING_MAX_UNITS; + } + is.get(c, n); + return is; + + } + template _UCXXEXPORT basic_istream& + operator>>(basic_istream& is, unsigned char* c) + { + typename basic_istream::sentry s(is); + int n = is.width(); + if(n == 0){ + n = __STRING_MAX_UNITS; + } + is.get(c, n); + return is; + } + template _UCXXEXPORT basic_istream& + operator>>(basic_istream& is, signed char* c) + { + typename basic_istream::sentry s(is); + int n = is.width(); + if(n == 0){ + n = __STRING_MAX_UNITS; + } + is.get(c, n); + return is; + } + + template _UCXXEXPORT basic_istream& + basic_istream::operator>>(basic_istream& (*pf)(basic_istream&)) + { + sentry(*this); + pf(*this); + return *this; + } + + template _UCXXEXPORT basic_istream& + basic_istream::operator>>(basic_ios& (*pf)(basic_ios&)) + { + sentry(*this); + pf(*this); + return *this; + } + + template _UCXXEXPORT basic_istream& + ws(basic_istream& is) + { + __skipws(is); + return is; + } + + +#ifdef __UCLIBCXX_EXPAND_ISTREAM_CHAR__ +#ifndef __UCLIBCXX_COMPILE_ISTREAM__ + + + template <> _UCXXEXPORT istream & basic_istream >::get(char & c); + template <> _UCXXEXPORT istream::int_type basic_istream >::get(); + + template <> _UCXXEXPORT istream & istream::operator>>(bool &n); + template <> _UCXXEXPORT istream & istream::operator>>(short &n); + template <> _UCXXEXPORT istream & istream::operator>>(unsigned short &n); + template <> _UCXXEXPORT istream & istream::operator>>(int &n); + template <> _UCXXEXPORT istream & istream::operator>>(unsigned int &n); + template <> _UCXXEXPORT istream & istream::operator>>(long unsigned &n); + template <> _UCXXEXPORT istream & istream::operator>>(long int &n); + template <> _UCXXEXPORT istream & istream::operator>>(void *& p); + +#ifdef __UCLIBCXX_HAS_FLOATS__ + template <> _UCXXEXPORT istream & istream::operator>>(float &f); + template <> _UCXXEXPORT istream & istream::operator>>(double &f); + template <> _UCXXEXPORT istream & istream::operator>>(long double &f); +#endif + + template <> _UCXXEXPORT istream & operator>>(istream & is, char & c); + + template <> _UCXXEXPORT void __skipws(basic_istream >& is); + +#endif +#endif + + + +} + +#pragma GCC visibility pop + +#endif + Index: branches/slice/rev749/modules/uClibc++/include/stack =================================================================== --- branches/slice/rev749/modules/uClibc++/include/stack (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/stack (revision 1169) @@ -0,0 +1,84 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + This file is part of the uClibc++ Library. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include + +#ifndef __HEADER_STD_STACK +#define __HEADER_STD_STACK 1 + +#pragma GCC visibility push(default) + +namespace std{ + + template > class _UCXXEXPORT stack{ + protected: + Container c; + + public: + typedef typename Container::value_type value_type; + typedef typename Container::size_type size_type; + typedef Container container_type; + + explicit stack(const Container& a = Container()) : c(a) { }; + bool empty() const { return c.empty(); } + size_type size() const { return c.size(); } + value_type& top() { return c.back(); } + const value_type& top() const { return c.back(); } + void push(const value_type& x) { c.push_back(x); } + void pop() { c.pop_back(); } + + bool operator==(const stack &x) const{ + return x.c == c; + } + + }; + + + template _UCXXEXPORT bool + operator< (const stack& x, const stack& y) + { + return (x.c < y.c); + } + template _UCXXEXPORT bool + operator!=(const stack& x, const stack& y) + { + return (x.c != y.c); + } + template _UCXXEXPORT bool + operator> (const stack& x, const stack& y) + { + return (x.c > y.c); + } + template _UCXXEXPORT bool + operator>=(const stack& x, const stack& y) + { + return (x.c >= y.c); + } + template _UCXXEXPORT bool + operator<=(const stack& x, const stack& y) + { + return (x.c <= y.c); + } + +} + +#pragma GCC visibility pop + +#endif + + Index: branches/slice/rev749/modules/uClibc++/include/csetjmp =================================================================== --- branches/slice/rev749/modules/uClibc++/include/csetjmp (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/csetjmp (revision 1169) @@ -0,0 +1,44 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include + +#ifndef __STD_HEADER_CSETJMP +#define __STD_HEADER_CSETJMP 1 + + +//From GCC Header files +#undef longjmp + +// Adhere to section 17.4.1.2 clause 5 of ISO 14882:1998 +#ifndef setjmp +#define setjmp(env) setjmp (env) +#endif + +//Mine again + + +namespace std{ + using ::longjmp; + using ::jmp_buf; +} + + +#endif + Index: branches/slice/rev749/modules/uClibc++/include/string =================================================================== --- branches/slice/rev749/modules/uClibc++/include/string (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/string (revision 1169) @@ -0,0 +1,1042 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include +#include +#include + + +#ifdef __UCLIBCXX_HAS_WCHAR__ +#include +#include +#endif + +#ifndef __HEADER_STD_STRING +#define __HEADER_STD_STRING 1 + +#pragma GCC visibility push(default) + +namespace std{ + + //Basic basic_string + + template, class A = allocator > class basic_string; + + typedef basic_string string; + #ifdef __UCLIBCXX_HAS_WCHAR__ + typedef basic_string wstring; + #endif + + + +//template, class A = allocator > class _UCXXEXPORT basic_string +template class basic_string + : public std::vector +{ +public: + typedef Tr traits_type; + typedef typename Tr::char_type value_type; + typedef A allocator_type; + typedef typename A::size_type size_type; + typedef typename A::difference_type difference_type; + + typedef typename A::reference reference; + typedef typename A::const_reference const_reference; + typedef typename A::pointer pointer; + typedef typename A::const_pointer const_pointer; + + typedef typename vector::iterator iterator; + typedef typename vector::const_iterator const_iterator; + + typedef typename vector::reverse_iterator reverse_iterator; + typedef typename vector::const_reverse_iterator const_reverse_iterator; + + static const size_type npos = (size_type)-1; + + explicit _UCXXEXPORT basic_string(const A& al = A()) : vector(al){ return; } + + _UCXXEXPORT basic_string(const basic_string& str, size_type pos = 0, size_type n = npos, const A& al = A()); //Below + + _UCXXEXPORT basic_string(const Ch* s, size_type n, const A& al = A()) + : vector(al) + { + if(n == npos){ + __throw_out_of_range(); + } + if(s > 0){ + resize(n); + Tr::copy(vector::data, s, vector::elements); + } + } + + _UCXXEXPORT basic_string(const Ch* s, const A& al = A()); //Below + + _UCXXEXPORT basic_string(size_type n, Ch c, const A& al = A()) + : vector(n, c, al) + { + } + + template _UCXXEXPORT basic_string(InputIterator begin, InputIterator end, const A& a = A()) + :vector(begin, end) + { + + } + + _UCXXEXPORT ~basic_string() { + return; + } + + _UCXXEXPORT basic_string& operator=(const basic_string& str); //Below + + _UCXXEXPORT basic_string& operator=(const Ch* s){ + vector::clear(); + if(s!=0){ + size_type len = Tr::length(s); + resize(len); + Tr::copy( vector::data, s, len); + } + return *this; + } + + _UCXXEXPORT basic_string& operator=(Ch c){ + vector::clear(); + vector::push_back(c); + return *this; + } + + inline _UCXXEXPORT size_type length() const { return vector::size(); } + + void _UCXXEXPORT resize(size_type n, Ch c = Ch()){ + vector::resize(n, c); + } + + _UCXXEXPORT basic_string& operator+=(const basic_string& str){ + return append(str); + } + + _UCXXEXPORT basic_string& operator+=(const Ch * s){ + return append(s); + } + + _UCXXEXPORT basic_string& operator+=(Ch c){ + vector::push_back(c); + return *this; + } + + _UCXXEXPORT basic_string& append(const basic_string& str){ + size_t temp = vector::elements; + resize(vector::elements + str.elements); + Tr::copy( vector::data + temp, str.vector::data, str.elements); + + return *this; + } + + _UCXXEXPORT basic_string& append(const basic_string& str, size_type pos, size_type n){ + if(pos > str.size()){ + __throw_out_of_range(); + } + + size_type rlen = str.elements - pos; + if(rlen > n){ + rlen = n; + } + if(vector::elements > npos - rlen){ + __throw_length_error(); + } + size_t temp = vector::elements; + resize(vector::elements + rlen); + Tr::copy( vector::data + temp, str.vector::data + pos, rlen); + return *this; + } + + _UCXXEXPORT basic_string& append(const Ch* s, size_type n){ + size_t temp = vector::elements; + resize(vector::elements + n); + Tr::copy( vector::data + temp, s, n); + return *this; + } + + _UCXXEXPORT basic_string& append(const Ch* s){ + size_type strLen = Tr::length(s); + size_t temp = vector::elements; + resize(vector::elements + strLen); + Tr::copy( vector::data + temp, s, strLen); + return *this; + } + + _UCXXEXPORT basic_string& append(size_type n, Ch c){ + vector::resize(vector::elements + n, c); + return *this; + } + + _UCXXEXPORT basic_string& assign(const basic_string& str){ + operator=(str); + return *this; + } + + _UCXXEXPORT basic_string& assign(const basic_string& str, size_type pos, size_type n){ + if(pos > str.elements){ + __throw_out_of_range(); + } + size_type r = str.elements - pos; + if(r > n){ + r = n; + } + resize(r); + Tr::copy(vector::data, str.vector::data + pos, r); + return *this; + } + + _UCXXEXPORT basic_string& assign(const Ch* s, size_type n){ + resize(n); + Tr::copy(vector::data, s, n); + return *this; + } + + _UCXXEXPORT basic_string& assign(const Ch* s){ + size_type len = Tr::length(s); + return assign(s, len); + } + + _UCXXEXPORT basic_string& assign(size_type n, Ch c){ + vector::clear(); + vector::resize(n, Ch() ); + return *this; + } + + template _UCXXEXPORT basic_string& assign(InputIterator first, InputIterator last){ + vector::resize(0, Ch()); + while (first != last){ + append(*first); + ++first; + } + return *this; + } + + _UCXXEXPORT basic_string& insert(size_type pos1, const basic_string& str, size_type pos2=0, size_type n=npos){ + if(pos1 > vector::elements || pos2 > str.elements){ + __throw_out_of_range(); + } + size_type r = str.elements - pos2; + if( r > n){ + r = n; + } + if(vector::elements > npos - r){ + __throw_length_error(); + } + size_type temp = vector::elements; + resize(vector::elements + r); + Tr::move(vector::data + pos1 + r, vector::data + pos1, temp - pos1); + Tr::copy(vector::data + pos1, str.vector::data + pos2, r); + return *this; + } + + _UCXXEXPORT basic_string& insert(size_type pos, const Ch* s, size_type n){ + if(pos > vector::elements){ + __throw_out_of_range(); + } + if(vector::elements > npos - n){ + __throw_length_error(); + } + size_type temp = vector::elements; + resize(vector::elements + n); + Tr::move(vector::data + pos + n, vector::data + pos, temp - pos); + Tr::copy(vector::data + pos, s, n); + return *this; + } + + inline _UCXXEXPORT basic_string& insert(size_type pos, const Ch* s){ + size_type len = Tr::length(s); + return insert(pos, s, len); + } + + _UCXXEXPORT basic_string& insert(size_type pos, size_type n, Ch c){ + if(pos > vector::elements){ + __throw_out_of_range(); + } + if(vector::elements > npos - n){ + __throw_length_error(); + } + size_type temp = vector::elements; + resize(vector::elements + n); + Tr::move(vector::data + pos + n, vector::data + pos, temp - pos); + Tr::assign(vector::data + pos, n, c); + return *this; + } + +// iterator insert(iterator p, charT c = charT()); +// void insert(iterator p, size_type n, charT c); +// template void insert(iterator p, InputIterator first, InputIterator last); + + _UCXXEXPORT basic_string& erase(size_type pos = 0, size_type n = npos){ + size_type xlen = vector::elements - pos; + + if(xlen > n){ + xlen = n; + } + size_type temp = vector::elements; + + Tr::move(vector::data + pos, vector::data + pos + xlen, temp - pos - xlen); + resize(temp - xlen); + return *this; + } + + _UCXXEXPORT iterator erase(iterator position){ + if(position == vector::end()){ + return position; + } + + ++position; + + iterator temp = position; + + while(position != vector::end()){ + *(position-1) = *position; + ++position; + } + vector::pop_back(); + return temp; + } + + _UCXXEXPORT iterator erase(iterator first, iterator last){ + size_t count = last - first; + + iterator temp = last; + + while(last != vector::end()){ + *(last - count) = *last; + ++last; + } + + resize( vector::elements-count); + + return temp; + } + + _UCXXEXPORT basic_string& + replace(size_type pos1, size_type n1, const basic_string& str, size_type pos2=0, size_type n2=npos) + { + if(pos1 > vector::elements){ + __throw_out_of_range(); + } + size_type xlen = vector::elements - pos1; + if(xlen > n1){ + xlen = n1; + } + size_type rlen = str.elements - pos2; + if(rlen > n2){ + rlen = n2; + } + if((vector::elements - xlen) >= (npos - rlen)){ + __throw_length_error(); + } + + size_t temp = vector::elements; + + if(rlen > xlen){ //Only if making larger + resize(temp - xlen + rlen); + } + + //Final length = vector::elements - xlen + rlen + //Initial block is of size pos1 + //Block 2 is of size len + + Tr::move(vector::data + pos1 + rlen, vector::data + pos1 + xlen, temp - pos1 - xlen); + Tr::copy(vector::data + pos1, str.vector::data + pos2, rlen); + resize(temp - xlen + rlen); + return *this; + } + + _UCXXEXPORT basic_string& replace(size_type pos, size_type n1, const Ch* s, size_type n2){ + return replace(pos,n1,basic_string(s,n2)); + + } + + inline _UCXXEXPORT basic_string& replace(size_type pos, size_type n1, const Ch* s){ + return replace(pos,n1,basic_string(s)); + } + + _UCXXEXPORT basic_string& replace(size_type pos, size_type n1, size_type n2, Ch c){ + return replace(pos,n1,basic_string(n2,c)); + } +// _UCXXEXPORT basic_string& replace(iterator i1, iterator i2, const basic_string& str); +// _UCXXEXPORT basic_string& replace(iterator i1, iterator i2, const Ch* s, size_type n); +// _UCXXEXPORT basic_string& replace(iterator i1, iterator i2, const Ch* s); +// _UCXXEXPORT basic_string& replace(iterator i1, iterator i2, size_type n, Ch c); +/* template _UCXXEXPORT basic_string& replace(iterator i1, iterator i2, + InputIterator j1, InputIterator j2);*/ + + size_type _UCXXEXPORT copy(Ch* s, size_type n, size_type pos = 0) const{ + if(pos > vector::elements){ + __throw_out_of_range(); + } + size_type r = vector::elements - pos; + if(r > n){ + r = n; + } + Tr::copy(s, vector::data + pos, r); + return r; + } + + _UCXXEXPORT void swap(basic_string& s){ + //Data pointers + + vector::swap(s); + } + + _UCXXEXPORT const Ch* c_str() const{ + const_cast *>(this)->reserve(vector::elements+1); + vector::data[vector::elements] = 0; //Add 0 at the end + return vector::data; + } + + _UCXXEXPORT const Ch* data() const{ + return vector::data; + } + _UCXXEXPORT allocator_type get_allocator() const{ + return vector::a; + } + + _UCXXEXPORT size_type find (const basic_string& str, size_type pos = 0) const; //Below + + _UCXXEXPORT size_type find (const Ch* s, size_type pos, size_type n) const{ + return find(basic_string(s,n), pos); + } + _UCXXEXPORT size_type find (const Ch* s, size_type pos = 0) const{ + return find(basic_string(s), pos); + } + _UCXXEXPORT size_type find (Ch c, size_type pos = 0) const{ + for(size_type i = pos; i < length(); ++i){ + if(operator[](i) == c){ + return i; + } + } + return npos; + } + _UCXXEXPORT size_type rfind(const basic_string& str, size_type pos = npos) const{ + if(pos >= length()){ + pos = length(); + } + for(size_type i = pos; i > 0; --i){ + if(str == substr(i-1, str.length())){ + return i-1; + } + } + return npos; + } + _UCXXEXPORT size_type rfind(const Ch* s, size_type pos, size_type n) const{ + return rfind(basic_string(s,n),pos); + } + _UCXXEXPORT size_type rfind(const Ch* s, size_type pos = npos) const{ + return rfind(basic_string(s),pos); + } + _UCXXEXPORT size_type rfind(Ch c, size_type pos = npos) const{ + return rfind(basic_string(1,c),pos); + } + + _UCXXEXPORT size_type find_first_of(const basic_string& str, size_type pos = 0) const{ + for(size_type i = pos; i < length(); ++i){ + for(size_type j = 0; j < str.length() ; ++j){ + if( Tr::eq(str[j], operator[](i)) ){ + return i; + } + } + } + return npos; + } + + _UCXXEXPORT size_type find_first_of(const Ch* s, size_type pos, size_type n) const{ + return find_first_of(basic_string(s,n),pos); + } + _UCXXEXPORT size_type find_first_of(const Ch* s, size_type pos = 0) const{ + return find_first_of(basic_string(s),pos); + } + _UCXXEXPORT size_type find_first_of(Ch c, size_type pos = 0) const{ + for(size_type i = pos; i< length(); ++i){ + if( Tr::eq(operator[](i), c) ){ + return i; + } + } + return npos; + } + + _UCXXEXPORT size_type find_last_of (const basic_string& str, size_type pos = npos) const{ + if(pos > length()){ + pos = length(); + } + for(size_type i = pos; i >0 ; --i){ + for(size_type j = 0 ; j < str.length(); ++j){ + if( Tr::eq(operator[](i-1), str[j]) ){ + return i-1; + } + } + } + return npos; + } + _UCXXEXPORT size_type find_last_of (const Ch* s, size_type pos, size_type n) const{ + return find_last_of(basic_string(s,n),pos); + } + _UCXXEXPORT size_type find_last_of (const Ch* s, size_type pos = npos) const{ + return find_last_of(basic_string(s),pos); + } + _UCXXEXPORT size_type find_last_of (Ch c, size_type pos = npos) const{ + if(pos > length()){ + pos = length(); + } + for(size_type i = pos; i >0 ; --i){ + if( Tr::eq(operator[](i-1), c) ){ + return i-1; + } + } + return npos; + } + + _UCXXEXPORT size_type find_first_not_of(const basic_string& str, size_type pos = 0) const{ + bool foundCharacter; + for(size_type i = pos; i < length(); ++i){ + foundCharacter = false; + for(size_type j = 0; j < str.length() ; ++j){ + if( Tr::eq(str[j], operator[](i)) ){ + foundCharacter = true; + } + } + if(foundCharacter == false){ + return i; + } + } + return npos; + } + + _UCXXEXPORT size_type find_first_not_of(const Ch* s, size_type pos, size_type n) const{ + return find_first_not_of(basic_string(s,n),pos); + } + _UCXXEXPORT size_type find_first_not_of(const Ch* s, size_type pos = 0) const{ + return find_first_not_of(basic_string(s),pos); + } + _UCXXEXPORT size_type find_first_not_of(Ch c, size_type pos = 0) const{ + for(size_type i = pos; i < length() ; ++i){ + if(operator[](i) != c){ + return i; + } + } + return npos; + } + _UCXXEXPORT size_type find_last_not_of (const basic_string& str, size_type pos = npos) const{ + size_type xpos(length() - 1); + if(xpos > pos){ + xpos = pos; + } + + while(xpos != npos && npos != str.find_first_of(at(xpos))){ + --xpos; + } + + return xpos; + } + + _UCXXEXPORT size_type find_last_not_of (const Ch* s, size_type pos, size_type n) const{ + return find_last_not_of(basic_string(s,n),pos); + } + _UCXXEXPORT size_type find_last_not_of (const Ch* s, size_type pos = npos) const{ + return find_last_not_of(basic_string(s),pos); + } + _UCXXEXPORT size_type find_last_not_of (Ch c, size_type pos = npos) const{ + size_type xpos(length() - 1); + if(xpos > pos){ + xpos = pos; + } + while(xpos != npos && Tr::eq(at(xpos), c)){ + --xpos; + } + return xpos; + + } + + _UCXXEXPORT basic_string substr(size_type pos = 0, size_type n = npos) const; + + _UCXXEXPORT int compare(const basic_string& str) const{ + size_type rlen = vector::elements; + if(rlen > str.elements){ + rlen = str.elements; + } + int retval = Tr::compare(vector::data, str.vector::data, rlen); + if(retval == 0){ + if(vector::elements < str.elements){ + retval = -1; + } + if(vector::elements > str.elements){ + retval = 1; + } + } + return retval; + } + + _UCXXEXPORT int compare(size_type pos1, size_type n1, const basic_string& str, + size_type pos2=0, size_type n2=npos) const{ + size_type len1 = vector::elements - pos1; + if(len1 > n1){ + len1 = n1; + } + size_type len2 = str.vector::elements - pos2; + if(len2 > n2){ + len2 = n2; + } + size_type rlen = len1; + if(rlen > len2){ + rlen = len2; + } + int retval = Tr::compare(vector::data + pos1, str.vector::data + pos2, rlen); + if(retval == 0){ + if(len1 < len2){ + retval = -1; + } + if(len1 > len2){ + retval = 1; + } + } + return retval; + } + + _UCXXEXPORT int compare(const Ch* s) const{ + size_type slen = Tr::length(s); + size_type rlen = slen; + if(rlen > vector::elements){ + rlen=vector::elements; + } + int retval = Tr::compare(vector::data, s, rlen); + if(retval==0){ + if(vector::elements < slen){ + retval = -1; + } + if(vector::elements > slen){ + retval = 1; + } + } + return retval; + } + + _UCXXEXPORT int compare(size_type pos1, size_type n1, const Ch* s, size_type n2 = npos) const{ + size_type len1 = vector::elements - pos1; + if(len1 > n1){ + len1 = n1; + } + size_type slen = Tr::length(s); + size_type len2 = slen; + if(len2 > n2){ + len2 = n2; + } + size_type rlen = len1; + if(rlen > len2){ + rlen = len2; + } + int retval = Tr::compare(vector::data + pos1, s, rlen); + if(retval == 0){ + if(len1 < len2){ + retval = -1; + } + if(len1 > len2){ + retval = 1; + } + } + return retval; + } + +}; + + +//Functions + +template _UCXXEXPORT basic_string::basic_string(const Ch* s, const A& al) + : vector(al) +{ + if(s!=0){ + size_type temp = Tr::length(s); + append(s, temp); + } +} + +template _UCXXEXPORT basic_string:: + basic_string(const basic_string& str, size_type pos, size_type n, const A& al) + : vector(al) +{ + if(pos>str.size()){ + __throw_out_of_range(); + } + size_type rlen = str.size() - pos; + if( rlen > n){ + rlen = n; + } + resize(rlen); + Tr::copy(vector::data, str.vector::data + pos, vector::elements); +} + +template _UCXXEXPORT basic_string& + basic_string::operator=(const basic_string & str) +{ + if(&str == this){ //Check if we are doing a=a + return *this; + } + vector::clear(); + resize(str.elements); + Tr::copy( vector::data, str.vector::data, str.elements); + return *this; +} + + +template _UCXXEXPORT typename basic_string::size_type + basic_string::find (const basic_string& str, size_type pos) const +{ + if(str.length() > length()){ + return npos; + } + size_type max_string_start = 1 + length() - str.length(); + for(size_type i = pos; i < max_string_start; ++i){ + if(str == substr(i, str.length())){ + return i; + } + } + return npos; +} + + +template + _UCXXEXPORT basic_string basic_string::substr(size_type pos, size_type n) const +{ + if(pos > vector::elements){ + __throw_out_of_range(); + } + size_type rlen = vector::elements - pos; + if(rlen > n){ + rlen = n; + } + return basic_string(vector::data + pos,rlen); +} + + + + +#ifdef __UCLIBCXX_EXPAND_STRING_CHAR__ +#ifndef __UCLIBCXX_COMPILE_STRING__ + +#ifdef __UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ + + template <> _UCXXEXPORT string::basic_string(const allocator &); + template <> _UCXXEXPORT string::basic_string(size_type n, char c, const allocator & ); + template <> _UCXXEXPORT string::basic_string(const char* s, const allocator& al); + template <> _UCXXEXPORT string::basic_string(const basic_string& str, size_type pos, size_type n, const allocator& al); + template <> _UCXXEXPORT string::~basic_string(); + +#endif + + template <> _UCXXEXPORT string & string::append(const char * s, size_type n); + + + template <> _UCXXEXPORT string::size_type string::find(const string & str, size_type pos) const; + template <> _UCXXEXPORT string::size_type string::find(const char* s, size_type pos) const; + template <> _UCXXEXPORT string::size_type string::find (char c, size_type pos) const; + + template <> _UCXXEXPORT string::size_type string::rfind(const string & str, size_type pos) const; + template <> _UCXXEXPORT string::size_type string::rfind(char c, size_type pos) const; + template <> _UCXXEXPORT string::size_type string::rfind(const char* s, size_type pos) const; + + template <> _UCXXEXPORT string::size_type string::find_first_of(const string &, size_type) const; + template <> _UCXXEXPORT string::size_type string::find_first_of(const char *, size_type pos, size_type n) const; + template <> _UCXXEXPORT string::size_type string::find_first_of(const char*, size_type pos) const; + template <> _UCXXEXPORT string::size_type string::find_first_of(char c, size_type pos) const; + + template <> _UCXXEXPORT string::size_type string::find_last_of (const string & , size_type pos) const; + template <> _UCXXEXPORT string::size_type string::find_last_of (const char* s, size_type pos, size_type n) const; + template <> _UCXXEXPORT string::size_type string::find_last_of (const char* s, size_type pos) const; + template <> _UCXXEXPORT string::size_type string::find_last_of (char c, size_type pos) const; + + template <> _UCXXEXPORT string::size_type string::find_first_not_of(const string &, size_type) const; + template <> _UCXXEXPORT string::size_type string::find_first_not_of(const char*, size_type, size_type) const; + template <> _UCXXEXPORT string::size_type string::find_first_not_of(const char*, size_type) const; + template <> _UCXXEXPORT string::size_type string::find_first_not_of(char c, size_type) const; + + template <> _UCXXEXPORT int string::compare(const string & str) const; + template <> _UCXXEXPORT int string::compare( + size_type pos1, size_type n1, const string & str, size_type pos2, size_type n2) const; + + template <> _UCXXEXPORT string string::substr(size_type pos, size_type n) const; + + template <> _UCXXEXPORT string & string::operator=(const string & str); + template <> _UCXXEXPORT string & string::operator=(const char * s); + +#endif +#endif + + + + +//typedef basic_string string; + +template _UCXXEXPORT basic_string + operator+(const basic_string& lhs, const basic_string& rhs) +{ + basic_string temp(lhs); + temp.append(rhs); + return temp; +} + +template _UCXXEXPORT basic_string + operator+(const charT* lhs, const basic_string& rhs) +{ + basic_string temp(lhs); + temp.append(rhs); + return temp; +} + + +template _UCXXEXPORT basic_string + operator+(charT lhs, const basic_string& rhs) +{ + basic_string temp(1, lhs); + temp.append(rhs); + return temp; +} + +template _UCXXEXPORT basic_string + operator+(const basic_string& lhs, const charT* rhs) +{ + basic_string temp(lhs); + temp.append(rhs); + return temp; +} + +template _UCXXEXPORT basic_string + operator+(const basic_string& lhs, charT rhs) +{ + basic_string temp(lhs); + temp+=rhs; + return temp; +} + +template _UCXXEXPORT bool + operator==(const basic_string& lhs, const basic_string& rhs) +{ + if(lhs.compare(rhs) == 0){ + return true; + } + return false; +} + +template _UCXXEXPORT bool + operator==(const charT* lhs, const basic_string& rhs) +{ + if(rhs.compare(lhs) == 0){ + return true; + } + return false; +} + +template _UCXXEXPORT bool + operator==(const basic_string& lhs, const charT* rhs) +{ + if(lhs.compare(rhs)==0){ + return true; + } + return false; +} + +template _UCXXEXPORT bool + operator!=(const basic_string& lhs, const basic_string& rhs) +{ + if(lhs.compare(rhs) !=0){ + return true; + } + return false; +} + +template _UCXXEXPORT bool + operator!=(const charT* lhs, const basic_string& rhs) +{ + basic_string temp(lhs); + return (temp != rhs); +} + +template _UCXXEXPORT bool + operator!=(const basic_string& lhs, const charT* rhs) +{ + basic_string temp(rhs); + return (lhs != temp); +} + +template _UCXXEXPORT bool + operator< (const basic_string& lhs, const basic_string& rhs) +{ + if(lhs.compare(rhs) < 0){ + return true; + } + return false; +} + +template _UCXXEXPORT bool + operator< (const basic_string& lhs, const charT* rhs) +{ + basic_string temp(rhs); + if(lhs.compare(rhs) < 0){ + return true; + } + return false; +} + +template _UCXXEXPORT bool + operator< (const charT* lhs, const basic_string& rhs) +{ + basic_string temp(lhs); + if(temp.compare(rhs) < 0){ + return true; + } + return false; +} + + +template _UCXXEXPORT bool + operator> (const basic_string& lhs, const basic_string& rhs) +{ + if(lhs.compare(rhs) > 0){ + return true; + } + return false; +} + +template _UCXXEXPORT bool + operator> (const basic_string& lhs, const charT* rhs) +{ + basic_string temp(rhs); + if(lhs.compare(rhs) > 0){ + return true; + } + return false; +} + +template _UCXXEXPORT bool + operator> (const charT* lhs, const basic_string& rhs) +{ + basic_string temp(lhs); + if(temp.compare(rhs) > 0){ + return true; + } + return false; +} + +template _UCXXEXPORT bool + operator<=(const basic_string& lhs, const basic_string& rhs) +{ + if(lhs.compare(rhs) <=0){ + return true; + } + return false; +} + +template _UCXXEXPORT bool + operator<=(const basic_string& lhs, const charT* rhs) +{ + basic_string temp(rhs); + if(lhs.compare(temp) <=0 ){ + return true; + } + return false; +} + +template _UCXXEXPORT bool + operator<=(const charT* lhs, const basic_string& rhs) +{ + basic_string temp(lhs); + if(temp.compare(rhs) <= 0){ + return true; + } + return false; +} + +template _UCXXEXPORT bool + operator>=(const basic_string& lhs, const basic_string& rhs) +{ + if(lhs.compare(rhs) >=0){ + return true; + } + return false; +} + +template _UCXXEXPORT bool + operator>=(const basic_string& lhs, const charT* rhs) +{ + basic_string temp(rhs); + if(lhs.compare(temp) >=0 ){ + return true; + } + return false; +} + +template _UCXXEXPORT bool + operator>=(const charT* lhs, const basic_string& rhs) +{ + basic_string temp(lhs); + if(temp.compare(rhs) >=0 ){ + return true; + } + return false; +} + +template _UCXXEXPORT void + swap(basic_string& lhs, basic_string& rhs) +{ + lhs.swap(rhs); +} + +/*template _UCXXEXPORT basic_ostream& + operator<<(basic_ostream& os, const basic_string& str) +{ + return os.write(str.data(), str.length()); +}*/ + +#ifdef __UCLIBCXX_EXPAND_STRING_CHAR__ +#ifndef __UCLIBCXX_COMPILE_STRING__ + +//Operators we can avoid duplication of + +template <> _UCXXEXPORT bool operator==(const string & lhs, const string & rhs); +template <> _UCXXEXPORT bool operator==(const char * lhs, const string & rhs); +template <> _UCXXEXPORT bool operator==(const string & rhs, const char * rhs); + +template <> _UCXXEXPORT bool operator!=(const string & lhs, const string & rhs); +template <> _UCXXEXPORT bool operator!=(const char * lhs, const string & rhs); +template <> _UCXXEXPORT bool operator!=(const string & rhs, const char * rhs); + +template <> _UCXXEXPORT string operator+(const string & lhs, const char* rhs); +template <> _UCXXEXPORT string operator+(const char* lhs, const string & rhs); +template <> _UCXXEXPORT string operator+(const string & lhs, const string & rhs); + +template <> _UCXXEXPORT bool operator> (const string & lhs, const string & rhs); +template <> _UCXXEXPORT bool operator< (const string & lhs, const string & rhs); + + +#endif +#endif + + +} + +#pragma GCC visibility pop + +#endif Index: branches/slice/rev749/modules/uClibc++/include/complex =================================================================== --- branches/slice/rev749/modules/uClibc++/include/complex (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/complex (revision 1169) @@ -0,0 +1,327 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include + +#ifndef __STD_HEADER_COMPLEX +#define __STD_HEADER_COMPLEX 1 + + +namespace std { +// class complex; +// class complex; +// class complex; + + template class _UCXXEXPORT complex{ + public: + typedef T value_type; + + complex(const T& re = T(), const T& im = T()) : r(re), i(im) { } + complex(const complex& c): r(c.r), i(c.i){ } + template complex(const complex& c): r(c.r), i(c.i){ } + + inline T real() const{ + return r; + } + inline T imag() const{ + return i; + } + + complex& operator= (const T& v){ + r = v; + i = 0; + return *this; + } + complex& operator+=(const T& v){ + r +=v; + return *this; + } + complex& operator-=(const T& v){ + r -=v; + return *this; + } + complex& operator*=(const T& v){ + r*=v; + i*=v; + return *this; + } + complex& operator/=(const T& v){ + r/=v; + i/=v; + return *this; + } + complex& operator=(const complex& v){ + if(&v != this){ + r = v.r; + i = v.i; + } + return *this; + } + template complex& operator= (const complex& v){ + r = v.r; + i = v.i; + return *this; + } + template complex& operator+=(const complex& v){ + r+=v.r; + i+=v.i; + return *this; + } + template complex& operator-=(const complex& v){ + r-=v.r; + i-=v.i; + return *this; + } + template complex& operator*=(const complex& v){ + T tempr = r*v.r - i*v.i; + T tempi = r*v.i + i*v.r; + r = tempr; + i = tempi; + return *this; + } + template complex& operator/=(const complex& v){ + T tempr = (r*v.r + i*v.i) / (v.r*v.r + v.i*v.i); + T tempi = (i*v.r - r*v.i) / (v.r*v.r + v.i*v.i); + r = tempr; + i = tempi; + return *this; + } + private: + T r; + T i; + }; + + template _UCXXEXPORT complex operator+(const complex& ls, const complex& rs){ + complex retval(ls); + retval += rs; + return retval; + } + template _UCXXEXPORT complex operator+(const complex& ls, const T& rs){ + complex retval(ls); + ls += rs; + return retval; + } + template _UCXXEXPORT inline complex operator+(const T& ls, const complex& rs){ + return rs + ls; + } + template _UCXXEXPORT complex operator-(const complex& ls, const complex& rs){ + complex retval(ls); + retval -= rs; + return retval; + } + template _UCXXEXPORT complex operator-(const complex& ls, const T& rs){ + complex retval(ls); + retval -= rs; + return retval; + } + template _UCXXEXPORT complex operator-(const T& ls, const complex& rs){ + complex retval(ls); + retval -= rs; + return retval; + } + template _UCXXEXPORT complex operator*(const complex& ls, const complex& rs){ + complex retval(ls); + retval *= rs; + return retval; + } + template _UCXXEXPORT complex operator*(const complex& ls, const T& rs){ + complex retval(ls); + retval *= rs; + return retval; + } + template _UCXXEXPORT complex operator*(const T& ls, const complex& rs){ + complex retval(ls); + retval *=rs; + return retval; + } + template _UCXXEXPORT complex operator/(const complex& ls, const complex& rs){ + complex retval(ls); + retval/=rs; + return retval; + } + template _UCXXEXPORT complex operator/(const complex& ls, const T& rs){ + complex retval(ls); + retval/=rs; + return retval; + } + template _UCXXEXPORT complex operator/(const T& ls, const complex& rs){ + complex retval(ls); + retval/=rs; + return retval; + } + template _UCXXEXPORT complex operator+(const complex& v){ + return v; + } + template _UCXXEXPORT complex operator-(const complex& v){ + return complex (-v.real(), -v.imag()); + } + template _UCXXEXPORT bool operator==(const complex& ls, const complex& rs){ + if( ls.real() == rs.real() && ls.imag() == rs.image()){ + return true; + } + return false; + } + template _UCXXEXPORT bool operator==(const complex& ls, const T& rs){ + if(ls.real() == rs && ls.imag() == T()){ + return true; + } + return false; + } + template _UCXXEXPORT bool operator==(const T& ls, const complex& rs){ + if(ls == rs.real() && rs.imag() == T()){ + return true; + } + return false; + } + template _UCXXEXPORT bool operator!=(const complex& ls, const complex& rs){ + if(ls == rs){ + return false; + } + return true; + } + template _UCXXEXPORT bool operator!=(const complex& ls, const T& rs){ + if(ls == rs){ + return false; + } + return true; + } + template _UCXXEXPORT bool operator!=(const T& ls, const complex& rs){ + if(ls == rs){ + return false; + } + return true; + } + template _UCXXEXPORT basic_istream& + operator>>(basic_istream& is, complex& v) + { + T tempr; + T tempi; + is >> tempr; + is.get(); + is >> tempi; + v = complex(tempr, tempi); + return is; + } + + template _UCXXEXPORT basic_ostream& + operator<<(basic_ostream& os, const complex&v) + { + os << v.real() << ", " << v.imag(); + return os; + } + + template _UCXXEXPORT T real(const complex& v){ + return v.real(); + } + + template _UCXXEXPORT T imag(const complex& v){ + return v.imag(); + } + + template _UCXXEXPORT T norm(const complex& v){ + return (v.real() * v.real() + v.imag() * v.imag()); + } + + template _UCXXEXPORT complex conj(const complex& v){ + return complex(v.real(), -v.imag()); + } + +#ifdef __UCLIBCXX_SUPPORT_MATH__ //Can we link with libm? + + template _UCXXEXPORT T abs(const complex& v){ + return sqrt(v.real() * v.real() + v.imag() * v.imag()); + } + + template _UCXXEXPORT T arg(const complex& v){ + return atan2(v.imag(), v.real()); + } + + template _UCXXEXPORT complex polar(const T& rho, const T& theta){ + return complex(rho * cos(theta), rho * sin(theta)); + } + + template _UCXXEXPORT complex cos (const complex& v){ + return complex(cos(v.real()) * cosh(v.imag()), -sin(v.real()) * sinh(v.imag())); + } + + template _UCXXEXPORT complex cosh (const complex& v){ + return complex(cosh(v.real()) * cos(v.imag()), sinh(v.real()) * sin(v.imag())); + } + + template _UCXXEXPORT complex exp (const complex& v){ + return polar(exp(v.real()), v.imag()); + } + + template _UCXXEXPORT complex log (const complex& v){ + return complex(log(abs(v)), arg(v)); + } + + template _UCXXEXPORT complex log10(const complex& v){ + return (log(v) / log(T(10.0))); + } + + template _UCXXEXPORT complex pow(const complex& v, int p){ + T rho = pow(abs(v), p); + T theta = arg(v); + return complex(rho * cos(p * theta), rho * sin(p * theta) ); + } + + template _UCXXEXPORT complex pow(const complex& v, const T& p){ + return polar( pow(abs(v),p), arg(v)*p ); + } + + template _UCXXEXPORT complex pow(const complex& v, const complex& p){ + if(v == T()){ + //We are using "0" as the value + return T(); + } + return exp(p * log(v)); + } + + template _UCXXEXPORT complex pow(const T& v, const complex& p){ + if(v == T()){ + return T(); + } + return polar(pow(v,p.real()), y.imag() * log(x) ); + } + + template _UCXXEXPORT complex sin (const complex& v){ + return complex(sin(v.real()) * cosh(v.imag()), cosh(v.real()) * sin(v.imag())); + } + + template _UCXXEXPORT complex sinh (const complex& v){ + return complext(sinh(v.real()) * cos(v.imag()), cosh(v.real()) * sin(v.imag()) ); + } + + template _UCXXEXPORT complex sqrt (const complex&); + template _UCXXEXPORT complex tan (const complex& v){ + return sin(v) / cos(v); + } + + template _UCXXEXPORT complex tanh (const complex& v){ + return sinh(v) / cosh(v); + } + +#endif + +} + +#endif + Index: branches/slice/rev749/modules/uClibc++/include/cfloat =================================================================== --- branches/slice/rev749/modules/uClibc++/include/cfloat (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/cfloat (revision 1169) @@ -0,0 +1,30 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include + +#ifndef __STD_HEADER_CFLOAT +#define __STD_HEADER_CFLOAT 1 + + +#include + + +#endif + Index: branches/slice/rev749/modules/uClibc++/include/ostream =================================================================== --- branches/slice/rev749/modules/uClibc++/include/ostream (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/ostream (revision 1169) @@ -0,0 +1,483 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include + +#ifndef STD_HEADER_OSTREAM +#define STD_HEADER_OSTREAM 1 + +#include +#include +#include +#include + +#pragma GCC visibility push(default) + +namespace std { + template class basic_ostream; + typedef basic_ostream ostream; + +#ifdef __UCLIBCXX_HAS_WCHAR__ + typedef basic_ostream wostream; +#endif + + template basic_ostream& endl(basic_ostream& os); + template basic_ostream& ends(basic_ostream& os); + template basic_ostream& flush(basic_ostream& os); + + template class _UCXXEXPORT basic_ostream + : virtual public basic_ios + { + public: + + typedef charT char_type; + typedef typename traits::int_type int_type; + typedef typename traits::pos_type pos_type; + typedef typename traits::off_type off_type; + typedef traits traits_type; + + + _UCXXEXPORT basic_ostream(basic_streambuf* sb) + : basic_ios(sb) + { + basic_ios::init(sb); + } + virtual _UCXXEXPORT ~basic_ostream(); + + class sentry; + + _UCXXEXPORT basic_ostream& operator<<(basic_ostream& (*pf)(basic_ostream&)){ + return pf(*this); + } + _UCXXEXPORT basic_ostream& operator<<(basic_ios& (*pf)(basic_ios&)){ + pf(*this); + return *this; + } + _UCXXEXPORT basic_ostream& operator<<(ios_base& (*pf)(ios_base&)){ + pf(*this); + return *this; + } + basic_ostream& operator<<(bool n); + basic_ostream& operator<<(short n); + basic_ostream& operator<<(unsigned short n); + basic_ostream& operator<<(int n); + basic_ostream& operator<<(unsigned int n); + basic_ostream& operator<<(long n); + basic_ostream& operator<<(unsigned long n); + basic_ostream& operator<<(float f); + basic_ostream& operator<<(double f); + basic_ostream& operator<<(long double f); + basic_ostream& operator<<(void* p); + basic_ostream& operator<<(basic_streambuf* sb); + + _UCXXEXPORT basic_ostream& put(char_type c){ + if(basic_ostream::traits_type::eq_int_type( + basic_ios::mstreambuf->sputc(c), + basic_ostream::traits_type::eof())) + { + basic_ios::setstate(ios_base::eofbit); + } + return *this; + } + _UCXXEXPORT basic_ostream& write(const char_type* s, streamsize n){ + if(basic_ostream::traits_type::eq_int_type( + basic_ios::mstreambuf->sputn(s, n), + basic_ostream::traits_type::eof()) + ){ + basic_ios::setstate(ios_base::eofbit); + } + return *this; + } + _UCXXEXPORT basic_ostream& flush(){ + if(basic_ios::mstreambuf->pubsync() == -1){ + basic_ios::setstate(ios_base::badbit); + } + return *this; + } + _UCXXEXPORT pos_type tellp(){ + if(basic_ios::fail() != false){ + return pos_type(-1); + } + return basic_ios::rdbuf()->pubseekoff(0, ios_base::cur, ios_base::out); + } + _UCXXEXPORT basic_ostream& seekp(pos_type pos){ + if( basic_ios::fail() != true ){ + basic_ios::rdbuf()->pubseekpos(pos); + } + return *this; + } + _UCXXEXPORT basic_ostream& seekp(off_type off, ios_base::seekdir dir){ + if( basic_ios::fail() != true){ + basic_ios::rdbuf()->pubseekoff(off, dir); + } + return *this; + } + + protected: + basic_ostream(const basic_ostream &){ } + basic_ostream & operator=(const basic_ostream &){ return *this; } + }; + + //Implementations of template functions. To allow for partial specialization + + template _UCXXEXPORT basic_ostream::~basic_ostream(){ } + + template _UCXXEXPORT basic_ostream& basic_ostream::operator<<(bool n){ + sentry s(*this); + if( basic_ios::flags() & ios_base::boolalpha){ + if(n){ + write("true", 4); + }else{ + write("false", 5); + } + }else{ + if(n){ + write("1", 1); + }else{ + write("0", 1); + } + } + if(basic_ios::flags() & ios_base::unitbuf){ + flush(); + } + return *this; + } + + template _UCXXEXPORT basic_ostream& + basic_ostream::operator<<(unsigned short n){ + sentry s(*this); + __ostream_printout::printout(*this, n); + return *this; + } + + template _UCXXEXPORT basic_ostream& basic_ostream::operator<<(short n){ + sentry s(*this); + __ostream_printout::printout(*this, n); + return *this; + } + + template _UCXXEXPORT basic_ostream& basic_ostream::operator<<(int n){ + sentry s(*this); + __ostream_printout::printout(*this, n); + return *this; + } + + template _UCXXEXPORT basic_ostream& basic_ostream::operator<<(unsigned int n){ + sentry s(*this); + __ostream_printout::printout(*this, n); + return *this; + } + + template _UCXXEXPORT basic_ostream& basic_ostream::operator<<(long n){ + sentry s(*this); + __ostream_printout::printout(*this, n); + return *this; + } + + template _UCXXEXPORT basic_ostream& + basic_ostream::operator<<(unsigned long n) + { + sentry s(*this); + __ostream_printout::printout(*this, n); + return *this; + } + + template _UCXXEXPORT basic_ostream& basic_ostream::operator<<(float f){ + sentry s(*this); + __ostream_printout::printout(*this, f); + return *this; + } + + template _UCXXEXPORT basic_ostream& basic_ostream::operator<<(double f){ + sentry s(*this); + __ostream_printout::printout(*this, f); + return *this; + } + + template _UCXXEXPORT basic_ostream& basic_ostream::operator<<(long double f){ + sentry s(*this); + __ostream_printout::printout(*this, f); + return *this; + } + + template _UCXXEXPORT basic_ostream& basic_ostream::operator<<(void* p){ + sentry s(*this); + char buffer[20]; + write(buffer, snprintf(buffer, 20, "%p", p) ); + if(basic_ios::flags() & ios_base::unitbuf){ + flush(); + } + return *this; + } + + template _UCXXEXPORT basic_ostream& + basic_ostream::operator<<(basic_streambuf* sb) + { + sentry s(*this); + if(sb == 0){ + basic_ios::setstate(ios_base::badbit); + return *this; + } + + typename traits::int_type c; + + while(basic_ios::good() && (c = sb->sbumpc()) != traits::eof() ){ + put(c); + } + + if(basic_ios::flags() & ios_base::unitbuf){ + flush(); + } + return *this; + } + + /*Template Specializations*/ + +#ifdef __UCLIBCXX_EXPAND_OSTREAM_CHAR__ +#ifndef __UCLIBCXX_COMPILE_OSTREAM__ + +#ifdef __UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ + + template <> _UCXXEXPORT ostream::~basic_ostream(); + +#endif // __UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ + + template <> _UCXXEXPORT ostream & ostream::flush(); + + template <> _UCXXEXPORT ostream & ostream::operator<<(bool n); + template <> _UCXXEXPORT ostream & ostream::operator<<(short int n); + template <> _UCXXEXPORT ostream & ostream::operator<<(unsigned short int n); + template <> _UCXXEXPORT ostream & ostream::operator<<(int n); + template <> _UCXXEXPORT ostream & ostream::operator<<(unsigned int n); + template <> _UCXXEXPORT ostream & ostream::operator<<(long n); + template <> _UCXXEXPORT ostream & ostream::operator<<(unsigned long n); + template <> _UCXXEXPORT ostream & ostream::operator<<(float f); + template <> _UCXXEXPORT ostream & ostream::operator<<(double f); + template <> _UCXXEXPORT ostream & ostream::operator<<(long double f); + template <> _UCXXEXPORT ostream & ostream::operator<<(void* p); + template <> _UCXXEXPORT ostream & ostream::operator<<(basic_streambuf >* sb); +#endif +#endif + + template > + class _UCXXEXPORT basic_ostream::sentry + { + bool ok; + public: + explicit _UCXXEXPORT sentry(basic_ostream& os): ok(true){ + if(os.good() !=0){ //Prepare for output + } + + //Flush any tied buffer + if(os.tie() !=0 ){ + os.tie()->flush(); + } + } + _UCXXEXPORT ~sentry() { } + _UCXXEXPORT operator bool() { + return ok; + } + }; + + +#ifdef __UCLIBCXX_EXPAND_OSTREAM_CHAR__ +#ifndef __UCLIBCXX_COMPILE_OSTREAM__ +#ifdef __UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ + + template <> _UCXXEXPORT ostream::sentry::sentry(ostream & os); + template <> _UCXXEXPORT ostream::sentry::~sentry(); + +#endif //__UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ +#endif +#endif + + + //Non - class functions + + + template _UCXXEXPORT basic_ostream& + operator<<(basic_ostream& out, charT c) + { + typename basic_ostream::sentry s(out); + out.put(c); + return out; + } + + template _UCXXEXPORT basic_ostream& + operator<<(basic_ostream& out, char c) + { + typename basic_ostream::sentry s(out); + out.put(c); + return out; + } + + template _UCXXEXPORT basic_ostream& + operator<<(basic_ostream& out, char c) + { + typename basic_ostream::sentry s(out); + out.put(c); + return out; + } + + // signed and unsigned + template _UCXXEXPORT basic_ostream& + operator<<(basic_ostream& out, signed char c) + { + typename basic_ostream::sentry s(out); + out.put(c); + return out; + } + + template _UCXXEXPORT basic_ostream& + operator<<(basic_ostream& out, unsigned char c) + { + typename basic_ostream::sentry s(out); + out.put(c); + return out; + } + + template _UCXXEXPORT basic_ostream& + operator<<(basic_ostream& out, const charT* c) + { + typename basic_ostream::sentry s(out); + out.write(c, traits::length(c) ); + return out; + } + + template _UCXXEXPORT basic_ostream& + operator<<(basic_ostream& out, const char* c) + { + typename basic_ostream::sentry s(out); + out.write(c, char_traits::length(c) ); + return out; + } + + // partial specializations + template _UCXXEXPORT basic_ostream& + operator<<(basic_ostream& out, const char* c) + { + typename basic_ostream::sentry s(out); + out.write(c, traits::length(c)); + return out; + } + +#ifdef __UCLIBCXX_HAS_WCHAR__ + template _UCXXEXPORT basic_ostream& + operator<<(basic_ostream& out, const char* c) + { + typename basic_ostream::sentry s(out); + size_t numChars = char_traits::length(c); + wchar_t * temp = new wchar_t[numChars]; + + for(size_t i=0; i < numChars; ++i){ + temp[i] = out.widen(c[i]); + } + + out.write(temp, numChars); + return out; + } +#endif + + // signed and unsigned + template _UCXXEXPORT basic_ostream& + operator<<(basic_ostream& out, const signed char* c) + { + typename basic_ostream::sentry s(out); + out.write(reinterpret_cast(c), traits::length( reinterpret_cast(c))); + return out; + } + + template _UCXXEXPORT basic_ostream& + operator<<(basic_ostream& out, const unsigned char* c) + { + typename basic_ostream::sentry s(out); + out.write(reinterpret_cast(c), traits::length( reinterpret_cast(c))); + return out; + } + + template _UCXXEXPORT basic_ostream& + endl(basic_ostream& os) + { + typename basic_ostream::sentry s(os); + os.put('\n'); + os.flush(); + return os; + } + + template _UCXXEXPORT basic_ostream& + ends(basic_ostream& os) + { + typename basic_ostream::sentry s(os); + os.put(traits::eos()); + return os; + } + + template _UCXXEXPORT basic_ostream& flush(basic_ostream& os){ + typename basic_ostream::sentry s(os); + os.flush(); + return os; + } + + +#ifdef __UCLIBCXX_EXPAND_OSTREAM_CHAR__ +#ifndef __UCLIBCXX_COMPILE_OSTREAM__ + template <> _UCXXEXPORT ostream & endl(ostream & os); + template <> _UCXXEXPORT ostream & flush(ostream & os); + template <> _UCXXEXPORT ostream & operator<<(ostream & out, char c); + template <> _UCXXEXPORT ostream & operator<<(ostream & out, const char* c); + template <> _UCXXEXPORT ostream & operator<<(ostream & out, unsigned char c); + template <> _UCXXEXPORT ostream & operator<<(ostream & out, unsigned const char* c); + +#endif +#endif + + +#ifndef __STRICT_ANSI__ + +//Support for output of long long data types + +template _UCXXEXPORT basic_ostream& + operator<<(basic_ostream& os, signed long long int i) +{ + typename basic_ostream::sentry s(os); + __ostream_printout::printout(os, i); + return os; +} + + +template _UCXXEXPORT basic_ostream& + operator<<(basic_ostream& os, unsigned long long int i) +{ + typename basic_ostream::sentry s(os); + __ostream_printout::printout(os, i); + return os; +} + + +#endif //__STRICT_ANSI__ + + + + +} + +#pragma GCC visibility pop + +#endif + Index: branches/slice/rev749/modules/uClibc++/include/sstream =================================================================== --- branches/slice/rev749/modules/uClibc++/include/sstream (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/sstream (revision 1169) @@ -0,0 +1,384 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include + +#ifndef HEADER_STD_SSTREAM +#define HEADER_STD_SSTREAM 1 + +#include +#include +#include +#include +#include +#include + +#pragma GCC visibility push(default) + +namespace std{ + + template + class _UCXXEXPORT basic_stringbuf : public basic_streambuf + { + public: + typedef charT char_type; + typedef typename traits::int_type int_type; + typedef typename traits::pos_type pos_type; + typedef typename traits::off_type off_type; + typedef typename Allocator::size_type size_type; + + explicit _UCXXEXPORT basic_stringbuf(ios_base::openmode which = ios_base::in | ios_base::out) + : data(), ielement(0), oelement(0) + { + basic_streambuf::openedFor = which; + } + + explicit _UCXXEXPORT basic_stringbuf(const basic_string& str, + ios_base::openmode which = ios_base::in | ios_base::out) + : data(str), ielement(0), oelement(0) + { + if(which & ios_base::ate){ + oelement = data.length(); + } + basic_streambuf::openedFor = which; + } + + virtual _UCXXEXPORT ~basic_stringbuf() { } + + _UCXXEXPORT basic_string str() const{ + return data; + } + + _UCXXEXPORT void str(const basic_string& s){ + data = s; + ielement = 0; + if(basic_streambuf::openedFor & ios_base::ate){ + oelement = data.length(); + }else{ + oelement = 0; + } + } + + protected: + virtual _UCXXEXPORT int sync(){ + return 0; + } + virtual _UCXXEXPORT int_type underflow(){ + if(ielement >= data.length()){ + return traits::eof(); + } + return traits::to_int_type(data[ielement]); + } + + virtual _UCXXEXPORT int_type uflow(){ + int_type retval = underflow(); + if(retval != traits::eof()){ + ++ielement; + } + return retval; + } + + virtual _UCXXEXPORT int_type pbackfail(int_type c = traits::eof()){ + //Error possibilities + if(ielement == 0){ + return traits::eof(); + } + if(ielement > data.length()){ + ielement = data.length(); + return traits::eof(); + } + //eof passed in + if(traits::eq_int_type(c,traits::eof())==true){ + --ielement; + return traits::not_eof(c); + } + if(traits::eq(traits::to_char_type(c),data[ielement-1]) == true){ + --ielement; + return c; + } + if(basic_streambuf::openedFor & ios_base::out){ + --ielement; + data[ielement] = c; + return c; + } + return traits::eof(); + } + + virtual _UCXXEXPORT int showmanyc(){ + return data.length() - ielement; + } + virtual _UCXXEXPORT streamsize xsgetn(char_type* c, streamsize n){ + streamsize i = 0; + while(ielement < data.length() && i < n ){ + c[i] = data[ielement]; + ++i; + ++ielement; + } + return i; + } + + virtual _UCXXEXPORT int_type overflow (int_type c = traits::eof()){ + //Nothing to do + if(traits::eq_int_type(c,traits::eof())){ + return traits::not_eof(c); + } + + //Actually add character, if possible + if(basic_streambuf::openedFor & ios_base::out){ + if(oelement >= data.length()){ + data.push_back(c); + }else{ + data[oelement] = c; + } + ++oelement; + return c; + } + //Not possible + return traits::eof(); + } + + virtual _UCXXEXPORT basic_streambuf* setbuf(charT*, streamsize){ + //This function does nothing + return this; + } + + virtual _UCXXEXPORT streamsize xsputn(const char_type* s, streamsize n){ + data.replace(oelement, n, s, n); + oelement += n; + return n; + } + + virtual _UCXXEXPORT pos_type seekoff(off_type off, ios_base::seekdir way, + ios_base::openmode which = ios_base::in | ios_base::out) + { + //Test for invalid option + if( (which & ios_base::in) && (which & ios_base::out) && (way == ios_base::cur)){ + return -1; + } + + //Calculate new location + size_type newpos = 0; + + if(way == ios_base::beg){ + newpos = off; + }else if(way == ios_base::cur){ + if(which & ios_base::out){ + newpos = data.length() + off; + } + if(which & ios_base::in){ + newpos = ielement + off; + } + + }else{ + newpos = data.length() + off; + } + + //Test for error conditions + if(newpos > data.length()){ + return -1; + } + + //Shuffle pointers + + if(which & ios_base::in){ + ielement = newpos; + } + if(which & ios_base::out){ + data.resize(newpos); + if(ielement > data.length()){ + ielement = data.length(); + } + } + + return newpos; + } + + virtual _UCXXEXPORT pos_type seekpos(pos_type sp, + ios_base::openmode which = ios_base::in | ios_base::out) + { + return seekoff(sp, ios_base::beg, which); + } + + basic_string data; + size_type ielement; + size_type oelement; + }; + + + template class _UCXXEXPORT basic_istringstream + : public basic_istream + { + public: + typedef charT char_type; + typedef typename traits::int_type int_type; + typedef typename traits::pos_type pos_type; + typedef typename traits::off_type off_type; + + + explicit _UCXXEXPORT basic_istringstream(ios_base::openmode m = ios_base::in) + : basic_ios(&sb), basic_istream(&sb), sb(m) + { + } + explicit _UCXXEXPORT basic_istringstream( const basic_string& str, + ios_base::openmode which = ios_base::in) + : basic_ios(&sb), basic_istream(&sb), sb(str, which) + { + } + virtual _UCXXEXPORT ~basic_istringstream() { } + _UCXXEXPORT basic_stringbuf* rdbuf() const{ + return &sb; + } + _UCXXEXPORT basic_string str() const{ + return sb.str(); + } + _UCXXEXPORT void str(const basic_string& s){ + sb.str(s); + basic_istream::clear(); + } + private: + basic_stringbuf sb; + }; + + + template class _UCXXEXPORT basic_ostringstream + : public basic_ostream + { + public: + + typedef charT char_type; + typedef typename traits::int_type int_type; + typedef typename traits::pos_type pos_type; + typedef typename traits::off_type off_type; + + explicit _UCXXEXPORT basic_ostringstream(ios_base::openmode m = ios_base::out) + : basic_ios(&sb), basic_ostream(&sb), sb(m) + { + } + explicit _UCXXEXPORT basic_ostringstream(const basic_string& str, + ios_base::openmode which = ios_base::out) + : basic_ios(&sb), basic_ostream(&sb), sb(str, which) + { + } + virtual _UCXXEXPORT ~basic_ostringstream() { } + + _UCXXEXPORT basic_stringbuf* rdbuf() const{ + return &sb; + } + _UCXXEXPORT basic_string str() const{ + return sb.str(); + } + _UCXXEXPORT void str(const basic_string& s){ + sb.str(s); + basic_ostream::clear(); + } + private: + basic_stringbuf sb; + }; + + + template class _UCXXEXPORT basic_stringstream + : public basic_iostream + { + public: + + typedef charT char_type; + typedef typename traits::int_type int_type; + typedef typename traits::pos_type pos_type; + typedef typename traits::off_type off_type; + + explicit _UCXXEXPORT basic_stringstream(ios_base::openmode which = ios_base::out|ios_base::in) + : basic_ios(&sb), basic_iostream(&sb), sb(which) + { + } + + explicit _UCXXEXPORT basic_stringstream(const basic_string& str, + ios_base::openmode which = ios_base::out|ios_base::in) + : basic_ios(&sb), basic_iostream(&sb), sb(str, which) + { + } + virtual _UCXXEXPORT ~basic_stringstream(){ } + + _UCXXEXPORT basic_stringbuf* rdbuf(){ + return &sb; + } + _UCXXEXPORT basic_string str() const{ + return sb.str(); + } + _UCXXEXPORT void str(const basic_string& s){ + sb.str(s); + basic_iostream::clear(); + } + private: + basic_stringbuf sb; + }; + +#ifdef __UCLIBCXX_EXPAND_SSTREAM_CHAR__ +#ifndef __UCLIBCXX_COMPILE_SSTREAM__ + +#ifdef __UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ + + template <> _UCXXEXPORT basic_stringbuf, allocator >:: + basic_stringbuf(ios_base::openmode which); + template <> _UCXXEXPORT basic_stringbuf, allocator >::~basic_stringbuf(); + +#endif // __UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ + + template <> _UCXXEXPORT basic_string, allocator > + basic_stringbuf, allocator >::str() const; + + template <> _UCXXEXPORT basic_stringbuf, allocator >::int_type + basic_stringbuf, allocator >:: + pbackfail(basic_stringbuf, allocator >::int_type c); + + template <> _UCXXEXPORT basic_stringbuf, allocator >::pos_type + basic_stringbuf, allocator >:: + seekoff (basic_stringbuf, allocator >::off_type off, + ios_base::seekdir way, + ios_base::openmode which + ); + + template <> _UCXXEXPORT basic_stringbuf, allocator >::int_type + basic_stringbuf, allocator >:: + overflow (basic_stringbuf, allocator >::int_type c); + + template <> _UCXXEXPORT basic_stringbuf, allocator >::int_type + basic_stringbuf, allocator >::underflow (); + + template <> _UCXXEXPORT streamsize basic_stringbuf, allocator >:: + xsputn(const char* s, streamsize n); + +#ifdef __UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ + + template <> _UCXXEXPORT basic_stringstream, allocator >:: + basic_stringstream(ios_base::openmode which); + template <> _UCXXEXPORT basic_stringstream, allocator >::~basic_stringstream(); + template <> _UCXXEXPORT basic_istringstream, allocator >::~basic_istringstream(); + template <> _UCXXEXPORT basic_ostringstream, allocator >::~basic_ostringstream(); + +#endif //__UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ + +#endif +#endif + +#pragma GCC visibility pop + +} + + +#endif Index: branches/slice/rev749/modules/uClibc++/include/csignal =================================================================== --- branches/slice/rev749/modules/uClibc++/include/csignal (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/csignal (revision 1169) @@ -0,0 +1,61 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 +// Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// +// ISO C++ 14882: 20.4.6 C library +// + +/** @file csignal + * This is a Standard C++ Library file. You should @c #include this file + * in your programs, rather than any of the "*.h" implementation files. + * + * This is the C++ version of the Standard C Library header @c signal.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std. + */ + +#ifndef _CPP_CSIGNAL +#define _CPP_CSIGNAL 1 + +#pragma GCC system_header + +#include + +// Get rid of those macros defined in in lieu of real functions. +#undef raise + +namespace std +{ + using ::sig_atomic_t; + using ::signal; + using ::raise; +} + +#endif Index: branches/slice/rev749/modules/uClibc++/include/valarray =================================================================== --- branches/slice/rev749/modules/uClibc++/include/valarray (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/valarray (revision 1169) @@ -0,0 +1,996 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include + +#ifndef __HEADER_STD_VALARRAY +#define __HEADER_STD_VALARRAY 1 + +#include +#include + +#pragma GCC visibility push(default) + +namespace std{ + + template class valarray; + class slice; + template class slice_array; + class gslice; + template class gslice_array; + template class mask_array; + template class indirect_array; + + //Actual class definitions + + + class _UCXXEXPORT slice { + protected: + size_t sta; + size_t siz; + size_t str; + + public: + slice() : sta(0), siz(0), str(0){ } + slice(size_t a, size_t b, size_t c) : sta(a), siz(b), str(c) { } + slice(const slice& s) : sta(s.sta), siz(s.siz), str(s.str) { } + ~slice() { } + size_t start() const{ + return sta; + } + size_t size() const{ + return siz; + } + size_t stride() const{ + return str; + } + }; + + + + template class _UCXXEXPORT valarray { + friend class slice_array; + protected: + T * data; + size_t length; + + public: + typedef T value_type; + + valarray() : data(0), length(0) { } + + explicit valarray(size_t t) : data(0), length(t){ + data = new T[length]; + } + + valarray(const T& v, size_t t) : data(0), length(t){ + data = new T[length]; + for(size_t i = 0; i < length; ++i){ + data[i] = v; + } + } + valarray(const T* p, size_t t) : data(0), length(t) { + data = new T[length]; + for(size_t i = 0; i < length; ++i){ + data[i] = p[i]; + } + } + valarray(const valarray& v) : data(0), length(v.length){ + data = new T[length]; + for(size_t i = 0; i < length; ++i){ + data[i] = v.data[i]; + } + } + valarray(const slice_array & sa) : data(0), length(sa.s.size()){ + data = new T[length]; + for(unsigned int i = 0; i < length; ++i){ + data[i] = sa.array->data[sa.s.start() + i * sa.s.stride()]; + } + } + valarray(const gslice_array&); + valarray(const mask_array&); + valarray(const indirect_array&); + ~valarray(){ + delete [] data; + data = 0; + length = 0; + } + + valarray& operator=(const valarray& v){ + for(size_t i =0; i< length; ++i){ + data[i] = v.data[i]; + } + return *this; + } + valarray& operator=(const T& t){ + for(size_t i = 0; i < length; ++i){ + data[i] = t; + } + return *this; + } + valarray& operator=(const slice_array& sa){ + for(size_t i =0; i < length; ++i){ + data[i] = sa.data[sa.s.start() + i * sa.s.stride()]; + } + return *this; + } + valarray& operator=(const gslice_array&); + valarray& operator=(const mask_array&); + valarray& operator=(const indirect_array&); + + T operator[](size_t t) const{ + return data[t]; + } + T& operator[](size_t t){ + return data[t]; + } + + valarray operator[](slice s) const{ + valarray retval(s.size()); + for(unsigned int i = 0; i< s.size(); ++i){ + retval.data[i] = data[s.start() + i * s.stride()]; + } + return retval; + } + + slice_array operator[](slice sl){ + slice_array retval; + retval.s = sl; + retval.array = this; + return retval; + } + + valarray operator[](const gslice&) const; + gslice_array operator[](const gslice&); + valarray operator[](const valarray&) const; + mask_array operator[](const valarray&); + valarray operator[](const valarray&) const; + indirect_array operator[](const valarray&); + + valarray operator+() const{ + valarray retval(length); + for(size_t i = 0; i< length ; ++i){ + retval.data[i] = +data[i]; + } + return retval; + } + valarray operator-() const{ + valarray retval(length); + for(size_t i = 0; i< length; ++i){ + retval.data[i] = -data[i]; + } + return retval; + } + valarray operator~() const{ + valarray retval(length); + for(size_t i = 0; i< length ; ++i){ + retval.data[i] = ~data[i]; + } + return retval; + } + valarray operator!() const{ + valarray retval(length); + for(size_t i = 0; i< length ; ++i){ + retval.data[i] = !data[i]; + } + return retval; + } + valarray& operator*= (const T& t){ + for(size_t i=0;i& operator/= (const T& t){ + for(size_t i=0;i& operator%= (const T& t){ + for(size_t i=0;i& operator+= (const T& t){ + for(size_t i=0;i& operator-= (const T& t){ + for(size_t i=0;i& operator^= (const T& t){ + for(size_t i=0;i& operator&= (const T& t){ + for(size_t i=0;i& operator|= (const T& t){ + for(size_t i=0;i& operator<<=(const T& t){ + for(size_t i=0;i& operator>>=(const T& t){ + for(size_t i=0;i>= t; + } + return *this; + } + valarray& operator*= (const valarray& a){ + for(size_t i=0;i& operator/= (const valarray& a){ + for(size_t i=0;i& operator%= (const valarray& a){ + for(size_t i=0;i& operator+= (const valarray& a){ + for(size_t i=0;i& operator-= (const valarray& a){ + for(size_t i=0;i& operator^= (const valarray& a){ + for(size_t i=0;i& operator|= (const valarray& a){ + for(size_t i=0;i& operator&= (const valarray& a){ + for(size_t i=0;i& operator<<=(const valarray& a){ + for(size_t i=0;i& operator>>=(const valarray& a){ + for(size_t i=0;i>= a.data[i]; + } + return *this; + } + + size_t size() const{ + return length; + } + + T sum() const{ + T retval(data[0]); + for(size_t i = 1; i< length; ++i){ + retval += data[i]; + } + return retval; + } + + T min() const{ + T retval(data[0]); + for(size_t i = 1; i< length; ++i){ + if(data[i] < retval){ + retval = data[i]; + } + } + return retval; + } + + T max() const{ + T retval(data[0]); + for(size_t i = 1; i< length; ++i){ + if(retval < data[i]){ + retval = data[i]; + } + } + return retval; + } + + valarray shift (int n) const{ + valarray retval(length); + for(size_t i = 0; i < length ; ++i){ + if(i + n > 0 && i + n < length){ + retval.data[i] = data[i + n]; + } + } + return retval; + } + valarray cshift(int n) const{ + valarray retval(length); + for(size_t i = 0; i < length ; ++i){ + retval.data[i] = data[ (i + n) % length ]; + } + return retval; + } + valarray apply(T func(T) ) const{ + valarray retval(length); + for(size_t i = 0; i< length; ++i){ + retval.data[i] = func(data[i]); + } + return retval; + } + valarray apply(T func(const T&)) const{ + valarray retval(length); + for(size_t i = 0; i< length; ++i){ + retval.data[i] = func(data[i]); + } + return retval; + } + void resize(size_t sz, T c = T()){ + delete [] data; + data = 0; + if(sz > 0){ + data = new T[sz]; + for(size_t i = 0; i < sz; ++i){ + data[i] = c; + } + } + length = sz; + } + }; + + + + template class _UCXXEXPORT slice_array { + friend class valarray; + public: + typedef T value_type; + + void operator= (const valarray& v) const{ + for(unsigned int i = 0; i < s.size(); ++i){ + array->data[s.start() + i * s.stride()] = v[i]; + } + } + void operator= (const T & v){ + for(unsigned int i = 0; i < s.size(); ++i){ + array->data[s.start() + i * s.stride()] = v; + } + } + void fill(const T & v){ + for(unsigned int i = 0; i < s.size(); ++i){ + array->data[s.start() + i * s.stride()] = v; + } + } + void operator*= (const valarray& v) const{ + for(unsigned int i = 0; i < s.size(); ++i){ + array->data[s.start() + i * s.stride()] *= v[i]; + } + } + void operator/= (const valarray& v) const{ + for(unsigned int i = 0; i < s.size(); ++i){ + array->data[s.start() + i * s.stride()] /= v[i]; + } + } + void operator%= (const valarray& v) const{ + for(unsigned int i = 0; i < s.size(); ++i){ + array->data[s.start() + i * s.stride()] %= v[i]; + } + } + void operator+= (const valarray& v) const{ + for(unsigned int i = 0; i < s.size(); ++i){ + array->data[s.start() + i * s.stride()] += v[i]; + } + } + void operator-= (const valarray& v) const{ + for(unsigned int i = 0; i < s.size(); ++i){ + array->data[s.start() + i * s.stride()] -= v[i]; + } + } + void operator^= (const valarray& v) const{ + for(unsigned int i = 0; i < s.size(); ++i){ + array->data[s.start() + i * s.stride()] ^= v[i]; + } + } + void operator&= (const valarray& v) const{ + for(unsigned int i = 0; i < s.size(); ++i){ + array->data[s.start() + i * s.stride()] &= v[i]; + } + } + void operator|= (const valarray& v) const{ + for(unsigned int i = 0; i < s.size(); ++i){ + array->data[s.start() + i * s.stride()] |= v[i]; + } + } + void operator<<=(const valarray& v) const{ + for(unsigned int i = 0; i < s.size(); ++i){ + array->data[s.start() + i * s.stride()] <<= v[i]; + } + } + void operator>>=(const valarray& v) const{ + for(unsigned int i = 0; i < s.size(); ++i){ + array->data[s.start() + i * s.stride()] >>= v[i]; + } + } + ~slice_array(){ + array = 0; + } + + private: + slice_array() : array(0){ } + + public: + slice_array(const slice_array& sa) : array(sa.array), s(sa.s){ } + slice_array& operator=(const slice_array& sa){ + array = sa.array; + s = sa.s; + } + + private: + valarray * array; + slice s; + }; + + + class _UCXXEXPORT gslice { + private: + size_t sta; + valarray siz; + valarray str; + + public: + gslice() : sta(0) { } + gslice(size_t s, const valarray& l, const valarray& d) + : sta(s), siz(l), str(d) { } + + size_t start() const{ + return sta; + } + valarray size() const{ + return siz; + } + valarray stride() const{ + return str; + } + }; + + template class gslice_array { + private: + friend class valarray; + + public: + ~gslice_array(); + + void operator=(const valarray& array) const; + void operator*=(const valarray& array) const; + void operator/=(const valarray& array) const; + void operator%=(const valarray& array) const; + void operator+=(const valarray& array) const; + void operator-=(const valarray& array) const; + void operator^=(const valarray& array) const; + void operator&=(const valarray& array) const; + void operator|=(const valarray& array) const; + void operator<<=(const valarray& array) const; + void operator>>=(const valarray& array) const; + + void operator=(const T&); + + private: + gslice_array(); + gslice_array(const gslice_array&); + gslice_array& operator= (const gslice_array& array); + }; + + + + template valarray operator* (const valarray& lhs, const valarray& rhs){ + valarray retval(lhs); + retval *= rhs; + return retval; + } + + template valarray operator* (const valarray& lhs, const T& rhs){ + valarray retval(lhs); + retval *= rhs; + return retval; + } + template valarray operator* (const T& lhs, const valarray& rhs){ + valarray retval(rhs); + retval *= lhs; + return retval; + } + template valarray operator/ (const valarray& lhs, const valarray& rhs){ + valarray retval(lhs); + retval /= rhs; + return retval; + } + template valarray operator/ (const valarray& lhs, const T& rhs){ + valarray retval(lhs); + retval /= rhs; + return retval; + } + template valarray operator/ (const T& lhs, const valarray& rhs){ + valarray retval(lhs, rhs.size()); + retval /= rhs; + return retval; + } + template valarray operator% (const valarray& lhs, const valarray& rhs){ + valarray retval(lhs); + retval %= rhs; + return retval; + } + template valarray operator% (const valarray& lhs, const T& rhs){ + valarray retval(lhs); + retval %= rhs; + return retval; + } + template valarray operator% (const T& lhs, const valarray& rhs){ + valarray retval(lhs, rhs.size()); + retval %= rhs; + return retval; + } + template valarray operator+ (const valarray& lhs, const valarray& rhs){ + valarray retval(lhs); + retval += rhs; + return retval; + } + template valarray operator+ (const valarray& lhs, const T& rhs){ + valarray retval(lhs); + retval += rhs; + return retval; + } + template valarray operator+ (const T& lhs, const valarray& rhs){ + valarray retval(lhs, rhs.size()); + retval += rhs; + return retval; + } + template valarray operator- (const valarray& lhs, const valarray& rhs){ + valarray retval(lhs); + retval -= rhs; + return retval; + } + template valarray operator- (const valarray& lhs, const T& rhs){ + valarray retval(lhs); + retval-= rhs; + return retval; + } + template valarray operator- (const T& lhs, const valarray& rhs){ + valarray retval(lhs, rhs.size()); + retval -= rhs; + return retval; + } + template valarray operator^ (const valarray& lhs, const valarray& rhs){ + valarray retval(lhs); + retval ^= rhs; + return retval; + } + template valarray operator^ (const valarray& lhs, const T& rhs){ + valarray retval(lhs); + retval ^= rhs; + return retval; + } + template valarray operator^ (const T& lhs, const valarray& rhs){ + valarray retval(lhs, rhs.size()); + retval ^= rhs; + return retval; + } + template valarray operator& (const valarray& lhs, const valarray& rhs){ + valarray retval(lhs); + retval &= rhs; + return retval; + } + template valarray operator& (const valarray& lhs, const T& rhs){ + valarray retval(lhs); + retval &= rhs; + return retval; + } + template valarray operator& (const T& lhs, const valarray& rhs){ + valarray retval(lhs, rhs.size()); + retval &= rhs; + return retval; + } + template valarray operator| (const valarray& lhs, const valarray& rhs){ + valarray retval(lhs); + retval |= rhs; + return retval; + } + template valarray operator| (const valarray& lhs, const T& rhs){ + valarray retval(lhs); + retval |= rhs; + return retval; + } + template valarray operator| (const T& lhs, const valarray& rhs){ + valarray retval(lhs, rhs.size()); + retval |= rhs; + return retval; + } + template valarray operator<<(const valarray& lhs, const valarray& rhs){ + valarray retval(lhs); + retval <<= rhs; + return retval; + } + template valarray operator<<(const valarray& lhs, const T& rhs){ + valarray retval(lhs); + retval <<= rhs; + return retval; + } + template valarray operator<<(const T& lhs, const valarray& rhs){ + valarray retval(lhs, rhs.size()); + retval <<= rhs; + return retval; + } + template valarray operator>>(const valarray& lhs, const valarray& rhs){ + valarray retval(lhs); + retval >>= rhs; + return retval; + } + template valarray operator>>(const valarray& lhs, const T& rhs){ + valarray retval(lhs); + retval >>= rhs; + return retval; + } + template valarray operator>>(const T& lhs, const valarray& rhs){ + valarray retval(lhs, rhs.size()); + retval >>= rhs; + return retval; + } + + template valarray operator&&(const valarray& lhs, const valarray& rhs){ + valarray retval(lhs.size()); + for(size_t i = 0; i < retval.size(); ++i){ + retval[i] = lhs[i] && rhs[i]; + } + return retval; + } + template valarray operator&&(const valarray& lhs, const T& rhs){ + valarray retval(lhs.size()); + for(size_t i = 0; i valarray operator&&(const T& lhs, const valarray& rhs){ + valarray retval(rhs.size()); + for(size_t i = 0; i valarray operator||(const valarray&lhs, const valarray& rhs){ + valarray retval(lhs.size()); + for(size_t i = 0; i valarray operator||(const valarray& lhs, const T& rhs){ + valarray retval(lhs.size()); + for(size_t i = 0; i valarray operator||(const T& lhs, const valarray& rhs){ + valarray retval(rhs.size()); + for(size_t i = 0; i < retval.size(); ++i){ + retval[i] = lhs || rhs[i]; + } + return retval; + } + + template valarray operator==(const valarray& lhs, const valarray& rhs){ + valarray retval(lhs.size()); + for(size_t i = 0; i valarray operator==(const valarray& lhs, const T& rhs){ + valarray retval(lhs.size()); + for(size_t i = 0; i < retval.size(); ++i){ + retval[i] = lhs[i] == rhs; + } + return retval; + } + template valarray operator==(const T& lhs, const valarray& rhs){ + valarray retval(rhs.size()); + for(size_t i = 0; i < retval.size(); ++i){ + retval[i] = lhs == rhs[i]; + } + return retval; + } + template valarray operator!=(const valarray& lhs, const valarray& rhs){ + valarray retval(lhs.size()); + for(size_t i = 0; i valarray operator!=(const valarray& lhs, const T& rhs){ + valarray retval(lhs.size()); + for(size_t i = 0; i valarray operator!=(const T& lhs, const valarray& rhs){ + valarray retval(rhs.size()); + for(size_t i = 0; i valarray operator< (const valarray& lhs, const valarray& rhs){ + valarray retval(lhs.size()); + for(size_t i = 0; i valarray operator< (const valarray& lhs, const T& rhs){ + valarray retval(lhs.size()); + for(size_t i = 0; i valarray operator< (const T& lhs, const valarray& rhs){ + valarray retval(rhs.size()); + for(size_t i = 0; i valarray operator> (const valarray& lhs, const valarray& rhs){ + valarray retval(lhs.size()); + for(size_t i = 0; i rhs[i]; + } + return retval; + } + template valarray operator> (const valarray& lhs, const T& rhs){ + valarray retval(lhs.size()); + for(size_t i = 0; i rhs; + } + return retval; + } + template valarray operator> (const T& rhs, const valarray& lhs){ + valarray retval(rhs.size()); + for(size_t i = 0; i rhs[i]; + } + return retval; + } + template valarray operator<=(const valarray& lhs, const valarray& rhs){ + valarray retval(lhs.size()); + for(size_t i = 0; i valarray operator<=(const valarray& lhs, const T& rhs){ + valarray retval(lhs.size()); + for(size_t i = 0; i valarray operator<=(const T& lhs, const valarray& rhs){ + valarray retval(rhs.size()); + for(size_t i = 0; i valarray operator>=(const valarray& lhs, const valarray& rhs){ + valarray retval(lhs.size()); + for(size_t i = 0; i = rhs[i]; + } + return retval; + } + template valarray operator>=(const valarray& lhs, const T& rhs){ + valarray retval(lhs.size()); + for(size_t i = 0; i = rhs; + } + return retval; + } + template valarray operator>=(const T& lhs, const valarray& rhs){ + valarray retval(rhs.size()); + for(size_t i = 0; i = rhs[i]; + } + return retval; + } + template T min(const valarray& x){ + T retval(x[0]); + for(size_t i = 1; i < x.size(); ++i){ + if(x[i] < retval){ + retval = x[i]; + } + } + } + template T max(const valarray& x){ + T retval(x[0]); + for(size_t i = 1; i < x.size(); ++i){ + if(x[i] > retval){ + retval = x[i]; + } + } + } + + template valarray abs (const valarray& x){ + valarray retval(x.size()); + for(size_t i = 0; i < retval.size(); ++i){ + retval[i] = abs(x[i]); + } + } + template valarray acos (const valarray& x){ + valarray retval(x.size()); + for(size_t i = 0; i < retval.size(); ++i){ + retval[i] = acos(x[i]); + } + } + template valarray asin (const valarray& x){ + valarray retval(x.size()); + for(size_t i = 0; i < retval.size(); ++i){ + retval[i] = asin(x[i]); + } + } + template valarray atan (const valarray& x){ + valarray retval(x.size()); + for(size_t i = 0; i < retval.size(); ++i){ + retval[i] = atan(x[i]); + } + } + template valarray atan2(const valarray& y, const valarray& x){ + valarray retval(y.size()); + for(size_t i = 0; i < retval.size(); ++i){ + retval[i] = atan2(y[i], x[i]); + } + } + template valarray atan2(const valarray& y, const T& x){ + valarray retval(y.size()); + for(size_t i = 0; i < retval.size(); ++i){ + retval[i] = atan2(y[i], x); + } + } + template valarray atan2(const T& y, const valarray& x){ + valarray retval(x.size()); + for(size_t i = 0; i < retval.size(); ++i){ + retval[i] = abs(y, x[i]); + } + } + template valarray cos (const valarray& x){ + valarray retval(x.size()); + for(size_t i = 0; i < retval.size(); ++i){ + retval[i] = cos(x[i]); + } + } + template valarray cosh (const valarray& x){ + valarray retval(x.size()); + for(size_t i = 0; i < retval.size(); ++i){ + retval[i] = cosh(x[i]); + } + } + template valarray exp (const valarray& x){ + valarray retval(x.size()); + for(size_t i = 0; i < retval.size(); ++i){ + retval[i] = exp(x[i]); + } + } + template valarray log (const valarray& x){ + valarray retval(x.size()); + for(size_t i = 0; i < retval.size(); ++i){ + retval[i] = log(x[i]); + } + } + template valarray log10(const valarray& x){ + valarray retval(x.size()); + for(size_t i = 0; i < retval.size(); ++i){ + retval[i] = log10(x[i]); + } + } + template valarray pow (const valarray& x, const valarray& y){ + valarray retval(x.size()); + for(size_t i = 0; i < retval.size(); ++i){ + retval[i] = pow(x[i], y[i]); + } + } + template valarray pow (const valarray& x, const T& y){ + valarray retval(x.size()); + for(size_t i = 0; i < retval.size(); ++i){ + retval[i] = pow(x[i], y); + } + } + template valarray pow (const T& x, const valarray& y){ + valarray retval(x.size()); + for(size_t i = 0; i < retval.size(); ++i){ + retval[i] = pow(x, y[i]); + } + } + template valarray sin (const valarray& x){ + valarray retval(x.size()); + for(size_t i = 0; i < retval.size(); ++i){ + retval[i] = sin(x[i]); + } + } + template valarray sinh (const valarray& x){ + valarray retval(x.size()); + for(size_t i = 0; i < retval.size(); ++i){ + retval[i] = sinh(x[i]); + } + } + template valarray sqrt (const valarray& x){ + valarray retval(x.size()); + for(size_t i = 0; i < retval.size(); ++i){ + retval[i] = sqrt(x[i]); + } + } + template valarray tan (const valarray& x){ + valarray retval(x.size()); + for(size_t i = 0; i < retval.size(); ++i){ + retval[i] = tan(x[i]); + } + } + template valarray tanh (const valarray& x){ + valarray retval(x.size()); + for(size_t i = 0; i < retval.size(); ++i){ + retval[i] = tanh(x[i]); + } + } + +} + +#pragma GCC visibility pop + +#endif Index: branches/slice/rev749/modules/uClibc++/include/iterator_base =================================================================== --- branches/slice/rev749/modules/uClibc++/include/iterator_base (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/iterator_base (revision 1169) @@ -0,0 +1,305 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include + +#ifndef __STD_HEADER_ITERATOR_BASE +#define __STD_HEADER_ITERATOR_BASE 1 + +#pragma GCC visibility push(default) + +namespace std{ + template struct iterator_traits; + template struct iterator_traits; + + template struct iterator; + + struct _UCXXEXPORT input_iterator_tag {}; + struct _UCXXEXPORT output_iterator_tag {}; + struct _UCXXEXPORT forward_iterator_tag: public input_iterator_tag {}; + struct _UCXXEXPORT bidirectional_iterator_tag: public forward_iterator_tag {}; + struct _UCXXEXPORT random_access_iterator_tag: public bidirectional_iterator_tag {}; + + template _UCXXEXPORT void advance(InputIterator& i, Distance n){ + while(n > 0){ + --n; + ++i; + } + } + + template _UCXXEXPORT typename iterator_traits::difference_type + distance(InputIterator first, InputIterator last) + { + typename iterator_traits::difference_type d = 0; + while(first++ !=last){ + d++; + } + return d; + } + + // subclause _lib.predef.iterators_, predefined iterators: + template class reverse_iterator; + template bool operator==(const reverse_iterator& x, const reverse_iterator& y); + template bool operator<(const reverse_iterator& x, const reverse_iterator& y); + template bool operator!=(const reverse_iterator& x, const reverse_iterator& y); + template bool operator>(const reverse_iterator& x, const reverse_iterator& y); + template bool operator>=(const reverse_iterator& x, const reverse_iterator& y); + template bool operator<=(const reverse_iterator& x, const reverse_iterator& y); + template typename reverse_iterator::difference_type + operator-( const reverse_iterator& x, const reverse_iterator& y); + template reverse_iterator + operator+( typename reverse_iterator::difference_type n, const reverse_iterator& x); + template class back_insert_iterator; + template back_insert_iterator back_inserter(Container& x); + template class front_insert_iterator; + template front_insert_iterator front_inserter(Container& x); + template class insert_iterator; + template + insert_iterator inserter(Container& x, Iterator i); + + //Actual Template definitions + + template struct _UCXXEXPORT iterator_traits { + typedef typename Iterator::difference_type difference_type; + typedef typename Iterator::value_type value_type; + typedef typename Iterator::pointer pointer; + typedef typename Iterator::reference reference; + typedef typename Iterator::iterator_category iterator_category; + }; + + //Pointer specialization - required by standard + template struct _UCXXEXPORT iterator_traits { + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef T* pointer; + typedef T& reference; + typedef random_access_iterator_tag iterator_category; + }; + + //Specialization recomended by standard +/* template struct _UCXXEXPORT iterator_traits { + typedef long difference_type; + typedef T value_type; + typedef T __far* pointer; + typedef T __far& reference; + typedef random_access_iterator_tag iterator_category; + };*/ + +/* template _UCXXEXPORT void + reverse(BidirectionalIterator first, BidirectionalIterator last) + { + typename iterator_traits::difference_type n = distance(first, last); + --n; + while(n > 0){ + typename iterator_traits::value_type tmp = *first; + *first++ = * --last; + *last = tmp; + n -= 2; + } + };*/ + + + template + struct _UCXXEXPORT iterator + { + typedef T value_type; + typedef Distance difference_type; + typedef Pointer pointer; + typedef Reference reference; + typedef Category iterator_category; + }; + + + template class _UCXXEXPORT reverse_iterator + : public iterator::iterator_category, + typename iterator_traits::value_type, typename iterator_traits::difference_type, + typename iterator_traits::pointer, typename iterator_traits::reference> + { + protected: + Iterator current; + friend bool operator== (const reverse_iterator& x, const reverse_iterator& y); + friend bool operator< (const reverse_iterator& x, const reverse_iterator& y); + + public: + typedef Iterator iterator_type; + + reverse_iterator() : current(){}; + explicit reverse_iterator(Iterator x) : current(x) { } + template reverse_iterator(const reverse_iterator &x) : current(x.base()){} + + Iterator base() const { return current; } // explicit + + typename iterator_traits::reference operator*() const { Iterator tmp = current; return *--tmp; } + typename iterator_traits::pointer operator->() const { return &(operator*()); } + typename iterator_traits::reference operator[](typename iterator_traits::difference_type n) const{ + return current[-n-1]; + } + + reverse_iterator& operator++(){ --current; return *this; } + reverse_iterator operator++(int) {reverse_iterator tmp = *this; --current; return tmp; } + reverse_iterator& operator--() { ++ current; return *this; } + reverse_iterator operator--(int) {reverse_iterator tmp = *this; ++current; return tmp; } + + reverse_iterator operator+ (typename iterator_traits::difference_type n) const{ + reverse_iterator retval( *this ); + retval+=n; + return retval; + } + reverse_iterator& operator+=(typename iterator_traits::difference_type n){ + current -= n; + return *this; + } + reverse_iterator operator- (typename iterator_traits::difference_type n) const{ + reverse_iterator retval( *this ); + retval-=n; + return retval; + } + reverse_iterator& operator-=(typename iterator_traits::difference_type n){ + current += n; + return *this; + } + }; + + + template _UCXXEXPORT bool + operator==(const reverse_iterator& x, const reverse_iterator& y) + { + return x.base() == y.base(); + } + template _UCXXEXPORT bool + operator<(const reverse_iterator& x, const reverse_iterator& y) + { + return x.base() < y.base(); + } + template _UCXXEXPORT bool + operator!=(const reverse_iterator& x, const reverse_iterator& y) + { + return x.base() != y.base(); + } + template _UCXXEXPORT bool + operator>(const reverse_iterator& x, const reverse_iterator& y) + { + return x.base() > y.base(); + } + template _UCXXEXPORT bool + operator>=(const reverse_iterator& x, const reverse_iterator& y) + { + return x.base() >= y.base(); + } + template _UCXXEXPORT bool + operator<=(const reverse_iterator& x, const reverse_iterator& y) + { + return x.base() <= y.base(); + } + template _UCXXEXPORT typename reverse_iterator::difference_type + operator-( const reverse_iterator& x, const reverse_iterator& y) + { + return y.base() - x.base(); + } + template _UCXXEXPORT reverse_iterator + operator+(typename reverse_iterator::difference_type n, const reverse_iterator& x) + { + return reverse_iterator (x.base() - n); + } + + template class _UCXXEXPORT back_insert_iterator : + public iterator + { + protected: + Container& container; + public: + typedef Container container_type; + explicit back_insert_iterator(Container& x):container(x) {}; + back_insert_iterator& operator=(const typename Container::value_type& value){ + container.push_back(value); + return *this; + } + back_insert_iterator& operator*(){ + return *this; + } + back_insert_iterator& operator++(){ + return *this; + } + back_insert_iterator operator++(int){ + return *this; + } + }; + + template _UCXXEXPORT back_insert_iterator + back_inserter(Container& x) + { + return back_insert_iterator(x); + } + + template class _UCXXEXPORT front_insert_iterator + : public iterator + { + protected: + Container& container; + public: + typedef Container container_type; + explicit front_insert_iterator(Container& x): container(x) {} + front_insert_iterator& operator=(const typename Container::value_type& value){ + container.push_front(value); + return *this; + } + + front_insert_iterator& operator*() { return *this; } + front_insert_iterator& operator++() { return *this; } + front_insert_iterator operator++(int) { return *this; } + }; + + template _UCXXEXPORT front_insert_iterator + front_inserter(Container& x) + { + return front_insert_iterator(x); + } + + template class _UCXXEXPORT insert_iterator + : public iterator + { + protected: + Container& container; + typename Container::iterator iter; + public: + typedef Container container_type; + insert_iterator(Container& x, typename Container::iterator i) : container(x), iter(i) {} + insert_iterator& operator=(const typename Container::value_type& value){ + iter = container.insert(iter, value); + ++iter; + return *this; + } + insert_iterator& operator*() { return *this; } + insert_iterator& operator++() { return *this; } + insert_iterator operator++(int) { return *this; } + }; + + template _UCXXEXPORT insert_iterator + inserter(Container& x, Iterator i) + { + return insert_iterator(x,typename Container::iterator(i)); + } + +} + +#pragma GCC visibility pop + +#endif + + Index: branches/slice/rev749/modules/uClibc++/include/algorithm =================================================================== --- branches/slice/rev749/modules/uClibc++/include/algorithm (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/algorithm (revision 1169) @@ -0,0 +1,1695 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + This file is part of the uClibc++ Library. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include + +#ifndef __STD_HEADER_ALGORITHM +#define __STD_HEADER_ALGORITHM 1 + +//Elliminate any previously defined macro +#undef min +#undef max + +#pragma GCC visibility push(default) + +namespace std{ + + // subclause _lib.alg.nonmodifying_, non-modifying sequence operations: + template _UCXXEXPORT + Function for_each(InputIterator first, InputIterator last, Function f) + { + while(first !=last){ + f(*first); + ++first; + } + return f; + } + + + template _UCXXEXPORT + InputIterator find(InputIterator first, InputIterator last, const T& value) + { + while(first !=last && *first != value){ + ++first; + } + return first; + } + + template _UCXXEXPORT + InputIterator find_if(InputIterator first, InputIterator last, Predicate pred) + { + while(first !=last && !pred(*first)){ + ++first; + } + return first; + } + + template _UCXXEXPORT ForwardIterator1 + find_end(ForwardIterator1 first1, ForwardIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2) + { + ForwardIterator1 retval = last1; + while(first1 !=last1){ + ForwardIterator1 temp1(first1); + ForwardIterator2 temp2(first2); + while(temp2!=last2 && temp1!= last1){ + if(*temp1 != *temp2){ + break; //Exit while loop + } + ++temp1; + ++temp2; + if(temp2 == last2){ //Have successfully checked the whole sequence + retval = first1; + } + } + } + return retval; + } + + template _UCXXEXPORT + ForwardIterator1 + find_end(ForwardIterator1 first1, ForwardIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2, + BinaryPredicate pred) + { + ForwardIterator1 retval = last1; + while(first1 !=last1){ + ForwardIterator1 temp1(first1); + ForwardIterator2 temp2(first2); + while(temp2!=last2 && temp1!= last1){ + if( ! pred(*temp1, *temp2)){ + break; //Exit while loop + } + ++temp1; + ++temp2; + if(temp2 == last2){ //Have successfully checked the whole sequence + retval = first1; + } + } + } + return retval; + } + + template _UCXXEXPORT + ForwardIterator1 + find_first_of(ForwardIterator1 first1, ForwardIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2) + { + while(first1 != last1){ + ForwardIterator2 temp2(first2); + while(temp2 != last2 ){ + if(*temp2 == first1){ + return first1; + } + ++temp2; + } + + } + return last1; + } + + template _UCXXEXPORT + ForwardIterator1 + find_first_of(ForwardIterator1 first1, ForwardIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2, + BinaryPredicate pred) + { + while(first1 != last1){ + ForwardIterator2 temp2(first2); + while(temp2 != last2 ){ + if(*temp2 == first1){ + return first1; + } + ++temp2; + } + + } + return last1; + } + + template _UCXXEXPORT ForwardIterator + adjacent_find(ForwardIterator first, ForwardIterator last) + { + ForwardIterator temp; + while(first != last){ + temp = first; + ++temp; + if(*temp == *first){ + return first; + } + ++first; + } + return first; + } + + template _UCXXEXPORT + ForwardIterator + adjacent_find(ForwardIterator first, ForwardIterator last, BinaryPredicate pred) + { + ForwardIterator temp; + while(first != last){ + temp = first; + ++temp; + if( pred(*temp, *first)){ + return first; + } + ++first; + } + return first; + } + + template _UCXXEXPORT + typename iterator_traits::difference_type + count(InputIterator first, InputIterator last, const T& value) + { + typename iterator_traits::difference_type i = 0; + while(first!=last){ + if(*first == value){ + ++i; + } + ++first; + } + return i; + } + + template _UCXXEXPORT + typename iterator_traits::difference_type + count_if(InputIterator first, InputIterator last, Predicate pred) + { + typename iterator_traits::difference_type i = 0; + while(first!=last){ + if( pred(*first) ){ + ++i; + } + ++first; + } + return i; + } + + template _UCXXEXPORT + pair + mismatch(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2) + { + while(first1 != last1){ + if(*first1 != *first2){ + break; + } + ++first1; + ++first2; + } + + pair retval; + retval.first = first1; + retval.second = first2; + return retval; + } + + template _UCXXEXPORT + pair + mismatch(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, BinaryPredicate pred) + { + while(first1 != last1){ + if( !pred(*first1, *first2) ){ + break; + } + ++first1; + ++first2; + } + + pair retval; + retval.first = first1; + retval.second = first2; + return retval; + } + + template _UCXXEXPORT + bool + equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2) + { + while(first1 !=last1){ + if(*first1 != *first2){ + return false; + } + ++first1; + ++first2; + } + return true; + } + + template _UCXXEXPORT + bool + equal(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, BinaryPredicate pred) + { + while(first1 !=last1){ + if( !pred(*first1, *first2) ){ + return false; + } + ++first1; + ++first2; + } + return true; + } + + template _UCXXEXPORT + ForwardIterator1 search(ForwardIterator1 first1, ForwardIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2) + { + equal_to::value_type> c; + return search(first1, last1, first2, last2, c); + } + + + template _UCXXEXPORT + ForwardIterator1 + search(ForwardIterator1 first1, ForwardIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2, + BinaryPredicate pred) + { + while(first1 != last1){ + ForwardIterator1 temp1(first1); + ForwardIterator2 temp2(first2); + while(temp2 != last2 && temp1 != last1){ + if( !pred(*temp2, *temp1) ){ + break; + } + ++temp1; + ++temp2; + if(temp2 == last2){ + return first1; + } + } + ++first1; + } + return last1; + } + + + template _UCXXEXPORT + ForwardIterator + search_n(ForwardIterator first, ForwardIterator last, Size count, const T& value) + { + while( first != last ){ + if(*first == value){ + ForwardIterator temp(first); + Size i = 1; + ++first; //Avoid doing the same comparison over again + while(i < count && *temp == value){ + ++first; + ++i; + } + if(i == count){ + return first; + } + } + ++first; + } + return first; + } + + + template _UCXXEXPORT + ForwardIterator + search_n(ForwardIterator first, ForwardIterator last, + Size count, const T& value, BinaryPredicate pred) + { + while( first != last ){ + if( pred(*first, value) ){ + ForwardIterator temp(first); + Size i = 1; + ++first; //Avoid doing the same comparison over again + while(i < count && pred(*temp, value) ){ + ++first; + ++i; + } + if(i == count){ + return first; + } + } + ++first; + } + return first; + + } + + // subclause _lib.alg.modifying.operations_, modifying sequence operations: + + template _UCXXEXPORT + OutputIterator + copy(InputIterator first, InputIterator last, OutputIterator result) + { + while(first != last){ + *result = *first; + ++first; + ++result; + } + return result; + } + + template _UCXXEXPORT + BidirectionalIterator2 + copy_backward(BidirectionalIterator1 first, BidirectionalIterator1 last, + BidirectionalIterator2 result) + { + while(first !=last ){ + --result; + --last; + *result = *last; + } + return result; + } + + template _UCXXEXPORT void swap(T& a, T& b){ + T temp(a); + a = b; + b = temp; + } + + template _UCXXEXPORT + ForwardIterator2 + swap_ranges(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2) + { + while(first1 != last1){ + iter_swap(first1, first2); + ++first1; + ++first2; + } + return first2; + } + + + template _UCXXEXPORT + void + iter_swap(ForwardIterator1 a, ForwardIterator2 b) + { + typename iterator_traits::value_type temp(*a); + *a = *b; + *b = temp; + } + + + template _UCXXEXPORT + OutputIterator + transform(InputIterator first, InputIterator last, + OutputIterator result, UnaryOperation op) + { + while(first != last){ + *result = op(*first); + ++first; + ++result; + } + return result; + } + + + template _UCXXEXPORT + OutputIterator transform(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, OutputIterator result, + BinaryOperation binary_op) + { + while(first1 != last1){ + *result = binary_op(*first1, *first2); + ++first1; + ++first2; + ++result; + } + return result; + } + + + template _UCXXEXPORT + void + replace(ForwardIterator first, ForwardIterator last, + const T& old_value, const T& new_value) + { + while(first != last){ + if(*first == old_value){ + *first = new_value; + } + ++first; + } + } + + template _UCXXEXPORT + void + replace_if(ForwardIterator first, ForwardIterator last, + Predicate pred, const T& new_value) + { + while(first != last){ + if( pred(*first) ){ + *first = new_value; + } + ++first; + } + } + + + template _UCXXEXPORT + OutputIterator + replace_copy(InputIterator first, InputIterator last, + OutputIterator result, const T& old_value, const T& new_value) + { + while(first != last){ + if(*first == old_value){ + *result = new_value; + }else{ + *result = *first; + } + ++first; + ++result; + } + return result; + } + + template _UCXXEXPORT + OutputIterator + replace_copy_if(Iterator first, Iterator last, + OutputIterator result, Predicate pred, const T& new_value) + { + while(first != last){ + if( pred(*first) ){ + *result = new_value; + }else{ + *result = *first; + } + ++first; + ++result; + } + return result; + } + + template _UCXXEXPORT + void + fill(ForwardIterator first, ForwardIterator last, const T& value) + { + while(first != last){ + *first = value; + ++first; + } + } + + template _UCXXEXPORT + void + fill_n(OutputIterator first, Size n, const T& value) + { + while(n != 0){ + *first = value; + --n; + ++first; + } + } + + template _UCXXEXPORT + void + generate(ForwardIterator first, ForwardIterator last, Generator gen) + { + while(first != last){ + *first = gen(); + ++first; + } + } + + template _UCXXEXPORT + void + generate_n(OutputIterator first, Size n, Generator gen) + { + while(n !=0){ + *first = gen(); + --n; + ++first; + } + } + + template _UCXXEXPORT + ForwardIterator + remove(ForwardIterator first, ForwardIterator last, const T& value) + { + ForwardIterator temp(first); + while(temp !=last){ + if(*temp == value){ + + }else{ + *first = *temp; + ++first; + } + ++temp; + } + return first; + } + + template _UCXXEXPORT + ForwardIterator + remove_if(ForwardIterator first, ForwardIterator last, Predicate pred) + { + ForwardIterator temp(first); + while(temp !=last){ + if( pred(*temp) ){ + + }else{ + *first = *temp; + ++first; + } + ++temp; + } + return first; + } + + + template _UCXXEXPORT + OutputIterator + remove_copy(InputIterator first, InputIterator last, + OutputIterator result, const T& value) + { + while(first !=last){ + if(*first != value){ + *result = *first; + ++result; + } + ++first; + } + return result; + } + + template _UCXXEXPORT + OutputIterator + remove_copy_if(InputIterator first, InputIterator last, + OutputIterator result, Predicate pred) + { + while(first !=last){ + if( !pred(*first) ){ + *result = *first; + ++result; + } + ++first; + } + return result; + } + + template _UCXXEXPORT + ForwardIterator + unique(ForwardIterator first, ForwardIterator last) + { + ForwardIterator new_val(first); + ForwardIterator old_val(first); + + while(new_val !=last){ + if(*new_val == *old_val && new_val != old_val){ + + }else{ + *first = *new_val; + old_val = new_val; + ++first; + } + ++new_val; + } + return first; + } + + template _UCXXEXPORT + ForwardIterator + unique(ForwardIterator first, ForwardIterator last, BinaryPredicate pred) + { + ForwardIterator new_val(first); + ForwardIterator old_val(first); + + while(new_val !=last){ + if( pred(*new_val, *old_val) && new_val != old_val){ + + }else{ + *first = *new_val; + old_val = new_val; + ++first; + } + ++new_val; + } + return first; + } + + template _UCXXEXPORT + OutputIterator + unique_copy(InputIterator first, InputIterator last, OutputIterator result) + { + InputIterator temp(first); + while(first !=last ){ + if(*first == *temp && first != temp){ + + }else{ + *result = *first; + temp = first; + ++result; + } + ++first; + } + return result; + } + + template _UCXXEXPORT + OutputIterator + unique_copy(InputIterator first, InputIterator last, + OutputIterator result, BinaryPredicate pred) + { + InputIterator temp(first); + while(first !=last ){ + if( pred(*first, *temp) && first != temp){ + + }else{ + *result = *first; + temp = first; + ++result; + } + ++first; + } + return result; + } + + template _UCXXEXPORT + void + reverse(BidirectionalIterator first, BidirectionalIterator last) + { + --last; //Don't work with one past the end element + while(first < last){ + iter_swap(first, last); + ++first; + --last; + } + } + + template _UCXXEXPORT + OutputIterator + reverse_copy(BidirectionalIterator first, BidirectionalIterator last, + OutputIterator result) + { + while(last > first){ + --last; + *result = *last; + ++result; + } + return result; + } + + template _UCXXEXPORT + void + rotate(ForwardIterator first, ForwardIterator middle, ForwardIterator last) + { + if ((first == middle) || (last == middle)){ + return; + } + + ForwardIterator first2 = middle; + + do { + swap(*first, *first2); + first++; + first2++; + if(first == middle){ + middle = first2; + } + } while(first2 != last); + + first2 = middle; + + while (first2 != last) { + swap(*first, *first2); + first++; + first2++; + if (first == middle){ + middle = first2; + }else if (first2 == last){ + first2 = middle; + } + } + } + + template _UCXXEXPORT + OutputIterator + rotate_copy(ForwardIterator first, ForwardIterator middle, + ForwardIterator last, OutputIterator result) + { + ForwardIterator temp(middle); + while(temp !=last){ + *result = *temp; + ++temp; + ++result; + } + while(first != middle){ + *result = *first; + ++first; + ++result; + } + return result; + } + + + template _UCXXEXPORT + void + random_shuffle(RandomAccessIterator first, RandomAccessIterator last) + { + --last; + while(first != last){ + iter_swap(first, (first + (rand() % (last - first) ) ) ); + ++first; + } + } + + template _UCXXEXPORT + void + random_shuffle(RandomAccessIterator first, RandomAccessIterator last, + RandomNumberGenerator& rand) + { + --last; + while(first != last){ + iter_swap(first, (first + (rand(last - first) ) ) ); + ++first; + } + } + + // _lib.alg.partitions_, partitions: + template _UCXXEXPORT BidirectionalIterator + partition(BidirectionalIterator first, BidirectionalIterator last, Predicate pred) + { + return stable_partition(first, last, pred); + } + + template _UCXXEXPORT BidirectionalIterator + stable_partition(BidirectionalIterator first, BidirectionalIterator last, Predicate pred) + { + //first now points to the first non-desired element + while( first != last && pred(*first) ){ + ++first; + } + + BidirectionalIterator tempb; + BidirectionalIterator tempe = first; + + while( tempe != last ){ + //Find the next desired element + while( !pred(*tempe) ){ + ++tempe; + + //See if we should exit + if(tempe == last){ + return first; + } + } + + //Rotate the element back to the begining + tempb = tempe; + while(tempb != first){ + iter_swap(tempb, tempb-1 ); + --tempb; + } + //First now has a desired element + ++first; + } + + return first; + } + + template _UCXXEXPORT + void sort(RandomAccessIterator first, RandomAccessIterator last) + { + less::value_type> c; + sort(first, last, c ); + } + + template _UCXXEXPORT + void sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp) + { + stable_sort(first, last, comp); + } + + template _UCXXEXPORT + void stable_sort(RandomAccessIterator first, RandomAccessIterator last) + { + less::value_type> c; + stable_sort(first, last, c); + } + + template _UCXXEXPORT + void stable_sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp) + { + //FIXME - bubble sort + RandomAccessIterator temp; + --last; + while(last - first > 0){ + temp = last; + while(temp != first){ + if( comp( *temp, *(temp-1) ) ){ + iter_swap( temp-1, temp); + } + --temp; + } + ++first; + } + } + + template _UCXXEXPORT + void partial_sort(RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last) + { + less::value_type> c; + partial_sort(first, middle, last, c); + } + template _UCXXEXPORT + void partial_sort(RandomAccessIterator first, RandomAccessIterator middle, + RandomAccessIterator last, Compare comp) + { + //Fixme - partial bubble sort + RandomAccessIterator temp; + --last; + while(first < middle){ + temp = last; + while(temp != first){ + if( comp(*temp, *(temp -1 ) ) ) { + iter_swap( temp-1, temp); + } + --temp; + } + ++first; + } + } + template _UCXXEXPORT + RandomAccessIterator + partial_sort_copy(InputIterator first, InputIterator last, + RandomAccessIterator result_first, RandomAccessIterator result_last) + { + less::value_type> c; + return partial_sort_copy(first, last, result_first, result_last, c); + } + template _UCXXEXPORT + RandomAccessIterator + partial_sort_copy(InputIterator first, InputIterator last, + RandomAccessIterator result_first, RandomAccessIterator result_last, Compare comp) + { + size_t output_size = last-first; + size_t temp_size = result_last - result_first; + if(temp_size < output_size){ + output_size = temp_size; + } + + RandomAccessIterator middle = result_first + output_size; + RandomAccessIterator temp = result_first; + + while(temp != middle){ + *temp = *first; + ++temp; + ++first; + } + sort(result_first, middle, comp); + + while( first != last){ + if( comp( *first, *(middle-1) ) ){ + *(middle-1) = *first; + sort(result_first, middle, comp); + } + ++first; + } + + return middle; + } + template _UCXXEXPORT + void nth_element(RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last) + { + less::value_type> c; + nth_element(first, nth, last, c); + } + template _UCXXEXPORT + void nth_element(RandomAccessIterator first, RandomAccessIterator nth, + RandomAccessIterator last, Compare comp) + { + partial_sort(first, nth, last, comp); + } + + template _UCXXEXPORT + ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, + const T& value) + { + less::value_type> c; + return lower_bound(first, last, value, c); + } + + template _UCXXEXPORT + ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, + const T& value, Compare comp) + { + if(first == last){ + return last; + } + //If below or equal to the first element + if( comp(*first, value) == false){ + return first; + } + ForwardIterator middle; + + //If greater than the top element + middle = first; + advance(middle, distance(first, last) - 1); + if( comp(*middle, value) ){ + return last; + } + + //Now begin the actual search for the begining + while( distance(first, last) > 1 ){ + //Find middle + middle = first; + advance(middle, (distance(first, last)/2) ); + if( !comp(*middle, value) ){ + last = middle; + }else{ + first = middle; + } + } + + if( !comp(*first, value) ){ + return first; + } + return last; + } + + template _UCXXEXPORT + ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, + const T& value) + { + less::value_type> c; + return upper_bound(first, last, value, c); + } + + + template _UCXXEXPORT + ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, + const T& value, Compare comp) + { + if(first == last){ + return last; + } + //If below the first element + if( comp(value, *first) == true){ + return first; + } + + ForwardIterator middle; + + //If greater than the top element + middle = first; + advance(middle, distance(first, last) - 1); + if( comp(*middle, value) ){ + return last; + } + + //Now begin the actual search for the end + while( distance(first, last) > 1 ){ + //Find middle + middle = first; + advance(middle, (distance(first, last)/2) ); + if( comp(value, *middle) ){ + last = middle; + }else{ + first = middle; + } + } + + if( comp(value, *first) ){ + return first; + } + return last; + } + + + template _UCXXEXPORT + pair + equal_range(ForwardIterator first, ForwardIterator last, const T& value) + { + less::value_type> c; + return equal_range(first, last, value, c); + } + + template _UCXXEXPORT + pair + equal_range(ForwardIterator first, ForwardIterator last, const T& value, Compare comp) + { + pair retval; + retval.first = lower_bound(first, last, value, comp); + //Reuse retval.first in order to (possibly) save a few comparisons + retval.second = upper_bound(retval.first, last, value, comp); + return retval; + + } + + template _UCXXEXPORT + bool binary_search(ForwardIterator first, ForwardIterator last, + const T& value) + { + less::value_type> c; + return binary_search(first, last, value, c); + } + + template _UCXXEXPORT + bool binary_search(ForwardIterator first, ForwardIterator last, + const T& value, Compare comp) + { + if( distance(first, last) == 0){ + return false; + } + + ForwardIterator middle; + + while( distance(first, last) > 1 ){ + //Set middle between first and last + middle = first; + advance(middle, distance(first, last)/2 ); + + if( comp(*middle, value ) == true){ + first = middle; + }else{ + last = middle; + } + } + + if( !comp(*first, value) && !comp(value, *first) ){ + return true; + } + if( !comp(*last, value) && !comp(value, *last) ){ + return true; + } + + return false; + } + + // _lib.alg.merge_, merge: + template _UCXXEXPORT + OutputIterator + merge(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, OutputIterator result) + { + less::value_type> c; + return merge(first1, last1, first2, last2, result, c); + } + template _UCXXEXPORT + OutputIterator + merge(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp) + { + while( first1 != last1 && first2 != last2){ + //If in this order so first1 elements which are equal come first + if( comp(*first2, *first1) ){ + *result = *first2; + ++first2; + }else{ + *result = *first1; + ++first1; + } + ++result; + } + //Clean up remaining elements + while(first1 != last1){ + *result = *first1; + ++first1; + ++result; + } + while(first2 != last2){ + *result = *first2; + ++first2; + ++result; + } + return result; + } + template _UCXXEXPORT + void inplace_merge(BidirectionalIterator first, + BidirectionalIterator middle, BidirectionalIterator last) + { + less::value_type> c; + inplace_merge(first, middle, last, c); + } + template _UCXXEXPORT + void inplace_merge(BidirectionalIterator first, + BidirectionalIterator middle, BidirectionalIterator last, Compare comp) + { + //FIXME - using a bubble exchange method + while(first != middle && middle !=last){ + if( comp(*middle, *first) ){ + BidirectionalIterator temp(middle); + while( temp != first){ + iter_swap(temp, temp-1); + --temp; + } + ++middle; + } + ++first; + } + } + + // _lib.alg.set.operations_, set operations: + template _UCXXEXPORT + bool includes(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2) + { + less::value_type> c; + return includes(first1, last1, first2, last2, c ); + } + + template _UCXXEXPORT + bool includes(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, Compare comp) + { + while(first2 != last2){ + //Advance the large set until no longer smaller than the element we are looking for + while( comp(*first1, *first2) ){ + ++first1; + //If we are at the end of the list, we don't have the desired element + if(first1 == last1){ + return false; + } + } + //If we are past the element we want, it isn't here + if( comp(*first2, *first1) ){ + return false; + } + ++first2; //Move to next element + } + return true; + } + + template _UCXXEXPORT + OutputIterator set_union(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, OutputIterator result) + { + less::value_type> c; + return set_union(first1, last1, first2, last2, result, c); + } + + template _UCXXEXPORT + OutputIterator set_union(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp) + { + while( first1 != last1 && first2 != last2){ + if( comp(*first2, *first1) ){ + *result = *first2; + + //Elliminate duplicates + InputIterator2 temp = first2; + while( first1 != last1 && !comp( *temp, *first1) ){ + ++first1; + } + while( first2 != last2 && !comp( *temp, *first2) ){ + ++first2; + } + }else{ + *result = *first1; + //Elliminate duplicates + InputIterator1 temp = first1; + while( first1 != last1 && !comp( *temp, *first1) ){ + ++first1; + } + while( first2 != last2 && !comp( *temp, *first2) ){ + ++first2; + } + } + ++result; + } + + //Clean up remaining elements + while(first1 != last1){ + *result = *first1; + ++result; + InputIterator1 temp = first1; + while( first1 != last1 && !comp( *temp, *first1) ){ + ++first1; + } + } + + while(first2 != last2){ + *result = *first2; + ++result; + InputIterator2 temp = first2; + while( first2 != last2 && !comp( *temp, *first2) ){ + ++first2; + } + } + return result; + } + + template _UCXXEXPORT + OutputIterator set_intersection(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, OutputIterator result) + { + less::value_type> c; + return set_intersection(first1, last1, first2, last2, result, c); + } + template _UCXXEXPORT + OutputIterator set_intersection(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp) + { + while( first1 != last1 && first2 != last2){ + if( comp(*first2, *first1) ){ + ++first2; + }else if( comp(*first1, *first2) ) { + ++first1; + }else{ + *result = *first1; + ++result; + InputIterator1 temp = first1; + while( first1 != last1 && !comp( *temp, *first1) ){ + ++first1; + } + ++first2; + } + } + return result; + } + template _UCXXEXPORT + OutputIterator set_difference(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, OutputIterator result) + { + less::value_type> c; + return set_difference(first1, last1, first2, last2, result, c); + } + template _UCXXEXPORT + OutputIterator set_difference(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp) + { + while( first1 != last1 && first2 != last2){ + if( comp(*first1, *first2) ){ + *result = *first1; + ++result; + + //Elliminate duplicates + InputIterator1 temp = first1; + while( first1 != last1 && !comp( *temp, *first1) ){ + ++first1; + } + }else if( comp(*first2, *first1) ){ + + //Elliminate duplicates + InputIterator2 temp = first2; + while( first2 != last2 && !comp( *temp, *first2) ){ + ++first2; + } + + }else{ //They are identical - skip + //Elliminate duplicates + InputIterator1 temp = first1; + while( first1 != last1 && !comp( *temp, *first1) ){ + ++first1; + } + while( first2 != last2 && !comp( *temp, *first2) ){ + ++first2; + } + } + } + + //Clean up remaining elements + while(first1 != last1){ + *result = *first1; + ++result; + InputIterator1 temp = first1; + while( first1 != last1 && !comp( *temp, *first1) ){ + ++first1; + } + } + + return result; + } + template _UCXXEXPORT + OutputIterator set_symmetric_difference(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, OutputIterator result) + { + less::value_type> c; + return set_symmetric_difference(first1, last1, first2, last2, result, c); + } + template _UCXXEXPORT + OutputIterator set_symmetric_difference(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp) + { + while( first1 != last1 && first2 != last2){ + if( comp(*first1, *first2) ){ + *result = *first1; + ++result; + + //Elliminate duplicates + InputIterator1 temp = first1; + while( first1 != last1 && !comp( *temp, *first1) ){ + ++first1; + } + }else if( comp(*first2, *first1) ){ + *result = *first2; + ++result; + + //Elliminate duplicates + InputIterator2 temp = first2; + while( first2 != last2 && !comp( *temp, *first2) ){ + ++first2; + } + + }else{ //They are identical - skip + //Elliminate duplicates + InputIterator1 temp = first1; + while( first1 != last1 && !comp( *temp, *first1) ){ + ++first1; + } + while( first2 != last2 && !comp( *temp, *first2) ){ + ++first2; + } + } + } + + //Clean up remaining elements + while(first1 != last1){ + *result = *first1; + ++result; + InputIterator1 temp = first1; + while( first1 != last1 && !comp( *temp, *first1) ){ + ++first1; + } + } + + while(first2 != last2){ + *result = *first2; + ++result; + InputIterator2 temp = first2; + while( first2 != last2 && !comp( *temp, *first2) ){ + ++first2; + } + } + + return result; + } + + // _lib.alg.heap.operations_, heap operations: + + template _UCXXEXPORT + void push_heap(RandomAccessIterator first, RandomAccessIterator last) + { + less::value_type> c; + push_heap(first, last, c); + } + + template _UCXXEXPORT + void push_heap(RandomAccessIterator first, RandomAccessIterator last, Compare comp) + { + // *(last - 1) is the last element + RandomAccessIterator begin, middle, end; + begin = first; + end = last - 2; + if(last - first < 2){ //Empty heap + return; + } + if ( comp(*(last-1), *end) ){ //Belongs past the end - already in place + return; + } + while(end - begin > 1){ + middle = begin + ((end - begin)/2); + if( comp(*middle, *(last-1) ) ){ + end = middle; + }else{ + begin = middle; + } + } + + if( comp(*begin, *(last-1)) ){ + middle = begin; + }else{ + middle = end; + } + + //Now all we do is swap the elements up to the begining + --last; + + while(last > middle){ + iter_swap(last, last-1); + --last; + } + } + + template _UCXXEXPORT + void pop_heap(RandomAccessIterator first, RandomAccessIterator last) + { + less::value_type> c; + pop_heap(first, last, c); + } + template _UCXXEXPORT + void pop_heap(RandomAccessIterator first, RandomAccessIterator last, Compare) + { + --last; + while(first < last){ + iter_swap( first, first+1); + ++first; + } + } + + template _UCXXEXPORT + void make_heap(RandomAccessIterator first, RandomAccessIterator last) + { + less::value_type> c; + make_heap(first, last, c); + } + template _UCXXEXPORT + void make_heap(RandomAccessIterator first, RandomAccessIterator last, Compare comp) + { + sort( reverse_iterator(last), reverse_iterator(first), comp); + } + template _UCXXEXPORT + void sort_heap(RandomAccessIterator first, RandomAccessIterator last) + { + less::value_type> c; + sort_heap(first, last, c); + } + template _UCXXEXPORT + void sort_heap(RandomAccessIterator first, RandomAccessIterator last, Compare comp) + { + sort( first, last, comp); + } + + + // _lib.alg.min.max_, minimum and maximum: + template _UCXXEXPORT + const T& min(const T& a, const T& b) + { + if(b < a){ + return b; + } + return a; + } + + template _UCXXEXPORT + const T& min(const T& a, const T& b, Compare comp) + { + if( comp(b, a) == true){ + return b; + } + return a; + } + + template _UCXXEXPORT + const T& max(const T& a, const T& b) + { + if( a < b){ + return b; + } + return a; + } + + template _UCXXEXPORT + const T& max(const T& a, const T& b, Compare comp) + { + if( comp(a, b) ){ + return b; + } + return a; + } + + template _UCXXEXPORT + ForwardIterator min_element(ForwardIterator first, ForwardIterator last) + { + less::value_type> c; + return min_element(first, last, c); + } + + template _UCXXEXPORT + ForwardIterator min_element(ForwardIterator first, ForwardIterator last, Compare comp) + { + ForwardIterator retval = first; + ++first; + while(first != last){ + if( comp( *first, *retval) ){ + retval = first; + } + ++first; + } + return retval; + } + + template _UCXXEXPORT + ForwardIterator max_element(ForwardIterator first, ForwardIterator last) + { + less::value_type> c; + return max_element(first, last, c); + } + + template _UCXXEXPORT + ForwardIterator max_element(ForwardIterator first, ForwardIterator last, Compare comp) + { + ForwardIterator retval = first; + ++first; + while(first != last){ + if( comp( *retval, *first ) ){ + retval = first; + } + ++first; + } + return retval; + } + + template _UCXXEXPORT + bool lexicographical_compare(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2) + { + less::value_type> c; + return lexicographical_compare(first1, last1, first2, last2, c); + } + + template _UCXXEXPORT + bool lexicographical_compare(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, Compare comp) + { + while(first1 != last1 && first2 != last2){ + if( comp(*first1, *first2) ){ + return true; + } + if( comp(*first2, *first1) ){ + return false; + } + ++first1; + ++first2; + } + return first1==last1 && first2 != last2; + } + + // _lib.alg.permutation.generators_, permutations + template _UCXXEXPORT + bool next_permutation(BidirectionalIterator first, BidirectionalIterator last) + { + less::value_type> c; + return next_permutation(first, last, c); + } + + template _UCXXEXPORT + bool next_permutation(BidirectionalIterator first, BidirectionalIterator last, Compare comp) + { + if(first == last){ + return false; // No data + } + BidirectionalIterator i = last; + --i; + if(i == first){ + return false; //Only one element + } + BidirectionalIterator ii = i; + --ii; + //If the last two items are in order, swap them and call it done + if( comp(*ii, *i) ){ + iter_swap(ii, i); + return true; + } + + + //This part of the algorithm copied from G++ header files ver. 3.4.2 + i = last; + --i; + for(;;){ + ii = i; + --i; + if ( comp(*i, *ii) ){ + BidirectionalIterator j = last; + --j; + while ( !comp(*i, *j)){ + --j; + } + iter_swap(i, j); + reverse(ii, last); + return true; + } + if (i == first){ + reverse(first, last); + return false; + } + } + + + } + + template _UCXXEXPORT + bool prev_permutation(BidirectionalIterator first, BidirectionalIterator last) + { + less::value_type> c; + return prev_permutation(first, last, c); + } + + template _UCXXEXPORT + bool prev_permutation(BidirectionalIterator first, BidirectionalIterator last, Compare comp) + { + if(first == last){ + return false; // No data + } + BidirectionalIterator i = last; + --i; + if(i == first){ + return false; //Only one element + } + BidirectionalIterator ii = i; + --ii; + //If the last two items are in reverse order, swap them and call it done + if( comp(*i, *ii) ){ + iter_swap(ii, i); + return true; + } + + //Copied from GNU GCC header files version 3.4.2 + i = last; + --i; + + for(;;){ + ii = i; + --i; + if ( comp(*ii, *i)){ + BidirectionalIterator j = last; + --j; + while ( !comp(*j, *i)){ + --j; + } + iter_swap(i, j); + reverse(ii, last); + return true; + } + if (i == first){ + reverse(first, last); + return false; + } + } + + } + +} + +#pragma GCC visibility pop + +#endif + + + Index: branches/slice/rev749/modules/uClibc++/include/istream_helpers =================================================================== --- branches/slice/rev749/modules/uClibc++/include/istream_helpers (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/istream_helpers (revision 1169) @@ -0,0 +1,344 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include + +#include + +#ifndef __STD_HEADER_ISTREAM_HELPERS +#define __STD_HEADER_ISTREAM_HELPERS 1 + +#pragma GCC visibility push(default) + +namespace std{ + + + /* We are making the following template class for serveral reasons. Firstly, + * we want to keep the main istream code neat and tidy. Secondly, we want it + * to be easy to do partial specialization of the istream code so that it can + * be expanded and put into the library. This will allow us to make application + * code smaller at the expense of increased library size. This is a fair + * trade-off when there are multiple applications being compiled. Also, this + * feature will be used optionally via configuration options. It will also + * allow us to keep the code bases in sync, dramatically simplifying the + * maintenance required. We specialized for char because wchar and others + * require different scanf functions + */ + + template _UCXXEXPORT + basic_string _readToken(basic_istream& stream) + { + basic_string temp; + typename traits::int_type c; + while(true){ + c = stream.rdbuf()->sgetc(); + if(c != traits::eof() && isspace(c) == false){ + stream.rdbuf()->sbumpc(); + temp.append(1, traits::to_char_type(c)); + }else{ + break; + } + } + if (temp.size() == 0) + stream.setstate(ios_base::eofbit|ios_base::failbit); + + return temp; + } + + template _UCXXEXPORT + basic_string _readTokenDecimal(basic_istream& stream) + { + basic_string temp; + typename traits::int_type c; + while(true){ + c = stream.rdbuf()->sgetc(); + if(c != traits::eof() && isspace(c) == false && (isdigit(c) || c == '.' || c == ',' )){ + stream.rdbuf()->sbumpc(); + temp.append(1, traits::to_char_type(c)); + }else{ + break; + } + } + if (temp.size() == 0) + stream.setstate(ios_base::eofbit|ios_base::failbit); + + return temp; + } + +#ifdef __UCLIBCXX_EXPAND_ISTREAM_CHAR__ + + template <> _UCXXEXPORT string _readToken >(istream & stream); + +#endif + + + template class _UCXXEXPORT __istream_readin{ + public: + static void readin(basic_istream& stream, dataType & var); + }; + + template class _UCXXEXPORT __istream_readin{ + public: + inline static void readin(basic_istream& stream, bool & var) + { + basic_string temp; + temp = _readToken( stream); + if(temp == "true" || temp == "True" || temp == "TRUE" || temp == "1"){ + var = true; + }else{ + var = false; + } + } + }; + + + template class _UCXXEXPORT __istream_readin{ + public: + inline static void readin(basic_istream& stream, short & var) + { + basic_string temp; + + if(stream.flags() & ios_base::dec){ + temp = _readTokenDecimal( stream); + sscanf(temp.c_str(), "%hd", &var ); + }else{ + temp = _readToken( stream); + if( stream.flags() & ios_base::oct){ + sscanf(temp.c_str(), "%ho", (unsigned short int *)(&var) ); + }else if(stream.flags() & ios_base::hex){ + if(stream.flags() & ios_base::uppercase){ + sscanf(temp.c_str(), "%hX", (unsigned short int *)(&var) ); + }else{ + sscanf(temp.c_str(), "%hx", (unsigned short int *)(&var) ); + } + }else{ + sscanf(temp.c_str(), "%hi", &var); + + } + } + } + }; + + template class _UCXXEXPORT __istream_readin{ + public: + inline static void readin(basic_istream& stream, unsigned short & var) + { + basic_string temp; + + if(stream.flags() & ios_base::dec){ + temp = _readTokenDecimal( stream); + sscanf(temp.c_str(), "%hu", &var ); + }else{ + temp = _readToken( stream); + if( stream.flags() & ios_base::oct){ + sscanf(temp.c_str(), "%ho", &var); + }else if(stream.flags() & ios_base::hex){ + if(stream.flags() & ios_base::uppercase){ + sscanf(temp.c_str(), "%hX", &var ); + }else{ + sscanf(temp.c_str(), "%hx", &var); + } + }else{ + sscanf(temp.c_str(), "%hi", (signed short int*)(&var) ); + } + } + } + }; + + template class _UCXXEXPORT __istream_readin{ + public: + inline static void readin(basic_istream& stream, int & var) + { + basic_string temp; + + if(stream.flags() & ios_base::dec){ + temp = _readTokenDecimal( stream); + sscanf(temp.c_str(), "%d", &var ); + }else{ + temp = _readToken( stream); + if( stream.flags() & ios_base::oct){ + sscanf(temp.c_str(), "%o", (unsigned int *)(&var) ); + }else if(stream.flags() & ios_base::hex){ + if(stream.flags() & ios_base::uppercase){ + sscanf(temp.c_str(), "%X", (unsigned int *)(&var) ); + }else{ + sscanf(temp.c_str(), "%x", (unsigned int *)(&var) ); + } + }else{ + sscanf(temp.c_str(), "%i", &var); + } + } + } + }; + + template class _UCXXEXPORT __istream_readin{ + public: + inline static void readin(basic_istream& stream, unsigned int & var) + { + basic_string temp; + + if(stream.flags() & ios_base::dec){ + temp = _readTokenDecimal( stream); + sscanf(temp.c_str(), "%u", &var ); + }else{ + temp = _readToken( stream); + if( stream.flags() & ios_base::oct){ + sscanf(temp.c_str(), "%o", (unsigned int *)(&var) ); + }else if(stream.flags() & ios_base::hex){ + if(stream.flags() & ios_base::uppercase){ + sscanf(temp.c_str(), "%X", (unsigned int *)(&var) ); + }else{ + sscanf(temp.c_str(), "%x", (unsigned int *)(&var) ); + } + }else{ + sscanf(temp.c_str(), "%i", (int *)(&var) ); + } + } + + } + }; + + + template class _UCXXEXPORT __istream_readin{ + public: + inline static void readin(basic_istream& stream, long int & var) + { + basic_string temp; + + if(stream.flags() & ios_base::dec){ + temp = _readTokenDecimal( stream); + sscanf(temp.c_str(), "%ld", &var ); + }else{ + temp = _readToken( stream); + if( stream.flags() & ios_base::oct){ + sscanf(temp.c_str(), "%lo", (unsigned long int *)(&var) ); + }else if(stream.flags() & ios_base::hex){ + if(stream.flags() & ios_base::uppercase){ + sscanf(temp.c_str(), "%lX", (unsigned long int *)(&var) ); + }else{ + sscanf(temp.c_str(), "%lx", (unsigned long int *)(&var) ); + } + }else{ + sscanf(temp.c_str(), "%li", (long int *)(&var) ); + } + } + + } + }; + + + template class _UCXXEXPORT __istream_readin{ + public: + inline static void readin(basic_istream& stream, unsigned long int & var) + { + basic_string temp; + + if(stream.flags() & ios_base::dec){ + temp = _readTokenDecimal( stream); + sscanf(temp.c_str(), "%lu", &var ); + }else{ + temp = _readToken( stream); + if( stream.flags() & ios_base::oct){ + sscanf(temp.c_str(), "%lo", &var ); + }else if(stream.flags() & ios_base::hex){ + if(stream.flags() & ios_base::uppercase){ + sscanf(temp.c_str(), "%lX", &var ); + }else{ + sscanf(temp.c_str(), "%lx", &var); + } + }else{ + sscanf(temp.c_str(), "%li", (long int *)(&var) ); + } + } + } + }; + + +#ifdef __UCLIBCXX_HAS_FLOATS__ + + template class _UCXXEXPORT __istream_readin{ + public: + inline static void readin(basic_istream& stream, float & var) + { + basic_string temp; + temp = _readTokenDecimal( stream); + + sscanf(temp.c_str(), "%g", &var); + } + }; + + template class _UCXXEXPORT __istream_readin{ + public: + inline static void readin(basic_istream& stream, double & var) + { + basic_string temp; + temp = _readTokenDecimal( stream); + sscanf(temp.c_str(), "%lg", &var); + } + }; + + template class _UCXXEXPORT __istream_readin{ + public: + inline static void readin(basic_istream& stream, long double & var) + { + basic_string temp; + temp = _readTokenDecimal( stream); + sscanf(temp.c_str(), "%Lg", &var); + } + }; + +#endif // ifdef __UCLIBCXX_HAS_FLOATS__ + + template class _UCXXEXPORT __istream_readin{ + public: + inline static void readin(basic_istream& stream, void* & var) + { + basic_string temp; + temp = _readToken( stream); + sscanf(temp.c_str(), "%p", &var); + } + }; + + + template void __skipws(basic_istream& is){ + const typename basic_istream::int_type eof = traits::eof(); + typename basic_istream::int_type c; + //While the next character normally read doesn't equal eof + //and that character is a space, advance to the next read position + //Thus itterating through all whitespace until we get to the meaty stuff + while ( + !traits::eq_int_type((c = is.rdbuf()->sgetc()), eof) + && isspace(c) + ) + { + is.rdbuf()->sbumpc(); + } + if(traits::eq_int_type(c, eof)){ + is.setstate(ios_base::eofbit); + } + } +} + +#pragma GCC visibility pop + +#endif + + + Index: branches/slice/rev749/modules/uClibc++/include/ostream_helpers =================================================================== --- branches/slice/rev749/modules/uClibc++/include/ostream_helpers (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/ostream_helpers (revision 1169) @@ -0,0 +1,490 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include +#include + +#ifndef __STD_HEADER_OSTREAM_HELPERS +#define __STD_HEADER_OSTREAM_HELPERS 1 + +#pragma GCC visibility push(default) + +namespace std{ + + /* We are making the following template class for serveral reasons. Firstly, + * we want to keep the main ostream code neat and tidy. Secondly, we want it + * to be easy to do partial specialization of the ostream code so that it can + * be expanded and put into the library. This will allow us to make application + * code smaller at the expense of increased library size. This is a fair + * trade-off when there are multiple applications being compiled. Also, this + * feature will be used optionally via configuration options. It will also + * allow us to keep the code bases in sync, dramatically simplifying the + * maintenance required. We specialized for char because wchar and others + * require different scanf functions + */ + + + + template class _UCXXEXPORT __ostream_printout{ + public: + static void printout(basic_ostream& stream, const dataType n); + }; + + template class _UCXXEXPORT __ostream_printout{ + public: + static void printout(basic_ostream& stream, const signed long int n) + { + char buffer[20]; + const char * c_ld = "%ld"; + const char * c_lo = "%lo"; + const char * c_lX = "%lX"; + const char * c_lx = "%lx"; + const char * c_hashlo = "%#lo"; + const char * c_hashlX = "%#lX"; + const char * c_hashlx = "%#lx"; + + const char * formatString=0; + + if( stream.flags() & ios_base::dec){ + formatString = c_ld; + }else if( stream.flags() & ios_base::oct){ + if( stream.flags() & ios_base::showbase){ + formatString = c_hashlo; + }else{ + formatString = c_lo; + } + }else if (stream.flags() & ios_base::hex){ + if(stream.flags() & ios_base::showbase){ + if(stream.flags() & ios_base::uppercase){ + formatString = c_hashlX; + }else{ + formatString = c_hashlx; + } + }else{ + if(stream.flags() & ios_base::uppercase){ + formatString = c_lX; + }else{ + formatString = c_lx; + } + } + } + + stream.write(buffer, snprintf(buffer, 20, formatString, n) ); + + if(stream.flags() & ios_base::unitbuf){ + stream.flush(); + } + + } + }; + + template class _UCXXEXPORT __ostream_printout{ + public: + static void printout(basic_ostream& stream, const unsigned long int n) + { + char buffer[20]; + const char * c_lo = "%lo"; + const char * c_lu = "%lu"; + const char * c_lX = "%lX"; + const char * c_lx = "%lx"; + const char * c_hashlo = "%#lo"; + const char * c_hashlX = "%#lX"; + const char * c_hashlx = "%#lx"; + const char * formatString=0; + + if( stream.flags() & ios_base::dec){ + formatString = c_lu; + }else if( stream.flags() & ios_base::oct){ + if( stream.flags() & ios_base::showbase){ + formatString = c_hashlo; + }else{ + formatString = c_lo; + } + }else if (stream.flags() & ios_base::hex){ + if(stream.flags() & ios_base::showbase){ + if(stream.flags() & ios_base::uppercase){ + formatString = c_hashlX; + }else{ + formatString = c_hashlx; + } + }else{ + if(stream.flags() & ios_base::uppercase){ + formatString = c_lX; + }else{ + formatString = c_lx; + } + } + } + + stream.write(buffer, snprintf(buffer, 20, formatString, n)); + if(stream.flags() & ios_base::unitbuf){ + stream.flush(); + } + } + }; + +#ifndef __STRICT_ANSI__ + + template class _UCXXEXPORT __ostream_printout{ + public: + static void printout(basic_ostream& stream, const signed long long int n) + { + char buffer[28]; + const char * lld = "%lld"; + const char * llo = "%llo"; + const char * llX = "%llX"; + const char * llx = "%llx"; + const char * hashllo = "%#llo"; + const char * hashllX = "%#llX"; + const char * hashllx = "%#llx"; + const char * formatString=0; + + if( stream.flags() & ios_base::dec){ + formatString = lld; + }else if( stream.flags() & ios_base::oct){ + if( stream.flags() & ios_base::showbase){ + formatString = hashllo; + }else{ + formatString = llo; + } + }else if (stream.flags() & ios_base::hex){ + if(stream.flags() & ios_base::showbase){ + if(stream.flags() & ios_base::uppercase){ + formatString = hashllX; + }else{ + formatString = hashllx; + } + }else{ + if(stream.flags() & ios_base::uppercase){ + formatString = llX; + }else{ + formatString = llx; + } + } + } + + stream.write(buffer, snprintf(buffer, 27, formatString, n) ); + + if(stream.flags() & ios_base::unitbuf){ + stream.flush(); + } + } + }; + + template class _UCXXEXPORT __ostream_printout{ + public: + static void printout(basic_ostream& stream, const unsigned long long int n) + { + char buffer[28]; + const char * llo = "%llo"; + const char * llu = "%llu"; + const char * llX = "%llX"; + const char * llx = "%llx"; + const char * hashllo = "%#llo"; + const char * hashllX = "%#llX"; + const char * hashllx = "%#llx"; + const char * formatString=0; + + if( stream.flags() & ios_base::dec){ + formatString = llu; + }else if( stream.flags() & ios_base::oct){ + if( stream.flags() & ios_base::showbase){ + formatString = hashllo; + }else{ + formatString = llo; + } + }else if (stream.flags() & ios_base::hex){ + if(stream.flags() & ios_base::showbase){ + if(stream.flags() & ios_base::uppercase){ + formatString = hashllX; + }else{ + formatString = hashllx; + } + }else{ + if(stream.flags() & ios_base::uppercase){ + formatString = llX; + }else{ + formatString = llx; + } + } + } + + stream.write(buffer, snprintf(buffer, 27, formatString, n) ); + + if(stream.flags() & ios_base::unitbuf){ + stream.flush(); + } + } + }; + + +#endif //__STRICT_ANSI__ + + template class _UCXXEXPORT __ostream_printout{ + public: + static void printout(basic_ostream& stream, const double f) + { + char buffer[32]; + int length; + if(stream.flags() & ios_base::scientific){ + if(stream.flags() & ios_base::uppercase){ + length = snprintf(buffer, 32, "%*.*E", static_cast(stream.width()),static_cast(stream.precision()), f); + }else{ + length = snprintf(buffer, 32, "%*.*e", static_cast(stream.width()),static_cast(stream.precision()), f); + } + } else if(stream.flags() & ios_base::fixed){ + length = snprintf(buffer, 32, "%*.*f",static_cast(stream.width()),static_cast(stream.precision()), f); + } else { + length = snprintf(buffer, 32, "%*.*g",static_cast(stream.width()),static_cast(stream.precision()), f); + } + stream.write(buffer, length); + if(stream.flags() & ios_base::unitbuf){ + stream.flush(); + } + } + }; + + template class _UCXXEXPORT __ostream_printout{ + public: + static void printout(basic_ostream& stream, const long double f) + { + char buffer[32]; + int length; + if(stream.flags() & ios_base::scientific){ + if(stream.flags() & ios_base::uppercase){ + length = snprintf(buffer, 32, "%*.*LE", static_cast(stream.width()), static_cast(stream.precision()), f); + }else{ + length = snprintf(buffer, 32, "%*.*Le", static_cast(stream.width()), static_cast(stream.precision()), f); + } + } else if(stream.flags() & ios_base::fixed){ + length = snprintf(buffer, 32, "%*.*Lf", static_cast(stream.width()), static_cast(stream.precision()), f); + } else { + length = snprintf(buffer, 32, "%*.*Lg", static_cast(stream.width()), static_cast(stream.precision()), f); + } + stream.write(buffer, length); + if(stream.flags() & ios_base::unitbuf){ + stream.flush(); + } + + } + }; + +#ifdef __UCLIBCXX_HAS_WCHAR__ + template class _UCXXEXPORT __ostream_printout{ + public: + static void printout(basic_ostream& stream, const signed long int n) + { + wchar_t buffer[20]; + if( stream.flags() & ios_base::dec){ + stream.write(buffer, swprintf(buffer, 20, L"%ld", n)); + }else if( stream.flags() & ios_base::oct){ + if( stream.flags() & ios_base::showbase){ + stream.write(buffer, swprintf(buffer, 20, L"%#lo", n)); + }else{ + stream.write(buffer, swprintf(buffer, 20, L"%lo", n) ); + } + }else if (stream.flags() & ios_base::hex){ + if(stream.flags() & ios_base::showbase){ + if(stream.flags() & ios_base::uppercase){ + stream.write(buffer, swprintf(buffer, 20, L"%#lX", n) ); + }else{ + stream.write(buffer, swprintf(buffer, 20, L"%#lx", n) ); + } + }else{ + if(stream.flags() & ios_base::uppercase){ + stream.write(buffer, swprintf(buffer, 20, L"%lX", n) ); + }else{ + stream.write(buffer, swprintf(buffer, 20, L"%lx", n) ); + } + } + } + if(stream.flags() & ios_base::unitbuf){ + stream.flush(); + } + } + }; + + template class _UCXXEXPORT __ostream_printout{ + public: + static void printout(basic_ostream& stream, const unsigned long int n) + { + wchar_t buffer[20]; + if( stream.flags() & ios_base::dec){ + stream.write(buffer, swprintf(buffer, 20, L"%lu", n)); + }else if( stream.flags() & ios_base::oct){ + if( stream.flags() & ios_base::showbase){ + stream.write(buffer, swprintf(buffer, 20, L"%#lo", n)); + }else{ + stream.write(buffer, swprintf(buffer, 20, L"%lo", n) ); + } + }else if (stream.flags() & ios_base::hex){ + if(stream.flags() & ios_base::showbase){ + if(stream.flags() & ios_base::uppercase){ + stream.write(buffer, swprintf(buffer, 20, L"%#lX", n) ); + }else{ + stream.write(buffer, swprintf(buffer, 20, L"%#lx", n) ); + } + }else{ + if(stream.flags() & ios_base::uppercase){ + stream.write(buffer, swprintf(buffer, 20, L"%lX", n) ); + }else{ + stream.write(buffer, swprintf(buffer, 20, L"%lx", n) ); + } + } + } + if(stream.flags() & ios_base::unitbuf){ + stream.flush(); + } + } + }; + +#ifndef __STRICT_ANSI__ + + template class _UCXXEXPORT __ostream_printout{ + public: + static void printout(basic_ostream& stream, const signed long long int n) + { + wchar_t buffer[28]; + if( stream.flags() & ios_base::dec){ + stream.write(buffer, swprintf(buffer, 27, L"%lld", n)); + }else if( stream.flags() & ios_base::oct){ + if( stream.flags() & ios_base::showbase){ + stream.write(buffer, swprintf(buffer, 27, L"%#llo", n)); + }else{ + stream.write(buffer, swprintf(buffer, 27, L"%llo", n) ); + } + }else if (stream.flags() & ios_base::hex){ + if(stream.flags() & ios_base::showbase){ + if(stream.flags() & ios_base::uppercase){ + stream.write(buffer, swprintf(buffer, 27, L"%#llX", n) ); + }else{ + stream.write(buffer, swprintf(buffer, 27, L"%#llx", n) ); + } + }else{ + if(stream.flags() & ios_base::uppercase){ + stream.write(buffer, swprintf(buffer, 27, L"%llX", n) ); + }else{ + stream.write(buffer, swprintf(buffer, 27, L"%llx", n) ); + } + } + } + if(stream.flags() & ios_base::unitbuf){ + stream.flush(); + } + } + }; + + template class _UCXXEXPORT __ostream_printout{ + public: + static void printout(basic_ostream& stream, const unsigned long long int n) + { + wchar_t buffer[28]; + if( stream.flags() & ios_base::dec){ + stream.write(buffer, swprintf(buffer, 27, L"%llu", n)); + }else if( stream.flags() & ios_base::oct){ + if( stream.flags() & ios_base::showbase){ + stream.write(buffer, swprintf(buffer, 27, L"%#llo", n)); + }else{ + stream.write(buffer, swprintf(buffer, 27, L"%llo", n) ); + } + }else if (stream.flags() & ios_base::hex){ + if(stream.flags() & ios_base::showbase){ + if(stream.flags() & ios_base::uppercase){ + stream.write(buffer, swprintf(buffer, 27, L"%#llX", n) ); + }else{ + stream.write(buffer, swprintf(buffer, 27, L"%#llx", n) ); + } + }else{ + if(stream.flags() & ios_base::uppercase){ + stream.write(buffer, swprintf(buffer, 27, L"%llX", n) ); + }else{ + stream.write(buffer, swprintf(buffer, 27, L"%llx", n) ); + } + } + } + if(stream.flags() & ios_base::unitbuf){ + stream.flush(); + } + } + }; + + +#endif //__STRICT_ANSI__ + + template class _UCXXEXPORT __ostream_printout{ + public: + static void printout(basic_ostream& stream, const double f) + { + wchar_t buffer[32]; + wchar_t format_string[32]; + if(stream.flags() & ios_base::scientific){ + if(stream.flags() & ios_base::uppercase){ + swprintf(format_string, 32, L"%%%u.%uE", static_cast(stream.width()), static_cast(stream.precision())); + }else{ + swprintf(format_string, 32, L"%%%u.%ue", static_cast(stream.width()), static_cast(stream.precision())); + } + } else if(stream.flags() & ios_base::fixed){ + swprintf(format_string, 32, L"%%%u.%uf", static_cast(stream.width()), static_cast(stream.precision())); + } else { + swprintf(format_string, 32, L"%%%u.%ug", static_cast(stream.width()), static_cast(stream.precision())); + } + stream.write(buffer, swprintf(buffer, 32, format_string, f) ); + if(stream.flags() & ios_base::unitbuf){ + stream.flush(); + } + } + }; + + template class _UCXXEXPORT __ostream_printout{ + public: + static void printout(basic_ostream& stream, const long double f) + { + wchar_t buffer[32]; + wchar_t format_string[32]; + if(stream.flags() & ios_base::scientific){ + if(stream.flags() & ios_base::uppercase){ + swprintf(format_string, 32, L"%%%u.%uLE", static_cast(stream.width()), static_cast(stream.precision())); + }else{ + swprintf(format_string, 32, L"%%%u.%uLe", static_cast(stream.width()), static_cast(stream.precision())); + } + } else if(stream.flags() & ios_base::fixed){ + swprintf(format_string, 32, L"%%%u.%uLf", static_cast(stream.width()), static_cast(stream.precision())); + } else { + swprintf(format_string, 32, L"%%%u.%uLg", static_cast(stream.width()), static_cast(stream.precision())); + } + stream.write(buffer, swprintf(buffer, 32, format_string, f) ); + if(stream.flags() & ios_base::unitbuf){ + stream.flush(); + } + } + }; + +#endif //__UCLIBCXX_HAS_WCHAR__ + +} + +#pragma GCC visibility pop + +#endif + + + Index: branches/slice/rev749/modules/uClibc++/include/typeinfo =================================================================== --- branches/slice/rev749/modules/uClibc++/include/typeinfo (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/typeinfo (revision 1169) @@ -0,0 +1,156 @@ +// RTTI support for -*- C++ -*- +// Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002 +// Free Software Foundation +// +// This file is part of GNU CC. +// +// GNU CC is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// GNU CC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with GNU CC; see the file COPYING. If not, write to +// the Free Software Foundation, 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/** @file typeinfo + * This header provides RTTI support. + */ + +#ifndef __TYPEINFO__ +#define __TYPEINFO__ + +#include + +extern "C++" { + +namespace __cxxabiv1 +{ + class __class_type_info; +} // namespace __cxxabiv1 + +#if !__GXX_WEAK__ + // If weak symbols are not supported, typeinfo names are not merged. + #define __GXX_MERGED_TYPEINFO_NAMES 0 +#else + // On platforms that support weak symbols, typeinfo names are merged. + #define __GXX_MERGED_TYPEINFO_NAMES 1 +#endif + +namespace std +{ + /** + * @brief Part of RTTI. + * + * The @c type_info class describes type information generated by + * an implementation. + */ + class type_info + { + public: + /** Destructor. Being the first non-inline virtual function, this + * controls in which translation unit the vtable is emitted. The + * compiler makes use of that information to know where to emit + * the runtime-mandated type_info structures in the new-abi. */ + virtual ~type_info(); + + private: + /// Assigning type_info is not supported. Made private. + type_info& operator=(const type_info&); + type_info(const type_info&); + + protected: + const char *__name; + + protected: + explicit type_info(const char *__n): __name(__n) { } + + public: + // the public interface + /** Returns an @e implementation-defined byte string; this is not + * portable between compilers! */ + const char* name() const + { return __name; } + +#if !__GXX_MERGED_TYPEINFO_NAMES + bool before(const type_info& __arg) const; + // In old abi, or when weak symbols are not supported, there can + // be multiple instances of a type_info object for one + // type. Uniqueness must use the _name value, not object address. + bool operator==(const type_info& __arg) const; +#else + /** Returns true if @c *this precedes @c __arg in the implementation's + * collation order. */ + // In new abi we can rely on type_info's NTBS being unique, + // and therefore address comparisons are sufficient. + bool before(const type_info& __arg) const + { return __name < __arg.__name; } + bool operator==(const type_info& __arg) const + { return __name == __arg.__name; } +#endif + bool operator!=(const type_info& __arg) const + { return !operator==(__arg); } + + // the internal interface + public: + // return true if this is a pointer type of some kind + virtual bool __is_pointer_p() const; + // return true if this is a function type + virtual bool __is_function_p() const; + + // Try and catch a thrown type. Store an adjusted pointer to the + // caught type in THR_OBJ. If THR_TYPE is not a pointer type, then + // THR_OBJ points to the thrown object. If THR_TYPE is a pointer + // type, then THR_OBJ is the pointer itself. OUTER indicates the + // number of outer pointers, and whether they were const + // qualified. + virtual bool __do_catch(const type_info *__thr_type, void **__thr_obj, + unsigned __outer) const; + + // internally used during catch matching + virtual bool __do_upcast(const __cxxabiv1::__class_type_info *__target, + void **__obj_ptr) const; + }; + + /** + * @brief Thrown during incorrect typecasting. + * + * If you attempt an invalid @c dynamic_cast expression, an instance of + * this class (or something derived from this class) is thrown. */ + class bad_cast : public exception + { + public: + bad_cast() throw() { } + // This declaration is not useless: + // http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118 + virtual ~bad_cast() throw(); + }; + + /** If you use a NULL pointer in a @c typeid expression, this is thrown. */ + class bad_typeid : public exception + { + public: + bad_typeid () throw() { } + // This declaration is not useless: + // http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118 + virtual ~bad_typeid() throw(); + }; +} // namespace std + +} // extern "C++" +#endif Index: branches/slice/rev749/modules/uClibc++/include/exception =================================================================== --- branches/slice/rev749/modules/uClibc++/include/exception (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/exception (revision 1169) @@ -0,0 +1,120 @@ +// Exception Handling support header for -*- C++ -*- + +// Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2002 +// Free Software Foundation +// +// This file is part of GNU CC. +// +// GNU CC is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// GNU CC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with GNU CC; see the file COPYING. If not, write to +// the Free Software Foundation, 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/** @file exception + * This header defines several types and functions relating to the + * handling of exceptions in a C++ program. + */ + +#ifndef __EXCEPTION__ +#define __EXCEPTION__ + +#include + +extern "C++" { + +namespace std +{ + /** + * @brief Base class for all library exceptions. + * + * This is the base class for all exceptions thrown by the standard + * library, and by certain language expressions. You are free to derive + * your own %exception classes, or use a different hierarchy, or to + * throw non-class data (e.g., fundamental types). + */ + class exception + { + public: + exception() throw() { } + virtual ~exception() throw(); + /** Returns a C-style character string describing the general cause + * of the current error. */ + virtual const char* what() const throw(); + }; + + /** If an %exception is thrown which is not listed in a function's + * %exception specification, one of these may be thrown. */ + class bad_exception : public exception + { + public: + bad_exception() throw() { } + // This declaration is not useless: + // http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118 + virtual ~bad_exception() throw(); + }; + + /// If you write a replacement %terminate handler, it must be of this type. + typedef void (*terminate_handler) (); + /// If you write a replacement %unexpected handler, it must be of this type. + typedef void (*unexpected_handler) (); + + /// Takes a new handler function as an argument, returns the old function. + terminate_handler set_terminate(terminate_handler) throw(); + /** The runtime will call this function if %exception handling must be + * abandoned for any reason. */ + void terminate() __UCLIBCXX_NORETURN; + + /// Takes a new handler function as an argument, returns the old function. + unexpected_handler set_unexpected(unexpected_handler) throw(); + /** The runtime will call this function if an %exception is thrown which + * violates the function's %exception specification. */ + void unexpected() __UCLIBCXX_NORETURN; + + /** [18.6.4]/1: "Returns true after completing evaluation of a + * throw-expression until either completing initialization of the + * exception-declaration in the matching handler or entering @c unexpected() + * due to the throw; or after entering @c terminate() for any reason + * other than an explicit call to @c terminate(). [Note: This includes + * stack unwinding [15.2]. end note]" + * + * 2: "When @c uncaught_exception() is true, throwing an %exception can + * result in a call of @c terminate() (15.5.1)." + */ + bool uncaught_exception() throw(); +} // namespace std + +namespace __gnu_cxx +{ + /** A replacement for the standard terminate_handler which prints more + information about the terminating exception (if any) on stderr. Call + @code + std::set_terminate (__gnu_cxx::__verbose_terminate_handler) + @endcode + to use. For more info, see + http://gcc.gnu.org/onlinedocs/libstdc++/19_diagnostics/howto.html#4 + */ + void __verbose_terminate_handler (); +} // namespace __gnu_cxx + +} // extern "C++" + +#endif Index: branches/slice/rev749/modules/uClibc++/include/locale =================================================================== --- branches/slice/rev749/modules/uClibc++/include/locale (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/locale (revision 1169) @@ -0,0 +1,83 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include + +#ifndef __HEADER_STD_LOCALE +#define __HEADER_STD_LOCALE 1 + +#pragma GCC visibility push(default) + +namespace std{ + class _UCXXEXPORT locale { + public: + // types: + class facet; + class id; + typedef unsigned char category; + + static const category + none = 0, + collate = 0x01, ctype = 0x02, + monetary = 0x04, numeric = 0x08, + time = 0x10, messages = 0x20, + all = collate | ctype | monetary | numeric | time | messages; + + // construct/copy/destroy: + locale() throw(){ + return; + } + locale(const locale& other) throw(){ + (void)other; + return; + } + locale(const char *) throw(){ + return; + } + ~locale() throw(){ + return; + } + + const locale& operator=(const locale&) throw(){ + return *this; + } + std::string name() const { return "C"; } + }; + + class _UCXXEXPORT locale::facet { + friend class locale; + explicit facet(size_t = 0){ + return; + } + virtual ~facet(){ + return; + } + }; + + class _UCXXEXPORT locale::id { + id(){ } + }; + +} + +#pragma GCC visibility pop + +#endif Index: branches/slice/rev749/modules/uClibc++/include/vector =================================================================== --- branches/slice/rev749/modules/uClibc++/include/vector (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/vector (revision 1169) @@ -0,0 +1,517 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include +#include +#include +#include +#include +#include + + +#ifndef __STD_HEADER_VECTOR +#define __STD_HEADER_VECTOR + +#pragma GCC visibility push(default) + +namespace std{ + + template > class vector; + template bool operator==(const vector& x, const vector& y); + template bool operator< (const vector& x, const vector& y); + template bool operator!=(const vector& x, const vector& y); + template bool operator> (const vector& x, const vector& y); + template bool operator>=(const vector& x, const vector& y); + template bool operator<=(const vector& x, const vector& y); + template void swap(vector& x, vector& y); + + template class _UCXXEXPORT vector { + public: + + typedef typename Allocator::reference reference; + typedef typename Allocator::const_reference const_reference; + typedef typename Allocator::size_type size_type; + typedef typename Allocator::difference_type difference_type; + typedef typename Allocator::pointer pointer; + typedef typename Allocator::const_pointer const_pointer; + + typedef T* iterator; + typedef const T* const_iterator; + typedef T value_type; + typedef Allocator allocator_type; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + explicit _UCXXEXPORT vector(const Allocator& al= Allocator()): data(0), //defaultValue(T()), + data_size(__UCLIBCXX_STL_BUFFER_SIZE__), elements(0), a(al) + { + data = a.allocate(data_size); + } + + explicit _UCXXEXPORT vector(size_type n, const T& value = T(), const Allocator& al= Allocator()) : + data(0), data_size(0), elements(0), a(al) + { + data_size = n + __UCLIBCXX_STL_BUFFER_SIZE__; + data = a.allocate(data_size); + + resize(n, value); + } + + template _UCXXEXPORT + vector(InputIterator first, InputIterator last, const Allocator& al = Allocator()): + data(0), data_size(__UCLIBCXX_STL_BUFFER_SIZE__), elements(0), a(al) + { + data = a.allocate(data_size); + assign(first, last); + } + + _UCXXEXPORT vector(const vector& x){ + a = x.a; + + elements = x.elements; + data_size = elements + __UCLIBCXX_STL_BUFFER_SIZE__; + data = a.allocate(data_size); + + for(size_type i = 0; i < elements; i++){ + a.construct(data+i, x.data[i]); + } + } + + _UCXXEXPORT ~vector(); //Below + + _UCXXEXPORT vector& operator=(const vector& x){ + if(&x == this){ + return *this; + } + + reserve(x.elements); //Make sure that we have enough actual memory + + + //Copy as many elements as possible + + size_t minElements = elements; + if(minElements > x.elements){ + minElements = x.elements; + } + for(size_t i = 0; i < minElements; ++i){ + data[i] = x.data[i]; + } + + //If we need to add new elements + if(elements < x.elements){ + for(size_t i = elements; i< x.elements; ++i){ + a.construct(data+i, x.data[i]); + ++elements; + } + } + + if(elements > x.elements){ + downsize(x.elements); + } + + return *this; + } + + template _UCXXEXPORT void assign(InputIterator first, InputIterator last){ + clear(); + insert(begin(), first, last); + } + + template _UCXXEXPORT void assign(Size n, const U& u = U()){ + clear(); + resize(n, u); + } + + inline allocator_type get_allocator() const{ + return a; + } + + inline iterator begin(){ + return data; + } + + inline const_iterator begin() const{ + return data; + } + + inline iterator end(){ + return (data + elements); + } + + inline const_iterator end() const{ + return (data + elements); + } + + inline reverse_iterator rbegin(){ + return reverse_iterator(end()); + } + + inline const_reverse_iterator rbegin() const{ + return const_reverse_iterator(end()); + } + + inline reverse_iterator rend(){ + return reverse_iterator(begin()); + } + + inline const_reverse_iterator rend() const{ + return const_reverse_iterator(begin()); + } + + inline size_type size() const{ + return elements; + } + + _UCXXEXPORT size_type max_size() const{ + return ((size_type)(-1)) / sizeof(T); + } + + void downsize(size_type sz); + void resize(size_type sz, const T & c = T()); + + inline size_type capacity() const{ + return data_size; + } + + inline bool empty() const{ + return (size() == 0); + } + + void reserve(size_type n); + + inline reference operator[](size_type n){ + return data[n]; + } + + inline const_reference operator[](size_type n) const{ + return data[n]; + } + + _UCXXEXPORT const_reference at(size_type n) const{ + if(n >= elements){ + __throw_out_of_range("Invalid subscript"); + } + return data[n]; + } + + _UCXXEXPORT reference at(size_type n){ + if(n >= elements){ + __throw_out_of_range("Invalid subscript"); + } + return data[n]; + } + + inline reference front(){ + return data[0]; + } + + inline const_reference front() const{ + return data[0]; + } + + inline reference back(){ + return data[ size() - 1]; + } + + inline const_reference back() const{ + return data[ size() - 1 ]; + } + + inline void push_back(const T& x){ + resize( size() + 1, x); + } + + inline void pop_back(){ + downsize(size() - 1); + } + + _UCXXEXPORT iterator insert(iterator position, const T& x = T()){ + size_type index = position - data; + resize(size() + 1, x); + for(size_type i = elements - 1; i > index; --i){ + data[i] = data[i-1]; + } + data[index] = x; + return (data + index); + } + + _UCXXEXPORT void _insert_fill(iterator position, size_type n, const T & x){ + size_type index = position - data; + resize(size() + n, x); + + for(size_type i = elements -1; (i > (index+n-1)); --i){ + data[i] = data[i-n]; + } + for(size_type i = 0; i < n; i++){ + data[i + index] = x; + } + } + + template _UCXXEXPORT + void _insert_from_iterator(iterator position, InputIterator first, InputIterator last) + { + T temp; + while(first !=last){ + temp = *first; + position = insert(position, temp); + ++position; + ++first; + } + } + + template + inline void _dispatch_insert(iterator position, InputIterator first, InputIterator last, __true_type) + { + _insert_fill(position, first, last); + } + + template + inline void _dispatch_insert(iterator position, InputIterator first, InputIterator last, __false_type) + { + _insert_from_iterator(position, first, last); + } + + inline void insert(iterator position, size_type n, const T& x ){ + _insert_fill(position, n, x); + } + + template inline void insert(iterator position, InputIterator first, InputIterator last){ + typedef typename __is_integer::value __some_type; + _dispatch_insert(position, first, last, __some_type()); + } + + _UCXXEXPORT iterator erase(iterator position){ + size_type index = position - data; + for(size_type i = index; i < (elements - 1); ++i){ + data[i] = data[i+1]; + } + downsize(size() - 1); + return (data + index); + } + + _UCXXEXPORT iterator erase(iterator first, iterator last){ + size_type index = first - data; + size_type width = last - first; + for(size_type i = index; i < (elements - width) ;++i){ + data[i] = data[i+width]; + } + downsize(size() - width); + return (data + index); + } + + _UCXXEXPORT void swap(vector& v){ + if(this == &v){ //Avoid dv.swap(v) + return; + } + T* ptr; + size_type temp; + + //Swap pointers first + ptr = data; + data = v.data; + v.data = ptr; + + //Swap element counts + temp = elements; + elements = v.elements; + v.elements = temp; + + //Swap data size + temp = data_size; + data_size = v.data_size; + v.data_size = temp; + } + + _UCXXEXPORT void clear(){ + downsize(0); + } + + protected: + T* data; + size_type data_size; + size_type elements; + Allocator a; + }; + + + + //Here go template instantiations + + template _UCXXEXPORT vector::~vector(){ + for(size_t i = 0; i < elements; ++i){ + a.destroy(data + i); + } + a.deallocate(data, data_size); + } + + + template _UCXXEXPORT void vector::reserve(size_type n){ + if(n > data_size){ //We never shrink... + T * temp_ptr = data; + size_type temp_size = data_size; + + data_size = n; + data = a.allocate(data_size); + + for(size_type i = 0; i _UCXXEXPORT void vector::resize(size_type sz, const T & c){ + if(sz > elements){ //Need to actually call constructor + if(sz > data_size){ + reserve(sz + __UCLIBCXX_STL_BUFFER_SIZE__); + } + + for(size_type i = elements; i _UCXXEXPORT void vector::downsize(size_type sz){ + if(sz < elements){ //Actually are downsizing + for(size_t i = sz; i< elements; ++i){ + a.destroy(data+i); + } + elements = sz; + } + } + + +#ifndef __UCLIBCXX_COMPILE_VECTOR__ +#ifdef __UCLIBCXX_EXPAND_VECTOR_BASIC__ + + +#ifdef __UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ + template<> _UCXXEXPORT vector >::vector(const allocator& al); + template<> _UCXXEXPORT vector >::vector(size_type n, const char & value, const allocator & al); + + template<> _UCXXEXPORT vector >::~vector(); + template<> _UCXXEXPORT vector >::~vector(); + +#endif //__UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ + + template<> _UCXXEXPORT void vector >::reserve(size_type n); + template<> _UCXXEXPORT void vector >::reserve(size_type n); + template<> _UCXXEXPORT void vector >::reserve(size_type n); + template<> _UCXXEXPORT void vector >::reserve(size_type n); + template<> _UCXXEXPORT void vector >::reserve(size_type n); + template<> _UCXXEXPORT void vector >::reserve(size_type n); + template<> _UCXXEXPORT void vector >::reserve(size_type n); + template<> _UCXXEXPORT void vector >::reserve(size_type n); + template<> _UCXXEXPORT void vector >::reserve(size_type n); + template<> _UCXXEXPORT void vector >::reserve(size_type n); + template<> _UCXXEXPORT void vector >::reserve(size_type n); + + template<> _UCXXEXPORT void vector >::resize(size_type sz, const char & c); + template<> _UCXXEXPORT void + vector >::resize(size_type sz, const unsigned char & c); + template<> _UCXXEXPORT void vector >::resize(size_type sz, const short & c); + template<> _UCXXEXPORT void + vector >::resize(size_type sz, const unsigned short int & c); + template<> _UCXXEXPORT void vector >::resize(size_type sz, const int & c); + template<> _UCXXEXPORT void vector >::resize(size_type sz, const unsigned int & c); + template<> _UCXXEXPORT void vector >::resize(size_type sz, const long int & c); + template<> _UCXXEXPORT void + vector >::resize(size_type sz, const unsigned long int & c); + template<> _UCXXEXPORT void vector >::resize(size_type sz, const float & c); + template<> _UCXXEXPORT void vector >::resize(size_type sz, const double & c); + template<> _UCXXEXPORT void vector >::resize(size_type sz, const bool & c); + +#elif defined __UCLIBCXX_EXPAND_STRING_CHAR__ + +#ifdef __UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ + + template<> _UCXXEXPORT vector >::vector(const allocator& al); + template<> _UCXXEXPORT vector >::vector(size_type n, const char & value, const allocator & al); + template<> _UCXXEXPORT vector >::~vector(); + +#endif + + template<> _UCXXEXPORT void vector >::reserve(size_type n); + template<> _UCXXEXPORT void vector >::resize(size_type sz, const char & c); + +#endif +#endif + + + + template _UCXXEXPORT bool + operator==(const vector& x, const vector& y) + { + if(x.size() !=y.size() ){ + return false; + } + for(size_t i = 0; i < x.size(); ++i){ + if(x[i] != y[i]){ + return false; + } + } + return true; + } + + template _UCXXEXPORT bool + operator< (const vector& x, const vector& y) + { + less::iterator >::value_type> c; + return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end(), c); + } + template _UCXXEXPORT bool + operator!=(const vector& x, const vector& y) + { + return !(x == y); + } + template _UCXXEXPORT bool + operator> (const vector& x, const vector& y) + { + greater::iterator >::value_type> c; + return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end(), c); + } + template _UCXXEXPORT bool + operator>=(const vector& x, const vector& y) + { + greater_equal::iterator >::value_type> c; + return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end(), c); + } + template _UCXXEXPORT bool + operator<=(const vector& x, const vector& y) + { + less_equal::iterator >::value_type> c; + return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end(), c); + } + + template _UCXXEXPORT void swap(vector& x, vector& y){ + x.swap(y); + } + +} + +#pragma GCC visibility pop + +#endif + Index: branches/slice/rev749/modules/uClibc++/include/deque =================================================================== --- branches/slice/rev749/modules/uClibc++/include/deque (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/deque (revision 1169) @@ -0,0 +1,811 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + This file is part of the uClibc++ Library. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + + +#include +#include +#include + +#pragma GCC visibility push(default) + +#ifndef __STD_HEADER_DEQUE +#define __STD_HEADER_DEQUE + + +namespace std{ + template > class deque; + template bool operator==(const deque& x, const deque& y); + template bool operator< (const deque& x, const deque& y); + template bool operator!=(const deque& x, const deque& y); + template bool operator> (const deque& x, const deque& y); + template bool operator>=(const deque& x, const deque& y); + template bool operator<=(const deque& x, const deque& y); + template void swap(deque& x, deque& y); + + template class _UCXXEXPORT deque { + public: + friend bool operator==<>(const deque& x, const deque& y); + friend class deque_iter; + friend class deque_citer; + class deque_iter; + class deque_citer; + + typedef typename Allocator::reference reference; + typedef typename Allocator::const_reference const_reference; + typedef deque_iter iterator; + typedef deque_citer const_iterator; + typedef typename Allocator::size_type size_type; + typedef typename Allocator::difference_type difference_type; + typedef T value_type; + typedef Allocator allocator_type; + typedef typename Allocator::pointer pointer; + typedef typename Allocator::const_pointer const_pointer; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + explicit deque(const Allocator& al = Allocator()); + explicit deque(size_type n, const T& value = T(), const Allocator& al = Allocator()); + template deque(InputIterator first, InputIterator last, const Allocator& = Allocator()); + deque(const deque& x); + ~deque(); + + deque& operator=(const deque& x); + template void assign(InputIterator first, InputIterator last); + template void assign(Size n, const U& u = U()); + allocator_type get_allocator() const; + + iterator begin(); + const_iterator begin() const; + iterator end(); + const_iterator end() const; + reverse_iterator rbegin(); + const_reverse_iterator rbegin() const; + reverse_iterator rend(); + const_reverse_iterator rend() const; + + size_type size() const; + size_type max_size() const; + void resize(size_type sz, T c = T()); + bool empty() const; + + reference operator[](size_type n); + const_reference operator[](size_type n) const; + reference at(size_type n); + const_reference at(size_type n) const; + reference front(); + const_reference front() const; + reference back(); + const_reference back() const; + + void push_front(const T& x); + void push_back(const T& x); + iterator insert(iterator position, const T& x = T()); + void insert(iterator position, size_type n, const T& x); + template void insert (iterator position, InputIterator first, InputIterator last); + void pop_front(); + void pop_back(); + + iterator erase(iterator position); + iterator erase(iterator first, iterator last); + void swap(deque&); + void clear(); + + protected: + void reserve(size_type n); + inline size_type array_element(size_type deque_element) const{ + if(deque_element < (data_size - first_element)){ + return first_element + deque_element; + } + return deque_element - (data_size - first_element); + } + inline size_type first_subtract(size_type sub_size) const{ + if(sub_size > first_element){ + return (data_size - first_element) - sub_size; + } + return first_element - sub_size; + } + + T * data; + size_type data_size; //Physical size of array + size_type elements; //Elements in array + size_type first_element; //Element number of array 0..n + size_type last_element; //Element number of array 0..n + Allocator a; + + }; + + + template class _UCXXEXPORT deque::deque_iter + : public std::iterator< + random_access_iterator_tag, + T, + typename Allocator::difference_type, + typename Allocator::pointer, + typename Allocator::reference + > + { + friend class deque; + protected: + deque * container; + typename Allocator::size_type element; + + public: + deque_iter() : container(0), element(0) { } + deque_iter(const deque_iter & d) : container (d.container), element(d.element) { } + deque_iter(deque * c, typename Allocator::size_type e) + : container(c), element(e) + { + return; + } + ~deque_iter() { } + deque_iter & operator=(const deque_iter & d){ + container = d.container; + element = d.element; + return *this; + } + T & operator*(){ + return container->data[container->array_element(element)]; + } + T * operator->(){ + return container->data + container->array_element(element); + } + const T & operator*() const{ + return container->data[container->array_element(element)]; + } + const T * operator->() const{ + return container->data + container->array_element(element); + } + bool operator==(const deque_iter & d) const{ + if(container == d.container && element == d.element){ + return true; + } + return false; + } + bool operator!=(const deque_iter & d) const{ + if(container != d.container || element != d.element){ + return true; + } + return false; + } + bool operator<(const deque_iter & d) const{ + if(element < d.element){ + return true; + } + return false; + } + bool operator<=(const deque_iter & d) const{ + if(element <= d.element){ + return true; + } + return false; + } + bool operator>(const deque_iter & d) const{ + if(element > d.element){ + return true; + } + return false; + } + bool operator>=(const deque_iter & d) const{ + if(element >= d.element){ + return true; + } + return false; + } + deque_iter & operator++(){ + ++element; + return *this; + } + deque_iter operator++(int){ + deque_iter temp(container, element); + ++element; + return temp; + } + deque_iter operator+(typename Allocator::size_type n){ + deque_iter temp(container, element + n); + return temp; + } + deque_iter & operator+=(typename Allocator::size_type n){ + element += n; + return *this; + } + deque_iter & operator--(){ + --element; + return *this; + } + deque_iter operator--(int){ + deque_iter temp(container, element); + --element; + return temp; + } + deque_iter operator-(typename Allocator::size_type n){ + deque_iter temp(container, element - n); + return temp; + } + deque_iter & operator-=(typename Allocator::size_type n){ + element -= n; + return *this; + } + typename Allocator::size_type operator-(const deque_iter & d){ + return element - d.element; + } + + }; + + template class _UCXXEXPORT deque::deque_citer + : public std::iterator< + random_access_iterator_tag, + T, + typename Allocator::difference_type, + typename Allocator::const_pointer, + typename Allocator::const_reference + > + { + friend class deque; + protected: + const deque * container; + typename Allocator::size_type element; + + public: + deque_citer() : container(0), element(0) { } + deque_citer(const deque_citer & d) : container (d.container), element(d.element) { } + deque_citer(const deque * c, typename Allocator::size_type e) + : container(c), element(e) + { + return; + } + ~deque_citer() { } + deque_citer & operator=(const deque_iter & d){ + container = d.container; + element = d.element; + return *this; + } + const T & operator*() const{ + return container->data[container->array_element(element)]; + } + const T * operator->() const{ + return container->data + container->array_element(element); + } + bool operator==(const deque_citer & d) const{ + if(container == d.container && element == d.element){ + return true; + } + return false; + } + bool operator!=(const deque_citer & d) const{ + if(container != d.container || element != d.element){ + return true; + } + return false; + } + bool operator<(const deque_citer & d) const{ + if(element < d.element){ + return true; + } + return false; + } + bool operator<=(const deque_citer & d) const{ + if(element <= d.element){ + return true; + } + return false; + } + bool operator>(const deque_citer & d) const{ + if(element > d.element){ + return true; + } + return false; + } + bool operator>=(const deque_citer & d){ + if(element >= d.element){ + return true; + } + return false; + } + deque_citer & operator++(){ + ++element; + return *this; + } + deque_citer operator++(int){ + deque_citer temp(container, element); + ++element; + return temp; + } + deque_citer operator+(typename Allocator::size_type n){ + deque_citer temp(container, element + n); + return temp; + } + deque_citer & operator+=(typename Allocator::size_type n){ + element += n; + return *this; + } + deque_citer & operator--(){ + --element; + return *this; + } + deque_citer operator--(int){ + deque_citer temp(container, element); + --element; + return temp; + } + deque_citer operator-(typename Allocator::size_type n){ + deque_citer temp(container, element - n); + return temp; + } + deque_citer & operator-=(typename Allocator::size_type n){ + element -= n; + return *this; + } + typename Allocator::size_type operator-(const deque_citer & d){ + return element - d.element; + } + + }; + + template deque::deque(const Allocator& al) + : data(0), + data_size(0), elements(0), first_element(0), last_element(0), a(al) + { + data_size = __UCLIBCXX_STL_BUFFER_SIZE__; + data = a.allocate(data_size); + first_element = data_size /2; + last_element = first_element; + } + + + template deque::deque( + size_type n, const T& value, const Allocator& al) + : data(0), + elements(n), first_element(0), last_element(0), a(al) + { + data_size = elements + __UCLIBCXX_STL_BUFFER_SIZE__; + data = a.allocate(data_size); + first_element = (data_size - elements) / 2; + last_element = first_element; + + for(n=first_element ; n < last_element; ++n ){ + a.construct(data+n, value); + } + } + + + template template + deque::deque(InputIterator first, InputIterator last, const Allocator& al) + : data(0), + data_size(0), elements(0), first_element(0), last_element(0), a(al) + { + data_size = __UCLIBCXX_STL_BUFFER_SIZE__; + data = a.allocate(data_size); + first_element = data_size / 4; //Note sure how big, but let's add a little space... + last_element = first_element; + while(first != last){ + push_back(*first); + ++first; + } + } + + + template deque::deque(const deque& x) + : data(0), + elements(0), first_element(0), last_element(0), a(x.a) + { + data_size = x.elements + __UCLIBCXX_STL_BUFFER_SIZE__; + data = a.allocate(data_size); + first_element = (data_size - x.elements) / 2; + last_element = first_element; + for(size_type i=0; i < x.elements; ++i){ + push_back(x[i]); + } + } + + + template deque::~deque(){ + clear(); + a.deallocate(data, data_size); + } + + template deque& deque:: + operator=(const deque& x) + { + if(&x == this){ + return *this; + } + resize(x.elements); + for(size_t i = 0; i < elements; ++i){ + data[array_element(i)] = x[i]; + } + return *this; + } + + + template template void + deque::assign(InputIterator first, InputIterator last) + { + clear(); + while(first !=last){ + push_back(*first); + ++first; + } + } + + + template template void + deque::assign(Size n, const U& u) + { + if(&u == this){ + return; + } + clear(); + for(size_type i = 0; i < n; ++i){ + push_back(u); + } + } + + + template typename deque::allocator_type + deque::get_allocator() const + { + return a; + } + + template typename + deque::iterator deque::begin() + { + return deque_iter(this, 0); + } + + + template typename deque::const_iterator + deque::begin() const + { + return deque_citer(this, 0); + } + + template typename + deque::iterator deque::end() + { + return deque_iter(this, elements); + } + + template typename + deque::const_iterator deque::end() const + { + return deque_citer(this, elements); + } + + template typename + deque::reverse_iterator deque::rbegin() + { + return reverse_iterator(end()); + } + + template typename + deque::const_reverse_iterator deque::rbegin() const + { + return const_reverse_iterator(end()); + } + + template typename + deque::reverse_iterator deque::rend() + { + return reverse_iterator(begin()); + } + + template typename + deque::const_reverse_iterator deque::rend() const + { + return const_reverse_iterator(begin()); + } + + template typename + deque::size_type deque::size() const + { + return elements; + } + + template typename + deque::size_type deque::max_size() const + { + return ((size_type)(-1)) / sizeof(T); + } + + template void deque::resize(size_type sz, T c){ + reserve(sz); + while(sz > size()){ + push_back(c); + } + while(sz < size()){ + pop_back(); + } + } + + template bool deque::empty() const{ + return (elements == 0); + } + + template typename + deque::reference deque::operator[](size_type n) + { + return data[array_element(n)]; + } + + template typename + deque::const_reference deque::operator[](size_type n) const + { + return data[array_element(n)]; + } + + template typename + deque::reference deque::at(size_type n) + { + if(n > elements){ + __throw_out_of_range("Out of deque range"); + } + return data[array_element(n)]; + } + + template typename + deque::const_reference deque::at(size_type n) const + { + if(n > elements){ + __throw_out_of_range("Out of deque range"); + } + return data[array_element(n)]; + } + + template typename + deque::reference deque::front() + { + return data[first_element]; + } + + template typename + deque::const_reference deque::front() const + { + return data[first_element]; + } + + template typename + deque::reference deque::back() + { + return data[array_element(elements-1)]; + } + + template typename + deque::const_reference deque::back() const + { + return data[array_element(elements-1)]; + } + + template void deque::push_front(const T& x){ + reserve(elements + 1); + first_element = first_subtract(1); + a.construct(data + first_element, x); + ++elements; + } + + template void deque::push_back(const T& x){ + reserve(elements + 1); + a.construct(data + last_element, x); + ++elements; + last_element = array_element(elements); + } + + template typename + deque::iterator deque::insert(iterator position, const T& x) + { + reserve(elements+1); + if(position.element > (elements/2)){ + //Push all elements back 1 + push_back(x); + for(size_type i = elements-1; i > position.element; --i){ + at(i) = at(i-1); + } + }else{ + //Push all elements forward 1 + push_front(x); + for(size_type i = 0; i < position.element; ++i){ + at(i) = at(i+1); + } + } + at(position.element) = x; + return deque_iter(this, position.element); + } + + template void deque:: + insert(typename deque::iterator position, size_type n, const T& x) + { + reserve(elements + n); + for(size_t i =0; i < n; ++i){ + position = insert(position, x); + } + } + + template template + void deque::insert (iterator position, InputIterator first, InputIterator last) + { + while(first != last){ + position = insert(position, *first); + ++first; + } + } + + template void deque::pop_front(){ + if(elements == 0){ + __throw_out_of_range("deque pop_front"); + } + a.destroy(data + first_element); + first_element = array_element(1); + --elements; + } + + template void deque::pop_back(){ + last_element = array_element(elements - 1); + a.destroy(data + last_element); + --elements; + } + + template typename + deque::iterator deque::erase(typename deque::iterator position) + { + if(position.element > (elements /2)){ + for(size_type i = position.element; i < elements - 1; ++i){ + at(i) = at(i+1); + } + pop_back(); + }else{ + for(size_type i = position.element; i > 0; --i){ + at(i) = at(i-1); + } + pop_front(); + } + return deque_iter(this, position.element); + } + + template typename deque::iterator + deque:: + erase(typename deque::iterator first, typename deque::iterator last) + { + //Shift backwards + size_type num_move = last.element - first.element; + if( first.element > (elements - last.element) ){ + for(size_type i = last.element; i < elements ; ++i){ + at(i-num_move) = at(i); + } + for(size_type i = 0; i < num_move ; ++i){ + pop_back(); + } + }else{ + for(size_type i = 0; i < first.element ; ++i){ + at(last.element - i - 1) = at(first.element - i - 1); + } + for(size_type i = 0; i < num_move ; ++i){ + pop_front(); + } + } + return deque_iter(this, first.element); + } + + template void deque::swap(deque& x) + { + T * temp_data; + typename deque::size_type temp_size; + + //Swap data pointers + temp_data = x.data; + x.data = data; + data = temp_data; + + //Swap array sizes + temp_size = x.data_size; + x.data_size = data_size; + data_size = temp_size; + + //Swap num array elements + temp_size = x.elements; + x.elements = elements; + elements = temp_size; + + //Swap first_pointer + temp_size = x.first_element; + x.first_element = first_element; + first_element = temp_size; + + //Swap last_pointer + temp_size = x.last_element; + x.last_element = last_element; + last_element = temp_size; + } + + template void deque::clear() + { + while(elements > 0 ){ + pop_back(); + } + } + + + template void deque::reserve(typename deque::size_type n) + { + if(data_size >= n){ + return; + } + + size_type size_temp; + size_type first_temp; + T * data_temp; + size_temp = n + __UCLIBCXX_STL_BUFFER_SIZE__; //Reserve extra 'cause we can + data_temp = a.allocate(size_temp); + + first_temp = (size_temp - elements) / 2; + for(size_type i = 0; i < elements; ++i){ + a.construct(data_temp + first_temp + i, data[array_element(i)]); + a.destroy(data + array_element(i)); + } + + //Now shuffle pointers + a.deallocate(data, data_size); + data = data_temp; + data_size = size_temp; + first_element = first_temp; + last_element = first_element + elements; + } + + + template _UCXXEXPORT + bool + operator==(const deque& x, const deque& y) + { + if(x.elements != y.elements){ + return false; + } + for(typename deque::size_type i = 0; i < x.elements; ++i){ + if(x[i] < y[i] || y[i] < x[i]){ + return false; + } + } + return true; + } + + template bool operator< (const deque& x, const deque& y); + template _UCXXEXPORT + bool + operator!=(const deque& x, const deque& y) + { + if(x == y){ + return false; + } + return true; + } + template bool operator> (const deque& x, const deque& y); + template bool operator>=(const deque& x, const deque& y); + template bool operator<=(const deque& x, const deque& y); + template _UCXXEXPORT void swap(deque& x, deque& y){ + x.swap(y); + } + + + +} + +#pragma GCC visibility pop + +#endif + + + + Index: branches/slice/rev749/modules/uClibc++/include/stdexcept =================================================================== --- branches/slice/rev749/modules/uClibc++/include/stdexcept (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/stdexcept (revision 1169) @@ -0,0 +1,117 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include + +#ifndef HEADER_STD_EXCEPTIONS +#define HEADER_STD_EXCEPTIONS 1 + +//Don't include support if not needed +#ifdef __UCLIBCXX_EXCEPTION_SUPPORT__ + +#pragma GCC visibility push(default) + +namespace std{ + +//typedef basic_string string; + +class _UCXXEXPORT logic_error : public exception { +protected: + string mstring; +public: + logic_error() throw(); + logic_error(const string& what_arg); + + virtual ~logic_error() throw() {} + virtual const char * what() const throw(); + +}; + +class _UCXXEXPORT domain_error : public logic_error { +public: + domain_error() : logic_error() {} + domain_error(const string& what_arg) : logic_error(what_arg) {} + virtual ~domain_error() throw() {} +}; + +class _UCXXEXPORT invalid_argument : public logic_error { +public: + invalid_argument() : logic_error(){} + invalid_argument(const string& what_arg) : logic_error(what_arg){} + virtual ~invalid_argument() throw() {} +}; + +class _UCXXEXPORT length_error : public logic_error { +public: + length_error() : logic_error(){} + length_error(const string& what_arg) : logic_error(what_arg){} + virtual ~length_error() throw() {} +}; + +class _UCXXEXPORT out_of_range : public logic_error{ +public: + out_of_range(); + out_of_range(const string & what_arg); + virtual ~out_of_range() throw() {} + +}; + +class _UCXXEXPORT runtime_error : public exception{ +protected: + string mstring; +public: + runtime_error(); + runtime_error(const string& what_arg); + + virtual ~runtime_error() throw() {} + virtual const char * what() const throw(); +}; + +class _UCXXEXPORT range_error : public runtime_error{ +public: + range_error() : runtime_error(){} + range_error(const string& what_arg) : runtime_error(what_arg) {} + virtual ~range_error() throw(){ } +}; + + +class _UCXXEXPORT overflow_error : public runtime_error{ +public: + overflow_error() : runtime_error(){} + overflow_error(const string& what_arg) : runtime_error(what_arg) {} + virtual ~overflow_error() throw(){} +}; + +class _UCXXEXPORT underflow_error : public runtime_error{ +public: + underflow_error() : runtime_error(){} + underflow_error(const string& what_arg) : runtime_error(what_arg) {} + virtual ~underflow_error() throw(){} +}; + + + +} + +#pragma GCC visibility pop + +#endif +#endif Index: branches/slice/rev749/modules/uClibc++/include/climits =================================================================== --- branches/slice/rev749/modules/uClibc++/include/climits (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/climits (revision 1169) @@ -0,0 +1,28 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __STD_HEADER_CLIMITS +#define __STD_HEADER_CLIMITS 1 + + +#include + + +#endif + Index: branches/slice/rev749/modules/uClibc++/include/cstring =================================================================== --- branches/slice/rev749/modules/uClibc++/include/cstring (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/cstring (revision 1169) @@ -0,0 +1,78 @@ +/* Copyright (C) 2005 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include + +#ifndef __HEADER_CSTRING +#define __HEADER_CSTRING 1 + + +namespace std{ + + using ::memchr; + using ::memcmp; + using ::memcpy; + using ::memmove; + using ::memset; + using ::strcat; + using ::strchr; + using ::strcmp; + using ::strcoll; + using ::strcpy; + using ::strcspn; + using ::strerror; + using ::strlen; + using ::strncat; + using ::strncmp; + using ::strncpy; + using ::strpbrk; + using ::strrchr; + using ::strspn; + using ::strstr; + using ::strtok; + using ::strxfrm; + + + //Extra definitions required in c++ spec + + + inline void* memchr(void* s, int c, size_t n){ + return memchr(const_cast(s), c, n); + } + + inline char* strchr(char* s, int c){ + return strchr(const_cast(s), c); + } + + inline char* strpbrk(char* s1, const char* s2){ + return strpbrk(const_cast(s1), s2); + } + + inline char* strrchr(char* s, int c){ + return strrchr(const_cast(s), c); + } + + inline char* strstr(char* s1, const char* s2){ + return strstr(const_cast(s1), s2); + } + +} + +#endif + Index: branches/slice/rev749/modules/uClibc++/include/list =================================================================== --- branches/slice/rev749/modules/uClibc++/include/list (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/list (revision 1169) @@ -0,0 +1,927 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include + +#ifndef __STD_HEADER_LIST +#define __STD_HEADER_LIST 1 + +#pragma GCC visibility push(default) + +namespace std{ + + template > class _UCXXEXPORT list { + public: + typedef typename Allocator::reference reference; + typedef typename Allocator::const_reference const_reference; + typedef typename Allocator::size_type size_type; + typedef typename Allocator::difference_type difference_type; + typedef T value_type; + typedef Allocator allocator_type; + typedef typename Allocator::pointer pointer; + typedef typename Allocator::const_pointer const_pointer; + + protected: + class node; + class iter_list; + + node * list_start; + node * list_end; + size_type elements; + Allocator a; + + public: + + typedef iter_list iterator; + typedef iter_list const_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + explicit list(const Allocator& = Allocator()); + explicit list(size_type n, const T& value = T(), const Allocator& = Allocator()); + template list(InputIterator first, InputIterator last, + const Allocator& al= Allocator()); + list(const list& x); + ~list(); + + list& operator=(const list& x){ + if(&x == this){ + return *this; + } + clear(); + iterator i = x.begin(); + while(i != x.end()){ + push_back(*i); + ++i; + } + return *this; + } + + template void assign(InputIterator first, InputIterator last); + template void assign(Size n, const U& u = U()); + allocator_type get_allocator() const; + + iterator begin(); + const_iterator begin() const; + iterator end(); + const_iterator end() const; + reverse_iterator rbegin(); + const_reverse_iterator rbegin() const; + reverse_iterator rend(); + const_reverse_iterator rend() const; + + bool empty() const; + size_type size() const; + size_type max_size() const; + void resize(size_type sz, T c = T()); + + reference front(); + const_reference front() const; + reference back(); + const_reference back() const; + + void push_front(const T& x); + void pop_front(); + void push_back(const T& x); + void pop_back(); + iterator insert(iterator position, const T& x = T()); + void insert(iterator position, size_type n, const T& x); + template void insert(iterator position, InputIterator first, InputIterator last); + iterator erase(iterator position); + iterator erase(iterator position, iterator last); + void swap(list&); + void clear(); + + void splice(iterator position, list& x); + void splice(iterator position, list& x, iterator i); + void splice(iterator position, list& x, iterator first, iterator last); + void remove(const T& value); + template void remove_if(Predicate pred); + void unique(); + template void unique(BinaryPredicate binary_pred); + void merge(list& x); + template void merge(list& x, Compare comp); + void sort(); + template void sort(Compare comp); + void reverse(); + protected: + void swap_nodes(node * x, node * y); + }; + + + //Implementations of List + + //List node + template class _UCXXEXPORT list::node{ + public: + node * previous; + node * next; + T * val; + + node(): previous(0), next(0), val(0){ } + node(const T & t ): previous(0), next(0), val(0) { + val = new T(t); + //FIXME use allocator somehow but only call constructor once + } + node(const T & t, node * p, node * n): previous(p), next(n), val(0) { + val = new T(t); + } + ~node(){ } + }; + + //List iterator + template class _UCXXEXPORT list::iter_list + : public std::iterator< + bidirectional_iterator_tag, + T, + typename Allocator::difference_type, + typename Allocator::pointer, + typename Allocator::reference + > + { + private: + node * current; + public: + iter_list():current(0) { } + iter_list( typename list::node * n): current(n) { } + iter_list(const list::iter_list & l): current(l.current) { } + ~iter_list(){ } + + iter_list & operator=(const list::iter_list & right ){ + current = right.current; + return *this; + } + + T & operator*(){ + return *(current->val); + } + T * operator->(){ + return current->val; + } + const T & operator*() const{ + return *current->val; + } + const T * operator->() const{ + return current->val; + } + + bool operator==(const list::iter_list & right) const { + return (current == right.current); + } + + bool operator!=(const list::iter_list & right) const { + return (current != right.current); + } + + iter_list & operator++(){ + current = current->next; + return *this; + } + + iter_list operator++(int){ + iter_list temp(current); + current = current->next; + return temp; + } + iter_list & operator--(){ + current = current->previous; + return *this; + } + + iter_list operator--(int){ + iter_list temp(current); + current = current->previous; + return temp; + } + node * link_struct(){ + return current; + } + iter_list & operator+=(unsigned int n){ + for(unsigned int i = 0; i < n; ++i){ + current = current->next; + } + return *this; + } + iter_list & operator-=(unsigned int n){ + for(unsigned int i = 0; i < n; ++i){ + current = current->previous; + } + return *this; + } + }; + + + template list::list(const Allocator& al) + :list_start(0), list_end(0), elements(0), a(al) + { + //End node + list_start = new node(); + list_end = list_start; + return; + } + + template list::list + (typename Allocator::size_type n, const T& value, const Allocator& al) + :list_start(0), list_end(0), elements(0), a(al) + { + //End node + list_start = new node(); + list_end = list_start; + + for(typename Allocator::size_type i = 0; i < n ; ++i){ + push_back(value); + } + } + + template template + list::list + (InputIterator first, InputIterator last, const Allocator& al) + : list_start(0), list_end(0), elements(0), a(al) + { + list_start = new node(); + list_end = list_start; + while(first != last){ + push_back(*first); + ++first; + } + } + + template list::list(const list& x) + : list_start(0), list_end(0), elements(0), a(x.a) + { + list_start = new node(); + list_end = list_start; + + iterator i = x.begin(); + while(i != x.end()){ + push_back( *i); + ++i; + } + } + + template list::~list(){ + while(elements > 0){ + pop_front(); + } + delete list_start->val; +#if UCLIBCXX_DEBUG + list_start->val = 0; +#endif + delete list_start; +#if UCLIBCXX_DEBUG + list_start = 0; + list_end = 0; +#endif + } + + + template void list::swap_nodes(node * x, node * y){ + T * v = x->val; + x->val = y->val; + y->val = v; + } + + template typename list::iterator + list::begin() + { + return iterator(list_start); + } + + + template typename list::const_iterator + list::begin() const + { + return const_iterator(list_start); + } + + + template typename list::iterator + list::end() + { + return iterator(list_end); + } + + template typename list::const_iterator + list::end() const + { + return const_iterator(list_end); + } + + template typename list::reverse_iterator + list::rbegin() + { + return reverse_iterator(end()); + } + + template typename list::const_reverse_iterator + list::rbegin() const + { + return const_reverse_iterator(end()); + } + + template typename list::reverse_iterator + list::rend() + { + return reverse_iterator(begin()); + } + + template typename list::const_reverse_iterator + list::rend() const + { + return const_reverse_iterator(begin()); + } + + template bool list::empty() const{ + return (elements == 0); + } + template typename list::size_type list::size() const{ + return elements; + } + template typename list::size_type list::max_size() const{ + return ((size_type)(-1)) / (sizeof(T) + sizeof(node)); + } + template void list::resize(typename Allocator::size_type sz, T c){ +// if(sz > elements){ + for(typename Allocator::size_type i = elements; i < sz; ++i){ + push_back(c); + } +// } +// if(sz < elements){ + for(typename Allocator::size_type i = elements; i > sz; --i){ + pop_back(); + } +// } + } + + template typename list::reference list::front(){ + return *(list_start->val); + } + template typename list::const_reference list::front() const{ + return *(list_start->val); + } + template typename list::reference list::back(){ + return *(list_end->previous->val); + } + template typename list::const_reference list::back() const{ + return *(list_end->previous->val); + } + + + template void list::push_front(const T& x){ + node * temp = new node(x); + list_start->previous = temp; + temp->previous = 0; + temp->next = list_start; + list_start = temp; + ++elements; + } + + template void list::pop_front(){ + if(elements > 0){ + list_start = list_start->next; + delete list_start->previous->val; +#if UCLIBCXX_DEBUG + list_start->previous->val = 0; + list_start->previous->next = 0; + list_start->previous->previous = 0; +#endif + delete list_start->previous; + list_start->previous = 0; + --elements; + } + } + + template void list::push_back(const T& x){ + if(elements == 0){ + //The list is completely empty + list_start = new node(x); + list_end->previous = list_start; + list_start->previous = 0; + list_start->next = list_end; + elements = 1; + }else{ + node * temp = new node(x); + temp->previous = list_end->previous; + temp->next = list_end; + list_end->previous->next = temp; + list_end->previous = temp; + ++elements; + } + } + + template void list::pop_back(){ + if(elements > 0){ + node * temp = list_end->previous; + if(temp == list_start){ + list_end->previous = 0; + list_start = list_end; + }else{ + temp->previous->next = temp->next; + list_end->previous = temp->previous; + } + delete temp->val; +#if UCLIBCXX_DEBUG + temp->val = 0; + temp->next = 0; + temp->previous = 0; +#endif + delete temp; +#if UCLIBCXX_DEBUG + temp = 0; +#endif + --elements; + } + } + + + template typename list::iterator + list::insert(iterator position, const T& x) + { + node * temp = new node(x); + + temp->previous = position.link_struct()->previous; + temp->next = position.link_struct(); + + if(temp->previous == 0){ + list_start = temp; + }else{ + position.link_struct()->previous->next = temp; + } + + position.link_struct()->previous = temp; + + ++elements; + --position; + return position; + } + + template void list::insert(iterator position, size_type n, const T& x){ + for(typename list::size_type i = 0; i < n; ++i){ + position = insert(position, x); + } + } + + template template void + list::insert(iterator position, InputIterator first, InputIterator last) + { + while(first !=last){ + insert(position, *first); + ++first; + } + } + template typename list::iterator + list::erase(iterator position) + { + if(position != end() ){ + node * temp = position.link_struct(); + if(temp == list_start){ + ++position; + temp->next->previous = 0; + list_start = temp->next; + }else{ + --position; + temp->next->previous = temp->previous; + temp->previous->next = temp->next; + ++position; + } + delete temp->val; +#if UCLIBCXX_DEBUG + temp->next = 0; + temp->previous = 0; + temp->val = 0; +#endif + delete temp; +#if UCLIBCXX_DEBUG + temp = 0; +#endif + --elements; + } + return position; + } + template typename list::iterator + list::erase(iterator position, iterator last) + { + iterator temp = position; + while(position !=last){ + position = erase(position); + } + return position; + } + template void list::swap(list& l){ + node * temp; + size_type tempel; + + temp = list_start; + list_start = l.list_start; + l.list_start = temp; + + temp = list_end; + list_end = l.list_end; + l.list_end = temp; + + tempel = elements; + elements = l.elements; + l.elements = tempel; + } + template void list::clear(){ + while(elements > 0){ + pop_front(); + } + } + + template + void list::splice(iterator position, list& x) + { + + //Can't add non-existant elements + if(x.elements == 0){ + return; + } + + elements += x.elements; + x.elements = 0; + + + //Chaining to the begining + if(position == begin()){ + x.list_end->previous->next = list_start; + list_start->previous = x.list_end->previous; + + list_start = x.list_start; + + x.list_start = x.list_end; + x.list_end->previous = 0; + + return; + } + + //Link everything we need + x.list_start->previous = position.link_struct()->previous; + position.link_struct()->previous->next = x.list_start; + + position.link_struct()->previous = x.list_end->previous; + x.list_end->previous->next = position.link_struct(); + + //Clean up the other list + + x.list_start = x.list_end; + x.list_end->previous=0; + + } + + template + void list::splice(iterator position, list& x, iterator i) + { + //Invalid conditions + if( x.elements == 0 || i == position || position.link_struct() == i.link_struct()->next ){ + return; + } + + + //Do we need to adjust the begining pointer? + if(i == x.begin()){ + x.list_start = x.list_start->next; + x.list_start->previous = 0; + } + + + //Insert at begining special case + if(position == begin()){ + + i.link_struct()->previous->next = i.link_struct()->next; + i.link_struct()->next->previous = i.link_struct()->previous; + + i.link_struct()->previous = 0; + i.link_struct()->next = position.link_struct(); + position.link_struct()->previous = i.link_struct(); + + list_start = i.link_struct(); + + --x.elements; + ++elements; + return; + } + + if( i.link_struct()->previous != 0){ + i.link_struct()->previous->next = i.link_struct()->next; + i.link_struct()->next->previous = i.link_struct()->previous; + }else{ + i.link_struct()->next->previous = 0; + x.list_start = i.link_struct()->next; + } + + i.link_struct()->previous = position.link_struct()->previous; + position.link_struct()->previous->next = i.link_struct(); + + i.link_struct()->next = position.link_struct(); + position.link_struct()->previous = i.link_struct(); + + --x.elements; + ++elements; + } + + template + void list::splice(iterator position, list& x, + iterator first, iterator last) + { + if(x.elements == 0){ + return; + } + + iterator temp; + while(first != last){ + temp = first; + ++first; + splice(position, x, temp); + } + } + + + template void list::remove(const T& value){ + iterator temp = begin(); + while( temp != end() ){ + if(*temp == value){ + temp = erase(temp); + }else{ + ++temp; + } + } + } + + + template template void list::remove_if(Predicate pred){ + iterator temp = begin(); + while( temp != end() ){ + if( pred(*temp) ){ + temp = erase(temp); + }else{ + ++temp; + } + } + } + + + template void list::unique(){ + equal_to::value_type> p; + unique(p); + } + + template template + void list::unique(BinaryPredicate binary_pred) + { + iterator temp1 = begin(); + iterator temp2; + ++temp1; + while( temp1 != end() ){ + temp2 = temp1; + --temp2; + if( binary_pred(*temp1, *temp2) ){ + erase(temp1); + temp1 = temp2; + } + ++temp1; + } + } + + template void list::merge(list& x){ + less::iterator>::value_type> c; + merge(x, c); + } + + template template + void list::merge(list& x, Compare comp) + { + iterator source = x.begin(); + iterator temp; + iterator dest = begin(); + + while(source != x.end()){ + while( dest != end() && comp (*dest, *source) ){ + ++dest; + } + ++elements; + --x.elements; + + temp = source; + ++temp; + + if(dest == begin()){ + dest.link_struct()->previous = source.link_struct(); + source.link_struct()->next = dest.link_struct(); + source.link_struct()->previous = 0; + list_start = source.link_struct(); + }else{ + source.link_struct()->previous = dest.link_struct()->previous; + dest.link_struct()->previous->next = source.link_struct(); + source.link_struct()->next = dest.link_struct(); + dest.link_struct()->previous = source.link_struct(); + } + source = temp; + } + + //Fix up x; + x.list_start = x.list_end; + x.list_start->previous = 0; + } + + template void list::sort(){ + less::iterator>::value_type> c; + sort(c); + } + + template template + void list::sort(Compare comp) + { + typename list::iterator i, j, k; + + //FIXME - bubble sort + + if(elements == 0){ + return; + } + + i = end(); + --i; + while(i != begin()){ + j = begin(); + k = j; + ++k; + while(j != i){ + if( comp(*k, *j) ){ + swap_nodes(k.link_struct(), j.link_struct()); + } + ++j; + ++k; + } + --i; + } + } + + + template void list::reverse(){ + if(elements == 0){ + return; + } + + node * current; + node * following; + node * temp; + + //Need to move the list_end element to the begining + + temp = list_end; + list_end = temp->previous; + list_end->next = 0; + + list_start->previous = temp; + temp->previous = 0; + temp->next = list_start; + list_start = temp; + + current = list_start; + + while( current != list_end ){ + following = current->next; + + //Swap the values pointed to/at with the current node + temp = current->next; + current->next = current->previous; + current->previous = temp; + + current = following; + } + + //Swap pointers on the end node + temp = list_end->next; + list_end->next = list_end->previous; + list_end->previous = temp; + + + //Swap the fixed pointers + temp = list_start; + list_start = list_end; + list_end = temp; + + } + + template + bool operator==(const list& x, const list& y){ + if(x.size() != y.size()){ + return false; + } + typename list::const_iterator i = x.begin(); + typename list::const_iterator j = y.begin(); + + while(i != x.end()){ + if( *i != *j){ + return false; + } + ++i; + ++j; + } + return true; + } + + template + bool operator< (const list& x, const list& y){ + typename list::const_iterator i = x.begin(); + typename list::const_iterator j = y.begin(); + while(i != x.end() && j != y.end()){ + if( *i < *j){ + return true; + } + if(*j < *i){ + return false; + } + ++i; + ++j; + } + return (i == x.end() && j != y.end()); + } + + template + bool operator!=(const list& x, const list& y){ + return !(x == y); + } + + template + bool operator> (const list& x, const list& y){ + typename list::const_iterator i = x.begin(); + typename list::const_iterator j = y.begin(); + while(i != x.end() && j != y.end()){ + if( *i > *j){ + return true; + } + if( *j > *i){ + return false; + } + ++i; + ++j; + } + return (i != x.end() && j == y.end()); + } + + template + bool operator>=(const list& x, const list& y){ + typename list::const_iterator i = x.begin(); + typename list::const_iterator j = y.begin(); + while(i != x.end() && j != y.end()){ + if( *i >= *j){ + return true; + } + if(*j >= *i){ + return false; + } + ++i; + ++j; + } + return (i != x.end() && j == y.end()); + } + + template + bool operator<=(const list& x, const list& y){ + typename list::const_iterator i = x.begin(); + typename list::const_iterator j = y.begin(); + while(i != x.end() && j != y.end()){ + if( *i <= *j){ + return true; + } + if(*j <= *i){ + return false; + } + ++i; + ++j; + } + return (i == x.end()); + } + + template + void swap(list& x, list& y){ + x.swap(y); + } + +} + +#pragma GCC visibility pop + +#endif + + Index: branches/slice/rev749/modules/uClibc++/include/basic_definitions =================================================================== --- branches/slice/rev749/modules/uClibc++/include/basic_definitions (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/basic_definitions (revision 1169) @@ -0,0 +1,66 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + This file is part of the uClibc++ Library. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __BASIC_DEFINITIONS +#define __BASIC_DEFINITIONS 1 + +#include + +#pragma GCC visibility push(default) + +//The following is used to support GCC symbol visibility patch + +#ifdef GCC_HASCLASSVISIBILITY + #define _UCXXEXPORT __attribute__ ((visibility("default"))) + #define _UCXXLOCAL __attribute__ ((visibility("hidden"))) +#else + #define _UCXXEXPORT + #define _UCXXLOCAL + +#endif + +#ifdef __GCC__ +#define __UCLIBCXX_NORETURN __attribute__ ((__noreturn__)) +#else +#define __UCLIBCXX_NORETURN +#endif + +#ifdef __UCLIBCXX_HAS_TLS__ + #define __UCLIBCXX_TLS __thread +#else + #define __UCLIBCXX_TLS +#endif + + + +//Testing purposes +#define __STRING_MAX_UNITS 65535 + +namespace std{ + typedef signed long int streamsize; +} + +#pragma GCC visibility pop + +#endif + + +#ifdef __DODEBUG__ + #define UCLIBCXX_DEBUG 1 +#else + #define UCLIBCXX_DEBUG 0 +#endif Index: branches/slice/rev749/modules/uClibc++/include/cwctype =================================================================== --- branches/slice/rev749/modules/uClibc++/include/cwctype (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/cwctype (revision 1169) @@ -0,0 +1,106 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 +// Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// +// ISO C++ 14882: +// + +/** @file cwctype + * This is a Standard C++ Library file. You should @c #include this file + * in your programs, rather than any of the "*.h" implementation files. + * + * This is the C++ version of the Standard C Library header @c wctype.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std. + */ + +#ifndef _CPP_CWCTYPE +#define _CPP_CWCTYPE 1 + +#pragma GCC system_header + +//#include + +#ifdef __UCLIBCXX_HAS_WCHAR__ +#include +#endif + +// Get rid of those macros defined in in lieu of real functions. +#undef iswalnum +#undef iswalpha +#undef iswblank +#undef iswcntrl +#undef iswdigit +#undef iswgraph +#undef iswlower +#undef iswprint +#undef iswprint +#undef iswpunct +#undef iswspace +#undef iswupper +#undef iswxdigit +#undef iswctype +#undef towlower +#undef towupper +#undef towctrans +#undef wctrans +#undef wctype + +#if __UCLIBCXX_HAS_WCHAR__ +namespace std +{ + using ::wint_t; // cwchar + + using ::wctype_t; + using ::wctrans_t; + + using ::iswalnum; + using ::iswalpha; + using ::iswblank; + using ::iswcntrl; + using ::iswdigit; + using ::iswgraph; + using ::iswlower; + using ::iswprint; + using ::iswprint; + using ::iswpunct; + using ::iswspace; + using ::iswupper; + using ::iswxdigit; + using ::iswctype; + using ::towlower; + using ::towupper; + using ::towctrans; + using ::wctrans; + using ::wctype; +} +#endif //__ULIBCXX_HAS_WCHAR__ + +#endif Index: branches/slice/rev749/modules/uClibc++/include/queue =================================================================== --- branches/slice/rev749/modules/uClibc++/include/queue (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/queue (revision 1169) @@ -0,0 +1,126 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + This file is part of the uClibc++ Library. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include + +#ifndef __HEADER_STD_QUEUE +#define __HEADER_STD_QUEUE 1 + +#pragma GCC visibility push(default) + +namespace std{ + + template > class _UCXXEXPORT queue{ + protected: + Container c; + public: + typedef typename Container::value_type value_type; + typedef typename Container::size_type size_type; + typedef Container container_type; + + explicit queue(const Container& a = Container()) : c(a) { } + + bool empty() const { return c.empty(); } + size_type size() const { return c.size(); } + value_type& front() { return c.front(); } + const value_type& front() const { return c.front(); } + value_type& back() { return c.back(); } + const value_type& back() const { return c.back(); } + void push(const value_type& x) { c.push_back(x); } + void pop() { c.pop_front(); } + }; + + + template _UCXXEXPORT bool + operator==(const queue& x, const queue& y) + { + return (x.c == y.c); + } + template _UCXXEXPORT bool + operator< (const queue& x, const queue& y) + { + return (x.c < y.c); + } + template _UCXXEXPORT bool + operator!=(const queue& x, const queue& y) + { + return (x.c != y.c); + } + template _UCXXEXPORT bool + operator> (const queue& x, const queue& y) + { + return (x.c > y.c); + } + template _UCXXEXPORT bool + operator>=(const queue& x, const queue& y) + { + return (x.c >= y.c); + } + template _UCXXEXPORT bool + operator<=(const queue& x, const queue& y) + { + return (x.c <= y.c); + } + + + template , + class Compare = less + > class _UCXXEXPORT priority_queue { + protected: + Container c; + Compare comp; + public: + typedef typename Container::value_type value_type; + typedef typename Container::size_type size_type; + typedef Container container_type; + + explicit priority_queue(const Compare& x = Compare(), const Container& a = Container()) + : c(a), comp(x) { make_heap(c.begin(), c.end(), comp) ; } + template priority_queue(InputIterator first, + InputIterator last, + const Compare& x = Compare(), + const Container& y= Container()) + : c(y), comp(c) + { + c.insert(c.end(), first, last); + make_heap(c.begin(), c.end(), comp); + } + + bool empty() const { return c.empty(); } + size_type size() const { return c.size(); } + const value_type& top() const { return c.front(); } + void push(const value_type& x){ + c.push_back(x); + push_heap(c.begin(), c.end(), comp); + } + void pop(){ + pop_heap(c.begin(), c.end(), comp); + c.pop_back(); + } + }; + +} + +#pragma GCC visibility pop + +#endif + + Index: branches/slice/rev749/modules/uClibc++/include/cerrno =================================================================== --- branches/slice/rev749/modules/uClibc++/include/cerrno (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/cerrno (revision 1169) @@ -0,0 +1,19 @@ +/* Copyright (C) 2005 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include Index: branches/slice/rev749/modules/uClibc++/include/streambuf =================================================================== --- branches/slice/rev749/modules/uClibc++/include/streambuf (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/streambuf (revision 1169) @@ -0,0 +1,329 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include + +#ifndef HEADER_STD_STREAMBUF +#define HEADER_STD_STREAMBUF 1 + +#include + +#pragma GCC visibility push(default) + +namespace std{ + + template class _UCXXEXPORT basic_streambuf{ + public: +#ifdef __UCLIBCXX_SUPPORT_CDIR__ + friend ios_base::Init::Init(); +#endif + // Types: + typedef charT char_type; + typedef typename traits::int_type int_type; + typedef typename traits::pos_type pos_type; + typedef typename traits::off_type off_type; + typedef traits traits_type; + + virtual ~basic_streambuf(); + + locale pubimbue(const locale &loc); + + locale getloc() const{ + return myLocale; + } + + basic_streambuf* pubsetbuf(char_type* s, streamsize n){ + return setbuf(s,n); + } + pos_type pubseekoff(off_type off, + typename ios_base::seekdir way, + ios_base::openmode which = ios_base::in | + ios_base::out + ) + { + return seekoff(off,way,which); + } + pos_type pubseekpos(pos_type sp, ios_base::openmode which = ios_base::in | ios_base::out){ + return seekpos(sp,which); + } + int pubsync(){ + return sync(); + } + + streamsize in_avail(); + + int_type snextc(); + + int_type sbumpc(); + + int_type sgetc(); + + streamsize sgetn(char_type* s, streamsize n){ + return xsgetn(s,n); + } + + int_type sputbackc(char_type c); + + int_type sungetc(); + + int_type sputc(char_type c); + + streamsize sputn(const char_type* s, streamsize n){ + if(openedFor & ios_base::app){ + seekoff(0, ios_base::end, ios_base::out); + } + return xsputn(s, n); + } + + protected: + locale myLocale; + //Pointers for the "get" buffers + charT * mgbeg; + charT * mgnext; + charT * mgend; + + //Pointers for the "put" buffers + charT * mpbeg; + charT * mpnext; + charT * mpend; + + //In the event of null buffers Lets us know what the buffer is opened for + ios_base::openmode openedFor; + + basic_streambuf(); + + basic_streambuf(const basic_streambuf > &) + : myLocale(), + mgbeg(0), mgnext(0), mgend(0), mpbeg(0), mpnext(0), mpend(0), + openedFor(0) + { } + basic_streambuf > & operator=(const basic_streambuf > &){ + return *this; + } + + char_type* eback() const{ + return mgbeg; + } + char_type* gptr() const{ + return mgnext; + } + char_type* egptr() const{ + return mgend; + } + void gbump(int n){ + mgnext+=n; + } + void setg(char_type* gbeg, char_type* gnext, char_type* gend){ + mgbeg = gbeg; + mgnext = gnext; + mgend = gend; + } + + char_type* pbase() const{ + return mpbeg; + } + char_type* pptr() const{ + return mpnext; + } + char_type* epptr() const{ + return mpend; + } + void pbump(int n){ + mpnext+=n; + } + void setp(char_type* pbeg, char_type* pend){ + mpbeg = pbeg; + mpnext = pbeg; + mpend = pend; + } + + virtual void imbue(const locale &loc){ + myLocale = loc; + } + + //Virtual functions which we will not implement + + virtual basic_streambuf* setbuf(char_type* , streamsize){ + return 0; + } + virtual pos_type seekoff(off_type , ios_base::seekdir, + ios_base::openmode = ios_base::in | ios_base::out) + { + return 0; + } + virtual pos_type seekpos(pos_type , ios_base::openmode = ios_base::in | ios_base::out){ + return 0; + } + virtual int sync(){ + return 0; + } + + virtual int showmanyc(){ + return 0; + } + virtual streamsize xsgetn(char_type* , streamsize ){ + return 0; + } + virtual int_type underflow(){ + return traits_type::eof(); + } + virtual int_type uflow(){ + int_type ret = underflow(); + if (!traits_type::eq_int_type(ret, traits_type::eof())) + gbump(1); + return ret; + } + + virtual int_type pbackfail(int_type c = traits::eof()){ + return c; + } + virtual streamsize xsputn(const char_type* c, streamsize n){ + //This function is designed to be replaced by subclasses + for(streamsize i = 0; i< n; ++i){ + if(sputc(c[i]) == traits::eof()){ + return i; + } + } + return n; + } + virtual int_type overflow (int_type c = traits::eof()){ + return c; + } + }; + + typedef basic_streambuf streambuf; +#ifdef __UCLIBCXX_HAS_WCHAR__ + typedef basic_streambuf wstreambuf; +#endif + + +//Definitions put below to allow for easy expansion of code + + template basic_streambuf::~basic_streambuf(){ } + + template locale basic_streambuf::pubimbue(const locale &loc){ + locale temp = myLocale; + myLocale = loc; + return temp; + } + + template streamsize basic_streambuf::in_avail(){ + if(mgend !=0 && mgnext !=0){ + return mgend - mgnext; + } + return showmanyc(); + } + + template typename basic_streambuf::int_type basic_streambuf::sbumpc(){ + if(mgbeg == 0 || mgnext == mgend){ + return uflow(); + } + int_type retval = T::to_int_type(*gptr()); + gbump(1); + return retval; + } + + template typename basic_streambuf::int_type basic_streambuf::snextc(){ + if(sbumpc() == T::eof() ){ + return T::eof() ; + } + return sgetc(); + } + + template typename basic_streambuf::int_type basic_streambuf::sgetc(){ + if(mgbeg == 0 || mgnext == mgend){ + return underflow(); + } + return T::to_int_type(*gptr()); + } + + template typename basic_streambuf::int_type basic_streambuf::sputbackc(char_type c){ + if(mgbeg == 0 || mgnext == mgbeg || !T::eq(c, gptr()[-1] )){ + return pbackfail(T::to_int_type(c)); + } + gbump(-1); + return T::to_int_type(*gptr()); + } + + template typename basic_streambuf::int_type basic_streambuf::sungetc(){ + if(mgbeg == 0 || mgnext == mgbeg){ + return ios_base::failbit; + } + gbump(-1); + return T::to_int_type(*gptr()); + } + + template typename basic_streambuf::int_type basic_streambuf::sputc(char_type c){ + if(openedFor & ios_base::app){ + seekoff(0, ios_base::end, ios_base::out); + } + if(mpnext < mpend){ + *mpnext = c; + ++mpnext; + }else{ + return overflow( T::to_int_type(c) ); + } + return T::to_int_type(c); + } + + template basic_streambuf::basic_streambuf() + : myLocale(), + mgbeg(0), mgnext(0), mgend(0), mpbeg(0), mpnext(0), mpend(0), + openedFor(0) + { } + + + + + + +#ifdef __UCLIBCXX_EXPAND_STREAMBUF_CHAR__ +#ifndef __UCLIBCXX_COMPILE_STREAMBUF__ + +#ifdef __UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ + + template <> _UCXXEXPORT streambuf::basic_streambuf(); + template <> _UCXXEXPORT streambuf::~basic_streambuf(); + +#endif //__UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ + + template <> _UCXXEXPORT locale streambuf::pubimbue(const locale &loc); + template <> _UCXXEXPORT streamsize streambuf::in_avail(); + template <> _UCXXEXPORT streambuf::int_type streambuf::sbumpc(); + template <> _UCXXEXPORT streambuf::int_type streambuf::snextc(); + template <> _UCXXEXPORT streambuf::int_type streambuf::sgetc(); + template <> _UCXXEXPORT streambuf::int_type streambuf::sputbackc(char_type c); + template <> _UCXXEXPORT streambuf::int_type streambuf::sungetc(); + template <> _UCXXEXPORT streambuf::int_type streambuf::sputc(char_type c); + +#endif +#endif + + + + + +} + +#pragma GCC visibility pop + +#endif Index: branches/slice/rev749/modules/uClibc++/include/new =================================================================== --- branches/slice/rev749/modules/uClibc++/include/new (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/new (revision 1169) @@ -0,0 +1,64 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include + +#ifndef __STD_NEW_OPERATOR +#define __STD_NEW_OPERATOR 1 + +#pragma GCC visibility push(default) + +namespace std{ + class _UCXXEXPORT bad_alloc : public exception {}; + + struct _UCXXEXPORT nothrow_t {}; + extern const nothrow_t nothrow; + + typedef void (*new_handler)(); + _UCXXEXPORT new_handler set_new_handler(new_handler new_p) throw(); +} + + +_UCXXEXPORT void* operator new(std::size_t numBytes) throw(std::bad_alloc); +_UCXXEXPORT void operator delete(void* ptr) throw(); + +_UCXXEXPORT void* operator new[](std::size_t numBytes) throw(std::bad_alloc); +_UCXXEXPORT void operator delete[](void * ptr) throw(); + +#ifndef NO_NOTHROW +_UCXXEXPORT void* operator new(std::size_t numBytes, const std::nothrow_t& ) throw(); +_UCXXEXPORT void operator delete(void* ptr, const std::nothrow_t& ) throw(); + +_UCXXEXPORT void* operator new[](std::size_t numBytes, const std::nothrow_t& ) throw(); +_UCXXEXPORT void operator delete[](void* ptr, const std::nothrow_t& ) throw(); +#endif + + /* Placement operators */ +inline void* operator new(std::size_t, void* ptr) throw() {return ptr; } +inline void operator delete(void* , void *) throw() { } + +inline void* operator new[](std::size_t, void *p) throw() { return p; } +inline void operator delete[](void* , void *) throw() {} + +#pragma GCC visibility pop + +#endif + Index: branches/slice/rev749/modules/uClibc++/include/ios =================================================================== --- branches/slice/rev749/modules/uClibc++/include/ios (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/ios (revision 1169) @@ -0,0 +1,501 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include + +#ifndef __HEADER_STD_IOS +#define __HEADER_STD_IOS 1 + +#pragma GCC visibility push(default) + +namespace std{ + typedef signed long int streamoff; + + template class fpos; + + class _UCXXEXPORT ios_base { + public: + class failure; +#ifdef __UCLIBCXX_EXCEPTION_SUPPORT__ + class failure : public exception { + public: + explicit failure(const std::string& msg) { } + explicit failure() { } + virtual const char* what() const throw() { + return "std::ios_base failure exception"; + } + }; +#endif +#ifdef __UCLIBCXX_SUPPORT_CDIR__ + class _UCXXLOCAL Init{ + public: + _UCXXEXPORT Init(); + _UCXXEXPORT ~Init(); + private: + static int init_cnt; + }; +#endif + + public: + + typedef unsigned short int fmtflags; + + static const fmtflags skipws = 0x0001; + + static const fmtflags left = 0x0002; + static const fmtflags right = 0x0004; + static const fmtflags internal = 0x0008; + + static const fmtflags boolalpha = 0x0010; + + static const fmtflags dec = 0x0020; + static const fmtflags oct = 0x0040; + static const fmtflags hex = 0x0080; + + static const fmtflags scientific = 0x0100; + static const fmtflags fixed = 0x0200; + + static const fmtflags showbase = 0x0400; + static const fmtflags showpoint = 0x0800; + static const fmtflags showpos = 0x1000; + static const fmtflags uppercase = 0x2000; + + static const fmtflags adjustfield = left | right | internal; + static const fmtflags basefield = dec | oct | hex; + static const fmtflags floatfield = fixed | scientific; + + static const fmtflags unitbuf = 0x4000; + + typedef unsigned char iostate; + static const iostate goodbit = 0x00; + static const iostate badbit = 0x01; + static const iostate eofbit = 0x02; + static const iostate failbit = 0x04; + + typedef unsigned char openmode; + static const openmode app = 0x01; + static const openmode ate = 0x02; + static const openmode binary = 0x04; + static const openmode in = 0x08; + static const openmode out = 0x10; + static const openmode trunc = 0x20; + + typedef unsigned char seekdir; + static const seekdir beg = 0x01; + static const seekdir cur = 0x02; + static const seekdir end = 0x04; + + _UCXXEXPORT fmtflags flags() const{ + return mformat; + } + _UCXXEXPORT fmtflags flags(fmtflags fmtfl); + + fmtflags setf(fmtflags fmtfl); + fmtflags setf(fmtflags fmtfl, fmtflags mask ); + + _UCXXEXPORT void unsetf(fmtflags mask){ + mformat&= ~mask; + } + + _UCXXEXPORT streamsize precision() const{ + return mprecision; + } + + _UCXXEXPORT streamsize precision(streamsize prec); + + _UCXXEXPORT streamsize width() const{ + return mwidth; + } + + _UCXXEXPORT streamsize width(streamsize wide); + + _UCXXEXPORT locale imbue(const locale& loc); + + _UCXXEXPORT locale getloc() const{ + return mLocale; + } + +// FIXME - These need to be implemented +// static int xalloc(); +// long& iword(int index); +// void*& pword(int index); + + _UCXXEXPORT ~ios_base() { } + + enum event { erase_event, imbue_event, copyfmt_event }; + + typedef void (*event_callback)(event, ios_base&, int index); +// void register_callback(event_call_back fn, int index); + + //We are going to wrap stdio so we don't need implementation of the following: + inline static bool sync_with_stdio(bool = true) { return true; } + + protected: + _UCXXEXPORT ios_base() : mLocale(), mformat(dec | skipws ), mstate(goodbit), + mmode(), mdir(), mprecision(6), mwidth(0) +#ifdef __UCLIBCXX_SUPPORT_CDIR__ + ,mInit() +#endif + { + + } + locale mLocale; + fmtflags mformat; + iostate mstate; + openmode mmode; + seekdir mdir; + streamsize mprecision; + streamsize mwidth; +#ifdef __UCLIBCXX_SUPPORT_CDIR__ + Init mInit; +#endif + }; + + + //ios_base manipulators + + + inline ios_base& boolalpha (ios_base& str){ + str.setf(ios_base::boolalpha); + return str; + } + inline ios_base& noboolalpha(ios_base& str){ + str.unsetf(ios_base::boolalpha); + return str; + } + inline ios_base& showbase (ios_base& str){ + str.setf(ios_base::showbase); + return str; + } + inline ios_base& noshowbase (ios_base& str){ + str.unsetf(ios_base::showbase); + return str; + } + inline ios_base& showpoint (ios_base& str){ + str.setf(ios_base::showpoint); + return str; + } + inline ios_base& noshowpoint(ios_base& str){ + str.unsetf(ios_base::showpoint); + return str; + } + inline ios_base& showpos (ios_base& str){ + str.setf(ios_base::showpos); + return str; + } + inline ios_base& noshowpos (ios_base& str){ + str.unsetf(ios_base::showpos); + return str; + } + inline ios_base& skipws (ios_base& str){ + str.setf(ios_base::skipws); + return str; + } + inline ios_base& noskipws (ios_base& str){ + str.unsetf(ios_base::skipws); + return str; + } + inline ios_base& uppercase (ios_base& str){ + str.setf(ios_base::uppercase); + return str; + } + inline ios_base& nouppercase(ios_base& str){ + str.unsetf(ios_base::uppercase); + return str; + } + + inline ios_base& unitbuf (ios_base& str){ + str.setf(ios_base::unitbuf); + return str; + } + inline ios_base& nounitbuf (ios_base& str){ + str.unsetf(ios_base::unitbuf); + return str; + } + inline ios_base& internal (ios_base& str){ + str.setf(ios_base::internal, ios_base::adjustfield); + return str; + } + inline ios_base& left (ios_base& str){ + str.setf(ios_base::left, ios_base::adjustfield); + return str; + } + inline ios_base& right (ios_base& str){ + str.setf(ios_base::right, ios_base::adjustfield); + return str; + } + + inline ios_base& dec (ios_base& str){ + str.setf(ios_base::dec, ios_base::basefield); + return str; + } + inline ios_base& hex (ios_base& str){ + str.setf(ios_base::hex, ios_base::basefield); + return str; + } + inline ios_base& oct (ios_base& str){ + str.setf(ios_base::oct, ios_base::basefield); + return str; + } + + inline ios_base& fixed (ios_base& str){ + str.setf(ios_base::fixed, ios_base::floatfield); + return str; + } + inline ios_base& scientific (ios_base& str){ + str.setf(ios_base::scientific, ios_base::floatfield); + return str; + } + + + //basic_ios class definition + + + template class _UCXXEXPORT basic_ios + : public ios_base + { + public: + // Types: + typedef charT char_type; + typedef typename traits::int_type int_type; + typedef typename traits::pos_type pos_type; + typedef typename traits::off_type off_type; + typedef traits traits_type; + + _UCXXEXPORT operator void*() const{ + if(fail() ){ + return 0; + } + return (void *)(1); //Must return a non-NULL pointer (though it can be *any* pointer) + } + + _UCXXEXPORT bool operator!() const{ + return fail(); + } + _UCXXEXPORT iostate rdstate() const{ + return mstate; + } + _UCXXEXPORT void clear(iostate state = goodbit){ + if(rdbuf()!=0){ + mstate = state; + }else{ + mstate = state|ios_base::badbit; + } + } + _UCXXEXPORT void setstate(iostate state) { + clear(rdstate() | state); +#ifdef __UCLIBCXX_EXCEPTION_SUPPORT__ + if(rdstate() & throw_mask){ + throw failure(); + } +#endif + } + + _UCXXEXPORT bool good() const{ + return (rdstate() == 0); + } + _UCXXEXPORT bool eof() const{ + if(rdstate() & eofbit){ + return true; + } + return false; + } + _UCXXEXPORT bool fail() const{ + if( mstate & (failbit | badbit) ){ + return true; + } + return false; + } + + _UCXXEXPORT bool bad() const{ + if(mstate & badbit){ + return true; + } + return false; + } + + _UCXXEXPORT iostate exceptions() const{ + return throw_mask; + } + _UCXXEXPORT void exceptions(iostate except){ + throw_mask = except; + } + + explicit _UCXXEXPORT basic_ios(basic_streambuf* sb) : fill_char(' '), mtied(0), mstreambuf(0){ + init(sb); + } + + basic_ios() : mtied(0), mstreambuf(0){ } + + virtual _UCXXEXPORT ~basic_ios(){ + } + + _UCXXEXPORT basic_ostream* tie() const{ + return mtied; + } + _UCXXEXPORT basic_ostream* tie(basic_ostream* tiestr){ + basic_ostream* retval= mtied; + mtied = tiestr; + return retval; + } + _UCXXEXPORT basic_streambuf* rdbuf() const{ + return mstreambuf; + } + _UCXXEXPORT basic_streambuf* rdbuf(basic_streambuf* sb){ + basic_streambuf* retval = mstreambuf; + mstreambuf = sb; + return retval; + } + _UCXXEXPORT basic_ios& copyfmt(const basic_ios& rhs); + _UCXXEXPORT char_type fill() const{ + return fill_char; + } + _UCXXEXPORT char_type fill(char_type ch){ + char_type temp = fill_char; + fill_char = ch; + return temp; + } + + _UCXXEXPORT locale imbue(const locale& loc){ + return ios_base::imbue(loc); + } + _UCXXEXPORT char narrow(char_type c, char dfault) const; + _UCXXEXPORT char_type widen(char c) const; + + protected: + char_type fill_char; + basic_ostream* mtied; + basic_streambuf* mstreambuf; + iostate throw_mask; + _UCXXEXPORT basic_ios(const basic_ios &){ } + _UCXXEXPORT basic_ios & operator=(const basic_ios &){ return *this; } + _UCXXEXPORT void init(basic_streambuf* sb){ + ios_base::mformat = skipws|dec; + mstreambuf = sb; + mstate = goodbit; + throw_mask = goodbit; + } + }; + +#ifdef __UCLIBCXX_EXPAND_IOS_CHAR__ +#ifndef __UCLIBCXX_COMPILE_IOS__ + + template <> _UCXXEXPORT void basic_ios >::clear(iostate state); + template <> _UCXXEXPORT void basic_ios >::setstate(iostate state); + +#endif +#endif + + + template + inline char basic_ios::narrow(char_type c, char dfault) const + { + return dfault; + } + + template <> + inline char basic_ios >::narrow(char_type c, char) const + { + return c; + } + +#ifdef __UCLIBCXX_HAS_WCHAR__ + + template <> + inline char basic_ios >::narrow(char_type c, char dfault) const + { + char retval = wctob (c); + if(retval == EOF){ + retval = dfault; + } + return retval; + } + +#endif //__UCLIBCXX_HAS_WCHAR__ + + template + inline typename basic_ios::char_type + basic_ios::widen(char c) const + { + return c; + } + + template <> + inline basic_ios >::char_type + basic_ios >::widen(char c) const + { + return c; + } + +#ifdef __UCLIBCXX_HAS_WCHAR__ + + template <> + inline basic_ios >::char_type + basic_ios >::widen(char c) const + { + return btowc(c); + } + +#endif //__UCLIBCXX_HAS_WCHAR__ + + + template class _UCXXEXPORT fpos{ + public: + _UCXXEXPORT fpos(stateT s){ + st = s; + } + _UCXXEXPORT stateT state() const{ + return st; + } + _UCXXEXPORT void state(stateT s){ + st = s; + } + _UCXXEXPORT bool operator==(const fpos &rhs){ + return st == rhs.st; + } + _UCXXEXPORT bool operator!=(const fpos &rhs){ + return st == rhs.st; + } + _UCXXEXPORT fpos & operator+(const streamoff & o){ + st += o; + return *this; + } + _UCXXEXPORT fpos & operator-(const streamoff & o){ + st -= o; + return *this; + } + _UCXXEXPORT streamoff operator-(const fpos & rhs){ + return st - rhs.st; + } + + + private: + stateT st; + }; + + +} + +#pragma GCC visibility pop + +#endif + Index: branches/slice/rev749/modules/uClibc++/include/fstream =================================================================== --- branches/slice/rev749/modules/uClibc++/include/fstream (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/fstream (revision 1169) @@ -0,0 +1,678 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#if 0 +#ifndef __STD_HEADER_FSTREAM +#define __STD_HEADER_FSTREAM 1 + +//#if __UCLIBCXX_SUPPORT_FILEIO__ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef __UCLIBCXX_HAS_WCHAR__ +#include +#include +#endif //__UCLIBCXX_HAS_WCHAR__ + +#pragma GCC visibility push(default) + +namespace std{ + + template class basic_filebuf; + + typedef basic_filebuf filebuf; +#ifdef __UCLIBCXX_HAS_WCHAR__ + typedef basic_filebuf wfilebuf; +#endif + + + template class _UCXXEXPORT basic_filebuf + : public basic_streambuf + { +#ifdef __UCLIBCXX_SUPPORT_CDIR__ + friend ios_base::Init::Init(); //Needed for cout/cin stuff +#endif + public: + // Types (inherited from basic_streambuf: + typedef typename basic_streambuf::char_type char_type; + typedef typename basic_streambuf::int_type int_type; + typedef typename basic_streambuf::pos_type pos_type; + typedef typename basic_streambuf::off_type off_type; + typedef traits traits_type; + + //Constructors/destructor: + + _UCXXEXPORT basic_filebuf() : basic_streambuf(), fp(0), pbuffer(0), gbuffer(0) + { + append=false; + pbuffer = new char_type[__UCLIBCXX_IOSTREAM_BUFSIZE__]; + gbuffer = new char_type[__UCLIBCXX_IOSTREAM_BUFSIZE__]; + + setp(pbuffer, pbuffer + __UCLIBCXX_IOSTREAM_BUFSIZE__); + //Position get buffer so that there is no data available + setg(gbuffer, gbuffer + __UCLIBCXX_IOSTREAM_BUFSIZE__, + gbuffer + __UCLIBCXX_IOSTREAM_BUFSIZE__); + } + + + _UCXXEXPORT virtual ~basic_filebuf(){ + sync(); + close(); + delete [] pbuffer; + delete [] gbuffer; + pbuffer = 0; + gbuffer = 0; + } + + + //Members: + + _UCXXEXPORT bool is_open() const{ + if(fp == 0){ + return false; + } + return true; + } + + _UCXXEXPORT basic_filebuf* open(const char* s, ios_base::openmode mode){ + bool move_end = (mode & ios_base::ate) != 0; + if(is_open() !=false){ //Must call close() first + return 0; + } + basic_streambuf::openedFor = mode; + mode = mode & ~ios_base::ate; + + if(mode == ios_base::out || mode == (ios_base::out | ios_base::trunc)){ + fp = fopen(s, "w" ); + }else if((mode & ios_base::app) && ! (mode & ios_base::trunc)){ + if(mode & ios_base::binary){ + if(mode & ios_base::in){ + fp = fopen(s, "a+b"); + }else{ + fp = fopen(s, "ab"); + } + }else{ + if(mode & ios_base::in){ + fp = fopen(s, "a+"); + }else{ + fp = fopen(s, "a"); + } + } + }else if(mode == ios_base::in){ + fp = fopen(s, "r"); + }else if(mode == (ios_base::in | ios_base::out)){ + fp = fopen(s, "r+"); + }else if(mode == (ios_base::in | ios_base::out | ios_base::trunc)){ + fp = fopen(s, "w+"); + }else if(mode == (ios_base::binary | ios_base::out)){ + fp = fopen(s, "wb"); + }else if(mode == (ios_base::in | ios_base::binary)){ + fp = fopen(s, "rb"); + }else if(mode == (ios_base::in | ios_base::binary | ios_base::out)){ + fp = fopen(s, "r+b"); + }else if(mode==(ios_base::binary | ios_base::out | ios_base::trunc)){ + fp = fopen(s, "w+b"); + }else if(mode == (ios_base::in | ios_base::binary | ios_base::out | ios_base::trunc)){ + fp = fopen(s, "w+b"); + } + + if(fp == 0){ + return 0; + } + if(ferror(fp)){ + fclose(fp); + fp=0; + return 0; + } + int retval = 0; + + //Check to make sure the stream is good + if(move_end == true){ + retval = fseek(fp, 0, SEEK_END); + }else{ + retval = fseek(fp, 0, SEEK_SET); + } + if(retval!=0){ //Seek error + fclose(fp); + fp=0; + return 0; + } + + basic_streambuf::mgnext = basic_streambuf::mgend; + + return this; + } + _UCXXEXPORT basic_filebuf* close(){ + if(fp != 0 && fp != stdin && fp != stdout && fp !=stderr ){ + overflow(); + sync(); + int retval = fclose(fp); + if(retval !=0){ //Error of some sort + return 0; + } + fp=0; + } + return this; + } + protected: + _UCXXEXPORT basic_filebuf(const basic_filebuf &){ } + _UCXXEXPORT basic_filebuf & operator=(const basic_filebuf &){ return *this; } + + //Overridden virtual functions: + + virtual _UCXXEXPORT int showmanyc(){ + return basic_streambuf::egptr() - basic_streambuf::gptr(); + } + virtual _UCXXEXPORT int_type underflow(){ + /* Some variables used internally: + Buffer pointers: + charT * mgbeg; + charT * mgnext; + charT * mgend; + + eback() returns mgbeg + gptr() returns mgnext + egptr() returns mgend + + gbump(int n) mgnext+=n + + */ + + if(!is_open()){ + return traits::eof(); + } + + if(basic_streambuf::eback() == 0){ + //No buffer, so... + charT c; + int retval; + retval = fread(&c, sizeof(charT), 1, fp); + + if(retval == 0 || feof(fp) || ferror(fp) ){ + return traits::eof(); + } + return traits::to_int_type(c); + } + + if(basic_streambuf::eback() == basic_streambuf::gptr()){ //Buffer is full + return traits::to_int_type(*basic_streambuf::gptr()); + } + //Shift entire buffer back to the begining + size_t offset = basic_streambuf::gptr() - basic_streambuf::eback(); + size_t amountData = basic_streambuf::egptr() - basic_streambuf::gptr(); + + for(charT * i = basic_streambuf::gptr(); i < basic_streambuf::egptr(); ++i){ + *(i-offset) = *i; + } + + size_t retval = 0; + //Save operating flags from file descriptor + int fcntl_flags = fcntl(fileno(fp), F_GETFL); + retval = 0; + + //Set to non_blocking mode + fcntl(fileno(fp), F_SETFL, fcntl_flags | O_NONBLOCK); + + //Fill rest of buffer + retval = fread(basic_streambuf::egptr() - + basic_streambuf::gptr() + basic_streambuf::eback(), + sizeof(charT), + offset, + fp + ); + + //Clear problems where we didn't read in enough characters + if(EAGAIN == errno){ + clearerr(fp); + } + + //Restore file descriptor clase + fcntl(fileno(fp), F_SETFL, fcntl_flags); + + //Now we are going to make sure that we read in at least one character. The hard way. + if(retval == 0){ + fcntl_flags = fcntl(fileno(fp), F_GETFL); + //Set to blocking mode + fcntl(fileno(fp), F_SETFL, fcntl_flags & ~O_NONBLOCK); + + retval = fread(basic_streambuf::egptr() - + basic_streambuf::gptr() + basic_streambuf::eback(), + sizeof(charT), + 1, + fp + ); + + //Restore file descriptor clase + fcntl(fileno(fp), F_SETFL, fcntl_flags); + + } + + if(retval !=offset){ //Slide buffer forward again + for(size_t i = 0; i < amountData + retval; ++i){ + *(basic_streambuf::egptr() - i - 1) = + *(basic_streambuf::eback() + amountData + retval - i - 1); + } + } + + basic_streambuf::mgnext -= retval; + + if( (retval <= 0 && feof(fp)) || ferror(fp) ){ + return traits::eof(); + } + + return traits::to_int_type(*basic_streambuf::gptr()); + } + virtual _UCXXEXPORT int_type uflow(){ + bool dobump = (basic_streambuf::gptr() != 0); + int_type retval = underflow(); + if(dobump){ + basic_streambuf::gbump(1); + } + return retval; + } + virtual _UCXXEXPORT int_type pbackfail(int_type c = traits::eof()){ + if(is_open() == false || + basic_streambuf::gptr() == basic_streambuf::eback()) + { + return traits::eof(); + } + if(traits::eq_int_type(c,traits::eof()) == false){ + if(traits::eq(traits::to_char_type(c), basic_streambuf::gptr()[-1]) == true){ + basic_streambuf::gbump(-1); + }else{ + basic_streambuf::gbump(-1); + basic_streambuf::gptr()[0] = c; + } + return c; + }else{ + basic_streambuf::gbump(-1); + return traits::not_eof(c); + } + } + + virtual _UCXXEXPORT int_type overflow(int_type c = traits::eof()){ + if(is_open() == false){ + //Can't do much + return traits::eof(); + } + if(basic_streambuf::pbase() == 0){ //Unbuffered - elliminate dupe code below + if(fputc(c, fp) == EOF){ + return traits::eof(); + } + return c; + } + if(basic_streambuf::pbase() == 0 && traits::eq_int_type(c,traits::eof()) ){ + //Nothing to flush + return traits::not_eof(c); + } + size_t r = basic_streambuf::pptr() - basic_streambuf::pbase(); + + if( r == 0 && traits::eq_int_type(c,traits::eof()) ){ + return traits::not_eof(c); + }else if (r == 0 ){ + if(fputc(c, fp) == EOF){ + return traits::eof(); + } + return c; + } + + size_t totalChars = r; + + char_type *buffer = 0; + if(traits::eq_int_type(c,traits::eof())){ + buffer = new char_type[r]; + }else{ + buffer = new char_type[r+1]; + buffer[r] = c; + totalChars++; + } + + traits::copy(buffer, basic_streambuf::pbase(), r); +// memcpy(buffer, basic_streambuf::pbase(), r); + + size_t retval = fwrite(buffer, sizeof(charT), totalChars, fp); + if(retval !=totalChars){ + if(retval == 0){ + delete [] buffer; + return traits::eof(); + } + basic_streambuf::pbump(-retval); + fprintf(stderr, "***** Did not write the full buffer out. Should be: %d, actually: %d\n", + totalChars, retval); + }else{ + basic_streambuf::pbump(-r); + } + + delete [] buffer; + return traits::not_eof(c); + } + + virtual _UCXXEXPORT basic_streambuf* setbuf(char_type* s, streamsize n){ + if(s == 0 && n == 0){ //Unbuffered + if(pbuffer !=0){ + delete [] pbuffer; + } + if(gbuffer !=0){ + delete [] gbuffer; + } + pbuffer = 0; + gbuffer = 0; + }else if(basic_streambuf::gptr() !=0 && + basic_streambuf::gptr()==basic_streambuf::egptr()) + { + delete [] pbuffer; + pbuffer = s; + } + return this; + } + virtual _UCXXEXPORT pos_type seekoff(off_type off, ios_base::seekdir way, + ios_base::openmode = ios_base::in | ios_base::out) + { + if(is_open() == false){ + return -1; + } + int whence = SEEK_SET; // if(way == basic_ios::beg) + off_type position = off; + + if(way == basic_ios::cur){ + whence = SEEK_CUR; + position -= (basic_streambuf::egptr() - basic_streambuf::gptr()); + }else if(way == basic_ios::end){ + whence = SEEK_END; + } + + sync(); + + int retval = fseek( + fp, + sizeof(charT)*(position), + whence + ); + + //Invalidate read buffer + basic_streambuf::gbump( + basic_streambuf::egptr() - basic_streambuf::gptr() + ); + + if(-1 != retval){ + retval = ftell(fp); + } + + return retval; + } + virtual _UCXXEXPORT pos_type seekpos(pos_type sp, ios_base::openmode = ios_base::in | ios_base::out){ + if(is_open() == false){ + return -1; + } + sync(); + + int retval = fseek(fp,sizeof(charT)* sp, SEEK_SET); + + //Invalidate read buffer + basic_streambuf::gbump(basic_streambuf::egptr() - basic_streambuf::gptr()); + if(retval > -1){ + return sp; + } + return -1; + } + virtual _UCXXEXPORT int sync(){ + if(pbuffer !=0){ + if(overflow() == traits::eof()){ + return -1; + } + } + if(0 != fp && 0 != fflush(fp)){ + return -1; + } + return 0; + } + virtual _UCXXEXPORT void imbue(const locale&){ + return; + } + + + virtual _UCXXEXPORT streamsize xsputn(const char_type* s, streamsize n){ + if(is_open() == false){ + return 0; + } + //Check to see if buffered + + //Check to see if we can buffer the data + streamsize buffer_avail = basic_streambuf::epptr() - basic_streambuf::pptr(); + + if(n > buffer_avail){ //Flush buffer and write directly + overflow(); //Flush the buffer + return fwrite(s, sizeof(charT), n, fp); + } + + //Add to buffer to be written later + + traits::copy(basic_streambuf::pptr(), s, n); + basic_streambuf::pbump(n); + + return n; + } + + FILE * fp; + char_type * pbuffer; + char_type * gbuffer; + bool append; + }; + + +#ifdef __UCLIBCXX_HAS_WCHAR__ + +template <> _UCXXEXPORT basic_filebuf >::int_type + basic_filebuf >::overflow(int_type c); + +template <> _UCXXEXPORT basic_filebuf >::int_type + basic_filebuf >::underflow(); + +#endif //__UCLIBCXX_HAS_WCHAR__ + + + +#ifdef __UCLIBCXX_EXPAND_FSTREAM_CHAR__ +#ifndef __UCLIBCXX_COMPILE_FSTREAM__ + +#ifdef __UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ + + template <> _UCXXEXPORT filebuf::basic_filebuf(); + template <> _UCXXEXPORT filebuf::~basic_filebuf(); + +#endif // __UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ + + template <> _UCXXEXPORT filebuf::int_type filebuf::pbackfail(filebuf::int_type c); + template <> _UCXXEXPORT filebuf * filebuf::open(const char* s, ios_base::openmode mode); + template <> _UCXXEXPORT filebuf * filebuf::close(); + template <> _UCXXEXPORT filebuf::int_type filebuf::overflow(filebuf::int_type c); + template <> _UCXXEXPORT filebuf::int_type filebuf::underflow (); + + template <> _UCXXEXPORT basic_streambuf > * filebuf::setbuf(char * s, streamsize n); + template <> _UCXXEXPORT streamsize filebuf::xsputn(const char* s, streamsize n); + +#endif +#endif + + + template class _UCXXEXPORT basic_ifstream + : public basic_istream + { + public: + typedef charT char_type; + typedef typename traits::int_type int_type; + typedef typename traits::pos_type pos_type; + typedef typename traits::off_type off_type; + + _UCXXEXPORT basic_ifstream(): basic_ios(&sb), basic_istream(&sb){ + //Passing the address of sb + } + explicit _UCXXEXPORT basic_ifstream(const char* s, ios_base::openmode mode = ios_base::in) + : basic_ios(&sb), basic_istream(&sb) + { + if(sb.open(s, mode) == 0){ + basic_ios::setstate(ios_base::failbit); + } + } + + virtual _UCXXEXPORT ~basic_ifstream(){ + + } + + _UCXXEXPORT basic_filebuf* rdbuf() const{ + return (basic_filebuf*)&sb; + } + _UCXXEXPORT bool is_open() const{ + return sb.is_open(); + } + _UCXXEXPORT void open(const char* s, ios_base::openmode mode = ios_base::in){ + if(sb.open(s, mode) == 0){ + basic_ios::setstate(ios_base::failbit); + } + } + _UCXXEXPORT void close(){ + sb.close(); + } + private: + basic_filebuf sb; + }; + + + template class _UCXXEXPORT basic_ofstream + : public basic_ostream + { + public: + typedef charT char_type; + typedef typename traits::int_type int_type; + typedef typename traits::pos_type pos_type; + typedef typename traits::off_type off_type; + + _UCXXEXPORT basic_ofstream() : basic_ios(&sb), basic_ostream(&sb){ + + } + + virtual _UCXXEXPORT ~basic_ofstream(); + + explicit _UCXXEXPORT basic_ofstream(const char* s, ios_base::openmode mode = ios_base::out | ios_base::trunc) : + basic_ios(&sb), basic_ostream(&sb) + { + if(sb.open(s, mode) == 0){ + basic_ios::setstate(ios_base::failbit); + } + } + + _UCXXEXPORT basic_filebuf* rdbuf() const{ + return (basic_filebuf*)&sb; + } + + _UCXXEXPORT bool is_open() const{ + return sb.is_open(); + } + _UCXXEXPORT void open(const char* s, ios_base::openmode mode = ios_base::out | ios_base::trunc){ + if(sb.open(s, mode) == 0){ + basic_ios::setstate(ios_base::failbit); + } + } + _UCXXEXPORT void close(){ + sb.close(); + } + private: + basic_filebuf sb; + }; + + template _UCXXEXPORT basic_ofstream::~basic_ofstream(){ + basic_ostream::flush(); + } + + + template class _UCXXEXPORT basic_fstream + : public basic_iostream + { + public: + typedef charT char_type; + typedef typename traits::int_type ins_type; + typedef typename traits::pos_type pos_type; + typedef typename traits::off_type off_type; + + _UCXXEXPORT basic_fstream(): basic_ios(&sb), basic_iostream(&sb){ } + + explicit _UCXXEXPORT basic_fstream(const char* s, ios_base::openmode mode = ios_base::in|ios_base::out): + basic_ios(&sb), basic_iostream(&sb) + { + if(sb.open(s, mode) == 0){ + basic_ios::setstate(ios_base::failbit); + } + } + + _UCXXEXPORT basic_filebuf* rdbuf() const{ + return (basic_filebuf*)&sb; + } + _UCXXEXPORT bool is_open() const{ + return sb.is_open(); + } + _UCXXEXPORT void open(const char* s, ios_base::openmode mode = ios_base::in|ios_base::out){ + if(sb.open(s, mode) == 0){ + basic_ios::setstate(ios_base::failbit); + } + } + _UCXXEXPORT void close(){ + sb.close(); + } + private: + basic_filebuf sb; + }; + + + +#ifdef __UCLIBCXX_EXPAND_FSTREAM_CHAR__ +#ifndef __UCLIBCXX_COMPILE_FSTREAM__ + +#ifdef __UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ + + template <> _UCXXEXPORT basic_ofstream >::basic_ofstream(); + template <> _UCXXEXPORT basic_ofstream >::basic_ofstream(const char* s, ios_base::openmode mode); + template <> _UCXXEXPORT basic_ofstream >::~basic_ofstream(); + + template <> _UCXXEXPORT basic_ifstream >::basic_ifstream(); + template <> _UCXXEXPORT basic_ifstream >::basic_ifstream(const char* s, ios_base::openmode mode); + template <> _UCXXEXPORT basic_ifstream >::~basic_ifstream(); + +#endif // __UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ + +#endif +#endif + + + +} + +#pragma GCC visibility pop + +#endif + +#endif \ No newline at end of file Index: branches/slice/rev749/modules/uClibc++/include/ctime =================================================================== --- branches/slice/rev749/modules/uClibc++/include/ctime (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/ctime (revision 1169) @@ -0,0 +1,81 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 +// Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// +// ISO C++ 14882: 20.5 Date and time +// + +/** @file ctime + * This is a Standard C++ Library file. You should @c #include this file + * in your programs, rather than any of the "*.h" implementation files. + * + * This is the C++ version of the Standard C Library header @c time.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std. + */ + +#ifndef _CPP_CTIME +#define _CPP_CTIME 1 + +#pragma GCC system_header + +#include + +#include + +// Get rid of those macros defined in in lieu of real functions. +#undef clock +#undef difftime +#undef mktime +#undef time +#undef asctime +#undef ctime +#undef gmtime +#undef localtime +#undef strftime + +namespace std +{ + using ::clock_t; + using ::time_t; + using ::tm; + + using ::clock; + using ::difftime; + using ::mktime; + using ::time; + using ::asctime; + using ::ctime; + using ::gmtime; + using ::localtime; + using ::strftime; +} + +#endif Index: branches/slice/rev749/modules/uClibc++/include/clocale =================================================================== --- branches/slice/rev749/modules/uClibc++/include/clocale (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/clocale (revision 1169) @@ -0,0 +1,30 @@ +/* Copyright (C) 2005 Garrett A. Kajmowicz + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __STD_HEADER_CLOCALE +#define __STD_HEADER_CLOCALE 1 + +#include + +namespace std { + using ::lconv; + using ::setlocale; + using ::localeconv; +} + +#endif // __STD_HEADER_CLOCALE Index: branches/slice/rev749/modules/uClibc++/include/char_traits =================================================================== --- branches/slice/rev749/modules/uClibc++/include/char_traits (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/char_traits (revision 1169) @@ -0,0 +1,198 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include + +#ifdef __UCLIBCXX_HAS_WCHAR__ +#include +#include +#endif + +#ifndef __HEADER_CHAR_TRAITS +#define __HEADER_CHAR_TRAITS 1 + +namespace std{ + /* Inlining all wrapped function calls to shrink the amount of code generated*/ + //Typedefs to use for stuff + typedef signed int char_traits_off_type; + + //Generic char_traits + template struct _UCXXEXPORT char_traits { }; + + //Specialize for char + template<> struct _UCXXEXPORT char_traits { + typedef char char_type; + typedef short int int_type; + typedef char_traits_off_type off_type; + typedef char_traits_off_type pos_type; + typedef char state_type; + + inline static void assign(char_type & c, const char_type & d) { c = d; } + + static bool eq(const char_type& c1, const char_type& c2); + + static char_type to_char_type(const int_type & i); + + inline static int_type to_int_type(const char_type & c){ + return (short int)(unsigned char)c; + } + + inline static bool eq_int_type(const int_type & a, const int_type & b){ + if(a==b){ + return true; + } + return false; + } + + + inline static bool lt(const char_type& c1, const char_type& c2){ + if(strncmp(&c1, &c2, 1) < 0){ + return true; + } + return false; + } + + inline static char_type* move(char_type* s1, const char_type* s2, size_t n){ + return (char*) memmove(s1, s2, n); + } + + inline static char_type* copy(char_type* s1, const char_type* s2, size_t n){ + for(unsigned long int i=0; i< n; ++i){ + assign(s1[i], s2[i]); + } + return s1 + n; + } + + inline static char_type* assign(char_type* s, size_t n, char_type a){ + return (char *)memset(s, a, n); + } + + inline static int compare(const char_type* s1, const char_type* s2, size_t n){ + return strncmp(s1, s2, n); + } + + inline static size_t length(const char_type* s){ + return strlen(s); + } + + static const char_type* find(const char_type* s, int n, const char_type& a); + + inline static char_type eos() { return 0; } + inline static int_type eof() { return -1; } + inline static int_type not_eof(const int_type & i) { + if(i == -1){ + return 0; + } else { + return i; + } + } + static state_type get_state(pos_type p){ + p = p; + state_type a; + return a; + } + }; + + +#ifdef __UCLIBCXX_HAS_WCHAR__ + template<> struct _UCXXEXPORT char_traits { + typedef wchar_t char_type; + typedef wint_t int_type; + typedef char_traits_off_type off_type; + typedef char_traits_off_type pos_type; + typedef mbstate_t state_type; + + static void assign(char_type & c, const char_type & d){ c=d; } + + static char_type to_char_type(const int_type & i){ + return i; + } + + static int_type to_int_type(const char_type & c){ + return c; + } + + inline static bool eq_int_type(const int_type & a, const int_type & b){ + if(a==b){ + return true; + } + return false; + } + + inline static bool eq(const char_type& c1, const char_type& c2){ + if(wcsncmp(&c1, &c2, 1) == 0){ + return true; + } + return false; + } + + inline static bool lt(const char_type& c1, const char_type& c2){ + if(wcsncmp(&c1, &c2, 1) < 0){ + return true; + } + return false; + } + + inline static char_type* move(char_type* s1, const char_type* s2, size_t n){ + return (char_type*) memmove(s1, s2, n * sizeof(char_type)); + } + + inline static char_type* copy(char_type* s1, const char_type* s2, size_t n){ + for(unsigned long int i=0; i< n; ++i){ + assign(s1[i], s2[i]); + } + return s1 + n; + } + + inline static char_type* assign(char_type* s, size_t n, char_type a){ + return (char_type *)memset(s, a, n); /*FIXME*/ + } + + inline static int compare(const char_type* s1, const char_type* s2, size_t n){ + return wcsncmp(s1, s2, n); + } + + inline static size_t length(const char_type* s){ + return wcslen(s); + } + + static const char_type* find(const char_type* s, int n, const char_type& a); + + inline static char_type eos() { return 0; } + inline static int_type eof() { return WEOF; } + inline static int_type not_eof(const int_type & i) { + if(i == WEOF){ + return (int_type)0; + } else { + return i; + } + } + static state_type get_state(pos_type){ + state_type a; + return a; + } + }; +#endif + +} + +#endif + Index: branches/slice/rev749/modules/uClibc++/include/associative_base =================================================================== --- branches/slice/rev749/modules/uClibc++/include/associative_base (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/associative_base (revision 1169) @@ -0,0 +1,643 @@ +/* Copyright (C) 2007 Garrett A. Kajmowicz + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + + +#include +#include +#include +#include +#include + + +#ifndef __STD_HEADER_ASSOCIATIVE_BASE +#define __STD_HEADER_ASSOCIATIVE_BASE + +#pragma GCC visibility push(default) + +namespace std{ + + +/* + * The basic premis here is that most of the code used by map, multimap, set and + * multiset is really common. There are a number of interface additions, and + * considerations about how to address multiple enteries with the same key. + * The goal is that the code tree/storage code should be here, and managing + * single or moultiple counts will be loeft to subclasses. + * Yes, inheritence for the purpose of code sharing is usually a bad idea. However, + * since our goal is to reduce tht total amount of code written and the overall binary + * size, this seems to be the best approach possible. + */ + +template, class Allocator = allocator > class __base_associative; +template class _associative_iter; +template class _associative_citer; + +template, class Allocator = allocator > class __single_associative; +template, class Allocator = allocator > class __multi_associative; + +template class _UCXXEXPORT __base_associative{ + +protected: + +public: + typedef Key key_type; + typedef ValueType value_type; + typedef Compare key_compare; + typedef Allocator allocator_type; + typedef typename Allocator::reference reference; + typedef typename Allocator::const_reference const_reference; + typedef typename Allocator::size_type size_type; + typedef typename Allocator::difference_type difference_type; + typedef typename Allocator::pointer pointer; + typedef typename Allocator::const_pointer const_pointer; + typedef __base_associative associative_type; + + typedef _associative_iter iterator; + typedef _associative_citer const_iterator; + typedef typename std::reverse_iterator reverse_iterator; + typedef typename std::reverse_iterator const_reverse_iterator; + + + explicit __base_associative(const Compare& comp, const Allocator& A, const key_type (*v_to_k)(const value_type)) + : c(comp), value_to_key(v_to_k) { } +protected: + __base_associative(const associative_type& x) + : c(x.c), backing(x.backing), value_to_key(x.value_to_key) { } + +public: + ~__base_associative(){ + } + + bool empty() const{ + return backing.empty(); + } + size_type size() const{ + return backing.size(); + } + size_type max_size() const{ + return backing.max_size(); + } + + iterator begin(){ + return iterator(backing.begin()); + } + + const_iterator begin() const{ + return const_iterator(backing.begin()); + } + + iterator end() { + return iterator(backing.end()); + } + + const_iterator end() const{ + return const_iterator(backing.end()); + } + + reverse_iterator rbegin(){ + return reverse_iterator(end()); + } + + const_reverse_iterator rbegin() const{ + return const_reverse_iterator(end()); + } + + reverse_iterator rend(){ + return reverse_iterator(begin()); + } + + const_reverse_iterator rend() const{ + return const_reverse_iterator(begin()); + } + + + iterator lower_bound(const key_type &x); + const_iterator lower_bound(const key_type &x) const; + iterator upper_bound(const key_type &x); + const_iterator upper_bound(const key_type &x) const; + + pair equal_range(const key_type& x){ + pair retval; + retval.first = lower_bound(x); + retval.second = retval.first; + while(retval.second != end() && !c(x, value_to_key(*retval.second))){ + ++retval.second; + } + return retval; + } + pair equal_range(const key_type& x) const{ + pair retval; + retval.first = lower_bound(x); + retval.second = retval.first; + while(retval.second != end() && !c(x, value_to_key(*retval.second))){ + ++retval.second; + } + return retval; + } + + iterator find(const key_type& x){ + iterator retval = lower_bound(x); + if(retval == end()){ + return retval; + } + if(c(x, value_to_key(*retval))){ + return end(); + } + return retval; + } + const_iterator find(const key_type& x) const{ + const_iterator retval = lower_bound(x); + if(retval == end()){ + return retval; + } + if(c(x, value_to_key(*retval))){ + return end(); + } + return retval; + } + size_type count(const key_type& x) const{ + size_type retval(0); + const_iterator first = lower_bound(x); + while(first != end() && !c(x, value_to_key(*first))){ + ++retval; + ++first; + } + return retval; + } + + void clear(){ + backing.clear(); + } + + void erase(iterator pos){ + backing.erase(pos.base_iterator()); + } + size_type erase(const key_type& x){ + size_type count(0); + iterator start = lower_bound(x); + iterator end = upper_bound(x); + while(start != end){ + start = backing.erase(start.base_iterator()); + ++count; + } + return count; + } + void erase(iterator first, iterator last){ + while(first != last){ + backing.erase(first.base_iterator()); + ++first; + } + } + + key_compare key_comp() const{ + return c; + } + + __base_associative &operator=(const __base_associative & x){ + c = x.c; + backing = x.backing; + value_to_key = x.value_to_key; + return *this; + } + bool operator==(const __base_associative & x){ + return x.backing == backing; + } + bool operator!=(const __base_associative & x){ + return !(x.backing == backing); + } + +protected: + void swap(__base_associative & x); + + Compare c; + std::list backing; + + const key_type (*value_to_key)(const value_type); + +}; + + +/* + * Tree interators for the base associative class + */ + +template class _associative_citer + : public std::iterator< + bidirectional_iterator_tag, + ValueType, + typename Allocator::difference_type, + ValueType*, + ValueType& + > +{ +protected: + typedef std::list listtype; + + typename listtype::const_iterator base_iter; + friend class _associative_iter; +public: + _associative_citer() { } + _associative_citer(const _associative_citer & m) + : base_iter(m.base_iter) { } + _associative_citer(const typename listtype::const_iterator & m) + : base_iter(m) { } + ~_associative_citer() { } + ValueType operator*() const{ + return *base_iter; + } + const ValueType * operator->() const{ + return &(*base_iter); + } + _associative_citer & operator=(const _associative_citer & m){ + base_iter = m.base_iter; + return *this; + } + bool operator==(const _associative_citer & m) const{ + return m.base_iter == base_iter; + } + bool operator!=(const _associative_citer & m) const{ + return m.base_iter != base_iter; + } + _associative_citer & operator++(){ + ++base_iter; + return *this; + } + _associative_citer operator++(int){ + //The following approach ensures that we only need to + //provide code for ++ in one place (above) + _associative_citer temp(base_iter); + ++base_iter; + return temp; + } + _associative_citer & operator--(){ + --base_iter; + return *this; + } + _associative_citer operator--(int){ + //The following approach ensures that we only need to + //provide code for -- in one place (above) + _associative_citer temp(base_iter); + --base_iter; + return temp; + } + + //This is an implementation-defined function designed to make internals work correctly + typename listtype::const_iterator base_iterator(){ + return base_iter; + } + +}; + + +template class _associative_iter + : public std::iterator< + bidirectional_iterator_tag, + ValueType, + typename Allocator::difference_type, + ValueType*, + ValueType& + > +{ +protected: + typedef std::list listtype; + + typename listtype::iterator base_iter; + typedef _associative_citer _associative_citer; + + +public: + _associative_iter() { } + _associative_iter(const _associative_iter & m) + : base_iter(m.base_iter) { } + _associative_iter(const typename listtype::iterator & m) + : base_iter(m) { } + ~_associative_iter() { } + const ValueType & operator*() const{ + return *base_iter; + } + ValueType & operator*(){ + return *base_iter; + } + ValueType * operator->(){ + return &(*base_iter); + } + const ValueType * operator->() const{ + return &(*base_iter); + } + _associative_iter & operator=(const _associative_iter & m){ + base_iter = m.base_iter; + return *this; + } + bool operator==(const _associative_iter & m) const{ + return m.base_iter == base_iter; + } + bool operator==(const _associative_citer & m) const{ + return m.base_iter == base_iter; + } + bool operator!=(const _associative_iter & m) const{ + return m.base_iter != base_iter; + } + bool operator!=(const _associative_citer & m) const{ + return m.base_iter != base_iter; + } + _associative_iter & operator++(){ + ++base_iter; + return *this; + } + _associative_iter operator++(int){ + //The following approach ensures that we only need to + //provide code for ++ in one place (above) + _associative_iter temp(base_iter); + ++base_iter; + return temp; + } + _associative_iter & operator--(){ + --base_iter; + return *this; + } + _associative_iter operator--(int){ + //The following approach ensures that we only need to + //provide code for -- in one place (above) + _associative_iter temp(base_iter); + --base_iter; + return temp; + } + operator _associative_citer() const{ + return _associative_citer(base_iter); + } + typename listtype::iterator base_iterator(){ + return base_iter; + } + const typename listtype::iterator base_iterator() const{ + return base_iter; + } + +}; + + + // The lower_bound code is really crappy linear search. However, it is a dead + // simple implimentation (easy to audit). It can also be easily replaced. + + + template + typename __base_associative::iterator + __base_associative::lower_bound(const key_type &x) + { + iterator retval = begin(); + while(retval != end() && c(value_to_key(*retval), x)){ + ++retval; + } + return retval; + } + + template + typename __base_associative::const_iterator + __base_associative::lower_bound(const key_type &x) const + { + const_iterator retval = begin(); + while(retval != end() && c(value_to_key(*retval), x)){ + ++retval; + } + return retval; + } + + // Upper bound search is linear from the point of lower_bound. This is likely the best solution + // in all but the most pathalogical of cases. + + template + typename __base_associative::iterator + __base_associative::upper_bound(const key_type &x) + { + iterator retval = lower_bound(x); + while(retval != end() && !c(x, value_to_key(*retval))){ + ++retval; + } + return retval; + } + + template + typename __base_associative::const_iterator + __base_associative::upper_bound(const key_type &x) const + { + const_iterator retval = begin(); + while(retval != end() && !c(x, value_to_key(*retval))){ + ++retval; + } + return retval; + } + + + template + void __base_associative::swap(__base_associative& m) + { + Compare n = c; + c = m.c; + m.c = n; + + m.backing.swap(backing); + } + + +template class _UCXXEXPORT __single_associative : + public __base_associative +{ +protected: + typedef __base_associative base; + using base::backing; + + using base::c; + +public: + typedef typename base::key_type key_type; + typedef typename base::value_type value_type; + typedef typename base::key_compare key_compare; + typedef typename base::allocator_type allocator_type; + typedef typename base::reference reference; + typedef typename base::const_reference const_reference; + typedef typename base::iterator iterator; + typedef typename base::const_iterator const_iterator; + typedef typename base::size_type size_type; + typedef typename base::difference_type difference_type; + typedef typename base::pointer pointer; + typedef typename base::const_pointer const_pointer; + typedef typename base::reverse_iterator reverse_iterator; + typedef typename base::const_reverse_iterator const_reverse_iterator; + + using base::begin; + using base::end; + using base::rbegin; + using base::rend; + + using base::empty; + using base::size; + using base::max_size; + + using base::find; + using base::count; + using base::lower_bound; + using base::upper_bound; + using base::equal_range; + + using base::operator=; + using base::operator==; + using base::operator!=; + + explicit __single_associative(const Compare& comp, const Allocator& A, const key_type (*v_to_k)(const value_type)) + : base(comp, A, v_to_k) { } + + template __single_associative( + InputIterator first, + InputIterator last, + const Compare& comp, + const Allocator& A, + const key_type (*v_to_k)(const value_type) + ) : base(comp, A, v_to_k) { + insert(first, last); + } + + pair insert(const value_type& x){ + pair retval; + iterator location = lower_bound(value_to_key(x)); + retval.second = true; + //Empty list or need to insert at end + if(end() == location){ + backing.push_back(x); + retval.first = --(end()); + return retval; + } + //Something in the list + if(c(value_to_key(x), value_to_key(*location))){ + location = backing.insert(location.base_iterator(), x); + retval.first = location; + }else{ + retval.second = false; + retval.first = location; + } + return retval; + } + + iterator insert(iterator position, const value_type& x){ + // FIXME - this is cheeting and probably should be more efficient since we are + // now log(n) to find for inserts + return insert(x).first; + } + + template void insert(InputIterator first, InputIterator last){ + while(first != last){ + insert(*first); + ++first; + } + } + +}; + + +template class _UCXXEXPORT __multi_associative : + public __base_associative +{ +protected: + typedef __base_associative base; + using base::backing; + + using base::c; + +public: + typedef typename base::key_type key_type; + typedef typename base::value_type value_type; + typedef typename base::key_compare key_compare; + typedef typename base::allocator_type allocator_type; + typedef typename base::reference reference; + typedef typename base::const_reference const_reference; + typedef typename base::iterator iterator; + typedef typename base::const_iterator const_iterator; + typedef typename base::size_type size_type; + typedef typename base::difference_type difference_type; + typedef typename base::pointer pointer; + typedef typename base::const_pointer const_pointer; + typedef typename base::reverse_iterator reverse_iterator; + typedef typename base::const_reverse_iterator const_reverse_iterator; + + using base::begin; + using base::end; + using base::rbegin; + using base::rend; + + using base::empty; + using base::size; + using base::max_size; + + using base::find; + using base::count; + using base::lower_bound; + using base::upper_bound; + using base::equal_range; + + using base::operator=; + using base::operator==; + + + explicit __multi_associative(const Compare& comp, const Allocator& A, const key_type (*v_to_k)(const value_type)) + : base(comp, A, v_to_k) { } + + template __multi_associative( + InputIterator first, + InputIterator last, + const Compare& comp, + const Allocator& A, + const key_type (*v_to_k)(const value_type) + ) : base(comp, A, v_to_k) { + insert(first, last); + } + + iterator insert(const value_type& x){ + iterator location = lower_bound(value_to_key(x)); + + if(location == begin()){ + backing.push_front(x); + location = begin(); + }else{ + location = backing.insert(location.base_iterator(), x); + } + return location; + } + + iterator insert(iterator position, const value_type& x){ + // FIXME - this is cheeting and probably should be more efficient since we are + // now log(n) to find for inserts + return insert(x); + } + + template void insert(InputIterator first, InputIterator last){ + while(first != last){ + insert(*first); + ++first; + } + } +}; + + + + +} + +#pragma GCC visibility pop + +#endif //__STD_HEADER_ASSOCIATIVE_BASE + + Index: branches/slice/rev749/modules/uClibc++/include/cassert =================================================================== --- branches/slice/rev749/modules/uClibc++/include/cassert (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/cassert (revision 1169) @@ -0,0 +1,19 @@ +/* Copyright (C) 2005 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include Index: branches/slice/rev749/modules/uClibc++/include/func_exception =================================================================== --- branches/slice/rev749/modules/uClibc++/include/func_exception (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/func_exception (revision 1169) @@ -0,0 +1,41 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include + + +#ifndef HEADER_IMPLEMENTATION_FUNC_EXCEPTION +#define HEADER_IMPLEMENTATION_FUNC_EXCEPTION + +#pragma GCC visibility push(default) + +namespace std{ + + _UCXXEXPORT void __throw_bad_alloc(); + _UCXXEXPORT void __throw_out_of_range(const char * message = 0); + _UCXXEXPORT void __throw_overflow_error(const char * message = 0); + _UCXXEXPORT void __throw_length_error(const char * message = 0); + _UCXXEXPORT void __throw_invalid_argument(const char * message = 0); +} + +#pragma GCC visibility pop + +#endif + Index: branches/slice/rev749/modules/uClibc++/include/string_iostream =================================================================== --- branches/slice/rev749/modules/uClibc++/include/string_iostream (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/string_iostream (revision 1169) @@ -0,0 +1,146 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include + +#ifdef __UCLIBCXX_HAS_WCHAR__ +#include +#include +#endif + +#ifndef __HEADER_STD_STRING_IOSTREAM +#define __HEADER_STD_STRING_IOSTREAM 1 + +#pragma GCC visibility push(default) + +namespace std{ + + + +template _UCXXEXPORT basic_ostream& + operator<<(basic_ostream& os, const basic_string& str) +{ + return os.write(str.data(), str.length()); +} + +template _UCXXEXPORT basic_istream& + operator>>(basic_istream& is, basic_string& str) +{ + + typename basic_istream::sentry s(is); + if(s == false){ + return is; + } + + str.clear(); + + typename basic_istream::int_type c; + typename Allocator::size_type n = is.width(); + bool exitnow = false; + if(n == 0){ + n = str.max_size(); + } + +// //Clear out preliminary spaces first +// c = is.get(); +// while(isspace(c)){ +// c = is.get(); +// } +// +// is.putback(c); + + do{ + c = is.get(); + if(c == traits::eof() || isspace(c) || n == 0){ + is.putback(c); + exitnow = true; + }else{ + str.append(1, traits::to_char_type(c) ); + --n; + } + }while(exitnow == false); + return is; +} + +template _UCXXEXPORT basic_istream& + getline(basic_istream& is, basic_string& str, charT delim) +{ + typename basic_istream::sentry s(is); + if(s == false){ + return is; + } + + str.erase(); + + streamsize i = 0; + typename basic_istream::int_type c_i; + charT c; + unsigned int n = str.max_size(); + for(i=0;i _UCXXEXPORT basic_istream& + getline(basic_istream& is, basic_string& str) +{ + return getline(is, str, '\n'); +} + + +#ifdef __UCLIBCXX_EXPAND_STRING_CHAR__ +#ifndef __UCLIBCXX_COMPILE_STRING__ + + +#ifdef __UCLIBCXX_EXPAND_ISTREAM_CHAR__ +template<> _UCXXEXPORT basic_istream >& operator>>( + basic_istream >& is, + basic_string, allocator >& str); +#endif + + +#ifdef __UCLIBCXX_EXPAND_OSTREAM_CHAR__ +template<> _UCXXEXPORT basic_ostream >& + operator<<(basic_ostream >& os, + const basic_string, std::allocator >& str); + +#endif + + +#endif +#endif + + +} + +#pragma GCC visibility pop + +#endif + Index: branches/slice/rev749/modules/uClibc++/include/support =================================================================== --- branches/slice/rev749/modules/uClibc++/include/support (revision 0) +++ branches/slice/rev749/modules/uClibc++/include/support (revision 1169) @@ -0,0 +1,167 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include + +#ifndef HEADER_ULC_SUPPORT +#define HEADER_ULC_SUPPORT 1 + +using namespace std; + +//From C++ ABI spec +typedef enum { + _URC_NO_REASON = 0, + _URC_FOREIGN_EXCEPTION_CAUGHT = 1, + _URC_FATAL_PHASE2_ERROR = 2, + _URC_FATAL_PHASE1_ERROR = 3, + _URC_NORMAL_STOP = 4, + _URC_END_OF_STACK = 5, + _URC_HANDLER_FOUND = 6, + _URC_INSTALL_CONTEXT = 7, + _URC_CONTINUE_UNWIND = 8 +} _Unwind_Reason_Code; + + +typedef void (*_Unwind_Exception_Cleanup_Fn) + (_Unwind_Reason_Code reason, struct _Unwind_Exception *exc); + +//The following definitions were grabbed from the gcc implementation +typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__))); +typedef unsigned _Unwind_Word __attribute__((__mode__(__word__))); +typedef signed _Unwind_Sword __attribute__((__mode__(__word__))); +typedef unsigned _Unwind_Exception_Class __attribute__((__mode__(__DI__))); +typedef void (*_Unwind_Exception_Cleanup_Fn) (_Unwind_Reason_Code, struct _Unwind_Exception *); + +typedef int _Unwind_Action; +static const _Unwind_Action _UA_SEARCH_PHASE = 1; +static const _Unwind_Action _UA_CLEANUP_PHASE = 2; +static const _Unwind_Action _UA_HANDLER_FRAME = 4; +static const _Unwind_Action _UA_FORCE_UNWIND = 8; + +const _Unwind_Exception_Class __uclibcxx_exception_class = (((((((( + _Unwind_Exception_Class) 'u' << 8 | (_Unwind_Exception_Class) 'l') << 8 + | (_Unwind_Exception_Class) 'i') << 8 | (_Unwind_Exception_Class) 'b') << 8 + | (_Unwind_Exception_Class) 'C')<< 8 | (_Unwind_Exception_Class) '+') << 8 + | (_Unwind_Exception_Class) '+') << 8 | (_Unwind_Exception_Class) '\0'); + + +#define _UA_SEARCH_PHASE 1 +#define _UA_CLEANUP_PHASE 2 +#define _UA_HANDLER_FRAME 4 +#define _UA_FORCE_UNWIND 8 +#define _UA_END_OF_STACK 16 + +struct _Unwind_Exception{ + _Unwind_Exception_Class exception_class; //Type of exception, eg ulibC++\0 + _Unwind_Exception_Cleanup_Fn exception_cleanup; //Destructor if from diff runtime + _Unwind_Word private_1; //Don't touch at all! + _Unwind_Word private_2; //Don't touch at all! +} __attribute__((__aligned__)); + + +//The following structure is system-dependent and defined by the compiler +//Thus it's definition was copied from the gcc 3.4.0 header files +struct _Unwind_Context; +//{ +// void *reg[DWARF_FRAME_REGISTERS+1]; +// void *cfa; +// void *ra; +// void *lsda; +// struct dwarf_eh_bases bases; +// _Unwind_Word args_size; +//}; + + + +_Unwind_Reason_Code _Unwind_RaiseException ( struct _Unwind_Exception *exception_object ); + +//_Unwind_ForcedUnwind + +typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn) + (int version, _Unwind_Action actions, _Unwind_Exception_Class exceptionClass, + struct _Unwind_Exception *exceptionObject, + struct _Unwind_Context *context, void *stop_parameter ); + +_Unwind_Reason_Code _Unwind_ForcedUnwind ( + struct _Unwind_Exception *exception_object, _Unwind_Stop_Fn stop, + void *stop_parameter ); + +void _Unwind_Resume (struct _Unwind_Exception *exception_object); +void _Unwind_DeleteException (struct _Unwind_Exception *exception_object); + +_Unwind_Word _Unwind_GetGR (struct _Unwind_Context *context, int index); +void _Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word); + +_Unwind_Ptr _Unwind_GetIP (struct _Unwind_Context *context); +void _Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr new_value); + +_Unwind_Ptr _Unwind_GetLanguageSpecificData (struct _Unwind_Context *context); +_Unwind_Ptr _Unwind_GetRegionStart (struct _Unwind_Context *context); + +_Unwind_Reason_Code (*__personality_routine) + (int version, //Should be 1 + _Unwind_Action actions, //Actions the routine will perform (bitmask) + _Unwind_Exception_Class exceptionClass, //Type of exception - vendor is high 4 bytes + struct _Unwind_Exception *exceptionObject, //Points to exception header + struct _Unwind_Context *context); //Unwinder state information + + +/*The following part is the Level II ABI which is required for compatability*/ +//This might be the only stuff that *I* need to implement + +struct __cxa_exception { + std::type_info *exceptionType; //Type of thrown exception + void (*exceptionDestructor) (void *); //Pointer to the destructor + unexpected_handler unexpectedHandler; //Unexpected handler to use + terminate_handler terminateHandler; //Terminate handle to use + __cxa_exception *nextException; //per thread linked list + + int handlerCount; //How many handlers have caught this + int handlerSwitchValue; + const char *actionRecord; + const char *languageSpecificData; + void *catchTemp; + void *adjustedPtr; + + _Unwind_Exception unwindHeader; +}; + +struct __cxa_eh_globals { + __cxa_exception *caughtExceptions; + unsigned int uncaughtExceptions; +}; + +extern "C" __cxa_eh_globals *__cxa_get_globals(void); //Return ptr to the eh_globals object for current thread +extern "C" __cxa_eh_globals *__cxa_get_globals_fast(void); //Same as above, assumes that above called at least once + +extern "C" void *__cxa_allocate_exception(size_t thrown_size); //Allocate space for exception plus header +extern "C" void __cxa_free_exception(void *thrown_exception); //Free space allocated from the above + +extern "C" void __cxa_throw (void *thrown_exception, //This is the actual throw call +// std::type_info *tinfo, //Type of object + void * tinfo, //Type of object + void (*dest) (void *) ); //Pointer to destructor destroy object + + +#endif + + + Index: branches/slice/rev749/modules/uClibc++/char_traits.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/char_traits.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/char_traits.cpp (revision 1169) @@ -0,0 +1,69 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#define __UCLIBCXX_COMPILE_CHAR_TRAITS__ 1 + + +#include +#include + +namespace std{ + +_UCXXEXPORT const char_traits::char_type* char_traits::find(const char_type* s, int n, const char_type& a){ + for(int i=0; i < n; i++){ + if(eq(s[i], a)){ + return (s+i); + } + } + return 0; +} + +_UCXXEXPORT bool char_traits::eq(const char_type& c1, const char_type& c2){ + if(strncmp(&c1, &c2, 1) == 0){ + return true; + } + return false; +} + +_UCXXEXPORT char_traits::char_type char_traits::to_char_type(const int_type & i){ + if(i > 0 && i <= 255){ + return (char)(unsigned char)i; + } + + //Out of range + return 0; +} + + + +#ifdef __UCLIBCXX_HAS_WCHAR__ + +_UCXXEXPORT const char_traits::char_type* char_traits::find(const char_type* s, int n, const char_type& a){ + for(int i=0; i < n; i++){ + if(eq(s[i], a)){ + return (s+i); + } + } + return 0; +} + +#endif + +} Index: branches/slice/rev749/modules/uClibc++/del_opnt.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/del_opnt.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/del_opnt.cpp (revision 1169) @@ -0,0 +1,28 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include + +#ifndef NO_NOTHROW +_UCXXEXPORT void operator delete(void* ptr, const std::nothrow_t& ) throw() { + free(ptr); +} +#endif Index: branches/slice/rev749/modules/uClibc++/associative_base.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/associative_base.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/associative_base.cpp (revision 1169) @@ -0,0 +1,26 @@ +/* Copyright (C) 2007 Garrett A. Kajmowicz + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include + +namespace std{ + + + +} Index: branches/slice/rev749/modules/uClibc++/istream.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/istream.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/istream.cpp (revision 1169) @@ -0,0 +1,75 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#define __UCLIBCXX_COMPILE_ISTREAM__ 1 + +#include + + +namespace std{ + +#ifdef __UCLIBCXX_EXPAND_ISTREAM_CHAR__ + + template <> _UCXXEXPORT string _readToken >(istream & stream) + { + string temp; + char_traits::int_type c; + while(true){ + c = stream.rdbuf()->sgetc(); + if(c != char_traits::eof() && isspace(c) == false){ + stream.rdbuf()->sbumpc(); + temp.append(1, char_traits::to_char_type(c)); + }else{ + break; + } + } + if (temp.size() == 0) + stream.setstate(ios_base::eofbit|ios_base::failbit); + + return temp; + } + + template _UCXXEXPORT istream::int_type istream::get(); + template _UCXXEXPORT istream & istream::get(char &c); + + template _UCXXEXPORT istream & istream::operator>>(bool &n); + template _UCXXEXPORT istream & istream::operator>>(short &n); + template _UCXXEXPORT istream & istream::operator>>(unsigned short &n); + template _UCXXEXPORT istream & istream::operator>>(int &n); + template _UCXXEXPORT istream & istream::operator>>(unsigned int &n); + template _UCXXEXPORT istream & istream::operator>>(long unsigned &n); + template _UCXXEXPORT istream & istream::operator>>(long int &n); + template _UCXXEXPORT istream & istream::operator>>(void *& p); + template _UCXXEXPORT istream & operator>>(istream & is, char & c); + + +#ifdef __UCLIBCXX_HAS_FLOATS__ + template _UCXXEXPORT istream & istream::operator>>(float &f); + template _UCXXEXPORT istream & istream::operator>>(double &f); + template _UCXXEXPORT istream & istream::operator>>(long double &f); +#endif + + template _UCXXEXPORT void __skipws(basic_istream >& is); + +#endif + + +} + Index: branches/slice/rev749/modules/uClibc++/stack.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/stack.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/stack.cpp (revision 1169) @@ -0,0 +1,27 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include + + +namespace std{ + + + + +} Index: branches/slice/rev749/modules/uClibc++/string.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/string.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/string.cpp (revision 1169) @@ -0,0 +1,112 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#define __UCLIBCXX_COMPILE_STRING__ 1 + +#include +#include +#include +#include +#include +#include + +namespace std{ + +#ifdef __UCLIBCXX_EXPAND_STRING_CHAR__ + +#ifdef __UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ + + template _UCXXEXPORT string::basic_string(const allocator &); + template _UCXXEXPORT string::basic_string(size_type n, char c, const allocator & ); + template _UCXXEXPORT string::basic_string(const char* s, const allocator& al); + template _UCXXEXPORT string::basic_string(const basic_string& str, size_type pos, size_type n, const allocator& al); + template _UCXXEXPORT string::~basic_string(); + +#endif // __UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ + + template _UCXXEXPORT string & string::append(const char * s, size_type n); + + template _UCXXEXPORT string::size_type string::find(const string & str, size_type pos) const; + template _UCXXEXPORT string::size_type string::find(const char* s, size_type pos) const; + template _UCXXEXPORT string::size_type string::find (char c, size_type pos) const; + template _UCXXEXPORT string::size_type string::rfind(const string & str, size_type pos) const; + template _UCXXEXPORT string::size_type string::rfind(char c, size_type pos) const; + template _UCXXEXPORT string::size_type string::rfind(const char* s, size_type pos) const; + + template _UCXXEXPORT string::size_type string::find_first_of(const string &, size_type) const; + template _UCXXEXPORT string::size_type string::find_first_of(const char *, size_type pos, size_type n) const; + template _UCXXEXPORT string::size_type string::find_first_of(const char*, size_type pos) const; + template _UCXXEXPORT string::size_type string::find_first_of(char c, size_type pos) const; + + template _UCXXEXPORT string::size_type string::find_last_of (const string & , size_type pos) const; + template _UCXXEXPORT string::size_type string::find_last_of (const char* s, size_type pos, size_type n) const; + template _UCXXEXPORT string::size_type string::find_last_of (const char* s, size_type pos) const; + template _UCXXEXPORT string::size_type string::find_last_of (char c, size_type pos) const; + + template _UCXXEXPORT string::size_type string::find_first_not_of(const string &, size_type) const; + template _UCXXEXPORT string::size_type string::find_first_not_of(const char*, size_type, size_type) const; + template _UCXXEXPORT string::size_type string::find_first_not_of(const char*, size_type) const; + template _UCXXEXPORT string::size_type string::find_first_not_of(char c, size_type) const; + + template _UCXXEXPORT int string::compare(const string & str) const; +// template _UCXXEXPORT int string::compare(size_type pos1, size_type n1, const string & str) const; + template _UCXXEXPORT int string::compare( + size_type pos1, size_type n1, const string & str, size_type pos2, size_type n2) const; + + template _UCXXEXPORT string string::substr(size_type pos, size_type n) const; + + template _UCXXEXPORT string & string::operator=(const string & str); + template _UCXXEXPORT string & string::operator=(const char * s); + + template _UCXXEXPORT bool operator==(const string & lhs, const string & rhs); + template _UCXXEXPORT bool operator==(const char * lhs, const string & rhs); + template _UCXXEXPORT bool operator==(const string & rhs, const char * rhs); + + template _UCXXEXPORT bool operator!=(const string & lhs, const string & rhs); + template _UCXXEXPORT bool operator!=(const char * lhs, const string & rhs); + template _UCXXEXPORT bool operator!=(const string & rhs, const char * rhs); + + template _UCXXEXPORT string operator+(const string & lhs, const char* rhs); + template _UCXXEXPORT string operator+(const char* lhs, const string & rhs); + template _UCXXEXPORT string operator+(const string & lhs, const string & rhs); + + template _UCXXEXPORT bool operator> (const string & lhs, const string & rhs); + template _UCXXEXPORT bool operator< (const string & lhs, const string & rhs); + + +//Functions dependent upon OSTREAM +#ifdef __UCLIBCXX_EXPAND_OSTREAM_CHAR__ + +template _UCXXEXPORT ostream & operator<<(ostream & os, const string & str); + +#endif + + +//Functions dependent upon ISTREAM +#ifdef __UCLIBCXX_EXPAND_ISTREAM_CHAR__ + +template _UCXXEXPORT istream & operator>>(istream & is, string & str); + + +#endif + + +#endif + +} Index: branches/slice/rev749/modules/uClibc++/complex.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/complex.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/complex.cpp (revision 1169) @@ -0,0 +1,28 @@ +/* Copyright (C) 2005 Garrett A. Kajmowicz + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include + + +namespace std{ + + + template class _UCXXEXPORT complex; + + +} Index: branches/slice/rev749/modules/uClibc++/func_exception.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/func_exception.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/func_exception.cpp (revision 1169) @@ -0,0 +1,87 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include + +namespace std{ + +#ifdef __UCLIBCXX_EXCEPTION_SUPPORT__ + +_UCXXEXPORT void __throw_bad_alloc(){ + throw bad_alloc(); +} + +_UCXXEXPORT void __throw_out_of_range( const char * message){ + if(message == 0){ + throw out_of_range(); + } + throw out_of_range(message); +} + +_UCXXEXPORT void __throw_overflow_error( const char * message){ + if(message == 0){ + throw overflow_error(); + } + throw overflow_error(message); +} + +_UCXXEXPORT void __throw_length_error(const char * message){ + if(message == 0){ + throw length_error(); + } + throw length_error(message); +} + +_UCXXEXPORT void __throw_invalid_argument(const char * message){ + if(message == 0){ + throw invalid_argument(); + } + throw invalid_argument(message); +} + +#else + +_UCXXEXPORT void __throw_bad_alloc(){ + abort(); +} + +_UCXXEXPORT void __throw_out_of_range( const char * ){ + abort(); +} + +_UCXXEXPORT void __throw_overflow_error( const char * ){ + abort(); +} + +_UCXXEXPORT void __throw_length_error(const char * ){ + abort(); +} + +_UCXXEXPORT void __throw_invalid_argument(const char *){ + abort(); +} + +#endif + + + +} Index: branches/slice/rev749/modules/uClibc++/ostream.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/ostream.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/ostream.cpp (revision 1169) @@ -0,0 +1,65 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#define __UCLIBCXX_COMPILE_OSTREAM__ 1 + +#include + +namespace std{ + + +#ifdef __UCLIBCXX_EXPAND_OSTREAM_CHAR__ + +#ifdef __UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ + template _UCXXEXPORT ostream::~basic_ostream(); +#endif //__UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ + + template _UCXXEXPORT ostream & ostream::flush(); + + template _UCXXEXPORT ostream & ostream::operator<<(bool n); + template _UCXXEXPORT ostream & ostream::operator<<(short int n); + template _UCXXEXPORT ostream & ostream::operator<<(unsigned short int n); + template _UCXXEXPORT ostream & ostream::operator<<(int n); + template _UCXXEXPORT ostream & ostream::operator<<(unsigned int n); + template _UCXXEXPORT ostream & ostream::operator<<(long n); + template _UCXXEXPORT ostream & ostream::operator<<(unsigned long n); + template _UCXXEXPORT ostream & ostream::operator<<(float f); + template _UCXXEXPORT ostream & ostream::operator<<(double f); + template _UCXXEXPORT ostream & ostream::operator<<(long double f); + template _UCXXEXPORT ostream & ostream::operator<<(void* p); + template _UCXXEXPORT ostream & ostream::operator<<(basic_streambuf >* sb); + +#ifdef __UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ + + template _UCXXEXPORT ostream::sentry::sentry(ostream & os); + template _UCXXEXPORT ostream::sentry::~sentry(); + +#endif //__UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ + + template _UCXXEXPORT ostream & endl(ostream & os); + template _UCXXEXPORT ostream & flush(ostream & os); + template _UCXXEXPORT ostream & operator<<(ostream & out, char c); + template _UCXXEXPORT ostream & operator<<(ostream & out, const char* c); + template _UCXXEXPORT ostream & operator<<(ostream & out, unsigned char c); + template _UCXXEXPORT ostream & operator<<(ostream & out, const unsigned char* c); + +#endif + + +} Index: branches/slice/rev749/modules/uClibc++/support.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/support.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/support.cpp (revision 1169) @@ -0,0 +1,54 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#ifdef __UCLIBCXX_EXCEPTION_SUPPORT__ +extern "C" void *__cxa_allocate_exception(size_t thrown_size) +{ + void * retval; + + /*The amount of data needed is the size of the object *PLUS* + the size of the header. The header is of struct __cxa_exception + The address needs to be adjusted because the pointer we return + should not point to the start of the memory, but to the point + where the object being thrown actually starts*/ + + retval = malloc(thrown_size + sizeof(__cxa_exception)); + +// Check to see that we actuall allocated memory + if(retval == 0){ + std::terminate(); + } + + //Need to do a typecast to char* otherwize we are doing math with + //a void* which makes the compiler cranky (Like me) + return ((char *)retval + sizeof(__cxa_exception)); +} + +extern "C" void __cxa_free_exception(void *thrown_exception){ + + + +} + +extern "C" void __cxa_throw (void *thrown_exception, std::type_info *tinfo,void (*dest) (void *) ){ + +} +#endif + Index: branches/slice/rev749/modules/uClibc++/new_opv.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/new_opv.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/new_opv.cpp (revision 1169) @@ -0,0 +1,38 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include +#include +#include +extern "C" { +#include "libsaio.h" +}; +_UCXXEXPORT void* operator new[](std::size_t numBytes) throw(std::bad_alloc){ + //C++ stardard 5.3.4.8 requires that a valid pointer be returned for + //a call to new(0). Thus: + if(numBytes == 0){ + numBytes = 1; + } + void * p = malloc(numBytes); + if(p == 0){ + std::__throw_bad_alloc(); + } + return p; +} Index: branches/slice/rev749/modules/uClibc++/sstream.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/sstream.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/sstream.cpp (revision 1169) @@ -0,0 +1,59 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#define __UCLIBCXX_COMPILE_SSTREAM__ 1 + +#include + +namespace std{ + +#ifdef __UCLIBCXX_EXPAND_SSTREAM_CHAR__ + + typedef char_traits tr_ch; + typedef basic_stringbuf > char_stringbuf; + +#ifdef __UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ + + template _UCXXEXPORT char_stringbuf::basic_stringbuf(ios_base::openmode which); + template _UCXXEXPORT char_stringbuf::~basic_stringbuf(); + +#endif //__UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ + + template _UCXXEXPORT basic_string, allocator > char_stringbuf::str() const; + template _UCXXEXPORT char_stringbuf::int_type char_stringbuf::pbackfail(char_stringbuf::int_type c); + template _UCXXEXPORT char_stringbuf::int_type char_stringbuf::overflow(char_stringbuf::int_type c); + template _UCXXEXPORT char_stringbuf::pos_type + char_stringbuf::seekoff(char_stringbuf::off_type, ios_base::seekdir, ios_base::openmode); + template _UCXXEXPORT char_stringbuf::int_type char_stringbuf::underflow (); + template _UCXXEXPORT streamsize char_stringbuf::xsputn(const char* s, streamsize n); + +#ifdef __UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ + + template _UCXXEXPORT basic_stringstream >::basic_stringstream(ios_base::openmode which); + template _UCXXEXPORT basic_istringstream >::~basic_istringstream(); + template _UCXXEXPORT basic_ostringstream >::~basic_ostringstream(); + template _UCXXEXPORT basic_stringstream >::~basic_stringstream(); + +#endif //__UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ + +#endif + +} + + Index: branches/slice/rev749/modules/uClibc++/valarray.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/valarray.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/valarray.cpp (revision 1169) @@ -0,0 +1,29 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include + +namespace std{ + + + + +} + + Index: branches/slice/rev749/modules/uClibc++/iostream.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/iostream.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/iostream.cpp (revision 1169) @@ -0,0 +1,38 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#define __UCLIBCXX_COMPILE_IOSTREAM__ 1 + +#include + +namespace std{ + +#ifdef __UCLIBCXX_EXPAND_OSTREAM_CHAR__ +#ifdef __UCLIBCXX_EXPAND_ISTREAM_CHAR__ + + template _UCXXEXPORT basic_iostream >:: + basic_iostream(basic_streambuf >* sb); + template _UCXXEXPORT basic_iostream >::~basic_iostream(); + +#endif +#endif + +} + + Index: branches/slice/rev749/modules/uClibc++/new_handler.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/new_handler.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/new_handler.cpp (revision 1169) @@ -0,0 +1,31 @@ +/* Copyright (C) 2005 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include + +const std::nothrow_t std::nothrow = { }; + +//Name selected to be compatable with g++ code +std::new_handler __new_handler; + +_UCXXEXPORT std::new_handler std::set_new_handler(std::new_handler new_p) throw(){ + std::new_handler retval = __new_handler; + __new_handler = new_p; + return retval; +} Index: branches/slice/rev749/modules/uClibc++/algorithm.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/algorithm.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/algorithm.cpp (revision 1169) @@ -0,0 +1,30 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + + +#include + + +namespace std{ + + + +} + + Index: branches/slice/rev749/modules/uClibc++/new_op.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/new_op.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/new_op.cpp (revision 1169) @@ -0,0 +1,38 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include +#include +#include + +extern "C" { +#include "libsaio.h" +}; + +_UCXXEXPORT void* operator new(std::size_t numBytes) throw(std::bad_alloc){ + //C++ stardard 5.3.4.8 requires that a valid pointer be returned for + //a call to new(0). Thus: + if(numBytes == 0){ + numBytes = 1; + } + void * p = malloc(numBytes); + if(p == 0){ + std::__throw_bad_alloc(); + } + return p; +} Index: branches/slice/rev749/modules/uClibc++/uClibc++.c =================================================================== --- branches/slice/rev749/modules/uClibc++/uClibc++.c (revision 0) +++ branches/slice/rev749/modules/uClibc++/uClibc++.c (revision 1169) @@ -0,0 +1,12 @@ +#include "libsaio.h" + +void uClibcxx_start() +{ +} + +void abort() +{ + stop("uClibc+: abort()\n"); +} + + Index: branches/slice/rev749/modules/uClibc++/del_opvnt.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/del_opvnt.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/del_opvnt.cpp (revision 1169) @@ -0,0 +1,28 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include + +#ifndef NO_NOTHROW +_UCXXEXPORT void operator delete[](void* ptr, const std::nothrow_t& ) throw(){ + free(ptr); +} +#endif Index: branches/slice/rev749/modules/uClibc++/iomanip.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/iomanip.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/iomanip.cpp (revision 1169) @@ -0,0 +1,29 @@ +/* Copyright (C) 2005 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include + +namespace std{ + + + + +} + + Index: branches/slice/rev749/modules/uClibc++/typeinfo.cpp =================================================================== --- branches/slice/rev749/modules/uClibc++/typeinfo.cpp (revision 0) +++ branches/slice/rev749/modules/uClibc++/typeinfo.cpp (revision 1169) @@ -0,0 +1,34 @@ +/* Copyright (C) 2004 Garrett A. Kajmowicz + + This file is part of the uClibc++ Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include + +namespace std{ + + _UCXXEXPORT bad_cast::~bad_cast() throw(){ + + } + + _UCXXEXPORT bad_typeid::~bad_typeid() throw(){ + + } + +} + + Index: branches/slice/rev749/modules/KernelPatcher/include/kernel_patcher.h =================================================================== --- branches/slice/rev749/modules/KernelPatcher/include/kernel_patcher.h (revision 0) +++ branches/slice/rev749/modules/KernelPatcher/include/kernel_patcher.h (revision 1169) @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2009 Evan Lojewski. All rights reserved. + * + */ + +#include +#include + +#ifndef __BOOT2_KERNEL_PATCHER_H +#define __BOOT2_KERNEL_PATCHER_H + +#define CPUID_MODEL_ANY 0x00 +#define CPUID_MODEL_UNKNOWN 0x01 + +#define CPUID_MODEL_YONAH 14 +#define CPUID_MODEL_MEROM 15 +#define CPUID_MODEL_PENRYN 23 +#define CPUID_MODEL_NEHALEM 26 +#define CPUID_MODEL_ATOM 28 +#define CPUID_MODEL_FIELDS 30 /* Lynnfield, Clarksfield, Jasper */ +#define CPUID_MODEL_DALES 31 /* Havendale, Auburndale */ +#define CPUID_MODEL_NEHALEM_EX 46 + +#define KERNEL_ANY 0x00 +#define KERNEL_64 0x01 +#define KERNEL_32 0x02 +#define KERNEL_ERR 0xFF + +typedef struct patchRoutine_t +{ + void(*patchRoutine)(void*); + int validArchs; + int validCpu; + struct patchRoutine_t* next; +} patchRoutine_t; + + +typedef struct kernSymbols_t +{ + char* symbol; + UInt64 addr; + struct kernSymbols_t* next; +} kernSymbols_t; + +kernSymbols_t* lookup_kernel_symbol(const char* name); +void register_kernel_symbol(int kernelType, const char* name); + +long long symbol_handler(char* symbolName, long long addr, char is64); +void patch_kernel(void* kernelData, void* arg2, void* arg3, void *arg4); +void register_kernel_patch(void* patch, int arch, int cpus); + +int locate_symbols(void* kernelData); + +int determineKernelArchitecture(void* kernelData); + +/* + * Internal patches provided by this module. + */ +void patch_cpuid_set_info_all(void* kernelData); +void patch_cpuid_set_info_32(void* kernelData, UInt32 impersonateFamily, UInt8 impersonateModel); +void patch_cpuid_set_info_64(void* kernelData, UInt32 impersonateFamily, UInt8 impersonateModel); + +void patch_pmCPUExitHaltToOff(void* kernelData); +void patch_lapic_init(void* kernelData); +void patch_commpage_stuff_routine(void* kernelData); +void patch_lapic_configure(void* kernelData); +void patch_lapic_interrupt(void* kernelData); + +#endif /* !__BOOT2_KERNEL_PATCHER_H */ Index: branches/slice/rev749/modules/KernelPatcher/kernel_patcher.c =================================================================== --- branches/slice/rev749/modules/KernelPatcher/kernel_patcher.c (revision 0) +++ branches/slice/rev749/modules/KernelPatcher/kernel_patcher.c (revision 1169) @@ -0,0 +1,956 @@ + /* + * Copyright (c) 2009-2010 Evan Lojewski. All rights reserved. + * + */ + +#include "libsaio.h" +#include "kernel_patcher.h" +#include "platform.h" +#include "modules.h" +extern PlatformInfo_t* Platform; + +patchRoutine_t* patches = NULL; +kernSymbols_t* kernelSymbols = NULL; + + +void KernelPatcher_start() +{ + register_kernel_patch(patch_cpuid_set_info_all, KERNEL_ANY, CPUID_MODEL_UNKNOWN); + + register_kernel_patch(patch_commpage_stuff_routine, KERNEL_ANY, CPUID_MODEL_ANY); + + register_kernel_patch(patch_lapic_init, KERNEL_ANY, CPUID_MODEL_ANY); + + // NOTE: following is currently 32bit only + register_kernel_patch(patch_lapic_configure, KERNEL_32, CPUID_MODEL_ANY); + + + register_kernel_symbol(KERNEL_ANY, "_panic"); + register_kernel_symbol(KERNEL_ANY, "_cpuid_set_info"); + register_kernel_symbol(KERNEL_ANY, "_pmCPUExitHaltToOff"); + register_kernel_symbol(KERNEL_ANY, "_lapic_init"); + register_kernel_symbol(KERNEL_ANY, "_commpage_stuff_routine"); + + // lapic_configure symbols + register_kernel_symbol(KERNEL_ANY, "_lapic_configure"); + register_kernel_symbol(KERNEL_ANY, "_lapic_start"); + register_kernel_symbol(KERNEL_ANY, "_lapic_interrupt_base"); + + // lapic_interrup symbols + //register_kernel_patch(patch_lapic_interrupt, KERNEL_ANY, CPUID_MODEL_ANY); + //register_kernel_symbol(KERNEL_ANY, "_lapic_interrupt"); + + + + // TODO: register needed symbols + + + register_hook_callback("ExecKernel", &patch_kernel); +} + +/* + * Register a kerenl patch + */ +void register_kernel_patch(void* patch, int arch, int cpus) +{ + // TODO: only insert valid patches based on current cpuid and architecture + // AKA, don't at 64bit patches if it's a 32bit only machine + patchRoutine_t* entry; + + // TODO: verify Platform->CPU.Model is populated this early in bootup + // Check to ensure that the patch is valid on this machine + // If it is not, exit early form this function + if(cpus != Platform->CPU.Model) + { + if(cpus != CPUID_MODEL_ANY) + { + if(cpus == CPUID_MODEL_UNKNOWN) + { + switch(Platform->CPU.Model) + { + case 13: + case CPUID_MODEL_YONAH: + case CPUID_MODEL_MEROM: + case CPUID_MODEL_PENRYN: + case CPUID_MODEL_NEHALEM: + case CPUID_MODEL_FIELDS: + case CPUID_MODEL_DALES: + case CPUID_MODEL_NEHALEM_EX: + // Known cpu's we don't want to add the patch + return; + break; + + default: + // CPU not in supported list, so we are going to add + // The patch will be applied + break; + + } + } + else + { + // Invalid cpuid for current cpu. Ignoring patch + return; + } + + } + } + + if(patches == NULL) + { + patches = entry = malloc(sizeof(patchRoutine_t)); + } + else + { + entry = patches; + while(entry->next) + { + entry = entry->next; + } + + entry->next = malloc(sizeof(patchRoutine_t)); + entry = entry->next; + } + + entry->next = NULL; + entry->patchRoutine = patch; + entry->validArchs = arch; + entry->validCpu = cpus; +} + +void register_kernel_symbol(int kernelType, const char* name) +{ + if(kernelSymbols == NULL) + { + kernelSymbols = malloc(sizeof(kernSymbols_t)); + kernelSymbols->next = NULL; + kernelSymbols->symbol = (char*)name; + kernelSymbols->addr = 0; + } + else { + kernSymbols_t *symbol = kernelSymbols; + while(symbol->next != NULL) + { + symbol = symbol->next; + } + + symbol->next = malloc(sizeof(kernSymbols_t)); + symbol = symbol->next; + + symbol->next = NULL; + symbol->symbol = (char*)name; + symbol->addr = 0; + } +} + +kernSymbols_t* lookup_kernel_symbol(const char* name) +{ + kernSymbols_t *symbol = kernelSymbols; + + while(symbol && strcmp(symbol->symbol, name) !=0) + { + symbol = symbol->next; + } + + if(!symbol) + { + return NULL; + } + else + { + return symbol; + } + +} + +void patch_kernel(void* kernelData, void* arg2, void* arg3, void *arg4) +{ + patchRoutine_t* entry = patches; + + + int arch = determineKernelArchitecture(kernelData); + + locate_symbols(kernelData); + + if(patches != NULL) + { + while(entry) + { + if(entry->validArchs == KERNEL_ANY || arch == entry->validArchs) + { + if(entry->patchRoutine) entry->patchRoutine(kernelData); + } + entry = entry->next; + } + } +} + +int determineKernelArchitecture(void* kernelData) +{ + if(((struct mach_header*)kernelData)->magic == MH_MAGIC) + { + return KERNEL_32; + } + if(((struct mach_header*)kernelData)->magic == MH_MAGIC_64) + { + return KERNEL_64; + } + else + { + return KERNEL_ERR; + } +} + + +/** + ** This functions located the requested symbols in the mach-o file. + ** as well as determines the start of the __TEXT segment and __TEXT,__text sections + **/ +int locate_symbols(void* kernelData) +{ + char is64 = 1; + parse_mach(kernelData, NULL, symbol_handler); + //handle_symtable((UInt32)kernelData, symtableData, &symbol_handler, determineKernelArchitecture(kernelData) == KERNEL_64); + return 1 << is64; +} + +long long symbol_handler(char* symbolName, long long addr, char is64) +{ + // Locate the symbol in the list, if it exists, update it's address + kernSymbols_t *symbol = lookup_kernel_symbol(symbolName); + + if(symbol) + { + symbol->addr = addr; + } + + return 0xFFFFFFFF; // fixme +} + + +/** + ** Locate the fisrt instance of _panic inside of _cpuid_set_info, and either remove it + ** Or replace it so that the cpuid is set to a valid value. + **/ +void patch_cpuid_set_info_all(void* kernelData) +{ + switch(Platform->CPU.Model) + { + case CPUID_MODEL_ATOM: + if(determineKernelArchitecture(kernelData) == KERNEL_32) + { + patch_cpuid_set_info_32(kernelData, CPUFAMILY_INTEL_PENRYN, CPUID_MODEL_PENRYN); + } + else + { + patch_cpuid_set_info_64(kernelData, CPUFAMILY_INTEL_PENRYN, CPUID_MODEL_PENRYN); + + } + + break; + + default: + if(determineKernelArchitecture(kernelData) == KERNEL_32) + { + patch_cpuid_set_info_32(kernelData, 0, 0); + } + else + { + patch_cpuid_set_info_64(kernelData, 0, 0); + } + + break; + } +} +void patch_cpuid_set_info_64(void* kernelData, UInt32 impersonateFamily, UInt8 impersonateModel) +{ + UInt8* bytes = (UInt8*)kernelData; + + kernSymbols_t *symbol = lookup_kernel_symbol("_cpuid_set_info"); + + UInt32 patchLocation = symbol ? symbol->addr - textAddress + textSection: 0; // (kernelSymbolAddresses[SYMBOL_CPUID_SET_INFO] - textAddress + textSection); + patchLocation -= (UInt32)kernelData; // Remove offset + + + + //UInt32 jumpLocation = 0; + + + if(symbol == 0 || symbol->addr == 0) + { + verbose("Unable to locate _cpuid_set_info\n"); + return; + + } + + symbol = lookup_kernel_symbol("_panic"); + UInt32 panicAddr = symbol ? symbol->addr - textAddress: 0; //kernelSymbolAddresses[SYMBOL_PANIC] - textAddress; + if(symbol == 0 || symbol->addr == 0) + { + verbose("Unable to locate _panic\n"); + return; + } + panicAddr -= (UInt32)kernelData; + + + + //TODO: don't assume it'll always work (Look for *next* function address in symtab and fail once it's been reached) + while( + (bytes[patchLocation -1] != 0xE8) || + ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 | + bytes[patchLocation + 1] << 8 | + bytes[patchLocation + 2] << 16 | + bytes[patchLocation + 3] << 24))) + ) + { + patchLocation++; + } + patchLocation--; + + // Remove panic just in ca se + // The panic instruction is exactly 5 bytes long. + bytes[patchLocation + 0] = 0x90; + bytes[patchLocation + 1] = 0x90; + bytes[patchLocation + 2] = 0x90; + bytes[patchLocation + 3] = 0x90; + bytes[patchLocation + 4] = 0x90; + + + + // Check for a 10.2.0+ kernel + if(bytes[patchLocation - 19] == 0xC7 && bytes[patchLocation - 18] == 0x05) + { + + UInt32 cpuid_cpufamily_addr = bytes[patchLocation - 17] << 0 | + bytes[patchLocation - 16] << 8 | + bytes[patchLocation - 15] << 16 | + bytes[patchLocation - 14] << 24; + + // NOTE: may change, determined based on cpuid_info struct + UInt32 cpuid_model_addr = cpuid_cpufamily_addr - 310; + + + //ffffff8000228b3b -> 0x00490e8b + //ffffff8000228c28 -> -237 -> 0x490D9E -> -310 + + + // The mov is 10 bytes + /* + bytes[patchLocation - 19] = 0x90; // c7 + bytes[patchLocation - 18] = 0x90; // 05 + bytes[patchLocation - 17] = 0x90; // family location + bytes[patchLocation - 16] = 0x90; // family location + bytes[patchLocation - 15] = 0x90; // family location + bytes[patchLocation - 14] = 0x90; // family location + */ + bytes[patchLocation - 13] = (impersonateFamily & 0x000000FF) >> 0; + bytes[patchLocation - 12] = (impersonateFamily & 0x0000FF00) >> 8; + bytes[patchLocation - 11] = (impersonateFamily & 0x00FF0000) >> 16; + bytes[patchLocation - 10] = (impersonateFamily & 0xFF000000) >> 24; + + + // The lea (%rip),%rip is 7 bytes + bytes[patchLocation - 9] = 0xC7; + bytes[patchLocation - 8] = 0x05; + bytes[patchLocation - 7] = ((cpuid_model_addr -10) & 0x000000FF) >> 0; // NOTE: this opcode is relative in 64bit mode, subtract offset + bytes[patchLocation - 6] = ((cpuid_model_addr -10) & 0x0000FF00) >> 8; + bytes[patchLocation - 5] = ((cpuid_model_addr -10) & 0x00FF0000) >> 16; + bytes[patchLocation - 4] = ((cpuid_model_addr -10) & 0xFF000000) >> 24; + bytes[patchLocation - 3] = impersonateModel; // cpuid_model + + + + // The xor eax eax is 2 bytes + bytes[patchLocation - 2] = 0x01; // cpuid_extmodel + bytes[patchLocation - 1] = 0x00; // cpuid_extfamily + + // The panic instruction is exactly 5 bytes long. + bytes[patchLocation - 0] = 0x02; // cpuid_stepping + /*bytes[patchLocation + 1] = 0x90; + bytes[patchLocation + 2] = 0x90; + bytes[patchLocation + 3] = 0x90; + bytes[patchLocation + 4] = 0x90; + */ + + // Panic call has been removed. + // Override the CPUID now. This requires ~ 10 bytes on 10.0.0 kernels + // On 10.2.0+ kernels, this requires ~16 bytes + + // Total: 24 bytes + verbose("Running on a 10.2.0+ kernel\n"); + getc(); + + } + else { + verbose("Running on a 10.0.0 kernel, patch unsupported\n"); + getc(); + } + + +} + + + + + +void patch_cpuid_set_info_32(void* kernelData, UInt32 impersonateFamily, UInt8 impersonateModel) +{ + UInt8* bytes = (UInt8*)kernelData; + + kernSymbols_t *symbol = lookup_kernel_symbol("_cpuid_set_info"); + + UInt32 patchLocation = symbol ? symbol->addr - textAddress + textSection: 0; // (kernelSymbolAddresses[SYMBOL_CPUID_SET_INFO] - textAddress + textSection); + patchLocation -= (UInt32)kernelData; // Remove offset + UInt32 addrLocation = patchLocation; + + + UInt32 jumpLocation = 0; + + + if(symbol == 0 || symbol->addr == 0) + { + verbose("Unable to locate _cpuid_set_info\n"); + return; + + } + + symbol = lookup_kernel_symbol("_panic"); + UInt32 panicAddr = symbol ? symbol->addr - textAddress: 0; //kernelSymbolAddresses[SYMBOL_PANIC] - textAddress; + if(symbol == 0 || symbol->addr == 0) + { + verbose("Unable to locate _panic\n"); + return; + } + panicAddr -= (UInt32)kernelData; + + + + //TODO: don't assume it'll always work (Look for *next* function address in symtab and fail once it's been reached) + while( + (bytes[patchLocation -1] != 0xE8) || + ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 | + bytes[patchLocation + 1] << 8 | + bytes[patchLocation + 2] << 16 | + bytes[patchLocation + 3] << 24))) + ) + { + patchLocation++; + } + patchLocation--; + + // Remove panic call, just in case the following patch routines fail + bytes[patchLocation + 0] = 0x90; + bytes[patchLocation + 1] = 0x90; + bytes[patchLocation + 2] = 0x90; + bytes[patchLocation + 3] = 0x90; + bytes[patchLocation + 4] = 0x90; + + + // Locate the jump call, so that 10 bytes can be reclamed. + // NOTE: This will *NOT* be located on pre 10.6.2 kernels + jumpLocation = patchLocation - 15; + while((bytes[jumpLocation - 1] != 0x77 || + bytes[jumpLocation] != (patchLocation - jumpLocation - 18)) && + (patchLocation - jumpLocation) < 0xF0) + { + jumpLocation--; + } + // If found... AND we want to impersonate a specific cpumodel / family... + if(impersonateFamily && impersonateModel && + ((patchLocation - jumpLocation) < 0xF0)) + { + bytes[jumpLocation] -= 10; // sizeof(movl $0x6b5a4cd2,0x00872eb4) = 10bytes + + /* + * Inpersonate the specified CPU FAMILY and CPU Model + */ + // cpuid_cpufamily_addr, impersonateFamily cpuid_model_addr impersonateModel + //char new_bytes[] = {0xC7, 0x05, 0x__, 0x__, 0x__, 0x__, 0x__, 0x__, 0x__, 0x__, 0x90, 0x90, 0xC7, 0x05, 0x__, 0x__, 0x__, 0x__, 0x__, 0x01, 0x00, 0x02}; + // bytes[patchLocation - 17] = 0xC7; // already here... not needed to be done + // bytes[patchLocation - 16] = 0x05; // see above + //UInt32 cpuid_cpufamily_addr = bytes[patchLocation - 15] << 0 | + // bytes[patchLocation - 14] << 8 | + // bytes[patchLocation - 13] << 16 | + // bytes[patchLocation - 12] << 24; + + // NOTE: may change, determined based on cpuid_info struct: TODO: read from binary + //UInt32 cpuid_model_addr = cpuid_cpufamily_addr - 295; + + + // cpufamily + bytes[patchLocation - 11] = (impersonateFamily & 0x000000FF) >> 0; + bytes[patchLocation - 10] = (impersonateFamily & 0x0000FF00) >> 8; + bytes[patchLocation - 9] = (impersonateFamily & 0x00FF0000) >> 16; + bytes[patchLocation - 8] = (impersonateFamily & 0xFF000000) >> 24; + + // NOPS, just in case if the jmp call wasn't patched, we'll jump to a + // nop and continue with the rest of the patch + // Yay two free bytes :), 10 more can be reclamed if needed, as well as a few + // from the above code (only cpuid_model needs to be set. + bytes[patchLocation - 7] = 0x90; + bytes[patchLocation - 6] = 0x90; + + bytes[patchLocation - 5] = 0xC7; + bytes[patchLocation - 4] = 0x05; + + // Locate cpuid_addr_addr -> first four bytes after 8b 45 d8 25 f0 00 00 00 c1 e8 04 a2 + while(bytes[addrLocation -12] != 0x8B || + bytes[addrLocation -11] != 0x45 || + bytes[addrLocation -10] != 0xD8 || + bytes[addrLocation -9] != 0x25 || + bytes[addrLocation -8] != 0xF0 || + bytes[addrLocation -7] != 0x00 || + bytes[addrLocation -6] != 0x00 || + bytes[addrLocation -5] != 0x00 || + bytes[addrLocation -4] != 0xC1 || + bytes[addrLocation -3] != 0xE8 || + bytes[addrLocation -2] != 0x04 || + bytes[addrLocation -1] != 0xA2) + { + // TODO: break if location is too large + addrLocation++; + } + + bytes[patchLocation - 3] = bytes[addrLocation]; + bytes[patchLocation - 2] = bytes[addrLocation+1]; + bytes[patchLocation - 1] = bytes[addrLocation+2]; + bytes[patchLocation - 0] = bytes[addrLocation+3]; + + // Note: I could have just copied the 8bit cpuid_model in and saved about 4 bytes + // so if this function need a different patch it's still possible. Also, about ten bytes previous can be freed. + bytes[patchLocation + 1] = impersonateModel; // cpuid_model + bytes[patchLocation + 2] = 0x01; // cpuid_extmodel + bytes[patchLocation + 3] = 0x00; // cpuid_extfamily + bytes[patchLocation + 4] = 0x02; // cpuid_stepping + } + else if(impersonateFamily && impersonateModel) + { + + // pre 10.6.2 kernel + // Locate the jump to directly *after* the panic call, + jumpLocation = patchLocation - 4; + while((bytes[jumpLocation - 1] != 0x77 || + bytes[jumpLocation] != (patchLocation - jumpLocation + 4)) && + (patchLocation - jumpLocation) < 0x20) + { + jumpLocation--; + } + // NOTE above isn't needed (I was going to use it, but I'm not, so instead, + // I'll just leave it to verify the binary stucture. + + // NOTE: the cpumodel_familt data is not set in _cpuid_set_info + // so we don't need to set it here, I'll get set later based on the model + // we set now. + + if((patchLocation - jumpLocation) < 0x20) + { + UInt32 cpuid_model_addr = (bytes[patchLocation - 14] << 0 | + bytes[patchLocation - 13] << 8 | + bytes[patchLocation - 12] << 16 | + bytes[patchLocation - 11] << 24); + // Remove jump + bytes[patchLocation - 9] = 0x90; /// Was a jump if supported cpu + bytes[patchLocation - 8] = 0x90; // jumped past the panic call, we want to override the panic + + bytes[patchLocation - 7] = 0x90; + bytes[patchLocation - 6] = 0x90; + + bytes[patchLocation - 5] = 0xC7; + bytes[patchLocation - 4] = 0x05; + bytes[patchLocation - 3] = (cpuid_model_addr & 0x000000FF) >> 0; + bytes[patchLocation - 2] = (cpuid_model_addr & 0x0000FF00) >> 8; + bytes[patchLocation - 1] = (cpuid_model_addr & 0x00FF0000) >> 16; + bytes[patchLocation - 0] = (cpuid_model_addr & 0xFF000000) >> 24; + + // Note: I could have just copied the 8bit cpuid_model in and saved about 4 bytes + // so if this function need a different patch it's still possible. Also, about ten bytes previous can be freed. + bytes[patchLocation + 1] = impersonateModel; // cpuid_model + bytes[patchLocation + 2] = 0x01; // cpuid_extmodel + bytes[patchLocation + 3] = 0x00; // cpuid_extfamily + bytes[patchLocation + 4] = 0x02; // cpuid_stepping + + + + //patchLocation = jumpLocation; + // We now have 14 bytes available for a patch + + } + else + { + // Patching failed, using NOP replacement done initialy + } + } + else + { + // Either We were unable to change the jump call due to the function's sctructure + // changing, or the user did not request a patch. As such, resort to just + // removing the panic call (using NOP replacement above). Note that the + // IntelCPUPM kext may still panic due to the cpu's Model ID not being patched + } +} + + +/** + ** SleepEnabler.kext replacement (for those that need it) + ** Located the KERN_INVALID_ARGUMENT return and replace it with KERN_SUCCESS + **/ +void patch_pmCPUExitHaltToOff(void* kernelData) +{ + UInt8* bytes = (UInt8*)kernelData; + + kernSymbols_t *symbol = lookup_kernel_symbol("_PmCpuExitHaltToOff"); + UInt32 patchLocation = symbol ? symbol->addr - textAddress + textSection: 0; + + if(symbol == 0 || symbol->addr == 0) + { + verbose("Unable to locate _pmCPUExitHaltToOff\n"); + return; + } + + patchLocation -= (UInt32)kernelData; // Remove offset + + + + while(bytes[patchLocation - 1] != 0xB8 || + bytes[patchLocation] != 0x04 || // KERN_INVALID_ARGUMENT (0x00000004) + bytes[patchLocation + 1] != 0x00 || // KERN_INVALID_ARGUMENT + bytes[patchLocation + 2] != 0x00 || // KERN_INVALID_ARGUMENT + bytes[patchLocation + 3] != 0x00) // KERN_INVALID_ARGUMENT + + { + patchLocation++; + } + bytes[patchLocation] = 0x00; // KERN_SUCCESS; +} + +void patch_lapic_init(void* kernelData) +{ + UInt8 panicIndex = 0; + UInt8* bytes = (UInt8*)kernelData; + + kernSymbols_t *symbol = lookup_kernel_symbol("_lapic_init"); + UInt32 patchLocation = symbol ? symbol->addr - textAddress + textSection: 0; + if(symbol == 0 || symbol->addr == 0) + { + verbose("Unable to locate %s\n", "_lapic_init"); + return; + + } + + symbol = lookup_kernel_symbol("_panic"); + UInt32 panicAddr = symbol ? symbol->addr - textAddress: 0; + if(symbol == 0 || symbol->addr == 0) + { + verbose("Unable to locate %s\n", "_panic"); + return; + } + + patchLocation -= (UInt32)kernelData; // Remove offset + panicAddr -= (UInt32)kernelData; // Remove offset + + + + + // Locate the (panicIndex + 1) panic call + while(panicIndex < 3) // Find the third panic call + { + while( + (bytes[patchLocation -1] != 0xE8) || + ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 | + bytes[patchLocation + 1] << 8 | + bytes[patchLocation + 2] << 16 | + bytes[patchLocation + 3] << 24))) + ) + { + patchLocation++; + } + patchLocation++; + panicIndex++; + } + patchLocation--; // Remove extra increment from the < 3 while loop + + bytes[--patchLocation] = 0x90; + bytes[++patchLocation] = 0x90; + bytes[++patchLocation] = 0x90; + bytes[++patchLocation] = 0x90; + bytes[++patchLocation] = 0x90; + + +} + + +void patch_commpage_stuff_routine(void* kernelData) +{ + UInt8* bytes = (UInt8*)kernelData; + + kernSymbols_t *symbol = lookup_kernel_symbol("_commpage_stuff_routine"); + if(symbol == 0 || symbol->addr == 0) + { + //printf("Unable to locate %s\n", "_commpage_stuff_routine"); + return; + + } + + UInt32 patchLocation = symbol->addr - textAddress + textSection; + + + symbol = lookup_kernel_symbol("_panic"); + if(symbol == 0 || symbol->addr == 0) + { + verbose("Unable to locate %s\n", "_panic"); + return; + } + UInt32 panicAddr = symbol->addr - textAddress; + + patchLocation -= (UInt32)kernelData; + panicAddr -= (UInt32)kernelData; + + while( + (bytes[patchLocation -1] != 0xE8) || + ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 | + bytes[patchLocation + 1] << 8 | + bytes[patchLocation + 2] << 16 | + bytes[patchLocation + 3] << 24))) + ) + { + patchLocation++; + } + patchLocation--; + + // Replace panic with nops + bytes[patchLocation + 0] = 0x90; + bytes[patchLocation + 1] = 0x90; + bytes[patchLocation + 2] = 0x90; + bytes[patchLocation + 3] = 0x90; + bytes[patchLocation + 4] = 0x90; + + +} + +void patch_lapic_interrupt(void* kernelData) +{ + // NOTE: this is a hack untill I finish patch_lapic_configure + UInt8* bytes = (UInt8*)kernelData; + + kernSymbols_t *symbol = lookup_kernel_symbol("_lapic_interrupt"); + if(symbol == 0 || symbol->addr == 0) + { + verbose("Unable to locate %s\n", "_lapic_interrupt"); + return; + + } + + UInt32 patchLocation = symbol->addr - textAddress + textSection; + + + symbol = lookup_kernel_symbol("_panic"); + if(symbol == 0 || symbol->addr == 0) + { + verbose("Unable to locate %s\n", "_panic"); + return; + } + UInt32 panicAddr = symbol->addr - textAddress; + + patchLocation -= (UInt32)kernelData; + panicAddr -= (UInt32)kernelData; + + while( + (bytes[patchLocation -1] != 0xE8) || + ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 | + bytes[patchLocation + 1] << 8 | + bytes[patchLocation + 2] << 16 | + bytes[patchLocation + 3] << 24))) + ) + { + patchLocation++; + } + patchLocation--; + + // Replace panic with nops + bytes[patchLocation + 0] = 0x90; + bytes[patchLocation + 1] = 0x90; + bytes[patchLocation + 2] = 0x90; + bytes[patchLocation + 3] = 0x90; + bytes[patchLocation + 4] = 0x90; + + +} + + +void patch_lapic_configure(void* kernelData) +{ + UInt8* bytes = (UInt8*)kernelData; + + UInt32 patchLocation; + UInt32 lapicStart; + UInt32 lapicInterruptBase; + + kernSymbols_t *symbol = lookup_kernel_symbol("_lapic_configure"); + if(symbol == 0 || symbol->addr == 0) + { + verbose("Unable to locate %s\n", "_lapic_configure"); + return; + } + patchLocation = symbol->addr - textAddress + textSection; + + symbol = lookup_kernel_symbol("_lapic_start"); + if(symbol == 0 || symbol->addr == 0) + { + verbose("Unable to locate %s\n", "_lapic_start"); + return; + } + lapicStart = symbol->addr; + + + symbol = lookup_kernel_symbol("_lapic_interrupt_base"); + if(symbol == 0 || symbol->addr == 0) + { + verbose("Unable to locate %s\n", "_lapic_interrupt_base"); + return; + } + lapicInterruptBase = symbol->addr; + patchLocation -= (UInt32)kernelData; + lapicStart -= (UInt32)kernelData; + lapicInterruptBase -= (UInt32)kernelData; + + + // Looking for the following: + //movl _lapic_start,%e_x + //addl $0x00000320,%e_x + // 8b 15 __ __ __ __ 81 c2 20 03 00 00 + while( + (bytes[patchLocation - 2] != 0x8b) || + //bytes[patchLocation -1] != 0x15) || // Register, we don't care what it is + ( lapicStart != (UInt32)( + (bytes[patchLocation + 0] << 0 | + bytes[patchLocation + 1] << 8 | + bytes[patchLocation + 2] << 16 | + bytes[patchLocation + 3] << 24 + ) + ) + ) || + (bytes[patchLocation + 4 ] != 0x81) || + //(bytes[patchLocation + 5 ] != 0Cx2) || // register + (bytes[patchLocation + 6 ] != 0x20) || + (bytes[patchLocation + 7 ] != 0x03) || + (bytes[patchLocation + 8 ] != 0x00) || + (bytes[patchLocation + 9] != 0x00) + + ) + { + patchLocation++; + } + patchLocation-=2; + + // NOTE: this is currently hardcoded, change it to be more resilient to changes + // At a minimum, I should have this do a cheksup first and if not matching, remove the panic instead. + + // 8b 15 __ __ __ __ -> movl _lapic_start,%edx (NOTE: this should already be here) + /* + bytes[patchLocation++] = 0x8B; + bytes[patchLocation++] = 0x15; + bytes[patchLocation++] = (lapicStart & 0x000000FF) >> 0; + bytes[patchLocation++] = (lapicStart & 0x0000FF00) >> 8; + bytes[patchLocation++] = (lapicStart & 0x00FF0000) >> 16; + bytes[patchLocation++] = (lapicStart & 0xFF000000) >> 24; + */ + patchLocation += 6; + + // 81 c2 60 03 00 00 -> addl $0x00000320,%edx + /* + bytes[patchLocation++] = 0x81; + bytes[patchLocation++] = 0xC2; + */ + patchLocation += 2; + bytes[patchLocation++] = 0x60; + /* + bytes[patchLocation++];// = 0x03; + bytes[patchLocation++];// = 0x00; + bytes[patchLocation++];// = 0x00; + */ + patchLocation += 3; + + // c7 02 00 04 00 00 -> movl $0x00000400,(%edx) + bytes[patchLocation++] = 0xC7; + bytes[patchLocation++] = 0x02; + bytes[patchLocation++] = 0x00; + bytes[patchLocation++] = 0x04; + bytes[patchLocation++] = 0x00; + bytes[patchLocation++] = 0x00; + + // 83 ea 40 -> subl $0x40,edx + bytes[patchLocation++] = 0x83; + bytes[patchLocation++] = 0xEA; + bytes[patchLocation++] = 0x40; + + // a1 __ __ __ __ -> movl _lapic_interrupt_base,%eax + bytes[patchLocation++] = 0xA1; + bytes[patchLocation++] = (lapicInterruptBase & 0x000000FF) >> 0; + bytes[patchLocation++] = (lapicInterruptBase & 0x0000FF00) >> 8; + bytes[patchLocation++] = (lapicInterruptBase & 0x00FF0000) >> 16; + bytes[patchLocation++] = (lapicInterruptBase & 0xFF000000) >> 24; + + // 83 c0 0e -> addl $0x0e,%eax + bytes[patchLocation++] = 0x83; + bytes[patchLocation++] = 0xC0; + bytes[patchLocation++] = 0x0E; + + // 89 02 -> movl %eax,(%edx) + bytes[patchLocation++] = 0x89; + bytes[patchLocation++] = 0x02; + + // 81c230030000 addl $0x00000330,%edx + bytes[patchLocation++] = 0x81; + bytes[patchLocation++] = 0xC2; + bytes[patchLocation++] = 0x30; + bytes[patchLocation++] = 0x03; + bytes[patchLocation++] = 0x00; + bytes[patchLocation++] = 0x00; + + // a1 __ __ __ __ -> movl _lapic_interrupt_base,%eax + bytes[patchLocation++] = 0xA1; + bytes[patchLocation++] = (lapicInterruptBase & 0x000000FF) >> 0; + bytes[patchLocation++] = (lapicInterruptBase & 0x0000FF00) >> 8; + bytes[patchLocation++] = (lapicInterruptBase & 0x00FF0000) >> 16; + bytes[patchLocation++] = (lapicInterruptBase & 0xFF000000) >> 24; + + // 83 c0 0f -> addl $0x0f,%eax + bytes[patchLocation++] = 0x83; + bytes[patchLocation++] = 0xC0; + bytes[patchLocation++] = 0x0F; + + // 89 02 -> movl %eax,(%edx) + bytes[patchLocation++] = 0x89; + bytes[patchLocation++] = 0x02; + + // 83 ea 10 -> subl $0x10,edx + bytes[patchLocation++] = 0x83; + bytes[patchLocation++] = 0xEA; + bytes[patchLocation++] = 0x10; + + // a1 __ __ __ __ -> movl _lapic_interrupt_base,%eax + bytes[patchLocation++] = 0xA1; + bytes[patchLocation++] = (lapicInterruptBase & 0x000000FF) >> 0; + bytes[patchLocation++] = (lapicInterruptBase & 0x0000FF00) >> 8; + bytes[patchLocation++] = (lapicInterruptBase & 0x00FF0000) >> 16; + bytes[patchLocation++] = (lapicInterruptBase & 0xFF000000) >> 24; + + // 83 c0 0c -> addl $0x0c,%eax + bytes[patchLocation++] = 0x83; + bytes[patchLocation++] = 0xC0; + bytes[patchLocation++] = 0x0C; + + // 89 02 -> movl %eax,(%edx) + bytes[patchLocation++] = 0x89; + bytes[patchLocation++] = 0x02; + + // Replace remaining with nops + + + bytes[patchLocation++] = 0x90; + bytes[patchLocation++] = 0x90; + bytes[patchLocation++] = 0x90; + bytes[patchLocation++] = 0x90; + // bytes[patchLocation++] = 0x90; // double check the lenght of the patch... + // bytes[patchLocation++] = 0x90; +} Index: branches/slice/rev749/modules/KernelPatcher/Makefile =================================================================== --- branches/slice/rev749/modules/KernelPatcher/Makefile (revision 0) +++ branches/slice/rev749/modules/KernelPatcher/Makefile (revision 1169) @@ -0,0 +1,42 @@ +MODULE_NAME = KernelPatcher +MODULE_VERSION = "1.0.0" +MODULE_COMPAT_VERSION = "1.0.0" +MODULE_START = _$(MODULE_NAME)_start +MODULE_DEPENDENCIES = + +DIR = KernelPatcher + +MODULE_OBJS = kernel_patcher.o + +OPTIM = -O3 +DEBUG = -DNOTHING +#DEBUG = -DDEBUG_HELLO_WORLD=1 +CFLAGS = $(RC_CFLAGS) $(OPTIM) $(MORECPP) -arch i386 -g -Wmost \ + -D__ARCHITECTURE__=\"i386\" -DSAIO_INTERNAL_USER \ + -DRCZ_COMPRESSED_FILE_SUPPORT $(DEBUG) \ + -fno-builtin $(OMIT_FRAME_POINTER_CFLAG) \ + -mpreferred-stack-boundary=2 -fno-align-functions -fno-stack-protector \ + -march=pentium4 -msse2 -mfpmath=sse -msoft-float -fno-common + +DEFINES= +CONFIG = hd +INC = -I. -I.. -I$(SYMROOT) -I$(UTILDIR) -I$(LIBSADIR) -I$(LIBSAIODIR) -I$(BOOT2DIR) +LIBS= + +VPATH = $(OBJROOT):$(SYMROOT) + + + +SFILES = +CFILES = +HFILES = +EXPORTED_HFILES = +INSTALLED_HFILES = +OTHERFILES = Makefile +ALLSRC = $(SFILES) $(CFILES) \ + $(HFILES) $(OTHERFILES) +DIRS_NEEDED = $(OBJROOT) $(SYMROOT) + +all embedtheme optionrom: dylib + +include ../MakeInc.dir \ No newline at end of file Index: branches/slice/rev749/modules/Networking/Networking.c =================================================================== --- branches/slice/rev749/modules/Networking/Networking.c (revision 0) +++ branches/slice/rev749/modules/Networking/Networking.c (revision 1169) @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2009 Evan Lojewski. All rights reserved. + * + */ + +#include "libsaio.h" +#include "modules.h" +#include "boot.h" +#include "bootstruct.h" +#include "pci.h" +#include "device_inject.h" + +#ifndef DEBUG_ETHERNET +#define DEBUG_ETHERNET 0 +#endif + +#if DEBUG_ETHERNET +#define DBG(x...) verbose(x) +#else +#define DBG(x...) +#endif + +void set_eth_builtin(pci_dt_t *eth_dev); +void set_wifi_airport(pci_dt_t *wlan_dev); + +uint32_t builtin_set = 0; + + + +void Networking_hook(void* arg1, void* arg2, void* arg3, void* arg4) +{ + pci_dt_t* current = arg1; + + if(current->class_id == PCI_CLASS_NETWORK_ETHERNET) + { + // LAN + + bool do_eth_devprop = false; + getBoolForKey(kEthernetBuiltIn, &do_eth_devprop, &bootInfo->bootConfig); + + if (do_eth_devprop) + { + set_eth_builtin(current); + } + } + else if(current->class_id == PCI_CLASS_NETWORK_OTHER) + { + // WIFI + set_wifi_airport(current); + + } + +} + +void Networking_start() +{ + register_hook_callback("PCIDevice", &Networking_hook); +} + +/* a fine place for this code */ + +int devprop_add_network_template(struct DevPropDevice *device, uint16_t vendor_id) +{ + uint8_t builtin = 0x0; + + if(device) + { + + if((vendor_id != 0x168c) && (builtin_set == 0)) + { + builtin_set = 1; + builtin = 0x01; + } + + if(!devprop_add_value(device, "built-in", (uint8_t*)&builtin, 1)) + { + return 0; + } + + devices_number++; + return 1; + } + else + { + return 0; + } + +} + +void set_eth_builtin(pci_dt_t *eth_dev) +{ + char *devicepath = get_pci_dev_path(eth_dev); + struct DevPropDevice *device = (struct DevPropDevice*)malloc(sizeof(struct DevPropDevice)); + + verbose("LAN Controller [%04x:%04x] :: %s\n", eth_dev->vendor_id, eth_dev->device_id, devicepath); + + if (!string) + string = devprop_create_string(); + + device = devprop_add_device(string, devicepath); + if(device) + { + verbose("Setting up lan keys\n"); + devprop_add_network_template(device, eth_dev->vendor_id); + stringdata = (uint8_t*)malloc(sizeof(uint8_t) * string->length); + if(stringdata) + { + memcpy(stringdata, (uint8_t*)devprop_generate_string(string), string->length); + stringlength = string->length; + } + } +} + + +struct wifi_cards +{ + uint16_t vendor_id; + uint16_t device_id; + char* model; +}; + +struct wifi_cards known_wifi_cards[] = +{ + {0x14e4, 0x4315, "Dell Wireless 1395"}, + {0x14e4, 0x432b, "Dell Wireless 1510"}, + {0x168C, 0x002B, "Atheros 9285 8802.11 b/g/n Wireless Network Adapter"}, +}; + +void set_wifi_airport(pci_dt_t *wlan_dev) +{ + char tmp[16]; + + char *devicepath = get_pci_dev_path(wlan_dev); + struct DevPropDevice *device = (struct DevPropDevice*)malloc(sizeof(struct DevPropDevice)); + + verbose("Wifi Controller [%04x:%04x] :: %s\n", wlan_dev->vendor_id, wlan_dev->device_id, devicepath); + + if (!string) + string = devprop_create_string(); + + device = devprop_add_device(string, devicepath); + if(device) + { + sprintf(tmp, "Airport"); + devprop_add_value(device, "AAPL,slot-name", (uint8_t *) tmp, strlen(tmp) + 1); + devprop_add_value(device, "device_type", (uint8_t *) tmp, strlen(tmp) + 1); + + + int i = 0; + for( ; i < sizeof(known_wifi_cards) / sizeof(known_wifi_cards[0]); i++) + { + if(wlan_dev->vendor_id == known_wifi_cards[i].vendor_id && + wlan_dev->device_id == known_wifi_cards[i].device_id) + { + verbose("Setting up wifi keys\n"); + + devprop_add_value(device, "model", (uint8_t*)known_wifi_cards[i].model, (strlen(known_wifi_cards[i].model) + 1)); + + // NOTE: I would set the subsystem id and subsystem vendor id here, + // however, those values seem to be ovverriden in the boot process. + // A batter method would be injecting the DTGP dsdt method + // and then injectinve the subsystem id there. + + stringdata = (uint8_t*)malloc(sizeof(uint8_t) * string->length); + if(stringdata) + { + memcpy(stringdata, (uint8_t*)devprop_generate_string(string), string->length); + stringlength = string->length; + } + + return; + + } + } + + + } +} Index: branches/slice/rev749/modules/Networking/Makefile =================================================================== --- branches/slice/rev749/modules/Networking/Makefile (revision 0) +++ branches/slice/rev749/modules/Networking/Makefile (revision 1169) @@ -0,0 +1,50 @@ +MODULE_NAME = Networking +MODULE_VERSION = "1.0.0" +MODULE_COMPAT_VERSION = "1.0.0" +MODULE_START = _$(MODULE_NAME)_start +MODULE_DEPENDENCIES = + +DIR = Networking + +MODULE_OBJS = Networking.o + +OPTIM = -Os -Oz +DEBUG = -DNOTHING +#DEBUG = -DDEBUG_HELLO_WORLD=1 +CFLAGS = $(RC_CFLAGS) $(OPTIM) $(MORECPP) -arch i386 -g -Wmost \ + -D__ARCHITECTURE__=\"i386\" -DSAIO_INTERNAL_USER \ + -DRCZ_COMPRESSED_FILE_SUPPORT $(DEBUG) \ + -fno-builtin $(OMIT_FRAME_POINTER_CFLAG) \ + -mpreferred-stack-boundary=2 -fno-align-functions -fno-stack-protector \ + -march=pentium4 -msse2 -mfpmath=sse -msoft-float -fno-common + +DEFINES= +CONFIG = hd +INC = -I. -I.. -I$(SYMROOT) -I$(UTILDIR) -I$(LIBSADIR) -I$(LIBSAIODIR) -I$(BOOT2DIR) +ifneq "" "$(wildcard /bin/mkdirs)" + MKDIRS = /bin/mkdirs +else + MKDIRS = /bin/mkdir -p +endif +AS = as +LD = ld +# LIBS= -lc_static +LIBS= + +VPATH = $(OBJROOT):$(SYMROOT) + + + +SFILES = +CFILES = +HFILES = +EXPORTED_HFILES = +INSTALLED_HFILES = +OTHERFILES = Makefile +ALLSRC = $(SFILES) $(CFILES) \ + $(HFILES) $(OTHERFILES) +DIRS_NEEDED = $(OBJROOT) $(SYMROOT) + +all embedtheme optionrom: dylib + +include ../MakeInc.dir \ No newline at end of file Index: branches/slice/rev749/modules/GraphicsEnabler/nvidia.h =================================================================== --- branches/slice/rev749/modules/GraphicsEnabler/nvidia.h (revision 0) +++ branches/slice/rev749/modules/GraphicsEnabler/nvidia.h (revision 1169) @@ -0,0 +1,135 @@ +/* + * NVidia injector + * + * Copyright (C) 2009 Jasmin Fazlic, iNDi + * + * NVidia injector is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * NVidia driver and injector is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with NVidia injector. If not, see . + */ + /* + * Alternatively you can choose to comply with APSL + */ + +/* + * DCB-Table parsing is based on software (nouveau driver) originally distributed under following license: + * + * + * Copyright 2005-2006 Erik Waling + * Copyright 2006 Stephane Marchesin + * Copyright 2007-2009 Stuart Bennett + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __LIBSAIO_NVIDIA_H +#define __LIBSAIO_NVIDIA_H + +bool setup_nvidia_devprop(pci_dt_t *nvda_dev); + +struct nv_chipsets_t { + unsigned device; + char *name; +}; + +#define DCB_MAX_NUM_ENTRIES 16 +#define DCB_MAX_NUM_I2C_ENTRIES 16 + +#define DCB_LOC_ON_CHIP 0 + +struct bios { + uint16_t signature; /* 0x55AA */ + uint8_t size; /* Size in multiples of 512 */ +}; + +#define NV_PROM_OFFSET 0x300000 +#define NV_PROM_SIZE 0x0000ffff +#define NV_PRAMIN_OFFSET 0x00700000 +#define NV_PRAMIN_SIZE 0x00100000 +#define NV04_PFB_FIFO_DATA 0x0010020c +#define NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK 0xfff00000 +#define NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_SHIFT 20 +#define NVC0_MEM_CTRLR_COUNT 0x00121c74 +#define NVC0_MEM_CTRLR_RAM_AMOUNT 0x0010f20c + +#define NV_PBUS_PCI_NV_20 0x00001850 +#define NV_PBUS_PCI_NV_20_ROM_SHADOW_DISABLED (0 << 0) +#define NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED (1 << 0) + +#define REG8(reg) ((volatile uint8_t *)regs)[(reg)] +#define REG16(reg) ((volatile uint16_t *)regs)[(reg) >> 1] +#define REG32(reg) ((volatile uint32_t *)regs)[(reg) >> 2] + +#define NV_ARCH_03 0x03 +#define NV_ARCH_04 0x04 +#define NV_ARCH_10 0x10 +#define NV_ARCH_20 0x20 +#define NV_ARCH_30 0x30 +#define NV_ARCH_40 0x40 +#define NV_ARCH_50 0x50 +#define NV_ARCH_C0 0xC0 + +#define CHIPSET_NV03 0x0010 +#define CHIPSET_NV04 0x0020 +#define CHIPSET_NV10 0x0100 +#define CHIPSET_NV11 0x0110 +#define CHIPSET_NV15 0x0150 +#define CHIPSET_NV17 0x0170 +#define CHIPSET_NV18 0x0180 +#define CHIPSET_NFORCE 0x01A0 +#define CHIPSET_NFORCE2 0x01F0 +#define CHIPSET_NV20 0x0200 +#define CHIPSET_NV25 0x0250 +#define CHIPSET_NV28 0x0280 +#define CHIPSET_NV30 0x0300 +#define CHIPSET_NV31 0x0310 +#define CHIPSET_NV34 0x0320 +#define CHIPSET_NV35 0x0330 +#define CHIPSET_NV36 0x0340 +#define CHIPSET_NV40 0x0040 +#define CHIPSET_NV41 0x00C0 +#define CHIPSET_NV43 0x0140 +#define CHIPSET_NV44 0x0160 +#define CHIPSET_NV44A 0x0220 +#define CHIPSET_NV45 0x0210 +#define CHIPSET_NV50 0x0190 +#define CHIPSET_NV84 0x0400 +#define CHIPSET_MISC_BRIDGED 0x00F0 +#define CHIPSET_G70 0x0090 +#define CHIPSET_G71 0x0290 +#define CHIPSET_G72 0x01D0 +#define CHIPSET_G73 0x0390 + +// integrated GeForces (6100, 6150) +#define CHIPSET_C51 0x0240 + +// variant of C51, seems based on a G70 design +#define CHIPSET_C512 0x03D0 +#define CHIPSET_G73_BRIDGED 0x02E0 + +#endif /* !__LIBSAIO_NVIDIA_H */ Index: branches/slice/rev749/modules/GraphicsEnabler/ati.h =================================================================== --- branches/slice/rev749/modules/GraphicsEnabler/ati.h (revision 0) +++ branches/slice/rev749/modules/GraphicsEnabler/ati.h (revision 1169) @@ -0,0 +1,46 @@ +/* + * ATI injector + * + * Copyright (C) 2009 Jasmin Fazlic, iNDi, netkas + * + * ATI injector is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ATI driver and injector is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ATI injector. If not, see . + */ + /* + * Alternatively you can choose to comply with APSL + */ + + +#ifndef __LIBSAIO_ATI_H +#define __LIBSAIO_ATI_H + +bool setup_ati_devprop(pci_dt_t *ati_dev); + +struct ati_chipsets_t { + unsigned device; + char *name; +}; + +struct ati_data_key { + uint32_t size; + char *name; + uint8_t data[]; +}; + +#define REG8(reg) ((volatile uint8_t *)regs)[(reg)] +#define REG16(reg) ((volatile uint16_t *)regs)[(reg) >> 1] +#define REG32R(reg) ((volatile uint32_t *)regs)[(reg) >> 2] +#define REG32W(reg, val) ((volatile uint32_t *)regs)[(reg) >> 2] = (val) + + +#endif /* !__LIBSAIO_ATI_H */ Index: branches/slice/rev749/modules/GraphicsEnabler/gma.c =================================================================== --- branches/slice/rev749/modules/GraphicsEnabler/gma.c (revision 0) +++ branches/slice/rev749/modules/GraphicsEnabler/gma.c (revision 1169) @@ -0,0 +1,171 @@ +/* +Original patch by nawcom -> http://forum.voodooprojects.org/index.php/topic,1029.msg4427.html#msg4427 +*/ +#include "libsaio.h" +#include "bootstruct.h" +#include "pci.h" +#include "platform.h" +#include "device_inject.h" +#include "gma.h" +#include "graphics.h" + +#ifndef DEBUG_GMA +#define DEBUG_GMA 0 +#endif + +#if DEBUG_GMA +#define DBG(x...) verbose(x) +#else +#define DBG(x...) +#endif +//Slice - correct all values, still not sure +uint8_t GMAX3100_vals[23][4] = { + { 0x01,0x00,0x00,0x00 }, //0 "AAPL,HasPanel" + { 0x01,0x00,0x00,0x00 }, //1 "AAPL,SelfRefreshSupported" + { 0x01,0x00,0x00,0x00 }, //2 "AAPL,aux-power-connected" + { 0x01,0x00,0x00,0x08 }, //3 "AAPL,backlight-control" + { 0x00,0x00,0x00,0x00 }, //4 "AAPL00,blackscreen-preferences" + { 0x56,0x00,0x00,0x08 }, //5 "AAPL01,BacklightIntensity" + { 0x00,0x00,0x00,0x00 }, //6 "AAPL01,blackscreen-preferences" + { 0x01,0x00,0x00,0x00 }, //7 "AAPL01,DataJustify" + { 0x20,0x00,0x00,0x00 }, //8 "AAPL01,Depth" + { 0x01,0x00,0x00,0x00 }, //9 "AAPL01,Dither" + { 0x20,0x03,0x00,0x00 }, //10 "AAPL01,Height" + { 0x00,0x00,0x00,0x00 }, //11 "AAPL01,Interlace" + { 0x00,0x00,0x00,0x00 }, //12 "AAPL01,Inverter" + { 0x08,0x52,0x00,0x00 }, //13 "AAPL01,InverterCurrent" + { 0x00,0x00,0x00,0x00 }, //14 "AAPL01,LinkFormat" + { 0x00,0x00,0x00,0x00 }, //15 "AAPL01,LinkType" + { 0x01,0x00,0x00,0x00 }, //16 "AAPL01,Pipe" + { 0x01,0x00,0x00,0x00 }, //17 "AAPL01,PixelFormat" + { 0x01,0x00,0x00,0x00 }, //18 "AAPL01,Refresh" + { 0x3B,0x00,0x00,0x00 }, //19 "AAPL01,Stretch" + { 0xc8,0x95,0x00,0x00 }, //20 "AAPL01,InverterFrequency" + { 0x6B,0x10,0x00,0x00 }, //21 "subsystem-vendor-id" + { 0xA2,0x00,0x00,0x00 } //22 "subsystem-id" +}; +uint8_t reg_TRUE[] = { 0x01 ,0x00 ,0x00 ,0x00 }; +uint8_t reg_FALSE[] = { 0x00,0x00,0x00,0x00 }; + +static struct gma_gpu_t KnownGPUS[] = { + { 0x00000000, "Unknown" }, + { 0x808627A2, "Mobile GMA950" }, + { 0x808627AE, "Mobile GMA950" }, + { 0x808627A6, "Mobile GMA950" }, + { 0x8086A011, "Mobile GMA3150" }, + { 0x8086A012, "Mobile GMA3150" }, + { 0x80862772, "Desktop GMA950" }, + { 0x80862776, "Desktop GMA950" }, + { 0x8086A001, "Desktop GMA3150" }, + { 0x8086A002, "Desktop GMA3150" }, + { 0x80862A02, "GMAX3100" }, + { 0x80862A03, "GMAX3100" }, + { 0x80862A12, "GMAX3100" }, + { 0x80862A13, "GMAX3100" }, + { 0x80862A42, "GMAX3100" }, + { 0x80862A43, "GMAX3100" }, +}; + +char *get_gma_model(uint32_t id) { + int i=0; + for(i = 0; i < (sizeof(KnownGPUS) / sizeof(KnownGPUS[0])); i++) { + if(KnownGPUS[i].device == id) + return KnownGPUS[i].name; + } + return KnownGPUS[0].name; +} + +bool setup_gma_devprop(pci_dt_t *gma_dev) +{ + //int len; + char *devicepath; + volatile uint8_t *regs; + uint32_t bar[7]; + char *model; + uint8_t BuiltIn = 0x00; + uint8_t ClassFix[4] = { 0x00, 0x00, 0x03, 0x00 }; + + devicepath = get_pci_dev_path(gma_dev); + + bar[0] = pci_config_read32(gma_dev->dev.addr, 0x10); + regs = (uint8_t *) (bar[0] & ~0x0f); + + model = get_gma_model((gma_dev->vendor_id << 16) | gma_dev->device_id); + + verbose("Intel %s [%04x:%04x] :: %s\n", + model, gma_dev->vendor_id, gma_dev->device_id, devicepath); + + if (!string) + string = devprop_create_string(); + struct DevPropDevice *device = malloc(sizeof(struct DevPropDevice)); + device = devprop_add_device(string, devicepath); + + if(!device) + { + verbose("Failed initializing dev-prop string dev-entry, press any key...\n"); + + getc(); + return false; + } + + devprop_add_value(device, "model", (uint8_t*)model, (strlen(model) + 1)); + devprop_add_value(device, "device_type", (uint8_t*)"display", 8); + + if ((model == (char *)"Mobile GMA950") || + (model == (char *)"Mobile GMA3150")) + { + devprop_add_value(device, "AAPL,HasPanel", reg_TRUE, 4); + devprop_add_value(device, "built-in", &BuiltIn, 1); + devprop_add_value(device, "class-code", ClassFix, 4); + } + else if ((model == (char *)"Desktop GMA950") || + (model == (char *)"Desktop GMA3150")) + { + BuiltIn = 0x01; + devprop_add_value(device, "built-in", &BuiltIn, 1); + devprop_add_value(device, "class-code", ClassFix, 4); + } + else if (model == (char *)"GMAX3100") + { + BuiltIn = gDualLink; + devprop_add_value(device, "AAPL,HasPanel",GMAX3100_vals[0], 4); + devprop_add_value(device, "AAPL,SelfRefreshSupported",GMAX3100_vals[1], 4); + devprop_add_value(device, "AAPL,aux-power-connected",GMAX3100_vals[2], 4); + devprop_add_value(device, "AAPL,backlight-control",GMAX3100_vals[3], 4); + devprop_add_value(device, "AAPL00,blackscreen-preferences",GMAX3100_vals[4], 4); + devprop_add_value(device, "AAPL01,BacklightIntensity",GMAX3100_vals[5], 4); + devprop_add_value(device, "AAPL01,blackscreen-preferences",GMAX3100_vals[6], 4); + devprop_add_value(device, "AAPL01,DataJustify",GMAX3100_vals[7], 4); + devprop_add_value(device, "AAPL01,Depth",GMAX3100_vals[8], 4); + devprop_add_value(device, "AAPL01,Dither",GMAX3100_vals[9], 4); + devprop_add_value(device, "AAPL01,DualLink", &BuiltIn, 1); //GMAX3100_vals[10] + devprop_add_value(device, "AAPL01,Height",GMAX3100_vals[10], 4); + devprop_add_value(device, "AAPL01,Interlace",GMAX3100_vals[11], 4); + devprop_add_value(device, "AAPL01,Inverter",GMAX3100_vals[12], 4); + devprop_add_value(device, "AAPL01,InverterCurrent",GMAX3100_vals[13], 4); +// devprop_add_value(device, "AAPL01,InverterCurrency",GMAX3100_vals[15], 4); + devprop_add_value(device, "AAPL01,LinkFormat",GMAX3100_vals[14], 4); + devprop_add_value(device, "AAPL01,LinkType",GMAX3100_vals[15], 4); + devprop_add_value(device, "AAPL01,Pipe",GMAX3100_vals[16], 4); + devprop_add_value(device, "AAPL01,PixelFormat",GMAX3100_vals[17], 4); + devprop_add_value(device, "AAPL01,Refresh",GMAX3100_vals[18], 4); + devprop_add_value(device, "AAPL01,Stretch",GMAX3100_vals[19], 4); + devprop_add_value(device, "AAPL01,InverterFrequency",GMAX3100_vals[20], 4); + devprop_add_value(device, "class-code", ClassFix, 4); + devprop_add_value(device, "subsystem-vendor-id", GMAX3100_vals[21], 4); + devprop_add_value(device, "subsystem-id", GMAX3100_vals[22], 4); + } + + stringdata = malloc(sizeof(uint8_t) * string->length); + if(!stringdata) + { + verbose("no GMA stringdata press a key...\n"); + getc(); + return false; + } + + memcpy(stringdata, (uint8_t*)devprop_generate_string(string), string->length); + stringlength = string->length; + + return true; +} Index: branches/slice/rev749/modules/GraphicsEnabler/GraphicsEnabler.c =================================================================== --- branches/slice/rev749/modules/GraphicsEnabler/GraphicsEnabler.c (revision 0) +++ branches/slice/rev749/modules/GraphicsEnabler/GraphicsEnabler.c (revision 1169) @@ -0,0 +1,63 @@ +/* + * GraphicsEnabler Module + * Enabled many nvidia and ati cards to be used out of the box in + * OS X. This was converted from boot2 code to a boot2 module. + * + */ + +#include "libsaio.h" +#include "pci.h" +#include "bootstruct.h" +#include "nvidia.h" +#include "ati.h" +#include "gma.h" +#include "modules.h" + + +#define kGraphicsEnabler "GraphicsEnabler" + + +void GraphicsEnabler_hook(void* arg1, void* arg2, void* arg3, void* arg4); + +void GraphicsEnabler_start() +{ + register_hook_callback("PCIDevice", &GraphicsEnabler_hook); +} + + +void GraphicsEnabler_hook(void* arg1, void* arg2, void* arg3, void* arg4) +{ + pci_dt_t* current = arg1; + if(current && current->class_id == PCI_CLASS_DISPLAY_VGA) + { + char *devicepath = get_pci_dev_path(current); + + bool do_gfx_devprop = true; + getBoolForKey(kGraphicsEnabler, &do_gfx_devprop, &bootInfo->bootConfig); + + if (do_gfx_devprop) + { + switch (current->vendor_id) + { + case PCI_VENDOR_ID_ATI: + verbose("ATI VGA Controller [%04x:%04x] :: %s \n", + current->vendor_id, current->device_id, devicepath); + setup_ati_devprop(current); + break; + + case PCI_VENDOR_ID_INTEL: + verbose("Intel VGA Controller [%04x:%04x] :: %s \n", + current->vendor_id, current->device_id, devicepath); + setup_gma_devprop(current); + break; + + case PCI_VENDOR_ID_NVIDIA: + verbose("NVidia VGA Controller [%04x:%04x] :: %s \n", + current->vendor_id, current->device_id, devicepath); + setup_nvidia_devprop(current); + break; + } + } + + } +} Index: branches/slice/rev749/modules/GraphicsEnabler/gma.h =================================================================== --- branches/slice/rev749/modules/GraphicsEnabler/gma.h (revision 0) +++ branches/slice/rev749/modules/GraphicsEnabler/gma.h (revision 1169) @@ -0,0 +1,16 @@ +#ifndef __LIBSAIO_GMA_H +#define __LIBSAIO_GMA_H + +bool setup_gma_devprop(pci_dt_t *gma_dev); + +struct gma_gpu_t { + unsigned device; + char *name; +}; + +#define REG8(reg) ((volatile uint8_t *)regs)[(reg)] +#define REG16(reg) ((volatile uint16_t *)regs)[(reg) >> 1] +#define REG32(reg) ((volatile uint32_t *)regs)[(reg) >> 2] + + +#endif /* !__LIBSAIO_GMA_H */ Index: branches/slice/rev749/modules/GraphicsEnabler/nvidia.c =================================================================== --- branches/slice/rev749/modules/GraphicsEnabler/nvidia.c (revision 0) +++ branches/slice/rev749/modules/GraphicsEnabler/nvidia.c (revision 1169) @@ -0,0 +1,994 @@ +/* + * NVidia injector + * + * Copyright (C) 2009 Jasmin Fazlic, iNDi + * + * NVidia injector is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * NVidia driver and injector is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with NVidia injector. If not, see . + */ +/* + * Alternatively you can choose to comply with APSL + */ + + +/* + * DCB-Table parsing is based on software (nouveau driver) originally distributed under following license: + * + * + * Copyright 2005-2006 Erik Waling + * Copyright 2006 Stephane Marchesin + * Copyright 2007-2009 Stuart Bennett + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "libsaio.h" +#include "boot.h" +#include "bootstruct.h" +#include "pci.h" +#include "platform.h" +#include "device_inject.h" +#include "nvidia.h" + +#ifndef DEBUG_NVIDIA +#define DEBUG_NVIDIA 0 +#endif + +#if DEBUG_NVIDIA +#define DBG(x...) verbose(x) +#else +#define DBG(x...) +#endif + +#define NVIDIA_ROM_SIZE 0x10000 +#define PATCH_ROM_SUCCESS 1 +#define PATCH_ROM_SUCCESS_HAS_LVDS 2 +#define PATCH_ROM_FAILED 0 +#define MAX_NUM_DCB_ENTRIES 16 + +#define TYPE_GROUPED 0xff + +extern uint32_t devices_number; + +const char *nvidia_compatible_0[] = { "@0,compatible", "NVDA,NVMac" }; +const char *nvidia_compatible_1[] = { "@1,compatible", "NVDA,NVMac" }; +const char *nvidia_device_type_0[] = { "@0,device_type", "display" }; +const char *nvidia_device_type_1[] = { "@1,device_type", "display" }; +const char *nvidia_device_type[] = { "device_type", "NVDA,Parent" }; +const char *nvidia_name_0[] = { "@0,name", "NVDA,Display-A" }; +const char *nvidia_name_1[] = { "@1,name", "NVDA,Display-B" }; +const char *nvidia_slot_name[] = { "AAPL,slot-name", "Slot-1" }; + +uint8_t display_cfg_0[]= {0x03, 0x01, 0x03, 0x00}; +uint8_t display_cfg_1[]= {0xff, 0xff, 0x00, 0x01}; + + +uint8_t default_NVCAP[]= { + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, + 0x00, 0x00, 0x00, 0x00 +}; + +static uint8_t default_NVPM[]= { + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; + + +#define NVCAP_LEN ( sizeof(default_NVCAP) / sizeof(uint8_t) ) +#define NVPM_LEN ( sizeof(default_NVPM) / sizeof(uint8_t) ) + +struct nv_chipsets_t NVKnownChipsets[] = { + { 0x00000000, "Unknown" }, + { 0x10DE0301, "GeForce FX 5800 Ultra" }, + { 0x10DE0302, "GeForce FX 5800" }, + { 0x10DE0308, "Quadro FX 2000" }, + { 0x10DE0309, "Quadro FX 1000" }, + { 0x10DE0311, "GeForce FX 5600 Ultra" }, + { 0x10DE0312, "GeForce FX 5600" }, + { 0x10DE0314, "GeForce FX 5600XT" }, + { 0x10DE031A, "GeForce FX Go5600" }, + { 0x10DE031B, "GeForce FX Go5650" }, + { 0x10DE031C, "Quadro FX Go700" }, + { 0x10DE0324, "GeForce FX Go5200" }, + { 0x10DE0325, "GeForce FX Go5250" }, + { 0x10DE0326, "GeForce FX 5500" }, + { 0x10DE0328, "GeForce FX Go5200 32M/64M" }, + { 0x10DE032A, "Quadro NVS 55/280 PCI" }, + { 0x10DE032B, "Quadro FX 500/600 PCI" }, + { 0x10DE032C, "GeForce FX Go53xx Series" }, + { 0x10DE032D, "GeForce FX Go5100" }, + { 0x10DE0330, "GeForce FX 5900 Ultra" }, + { 0x10DE0331, "GeForce FX 5900" }, + { 0x10DE0332, "GeForce FX 5900XT" }, + { 0x10DE0333, "GeForce FX 5950 Ultra" }, + { 0x10DE0334, "GeForce FX 5900ZT" }, + { 0x10DE0338, "Quadro FX 3000" }, + { 0x10DE033F, "Quadro FX 700" }, + { 0x10DE0341, "GeForce FX 5700 Ultra" }, + { 0x10DE0342, "GeForce FX 5700" }, + { 0x10DE0343, "GeForce FX 5700LE" }, + { 0x10DE0344, "GeForce FX 5700VE" }, + { 0x10DE0347, "GeForce FX Go5700" }, + { 0x10DE0348, "GeForce FX Go5700" }, + { 0x10DE034C, "Quadro FX Go1000" }, + { 0x10DE034E, "Quadro FX 1100" }, + { 0x10DE0040, "GeForce 6800 Ultra" }, + { 0x10DE0041, "GeForce 6800" }, + { 0x10DE0042, "GeForce 6800 LE" }, + { 0x10DE0043, "GeForce 6800 XE" }, + { 0x10DE0044, "GeForce 6800 XT" }, + { 0x10DE0045, "GeForce 6800 GT" }, + { 0x10DE0046, "GeForce 6800 GT" }, + { 0x10DE0047, "GeForce 6800 GS" }, + { 0x10DE0048, "GeForce 6800 XT" }, + { 0x10DE004E, "Quadro FX 4000" }, + { 0x10DE0090, "GeForce 7800 GTX" }, + { 0x10DE0091, "GeForce 7800 GTX" }, + { 0x10DE0092, "GeForce 7800 GT" }, + { 0x10DE0093, "GeForce 7800 GS" }, + { 0x10DE0095, "GeForce 7800 SLI" }, + { 0x10DE0098, "GeForce Go 7800" }, + { 0x10DE0099, "GeForce Go 7800 GTX" }, + { 0x10DE009D, "Quadro FX 4500" }, + { 0x10DE00C0, "GeForce 6800 GS" }, + { 0x10DE00C1, "GeForce 6800" }, + { 0x10DE00C2, "GeForce 6800 LE" }, + { 0x10DE00C3, "GeForce 6800 XT" }, + { 0x10DE00C8, "GeForce Go 6800" }, + { 0x10DE00C9, "GeForce Go 6800 Ultra" }, + { 0x10DE00CC, "Quadro FX Go1400" }, + { 0x10DE00CD, "Quadro FX 3450/4000 SDI" }, + { 0x10DE00CE, "Quadro FX 1400" }, + { 0x10DE0140, "GeForce 6600 GT" }, + { 0x10DE0141, "GeForce 6600" }, + { 0x10DE0142, "GeForce 6600 LE" }, + { 0x10DE0143, "GeForce 6600 VE" }, + { 0x10DE0144, "GeForce Go 6600" }, + { 0x10DE0145, "GeForce 6610 XL" }, + { 0x10DE0146, "GeForce Go 6600 TE/6200 TE" }, + { 0x10DE0147, "GeForce 6700 XL" }, + { 0x10DE0148, "GeForce Go 6600" }, + { 0x10DE0149, "GeForce Go 6600 GT" }, + { 0x10DE014C, "Quadro FX 550" }, + { 0x10DE014D, "Quadro FX 550" }, + { 0x10DE014E, "Quadro FX 540" }, + { 0x10DE014F, "GeForce 6200" }, + { 0x10DE0160, "GeForce 6500" }, + { 0x10DE0161, "GeForce 6200 TurboCache(TM)" }, + { 0x10DE0162, "GeForce 6200SE TurboCache(TM)" }, + { 0x10DE0163, "GeForce 6200 LE" }, + { 0x10DE0164, "GeForce Go 6200" }, + { 0x10DE0165, "Quadro NVS 285" }, + { 0x10DE0166, "GeForce Go 6400" }, + { 0x10DE0167, "GeForce Go 6200" }, + { 0x10DE0168, "GeForce Go 6400" }, + { 0x10DE0169, "GeForce 6250" }, + { 0x10DE016A, "GeForce 7100 GS" }, + { 0x10DE0191, "GeForce 8800 GTX" }, + { 0x10DE0193, "GeForce 8800 GTS" }, + { 0x10DE0194, "GeForce 8800 Ultra" }, + { 0x10DE019D, "Quadro FX 5600" }, + { 0x10DE019E, "Quadro FX 4600" }, + { 0x10DE01D1, "GeForce 7300 LE" }, + { 0x10DE01D3, "GeForce 7300 SE" }, + { 0x10DE01D6, "GeForce Go 7200" }, + { 0x10DE01D7, "GeForce Go 7300" }, + { 0x10DE01D8, "GeForce Go 7400" }, + { 0x10DE01D9, "GeForce Go 7400 GS" }, + { 0x10DE01DA, "Quadro NVS 110M" }, + { 0x10DE01DB, "Quadro NVS 120M" }, + { 0x10DE01DC, "Quadro FX 350M" }, + { 0x10DE01DD, "GeForce 7500 LE" }, + { 0x10DE01DE, "Quadro FX 350" }, + { 0x10DE01DF, "GeForce 7300 GS" }, + { 0x10DE0211, "GeForce 6800" }, + { 0x10DE0212, "GeForce 6800 LE" }, + { 0x10DE0215, "GeForce 6800 GT" }, + { 0x10DE0218, "GeForce 6800 XT" }, + { 0x10DE0221, "GeForce 6200" }, + { 0x10DE0222, "GeForce 6200 A-LE" }, + { 0x10DE0240, "GeForce 6150" }, + { 0x10DE0241, "GeForce 6150 LE" }, + { 0x10DE0242, "GeForce 6100" }, + { 0x10DE0244, "GeForce Go 6150" }, + { 0x10DE0247, "GeForce Go 6100" }, + { 0x10DE0290, "GeForce 7900 GTX" }, + { 0x10DE0291, "GeForce 7900 GT" }, + { 0x10DE0292, "GeForce 7900 GS" }, + { 0x10DE0298, "GeForce Go 7900 GS" }, + { 0x10DE0299, "GeForce Go 7900 GTX" }, + { 0x10DE029A, "Quadro FX 2500M" }, + { 0x10DE029B, "Quadro FX 1500M" }, + { 0x10DE029C, "Quadro FX 5500" }, + { 0x10DE029D, "Quadro FX 3500" }, + { 0x10DE029E, "Quadro FX 1500" }, + { 0x10DE029F, "Quadro FX 4500 X2" }, + { 0x10DE0301, "GeForce FX 5800 Ultra" }, + { 0x10DE0302, "GeForce FX 5800" }, + { 0x10DE0308, "Quadro FX 2000" }, + { 0x10DE0309, "Quadro FX 1000" }, + { 0x10DE0311, "GeForce FX 5600 Ultra" }, + { 0x10DE0312, "GeForce FX 5600" }, + { 0x10DE0314, "GeForce FX 5600XT" }, + { 0x10DE031A, "GeForce FX Go5600" }, + { 0x10DE031B, "GeForce FX Go5650" }, + { 0x10DE031C, "Quadro FX Go700" }, + { 0x10DE0324, "GeForce FX Go5200" }, + { 0x10DE0325, "GeForce FX Go5250" }, + { 0x10DE0326, "GeForce FX 5500" }, + { 0x10DE0328, "GeForce FX Go5200 32M/64M" }, + { 0x10DE032A, "Quadro NVS 55/280 PCI" }, + { 0x10DE032B, "Quadro FX 500/600 PCI" }, + { 0x10DE032C, "GeForce FX Go53xx Series" }, + { 0x10DE032D, "GeForce FX Go5100" }, + { 0x10DE0330, "GeForce FX 5900 Ultra" }, + { 0x10DE0331, "GeForce FX 5900" }, + { 0x10DE0332, "GeForce FX 5900XT" }, + { 0x10DE0333, "GeForce FX 5950 Ultra" }, + { 0x10DE0334, "GeForce FX 5900ZT" }, + { 0x10DE0338, "Quadro FX 3000" }, + { 0x10DE033F, "Quadro FX 700" }, + { 0x10DE0341, "GeForce FX 5700 Ultra" }, + { 0x10DE0342, "GeForce FX 5700" }, + { 0x10DE0343, "GeForce FX 5700LE" }, + { 0x10DE0344, "GeForce FX 5700VE" }, + { 0x10DE0347, "GeForce FX Go5700" }, + { 0x10DE0348, "GeForce FX Go5700" }, + { 0x10DE034C, "Quadro FX Go1000" }, + { 0x10DE034E, "Quadro FX 1100" }, + { 0x10DE0391, "GeForce 7600 GT" }, + { 0x10DE0392, "GeForce 7600 GS" }, + { 0x10DE0393, "GeForce 7300 GT" }, + { 0x10DE0394, "GeForce 7600 LE" }, + { 0x10DE0395, "GeForce 7300 GT" }, + { 0x10DE0397, "GeForce Go 7700" }, + { 0x10DE0398, "GeForce Go 7600" }, + { 0x10DE0399, "GeForce Go 7600 GT"}, + { 0x10DE039A, "Quadro NVS 300M" }, + { 0x10DE039B, "GeForce Go 7900 SE" }, + { 0x10DE039C, "Quadro FX 550M" }, + { 0x10DE039E, "Quadro FX 560" }, + { 0x10DE0400, "GeForce 8600 GTS" }, + { 0x10DE0401, "GeForce 8600 GT" }, + { 0x10DE0402, "GeForce 8600 GT" }, + { 0x10DE0403, "GeForce 8600 GS" }, + { 0x10DE0404, "GeForce 8400 GS" }, + { 0x10DE0405, "GeForce 9500M GS" }, + { 0x10DE0407, "GeForce 8600M GT" }, + { 0x10DE0408, "GeForce 9650M GS" }, + { 0x10DE0409, "GeForce 8700M GT" }, + { 0x10DE040A, "Quadro FX 370" }, + { 0x10DE040B, "Quadro NVS 320M" }, + { 0x10DE040C, "Quadro FX 570M" }, + { 0x10DE040D, "Quadro FX 1600M" }, + { 0x10DE040E, "Quadro FX 570" }, + { 0x10DE040F, "Quadro FX 1700" }, + { 0x10DE0420, "GeForce 8400 SE" }, + { 0x10DE0421, "GeForce 8500 GT" }, + { 0x10DE0422, "GeForce 8400 GS" }, + { 0x10DE0423, "GeForce 8300 GS" }, + { 0x10DE0424, "GeForce 8400 GS" }, + { 0x10DE0425, "GeForce 8600M GS" }, + { 0x10DE0426, "GeForce 8400M GT" }, + { 0x10DE0427, "GeForce 8400M GS" }, + { 0x10DE0428, "GeForce 8400M G" }, + { 0x10DE0429, "Quadro NVS 140M" }, + { 0x10DE042A, "Quadro NVS 130M" }, + { 0x10DE042B, "Quadro NVS 135M" }, + { 0x10DE042C, "GeForce 9400 GT" }, + { 0x10DE042D, "Quadro FX 360M" }, + { 0x10DE042E, "GeForce 9300M G" }, + { 0x10DE042F, "Quadro NVS 290" }, + { 0x10DE05E0, "GeForce GTX 295" }, + { 0x10DE05E1, "GeForce GTX 280" }, + { 0x10DE05E2, "GeForce GTX 260" }, + { 0x10DE05E3, "GeForce GTX 285" }, + { 0x10DE05E6, "GeForce GTX 275" }, + { 0x10DE05EA, "GeForce GTX 260" }, + { 0x10DE05EB, "GeForce GTX 295" }, + { 0x10DE05F9, "Quadro CX" }, + { 0x10DE05FD, "Quadro FX 5800" }, + { 0x10DE05FE, "Quadro FX 4800" }, + { 0x10DE0600, "GeForce 8800 GTS 512" }, + { 0x10DE0602, "GeForce 8800 GT" }, + { 0x10DE0604, "GeForce 9800 GX2" }, + { 0x10DE0605, "GeForce 9800 GT" }, + { 0x10DE0606, "GeForce 8800 GS" }, + { 0x10DE0607, "GeForce GTS 240" }, + { 0x10DE0608, "GeForce 9800M GTX" }, + { 0x10DE0609, "GeForce 8800M GTS" }, + { 0x10DE060A, "GeForce GTX 280M" }, + { 0x10DE060B, "GeForce 9800M GT" }, + { 0x10DE060C, "GeForce 8800M GTX" }, + { 0x10DE060D, "GeForce 8800 GS" }, + { 0x10DE0610, "GeForce 9600 GSO" }, + { 0x10DE0611, "GeForce 8800 GT" }, + { 0x10DE0612, "GeForce 9800 GTX" }, + { 0x10DE0613, "GeForce 9800 GTX+" }, + { 0x10DE0614, "GeForce 9800 GT" }, + { 0x10DE0615, "GeForce GTS 250" }, + { 0x10DE0617, "GeForce 9800M GTX" }, + { 0x10DE0618, "GeForce GTX 260M" }, + { 0x10DE061A, "Quadro FX 3700" }, + { 0x10DE061C, "Quadro FX 3600M" }, + { 0x10DE061D, "Quadro FX 2800M" }, + { 0x10DE061F, "Quadro FX 3800M" }, + { 0x10DE0622, "GeForce 9600 GT" }, + { 0x10DE0623, "GeForce 9600 GS" }, + { 0x10DE0625, "GeForce 9600 GSO 512"}, + { 0x10DE0626, "GeForce GT 130" }, + { 0x10DE0627, "GeForce GT 140" }, + { 0x10DE0628, "GeForce 9800M GTS" }, + { 0x10DE062A, "GeForce 9700M GTS" }, + { 0x10DE062C, "GeForce 9800M GTS" }, + { 0x10DE0640, "GeForce 9500 GT" }, + { 0x10DE0641, "GeForce 9400 GT" }, + { 0x10DE0642, "GeForce 8400 GS" }, + { 0x10DE0643, "GeForce 9500 GT" }, + { 0x10DE0644, "GeForce 9500 GS" }, + { 0x10DE0645, "GeForce 9500 GS" }, + { 0x10DE0646, "GeForce GT 120" }, + { 0x10DE0647, "GeForce 9600M GT" }, + { 0x10DE0648, "GeForce 9600M GS" }, + { 0x10DE0649, "GeForce 9600M GT" }, + { 0x10DE064A, "GeForce 9700M GT" }, + { 0x10DE064B, "GeForce 9500M G" }, + { 0x10DE064C, "GeForce 9650M GT" }, + { 0x10DE0652, "GeForce GT 130M" }, + { 0x10DE0658, "Quadro FX 380" }, + { 0x10DE0659, "Quadro FX 580" }, + { 0x10DE065A, "Quadro FX 1700M" }, + { 0x10DE065B, "GeForce 9400 GT" }, + { 0x10DE065C, "Quadro FX 770M" }, + { 0x10DE06C0, "GeForce GTX 480" }, + { 0x10DE06C3, "GeForce GTX D12U" }, + { 0x10DE06C4, "GeForce GTX 465" }, + { 0x10DE06CA, "GeForce GTX 480M" }, + { 0x10DE06CD, "GeForce GTX 470" }, + { 0x10DE06D1, "Tesla C2050" }, // TODO: sub-device id: 0x0771 + { 0x10DE06D1, "Tesla C2070" }, // TODO: sub-device id: 0x0772 + { 0x10DE06D2, "Tesla M2070" }, + { 0x10DE06D8, "Quadro 6000" }, + { 0x10DE06D9, "Quadro 5000" }, + { 0x10DE06DA, "Quadro 5000M" }, + { 0x10DE06DC, "Quadro 6000" }, + { 0x10DE06DD, "Quadro 4000" }, + { 0x10DE06DE, "Tesla M2050" }, // TODO: sub-device id: 0x0846 + { 0x10DE06DE, "Tesla M2070" }, // TODO: sub-device id: ? + // 0x10DE06DE also applies to misc S2050, X2070, M2050, M2070 + { 0x10DE06E0, "GeForce 9300 GE" }, + { 0x10DE06E1, "GeForce 9300 GS" }, + { 0x10DE06E4, "GeForce 8400 GS" }, + { 0x10DE06E5, "GeForce 9300M GS" }, + { 0x10DE06E8, "GeForce 9200M GS" }, + { 0x10DE06E9, "GeForce 9300M GS" }, + { 0x10DE06EA, "Quadro NVS 150M" }, + { 0x10DE06EB, "Quadro NVS 160M" }, + { 0x10DE06EC, "GeForce G 105M" }, + { 0x10DE06EF, "GeForce G 103M" }, + { 0x10DE06F8, "Quadro NVS 420" }, + { 0x10DE06F9, "Quadro FX 370 LP" }, + { 0x10DE06FA, "Quadro NVS 450" }, + { 0x10DE06FD, "Quadro NVS 295" }, + { 0x10DE086A, "GeForce 9400" }, + { 0x10DE0874, "ION 9300M" }, + { 0x10DE086C, "GeForce 9300/nForce 730i" }, + { 0x10DE0876, "ION 9400M" }, + { 0x10DE087D, "ION 9400M" }, + { 0x10DE087E, "ION LE" }, + { 0x10DE0A20, "GeForce GT220" }, + { 0x10DE0A23, "GeForce 210" }, + { 0x10DE0A28, "GeForce GT 230M" }, + { 0x10DE0A29, "GeForce GT 330M" }, + { 0x10DE0A2A, "GeForce GT 230M" }, + { 0x10DE0A34, "GeForce GT 240M" }, + { 0x10DE0A60, "GeForce G210" }, + { 0x10DE0A62, "GeForce 205" }, + { 0x10DE0A63, "GeForce 310" }, + { 0x10DE0A65, "GeForce 210" }, + { 0x10DE0A66, "GeForce 310" }, + { 0x10DE0A74, "GeForce G210M" }, + { 0x10DE0A75, "GeForce G310M" }, + { 0x10DE0A78, "Quadro FX 380 LP" }, + { 0x10DE0CA3, "GeForce GT 240" }, + { 0x10DE0CA8, "GeForce GTS 260M" }, + { 0x10DE0CA9, "GeForce GTS 250M" }, + { 0x10DE0CB1, "GeForce GTS 360M" }, + { 0x10DE0CA3, "GeForce GT240" }, + + { 0x10DE0DC0, "GeForce GT 440" }, + { 0x10DE0DC1, "D12-P1-35" }, + { 0x10DE0DC2, "D12-P1-35" }, + { 0x10DE0DC4, "GeForce GTS 450" }, + { 0x10DE0DC5, "GeForce GTS 450" }, + { 0x10DE0DC6, "GeForce GTS 450" }, + { 0x10DE0DCA, "GF10x" }, + { 0x10DE0DD1, "GeForce GTX 460M" }, + { 0x10DE0DD2, "GeForce GT 445M" }, + { 0x10DE0DD3, "GeForce GT 435M" }, + { 0x10DE0DD8, "Quadro 2000" }, + { 0x10DE0DDE, "GF106-ES" }, + { 0x10DE0DDF, "GF106-INT" }, + { 0x10DE0DE1, "GeForce GT 430" }, + { 0x10DE0DE2, "GeForce GT 420" }, + { 0x10DE0DEB, "GeForce GT 555M" }, + { 0x10DE0DEE, "GeForce GT 415M" }, + { 0x10DE0DF0, "GeForce GT 425M" }, + { 0x10DE0DF1, "GeForce GT 420M" }, + { 0x10DE0DF2, "GeForce GT 435M" }, + { 0x10DE0DF3, "GeForce GT 420M" }, + { 0x10DE0DF8, "Quadro 600" }, + { 0x10DE0DFE, "GF108 ES" }, + { 0x10DE0DFF, "GF108 INT" }, + + // 0E20 - 0E3F + { 0x10DE0E21, "D12U-25" }, + { 0x10DE0E22, "GeForce GTX 460" }, + { 0x10DE0E23, "GeForce GTX 460 SE" }, + { 0x10DE0E24, "GeForce GTX 460" }, + { 0x10DE0E25, "D12U-50" }, + { 0x10DE0E30, "GeForce GTX 470M" }, + { 0x10DE0E38, "GF104GL" }, + { 0x10DE0E3E, "GF104-ES" }, + { 0x10DE0E3F, "GF104-INT" }, + + // 0EE0 - 0EFF: none yet + // 0F00 - 0F3F: none yet + // 1040 - 107F: none yet + + // 1080 - 109F + { 0x10DE1080, "GeForce GTX 580" }, + { 0x10DE1081, "D13U" }, + { 0x10DE1082, "D13U" }, + { 0x10DE1083, "D13U" }, + { 0x10DE1098, "D13U" }, + { 0x10DE109A, "N12E-Q5" } +}; + +static uint16_t swap16(uint16_t x) +{ + return (((x & 0x00FF) << 8) | ((x & 0xFF00) >> 8)); +} + +static uint16_t read16(uint8_t *ptr, uint16_t offset) +{ + uint8_t ret[2]; + ret[0] = ptr[offset+1]; + ret[1] = ptr[offset]; + return *((uint16_t*)&ret); +} + +#if 0 +static uint32_t swap32(uint32_t x) +{ + return ((x & 0x000000FF) << 24) | ((x & 0x0000FF00) << 8 ) | ((x & 0x00FF0000) >> 8 ) | ((x & 0xFF000000) >> 24); +} + +static uint8_t read8(uint8_t *ptr, uint16_t offset) +{ + return ptr[offset]; +} + +static uint32_t read32(uint8_t *ptr, uint16_t offset) +{ + uint8_t ret[4]; + ret[0] = ptr[offset+3]; + ret[1] = ptr[offset+2]; + ret[2] = ptr[offset+1]; + ret[3] = ptr[offset]; + return *((uint32_t*)&ret); +} +#endif + +static int patch_nvidia_rom(uint8_t *rom) +{ + if (!rom || (rom[0] != 0x55 && rom[1] != 0xaa)) { + verbose("False ROM signature: 0x%02x%02x\n", rom[0], rom[1]); + return PATCH_ROM_FAILED; + } + + uint16_t dcbptr = swap16(read16(rom, 0x36)); + if(!dcbptr) { + verbose("no dcb table found\n"); + return PATCH_ROM_FAILED; + }/* else + verbose("dcb table at offset 0x%04x\n", dcbptr); + */ + uint8_t *dcbtable = &rom[dcbptr]; + uint8_t dcbtable_version = dcbtable[0]; + uint8_t headerlength = 0; + uint8_t recordlength = 0; + uint8_t numentries = 0; + + if(dcbtable_version >= 0x20) { + uint32_t sig; + + if(dcbtable_version >= 0x30) { + headerlength = dcbtable[1]; + numentries = dcbtable[2]; + recordlength = dcbtable[3]; + sig = *(uint32_t *)&dcbtable[6]; + } else { + sig = *(uint32_t *)&dcbtable[4]; + headerlength = 8; + } + if (sig != 0x4edcbdcb) { + verbose("bad display config block signature (0x%8x)\n", sig); + return PATCH_ROM_FAILED; + } + } else if (dcbtable_version >= 0x14) { /* some NV15/16, and NV11+ */ + char sig[8] = { 0 }; + + strncpy(sig, (char *)&dcbtable[-7], 7); + recordlength = 10; + if (strcmp(sig, "DEV_REC")) { + verbose("Bad Display Configuration Block signature (%s)\n", sig); + return PATCH_ROM_FAILED; + } + } else { + verbose("ERROR: dcbtable_version is 0x%X\n", dcbtable_version); + return PATCH_ROM_FAILED; + } + + if(numentries >= MAX_NUM_DCB_ENTRIES) + numentries = MAX_NUM_DCB_ENTRIES; + + uint8_t num_outputs = 0, i=0; + struct dcbentry { + uint8_t type; + uint8_t index; + uint8_t *heads; + } entries[numentries]; + + for (i = 0; i < numentries; i++) { + uint32_t connection; + connection = *(uint32_t *)&dcbtable[headerlength + recordlength * i]; + /* Should we allow discontinuous DCBs? Certainly DCB I2C tables can be discontinuous */ + if ((connection & 0x0000000f) == 0x0000000f) /* end of records */ + continue; + if (connection == 0x00000000) /* seen on an NV11 with DCB v1.5 */ + continue; + if ((connection & 0xf) == 0x6) /* we skip type 6 as it doesnt appear on macbook nvcaps */ + continue; + + entries[num_outputs].type = connection & 0xf; + entries[num_outputs].index = num_outputs; + entries[num_outputs++].heads = (uint8_t*)&(dcbtable[(headerlength + recordlength * i) + 1]); + + } + + int has_lvds = false; + uint8_t channel1 = 0, channel2 = 0; + + for(i=0; i channel2) { + uint8_t buff = channel1; + channel1 = channel2; + channel2 = buff; + } + + default_NVCAP[6] = channel1; + default_NVCAP[8] = channel2; + + // patching HEADS + for(i=0; i bufsize) { + printf("Filesize of %s is bigger than expected! Truncating to 0x%x Bytes!\n", filename, bufsize); + size = bufsize; + } + size = read(fd, (char *)buf, size); + close(fd); + return size > 0 ? size : 0; +} + +static int devprop_add_nvidia_template(struct DevPropDevice *device) +{ + char tmp[16]; + + if(!device) + return 0; + + if(!DP_ADD_TEMP_VAL(device, nvidia_compatible_0)) + return 0; + if(!DP_ADD_TEMP_VAL(device, nvidia_device_type_0)) + return 0; + if(!DP_ADD_TEMP_VAL(device, nvidia_name_0)) + return 0; + if(!DP_ADD_TEMP_VAL(device, nvidia_compatible_1)) + return 0; + if(!DP_ADD_TEMP_VAL(device, nvidia_device_type_1)) + return 0; + if(!DP_ADD_TEMP_VAL(device, nvidia_name_1)) + return 0; + if(!DP_ADD_TEMP_VAL(device, nvidia_device_type)) + return 0; + // Rek : Dont use sprintf return, it does not WORK !! our custom sprintf() always return 0! + // len = sprintf(tmp, "Slot-%x", devices_number); + sprintf(tmp, "Slot-%x",devices_number); + devprop_add_value(device, "AAPL,slot-name", (uint8_t *) tmp, strlen(tmp)); + devices_number++; + + return 1; +} + +int hex2bin(const char *hex, uint8_t *bin, int len) +{ + char *p; + int i; + char buf[3]; + + if (hex == NULL || bin == NULL || len <= 0 || strlen(hex) != len * 2) { + verbose("[ERROR] bin2hex input error\n"); + return -1; + } + + buf[2] = '\0'; + p = (char *) hex; + for (i=0; i= NV_ARCH_C0 + vram_size = REG32(NVC0_MEM_CTRLR_RAM_AMOUNT) << 20; + vram_size *= REG32(NVC0_MEM_CTRLR_COUNT); + } + + return vram_size; +} + +bool setup_nvidia_devprop(pci_dt_t *nvda_dev) +{ + struct DevPropDevice *device; + char *devicepath; + struct pci_rom_pci_header_t *rom_pci_header; + volatile uint8_t *regs; + uint8_t *rom; + uint8_t *nvRom; + uint8_t nvCardType; + unsigned long long videoRam; + uint32_t nvBiosOveride; + uint32_t bar[7]; + uint32_t boot_display; + int nvPatch; + int len; + char biosVersion[32]; + char nvFilename[32]; + char kNVCAP[12]; + char *model; + const char *value; + bool doit; + + devicepath = get_pci_dev_path(nvda_dev); + bar[0] = pci_config_read32(nvda_dev->dev.addr, 0x10 ); + regs = (uint8_t *) (bar[0] & ~0x0f); + + delay(50); + + // get card type + nvCardType = (REG32(0) >> 20) & 0x1ff; + + // Amount of VRAM in kilobytes + videoRam = mem_detect(regs, nvCardType, nvda_dev); + model = get_nvidia_model((nvda_dev->vendor_id << 16) | nvda_dev->device_id); + + verbose("nVidia %s %dMB NV%02x [%04x:%04x] :: %s\n", + model, (uint32_t)(videoRam / 1024 / 1024), + (REG32(0) >> 20) & 0x1ff, nvda_dev->vendor_id, nvda_dev->device_id, + devicepath); + + rom = malloc(NVIDIA_ROM_SIZE); + sprintf(nvFilename, "bt(0,0)/Extra/%04x_%04x.rom", (uint16_t)nvda_dev->vendor_id, (uint16_t)nvda_dev->device_id); + if (getBoolForKey(kUseNvidiaROM, &doit, &bootInfo->bootConfig) && doit) { + verbose("Looking for nvidia video bios file %s\n", nvFilename); + nvBiosOveride = load_nvidia_bios_file(nvFilename, rom, NVIDIA_ROM_SIZE); + if (nvBiosOveride > 0) { + verbose("Using nVidia Video BIOS File %s (%d Bytes)\n", nvFilename, nvBiosOveride); + DBG("%s Signature 0x%02x%02x %d bytes\n", nvFilename, rom[0], rom[1], nvBiosOveride); + } else { + verbose("ERROR: unable to open nVidia Video BIOS File %s\n", nvFilename); + return false; + } + } else { + // Otherwise read bios from card + nvBiosOveride = 0; + + // TODO: we should really check for the signature before copying the rom, i think. + + // PRAMIN first + nvRom = (uint8_t*)®s[NV_PRAMIN_OFFSET]; + bcopy((uint32_t *)nvRom, rom, NVIDIA_ROM_SIZE); + + // Valid Signature ? + if (rom[0] != 0x55 && rom[1] != 0xaa) { + // PROM next + // Enable PROM access + (REG32(NV_PBUS_PCI_NV_20)) = NV_PBUS_PCI_NV_20_ROM_SHADOW_DISABLED; + + nvRom = (uint8_t*)®s[NV_PROM_OFFSET]; + bcopy((uint8_t *)nvRom, rom, NVIDIA_ROM_SIZE); + + // disable PROM access + (REG32(NV_PBUS_PCI_NV_20)) = NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED; + + // Valid Signature ? + if (rom[0] != 0x55 && rom[1] != 0xaa) { + // 0xC0000 last + bcopy((char *)0xc0000, rom, NVIDIA_ROM_SIZE); + + // Valid Signature ? + if (rom[0] != 0x55 && rom[1] != 0xaa) { + verbose("ERROR: Unable to locate nVidia Video BIOS\n"); + return false; + } else { + DBG("ROM Address 0x%x Signature 0x%02x%02x\n", nvRom, rom[0], rom[1]); + } + } else { + DBG("PROM Address 0x%x Signature 0x%02x%02x\n", nvRom, rom[0], rom[1]); + } + } else { + DBG("PRAM Address 0x%x Signature 0x%02x%02x\n", nvRom, rom[0], rom[1]); + } + } + + if ((nvPatch = patch_nvidia_rom(rom)) == PATCH_ROM_FAILED) { + verbose("ERROR: nVidia ROM Patching Failed!\n"); + return false; + } + + rom_pci_header = (struct pci_rom_pci_header_t*)(rom + *(uint16_t *)&rom[24]); + + // check for 'PCIR' sig + if (rom_pci_header->signature == 0x50434952) { + if (rom_pci_header->device != nvda_dev->device_id) { + // Get Model from the OpROM + model = get_nvidia_model((rom_pci_header->vendor << 16) | rom_pci_header->device); + } else { + verbose("nVidia incorrect PCI ROM signature: 0x%x\n", rom_pci_header->signature); + } + } + + if (!string) { + string = devprop_create_string(); + } + device = devprop_add_device(string, devicepath); + + /* FIXME: for primary graphics card only */ + boot_display = 1; + devprop_add_value(device, "@0,AAPL,boot-display", (uint8_t*)&boot_display, 4); + + if(nvPatch == PATCH_ROM_SUCCESS_HAS_LVDS) { + uint8_t built_in = 0x01; + devprop_add_value(device, "@0,built-in", &built_in, 1); + } + + // get bios version + const int MAX_BIOS_VERSION_LENGTH = 32; + char* version_str = (char*)malloc(MAX_BIOS_VERSION_LENGTH); + memset(version_str, 0, MAX_BIOS_VERSION_LENGTH); + int i, version_start; + int crlf_count = 0; + // only search the first 384 bytes + for(i = 0; i < 0x180; i++) { + if(rom[i] == 0x0D && rom[i+1] == 0x0A) { + crlf_count++; + // second 0x0D0A was found, extract bios version + if(crlf_count == 2) { + if(rom[i-1] == 0x20) i--; // strip last " " + for(version_start = i; version_start > (i-MAX_BIOS_VERSION_LENGTH); version_start--) { + // find start + if(rom[version_start] == 0x00) { + version_start++; + + // strip "Version " + if(strncmp((const char*)rom+version_start, "Version ", 8) == 0) { + version_start += 8; + } + + strncpy(version_str, (const char*)rom+version_start, i-version_start); + break; + } + } + break; + } + } + } + + sprintf(biosVersion, "%s", (nvBiosOveride > 0) ? nvFilename : version_str); + + sprintf(kNVCAP, "NVCAP_%04x", nvda_dev->device_id); + if (getValueForKey(kNVCAP, &value, &len, &bootInfo->bootConfig) && len == NVCAP_LEN * 2) { + uint8_t new_NVCAP[NVCAP_LEN]; + + if (hex2bin(value, new_NVCAP, NVCAP_LEN) == 0) { + verbose("Using user supplied NVCAP for %s :: %s\n", model, devicepath); + memcpy(default_NVCAP, new_NVCAP, NVCAP_LEN); + } + } + + #if 1 //DEBUG_NVCAP + verbose("NVCAP: %02x%02x%02x%02x-%02x%02x%02x%02x-%02x%02x%02x%02x-%02x%02x%02x%02x-%02x%02x%02x%02x\n", + default_NVCAP[0], default_NVCAP[1], default_NVCAP[2], default_NVCAP[3], + default_NVCAP[4], default_NVCAP[5], default_NVCAP[6], default_NVCAP[7], + default_NVCAP[8], default_NVCAP[9], default_NVCAP[10], default_NVCAP[11], + default_NVCAP[12], default_NVCAP[13], default_NVCAP[14], default_NVCAP[15], + default_NVCAP[16], default_NVCAP[17], default_NVCAP[18], default_NVCAP[19]); +#endif + + + devprop_add_nvidia_template(device); + devprop_add_value(device, "NVCAP", default_NVCAP, NVCAP_LEN); + devprop_add_value(device, "NVPM", default_NVPM, NVPM_LEN); + devprop_add_value(device, "VRAM,totalsize", (uint8_t*)&videoRam, 4); + devprop_add_value(device, "model", (uint8_t*)model, strlen(model) + 1); + devprop_add_value(device, "rom-revision", (uint8_t*)biosVersion, strlen(biosVersion) + 1); + + devprop_add_value(device, "@0,display-cfg", display_cfg_0, 4); + devprop_add_value(device, "@1,display-cfg", display_cfg_1, 4); + + + if (getBoolForKey(kVBIOS, &doit, &bootInfo->bootConfig) && doit) { + devprop_add_value(device, "vbios", rom, (nvBiosOveride > 0) ? nvBiosOveride : (rom[2] * 512)); + } + + stringdata = malloc(sizeof(uint8_t) * string->length); + memcpy(stringdata, (uint8_t*)devprop_generate_string(string), string->length); + stringlength = string->length; + + return true; +} Index: branches/slice/rev749/modules/GraphicsEnabler/Makefile =================================================================== --- branches/slice/rev749/modules/GraphicsEnabler/Makefile (revision 0) +++ branches/slice/rev749/modules/GraphicsEnabler/Makefile (revision 1169) @@ -0,0 +1,41 @@ +MODULE_NAME = GraphicsEnabler +MODULE_VERSION = "1.0.0" +MODULE_COMPAT_VERSION = "1.0.0" +MODULE_START = _$(MODULE_NAME)_start +MODULE_DEPENDENCIES = + +DIR = GraphicsEnabler + +MODULE_OBJS = nvidia.o ati.o gma.o GraphicsEnabler.o + +OPTIM = -Os -Oz +DEBUG = -DNOTHING +#DEBUG = -DDEBUG_HELLO_WORLD=1 +CFLAGS = $(RC_CFLAGS) $(OPTIM) $(MORECPP) -arch i386 -g -Wmost \ + -D__ARCHITECTURE__=\"i386\" -DSAIO_INTERNAL_USER \ + -DRCZ_COMPRESSED_FILE_SUPPORT $(DEBUG) \ + -fno-builtin $(OMIT_FRAME_POINTER_CFLAG) \ + -mpreferred-stack-boundary=2 -fno-align-functions -fno-stack-protector \ + -march=pentium4 -msse2 -mfpmath=sse -msoft-float -fno-common + +DEFINES= +CONFIG = hd +INC = -I. -I.. -I$(SYMROOT) -I$(UTILDIR) -I$(LIBSADIR) -I$(LIBSAIODIR) -I$(BOOT2DIR) +LIBS= + +VPATH = $(OBJROOT):$(SYMROOT) + +SFILES = +CFILES = +HFILES = +EXPORTED_HFILES = +INSTALLED_HFILES = +OTHERFILES = Makefile +ALLSRC = $(SFILES) $(CFILES) \ + $(HFILES) $(OTHERFILES) +DIRS_NEEDED = $(OBJROOT) $(SYMROOT) + +all embedtheme optionrom: dylib + + +include ../MakeInc.dir Index: branches/slice/rev749/modules/GraphicsEnabler/ati.c =================================================================== --- branches/slice/rev749/modules/GraphicsEnabler/ati.c (revision 0) +++ branches/slice/rev749/modules/GraphicsEnabler/ati.c (revision 1169) @@ -0,0 +1,819 @@ +/* + * ATI injector + * + * Copyright (C) 2009 Jasmin Fazlic, iNDi, netkas + * + * ATI injector is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ATI driver and injector is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ATI injector. If not, see . + */ +/* + * Alternatively you can choose to comply with APSL + */ + + +#include "libsaio.h" +#include "boot.h" +#include "bootstruct.h" +#include "pci.h" +#include "platform.h" +#include "device_inject.h" +#include "ati.h" + +#ifndef DEBUG_ATI +#define DEBUG_ATI 0 +#endif + +#if DEBUG_ATI +#define DBG(x...) verbose(x) +#else +#define DBG(x...) +#endif + +#define MAX_NUM_DCB_ENTRIES 16 + +#define TYPE_GROUPED 0xff + +extern uint32_t devices_number; + +const char *ati_compatible_0[] = { "@0,compatible", "ATY,%s" }; +const char *ati_compatible_1[] = { "@1,compatible", "ATY,%s" }; +const char *ati_device_type_0[] = { "@0,device_type", "display" }; +const char *ati_device_type_1[] = { "@1,device_type", "display" }; +const char *ati_device_type[] = { "device_type", "ATY,%sParent" }; +const char *ati_name_0[] = { "@0,name", "ATY,%s" }; +const char *ati_name_1[] = { "@1,name", "ATY,%s" }; +const char *ati_name[] = { "name", "ATY,%sParent" }; +const char *ati_efidisplay_0[] = { "@0,ATY,EFIDisplay", "TMDSB" }; +struct ati_data_key ati_connector_type_0 = { 0x04, "@0,connector-type", {0x00, 0x04, 0x00, 0x00} }; +struct ati_data_key ati_connector_type_1 = { 0x04, "@1,connector-type", {0x04, 0x00, 0x00, 0x00} }; +struct ati_data_key ati_display_con_fl_type_0 = { 0x04, "@0,display-connect-flags", {0x00, 0x00, 0x04, 0x00} }; +const char *ati_display_type_0[] = { "@0,display-type", "LCD" }; +const char *ati_display_type_1[] = { "@1,display-type", "NONE" }; +struct ati_data_key ati_aux_power_conn = { 0x04, "AAPL,aux-power-connected", {0x01, 0x00, 0x00, 0x00} }; +struct ati_data_key ati_backlight_ctrl = { 0x04, "AAPL,backlight-control", {0x00, 0x00, 0x00, 0x00} }; +struct ati_data_key ati_aapl01_coher = { 0x04, "AAPL01,Coherency", {0x01, 0x00, 0x00, 0x00} }; +const char *ati_card_no[] = { "ATY,Card#", "109-B77101-00" }; +const char *ati_copyright[] = { "ATY,Copyright", "Copyright AMD Inc. All Rights Reserved. 2005-2009" }; +const char *ati_efi_compile_d[] = { "ATY,EFICompileDate", "Jan 26 2009" }; +struct ati_data_key ati_efi_disp_conf = { 0x08, "ATY,EFIDispConfig", {0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01} }; +struct ati_data_key ati_efi_drv_type = { 0x01, "ATY,EFIDriverType", {0x02} }; +struct ati_data_key ati_efi_enbl_mode = { 0x01, "ATY,EFIEnabledMode", {0x01} }; +struct ati_data_key ati_efi_init_stat = { 0x04, "ATY,EFIHWInitStatus", {0x00, 0x00, 0x00, 0x00} }; +struct ati_data_key ati_efi_orientation = { 0x02, "ATY,EFIOrientation", {0x02, 0x00} }; +const char *ati_efi_version[] = { "ATY,EFIVersion", "01.00.318" }; +const char *ati_efi_versionB[] = { "ATY,EFIVersionB", "113-SBSJ1G04-00R-02" }; +const char *ati_efi_versionE[] = { "ATY,EFIVersionE", "113-B7710A-318" }; +struct ati_data_key ati_mclk = { 0x04, "ATY,MCLK", {0x70, 0x2e, 0x11, 0x00} }; //"ATY,MCLK" = 0x186a0 +struct ati_data_key ati_mem_rev_id = { 0x02, "ATY,MemRevisionID", {0x03, 0x00} }; +struct ati_data_key ati_mem_vend_id = { 0x02, "ATY,MemVendorID", {0x02, 0x00} }; +const char *ati_mrt[] = { "ATY,MRT", " " }; +const char *ati_romno[] = { "ATY,Rom#", "113-B7710C-176" }; +struct ati_data_key ati_sclk = { 0x04, "ATY,SCLK", {0x28, 0xdb, 0x0b, 0x00} }; //"ATY,SCLK" = 0x11b33 +struct ati_data_key ati_vendor_id = { 0x02, "ATY,VendorID", {0x02, 0x10} }; +struct ati_data_key ati_platform_info = { 0x80, "ATY,PlatformInfo", {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }; +struct ati_data_key ati_mvad = { 0x40, "MVAD", {0x3f, 0x5c, 0x82, 0x02, 0xff, 0x90, 0x00, 0x54, 0x60, 0x00, 0xac, 0x10, 0xa0, 0x17, 0x00, 0x03, 0xb0, 0x68, 0x00, 0x0a, 0xa0, 0x0a, 0x30, 0x00, 0x20, 0x00, 0x40, 0x06, 0x6e, 0x06, 0x03, 0x00, 0x06, 0x00, 0x40, 0x06, 0x00, 0x0a, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x10, 0x06, 0x92, 0x20, 0x00, 0x03} }; +struct ati_data_key ati_saved_config = { 0x100, "saved-config", {0x3f, 0x5c, 0x82, 0x02, 0xff, 0x90, 0x00, 0x54, 0x60, 0x00, 0xac, 0x10, 0xa0, 0x17, 0x00, 0x03, 0xb0, 0x68, 0x00, 0x0a, 0xa0, 0x0a, 0x30, 0x00, 0x20, 0x00, 0x40, 0x06, 0x6e, 0x06, 0x03, 0x00, 0x06, 0x00, 0x40, 0x06, 0x00, 0x0a, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x10, 0x06, 0x92, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xee, 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x31, 0x30, 0x50, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x32, 0x32, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }; +///non 48xx keys +const char *ati_efidisplay_0_n4[] = { "@0,ATY,EFIDisplay", "TMDSA" }; +struct ati_data_key ati_connector_type_0_n4 = { 0x04, "@0,connector-type", {0x04, 0x00, 0x00, 0x00} }; +struct ati_data_key ati_connector_type_1_n4 = { 0x04, "@1,connector-type", {0x00, 0x02, 0x00, 0x00} }; +struct ati_data_key ati_aapl_emc_disp_list_n4 = { 0x40, "AAPL,EMC-Display-List", {0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10, 0x00, 0x00, 0x1b, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10, 0x00, 0x00, 0x1c, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10, 0x00, 0x00, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }; +struct ati_data_key ati_fb_offset_n4 = { 0x08, "ATY,FrameBufferOffset", {0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00} }; +struct ati_data_key ati_hwgpio_n4 = { 0x04, "ATY,HWGPIO", {0x23, 0xa8, 0x48, 0x00} }; +struct ati_data_key ati_iospace_offset_n4 = { 0x08, "ATY,IOSpaceOffset", {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00} }; +struct ati_data_key ati_mclk_n4 = { 0x04, "ATY,MCLK", {0x00, 0x35, 0x0c, 0x00} }; //"ATY,MCLK" = 0x186a0 +struct ati_data_key ati_sclk_n4 = { 0x04, "ATY,SCLK", {0x60, 0xae, 0x0a, 0x00} }; //"ATY,SCLK" = 0x11b33 (HD5850) +struct ati_data_key ati_refclk_n4 = { 0x04, "ATY,RefCLK", {0x8c, 0x0a, 0x00, 0x00} }; +struct ati_data_key ati_regspace_offset_n4 = { 0x08, "ATY,RegisterSpaceOffset", {0x00, 0x00, 0x00, 0x00, 0x90, 0xa2, 0x00, 0x00} }; +struct ati_data_key ati_vram_memsize_0 = { 0x08, "@0,VRAM,memsize", {0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00} }; +struct ati_data_key ati_vram_memsize_1 = { 0x08, "@1,VRAM,memsize", {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }; +struct ati_data_key ati_aapl_blackscr_prefs_0_n4= { 0x04, "AAPL00,blackscreen-preferences", {0x00, 0x00, 0x00, 0x00} }; +struct ati_data_key ati_aapl_blackscr_prefs_1_n4= { 0x04, "AAPL01,blackscreen-preferences", {0x00, 0x00, 0x00, 0x00} }; +struct ati_data_key ati_swgpio_info_n4 = { 0x04, "ATY,SWGPIO Info", {0x00, 0x48, 0xa8, 0x23} }; +struct ati_data_key ati_efi_orientation_n4 = { 0x01, "ATY,EFIOrientation", {0x08} }; +struct ati_data_key ati_mvad_n4 = { 0x100, "MVAD", {0x3e, 0x5c, 0x82, 0x00, 0xff, 0x90, 0x00, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x3c, 0x80, 0x07, 0x20, 0x08, 0x30, 0x00, 0x20, 0x00, 0xb0, 0x04, 0xd3, 0x04, 0x03, 0x00, 0x06, 0x00, 0xb0, 0x04, 0x80, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x90, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x31, 0x30, 0x50, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x32, 0x32, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }; +struct ati_data_key ati_saved_config_n4 = { 0x100, "saved-config", {0x3e, 0x5c, 0x82, 0x00, 0xff, 0x90, 0x00, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x3c, 0x80, 0x07, 0x20, 0x08, 0x30, 0x00, 0x20, 0x00, 0xb0, 0x04, 0xd3, 0x04, 0x03, 0x00, 0x06, 0x00, 0xb0, 0x04, 0x80, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x90, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x31, 0x30, 0x50, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x32, 0x32, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }; + +struct pcir_s { + uint32_t signature; + uint16_t vid; + uint16_t devid; +}; + +// Known cards as of 2008/08/26 +struct ati_chipsets_t ATIKnownChipsets[] = { + { 0x00000000, "Unknown" } , + { 0x10029588, "ATI Radeon 2600 Series"} , + { 0x10029589, "ATI Radeon 3600 Series"} , + { 0x10029591, "ATI Radeon 3600 Series"} , + { 0x100294C1, "ATI Radeon 2400XT Series"} , + { 0x100294C3, "ATI Radeon 2400 Series"} , + { 0x100294C4, "ATI Radeon 2400 Series"} , + { 0x100294C6, "ATI Radeon 2400 Series"} , + { 0x10029400, "ATI Radeon 2900 Series"} , + { 0x10029405, "ATI Radeon 2900GT Series"} , + { 0x10029581, "ATI Radeon 2600 Series"} , + { 0x10029583, "ATI Radeon 2600 Series"} , + { 0x10029586, "ATI Radeon 2600 Series"} , + { 0x10029587, "ATI Radeon 2600 Series"} , + { 0x100294C9, "ATI Radeon 2400 Series"} , + { 0x10029501, "ATI Radeon 3800 Series"} , + { 0x10029505, "ATI Radeon 3800 Series"} , + { 0x10029515, "ATI Radeon 3800 Series"} , + { 0x10029507, "ATI Radeon 3800 Series"} , + { 0x10029500, "ATI Radeon 3800 Series"} , + { 0x1002950F, "ATI Radeon 3800X2 Series"} , + { 0x100295C5, "ATI Radeon 3400 Series"} , + { 0x100295C7, "ATI Radeon 3400 Series"} , + { 0x100295C0, "ATI Radeon 3400 Series"} , + { 0x10029590, "ATI Radeon 3600 Series"} , + { 0x10029596, "ATI Radeon 3600 Series"} , + { 0x10029599, "ATI Radeon 3600 Series"} , + { 0x10029597, "ATI Radeon 3600 Series"} , + { 0x10029598, "ATI Radeon 3600 Series"} , + { 0x10029442, "ATI Radeon 4850 Series"} , + { 0x10029440, "ATI Radeon 4870 Series"} , + { 0x1002944C, "ATI Radeon 4830 Series"} , + { 0x10029460, "ATI Radeon 4890 Series"} , + { 0x10029462, "ATI Radeon 4890 Series"} , + { 0x10029441, "ATI Radeon 4870X2 Series"} , + { 0x10029443, "ATI Radeon 4850X2 Series"} , + { 0x10029444, "ATI Radeon 4800 Series"} , + { 0x10029446, "ATI Radeon 4800 Series"} , + { 0x1002944E, "ATI Radeon 4730 Series"} , + { 0x10029450, "ATI Radeon 4800 Series"} , + { 0x10029452, "ATI Radeon 4800 Series"} , + { 0x10029456, "ATI Radeon 4800 Series"} , + { 0x1002944A, "ATI Radeon 4800 Mobility Series"} , + { 0x1002945A, "ATI Radeon 4800 Mobility Series"} , + { 0x1002945B, "ATI Radeon 4800 Mobility Series"} , + { 0x1002944B, "ATI Radeon 4800 Mobility Series"} , + { 0x10029490, "ATI Radeon 4670 Series"} , + { 0x10029498, "ATI Radeon 4650 Series"} , + { 0x1002949E, "ATI Radeon 4600 Series"} , + { 0x10029480, "ATI Radeon 4600 Series"} , + { 0x10029488, "ATI Radeon 4600 Series"} , + { 0x100294B3, "ATI Radeon 4770 Series"} , + { 0x100294B5, "ATI Radeon 4770 Series"} , + { 0x10029540, "ATI Radeon 4500 Series"} , + { 0x10029541, "ATI Radeon 4500 Series"} , + { 0x1002954E, "ATI Radeon 4500 Series"} , + { 0x1002954F, "ATI Radeon 4300 Series"} , + { 0x10029552, "ATI Radeon 4300 Mobility Series"} , + { 0x10029553, "ATI Radeon 4500 Mobility Series"} , + { 0x10029610, "ATI Radeon 3200 Mobility Series"} , + { 0x10029611, "ATI Radeon 3100 Mobility Series"} , + { 0x10029614, "ATI Radeon 3300 Mobility Series"} , + { 0x10029616, "AMD 760G Series"} , + { 0x10029710, "ATI Radeon 4200 Mobility Series"} , + { 0x10029714, "ATI Radeon 4290 Mobility Series"} , + { 0x10029715, "ATI Radeon 4250 Mobility Series"} , + + { 0x100268B8, "ATI Radeon 5770 Series"} , + { 0x100268BE, "ATI Radeon 5750 Series"} , + { 0x10026898, "ATI Radeon 5870 Series"} , + { 0x10026899, "ATI Radeon 5850 Series"}, + { 0x1002689C, "ATI Radeon 5870 Series"} , + { 0x100268D8, "ATI Radeon 5690 Series"}, + { 0x100268D9, "ATI Radeon 5670 Series"}, + { 0x100268C0, "ATI Radeon 5670 Series"}, + { 0x100268DA, "ATI Radeon 5630 Series"}, + { 0x100268F9, "ATI Radeon 5470 Series"} +}; + +struct ati_chipsets_t ATIKnownFramebuffers[] = { + { 0x00000000, "Megalodon" }, + { 0x10029588, "Lamna"} , + { 0x10029589, "Lamna"} , + { 0x10029591, "Lamna"} , + { 0x100294C1, "Iago"} , + { 0x100294C3, "Iago"} , + { 0x100294C4, "Iago"} , + { 0x100294C6, "Iago"} , + { 0x10029400, "Iago"} , + { 0x10029405, "Iago"} , + { 0x10029581, "Hypoprion"} , + { 0x10029583, "Hypoprion"} , + { 0x10029586, "Hypoprion"} , + { 0x10029587, "Hypoprion"} , + { 0x100294C9, "Iago"} , + { 0x10029501, "Megalodon"} , + { 0x10029505, "Megalodon"} , + { 0x10029515, "Megalodon"} , + { 0x10029507, "Megalodon"} , + { 0x10029500, "Megalodon"} , + { 0x1002950F, "Triakis"} , + { 0x100295C5, "Iago"} , + { 0x100295C7, "Iago"} , + { 0x100295C0, "Iago"} , + { 0x10029590, "Megalodon"} , + { 0x10029596, "Megalodon"} , + { 0x10029599, "Megalodon"} , + { 0x10029597, "Megalodon"} , + { 0x10029598, "Megalodon"} , + { 0x10029442, "Motmot"} , + { 0x10029440, "Motmot"} , + { 0x1002944C, "Motmot"} , + { 0x10029460, "Motmot"} , + { 0x10029462, "Motmot"} , + { 0x10029441, "Motmot"} , + { 0x10029443, "Motmot"} , + { 0x10029444, "Motmot"} , + { 0x10029446, "Motmot"} , + { 0x1002944E, "Motmot"} , + { 0x10029450, "Motmot"} , + { 0x10029452, "Motmot"} , + { 0x10029456, "Motmot"} , + { 0x1002944A, "Motmot"} , + { 0x1002945A, "Motmot"} , + { 0x1002945B, "Motmot"} , + { 0x1002944B, "Motmot"} , + { 0x10029480, "Peregrine"} , + { 0x10029488, "Peregrine"} , + { 0x10029490, "Flicker"} , + { 0x10029498, "Flicker"} , + { 0x1002949E, "Flicker"} , + { 0x100294B3, "Flicker"}, + { 0x100294B5, "Flicker"}, + { 0x10029540, "Peregrine"} , + { 0x10029541, "Peregrine"} , + { 0x1002954E, "Peregrine"} , + { 0x1002954F, "Peregrine"} , + { 0x10029552, "Peregrine"} , + { 0x10029553, "Peregrine"} , + { 0x10029610, "ATI Radeon 3200 Mobility Series"} , + { 0x10029611, "ATI Radeon 3100 Mobility Series"} , + { 0x10029614, "ATI Radeon 3300 Mobility Series"} , + { 0x10029616, "AMD 760G Series"} , + { 0x10029710, "ATI Radeon 4200 Mobility Series"} , + { 0x10029714, "ATI Radeon 4290 Mobility Series"} , + { 0x10029715, "ATI Radeon 4250 Mobility Series"} , + { 0x100268B8, "Vervet"}, + { 0x100268BE, "Vervet"}, + { 0x10026898, "Uakari"}, + { 0x10026899, "Uakari"}, + { 0x1002689C, "Baboon"}, + { 0x100268D8, "Baboon"}, + { 0x100268D9, "Baboon"}, + { 0x100268DA, "Baboon"}, + { 0x100268C0, "Galago"}, + { 0x100268F9, "Baboon"} +}; + +static uint32_t accessROM(pci_dt_t *ati_dev, unsigned int mode) +{ + uint32_t bar[7]; + volatile uint32_t *regs; + + bar[2] = pci_config_read32(ati_dev->dev.addr, 0x18 ); + regs = (uint32_t *) (bar[2] & ~0x0f); + + if (mode) { + if (mode != 1) { + return 0xe00002c7; + } + REG32W(0x179c, 0x00080000); + REG32W(0x1798, 0x00080721); + REG32W(0x17a0, 0x00080621); + REG32W(0x1600, 0x14030300); + REG32W(0x1798, 0x21); + REG32W(0x17a0, 0x21); + REG32W(0x179c, 0x00); + REG32W(0x17a0, 0x21); + REG32W(0x1798, 0x21); + REG32W(0x1798, 0x21); + } else { + REG32W(0x1600, 0x14030302); + REG32W(0x1798, 0x21); + REG32W(0x17a0, 0x21); + REG32W(0x179c, 0x00080000); + REG32W(0x17a0, 0x00080621); + REG32W(0x1798, 0x00080721); + REG32W(0x1798, 0x21); + REG32W(0x17a0, 0x21); + REG32W(0x179c, 0x00); + REG32W(0x1604, 0x0400e9fc); + REG32W(0x161c, 0x00); + REG32W(0x1620, 0x9f); + REG32W(0x1618, 0x00040004); + REG32W(0x161c, 0x00); + REG32W(0x1604, 0xe9fc); + REG32W(0x179c, 0x00080000); + REG32W(0x1798, 0x00080721); + REG32W(0x17a0, 0x00080621); + REG32W(0x1798, 0x21); + REG32W(0x17a0, 0x21); + REG32W(0x179c, 0x00); + } + return 0; +} + +static uint8_t *readAtomBIOS(pci_dt_t *ati_dev) +{ + uint32_t bar[7]; + uint32_t *BIOSBase = NULL; + uint32_t counter; + volatile uint32_t *regs; + + bar[2] = pci_config_read32(ati_dev->dev.addr, 0x18 ); + regs = (volatile uint32_t *) (bar[2] & ~0x0f); + accessROM(ati_dev, 0); + REG32W(0xa8, 0); + REG32R(0xac); + REG32W(0xa8, 0); + REG32R(0xac); + + BIOSBase = malloc(0x10000); + if(BIOSBase) + { + REG32W(0xa8, 0); + BIOSBase[0] = REG32R(0xac); + counter = 4; + do { + REG32W(0xa8, counter); + BIOSBase[counter/4] = REG32R(0xac); + counter +=4; + } + while(counter != 0x10000); + } + accessROM((pci_dt_t *)regs, 1); + + if (*(uint16_t *)BIOSBase != 0xAA55) { + //Slice + verbose("Wrong BIOS signature: %04x\n", *(uint16_t *)BIOSBase); + return 0; + } + return (uint8_t *)BIOSBase; +} + +#define R5XX_CONFIG_MEMSIZE 0x00F8 +#define R6XX_CONFIG_MEMSIZE 0x5428 + +uint32_t getvramsizekb(pci_dt_t *ati_dev) +{ + uint32_t bar[7]; + uint32_t size = 0; + volatile uint32_t *regs; + + bar[2] = pci_config_read32(ati_dev->dev.addr, 0x18 ); + regs = (uint32_t *) (bar[2] & ~0x0f); + if (ati_dev->device_id < 0x9400) { + size = (REG32R(R5XX_CONFIG_MEMSIZE)) >> 10; + } else { + size = (REG32R(R6XX_CONFIG_MEMSIZE)) >> 10; + } + return size; +} + +#define AVIVO_D1CRTC_CONTROL 0x6080 +#define AVIVO_CRTC_EN (1<<0) +#define AVIVO_D2CRTC_CONTROL 0x6880 + +static bool radeon_card_posted(pci_dt_t *ati_dev) +{ + // if devid matches biosimage(from legacy) devid - posted card, fails with X2/crossfire cards. + /* char *biosimage = 0xC0000; + + if ((uint8_t)biosimage[0] == 0x55 && (uint8_t)biosimage[1] == 0xaa) + { + struct pci_rom_pci_header_t *rom_pci_header; + rom_pci_header = (struct pci_rom_pci_header_t*)(biosimage + (uint8_t)biosimage[24] + (uint8_t)biosimage[25]*256); + + if (rom_pci_header->signature == 0x52494350) + { + if (rom_pci_header->device == ati_dev->device_id) + { + return true; + printf("Card was POSTed\n"); + } + } + } + return false; + printf("Card was not POSTed\n"); + */ + //fails yet + uint32_t bar[7]; + uint32_t val; + volatile uint32_t *regs; + + bar[2] = pci_config_read32(ati_dev->dev.addr, 0x18); + regs = (uint32_t *) (bar[2] & ~0x0f); + + val = REG32R(AVIVO_D1CRTC_CONTROL) | REG32R(AVIVO_D2CRTC_CONTROL); + if (val & AVIVO_CRTC_EN) { + return true; + } + + return false; +} + +static uint32_t load_ati_bios_file(const char *filename, uint8_t *buf, int bufsize) +{ + int fd; + int size; + + if ((fd = open_bvdev("bt(0,0)", filename, 0)) < 0) { + return 0; + } + size = file_size(fd); + if (size > bufsize) { + printf("Filesize of %s is bigger than expected! Truncating to 0x%x Bytes!\n", filename, bufsize); + size = bufsize; + } + size = read(fd, (char *)buf, size); + close(fd); + return size > 0 ? size : 0; +} + +static char *get_ati_model(uint32_t id) +{ + int i; + + for (i=0; i< (sizeof(ATIKnownChipsets) / sizeof(ATIKnownChipsets[0])); i++) { + if (ATIKnownChipsets[i].device == id) { + return ATIKnownChipsets[i].name; + } + } + return ATIKnownChipsets[0].name; +} + +static char *get_ati_fb(uint32_t id) +{ + int i; + + for (i=0; i< (sizeof(ATIKnownFramebuffers) / sizeof(ATIKnownFramebuffers[0])); i++) { + if (ATIKnownFramebuffers[i].device == id) { + return ATIKnownFramebuffers[i].name; + } + } + return ATIKnownFramebuffers[0].name; +} + +static int devprop_add_iopciconfigspace(struct DevPropDevice *device, pci_dt_t *ati_dev) +{ + int i; + uint8_t *config_space; + + if (!device || !ati_dev) { + return 0; + } + verbose("dumping pci config space, 256 bytes\n"); + config_space = malloc(256); + for (i=0; i<=255; i++) { + config_space[i] = pci_config_read8( ati_dev->dev.addr, i); + } + devprop_add_value(device, "ATY,PCIConfigSpace", config_space, 256); + free (config_space); + return 1; +} + +static int devprop_add_ati_template_4xxx(struct DevPropDevice *device) +{ + if(!device) + return 0; + + // if(!DP_ADD_TEMP_VAL(device, ati_compatible_0)) + // return 0; + // if(!DP_ADD_TEMP_VAL(device, ati_compatible_1)) + // return 0; + if(!DP_ADD_TEMP_VAL(device, ati_device_type_0)) + return 0; + if(!DP_ADD_TEMP_VAL(device, ati_device_type_1)) + return 0; + // if(!DP_ADD_TEMP_VAL(device, ati_device_type)) + // return 0; + // if(!DP_ADD_TEMP_VAL(device, ati_name_0)) + // return 0; + // if(!DP_ADD_TEMP_VAL(device, ati_name_1)) + // return 0; + // if(!DP_ADD_TEMP_VAL(device, ati_name)) + // return 0; + if(!DP_ADD_TEMP_VAL(device, ati_efidisplay_0)) + return 0; + if(!DP_ADD_TEMP_VAL(device, ati_display_type_0)) + return 0; + if(!DP_ADD_TEMP_VAL(device, ati_display_type_1)) + return 0; + // if(!DP_ADD_TEMP_VAL(device, ati_slot_name)) + // return 0; + if(!DP_ADD_TEMP_VAL(device, ati_card_no)) + return 0; + if(!DP_ADD_TEMP_VAL(device, ati_copyright)) + return 0; + if(!DP_ADD_TEMP_VAL(device, ati_efi_compile_d)) + return 0; + if(!DP_ADD_TEMP_VAL(device, ati_efi_version)) + return 0; + if(!DP_ADD_TEMP_VAL(device, ati_efi_versionB)) + return 0; + if(!DP_ADD_TEMP_VAL(device, ati_efi_versionE)) + return 0; + if(!DP_ADD_TEMP_VAL(device, ati_mrt)) + return 0; + if(!DP_ADD_TEMP_VAL(device, ati_romno)) + return 0; + if(!DP_ADD_TEMP_VAL(device, ati_name_1)) + return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_connector_type_0)) + return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_connector_type_1)) + return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_display_con_fl_type_0)) + return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_aux_power_conn)) + return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_backlight_ctrl)) + return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_aapl01_coher)) + return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_efi_disp_conf)) + return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_efi_drv_type)) + return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_efi_enbl_mode)) + return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_efi_init_stat)) + return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_efi_orientation)) + return 0; +// if(!DP_ADD_TEMP_VAL_DATA(device, ati_mclk)) +// return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_mem_rev_id)) + return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_mem_vend_id)) + return 0; +// if(!DP_ADD_TEMP_VAL_DATA(device, ati_sclk)) +// return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_vendor_id)) + return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_platform_info)) + return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_mvad)) + return 0; +// if(!DP_ADD_TEMP_VAL_DATA(device, ati_saved_config)) +// return 0; + return 1; +} + +static int devprop_add_ati_template(struct DevPropDevice *device) +{ + if(!device) + return 0; + + if(!DP_ADD_TEMP_VAL_DATA(device, ati_platform_info)) + return 0; + if(!DP_ADD_TEMP_VAL(device, ati_device_type_0)) + return 0; + if(!DP_ADD_TEMP_VAL(device, ati_device_type_1)) + return 0; + if(!DP_ADD_TEMP_VAL(device, ati_efidisplay_0_n4)) + return 0; + // if(!DP_ADD_TEMP_VAL(device, ati_slot_name_n4)) + // return 0; + if(!DP_ADD_TEMP_VAL(device, ati_card_no)) + return 0; + if(!DP_ADD_TEMP_VAL(device, ati_copyright)) + return 0; + if(!DP_ADD_TEMP_VAL(device, ati_efi_compile_d)) + return 0; + if(!DP_ADD_TEMP_VAL(device, ati_efi_version)) + return 0; + if(!DP_ADD_TEMP_VAL(device, ati_efi_versionB)) + return 0; + if(!DP_ADD_TEMP_VAL(device, ati_efi_versionE)) + return 0; + if(!DP_ADD_TEMP_VAL(device, ati_mrt)) + return 0; + if(!DP_ADD_TEMP_VAL(device, ati_romno)) + return 0; + if(!DP_ADD_TEMP_VAL(device, ati_name_1)) + return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_connector_type_0_n4)) + return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_connector_type_1_n4)) + return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_aux_power_conn)) + return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_backlight_ctrl)) + return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_aapl01_coher)) + return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_efi_drv_type)) + return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_efi_enbl_mode)) + return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_mem_rev_id)) + return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_mem_vend_id)) + return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_vendor_id)) + return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_aapl_emc_disp_list_n4)) + return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_fb_offset_n4)) + return 0; +/* if(!DP_ADD_TEMP_VAL_DATA(device, ati_hwgpio_n4)) + return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_iospace_offset_n4)) + return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_mclk_n4)) + return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_sclk_n4)) + return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_refclk_n4)) + return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_regspace_offset_n4)) + return 0; */ + if(!DP_ADD_TEMP_VAL_DATA(device, ati_efi_orientation_n4)) + return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_aapl_blackscr_prefs_0_n4)) + return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_aapl_blackscr_prefs_1_n4)) + return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_swgpio_info_n4)) + return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_efi_orientation_n4)) + return 0; + if(!DP_ADD_TEMP_VAL_DATA(device, ati_mvad_n4)) + return 0; +// if(!DP_ADD_TEMP_VAL_DATA(device, ati_saved_config_n4)) +// return 0; + return 1; +} + + +bool setup_ati_devprop(pci_dt_t *ati_dev) +{ + struct DevPropDevice *device; + char *devicepath; + char *model; + char *framebuffer; + char tmp[64]; + uint8_t *rom = NULL; + uint32_t rom_size = 0; + uint8_t *bios; + uint32_t bios_size; + uint32_t vram_size; + uint32_t boot_display; + uint8_t cmd; + bool doit; + bool toFree; + + devicepath = get_pci_dev_path(ati_dev); + + cmd = pci_config_read8(ati_dev->dev.addr, 4); + verbose("old pci command - %x\n", cmd); + if (cmd == 0) { + pci_config_write8(ati_dev->dev.addr, 4, 6); + cmd = pci_config_read8(ati_dev->dev.addr, 4); + verbose("new pci command - %x\n", cmd); + } + + model = get_ati_model((ati_dev->vendor_id << 16) | ati_dev->device_id); + framebuffer = (char*)getStringForKey(kAtiConfig, &bootInfo->bootConfig); + if (!framebuffer) { + framebuffer = get_ati_fb((ati_dev->vendor_id << 16) | ati_dev->device_id); + } + if (!string) { + string = devprop_create_string(); + } + device = devprop_add_device(string, devicepath); + if (!device) { + printf("Failed initializing dev-prop string dev-entry, press any key...\n"); + getc(); + return false; + } + + /* FIXME: for primary graphics card only */ + if (radeon_card_posted(ati_dev)) { + boot_display = 1; + } else { + boot_display = 0; + } + verbose("boot display - %x\n", boot_display); + devprop_add_value(device, "@0,AAPL,boot-display", (uint8_t*)&boot_display, 4); + + if((framebuffer[0] == 'M' && framebuffer[1] == 'o' && framebuffer[2] == 't') || + (framebuffer[0] == 'S' && framebuffer[1] == 'h' && framebuffer[2] == 'r') || + (framebuffer[0] == 'P' && framebuffer[1] == 'e' && framebuffer[2] == 'r') || + (framebuffer[0] == 'V' && framebuffer[1] == 'e' && framebuffer[2] == 'r') || + (framebuffer[0] == 'U' && framebuffer[1] == 'a' && framebuffer[2] == 'k')) //faster than strcmp ;) + devprop_add_ati_template_4xxx(device); + else { + devprop_add_ati_template(device); + vram_size = getvramsizekb(ati_dev) * 1024; + if ((vram_size > 0x80000000) || (vram_size == 0)) { + vram_size = 0x10000000; //vram reported wrong, defaulting to 256 mb + } + devprop_add_value(device, "VRAM,totalsize", (uint8_t*)&vram_size, 4); + ati_vram_memsize_0.data[6] = (vram_size >> 16) & 0xFF; //4,5 are 0x00 anyway + ati_vram_memsize_0.data[7] = (vram_size >> 24) & 0xFF; + ati_vram_memsize_1.data[6] = (vram_size >> 16) & 0xFF; //4,5 are 0x00 anyway + ati_vram_memsize_1.data[7] = (vram_size >> 24) & 0xFF; + DP_ADD_TEMP_VAL_DATA(device, ati_vram_memsize_0); + DP_ADD_TEMP_VAL_DATA(device, ati_vram_memsize_1); + devprop_add_iopciconfigspace(device, ati_dev); + } + devprop_add_value(device, "model", (uint8_t*)model, (strlen(model) + 1)); + devprop_add_value(device, "ATY,DeviceID", (uint8_t*)&ati_dev->device_id, 2); + + //fb setup + sprintf(tmp, "Slot-%x",devices_number); + devprop_add_value(device, "AAPL,slot-name", (uint8_t*)tmp, strlen(tmp) + 1); + devices_number++; + + sprintf(tmp, ati_compatible_0[1], framebuffer); + devprop_add_value(device, (char *) ati_compatible_0[0], (uint8_t *)tmp, strlen(tmp) + 1); + + sprintf(tmp, ati_compatible_1[1], framebuffer); + devprop_add_value(device, (char *) ati_compatible_1[0], (uint8_t *)tmp, strlen(tmp) + 1); + + sprintf(tmp, ati_device_type[1], framebuffer); + devprop_add_value(device, (char *) ati_device_type[0], (uint8_t *)tmp, strlen(tmp) + 1); + + sprintf(tmp, ati_name[1], framebuffer); + devprop_add_value(device, (char *) ati_name[0], (uint8_t *)tmp, strlen(tmp) + 1); + + sprintf(tmp, ati_name_0[1], framebuffer); + devprop_add_value(device, (char *) ati_name_0[0], (uint8_t *)tmp, strlen(tmp) + 1); + + sprintf(tmp, ati_name_1[1], framebuffer); + devprop_add_value(device, (char *) ati_name_1[0], (uint8_t *)tmp, strlen(tmp) + 1); + + sprintf(tmp, "/Extra/%04x_%04x.rom", (uint16_t)ati_dev->vendor_id, (uint16_t)ati_dev->device_id); + if (getBoolForKey(kUseAtiROM, &doit, &bootInfo->bootConfig) && doit) { + verbose("looking for ati video bios file %s\n", tmp); + rom = malloc(0x20000); + rom_size = load_ati_bios_file(tmp, rom, 0x20000); + if (rom_size > 0) { + verbose("Using ATI Video BIOS File %s (%d Bytes)\n", tmp, rom_size); + if (rom_size > 0x10000) { + rom_size = 0x10000; //we dont need rest anyway; + } + } else { + verbose("ERROR: unable to open ATI Video BIOS File %s\n", tmp); + } + } + if (rom_size == 0) { + if (boot_display) { // no custom rom + bios = NULL; // try to dump from legacy space, otherwise can result in 100% fan speed + } else { + // readAtomBios result in bug on some cards (100% fan speed and black screen), + // not using it for posted card, rading from legacy space instead + bios = readAtomBIOS(ati_dev); + } + } else { + bios = rom; //going custom rom way + verbose("Using rom %s\n", tmp); + } + if (bios == NULL) { + bios = (uint8_t *)0x000C0000; + toFree = false; + verbose("Not going to use bios image file\n"); + } else { + toFree = true; + } + + if (bios[0] == 0x55 && bios[1] == 0xaa) { + verbose("Found bios image\n"); + bios_size = bios[2] * 512; + + struct pci_rom_pci_header_t *rom_pci_header; + rom_pci_header = (struct pci_rom_pci_header_t*)(bios + bios[24] + bios[25]*256); + + if (rom_pci_header->signature == 0x52494350) { + if (rom_pci_header->device != ati_dev->device_id) { + verbose("Bios image (%x) doesnt match card (%x), ignoring\n", rom_pci_header->device, ati_dev->device_id); + } else { + if (toFree) { + verbose("Adding binimage to card %x from mmio space with size %x\n", ati_dev->device_id, bios_size); + } else { + verbose("Adding binimage to card %x from legacy space with size %x\n", ati_dev->device_id, bios_size); + } + devprop_add_value(device, "ATY,bin_image", bios, bios_size); + } + } else { + verbose("Wrong pci header signature %x\n", rom_pci_header->signature); + } + } else { + verbose("Bios image not found at %x, content %x %x\n", bios, bios[0], bios[1]); + } + if (toFree) { + free(bios); + } + stringdata = malloc(sizeof(uint8_t) * string->length); + memcpy(stringdata, (uint8_t*)devprop_generate_string(string), string->length); + stringlength = string->length; + + return true; +} Index: branches/slice/rev749/modules/HPET/HPET.c =================================================================== --- branches/slice/rev749/modules/HPET/HPET.c (revision 0) +++ branches/slice/rev749/modules/HPET/HPET.c (revision 1169) @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2009 Evan Lojewski. All rights reserved. + * + */ + +#include "libsaio.h" +#include "modules.h" +#include "boot.h" +#include "bootstruct.h" +#include "pci.h" +#include "hpet.h" + +#ifndef DEBUG_HPET +#define DEBUG_HPET 0 +#endif + +#if DEBUG_HPET +#define DBG(x...) printf(x) +#else +#define DBG(x...) +#endif + +void force_enable_hpet_intel(pci_dt_t *lpc_dev); +void force_enable_hpet_via(pci_dt_t *lpc_dev); + + +void HPET_hook(void* arg1, void* arg2, void* arg3, void* arg4) +{ + pci_dt_t* current = arg1; + + if(current->class_id != PCI_CLASS_BRIDGE_ISA) return; + + + bool do_enable_hpet = true; + getBoolForKey(kForceHPET, &do_enable_hpet, &bootInfo->bootConfig); + + if (do_enable_hpet) + force_enable_hpet(current); +} + +void HPET_start() +{ + register_hook_callback("PCIDevice", &HPET_hook); +} + +/* + * Force HPET enabled + * + * via fix from http://forum.voodooprojects.org/index.php/topic,1596.0.html + */ + +static struct lpc_controller_t lpc_controllers_intel[] = { + + // Default unknown chipset + { 0, 0, "" }, + + // Intel + { 0x8086, 0x24dc, "ICH5" }, + { 0x8086, 0x2640, "ICH6" }, + { 0x8086, 0x2641, "ICH6M" }, + + { 0x8086, 0x27b0, "ICH7 DH" }, + { 0x8086, 0x27b8, "ICH7" }, + { 0x8086, 0x27b9, "ICH7M" }, + { 0x8086, 0x27bd, "ICH7M DH" }, + + { 0x8086, 0x27bc, "NM10" }, + + { 0x8086, 0x2810, "ICH8R" }, + { 0x8086, 0x2811, "ICH8M-E" }, + { 0x8086, 0x2812, "ICH8DH" }, + { 0x8086, 0x2814, "ICH8DO" }, + { 0x8086, 0x2815, "ICH8M" }, + + { 0x8086, 0x2912, "ICH9DH" }, + { 0x8086, 0x2914, "ICH9DO" }, + { 0x8086, 0x2916, "ICH9R" }, + { 0x8086, 0x2917, "ICH9M-E" }, + { 0x8086, 0x2918, "ICH9" }, + { 0x8086, 0x2919, "ICH9M" }, + + { 0x8086, 0x3a14, "ICH10DO" }, + { 0x8086, 0x3a16, "ICH10R" }, + { 0x8086, 0x3a18, "ICH10" }, + { 0x8086, 0x3a1a, "ICH10D" }, +}; + +static struct lpc_controller_t lpc_controllers_via[] = { + // Default unknown chipset + { 0, 0, "" }, + + { 0x1106, 0x3372, "VT8237S" }, +}; + + +void force_enable_hpet(pci_dt_t *lpc_dev) +{ + switch(lpc_dev->vendor_id) + { + case 0x8086: + force_enable_hpet_intel(lpc_dev); + break; + + case 0x1106: + force_enable_hpet_via(lpc_dev); + break; + } + + +#if DEBUG_HPET + printf("Press [Enter] to continue...\n"); + getc(); +#endif +} + +void force_enable_hpet_via(pci_dt_t *lpc_dev) +{ + uint32_t val, hpet_address = 0xFED00000; + int i; + + for(i = 1; i < sizeof(lpc_controllers_via) / sizeof(lpc_controllers_via[0]); i++) + { + if ( (lpc_controllers_via[i].vendor == lpc_dev->vendor_id) + && (lpc_controllers_via[i].device == lpc_dev->device_id)) + { + val = pci_config_read32(lpc_dev->dev.addr, 0x68); + + DBG("VIA %s LPC Interface [%04x:%04x], MMIO\n", + lpc_controllers_via[i].name, lpc_dev->vendor_id, lpc_dev->device_id); + + if (val & 0x80) { + hpet_address = (val & ~0x3ff); + DBG("HPET at 0x%lx\n", hpet_address); + } + else + { + val = 0xfed00000 | 0x80; + pci_config_write32(lpc_dev->dev.addr, 0x68, val); + val = pci_config_read32(lpc_dev->dev.addr, 0x68); + if (val & 0x80) { + hpet_address = (val & ~0x3ff); + DBG("Force enabled HPET at 0x%lx\n", hpet_address); + } + else { + DBG("Unable to enable HPET"); + } + } + } + } +} + + + +void force_enable_hpet_intel(pci_dt_t *lpc_dev) +{ + uint32_t val, hpet_address = 0xFED00000; + int i; + void *rcba; + + /* LPC on Intel ICH is always (?) at 00:1f.0 */ + for(i = 1; i < sizeof(lpc_controllers_intel) / sizeof(lpc_controllers_intel[0]); i++) + { + if ( (lpc_controllers_intel[i].vendor == lpc_dev->vendor_id) + && (lpc_controllers_intel[i].device == lpc_dev->device_id)) + { + + rcba = (void *)(pci_config_read32(lpc_dev->dev.addr, 0xF0) & 0xFFFFC000); + + DBG("Intel(R) %s LPC Interface [%04x:%04x], MMIO @ 0x%lx\n", + lpc_controllers_intel[i].name, lpc_dev->vendor_id, lpc_dev->device_id, rcba); + + if (rcba == 0) + verbose(" RCBA disabled; cannot force enable HPET\n"); + else + { + val = REG32(rcba, 0x3404); + if (val & 0x80) + { + // HPET is enabled in HPTC. Just not reported by BIOS + DBG(" HPET is enabled in HPTC, just not reported by BIOS\n"); + hpet_address |= (val & 3) << 12 ; + DBG(" HPET MMIO @ 0x%lx\n", hpet_address); + } + else + { + // HPET disabled in HPTC. Trying to enable + DBG(" HPET is disabled in HPTC, trying to enable\n"); + REG32(rcba, 0x3404) = val | 0x80; + hpet_address |= (val & 3) << 12 ; + DBG(" Force enabled HPET, MMIO @ 0x%lx\n", hpet_address); + } + + // verify if the job is done + val = REG32(rcba, 0x3404); + if (!(val & 0x80)) + verbose(" Failed to force enable HPET\n"); + } + break; + } +#if DEBUG_HPET + printf("Press [Enter] to continue...\n"); + getc(); +#endif + } +} \ No newline at end of file Index: branches/slice/rev749/modules/HPET/hpet.h =================================================================== --- branches/slice/rev749/modules/HPET/hpet.h (revision 0) +++ branches/slice/rev749/modules/HPET/hpet.h (revision 1169) @@ -0,0 +1,20 @@ +/* + * + */ + +#ifndef __LIBSAIO_HPET_H +#define __LIBSAIO_HPET_H + +#include "libsaio.h" + +#define REG32(base, reg) ((volatile uint32_t *)base)[(reg) >> 2] + +void force_enable_hpet(pci_dt_t *lpc_dev); + +struct lpc_controller_t { + unsigned vendor; + unsigned device; + char *name; +}; + +#endif /* !__LIBSAIO_HPET_H */ Index: branches/slice/rev749/modules/HPET/Makefile =================================================================== --- branches/slice/rev749/modules/HPET/Makefile (revision 0) +++ branches/slice/rev749/modules/HPET/Makefile (revision 1169) @@ -0,0 +1,44 @@ + +MODULE_NAME = HPET +MODULE_VERSION = "1.0.0" +MODULE_COMPAT_VERSION = "1.0.0" +MODULE_START = _$(MODULE_NAME)_start +MODULE_DEPENDENCIES = + +DIR = HPET + +MODULE_OBJS = HPET.o + +OPTIM = -Os -Oz +DEBUG = -DNOTHING +#DEBUG = -DDEBUG_HELLO_WORLD=1 +CFLAGS = $(RC_CFLAGS) $(OPTIM) $(MORECPP) -arch i386 -g -Wmost \ + -D__ARCHITECTURE__=\"i386\" -DSAIO_INTERNAL_USER \ + -DRCZ_COMPRESSED_FILE_SUPPORT $(DEBUG) \ + -fno-builtin $(OMIT_FRAME_POINTER_CFLAG) \ + -mpreferred-stack-boundary=2 -fno-align-functions -fno-stack-protector \ + -march=pentium4 -msse2 -mfpmath=sse -msoft-float -fno-common + +DEFINES= +CONFIG = hd +INC = -I. -I.. -I$(SYMROOT) -I$(UTILDIR) -I$(LIBSADIR) -I$(LIBSAIODIR) -I$(BOOT2DIR) +LIBS= + +VPATH = $(OBJROOT):$(SYMROOT) + + + +SFILES = +CFILES = +HFILES = +EXPORTED_HFILES = +INSTALLED_HFILES = +OTHERFILES = Makefile +ALLSRC = $(SFILES) $(CFILES) \ + $(HFILES) $(OTHERFILES) +DIRS_NEEDED = $(OBJROOT) $(SYMROOT) + +all embedtheme optionrom: dylib + + +include ../MakeInc.dir \ No newline at end of file Index: branches/slice/rev749/modules/USBFix/USBFix.c =================================================================== --- branches/slice/rev749/modules/USBFix/USBFix.c (revision 0) +++ branches/slice/rev749/modules/USBFix/USBFix.c (revision 1169) @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2009 Evan Lojewski. All rights reserved. + * + */ + +#include "libsaio.h" +#include "modules.h" +#include "pci.h" + +int usb_loop(); +void notify_usb_dev(pci_dt_t *pci_dev); + +void USBFix_pci_hook(void* arg1, void* arg2, void* arg3, void* arg4) +{ + pci_dt_t* current = arg1; + if(current->class_id == PCI_CLASS_SERIAL_USB) + { + notify_usb_dev(current); + } +} + +void USBFix_start_hook(void* arg1, void* arg2, void* arg3, void* arg4) +{ + usb_loop(); +} + + +void USBFix_start() +{ + register_hook_callback("PCIDevice", &USBFix_pci_hook); + register_hook_callback("Kernel Start", &USBFix_start_hook); + +} + Index: branches/slice/rev749/modules/USBFix/usb.c =================================================================== --- branches/slice/rev749/modules/USBFix/usb.c (revision 0) +++ branches/slice/rev749/modules/USBFix/usb.c (revision 1169) @@ -0,0 +1,377 @@ +/* + * usb.c + * + * + * Created by mackerintel on 12/20/08. + * Copyright 2008 mackerintel. All rights reserved. + * + */ + +#include "libsaio.h" +#include "boot.h" +#include "bootstruct.h" +#include "pci.h" + +#ifndef DEBUG_USB +#define DEBUG_USB 0 +#endif + +#if DEBUG_USB +#define DBG(x...) verbose(x) +#else +#define DBG(x...) +#endif + + +struct pciList +{ + pci_dt_t* pciDev; + struct pciList* next; +}; + +struct pciList* usbList = NULL; + +int legacy_off (pci_dt_t *pci_dev); +int ehci_acquire (pci_dt_t *pci_dev); +int uhci_reset (pci_dt_t *pci_dev); +int ohci_handsoff (pci_dt_t *pci_dev); + +// Add usb device to the list +void notify_usb_dev(pci_dt_t *pci_dev) +{ + struct pciList* current = (struct pciList*)malloc(sizeof(struct pciList)); + current->next = usbList; + current->pciDev = pci_dev; + + usbList = current; +} + +// Loop through the list and call the apropriate patch function +int usb_loop() +{ + int retVal = 1; + bool fix_ehci, fix_uhci, fix_usb, fix_legacy; + fix_ehci = fix_uhci = fix_usb = fix_legacy = true; + + if (getBoolForKey(kUSBBusFix, &fix_usb, &bootInfo->bootConfig)) + { + fix_ehci = fix_uhci = fix_legacy = fix_usb; // Disable all if none set + } + else + { + getBoolForKey(kEHCIacquire, &fix_ehci, &bootInfo->bootConfig); + getBoolForKey(kUHCIreset, &fix_uhci, &bootInfo->bootConfig); + getBoolForKey(kLegacyOff, &fix_legacy, &bootInfo->bootConfig); + } + + struct pciList* current = usbList; + + while(current) + { + switch (pci_config_read8(current->pciDev->dev.addr, PCI_CLASS_PROG)) + { + // EHCI + case 0x20: + if(fix_legacy) retVal &= legacy_off(current->pciDev); + if(fix_ehci) retVal &= ehci_acquire(current->pciDev); + + break; + // OHCI + case 0x10: // + if (fix_uhci) retVal &= ohci_handsoff(current->pciDev); + + break; + + + // UHCI + case 0x00: + if (fix_uhci) retVal &= uhci_reset(current->pciDev); + + break; + } + + current = current->next; + } + return retVal; +} + +int legacy_off (pci_dt_t *pci_dev) +{ + // Set usb legacy off modification by Signal64 + // NOTE: This *must* be called after the last file is loaded from the drive in the event that we are booting form usb. + // NOTE2: This should be called after any getc() call. (aka, after the Wait=y keyworkd is used) + // AKA: Make this run immediatly before the kernel is called + uint32_t capaddr, opaddr; + uint8_t eecp; + uint32_t usbcmd, usbsts, usbintr; + uint32_t usblegsup, usblegctlsts; + + int isOSowned; + int isBIOSowned; + + verbose("Setting Legacy USB Off on controller [%04x:%04x] at %02x:%2x.%x\n", + pci_dev->vendor_id, pci_dev->device_id, + pci_dev->dev.bits.bus, pci_dev->dev.bits.dev, pci_dev->dev.bits.func); + + + // capaddr = Capability Registers = dev.addr + offset stored in dev.addr + 0x10 (USBBASE) + capaddr = pci_config_read32(pci_dev->dev.addr, 0x10); + + // opaddr = Operational Registers = capaddr + offset (8bit CAPLENGTH in Capability Registers + offset 0) + opaddr = capaddr + *((unsigned char*)(capaddr)); + + // eecp = EHCI Extended Capabilities offset = capaddr HCCPARAMS bits 15:8 + eecp=*((unsigned char*)(capaddr + 9)); + + DBG("capaddr=%x opaddr=%x eecp=%x\n", capaddr, opaddr, eecp); + + usbcmd = *((unsigned int*)(opaddr)); // Command Register + usbsts = *((unsigned int*)(opaddr + 4)); // Status Register + usbintr = *((unsigned int*)(opaddr + 8)); // Interrupt Enable Register + + DBG("usbcmd=%08x usbsts=%08x usbintr=%08x\n", usbcmd, usbsts, usbintr); + + // read PCI Config 32bit USBLEGSUP (eecp+0) + usblegsup = pci_config_read32(pci_dev->dev.addr, eecp); + + // informational only + isBIOSowned = !!((usblegsup) & (1 << (16))); + isOSowned = !!((usblegsup) & (1 << (24))); + + // read PCI Config 32bit USBLEGCTLSTS (eecp+4) + usblegctlsts = pci_config_read32(pci_dev->dev.addr, eecp + 4); + + DBG("usblegsup=%08x isOSowned=%d isBIOSowned=%d usblegctlsts=%08x\n", usblegsup, isOSowned, isBIOSowned, usblegctlsts); + + // Reset registers to Legacy OFF + DBG("Clearing USBLEGCTLSTS\n"); + pci_config_write32(pci_dev->dev.addr, eecp + 4, 0); //usblegctlsts + + // if delay value is in milliseconds it doesn't appear to work. + // setting value to anything up to 65535 does not add the expected delay here. + delay(100); + + usbcmd = *((unsigned int*)(opaddr)); + usbsts = *((unsigned int*)(opaddr + 4)); + usbintr = *((unsigned int*)(opaddr + 8)); + + DBG("usbcmd=%08x usbsts=%08x usbintr=%08x\n", usbcmd, usbsts, usbintr); + + DBG("Clearing Registers\n"); + + // clear registers to default + usbcmd = (usbcmd & 0xffffff00); + *((unsigned int*)(opaddr)) = usbcmd; + *((unsigned int*)(opaddr + 8)) = 0; //usbintr - clear interrupt registers + *((unsigned int*)(opaddr + 4)) = 0x1000; //usbsts - clear status registers + pci_config_write32(pci_dev->dev.addr, eecp, 1); //usblegsup + + // get the results + usbcmd = *((unsigned int*)(opaddr)); + usbsts = *((unsigned int*)(opaddr + 4)); + usbintr = *((unsigned int*)(opaddr + 8)); + + DBG("usbcmd=%08x usbsts=%08x usbintr=%08x\n", usbcmd, usbsts, usbintr); + + // read 32bit USBLEGSUP (eecp+0) + usblegsup = pci_config_read32(pci_dev->dev.addr, eecp); + + // informational only + isBIOSowned = !!((usblegsup) & (1 << (16))); + isOSowned = !!((usblegsup) & (1 << (24))); + + // read 32bit USBLEGCTLSTS (eecp+4) + usblegctlsts = pci_config_read32(pci_dev->dev.addr, eecp + 4); + + DBG("usblegsup=%08x isOSowned=%d isBIOSowned=%d usblegctlsts=%08x\n", usblegsup, isOSowned, isBIOSowned, usblegctlsts); + + msglog("Legacy USB Off Done\n"); + return 1; +} + +int ehci_acquire (pci_dt_t *pci_dev) +{ + int j, k; + uint32_t base; + uint8_t eecp; + uint8_t legacy[8]; + bool isOwnershipConflict; + bool alwaysHardBIOSReset; + + alwaysHardBIOSReset = false; + if (!getBoolForKey(kEHCIhard, &alwaysHardBIOSReset, &bootInfo->bootConfig)) { + alwaysHardBIOSReset = true; + } + + pci_config_write16(pci_dev->dev.addr, 0x04, 0x0002); + base = pci_config_read32(pci_dev->dev.addr, 0x10); + + msglog("EHCI controller [%04x:%04x] at %02x:%2x.%x DMA @%x\n", + pci_dev->vendor_id, pci_dev->device_id, + pci_dev->dev.bits.bus, pci_dev->dev.bits.dev, pci_dev->dev.bits.func, + base); + + if (*((unsigned char*)base) < 0xc) + { + DBG("Config space too small: no legacy implementation\n"); + return 1; + } + eecp = *((unsigned char*)(base + 9)); + if (!eecp) { + DBG("No extended capabilities: no legacy implementation\n"); + return 1; + } + + DBG("eecp=%x\n",eecp); + + // bad way to do it + // pci_conf_write(pci_dev->dev.addr, eecp, 4, 0x01000001); + for (j = 0; j < 8; j++) { + legacy[j] = pci_config_read8(pci_dev->dev.addr, eecp + j); + DBG("%02x ", legacy[j]); + } + DBG("\n"); + + //Real Job: based on orByte's AppleUSBEHCI.cpp + //We try soft reset first - some systems hang on reboot with hard reset + // Definitely needed during reboot on 10.4.6 + + isOwnershipConflict = ((legacy[3] & 1 != 0) && (legacy[2] & 1 != 0)); + if (!alwaysHardBIOSReset && isOwnershipConflict) { + DBG("EHCI - Ownership conflict - attempting soft reset ...\n"); + DBG("EHCI - toggle OS Ownership to 0\n"); + pci_config_write8(pci_dev->dev.addr, eecp + 3, 0); + for (k = 0; k < 25; k++) { + for (j = 0; j < 8; j++) { + legacy[j] = pci_config_read8(pci_dev->dev.addr, eecp + j); + } + if (legacy[3] == 0) { + break; + } + delay(10); + } + } + + DBG("Found USBLEGSUP_ID - value %x:%x - writing OSOwned\n", legacy[3],legacy[2]); + pci_config_write8(pci_dev->dev.addr, eecp + 3, 1); + + // wait for kEHCI_USBLEGSUP_BIOSOwned bit to clear + for (k = 0; k < 25; k++) { + for (j = 0;j < 8; j++) { + legacy[j] = pci_config_read8(pci_dev->dev.addr, eecp + j); + } + DBG ("%x:%x,",legacy[3],legacy[2]); + if (legacy[2] == 0) { + break; + } + delay(10); + } + + for (j = 0;j < 8; j++) { + legacy[j] = pci_config_read8(pci_dev->dev.addr, eecp + j); + } + isOwnershipConflict = ((legacy[2]) != 0); + if (isOwnershipConflict) { + // Soft reset has failed. Assume SMI being ignored + // Hard reset + // Force Clear BIOS BIT + DBG("EHCI - Ownership conflict - attempting hard reset ...\n"); + DBG ("%x:%x\n",legacy[3],legacy[2]); + DBG("EHCI - Force BIOS Ownership to 0\n"); + + pci_config_write8(pci_dev->dev.addr, eecp + 2, 0); + for (k = 0; k < 25; k++) { + for (j = 0; j < 8; j++) { + legacy[j] = pci_config_read8(pci_dev->dev.addr, eecp + j); + } + DBG ("%x:%x,",legacy[3],legacy[2]); + + if ((legacy[2]) == 0) { + break; + } + delay(10); + } + // Disable further SMI events + for (j = 4; j < 8; j++) { + pci_config_write8(pci_dev->dev.addr, eecp + j, 0); + } + } + + for (j = 0; j < 8; j++) { + legacy[j] = pci_config_read8(pci_dev->dev.addr, eecp + j); + } + + DBG ("%x:%x\n",legacy[3],legacy[2]); + + // Final Ownership Resolution Check... + if (legacy[2] & 1) { + DBG("EHCI controller unable to take control from BIOS\n"); + return 0; + } + + msglog("EHCI Acquire OS Ownership done\n"); + return 1; +} + +int uhci_reset (pci_dt_t *pci_dev) +{ + uint32_t base, port_base; + + base = pci_config_read32(pci_dev->dev.addr, 0x20); + port_base = (base >> 5) & 0x07ff; + + msglog("UHCI controller [%04x:%04x] at %02x:%2x.%x base %x(%x) reset\n", + pci_dev->vendor_id, pci_dev->device_id, + pci_dev->dev.bits.bus, pci_dev->dev.bits.dev, pci_dev->dev.bits.func, + port_base, base); + + pci_config_write16(pci_dev->dev.addr, 0xc0, 0x8f00); + + outw (port_base, 0x0002); + delay(10); + outw (port_base+4,0); + delay(10); + outw (port_base,0); + return 1; +} + +int ohci_handsoff (pci_dt_t *pci_dev) +{ + uint32_t base, control; +#define OHCI_CTRL_MASK (1 << 9) +#define OHCI_CONTROL 0x04 +#define OHCI_INTRDISABLE 0x14 +#define OHCI_INTRSTATUS 0x0c + + base = pci_config_read32(pci_dev->dev.addr, 0x10); + msglog("OHCI controller [%04x:%04x] at %02x:%2x.%x base %x reset\n", + pci_dev->vendor_id, pci_dev->device_id, + pci_dev->dev.bits.bus, pci_dev->dev.bits.dev, pci_dev->dev.bits.func, + base); +//Linux + /* + if (control & OHCI_CTRL_IR) { + int wait_time = 500; // arbitrary; 5 seconds + writel(OHCI_INTR_OC, base + OHCI_INTRENABLE); + writel(OHCI_OCR, base + OHCI_CMDSTATUS); + while (wait_time > 0 && + 194 readl(base + OHCI_CONTROL) & OHCI_CTRL_IR) { + wait_time -= 10; + msleep(10); + } + if (wait_time <= 0) + dev_warn(&pdev->dev, "OHCI: BIOS handoff failed" + " (BIOS bug?) %08x\n", readl(base + OHCI_CONTROL)); + } + */ + control = *(uint32_t *)(base + OHCI_CONTROL); + *(uint32_t *)(base + OHCI_CONTROL) = control & OHCI_CTRL_MASK; +//Linux + /* + * disable interrupts + writel(~(u32)0, base + OHCI_INTRDISABLE); + writel(~(u32)0, base + OHCI_INTRSTATUS); + + */ + return 1; +} Index: branches/slice/rev749/modules/USBFix/Makefile =================================================================== --- branches/slice/rev749/modules/USBFix/Makefile (revision 0) +++ branches/slice/rev749/modules/USBFix/Makefile (revision 1169) @@ -0,0 +1,48 @@ +MODULE_NAME = USBFix +MODULE_VERSION = "1.0.0" +MODULE_COMPAT_VERSION = "1.0.0" +MODULE_START = _$(MODULE_NAME)_start +MODULE_DEPENDENCIES = + +DIR = USBFix + +MODULE_OBJS = USBFix.o usb.o + +OPTIM = -Os -Oz +DEBUG = -DNOTHING +#DEBUG = -DDEBUG_HELLO_WORLD=1 +CFLAGS = $(RC_CFLAGS) $(OPTIM) $(MORECPP) -arch i386 -g -Wmost \ + -D__ARCHITECTURE__=\"i386\" -DSAIO_INTERNAL_USER \ + -DRCZ_COMPRESSED_FILE_SUPPORT $(DEBUG) \ + -fno-builtin $(OMIT_FRAME_POINTER_CFLAG) \ + -mpreferred-stack-boundary=2 -fno-align-functions -fno-stack-protector \ + -march=pentium4 -msse2 -mfpmath=sse -msoft-float -fno-common + +DEFINES= +CONFIG = hd +INC = -I. -I.. -I$(SYMROOT) -I$(UTILDIR) -I$(LIBSADIR) -I$(LIBSAIODIR) -I$(BOOT2DIR) +ifneq "" "$(wildcard /bin/mkdirs)" + MKDIRS = /bin/mkdirs +else + MKDIRS = /bin/mkdir -p +endif +AS = as +LD = ld +# LIBS= -lc_static +LIBS= + +VPATH = $(OBJROOT):$(SYMROOT) + +SFILES = +CFILES = +HFILES = +EXPORTED_HFILES = +INSTALLED_HFILES = +OTHERFILES = Makefile +ALLSRC = $(SFILES) $(CFILES) \ + $(HFILES) $(OTHERFILES) +DIRS_NEEDED = $(OBJROOT) $(SYMROOT) + +all embedtheme optionrom: dylib + +include ../MakeInc.dir \ No newline at end of file Index: branches/slice/rev749/modules/Resolution/915resolution.c =================================================================== --- branches/slice/rev749/modules/Resolution/915resolution.c (revision 0) +++ branches/slice/rev749/modules/Resolution/915resolution.c (revision 1169) @@ -0,0 +1,892 @@ +/* + * resolution.h + * + * NOTE: I don't beleive this code is production ready / should be in trunk + * Atleast, not in it's current state. + * + * Created by Evan Lojewski on 3/4/10. + * Copyright 2009. All rights reserved. + * + */ +#ifndef _RESOLUTION_H_ +#define _RESOLUTION_H_ + +//#include "libsaio.h" +//#include "edid.h" //included +#include "915resolution.h" + + +void patchVideoBios() +{ + UInt32 x = 0, y = 0, bp = 0; + + getResolution(&x, &y, &bp); + verbose("getResolution: %dx%dx%d\n", (int)x, (int)y, (int)bp); + + if (x != 0 && + y != 0 && + bp != 0) + { + vbios_map * map; + + map = open_vbios(CT_UNKWN); + // verbose("open_vbios\n"); + if(map) + { + unlock_vbios(map); + + set_mode(map, x, y, bp, 0, 0); + + relock_vbios(map); + + close_vbios(map); + } + } + +} + + +/* Copied from 915 resolution created by steve tomljenovic + * + * This code is based on the techniques used in : + * + * - 855patch. Many thanks to Christian Zietz (czietz gmx net) + * for demonstrating how to shadow the VBIOS into system RAM + * and then modify it. + * + * - 1280patch by Andrew Tipton (andrewtipton null li). + * + * - 855resolution by Alain Poirier + * + * This source code is into the public domain. + */ + +/** + ** + **/ + +#define CONFIG_MECH_ONE_ADDR 0xCF8 +#define CONFIG_MECH_ONE_DATA 0xCFC + +int freqs[] = { 60, 75, 85 }; + +UInt32 get_chipset_id(void) +{ + outl(CONFIG_MECH_ONE_ADDR, 0x80000000); + return inl(CONFIG_MECH_ONE_DATA); +} + +chipset_type get_chipset(UInt32 id) +{ + chipset_type type; + + switch (id) { + case 0x35758086: + type = CT_830; + break; + + case 0x25608086: + type = CT_845G; + break; + + case 0x35808086: + type = CT_855GM; + break; + + case 0x25708086: + type = CT_865G; + break; + + case 0x25808086: + type = CT_915G; + break; + + case 0x25908086: + type = CT_915GM; + break; + + case 0x27708086: + type = CT_945G; + break; + + case 0x27a08086: + type = CT_945GM; + break; + + case 0x27ac8086: + type = CT_945GME; + break; + + case 0x29708086: + type = CT_946GZ; + break; + + case 0x27748086: + type = CT_955X; + break; + + case 0x277c8086: + type = CT_975X; + break; + + case 0x29a08086: + type = CT_G965; + break; + + case 0x29908086: + type = CT_Q965; + break; + + case 0x81008086: + type = CT_500; + break; + + case 0x2e108086: + case 0X2e908086: + type = CT_B43; + break; + + case 0x2e208086: + type = CT_P45; + break; + + case 0x2e308086: + type = CT_G41; + break; + + case 0x29c08086: + type = CT_G31; + break; + + case 0x29208086: + type = CT_G45; + break; + + case 0xA0108086: // mobile + case 0xA0008086: // desktop + type = CT_3150; + break; + + case 0x2a008086: + type = CT_965GM; + break; + + case 0x29e08086: + type = CT_X48; + break; + + case 0x2a408086: + type = CT_GM45; + break; + + + default: + if((id & 0x0000FFFF) == 0x00008086) // Intel chipset + { + //printf("Unknown chipset 0x%llX, please email id to meklort@gmail.com", id); + //getc(); + //type = CT_UNKWN_INTEL; + type = CT_UNKWN; + + } + type = CT_UNKWN; + break; + } + return type; +} + +vbios_resolution_type1 * map_type1_resolution(vbios_map * map, UInt16 res) +{ + vbios_resolution_type1 * ptr = ((vbios_resolution_type1*)(map->bios_ptr + res)); + return ptr; +} + +vbios_resolution_type2 * map_type2_resolution(vbios_map * map, UInt16 res) +{ + vbios_resolution_type2 * ptr = ((vbios_resolution_type2*)(map->bios_ptr + res)); + return ptr; +} + +vbios_resolution_type3 * map_type3_resolution(vbios_map * map, UInt16 res) +{ + vbios_resolution_type3 * ptr = ((vbios_resolution_type3*)(map->bios_ptr + res)); + return ptr; +} + +char detect_bios_type(vbios_map * map, char modeline, int entry_size) +{ + UInt32 i; + UInt16 r1, r2; + + r1 = r2 = 32000; + + for (i=0; i < map->mode_table_size; i++) + { + if (map->mode_table[i].resolution <= r1) + { + r1 = map->mode_table[i].resolution; + } + else + { + if (map->mode_table[i].resolution <= r2) + { + r2 = map->mode_table[i].resolution; + } + } + + /*printf("r1 = %d r2 = %d\n", r1, r2);*/ + } + + return (r2-r1-6) % entry_size == 0; +} + +void close_vbios(vbios_map * map); + +char detect_ati_bios_type(vbios_map * map) +{ + return map->mode_table_size % sizeof(ATOM_MODE_TIMING) == 0; +} + + +vbios_map * open_vbios(chipset_type forced_chipset) +{ + UInt32 z; + vbios_map * map = malloc(sizeof(vbios_map)); + for(z=0; zchipset_id = get_chipset_id(); + map->chipset = get_chipset(map->chipset_id); + } + else if (forced_chipset != CT_UNKWN) + { + map->chipset = forced_chipset; + } + + + if (map->chipset == CT_UNKWN) + { + //verbose("Unknown chipset type.\n"); + //verbose("915resolution only works with Intel 800/900 series graphic chipsets.\n"); + //verbose("Chipset Id: %x\n", map->chipset_id); + close_vbios(map); + return 0; + } + + + /* + * Map the video bios to memory + */ + map->bios_ptr=(char*)VBIOS_START; + + /* + * check if we have ATI Radeon + */ + map->ati_tables.base = map->bios_ptr; + map->ati_tables.AtomRomHeader = (ATOM_ROM_HEADER *) (map->bios_ptr + *(unsigned short *) (map->bios_ptr + OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER)); + if (strcmp ((char *) map->ati_tables.AtomRomHeader->uaFirmWareSignature, "ATOM") == 0) + { + // ATI Radeon Card + map->bios = BT_ATI_1; + + map->ati_tables.MasterDataTables = (unsigned short *) &((ATOM_MASTER_DATA_TABLE *) (map->bios_ptr + map->ati_tables.AtomRomHeader->usMasterDataTableOffset))->ListOfDataTables; + unsigned short std_vesa_offset = (unsigned short) ((ATOM_MASTER_LIST_OF_DATA_TABLES *)map->ati_tables.MasterDataTables)->StandardVESA_Timing; + ATOM_STANDARD_VESA_TIMING * std_vesa = (ATOM_STANDARD_VESA_TIMING *) (map->bios_ptr + std_vesa_offset); + + map->ati_mode_table = (char *) &std_vesa->aModeTimings; + if (map->ati_mode_table == 0) + { + verbose("Unable to locate the mode table.\n"); + verbose("Please run the program 'dump_bios' as root and\n"); + verbose("email the file 'vbios.dmp' to stomljen@yahoo.com.\n"); + verbose("Chipset: %d\n", map->chipset); + close_vbios(map); + return 0; + } + map->mode_table_size = std_vesa->sHeader.usStructureSize - sizeof(ATOM_COMMON_TABLE_HEADER); + + if (!detect_ati_bios_type(map)) map->bios = BT_ATI_2; + + } + else { + + /* + * check if we have NVIDIA + */ + + int i = 0; + while (i < 512) + { // we don't need to look through the whole bios, just the first 512 bytes + if (( map->bios_ptr[i] == 'N') + && (map->bios_ptr[i+1] == 'V') + && (map->bios_ptr[i+2] == 'I') + && (map->bios_ptr[i+3] == 'D')) + { + map->bios = BT_NVDA; + unsigned short nv_data_table_offset = 0; + unsigned short * nv_data_table; + NV_VESA_TABLE * std_vesa; + + int i = 0; + + while (i < 0x300) + { //We don't need to look for the table in the whole bios, the 768 first bytes only + if (( map->bios_ptr[i] == 0x44) + && (map->bios_ptr[i+1] == 0x01) + && (map->bios_ptr[i+2] == 0x04) + && (map->bios_ptr[i+3] == 0x00)) + { + nv_data_table_offset = (unsigned short) (map->bios_ptr[i+4] | (map->bios_ptr[i+5] << 8)); + break; + } + i++; + } + + nv_data_table = (unsigned short *) (map->bios_ptr + (nv_data_table_offset + OFFSET_TO_VESA_TABLE_INDEX)); + std_vesa = (NV_VESA_TABLE *) (map->bios_ptr + *nv_data_table); + + map->nv_mode_table = (char *) std_vesa->sModelines; + if (map->nv_mode_table == 0) + { + verbose("Unable to locate the mode table.\n"); + verbose("Please run the program 'dump_bios' as root and\n"); + verbose("email the file 'vbios.dmp' to stomljen@yahoo.com.\n"); + verbose("Chipset: %s\n", map->chipset); + close_vbios(map); + return 0; + } + map->mode_table_size = std_vesa->sHeader.usTable_Size; + + break; + } + i++; + } + } + + + /* + * check if we have Intel + */ + + /*if (map->chipset == CT_UNKWN && memmem(map->bios_ptr, VBIOS_SIZE, INTEL_SIGNATURE, strlen(INTEL_SIGNATURE))) { + printf( "Intel chipset detected. However, 915resolution was unable to determine the chipset type.\n"); + + printf("Chipset Id: %x\n", map->chipset_id); + + printf("Please report this problem to stomljen@yahoo.com\n"); + + close_vbios(map); + return 0; + }*/ + //Slice - Intel = 49 6E 74 65 6C located @ 0xBE6 + /* + PCIptr @0x18 = 0x0040 + version @0x20 = 0x0AE0 + */ + int i = 0; + while (i < 4096) + { // we don't need to look through the whole bios, just the first 0x1000 bytes + if (( map->bios_ptr[i] == 0x49) + && (map->bios_ptr[i+1] == 0x6E) + && (map->bios_ptr[i+2] == 0x74) + && (map->bios_ptr[i+3] == 0x65) + && (map->bios_ptr[i+4] == 0x6C)) + { + verbose( "Intel VideoBIOS detected. \n"); + map->bios = BT_INTEL; + close_vbios(map); + return 0; + //break; + } + i++; + } + + /* + * check for others + */ + + + + /* + * Figure out where the mode table is + */ + if ((map->bios != BT_ATI_1) && (map->bios != BT_NVDA)) + { + char* p = map->bios_ptr + 16; + char* limit = map->bios_ptr + VBIOS_SIZE - (3 * sizeof(vbios_mode)); + + while (p < limit && map->mode_table == 0) + { + vbios_mode * mode_ptr = (vbios_mode *) p; + + if (((mode_ptr[0].mode & 0xf0) == 0x30) && ((mode_ptr[1].mode & 0xf0) == 0x30) && + ((mode_ptr[2].mode & 0xf0) == 0x30) && ((mode_ptr[3].mode & 0xf0) == 0x30)) + { + map->mode_table = mode_ptr; + } + + p++; + } + + if (map->mode_table == 0) + { + close_vbios(map); + return 0; + } + } + + + /* + * Determine size of mode table + */ + if ((map->bios != BT_ATI_1) && (map->bios != BT_ATI_2) && (map->bios != BT_NVDA)) + { + vbios_mode * mode_ptr = map->mode_table; + + while (mode_ptr->mode != 0xff) + { + map->mode_table_size++; + mode_ptr++; + } + } + + /* + * Figure out what type of bios we have + * order of detection is important + */ + if ((map->bios != BT_ATI_1) && (map->bios != BT_ATI_2) && (map->bios != BT_NVDA)) + { + if (detect_bios_type(map, TRUE, sizeof(vbios_modeline_type3))) + { + map->bios = BT_3; + } + else if (detect_bios_type(map, TRUE, sizeof(vbios_modeline_type2))) + { + map->bios = BT_2; + } + else if (detect_bios_type(map, FALSE, sizeof(vbios_resolution_type1))) + { + map->bios = BT_1; + } + else { + return 0; + } + } + + return map; +} + +void close_vbios(vbios_map * map) +{ + free(map); +} + +void unlock_vbios(vbios_map * map) +{ + + map->unlocked = TRUE; + + switch (map->chipset) { + case CT_UNKWN: + break; + case CT_830: + case CT_855GM: + outl(CONFIG_MECH_ONE_ADDR, 0x8000005a); + map->b1 = inb(CONFIG_MECH_ONE_DATA + 2); + + outl(CONFIG_MECH_ONE_ADDR, 0x8000005a); + outb(CONFIG_MECH_ONE_DATA + 2, 0x33); + break; + case CT_845G: + case CT_865G: + case CT_915G: + case CT_915GM: + case CT_945G: + case CT_945GM: + case CT_945GME: + case CT_946GZ: + case CT_G965: + case CT_Q965: + case CT_965GM: + case CT_975X: + case CT_P35: + case CT_955X: + case CT_X48: + case CT_B43: + case CT_Q45: + case CT_P45: + case CT_GM45: + case CT_G45: + case CT_G41: + case CT_G31: + case CT_500: + case CT_3150: + case CT_UNKWN_INTEL: // Assume newer intel chipset is the same as before + outl(CONFIG_MECH_ONE_ADDR, 0x80000090); + map->b1 = inb(CONFIG_MECH_ONE_DATA + 1); + map->b2 = inb(CONFIG_MECH_ONE_DATA + 2); + outl(CONFIG_MECH_ONE_ADDR, 0x80000090); + outb(CONFIG_MECH_ONE_DATA + 1, 0x33); + outb(CONFIG_MECH_ONE_DATA + 2, 0x33); + break; + } + +#if DEBUG + { + UInt32 t = inl(CONFIG_MECH_ONE_DATA); + verbose("unlock PAM: (0x%08x)\n", t); + } +#endif +} + +void relock_vbios(vbios_map * map) +{ + + map->unlocked = FALSE; + + switch (map->chipset) + { + case CT_UNKWN: + break; + case CT_830: + case CT_855GM: + outl(CONFIG_MECH_ONE_ADDR, 0x8000005a); + outb(CONFIG_MECH_ONE_DATA + 2, map->b1); + break; + case CT_845G: + case CT_865G: + case CT_915G: + case CT_915GM: + case CT_945G: + case CT_945GM: + case CT_945GME: + case CT_946GZ: + case CT_G965: + case CT_955X: + case CT_G45: + case CT_Q965: + case CT_965GM: + case CT_975X: + case CT_P35: + case CT_X48: + case CT_B43: + case CT_Q45: + case CT_P45: + case CT_GM45: + case CT_G41: + case CT_G31: + case CT_500: + case CT_3150: + case CT_UNKWN_INTEL: + outl(CONFIG_MECH_ONE_ADDR, 0x80000090); + outb(CONFIG_MECH_ONE_DATA + 1, map->b1); + outb(CONFIG_MECH_ONE_DATA + 2, map->b2); + break; + } + +#if DEBUG + { + UInt32 t = inl(CONFIG_MECH_ONE_DATA); + verbose("relock PAM: (0x%08x)\n", t); + } +#endif +} + + +int getMode(edid_mode *mode) +{ + char* edidInfo = readEDID(); + + if(!edidInfo) return 1; +//Slice + if(!fb_parse_edid((struct EDID *)edidInfo, mode)) + { + free( edidInfo ); + return 1; + } +/* mode->pixel_clock = (edidInfo[55] << 8) | edidInfo[54]; + mode->h_active = edidInfo[56] | ((edidInfo[58] & 0xF0) << 4); + mode->h_blanking = ((edidInfo[58] & 0x0F) << 8) | edidInfo[57]; + mode->v_active = edidInfo[59] | ((edidInfo[61] & 0xF0) << 4); + mode->v_blanking = ((edidInfo[61] & 0x0F) << 8) | edidInfo[60]; + mode->h_sync_offset = ((edidInfo[65] & 0xC0) >> 2) | edidInfo[62]; + mode->h_sync_width = (edidInfo[65] & 0x30) | edidInfo[63]; + mode->v_sync_offset = (edidInfo[65] & 0x0C) | ((edidInfo[64] & 0x0C) >> 2); + mode->v_sync_width = ((edidInfo[65] & 0x3) << 2) | (edidInfo[64] & 0x03); +*/ + + free( edidInfo ); + + if(!mode->h_active) return 1; + + return 0; + +} + + +static void gtf_timings(UInt32 x, UInt32 y, UInt32 freq, + unsigned long *clock, + UInt16 *hsyncstart, UInt16 *hsyncend, UInt16 *hblank, + UInt16 *vsyncstart, UInt16 *vsyncend, UInt16 *vblank) +{ + UInt32 hbl, vbl, vfreq; + + vbl = y + (y+1)/(20000.0/(11*freq) - 1) + 1.5; + vfreq = vbl * freq; + hbl = 16 * (int)(x * (30.0 - 300000.0 / vfreq) / + + (70.0 + 300000.0 / vfreq) / 16.0 + 0.5); + + *vsyncstart = y; + *vsyncend = y + 3; + *vblank = vbl - 1; + *hsyncstart = x + hbl / 2 - (x + hbl + 50) / 100 * 8 - 1; + *hsyncend = x + hbl / 2 - 1; + *hblank = x + hbl - 1; + *clock = (x + hbl) * vfreq / 1000; +} + +void set_mode(vbios_map * map, /*UInt32 mode,*/ UInt32 x, UInt32 y, UInt32 bp, UInt32 htotal, UInt32 vtotal) { + UInt32 xprev, yprev; + UInt32 i = 0, j; + // patch first available mode + + // for (i=0; i < map->mode_table_size; i++) { + // if (map->mode_table[0].mode == mode) { + switch(map->bios) { + case BT_INTEL: + return; + + case BT_1: + { + vbios_resolution_type1 * res = map_type1_resolution(map, map->mode_table[i].resolution); + + if (bp) { + map->mode_table[i].bits_per_pixel = bp; + } + + res->x2 = (htotal?(((htotal-x) >> 8) & 0x0f) : (res->x2 & 0x0f)) | ((x >> 4) & 0xf0); + res->x1 = (x & 0xff); + + res->y2 = (vtotal?(((vtotal-y) >> 8) & 0x0f) : (res->y2 & 0x0f)) | ((y >> 4) & 0xf0); + res->y1 = (y & 0xff); + if (htotal) + res->x_total = ((htotal-x) & 0xff); + + if (vtotal) + res->y_total = ((vtotal-y) & 0xff); + + break; + } + case BT_2: + { + vbios_resolution_type2 * res = map_type2_resolution(map, map->mode_table[i].resolution); + + res->xchars = x / 8; + res->ychars = y / 16 - 1; + xprev = res->modelines[0].x1; + yprev = res->modelines[0].y1; + + for(j=0; j < 3; j++) { + vbios_modeline_type2 * modeline = &res->modelines[j]; + + if (modeline->x1 == xprev && modeline->y1 == yprev) { + modeline->x1 = modeline->x2 = x-1; + modeline->y1 = modeline->y2 = y-1; + + gtf_timings(x, y, freqs[j], &modeline->clock, + &modeline->hsyncstart, &modeline->hsyncend, + &modeline->hblank, &modeline->vsyncstart, + &modeline->vsyncend, &modeline->vblank); + + if (htotal) + modeline->htotal = htotal; + else + modeline->htotal = modeline->hblank; + + if (vtotal) + modeline->vtotal = vtotal; + else + modeline->vtotal = modeline->vblank; + } + } + break; + } + case BT_3: + { + vbios_resolution_type3 * res = map_type3_resolution(map, map->mode_table[i].resolution); + + xprev = res->modelines[0].x1; + yprev = res->modelines[0].y1; + + for (j=0; j < 3; j++) { + vbios_modeline_type3 * modeline = &res->modelines[j]; + + if (modeline->x1 == xprev && modeline->y1 == yprev) { + modeline->x1 = modeline->x2 = x-1; + modeline->y1 = modeline->y2 = y-1; + + gtf_timings(x, y, freqs[j], &modeline->clock, + &modeline->hsyncstart, &modeline->hsyncend, + &modeline->hblank, &modeline->vsyncstart, + &modeline->vsyncend, &modeline->vblank); + if (htotal) + modeline->htotal = htotal; + else + modeline->htotal = modeline->hblank; + if (vtotal) + modeline->vtotal = vtotal; + else + modeline->vtotal = modeline->vblank; + + modeline->timing_h = y-1; + modeline->timing_v = x-1; + } + } + break; + } + case BT_ATI_1: + { + edid_mode mode; + + ATOM_MODE_TIMING *mode_timing = (ATOM_MODE_TIMING *) map->ati_mode_table; + + //if (mode.pixel_clock && (mode.h_active == x) && (mode.v_active == y) && !force) { + if (!getMode(&mode)) { + mode_timing->usCRTC_H_Total = mode.h_active + mode.h_blanking; + mode_timing->usCRTC_H_Disp = mode.h_active; + mode_timing->usCRTC_H_SyncStart = mode.h_active + mode.h_sync_offset; + mode_timing->usCRTC_H_SyncWidth = mode.h_sync_width; + + mode_timing->usCRTC_V_Total = mode.v_active + mode.v_blanking; + mode_timing->usCRTC_V_Disp = mode.v_active; + mode_timing->usCRTC_V_SyncStart = mode.v_active + mode.v_sync_offset; + mode_timing->usCRTC_V_SyncWidth = mode.v_sync_width; + + mode_timing->usPixelClock = mode.pixel_clock; + } + /*else + { + vbios_modeline_type2 modeline; + + cvt_timings(x, y, freqs[0], &modeline.clock, + &modeline.hsyncstart, &modeline.hsyncend, + &modeline.hblank, &modeline.vsyncstart, + &modeline.vsyncend, &modeline.vblank, 0); + + mode_timing->usCRTC_H_Total = x + modeline.hblank; + mode_timing->usCRTC_H_Disp = x; + mode_timing->usCRTC_H_SyncStart = modeline.hsyncstart; + mode_timing->usCRTC_H_SyncWidth = modeline.hsyncend - modeline.hsyncstart; + + mode_timing->usCRTC_V_Total = y + modeline.vblank; + mode_timing->usCRTC_V_Disp = y; + mode_timing->usCRTC_V_SyncStart = modeline.vsyncstart; + mode_timing->usCRTC_V_SyncWidth = modeline.vsyncend - modeline.vsyncstart; + + mode_timing->usPixelClock = modeline.clock; + }*/ + + break; + } + case BT_ATI_2: + { + edid_mode mode; + + ATOM_DTD_FORMAT *mode_timing = (ATOM_DTD_FORMAT *) map->ati_mode_table; + + /*if (mode.pixel_clock && (mode.h_active == x) && (mode.v_active == y) && !force) {*/ + if (!getMode(&mode)) { + mode_timing->usHBlanking_Time = mode.h_blanking; + mode_timing->usHActive = mode.h_active; + mode_timing->usHSyncOffset = mode.h_sync_offset; + mode_timing->usHSyncWidth = mode.h_sync_width; + + mode_timing->usVBlanking_Time = mode.v_blanking; + mode_timing->usVActive = mode.v_active; + mode_timing->usVSyncOffset = mode.v_sync_offset; + mode_timing->usVSyncWidth = mode.v_sync_width; + + mode_timing->usPixClk = mode.pixel_clock; + } + /*else + { + vbios_modeline_type2 modeline; + + cvt_timings(x, y, freqs[0], &modeline.clock, + &modeline.hsyncstart, &modeline.hsyncend, + &modeline.hblank, &modeline.vsyncstart, + &modeline.vsyncend, &modeline.vblank, 0); + + mode_timing->usHBlanking_Time = modeline.hblank; + + mode_timing->usHActive = x; + + mode_timing->usHSyncOffset = modeline.hsyncstart - x; + + mode_timing->usHSyncWidth = modeline.hsyncend - modeline.hsyncstart; + + + + mode_timing->usVBlanking_Time = modeline.vblank; + + mode_timing->usVActive = y; + + mode_timing->usVSyncOffset = modeline.vsyncstart - y; + + mode_timing->usVSyncWidth = modeline.hsyncend - modeline.hsyncstart; + + + + mode_timing->usPixClk = modeline.clock; + + }*/ + + + break; + } + case BT_NVDA: + { + edid_mode mode; + + NV_MODELINE *mode_timing = (NV_MODELINE *) map->nv_mode_table; + + /*if (mode.pixel_clock && (mode.h_active == x) && (mode.v_active == y) && !force) {*/ + if (!getMode(&mode)) { + mode_timing[i].usH_Total = mode.h_active + mode.h_blanking; + mode_timing[i].usH_Active = mode.h_active; + mode_timing[i].usH_SyncStart = mode.h_active + mode.h_sync_offset; + mode_timing[i].usH_SyncEnd = mode.h_active + mode.h_sync_offset + mode.h_sync_width; + + mode_timing[i].usV_Total = mode.v_active + mode.v_blanking; + mode_timing[i].usV_Active = mode.v_active; + mode_timing[i].usV_SyncStart = mode.v_active + mode.v_sync_offset; + mode_timing[i].usV_SyncEnd = mode.v_active + mode.v_sync_offset + mode.v_sync_width; + + mode_timing[i].usPixel_Clock = mode.pixel_clock; + } + /*else + { + vbios_modeline_type2 modeline; + + cvt_timings(x, y, freqs[0], &modeline.clock, + &modeline.hsyncstart, &modeline.hsyncend, + &modeline.hblank, &modeline.vsyncstart, + &modeline.vsyncend, &modeline.vblank, 0); + + mode_timing[i].usH_Total = x + modeline.hblank - 1; + mode_timing[i].usH_Active = x; + mode_timing[i].usH_SyncStart = modeline.hsyncstart - 1; + mode_timing[i].usH_SyncEnd = modeline.hsyncend - 1; + + mode_timing[i].usV_Total = y + modeline.vblank - 1; + mode_timing[i].usV_Active = y; + mode_timing[i].usV_SyncStart = modeline.vsyncstart - 1; + mode_timing[i].usV_SyncEnd = modeline.vsyncend - 1; + + mode_timing[i].usPixel_Clock = modeline.clock; + }*/ + break; + } + case BT_UNKWN: + { + break; + } + } + // } + // } +} + +#endif // _RESOLUTION_H_ \ No newline at end of file Index: branches/slice/rev749/modules/Resolution/include/edid.h =================================================================== --- branches/slice/rev749/modules/Resolution/include/edid.h (revision 0) +++ branches/slice/rev749/modules/Resolution/include/edid.h (revision 1169) @@ -0,0 +1,172 @@ +/* + * edid.h + * + * + * Created by Evan Lojewski on 12/1/09. + * Copyright 2009. All rights reserved. + * + * Slice 2010 + */ +//#ifndef __EDID_H__ +//#define __EDID_H__ + + +#include "libsaio.h" + +#define EDID_BLOCK_SIZE 128 +#define EDID_V1_BLOCKS_TO_GO_OFFSET 126 +//Slice - some more info about EDID +#define EDID_LENGTH 0x80 +#define EDID_HEADER 0x00 +#define EDID_HEADER_END 0x07 + +#define ID_MANUFACTURER_NAME 0x08 +#define ID_MANUFACTURER_NAME_END 0x09 +#define ID_MODEL 0x0a + +#define ID_SERIAL_NUMBER 0x0c + +#define MANUFACTURE_WEEK 0x10 +#define MANUFACTURE_YEAR 0x11 + +#define EDID_STRUCT_VERSION 0x12 +#define EDID_STRUCT_REVISION 0x13 + +#define EDID_STRUCT_DISPLAY 0x14 + +#define DPMS_FLAGS 0x18 +#define ESTABLISHED_TIMING_1 0x23 +#define ESTABLISHED_TIMING_2 0x24 +#define MANUFACTURERS_TIMINGS 0x25 + +/* standard timings supported */ +#define STD_TIMING 8 +#define STD_TIMING_DESCRIPTION_SIZE 2 +#define STD_TIMING_DESCRIPTIONS_START 0x26 + +#define DETAILED_TIMING_DESCRIPTIONS_START 0x36 +#define DETAILED_TIMING_DESCRIPTION_SIZE 18 +#define NO_DETAILED_TIMING_DESCRIPTIONS 4 + +#define DETAILED_TIMING_DESCRIPTION_1 0x36 +#define DETAILED_TIMING_DESCRIPTION_2 0x48 +#define DETAILED_TIMING_DESCRIPTION_3 0x5a +#define DETAILED_TIMING_DESCRIPTION_4 0x6c + +#define DESCRIPTOR_DATA 5 + +#define UPPER_NIBBLE( x ) \ +(((128|64|32|16) & (x)) >> 4) + +#define LOWER_NIBBLE( x ) \ +((1|2|4|8) & (x)) + +#define COMBINE_HI_8LO( hi, lo ) \ +( (((unsigned)hi) << 8) | (unsigned)lo ) + +#define COMBINE_HI_4LO( hi, lo ) \ +( (((unsigned)hi) << 4) | (unsigned)lo ) + +#define PIXEL_CLOCK_LO (unsigned)block[ 0 ] +#define PIXEL_CLOCK_HI (unsigned)block[ 1 ] +#define PIXEL_CLOCK (COMBINE_HI_8LO( PIXEL_CLOCK_HI,PIXEL_CLOCK_LO )*10000) +#define H_ACTIVE_LO (unsigned)block[ 2 ] +#define H_BLANKING_LO (unsigned)block[ 3 ] +#define H_ACTIVE_HI UPPER_NIBBLE( (unsigned)block[ 4 ] ) +#define H_ACTIVE COMBINE_HI_8LO( H_ACTIVE_HI, H_ACTIVE_LO ) +#define H_BLANKING_HI LOWER_NIBBLE( (unsigned)block[ 4 ] ) +#define H_BLANKING COMBINE_HI_8LO( H_BLANKING_HI, H_BLANKING_LO ) + +#define V_ACTIVE_LO (unsigned)block[ 5 ] +#define V_BLANKING_LO (unsigned)block[ 6 ] +#define V_ACTIVE_HI UPPER_NIBBLE( (unsigned)block[ 7 ] ) +#define V_ACTIVE COMBINE_HI_8LO( V_ACTIVE_HI, V_ACTIVE_LO ) +#define V_BLANKING_HI LOWER_NIBBLE( (unsigned)block[ 7 ] ) +#define V_BLANKING COMBINE_HI_8LO( V_BLANKING_HI, V_BLANKING_LO ) + +#define H_SYNC_OFFSET_LO (unsigned)block[ 8 ] +#define H_SYNC_WIDTH_LO (unsigned)block[ 9 ] + +#define V_SYNC_OFFSET_LO UPPER_NIBBLE( (unsigned)block[ 10 ] ) +#define V_SYNC_WIDTH_LO LOWER_NIBBLE( (unsigned)block[ 10 ] ) + +#define V_SYNC_WIDTH_HI ((unsigned)block[ 11 ] & (1|2)) +#define V_SYNC_OFFSET_HI (((unsigned)block[ 11 ] & (4|8)) >> 2) + +#define H_SYNC_WIDTH_HI (((unsigned)block[ 11 ] & (16|32)) >> 4) +#define H_SYNC_OFFSET_HI (((unsigned)block[ 11 ] & (64|128)) >> 6) + +#define V_SYNC_WIDTH COMBINE_HI_4LO( V_SYNC_WIDTH_HI, V_SYNC_WIDTH_LO ) +#define V_SYNC_OFFSET COMBINE_HI_4LO( V_SYNC_OFFSET_HI, V_SYNC_OFFSET_LO ) + +#define H_SYNC_WIDTH COMBINE_HI_4LO( H_SYNC_WIDTH_HI, H_SYNC_WIDTH_LO ) +#define H_SYNC_OFFSET COMBINE_HI_4LO( H_SYNC_OFFSET_HI, H_SYNC_OFFSET_LO ) + +#define H_SIZE_LO (unsigned)block[ 12 ] +#define V_SIZE_LO (unsigned)block[ 13 ] + +#define H_SIZE_HI UPPER_NIBBLE( (unsigned)block[ 14 ] ) +#define V_SIZE_HI LOWER_NIBBLE( (unsigned)block[ 14 ] ) + +#define H_SIZE COMBINE_HI_8LO( H_SIZE_HI, H_SIZE_LO ) +#define V_SIZE COMBINE_HI_8LO( V_SIZE_HI, V_SIZE_LO ) + +#define H_BORDER (unsigned)block[ 15 ] +#define V_BORDER (unsigned)block[ 16 ] + +#define FLAGS (unsigned)block[ 17 ] + +#define INTERLACED (FLAGS&128) +#define SYNC_TYPE (FLAGS&3<<3) /* bits 4,3 */ +#define SYNC_SEPARATE (3<<3) +#define HSYNC_POSITIVE (FLAGS & 4) +#define VSYNC_POSITIVE (FLAGS & 2) + +#define V_MIN_RATE block[ 5 ] +#define V_MAX_RATE block[ 6 ] +#define H_MIN_RATE block[ 7 ] +#define H_MAX_RATE block[ 8 ] +#define MAX_PIXEL_CLOCK (((int)block[ 9 ]) * 10) +#define GTF_SUPPORT block[10] + +#define DPMS_ACTIVE_OFF (1 << 5) +#define DPMS_SUSPEND (1 << 6) +#define DPMS_STANDBY (1 << 7) + +struct EDID +{ + UInt8 header[8]; //0 + UInt8 vendorProduct[4]; //8 + UInt8 serialNumber[4]; //12 + UInt8 weekOfManufacture; //16 + UInt8 yearOfManufacture; //17 + UInt8 version; //18 + UInt8 revision; //19 + UInt8 displayParams[5]; //20 + UInt8 colorCharacteristics[10]; //25 + UInt8 establishedTimings[3]; //35 + UInt16 standardTimings[8]; //38 + UInt8 detailedTimings[72]; //54 + UInt8 extension; //126 + UInt8 checksum; //127 +}; + + +typedef struct _edid_mode { + unsigned short pixel_clock; + unsigned short h_active; + unsigned short h_blanking; + unsigned short v_active; + unsigned short v_blanking; + unsigned short h_sync_offset; + unsigned short h_sync_width; + unsigned short v_sync_offset; + unsigned short v_sync_width; +} edid_mode; + + +char* readEDID(); +void getResolution(UInt32* x, UInt32* y, UInt32* bp); +int fb_parse_edid(struct EDID *edid, edid_mode* var); + +//#endif \ No newline at end of file Index: branches/slice/rev749/modules/Resolution/Resolution.c =================================================================== --- branches/slice/rev749/modules/Resolution/Resolution.c (revision 0) +++ branches/slice/rev749/modules/Resolution/Resolution.c (revision 1169) @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2009 Evan Lojewski. All rights reserved. + * + */ + +//#include "libsaio.h" +//#include "915resolution.h" +extern void patchVideoBios(void); + +void Resolution_start() +{ + patchVideoBios(); +} + Index: branches/slice/rev749/modules/Resolution/edid.c =================================================================== --- branches/slice/rev749/modules/Resolution/edid.c (revision 0) +++ branches/slice/rev749/modules/Resolution/edid.c (revision 1169) @@ -0,0 +1,390 @@ +/* + * edid.c + * + * + * Created by Evan Lojewski on 12/1/09. + * Copyright 2009. All rights reserved. + * + * Slice 2010 + */ + + +//#include "libsaio.h" +#include "edid.h" +#include "vbe.h" +#include "graphics.h" +#include "boot.h" +//---------------------------------------------------------------------------------- + +#define FBMON_FIX_HEADER 1 +#define FBMON_FIX_INPUT 2 +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +//---------------------------------------------------------------------------------- +/* +struct broken_edid { + const char manufacturer[4]; + UInt32 model; + UInt32 fix; +}; + +//---------------------------------------------------------------------------------- + +broken_edid brokendb[] = { + // DEC FR-PCXAV-YZ * + { "DEC", 0x073a, FBMON_FIX_HEADER,}, + // ViewSonic PF775a * + { "VSC", 0x5a44, FBMON_FIX_INPUT, } +}; +//---------------------------------------------------------------------------------- +*/ +const unsigned char edid_v1_header[] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 }; + +//---------------------------------------------------------------------------------- +int edid_compare(unsigned char *edid1, unsigned char *edid2) +{ + int result = 0; + unsigned char *block = edid1 + ID_MANUFACTURER_NAME, manufacturer1[4], manufacturer2[4];; + manufacturer1[0] = ((block[0] & 0x7c) >> 2) + '@'; + manufacturer1[1] = ((block[0] & 0x03) << 3) + ((block[1] & 0xe0) >> 5) + '@'; + manufacturer1[2] = (block[1] & 0x1f) + '@'; + manufacturer1[3] = 0; + + block = edid2 + ID_MANUFACTURER_NAME; + manufacturer2[0] = ((block[0] & 0x7c) >> 2) + '@'; + manufacturer2[1] = ((block[0] & 0x03) << 3) + ((block[1] & 0xe0) >> 5) + '@'; + manufacturer2[2] = (block[1] & 0x1f) + '@'; + manufacturer2[3] = 0; + int x; + for(x = 0; x < 4; x++) + { + if(manufacturer1[x] == manufacturer2[x]) + result++; + } + + return result; +} + +int check_edid(unsigned char *edid) +{ + unsigned char *block = edid + ID_MANUFACTURER_NAME, manufacturer[4]; + //unsigned char *b; + UInt32 model; + //int i, fix = 0, ret = 0; + + manufacturer[0] = ((block[0] & 0x7c) >> 2) + '@'; + manufacturer[1] = ((block[0] & 0x03) << 3) + + ((block[1] & 0xe0) >> 5) + '@'; + manufacturer[2] = (block[1] & 0x1f) + '@'; + manufacturer[3] = 0; + model = block[2] + (block[3] << 8); +/* + for (i = 0; i < (int)ARRAY_SIZE(brokendb); i++) { + if (!strncmp((const char *)manufacturer, brokendb[i].manufacturer, 4) && + brokendb[i].model == model) { + DEBG("ATIFB: The EDID Block of " + "Manufacturer: %s Model: 0x%08lx is known to " + "be broken,\n", manufacturer, model); + fix = brokendb[i].fix; + break; + } + } + + switch (fix) { + case FBMON_FIX_HEADER: + for (i = 0; i < 8; i++) { + if (edid[i] != edid_v1_header[i]) + ret = fix; + } + break; + case FBMON_FIX_INPUT: + b = edid + EDID_STRUCT_DISPLAY; + /// Only if display is GTF capable will + //the input type be reset to analog * + if (b[4] & 0x01 && b[0] & 0x80) + ret = fix; + break; + } +*/ + return 0; //ret; +} + +//---------------------------------------------------------------------------------- + +static void fix_edid(unsigned char *edid, int fix) +{ + unsigned char *b; + + switch (fix) { + case FBMON_FIX_HEADER: + msglog("EDID: trying a header reconstruct\n"); + memcpy(edid, edid_v1_header, 8); + break; + case FBMON_FIX_INPUT: + msglog("EDID: trying to fix input type\n"); + b = edid + EDID_STRUCT_DISPLAY; + b[0] &= ~0x80; + edid[127] += 0x80; + } +} + +//---------------------------------------------------------------------------------- + +int edid_checksum(unsigned char *edid) +{ + unsigned char i, csum = 0, all_null = 0; + int err = 0, fix = check_edid(edid); + + if (fix) + fix_edid(edid, fix); + + for (i = 0; i < EDID_LENGTH; i++) { + csum += edid[i]; + all_null |= edid[i]; + } + + if (csum == 0x00 && all_null) { + /* checksum passed, everything's good */ + err = 1; + } + + return err; +} + +//---------------------------------------------------------------------------------- + +static int edid_check_header(unsigned char *edid) +{ + int i, err = 1, fix = check_edid(edid); + + if (fix) + fix_edid(edid, fix); + + for (i = 0; i < 8; i++) { + if (edid[i] != edid_v1_header[i]) + err = 0; + } + + return err; +} +//------------------------------------------------------------------------ +bool verifyEDID(unsigned char *edid) +{ + if (edid == NULL || !edid_checksum(edid) || !edid_check_header(edid)) + { + return false; + } + return true; +} + +int edid_is_timing_block(unsigned char *block) +{ + if ((block[0] != 0x00) || (block[1] != 0x00) || + (block[2] != 0x00) || (block[4] != 0x00)) + return 1; + else + return 0; +} +//---------------------------------------------------------------------------------- + +int fb_parse_edid(struct EDID *edid, edid_mode* var) //(struct EDID *edid, UInt32* x, UInt32* y) +{ + int i; + unsigned char *block; + + if(!verifyEDID((unsigned char *)edid)) return 1; + + block = (unsigned char *)edid + DETAILED_TIMING_DESCRIPTIONS_START; //54 + + for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) { + if (edid_is_timing_block(block)) { + var->h_active = H_ACTIVE; + var->v_active = V_ACTIVE; + var->h_sync_offset = H_SYNC_OFFSET; + var->h_sync_width = H_SYNC_WIDTH; + var->h_blanking = H_BLANKING; + var->v_blanking = V_BLANKING; + var->pixel_clock = PIXEL_CLOCK; + var->h_sync_width = H_SYNC_WIDTH; + var->v_sync_width = V_SYNC_WIDTH; + /* + var->xres = var->xres_virtual = H_ACTIVE; + var->yres = var->yres_virtual = V_ACTIVE; + var->height = var->width = -1; + var->right_margin = H_SYNC_OFFSET; + var->left_margin = (H_ACTIVE + H_BLANKING) - + (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH); + var->upper_margin = V_BLANKING - V_SYNC_OFFSET - + V_SYNC_WIDTH; + var->lower_margin = V_SYNC_OFFSET; + var->hsync_len = H_SYNC_WIDTH; + var->vsync_len = V_SYNC_WIDTH; + var->pixclock = PIXEL_CLOCK; + var->pixclock /= 1000; + var->pixclock = KHZ2PICOS(var->pixclock); + + if (HSYNC_POSITIVE) + var->sync |= FB_SYNC_HOR_HIGH_ACT; + if (VSYNC_POSITIVE) + var->sync |= FB_SYNC_VERT_HIGH_ACT; + */ + return 1; + } + } + return 0; +} + +void getResolution(UInt32* x, UInt32* y, UInt32* bp) +{ + int val; + static UInt32 xResolution, yResolution, bpResolution; + + if(getIntForKey(kScreenWidth, &val, &bootInfo->bootConfig)) + { + xResolution = val; + } + + if(getIntForKey(kScreenHeight, &val, &bootInfo->bootConfig)) + { + yResolution = val; + } + + bpResolution = 32; // assume 32bits + + + if(!xResolution || !yResolution || !bpResolution) + { + + char* edidInfo = readEDID(); + + if(!edidInfo) return; + edid_mode mode; + // TODO: check *all* resolutions reported and either use the highest, or the native resolution (if there is a flag for that) + //xResolution = edidInfo[56] | ((edidInfo[58] & 0xF0) << 4); + //yResolution = edidInfo[59] | ((edidInfo[61] & 0xF0) << 4); + //Slice - done here + + if(fb_parse_edid((struct EDID *)edidInfo, &mode) == 0) + { + xResolution = DEFAULT_SCREEN_WIDTH; + yResolution = DEFAULT_SCREEN_HEIGHT; + } + else { + xResolution = mode.h_active; + yResolution = mode.v_active; + } + + /* + 0x00 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0x00 0x32 0x0C + 0x00 0xDF 0x00 0x00 0x00 0x00 0xFF 0xFF 0xFF 0x00 + 0x0C 0xDF 0x00 0x00 0x12 0x03 0x21 0x78 0xE9 0x99 + 0x53 0x28 0xFF 0xFF 0x32 0xDF 0x00 0x12 0x80 0x78 + 0xD5 0x53 0x26 0x00 0x01 0x01 0x01 0x01 0xFF 0x00 + 0xDF 0x00 0x03 0x78 0x99 0x28 0x00 0x01 0x01 0x01 + 0x01 0x21 0x84 0x20 0xFF 0x0C 0x00 0x03 0x0A 0x53 + 0x54 0x01 0x01 0x01 0xDE 0x84 0x56 0x00 0xA0 0x30 + 0xFF 0xDF 0x12 0x78 0x53 0x00 0x01 0x01 0x01 0x84 + 0x00 0x18 0x84 0x00 0x00 0x57 0xFF 0x00 0x80 0x99 + 0x54 0x01 0x01 0x21 0x20 0x00 0x50 0x00 0x00 0x35 + 0x57 0xFE 0x00 0x00 0x78 0x28 0x01 0x01 0x21 0x20 + 0x18 0x30 0x00 0x57 0x34 0xFE 0xAA 0x9A + + */ + + //msglog("H Active = %d ", edidInfo[56] | ((edidInfo[58] & 0xF0) << 4) ); + //msglog("V Active = %d \n", edidInfo[59] | ((edidInfo[61] & 0xF0) << 4) ); + + free( edidInfo ); + + //if(!xResolution) xResolution = DEFAULT_SCREEN_WIDTH; + //if(!yResolution) yResolution = DEFAULT_SCREEN_HEIGHT; + + } + + *x = xResolution; + *y = yResolution; + *bp = bpResolution; + +} + +char* readEDID() +{ + SInt16 last_reported = -1; + UInt8 edidInfo[EDID_BLOCK_SIZE]; + + UInt8 header1[] = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}; + UInt8 header2[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + SInt16 status; + UInt16 blocks_left = 1; +// msglog("readEDID\n"); + do + { + // TODO: This currently only retrieves the *last* block, make the block buffer expand as needed / calculated from the first block + + bzero( edidInfo, EDID_BLOCK_SIZE); + + status = getEDID(edidInfo, blocks_left); + + + msglog("Buffer location: 0x%X status: %d\n", SEG(edidInfo) << 16 | OFF(edidInfo), status); + + int j, i; + for (j = 0; j < 8; j++) { + for(i = 0; i < 16; i++) msglog("0x%02X ", edidInfo[((i+1) * (j + 1)) - 1]); + msglog("\n"); + } + + + + if(status == 0) + { + //if( edidInfo[0] == 0x00 || edidInfo[0] == 0xFF) + if((memcmp(edidInfo, header1, sizeof(header1)) != 0) || + (memcmp(edidInfo, header2, sizeof(header2)) != 0) ) + { + blocks_left--; + int reported = edidInfo[ EDID_V1_BLOCKS_TO_GO_OFFSET ]; + + if ( reported > blocks_left ) + { + + msglog("EDID claims %d more blocks left\n", reported); + } + + if ( (last_reported <= reported && last_reported != -1) + || reported == 0xff + /* 0xff frequently comes up in corrupt edids */ + //|| reported == MAGIC + ) + { + msglog("Last reported %d\n", last_reported); + msglog( "EDID blocks left is wrong.\n" + "Your EDID is probably invalid.\n"); + return 0; + } + else + { + //printf("Reading EDID block\n"); + //printf("H Active = %d", ebiosInfo[56] | ((ebiosInfo[58] & 0xF0) << 4) ); + //printf("V Active = %d", ebiosInfo[59] | ((ebiosInfo[61] & 0xF0) << 4) ); + + last_reported = reported; + blocks_left = reported; + } + } + else + { + msglog("Invalid block %d\n", blocks_left); + msglog("Header1 = %d", memcmp(edidInfo, header1, sizeof(header1)) ); + msglog("Header2 = %d", memcmp(edidInfo, header2, sizeof(header2)) ); + return 0; + } + } + blocks_left = 0; + } while(blocks_left); + + char* ret = malloc(sizeof(edidInfo)); + memcpy(ret, edidInfo, sizeof(edidInfo)); + return ret; +} Index: branches/slice/rev749/modules/Resolution/915resolution.h =================================================================== --- branches/slice/rev749/modules/Resolution/915resolution.h (revision 0) +++ branches/slice/rev749/modules/Resolution/915resolution.h (revision 1169) @@ -0,0 +1,217 @@ +/* + * resolution.h + * + * + * Created by Evan Lojewski on 3/4/10. + * Copyright 2009. All rights reserved. + * + */ + + +#ifndef __RESOLUTION_H +#define __RESOLUTION_H + +#include "shortatombios.h" +#include "edid.h" + + +void patchVideoBios(); + + + +/* Copied from 915 resolution created by steve tomljenovic + * + * This code is based on the techniques used in : + * + * - 855patch. Many thanks to Christian Zietz (czietz gmx net) + * for demonstrating how to shadow the VBIOS into system RAM + * and then modify it. + * + * - 1280patch by Andrew Tipton (andrewtipton null li). + * + * - 855resolution by Alain Poirier + * + * This source code is into the public domain. + */ + +#define VBIOS_START 0xc0000 +#define VBIOS_SIZE 0x10000 + +#define FALSE 0 +#define TRUE 1 + +#define MODE_TABLE_OFFSET_845G 617 + + +#define ATI_SIGNATURE1 "ATI MOBILITY RADEON" +#define ATI_SIGNATURE2 "ATI Technologies Inc" +#define NVIDIA_SIGNATURE "NVIDIA Corp" +#define INTEL_SIGNATURE "Intel Corp" + + + +/* + * NVidia Defines and structures + */ + +#define OFFSET_TO_VESA_TABLE_INDEX 2 + +typedef struct { + unsigned char ucTable_Major; + unsigned char ucTable_Minor; + unsigned char ucTable_Rev; + unsigned short usTable_Size; +} NV_COMMON_TABLE_HEADER; + +typedef struct { + short reserved1; + short reserved2; + short reserved3; +} NV_RESERVED; + +typedef struct { + unsigned short usPixel_Clock; + unsigned short usH_Active; + NV_RESERVED reserved1; + unsigned short usH_SyncStart; + unsigned short usH_SyncEnd; + unsigned short usH_Total; + unsigned short usV_Active; + NV_RESERVED reserved2; + unsigned short usV_SyncStart; + unsigned short usV_SyncEnd; + unsigned short usV_Total; + unsigned short reserved3; +} NV_MODELINE; + +typedef struct { + NV_COMMON_TABLE_HEADER sHeader; + NV_MODELINE * sModelines; +} NV_VESA_TABLE; + +/*---*/ + + +typedef enum { + CT_UNKWN, CT_UNKWN_INTEL, CT_830, CT_845G, CT_855GM, CT_865G, + CT_915G, CT_915GM, CT_945G, CT_945GM, CT_945GME, CT_946GZ, + CT_955X, CT_G965, CT_Q965, CT_965GM, CT_975X, + CT_P35, CT_X48, CT_B43, CT_Q45, CT_P45, + CT_GM45, CT_G41, CT_G31, CT_G45, CT_500, CT_3150 +} chipset_type; + + + +typedef enum { + BT_UNKWN, BT_1, BT_2, BT_3, BT_ATI_1, BT_ATI_2, BT_NVDA, BT_INTEL +} bios_type; + + +typedef struct { + char *base; + ATOM_ROM_HEADER *AtomRomHeader; + unsigned short *MasterCommandTables; + unsigned short *MasterDataTables; +} bios_tables_t; + +typedef struct { + UInt8 mode; + UInt8 bits_per_pixel; + UInt16 resolution; + UInt8 unknown; +} __attribute__((packed)) vbios_mode; + +typedef struct { + UInt8 unknow1[2]; + UInt8 x1; + UInt8 x_total; + UInt8 x2; + UInt8 y1; + UInt8 y_total; + UInt8 y2; +} __attribute__((packed)) vbios_resolution_type1; + +typedef struct { + unsigned long clock; + + UInt16 x1; + UInt16 htotal; + UInt16 x2; + UInt16 hblank; + UInt16 hsyncstart; + UInt16 hsyncend; + UInt16 y1; + UInt16 vtotal; + UInt16 y2; + UInt16 vblank; + UInt16 vsyncstart; + UInt16 vsyncend; +} __attribute__((packed)) vbios_modeline_type2; + +typedef struct { + UInt8 xchars; + UInt8 ychars; + UInt8 unknown[4]; + + vbios_modeline_type2 modelines[]; +} __attribute__((packed)) vbios_resolution_type2; + +typedef struct { + unsigned long clock; + + UInt16 x1; + UInt16 htotal; + UInt16 x2; + UInt16 hblank; + UInt16 hsyncstart; + UInt16 hsyncend; + + UInt16 y1; + UInt16 vtotal; + UInt16 y2; + UInt16 vblank; + UInt16 vsyncstart; + UInt16 vsyncend; + + UInt16 timing_h; + UInt16 timing_v; + + UInt8 unknown[6]; +} __attribute__((packed)) vbios_modeline_type3; + +typedef struct { + unsigned char unknown[6]; + + vbios_modeline_type3 modelines[]; +} __attribute__((packed)) vbios_resolution_type3; + +typedef struct { + UInt32 chipset_id; + chipset_type chipset; + bios_type bios; + + bios_tables_t ati_tables; + + + UInt32 bios_fd; + char* bios_ptr; + + vbios_mode * mode_table; + char * ati_mode_table; + char * nv_mode_table; + + UInt32 mode_table_size; + UInt8 b1, b2; + + UInt8 unlocked; +} vbios_map; + + + +vbios_map * open_vbios(chipset_type); +void close_vbios (vbios_map*); +void unlock_vbios(vbios_map*); +void relock_vbios(vbios_map*); +void set_mode(vbios_map*, UInt32, UInt32, UInt32, UInt32, UInt32); + +#endif //__RESOLUTION_H Index: branches/slice/rev749/modules/Resolution/Makefile =================================================================== --- branches/slice/rev749/modules/Resolution/Makefile (revision 0) +++ branches/slice/rev749/modules/Resolution/Makefile (revision 1169) @@ -0,0 +1,49 @@ +MODULE_NAME = Resolution +MODULE_VERSION = "1.0.0" +MODULE_COMPAT_VERSION = "1.0.0" +MODULE_START = _$(MODULE_NAME)_start +MODULE_DEPENDENCIES = + + +DIR = Resolution + +MODULE_OBJS = Resolution.o edid.o 915resolution.o + +OPTIM = -Os -Oz +DEBUG = -DNOTHING +#DEBUG = -DDEBUG_HELLO_WORLD=1 +CFLAGS = $(RC_CFLAGS) $(OPTIM) $(MORECPP) -arch i386 -g -Wmost \ + -D__ARCHITECTURE__=\"i386\" -DSAIO_INTERNAL_USER \ + -DRCZ_COMPRESSED_FILE_SUPPORT $(DEBUG) \ + -fno-builtin $(OMIT_FRAME_POINTER_CFLAG) \ + -mpreferred-stack-boundary=2 -fno-align-functions -fno-stack-protector \ + -march=pentium4 -msse2 -mfpmath=sse -msoft-float -fno-common + +DEFINES= +CONFIG = hd +INC = -I. -I.. -I$(SYMROOT) -I$(UTILDIR) -I$(LIBSADIR) -I$(LIBSAIODIR) -I$(BOOT2DIR) +ifneq "" "$(wildcard /bin/mkdirs)" + MKDIRS = /bin/mkdirs +else + MKDIRS = /bin/mkdir -p +endif +AS = as +LD = ld +# LIBS= -lc_static +LIBS= + +VPATH = $(OBJROOT):$(SYMROOT) + +SFILES = +CFILES = +HFILES = +EXPORTED_HFILES = +INSTALLED_HFILES = +OTHERFILES = Makefile +ALLSRC = $(SFILES) $(CFILES) \ + $(HFILES) $(OTHERFILES) +DIRS_NEEDED = $(OBJROOT) $(SYMROOT) + +all embedtheme optionrom: dylib + +include ../MakeInc.dir \ No newline at end of file Index: branches/slice/rev749/modules/lazydylib1.c =================================================================== --- branches/slice/rev749/modules/lazydylib1.c (revision 0) +++ branches/slice/rev749/modules/lazydylib1.c (revision 1169) @@ -0,0 +1,15 @@ +/* +000003b3 S _dyld_lazy_dylib_proxy +00000071 T _lazy_load_dylib +00000000 T dyld_lazy_dylib_stub_binding_helper +*/ +#if 0 +int dyld_lazy_dylib_proxy() +{ + return 0; +} + +void* lazy_load_dylib(void* lazyPointer) +{ +} +#endif \ No newline at end of file Index: branches/slice/rev749/modules/Memory/dram_controllers.h =================================================================== --- branches/slice/rev749/modules/Memory/dram_controllers.h (revision 0) +++ branches/slice/rev749/modules/Memory/dram_controllers.h (revision 1169) @@ -0,0 +1,32 @@ +/* + * dram controller access and scan from the pci host controller + * Integrated and adapted for chameleon 2.0 RC5 by Rekursor from bs0d work + * original source comes from: + * + * memtest86 + * + * Released under version 2 of the Gnu Public License. + * By Chris Brady, cbrady@sgi.com + * ---------------------------------------------------- + * MemTest86+ V4.00 Specific code (GPL V2.0) + * By Samuel DEMEULEMEESTER, sdemeule@memtest.org + * http://www.canardpc.com - http://www.memtest.org + */ + +#ifndef __LIBSAIO_DRAM_CONTROLLERS_H +#define __LIBSAIO_DRAM_CONTROLLERS_H + +#include "libsaio.h" + +void scan_dram_controller(); + +struct mem_controller_t { + uint16_t vendor; + uint16_t device; + char *name; + void (*initialise)(pci_dt_t *dram_dev); + void (*poll_speed)(pci_dt_t *dram_dev); + void (*poll_timings)(pci_dt_t *dram_dev); +}; + +#endif /* !__LIBSAIO_DRAM_CONTROLLERS_H */ Index: branches/slice/rev749/modules/Memory/mem.c =================================================================== --- branches/slice/rev749/modules/Memory/mem.c (revision 0) +++ branches/slice/rev749/modules/Memory/mem.c (revision 1169) @@ -0,0 +1,141 @@ +/* + * Copyright 2010 AsereBLN. All rights reserved. + * + * mem.c - obtain system memory information + */ + +#include "libsaio.h" +#include "pci.h" +#include "platform.h" +//#include "cpu.h" +#include "mem.h" +#include "smbios_patcher.h" + +#ifndef DEBUG_MEM +#define DEBUG_MEM 0 +#endif + +#if DEBUG_MEM +#define DBG(x...) verbose(x) +#else +#define DBG(x...) +#endif + +#define DC(c) (c >= 0x20 && c < 0x7f ? (char) c : '.') +#define STEP 16 + +void dumpPhysAddr(const char * title, void * a, int len) +{ + int i,j; + u_int8_t* ad = (u_int8_t*) a; + char buffer[80]; + char str[16]; + + if(ad==NULL) return; + + DBG("%s addr=0x%08x len=%04d\n",title ? title : "Dump of ", a, len); + DBG("Ofs-00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F ASCII\n"); + i = (len/STEP)*STEP; + for (j=0; j < i; j+=STEP) + { + DBG("%02x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", + j, + ad[j], ad[j+1], ad[j+2], ad[j+3] , ad[j+4], ad[j+5], ad[j+6], ad[j+7], + ad[j+8], ad[j+9], ad[j+10], ad[j+11] , ad[j+12], ad[j+13], ad[j+14], ad[j+15], + DC(ad[j]), DC(ad[j+1]), DC(ad[j+2]), DC(ad[j+3]) , DC(ad[j+4]), DC(ad[j+5]), DC(ad[j+6]), DC(ad[j+7]), + DC(ad[j+8]), DC(ad[j+9]), DC(ad[j+10]), DC(ad[j+11]) , DC(ad[j+12]), DC(ad[j+13]), DC(ad[j+14]), DC(ad[j+15]) + ); + } + + if (len%STEP==0) return; + sprintf(buffer,"%02x:", i); + for (j=0; j < STEP; j++) { + if (j<(len%STEP)) + sprintf(str, " %02x", ad[i+j]); + else + strcpy(str, " " ); + strncat(buffer, str, sizeof(buffer)); + } + strncat(buffer," ", sizeof(buffer)); + for (j=0; j < (len%STEP); j++) { + sprintf(str, "%c", DC(ad[i+j])); + strncat(buffer, str, sizeof(buffer)); + } + DBG("%s\n",buffer); +} + +void dumpAllTablesOfType(int i) +{ + char title[32]; + struct DMIHeader * dmihdr; + for(dmihdr = FindFirstDmiTableOfType(i, 4); + dmihdr; + dmihdr = FindNextDmiTableOfType(i, 4)) { + sprintf(title,"Table (type %d) :" , i); + dumpPhysAddr(title, dmihdr, dmihdr->length+32); + } +} + +const char * getDMIString(struct DMIHeader * dmihdr, uint8_t strNum) +{ + const char * ret =NULL; + const char * startAddr = (const char *) dmihdr; + const char * limit = NULL; + + if (!dmihdr || dmihdr->length<4 || strNum==0) return NULL; + startAddr += dmihdr->length; + limit = startAddr + 256; + for(; strNum; strNum--) { + if ((*startAddr)==0 && *(startAddr+1)==0) break; + if (*startAddr && strNum<=1) { + ret = startAddr; // current str + break; + } + while(*startAddr && startAddrDMI.MemoryModules = 0; + /* Now lets peek info rom table 16,17 as for some bios, table 5 & 6 are not used */ + physMemArray = (struct DMIPhysicalMemoryArray*) FindFirstDmiTableOfType(16, 4); + Platform->DMI.MaxMemorySlots = physMemArray ? physMemArray->numberOfMemoryDevices : 0; + + i = 0; + for(dmihdr = FindFirstDmiTableOfType(17, 4); + dmihdr; + dmihdr = FindNextDmiTableOfType(17, 4) ) { + memDev[i] = (struct DMIMemoryDevice*) dmihdr; + if (memDev[i]->size !=0 ) Platform->DMI.MemoryModules++; + if (memDev[i]->memorySpeed>0) Platform->RAM.DIMM[i].Frequency = memDev[i]->memorySpeed; // take it here for now but we'll check spd and dmi table 6 as well + i++; + } + // for table 6, we only have a look at the current speed + i = 0; + for(dmihdr = FindFirstDmiTableOfType(6, 4); + dmihdr; + dmihdr = FindNextDmiTableOfType(6, 4) ) { + memInfo[i] = (struct DMIMemoryModuleInfo*) dmihdr; + if (memInfo[i]->currentSpeed > Platform->RAM.DIMM[i].Frequency) + Platform->RAM.DIMM[i].Frequency = memInfo[i]->currentSpeed; // favor real overclocked speed if any + i++; + } +#if DEBUG_MEM + dumpAllTablesOfType(17); + // getc(); +#endif +} Index: branches/slice/rev749/modules/Memory/mem.h =================================================================== --- branches/slice/rev749/modules/Memory/mem.h (revision 0) +++ branches/slice/rev749/modules/Memory/mem.h (revision 1169) @@ -0,0 +1,15 @@ +/* + * Copyright 2010 AsereBLN. All rights reserved. + * + * mem.h + */ + +#ifndef __LIBSAIO_MEM_H +#define __LIBSAIO_MEM_H + +#include "platform.h" + +extern void scan_memory(); //PlatformInfo_t *); + + +#endif /* __LIBSAIO_MEM_H */ Index: branches/slice/rev749/modules/Memory/spd.c =================================================================== --- branches/slice/rev749/modules/Memory/spd.c (revision 0) +++ branches/slice/rev749/modules/Memory/spd.c (revision 1169) @@ -0,0 +1,435 @@ +/* + * spd.c - serial presence detect memory information + * + * Originally restored from pcefi10.5 + * Dynamic mem detection original impl. by Rekursor + * System profiler fix and other fixes by Mozodojo. + */ + +#include "libsaio.h" +#include "pci.h" +#include "platform.h" +#include "spd.h" +#include "saio_internal.h" +#include "bootstruct.h" +#include "memvendors.h" + +#ifndef DEBUG_SPD +#define DEBUG_SPD 0 +#endif + +#if DEBUG_SPD +#define DBG(x...) verbose(x) +#else +#define DBG(x...) +#endif + +const char *spd_memory_types[] = +{ + "RAM", /* 00h Undefined */ + "FPM", /* 01h FPM */ + "EDO", /* 02h EDO */ + "", /* 03h PIPELINE NIBBLE */ + "SDRAM", /* 04h SDRAM */ + "", /* 05h MULTIPLEXED ROM */ + "DDR SGRAM", /* 06h SGRAM DDR */ + "DDR SDRAM", /* 07h SDRAM DDR */ + "DDR2 SDRAM", /* 08h SDRAM DDR 2 */ + "", /* 09h Undefined */ + "", /* 0Ah Undefined */ + "DDR3 SDRAM" /* 0Bh SDRAM DDR 3 */ +}; + +#define UNKNOWN_MEM_TYPE 2 +uint8_t spd_mem_to_smbios[] = +{ + UNKNOWN_MEM_TYPE, /* 00h Undefined */ + UNKNOWN_MEM_TYPE, /* 01h FPM */ + UNKNOWN_MEM_TYPE, /* 02h EDO */ + UNKNOWN_MEM_TYPE, /* 03h PIPELINE NIBBLE */ + SMB_MEM_TYPE_SDRAM, /* 04h SDRAM */ + SMB_MEM_TYPE_ROM, /* 05h MULTIPLEXED ROM */ + SMB_MEM_TYPE_SGRAM, /* 06h SGRAM DDR */ + SMB_MEM_TYPE_DDR, /* 07h SDRAM DDR */ + SMB_MEM_TYPE_DDR2, /* 08h SDRAM DDR 2 */ + UNKNOWN_MEM_TYPE, /* 09h Undefined */ + UNKNOWN_MEM_TYPE, /* 0Ah Undefined */ + SMB_MEM_TYPE_DDR3 /* 0Bh SDRAM DDR 3 */ +}; +#define SPD_TO_SMBIOS_SIZE (sizeof(spd_mem_to_smbios)/sizeof(uint8_t)) + +#define rdtsc(low,high) \ +__asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high)) + +#define SMBHSTSTS 0 +#define SMBHSTCNT 2 +#define SMBHSTCMD 3 +#define SMBHSTADD 4 +#define SMBHSTDAT 5 +#define SBMBLKDAT 7 + +/** Read one byte from the intel i2c, used for reading SPD on intel chipsets only. */ +unsigned char smb_read_byte_intel(uint32_t base, uint8_t adr, uint8_t cmd) +{ + int l1 = 0; + int l2 = 0; + int h1 = 0; + int h2 = 0; + unsigned long long t; + if(!Platform->CPU.TSCFrequency) Platform->CPU.TSCFrequency = Platform->CPU.CPUFrequency; + outb(base + SMBHSTSTS, 0x1f); // reset SMBus Controller + outb(base + SMBHSTDAT, 0xff); + + while( inb(base + SMBHSTSTS) & 0x01) + { + rdtsc(l2, h2); + t = ((h2 - h1) * 0xffffffff + (l2 - l1)) / (Platform->CPU.TSCFrequency / 100); + if(t > 200) return 0xFF; // hack, exit if unresponsive. + } + + outb(base + SMBHSTCMD, cmd); + outb(base + SMBHSTADD, (adr << 1) | 0x01 ); + outb(base + SMBHSTCNT, 0x48 ); + + rdtsc(l1, h1); + + while (!( inb(base + SMBHSTSTS) & 0x02)) // wait til command finished + { + rdtsc(l2, h2); + t = ((h2 - h1) * 0xffffffff + (l2 - l1)) / (Platform->CPU.TSCFrequency / 100); + if (t > 5) + break; // break after 5ms + } + return inb(base + SMBHSTDAT); +} + +/* SPD i2c read optimization: prefetch only what we need, read non prefetcheable bytes on the fly */ +#define READ_SPD(spd, base, slot, x) spd[x] = smb_read_byte_intel(base, 0x50 + slot, x) + +int spd_indexes[] = { + SPD_MEMORY_TYPE, + SPD_DDR3_MEMORY_BANK, + SPD_DDR3_MEMORY_CODE, + SPD_NUM_ROWS, + SPD_NUM_COLUMNS, + SPD_NUM_DIMM_BANKS, + SPD_NUM_BANKS_PER_SDRAM, + 4,7,8,9,12,64, /* TODO: give names to these values */ + 95,96,97,98, 122,123,124,125 /* UIS */ +}; +#define SPD_INDEXES_SIZE (sizeof(spd_indexes) / sizeof(int)) + +/** Read from spd *used* values only*/ +static void init_spd(char * spd, uint32_t base, int slot) +{ + int i; + for (i=0; i< SPD_INDEXES_SIZE; i++) { + READ_SPD(spd, base, slot, spd_indexes[i]); + } +} + +/** Get Vendor Name from spd, 2 cases handled DDR3 and DDR2, + have different formats, always return a valid ptr.*/ +const char * getVendorName(RamSlotInfo_t* slot, uint32_t base, int slot_num) +{ + uint8_t bank = 0; + uint8_t code = 0; + int i = 0; + uint8_t * spd = (uint8_t *) slot->spd; + + if (spd[SPD_MEMORY_TYPE]==SPD_MEMORY_TYPE_SDRAM_DDR3) { // DDR3 + bank = (spd[SPD_DDR3_MEMORY_BANK] & 0x07f); // constructors like Patriot use b7=1 + code = spd[SPD_DDR3_MEMORY_CODE]; + for (i=0; i < VEN_MAP_SIZE; i++) + if (bank==vendorMap[i].bank && code==vendorMap[i].code) + return vendorMap[i].name; + } + else if (spd[SPD_MEMORY_TYPE]==SPD_MEMORY_TYPE_SDRAM_DDR2) { + if(spd[64]==0x7f) { + for (i=64; i<72 && spd[i]==0x7f;i++) { + bank++; + READ_SPD(spd, base, slot_num,i+1); // prefetch next spd byte to read for next loop + } + READ_SPD(spd, base, slot_num,i); + code = spd[i]; + } else { + code = spd[64]; + bank = 0; + } + for (i=0; i < VEN_MAP_SIZE; i++) + if (bank==vendorMap[i].bank && code==vendorMap[i].code) + return vendorMap[i].name; + } + /* OK there is no vendor id here lets try to match the partnum if it exists */ + if (strstr(slot->PartNo,"GU332") == slot->PartNo) // Unifosa fingerprint + return "Unifosa"; + return "NoName"; +} + +/** Get Default Memory Module Speed (no overclocking handled) */ +int getDDRspeedMhz(const char * spd) +{ + if (spd[SPD_MEMORY_TYPE]==SPD_MEMORY_TYPE_SDRAM_DDR3) { + switch(spd[12]) { + case 0x0f: + return 1066; + case 0x0c: + return 1333; + case 0x0a: + return 1600; + case 0x14: + default: + return 800; + } + } + else if (spd[SPD_MEMORY_TYPE]==SPD_MEMORY_TYPE_SDRAM_DDR2) { + switch(spd[9]) { + case 0x50: + return 400; + case 0x3d: + return 533; + case 0x30: + return 667; + case 0x25: + default: + return 800; + } + } + return 800; // default freq for unknown types +} + +#define SMST(a) ((uint8_t)((spd[a] & 0xf0) >> 4)) +#define SLST(a) ((uint8_t)(spd[a] & 0x0f)) + +/** Get DDR3 or DDR2 serial number, 0 most of the times, always return a valid ptr */ +char asciiSerial[16]; +const char *getDDRSerial(const char* spd) +{ + + if (spd[SPD_MEMORY_TYPE]==SPD_MEMORY_TYPE_SDRAM_DDR3) // DDR3 + { + sprintf(asciiSerial, "%X%X%X%X%X%X%X%X", SMST(122) /*& 0x7*/, SLST(122), SMST(123), SLST(123), SMST(124), SLST(124), SMST(125), SLST(125)); + } + else if (spd[SPD_MEMORY_TYPE]==SPD_MEMORY_TYPE_SDRAM_DDR2) // DDR2 or DDR + { + sprintf(asciiSerial, "%X%X%X%X%X%X%X%X", SMST(95) /*& 0x7*/, SLST(95), SMST(96), SLST(96), SMST(97), SLST(97), SMST(98), SLST(98)); + } + + return strdup(asciiSerial); +} + +/** Get DDR3 or DDR2 Part Number, always return a valid ptr */ +char asciiPartNo[32]; +const char * getDDRPartNum(char* spd, uint32_t base, int slot) +{ + int i, start=0, index = 0; + + if (spd[SPD_MEMORY_TYPE]==SPD_MEMORY_TYPE_SDRAM_DDR3) { + start = 128; + } + else if (spd[SPD_MEMORY_TYPE]==SPD_MEMORY_TYPE_SDRAM_DDR2) { + start = 73; + } + + // Check that the spd part name is zero terminated and that it is ascii: + bzero(asciiPartNo, sizeof(asciiPartNo)); + char c; + for (i=start; i < start + sizeof(asciiPartNo); i++) { + READ_SPD(spd, base, slot, i); // only read once the corresponding model part (ddr3 or ddr2) + c = spd[i]; + if (isalpha(c) || isdigit(c) || ispunct(c)) // It seems that System Profiler likes only letters and digits... + asciiPartNo[index++] = c; + else if (!isascii(c)) + break; + } + + return strdup(asciiPartNo); + return NULL; +} + +int mapping []= {0,2,1,3,4,6,5,7,8,10,9,11}; + + +/** Read from smbus the SPD content and interpret it for detecting memory attributes */ +static void read_smb_intel(pci_dt_t *smbus_dev) +{ + int i, speed; + uint8_t spd_size, spd_type; + uint32_t base, mmio, hostc; + bool dump = false; + RamSlotInfo_t* slot; + if (!Platform->CPU.TSCFrequency) { + Platform->CPU.TSCFrequency = Platform->CPU.CPUFrequency; + } + uint16_t cmd = pci_config_read16(smbus_dev->dev.addr, 0x04); + DBG("SMBus CmdReg: 0x%x\n", cmd); + pci_config_write16(smbus_dev->dev.addr, 0x04, cmd | 1); + + mmio = pci_config_read32(smbus_dev->dev.addr, 0x10);// & ~0x0f; + base = pci_config_read16(smbus_dev->dev.addr, 0x20) & 0xFFFE; + hostc = pci_config_read8(smbus_dev->dev.addr, 0x40); + DBG("Scanning SMBus [%04x:%04x], mmio: 0x%x, ioport: 0x%x, hostc: 0x%x\n", + smbus_dev->vendor_id, smbus_dev->device_id, mmio, base, hostc); + + getBoolForKey("DumpSPD", &dump, &bootInfo->bootConfig); + bool fullBanks = // needed at least for laptops + Platform->DMI.MemoryModules == Platform->DMI.MaxMemorySlots; + // Search MAX_RAM_SLOTS slots + char spdbuf[256]; + + for (i = 0; i < MAX_RAM_SLOTS; i++){ + DBG("Scanning slot %d\n", i); + slot = &Platform->RAM.DIMM[i]; + spd_size = smb_read_byte_intel(base, 0x50 + i, 0); + DBG("SPD[0] (size): %d @0x%x\n", spd_size, 0x50 + i); + // Check spd is present + if (spd_size && (spd_size != 0xff)) + { + + slot->spd = spdbuf; + slot->InUse = true; + + bzero(slot->spd, spd_size); + + // Copy spd data into buffer + + //for (x = 0; x < spd_size; x++) slot->spd[x] = smb_read_byte_intel(base, 0x50 + i, x); + init_spd(slot->spd, base, i); + + switch (slot->spd[SPD_MEMORY_TYPE]) { + case SPD_MEMORY_TYPE_SDRAM_DDR2: + + slot->ModuleSize = ((1 << (slot->spd[SPD_NUM_ROWS] & 0x0f) + (slot->spd[SPD_NUM_COLUMNS] & 0x0f) - 17) * + ((slot->spd[SPD_NUM_DIMM_BANKS] & 0x7) + 1) * slot->spd[SPD_NUM_BANKS_PER_SDRAM]); + break; + + case SPD_MEMORY_TYPE_SDRAM_DDR3: + + slot->ModuleSize = ((slot->spd[4] & 0x0f) + 28 ) + ((slot->spd[8] & 0x7) + 3 ); + slot->ModuleSize -= (slot->spd[7] & 0x7) + 25; + slot->ModuleSize = ((1 << slot->ModuleSize) * (((slot->spd[7] >> 3) & 0x1f) + 1)); + + break; + } + + spd_type = (slot->spd[SPD_MEMORY_TYPE] < ((char) 12) ? slot->spd[SPD_MEMORY_TYPE] : 0); + slot->Type = spd_mem_to_smbios[spd_type]; + slot->PartNo = getDDRPartNum(slot->spd, base, i); + slot->Vendor = getVendorName(slot, base, i); + slot->SerialNo = getDDRSerial(slot->spd); + + // determine spd speed + speed = getDDRspeedMhz(slot->spd); + if (slot->FrequencyFrequency = speed; + + // pci memory controller if available, is more reliable + if (Platform->RAM.Frequency > 0) { + uint32_t freq = (uint32_t)Platform->RAM.Frequency / 500000; + // now round off special cases + uint32_t fmod100 = freq %100; + switch(fmod100) { + case 1: freq--; break; + case 32: freq++; break; + case 65: freq++; break; + case 98: freq+=2;break; + case 99: freq++; break; + } + slot->Frequency = freq; + } + + DBG("Slot: %d Type %d %dMB (%s) %dMHz Vendor=%s\n PartNo=%s SerialNo=%s\n", + i, + (int)slot->Type, + slot->ModuleSize, + spd_memory_types[spd_type], + slot->Frequency, + slot->Vendor, + slot->PartNo, + slot->SerialNo); + if(DEBUG_SPD) { + dumpPhysAddr("spd content: ",slot->spd, spd_size); + // getc(); + } + } + // laptops sometimes show slot 0 and 2 with slot 1 empty when only 2 slots are presents so: + Platform->DMI.DIMM[i]= + i>0 && Platform->RAM.DIMM[1].InUse==false && fullBanks && Platform->DMI.MaxMemorySlots==2 ? + mapping[i] : i; // for laptops case, mapping setup would need to be more generic than this + + slot->spd = NULL; + + } // for +} + +struct smbus_controllers_t smbus_controllers[] = { + + {0x8086, 0x269B, "ESB2", read_smb_intel }, + {0x8086, 0x25A4, "6300ESB", read_smb_intel }, + {0x8086, 0x24C3, "ICH4", read_smb_intel }, + {0x8086, 0x24D3, "ICH5", read_smb_intel }, + {0x8086, 0x266A, "ICH6", read_smb_intel }, + {0x8086, 0x27DA, "ICH7", read_smb_intel }, + {0x8086, 0x283E, "ICH8", read_smb_intel }, + {0x8086, 0x2930, "ICH9", read_smb_intel }, + {0x8086, 0x3A30, "ICH10R", read_smb_intel }, + {0x8086, 0x3A60, "ICH10B", read_smb_intel }, + {0x8086, 0x3B30, "P55", read_smb_intel }, + {0x8086, 0x5032, "EP80579", read_smb_intel } + +}; +/* +// initial call : pci_dt = root_pci_dev; +// find_and_read_smbus_controller(root_pci_dev); +bool find_and_read_smbus_controller(pci_dt_t* pci_dt) +{ + pci_dt_t *current = pci_dt; + int i; + bool ret = false; + while (current) { +#if 1 + msglog("%02x:%02x.%x [%04x%02x] [%04x:%04x] :: %s\n", + current->dev.bits.bus, current->dev.bits.dev, current->dev.bits.func, + current->class_id, current->subclass, current->vendor_id, current->device_id, + get_pci_dev_path(current)); +#endif + for ( i = 0; i < sizeof(smbus_controllers) / sizeof(smbus_controllers[0]); i++ ) + { + if (current->vendor_id == smbus_controllers[i].vendor && + current->device_id == smbus_controllers[i].device) + { + smbus_controllers[i].read_smb(current); // read smb + return true; + } + } + ret = ret || find_and_read_smbus_controller(current->children); + current = current->next; + } + return ret; // not found +} +*/ +bool is_smbus_controller(pci_dt_t* pci_dt) +{ + int i = 0; + for ( ; i < sizeof(smbus_controllers) / sizeof(smbus_controllers[0]); i++ ) + { + if (pci_dt->vendor_id == smbus_controllers[i].vendor && + pci_dt->device_id == smbus_controllers[i].device) + { + return true; + } + } + return false; +} + +void scan_spd(PlatformInfo_t *p, pci_dt_t* smbus_controller_dev) +{ + int i = 0; + for ( ; i < sizeof(smbus_controllers) / sizeof(smbus_controllers[0]); i++ ) + { + if (smbus_controller_dev->vendor_id == smbus_controllers[i].vendor && + smbus_controller_dev->device_id == smbus_controllers[i].device) + { + smbus_controllers[i].read_smb(smbus_controller_dev); // read smb + } + } +} Index: branches/slice/rev749/modules/Memory/Memory.c =================================================================== --- branches/slice/rev749/modules/Memory/Memory.c (revision 0) +++ branches/slice/rev749/modules/Memory/Memory.c (revision 1169) @@ -0,0 +1,78 @@ +/* + * DRAM Controller Module + * Scans the dram controller and notifies OS X of the memory modules. + * This was converted from boot2 code to a boot2 module. + * + */ + +#include "libsaio.h" +#include "pci.h" +#include "platform.h" +#include "dram_controllers.h" +#include "spd.h" +#include "mem.h" +#include "boot.h" +#include "bootstruct.h" +#include "modules.h" + +#define DEBUG_MEMORY 0 + +#if DEBUG_MEMORY +#define DBG(x...) verbose(x) +#else +#define DBG(x...) +#endif + + +pci_dt_t * dram_controller_dev = NULL; +pci_dt_t * smbus_controller_dev = NULL; + + +void Memory_hook(void* arg1, void* arg2, void* arg3, void* arg4); +void Memory_PCIDevice_hook(void* arg1, void* arg2, void* arg3, void* arg4); + + +void Memory_start() +{ + register_hook_callback("PCIDevice", &Memory_PCIDevice_hook); + register_hook_callback("ScanMemory", &Memory_hook); + +} + +void Memory_PCIDevice_hook(void* arg1, void* arg2, void* arg3, void* arg4) +{ + pci_dt_t* current = arg1; + if(current->class_id == PCI_CLASS_BRIDGE_HOST) + { + dram_controller_dev = current; + DBG("dram_controller_dev found devID=%08x\n", current->device_id); + } + else if(is_smbus_controller(current)) + { + smbus_controller_dev = current; + DBG("smbus_controller_dev found devID=%08x\n", current->device_id); + } + +} + +void Memory_hook(void* arg1, void* arg2, void* arg3, void* arg4) +{ + bool useAutodetection = true; + getBoolForKey(kUseMemDetect, &useAutodetection, &bootInfo->bootConfig); + + + if (useAutodetection) { + + if (dram_controller_dev!=NULL) { + scan_dram_controller(dram_controller_dev); // Rek: pci dev ram controller direct and fully informative scan ... + } + scan_memory(Platform); // unfortunately still necesary for some comp where spd cant read correct speed + DBG("scan_memory \n"); + if(smbus_controller_dev) + { + scan_spd(Platform, smbus_controller_dev); + DBG("scan_spd \n"); + } + } + +} \ No newline at end of file Index: branches/slice/rev749/modules/Memory/dram_controllers.c =================================================================== --- branches/slice/rev749/modules/Memory/dram_controllers.c (revision 0) +++ branches/slice/rev749/modules/Memory/dram_controllers.c (revision 1169) @@ -0,0 +1,565 @@ +/* + * dram controller access and scan from the pci host controller + * Integrated and adapted for chameleon 2.0 RC5 by Rekursor from bs0d work + * original source comes from: + * + * memtest86 + * + * Released under version 2 of the Gnu Public License. + * By Chris Brady, cbrady@sgi.com + * ---------------------------------------------------- + * MemTest86+ V4.00 Specific code (GPL V2.0) + * By Samuel DEMEULEMEESTER, sdemeule@memtest.org + * http://www.canardpc.com - http://www.memtest.org + */ + +#include "libsaio.h" +#include "bootstruct.h" +#include "pci.h" +#include "platform.h" +#include "dram_controllers.h" + +#ifndef DEBUG_DRAM +#define DEBUG_DRAM 0 +#endif + +#if DEBUG_DRAM +#define DBG(x...) verbose(x) +#else +#define DBG(x...) +#endif + +/* + * Initialise memory controller functions + */ + +// Setup P35 Memory Controller +static void setup_p35(pci_dt_t *dram_dev) +{ + uint32_t dev0; + + // Activate MMR I/O + dev0 = pci_config_read32(dram_dev->dev.addr, 0x48); + if (!(dev0 & 0x1)) + pci_config_write8(dram_dev->dev.addr, 0x48, (dev0 | 1)); +} + +int nhm_bus = 0x3F; +long possible_nhm_bus[] = {0xFF, 0x7F, 0x3F}; + +// Setup Nehalem Integrated Memory Controller +static void setup_nhm(pci_dt_t *dram_dev) +{ + unsigned long did, vid; + int i; + + // Nehalem supports Scrubbing + // First, locate the PCI bus where the MCH is located + for(i = 0; i < sizeof(possible_nhm_bus); i++) + { + vid = pci_config_read16(PCIADDR(possible_nhm_bus[i], 3, 4), 0x00); + did = pci_config_read16(PCIADDR(possible_nhm_bus[i], 3, 4), 0x02); + vid &= 0xFFFF; + did &= 0xFF00; + + if(vid == 0x8086 && did >= 0x2C00) + nhm_bus = possible_nhm_bus[i]; + } +} + +/* + * Retrieve memory controller fsb functions + */ + + +// Get i965 Memory Speed +static void get_fsb_i965(pci_dt_t *dram_dev) +{ + uint32_t dev0, mch_ratio, mch_cfg, mch_fsb; + + long *ptr; + + // Find Ratio + dev0 = pci_config_read32(dram_dev->dev.addr, 0x48); + dev0 &= 0xFFFFC000; + ptr = (long*)(dev0 + 0xC00); + mch_cfg = *ptr & 0xFFFF; + + mch_ratio = 100000; + + switch (mch_cfg & 7) + { + case 0: mch_fsb = 1066; break; + case 1: mch_fsb = 533; break; + default: + case 2: mch_fsb = 800; break; + case 3: mch_fsb = 667; break; + case 4: mch_fsb = 1333; break; + case 6: mch_fsb = 1600; break; + } + + DBG("mch_fsb %d\n", mch_fsb); + + switch (mch_fsb) + { + case 533: + switch ((mch_cfg >> 4) & 7) + { + case 1: mch_ratio = 200000; break; + case 2: mch_ratio = 250000; break; + case 3: mch_ratio = 300000; break; + } + break; + + default: + case 800: + switch ((mch_cfg >> 4) & 7) + { + case 0: mch_ratio = 100000; break; + case 1: mch_ratio = 125000; break; + case 2: mch_ratio = 166667; break; // 1.666666667 + case 3: mch_ratio = 200000; break; + case 4: mch_ratio = 266667; break; // 2.666666667 + case 5: mch_ratio = 333333; break; // 3.333333333 + } + break; + + case 1066: + switch ((mch_cfg >> 4) & 7) + { + case 1: mch_ratio = 100000; break; + case 2: mch_ratio = 125000; break; + case 3: mch_ratio = 150000; break; + case 4: mch_ratio = 200000; break; + case 5: mch_ratio = 250000; break; + } + break; + + case 1333: + switch ((mch_cfg >> 4) & 7) + { + case 2: mch_ratio = 100000; break; + case 3: mch_ratio = 120000; break; + case 4: mch_ratio = 160000; break; + case 5: mch_ratio = 200000; break; + } + break; + + case 1600: + switch ((mch_cfg >> 4) & 7) + { + case 3: mch_ratio = 100000; break; + case 4: mch_ratio = 133333; break; // 1.333333333 + case 5: mch_ratio = 150000; break; + case 6: mch_ratio = 200000; break; + } + break; + } + + DBG("mch_ratio %d\n", mch_ratio); + + // Compute RAM Frequency + Platform->RAM.Frequency = (Platform->CPU.FSBFrequency * mch_ratio) / 100000; + + DBG("ram_fsb %d\n", Platform->RAM.Frequency); + +} + +// Get i965m Memory Speed +static void get_fsb_im965(pci_dt_t *dram_dev) +{ + uint32_t dev0, mch_ratio, mch_cfg, mch_fsb; + + long *ptr; + + // Find Ratio + dev0 = pci_config_read32(dram_dev->dev.addr, 0x48); + dev0 &= 0xFFFFC000; + ptr = (long*)(dev0 + 0xC00); + mch_cfg = *ptr & 0xFFFF; + + mch_ratio = 100000; + + switch (mch_cfg & 7) + { + case 1: mch_fsb = 533; break; + default: + case 2: mch_fsb = 800; break; + case 3: mch_fsb = 667; break; + case 6: mch_fsb = 1066; break; + } + + switch (mch_fsb) + { + case 533: + switch ((mch_cfg >> 4) & 7) + { + case 1: mch_ratio = 125000; break; + case 2: mch_ratio = 150000; break; + case 3: mch_ratio = 200000; break; + } + break; + + case 667: + switch ((mch_cfg >> 4)& 7) + { + case 1: mch_ratio = 100000; break; + case 2: mch_ratio = 120000; break; + case 3: mch_ratio = 160000; break; + case 4: mch_ratio = 200000; break; + case 5: mch_ratio = 240000; break; + } + break; + + default: + msglog("default mch_ratio \n"); + case 800: + switch ((mch_cfg >> 4) & 7) + { + case 1: mch_ratio = 83333; break; // 0.833333333 + case 2: mch_ratio = 100000; break; + case 3: mch_ratio = 133333; break; // 1.333333333 + case 4: mch_ratio = 166667; break; // 1.666666667 + case 5: mch_ratio = 200000; break; + } + break; + case 1066: + switch ((mch_cfg >> 4)&7) { + case 5: mch_ratio = 150000; break; + case 6: mch_ratio = 200000; break; + } + + } + + // Compute RAM Frequency + Platform->RAM.Frequency = (Platform->CPU.FSBFrequency * mch_ratio) / 100000; +} + + +// Get iCore7 Memory Speed +static void get_fsb_nhm(pci_dt_t *dram_dev) +{ + uint32_t mch_ratio, mc_dimm_clk_ratio; + + // Get the clock ratio + mc_dimm_clk_ratio = pci_config_read16(PCIADDR(nhm_bus, 3, 4), 0x54 ); + mch_ratio = (mc_dimm_clk_ratio & 0x1F); + + // Compute RAM Frequency + Platform->RAM.Frequency = Platform->CPU.FSBFrequency * mch_ratio / 2; +} + +/* + * Retrieve memory controller info functions + */ + +// Get i965 Memory Timings +static void get_timings_i965(pci_dt_t *dram_dev) +{ + // Thanks for CDH optis + uint32_t dev0, c0ckectrl, c1ckectrl, offset; + uint32_t ODT_Control_Register, Precharge_Register, ACT_Register, Read_Register, Misc_Register; + + long *ptr; + + // Read MMR Base Address + dev0 = pci_config_read32(dram_dev->dev.addr, 0x48); + dev0 &= 0xFFFFC000; + + ptr = (long*)(dev0 + 0x260); + c0ckectrl = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0 + 0x660); + c1ckectrl = *ptr & 0xFFFFFFFF; + + // If DIMM 0 not populated, check DIMM 1 + ((c0ckectrl) >> 20 & 0xF) ? (offset = 0) : (offset = 0x400); + + ptr = (long*)(dev0 + offset + 0x29C); + ODT_Control_Register = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0 + offset + 0x250); + Precharge_Register = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0 + offset + 0x252); + ACT_Register = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0 + offset + 0x258); + Read_Register = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0 + offset + 0x244); + Misc_Register = *ptr & 0xFFFFFFFF; + + // 965 Series only support DDR2 + Platform->RAM.Type = SMB_MEM_TYPE_DDR2; + + // CAS Latency (tCAS) + Platform->RAM.CAS = ((ODT_Control_Register >> 17) & 7) + 3; + + // RAS-To-CAS (tRCD) + Platform->RAM.TRC = (Read_Register >> 16) & 0xF; + + // RAS Precharge (tRP) + Platform->RAM.TRP = (ACT_Register >> 13) & 0xF; + + // RAS Active to precharge (tRAS) + Platform->RAM.RAS = (Precharge_Register >> 11) & 0x1F; + + if ((c0ckectrl >> 20 & 0xF) && (c1ckectrl >> 20 & 0xF)) + Platform->RAM.Channels = SMB_MEM_CHANNEL_DUAL; + else + Platform->RAM.Channels = SMB_MEM_CHANNEL_SINGLE; +} + +// Get im965 Memory Timings +static void get_timings_im965(pci_dt_t *dram_dev) +{ + // Thanks for CDH optis + uint32_t dev0, c0ckectrl, c1ckectrl, offset, ODT_Control_Register, Precharge_Register; + long *ptr; + + // Read MMR Base Address + dev0 = pci_config_read32(dram_dev->dev.addr, 0x48); + dev0 &= 0xFFFFC000; + + ptr = (long*)(dev0 + 0x1200); + c0ckectrl = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0 + 0x1300); + c1ckectrl = *ptr & 0xFFFFFFFF; + + // If DIMM 0 not populated, check DIMM 1 + ((c0ckectrl) >> 20 & 0xF) ? (offset = 0) : (offset = 0x100); + + ptr = (long*)(dev0 + offset + 0x121C); + ODT_Control_Register = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0 + offset + 0x1214); + Precharge_Register = *ptr & 0xFFFFFFFF; + + // Series only support DDR2 + Platform->RAM.Type = SMB_MEM_TYPE_DDR2; + + // CAS Latency (tCAS) + Platform->RAM.CAS = ((ODT_Control_Register >> 23) & 7) + 3; + + // RAS-To-CAS (tRCD) + Platform->RAM.TRC = ((Precharge_Register >> 5) & 7) + 2; + + // RAS Precharge (tRP) + Platform->RAM.TRP= (Precharge_Register & 7) + 2; + + // RAS Active to precharge (tRAS) + Platform->RAM.RAS = (Precharge_Register >> 21) & 0x1F; + + if ((c0ckectrl >> 20 & 0xF) && (c1ckectrl >> 20 & 0xF)) + Platform->RAM.Channels = SMB_MEM_CHANNEL_DUAL; + else + Platform->RAM.Channels = SMB_MEM_CHANNEL_SINGLE; +} + +// Get P35 Memory Timings +static void get_timings_p35(pci_dt_t *dram_dev) +{ + // Thanks for CDH optis + unsigned long dev0, Memory_Check, c0ckectrl, c1ckectrl, offset; + unsigned long ODT_Control_Register, Precharge_Register, ACT_Register, Read_Register, Misc_Register; + long *ptr; + + //Device_ID = pci_config_read16(dram_dev->dev.addr, 0x02); + //Device_ID &= 0xFFFF; + + // Now, read MMR Base Address + dev0 = pci_config_read32(dram_dev->dev.addr, 0x48); + dev0 &= 0xFFFFC000; + + ptr = (long*)(dev0 + 0x260); + c0ckectrl = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0 + 0x660); + c1ckectrl = *ptr & 0xFFFFFFFF; + + // If DIMM 0 not populated, check DIMM 1 + ((c0ckectrl) >> 20 & 0xF) ? (offset = 0) : (offset = 0x400); + + ptr = (long*)(dev0 + offset + 0x265); + ODT_Control_Register = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0 + offset + 0x25D); + Precharge_Register = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0 + offset + 0x252); + ACT_Register = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0 + offset + 0x258); + Read_Register = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0 + offset + 0x244); + Misc_Register = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0 + offset + 0x1E8); + Memory_Check = *ptr & 0xFFFFFFFF; + + // On P45, check 1A8 + if(dram_dev->device_id > 0x2E00) { + ptr = (long*)(dev0 + offset + 0x1A8); + Memory_Check = *ptr & 0xFFFFFFFF; + Memory_Check >>= 2; + Memory_Check &= 1; + Memory_Check = !Memory_Check; + } else { + ptr = (long*)(dev0 + offset + 0x1E8); + Memory_Check = *ptr & 0xFFFFFFFF; + } + + // Determine DDR-II or DDR-III + if (Memory_Check & 1) + Platform->RAM.Type = SMB_MEM_TYPE_DDR2; + else + Platform->RAM.Type = SMB_MEM_TYPE_DDR3; + + // CAS Latency (tCAS) + if(dram_dev->device_id > 0x2E00) + Platform->RAM.CAS = ((ODT_Control_Register >> 8) & 0x3F) - 6; + else + Platform->RAM.CAS = ((ODT_Control_Register >> 8) & 0x3F) - 9; + + // RAS-To-CAS (tRCD) + Platform->RAM.TRC = (Read_Register >> 17) & 0xF; + + // RAS Precharge (tRP) + Platform->RAM.TRP = (ACT_Register >> 13) & 0xF; + + // RAS Active to precharge (tRAS) + Platform->RAM.RAS = Precharge_Register & 0x3F; + + // Channel configuration + if (((c0ckectrl >> 20) & 0xF) && ((c1ckectrl >> 20) & 0xF)) + Platform->RAM.Channels = SMB_MEM_CHANNEL_DUAL; + else + Platform->RAM.Channels = SMB_MEM_CHANNEL_SINGLE; +} + +// Get Nehalem Memory Timings +static void get_timings_nhm(pci_dt_t *dram_dev) +{ + unsigned long mc_channel_bank_timing, mc_control, mc_channel_mrs_value; + int fvc_bn = 4; + + // Find which channels are populated + mc_control = pci_config_read16(PCIADDR(nhm_bus, 3, 0), 0x48); + mc_control = (mc_control >> 8) & 0x7; + + // DDR-III + Platform->RAM.Type = SMB_MEM_TYPE_DDR3; + + // Get the first valid channel + if(mc_control & 1) + fvc_bn = 4; + else if(mc_control & 2) + fvc_bn = 5; + else if(mc_control & 7) + fvc_bn = 6; + + // Now, detect timings + mc_channel_bank_timing = pci_config_read32(PCIADDR(nhm_bus, fvc_bn, 0), 0x88); + mc_channel_mrs_value = pci_config_read32(PCIADDR(nhm_bus, fvc_bn, 0), 0x70); + + // CAS Latency (tCAS) + Platform->RAM.CAS = ((mc_channel_mrs_value >> 4) & 0xF ) + 4; + + // RAS-To-CAS (tRCD) + Platform->RAM.TRC = (mc_channel_bank_timing >> 9) & 0xF; + + // RAS Active to precharge (tRAS) + Platform->RAM.RAS = (mc_channel_bank_timing >> 4) & 0x1F; + + // RAS Precharge (tRP) + Platform->RAM.TRP = mc_channel_bank_timing & 0xF; + + // Single , Dual or Triple Channels + if (mc_control == 1 || mc_control == 2 || mc_control == 4 ) + Platform->RAM.Channels = SMB_MEM_CHANNEL_SINGLE; + else if (mc_control == 7) + Platform->RAM.Channels = SMB_MEM_CHANNEL_TRIPLE; + else + Platform->RAM.Channels = SMB_MEM_CHANNEL_DUAL; +} + +struct mem_controller_t dram_controllers[] = { + + // Default unknown chipset + { 0, 0, "", NULL, NULL, NULL }, + + // Intel + { 0x8086, 0x7190, "VMWare", NULL, NULL, NULL }, + + { 0x8086, 0x1A30, "i845", NULL, NULL, NULL }, + + { 0x8086, 0x2970, "i946PL/GZ", setup_p35, get_fsb_i965, get_timings_i965 }, + { 0x8086, 0x2990, "Q963/Q965", setup_p35, get_fsb_i965, get_timings_i965 }, + { 0x8086, 0x29A0, "P965/G965", setup_p35, get_fsb_i965, get_timings_i965 }, + + { 0x8086, 0x2A00, "GM965/GL960", setup_p35, get_fsb_im965, get_timings_im965 }, + { 0x8086, 0x2A10, "GME965/GLE960", setup_p35, get_fsb_im965, get_timings_im965 }, + { 0x8086, 0x2A40, "PM/GM45/47", setup_p35, get_fsb_im965, get_timings_im965 }, + + { 0x8086, 0x29B0, "Q35", setup_p35, get_fsb_i965, get_timings_p35 }, + { 0x8086, 0x29C0, "P35/G33", setup_p35, get_fsb_i965, get_timings_p35 }, + { 0x8086, 0x29D0, "Q33", setup_p35, get_fsb_i965, get_timings_p35 }, + { 0x8086, 0x29E0, "X38/X48", setup_p35, get_fsb_i965, get_timings_p35 }, + { 0x8086, 0x2E00, "Eaglelake", setup_p35, get_fsb_i965, get_timings_p35 }, + { 0x8086, 0x2E10, "Q45/Q43", setup_p35, get_fsb_i965, get_timings_p35 }, + { 0x8086, 0x2E20, "P45/G45", setup_p35, get_fsb_i965, get_timings_p35 }, + { 0x8086, 0x2E30, "G41", setup_p35, get_fsb_i965, get_timings_p35 }, + + { 0x8086, 0xD131, "NHM IMC", setup_nhm, get_fsb_nhm, get_timings_nhm }, + { 0x8086, 0xD132, "NHM IMC", setup_nhm, get_fsb_nhm, get_timings_nhm }, + { 0x8086, 0x3400, "NHM IMC", setup_nhm, get_fsb_nhm, get_timings_nhm }, + { 0x8086, 0x3401, "NHM IMC", setup_nhm, get_fsb_nhm, get_timings_nhm }, + { 0x8086, 0x3402, "NHM IMC", setup_nhm, get_fsb_nhm, get_timings_nhm }, + { 0x8086, 0x3403, "NHM IMC", setup_nhm, get_fsb_nhm, get_timings_nhm }, + { 0x8086, 0x3404, "NHM IMC", setup_nhm, get_fsb_nhm, get_timings_nhm }, + { 0x8086, 0x3405, "NHM IMC", setup_nhm, get_fsb_nhm, get_timings_nhm }, + { 0x8086, 0x3406, "NHM IMC", setup_nhm, get_fsb_nhm, get_timings_nhm }, + { 0x8086, 0x3407, "NHM IMC", setup_nhm, get_fsb_nhm, get_timings_nhm }, + //end of array + { 0xFFFF, 0, "", NULL, NULL, NULL }, + +}; + +const char *memory_channel_types[] = +{ + "Unknown", "Single", "Dual", "Triple" +}; + +void scan_dram_controller(pci_dt_t *dram_dev) +{ + int i; + for(i = 1; /*i < sizeof(dram_controllers) / sizeof(dram_controllers[1],*/ dram_controllers[i].vendor != 0xFFFF; i++) + if ((dram_controllers[i].vendor == dram_dev->vendor_id) + && (dram_controllers[i].device == dram_dev->device_id)) + { + verbose("%s%s DRAM Controller [%4x:%4x] at %02x:%02x.%x\n", + (dram_dev->vendor_id == 0x8086) ? "Intel " : "" , + dram_controllers[i].name, dram_dev->vendor_id, dram_dev->device_id, + dram_dev->dev.bits.bus, dram_dev->dev.bits.dev, dram_dev->dev.bits.func); + + if (dram_controllers[i].initialise != NULL) + dram_controllers[i].initialise(dram_dev); + + if (dram_controllers[i].poll_timings != NULL) + dram_controllers[i].poll_timings(dram_dev); + + if (dram_controllers[i].poll_speed != NULL) + dram_controllers[i].poll_speed(dram_dev); + + verbose("Frequency detected: %d MHz (%d) %s Channel %d-%d-%d-%d\n", + (uint32_t)Platform->RAM.Frequency / 1000000, + (uint32_t)Platform->RAM.Frequency / 500000, + memory_channel_types[Platform->RAM.Channels], + Platform->RAM.CAS, Platform->RAM.TRC, Platform->RAM.TRP, Platform->RAM.RAS + ); + + } +} Index: branches/slice/rev749/modules/Memory/spd.h =================================================================== --- branches/slice/rev749/modules/Memory/spd.h (revision 0) +++ branches/slice/rev749/modules/Memory/spd.h (revision 1169) @@ -0,0 +1,161 @@ +/* + * Copyright 2010 AsereBLN. All rights reserved. + * + * spd.h + */ + +#ifndef __LIBSAIO_SPD_H +#define __LIBSAIO_SPD_H + +#include "platform.h" +#include "libsaio.h" + +bool is_smbus_controller(pci_dt_t* pci_dt); +void scan_spd(PlatformInfo_t *p, pci_dt_t* smbus_controller_dev); + +struct smbus_controllers_t { + uint32_t vendor; + uint32_t device; + char *name; + void (*read_smb)(pci_dt_t *smbus_dev); +}; + + +/* + * Serial Presence Detect (SPD) data stored on SDRAM modules. + * + * Datasheet: + * - Name: PC SDRAM Serial Presence Detect (SPD) Specification + * Revision 1.2A, December, 1997 + * - PDF: http://www.intel.com/design/chipsets/memory/spdsd12a.pdf + * + * Datasheet (alternative): + * - Name: SERIAL PRESENCE DETECT STANDARD, General Standard + * JEDEC Standard No. 21-C + * - PDF: http://www.jedec.org/download/search/4_01_02_00R9.PDF + */ + + +/* Byte numbers. */ +#define SPD_NUM_MANUFACTURER_BYTES 0 /* Number of bytes used by module manufacturer */ +#define SPD_TOTAL_SPD_MEMORY_SIZE 1 /* Total SPD memory size */ +#define SPD_MEMORY_TYPE 2 /* (Fundamental) memory type */ +#define SPD_NUM_ROWS 3 /* Number of row address bits */ +#define SPD_NUM_COLUMNS 4 /* Number of column address bits */ +#define SPD_NUM_DIMM_BANKS 5 /* Number of module rows (banks) */ +#define SPD_MODULE_DATA_WIDTH_LSB 6 /* Module data width (LSB) */ +#define SPD_MODULE_DATA_WIDTH_MSB 7 /* Module data width (MSB) */ +#define SPD_MODULE_VOLTAGE 8 /* Module interface signal levels */ +#define SPD_MIN_CYCLE_TIME_AT_CAS_MAX 9 /* SDRAM cycle time (highest CAS latency), RAS access time (tRAC) */ +#define SPD_ACCESS_TIME_FROM_CLOCK 10 /* SDRAM access time from clock (highest CAS latency), CAS access time (Tac, tCAC) */ +#define SPD_DIMM_CONFIG_TYPE 11 /* Module configuration type */ +#define SPD_REFRESH 12 /* Refresh rate/type */ +#define SPD_PRIMARY_SDRAM_WIDTH 13 /* SDRAM width (primary SDRAM) */ +#define SPD_ERROR_CHECKING_SDRAM_WIDTH 14 /* Error checking SDRAM (data) width */ +#define SPD_MIN_CLOCK_DELAY_B2B_RAND_COLUMN 15 /* SDRAM device attributes, minimum clock delay for back to back random column */ +#define SPD_SUPPORTED_BURST_LENGTHS 16 /* SDRAM device attributes, burst lengths supported */ +#define SPD_NUM_BANKS_PER_SDRAM 17 /* SDRAM device attributes, number of banks on SDRAM device */ +#define SPD_ACCEPTABLE_CAS_LATENCIES 18 /* SDRAM device attributes, CAS latency */ +#define SPD_CS_LATENCY 19 /* SDRAM device attributes, CS latency */ +#define SPD_WE_LATENCY 20 /* SDRAM device attributes, WE latency */ +#define SPD_MODULE_ATTRIBUTES 21 /* SDRAM module attributes */ +#define SPD_DEVICE_ATTRIBUTES_GENERAL 22 /* SDRAM device attributes, general */ +#define SPD_SDRAM_CYCLE_TIME_2ND 23 /* SDRAM cycle time (2nd highest CAS latency) */ +#define SPD_ACCESS_TIME_FROM_CLOCK_2ND 24 /* SDRAM access from clock (2nd highest CAS latency) */ +#define SPD_SDRAM_CYCLE_TIME_3RD 25 /* SDRAM cycle time (3rd highest CAS latency) */ +#define SPD_ACCESS_TIME_FROM_CLOCK_3RD 26 /* SDRAM access from clock (3rd highest CAS latency) */ +#define SPD_MIN_ROW_PRECHARGE_TIME 27 /* Minimum row precharge time (Trp) */ +#define SPD_MIN_ROWACTIVE_TO_ROWACTIVE 28 /* Minimum row active to row active (Trrd) */ +#define SPD_MIN_RAS_TO_CAS_DELAY 29 /* Minimum RAS to CAS delay (Trcd) */ +#define SPD_MIN_ACTIVE_TO_PRECHARGE_DELAY 30 /* Minimum RAS pulse width (Tras) */ +#define SPD_DENSITY_OF_EACH_ROW_ON_MODULE 31 /* Density of each row on module */ +#define SPD_CMD_SIGNAL_INPUT_SETUP_TIME 32 /* Command and address signal input setup time */ +#define SPD_CMD_SIGNAL_INPUT_HOLD_TIME 33 /* Command and address signal input hold time */ +#define SPD_DATA_SIGNAL_INPUT_SETUP_TIME 34 /* Data signal input setup time */ +#define SPD_DATA_SIGNAL_INPUT_HOLD_TIME 35 /* Data signal input hold time */ +#define SPD_WRITE_RECOVERY_TIME 36 /* Write recovery time (tWR) */ +#define SPD_INT_WRITE_TO_READ_DELAY 37 /* Internal write to read command delay (tWTR) */ +#define SPD_INT_READ_TO_PRECHARGE_DELAY 38 /* Internal read to precharge command delay (tRTP) */ +#define SPD_MEM_ANALYSIS_PROBE_PARAMS 39 /* Memory analysis probe characteristics */ +#define SPD_BYTE_41_42_EXTENSION 40 /* Extension of byte 41 (tRC) and byte 42 (tRFC) */ +#define SPD_MIN_ACT_TO_ACT_AUTO_REFRESH 41 /* Minimum active to active auto refresh (tRCmin) */ +#define SPD_MIN_AUTO_REFRESH_TO_ACT 42 /* Minimum auto refresh to active/auto refresh (tRFC) */ +#define SPD_MAX_DEVICE_CYCLE_TIME 43 /* Maximum device cycle time (tCKmax) */ +#define SPD_MAX_DQS_DQ_SKEW 44 /* Maximum skew between DQS and DQ (tDQSQ) */ +#define SPD_MAX_READ_DATAHOLD_SKEW 45 /* Maximum read data-hold skew factor (tQHS) */ +#define SPD_PLL_RELOCK_TIME 46 /* PLL relock time */ +#define SPD_SPD_DATA_REVISION_CODE 62 /* SPD data revision code */ +#define SPD_CHECKSUM_FOR_BYTES_0_TO_62 63 /* Checksum for bytes 0-62 */ +#define SPD_MANUFACTURER_JEDEC_ID_CODE 64 /* Manufacturer's JEDEC ID code, per EIA/JEP106 (bytes 64-71) */ +#define SPD_MANUFACTURING_LOCATION 72 /* Manufacturing location */ +#define SPD_MANUFACTURER_PART_NUMBER 73 /* Manufacturer's part number, in 6-bit ASCII (bytes 73-90) */ +#define SPD_REVISION_CODE 91 /* Revision code (bytes 91-92) */ +#define SPD_MANUFACTURING_DATE 93 /* Manufacturing date (byte 93: year, byte 94: week) */ +#define SPD_ASSEMBLY_SERIAL_NUMBER 95 /* Assembly serial number (bytes 95-98) */ +#define SPD_MANUFACTURER_SPECIFIC_DATA 99 /* Manufacturer specific data (bytes 99-125) */ +#define SPD_INTEL_SPEC_FOR_FREQUENCY 126 /* Intel specification for frequency */ +#define SPD_INTEL_SPEC_100_MHZ 127 /* Intel specification details for 100MHz support */ +#define SPD_DDR3_MEMORY_BANK 0x75 +#define SPD_DDR3_MEMORY_CODE 0x76 + +/* DRAM specifications use the following naming conventions for SPD locations */ +#define SPD_tRP SPD_MIN_ROW_PRECHARGE_TIME +#define SPD_tRRD SPD_MIN_ROWACTIVE_TO_ROWACTIVE +#define SPD_tRCD SPD_MIN_RAS_TO_CAS_DELAY +#define SPD_tRAS SPD_MIN_ACTIVE_TO_PRECHARGE_DELAY +#define SPD_BANK_DENSITY SPD_DENSITY_OF_EACH_ROW_ON_MODULE +#define SPD_ADDRESS_CMD_HOLD SPD_CMD_SIGNAL_INPUT_HOLD_TIME +#define SPD_tRC 41 /* SDRAM Device Minimum Active to Active/Auto Refresh Time (tRC) */ +#define SPD_tRFC 42 /* SDRAM Device Minimum Auto Refresh to Active/Auto Refresh (tRFC) */ + + +/* SPD_MEMORY_TYPE values. */ +#define SPD_MEMORY_TYPE_FPM_DRAM 1 +#define SPD_MEMORY_TYPE_EDO 2 +#define SPD_MEMORY_TYPE_PIPELINED_NIBBLE 3 +#define SPD_MEMORY_TYPE_SDRAM 4 +#define SPD_MEMORY_TYPE_MULTIPLEXED_ROM 5 +#define SPD_MEMORY_TYPE_SGRAM_DDR 6 +#define SPD_MEMORY_TYPE_SDRAM_DDR 7 +#define SPD_MEMORY_TYPE_SDRAM_DDR2 8 +#define SPD_MEMORY_TYPE_SDRAM_DDR3 0xb + +/* SPD_MODULE_VOLTAGE values. */ +#define SPD_VOLTAGE_TTL 0 /* 5.0 Volt/TTL */ +#define SPD_VOLTAGE_LVTTL 1 /* LVTTL */ +#define SPD_VOLTAGE_HSTL 2 /* HSTL 1.5 */ +#define SPD_VOLTAGE_SSTL3 3 /* SSTL 3.3 */ +#define SPD_VOLTAGE_SSTL2 4 /* SSTL 2.5 */ + +/* SPD_DIMM_CONFIG_TYPE values. */ +#define ERROR_SCHEME_NONE 0 +#define ERROR_SCHEME_PARITY 1 +#define ERROR_SCHEME_ECC 2 + +/* SPD_ACCEPTABLE_CAS_LATENCIES values. */ +// TODO: Check values. +#define SPD_CAS_LATENCY_1_0 0x01 +#define SPD_CAS_LATENCY_1_5 0x02 +#define SPD_CAS_LATENCY_2_0 0x04 +#define SPD_CAS_LATENCY_2_5 0x08 +#define SPD_CAS_LATENCY_3_0 0x10 +#define SPD_CAS_LATENCY_3_5 0x20 +#define SPD_CAS_LATENCY_4_0 0x40 + +#define SPD_CAS_LATENCY_DDR2_3 (1 << 3) +#define SPD_CAS_LATENCY_DDR2_4 (1 << 4) +#define SPD_CAS_LATENCY_DDR2_5 (1 << 5) +#define SPD_CAS_LATENCY_DDR2_6 (1 << 6) + +/* SPD_SUPPORTED_BURST_LENGTHS values. */ +#define SPD_BURST_LENGTH_1 1 +#define SPD_BURST_LENGTH_2 2 +#define SPD_BURST_LENGTH_4 4 +#define SPD_BURST_LENGTH_8 8 +#define SPD_BURST_LENGTH_PAGE (1 << 7) + +/* SPD_MODULE_ATTRIBUTES values. */ +#define MODULE_BUFFERED 1 +#define MODULE_REGISTERED 2 + +#endif /* !__LIBSAIO_SPD_H */ Index: branches/slice/rev749/modules/Memory/Makefile =================================================================== --- branches/slice/rev749/modules/Memory/Makefile (revision 0) +++ branches/slice/rev749/modules/Memory/Makefile (revision 1169) @@ -0,0 +1,40 @@ +MODULE_NAME = Memory +MODULE_VERSION = "1.0.0" +MODULE_COMPAT_VERSION = "1.0.0" +MODULE_START = _$(MODULE_NAME)_start +MODULE_DEPENDENCIES = + +DIR = Memory + +MODULE_OBJS = dram_controllers.o mem.o spd.o Memory.o + +OPTIM = -Os -Oz +DEBUG = -DNOTHING +#DEBUG = -DDEBUG_HELLO_WORLD=1 +CFLAGS = $(RC_CFLAGS) $(OPTIM) $(MORECPP) -arch i386 -g -Wmost \ + -D__ARCHITECTURE__=\"i386\" -DSAIO_INTERNAL_USER \ + -DRCZ_COMPRESSED_FILE_SUPPORT $(DEBUG) \ + -fno-builtin $(OMIT_FRAME_POINTER_CFLAG) \ + -mpreferred-stack-boundary=2 -fno-align-functions -fno-stack-protector \ + -march=pentium4 -msse2 -mfpmath=sse -msoft-float -fno-common + +DEFINES= +CONFIG = hd +INC = -I. -I.. -I$(SYMROOT) -I$(UTILDIR) -I$(LIBSADIR) -I$(LIBSAIODIR) -I$(BOOT2DIR) +LIBS= + +VPATH = $(OBJROOT):$(SYMROOT) + +SFILES = +CFILES = +HFILES = +EXPORTED_HFILES = +INSTALLED_HFILES = +OTHERFILES = Makefile +ALLSRC = $(SFILES) $(CFILES) \ + $(HFILES) $(OTHERFILES) +DIRS_NEEDED = $(OBJROOT) $(SYMROOT) + +all embedtheme optionrom: dylib + +include ../MakeInc.dir \ No newline at end of file Index: branches/slice/rev749/modules/HelloWorld/HelloWorld.cpp =================================================================== --- branches/slice/rev749/modules/HelloWorld/HelloWorld.cpp (revision 0) +++ branches/slice/rev749/modules/HelloWorld/HelloWorld.cpp (revision 1169) @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2009 Evan Lojewski. All rights reserved. + * + */ +#include +#include +#include + +using namespace std; + +class HW { +private: + int id; +public: + virtual void setId( int id ); + virtual void printHello( void ); +}; + +void helloWorld(void* binary, void* arg2, void* arg3, void* arg4) +{ + HW* obj = new HW; + HW* obj2 = new HW; + obj->setId(1); + obj->printHello(); + delete obj; + + obj2->setId(2); + obj2->printHello(); + delete obj2; + + printf("Hello world from ExecKernel hook. Binary located at 0x%X\n", binary); + //getchar(); + +} + +void HelloWorld_start() +{ + //printf("Hooking 'ExecKernel'\n"); + register_hook_callback("ExecKernel", &helloWorld); + register_hook_callback("Kernel Start", &helloWorld); + +} + +void HW::printHello() +{ + printf("[%d] HelloWorld from a c++ function\n", id); +} + +void HW::setId(int id) +{ + this->id = id; +} Index: branches/slice/rev749/modules/HelloWorld/Makefile =================================================================== --- branches/slice/rev749/modules/HelloWorld/Makefile (revision 0) +++ branches/slice/rev749/modules/HelloWorld/Makefile (revision 1169) @@ -0,0 +1,43 @@ +MODULE_NAME = HelloWorld +MODULE_VERSION = "1.0.0" +MODULE_COMPAT_VERSION = "1.0.0" +#MODULE_START = _$(MODULE_NAME)_start +MODULE_START = __Z16HelloWorld_startv +MODULE_DEPENDENCIES = + +DIR = HelloWorld + +MODULE_OBJS = HelloWorld.o + +OPTIM = -Os -Oz +DEBUG = -DNOTHING +#DEBUG = -DDEBUG_HELLO_WORLD=1 +CFLAGS = $(RC_CFLAGS) $(OPTIM) $(MORECPP) -arch i386 -g -Wmost \ + -D__ARCHITECTURE__=\"i386\" -DSAIO_INTERNAL_USER \ + -DRCZ_COMPRESSED_FILE_SUPPORT $(DEBUG) \ + -fno-builtin $(OMIT_FRAME_POINTER_CFLAG) \ + -mpreferred-stack-boundary=2 -fno-align-functions -fno-stack-protector \ + -march=pentium4 -msse2 -mfpmath=sse -msoft-float -fno-common + +DEFINES= +CONFIG = hd +INC = -I. -I.. -I$(SYMROOT) -I$(UTILDIR) -I$(LIBSADIR) -I$(LIBSAIODIR) -I$(BOOT2DIR) +LIBS= + +VPATH = $(OBJROOT):$(SYMROOT) + + + +SFILES = +CFILES = +HFILES = +EXPORTED_HFILES = +INSTALLED_HFILES = +OTHERFILES = Makefile +ALLSRC = $(SFILES) $(CFILES) \ + $(HFILES) $(OTHERFILES) +DIRS_NEEDED = $(OBJROOT) $(SYMROOT) + +all embedtheme optionrom: dylib + +include ../MakeInc.dir \ No newline at end of file Index: branches/slice/rev749/modules/ATI5000Enabler/ati_reg.h =================================================================== --- branches/slice/rev749/modules/ATI5000Enabler/ati_reg.h (revision 0) +++ branches/slice/rev749/modules/ATI5000Enabler/ati_reg.h (revision 1169) @@ -0,0 +1,5672 @@ +/* + * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and + * VA Linux Systems Inc., Fremont, California. + * + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation on the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR + * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/* + * Authors: + * Kevin E. Martin + * Rickard E. Faith + * Alan Hourihane + * + * References: + * + * !!!! FIXME !!!! + * RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical + * Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April + * 1999. + * + * !!!! FIXME !!!! + * RAGE 128 Software Development Manual (Technical Reference Manual P/N + * SDK-G04000 Rev. 0.01), ATI Technologies: June 1999. + * + */ + +/* !!!! FIXME !!!! NOTE: THIS FILE HAS BEEN CONVERTED FROM r128_reg.h + * AND CONTAINS REGISTERS AND REGISTER DEFINITIONS THAT ARE NOT CORRECT + * ON THE RADEON. A FULL AUDIT OF THIS CODE IS NEEDED! */ + +#ifndef _ATI_REG_H_ +#define _ATI_REG_H_ + +#define ATI_DATATYPE_VQ 0 +#define ATI_DATATYPE_CI4 1 +#define ATI_DATATYPE_CI8 2 +#define ATI_DATATYPE_ARGB1555 3 +#define ATI_DATATYPE_RGB565 4 +#define ATI_DATATYPE_RGB888 5 +#define ATI_DATATYPE_ARGB8888 6 +#define ATI_DATATYPE_RGB332 7 +#define ATI_DATATYPE_Y8 8 +#define ATI_DATATYPE_RGB8 9 +#define ATI_DATATYPE_CI16 10 +#define ATI_DATATYPE_VYUY_422 11 +#define ATI_DATATYPE_YVYU_422 12 +#define ATI_DATATYPE_AYUV_444 14 +#define ATI_DATATYPE_ARGB4444 15 + + /* Registers for 2D/Video/Overlay */ +#define RADEON_ADAPTER_ID 0x0f2c /* PCI */ +#define RADEON_AGP_BASE 0x0170 +#define RADEON_AGP_CNTL 0x0174 +# define RADEON_AGP_APER_SIZE_256MB (0x00 << 0) +# define RADEON_AGP_APER_SIZE_128MB (0x20 << 0) +# define RADEON_AGP_APER_SIZE_64MB (0x30 << 0) +# define RADEON_AGP_APER_SIZE_32MB (0x38 << 0) +# define RADEON_AGP_APER_SIZE_16MB (0x3c << 0) +# define RADEON_AGP_APER_SIZE_8MB (0x3e << 0) +# define RADEON_AGP_APER_SIZE_4MB (0x3f << 0) +# define RADEON_AGP_APER_SIZE_MASK (0x3f << 0) +#define RADEON_STATUS_PCI_CONFIG 0x06 +# define RADEON_CAP_LIST 0x100000 +#define RADEON_CAPABILITIES_PTR_PCI_CONFIG 0x34 /* offset in PCI config*/ +# define RADEON_CAP_PTR_MASK 0xfc /* mask off reserved bits of CAP_PTR */ +# define RADEON_CAP_ID_NULL 0x00 /* End of capability list */ +# define RADEON_CAP_ID_AGP 0x02 /* AGP capability ID */ +# define RADEON_CAP_ID_EXP 0x10 /* PCI Express */ +#define RADEON_AGP_COMMAND 0x0f60 /* PCI */ +#define RADEON_AGP_COMMAND_PCI_CONFIG 0x0060 /* offset in PCI config*/ +# define RADEON_AGP_ENABLE (1<<8) +#define RADEON_AGP_PLL_CNTL 0x000b /* PLL */ +#define RADEON_AGP_STATUS 0x0f5c /* PCI */ +# define RADEON_AGP_1X_MODE 0x01 +# define RADEON_AGP_2X_MODE 0x02 +# define RADEON_AGP_4X_MODE 0x04 +# define RADEON_AGP_FW_MODE 0x10 +# define RADEON_AGP_MODE_MASK 0x17 +# define RADEON_AGPv3_MODE 0x08 +# define RADEON_AGPv3_4X_MODE 0x01 +# define RADEON_AGPv3_8X_MODE 0x02 +#define RADEON_ATTRDR 0x03c1 /* VGA */ +#define RADEON_ATTRDW 0x03c0 /* VGA */ +#define RADEON_ATTRX 0x03c0 /* VGA */ +#define RADEON_AUX_WINDOW_HORZ_CNTL 0x02d8 +#define RADEON_AUX_WINDOW_VERT_CNTL 0x02dc + +#define RADEON_BASE_CODE 0x0f0b +#define RADEON_BIOS_0_SCRATCH 0x0010 +# define RADEON_FP_PANEL_SCALABLE (1 << 16) +# define RADEON_FP_PANEL_SCALE_EN (1 << 17) +# define RADEON_FP_CHIP_SCALE_EN (1 << 18) +# define RADEON_DRIVER_BRIGHTNESS_EN (1 << 26) +# define RADEON_DISPLAY_ROT_MASK (3 << 28) +# define RADEON_DISPLAY_ROT_00 (0 << 28) +# define RADEON_DISPLAY_ROT_90 (1 << 28) +# define RADEON_DISPLAY_ROT_180 (2 << 28) +# define RADEON_DISPLAY_ROT_270 (3 << 28) +#define RADEON_BIOS_1_SCRATCH 0x0014 +#define RADEON_BIOS_2_SCRATCH 0x0018 +#define RADEON_BIOS_3_SCRATCH 0x001c +#define RADEON_BIOS_4_SCRATCH 0x0020 +# define RADEON_CRT1_ATTACHED_MASK (3 << 0) +# define RADEON_CRT1_ATTACHED_MONO (1 << 0) +# define RADEON_CRT1_ATTACHED_COLOR (2 << 0) +# define RADEON_LCD1_ATTACHED (1 << 2) +# define RADEON_DFP1_ATTACHED (1 << 3) +# define RADEON_TV1_ATTACHED_MASK (3 << 4) +# define RADEON_TV1_ATTACHED_COMP (1 << 4) +# define RADEON_TV1_ATTACHED_SVIDEO (2 << 4) +# define RADEON_CRT2_ATTACHED_MASK (3 << 8) +# define RADEON_CRT2_ATTACHED_MONO (1 << 8) +# define RADEON_CRT2_ATTACHED_COLOR (2 << 8) +# define RADEON_DFP2_ATTACHED (1 << 11) +#define RADEON_BIOS_5_SCRATCH 0x0024 +# define RADEON_LCD1_ON (1 << 0) +# define RADEON_CRT1_ON (1 << 1) +# define RADEON_TV1_ON (1 << 2) +# define RADEON_DFP1_ON (1 << 3) +# define RADEON_CRT2_ON (1 << 5) +# define RADEON_CV1_ON (1 << 6) +# define RADEON_DFP2_ON (1 << 7) +# define RADEON_LCD1_CRTC_MASK (1 << 8) +# define RADEON_LCD1_CRTC_SHIFT 8 +# define RADEON_CRT1_CRTC_MASK (1 << 9) +# define RADEON_CRT1_CRTC_SHIFT 9 +# define RADEON_TV1_CRTC_MASK (1 << 10) +# define RADEON_TV1_CRTC_SHIFT 10 +# define RADEON_DFP1_CRTC_MASK (1 << 11) +# define RADEON_DFP1_CRTC_SHIFT 11 +# define RADEON_CRT2_CRTC_MASK (1 << 12) +# define RADEON_CRT2_CRTC_SHIFT 12 +# define RADEON_CV1_CRTC_MASK (1 << 13) +# define RADEON_CV1_CRTC_SHIFT 13 +# define RADEON_DFP2_CRTC_MASK (1 << 14) +# define RADEON_DFP2_CRTC_SHIFT 14 +#define RADEON_BIOS_6_SCRATCH 0x0028 +# define RADEON_ACC_MODE_CHANGE (1 << 2) +# define RADEON_EXT_DESKTOP_MODE (1 << 3) +# define RADEON_LCD_DPMS_ON (1 << 20) +# define RADEON_CRT_DPMS_ON (1 << 21) +# define RADEON_TV_DPMS_ON (1 << 22) +# define RADEON_DFP_DPMS_ON (1 << 23) +# define RADEON_DPMS_MASK (3 << 24) +# define RADEON_DPMS_ON (0 << 24) +# define RADEON_DPMS_STANDBY (1 << 24) +# define RADEON_DPMS_SUSPEND (2 << 24) +# define RADEON_DPMS_OFF (3 << 24) +# define RADEON_SCREEN_BLANKING (1 << 26) +# define RADEON_DRIVER_CRITICAL (1 << 27) +# define RADEON_DISPLAY_SWITCHING_DIS (1 << 30) +#define RADEON_BIOS_7_SCRATCH 0x002c +# define RADEON_SYS_HOTKEY (1 << 10) +# define RADEON_DRV_LOADED (1 << 12) +#define RADEON_BIOS_ROM 0x0f30 /* PCI */ +#define RADEON_BIST 0x0f0f /* PCI */ +#define RADEON_BRUSH_DATA0 0x1480 +#define RADEON_BRUSH_DATA1 0x1484 +#define RADEON_BRUSH_DATA10 0x14a8 +#define RADEON_BRUSH_DATA11 0x14ac +#define RADEON_BRUSH_DATA12 0x14b0 +#define RADEON_BRUSH_DATA13 0x14b4 +#define RADEON_BRUSH_DATA14 0x14b8 +#define RADEON_BRUSH_DATA15 0x14bc +#define RADEON_BRUSH_DATA16 0x14c0 +#define RADEON_BRUSH_DATA17 0x14c4 +#define RADEON_BRUSH_DATA18 0x14c8 +#define RADEON_BRUSH_DATA19 0x14cc +#define RADEON_BRUSH_DATA2 0x1488 +#define RADEON_BRUSH_DATA20 0x14d0 +#define RADEON_BRUSH_DATA21 0x14d4 +#define RADEON_BRUSH_DATA22 0x14d8 +#define RADEON_BRUSH_DATA23 0x14dc +#define RADEON_BRUSH_DATA24 0x14e0 +#define RADEON_BRUSH_DATA25 0x14e4 +#define RADEON_BRUSH_DATA26 0x14e8 +#define RADEON_BRUSH_DATA27 0x14ec +#define RADEON_BRUSH_DATA28 0x14f0 +#define RADEON_BRUSH_DATA29 0x14f4 +#define RADEON_BRUSH_DATA3 0x148c +#define RADEON_BRUSH_DATA30 0x14f8 +#define RADEON_BRUSH_DATA31 0x14fc +#define RADEON_BRUSH_DATA32 0x1500 +#define RADEON_BRUSH_DATA33 0x1504 +#define RADEON_BRUSH_DATA34 0x1508 +#define RADEON_BRUSH_DATA35 0x150c +#define RADEON_BRUSH_DATA36 0x1510 +#define RADEON_BRUSH_DATA37 0x1514 +#define RADEON_BRUSH_DATA38 0x1518 +#define RADEON_BRUSH_DATA39 0x151c +#define RADEON_BRUSH_DATA4 0x1490 +#define RADEON_BRUSH_DATA40 0x1520 +#define RADEON_BRUSH_DATA41 0x1524 +#define RADEON_BRUSH_DATA42 0x1528 +#define RADEON_BRUSH_DATA43 0x152c +#define RADEON_BRUSH_DATA44 0x1530 +#define RADEON_BRUSH_DATA45 0x1534 +#define RADEON_BRUSH_DATA46 0x1538 +#define RADEON_BRUSH_DATA47 0x153c +#define RADEON_BRUSH_DATA48 0x1540 +#define RADEON_BRUSH_DATA49 0x1544 +#define RADEON_BRUSH_DATA5 0x1494 +#define RADEON_BRUSH_DATA50 0x1548 +#define RADEON_BRUSH_DATA51 0x154c +#define RADEON_BRUSH_DATA52 0x1550 +#define RADEON_BRUSH_DATA53 0x1554 +#define RADEON_BRUSH_DATA54 0x1558 +#define RADEON_BRUSH_DATA55 0x155c +#define RADEON_BRUSH_DATA56 0x1560 +#define RADEON_BRUSH_DATA57 0x1564 +#define RADEON_BRUSH_DATA58 0x1568 +#define RADEON_BRUSH_DATA59 0x156c +#define RADEON_BRUSH_DATA6 0x1498 +#define RADEON_BRUSH_DATA60 0x1570 +#define RADEON_BRUSH_DATA61 0x1574 +#define RADEON_BRUSH_DATA62 0x1578 +#define RADEON_BRUSH_DATA63 0x157c +#define RADEON_BRUSH_DATA7 0x149c +#define RADEON_BRUSH_DATA8 0x14a0 +#define RADEON_BRUSH_DATA9 0x14a4 +#define RADEON_BRUSH_SCALE 0x1470 +#define RADEON_BRUSH_Y_X 0x1474 +#define RADEON_BUS_CNTL 0x0030 +# define RADEON_BUS_MASTER_DIS (1 << 6) +# define RADEON_BUS_BIOS_DIS_ROM (1 << 12) +# define RADEON_BUS_RD_DISCARD_EN (1 << 24) +# define RADEON_BUS_RD_ABORT_EN (1 << 25) +# define RADEON_BUS_MSTR_DISCONNECT_EN (1 << 28) +# define RADEON_BUS_WRT_BURST (1 << 29) +# define RADEON_BUS_READ_BURST (1 << 30) +#define RADEON_BUS_CNTL1 0x0034 +# define RADEON_BUS_WAIT_ON_LOCK_EN (1 << 4) + +#define RADEON_PCIE_INDEX 0x0030 +#define RADEON_PCIE_DATA 0x0034 +#define R600_PCIE_PORT_INDEX 0x0038 +#define R600_PCIE_PORT_DATA 0x003c +/* PCIE_LC_LINK_WIDTH_CNTL is PCIE on r1xx-r5xx, PCIE_PORT on r6xx-r7xx */ +#define RADEON_PCIE_LC_LINK_WIDTH_CNTL 0xa2 /* PCIE */ +# define RADEON_PCIE_LC_LINK_WIDTH_SHIFT 0 +# define RADEON_PCIE_LC_LINK_WIDTH_MASK 0x7 +# define RADEON_PCIE_LC_LINK_WIDTH_X0 0 +# define RADEON_PCIE_LC_LINK_WIDTH_X1 1 +# define RADEON_PCIE_LC_LINK_WIDTH_X2 2 +# define RADEON_PCIE_LC_LINK_WIDTH_X4 3 +# define RADEON_PCIE_LC_LINK_WIDTH_X8 4 +# define RADEON_PCIE_LC_LINK_WIDTH_X12 5 +# define RADEON_PCIE_LC_LINK_WIDTH_X16 6 +# define RADEON_PCIE_LC_LINK_WIDTH_RD_SHIFT 4 +# define RADEON_PCIE_LC_LINK_WIDTH_RD_MASK 0x70 +# define R600_PCIE_LC_RECONFIG_ARC_MISSING_ESCAPE (1 << 7) +# define RADEON_PCIE_LC_RECONFIG_NOW (1 << 8) +# define RADEON_PCIE_LC_RECONFIG_LATER (1 << 9) +# define RADEON_PCIE_LC_SHORT_RECONFIG_EN (1 << 10) +# define R600_PCIE_LC_RENEGOTIATE_EN (1 << 10) +# define R600_PCIE_LC_SHORT_RECONFIG_EN (1 << 11) +#define R600_TARGET_AND_CURRENT_PROFILE_INDEX 0x70c +#define R700_TARGET_AND_CURRENT_PROFILE_INDEX 0x66c + +#define RADEON_CACHE_CNTL 0x1724 +#define RADEON_CACHE_LINE 0x0f0c /* PCI */ +#define RADEON_CAPABILITIES_ID 0x0f50 /* PCI */ +#define RADEON_CAPABILITIES_PTR 0x0f34 /* PCI */ +#define RADEON_CLK_PIN_CNTL 0x0001 /* PLL */ +# define RADEON_DONT_USE_XTALIN (1 << 4) +# define RADEON_SCLK_DYN_START_CNTL (1 << 15) +#define RADEON_CLOCK_CNTL_DATA 0x000c +#define RADEON_CLOCK_CNTL_INDEX 0x0008 +# define RADEON_PLL_WR_EN (1 << 7) +# define RADEON_PLL_DIV_SEL (3 << 8) +# define RADEON_PLL2_DIV_SEL_MASK ~(3 << 8) +#define RADEON_M_SPLL_REF_FB_DIV 0x000a /* PLL */ +# define RADEON_M_SPLL_REF_DIV_MASK 0xff +# define RADEON_M_SPLL_REF_DIV_SHIFT 0 +# define RADEON_MPLL_FB_DIV_MASK 0xff +# define RADEON_MPLL_FB_DIV_SHIFT 8 +# define RADEON_SPLL_FB_DIV_MASK 0xff +# define RADEON_SPLL_FB_DIV_SHIFT 16 +#define RADEON_SPLL_CNTL 0x000c /* PLL */ +# define RADEON_SPLL_SLEEP (1 << 0) +# define RADEON_SPLL_RESET (1 << 1) +# define RADEON_SPLL_PCP_MASK 0x7 +# define RADEON_SPLL_PCP_SHIFT 8 +# define RADEON_SPLL_PVG_MASK 0x7 +# define RADEON_SPLL_PVG_SHIFT 11 +# define RADEON_SPLL_PDC_MASK 0x3 +# define RADEON_SPLL_PDC_SHIFT 14 +#define RADEON_CLK_PWRMGT_CNTL 0x0014 /* PLL */ +# define RADEON_ENGIN_DYNCLK_MODE (1 << 12) +# define RADEON_ACTIVE_HILO_LAT_MASK (3 << 13) +# define RADEON_ACTIVE_HILO_LAT_SHIFT 13 +# define RADEON_DISP_DYN_STOP_LAT_MASK (1 << 12) +# define RADEON_MC_BUSY (1 << 16) +# define RADEON_DLL_READY (1 << 19) +# define RADEON_CG_NO1_DEBUG_0 (1 << 24) +# define RADEON_CG_NO1_DEBUG_MASK (0x1f << 24) +# define RADEON_DYN_STOP_MODE_MASK (7 << 21) +# define RADEON_TVPLL_PWRMGT_OFF (1 << 30) +# define RADEON_TVCLK_TURNOFF (1 << 31) +#define RADEON_PLL_PWRMGT_CNTL 0x0015 /* PLL */ +# define RADEON_TCL_BYPASS_DISABLE (1 << 20) +#define RADEON_CLR_CMP_CLR_3D 0x1a24 +#define RADEON_CLR_CMP_CLR_DST 0x15c8 +#define RADEON_CLR_CMP_CLR_SRC 0x15c4 +#define RADEON_CLR_CMP_CNTL 0x15c0 +# define RADEON_SRC_CMP_EQ_COLOR (4 << 0) +# define RADEON_SRC_CMP_NEQ_COLOR (5 << 0) +# define RADEON_CLR_CMP_SRC_SOURCE (1 << 24) +#define RADEON_CLR_CMP_MASK 0x15cc +# define RADEON_CLR_CMP_MSK 0xffffffff +#define RADEON_CLR_CMP_MASK_3D 0x1A28 +#define RADEON_COMMAND 0x0f04 /* PCI */ +#define RADEON_COMPOSITE_SHADOW_ID 0x1a0c +#define RADEON_CONFIG_APER_0_BASE 0x0100 +#define RADEON_CONFIG_APER_1_BASE 0x0104 +#define RADEON_CONFIG_APER_SIZE 0x0108 +#define RADEON_CONFIG_BONDS 0x00e8 +#define RADEON_CONFIG_CNTL 0x00e0 +# define RADEON_CFG_ATI_REV_A11 (0 << 16) +# define RADEON_CFG_ATI_REV_A12 (1 << 16) +# define RADEON_CFG_ATI_REV_A13 (2 << 16) +# define RADEON_CFG_ATI_REV_ID_MASK (0xf << 16) +#define RADEON_CONFIG_MEMSIZE 0x00f8 +#define RADEON_CONFIG_MEMSIZE_EMBEDDED 0x0114 +#define RADEON_CONFIG_REG_1_BASE 0x010c +#define RADEON_CONFIG_REG_APER_SIZE 0x0110 +#define RADEON_CONFIG_XSTRAP 0x00e4 +#define RADEON_CONSTANT_COLOR_C 0x1d34 +# define RADEON_CONSTANT_COLOR_MASK 0x00ffffff +# define RADEON_CONSTANT_COLOR_ONE 0x00ffffff +# define RADEON_CONSTANT_COLOR_ZERO 0x00000000 +#define RADEON_CRC_CMDFIFO_ADDR 0x0740 +#define RADEON_CRC_CMDFIFO_DOUT 0x0744 +#define RADEON_GRPH_BUFFER_CNTL 0x02f0 +# define RADEON_GRPH_START_REQ_MASK (0x7f) +# define RADEON_GRPH_START_REQ_SHIFT 0 +# define RADEON_GRPH_STOP_REQ_MASK (0x7f<<8) +# define RADEON_GRPH_STOP_REQ_SHIFT 8 +# define RADEON_GRPH_CRITICAL_POINT_MASK (0x7f<<16) +# define RADEON_GRPH_CRITICAL_POINT_SHIFT 16 +# define RADEON_GRPH_CRITICAL_CNTL (1<<28) +# define RADEON_GRPH_BUFFER_SIZE (1<<29) +# define RADEON_GRPH_CRITICAL_AT_SOF (1<<30) +# define RADEON_GRPH_STOP_CNTL (1<<31) +#define RADEON_GRPH2_BUFFER_CNTL 0x03f0 +# define RADEON_GRPH2_START_REQ_MASK (0x7f) +# define RADEON_GRPH2_START_REQ_SHIFT 0 +# define RADEON_GRPH2_STOP_REQ_MASK (0x7f<<8) +# define RADEON_GRPH2_STOP_REQ_SHIFT 8 +# define RADEON_GRPH2_CRITICAL_POINT_MASK (0x7f<<16) +# define RADEON_GRPH2_CRITICAL_POINT_SHIFT 16 +# define RADEON_GRPH2_CRITICAL_CNTL (1<<28) +# define RADEON_GRPH2_BUFFER_SIZE (1<<29) +# define RADEON_GRPH2_CRITICAL_AT_SOF (1<<30) +# define RADEON_GRPH2_STOP_CNTL (1<<31) +#define RADEON_CRTC_CRNT_FRAME 0x0214 +#define RADEON_CRTC_EXT_CNTL 0x0054 +# define RADEON_CRTC_VGA_XOVERSCAN (1 << 0) +# define RADEON_VGA_ATI_LINEAR (1 << 3) +# define RADEON_XCRT_CNT_EN (1 << 6) +# define RADEON_CRTC_HSYNC_DIS (1 << 8) +# define RADEON_CRTC_VSYNC_DIS (1 << 9) +# define RADEON_CRTC_DISPLAY_DIS (1 << 10) +# define RADEON_CRTC_SYNC_TRISTAT (1 << 11) +# define RADEON_CRTC_CRT_ON (1 << 15) +#define RADEON_CRTC_EXT_CNTL_DPMS_BYTE 0x0055 +# define RADEON_CRTC_HSYNC_DIS_BYTE (1 << 0) +# define RADEON_CRTC_VSYNC_DIS_BYTE (1 << 1) +# define RADEON_CRTC_DISPLAY_DIS_BYTE (1 << 2) +#define RADEON_CRTC_GEN_CNTL 0x0050 +# define RADEON_CRTC_DBL_SCAN_EN (1 << 0) +# define RADEON_CRTC_INTERLACE_EN (1 << 1) +# define RADEON_CRTC_CSYNC_EN (1 << 4) +# define RADEON_CRTC_ICON_EN (1 << 15) +# define RADEON_CRTC_CUR_EN (1 << 16) +# define RADEON_CRTC_CUR_MODE_MASK (7 << 20) +# define RADEON_CRTC_EXT_DISP_EN (1 << 24) +# define RADEON_CRTC_EN (1 << 25) +# define RADEON_CRTC_DISP_REQ_EN_B (1 << 26) +#define RADEON_CRTC2_GEN_CNTL 0x03f8 +# define RADEON_CRTC2_DBL_SCAN_EN (1 << 0) +# define RADEON_CRTC2_INTERLACE_EN (1 << 1) +# define RADEON_CRTC2_SYNC_TRISTAT (1 << 4) +# define RADEON_CRTC2_HSYNC_TRISTAT (1 << 5) +# define RADEON_CRTC2_VSYNC_TRISTAT (1 << 6) +# define RADEON_CRTC2_CRT2_ON (1 << 7) +# define RADEON_CRTC2_PIX_WIDTH_SHIFT 8 +# define RADEON_CRTC2_PIX_WIDTH_MASK (0xf << 8) +# define RADEON_CRTC2_ICON_EN (1 << 15) +# define RADEON_CRTC2_CUR_EN (1 << 16) +# define RADEON_CRTC2_CUR_MODE_MASK (7 << 20) +# define RADEON_CRTC2_DISP_DIS (1 << 23) +# define RADEON_CRTC2_EN (1 << 25) +# define RADEON_CRTC2_DISP_REQ_EN_B (1 << 26) +# define RADEON_CRTC2_CSYNC_EN (1 << 27) +# define RADEON_CRTC2_HSYNC_DIS (1 << 28) +# define RADEON_CRTC2_VSYNC_DIS (1 << 29) +#define RADEON_CRTC_MORE_CNTL 0x27c +# define RADEON_CRTC_AUTO_HORZ_CENTER_EN (1<<2) +# define RADEON_CRTC_AUTO_VERT_CENTER_EN (1<<3) +# define RADEON_CRTC_H_CUTOFF_ACTIVE_EN (1<<4) +# define RADEON_CRTC_V_CUTOFF_ACTIVE_EN (1<<5) +#define RADEON_CRTC_GUI_TRIG_VLINE 0x0218 +# define RADEON_CRTC_GUI_TRIG_VLINE_START_SHIFT 0 +# define RADEON_CRTC_GUI_TRIG_VLINE_INV (1 << 15) +# define RADEON_CRTC_GUI_TRIG_VLINE_END_SHIFT 16 +# define RADEON_CRTC_GUI_TRIG_VLINE_STALL (1 << 30) +#define RADEON_CRTC_H_SYNC_STRT_WID 0x0204 +# define RADEON_CRTC_H_SYNC_STRT_PIX (0x07 << 0) +# define RADEON_CRTC_H_SYNC_STRT_CHAR (0x3ff << 3) +# define RADEON_CRTC_H_SYNC_STRT_CHAR_SHIFT 3 +# define RADEON_CRTC_H_SYNC_WID (0x3f << 16) +# define RADEON_CRTC_H_SYNC_WID_SHIFT 16 +# define RADEON_CRTC_H_SYNC_POL (1 << 23) +#define RADEON_CRTC2_H_SYNC_STRT_WID 0x0304 +# define RADEON_CRTC2_H_SYNC_STRT_PIX (0x07 << 0) +# define RADEON_CRTC2_H_SYNC_STRT_CHAR (0x3ff << 3) +# define RADEON_CRTC2_H_SYNC_STRT_CHAR_SHIFT 3 +# define RADEON_CRTC2_H_SYNC_WID (0x3f << 16) +# define RADEON_CRTC2_H_SYNC_WID_SHIFT 16 +# define RADEON_CRTC2_H_SYNC_POL (1 << 23) +#define RADEON_CRTC_H_TOTAL_DISP 0x0200 +# define RADEON_CRTC_H_TOTAL (0x03ff << 0) +# define RADEON_CRTC_H_TOTAL_SHIFT 0 +# define RADEON_CRTC_H_DISP (0x01ff << 16) +# define RADEON_CRTC_H_DISP_SHIFT 16 +#define RADEON_CRTC2_H_TOTAL_DISP 0x0300 +# define RADEON_CRTC2_H_TOTAL (0x03ff << 0) +# define RADEON_CRTC2_H_TOTAL_SHIFT 0 +# define RADEON_CRTC2_H_DISP (0x01ff << 16) +# define RADEON_CRTC2_H_DISP_SHIFT 16 + +#define RADEON_CRTC_OFFSET_RIGHT 0x0220 +#define RADEON_CRTC_OFFSET 0x0224 +# define RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET (1<<30) +# define RADEON_CRTC_OFFSET__OFFSET_LOCK (1<<31) + +#define RADEON_CRTC2_OFFSET 0x0324 +# define RADEON_CRTC2_OFFSET__GUI_TRIG_OFFSET (1<<30) +# define RADEON_CRTC2_OFFSET__OFFSET_LOCK (1<<31) +#define RADEON_CRTC_OFFSET_CNTL 0x0228 +# define RADEON_CRTC_TILE_LINE_SHIFT 0 +# define RADEON_CRTC_TILE_LINE_RIGHT_SHIFT 4 +# define R300_CRTC_X_Y_MODE_EN_RIGHT (1 << 6) +# define R300_CRTC_MICRO_TILE_BUFFER_RIGHT_MASK (3 << 7) +# define R300_CRTC_MICRO_TILE_BUFFER_RIGHT_AUTO (0 << 7) +# define R300_CRTC_MICRO_TILE_BUFFER_RIGHT_SINGLE (1 << 7) +# define R300_CRTC_MICRO_TILE_BUFFER_RIGHT_DOUBLE (2 << 7) +# define R300_CRTC_MICRO_TILE_BUFFER_RIGHT_DIS (3 << 7) +# define R300_CRTC_X_Y_MODE_EN (1 << 9) +# define R300_CRTC_MICRO_TILE_BUFFER_MASK (3 << 10) +# define R300_CRTC_MICRO_TILE_BUFFER_AUTO (0 << 10) +# define R300_CRTC_MICRO_TILE_BUFFER_SINGLE (1 << 10) +# define R300_CRTC_MICRO_TILE_BUFFER_DOUBLE (2 << 10) +# define R300_CRTC_MICRO_TILE_BUFFER_DIS (3 << 10) +# define R300_CRTC_MICRO_TILE_EN_RIGHT (1 << 12) +# define R300_CRTC_MICRO_TILE_EN (1 << 13) +# define R300_CRTC_MACRO_TILE_EN_RIGHT (1 << 14) +# define R300_CRTC_MACRO_TILE_EN (1 << 15) +# define RADEON_CRTC_TILE_EN_RIGHT (1 << 14) +# define RADEON_CRTC_TILE_EN (1 << 15) +# define RADEON_CRTC_OFFSET_FLIP_CNTL (1 << 16) +# define RADEON_CRTC_STEREO_OFFSET_EN (1 << 17) + +#define R300_CRTC_TILE_X0_Y0 0x0350 +#define R300_CRTC2_TILE_X0_Y0 0x0358 + +#define RADEON_CRTC2_OFFSET_CNTL 0x0328 +# define RADEON_CRTC2_OFFSET_FLIP_CNTL (1 << 16) +# define RADEON_CRTC2_TILE_EN (1 << 15) +#define RADEON_CRTC_PITCH 0x022c +# define RADEON_CRTC_PITCH__SHIFT 0 +# define RADEON_CRTC_PITCH__RIGHT_SHIFT 16 + +#define RADEON_CRTC2_PITCH 0x032c +#define RADEON_CRTC_STATUS 0x005c +# define RADEON_CRTC_VBLANK_SAVE (1 << 1) +# define RADEON_CRTC_VBLANK_SAVE_CLEAR (1 << 1) +#define RADEON_CRTC2_STATUS 0x03fc +# define RADEON_CRTC2_VBLANK_SAVE (1 << 1) +# define RADEON_CRTC2_VBLANK_SAVE_CLEAR (1 << 1) +#define RADEON_CRTC_V_SYNC_STRT_WID 0x020c +# define RADEON_CRTC_V_SYNC_STRT (0x7ff << 0) +# define RADEON_CRTC_V_SYNC_STRT_SHIFT 0 +# define RADEON_CRTC_V_SYNC_WID (0x1f << 16) +# define RADEON_CRTC_V_SYNC_WID_SHIFT 16 +# define RADEON_CRTC_V_SYNC_POL (1 << 23) +#define RADEON_CRTC2_V_SYNC_STRT_WID 0x030c +# define RADEON_CRTC2_V_SYNC_STRT (0x7ff << 0) +# define RADEON_CRTC2_V_SYNC_STRT_SHIFT 0 +# define RADEON_CRTC2_V_SYNC_WID (0x1f << 16) +# define RADEON_CRTC2_V_SYNC_WID_SHIFT 16 +# define RADEON_CRTC2_V_SYNC_POL (1 << 23) +#define RADEON_CRTC_V_TOTAL_DISP 0x0208 +# define RADEON_CRTC_V_TOTAL (0x07ff << 0) +# define RADEON_CRTC_V_TOTAL_SHIFT 0 +# define RADEON_CRTC_V_DISP (0x07ff << 16) +# define RADEON_CRTC_V_DISP_SHIFT 16 +#define RADEON_CRTC2_V_TOTAL_DISP 0x0308 +# define RADEON_CRTC2_V_TOTAL (0x07ff << 0) +# define RADEON_CRTC2_V_TOTAL_SHIFT 0 +# define RADEON_CRTC2_V_DISP (0x07ff << 16) +# define RADEON_CRTC2_V_DISP_SHIFT 16 +#define RADEON_CRTC_VLINE_CRNT_VLINE 0x0210 +# define RADEON_CRTC_CRNT_VLINE_MASK (0x7ff << 16) +#define RADEON_CRTC2_CRNT_FRAME 0x0314 +#define RADEON_CRTC2_GUI_TRIG_VLINE 0x0318 +#define RADEON_CRTC2_STATUS 0x03fc +#define RADEON_CRTC2_VLINE_CRNT_VLINE 0x0310 +#define RADEON_CRTC8_DATA 0x03d5 /* VGA, 0x3b5 */ +#define RADEON_CRTC8_IDX 0x03d4 /* VGA, 0x3b4 */ +#define RADEON_CUR_CLR0 0x026c +#define RADEON_CUR_CLR1 0x0270 +#define RADEON_CUR_HORZ_VERT_OFF 0x0268 +#define RADEON_CUR_HORZ_VERT_POSN 0x0264 +#define RADEON_CUR_OFFSET 0x0260 +# define RADEON_CUR_LOCK (1 << 31) +#define RADEON_CUR2_CLR0 0x036c +#define RADEON_CUR2_CLR1 0x0370 +#define RADEON_CUR2_HORZ_VERT_OFF 0x0368 +#define RADEON_CUR2_HORZ_VERT_POSN 0x0364 +#define RADEON_CUR2_OFFSET 0x0360 +# define RADEON_CUR2_LOCK (1 << 31) + +#define RADEON_DAC_CNTL 0x0058 +# define RADEON_DAC_RANGE_CNTL (3 << 0) +# define RADEON_DAC_RANGE_CNTL_PS2 (2 << 0) +# define RADEON_DAC_RANGE_CNTL_MASK 0x03 +# define RADEON_DAC_BLANKING (1 << 2) +# define RADEON_DAC_CMP_EN (1 << 3) +# define RADEON_DAC_CMP_OUTPUT (1 << 7) +# define RADEON_DAC_8BIT_EN (1 << 8) +# define RADEON_DAC_TVO_EN (1 << 10) +# define RADEON_DAC_VGA_ADR_EN (1 << 13) +# define RADEON_DAC_PDWN (1 << 15) +# define RADEON_DAC_MASK_ALL (0xff << 24) +#define RADEON_DAC_CNTL2 0x007c +# define RADEON_DAC2_TV_CLK_SEL (0 << 1) +# define RADEON_DAC2_DAC_CLK_SEL (1 << 0) +# define RADEON_DAC2_DAC2_CLK_SEL (1 << 1) +# define RADEON_DAC2_PALETTE_ACC_CTL (1 << 5) +# define RADEON_DAC2_CMP_EN (1 << 7) +# define RADEON_DAC2_CMP_OUT_R (1 << 8) +# define RADEON_DAC2_CMP_OUT_G (1 << 9) +# define RADEON_DAC2_CMP_OUT_B (1 << 10) +# define RADEON_DAC2_CMP_OUTPUT (1 << 11) +#define RADEON_DAC_EXT_CNTL 0x0280 +# define RADEON_DAC2_FORCE_BLANK_OFF_EN (1 << 0) +# define RADEON_DAC2_FORCE_DATA_EN (1 << 1) +# define RADEON_DAC_FORCE_BLANK_OFF_EN (1 << 4) +# define RADEON_DAC_FORCE_DATA_EN (1 << 5) +# define RADEON_DAC_FORCE_DATA_SEL_MASK (3 << 6) +# define RADEON_DAC_FORCE_DATA_SEL_R (0 << 6) +# define RADEON_DAC_FORCE_DATA_SEL_G (1 << 6) +# define RADEON_DAC_FORCE_DATA_SEL_B (2 << 6) +# define RADEON_DAC_FORCE_DATA_SEL_RGB (3 << 6) +# define RADEON_DAC_FORCE_DATA_MASK 0x0003ff00 +# define RADEON_DAC_FORCE_DATA_SHIFT 8 +#define RADEON_DAC_MACRO_CNTL 0x0d04 +# define RADEON_DAC_PDWN_R (1 << 16) +# define RADEON_DAC_PDWN_G (1 << 17) +# define RADEON_DAC_PDWN_B (1 << 18) +#define RADEON_TV_DAC_CNTL 0x088c +# define RADEON_TV_DAC_NBLANK (1 << 0) +# define RADEON_TV_DAC_NHOLD (1 << 1) +# define RADEON_TV_DAC_PEDESTAL (1 << 2) +# define RADEON_TV_MONITOR_DETECT_EN (1 << 4) +# define RADEON_TV_DAC_CMPOUT (1 << 5) +# define RADEON_TV_DAC_STD_MASK (3 << 8) +# define RADEON_TV_DAC_STD_PAL (0 << 8) +# define RADEON_TV_DAC_STD_NTSC (1 << 8) +# define RADEON_TV_DAC_STD_PS2 (2 << 8) +# define RADEON_TV_DAC_STD_RS343 (3 << 8) +# define RADEON_TV_DAC_BGSLEEP (1 << 6) +# define RADEON_TV_DAC_BGADJ_MASK (0xf << 16) +# define RADEON_TV_DAC_BGADJ_SHIFT 16 +# define RADEON_TV_DAC_DACADJ_MASK (0xf << 20) +# define RADEON_TV_DAC_DACADJ_SHIFT 20 +# define RADEON_TV_DAC_RDACPD (1 << 24) +# define RADEON_TV_DAC_GDACPD (1 << 25) +# define RADEON_TV_DAC_BDACPD (1 << 26) +# define RADEON_TV_DAC_RDACDET (1 << 29) +# define RADEON_TV_DAC_GDACDET (1 << 30) +# define RADEON_TV_DAC_BDACDET (1 << 31) +# define R420_TV_DAC_DACADJ_MASK (0x1f << 20) +# define R420_TV_DAC_RDACPD (1 << 25) +# define R420_TV_DAC_GDACPD (1 << 26) +# define R420_TV_DAC_BDACPD (1 << 27) +# define R420_TV_DAC_TVENABLE (1 << 28) +#define RADEON_DISP_HW_DEBUG 0x0d14 +# define RADEON_CRT2_DISP1_SEL (1 << 5) +#define RADEON_DISP_OUTPUT_CNTL 0x0d64 +# define RADEON_DISP_DAC_SOURCE_MASK 0x03 +# define RADEON_DISP_DAC2_SOURCE_MASK 0x0c +# define RADEON_DISP_DAC_SOURCE_CRTC2 0x01 +# define RADEON_DISP_DAC_SOURCE_RMX 0x02 +# define RADEON_DISP_DAC_SOURCE_LTU 0x03 +# define RADEON_DISP_DAC2_SOURCE_CRTC2 0x04 +# define RADEON_DISP_TVDAC_SOURCE_MASK (0x03 << 2) +# define RADEON_DISP_TVDAC_SOURCE_CRTC 0x0 +# define RADEON_DISP_TVDAC_SOURCE_CRTC2 (0x01 << 2) +# define RADEON_DISP_TVDAC_SOURCE_RMX (0x02 << 2) +# define RADEON_DISP_TVDAC_SOURCE_LTU (0x03 << 2) +# define RADEON_DISP_TRANS_MATRIX_MASK (0x03 << 4) +# define RADEON_DISP_TRANS_MATRIX_ALPHA_MSB (0x00 << 4) +# define RADEON_DISP_TRANS_MATRIX_GRAPHICS (0x01 << 4) +# define RADEON_DISP_TRANS_MATRIX_VIDEO (0x02 << 4) +# define RADEON_DISP_TV_SOURCE_CRTC (1 << 16) /* crtc1 or crtc2 */ +# define RADEON_DISP_TV_SOURCE_LTU (0 << 16) /* linear transform unit */ +#define RADEON_DISP_TV_OUT_CNTL 0x0d6c +# define RADEON_DISP_TV_PATH_SRC_CRTC2 (1 << 16) +# define RADEON_DISP_TV_PATH_SRC_CRTC1 (0 << 16) +#define RADEON_DAC_CRC_SIG 0x02cc +#define RADEON_DAC_DATA 0x03c9 /* VGA */ +#define RADEON_DAC_MASK 0x03c6 /* VGA */ +#define RADEON_DAC_R_INDEX 0x03c7 /* VGA */ +#define RADEON_DAC_W_INDEX 0x03c8 /* VGA */ +#define RADEON_DDA_CONFIG 0x02e0 +#define RADEON_DDA_ON_OFF 0x02e4 +#define RADEON_DEFAULT_OFFSET 0x16e0 +#define RADEON_DEFAULT_PITCH 0x16e4 +#define RADEON_DEFAULT_SC_BOTTOM_RIGHT 0x16e8 +# define RADEON_DEFAULT_SC_RIGHT_MAX (0x1fff << 0) +# define RADEON_DEFAULT_SC_BOTTOM_MAX (0x1fff << 16) +#define RADEON_DESTINATION_3D_CLR_CMP_VAL 0x1820 +#define RADEON_DESTINATION_3D_CLR_CMP_MSK 0x1824 +#define RADEON_DEVICE_ID 0x0f02 /* PCI */ +#define RADEON_DISP_MISC_CNTL 0x0d00 +# define RADEON_SOFT_RESET_GRPH_PP (1 << 0) +#define RADEON_DISP_MERGE_CNTL 0x0d60 +# define RADEON_DISP_ALPHA_MODE_MASK 0x03 +# define RADEON_DISP_ALPHA_MODE_KEY 0 +# define RADEON_DISP_ALPHA_MODE_PER_PIXEL 1 +# define RADEON_DISP_ALPHA_MODE_GLOBAL 2 +# define RADEON_DISP_RGB_OFFSET_EN (1 << 8) +# define RADEON_DISP_GRPH_ALPHA_MASK (0xff << 16) +# define RADEON_DISP_OV0_ALPHA_MASK (0xff << 24) +# define RADEON_DISP_LIN_TRANS_BYPASS (0x01 << 9) +#define RADEON_DISP2_MERGE_CNTL 0x0d68 +# define RADEON_DISP2_RGB_OFFSET_EN (1 << 8) +#define RADEON_DISP_LIN_TRANS_GRPH_A 0x0d80 +#define RADEON_DISP_LIN_TRANS_GRPH_B 0x0d84 +#define RADEON_DISP_LIN_TRANS_GRPH_C 0x0d88 +#define RADEON_DISP_LIN_TRANS_GRPH_D 0x0d8c +#define RADEON_DISP_LIN_TRANS_GRPH_E 0x0d90 +#define RADEON_DISP_LIN_TRANS_GRPH_F 0x0d98 +#define RADEON_DP_BRUSH_BKGD_CLR 0x1478 +#define RADEON_DP_BRUSH_FRGD_CLR 0x147c +#define RADEON_DP_CNTL 0x16c0 +# define RADEON_DST_X_LEFT_TO_RIGHT (1 << 0) +# define RADEON_DST_Y_TOP_TO_BOTTOM (1 << 1) +# define RADEON_DP_DST_TILE_LINEAR (0 << 3) +# define RADEON_DP_DST_TILE_MACRO (1 << 3) +# define RADEON_DP_DST_TILE_MICRO (2 << 3) +# define RADEON_DP_DST_TILE_BOTH (3 << 3) +#define RADEON_DP_CNTL_XDIR_YDIR_YMAJOR 0x16d0 +# define RADEON_DST_Y_MAJOR (1 << 2) +# define RADEON_DST_Y_DIR_TOP_TO_BOTTOM (1 << 15) +# define RADEON_DST_X_DIR_LEFT_TO_RIGHT (1 << 31) +#define RADEON_DP_DATATYPE 0x16c4 +# define RADEON_HOST_BIG_ENDIAN_EN (1 << 29) +#define RADEON_DP_GUI_MASTER_CNTL 0x146c +# define RADEON_GMC_SRC_PITCH_OFFSET_CNTL (1 << 0) +# define RADEON_GMC_DST_PITCH_OFFSET_CNTL (1 << 1) +# define RADEON_GMC_SRC_CLIPPING (1 << 2) +# define RADEON_GMC_DST_CLIPPING (1 << 3) +# define RADEON_GMC_BRUSH_DATATYPE_MASK (0x0f << 4) +# define RADEON_GMC_BRUSH_8X8_MONO_FG_BG (0 << 4) +# define RADEON_GMC_BRUSH_8X8_MONO_FG_LA (1 << 4) +# define RADEON_GMC_BRUSH_1X8_MONO_FG_BG (4 << 4) +# define RADEON_GMC_BRUSH_1X8_MONO_FG_LA (5 << 4) +# define RADEON_GMC_BRUSH_32x1_MONO_FG_BG (6 << 4) +# define RADEON_GMC_BRUSH_32x1_MONO_FG_LA (7 << 4) +# define RADEON_GMC_BRUSH_32x32_MONO_FG_BG (8 << 4) +# define RADEON_GMC_BRUSH_32x32_MONO_FG_LA (9 << 4) +# define RADEON_GMC_BRUSH_8x8_COLOR (10 << 4) +# define RADEON_GMC_BRUSH_1X8_COLOR (12 << 4) +# define RADEON_GMC_BRUSH_SOLID_COLOR (13 << 4) +# define RADEON_GMC_BRUSH_NONE (15 << 4) +# define RADEON_GMC_DST_8BPP_CI (2 << 8) +# define RADEON_GMC_DST_15BPP (3 << 8) +# define RADEON_GMC_DST_16BPP (4 << 8) +# define RADEON_GMC_DST_24BPP (5 << 8) +# define RADEON_GMC_DST_32BPP (6 << 8) +# define RADEON_GMC_DST_8BPP_RGB (7 << 8) +# define RADEON_GMC_DST_Y8 (8 << 8) +# define RADEON_GMC_DST_RGB8 (9 << 8) +# define RADEON_GMC_DST_VYUY (11 << 8) +# define RADEON_GMC_DST_YVYU (12 << 8) +# define RADEON_GMC_DST_AYUV444 (14 << 8) +# define RADEON_GMC_DST_ARGB4444 (15 << 8) +# define RADEON_GMC_DST_DATATYPE_MASK (0x0f << 8) +# define RADEON_GMC_DST_DATATYPE_SHIFT 8 +# define RADEON_GMC_SRC_DATATYPE_MASK (3 << 12) +# define RADEON_GMC_SRC_DATATYPE_MONO_FG_BG (0 << 12) +# define RADEON_GMC_SRC_DATATYPE_MONO_FG_LA (1 << 12) +# define RADEON_GMC_SRC_DATATYPE_COLOR (3 << 12) +# define RADEON_GMC_BYTE_PIX_ORDER (1 << 14) +# define RADEON_GMC_BYTE_MSB_TO_LSB (0 << 14) +# define RADEON_GMC_BYTE_LSB_TO_MSB (1 << 14) +# define RADEON_GMC_CONVERSION_TEMP (1 << 15) +# define RADEON_GMC_CONVERSION_TEMP_6500 (0 << 15) +# define RADEON_GMC_CONVERSION_TEMP_9300 (1 << 15) +# define RADEON_GMC_ROP3_MASK (0xff << 16) +# define RADEON_DP_SRC_SOURCE_MASK (7 << 24) +# define RADEON_DP_SRC_SOURCE_MEMORY (2 << 24) +# define RADEON_DP_SRC_SOURCE_HOST_DATA (3 << 24) +# define RADEON_GMC_3D_FCN_EN (1 << 27) +# define RADEON_GMC_CLR_CMP_CNTL_DIS (1 << 28) +# define RADEON_GMC_AUX_CLIP_DIS (1 << 29) +# define RADEON_GMC_WR_MSK_DIS (1 << 30) +# define RADEON_GMC_LD_BRUSH_Y_X (1 << 31) +# define RADEON_ROP3_ZERO 0x00000000 +# define RADEON_ROP3_DSa 0x00880000 +# define RADEON_ROP3_SDna 0x00440000 +# define RADEON_ROP3_S 0x00cc0000 +# define RADEON_ROP3_DSna 0x00220000 +# define RADEON_ROP3_D 0x00aa0000 +# define RADEON_ROP3_DSx 0x00660000 +# define RADEON_ROP3_DSo 0x00ee0000 +# define RADEON_ROP3_DSon 0x00110000 +# define RADEON_ROP3_DSxn 0x00990000 +# define RADEON_ROP3_Dn 0x00550000 +# define RADEON_ROP3_SDno 0x00dd0000 +# define RADEON_ROP3_Sn 0x00330000 +# define RADEON_ROP3_DSno 0x00bb0000 +# define RADEON_ROP3_DSan 0x00770000 +# define RADEON_ROP3_ONE 0x00ff0000 +# define RADEON_ROP3_DPa 0x00a00000 +# define RADEON_ROP3_PDna 0x00500000 +# define RADEON_ROP3_P 0x00f00000 +# define RADEON_ROP3_DPna 0x000a0000 +# define RADEON_ROP3_D 0x00aa0000 +# define RADEON_ROP3_DPx 0x005a0000 +# define RADEON_ROP3_DPo 0x00fa0000 +# define RADEON_ROP3_DPon 0x00050000 +# define RADEON_ROP3_PDxn 0x00a50000 +# define RADEON_ROP3_PDno 0x00f50000 +# define RADEON_ROP3_Pn 0x000f0000 +# define RADEON_ROP3_DPno 0x00af0000 +# define RADEON_ROP3_DPan 0x005f0000 +#define RADEON_DP_GUI_MASTER_CNTL_C 0x1c84 +#define RADEON_DP_MIX 0x16c8 +#define RADEON_DP_SRC_BKGD_CLR 0x15dc +#define RADEON_DP_SRC_FRGD_CLR 0x15d8 +#define RADEON_DP_WRITE_MASK 0x16cc +#define RADEON_DST_BRES_DEC 0x1630 +#define RADEON_DST_BRES_ERR 0x1628 +#define RADEON_DST_BRES_INC 0x162c +#define RADEON_DST_BRES_LNTH 0x1634 +#define RADEON_DST_BRES_LNTH_SUB 0x1638 +#define RADEON_DST_HEIGHT 0x1410 +#define RADEON_DST_HEIGHT_WIDTH 0x143c +#define RADEON_DST_HEIGHT_WIDTH_8 0x158c +#define RADEON_DST_HEIGHT_WIDTH_BW 0x15b4 +#define RADEON_DST_HEIGHT_Y 0x15a0 +#define RADEON_DST_LINE_START 0x1600 +#define RADEON_DST_LINE_END 0x1604 +#define RADEON_DST_LINE_PATCOUNT 0x1608 +# define RADEON_BRES_CNTL_SHIFT 8 +#define RADEON_DST_OFFSET 0x1404 +#define RADEON_DST_PITCH 0x1408 +#define RADEON_DST_PITCH_OFFSET 0x142c +#define RADEON_DST_PITCH_OFFSET_C 0x1c80 +# define RADEON_PITCH_SHIFT 21 +# define RADEON_DST_TILE_LINEAR (0 << 30) +# define RADEON_DST_TILE_MACRO (1 << 30) +# define RADEON_DST_TILE_MICRO (2 << 30) +# define RADEON_DST_TILE_BOTH (3 << 30) +#define RADEON_DST_WIDTH 0x140c +#define RADEON_DST_WIDTH_HEIGHT 0x1598 +#define RADEON_DST_WIDTH_X 0x1588 +#define RADEON_DST_WIDTH_X_INCY 0x159c +#define RADEON_DST_X 0x141c +#define RADEON_DST_X_SUB 0x15a4 +#define RADEON_DST_X_Y 0x1594 +#define RADEON_DST_Y 0x1420 +#define RADEON_DST_Y_SUB 0x15a8 +#define RADEON_DST_Y_X 0x1438 + +#define RADEON_FCP_CNTL 0x0910 +# define RADEON_FCP0_SRC_PCICLK 0 +# define RADEON_FCP0_SRC_PCLK 1 +# define RADEON_FCP0_SRC_PCLKb 2 +# define RADEON_FCP0_SRC_HREF 3 +# define RADEON_FCP0_SRC_GND 4 +# define RADEON_FCP0_SRC_HREFb 5 +#define RADEON_FLUSH_1 0x1704 +#define RADEON_FLUSH_2 0x1708 +#define RADEON_FLUSH_3 0x170c +#define RADEON_FLUSH_4 0x1710 +#define RADEON_FLUSH_5 0x1714 +#define RADEON_FLUSH_6 0x1718 +#define RADEON_FLUSH_7 0x171c +#define RADEON_FOG_3D_TABLE_START 0x1810 +#define RADEON_FOG_3D_TABLE_END 0x1814 +#define RADEON_FOG_3D_TABLE_DENSITY 0x181c +#define RADEON_FOG_TABLE_INDEX 0x1a14 +#define RADEON_FOG_TABLE_DATA 0x1a18 +#define RADEON_FP_CRTC_H_TOTAL_DISP 0x0250 +#define RADEON_FP_CRTC_V_TOTAL_DISP 0x0254 +# define RADEON_FP_CRTC_H_TOTAL_MASK 0x000003ff +# define RADEON_FP_CRTC_H_DISP_MASK 0x01ff0000 +# define RADEON_FP_CRTC_V_TOTAL_MASK 0x00000fff +# define RADEON_FP_CRTC_V_DISP_MASK 0x0fff0000 +# define RADEON_FP_H_SYNC_STRT_CHAR_MASK 0x00001ff8 +# define RADEON_FP_H_SYNC_WID_MASK 0x003f0000 +# define RADEON_FP_V_SYNC_STRT_MASK 0x00000fff +# define RADEON_FP_V_SYNC_WID_MASK 0x001f0000 +# define RADEON_FP_CRTC_H_TOTAL_SHIFT 0x00000000 +# define RADEON_FP_CRTC_H_DISP_SHIFT 0x00000010 +# define RADEON_FP_CRTC_V_TOTAL_SHIFT 0x00000000 +# define RADEON_FP_CRTC_V_DISP_SHIFT 0x00000010 +# define RADEON_FP_H_SYNC_STRT_CHAR_SHIFT 0x00000003 +# define RADEON_FP_H_SYNC_WID_SHIFT 0x00000010 +# define RADEON_FP_V_SYNC_STRT_SHIFT 0x00000000 +# define RADEON_FP_V_SYNC_WID_SHIFT 0x00000010 +#define RADEON_FP_GEN_CNTL 0x0284 +# define RADEON_FP_FPON (1 << 0) +# define RADEON_FP_BLANK_EN (1 << 1) +# define RADEON_FP_TMDS_EN (1 << 2) +# define RADEON_FP_PANEL_FORMAT (1 << 3) +# define RADEON_FP_EN_TMDS (1 << 7) +# define RADEON_FP_DETECT_SENSE (1 << 8) +# define R200_FP_SOURCE_SEL_MASK (3 << 10) +# define R200_FP_SOURCE_SEL_CRTC1 (0 << 10) +# define R200_FP_SOURCE_SEL_CRTC2 (1 << 10) +# define R200_FP_SOURCE_SEL_RMX (2 << 10) +# define R200_FP_SOURCE_SEL_TRANS (3 << 10) +# define RADEON_FP_SEL_CRTC1 (0 << 13) +# define RADEON_FP_SEL_CRTC2 (1 << 13) +# define RADEON_FP_CRTC_DONT_SHADOW_HPAR (1 << 15) +# define RADEON_FP_CRTC_DONT_SHADOW_VPAR (1 << 16) +# define RADEON_FP_CRTC_DONT_SHADOW_HEND (1 << 17) +# define RADEON_FP_CRTC_USE_SHADOW_VEND (1 << 18) +# define RADEON_FP_RMX_HVSYNC_CONTROL_EN (1 << 20) +# define RADEON_FP_DFP_SYNC_SEL (1 << 21) +# define RADEON_FP_CRTC_LOCK_8DOT (1 << 22) +# define RADEON_FP_CRT_SYNC_SEL (1 << 23) +# define RADEON_FP_USE_SHADOW_EN (1 << 24) +# define RADEON_FP_CRT_SYNC_ALT (1 << 26) +#define RADEON_FP2_GEN_CNTL 0x0288 +# define RADEON_FP2_BLANK_EN (1 << 1) +# define RADEON_FP2_ON (1 << 2) +# define RADEON_FP2_PANEL_FORMAT (1 << 3) +# define RADEON_FP2_DETECT_SENSE (1 << 8) +# define R200_FP2_SOURCE_SEL_MASK (3 << 10) +# define R200_FP2_SOURCE_SEL_CRTC1 (0 << 10) +# define R200_FP2_SOURCE_SEL_CRTC2 (1 << 10) +# define R200_FP2_SOURCE_SEL_RMX (2 << 10) +# define R200_FP2_SOURCE_SEL_TRANS_UNIT (3 << 10) +# define RADEON_FP2_SRC_SEL_MASK (3 << 13) +# define RADEON_FP2_SRC_SEL_CRTC2 (1 << 13) +# define RADEON_FP2_FP_POL (1 << 16) +# define RADEON_FP2_LP_POL (1 << 17) +# define RADEON_FP2_SCK_POL (1 << 18) +# define RADEON_FP2_LCD_CNTL_MASK (7 << 19) +# define RADEON_FP2_PAD_FLOP_EN (1 << 22) +# define RADEON_FP2_CRC_EN (1 << 23) +# define RADEON_FP2_CRC_READ_EN (1 << 24) +# define RADEON_FP2_DVO_EN (1 << 25) +# define RADEON_FP2_DVO_RATE_SEL_SDR (1 << 26) +# define R200_FP2_DVO_RATE_SEL_SDR (1 << 27) +# define R200_FP2_DVO_CLOCK_MODE_SINGLE (1 << 28) +# define R300_FP2_DVO_DUAL_CHANNEL_EN (1 << 29) +#define RADEON_FP_H_SYNC_STRT_WID 0x02c4 +#define RADEON_FP_H2_SYNC_STRT_WID 0x03c4 +#define RADEON_FP_HORZ_STRETCH 0x028c +#define RADEON_FP_HORZ2_STRETCH 0x038c +# define RADEON_HORZ_STRETCH_RATIO_MASK 0xffff +# define RADEON_HORZ_STRETCH_RATIO_MAX 4096 +# define RADEON_HORZ_PANEL_SIZE (0x1ff << 16) +# define RADEON_HORZ_PANEL_SHIFT 16 +# define RADEON_HORZ_STRETCH_PIXREP (0 << 25) +# define RADEON_HORZ_STRETCH_BLEND (1 << 26) +# define RADEON_HORZ_STRETCH_ENABLE (1 << 25) +# define RADEON_HORZ_AUTO_RATIO (1 << 27) +# define RADEON_HORZ_FP_LOOP_STRETCH (0x7 << 28) +# define RADEON_HORZ_AUTO_RATIO_INC (1 << 31) +#define RADEON_FP_HORZ_VERT_ACTIVE 0x0278 +#define RADEON_FP_V_SYNC_STRT_WID 0x02c8 +#define RADEON_FP_VERT_STRETCH 0x0290 +#define RADEON_FP_V2_SYNC_STRT_WID 0x03c8 +#define RADEON_FP_VERT2_STRETCH 0x0390 +# define RADEON_VERT_PANEL_SIZE (0xfff << 12) +# define RADEON_VERT_PANEL_SHIFT 12 +# define RADEON_VERT_STRETCH_RATIO_MASK 0xfff +# define RADEON_VERT_STRETCH_RATIO_SHIFT 0 +# define RADEON_VERT_STRETCH_RATIO_MAX 4096 +# define RADEON_VERT_STRETCH_ENABLE (1 << 25) +# define RADEON_VERT_STRETCH_LINEREP (0 << 26) +# define RADEON_VERT_STRETCH_BLEND (1 << 26) +# define RADEON_VERT_AUTO_RATIO_EN (1 << 27) +# define RADEON_VERT_AUTO_RATIO_INC (1 << 31) +# define RADEON_VERT_STRETCH_RESERVED 0x71000000 +#define RS400_FP_2ND_GEN_CNTL 0x0384 +# define RS400_FP_2ND_ON (1 << 0) +# define RS400_FP_2ND_BLANK_EN (1 << 1) +# define RS400_TMDS_2ND_EN (1 << 2) +# define RS400_PANEL_FORMAT_2ND (1 << 3) +# define RS400_FP_2ND_EN_TMDS (1 << 7) +# define RS400_FP_2ND_DETECT_SENSE (1 << 8) +# define RS400_FP_2ND_SOURCE_SEL_MASK (3 << 10) +# define RS400_FP_2ND_SOURCE_SEL_CRTC1 (0 << 10) +# define RS400_FP_2ND_SOURCE_SEL_CRTC2 (1 << 10) +# define RS400_FP_2ND_SOURCE_SEL_RMX (2 << 10) +# define RS400_FP_2ND_DETECT_EN (1 << 12) +# define RS400_HPD_2ND_SEL (1 << 13) +#define RS400_FP2_2_GEN_CNTL 0x0388 +# define RS400_FP2_2_BLANK_EN (1 << 1) +# define RS400_FP2_2_ON (1 << 2) +# define RS400_FP2_2_PANEL_FORMAT (1 << 3) +# define RS400_FP2_2_DETECT_SENSE (1 << 8) +# define RS400_FP2_2_SOURCE_SEL_MASK (3 << 10) +# define RS400_FP2_2_SOURCE_SEL_CRTC1 (0 << 10) +# define RS400_FP2_2_SOURCE_SEL_CRTC2 (1 << 10) +# define RS400_FP2_2_SOURCE_SEL_RMX (2 << 10) +# define RS400_FP2_2_DVO2_EN (1 << 25) +#define RS400_TMDS2_CNTL 0x0394 +#define RS400_TMDS2_TRANSMITTER_CNTL 0x03a4 +# define RS400_TMDS2_PLLEN (1 << 0) +# define RS400_TMDS2_PLLRST (1 << 1) + +#define RADEON_GEN_INT_CNTL 0x0040 +#define RADEON_GEN_INT_STATUS 0x0044 +# define RADEON_VSYNC_INT_AK (1 << 2) +# define RADEON_VSYNC_INT (1 << 2) +# define RADEON_VSYNC2_INT_AK (1 << 6) +# define RADEON_VSYNC2_INT (1 << 6) +#define RADEON_GENENB 0x03c3 /* VGA */ +#define RADEON_GENFC_RD 0x03ca /* VGA */ +#define RADEON_GENFC_WT 0x03da /* VGA, 0x03ba */ +#define RADEON_GENMO_RD 0x03cc /* VGA */ +#define RADEON_GENMO_WT 0x03c2 /* VGA */ +#define RADEON_GENS0 0x03c2 /* VGA */ +#define RADEON_GENS1 0x03da /* VGA, 0x03ba */ +#define RADEON_GPIO_MONID 0x0068 /* DDC interface via I2C */ /* DDC3 */ +#define RADEON_GPIO_MONIDB 0x006c +#define RADEON_GPIO_CRT2_DDC 0x006c +#define RADEON_GPIO_DVI_DDC 0x0064 /* DDC2 */ +#define RADEON_GPIO_VGA_DDC 0x0060 /* DDC1 */ +# define RADEON_GPIO_A_0 (1 << 0) +# define RADEON_GPIO_A_1 (1 << 1) +# define RADEON_GPIO_Y_0 (1 << 8) +# define RADEON_GPIO_Y_1 (1 << 9) +# define RADEON_GPIO_Y_SHIFT_0 8 +# define RADEON_GPIO_Y_SHIFT_1 9 +# define RADEON_GPIO_EN_0 (1 << 16) +# define RADEON_GPIO_EN_1 (1 << 17) +# define RADEON_GPIO_MASK_0 (1 << 24) /*??*/ +# define RADEON_GPIO_MASK_1 (1 << 25) /*??*/ +#define RADEON_GRPH8_DATA 0x03cf /* VGA */ +#define RADEON_GRPH8_IDX 0x03ce /* VGA */ +#define RADEON_GUI_SCRATCH_REG0 0x15e0 +#define RADEON_GUI_SCRATCH_REG1 0x15e4 +#define RADEON_GUI_SCRATCH_REG2 0x15e8 +#define RADEON_GUI_SCRATCH_REG3 0x15ec +#define RADEON_GUI_SCRATCH_REG4 0x15f0 +#define RADEON_GUI_SCRATCH_REG5 0x15f4 + +#define RADEON_HEADER 0x0f0e /* PCI */ +#define RADEON_HOST_DATA0 0x17c0 +#define RADEON_HOST_DATA1 0x17c4 +#define RADEON_HOST_DATA2 0x17c8 +#define RADEON_HOST_DATA3 0x17cc +#define RADEON_HOST_DATA4 0x17d0 +#define RADEON_HOST_DATA5 0x17d4 +#define RADEON_HOST_DATA6 0x17d8 +#define RADEON_HOST_DATA7 0x17dc +#define RADEON_HOST_DATA_LAST 0x17e0 +#define RADEON_HOST_PATH_CNTL 0x0130 +# define RADEON_HDP_SOFT_RESET (1 << 26) +# define RADEON_HDP_APER_CNTL (1 << 23) +#define RADEON_HTOTAL_CNTL 0x0009 /* PLL */ +# define RADEON_HTOT_CNTL_VGA_EN (1 << 28) +#define RADEON_HTOTAL2_CNTL 0x002e /* PLL */ + + /* Multimedia I2C bus */ +#define RADEON_I2C_CNTL_0 0x0090 +#define RADEON_I2C_DONE (1 << 0) +#define RADEON_I2C_NACK (1 << 1) +#define RADEON_I2C_HALT (1 << 2) +#define RADEON_I2C_SOFT_RST (1 << 5) +#define RADEON_I2C_DRIVE_EN (1 << 6) +#define RADEON_I2C_DRIVE_SEL (1 << 7) +#define RADEON_I2C_START (1 << 8) +#define RADEON_I2C_STOP (1 << 9) +#define RADEON_I2C_RECEIVE (1 << 10) +#define RADEON_I2C_ABORT (1 << 11) +#define RADEON_I2C_GO (1 << 12) +#define RADEON_I2C_CNTL_1 0x0094 +#define RADEON_I2C_SEL (1 << 16) +#define RADEON_I2C_EN (1 << 17) +#define RADEON_I2C_DATA 0x0098 + +#define RADEON_DVI_I2C_CNTL_0 0x02e0 +# define R200_DVI_I2C_PIN_SEL(x) ((x) << 3) +# define R200_SEL_DDC1 0 /* 0x60 - VGA_DDC */ +# define R200_SEL_DDC2 1 /* 0x64 - DVI_DDC */ +# define R200_SEL_DDC3 2 /* 0x68 - MONID_DDC */ +#define RADEON_DVI_I2C_CNTL_1 0x02e4 +#define RADEON_DVI_I2C_DATA 0x02e8 + +#define RADEON_INTERRUPT_LINE 0x0f3c /* PCI */ +#define RADEON_INTERRUPT_PIN 0x0f3d /* PCI */ +#define RADEON_IO_BASE 0x0f14 /* PCI */ + +#define RADEON_LATENCY 0x0f0d /* PCI */ +#define RADEON_LEAD_BRES_DEC 0x1608 +#define RADEON_LEAD_BRES_LNTH 0x161c +#define RADEON_LEAD_BRES_LNTH_SUB 0x1624 +#define RADEON_LVDS_GEN_CNTL 0x02d0 +# define RADEON_LVDS_ON (1 << 0) +# define RADEON_LVDS_DISPLAY_DIS (1 << 1) +# define RADEON_LVDS_PANEL_TYPE (1 << 2) +# define RADEON_LVDS_PANEL_FORMAT (1 << 3) +# define RADEON_LVDS_RST_FM (1 << 6) +# define RADEON_LVDS_EN (1 << 7) +# define RADEON_LVDS_BL_MOD_LEVEL_SHIFT 8 +# define RADEON_LVDS_BL_MOD_LEVEL_MASK (0xff << 8) +# define RADEON_LVDS_BL_MOD_EN (1 << 16) +# define RADEON_LVDS_DIGON (1 << 18) +# define RADEON_LVDS_BLON (1 << 19) +# define RADEON_LVDS_SEL_CRTC2 (1 << 23) +#define RADEON_LVDS_PLL_CNTL 0x02d4 +# define RADEON_HSYNC_DELAY_SHIFT 28 +# define RADEON_HSYNC_DELAY_MASK (0xf << 28) +# define RADEON_LVDS_PLL_EN (1 << 16) +# define RADEON_LVDS_PLL_RESET (1 << 17) +# define R300_LVDS_SRC_SEL_MASK (3 << 18) +# define R300_LVDS_SRC_SEL_CRTC1 (0 << 18) +# define R300_LVDS_SRC_SEL_CRTC2 (1 << 18) +# define R300_LVDS_SRC_SEL_RMX (2 << 18) + +#define RADEON_MAX_LATENCY 0x0f3f /* PCI */ +#define RADEON_MC_AGP_LOCATION 0x014c +#define RADEON_MC_FB_LOCATION 0x0148 +#define RADEON_DISPLAY_BASE_ADDR 0x23c +#define RADEON_DISPLAY2_BASE_ADDR 0x33c +#define RADEON_OV0_BASE_ADDR 0x43c +#define RADEON_NB_TOM 0x15c +#define R300_MC_INIT_MISC_LAT_TIMER 0x180 +# define R300_MC_DISP0R_INIT_LAT_SHIFT 8 +# define R300_MC_DISP0R_INIT_LAT_MASK 0xf +# define R300_MC_DISP1R_INIT_LAT_SHIFT 12 +# define R300_MC_DISP1R_INIT_LAT_MASK 0xf +#define RADEON_MCLK_CNTL 0x0012 /* PLL */ +# define RADEON_FORCEON_MCLKA (1 << 16) +# define RADEON_FORCEON_MCLKB (1 << 17) +# define RADEON_FORCEON_YCLKA (1 << 18) +# define RADEON_FORCEON_YCLKB (1 << 19) +# define RADEON_FORCEON_MC (1 << 20) +# define RADEON_FORCEON_AIC (1 << 21) +# define R300_DISABLE_MC_MCLKA (1 << 21) +# define R300_DISABLE_MC_MCLKB (1 << 21) +#define RADEON_MCLK_MISC 0x001f /* PLL */ +# define RADEON_MC_MCLK_MAX_DYN_STOP_LAT (1 << 12) +# define RADEON_IO_MCLK_MAX_DYN_STOP_LAT (1 << 13) +# define RADEON_MC_MCLK_DYN_ENABLE (1 << 14) +# define RADEON_IO_MCLK_DYN_ENABLE (1 << 15) +#define RADEON_LCD_GPIO_MASK 0x01a0 +#define RADEON_GPIOPAD_EN 0x01a0 +#define RADEON_LCD_GPIO_Y_REG 0x01a4 +#define RADEON_MDGPIO_A_REG 0x01ac +#define RADEON_MDGPIO_EN_REG 0x01b0 +#define RADEON_MDGPIO_MASK 0x0198 +#define RADEON_GPIOPAD_MASK 0x0198 +#define RADEON_GPIOPAD_A 0x019c +#define RADEON_MDGPIO_Y_REG 0x01b4 +#define RADEON_MEM_ADDR_CONFIG 0x0148 +#define RADEON_MEM_BASE 0x0f10 /* PCI */ +#define RADEON_MEM_CNTL 0x0140 +# define RADEON_MEM_NUM_CHANNELS_MASK 0x01 +# define RADEON_MEM_USE_B_CH_ONLY (1 << 1) +# define RV100_HALF_MODE (1 << 3) +# define R300_MEM_NUM_CHANNELS_MASK 0x03 +# define R300_MEM_USE_CD_CH_ONLY (1 << 2) +#define RADEON_MEM_TIMING_CNTL 0x0144 /* EXT_MEM_CNTL */ +#define RADEON_MEM_INIT_LAT_TIMER 0x0154 +#define RADEON_MEM_INTF_CNTL 0x014c +#define RADEON_MEM_SDRAM_MODE_REG 0x0158 +# define RADEON_SDRAM_MODE_MASK 0xffff0000 +# define RADEON_B3MEM_RESET_MASK 0x6fffffff +# define RADEON_MEM_CFG_TYPE_DDR (1 << 30) +#define RADEON_MEM_STR_CNTL 0x0150 +# define RADEON_MEM_PWRUP_COMPL_A (1 << 0) +# define RADEON_MEM_PWRUP_COMPL_B (1 << 1) +# define R300_MEM_PWRUP_COMPL_C (1 << 2) +# define R300_MEM_PWRUP_COMPL_D (1 << 3) +# define RADEON_MEM_PWRUP_COMPLETE 0x03 +# define R300_MEM_PWRUP_COMPLETE 0x0f +#define RADEON_MC_STATUS 0x0150 +# define RADEON_MC_IDLE (1 << 2) +# define R300_MC_IDLE (1 << 4) +#define RADEON_MEM_VGA_RP_SEL 0x003c +#define RADEON_MEM_VGA_WP_SEL 0x0038 +#define RADEON_MIN_GRANT 0x0f3e /* PCI */ +#define RADEON_MM_DATA 0x0004 +#define RADEON_MM_INDEX 0x0000 +#define RADEON_MPLL_CNTL 0x000e /* PLL */ +#define RADEON_MPP_TB_CONFIG 0x01c0 /* ? */ +#define RADEON_MPP_GP_CONFIG 0x01c8 /* ? */ +#define RADEON_SEPROM_CNTL1 0x01c0 +# define RADEON_SCK_PRESCALE_SHIFT 24 +# define RADEON_SCK_PRESCALE_MASK (0xff << 24) +#define R300_MC_IND_INDEX 0x01f8 +# define R300_MC_IND_ADDR_MASK 0x3f +# define R300_MC_IND_WR_EN (1 << 8) +#define R300_MC_IND_DATA 0x01fc +#define R300_MC_READ_CNTL_AB 0x017c +# define R300_MEM_RBS_POSITION_A_MASK 0x03 +#define R300_MC_READ_CNTL_CD_mcind 0x24 +# define R300_MEM_RBS_POSITION_C_MASK 0x03 + +#define RADEON_N_VIF_COUNT 0x0248 + +#define RADEON_OV0_AUTO_FLIP_CNTL 0x0470 +# define RADEON_OV0_AUTO_FLIP_CNTL_SOFT_BUF_NUM 0x00000007 +# define RADEON_OV0_AUTO_FLIP_CNTL_SOFT_REPEAT_FIELD 0x00000008 +# define RADEON_OV0_AUTO_FLIP_CNTL_SOFT_BUF_ODD 0x00000010 +# define RADEON_OV0_AUTO_FLIP_CNTL_IGNORE_REPEAT_FIELD 0x00000020 +# define RADEON_OV0_AUTO_FLIP_CNTL_SOFT_EOF_TOGGLE 0x00000040 +# define RADEON_OV0_AUTO_FLIP_CNTL_VID_PORT_SELECT 0x00000300 +# define RADEON_OV0_AUTO_FLIP_CNTL_P1_FIRST_LINE_EVEN 0x00010000 +# define RADEON_OV0_AUTO_FLIP_CNTL_SHIFT_EVEN_DOWN 0x00040000 +# define RADEON_OV0_AUTO_FLIP_CNTL_SHIFT_ODD_DOWN 0x00080000 +# define RADEON_OV0_AUTO_FLIP_CNTL_FIELD_POL_SOURCE 0x00800000 + +#define RADEON_OV0_COLOUR_CNTL 0x04E0 +#define RADEON_OV0_DEINTERLACE_PATTERN 0x0474 +#define RADEON_OV0_EXCLUSIVE_HORZ 0x0408 +# define RADEON_EXCL_HORZ_START_MASK 0x000000ff +# define RADEON_EXCL_HORZ_END_MASK 0x0000ff00 +# define RADEON_EXCL_HORZ_BACK_PORCH_MASK 0x00ff0000 +# define RADEON_EXCL_HORZ_EXCLUSIVE_EN 0x80000000 +#define RADEON_OV0_EXCLUSIVE_VERT 0x040C +# define RADEON_EXCL_VERT_START_MASK 0x000003ff +# define RADEON_EXCL_VERT_END_MASK 0x03ff0000 +#define RADEON_OV0_FILTER_CNTL 0x04A0 +# define RADEON_FILTER_PROGRAMMABLE_COEF 0x0 +# define RADEON_FILTER_HC_COEF_HORZ_Y 0x1 +# define RADEON_FILTER_HC_COEF_HORZ_UV 0x2 +# define RADEON_FILTER_HC_COEF_VERT_Y 0x4 +# define RADEON_FILTER_HC_COEF_VERT_UV 0x8 +# define RADEON_FILTER_HARDCODED_COEF 0xf +# define RADEON_FILTER_COEF_MASK 0xf + +#define RADEON_OV0_FOUR_TAP_COEF_0 0x04B0 +#define RADEON_OV0_FOUR_TAP_COEF_1 0x04B4 +#define RADEON_OV0_FOUR_TAP_COEF_2 0x04B8 +#define RADEON_OV0_FOUR_TAP_COEF_3 0x04BC +#define RADEON_OV0_FOUR_TAP_COEF_4 0x04C0 +#define RADEON_OV0_FLAG_CNTL 0x04DC +#define RADEON_OV0_GAMMA_000_00F 0x0d40 +#define RADEON_OV0_GAMMA_010_01F 0x0d44 +#define RADEON_OV0_GAMMA_020_03F 0x0d48 +#define RADEON_OV0_GAMMA_040_07F 0x0d4c +#define RADEON_OV0_GAMMA_080_0BF 0x0e00 +#define RADEON_OV0_GAMMA_0C0_0FF 0x0e04 +#define RADEON_OV0_GAMMA_100_13F 0x0e08 +#define RADEON_OV0_GAMMA_140_17F 0x0e0c +#define RADEON_OV0_GAMMA_180_1BF 0x0e10 +#define RADEON_OV0_GAMMA_1C0_1FF 0x0e14 +#define RADEON_OV0_GAMMA_200_23F 0x0e18 +#define RADEON_OV0_GAMMA_240_27F 0x0e1c +#define RADEON_OV0_GAMMA_280_2BF 0x0e20 +#define RADEON_OV0_GAMMA_2C0_2FF 0x0e24 +#define RADEON_OV0_GAMMA_300_33F 0x0e28 +#define RADEON_OV0_GAMMA_340_37F 0x0e2c +#define RADEON_OV0_GAMMA_380_3BF 0x0d50 +#define RADEON_OV0_GAMMA_3C0_3FF 0x0d54 +#define RADEON_OV0_GRAPHICS_KEY_CLR_LOW 0x04EC +#define RADEON_OV0_GRAPHICS_KEY_CLR_HIGH 0x04F0 +#define RADEON_OV0_H_INC 0x0480 +#define RADEON_OV0_KEY_CNTL 0x04F4 +# define RADEON_VIDEO_KEY_FN_MASK 0x00000003L +# define RADEON_VIDEO_KEY_FN_FALSE 0x00000000L +# define RADEON_VIDEO_KEY_FN_TRUE 0x00000001L +# define RADEON_VIDEO_KEY_FN_EQ 0x00000002L +# define RADEON_VIDEO_KEY_FN_NE 0x00000003L +# define RADEON_GRAPHIC_KEY_FN_MASK 0x00000030L +# define RADEON_GRAPHIC_KEY_FN_FALSE 0x00000000L +# define RADEON_GRAPHIC_KEY_FN_TRUE 0x00000010L +# define RADEON_GRAPHIC_KEY_FN_EQ 0x00000020L +# define RADEON_GRAPHIC_KEY_FN_NE 0x00000030L +# define RADEON_CMP_MIX_MASK 0x00000100L +# define RADEON_CMP_MIX_OR 0x00000000L +# define RADEON_CMP_MIX_AND 0x00000100L +#define RADEON_OV0_LIN_TRANS_A 0x0d20 +#define RADEON_OV0_LIN_TRANS_B 0x0d24 +#define RADEON_OV0_LIN_TRANS_C 0x0d28 +#define RADEON_OV0_LIN_TRANS_D 0x0d2c +#define RADEON_OV0_LIN_TRANS_E 0x0d30 +#define RADEON_OV0_LIN_TRANS_F 0x0d34 +#define RADEON_OV0_P1_BLANK_LINES_AT_TOP 0x0430 +# define RADEON_P1_BLNK_LN_AT_TOP_M1_MASK 0x00000fffL +# define RADEON_P1_ACTIVE_LINES_M1 0x0fff0000L +#define RADEON_OV0_P1_H_ACCUM_INIT 0x0488 +#define RADEON_OV0_P1_V_ACCUM_INIT 0x0428 +# define RADEON_OV0_P1_MAX_LN_IN_PER_LN_OUT 0x00000003L +# define RADEON_OV0_P1_V_ACCUM_INIT_MASK 0x01ff8000L +#define RADEON_OV0_P1_X_START_END 0x0494 +#define RADEON_OV0_P2_X_START_END 0x0498 +#define RADEON_OV0_P23_BLANK_LINES_AT_TOP 0x0434 +# define RADEON_P23_BLNK_LN_AT_TOP_M1_MASK 0x000007ffL +# define RADEON_P23_ACTIVE_LINES_M1 0x07ff0000L +#define RADEON_OV0_P23_H_ACCUM_INIT 0x048C +#define RADEON_OV0_P23_V_ACCUM_INIT 0x042C +#define RADEON_OV0_P3_X_START_END 0x049C +#define RADEON_OV0_REG_LOAD_CNTL 0x0410 +# define RADEON_REG_LD_CTL_LOCK 0x00000001L +# define RADEON_REG_LD_CTL_VBLANK_DURING_LOCK 0x00000002L +# define RADEON_REG_LD_CTL_STALL_GUI_UNTIL_FLIP 0x00000004L +# define RADEON_REG_LD_CTL_LOCK_READBACK 0x00000008L +# define RADEON_REG_LD_CTL_FLIP_READBACK 0x00000010L +#define RADEON_OV0_SCALE_CNTL 0x0420 +# define RADEON_SCALER_HORZ_PICK_NEAREST 0x00000004L +# define RADEON_SCALER_VERT_PICK_NEAREST 0x00000008L +# define RADEON_SCALER_SIGNED_UV 0x00000010L +# define RADEON_SCALER_GAMMA_SEL_MASK 0x00000060L +# define RADEON_SCALER_GAMMA_SEL_BRIGHT 0x00000000L +# define RADEON_SCALER_GAMMA_SEL_G22 0x00000020L +# define RADEON_SCALER_GAMMA_SEL_G18 0x00000040L +# define RADEON_SCALER_GAMMA_SEL_G14 0x00000060L +# define RADEON_SCALER_COMCORE_SHIFT_UP_ONE 0x00000080L +# define RADEON_SCALER_SURFAC_FORMAT 0x00000f00L +# define RADEON_SCALER_SOURCE_15BPP 0x00000300L +# define RADEON_SCALER_SOURCE_16BPP 0x00000400L +# define RADEON_SCALER_SOURCE_32BPP 0x00000600L +# define RADEON_SCALER_SOURCE_YUV9 0x00000900L +# define RADEON_SCALER_SOURCE_YUV12 0x00000A00L +# define RADEON_SCALER_SOURCE_VYUY422 0x00000B00L +# define RADEON_SCALER_SOURCE_YVYU422 0x00000C00L +# define RADEON_SCALER_ADAPTIVE_DEINT 0x00001000L +# define RADEON_SCALER_TEMPORAL_DEINT 0x00002000L +# define RADEON_SCALER_CRTC_SEL 0x00004000L +# define RADEON_SCALER_SMART_SWITCH 0x00008000L +# define RADEON_SCALER_BURST_PER_PLANE 0x007F0000L +# define RADEON_SCALER_DOUBLE_BUFFER 0x01000000L +# define RADEON_SCALER_DIS_LIMIT 0x08000000L +# define RADEON_SCALER_LIN_TRANS_BYPASS 0x10000000L +# define RADEON_SCALER_INT_EMU 0x20000000L +# define RADEON_SCALER_ENABLE 0x40000000L +# define RADEON_SCALER_SOFT_RESET 0x80000000L +#define RADEON_OV0_STEP_BY 0x0484 +#define RADEON_OV0_TEST 0x04F8 +#define RADEON_OV0_V_INC 0x0424 +#define RADEON_OV0_VID_BUF_PITCH0_VALUE 0x0460 +#define RADEON_OV0_VID_BUF_PITCH1_VALUE 0x0464 +#define RADEON_OV0_VID_BUF0_BASE_ADRS 0x0440 +# define RADEON_VIF_BUF0_PITCH_SEL 0x00000001L +# define RADEON_VIF_BUF0_TILE_ADRS 0x00000002L +# define RADEON_VIF_BUF0_BASE_ADRS_MASK 0x03fffff0L +# define RADEON_VIF_BUF0_1ST_LINE_LSBS_MASK 0x48000000L +#define RADEON_OV0_VID_BUF1_BASE_ADRS 0x0444 +# define RADEON_VIF_BUF1_PITCH_SEL 0x00000001L +# define RADEON_VIF_BUF1_TILE_ADRS 0x00000002L +# define RADEON_VIF_BUF1_BASE_ADRS_MASK 0x03fffff0L +# define RADEON_VIF_BUF1_1ST_LINE_LSBS_MASK 0x48000000L +#define RADEON_OV0_VID_BUF2_BASE_ADRS 0x0448 +# define RADEON_VIF_BUF2_PITCH_SEL 0x00000001L +# define RADEON_VIF_BUF2_TILE_ADRS 0x00000002L +# define RADEON_VIF_BUF2_BASE_ADRS_MASK 0x03fffff0L +# define RADEON_VIF_BUF2_1ST_LINE_LSBS_MASK 0x48000000L +#define RADEON_OV0_VID_BUF3_BASE_ADRS 0x044C +#define RADEON_OV0_VID_BUF4_BASE_ADRS 0x0450 +#define RADEON_OV0_VID_BUF5_BASE_ADRS 0x0454 +#define RADEON_OV0_VIDEO_KEY_CLR_HIGH 0x04E8 +#define RADEON_OV0_VIDEO_KEY_CLR_LOW 0x04E4 +#define RADEON_OV0_Y_X_START 0x0400 +#define RADEON_OV0_Y_X_END 0x0404 +#define RADEON_OV1_Y_X_START 0x0600 +#define RADEON_OV1_Y_X_END 0x0604 +#define RADEON_OVR_CLR 0x0230 +#define RADEON_OVR_WID_LEFT_RIGHT 0x0234 +#define RADEON_OVR_WID_TOP_BOTTOM 0x0238 + +/* first capture unit */ + +#define RADEON_CAP0_BUF0_OFFSET 0x0920 +#define RADEON_CAP0_BUF1_OFFSET 0x0924 +#define RADEON_CAP0_BUF0_EVEN_OFFSET 0x0928 +#define RADEON_CAP0_BUF1_EVEN_OFFSET 0x092C + +#define RADEON_CAP0_BUF_PITCH 0x0930 +#define RADEON_CAP0_V_WINDOW 0x0934 +#define RADEON_CAP0_H_WINDOW 0x0938 +#define RADEON_CAP0_VBI0_OFFSET 0x093C +#define RADEON_CAP0_VBI1_OFFSET 0x0940 +#define RADEON_CAP0_VBI_V_WINDOW 0x0944 +#define RADEON_CAP0_VBI_H_WINDOW 0x0948 +#define RADEON_CAP0_PORT_MODE_CNTL 0x094C +#define RADEON_CAP0_TRIG_CNTL 0x0950 +#define RADEON_CAP0_DEBUG 0x0954 +#define RADEON_CAP0_CONFIG 0x0958 +# define RADEON_CAP0_CONFIG_CONTINUOS 0x00000001 +# define RADEON_CAP0_CONFIG_START_FIELD_EVEN 0x00000002 +# define RADEON_CAP0_CONFIG_START_BUF_GET 0x00000004 +# define RADEON_CAP0_CONFIG_START_BUF_SET 0x00000008 +# define RADEON_CAP0_CONFIG_BUF_TYPE_ALT 0x00000010 +# define RADEON_CAP0_CONFIG_BUF_TYPE_FRAME 0x00000020 +# define RADEON_CAP0_CONFIG_ONESHOT_MODE_FRAME 0x00000040 +# define RADEON_CAP0_CONFIG_BUF_MODE_DOUBLE 0x00000080 +# define RADEON_CAP0_CONFIG_BUF_MODE_TRIPLE 0x00000100 +# define RADEON_CAP0_CONFIG_MIRROR_EN 0x00000200 +# define RADEON_CAP0_CONFIG_ONESHOT_MIRROR_EN 0x00000400 +# define RADEON_CAP0_CONFIG_VIDEO_SIGNED_UV 0x00000800 +# define RADEON_CAP0_CONFIG_ANC_DECODE_EN 0x00001000 +# define RADEON_CAP0_CONFIG_VBI_EN 0x00002000 +# define RADEON_CAP0_CONFIG_SOFT_PULL_DOWN_EN 0x00004000 +# define RADEON_CAP0_CONFIG_VIP_EXTEND_FLAG_EN 0x00008000 +# define RADEON_CAP0_CONFIG_FAKE_FIELD_EN 0x00010000 +# define RADEON_CAP0_CONFIG_ODD_ONE_MORE_LINE 0x00020000 +# define RADEON_CAP0_CONFIG_EVEN_ONE_MORE_LINE 0x00040000 +# define RADEON_CAP0_CONFIG_HORZ_DIVIDE_2 0x00080000 +# define RADEON_CAP0_CONFIG_HORZ_DIVIDE_4 0x00100000 +# define RADEON_CAP0_CONFIG_VERT_DIVIDE_2 0x00200000 +# define RADEON_CAP0_CONFIG_VERT_DIVIDE_4 0x00400000 +# define RADEON_CAP0_CONFIG_FORMAT_BROOKTREE 0x00000000 +# define RADEON_CAP0_CONFIG_FORMAT_CCIR656 0x00800000 +# define RADEON_CAP0_CONFIG_FORMAT_ZV 0x01000000 +# define RADEON_CAP0_CONFIG_FORMAT_VIP 0x01800000 +# define RADEON_CAP0_CONFIG_FORMAT_TRANSPORT 0x02000000 +# define RADEON_CAP0_CONFIG_HORZ_DECIMATOR 0x04000000 +# define RADEON_CAP0_CONFIG_VIDEO_IN_YVYU422 0x00000000 +# define RADEON_CAP0_CONFIG_VIDEO_IN_VYUY422 0x20000000 +# define RADEON_CAP0_CONFIG_VBI_DIVIDE_2 0x40000000 +# define RADEON_CAP0_CONFIG_VBI_DIVIDE_4 0x80000000 +#define RADEON_CAP0_ANC_ODD_OFFSET 0x095C +#define RADEON_CAP0_ANC_EVEN_OFFSET 0x0960 +#define RADEON_CAP0_ANC_H_WINDOW 0x0964 +#define RADEON_CAP0_VIDEO_SYNC_TEST 0x0968 +#define RADEON_CAP0_ONESHOT_BUF_OFFSET 0x096C +#define RADEON_CAP0_BUF_STATUS 0x0970 +/* #define RADEON_CAP0_DWNSC_XRATIO 0x0978 */ +/* #define RADEON_CAP0_XSHARPNESS 0x097C */ +#define RADEON_CAP0_VBI2_OFFSET 0x0980 +#define RADEON_CAP0_VBI3_OFFSET 0x0984 +#define RADEON_CAP0_ANC2_OFFSET 0x0988 +#define RADEON_CAP0_ANC3_OFFSET 0x098C +#define RADEON_VID_BUFFER_CONTROL 0x0900 + +/* second capture unit */ + +#define RADEON_CAP1_BUF0_OFFSET 0x0990 +#define RADEON_CAP1_BUF1_OFFSET 0x0994 +#define RADEON_CAP1_BUF0_EVEN_OFFSET 0x0998 +#define RADEON_CAP1_BUF1_EVEN_OFFSET 0x099C + +#define RADEON_CAP1_BUF_PITCH 0x09A0 +#define RADEON_CAP1_V_WINDOW 0x09A4 +#define RADEON_CAP1_H_WINDOW 0x09A8 +#define RADEON_CAP1_VBI_ODD_OFFSET 0x09AC +#define RADEON_CAP1_VBI_EVEN_OFFSET 0x09B0 +#define RADEON_CAP1_VBI_V_WINDOW 0x09B4 +#define RADEON_CAP1_VBI_H_WINDOW 0x09B8 +#define RADEON_CAP1_PORT_MODE_CNTL 0x09BC +#define RADEON_CAP1_TRIG_CNTL 0x09C0 +#define RADEON_CAP1_DEBUG 0x09C4 +#define RADEON_CAP1_CONFIG 0x09C8 +#define RADEON_CAP1_ANC_ODD_OFFSET 0x09CC +#define RADEON_CAP1_ANC_EVEN_OFFSET 0x09D0 +#define RADEON_CAP1_ANC_H_WINDOW 0x09D4 +#define RADEON_CAP1_VIDEO_SYNC_TEST 0x09D8 +#define RADEON_CAP1_ONESHOT_BUF_OFFSET 0x09DC +#define RADEON_CAP1_BUF_STATUS 0x09E0 +#define RADEON_CAP1_DWNSC_XRATIO 0x09E8 +#define RADEON_CAP1_XSHARPNESS 0x09EC + +/* misc multimedia registers */ + +#define RADEON_IDCT_RUNS 0x1F80 +#define RADEON_IDCT_LEVELS 0x1F84 +#define RADEON_IDCT_CONTROL 0x1FBC +#define RADEON_IDCT_AUTH_CONTROL 0x1F88 +#define RADEON_IDCT_AUTH 0x1F8C + +#define RADEON_P2PLL_CNTL 0x002a /* P2PLL */ +# define RADEON_P2PLL_RESET (1 << 0) +# define RADEON_P2PLL_SLEEP (1 << 1) +# define RADEON_P2PLL_PVG_MASK (7 << 11) +# define RADEON_P2PLL_PVG_SHIFT 11 +# define RADEON_P2PLL_ATOMIC_UPDATE_EN (1 << 16) +# define RADEON_P2PLL_VGA_ATOMIC_UPDATE_EN (1 << 17) +# define RADEON_P2PLL_ATOMIC_UPDATE_VSYNC (1 << 18) +#define RADEON_P2PLL_DIV_0 0x002c +# define RADEON_P2PLL_FB0_DIV_MASK 0x07ff +# define RADEON_P2PLL_POST0_DIV_MASK 0x00070000 +#define RADEON_P2PLL_REF_DIV 0x002B /* PLL */ +# define RADEON_P2PLL_REF_DIV_MASK 0x03ff +# define RADEON_P2PLL_ATOMIC_UPDATE_R (1 << 15) /* same as _W */ +# define RADEON_P2PLL_ATOMIC_UPDATE_W (1 << 15) /* same as _R */ +# define R300_PPLL_REF_DIV_ACC_MASK (0x3ff << 18) +# define R300_PPLL_REF_DIV_ACC_SHIFT 18 +#define RADEON_PALETTE_DATA 0x00b4 +#define RADEON_PALETTE_30_DATA 0x00b8 +#define RADEON_PALETTE_INDEX 0x00b0 +#define RADEON_PCI_GART_PAGE 0x017c +#define RADEON_PIXCLKS_CNTL 0x002d +# define RADEON_PIX2CLK_SRC_SEL_MASK 0x03 +# define RADEON_PIX2CLK_SRC_SEL_CPUCLK 0x00 +# define RADEON_PIX2CLK_SRC_SEL_PSCANCLK 0x01 +# define RADEON_PIX2CLK_SRC_SEL_BYTECLK 0x02 +# define RADEON_PIX2CLK_SRC_SEL_P2PLLCLK 0x03 +# define RADEON_PIX2CLK_ALWAYS_ONb (1<<6) +# define RADEON_PIX2CLK_DAC_ALWAYS_ONb (1<<7) +# define RADEON_PIXCLK_TV_SRC_SEL (1 << 8) +# define RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb (1 << 9) +# define R300_DVOCLK_ALWAYS_ONb (1 << 10) +# define RADEON_PIXCLK_BLEND_ALWAYS_ONb (1 << 11) +# define RADEON_PIXCLK_GV_ALWAYS_ONb (1 << 12) +# define RADEON_PIXCLK_DIG_TMDS_ALWAYS_ONb (1 << 13) +# define R300_PIXCLK_DVO_ALWAYS_ONb (1 << 13) +# define RADEON_PIXCLK_LVDS_ALWAYS_ONb (1 << 14) +# define RADEON_PIXCLK_TMDS_ALWAYS_ONb (1 << 15) +# define R300_PIXCLK_TRANS_ALWAYS_ONb (1 << 16) +# define R300_PIXCLK_TVO_ALWAYS_ONb (1 << 17) +# define R300_P2G2CLK_ALWAYS_ONb (1 << 18) +# define R300_P2G2CLK_DAC_ALWAYS_ONb (1 << 19) +# define R300_DISP_DAC_PIXCLK_DAC2_BLANK_OFF (1 << 23) +#define RADEON_PLANE_3D_MASK_C 0x1d44 +#define RADEON_PLL_TEST_CNTL 0x0013 /* PLL */ +# define RADEON_PLL_MASK_READ_B (1 << 9) +#define RADEON_PMI_CAP_ID 0x0f5c /* PCI */ +#define RADEON_PMI_DATA 0x0f63 /* PCI */ +#define RADEON_PMI_NXT_CAP_PTR 0x0f5d /* PCI */ +#define RADEON_PMI_PMC_REG 0x0f5e /* PCI */ +#define RADEON_PMI_PMCSR_REG 0x0f60 /* PCI */ +#define RADEON_PMI_REGISTER 0x0f5c /* PCI */ +#define RADEON_PPLL_CNTL 0x0002 /* PLL */ +# define RADEON_PPLL_RESET (1 << 0) +# define RADEON_PPLL_SLEEP (1 << 1) +# define RADEON_PPLL_PVG_MASK (7 << 11) +# define RADEON_PPLL_PVG_SHIFT 11 +# define RADEON_PPLL_ATOMIC_UPDATE_EN (1 << 16) +# define RADEON_PPLL_VGA_ATOMIC_UPDATE_EN (1 << 17) +# define RADEON_PPLL_ATOMIC_UPDATE_VSYNC (1 << 18) +#define RADEON_PPLL_DIV_0 0x0004 /* PLL */ +#define RADEON_PPLL_DIV_1 0x0005 /* PLL */ +#define RADEON_PPLL_DIV_2 0x0006 /* PLL */ +#define RADEON_PPLL_DIV_3 0x0007 /* PLL */ +# define RADEON_PPLL_FB3_DIV_MASK 0x07ff +# define RADEON_PPLL_POST3_DIV_MASK 0x00070000 +#define RADEON_PPLL_REF_DIV 0x0003 /* PLL */ +# define RADEON_PPLL_REF_DIV_MASK 0x03ff +# define RADEON_PPLL_ATOMIC_UPDATE_R (1 << 15) /* same as _W */ +# define RADEON_PPLL_ATOMIC_UPDATE_W (1 << 15) /* same as _R */ +#define RADEON_PWR_MNGMT_CNTL_STATUS 0x0f60 /* PCI */ + +#define RADEON_RBBM_GUICNTL 0x172c +# define RADEON_HOST_DATA_SWAP_NONE (0 << 0) +# define RADEON_HOST_DATA_SWAP_16BIT (1 << 0) +# define RADEON_HOST_DATA_SWAP_32BIT (2 << 0) +# define RADEON_HOST_DATA_SWAP_HDW (3 << 0) +#define RADEON_RBBM_SOFT_RESET 0x00f0 +# define RADEON_SOFT_RESET_CP (1 << 0) +# define RADEON_SOFT_RESET_HI (1 << 1) +# define RADEON_SOFT_RESET_SE (1 << 2) +# define RADEON_SOFT_RESET_RE (1 << 3) +# define RADEON_SOFT_RESET_PP (1 << 4) +# define RADEON_SOFT_RESET_E2 (1 << 5) +# define RADEON_SOFT_RESET_RB (1 << 6) +# define RADEON_SOFT_RESET_HDP (1 << 7) +#define RADEON_RBBM_STATUS 0x0e40 +# define RADEON_RBBM_FIFOCNT_MASK 0x007f +# define RADEON_RBBM_ACTIVE (1 << 31) +#define RADEON_RB2D_DSTCACHE_CTLSTAT 0x342c +# define RADEON_RB2D_DC_FLUSH (3 << 0) +# define RADEON_RB2D_DC_FREE (3 << 2) +# define RADEON_RB2D_DC_FLUSH_ALL 0xf +# define RADEON_RB2D_DC_BUSY (1 << 31) +#define RADEON_RB2D_DSTCACHE_MODE 0x3428 +#define RADEON_DSTCACHE_CTLSTAT 0x1714 + +#define RADEON_RB3D_ZCACHE_MODE 0x3250 +#define RADEON_RB3D_ZCACHE_CTLSTAT 0x3254 +# define RADEON_RB3D_ZC_FLUSH_ALL 0x5 +#define RADEON_RB3D_DSTCACHE_MODE 0x3258 +# define RADEON_RB3D_DC_CACHE_ENABLE (0) +# define RADEON_RB3D_DC_2D_CACHE_DISABLE (1) +# define RADEON_RB3D_DC_3D_CACHE_DISABLE (2) +# define RADEON_RB3D_DC_CACHE_DISABLE (3) +# define RADEON_RB3D_DC_2D_CACHE_LINESIZE_128 (1 << 2) +# define RADEON_RB3D_DC_3D_CACHE_LINESIZE_128 (2 << 2) +# define RADEON_RB3D_DC_2D_CACHE_AUTOFLUSH (1 << 8) +# define RADEON_RB3D_DC_3D_CACHE_AUTOFLUSH (2 << 8) +# define R200_RB3D_DC_2D_CACHE_AUTOFREE (1 << 10) +# define R200_RB3D_DC_3D_CACHE_AUTOFREE (2 << 10) +# define RADEON_RB3D_DC_FORCE_RMW (1 << 16) +# define RADEON_RB3D_DC_DISABLE_RI_FILL (1 << 24) +# define RADEON_RB3D_DC_DISABLE_RI_READ (1 << 25) + +#define RADEON_RB3D_DSTCACHE_CTLSTAT 0x325C +# define RADEON_RB3D_DC_FLUSH (3 << 0) +# define RADEON_RB3D_DC_FREE (3 << 2) +# define RADEON_RB3D_DC_FLUSH_ALL 0xf +# define RADEON_RB3D_DC_BUSY (1 << 31) + +#define RADEON_REG_BASE 0x0f18 /* PCI */ +#define RADEON_REGPROG_INF 0x0f09 /* PCI */ +#define RADEON_REVISION_ID 0x0f08 /* PCI */ + +#define RADEON_SC_BOTTOM 0x164c +#define RADEON_SC_BOTTOM_RIGHT 0x16f0 +#define RADEON_SC_BOTTOM_RIGHT_C 0x1c8c +#define RADEON_SC_LEFT 0x1640 +#define RADEON_SC_RIGHT 0x1644 +#define RADEON_SC_TOP 0x1648 +#define RADEON_SC_TOP_LEFT 0x16ec +#define RADEON_SC_TOP_LEFT_C 0x1c88 +# define RADEON_SC_SIGN_MASK_LO 0x8000 +# define RADEON_SC_SIGN_MASK_HI 0x80000000 +#define RADEON_SCLK_CNTL 0x000d /* PLL */ +# define RADEON_SCLK_SRC_SEL_MASK 0x0007 +# define RADEON_DYN_STOP_LAT_MASK 0x00007ff8 +# define RADEON_CP_MAX_DYN_STOP_LAT 0x0008 +# define RADEON_SCLK_FORCEON_MASK 0xffff8000 +# define RADEON_SCLK_FORCE_DISP2 (1<<15) +# define RADEON_SCLK_FORCE_CP (1<<16) +# define RADEON_SCLK_FORCE_HDP (1<<17) +# define RADEON_SCLK_FORCE_DISP1 (1<<18) +# define RADEON_SCLK_FORCE_TOP (1<<19) +# define RADEON_SCLK_FORCE_E2 (1<<20) +# define RADEON_SCLK_FORCE_SE (1<<21) +# define RADEON_SCLK_FORCE_IDCT (1<<22) +# define RADEON_SCLK_FORCE_VIP (1<<23) +# define RADEON_SCLK_FORCE_RE (1<<24) +# define RADEON_SCLK_FORCE_PB (1<<25) +# define RADEON_SCLK_FORCE_TAM (1<<26) +# define RADEON_SCLK_FORCE_TDM (1<<27) +# define RADEON_SCLK_FORCE_RB (1<<28) +# define RADEON_SCLK_FORCE_TV_SCLK (1<<29) +# define RADEON_SCLK_FORCE_SUBPIC (1<<30) +# define RADEON_SCLK_FORCE_OV0 (1<<31) +# define R300_SCLK_FORCE_VAP (1<<21) +# define R300_SCLK_FORCE_SR (1<<25) +# define R300_SCLK_FORCE_PX (1<<26) +# define R300_SCLK_FORCE_TX (1<<27) +# define R300_SCLK_FORCE_US (1<<28) +# define R300_SCLK_FORCE_SU (1<<30) +#define R300_SCLK_CNTL2 0x1e /* PLL */ +# define R300_SCLK_TCL_MAX_DYN_STOP_LAT (1<<10) +# define R300_SCLK_GA_MAX_DYN_STOP_LAT (1<<11) +# define R300_SCLK_CBA_MAX_DYN_STOP_LAT (1<<12) +# define R300_SCLK_FORCE_TCL (1<<13) +# define R300_SCLK_FORCE_CBA (1<<14) +# define R300_SCLK_FORCE_GA (1<<15) +#define RADEON_SCLK_MORE_CNTL 0x0035 /* PLL */ +# define RADEON_SCLK_MORE_MAX_DYN_STOP_LAT 0x0007 +# define RADEON_SCLK_MORE_FORCEON 0x0700 +#define RADEON_SDRAM_MODE_REG 0x0158 +#define RADEON_SEQ8_DATA 0x03c5 /* VGA */ +#define RADEON_SEQ8_IDX 0x03c4 /* VGA */ +#define RADEON_SNAPSHOT_F_COUNT 0x0244 +#define RADEON_SNAPSHOT_VH_COUNTS 0x0240 +#define RADEON_SNAPSHOT_VIF_COUNT 0x024c +#define RADEON_SRC_OFFSET 0x15ac +#define RADEON_SRC_PITCH 0x15b0 +#define RADEON_SRC_PITCH_OFFSET 0x1428 +#define RADEON_SRC_SC_BOTTOM 0x165c +#define RADEON_SRC_SC_BOTTOM_RIGHT 0x16f4 +#define RADEON_SRC_SC_RIGHT 0x1654 +#define RADEON_SRC_X 0x1414 +#define RADEON_SRC_X_Y 0x1590 +#define RADEON_SRC_Y 0x1418 +#define RADEON_SRC_Y_X 0x1434 +#define RADEON_STATUS 0x0f06 /* PCI */ +#define RADEON_SUBPIC_CNTL 0x0540 /* ? */ +#define RADEON_SUB_CLASS 0x0f0a /* PCI */ +#define RADEON_SURFACE_CNTL 0x0b00 +# define RADEON_SURF_TRANSLATION_DIS (1 << 8) +# define RADEON_NONSURF_AP0_SWP_16BPP (1 << 20) +# define RADEON_NONSURF_AP0_SWP_32BPP (1 << 21) +# define RADEON_NONSURF_AP1_SWP_16BPP (1 << 22) +# define RADEON_NONSURF_AP1_SWP_32BPP (1 << 23) +#define RADEON_SURFACE0_INFO 0x0b0c +# define RADEON_SURF_TILE_COLOR_MACRO (0 << 16) +# define RADEON_SURF_TILE_COLOR_BOTH (1 << 16) +# define RADEON_SURF_TILE_DEPTH_32BPP (2 << 16) +# define RADEON_SURF_TILE_DEPTH_16BPP (3 << 16) +# define R200_SURF_TILE_NONE (0 << 16) +# define R200_SURF_TILE_COLOR_MACRO (1 << 16) +# define R200_SURF_TILE_COLOR_MICRO (2 << 16) +# define R200_SURF_TILE_COLOR_BOTH (3 << 16) +# define R200_SURF_TILE_DEPTH_32BPP (4 << 16) +# define R200_SURF_TILE_DEPTH_16BPP (5 << 16) +# define R300_SURF_TILE_NONE (0 << 16) +# define R300_SURF_TILE_COLOR_MACRO (1 << 16) +# define R300_SURF_TILE_DEPTH_32BPP (2 << 16) +# define RADEON_SURF_AP0_SWP_16BPP (1 << 20) +# define RADEON_SURF_AP0_SWP_32BPP (1 << 21) +# define RADEON_SURF_AP1_SWP_16BPP (1 << 22) +# define RADEON_SURF_AP1_SWP_32BPP (1 << 23) +#define RADEON_SURFACE0_LOWER_BOUND 0x0b04 +#define RADEON_SURFACE0_UPPER_BOUND 0x0b08 +#define RADEON_SURFACE1_INFO 0x0b1c +#define RADEON_SURFACE1_LOWER_BOUND 0x0b14 +#define RADEON_SURFACE1_UPPER_BOUND 0x0b18 +#define RADEON_SURFACE2_INFO 0x0b2c +#define RADEON_SURFACE2_LOWER_BOUND 0x0b24 +#define RADEON_SURFACE2_UPPER_BOUND 0x0b28 +#define RADEON_SURFACE3_INFO 0x0b3c +#define RADEON_SURFACE3_LOWER_BOUND 0x0b34 +#define RADEON_SURFACE3_UPPER_BOUND 0x0b38 +#define RADEON_SURFACE4_INFO 0x0b4c +#define RADEON_SURFACE4_LOWER_BOUND 0x0b44 +#define RADEON_SURFACE4_UPPER_BOUND 0x0b48 +#define RADEON_SURFACE5_INFO 0x0b5c +#define RADEON_SURFACE5_LOWER_BOUND 0x0b54 +#define RADEON_SURFACE5_UPPER_BOUND 0x0b58 +#define RADEON_SURFACE6_INFO 0x0b6c +#define RADEON_SURFACE6_LOWER_BOUND 0x0b64 +#define RADEON_SURFACE6_UPPER_BOUND 0x0b68 +#define RADEON_SURFACE7_INFO 0x0b7c +#define RADEON_SURFACE7_LOWER_BOUND 0x0b74 +#define RADEON_SURFACE7_UPPER_BOUND 0x0b78 +#define RADEON_SW_SEMAPHORE 0x013c + +#define RADEON_TEST_DEBUG_CNTL 0x0120 +#define RADEON_TEST_DEBUG_CNTL__TEST_DEBUG_OUT_EN 0x00000001 + +#define RADEON_TEST_DEBUG_MUX 0x0124 +#define RADEON_TEST_DEBUG_OUT 0x012c +#define RADEON_TMDS_PLL_CNTL 0x02a8 +#define RADEON_TMDS_TRANSMITTER_CNTL 0x02a4 +# define RADEON_TMDS_TRANSMITTER_PLLEN 1 +# define RADEON_TMDS_TRANSMITTER_PLLRST 2 +#define RADEON_TRAIL_BRES_DEC 0x1614 +#define RADEON_TRAIL_BRES_ERR 0x160c +#define RADEON_TRAIL_BRES_INC 0x1610 +#define RADEON_TRAIL_X 0x1618 +#define RADEON_TRAIL_X_SUB 0x1620 + +#define RADEON_VCLK_ECP_CNTL 0x0008 /* PLL */ +# define RADEON_VCLK_SRC_SEL_MASK 0x03 +# define RADEON_VCLK_SRC_SEL_CPUCLK 0x00 +# define RADEON_VCLK_SRC_SEL_PSCANCLK 0x01 +# define RADEON_VCLK_SRC_SEL_BYTECLK 0x02 +# define RADEON_VCLK_SRC_SEL_PPLLCLK 0x03 +# define RADEON_PIXCLK_ALWAYS_ONb (1<<6) +# define RADEON_PIXCLK_DAC_ALWAYS_ONb (1<<7) +# define R300_DISP_DAC_PIXCLK_DAC_BLANK_OFF (1<<23) + +#define RADEON_VENDOR_ID 0x0f00 /* PCI */ +#define RADEON_VGA_DDA_CONFIG 0x02e8 +#define RADEON_VGA_DDA_ON_OFF 0x02ec +#define RADEON_VID_BUFFER_CONTROL 0x0900 +#define RADEON_VIDEOMUX_CNTL 0x0190 + + /* VIP bus */ +#define RADEON_VIPH_CH0_DATA 0x0c00 +#define RADEON_VIPH_CH1_DATA 0x0c04 +#define RADEON_VIPH_CH2_DATA 0x0c08 +#define RADEON_VIPH_CH3_DATA 0x0c0c +#define RADEON_VIPH_CH0_ADDR 0x0c10 +#define RADEON_VIPH_CH1_ADDR 0x0c14 +#define RADEON_VIPH_CH2_ADDR 0x0c18 +#define RADEON_VIPH_CH3_ADDR 0x0c1c +#define RADEON_VIPH_CH0_SBCNT 0x0c20 +#define RADEON_VIPH_CH1_SBCNT 0x0c24 +#define RADEON_VIPH_CH2_SBCNT 0x0c28 +#define RADEON_VIPH_CH3_SBCNT 0x0c2c +#define RADEON_VIPH_CH0_ABCNT 0x0c30 +#define RADEON_VIPH_CH1_ABCNT 0x0c34 +#define RADEON_VIPH_CH2_ABCNT 0x0c38 +#define RADEON_VIPH_CH3_ABCNT 0x0c3c +#define RADEON_VIPH_CONTROL 0x0c40 +# define RADEON_VIP_BUSY 0 +# define RADEON_VIP_IDLE 1 +# define RADEON_VIP_RESET 2 +# define RADEON_VIPH_EN (1 << 21) +#define RADEON_VIPH_DV_LAT 0x0c44 +#define RADEON_VIPH_BM_CHUNK 0x0c48 +#define RADEON_VIPH_DV_INT 0x0c4c +#define RADEON_VIPH_TIMEOUT_STAT 0x0c50 +#define RADEON_VIPH_TIMEOUT_STAT__VIPH_REG_STAT 0x00000010 +#define RADEON_VIPH_TIMEOUT_STAT__VIPH_REG_AK 0x00000010 +#define RADEON_VIPH_TIMEOUT_STAT__VIPH_REGR_DIS 0x01000000 + +#define RADEON_VIPH_REG_DATA 0x0084 +#define RADEON_VIPH_REG_ADDR 0x0080 + + +#define RADEON_WAIT_UNTIL 0x1720 +# define RADEON_WAIT_CRTC_PFLIP (1 << 0) +# define RADEON_WAIT_RE_CRTC_VLINE (1 << 1) +# define RADEON_WAIT_FE_CRTC_VLINE (1 << 2) +# define RADEON_WAIT_CRTC_VLINE (1 << 3) +# define RADEON_WAIT_DMA_VID_IDLE (1 << 8) +# define RADEON_WAIT_DMA_GUI_IDLE (1 << 9) +# define RADEON_WAIT_CMDFIFO (1 << 10) /* wait for CMDFIFO_ENTRIES */ +# define RADEON_WAIT_OV0_FLIP (1 << 11) +# define RADEON_WAIT_AGP_FLUSH (1 << 13) +# define RADEON_WAIT_2D_IDLE (1 << 14) +# define RADEON_WAIT_3D_IDLE (1 << 15) +# define RADEON_WAIT_2D_IDLECLEAN (1 << 16) +# define RADEON_WAIT_3D_IDLECLEAN (1 << 17) +# define RADEON_WAIT_HOST_IDLECLEAN (1 << 18) +# define RADEON_CMDFIFO_ENTRIES_SHIFT 10 +# define RADEON_CMDFIFO_ENTRIES_MASK 0x7f +# define RADEON_WAIT_VAP_IDLE (1 << 28) +# define RADEON_WAIT_BOTH_CRTC_PFLIP (1 << 30) +# define RADEON_ENG_DISPLAY_SELECT_CRTC0 (0 << 31) +# define RADEON_ENG_DISPLAY_SELECT_CRTC1 (1 << 31) + +#define RADEON_X_MPLL_REF_FB_DIV 0x000a /* PLL */ +#define RADEON_XCLK_CNTL 0x000d /* PLL */ +#define RADEON_XDLL_CNTL 0x000c /* PLL */ +#define RADEON_XPLL_CNTL 0x000b /* PLL */ + + + + /* Registers for 3D/TCL */ +#define RADEON_PP_BORDER_COLOR_0 0x1d40 +#define RADEON_PP_BORDER_COLOR_1 0x1d44 +#define RADEON_PP_BORDER_COLOR_2 0x1d48 +#define RADEON_PP_CNTL 0x1c38 +# define RADEON_STIPPLE_ENABLE (1 << 0) +# define RADEON_SCISSOR_ENABLE (1 << 1) +# define RADEON_PATTERN_ENABLE (1 << 2) +# define RADEON_SHADOW_ENABLE (1 << 3) +# define RADEON_TEX_ENABLE_MASK (0xf << 4) +# define RADEON_TEX_0_ENABLE (1 << 4) +# define RADEON_TEX_1_ENABLE (1 << 5) +# define RADEON_TEX_2_ENABLE (1 << 6) +# define RADEON_TEX_3_ENABLE (1 << 7) +# define RADEON_TEX_BLEND_ENABLE_MASK (0xf << 12) +# define RADEON_TEX_BLEND_0_ENABLE (1 << 12) +# define RADEON_TEX_BLEND_1_ENABLE (1 << 13) +# define RADEON_TEX_BLEND_2_ENABLE (1 << 14) +# define RADEON_TEX_BLEND_3_ENABLE (1 << 15) +# define RADEON_PLANAR_YUV_ENABLE (1 << 20) +# define RADEON_SPECULAR_ENABLE (1 << 21) +# define RADEON_FOG_ENABLE (1 << 22) +# define RADEON_ALPHA_TEST_ENABLE (1 << 23) +# define RADEON_ANTI_ALIAS_NONE (0 << 24) +# define RADEON_ANTI_ALIAS_LINE (1 << 24) +# define RADEON_ANTI_ALIAS_POLY (2 << 24) +# define RADEON_ANTI_ALIAS_LINE_POLY (3 << 24) +# define RADEON_BUMP_MAP_ENABLE (1 << 26) +# define RADEON_BUMPED_MAP_T0 (0 << 27) +# define RADEON_BUMPED_MAP_T1 (1 << 27) +# define RADEON_BUMPED_MAP_T2 (2 << 27) +# define RADEON_TEX_3D_ENABLE_0 (1 << 29) +# define RADEON_TEX_3D_ENABLE_1 (1 << 30) +# define RADEON_MC_ENABLE (1 << 31) +#define RADEON_PP_FOG_COLOR 0x1c18 +# define RADEON_FOG_COLOR_MASK 0x00ffffff +# define RADEON_FOG_VERTEX (0 << 24) +# define RADEON_FOG_TABLE (1 << 24) +# define RADEON_FOG_USE_DEPTH (0 << 25) +# define RADEON_FOG_USE_DIFFUSE_ALPHA (2 << 25) +# define RADEON_FOG_USE_SPEC_ALPHA (3 << 25) +#define RADEON_PP_LUM_MATRIX 0x1d00 +#define RADEON_PP_MISC 0x1c14 +# define RADEON_REF_ALPHA_MASK 0x000000ff +# define RADEON_ALPHA_TEST_FAIL (0 << 8) +# define RADEON_ALPHA_TEST_LESS (1 << 8) +# define RADEON_ALPHA_TEST_LEQUAL (2 << 8) +# define RADEON_ALPHA_TEST_EQUAL (3 << 8) +# define RADEON_ALPHA_TEST_GEQUAL (4 << 8) +# define RADEON_ALPHA_TEST_GREATER (5 << 8) +# define RADEON_ALPHA_TEST_NEQUAL (6 << 8) +# define RADEON_ALPHA_TEST_PASS (7 << 8) +# define RADEON_ALPHA_TEST_OP_MASK (7 << 8) +# define RADEON_CHROMA_FUNC_FAIL (0 << 16) +# define RADEON_CHROMA_FUNC_PASS (1 << 16) +# define RADEON_CHROMA_FUNC_NEQUAL (2 << 16) +# define RADEON_CHROMA_FUNC_EQUAL (3 << 16) +# define RADEON_CHROMA_KEY_NEAREST (0 << 18) +# define RADEON_CHROMA_KEY_ZERO (1 << 18) +# define RADEON_SHADOW_ID_AUTO_INC (1 << 20) +# define RADEON_SHADOW_FUNC_EQUAL (0 << 21) +# define RADEON_SHADOW_FUNC_NEQUAL (1 << 21) +# define RADEON_SHADOW_PASS_1 (0 << 22) +# define RADEON_SHADOW_PASS_2 (1 << 22) +# define RADEON_RIGHT_HAND_CUBE_D3D (0 << 24) +# define RADEON_RIGHT_HAND_CUBE_OGL (1 << 24) +#define RADEON_PP_ROT_MATRIX_0 0x1d58 +#define RADEON_PP_ROT_MATRIX_1 0x1d5c +#define RADEON_PP_TXFILTER_0 0x1c54 +#define RADEON_PP_TXFILTER_1 0x1c6c +#define RADEON_PP_TXFILTER_2 0x1c84 +# define RADEON_MAG_FILTER_NEAREST (0 << 0) +# define RADEON_MAG_FILTER_LINEAR (1 << 0) +# define RADEON_MAG_FILTER_MASK (1 << 0) +# define RADEON_MIN_FILTER_NEAREST (0 << 1) +# define RADEON_MIN_FILTER_LINEAR (1 << 1) +# define RADEON_MIN_FILTER_NEAREST_MIP_NEAREST (2 << 1) +# define RADEON_MIN_FILTER_NEAREST_MIP_LINEAR (3 << 1) +# define RADEON_MIN_FILTER_LINEAR_MIP_NEAREST (6 << 1) +# define RADEON_MIN_FILTER_LINEAR_MIP_LINEAR (7 << 1) +# define RADEON_MIN_FILTER_ANISO_NEAREST (8 << 1) +# define RADEON_MIN_FILTER_ANISO_LINEAR (9 << 1) +# define RADEON_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST (10 << 1) +# define RADEON_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR (11 << 1) +# define RADEON_MIN_FILTER_MASK (15 << 1) +# define RADEON_MAX_ANISO_1_TO_1 (0 << 5) +# define RADEON_MAX_ANISO_2_TO_1 (1 << 5) +# define RADEON_MAX_ANISO_4_TO_1 (2 << 5) +# define RADEON_MAX_ANISO_8_TO_1 (3 << 5) +# define RADEON_MAX_ANISO_16_TO_1 (4 << 5) +# define RADEON_MAX_ANISO_MASK (7 << 5) +# define RADEON_LOD_BIAS_MASK (0xff << 8) +# define RADEON_LOD_BIAS_SHIFT 8 +# define RADEON_MAX_MIP_LEVEL_MASK (0x0f << 16) +# define RADEON_MAX_MIP_LEVEL_SHIFT 16 +# define RADEON_YUV_TO_RGB (1 << 20) +# define RADEON_YUV_TEMPERATURE_COOL (0 << 21) +# define RADEON_YUV_TEMPERATURE_HOT (1 << 21) +# define RADEON_YUV_TEMPERATURE_MASK (1 << 21) +# define RADEON_WRAPEN_S (1 << 22) +# define RADEON_CLAMP_S_WRAP (0 << 23) +# define RADEON_CLAMP_S_MIRROR (1 << 23) +# define RADEON_CLAMP_S_CLAMP_LAST (2 << 23) +# define RADEON_CLAMP_S_MIRROR_CLAMP_LAST (3 << 23) +# define RADEON_CLAMP_S_CLAMP_BORDER (4 << 23) +# define RADEON_CLAMP_S_MIRROR_CLAMP_BORDER (5 << 23) +# define RADEON_CLAMP_S_CLAMP_GL (6 << 23) +# define RADEON_CLAMP_S_MIRROR_CLAMP_GL (7 << 23) +# define RADEON_CLAMP_S_MASK (7 << 23) +# define RADEON_WRAPEN_T (1 << 26) +# define RADEON_CLAMP_T_WRAP (0 << 27) +# define RADEON_CLAMP_T_MIRROR (1 << 27) +# define RADEON_CLAMP_T_CLAMP_LAST (2 << 27) +# define RADEON_CLAMP_T_MIRROR_CLAMP_LAST (3 << 27) +# define RADEON_CLAMP_T_CLAMP_BORDER (4 << 27) +# define RADEON_CLAMP_T_MIRROR_CLAMP_BORDER (5 << 27) +# define RADEON_CLAMP_T_CLAMP_GL (6 << 27) +# define RADEON_CLAMP_T_MIRROR_CLAMP_GL (7 << 27) +# define RADEON_CLAMP_T_MASK (7 << 27) +# define RADEON_BORDER_MODE_OGL (0 << 31) +# define RADEON_BORDER_MODE_D3D (1 << 31) +#define RADEON_PP_TXFORMAT_0 0x1c58 +#define RADEON_PP_TXFORMAT_1 0x1c70 +#define RADEON_PP_TXFORMAT_2 0x1c88 +# define RADEON_TXFORMAT_I8 (0 << 0) +# define RADEON_TXFORMAT_AI88 (1 << 0) +# define RADEON_TXFORMAT_RGB332 (2 << 0) +# define RADEON_TXFORMAT_ARGB1555 (3 << 0) +# define RADEON_TXFORMAT_RGB565 (4 << 0) +# define RADEON_TXFORMAT_ARGB4444 (5 << 0) +# define RADEON_TXFORMAT_ARGB8888 (6 << 0) +# define RADEON_TXFORMAT_RGBA8888 (7 << 0) +# define RADEON_TXFORMAT_Y8 (8 << 0) +# define RADEON_TXFORMAT_VYUY422 (10 << 0) +# define RADEON_TXFORMAT_YVYU422 (11 << 0) +# define RADEON_TXFORMAT_DXT1 (12 << 0) +# define RADEON_TXFORMAT_DXT23 (14 << 0) +# define RADEON_TXFORMAT_DXT45 (15 << 0) +# define RADEON_TXFORMAT_FORMAT_MASK (31 << 0) +# define RADEON_TXFORMAT_FORMAT_SHIFT 0 +# define RADEON_TXFORMAT_APPLE_YUV_MODE (1 << 5) +# define RADEON_TXFORMAT_ALPHA_IN_MAP (1 << 6) +# define RADEON_TXFORMAT_NON_POWER2 (1 << 7) +# define RADEON_TXFORMAT_WIDTH_MASK (15 << 8) +# define RADEON_TXFORMAT_WIDTH_SHIFT 8 +# define RADEON_TXFORMAT_HEIGHT_MASK (15 << 12) +# define RADEON_TXFORMAT_HEIGHT_SHIFT 12 +# define RADEON_TXFORMAT_F5_WIDTH_MASK (15 << 16) +# define RADEON_TXFORMAT_F5_WIDTH_SHIFT 16 +# define RADEON_TXFORMAT_F5_HEIGHT_MASK (15 << 20) +# define RADEON_TXFORMAT_F5_HEIGHT_SHIFT 20 +# define RADEON_TXFORMAT_ST_ROUTE_STQ0 (0 << 24) +# define RADEON_TXFORMAT_ST_ROUTE_MASK (3 << 24) +# define RADEON_TXFORMAT_ST_ROUTE_STQ1 (1 << 24) +# define RADEON_TXFORMAT_ST_ROUTE_STQ2 (2 << 24) +# define RADEON_TXFORMAT_ENDIAN_NO_SWAP (0 << 26) +# define RADEON_TXFORMAT_ENDIAN_16BPP_SWAP (1 << 26) +# define RADEON_TXFORMAT_ENDIAN_32BPP_SWAP (2 << 26) +# define RADEON_TXFORMAT_ENDIAN_HALFDW_SWAP (3 << 26) +# define RADEON_TXFORMAT_ALPHA_MASK_ENABLE (1 << 28) +# define RADEON_TXFORMAT_CHROMA_KEY_ENABLE (1 << 29) +# define RADEON_TXFORMAT_CUBIC_MAP_ENABLE (1 << 30) +# define RADEON_TXFORMAT_PERSPECTIVE_ENABLE (1 << 31) +#define RADEON_PP_CUBIC_FACES_0 0x1d24 +#define RADEON_PP_CUBIC_FACES_1 0x1d28 +#define RADEON_PP_CUBIC_FACES_2 0x1d2c +# define RADEON_FACE_WIDTH_1_SHIFT 0 +# define RADEON_FACE_HEIGHT_1_SHIFT 4 +# define RADEON_FACE_WIDTH_1_MASK (0xf << 0) +# define RADEON_FACE_HEIGHT_1_MASK (0xf << 4) +# define RADEON_FACE_WIDTH_2_SHIFT 8 +# define RADEON_FACE_HEIGHT_2_SHIFT 12 +# define RADEON_FACE_WIDTH_2_MASK (0xf << 8) +# define RADEON_FACE_HEIGHT_2_MASK (0xf << 12) +# define RADEON_FACE_WIDTH_3_SHIFT 16 +# define RADEON_FACE_HEIGHT_3_SHIFT 20 +# define RADEON_FACE_WIDTH_3_MASK (0xf << 16) +# define RADEON_FACE_HEIGHT_3_MASK (0xf << 20) +# define RADEON_FACE_WIDTH_4_SHIFT 24 +# define RADEON_FACE_HEIGHT_4_SHIFT 28 +# define RADEON_FACE_WIDTH_4_MASK (0xf << 24) +# define RADEON_FACE_HEIGHT_4_MASK (0xf << 28) + +#define RADEON_PP_TXOFFSET_0 0x1c5c +#define RADEON_PP_TXOFFSET_1 0x1c74 +#define RADEON_PP_TXOFFSET_2 0x1c8c +# define RADEON_TXO_ENDIAN_NO_SWAP (0 << 0) +# define RADEON_TXO_ENDIAN_BYTE_SWAP (1 << 0) +# define RADEON_TXO_ENDIAN_WORD_SWAP (2 << 0) +# define RADEON_TXO_ENDIAN_HALFDW_SWAP (3 << 0) +# define RADEON_TXO_MACRO_LINEAR (0 << 2) +# define RADEON_TXO_MACRO_TILE (1 << 2) +# define RADEON_TXO_MICRO_LINEAR (0 << 3) +# define RADEON_TXO_MICRO_TILE_X2 (1 << 3) +# define RADEON_TXO_MICRO_TILE_OPT (2 << 3) +# define RADEON_TXO_OFFSET_MASK 0xffffffe0 +# define RADEON_TXO_OFFSET_SHIFT 5 + +#define RADEON_PP_CUBIC_OFFSET_T0_0 0x1dd0 /* bits [31:5] */ +#define RADEON_PP_CUBIC_OFFSET_T0_1 0x1dd4 +#define RADEON_PP_CUBIC_OFFSET_T0_2 0x1dd8 +#define RADEON_PP_CUBIC_OFFSET_T0_3 0x1ddc +#define RADEON_PP_CUBIC_OFFSET_T0_4 0x1de0 +#define RADEON_PP_CUBIC_OFFSET_T1_0 0x1e00 +#define RADEON_PP_CUBIC_OFFSET_T1_1 0x1e04 +#define RADEON_PP_CUBIC_OFFSET_T1_2 0x1e08 +#define RADEON_PP_CUBIC_OFFSET_T1_3 0x1e0c +#define RADEON_PP_CUBIC_OFFSET_T1_4 0x1e10 +#define RADEON_PP_CUBIC_OFFSET_T2_0 0x1e14 +#define RADEON_PP_CUBIC_OFFSET_T2_1 0x1e18 +#define RADEON_PP_CUBIC_OFFSET_T2_2 0x1e1c +#define RADEON_PP_CUBIC_OFFSET_T2_3 0x1e20 +#define RADEON_PP_CUBIC_OFFSET_T2_4 0x1e24 + +#define RADEON_PP_TEX_SIZE_0 0x1d04 /* NPOT */ +#define RADEON_PP_TEX_SIZE_1 0x1d0c +#define RADEON_PP_TEX_SIZE_2 0x1d14 +# define RADEON_TEX_USIZE_MASK (0x7ff << 0) +# define RADEON_TEX_USIZE_SHIFT 0 +# define RADEON_TEX_VSIZE_MASK (0x7ff << 16) +# define RADEON_TEX_VSIZE_SHIFT 16 +# define RADEON_SIGNED_RGB_MASK (1 << 30) +# define RADEON_SIGNED_RGB_SHIFT 30 +# define RADEON_SIGNED_ALPHA_MASK (1 << 31) +# define RADEON_SIGNED_ALPHA_SHIFT 31 +#define RADEON_PP_TEX_PITCH_0 0x1d08 /* NPOT */ +#define RADEON_PP_TEX_PITCH_1 0x1d10 /* NPOT */ +#define RADEON_PP_TEX_PITCH_2 0x1d18 /* NPOT */ +/* note: bits 13-5: 32 byte aligned stride of texture map */ + +#define RADEON_PP_TXCBLEND_0 0x1c60 +#define RADEON_PP_TXCBLEND_1 0x1c78 +#define RADEON_PP_TXCBLEND_2 0x1c90 +# define RADEON_COLOR_ARG_A_SHIFT 0 +# define RADEON_COLOR_ARG_A_MASK (0x1f << 0) +# define RADEON_COLOR_ARG_A_ZERO (0 << 0) +# define RADEON_COLOR_ARG_A_CURRENT_COLOR (2 << 0) +# define RADEON_COLOR_ARG_A_CURRENT_ALPHA (3 << 0) +# define RADEON_COLOR_ARG_A_DIFFUSE_COLOR (4 << 0) +# define RADEON_COLOR_ARG_A_DIFFUSE_ALPHA (5 << 0) +# define RADEON_COLOR_ARG_A_SPECULAR_COLOR (6 << 0) +# define RADEON_COLOR_ARG_A_SPECULAR_ALPHA (7 << 0) +# define RADEON_COLOR_ARG_A_TFACTOR_COLOR (8 << 0) +# define RADEON_COLOR_ARG_A_TFACTOR_ALPHA (9 << 0) +# define RADEON_COLOR_ARG_A_T0_COLOR (10 << 0) +# define RADEON_COLOR_ARG_A_T0_ALPHA (11 << 0) +# define RADEON_COLOR_ARG_A_T1_COLOR (12 << 0) +# define RADEON_COLOR_ARG_A_T1_ALPHA (13 << 0) +# define RADEON_COLOR_ARG_A_T2_COLOR (14 << 0) +# define RADEON_COLOR_ARG_A_T2_ALPHA (15 << 0) +# define RADEON_COLOR_ARG_A_T3_COLOR (16 << 0) +# define RADEON_COLOR_ARG_A_T3_ALPHA (17 << 0) +# define RADEON_COLOR_ARG_B_SHIFT 5 +# define RADEON_COLOR_ARG_B_MASK (0x1f << 5) +# define RADEON_COLOR_ARG_B_ZERO (0 << 5) +# define RADEON_COLOR_ARG_B_CURRENT_COLOR (2 << 5) +# define RADEON_COLOR_ARG_B_CURRENT_ALPHA (3 << 5) +# define RADEON_COLOR_ARG_B_DIFFUSE_COLOR (4 << 5) +# define RADEON_COLOR_ARG_B_DIFFUSE_ALPHA (5 << 5) +# define RADEON_COLOR_ARG_B_SPECULAR_COLOR (6 << 5) +# define RADEON_COLOR_ARG_B_SPECULAR_ALPHA (7 << 5) +# define RADEON_COLOR_ARG_B_TFACTOR_COLOR (8 << 5) +# define RADEON_COLOR_ARG_B_TFACTOR_ALPHA (9 << 5) +# define RADEON_COLOR_ARG_B_T0_COLOR (10 << 5) +# define RADEON_COLOR_ARG_B_T0_ALPHA (11 << 5) +# define RADEON_COLOR_ARG_B_T1_COLOR (12 << 5) +# define RADEON_COLOR_ARG_B_T1_ALPHA (13 << 5) +# define RADEON_COLOR_ARG_B_T2_COLOR (14 << 5) +# define RADEON_COLOR_ARG_B_T2_ALPHA (15 << 5) +# define RADEON_COLOR_ARG_B_T3_COLOR (16 << 5) +# define RADEON_COLOR_ARG_B_T3_ALPHA (17 << 5) +# define RADEON_COLOR_ARG_C_SHIFT 10 +# define RADEON_COLOR_ARG_C_MASK (0x1f << 10) +# define RADEON_COLOR_ARG_C_ZERO (0 << 10) +# define RADEON_COLOR_ARG_C_CURRENT_COLOR (2 << 10) +# define RADEON_COLOR_ARG_C_CURRENT_ALPHA (3 << 10) +# define RADEON_COLOR_ARG_C_DIFFUSE_COLOR (4 << 10) +# define RADEON_COLOR_ARG_C_DIFFUSE_ALPHA (5 << 10) +# define RADEON_COLOR_ARG_C_SPECULAR_COLOR (6 << 10) +# define RADEON_COLOR_ARG_C_SPECULAR_ALPHA (7 << 10) +# define RADEON_COLOR_ARG_C_TFACTOR_COLOR (8 << 10) +# define RADEON_COLOR_ARG_C_TFACTOR_ALPHA (9 << 10) +# define RADEON_COLOR_ARG_C_T0_COLOR (10 << 10) +# define RADEON_COLOR_ARG_C_T0_ALPHA (11 << 10) +# define RADEON_COLOR_ARG_C_T1_COLOR (12 << 10) +# define RADEON_COLOR_ARG_C_T1_ALPHA (13 << 10) +# define RADEON_COLOR_ARG_C_T2_COLOR (14 << 10) +# define RADEON_COLOR_ARG_C_T2_ALPHA (15 << 10) +# define RADEON_COLOR_ARG_C_T3_COLOR (16 << 10) +# define RADEON_COLOR_ARG_C_T3_ALPHA (17 << 10) +# define RADEON_COMP_ARG_A (1 << 15) +# define RADEON_COMP_ARG_A_SHIFT 15 +# define RADEON_COMP_ARG_B (1 << 16) +# define RADEON_COMP_ARG_B_SHIFT 16 +# define RADEON_COMP_ARG_C (1 << 17) +# define RADEON_COMP_ARG_C_SHIFT 17 +# define RADEON_BLEND_CTL_MASK (7 << 18) +# define RADEON_BLEND_CTL_ADD (0 << 18) +# define RADEON_BLEND_CTL_SUBTRACT (1 << 18) +# define RADEON_BLEND_CTL_ADDSIGNED (2 << 18) +# define RADEON_BLEND_CTL_BLEND (3 << 18) +# define RADEON_BLEND_CTL_DOT3 (4 << 18) +# define RADEON_SCALE_SHIFT 21 +# define RADEON_SCALE_MASK (3 << 21) +# define RADEON_SCALE_1X (0 << 21) +# define RADEON_SCALE_2X (1 << 21) +# define RADEON_SCALE_4X (2 << 21) +# define RADEON_CLAMP_TX (1 << 23) +# define RADEON_T0_EQ_TCUR (1 << 24) +# define RADEON_T1_EQ_TCUR (1 << 25) +# define RADEON_T2_EQ_TCUR (1 << 26) +# define RADEON_T3_EQ_TCUR (1 << 27) +# define RADEON_COLOR_ARG_MASK 0x1f +# define RADEON_COMP_ARG_SHIFT 15 +#define RADEON_PP_TXABLEND_0 0x1c64 +#define RADEON_PP_TXABLEND_1 0x1c7c +#define RADEON_PP_TXABLEND_2 0x1c94 +# define RADEON_ALPHA_ARG_A_SHIFT 0 +# define RADEON_ALPHA_ARG_A_MASK (0xf << 0) +# define RADEON_ALPHA_ARG_A_ZERO (0 << 0) +# define RADEON_ALPHA_ARG_A_CURRENT_ALPHA (1 << 0) +# define RADEON_ALPHA_ARG_A_DIFFUSE_ALPHA (2 << 0) +# define RADEON_ALPHA_ARG_A_SPECULAR_ALPHA (3 << 0) +# define RADEON_ALPHA_ARG_A_TFACTOR_ALPHA (4 << 0) +# define RADEON_ALPHA_ARG_A_T0_ALPHA (5 << 0) +# define RADEON_ALPHA_ARG_A_T1_ALPHA (6 << 0) +# define RADEON_ALPHA_ARG_A_T2_ALPHA (7 << 0) +# define RADEON_ALPHA_ARG_A_T3_ALPHA (8 << 0) +# define RADEON_ALPHA_ARG_B_SHIFT 4 +# define RADEON_ALPHA_ARG_B_MASK (0xf << 4) +# define RADEON_ALPHA_ARG_B_ZERO (0 << 4) +# define RADEON_ALPHA_ARG_B_CURRENT_ALPHA (1 << 4) +# define RADEON_ALPHA_ARG_B_DIFFUSE_ALPHA (2 << 4) +# define RADEON_ALPHA_ARG_B_SPECULAR_ALPHA (3 << 4) +# define RADEON_ALPHA_ARG_B_TFACTOR_ALPHA (4 << 4) +# define RADEON_ALPHA_ARG_B_T0_ALPHA (5 << 4) +# define RADEON_ALPHA_ARG_B_T1_ALPHA (6 << 4) +# define RADEON_ALPHA_ARG_B_T2_ALPHA (7 << 4) +# define RADEON_ALPHA_ARG_B_T3_ALPHA (8 << 4) +# define RADEON_ALPHA_ARG_C_SHIFT 8 +# define RADEON_ALPHA_ARG_C_MASK (0xf << 8) +# define RADEON_ALPHA_ARG_C_ZERO (0 << 8) +# define RADEON_ALPHA_ARG_C_CURRENT_ALPHA (1 << 8) +# define RADEON_ALPHA_ARG_C_DIFFUSE_ALPHA (2 << 8) +# define RADEON_ALPHA_ARG_C_SPECULAR_ALPHA (3 << 8) +# define RADEON_ALPHA_ARG_C_TFACTOR_ALPHA (4 << 8) +# define RADEON_ALPHA_ARG_C_T0_ALPHA (5 << 8) +# define RADEON_ALPHA_ARG_C_T1_ALPHA (6 << 8) +# define RADEON_ALPHA_ARG_C_T2_ALPHA (7 << 8) +# define RADEON_ALPHA_ARG_C_T3_ALPHA (8 << 8) +# define RADEON_DOT_ALPHA_DONT_REPLICATE (1 << 9) +# define RADEON_ALPHA_ARG_MASK 0xf + +#define RADEON_PP_TFACTOR_0 0x1c68 +#define RADEON_PP_TFACTOR_1 0x1c80 +#define RADEON_PP_TFACTOR_2 0x1c98 + +#define RADEON_RB3D_BLENDCNTL 0x1c20 +# define RADEON_COMB_FCN_MASK (3 << 12) +# define RADEON_COMB_FCN_ADD_CLAMP (0 << 12) +# define RADEON_COMB_FCN_ADD_NOCLAMP (1 << 12) +# define RADEON_COMB_FCN_SUB_CLAMP (2 << 12) +# define RADEON_COMB_FCN_SUB_NOCLAMP (3 << 12) +# define RADEON_SRC_BLEND_GL_ZERO (32 << 16) +# define RADEON_SRC_BLEND_GL_ONE (33 << 16) +# define RADEON_SRC_BLEND_GL_SRC_COLOR (34 << 16) +# define RADEON_SRC_BLEND_GL_ONE_MINUS_SRC_COLOR (35 << 16) +# define RADEON_SRC_BLEND_GL_DST_COLOR (36 << 16) +# define RADEON_SRC_BLEND_GL_ONE_MINUS_DST_COLOR (37 << 16) +# define RADEON_SRC_BLEND_GL_SRC_ALPHA (38 << 16) +# define RADEON_SRC_BLEND_GL_ONE_MINUS_SRC_ALPHA (39 << 16) +# define RADEON_SRC_BLEND_GL_DST_ALPHA (40 << 16) +# define RADEON_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA (41 << 16) +# define RADEON_SRC_BLEND_GL_SRC_ALPHA_SATURATE (42 << 16) +# define RADEON_SRC_BLEND_MASK (63 << 16) +# define RADEON_DST_BLEND_GL_ZERO (32 << 24) +# define RADEON_DST_BLEND_GL_ONE (33 << 24) +# define RADEON_DST_BLEND_GL_SRC_COLOR (34 << 24) +# define RADEON_DST_BLEND_GL_ONE_MINUS_SRC_COLOR (35 << 24) +# define RADEON_DST_BLEND_GL_DST_COLOR (36 << 24) +# define RADEON_DST_BLEND_GL_ONE_MINUS_DST_COLOR (37 << 24) +# define RADEON_DST_BLEND_GL_SRC_ALPHA (38 << 24) +# define RADEON_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA (39 << 24) +# define RADEON_DST_BLEND_GL_DST_ALPHA (40 << 24) +# define RADEON_DST_BLEND_GL_ONE_MINUS_DST_ALPHA (41 << 24) +# define RADEON_DST_BLEND_MASK (63 << 24) +#define RADEON_RB3D_CNTL 0x1c3c +# define RADEON_ALPHA_BLEND_ENABLE (1 << 0) +# define RADEON_PLANE_MASK_ENABLE (1 << 1) +# define RADEON_DITHER_ENABLE (1 << 2) +# define RADEON_ROUND_ENABLE (1 << 3) +# define RADEON_SCALE_DITHER_ENABLE (1 << 4) +# define RADEON_DITHER_INIT (1 << 5) +# define RADEON_ROP_ENABLE (1 << 6) +# define RADEON_STENCIL_ENABLE (1 << 7) +# define RADEON_Z_ENABLE (1 << 8) +# define RADEON_DEPTH_XZ_OFFEST_ENABLE (1 << 9) +# define RADEON_COLOR_FORMAT_ARGB1555 (3 << 10) +# define RADEON_COLOR_FORMAT_RGB565 (4 << 10) +# define RADEON_COLOR_FORMAT_ARGB8888 (6 << 10) +# define RADEON_COLOR_FORMAT_RGB332 (7 << 10) +# define RADEON_COLOR_FORMAT_Y8 (8 << 10) +# define RADEON_COLOR_FORMAT_RGB8 (9 << 10) +# define RADEON_COLOR_FORMAT_YUV422_VYUY (11 << 10) +# define RADEON_COLOR_FORMAT_YUV422_YVYU (12 << 10) +# define RADEON_COLOR_FORMAT_aYUV444 (14 << 10) +# define RADEON_COLOR_FORMAT_ARGB4444 (15 << 10) +# define RADEON_CLRCMP_FLIP_ENABLE (1 << 14) +#define RADEON_RB3D_COLOROFFSET 0x1c40 +# define RADEON_COLOROFFSET_MASK 0xfffffff0 +#define RADEON_RB3D_COLORPITCH 0x1c48 +# define RADEON_COLORPITCH_MASK 0x000001ff8 +# define RADEON_COLOR_TILE_ENABLE (1 << 16) +# define RADEON_COLOR_MICROTILE_ENABLE (1 << 17) +# define RADEON_COLOR_ENDIAN_NO_SWAP (0 << 18) +# define RADEON_COLOR_ENDIAN_WORD_SWAP (1 << 18) +# define RADEON_COLOR_ENDIAN_DWORD_SWAP (2 << 18) +#define RADEON_RB3D_DEPTHOFFSET 0x1c24 +#define RADEON_RB3D_DEPTHPITCH 0x1c28 +# define RADEON_DEPTHPITCH_MASK 0x00001ff8 +# define RADEON_DEPTH_ENDIAN_NO_SWAP (0 << 18) +# define RADEON_DEPTH_ENDIAN_WORD_SWAP (1 << 18) +# define RADEON_DEPTH_ENDIAN_DWORD_SWAP (2 << 18) +#define RADEON_RB3D_PLANEMASK 0x1d84 +#define RADEON_RB3D_ROPCNTL 0x1d80 +# define RADEON_ROP_MASK (15 << 8) +# define RADEON_ROP_CLEAR (0 << 8) +# define RADEON_ROP_NOR (1 << 8) +# define RADEON_ROP_AND_INVERTED (2 << 8) +# define RADEON_ROP_COPY_INVERTED (3 << 8) +# define RADEON_ROP_AND_REVERSE (4 << 8) +# define RADEON_ROP_INVERT (5 << 8) +# define RADEON_ROP_XOR (6 << 8) +# define RADEON_ROP_NAND (7 << 8) +# define RADEON_ROP_AND (8 << 8) +# define RADEON_ROP_EQUIV (9 << 8) +# define RADEON_ROP_NOOP (10 << 8) +# define RADEON_ROP_OR_INVERTED (11 << 8) +# define RADEON_ROP_COPY (12 << 8) +# define RADEON_ROP_OR_REVERSE (13 << 8) +# define RADEON_ROP_OR (14 << 8) +# define RADEON_ROP_SET (15 << 8) +#define RADEON_RB3D_STENCILREFMASK 0x1d7c +# define RADEON_STENCIL_REF_SHIFT 0 +# define RADEON_STENCIL_REF_MASK (0xff << 0) +# define RADEON_STENCIL_MASK_SHIFT 16 +# define RADEON_STENCIL_VALUE_MASK (0xff << 16) +# define RADEON_STENCIL_WRITEMASK_SHIFT 24 +# define RADEON_STENCIL_WRITE_MASK (0xff << 24) +#define RADEON_RB3D_ZSTENCILCNTL 0x1c2c +# define RADEON_DEPTH_FORMAT_MASK (0xf << 0) +# define RADEON_DEPTH_FORMAT_16BIT_INT_Z (0 << 0) +# define RADEON_DEPTH_FORMAT_24BIT_INT_Z (2 << 0) +# define RADEON_DEPTH_FORMAT_24BIT_FLOAT_Z (3 << 0) +# define RADEON_DEPTH_FORMAT_32BIT_INT_Z (4 << 0) +# define RADEON_DEPTH_FORMAT_32BIT_FLOAT_Z (5 << 0) +# define RADEON_DEPTH_FORMAT_16BIT_FLOAT_W (7 << 0) +# define RADEON_DEPTH_FORMAT_24BIT_FLOAT_W (9 << 0) +# define RADEON_DEPTH_FORMAT_32BIT_FLOAT_W (11 << 0) +# define RADEON_Z_TEST_NEVER (0 << 4) +# define RADEON_Z_TEST_LESS (1 << 4) +# define RADEON_Z_TEST_LEQUAL (2 << 4) +# define RADEON_Z_TEST_EQUAL (3 << 4) +# define RADEON_Z_TEST_GEQUAL (4 << 4) +# define RADEON_Z_TEST_GREATER (5 << 4) +# define RADEON_Z_TEST_NEQUAL (6 << 4) +# define RADEON_Z_TEST_ALWAYS (7 << 4) +# define RADEON_Z_TEST_MASK (7 << 4) +# define RADEON_STENCIL_TEST_NEVER (0 << 12) +# define RADEON_STENCIL_TEST_LESS (1 << 12) +# define RADEON_STENCIL_TEST_LEQUAL (2 << 12) +# define RADEON_STENCIL_TEST_EQUAL (3 << 12) +# define RADEON_STENCIL_TEST_GEQUAL (4 << 12) +# define RADEON_STENCIL_TEST_GREATER (5 << 12) +# define RADEON_STENCIL_TEST_NEQUAL (6 << 12) +# define RADEON_STENCIL_TEST_ALWAYS (7 << 12) +# define RADEON_STENCIL_TEST_MASK (0x7 << 12) +# define RADEON_STENCIL_FAIL_KEEP (0 << 16) +# define RADEON_STENCIL_FAIL_ZERO (1 << 16) +# define RADEON_STENCIL_FAIL_REPLACE (2 << 16) +# define RADEON_STENCIL_FAIL_INC (3 << 16) +# define RADEON_STENCIL_FAIL_DEC (4 << 16) +# define RADEON_STENCIL_FAIL_INVERT (5 << 16) +# define RADEON_STENCIL_FAIL_MASK (0x7 << 16) +# define RADEON_STENCIL_ZPASS_KEEP (0 << 20) +# define RADEON_STENCIL_ZPASS_ZERO (1 << 20) +# define RADEON_STENCIL_ZPASS_REPLACE (2 << 20) +# define RADEON_STENCIL_ZPASS_INC (3 << 20) +# define RADEON_STENCIL_ZPASS_DEC (4 << 20) +# define RADEON_STENCIL_ZPASS_INVERT (5 << 20) +# define RADEON_STENCIL_ZPASS_MASK (0x7 << 20) +# define RADEON_STENCIL_ZFAIL_KEEP (0 << 24) +# define RADEON_STENCIL_ZFAIL_ZERO (1 << 24) +# define RADEON_STENCIL_ZFAIL_REPLACE (2 << 24) +# define RADEON_STENCIL_ZFAIL_INC (3 << 24) +# define RADEON_STENCIL_ZFAIL_DEC (4 << 24) +# define RADEON_STENCIL_ZFAIL_INVERT (5 << 24) +# define RADEON_STENCIL_ZFAIL_MASK (0x7 << 24) +# define RADEON_Z_COMPRESSION_ENABLE (1 << 28) +# define RADEON_FORCE_Z_DIRTY (1 << 29) +# define RADEON_Z_WRITE_ENABLE (1 << 30) +#define RADEON_RE_LINE_PATTERN 0x1cd0 +# define RADEON_LINE_PATTERN_MASK 0x0000ffff +# define RADEON_LINE_REPEAT_COUNT_SHIFT 16 +# define RADEON_LINE_PATTERN_START_SHIFT 24 +# define RADEON_LINE_PATTERN_LITTLE_BIT_ORDER (0 << 28) +# define RADEON_LINE_PATTERN_BIG_BIT_ORDER (1 << 28) +# define RADEON_LINE_PATTERN_AUTO_RESET (1 << 29) +#define RADEON_RE_LINE_STATE 0x1cd4 +# define RADEON_LINE_CURRENT_PTR_SHIFT 0 +# define RADEON_LINE_CURRENT_COUNT_SHIFT 8 +#define RADEON_RE_MISC 0x26c4 +# define RADEON_STIPPLE_COORD_MASK 0x1f +# define RADEON_STIPPLE_X_OFFSET_SHIFT 0 +# define RADEON_STIPPLE_X_OFFSET_MASK (0x1f << 0) +# define RADEON_STIPPLE_Y_OFFSET_SHIFT 8 +# define RADEON_STIPPLE_Y_OFFSET_MASK (0x1f << 8) +# define RADEON_STIPPLE_LITTLE_BIT_ORDER (0 << 16) +# define RADEON_STIPPLE_BIG_BIT_ORDER (1 << 16) +#define RADEON_RE_SOLID_COLOR 0x1c1c +#define RADEON_RE_TOP_LEFT 0x26c0 +# define RADEON_RE_LEFT_SHIFT 0 +# define RADEON_RE_TOP_SHIFT 16 +#define RADEON_RE_WIDTH_HEIGHT 0x1c44 +# define RADEON_RE_WIDTH_SHIFT 0 +# define RADEON_RE_HEIGHT_SHIFT 16 + +#define RADEON_SE_CNTL 0x1c4c +# define RADEON_FFACE_CULL_CW (0 << 0) +# define RADEON_FFACE_CULL_CCW (1 << 0) +# define RADEON_FFACE_CULL_DIR_MASK (1 << 0) +# define RADEON_BFACE_CULL (0 << 1) +# define RADEON_BFACE_SOLID (3 << 1) +# define RADEON_FFACE_CULL (0 << 3) +# define RADEON_FFACE_SOLID (3 << 3) +# define RADEON_FFACE_CULL_MASK (3 << 3) +# define RADEON_BADVTX_CULL_DISABLE (1 << 5) +# define RADEON_FLAT_SHADE_VTX_0 (0 << 6) +# define RADEON_FLAT_SHADE_VTX_1 (1 << 6) +# define RADEON_FLAT_SHADE_VTX_2 (2 << 6) +# define RADEON_FLAT_SHADE_VTX_LAST (3 << 6) +# define RADEON_DIFFUSE_SHADE_SOLID (0 << 8) +# define RADEON_DIFFUSE_SHADE_FLAT (1 << 8) +# define RADEON_DIFFUSE_SHADE_GOURAUD (2 << 8) +# define RADEON_DIFFUSE_SHADE_MASK (3 << 8) +# define RADEON_ALPHA_SHADE_SOLID (0 << 10) +# define RADEON_ALPHA_SHADE_FLAT (1 << 10) +# define RADEON_ALPHA_SHADE_GOURAUD (2 << 10) +# define RADEON_ALPHA_SHADE_MASK (3 << 10) +# define RADEON_SPECULAR_SHADE_SOLID (0 << 12) +# define RADEON_SPECULAR_SHADE_FLAT (1 << 12) +# define RADEON_SPECULAR_SHADE_GOURAUD (2 << 12) +# define RADEON_SPECULAR_SHADE_MASK (3 << 12) +# define RADEON_FOG_SHADE_SOLID (0 << 14) +# define RADEON_FOG_SHADE_FLAT (1 << 14) +# define RADEON_FOG_SHADE_GOURAUD (2 << 14) +# define RADEON_FOG_SHADE_MASK (3 << 14) +# define RADEON_ZBIAS_ENABLE_POINT (1 << 16) +# define RADEON_ZBIAS_ENABLE_LINE (1 << 17) +# define RADEON_ZBIAS_ENABLE_TRI (1 << 18) +# define RADEON_WIDELINE_ENABLE (1 << 20) +# define RADEON_VPORT_XY_XFORM_ENABLE (1 << 24) +# define RADEON_VPORT_Z_XFORM_ENABLE (1 << 25) +# define RADEON_VTX_PIX_CENTER_D3D (0 << 27) +# define RADEON_VTX_PIX_CENTER_OGL (1 << 27) +# define RADEON_ROUND_MODE_TRUNC (0 << 28) +# define RADEON_ROUND_MODE_ROUND (1 << 28) +# define RADEON_ROUND_MODE_ROUND_EVEN (2 << 28) +# define RADEON_ROUND_MODE_ROUND_ODD (3 << 28) +# define RADEON_ROUND_PREC_16TH_PIX (0 << 30) +# define RADEON_ROUND_PREC_8TH_PIX (1 << 30) +# define RADEON_ROUND_PREC_4TH_PIX (2 << 30) +# define RADEON_ROUND_PREC_HALF_PIX (3 << 30) +#define R200_RE_CNTL 0x1c50 +# define R200_STIPPLE_ENABLE 0x1 +# define R200_SCISSOR_ENABLE 0x2 +# define R200_PATTERN_ENABLE 0x4 +# define R200_PERSPECTIVE_ENABLE 0x8 +# define R200_POINT_SMOOTH 0x20 +# define R200_VTX_STQ0_D3D 0x00010000 +# define R200_VTX_STQ1_D3D 0x00040000 +# define R200_VTX_STQ2_D3D 0x00100000 +# define R200_VTX_STQ3_D3D 0x00400000 +# define R200_VTX_STQ4_D3D 0x01000000 +# define R200_VTX_STQ5_D3D 0x04000000 +#define R200_RE_SCISSOR_TL_0 0x1cd8 +#define R200_RE_SCISSOR_BR_0 0x1cdc +#define R200_RE_SCISSOR_TL_1 0x1ce0 +#define R200_RE_SCISSOR_BR_1 0x1ce4 +#define R200_RE_SCISSOR_TL_2 0x1ce8 +#define R200_RE_SCISSOR_BR_2 0x1cec +# define R200_SCISSOR_X_SHIFT 0 +# define R200_SCISSOR_Y_SHIFT 16 +#define RADEON_SE_CNTL_STATUS 0x2140 +# define RADEON_VC_NO_SWAP (0 << 0) +# define RADEON_VC_16BIT_SWAP (1 << 0) +# define RADEON_VC_32BIT_SWAP (2 << 0) +# define RADEON_VC_HALF_DWORD_SWAP (3 << 0) +# define RADEON_TCL_BYPASS (1 << 8) +#define RADEON_SE_COORD_FMT 0x1c50 +# define RADEON_VTX_XY_PRE_MULT_1_OVER_W0 (1 << 0) +# define RADEON_VTX_Z_PRE_MULT_1_OVER_W0 (1 << 1) +# define RADEON_VTX_ST0_NONPARAMETRIC (1 << 8) +# define RADEON_VTX_ST1_NONPARAMETRIC (1 << 9) +# define RADEON_VTX_ST2_NONPARAMETRIC (1 << 10) +# define RADEON_VTX_ST3_NONPARAMETRIC (1 << 11) +# define RADEON_VTX_W0_NORMALIZE (1 << 12) +# define RADEON_VTX_W0_IS_NOT_1_OVER_W0 (1 << 16) +# define RADEON_VTX_ST0_PRE_MULT_1_OVER_W0 (1 << 17) +# define RADEON_VTX_ST1_PRE_MULT_1_OVER_W0 (1 << 19) +# define RADEON_VTX_ST2_PRE_MULT_1_OVER_W0 (1 << 21) +# define RADEON_VTX_ST3_PRE_MULT_1_OVER_W0 (1 << 23) +# define RADEON_TEX1_W_ROUTING_USE_W0 (0 << 26) +# define RADEON_TEX1_W_ROUTING_USE_Q1 (1 << 26) +#define RADEON_SE_LINE_WIDTH 0x1db8 +#define RADEON_SE_TCL_LIGHT_MODEL_CTL 0x226c +# define RADEON_LIGHTING_ENABLE (1 << 0) +# define RADEON_LIGHT_IN_MODELSPACE (1 << 1) +# define RADEON_LOCAL_VIEWER (1 << 2) +# define RADEON_NORMALIZE_NORMALS (1 << 3) +# define RADEON_RESCALE_NORMALS (1 << 4) +# define RADEON_SPECULAR_LIGHTS (1 << 5) +# define RADEON_DIFFUSE_SPECULAR_COMBINE (1 << 6) +# define RADEON_LIGHT_ALPHA (1 << 7) +# define RADEON_LOCAL_LIGHT_VEC_GL (1 << 8) +# define RADEON_LIGHT_NO_NORMAL_AMBIENT_ONLY (1 << 9) +# define RADEON_LM_SOURCE_STATE_PREMULT 0 +# define RADEON_LM_SOURCE_STATE_MULT 1 +# define RADEON_LM_SOURCE_VERTEX_DIFFUSE 2 +# define RADEON_LM_SOURCE_VERTEX_SPECULAR 3 +# define RADEON_EMISSIVE_SOURCE_SHIFT 16 +# define RADEON_AMBIENT_SOURCE_SHIFT 18 +# define RADEON_DIFFUSE_SOURCE_SHIFT 20 +# define RADEON_SPECULAR_SOURCE_SHIFT 22 +#define RADEON_SE_TCL_MATERIAL_AMBIENT_RED 0x2220 +#define RADEON_SE_TCL_MATERIAL_AMBIENT_GREEN 0x2224 +#define RADEON_SE_TCL_MATERIAL_AMBIENT_BLUE 0x2228 +#define RADEON_SE_TCL_MATERIAL_AMBIENT_ALPHA 0x222c +#define RADEON_SE_TCL_MATERIAL_DIFFUSE_RED 0x2230 +#define RADEON_SE_TCL_MATERIAL_DIFFUSE_GREEN 0x2234 +#define RADEON_SE_TCL_MATERIAL_DIFFUSE_BLUE 0x2238 +#define RADEON_SE_TCL_MATERIAL_DIFFUSE_ALPHA 0x223c +#define RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED 0x2210 +#define RADEON_SE_TCL_MATERIAL_EMMISSIVE_GREEN 0x2214 +#define RADEON_SE_TCL_MATERIAL_EMMISSIVE_BLUE 0x2218 +#define RADEON_SE_TCL_MATERIAL_EMMISSIVE_ALPHA 0x221c +#define RADEON_SE_TCL_MATERIAL_SPECULAR_RED 0x2240 +#define RADEON_SE_TCL_MATERIAL_SPECULAR_GREEN 0x2244 +#define RADEON_SE_TCL_MATERIAL_SPECULAR_BLUE 0x2248 +#define RADEON_SE_TCL_MATERIAL_SPECULAR_ALPHA 0x224c +#define RADEON_SE_TCL_MATRIX_SELECT_0 0x225c +# define RADEON_MODELVIEW_0_SHIFT 0 +# define RADEON_MODELVIEW_1_SHIFT 4 +# define RADEON_MODELVIEW_2_SHIFT 8 +# define RADEON_MODELVIEW_3_SHIFT 12 +# define RADEON_IT_MODELVIEW_0_SHIFT 16 +# define RADEON_IT_MODELVIEW_1_SHIFT 20 +# define RADEON_IT_MODELVIEW_2_SHIFT 24 +# define RADEON_IT_MODELVIEW_3_SHIFT 28 +#define RADEON_SE_TCL_MATRIX_SELECT_1 0x2260 +# define RADEON_MODELPROJECT_0_SHIFT 0 +# define RADEON_MODELPROJECT_1_SHIFT 4 +# define RADEON_MODELPROJECT_2_SHIFT 8 +# define RADEON_MODELPROJECT_3_SHIFT 12 +# define RADEON_TEXMAT_0_SHIFT 16 +# define RADEON_TEXMAT_1_SHIFT 20 +# define RADEON_TEXMAT_2_SHIFT 24 +# define RADEON_TEXMAT_3_SHIFT 28 + + +#define RADEON_SE_TCL_OUTPUT_VTX_FMT 0x2254 +# define RADEON_TCL_VTX_W0 (1 << 0) +# define RADEON_TCL_VTX_FP_DIFFUSE (1 << 1) +# define RADEON_TCL_VTX_FP_ALPHA (1 << 2) +# define RADEON_TCL_VTX_PK_DIFFUSE (1 << 3) +# define RADEON_TCL_VTX_FP_SPEC (1 << 4) +# define RADEON_TCL_VTX_FP_FOG (1 << 5) +# define RADEON_TCL_VTX_PK_SPEC (1 << 6) +# define RADEON_TCL_VTX_ST0 (1 << 7) +# define RADEON_TCL_VTX_ST1 (1 << 8) +# define RADEON_TCL_VTX_Q1 (1 << 9) +# define RADEON_TCL_VTX_ST2 (1 << 10) +# define RADEON_TCL_VTX_Q2 (1 << 11) +# define RADEON_TCL_VTX_ST3 (1 << 12) +# define RADEON_TCL_VTX_Q3 (1 << 13) +# define RADEON_TCL_VTX_Q0 (1 << 14) +# define RADEON_TCL_VTX_WEIGHT_COUNT_SHIFT 15 +# define RADEON_TCL_VTX_NORM0 (1 << 18) +# define RADEON_TCL_VTX_XY1 (1 << 27) +# define RADEON_TCL_VTX_Z1 (1 << 28) +# define RADEON_TCL_VTX_W1 (1 << 29) +# define RADEON_TCL_VTX_NORM1 (1 << 30) +# define RADEON_TCL_VTX_Z0 (1 << 31) + +#define RADEON_SE_TCL_OUTPUT_VTX_SEL 0x2258 +# define RADEON_TCL_COMPUTE_XYZW (1 << 0) +# define RADEON_TCL_COMPUTE_DIFFUSE (1 << 1) +# define RADEON_TCL_COMPUTE_SPECULAR (1 << 2) +# define RADEON_TCL_FORCE_NAN_IF_COLOR_NAN (1 << 3) +# define RADEON_TCL_FORCE_INORDER_PROC (1 << 4) +# define RADEON_TCL_TEX_INPUT_TEX_0 0 +# define RADEON_TCL_TEX_INPUT_TEX_1 1 +# define RADEON_TCL_TEX_INPUT_TEX_2 2 +# define RADEON_TCL_TEX_INPUT_TEX_3 3 +# define RADEON_TCL_TEX_COMPUTED_TEX_0 8 +# define RADEON_TCL_TEX_COMPUTED_TEX_1 9 +# define RADEON_TCL_TEX_COMPUTED_TEX_2 10 +# define RADEON_TCL_TEX_COMPUTED_TEX_3 11 +# define RADEON_TCL_TEX_0_OUTPUT_SHIFT 16 +# define RADEON_TCL_TEX_1_OUTPUT_SHIFT 20 +# define RADEON_TCL_TEX_2_OUTPUT_SHIFT 24 +# define RADEON_TCL_TEX_3_OUTPUT_SHIFT 28 + +#define RADEON_SE_TCL_PER_LIGHT_CTL_0 0x2270 +# define RADEON_LIGHT_0_ENABLE (1 << 0) +# define RADEON_LIGHT_0_ENABLE_AMBIENT (1 << 1) +# define RADEON_LIGHT_0_ENABLE_SPECULAR (1 << 2) +# define RADEON_LIGHT_0_IS_LOCAL (1 << 3) +# define RADEON_LIGHT_0_IS_SPOT (1 << 4) +# define RADEON_LIGHT_0_DUAL_CONE (1 << 5) +# define RADEON_LIGHT_0_ENABLE_RANGE_ATTEN (1 << 6) +# define RADEON_LIGHT_0_CONSTANT_RANGE_ATTEN (1 << 7) +# define RADEON_LIGHT_0_SHIFT 0 +# define RADEON_LIGHT_1_ENABLE (1 << 16) +# define RADEON_LIGHT_1_ENABLE_AMBIENT (1 << 17) +# define RADEON_LIGHT_1_ENABLE_SPECULAR (1 << 18) +# define RADEON_LIGHT_1_IS_LOCAL (1 << 19) +# define RADEON_LIGHT_1_IS_SPOT (1 << 20) +# define RADEON_LIGHT_1_DUAL_CONE (1 << 21) +# define RADEON_LIGHT_1_ENABLE_RANGE_ATTEN (1 << 22) +# define RADEON_LIGHT_1_CONSTANT_RANGE_ATTEN (1 << 23) +# define RADEON_LIGHT_1_SHIFT 16 +#define RADEON_SE_TCL_PER_LIGHT_CTL_1 0x2274 +# define RADEON_LIGHT_2_SHIFT 0 +# define RADEON_LIGHT_3_SHIFT 16 +#define RADEON_SE_TCL_PER_LIGHT_CTL_2 0x2278 +# define RADEON_LIGHT_4_SHIFT 0 +# define RADEON_LIGHT_5_SHIFT 16 +#define RADEON_SE_TCL_PER_LIGHT_CTL_3 0x227c +# define RADEON_LIGHT_6_SHIFT 0 +# define RADEON_LIGHT_7_SHIFT 16 + +#define RADEON_SE_TCL_SHININESS 0x2250 + +#define RADEON_SE_TCL_TEXTURE_PROC_CTL 0x2268 +# define RADEON_TEXGEN_TEXMAT_0_ENABLE (1 << 0) +# define RADEON_TEXGEN_TEXMAT_1_ENABLE (1 << 1) +# define RADEON_TEXGEN_TEXMAT_2_ENABLE (1 << 2) +# define RADEON_TEXGEN_TEXMAT_3_ENABLE (1 << 3) +# define RADEON_TEXMAT_0_ENABLE (1 << 4) +# define RADEON_TEXMAT_1_ENABLE (1 << 5) +# define RADEON_TEXMAT_2_ENABLE (1 << 6) +# define RADEON_TEXMAT_3_ENABLE (1 << 7) +# define RADEON_TEXGEN_INPUT_MASK 0xf +# define RADEON_TEXGEN_INPUT_TEXCOORD_0 0 +# define RADEON_TEXGEN_INPUT_TEXCOORD_1 1 +# define RADEON_TEXGEN_INPUT_TEXCOORD_2 2 +# define RADEON_TEXGEN_INPUT_TEXCOORD_3 3 +# define RADEON_TEXGEN_INPUT_OBJ 4 +# define RADEON_TEXGEN_INPUT_EYE 5 +# define RADEON_TEXGEN_INPUT_EYE_NORMAL 6 +# define RADEON_TEXGEN_INPUT_EYE_REFLECT 7 +# define RADEON_TEXGEN_INPUT_EYE_NORMALIZED 8 +# define RADEON_TEXGEN_0_INPUT_SHIFT 16 +# define RADEON_TEXGEN_1_INPUT_SHIFT 20 +# define RADEON_TEXGEN_2_INPUT_SHIFT 24 +# define RADEON_TEXGEN_3_INPUT_SHIFT 28 + +#define RADEON_SE_TCL_UCP_VERT_BLEND_CTL 0x2264 +# define RADEON_UCP_IN_CLIP_SPACE (1 << 0) +# define RADEON_UCP_IN_MODEL_SPACE (1 << 1) +# define RADEON_UCP_ENABLE_0 (1 << 2) +# define RADEON_UCP_ENABLE_1 (1 << 3) +# define RADEON_UCP_ENABLE_2 (1 << 4) +# define RADEON_UCP_ENABLE_3 (1 << 5) +# define RADEON_UCP_ENABLE_4 (1 << 6) +# define RADEON_UCP_ENABLE_5 (1 << 7) +# define RADEON_TCL_FOG_MASK (3 << 8) +# define RADEON_TCL_FOG_DISABLE (0 << 8) +# define RADEON_TCL_FOG_EXP (1 << 8) +# define RADEON_TCL_FOG_EXP2 (2 << 8) +# define RADEON_TCL_FOG_LINEAR (3 << 8) +# define RADEON_RNG_BASED_FOG (1 << 10) +# define RADEON_LIGHT_TWOSIDE (1 << 11) +# define RADEON_BLEND_OP_COUNT_MASK (7 << 12) +# define RADEON_BLEND_OP_COUNT_SHIFT 12 +# define RADEON_POSITION_BLEND_OP_ENABLE (1 << 16) +# define RADEON_NORMAL_BLEND_OP_ENABLE (1 << 17) +# define RADEON_VERTEX_BLEND_SRC_0_PRIMARY (1 << 18) +# define RADEON_VERTEX_BLEND_SRC_0_SECONDARY (1 << 18) +# define RADEON_VERTEX_BLEND_SRC_1_PRIMARY (1 << 19) +# define RADEON_VERTEX_BLEND_SRC_1_SECONDARY (1 << 19) +# define RADEON_VERTEX_BLEND_SRC_2_PRIMARY (1 << 20) +# define RADEON_VERTEX_BLEND_SRC_2_SECONDARY (1 << 20) +# define RADEON_VERTEX_BLEND_SRC_3_PRIMARY (1 << 21) +# define RADEON_VERTEX_BLEND_SRC_3_SECONDARY (1 << 21) +# define RADEON_VERTEX_BLEND_WGT_MINUS_ONE (1 << 22) +# define RADEON_CULL_FRONT_IS_CW (0 << 28) +# define RADEON_CULL_FRONT_IS_CCW (1 << 28) +# define RADEON_CULL_FRONT (1 << 29) +# define RADEON_CULL_BACK (1 << 30) +# define RADEON_FORCE_W_TO_ONE (1 << 31) + +#define RADEON_SE_VPORT_XSCALE 0x1d98 +#define RADEON_SE_VPORT_XOFFSET 0x1d9c +#define RADEON_SE_VPORT_YSCALE 0x1da0 +#define RADEON_SE_VPORT_YOFFSET 0x1da4 +#define RADEON_SE_VPORT_ZSCALE 0x1da8 +#define RADEON_SE_VPORT_ZOFFSET 0x1dac +#define RADEON_SE_ZBIAS_FACTOR 0x1db0 +#define RADEON_SE_ZBIAS_CONSTANT 0x1db4 + +#define RADEON_SE_VTX_FMT 0x2080 +# define RADEON_SE_VTX_FMT_XY 0x00000000 +# define RADEON_SE_VTX_FMT_W0 0x00000001 +# define RADEON_SE_VTX_FMT_FPCOLOR 0x00000002 +# define RADEON_SE_VTX_FMT_FPALPHA 0x00000004 +# define RADEON_SE_VTX_FMT_PKCOLOR 0x00000008 +# define RADEON_SE_VTX_FMT_FPSPEC 0x00000010 +# define RADEON_SE_VTX_FMT_FPFOG 0x00000020 +# define RADEON_SE_VTX_FMT_PKSPEC 0x00000040 +# define RADEON_SE_VTX_FMT_ST0 0x00000080 +# define RADEON_SE_VTX_FMT_ST1 0x00000100 +# define RADEON_SE_VTX_FMT_Q1 0x00000200 +# define RADEON_SE_VTX_FMT_ST2 0x00000400 +# define RADEON_SE_VTX_FMT_Q2 0x00000800 +# define RADEON_SE_VTX_FMT_ST3 0x00001000 +# define RADEON_SE_VTX_FMT_Q3 0x00002000 +# define RADEON_SE_VTX_FMT_Q0 0x00004000 +# define RADEON_SE_VTX_FMT_BLND_WEIGHT_CNT_MASK 0x00038000 +# define RADEON_SE_VTX_FMT_N0 0x00040000 +# define RADEON_SE_VTX_FMT_XY1 0x08000000 +# define RADEON_SE_VTX_FMT_Z1 0x10000000 +# define RADEON_SE_VTX_FMT_W1 0x20000000 +# define RADEON_SE_VTX_FMT_N1 0x40000000 +# define RADEON_SE_VTX_FMT_Z 0x80000000 + +#define RADEON_SE_VF_CNTL 0x2084 +# define RADEON_VF_PRIM_TYPE_POINT_LIST 1 +# define RADEON_VF_PRIM_TYPE_LINE_LIST 2 +# define RADEON_VF_PRIM_TYPE_LINE_STRIP 3 +# define RADEON_VF_PRIM_TYPE_TRIANGLE_LIST 4 +# define RADEON_VF_PRIM_TYPE_TRIANGLE_FAN 5 +# define RADEON_VF_PRIM_TYPE_TRIANGLE_STRIP 6 +# define RADEON_VF_PRIM_TYPE_TRIANGLE_FLAG 7 +# define RADEON_VF_PRIM_TYPE_RECTANGLE_LIST 8 +# define RADEON_VF_PRIM_TYPE_POINT_LIST_3 9 +# define RADEON_VF_PRIM_TYPE_LINE_LIST_3 10 +# define RADEON_VF_PRIM_TYPE_SPIRIT_LIST 11 +# define RADEON_VF_PRIM_TYPE_LINE_LOOP 12 +# define RADEON_VF_PRIM_TYPE_QUAD_LIST 13 +# define RADEON_VF_PRIM_TYPE_QUAD_STRIP 14 +# define RADEON_VF_PRIM_TYPE_POLYGON 15 +# define RADEON_VF_PRIM_WALK_STATE (0<<4) +# define RADEON_VF_PRIM_WALK_INDEX (1<<4) +# define RADEON_VF_PRIM_WALK_LIST (2<<4) +# define RADEON_VF_PRIM_WALK_DATA (3<<4) +# define RADEON_VF_COLOR_ORDER_RGBA (1<<6) +# define RADEON_VF_RADEON_MODE (1<<8) +# define RADEON_VF_TCL_OUTPUT_CTL_ENA (1<<9) +# define RADEON_VF_PROG_STREAM_ENA (1<<10) +# define RADEON_VF_INDEX_SIZE_SHIFT 11 +# define RADEON_VF_NUM_VERTICES_SHIFT 16 + +#define RADEON_SE_PORT_DATA0 0x2000 + +#define R200_SE_VAP_CNTL 0x2080 +# define R200_VAP_TCL_ENABLE 0x00000001 +# define R200_VAP_SINGLE_BUF_STATE_ENABLE 0x00000010 +# define R200_VAP_FORCE_W_TO_ONE 0x00010000 +# define R200_VAP_D3D_TEX_DEFAULT 0x00020000 +# define R200_VAP_VF_MAX_VTX_NUM__SHIFT 18 +# define R200_VAP_VF_MAX_VTX_NUM (9 << 18) +# define R200_VAP_DX_CLIP_SPACE_DEF 0x00400000 +#define R200_VF_MAX_VTX_INDX 0x210c +#define R200_VF_MIN_VTX_INDX 0x2110 +#define R200_SE_VTE_CNTL 0x20b0 +# define R200_VPORT_X_SCALE_ENA 0x00000001 +# define R200_VPORT_X_OFFSET_ENA 0x00000002 +# define R200_VPORT_Y_SCALE_ENA 0x00000004 +# define R200_VPORT_Y_OFFSET_ENA 0x00000008 +# define R200_VPORT_Z_SCALE_ENA 0x00000010 +# define R200_VPORT_Z_OFFSET_ENA 0x00000020 +# define R200_VTX_XY_FMT 0x00000100 +# define R200_VTX_Z_FMT 0x00000200 +# define R200_VTX_W0_FMT 0x00000400 +# define R200_VTX_W0_NORMALIZE 0x00000800 +# define R200_VTX_ST_DENORMALIZED 0x00001000 +#define R200_SE_VAP_CNTL_STATUS 0x2140 +# define R200_VC_NO_SWAP (0 << 0) +# define R200_VC_16BIT_SWAP (1 << 0) +# define R200_VC_32BIT_SWAP (2 << 0) +#define R200_RE_AUX_SCISSOR_CNTL 0x26f0 +# define R200_EXCLUSIVE_SCISSOR_0 0x01000000 +# define R200_EXCLUSIVE_SCISSOR_1 0x02000000 +# define R200_EXCLUSIVE_SCISSOR_2 0x04000000 +# define R200_SCISSOR_ENABLE_0 0x10000000 +# define R200_SCISSOR_ENABLE_1 0x20000000 +# define R200_SCISSOR_ENABLE_2 0x40000000 +#define R200_PP_TXFILTER_0 0x2c00 +#define R200_PP_TXFILTER_1 0x2c20 +#define R200_PP_TXFILTER_2 0x2c40 +#define R200_PP_TXFILTER_3 0x2c60 +#define R200_PP_TXFILTER_4 0x2c80 +#define R200_PP_TXFILTER_5 0x2ca0 +# define R200_MAG_FILTER_NEAREST (0 << 0) +# define R200_MAG_FILTER_LINEAR (1 << 0) +# define R200_MAG_FILTER_MASK (1 << 0) +# define R200_MIN_FILTER_NEAREST (0 << 1) +# define R200_MIN_FILTER_LINEAR (1 << 1) +# define R200_MIN_FILTER_NEAREST_MIP_NEAREST (2 << 1) +# define R200_MIN_FILTER_NEAREST_MIP_LINEAR (3 << 1) +# define R200_MIN_FILTER_LINEAR_MIP_NEAREST (6 << 1) +# define R200_MIN_FILTER_LINEAR_MIP_LINEAR (7 << 1) +# define R200_MIN_FILTER_ANISO_NEAREST (8 << 1) +# define R200_MIN_FILTER_ANISO_LINEAR (9 << 1) +# define R200_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST (10 << 1) +# define R200_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR (11 << 1) +# define R200_MIN_FILTER_MASK (15 << 1) +# define R200_MAX_ANISO_1_TO_1 (0 << 5) +# define R200_MAX_ANISO_2_TO_1 (1 << 5) +# define R200_MAX_ANISO_4_TO_1 (2 << 5) +# define R200_MAX_ANISO_8_TO_1 (3 << 5) +# define R200_MAX_ANISO_16_TO_1 (4 << 5) +# define R200_MAX_ANISO_MASK (7 << 5) +# define R200_MAX_MIP_LEVEL_MASK (0x0f << 16) +# define R200_MAX_MIP_LEVEL_SHIFT 16 +# define R200_YUV_TO_RGB (1 << 20) +# define R200_YUV_TEMPERATURE_COOL (0 << 21) +# define R200_YUV_TEMPERATURE_HOT (1 << 21) +# define R200_YUV_TEMPERATURE_MASK (1 << 21) +# define R200_WRAPEN_S (1 << 22) +# define R200_CLAMP_S_WRAP (0 << 23) +# define R200_CLAMP_S_MIRROR (1 << 23) +# define R200_CLAMP_S_CLAMP_LAST (2 << 23) +# define R200_CLAMP_S_MIRROR_CLAMP_LAST (3 << 23) +# define R200_CLAMP_S_CLAMP_BORDER (4 << 23) +# define R200_CLAMP_S_MIRROR_CLAMP_BORDER (5 << 23) +# define R200_CLAMP_S_CLAMP_GL (6 << 23) +# define R200_CLAMP_S_MIRROR_CLAMP_GL (7 << 23) +# define R200_CLAMP_S_MASK (7 << 23) +# define R200_WRAPEN_T (1 << 26) +# define R200_CLAMP_T_WRAP (0 << 27) +# define R200_CLAMP_T_MIRROR (1 << 27) +# define R200_CLAMP_T_CLAMP_LAST (2 << 27) +# define R200_CLAMP_T_MIRROR_CLAMP_LAST (3 << 27) +# define R200_CLAMP_T_CLAMP_BORDER (4 << 27) +# define R200_CLAMP_T_MIRROR_CLAMP_BORDER (5 << 27) +# define R200_CLAMP_T_CLAMP_GL (6 << 27) +# define R200_CLAMP_T_MIRROR_CLAMP_GL (7 << 27) +# define R200_CLAMP_T_MASK (7 << 27) +# define R200_KILL_LT_ZERO (1 << 30) +# define R200_BORDER_MODE_OGL (0 << 31) +# define R200_BORDER_MODE_D3D (1 << 31) +#define R200_PP_TXFORMAT_0 0x2c04 +#define R200_PP_TXFORMAT_1 0x2c24 +#define R200_PP_TXFORMAT_2 0x2c44 +#define R200_PP_TXFORMAT_3 0x2c64 +#define R200_PP_TXFORMAT_4 0x2c84 +#define R200_PP_TXFORMAT_5 0x2ca4 +# define R200_TXFORMAT_I8 (0 << 0) +# define R200_TXFORMAT_AI88 (1 << 0) +# define R200_TXFORMAT_RGB332 (2 << 0) +# define R200_TXFORMAT_ARGB1555 (3 << 0) +# define R200_TXFORMAT_RGB565 (4 << 0) +# define R200_TXFORMAT_ARGB4444 (5 << 0) +# define R200_TXFORMAT_ARGB8888 (6 << 0) +# define R200_TXFORMAT_RGBA8888 (7 << 0) +# define R200_TXFORMAT_Y8 (8 << 0) +# define R200_TXFORMAT_AVYU4444 (9 << 0) +# define R200_TXFORMAT_VYUY422 (10 << 0) +# define R200_TXFORMAT_YVYU422 (11 << 0) +# define R200_TXFORMAT_DXT1 (12 << 0) +# define R200_TXFORMAT_DXT23 (14 << 0) +# define R200_TXFORMAT_DXT45 (15 << 0) +# define R200_TXFORMAT_ABGR8888 (22 << 0) +# define R200_TXFORMAT_FORMAT_MASK (31 << 0) +# define R200_TXFORMAT_FORMAT_SHIFT 0 +# define R200_TXFORMAT_ALPHA_IN_MAP (1 << 6) +# define R200_TXFORMAT_NON_POWER2 (1 << 7) +# define R200_TXFORMAT_WIDTH_MASK (15 << 8) +# define R200_TXFORMAT_WIDTH_SHIFT 8 +# define R200_TXFORMAT_HEIGHT_MASK (15 << 12) +# define R200_TXFORMAT_HEIGHT_SHIFT 12 +# define R200_TXFORMAT_F5_WIDTH_MASK (15 << 16) /* cube face 5 */ +# define R200_TXFORMAT_F5_WIDTH_SHIFT 16 +# define R200_TXFORMAT_F5_HEIGHT_MASK (15 << 20) +# define R200_TXFORMAT_F5_HEIGHT_SHIFT 20 +# define R200_TXFORMAT_ST_ROUTE_STQ0 (0 << 24) +# define R200_TXFORMAT_ST_ROUTE_STQ1 (1 << 24) +# define R200_TXFORMAT_ST_ROUTE_STQ2 (2 << 24) +# define R200_TXFORMAT_ST_ROUTE_STQ3 (3 << 24) +# define R200_TXFORMAT_ST_ROUTE_STQ4 (4 << 24) +# define R200_TXFORMAT_ST_ROUTE_STQ5 (5 << 24) +# define R200_TXFORMAT_ST_ROUTE_MASK (7 << 24) +# define R200_TXFORMAT_ST_ROUTE_SHIFT 24 +# define R200_TXFORMAT_ALPHA_MASK_ENABLE (1 << 28) +# define R200_TXFORMAT_CHROMA_KEY_ENABLE (1 << 29) +# define R200_TXFORMAT_CUBIC_MAP_ENABLE (1 << 30) +#define R200_PP_TXFORMAT_X_0 0x2c08 +#define R200_PP_TXFORMAT_X_1 0x2c28 +#define R200_PP_TXFORMAT_X_2 0x2c48 +#define R200_PP_TXFORMAT_X_3 0x2c68 +#define R200_PP_TXFORMAT_X_4 0x2c88 +#define R200_PP_TXFORMAT_X_5 0x2ca8 + +#define R200_PP_TXSIZE_0 0x2c0c /* NPOT only */ +#define R200_PP_TXSIZE_1 0x2c2c /* NPOT only */ +#define R200_PP_TXSIZE_2 0x2c4c /* NPOT only */ +#define R200_PP_TXSIZE_3 0x2c6c /* NPOT only */ +#define R200_PP_TXSIZE_4 0x2c8c /* NPOT only */ +#define R200_PP_TXSIZE_5 0x2cac /* NPOT only */ + +#define R200_PP_TXPITCH_0 0x2c10 /* NPOT only */ +#define R200_PP_TXPITCH_1 0x2c30 /* NPOT only */ +#define R200_PP_TXPITCH_2 0x2c50 /* NPOT only */ +#define R200_PP_TXPITCH_3 0x2c70 /* NPOT only */ +#define R200_PP_TXPITCH_4 0x2c90 /* NPOT only */ +#define R200_PP_TXPITCH_5 0x2cb0 /* NPOT only */ + +#define R200_PP_TXOFFSET_0 0x2d00 +# define R200_TXO_ENDIAN_NO_SWAP (0 << 0) +# define R200_TXO_ENDIAN_BYTE_SWAP (1 << 0) +# define R200_TXO_ENDIAN_WORD_SWAP (2 << 0) +# define R200_TXO_ENDIAN_HALFDW_SWAP (3 << 0) +# define R200_TXO_MACRO_LINEAR (0 << 2) +# define R200_TXO_MACRO_TILE (1 << 2) +# define R200_TXO_MICRO_LINEAR (0 << 3) +# define R200_TXO_MICRO_TILE (1 << 3) +# define R200_TXO_OFFSET_MASK 0xffffffe0 +# define R200_TXO_OFFSET_SHIFT 5 +#define R200_PP_TXOFFSET_1 0x2d18 +#define R200_PP_TXOFFSET_2 0x2d30 +#define R200_PP_TXOFFSET_3 0x2d48 +#define R200_PP_TXOFFSET_4 0x2d60 +#define R200_PP_TXOFFSET_5 0x2d78 + +#define R200_PP_TFACTOR_0 0x2ee0 +#define R200_PP_TFACTOR_1 0x2ee4 +#define R200_PP_TFACTOR_2 0x2ee8 +#define R200_PP_TFACTOR_3 0x2eec +#define R200_PP_TFACTOR_4 0x2ef0 +#define R200_PP_TFACTOR_5 0x2ef4 + +#define R200_PP_TXCBLEND_0 0x2f00 +# define R200_TXC_ARG_A_ZERO (0) +# define R200_TXC_ARG_A_CURRENT_COLOR (2) +# define R200_TXC_ARG_A_CURRENT_ALPHA (3) +# define R200_TXC_ARG_A_DIFFUSE_COLOR (4) +# define R200_TXC_ARG_A_DIFFUSE_ALPHA (5) +# define R200_TXC_ARG_A_SPECULAR_COLOR (6) +# define R200_TXC_ARG_A_SPECULAR_ALPHA (7) +# define R200_TXC_ARG_A_TFACTOR_COLOR (8) +# define R200_TXC_ARG_A_TFACTOR_ALPHA (9) +# define R200_TXC_ARG_A_R0_COLOR (10) +# define R200_TXC_ARG_A_R0_ALPHA (11) +# define R200_TXC_ARG_A_R1_COLOR (12) +# define R200_TXC_ARG_A_R1_ALPHA (13) +# define R200_TXC_ARG_A_R2_COLOR (14) +# define R200_TXC_ARG_A_R2_ALPHA (15) +# define R200_TXC_ARG_A_R3_COLOR (16) +# define R200_TXC_ARG_A_R3_ALPHA (17) +# define R200_TXC_ARG_A_R4_COLOR (18) +# define R200_TXC_ARG_A_R4_ALPHA (19) +# define R200_TXC_ARG_A_R5_COLOR (20) +# define R200_TXC_ARG_A_R5_ALPHA (21) +# define R200_TXC_ARG_A_TFACTOR1_COLOR (26) +# define R200_TXC_ARG_A_TFACTOR1_ALPHA (27) +# define R200_TXC_ARG_A_MASK (31 << 0) +# define R200_TXC_ARG_A_SHIFT 0 +# define R200_TXC_ARG_B_ZERO (0 << 5) +# define R200_TXC_ARG_B_CURRENT_COLOR (2 << 5) +# define R200_TXC_ARG_B_CURRENT_ALPHA (3 << 5) +# define R200_TXC_ARG_B_DIFFUSE_COLOR (4 << 5) +# define R200_TXC_ARG_B_DIFFUSE_ALPHA (5 << 5) +# define R200_TXC_ARG_B_SPECULAR_COLOR (6 << 5) +# define R200_TXC_ARG_B_SPECULAR_ALPHA (7 << 5) +# define R200_TXC_ARG_B_TFACTOR_COLOR (8 << 5) +# define R200_TXC_ARG_B_TFACTOR_ALPHA (9 << 5) +# define R200_TXC_ARG_B_R0_COLOR (10 << 5) +# define R200_TXC_ARG_B_R0_ALPHA (11 << 5) +# define R200_TXC_ARG_B_R1_COLOR (12 << 5) +# define R200_TXC_ARG_B_R1_ALPHA (13 << 5) +# define R200_TXC_ARG_B_R2_COLOR (14 << 5) +# define R200_TXC_ARG_B_R2_ALPHA (15 << 5) +# define R200_TXC_ARG_B_R3_COLOR (16 << 5) +# define R200_TXC_ARG_B_R3_ALPHA (17 << 5) +# define R200_TXC_ARG_B_R4_COLOR (18 << 5) +# define R200_TXC_ARG_B_R4_ALPHA (19 << 5) +# define R200_TXC_ARG_B_R5_COLOR (20 << 5) +# define R200_TXC_ARG_B_R5_ALPHA (21 << 5) +# define R200_TXC_ARG_B_TFACTOR1_COLOR (26 << 5) +# define R200_TXC_ARG_B_TFACTOR1_ALPHA (27 << 5) +# define R200_TXC_ARG_B_MASK (31 << 5) +# define R200_TXC_ARG_B_SHIFT 5 +# define R200_TXC_ARG_C_ZERO (0 << 10) +# define R200_TXC_ARG_C_CURRENT_COLOR (2 << 10) +# define R200_TXC_ARG_C_CURRENT_ALPHA (3 << 10) +# define R200_TXC_ARG_C_DIFFUSE_COLOR (4 << 10) +# define R200_TXC_ARG_C_DIFFUSE_ALPHA (5 << 10) +# define R200_TXC_ARG_C_SPECULAR_COLOR (6 << 10) +# define R200_TXC_ARG_C_SPECULAR_ALPHA (7 << 10) +# define R200_TXC_ARG_C_TFACTOR_COLOR (8 << 10) +# define R200_TXC_ARG_C_TFACTOR_ALPHA (9 << 10) +# define R200_TXC_ARG_C_R0_COLOR (10 << 10) +# define R200_TXC_ARG_C_R0_ALPHA (11 << 10) +# define R200_TXC_ARG_C_R1_COLOR (12 << 10) +# define R200_TXC_ARG_C_R1_ALPHA (13 << 10) +# define R200_TXC_ARG_C_R2_COLOR (14 << 10) +# define R200_TXC_ARG_C_R2_ALPHA (15 << 10) +# define R200_TXC_ARG_C_R3_COLOR (16 << 10) +# define R200_TXC_ARG_C_R3_ALPHA (17 << 10) +# define R200_TXC_ARG_C_R4_COLOR (18 << 10) +# define R200_TXC_ARG_C_R4_ALPHA (19 << 10) +# define R200_TXC_ARG_C_R5_COLOR (20 << 10) +# define R200_TXC_ARG_C_R5_ALPHA (21 << 10) +# define R200_TXC_ARG_C_TFACTOR1_COLOR (26 << 10) +# define R200_TXC_ARG_C_TFACTOR1_ALPHA (27 << 10) +# define R200_TXC_ARG_C_MASK (31 << 10) +# define R200_TXC_ARG_C_SHIFT 10 +# define R200_TXC_COMP_ARG_A (1 << 16) +# define R200_TXC_COMP_ARG_A_SHIFT (16) +# define R200_TXC_BIAS_ARG_A (1 << 17) +# define R200_TXC_SCALE_ARG_A (1 << 18) +# define R200_TXC_NEG_ARG_A (1 << 19) +# define R200_TXC_COMP_ARG_B (1 << 20) +# define R200_TXC_COMP_ARG_B_SHIFT (20) +# define R200_TXC_BIAS_ARG_B (1 << 21) +# define R200_TXC_SCALE_ARG_B (1 << 22) +# define R200_TXC_NEG_ARG_B (1 << 23) +# define R200_TXC_COMP_ARG_C (1 << 24) +# define R200_TXC_COMP_ARG_C_SHIFT (24) +# define R200_TXC_BIAS_ARG_C (1 << 25) +# define R200_TXC_SCALE_ARG_C (1 << 26) +# define R200_TXC_NEG_ARG_C (1 << 27) +# define R200_TXC_OP_MADD (0 << 28) +# define R200_TXC_OP_CND0 (2 << 28) +# define R200_TXC_OP_LERP (3 << 28) +# define R200_TXC_OP_DOT3 (4 << 28) +# define R200_TXC_OP_DOT4 (5 << 28) +# define R200_TXC_OP_CONDITIONAL (6 << 28) +# define R200_TXC_OP_DOT2_ADD (7 << 28) +# define R200_TXC_OP_MASK (7 << 28) +#define R200_PP_TXCBLEND2_0 0x2f04 +# define R200_TXC_TFACTOR_SEL_SHIFT 0 +# define R200_TXC_TFACTOR_SEL_MASK 0x7 +# define R200_TXC_TFACTOR1_SEL_SHIFT 4 +# define R200_TXC_TFACTOR1_SEL_MASK (0x7 << 4) +# define R200_TXC_SCALE_SHIFT 8 +# define R200_TXC_SCALE_MASK (7 << 8) +# define R200_TXC_SCALE_1X (0 << 8) +# define R200_TXC_SCALE_2X (1 << 8) +# define R200_TXC_SCALE_4X (2 << 8) +# define R200_TXC_SCALE_8X (3 << 8) +# define R200_TXC_SCALE_INV2 (5 << 8) +# define R200_TXC_SCALE_INV4 (6 << 8) +# define R200_TXC_SCALE_INV8 (7 << 8) +# define R200_TXC_CLAMP_SHIFT 12 +# define R200_TXC_CLAMP_MASK (3 << 12) +# define R200_TXC_CLAMP_WRAP (0 << 12) +# define R200_TXC_CLAMP_0_1 (1 << 12) +# define R200_TXC_CLAMP_8_8 (2 << 12) +# define R200_TXC_OUTPUT_REG_MASK (7 << 16) +# define R200_TXC_OUTPUT_REG_NONE (0 << 16) +# define R200_TXC_OUTPUT_REG_R0 (1 << 16) +# define R200_TXC_OUTPUT_REG_R1 (2 << 16) +# define R200_TXC_OUTPUT_REG_R2 (3 << 16) +# define R200_TXC_OUTPUT_REG_R3 (4 << 16) +# define R200_TXC_OUTPUT_REG_R4 (5 << 16) +# define R200_TXC_OUTPUT_REG_R5 (6 << 16) +# define R200_TXC_OUTPUT_MASK_MASK (7 << 20) +# define R200_TXC_OUTPUT_MASK_RGB (0 << 20) +# define R200_TXC_OUTPUT_MASK_RG (1 << 20) +# define R200_TXC_OUTPUT_MASK_RB (2 << 20) +# define R200_TXC_OUTPUT_MASK_R (3 << 20) +# define R200_TXC_OUTPUT_MASK_GB (4 << 20) +# define R200_TXC_OUTPUT_MASK_G (5 << 20) +# define R200_TXC_OUTPUT_MASK_B (6 << 20) +# define R200_TXC_OUTPUT_MASK_NONE (7 << 20) +# define R200_TXC_REPL_NORMAL 0 +# define R200_TXC_REPL_RED 1 +# define R200_TXC_REPL_GREEN 2 +# define R200_TXC_REPL_BLUE 3 +# define R200_TXC_REPL_ARG_A_SHIFT 26 +# define R200_TXC_REPL_ARG_A_MASK (3 << 26) +# define R200_TXC_REPL_ARG_B_SHIFT 28 +# define R200_TXC_REPL_ARG_B_MASK (3 << 28) +# define R200_TXC_REPL_ARG_C_SHIFT 30 +# define R200_TXC_REPL_ARG_C_MASK (3 << 30) +#define R200_PP_TXABLEND_0 0x2f08 +# define R200_TXA_ARG_A_ZERO (0) +# define R200_TXA_ARG_A_CURRENT_ALPHA (2) /* guess */ +# define R200_TXA_ARG_A_CURRENT_BLUE (3) /* guess */ +# define R200_TXA_ARG_A_DIFFUSE_ALPHA (4) +# define R200_TXA_ARG_A_DIFFUSE_BLUE (5) +# define R200_TXA_ARG_A_SPECULAR_ALPHA (6) +# define R200_TXA_ARG_A_SPECULAR_BLUE (7) +# define R200_TXA_ARG_A_TFACTOR_ALPHA (8) +# define R200_TXA_ARG_A_TFACTOR_BLUE (9) +# define R200_TXA_ARG_A_R0_ALPHA (10) +# define R200_TXA_ARG_A_R0_BLUE (11) +# define R200_TXA_ARG_A_R1_ALPHA (12) +# define R200_TXA_ARG_A_R1_BLUE (13) +# define R200_TXA_ARG_A_R2_ALPHA (14) +# define R200_TXA_ARG_A_R2_BLUE (15) +# define R200_TXA_ARG_A_R3_ALPHA (16) +# define R200_TXA_ARG_A_R3_BLUE (17) +# define R200_TXA_ARG_A_R4_ALPHA (18) +# define R200_TXA_ARG_A_R4_BLUE (19) +# define R200_TXA_ARG_A_R5_ALPHA (20) +# define R200_TXA_ARG_A_R5_BLUE (21) +# define R200_TXA_ARG_A_TFACTOR1_ALPHA (26) +# define R200_TXA_ARG_A_TFACTOR1_BLUE (27) +# define R200_TXA_ARG_A_MASK (31 << 0) +# define R200_TXA_ARG_A_SHIFT 0 +# define R200_TXA_ARG_B_ZERO (0 << 5) +# define R200_TXA_ARG_B_CURRENT_ALPHA (2 << 5) /* guess */ +# define R200_TXA_ARG_B_CURRENT_BLUE (3 << 5) /* guess */ +# define R200_TXA_ARG_B_DIFFUSE_ALPHA (4 << 5) +# define R200_TXA_ARG_B_DIFFUSE_BLUE (5 << 5) +# define R200_TXA_ARG_B_SPECULAR_ALPHA (6 << 5) +# define R200_TXA_ARG_B_SPECULAR_BLUE (7 << 5) +# define R200_TXA_ARG_B_TFACTOR_ALPHA (8 << 5) +# define R200_TXA_ARG_B_TFACTOR_BLUE (9 << 5) +# define R200_TXA_ARG_B_R0_ALPHA (10 << 5) +# define R200_TXA_ARG_B_R0_BLUE (11 << 5) +# define R200_TXA_ARG_B_R1_ALPHA (12 << 5) +# define R200_TXA_ARG_B_R1_BLUE (13 << 5) +# define R200_TXA_ARG_B_R2_ALPHA (14 << 5) +# define R200_TXA_ARG_B_R2_BLUE (15 << 5) +# define R200_TXA_ARG_B_R3_ALPHA (16 << 5) +# define R200_TXA_ARG_B_R3_BLUE (17 << 5) +# define R200_TXA_ARG_B_R4_ALPHA (18 << 5) +# define R200_TXA_ARG_B_R4_BLUE (19 << 5) +# define R200_TXA_ARG_B_R5_ALPHA (20 << 5) +# define R200_TXA_ARG_B_R5_BLUE (21 << 5) +# define R200_TXA_ARG_B_TFACTOR1_ALPHA (26 << 5) +# define R200_TXA_ARG_B_TFACTOR1_BLUE (27 << 5) +# define R200_TXA_ARG_B_MASK (31 << 5) +# define R200_TXA_ARG_B_SHIFT 5 +# define R200_TXA_ARG_C_ZERO (0 << 10) +# define R200_TXA_ARG_C_CURRENT_ALPHA (2 << 10) /* guess */ +# define R200_TXA_ARG_C_CURRENT_BLUE (3 << 10) /* guess */ +# define R200_TXA_ARG_C_DIFFUSE_ALPHA (4 << 10) +# define R200_TXA_ARG_C_DIFFUSE_BLUE (5 << 10) +# define R200_TXA_ARG_C_SPECULAR_ALPHA (6 << 10) +# define R200_TXA_ARG_C_SPECULAR_BLUE (7 << 10) +# define R200_TXA_ARG_C_TFACTOR_ALPHA (8 << 10) +# define R200_TXA_ARG_C_TFACTOR_BLUE (9 << 10) +# define R200_TXA_ARG_C_R0_ALPHA (10 << 10) +# define R200_TXA_ARG_C_R0_BLUE (11 << 10) +# define R200_TXA_ARG_C_R1_ALPHA (12 << 10) +# define R200_TXA_ARG_C_R1_BLUE (13 << 10) +# define R200_TXA_ARG_C_R2_ALPHA (14 << 10) +# define R200_TXA_ARG_C_R2_BLUE (15 << 10) +# define R200_TXA_ARG_C_R3_ALPHA (16 << 10) +# define R200_TXA_ARG_C_R3_BLUE (17 << 10) +# define R200_TXA_ARG_C_R4_ALPHA (18 << 10) +# define R200_TXA_ARG_C_R4_BLUE (19 << 10) +# define R200_TXA_ARG_C_R5_ALPHA (20 << 10) +# define R200_TXA_ARG_C_R5_BLUE (21 << 10) +# define R200_TXA_ARG_C_TFACTOR1_ALPHA (26 << 10) +# define R200_TXA_ARG_C_TFACTOR1_BLUE (27 << 10) +# define R200_TXA_ARG_C_MASK (31 << 10) +# define R200_TXA_ARG_C_SHIFT 10 +# define R200_TXA_COMP_ARG_A (1 << 16) +# define R200_TXA_COMP_ARG_A_SHIFT (16) +# define R200_TXA_BIAS_ARG_A (1 << 17) +# define R200_TXA_SCALE_ARG_A (1 << 18) +# define R200_TXA_NEG_ARG_A (1 << 19) +# define R200_TXA_COMP_ARG_B (1 << 20) +# define R200_TXA_COMP_ARG_B_SHIFT (20) +# define R200_TXA_BIAS_ARG_B (1 << 21) +# define R200_TXA_SCALE_ARG_B (1 << 22) +# define R200_TXA_NEG_ARG_B (1 << 23) +# define R200_TXA_COMP_ARG_C (1 << 24) +# define R200_TXA_COMP_ARG_C_SHIFT (24) +# define R200_TXA_BIAS_ARG_C (1 << 25) +# define R200_TXA_SCALE_ARG_C (1 << 26) +# define R200_TXA_NEG_ARG_C (1 << 27) +# define R200_TXA_OP_MADD (0 << 28) +# define R200_TXA_OP_CND0 (2 << 28) +# define R200_TXA_OP_LERP (3 << 28) +# define R200_TXA_OP_CONDITIONAL (6 << 28) +# define R200_TXA_OP_MASK (7 << 28) +#define R200_PP_TXABLEND2_0 0x2f0c +# define R200_TXA_TFACTOR_SEL_SHIFT 0 +# define R200_TXA_TFACTOR_SEL_MASK 0x7 +# define R200_TXA_TFACTOR1_SEL_SHIFT 4 +# define R200_TXA_TFACTOR1_SEL_MASK (0x7 << 4) +# define R200_TXA_SCALE_SHIFT 8 +# define R200_TXA_SCALE_MASK (7 << 8) +# define R200_TXA_SCALE_1X (0 << 8) +# define R200_TXA_SCALE_2X (1 << 8) +# define R200_TXA_SCALE_4X (2 << 8) +# define R200_TXA_SCALE_8X (3 << 8) +# define R200_TXA_SCALE_INV2 (5 << 8) +# define R200_TXA_SCALE_INV4 (6 << 8) +# define R200_TXA_SCALE_INV8 (7 << 8) +# define R200_TXA_CLAMP_SHIFT 12 +# define R200_TXA_CLAMP_MASK (3 << 12) +# define R200_TXA_CLAMP_WRAP (0 << 12) +# define R200_TXA_CLAMP_0_1 (1 << 12) +# define R200_TXA_CLAMP_8_8 (2 << 12) +# define R200_TXA_OUTPUT_REG_MASK (7 << 16) +# define R200_TXA_OUTPUT_REG_NONE (0 << 16) +# define R200_TXA_OUTPUT_REG_R0 (1 << 16) +# define R200_TXA_OUTPUT_REG_R1 (2 << 16) +# define R200_TXA_OUTPUT_REG_R2 (3 << 16) +# define R200_TXA_OUTPUT_REG_R3 (4 << 16) +# define R200_TXA_OUTPUT_REG_R4 (5 << 16) +# define R200_TXA_OUTPUT_REG_R5 (6 << 16) +# define R200_TXA_DOT_ALPHA (1 << 20) +# define R200_TXA_REPL_NORMAL 0 +# define R200_TXA_REPL_RED 1 +# define R200_TXA_REPL_GREEN 2 +# define R200_TXA_REPL_ARG_A_SHIFT 26 +# define R200_TXA_REPL_ARG_A_MASK (3 << 26) +# define R200_TXA_REPL_ARG_B_SHIFT 28 +# define R200_TXA_REPL_ARG_B_MASK (3 << 28) +# define R200_TXA_REPL_ARG_C_SHIFT 30 +# define R200_TXA_REPL_ARG_C_MASK (3 << 30) +#define R200_PP_TXCBLEND_1 0x2f10 +#define R200_PP_TXCBLEND2_1 0x2f14 +#define R200_PP_TXABLEND_1 0x2f18 +#define R200_PP_TXABLEND2_1 0x2f1c +#define R200_PP_TXCBLEND_2 0x2f20 +#define R200_PP_TXCBLEND2_2 0x2f24 +#define R200_PP_TXABLEND_2 0x2f28 +#define R200_PP_TXABLEND2_2 0x2f2c +#define R200_PP_TXCBLEND_3 0x2f30 +#define R200_PP_TXCBLEND2_3 0x2f34 +#define R200_PP_TXABLEND_3 0x2f38 +#define R200_PP_TXABLEND2_3 0x2f3c + +#define R200_SE_VTX_FMT_0 0x2088 +# define R200_VTX_XY 0 /* always have xy */ +# define R200_VTX_Z0 (1<<0) +# define R200_VTX_W0 (1<<1) +# define R200_VTX_WEIGHT_COUNT_SHIFT (2) +# define R200_VTX_PV_MATRIX_SEL (1<<5) +# define R200_VTX_N0 (1<<6) +# define R200_VTX_POINT_SIZE (1<<7) +# define R200_VTX_DISCRETE_FOG (1<<8) +# define R200_VTX_SHININESS_0 (1<<9) +# define R200_VTX_SHININESS_1 (1<<10) +# define R200_VTX_COLOR_NOT_PRESENT 0 +# define R200_VTX_PK_RGBA 1 +# define R200_VTX_FP_RGB 2 +# define R200_VTX_FP_RGBA 3 +# define R200_VTX_COLOR_MASK 3 +# define R200_VTX_COLOR_0_SHIFT 11 +# define R200_VTX_COLOR_1_SHIFT 13 +# define R200_VTX_COLOR_2_SHIFT 15 +# define R200_VTX_COLOR_3_SHIFT 17 +# define R200_VTX_COLOR_4_SHIFT 19 +# define R200_VTX_COLOR_5_SHIFT 21 +# define R200_VTX_COLOR_6_SHIFT 23 +# define R200_VTX_COLOR_7_SHIFT 25 +# define R200_VTX_XY1 (1<<28) +# define R200_VTX_Z1 (1<<29) +# define R200_VTX_W1 (1<<30) +# define R200_VTX_N1 (1<<31) +#define R200_SE_VTX_FMT_1 0x208c +# define R200_VTX_TEX0_COMP_CNT_SHIFT 0 +# define R200_VTX_TEX1_COMP_CNT_SHIFT 3 +# define R200_VTX_TEX2_COMP_CNT_SHIFT 6 +# define R200_VTX_TEX3_COMP_CNT_SHIFT 9 +# define R200_VTX_TEX4_COMP_CNT_SHIFT 12 +# define R200_VTX_TEX5_COMP_CNT_SHIFT 15 + +#define R200_SE_TCL_OUTPUT_VTX_FMT_0 0x2090 +#define R200_SE_TCL_OUTPUT_VTX_FMT_1 0x2094 +#define R200_SE_TCL_OUTPUT_VTX_COMP_SEL 0x2250 +# define R200_OUTPUT_XYZW (1<<0) +# define R200_OUTPUT_COLOR_0 (1<<8) +# define R200_OUTPUT_COLOR_1 (1<<9) +# define R200_OUTPUT_TEX_0 (1<<16) +# define R200_OUTPUT_TEX_1 (1<<17) +# define R200_OUTPUT_TEX_2 (1<<18) +# define R200_OUTPUT_TEX_3 (1<<19) +# define R200_OUTPUT_TEX_4 (1<<20) +# define R200_OUTPUT_TEX_5 (1<<21) +# define R200_OUTPUT_TEX_MASK (0x3f<<16) +# define R200_OUTPUT_DISCRETE_FOG (1<<24) +# define R200_OUTPUT_PT_SIZE (1<<25) +# define R200_FORCE_INORDER_PROC (1<<31) +#define R200_PP_CNTL_X 0x2cc4 +#define R200_PP_TXMULTI_CTL_0 0x2c1c +#define R200_SE_VTX_STATE_CNTL 0x2180 +# define R200_UPDATE_USER_COLOR_0_ENA_MASK (1<<16) + + /* Registers for CP and Microcode Engine */ +#define RADEON_CP_ME_RAM_ADDR 0x07d4 +#define RADEON_CP_ME_RAM_RADDR 0x07d8 +#define RADEON_CP_ME_RAM_DATAH 0x07dc +#define RADEON_CP_ME_RAM_DATAL 0x07e0 + +#define RADEON_CP_RB_BASE 0x0700 +#define RADEON_CP_RB_CNTL 0x0704 +#define RADEON_CP_RB_RPTR_ADDR 0x070c +#define RADEON_CP_RB_RPTR 0x0710 +#define RADEON_CP_RB_WPTR 0x0714 + +#define RADEON_CP_IB_BASE 0x0738 +#define RADEON_CP_IB_BUFSZ 0x073c + +#define RADEON_CP_CSQ_CNTL 0x0740 +# define RADEON_CSQ_CNT_PRIMARY_MASK (0xff << 0) +# define RADEON_CSQ_PRIDIS_INDDIS (0 << 28) +# define RADEON_CSQ_PRIPIO_INDDIS (1 << 28) +# define RADEON_CSQ_PRIBM_INDDIS (2 << 28) +# define RADEON_CSQ_PRIPIO_INDBM (3 << 28) +# define RADEON_CSQ_PRIBM_INDBM (4 << 28) +# define RADEON_CSQ_PRIPIO_INDPIO (15 << 28) +#define RADEON_CP_CSQ_STAT 0x07f8 +# define RADEON_CSQ_RPTR_PRIMARY_MASK (0xff << 0) +# define RADEON_CSQ_WPTR_PRIMARY_MASK (0xff << 8) +# define RADEON_CSQ_RPTR_INDIRECT_MASK (0xff << 16) +# define RADEON_CSQ_WPTR_INDIRECT_MASK (0xff << 24) +#define RADEON_CP_CSQ_ADDR 0x07f0 +#define RADEON_CP_CSQ_DATA 0x07f4 +#define RADEON_CP_CSQ_APER_PRIMARY 0x1000 +#define RADEON_CP_CSQ_APER_INDIRECT 0x1300 + +#define RADEON_CP_RB_WPTR_DELAY 0x0718 +# define RADEON_PRE_WRITE_TIMER_SHIFT 0 +# define RADEON_PRE_WRITE_LIMIT_SHIFT 23 + +#define RADEON_AIC_CNTL 0x01d0 +# define RADEON_PCIGART_TRANSLATE_EN (1 << 0) +#define RADEON_AIC_LO_ADDR 0x01dc + + + + /* Constants */ +#define RADEON_LAST_FRAME_REG RADEON_GUI_SCRATCH_REG0 +#define RADEON_LAST_CLEAR_REG RADEON_GUI_SCRATCH_REG2 + + + + /* CP packet types */ +#define RADEON_CP_PACKET0 0x00000000 +#define RADEON_CP_PACKET1 0x40000000 +#define RADEON_CP_PACKET2 0x80000000 +#define RADEON_CP_PACKET3 0xC0000000 +# define RADEON_CP_PACKET_MASK 0xC0000000 +# define RADEON_CP_PACKET_COUNT_MASK 0x3fff0000 +# define RADEON_CP_PACKET_MAX_DWORDS (1 << 12) +# define RADEON_CP_PACKET0_REG_MASK 0x000007ff +# define RADEON_CP_PACKET1_REG0_MASK 0x000007ff +# define RADEON_CP_PACKET1_REG1_MASK 0x003ff800 + +#define RADEON_CP_PACKET0_ONE_REG_WR 0x00008000 + +#define RADEON_CP_PACKET3_NOP 0xC0001000 +#define RADEON_CP_PACKET3_NEXT_CHAR 0xC0001900 +#define RADEON_CP_PACKET3_PLY_NEXTSCAN 0xC0001D00 +#define RADEON_CP_PACKET3_SET_SCISSORS 0xC0001E00 +#define RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM 0xC0002300 +#define RADEON_CP_PACKET3_LOAD_MICROCODE 0xC0002400 +#define RADEON_CP_PACKET3_WAIT_FOR_IDLE 0xC0002600 +#define RADEON_CP_PACKET3_3D_DRAW_VBUF 0xC0002800 +#define RADEON_CP_PACKET3_3D_DRAW_IMMD 0xC0002900 +#define RADEON_CP_PACKET3_3D_DRAW_INDX 0xC0002A00 +#define RADEON_CP_PACKET3_LOAD_PALETTE 0xC0002C00 +#define R200_CP_PACKET3_3D_DRAW_IMMD_2 0xc0003500 +#define RADEON_CP_PACKET3_3D_LOAD_VBPNTR 0xC0002F00 +#define RADEON_CP_PACKET3_CNTL_PAINT 0xC0009100 +#define RADEON_CP_PACKET3_CNTL_BITBLT 0xC0009200 +#define RADEON_CP_PACKET3_CNTL_SMALLTEXT 0xC0009300 +#define RADEON_CP_PACKET3_CNTL_HOSTDATA_BLT 0xC0009400 +#define RADEON_CP_PACKET3_CNTL_POLYLINE 0xC0009500 +#define RADEON_CP_PACKET3_CNTL_POLYSCANLINES 0xC0009800 +#define RADEON_CP_PACKET3_CNTL_PAINT_MULTI 0xC0009A00 +#define RADEON_CP_PACKET3_CNTL_BITBLT_MULTI 0xC0009B00 +#define RADEON_CP_PACKET3_CNTL_TRANS_BITBLT 0xC0009C00 + + +#define RADEON_CP_VC_FRMT_XY 0x00000000 +#define RADEON_CP_VC_FRMT_W0 0x00000001 +#define RADEON_CP_VC_FRMT_FPCOLOR 0x00000002 +#define RADEON_CP_VC_FRMT_FPALPHA 0x00000004 +#define RADEON_CP_VC_FRMT_PKCOLOR 0x00000008 +#define RADEON_CP_VC_FRMT_FPSPEC 0x00000010 +#define RADEON_CP_VC_FRMT_FPFOG 0x00000020 +#define RADEON_CP_VC_FRMT_PKSPEC 0x00000040 +#define RADEON_CP_VC_FRMT_ST0 0x00000080 +#define RADEON_CP_VC_FRMT_ST1 0x00000100 +#define RADEON_CP_VC_FRMT_Q1 0x00000200 +#define RADEON_CP_VC_FRMT_ST2 0x00000400 +#define RADEON_CP_VC_FRMT_Q2 0x00000800 +#define RADEON_CP_VC_FRMT_ST3 0x00001000 +#define RADEON_CP_VC_FRMT_Q3 0x00002000 +#define RADEON_CP_VC_FRMT_Q0 0x00004000 +#define RADEON_CP_VC_FRMT_BLND_WEIGHT_CNT_MASK 0x00038000 +#define RADEON_CP_VC_FRMT_N0 0x00040000 +#define RADEON_CP_VC_FRMT_XY1 0x08000000 +#define RADEON_CP_VC_FRMT_Z1 0x10000000 +#define RADEON_CP_VC_FRMT_W1 0x20000000 +#define RADEON_CP_VC_FRMT_N1 0x40000000 +#define RADEON_CP_VC_FRMT_Z 0x80000000 + +#define RADEON_CP_VC_CNTL_PRIM_TYPE_NONE 0x00000000 +#define RADEON_CP_VC_CNTL_PRIM_TYPE_POINT 0x00000001 +#define RADEON_CP_VC_CNTL_PRIM_TYPE_LINE 0x00000002 +#define RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP 0x00000003 +#define RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST 0x00000004 +#define RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN 0x00000005 +#define RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP 0x00000006 +#define RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_TYPE_2 0x00000007 +#define RADEON_CP_VC_CNTL_PRIM_TYPE_RECT_LIST 0x00000008 +#define RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_POINT_LIST 0x00000009 +#define RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_LINE_LIST 0x0000000a +#define RADEON_CP_VC_CNTL_PRIM_TYPE_QUAD_LIST 0x0000000d +#define RADEON_CP_VC_CNTL_PRIM_WALK_IND 0x00000010 +#define RADEON_CP_VC_CNTL_PRIM_WALK_LIST 0x00000020 +#define RADEON_CP_VC_CNTL_PRIM_WALK_RING 0x00000030 +#define RADEON_CP_VC_CNTL_COLOR_ORDER_BGRA 0x00000000 +#define RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA 0x00000040 +#define RADEON_CP_VC_CNTL_MAOS_ENABLE 0x00000080 +#define RADEON_CP_VC_CNTL_VTX_FMT_NON_RADEON_MODE 0x00000000 +#define RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE 0x00000100 +#define RADEON_CP_VC_CNTL_TCL_DISABLE 0x00000000 +#define RADEON_CP_VC_CNTL_TCL_ENABLE 0x00000200 +#define RADEON_CP_VC_CNTL_NUM_SHIFT 16 + +#define RADEON_VS_MATRIX_0_ADDR 0 +#define RADEON_VS_MATRIX_1_ADDR 4 +#define RADEON_VS_MATRIX_2_ADDR 8 +#define RADEON_VS_MATRIX_3_ADDR 12 +#define RADEON_VS_MATRIX_4_ADDR 16 +#define RADEON_VS_MATRIX_5_ADDR 20 +#define RADEON_VS_MATRIX_6_ADDR 24 +#define RADEON_VS_MATRIX_7_ADDR 28 +#define RADEON_VS_MATRIX_8_ADDR 32 +#define RADEON_VS_MATRIX_9_ADDR 36 +#define RADEON_VS_MATRIX_10_ADDR 40 +#define RADEON_VS_MATRIX_11_ADDR 44 +#define RADEON_VS_MATRIX_12_ADDR 48 +#define RADEON_VS_MATRIX_13_ADDR 52 +#define RADEON_VS_MATRIX_14_ADDR 56 +#define RADEON_VS_MATRIX_15_ADDR 60 +#define RADEON_VS_LIGHT_AMBIENT_ADDR 64 +#define RADEON_VS_LIGHT_DIFFUSE_ADDR 72 +#define RADEON_VS_LIGHT_SPECULAR_ADDR 80 +#define RADEON_VS_LIGHT_DIRPOS_ADDR 88 +#define RADEON_VS_LIGHT_HWVSPOT_ADDR 96 +#define RADEON_VS_LIGHT_ATTENUATION_ADDR 104 +#define RADEON_VS_MATRIX_EYE2CLIP_ADDR 112 +#define RADEON_VS_UCP_ADDR 116 +#define RADEON_VS_GLOBAL_AMBIENT_ADDR 122 +#define RADEON_VS_FOG_PARAM_ADDR 123 +#define RADEON_VS_EYE_VECTOR_ADDR 124 + +#define RADEON_SS_LIGHT_DCD_ADDR 0 +#define RADEON_SS_LIGHT_SPOT_EXPONENT_ADDR 8 +#define RADEON_SS_LIGHT_SPOT_CUTOFF_ADDR 16 +#define RADEON_SS_LIGHT_SPECULAR_THRESH_ADDR 24 +#define RADEON_SS_LIGHT_RANGE_CUTOFF_ADDR 32 +#define RADEON_SS_VERT_GUARD_CLIP_ADJ_ADDR 48 +#define RADEON_SS_VERT_GUARD_DISCARD_ADJ_ADDR 49 +#define RADEON_SS_HORZ_GUARD_CLIP_ADJ_ADDR 50 +#define RADEON_SS_HORZ_GUARD_DISCARD_ADJ_ADDR 51 +#define RADEON_SS_SHININESS 60 + +#define RADEON_TV_MASTER_CNTL 0x0800 +# define RADEON_TV_ASYNC_RST (1 << 0) +# define RADEON_CRT_ASYNC_RST (1 << 1) +# define RADEON_RESTART_PHASE_FIX (1 << 3) +# define RADEON_TV_FIFO_ASYNC_RST (1 << 4) +# define RADEON_VIN_ASYNC_RST (1 << 5) +# define RADEON_AUD_ASYNC_RST (1 << 6) +# define RADEON_DVS_ASYNC_RST (1 << 7) +# define RADEON_CRT_FIFO_CE_EN (1 << 9) +# define RADEON_TV_FIFO_CE_EN (1 << 10) +# define RADEON_RE_SYNC_NOW_SEL_MASK (3 << 14) +# define RADEON_TVCLK_ALWAYS_ONb (1 << 30) +# define RADEON_TV_ON (1 << 31) +#define RADEON_TV_PRE_DAC_MUX_CNTL 0x0888 +# define RADEON_Y_RED_EN (1 << 0) +# define RADEON_C_GRN_EN (1 << 1) +# define RADEON_CMP_BLU_EN (1 << 2) +# define RADEON_DAC_DITHER_EN (1 << 3) +# define RADEON_RED_MX_FORCE_DAC_DATA (6 << 4) +# define RADEON_GRN_MX_FORCE_DAC_DATA (6 << 8) +# define RADEON_BLU_MX_FORCE_DAC_DATA (6 << 12) +# define RADEON_TV_FORCE_DAC_DATA_SHIFT 16 +#define RADEON_TV_RGB_CNTL 0x0804 +# define RADEON_SWITCH_TO_BLUE (1 << 4) +# define RADEON_RGB_DITHER_EN (1 << 5) +# define RADEON_RGB_SRC_SEL_MASK (3 << 8) +# define RADEON_RGB_SRC_SEL_CRTC1 (0 << 8) +# define RADEON_RGB_SRC_SEL_RMX (1 << 8) +# define RADEON_RGB_SRC_SEL_CRTC2 (2 << 8) +# define RADEON_RGB_CONVERT_BY_PASS (1 << 10) +# define RADEON_UVRAM_READ_MARGIN_SHIFT 16 +# define RADEON_FIFORAM_FFMACRO_READ_MARGIN_SHIFT 20 +# define RADEON_RGB_ATTEN_SEL(x) ((x) << 24) +# define RADEON_TVOUT_SCALE_EN (1 << 26) +# define RADEON_RGB_ATTEN_VAL(x) ((x) << 28) +#define RADEON_TV_SYNC_CNTL 0x0808 +# define RADEON_SYNC_OE (1 << 0) +# define RADEON_SYNC_OUT (1 << 1) +# define RADEON_SYNC_IN (1 << 2) +# define RADEON_SYNC_PUB (1 << 3) +# define RADEON_SYNC_PD (1 << 4) +# define RADEON_TV_SYNC_IO_DRIVE (1 << 5) +#define RADEON_TV_HTOTAL 0x080c +#define RADEON_TV_HDISP 0x0810 +#define RADEON_TV_HSTART 0x0818 +#define RADEON_TV_HCOUNT 0x081C +#define RADEON_TV_VTOTAL 0x0820 +#define RADEON_TV_VDISP 0x0824 +#define RADEON_TV_VCOUNT 0x0828 +#define RADEON_TV_FTOTAL 0x082c +#define RADEON_TV_FCOUNT 0x0830 +#define RADEON_TV_FRESTART 0x0834 +#define RADEON_TV_HRESTART 0x0838 +#define RADEON_TV_VRESTART 0x083c +#define RADEON_TV_HOST_READ_DATA 0x0840 +#define RADEON_TV_HOST_WRITE_DATA 0x0844 +#define RADEON_TV_HOST_RD_WT_CNTL 0x0848 +# define RADEON_HOST_FIFO_RD (1 << 12) +# define RADEON_HOST_FIFO_RD_ACK (1 << 13) +# define RADEON_HOST_FIFO_WT (1 << 14) +# define RADEON_HOST_FIFO_WT_ACK (1 << 15) +#define RADEON_TV_VSCALER_CNTL1 0x084c +# define RADEON_UV_INC_MASK 0xffff +# define RADEON_UV_INC_SHIFT 0 +# define RADEON_Y_W_EN (1 << 24) +# define RADEON_RESTART_FIELD (1 << 29) /* restart on field 0 */ +# define RADEON_Y_DEL_W_SIG_SHIFT 26 +#define RADEON_TV_TIMING_CNTL 0x0850 +# define RADEON_H_INC_MASK 0xfff +# define RADEON_H_INC_SHIFT 0 +# define RADEON_REQ_Y_FIRST (1 << 19) +# define RADEON_FORCE_BURST_ALWAYS (1 << 21) +# define RADEON_UV_POST_SCALE_BYPASS (1 << 23) +# define RADEON_UV_OUTPUT_POST_SCALE_SHIFT 24 +#define RADEON_TV_VSCALER_CNTL2 0x0854 +# define RADEON_DITHER_MODE (1 << 0) +# define RADEON_Y_OUTPUT_DITHER_EN (1 << 1) +# define RADEON_UV_OUTPUT_DITHER_EN (1 << 2) +# define RADEON_UV_TO_BUF_DITHER_EN (1 << 3) +#define RADEON_TV_Y_FALL_CNTL 0x0858 +# define RADEON_Y_FALL_PING_PONG (1 << 16) +# define RADEON_Y_COEF_EN (1 << 17) +#define RADEON_TV_Y_RISE_CNTL 0x085c +# define RADEON_Y_RISE_PING_PONG (1 << 16) +#define RADEON_TV_Y_SAW_TOOTH_CNTL 0x0860 +#define RADEON_TV_UPSAMP_AND_GAIN_CNTL 0x0864 +# define RADEON_YUPSAMP_EN (1 << 0) +# define RADEON_UVUPSAMP_EN (1 << 2) +#define RADEON_TV_GAIN_LIMIT_SETTINGS 0x0868 +# define RADEON_Y_GAIN_LIMIT_SHIFT 0 +# define RADEON_UV_GAIN_LIMIT_SHIFT 16 +#define RADEON_TV_LINEAR_GAIN_SETTINGS 0x086c +# define RADEON_Y_GAIN_SHIFT 0 +# define RADEON_UV_GAIN_SHIFT 16 +#define RADEON_TV_MODULATOR_CNTL1 0x0870 +# define RADEON_YFLT_EN (1 << 2) +# define RADEON_UVFLT_EN (1 << 3) +# define RADEON_ALT_PHASE_EN (1 << 6) +# define RADEON_SYNC_TIP_LEVEL (1 << 7) +# define RADEON_BLANK_LEVEL_SHIFT 8 +# define RADEON_SET_UP_LEVEL_SHIFT 16 +# define RADEON_SLEW_RATE_LIMIT (1 << 23) +# define RADEON_CY_FILT_BLEND_SHIFT 28 +#define RADEON_TV_MODULATOR_CNTL2 0x0874 +# define RADEON_TV_U_BURST_LEVEL_MASK 0x1ff +# define RADEON_TV_V_BURST_LEVEL_MASK 0x1ff +# define RADEON_TV_V_BURST_LEVEL_SHIFT 16 +#define RADEON_TV_CRC_CNTL 0x0890 +#define RADEON_TV_UV_ADR 0x08ac +# define RADEON_MAX_UV_ADR_MASK 0x000000ff +# define RADEON_MAX_UV_ADR_SHIFT 0 +# define RADEON_TABLE1_BOT_ADR_MASK 0x0000ff00 +# define RADEON_TABLE1_BOT_ADR_SHIFT 8 +# define RADEON_TABLE3_TOP_ADR_MASK 0x00ff0000 +# define RADEON_TABLE3_TOP_ADR_SHIFT 16 +# define RADEON_HCODE_TABLE_SEL_MASK 0x06000000 +# define RADEON_HCODE_TABLE_SEL_SHIFT 25 +# define RADEON_VCODE_TABLE_SEL_MASK 0x18000000 +# define RADEON_VCODE_TABLE_SEL_SHIFT 27 +# define RADEON_TV_MAX_FIFO_ADDR 0x1a7 +# define RADEON_TV_MAX_FIFO_ADDR_INTERNAL 0x1ff +#define RADEON_TV_PLL_FINE_CNTL 0x0020 /* PLL */ +#define RADEON_TV_PLL_CNTL 0x0021 /* PLL */ +# define RADEON_TV_M0LO_MASK 0xff +# define RADEON_TV_M0HI_MASK 0x7 +# define RADEON_TV_M0HI_SHIFT 18 +# define RADEON_TV_N0LO_MASK 0x1ff +# define RADEON_TV_N0LO_SHIFT 8 +# define RADEON_TV_N0HI_MASK 0x3 +# define RADEON_TV_N0HI_SHIFT 21 +# define RADEON_TV_P_MASK 0xf +# define RADEON_TV_P_SHIFT 24 +# define RADEON_TV_SLIP_EN (1 << 23) +# define RADEON_TV_DTO_EN (1 << 28) +#define RADEON_TV_PLL_CNTL1 0x0022 /* PLL */ +# define RADEON_TVPLL_RESET (1 << 1) +# define RADEON_TVPLL_SLEEP (1 << 3) +# define RADEON_TVPLL_REFCLK_SEL (1 << 4) +# define RADEON_TVPCP_SHIFT 8 +# define RADEON_TVPCP_MASK (7 << 8) +# define RADEON_TVPVG_SHIFT 11 +# define RADEON_TVPVG_MASK (7 << 11) +# define RADEON_TVPDC_SHIFT 14 +# define RADEON_TVPDC_MASK (3 << 14) +# define RADEON_TVPLL_TEST_DIS (1 << 31) +# define RADEON_TVCLK_SRC_SEL_TVPLL (1 << 30) + +#define RS400_DISP2_REQ_CNTL1 0xe30 +# define RS400_DISP2_START_REQ_LEVEL_SHIFT 0 +# define RS400_DISP2_START_REQ_LEVEL_MASK 0x3ff +# define RS400_DISP2_STOP_REQ_LEVEL_SHIFT 12 +# define RS400_DISP2_STOP_REQ_LEVEL_MASK 0x3ff +# define RS400_DISP2_ALLOW_FID_LEVEL_SHIFT 22 +# define RS400_DISP2_ALLOW_FID_LEVEL_MASK 0x3ff +#define RS400_DISP2_REQ_CNTL2 0xe34 +# define RS400_DISP2_CRITICAL_POINT_START_SHIFT 12 +# define RS400_DISP2_CRITICAL_POINT_START_MASK 0x3ff +# define RS400_DISP2_CRITICAL_POINT_STOP_SHIFT 22 +# define RS400_DISP2_CRITICAL_POINT_STOP_MASK 0x3ff +#define RS400_DMIF_MEM_CNTL1 0xe38 +# define RS400_DISP2_START_ADR_SHIFT 0 +# define RS400_DISP2_START_ADR_MASK 0x3ff +# define RS400_DISP1_CRITICAL_POINT_START_SHIFT 12 +# define RS400_DISP1_CRITICAL_POINT_START_MASK 0x3ff +# define RS400_DISP1_CRITICAL_POINT_STOP_SHIFT 22 +# define RS400_DISP1_CRITICAL_POINT_STOP_MASK 0x3ff +#define RS400_DISP1_REQ_CNTL1 0xe3c +# define RS400_DISP1_START_REQ_LEVEL_SHIFT 0 +# define RS400_DISP1_START_REQ_LEVEL_MASK 0x3ff +# define RS400_DISP1_STOP_REQ_LEVEL_SHIFT 12 +# define RS400_DISP1_STOP_REQ_LEVEL_MASK 0x3ff +# define RS400_DISP1_ALLOW_FID_LEVEL_SHIFT 22 +# define RS400_DISP1_ALLOW_FID_LEVEL_MASK 0x3ff + +#define RS690_MC_INDEX 0x78 +# define RS690_MC_INDEX_MASK 0x1ff +# define RS690_MC_INDEX_WR_EN (1 << 9) +# define RS690_MC_INDEX_WR_ACK 0x7f +#define RS690_MC_DATA 0x7c + +#define RS690_MC_FB_LOCATION 0x100 +#define RS690_MC_AGP_LOCATION 0x101 +#define RS690_MC_AGP_BASE 0x102 +#define RS690_MC_AGP_BASE_2 0x103 +#define RS690_MC_INIT_MISC_LAT_TIMER 0x104 +#define RS690_MC_STATUS 0x90 +#define RS690_MC_STATUS_IDLE (1 << 0) + +#define RS600_MC_INDEX 0x70 +# define RS600_MC_ADDR_MASK 0xffff +# define RS600_MC_IND_SEQ_RBS_0 (1 << 16) +# define RS600_MC_IND_SEQ_RBS_1 (1 << 17) +# define RS600_MC_IND_SEQ_RBS_2 (1 << 18) +# define RS600_MC_IND_SEQ_RBS_3 (1 << 19) +# define RS600_MC_IND_AIC_RBS (1 << 20) +# define RS600_MC_IND_CITF_ARB0 (1 << 21) +# define RS600_MC_IND_CITF_ARB1 (1 << 22) +# define RS600_MC_IND_WR_EN (1 << 23) +#define RS600_MC_DATA 0x74 + +#define RS600_MC_STATUS 0x0 +# define RS600_MC_IDLE (1 << 1) +#define RS600_MC_FB_LOCATION 0x4 +#define RS600_MC_AGP_LOCATION 0x5 +#define RS600_AGP_BASE 0x6 +#define RS600_AGP_BASE2 0x7 + +#define AVIVO_MC_INDEX 0x0070 +#define R520_MC_STATUS 0x00 +# define R520_MC_STATUS_IDLE (1 << 1) +#define RV515_MC_STATUS 0x08 +# define RV515_MC_STATUS_IDLE (1 << 4) +#define RV515_MC_INIT_MISC_LAT_TIMER 0x09 +#define AVIVO_MC_DATA 0x0074 + +#define RV515_MC_FB_LOCATION 0x1 +#define RV515_MC_AGP_LOCATION 0x2 +#define RV515_MC_AGP_BASE 0x3 +#define RV515_MC_AGP_BASE_2 0x4 +#define RV515_MC_CNTL 0x5 +# define RV515_MEM_NUM_CHANNELS_MASK 0x3 +#define R520_MC_FB_LOCATION 0x4 +#define R520_MC_AGP_LOCATION 0x5 +#define R520_MC_AGP_BASE 0x6 +#define R520_MC_AGP_BASE_2 0x7 +#define R520_MC_CNTL0 0x8 +# define R520_MEM_NUM_CHANNELS_MASK (0x3 << 24) +# define R520_MEM_NUM_CHANNELS_SHIFT 24 +# define R520_MC_CHANNEL_SIZE (1 << 23) + +#define RS780_MC_INDEX 0x28f8 +# define RS780_MC_INDEX_MASK 0x1ff +# define RS780_MC_INDEX_WR_EN (1 << 9) +#define RS780_MC_DATA 0x28fc + +#define R600_RAMCFG 0x2408 +# define R600_CHANSIZE (1 << 7) +# define R600_CHANSIZE_OVERRIDE (1 << 10) + +#define R600_SRBM_STATUS 0x0e50 + +#define AVIVO_CP_DYN_CNTL 0x000f /* PLL */ +# define AVIVO_CP_FORCEON (1 << 0) +#define AVIVO_E2_DYN_CNTL 0x0011 /* PLL */ +# define AVIVO_E2_FORCEON (1 << 0) +#define AVIVO_IDCT_DYN_CNTL 0x0013 /* PLL */ +# define AVIVO_IDCT_FORCEON (1 << 0) + +#define AVIVO_HDP_FB_LOCATION 0x134 + +#define AVIVO_VGA_RENDER_CONTROL 0x0300 +# define AVIVO_VGA_VSTATUS_CNTL_MASK (3 << 16) +#define AVIVO_D1VGA_CONTROL 0x0330 +# define AVIVO_DVGA_CONTROL_MODE_ENABLE (1<<0) +# define AVIVO_DVGA_CONTROL_TIMING_SELECT (1<<8) +# define AVIVO_DVGA_CONTROL_SYNC_POLARITY_SELECT (1<<9) +# define AVIVO_DVGA_CONTROL_OVERSCAN_TIMING_SELECT (1<<10) +# define AVIVO_DVGA_CONTROL_OVERSCAN_COLOR_EN (1<<16) +# define AVIVO_DVGA_CONTROL_ROTATE (1<<24) +#define AVIVO_D2VGA_CONTROL 0x0338 + +#define AVIVO_VGA25_PPLL_REF_DIV_SRC 0x0360 +#define AVIVO_VGA25_PPLL_REF_DIV 0x0364 +#define AVIVO_VGA28_PPLL_REF_DIV_SRC 0x0368 +#define AVIVO_VGA28_PPLL_REF_DIV 0x036c +#define AVIVO_VGA41_PPLL_REF_DIV_SRC 0x0370 +#define AVIVO_VGA41_PPLL_REF_DIV 0x0374 +#define AVIVO_VGA25_PPLL_FB_DIV 0x0378 +#define AVIVO_VGA28_PPLL_FB_DIV 0x037c +#define AVIVO_VGA41_PPLL_FB_DIV 0x0380 +#define AVIVO_VGA25_PPLL_POST_DIV_SRC 0x0384 +#define AVIVO_VGA25_PPLL_POST_DIV 0x0388 +#define AVIVO_VGA28_PPLL_POST_DIV_SRC 0x038c +#define AVIVO_VGA28_PPLL_POST_DIV 0x0390 +#define AVIVO_VGA41_PPLL_POST_DIV_SRC 0x0394 +#define AVIVO_VGA41_PPLL_POST_DIV 0x0398 +#define AVIVO_VGA25_PPLL_CNTL 0x039c +#define AVIVO_VGA28_PPLL_CNTL 0x03a0 +#define AVIVO_VGA41_PPLL_CNTL 0x03a4 + +#define AVIVO_EXT1_PPLL_REF_DIV_SRC 0x400 +#define AVIVO_EXT1_PPLL_REF_DIV 0x404 +#define AVIVO_EXT1_PPLL_UPDATE_LOCK 0x408 +#define AVIVO_EXT1_PPLL_UPDATE_CNTL 0x40c + +#define AVIVO_EXT2_PPLL_REF_DIV_SRC 0x410 +#define AVIVO_EXT2_PPLL_REF_DIV 0x414 +#define AVIVO_EXT2_PPLL_UPDATE_LOCK 0x418 +#define AVIVO_EXT2_PPLL_UPDATE_CNTL 0x41c + +#define AVIVO_EXT1_PPLL_FB_DIV 0x430 +#define AVIVO_EXT2_PPLL_FB_DIV 0x434 + +#define AVIVO_EXT1_PPLL_POST_DIV_SRC 0x438 +#define AVIVO_EXT1_PPLL_POST_DIV 0x43c + +#define AVIVO_EXT2_PPLL_POST_DIV_SRC 0x440 +#define AVIVO_EXT2_PPLL_POST_DIV 0x444 + +#define AVIVO_EXT1_PPLL_CNTL 0x448 +#define AVIVO_EXT2_PPLL_CNTL 0x44c + +#define AVIVO_P1PLL_CNTL 0x450 +#define AVIVO_P2PLL_CNTL 0x454 +#define AVIVO_P1PLL_INT_SS_CNTL 0x458 +#define AVIVO_P2PLL_INT_SS_CNTL 0x45c +#define AVIVO_P1PLL_TMDSA_CNTL 0x460 +#define AVIVO_P2PLL_LVTMA_CNTL 0x464 + +#define AVIVO_PCLK_CRTC1_CNTL 0x480 +#define AVIVO_PCLK_CRTC2_CNTL 0x484 + +#define AVIVO_D1CRTC_H_TOTAL 0x6000 +#define AVIVO_D1CRTC_H_BLANK_START_END 0x6004 +#define AVIVO_D1CRTC_H_SYNC_A 0x6008 +#define AVIVO_D1CRTC_H_SYNC_A_CNTL 0x600c +#define AVIVO_D1CRTC_H_SYNC_B 0x6010 +#define AVIVO_D1CRTC_H_SYNC_B_CNTL 0x6014 + +#define AVIVO_D1CRTC_V_TOTAL 0x6020 +#define AVIVO_D1CRTC_V_BLANK_START_END 0x6024 +#define AVIVO_D1CRTC_V_SYNC_A 0x6028 +#define AVIVO_D1CRTC_V_SYNC_A_CNTL 0x602c +#define AVIVO_D1CRTC_V_SYNC_B 0x6030 +#define AVIVO_D1CRTC_V_SYNC_B_CNTL 0x6034 + +#define AVIVO_D1CRTC_CONTROL 0x6080 +# define AVIVO_CRTC_EN (1<<0) +#define AVIVO_D1CRTC_BLANK_CONTROL 0x6084 +#define AVIVO_D1CRTC_INTERLACE_CONTROL 0x6088 +#define AVIVO_D1CRTC_INTERLACE_STATUS 0x608c +#define AVIVO_D1CRTC_STEREO_CONTROL 0x60c4 + +/* master controls */ +#define AVIVO_DC_CRTC_MASTER_EN 0x60f8 +#define AVIVO_DC_CRTC_TV_CONTROL 0x60fc + +#define AVIVO_D1GRPH_ENABLE 0x6100 +#define AVIVO_D1GRPH_CONTROL 0x6104 +# define AVIVO_D1GRPH_CONTROL_DEPTH_8BPP (0<<0) +# define AVIVO_D1GRPH_CONTROL_DEPTH_16BPP (1<<0) +# define AVIVO_D1GRPH_CONTROL_DEPTH_32BPP (2<<0) +# define AVIVO_D1GRPH_CONTROL_DEPTH_64BPP (3<<0) + +# define AVIVO_D1GRPH_CONTROL_8BPP_INDEXED (0<<8) + +# define AVIVO_D1GRPH_CONTROL_16BPP_ARGB1555 (0<<8) +# define AVIVO_D1GRPH_CONTROL_16BPP_RGB565 (1<<8) +# define AVIVO_D1GRPH_CONTROL_16BPP_ARGB4444 (2<<8) +# define AVIVO_D1GRPH_CONTROL_16BPP_AI88 (3<<8) +# define AVIVO_D1GRPH_CONTROL_16BPP_MONO16 (4<<8) + +# define AVIVO_D1GRPH_CONTROL_32BPP_ARGB8888 (0<<8) +# define AVIVO_D1GRPH_CONTROL_32BPP_ARGB2101010 (1<<8) +# define AVIVO_D1GRPH_CONTROL_32BPP_DIGITAL (2<<8) +# define AVIVO_D1GRPH_CONTROL_32BPP_8B_ARGB2101010 (3<<8) + + +# define AVIVO_D1GRPH_CONTROL_64BPP_ARGB16161616 (0<<8) + +# define AVIVO_D1GRPH_SWAP_RB (1<<16) +# define AVIVO_D1GRPH_TILED (1<<20) +# define AVIVO_D1GRPH_MACRO_ADDRESS_MODE (1<<21) + +#define AVIVO_D1GRPH_LUT_SEL 0x6108 + +#define R600_D1GRPH_SWAP_CONTROL 0x610C +# define R600_D1GRPH_SWAP_ENDIAN_NONE (0 << 0) +# define R600_D1GRPH_SWAP_ENDIAN_16BIT (1 << 0) +# define R600_D1GRPH_SWAP_ENDIAN_32BIT (2 << 0) +# define R600_D1GRPH_SWAP_ENDIAN_64BIT (3 << 0) + +/* the *_HIGH surface regs are backwards; the D1 regs are in the D2 + * block and vice versa. This applies to GRPH, CUR, etc. + */ + +#define AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS 0x6110 +#define R700_D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH 0x6914 +#define R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH 0x6114 +#define AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS 0x6118 +#define R700_D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x691c +#define R700_D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x611c +#define AVIVO_D1GRPH_PITCH 0x6120 +#define AVIVO_D1GRPH_SURFACE_OFFSET_X 0x6124 +#define AVIVO_D1GRPH_SURFACE_OFFSET_Y 0x6128 +#define AVIVO_D1GRPH_X_START 0x612c +#define AVIVO_D1GRPH_Y_START 0x6130 +#define AVIVO_D1GRPH_X_END 0x6134 +#define AVIVO_D1GRPH_Y_END 0x6138 +#define AVIVO_D1GRPH_UPDATE 0x6144 +# define AVIVO_D1GRPH_UPDATE_LOCK (1<<16) +#define AVIVO_D1GRPH_FLIP_CONTROL 0x6148 + +#define AVIVO_D1GRPH_COLOR_MATRIX_TRANSFORMATION_CNTL 0x6380 + +#define AVIVO_D1CUR_CONTROL 0x6400 +# define AVIVO_D1CURSOR_EN (1<<0) +# define AVIVO_D1CURSOR_MODE_SHIFT 8 +# define AVIVO_D1CURSOR_MODE_MASK (0x3<<8) +# define AVIVO_D1CURSOR_MODE_24BPP (0x2) +#define AVIVO_D1CUR_SURFACE_ADDRESS 0x6408 +#define R700_D1CUR_SURFACE_ADDRESS_HIGH 0x6c0c +#define R700_D2CUR_SURFACE_ADDRESS_HIGH 0x640c +#define AVIVO_D1CUR_SIZE 0x6410 +#define AVIVO_D1CUR_POSITION 0x6414 +#define AVIVO_D1CUR_HOT_SPOT 0x6418 +#define AVIVO_D1CUR_UPDATE 0x6424 +# define AVIVO_D1CURSOR_UPDATE_LOCK (1 << 16) + +#define AVIVO_DC_LUT_RW_SELECT 0x6480 +#define AVIVO_DC_LUT_RW_MODE 0x6484 +#define AVIVO_DC_LUT_RW_INDEX 0x6488 +#define AVIVO_DC_LUT_SEQ_COLOR 0x648c +#define AVIVO_DC_LUT_PWL_DATA 0x6490 +#define AVIVO_DC_LUT_30_COLOR 0x6494 +#define AVIVO_DC_LUT_READ_PIPE_SELECT 0x6498 +#define AVIVO_DC_LUT_WRITE_EN_MASK 0x649c +#define AVIVO_DC_LUT_AUTOFILL 0x64a0 + +#define AVIVO_DC_LUTA_CONTROL 0x64c0 +#define AVIVO_DC_LUTA_BLACK_OFFSET_BLUE 0x64c4 +#define AVIVO_DC_LUTA_BLACK_OFFSET_GREEN 0x64c8 +#define AVIVO_DC_LUTA_BLACK_OFFSET_RED 0x64cc +#define AVIVO_DC_LUTA_WHITE_OFFSET_BLUE 0x64d0 +#define AVIVO_DC_LUTA_WHITE_OFFSET_GREEN 0x64d4 +#define AVIVO_DC_LUTA_WHITE_OFFSET_RED 0x64d8 + +#define AVIVO_DC_LB_MEMORY_SPLIT 0x6520 +# define AVIVO_DC_LB_MEMORY_SPLIT_MASK 0x3 +# define AVIVO_DC_LB_MEMORY_SPLIT_SHIFT 0 +# define AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF 0 +# define AVIVO_DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q 1 +# define AVIVO_DC_LB_MEMORY_SPLIT_D1_ONLY 2 +# define AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q 3 +# define AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE (1 << 2) +# define AVIVO_DC_LB_DISP1_END_ADR_SHIFT 4 +# define AVIVO_DC_LB_DISP1_END_ADR_MASK 0x7ff +#define AVIVO_D1MODE_PRIORITY_A_CNT 0x6548 +# define AVIVO_DxMODE_PRIORITY_MARK_MASK 0x7fff +# define AVIVO_DxMODE_PRIORITY_OFF (1 << 16) +# define AVIVO_DxMODE_PRIORITY_ALWAYS_ON (1 << 20) +# define AVIVO_DxMODE_PRIORITY_FORCE_MASK (1 << 24) +#define AVIVO_D1MODE_PRIORITY_B_CNT 0x654c +#define AVIVO_D2MODE_PRIORITY_A_CNT 0x6d48 +#define AVIVO_D2MODE_PRIORITY_B_CNT 0x6d4c +#define AVIVO_LB_MAX_REQ_OUTSTANDING 0x6d58 +# define AVIVO_LB_D1_MAX_REQ_OUTSTANDING_MASK 0xf +# define AVIVO_LB_D1_MAX_REQ_OUTSTANDING_SHIFT 0 +# define AVIVO_LB_D2_MAX_REQ_OUTSTANDING_MASK 0xf +# define AVIVO_LB_D2_MAX_REQ_OUTSTANDING_SHIFT 16 + +#define AVIVO_D1MODE_DATA_FORMAT 0x6528 +# define AVIVO_D1MODE_INTERLEAVE_EN (1 << 0) +#define AVIVO_D1MODE_DESKTOP_HEIGHT 0x652c +#define AVIVO_D1MODE_VLINE_START_END 0x6538 +# define AVIVO_D1MODE_VLINE_START_SHIFT 0 +# define AVIVO_D1MODE_VLINE_END_SHIFT 16 +# define AVIVO_D1MODE_VLINE_INV (1 << 31) +#define AVIVO_D1MODE_VLINE_STATUS 0x653c +# define AVIVO_D1MODE_VLINE_STAT (1 << 12) +#define AVIVO_D1MODE_VIEWPORT_START 0x6580 +#define AVIVO_D1MODE_VIEWPORT_SIZE 0x6584 +#define AVIVO_D1MODE_EXT_OVERSCAN_LEFT_RIGHT 0x6588 +#define AVIVO_D1MODE_EXT_OVERSCAN_TOP_BOTTOM 0x658c + +#define AVIVO_D1SCL_SCALER_ENABLE 0x6590 +#define AVIVO_D1SCL_SCALER_TAP_CONTROL 0x6594 +#define AVIVO_D1SCL_UPDATE 0x65cc +# define AVIVO_D1SCL_UPDATE_LOCK (1<<16) + +/* second crtc */ +#define AVIVO_D2CRTC_H_TOTAL 0x6800 +#define AVIVO_D2CRTC_H_BLANK_START_END 0x6804 +#define AVIVO_D2CRTC_H_SYNC_A 0x6808 +#define AVIVO_D2CRTC_H_SYNC_A_CNTL 0x680c +#define AVIVO_D2CRTC_H_SYNC_B 0x6810 +#define AVIVO_D2CRTC_H_SYNC_B_CNTL 0x6814 + +#define AVIVO_D2CRTC_V_TOTAL 0x6820 +#define AVIVO_D2CRTC_V_BLANK_START_END 0x6824 +#define AVIVO_D2CRTC_V_SYNC_A 0x6828 +#define AVIVO_D2CRTC_V_SYNC_A_CNTL 0x682c +#define AVIVO_D2CRTC_V_SYNC_B 0x6830 +#define AVIVO_D2CRTC_V_SYNC_B_CNTL 0x6834 + +#define AVIVO_D2CRTC_CONTROL 0x6880 +#define AVIVO_D2CRTC_BLANK_CONTROL 0x6884 +#define AVIVO_D2CRTC_INTERLACE_CONTROL 0x6888 +#define AVIVO_D2CRTC_INTERLACE_STATUS 0x688c +#define AVIVO_D2CRTC_STEREO_CONTROL 0x68c4 + +#define AVIVO_D2GRPH_ENABLE 0x6900 +#define AVIVO_D2GRPH_CONTROL 0x6904 +#define AVIVO_D2GRPH_LUT_SEL 0x6908 +#define AVIVO_D2GRPH_PRIMARY_SURFACE_ADDRESS 0x6910 +#define AVIVO_D2GRPH_SECONDARY_SURFACE_ADDRESS 0x6918 +#define AVIVO_D2GRPH_PITCH 0x6920 +#define AVIVO_D2GRPH_SURFACE_OFFSET_X 0x6924 +#define AVIVO_D2GRPH_SURFACE_OFFSET_Y 0x6928 +#define AVIVO_D2GRPH_X_START 0x692c +#define AVIVO_D2GRPH_Y_START 0x6930 +#define AVIVO_D2GRPH_X_END 0x6934 +#define AVIVO_D2GRPH_Y_END 0x6938 +#define AVIVO_D2GRPH_UPDATE 0x6944 +#define AVIVO_D2GRPH_FLIP_CONTROL 0x6948 + +#define AVIVO_D2CUR_CONTROL 0x6c00 +#define AVIVO_D2CUR_SURFACE_ADDRESS 0x6c08 +#define AVIVO_D2CUR_SIZE 0x6c10 +#define AVIVO_D2CUR_POSITION 0x6c14 + +#define RS690_DCP_CONTROL 0x6c9c + +#define AVIVO_D2MODE_DATA_FORMAT 0x6d28 +#define AVIVO_D2MODE_DESKTOP_HEIGHT 0x6d2c +#define AVIVO_D2MODE_VIEWPORT_START 0x6d80 +#define AVIVO_D2MODE_VIEWPORT_SIZE 0x6d84 +#define AVIVO_D2MODE_EXT_OVERSCAN_LEFT_RIGHT 0x6d88 +#define AVIVO_D2MODE_EXT_OVERSCAN_TOP_BOTTOM 0x6d8c + +#define AVIVO_D2SCL_SCALER_ENABLE 0x6d90 +#define AVIVO_D2SCL_SCALER_TAP_CONTROL 0x6d94 +#define AVIVO_D2SCL_UPDATE 0x6dcc + +#define AVIVO_DDIA_BIT_DEPTH_CONTROL 0x7214 + +#define AVIVO_DACA_ENABLE 0x7800 +# define AVIVO_DAC_ENABLE (1 << 0) +#define AVIVO_DACA_SOURCE_SELECT 0x7804 +# define AVIVO_DAC_SOURCE_CRTC1 (0 << 0) +# define AVIVO_DAC_SOURCE_CRTC2 (1 << 0) +# define AVIVO_DAC_SOURCE_TV (2 << 0) + +#define AVIVO_DACA_FORCE_OUTPUT_CNTL 0x783c +# define AVIVO_DACA_FORCE_OUTPUT_CNTL_FORCE_DATA_EN (1 << 0) +# define AVIVO_DACA_FORCE_OUTPUT_CNTL_DATA_SEL_SHIFT (8) +# define AVIVO_DACA_FORCE_OUTPUT_CNTL_DATA_SEL_BLUE (1 << 0) +# define AVIVO_DACA_FORCE_OUTPUT_CNTL_DATA_SEL_GREEN (1 << 1) +# define AVIVO_DACA_FORCE_OUTPUT_CNTL_DATA_SEL_RED (1 << 2) +# define AVIVO_DACA_FORCE_OUTPUT_CNTL_DATA_ON_BLANKB_ONLY (1 << 24) +#define AVIVO_DACA_POWERDOWN 0x7850 +# define AVIVO_DACA_POWERDOWN_POWERDOWN (1 << 0) +# define AVIVO_DACA_POWERDOWN_BLUE (1 << 8) +# define AVIVO_DACA_POWERDOWN_GREEN (1 << 16) +# define AVIVO_DACA_POWERDOWN_RED (1 << 24) + +#define AVIVO_DACB_ENABLE 0x7a00 +#define AVIVO_DACB_SOURCE_SELECT 0x7a04 +#define AVIVO_DACB_FORCE_OUTPUT_CNTL 0x7a3c +# define AVIVO_DACB_FORCE_OUTPUT_CNTL_FORCE_DATA_EN (1 << 0) +# define AVIVO_DACB_FORCE_OUTPUT_CNTL_DATA_SEL_SHIFT (8) +# define AVIVO_DACB_FORCE_OUTPUT_CNTL_DATA_SEL_BLUE (1 << 0) +# define AVIVO_DACB_FORCE_OUTPUT_CNTL_DATA_SEL_GREEN (1 << 1) +# define AVIVO_DACB_FORCE_OUTPUT_CNTL_DATA_SEL_RED (1 << 2) +# define AVIVO_DACB_FORCE_OUTPUT_CNTL_DATA_ON_BLANKB_ONLY (1 << 24) +#define AVIVO_DACB_POWERDOWN 0x7a50 +# define AVIVO_DACB_POWERDOWN_POWERDOWN (1 << 0) +# define AVIVO_DACB_POWERDOWN_BLUE (1 << 8) +# define AVIVO_DACB_POWERDOWN_GREEN (1 << 16) +# define AVIVO_DACB_POWERDOWN_RED + +#define AVIVO_TMDSA_CNTL 0x7880 +# define AVIVO_TMDSA_CNTL_ENABLE (1 << 0) +# define AVIVO_TMDSA_CNTL_HPD_MASK (1 << 4) +# define AVIVO_TMDSA_CNTL_HPD_SELECT (1 << 8) +# define AVIVO_TMDSA_CNTL_SYNC_PHASE (1 << 12) +# define AVIVO_TMDSA_CNTL_PIXEL_ENCODING (1 << 16) +# define AVIVO_TMDSA_CNTL_DUAL_LINK_ENABLE (1 << 24) +# define AVIVO_TMDSA_CNTL_SWAP (1 << 28) +#define AVIVO_TMDSA_SOURCE_SELECT 0x7884 +/* 78a8 appears to be some kind of (reasonably tolerant) clock? + * 78d0 definitely hits the transmitter, definitely clock. */ +/* MYSTERY1 This appears to control dithering? */ +#define AVIVO_TMDSA_BIT_DEPTH_CONTROL 0x7894 +# define AVIVO_TMDS_BIT_DEPTH_CONTROL_TRUNCATE_EN (1 << 0) +# define AVIVO_TMDS_BIT_DEPTH_CONTROL_TRUNCATE_DEPTH (1 << 4) +# define AVIVO_TMDS_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN (1 << 8) +# define AVIVO_TMDS_BIT_DEPTH_CONTROL_SPATIAL_DITHER_DEPTH (1 << 12) +# define AVIVO_TMDS_BIT_DEPTH_CONTROL_TEMPORAL_DITHER_EN (1 << 16) +# define AVIVO_TMDS_BIT_DEPTH_CONTROL_TEMPORAL_DITHER_DEPTH (1 << 20) +# define AVIVO_TMDS_BIT_DEPTH_CONTROL_TEMPORAL_LEVEL (1 << 24) +# define AVIVO_TMDS_BIT_DEPTH_CONTROL_TEMPORAL_DITHER_RESET (1 << 26) +#define AVIVO_TMDSA_DCBALANCER_CONTROL 0x78d0 +# define AVIVO_TMDSA_DCBALANCER_CONTROL_EN (1 << 0) +# define AVIVO_TMDSA_DCBALANCER_CONTROL_TEST_EN (1 << 8) +# define AVIVO_TMDSA_DCBALANCER_CONTROL_TEST_IN_SHIFT (16) +# define AVIVO_TMDSA_DCBALANCER_CONTROL_FORCE (1 << 24) +#define AVIVO_TMDSA_DATA_SYNCHRONIZATION 0x78d8 +# define AVIVO_TMDSA_DATA_SYNCHRONIZATION_DSYNSEL (1 << 0) +# define AVIVO_TMDSA_DATA_SYNCHRONIZATION_PFREQCHG (1 << 8) +#define AVIVO_TMDSA_CLOCK_ENABLE 0x7900 +#define AVIVO_TMDSA_TRANSMITTER_ENABLE 0x7904 +# define AVIVO_TMDSA_TRANSMITTER_ENABLE_TX0_ENABLE (1 << 0) +# define AVIVO_TMDSA_TRANSMITTER_ENABLE_LNKC0EN (1 << 1) +# define AVIVO_TMDSA_TRANSMITTER_ENABLE_LNKD00EN (1 << 2) +# define AVIVO_TMDSA_TRANSMITTER_ENABLE_LNKD01EN (1 << 3) +# define AVIVO_TMDSA_TRANSMITTER_ENABLE_LNKD02EN (1 << 4) +# define AVIVO_TMDSA_TRANSMITTER_ENABLE_TX1_ENABLE (1 << 8) +# define AVIVO_TMDSA_TRANSMITTER_ENABLE_LNKD10EN (1 << 10) +# define AVIVO_TMDSA_TRANSMITTER_ENABLE_LNKD11EN (1 << 11) +# define AVIVO_TMDSA_TRANSMITTER_ENABLE_LNKD12EN (1 << 12) +# define AVIVO_TMDSA_TRANSMITTER_ENABLE_TX_ENABLE_HPD_MASK (1 << 16) +# define AVIVO_TMDSA_TRANSMITTER_ENABLE_LNKCEN_HPD_MASK (1 << 17) +# define AVIVO_TMDSA_TRANSMITTER_ENABLE_LNKDEN_HPD_MASK (1 << 18) + +#define AVIVO_TMDSA_TRANSMITTER_CONTROL 0x7910 +# define AVIVO_TMDSA_TRANSMITTER_CONTROL_PLL_ENABLE (1 << 0) +# define AVIVO_TMDSA_TRANSMITTER_CONTROL_PLL_RESET (1 << 1) +# define AVIVO_TMDSA_TRANSMITTER_CONTROL_PLL_HPD_MASK_SHIFT (2) +# define AVIVO_TMDSA_TRANSMITTER_CONTROL_IDSCKSEL (1 << 4) +# define AVIVO_TMDSA_TRANSMITTER_CONTROL_BGSLEEP (1 << 5) +# define AVIVO_TMDSA_TRANSMITTER_CONTROL_PLL_PWRUP_SEQ_EN (1 << 6) +# define AVIVO_TMDSA_TRANSMITTER_CONTROL_TMCLK (1 << 8) +# define AVIVO_TMDSA_TRANSMITTER_CONTROL_TMCLK_FROM_PADS (1 << 13) +# define AVIVO_TMDSA_TRANSMITTER_CONTROL_TDCLK (1 << 14) +# define AVIVO_TMDSA_TRANSMITTER_CONTROL_TDCLK_FROM_PADS (1 << 15) +# define AVIVO_TMDSA_TRANSMITTER_CONTROL_CLK_PATTERN_SHIFT (16) +# define AVIVO_TMDSA_TRANSMITTER_CONTROL_BYPASS_PLL (1 << 28) +# define AVIVO_TMDSA_TRANSMITTER_CONTROL_USE_CLK_DATA (1 << 29) +# define AVIVO_TMDSA_TRANSMITTER_CONTROL_INPUT_TEST_CLK_SEL (1 << 31) + +#define AVIVO_LVTMA_CNTL 0x7a80 +# define AVIVO_LVTMA_CNTL_ENABLE (1 << 0) +# define AVIVO_LVTMA_CNTL_HPD_MASK (1 << 4) +# define AVIVO_LVTMA_CNTL_HPD_SELECT (1 << 8) +# define AVIVO_LVTMA_CNTL_SYNC_PHASE (1 << 12) +# define AVIVO_LVTMA_CNTL_PIXEL_ENCODING (1 << 16) +# define AVIVO_LVTMA_CNTL_DUAL_LINK_ENABLE (1 << 24) +# define AVIVO_LVTMA_CNTL_SWAP (1 << 28) +#define AVIVO_LVTMA_SOURCE_SELECT 0x7a84 +#define AVIVO_LVTMA_COLOR_FORMAT 0x7a88 +#define AVIVO_LVTMA_BIT_DEPTH_CONTROL 0x7a94 +# define AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_EN (1 << 0) +# define AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_DEPTH (1 << 4) +# define AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN (1 << 8) +# define AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_DEPTH (1 << 12) +# define AVIVO_LVTMA_BIT_DEPTH_CONTROL_TEMPORAL_DITHER_EN (1 << 16) +# define AVIVO_LVTMA_BIT_DEPTH_CONTROL_TEMPORAL_DITHER_DEPTH (1 << 20) +# define AVIVO_LVTMA_BIT_DEPTH_CONTROL_TEMPORAL_LEVEL (1 << 24) +# define AVIVO_LVTMA_BIT_DEPTH_CONTROL_TEMPORAL_DITHER_RESET (1 << 26) + + + +#define AVIVO_LVTMA_DCBALANCER_CONTROL 0x7ad0 +# define AVIVO_LVTMA_DCBALANCER_CONTROL_EN (1 << 0) +# define AVIVO_LVTMA_DCBALANCER_CONTROL_TEST_EN (1 << 8) +# define AVIVO_LVTMA_DCBALANCER_CONTROL_TEST_IN_SHIFT (16) +# define AVIVO_LVTMA_DCBALANCER_CONTROL_FORCE (1 << 24) + +#define AVIVO_LVTMA_DATA_SYNCHRONIZATION 0x78d8 +# define AVIVO_LVTMA_DATA_SYNCHRONIZATION_DSYNSEL (1 << 0) +# define AVIVO_LVTMA_DATA_SYNCHRONIZATION_PFREQCHG (1 << 8) +#define R500_LVTMA_CLOCK_ENABLE 0x7b00 +#define R600_LVTMA_CLOCK_ENABLE 0x7b04 + +#define R500_LVTMA_TRANSMITTER_ENABLE 0x7b04 +#define R600_LVTMA_TRANSMITTER_ENABLE 0x7b08 +# define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKC0EN (1 << 1) +# define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKD00EN (1 << 2) +# define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKD01EN (1 << 3) +# define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKD02EN (1 << 4) +# define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKD03EN (1 << 5) +# define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKC1EN (1 << 9) +# define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKD10EN (1 << 10) +# define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKD11EN (1 << 11) +# define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKD12EN (1 << 12) +# define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKCEN_HPD_MASK (1 << 17) +# define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKDEN_HPD_MASK (1 << 18) + +#define R500_LVTMA_TRANSMITTER_CONTROL 0x7b10 +#define R600_LVTMA_TRANSMITTER_CONTROL 0x7b14 +# define AVIVO_LVTMA_TRANSMITTER_CONTROL_PLL_ENABLE (1 << 0) +# define AVIVO_LVTMA_TRANSMITTER_CONTROL_PLL_RESET (1 << 1) +# define AVIVO_LVTMA_TRANSMITTER_CONTROL_PLL_HPD_MASK_SHIFT (2) +# define AVIVO_LVTMA_TRANSMITTER_CONTROL_IDSCKSEL (1 << 4) +# define AVIVO_LVTMA_TRANSMITTER_CONTROL_BGSLEEP (1 << 5) +# define AVIVO_LVTMA_TRANSMITTER_CONTROL_PLL_PWRUP_SEQ_EN (1 << 6) +# define AVIVO_LVTMA_TRANSMITTER_CONTROL_TMCLK (1 << 8) +# define AVIVO_LVTMA_TRANSMITTER_CONTROL_TMCLK_FROM_PADS (1 << 13) +# define AVIVO_LVTMA_TRANSMITTER_CONTROL_TDCLK (1 << 14) +# define AVIVO_LVTMA_TRANSMITTER_CONTROL_TDCLK_FROM_PADS (1 << 15) +# define AVIVO_LVTMA_TRANSMITTER_CONTROL_CLK_PATTERN_SHIFT (16) +# define AVIVO_LVTMA_TRANSMITTER_CONTROL_BYPASS_PLL (1 << 28) +# define AVIVO_LVTMA_TRANSMITTER_CONTROL_USE_CLK_DATA (1 << 29) +# define AVIVO_LVTMA_TRANSMITTER_CONTROL_INPUT_TEST_CLK_SEL (1 << 31) + +#define R500_LVTMA_PWRSEQ_CNTL 0x7af0 +#define R600_LVTMA_PWRSEQ_CNTL 0x7af4 +# define AVIVO_LVTMA_PWRSEQ_EN (1 << 0) +# define AVIVO_LVTMA_PWRSEQ_PLL_ENABLE_MASK (1 << 2) +# define AVIVO_LVTMA_PWRSEQ_PLL_RESET_MASK (1 << 3) +# define AVIVO_LVTMA_PWRSEQ_TARGET_STATE (1 << 4) +# define AVIVO_LVTMA_SYNCEN (1 << 8) +# define AVIVO_LVTMA_SYNCEN_OVRD (1 << 9) +# define AVIVO_LVTMA_SYNCEN_POL (1 << 10) +# define AVIVO_LVTMA_DIGON (1 << 16) +# define AVIVO_LVTMA_DIGON_OVRD (1 << 17) +# define AVIVO_LVTMA_DIGON_POL (1 << 18) +# define AVIVO_LVTMA_BLON (1 << 24) +# define AVIVO_LVTMA_BLON_OVRD (1 << 25) +# define AVIVO_LVTMA_BLON_POL (1 << 26) + +#define R500_LVTMA_PWRSEQ_STATE 0x7af4 +#define R600_LVTMA_PWRSEQ_STATE 0x7af8 +# define AVIVO_LVTMA_PWRSEQ_STATE_TARGET_STATE_R (1 << 0) +# define AVIVO_LVTMA_PWRSEQ_STATE_DIGON (1 << 1) +# define AVIVO_LVTMA_PWRSEQ_STATE_SYNCEN (1 << 2) +# define AVIVO_LVTMA_PWRSEQ_STATE_BLON (1 << 3) +# define AVIVO_LVTMA_PWRSEQ_STATE_DONE (1 << 4) +# define AVIVO_LVTMA_PWRSEQ_STATE_STATUS_SHIFT (8) + +#define AVIVO_LVDS_BACKLIGHT_CNTL 0x7af8 +# define AVIVO_LVDS_BACKLIGHT_CNTL_EN (1 << 0) +# define AVIVO_LVDS_BACKLIGHT_LEVEL_MASK 0x0000ff00 +# define AVIVO_LVDS_BACKLIGHT_LEVEL_SHIFT 8 + +#define AVIVO_DVOA_BIT_DEPTH_CONTROL 0x7988 + +#define AVIVO_GPIO_0 0x7e30 +#define AVIVO_GPIO_1 0x7e40 +#define AVIVO_GPIO_2 0x7e50 +#define AVIVO_GPIO_3 0x7e60 + +#define AVIVO_DC_GPIO_HPD_MASK 0x7e90 +#define AVIVO_DC_GPIO_HPD_A 0x7e94 +#define AVIVO_DC_GPIO_HPD_EN 0x7e98 +#define AVIVO_DC_GPIO_HPD_Y 0x7e9c + +#define AVIVO_I2C_STATUS 0x7d30 +# define AVIVO_I2C_STATUS_DONE (1 << 0) +# define AVIVO_I2C_STATUS_NACK (1 << 1) +# define AVIVO_I2C_STATUS_HALT (1 << 2) +# define AVIVO_I2C_STATUS_GO (1 << 3) +# define AVIVO_I2C_STATUS_MASK 0x7 +/* If radeon_mm_i2c is to be believed, this is HALT, NACK, and maybe + * DONE? */ +# define AVIVO_I2C_STATUS_CMD_RESET 0x7 +# define AVIVO_I2C_STATUS_CMD_WAIT (1 << 3) +#define AVIVO_I2C_STOP 0x7d34 +#define AVIVO_I2C_START_CNTL 0x7d38 +# define AVIVO_I2C_START (1 << 8) +# define AVIVO_I2C_CONNECTOR0 (0 << 16) +# define AVIVO_I2C_CONNECTOR1 (1 << 16) +#define R520_I2C_START (1<<0) +#define R520_I2C_STOP (1<<1) +#define R520_I2C_RX (1<<2) +#define R520_I2C_EN (1<<8) +#define R520_I2C_DDC1 (0<<16) +#define R520_I2C_DDC2 (1<<16) +#define R520_I2C_DDC3 (2<<16) +#define R520_I2C_DDC_MASK (3<<16) +#define AVIVO_I2C_CONTROL2 0x7d3c +# define AVIVO_I2C_7D3C_SIZE_SHIFT 8 +# define AVIVO_I2C_7D3C_SIZE_MASK (0xf << 8) +#define AVIVO_I2C_CONTROL3 0x7d40 +/* Reading is done 4 bytes at a time: read the bottom 8 bits from + * 7d44, four times in a row. + * Writing is a little more complex. First write DATA with + * 0xnnnnnnzz, then 0xnnnnnnyy, where nnnnnn is some non-deterministic + * magic number, zz is, I think, the slave address, and yy is the byte + * you want to write. */ +#define AVIVO_I2C_DATA 0x7d44 +#define R520_I2C_ADDR_COUNT_MASK (0x7) +#define R520_I2C_DATA_COUNT_SHIFT (8) +#define R520_I2C_DATA_COUNT_MASK (0xF00) +#define AVIVO_I2C_CNTL 0x7d50 +# define AVIVO_I2C_EN (1 << 0) +# define AVIVO_I2C_RESET (1 << 8) + +#define R600_GENERAL_PWRMGT 0x618 +# define R600_OPEN_DRAIN_PADS (1 << 11) + +#define R600_LOWER_GPIO_ENABLE 0x710 +#define R600_CTXSW_VID_LOWER_GPIO_CNTL 0x718 +#define R600_HIGH_VID_LOWER_GPIO_CNTL 0x71c +#define R600_MEDIUM_VID_LOWER_GPIO_CNTL 0x720 +#define R600_LOW_VID_LOWER_GPIO_CNTL 0x724 + +#define R600_MC_VM_FB_LOCATION 0x2180 +#define R600_MC_VM_AGP_TOP 0x2184 +#define R600_MC_VM_AGP_BOT 0x2188 +#define R600_MC_VM_AGP_BASE 0x218c +#define R600_MC_VM_SYSTEM_APERTURE_LOW_ADDR 0x2190 +#define R600_MC_VM_SYSTEM_APERTURE_HIGH_ADDR 0x2194 +#define R600_MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR 0x2198 + +#define R700_MC_VM_FB_LOCATION 0x2024 +#define R700_MC_VM_AGP_TOP 0x2028 +#define R700_MC_VM_AGP_BOT 0x202c +#define R700_MC_VM_AGP_BASE 0x2030 + +#define R600_HDP_NONSURFACE_BASE 0x2c04 + +#define R600_BUS_CNTL 0x5420 +#define R600_CONFIG_CNTL 0x5424 +#define R600_CONFIG_MEMSIZE 0x5428 +#define R600_CONFIG_F0_BASE 0x542C +#define R600_CONFIG_APER_SIZE 0x5430 + +#define R600_ROM_CNTL 0x1600 +# define R600_SCK_OVERWRITE (1 << 1) +# define R600_SCK_PRESCALE_CRYSTAL_CLK_SHIFT 28 +# define R600_SCK_PRESCALE_CRYSTAL_CLK_MASK (0xf << 28) + +#define R600_CG_SPLL_FUNC_CNTL 0x600 +# define R600_SPLL_BYPASS_EN (1 << 3) +#define R600_CG_SPLL_STATUS 0x60c +# define R600_SPLL_CHG_STATUS (1 << 1) + +#define R600_BIOS_0_SCRATCH 0x1724 +#define R600_BIOS_1_SCRATCH 0x1728 +#define R600_BIOS_2_SCRATCH 0x172c +#define R600_BIOS_3_SCRATCH 0x1730 +#define R600_BIOS_4_SCRATCH 0x1734 +#define R600_BIOS_5_SCRATCH 0x1738 +#define R600_BIOS_6_SCRATCH 0x173c +#define R600_BIOS_7_SCRATCH 0x1740 + +/* evergreen */ +#define EVERGREEN_VGA_MEMORY_BASE_ADDRESS 0x310 +#define EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH 0x324 +#define EVERGREEN_D3VGA_CONTROL 0x3e0 +#define EVERGREEN_D4VGA_CONTROL 0x3e4 +#define EVERGREEN_D5VGA_CONTROL 0x3e8 +#define EVERGREEN_D6VGA_CONTROL 0x3ec + +#define EVERGREEN_P1PLL_SS_CNTL 0x414 +#define EVERGREEN_P2PLL_SS_CNTL 0x454 +# define EVERGREEN_PxPLL_SS_EN (1 << 12) +/* GRPH blocks at 0x6800, 0x7400, 0x10000, 0x10c00, 0x11800, 0x12400 */ +#define EVERGREEN_GRPH_ENABLE 0x6800 +#define EVERGREEN_GRPH_CONTROL 0x6804 +# define EVERGREEN_GRPH_DEPTH(x) (((x) & 0x3) << 0) +# define EVERGREEN_GRPH_DEPTH_8BPP 0 +# define EVERGREEN_GRPH_DEPTH_16BPP 1 +# define EVERGREEN_GRPH_DEPTH_32BPP 2 +# define EVERGREEN_GRPH_FORMAT(x) (((x) & 0x7) << 8) +/* 8 BPP */ +# define EVERGREEN_GRPH_FORMAT_INDEXED 0 +/* 16 BPP */ +# define EVERGREEN_GRPH_FORMAT_ARGB1555 0 +# define EVERGREEN_GRPH_FORMAT_ARGB565 1 +# define EVERGREEN_GRPH_FORMAT_ARGB4444 2 +# define EVERGREEN_GRPH_FORMAT_AI88 3 +# define EVERGREEN_GRPH_FORMAT_MONO16 4 +# define EVERGREEN_GRPH_FORMAT_BGRA5551 5 +/* 32 BPP */ +# define EVERGREEN_GRPH_FORMAT_ARGB8888 0 +# define EVERGREEN_GRPH_FORMAT_ARGB2101010 1 +# define EVERGREEN_GRPH_FORMAT_32BPP_DIG 2 +# define EVERGREEN_GRPH_FORMAT_8B_ARGB2101010 3 +# define EVERGREEN_GRPH_FORMAT_BGRA1010102 4 +# define EVERGREEN_GRPH_FORMAT_8B_BGRA1010102 5 +# define EVERGREEN_GRPH_FORMAT_RGB111110 6 +# define EVERGREEN_GRPH_FORMAT_BGR101111 7 +#define EVERGREEN_GRPH_SWAP_CONTROL 0x680c +# define EVERGREEN_GRPH_ENDIAN_SWAP(x) (((x) & 0x3) << 0) +# define EVERGREEN_GRPH_ENDIAN_NONE 0 +# define EVERGREEN_GRPH_ENDIAN_8IN16 1 +# define EVERGREEN_GRPH_ENDIAN_8IN32 2 +# define EVERGREEN_GRPH_ENDIAN_8IN64 3 +# define EVERGREEN_GRPH_RED_CROSSBAR(x) (((x) & 0x3) << 4) +# define EVERGREEN_GRPH_RED_SEL_R 0 +# define EVERGREEN_GRPH_RED_SEL_G 1 +# define EVERGREEN_GRPH_RED_SEL_B 2 +# define EVERGREEN_GRPH_RED_SEL_A 3 +# define EVERGREEN_GRPH_GREEN_CROSSBAR(x) (((x) & 0x3) << 6) +# define EVERGREEN_GRPH_GREEN_SEL_G 0 +# define EVERGREEN_GRPH_GREEN_SEL_B 1 +# define EVERGREEN_GRPH_GREEN_SEL_A 2 +# define EVERGREEN_GRPH_GREEN_SEL_R 3 +# define EVERGREEN_GRPH_BLUE_CROSSBAR(x) (((x) & 0x3) << 8) +# define EVERGREEN_GRPH_BLUE_SEL_B 0 +# define EVERGREEN_GRPH_BLUE_SEL_A 1 +# define EVERGREEN_GRPH_BLUE_SEL_R 2 +# define EVERGREEN_GRPH_BLUE_SEL_G 3 +# define EVERGREEN_GRPH_ALPHA_CROSSBAR(x) (((x) & 0x3) << 10) +# define EVERGREEN_GRPH_ALPHA_SEL_A 0 +# define EVERGREEN_GRPH_ALPHA_SEL_R 1 +# define EVERGREEN_GRPH_ALPHA_SEL_G 2 +# define EVERGREEN_GRPH_ALPHA_SEL_B 3 +#define EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS 0x6810 +#define EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS 0x6814 +# define EVERGREEN_GRPH_DFQ_ENABLE (1 << 0) +# define EVERGREEN_GRPH_SURFACE_ADDRESS_MASK 0xffffff00 +#define EVERGREEN_GRPH_PITCH 0x6818 +#define EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH 0x681c +#define EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x6820 +#define EVERGREEN_GRPH_SURFACE_OFFSET_X 0x6824 +#define EVERGREEN_GRPH_SURFACE_OFFSET_Y 0x6828 +#define EVERGREEN_GRPH_X_START 0x682c +#define EVERGREEN_GRPH_Y_START 0x6830 +#define EVERGREEN_GRPH_X_END 0x6834 +#define EVERGREEN_GRPH_Y_END 0x6838 + +/* CUR blocks at 0x6998, 0x7598, 0x10198, 0x10d98, 0x11998, 0x12598 */ +#define EVERGREEN_CUR_CONTROL 0x6998 +# define EVERGREEN_CURSOR_EN (1 << 0) +# define EVERGREEN_CURSOR_MODE(x) (((x) & 0x3) << 8) +# define EVERGREEN_CURSOR_MONO 0 +# define EVERGREEN_CURSOR_24_1 1 +# define EVERGREEN_CURSOR_24_8_PRE_MULT 2 +# define EVERGREEN_CURSOR_24_8_UNPRE_MULT 3 +# define EVERGREEN_CURSOR_2X_MAGNIFY (1 << 16) +# define EVERGREEN_CURSOR_FORCE_MC_ON (1 << 20) +# define EVERGREEN_CURSOR_URGENT_CONTROL(x) (((x) & 0x7) << 24) +# define EVERGREEN_CURSOR_URGENT_ALWAYS 0 +# define EVERGREEN_CURSOR_URGENT_1_8 1 +# define EVERGREEN_CURSOR_URGENT_1_4 2 +# define EVERGREEN_CURSOR_URGENT_3_8 3 +# define EVERGREEN_CURSOR_URGENT_1_2 4 +#define EVERGREEN_CUR_SURFACE_ADDRESS 0x699c +# define EVERGREEN_CUR_SURFACE_ADDRESS_MASK 0xfffff000 +#define EVERGREEN_CUR_SIZE 0x69a0 +#define EVERGREEN_CUR_SURFACE_ADDRESS_HIGH 0x69a4 +#define EVERGREEN_CUR_POSITION 0x69a8 +#define EVERGREEN_CUR_HOT_SPOT 0x69ac +#define EVERGREEN_CUR_COLOR1 0x69b0 +#define EVERGREEN_CUR_COLOR2 0x69b4 +#define EVERGREEN_CUR_UPDATE 0x69b8 +# define EVERGREEN_CURSOR_UPDATE_PENDING (1 << 0) +# define EVERGREEN_CURSOR_UPDATE_TAKEN (1 << 1) +# define EVERGREEN_CURSOR_UPDATE_LOCK (1 << 16) +# define EVERGREEN_CURSOR_DISABLE_MULTIPLE_UPDATE (1 << 24) + +/* LUT blocks at 0x69e0, 0x75e0, 0x101e0, 0x10de0, 0x119e0, 0x125e0 */ +#define EVERGREEN_DC_LUT_RW_MODE 0x69e0 +#define EVERGREEN_DC_LUT_RW_INDEX 0x69e4 +#define EVERGREEN_DC_LUT_SEQ_COLOR 0x69e8 +#define EVERGREEN_DC_LUT_PWL_DATA 0x69ec +#define EVERGREEN_DC_LUT_30_COLOR 0x69f0 +#define EVERGREEN_DC_LUT_VGA_ACCESS_ENABLE 0x69f4 +#define EVERGREEN_DC_LUT_WRITE_EN_MASK 0x69f8 +#define EVERGREEN_DC_LUT_AUTOFILL 0x69fc +#define EVERGREEN_DC_LUT_CONTROL 0x6a00 +#define EVERGREEN_DC_LUT_BLACK_OFFSET_BLUE 0x6a04 +#define EVERGREEN_DC_LUT_BLACK_OFFSET_GREEN 0x6a08 +#define EVERGREEN_DC_LUT_BLACK_OFFSET_RED 0x6a0c +#define EVERGREEN_DC_LUT_WHITE_OFFSET_BLUE 0x6a10 +#define EVERGREEN_DC_LUT_WHITE_OFFSET_GREEN 0x6a14 +#define EVERGREEN_DC_LUT_WHITE_OFFSET_RED 0x6a18 + +#define EVERGREEN_DATA_FORMAT 0x6b00 +# define EVERGREEN_INTERLEAVE_EN (1 << 0) +#define EVERGREEN_DESKTOP_HEIGHT 0x6b04 + +#define EVERGREEN_VIEWPORT_START 0x6d70 +#define EVERGREEN_VIEWPORT_SIZE 0x6d74 + +/* display controller offsets used for crtc/cur/lut/grph/viewport/etc. */ +#define EVERGREEN_CRTC0_REGISTER_OFFSET (0x6df0 - 0x6df0) +#define EVERGREEN_CRTC1_REGISTER_OFFSET (0x79f0 - 0x6df0) +#define EVERGREEN_CRTC2_REGISTER_OFFSET (0x105f0 - 0x6df0) +#define EVERGREEN_CRTC3_REGISTER_OFFSET (0x111f0 - 0x6df0) +#define EVERGREEN_CRTC4_REGISTER_OFFSET (0x11df0 - 0x6df0) +#define EVERGREEN_CRTC5_REGISTER_OFFSET (0x129f0 - 0x6df0) + +/* CRTC blocks at 0x6df0, 0x79f0, 0x105f0, 0x111f0, 0x11df0, 0x129f0 */ +#define EVERGREEN_CRTC_CONTROL 0x6e70 +# define EVERGREEN_CRTC_MASTER_EN (1 << 0) +#define EVERGREEN_CRTC_UPDATE_LOCK 0x6ed4 + +#define EVERGREEN_DC_GPIO_HPD_MASK 0x64b0 +#define EVERGREEN_DC_GPIO_HPD_A 0x64b4 +#define EVERGREEN_DC_GPIO_HPD_EN 0x64b8 +#define EVERGREEN_DC_GPIO_HPD_Y 0x64bc + +#define R300_GB_TILE_CONFIG 0x4018 +# define R300_ENABLE_TILING (1 << 0) +# define R300_PIPE_COUNT_RV350 (0 << 1) +# define R300_PIPE_COUNT_R300 (3 << 1) +# define R300_PIPE_COUNT_R420_3P (6 << 1) +# define R300_PIPE_COUNT_R420 (7 << 1) +# define R300_TILE_SIZE_8 (0 << 4) +# define R300_TILE_SIZE_16 (1 << 4) +# define R300_TILE_SIZE_32 (2 << 4) +# define R300_SUBPIXEL_1_12 (0 << 16) +# define R300_SUBPIXEL_1_16 (1 << 16) +#define R300_GB_SELECT 0x401c +#define R300_GB_ENABLE 0x4008 +#define R300_GB_AA_CONFIG 0x4020 +#define R400_GB_PIPE_SELECT 0x402c +#define R300_GB_MSPOS0 0x4010 +# define R300_MS_X0_SHIFT 0 +# define R300_MS_Y0_SHIFT 4 +# define R300_MS_X1_SHIFT 8 +# define R300_MS_Y1_SHIFT 12 +# define R300_MS_X2_SHIFT 16 +# define R300_MS_Y2_SHIFT 20 +# define R300_MSBD0_Y_SHIFT 24 +# define R300_MSBD0_X_SHIFT 28 +#define R300_GB_MSPOS1 0x4014 +# define R300_MS_X3_SHIFT 0 +# define R300_MS_Y3_SHIFT 4 +# define R300_MS_X4_SHIFT 8 +# define R300_MS_Y4_SHIFT 12 +# define R300_MS_X5_SHIFT 16 +# define R300_MS_Y5_SHIFT 20 +# define R300_MSBD1_SHIFT 24 + +#define R300_GA_ENHANCE 0x4274 +# define R300_GA_DEADLOCK_CNTL (1 << 0) +# define R300_GA_FASTSYNC_CNTL (1 << 1) + +#define R300_GA_POLY_MODE 0x4288 +# define R300_FRONT_PTYPE_POINT (0 << 4) +# define R300_FRONT_PTYPE_LINE (1 << 4) +# define R300_FRONT_PTYPE_TRIANGE (2 << 4) +# define R300_BACK_PTYPE_POINT (0 << 7) +# define R300_BACK_PTYPE_LINE (1 << 7) +# define R300_BACK_PTYPE_TRIANGE (2 << 7) +#define R300_GA_ROUND_MODE 0x428c +# define R300_GEOMETRY_ROUND_TRUNC (0 << 0) +# define R300_GEOMETRY_ROUND_NEAREST (1 << 0) +# define R300_COLOR_ROUND_TRUNC (0 << 2) +# define R300_COLOR_ROUND_NEAREST (1 << 2) +#define R300_GA_COLOR_CONTROL 0x4278 +# define R300_RGB0_SHADING_SOLID (0 << 0) +# define R300_RGB0_SHADING_FLAT (1 << 0) +# define R300_RGB0_SHADING_GOURAUD (2 << 0) +# define R300_ALPHA0_SHADING_SOLID (0 << 2) +# define R300_ALPHA0_SHADING_FLAT (1 << 2) +# define R300_ALPHA0_SHADING_GOURAUD (2 << 2) +# define R300_RGB1_SHADING_SOLID (0 << 4) +# define R300_RGB1_SHADING_FLAT (1 << 4) +# define R300_RGB1_SHADING_GOURAUD (2 << 4) +# define R300_ALPHA1_SHADING_SOLID (0 << 6) +# define R300_ALPHA1_SHADING_FLAT (1 << 6) +# define R300_ALPHA1_SHADING_GOURAUD (2 << 6) +# define R300_RGB2_SHADING_SOLID (0 << 8) +# define R300_RGB2_SHADING_FLAT (1 << 8) +# define R300_RGB2_SHADING_GOURAUD (2 << 8) +# define R300_ALPHA2_SHADING_SOLID (0 << 10) +# define R300_ALPHA2_SHADING_FLAT (1 << 10) +# define R300_ALPHA2_SHADING_GOURAUD (2 << 10) +# define R300_RGB3_SHADING_SOLID (0 << 12) +# define R300_RGB3_SHADING_FLAT (1 << 12) +# define R300_RGB3_SHADING_GOURAUD (2 << 12) +# define R300_ALPHA3_SHADING_SOLID (0 << 14) +# define R300_ALPHA3_SHADING_FLAT (1 << 14) +# define R300_ALPHA3_SHADING_GOURAUD (2 << 14) +#define R300_GA_OFFSET 0x4290 + +#define R500_SU_REG_DEST 0x42c8 + +#define R300_VAP_CNTL_STATUS 0x2140 +# define R300_PVS_BYPASS (1 << 8) +#define R300_VAP_PVS_STATE_FLUSH_REG 0x2284 +#define R300_VAP_CNTL 0x2080 +# define R300_PVS_NUM_SLOTS_SHIFT 0 +# define R300_PVS_NUM_CNTLRS_SHIFT 4 +# define R300_PVS_NUM_FPUS_SHIFT 8 +# define R300_VF_MAX_VTX_NUM_SHIFT 18 +# define R300_GL_CLIP_SPACE_DEF (0 << 22) +# define R300_DX_CLIP_SPACE_DEF (1 << 22) +# define R500_TCL_STATE_OPTIMIZATION (1 << 23) +#define R300_VAP_VTE_CNTL 0x20B0 +# define R300_VPORT_X_SCALE_ENA (1 << 0) +# define R300_VPORT_X_OFFSET_ENA (1 << 1) +# define R300_VPORT_Y_SCALE_ENA (1 << 2) +# define R300_VPORT_Y_OFFSET_ENA (1 << 3) +# define R300_VPORT_Z_SCALE_ENA (1 << 4) +# define R300_VPORT_Z_OFFSET_ENA (1 << 5) +# define R300_VTX_XY_FMT (1 << 8) +# define R300_VTX_Z_FMT (1 << 9) +# define R300_VTX_W0_FMT (1 << 10) +#define R300_VAP_VTX_STATE_CNTL 0x2180 +#define R300_VAP_PSC_SGN_NORM_CNTL 0x21DC +#define R300_VAP_PROG_STREAM_CNTL_0 0x2150 +# define R300_DATA_TYPE_0_SHIFT 0 +# define R300_DATA_TYPE_FLOAT_1 0 +# define R300_DATA_TYPE_FLOAT_2 1 +# define R300_DATA_TYPE_FLOAT_3 2 +# define R300_DATA_TYPE_FLOAT_4 3 +# define R300_DATA_TYPE_BYTE 4 +# define R300_DATA_TYPE_D3DCOLOR 5 +# define R300_DATA_TYPE_SHORT_2 6 +# define R300_DATA_TYPE_SHORT_4 7 +# define R300_DATA_TYPE_VECTOR_3_TTT 8 +# define R300_DATA_TYPE_VECTOR_3_EET 9 +# define R300_SKIP_DWORDS_0_SHIFT 4 +# define R300_DST_VEC_LOC_0_SHIFT 8 +# define R300_LAST_VEC_0 (1 << 13) +# define R300_SIGNED_0 (1 << 14) +# define R300_NORMALIZE_0 (1 << 15) +# define R300_DATA_TYPE_1_SHIFT 16 +# define R300_SKIP_DWORDS_1_SHIFT 20 +# define R300_DST_VEC_LOC_1_SHIFT 24 +# define R300_LAST_VEC_1 (1 << 29) +# define R300_SIGNED_1 (1 << 30) +# define R300_NORMALIZE_1 (1 << 31) +#define R300_VAP_PROG_STREAM_CNTL_1 0x2154 +# define R300_DATA_TYPE_2_SHIFT 0 +# define R300_SKIP_DWORDS_2_SHIFT 4 +# define R300_DST_VEC_LOC_2_SHIFT 8 +# define R300_LAST_VEC_2 (1 << 13) +# define R300_SIGNED_2 (1 << 14) +# define R300_NORMALIZE_2 (1 << 15) +# define R300_DATA_TYPE_3_SHIFT 16 +# define R300_SKIP_DWORDS_3_SHIFT 20 +# define R300_DST_VEC_LOC_3_SHIFT 24 +# define R300_LAST_VEC_3 (1 << 29) +# define R300_SIGNED_3 (1 << 30) +# define R300_NORMALIZE_3 (1 << 31) +#define R300_VAP_PROG_STREAM_CNTL_EXT_0 0x21e0 +# define R300_SWIZZLE_SELECT_X_0_SHIFT 0 +# define R300_SWIZZLE_SELECT_Y_0_SHIFT 3 +# define R300_SWIZZLE_SELECT_Z_0_SHIFT 6 +# define R300_SWIZZLE_SELECT_W_0_SHIFT 9 +# define R300_SWIZZLE_SELECT_X 0 +# define R300_SWIZZLE_SELECT_Y 1 +# define R300_SWIZZLE_SELECT_Z 2 +# define R300_SWIZZLE_SELECT_W 3 +# define R300_SWIZZLE_SELECT_FP_ZERO 4 +# define R300_SWIZZLE_SELECT_FP_ONE 5 +# define R300_WRITE_ENA_0_SHIFT 12 +# define R300_WRITE_ENA_X 1 +# define R300_WRITE_ENA_Y 2 +# define R300_WRITE_ENA_Z 4 +# define R300_WRITE_ENA_W 8 +# define R300_SWIZZLE_SELECT_X_1_SHIFT 16 +# define R300_SWIZZLE_SELECT_Y_1_SHIFT 19 +# define R300_SWIZZLE_SELECT_Z_1_SHIFT 22 +# define R300_SWIZZLE_SELECT_W_1_SHIFT 25 +# define R300_WRITE_ENA_1_SHIFT 28 +#define R300_VAP_PROG_STREAM_CNTL_EXT_1 0x21e4 +# define R300_SWIZZLE_SELECT_X_2_SHIFT 0 +# define R300_SWIZZLE_SELECT_Y_2_SHIFT 3 +# define R300_SWIZZLE_SELECT_Z_2_SHIFT 6 +# define R300_SWIZZLE_SELECT_W_2_SHIFT 9 +# define R300_WRITE_ENA_2_SHIFT 12 +# define R300_SWIZZLE_SELECT_X_3_SHIFT 16 +# define R300_SWIZZLE_SELECT_Y_3_SHIFT 19 +# define R300_SWIZZLE_SELECT_Z_3_SHIFT 22 +# define R300_SWIZZLE_SELECT_W_3_SHIFT 25 +# define R300_WRITE_ENA_3_SHIFT 28 +#define R300_VAP_PVS_CODE_CNTL_0 0x22D0 +# define R300_PVS_FIRST_INST_SHIFT 0 +# define R300_PVS_XYZW_VALID_INST_SHIFT 10 +# define R300_PVS_LAST_INST_SHIFT 20 +#define R300_VAP_PVS_CODE_CNTL_1 0x22D8 +# define R300_PVS_LAST_VTX_SRC_INST_SHIFT 0 +#define R300_VAP_PVS_VECTOR_INDX_REG 0x2200 +# define R300_PVS_CODE_START 0 +# define R300_PVS_CONST_START 512 +# define R500_PVS_CONST_START 1024 +# define R300_PVS_VECTOR_INST_INDEX(x) ((x) + R300_PVS_CODE_START) +# define R300_PVS_VECTOR_CONST_INDEX(x) ((x) + R300_PVS_CONST_START) +# define R500_PVS_VECTOR_CONST_INDEX(x) ((x) + R500_PVS_CONST_START) +#define R300_VAP_PVS_VECTOR_DATA_REG 0x2204 +/* PVS instructions */ +/* Opcode and dst instruction */ +#define R300_PVS_DST_OPCODE(x) ((x) << 0) +/* Vector ops */ +# define R300_VECTOR_NO_OP 0 +# define R300_VE_DOT_PRODUCT 1 +# define R300_VE_MULTIPLY 2 +# define R300_VE_ADD 3 +# define R300_VE_MULTIPLY_ADD 4 +# define R300_VE_DISTANCE_VECTOR 5 +# define R300_VE_FRACTION 6 +# define R300_VE_MAXIMUM 7 +# define R300_VE_MINIMUM 8 +# define R300_VE_SET_GREATER_THAN_EQUAL 9 +# define R300_VE_SET_LESS_THAN 10 +# define R300_VE_MULTIPLYX2_ADD 11 +# define R300_VE_MULTIPLY_CLAMP 12 +# define R300_VE_FLT2FIX_DX 13 +# define R300_VE_FLT2FIX_DX_RND 14 +/* R500 additions */ +# define R500_VE_PRED_SET_EQ_PUSH 15 +# define R500_VE_PRED_SET_GT_PUSH 16 +# define R500_VE_PRED_SET_GTE_PUSH 17 +# define R500_VE_PRED_SET_NEQ_PUSH 18 +# define R500_VE_COND_WRITE_EQ 19 +# define R500_VE_COND_WRITE_GT 20 +# define R500_VE_COND_WRITE_GTE 21 +# define R500_VE_COND_WRITE_NEQ 22 +# define R500_VE_COND_MUX_EQ 23 +# define R500_VE_COND_MUX_GT 24 +# define R500_VE_COND_MUX_GTE 25 +# define R500_VE_SET_GREATER_THAN 26 +# define R500_VE_SET_EQUAL 27 +# define R500_VE_SET_NOT_EQUAL 28 +/* Math ops */ +# define R300_MATH_NO_OP 0 +# define R300_ME_EXP_BASE2_DX 1 +# define R300_ME_LOG_BASE2_DX 2 +# define R300_ME_EXP_BASEE_FF 3 +# define R300_ME_LIGHT_COEFF_DX 4 +# define R300_ME_POWER_FUNC_FF 5 +# define R300_ME_RECIP_DX 6 +# define R300_ME_RECIP_FF 7 +# define R300_ME_RECIP_SQRT_DX 8 +# define R300_ME_RECIP_SQRT_FF 9 +# define R300_ME_MULTIPLY 10 +# define R300_ME_EXP_BASE2_FULL_DX 11 +# define R300_ME_LOG_BASE2_FULL_DX 12 +# define R300_ME_POWER_FUNC_FF_CLAMP_B 13 +# define R300_ME_POWER_FUNC_FF_CLAMP_B1 14 +# define R300_ME_POWER_FUNC_FF_CLAMP_01 15 +# define R300_ME_SIN 16 +# define R300_ME_COS 17 +/* R500 additions */ +# define R500_ME_LOG_BASE2_IEEE 18 +# define R500_ME_RECIP_IEEE 19 +# define R500_ME_RECIP_SQRT_IEEE 20 +# define R500_ME_PRED_SET_EQ 21 +# define R500_ME_PRED_SET_GT 22 +# define R500_ME_PRED_SET_GTE 23 +# define R500_ME_PRED_SET_NEQ 24 +# define R500_ME_PRED_SET_CLR 25 +# define R500_ME_PRED_SET_INV 26 +# define R500_ME_PRED_SET_POP 27 +# define R500_ME_PRED_SET_RESTORE 28 +/* macro */ +# define R300_PVS_MACRO_OP_2CLK_MADD 0 +# define R300_PVS_MACRO_OP_2CLK_M2X_ADD 1 +#define R300_PVS_DST_MATH_INST (1 << 6) +#define R300_PVS_DST_MACRO_INST (1 << 7) +#define R300_PVS_DST_REG_TYPE(x) ((x) << 8) +# define R300_PVS_DST_REG_TEMPORARY 0 +# define R300_PVS_DST_REG_A0 1 +# define R300_PVS_DST_REG_OUT 2 +# define R500_PVS_DST_REG_OUT_REPL_X 3 +# define R300_PVS_DST_REG_ALT_TEMPORARY 4 +# define R300_PVS_DST_REG_INPUT 5 +#define R300_PVS_DST_ADDR_MODE_1 (1 << 12) +#define R300_PVS_DST_OFFSET(x) ((x) << 13) +#define R300_PVS_DST_WE_X (1 << 20) +#define R300_PVS_DST_WE_Y (1 << 21) +#define R300_PVS_DST_WE_Z (1 << 22) +#define R300_PVS_DST_WE_W (1 << 23) +#define R300_PVS_DST_VE_SAT (1 << 24) +#define R300_PVS_DST_ME_SAT (1 << 25) +#define R300_PVS_DST_PRED_ENABLE (1 << 26) +#define R300_PVS_DST_PRED_SENSE (1 << 27) +#define R300_PVS_DST_DUAL_MATH_OP (1 << 28) +#define R300_PVS_DST_ADDR_SEL(x) ((x) << 29) +#define R300_PVS_DST_ADDR_MODE_0 (1 << 31) +/* src operand instruction */ +#define R300_PVS_SRC_REG_TYPE(x) ((x) << 0) +# define R300_PVS_SRC_REG_TEMPORARY 0 +# define R300_PVS_SRC_REG_INPUT 1 +# define R300_PVS_SRC_REG_CONSTANT 2 +# define R300_PVS_SRC_REG_ALT_TEMPORARY 3 +#define R300_SPARE_0 (1 << 2) +#define R300_PVS_SRC_ABS_XYZW (1 << 3) +#define R300_PVS_SRC_ADDR_MODE_0 (1 << 4) +#define R300_PVS_SRC_OFFSET(x) ((x) << 5) +#define R300_PVS_SRC_SWIZZLE_X(x) ((x) << 13) +#define R300_PVS_SRC_SWIZZLE_Y(x) ((x) << 16) +#define R300_PVS_SRC_SWIZZLE_Z(x) ((x) << 19) +#define R300_PVS_SRC_SWIZZLE_W(x) ((x) << 22) +# define R300_PVS_SRC_SELECT_X 0 +# define R300_PVS_SRC_SELECT_Y 1 +# define R300_PVS_SRC_SELECT_Z 2 +# define R300_PVS_SRC_SELECT_W 3 +# define R300_PVS_SRC_SELECT_FORCE_0 4 +# define R300_PVS_SRC_SELECT_FORCE_1 5 +#define R300_PVS_SRC_NEG_X (1 << 25) +#define R300_PVS_SRC_NEG_Y (1 << 26) +#define R300_PVS_SRC_NEG_Z (1 << 27) +#define R300_PVS_SRC_NEG_W (1 << 28) +#define R300_PVS_SRC_ADDR_SEL(x) ((x) << 29) +#define R300_PVS_SRC_ADDR_MODE_1 (1 << 31) + +#define R300_VAP_PVS_CONST_CNTL 0x22d4 +# define R300_PVS_CONST_BASE_OFFSET(x) ((x) << 0) +# define R300_PVS_MAX_CONST_ADDR(x) ((x) << 16) + +#define R300_VAP_PVS_FLOW_CNTL_OPC 0x22dc +#define R300_VAP_OUT_VTX_FMT_0 0x2090 +# define R300_VTX_POS_PRESENT (1 << 0) +# define R300_VTX_COLOR_0_PRESENT (1 << 1) +# define R300_VTX_COLOR_1_PRESENT (1 << 2) +# define R300_VTX_COLOR_2_PRESENT (1 << 3) +# define R300_VTX_COLOR_3_PRESENT (1 << 4) +# define R300_VTX_PT_SIZE_PRESENT (1 << 16) +#define R300_VAP_OUT_VTX_FMT_1 0x2094 +# define R300_TEX_0_COMP_CNT_SHIFT 0 +# define R300_TEX_1_COMP_CNT_SHIFT 3 +# define R300_TEX_2_COMP_CNT_SHIFT 6 +# define R300_TEX_3_COMP_CNT_SHIFT 9 +# define R300_TEX_4_COMP_CNT_SHIFT 12 +# define R300_TEX_5_COMP_CNT_SHIFT 15 +# define R300_TEX_6_COMP_CNT_SHIFT 18 +# define R300_TEX_7_COMP_CNT_SHIFT 21 +#define R300_VAP_VTX_SIZE 0x20b4 +#define R300_VAP_GB_VERT_CLIP_ADJ 0x2220 +#define R300_VAP_GB_VERT_DISC_ADJ 0x2224 +#define R300_VAP_GB_HORZ_CLIP_ADJ 0x2228 +#define R300_VAP_GB_HORZ_DISC_ADJ 0x222c +#define R300_VAP_CLIP_CNTL 0x221c +# define R300_UCP_ENA_0 (1 << 0) +# define R300_UCP_ENA_1 (1 << 1) +# define R300_UCP_ENA_2 (1 << 2) +# define R300_UCP_ENA_3 (1 << 3) +# define R300_UCP_ENA_4 (1 << 4) +# define R300_UCP_ENA_5 (1 << 5) +# define R300_PS_UCP_MODE_SHIFT 14 +# define R300_CLIP_DISABLE (1 << 16) +# define R300_UCP_CULL_ONLY_ENA (1 << 17) +# define R300_BOUNDARY_EDGE_FLAG_ENA (1 << 18) +#define R300_VAP_PVS_STATE_FLUSH_REG 0x2284 + +#define R500_VAP_INDEX_OFFSET 0x208c + +#define R300_SU_TEX_WRAP 0x42a0 +#define R300_SU_POLY_OFFSET_ENABLE 0x42b4 +#define R300_SU_CULL_MODE 0x42b8 +# define R300_CULL_FRONT (1 << 0) +# define R300_CULL_BACK (1 << 1) +# define R300_FACE_POS (0 << 2) +# define R300_FACE_NEG (1 << 2) +#define R300_SU_DEPTH_SCALE 0x42c0 +#define R300_SU_DEPTH_OFFSET 0x42c4 + +#define R300_RS_COUNT 0x4300 +# define R300_RS_COUNT_IT_COUNT_SHIFT 0 +# define R300_RS_COUNT_IC_COUNT_SHIFT 7 +# define R300_RS_COUNT_HIRES_EN (1 << 18) + +#define R300_RS_IP_0 0x4310 +#define R300_RS_IP_1 0x4314 +# define R300_RS_TEX_PTR(x) ((x) << 0) +# define R300_RS_COL_PTR(x) ((x) << 6) +# define R300_RS_COL_FMT(x) ((x) << 9) +# define R300_RS_COL_FMT_RGBA 0 +# define R300_RS_COL_FMT_RGB0 2 +# define R300_RS_COL_FMT_RGB1 3 +# define R300_RS_COL_FMT_000A 4 +# define R300_RS_COL_FMT_0000 5 +# define R300_RS_COL_FMT_0001 6 +# define R300_RS_COL_FMT_111A 8 +# define R300_RS_COL_FMT_1110 9 +# define R300_RS_COL_FMT_1111 10 +# define R300_RS_SEL_S(x) ((x) << 13) +# define R300_RS_SEL_T(x) ((x) << 16) +# define R300_RS_SEL_R(x) ((x) << 19) +# define R300_RS_SEL_Q(x) ((x) << 22) +# define R300_RS_SEL_C0 0 +# define R300_RS_SEL_C1 1 +# define R300_RS_SEL_C2 2 +# define R300_RS_SEL_C3 3 +# define R300_RS_SEL_K0 4 +# define R300_RS_SEL_K1 5 +#define R300_RS_INST_COUNT 0x4304 +# define R300_INST_COUNT_RS(x) ((x) << 0) +# define R300_RS_W_EN (1 << 4) +# define R300_TX_OFFSET_RS(x) ((x) << 5) +#define R300_RS_INST_0 0x4330 +#define R300_RS_INST_1 0x4334 +# define R300_INST_TEX_ID(x) ((x) << 0) +# define R300_RS_INST_TEX_CN_WRITE (1 << 3) +# define R300_INST_TEX_ADDR(x) ((x) << 6) + +#define R300_TX_INVALTAGS 0x4100 +#define R300_TX_FILTER0_0 0x4400 +#define R300_TX_FILTER0_1 0x4404 +#define R300_TX_FILTER0_2 0x4408 +# define R300_TX_CLAMP_S(x) ((x) << 0) +# define R300_TX_CLAMP_T(x) ((x) << 3) +# define R300_TX_CLAMP_R(x) ((x) << 6) +# define R300_TX_CLAMP_WRAP 0 +# define R300_TX_CLAMP_MIRROR 1 +# define R300_TX_CLAMP_CLAMP_LAST 2 +# define R300_TX_CLAMP_MIRROR_CLAMP_LAST 3 +# define R300_TX_CLAMP_CLAMP_BORDER 4 +# define R300_TX_CLAMP_MIRROR_CLAMP_BORDER 5 +# define R300_TX_CLAMP_CLAMP_GL 6 +# define R300_TX_CLAMP_MIRROR_CLAMP_GL 7 +# define R300_TX_MAG_FILTER_NEAREST (1 << 9) +# define R300_TX_MIN_FILTER_NEAREST (1 << 11) +# define R300_TX_MAG_FILTER_LINEAR (2 << 9) +# define R300_TX_MIN_FILTER_LINEAR (2 << 11) +# define R300_TX_ID_SHIFT 28 +#define R300_TX_FILTER1_0 0x4440 +#define R300_TX_FILTER1_1 0x4444 +#define R300_TX_FILTER1_2 0x4448 +#define R300_TX_FORMAT0_0 0x4480 +#define R300_TX_FORMAT0_1 0x4484 +#define R300_TX_FORMAT0_2 0x4488 +# define R300_TXWIDTH_SHIFT 0 +# define R300_TXHEIGHT_SHIFT 11 +# define R300_NUM_LEVELS_SHIFT 26 +# define R300_NUM_LEVELS_MASK 0x +# define R300_TXPROJECTED (1 << 30) +# define R300_TXPITCH_EN (1 << 31) +#define R300_TX_FORMAT1_0 0x44c0 +#define R300_TX_FORMAT1_1 0x44c4 +#define R300_TX_FORMAT1_2 0x44c8 +# define R300_TX_FORMAT_X8 0x0 +# define R300_TX_FORMAT_X16 0x1 +# define R300_TX_FORMAT_Y4X4 0x2 +# define R300_TX_FORMAT_Y8X8 0x3 +# define R300_TX_FORMAT_Y16X16 0x4 +# define R300_TX_FORMAT_Z3Y3X2 0x5 +# define R300_TX_FORMAT_Z5Y6X5 0x6 +# define R300_TX_FORMAT_Z6Y5X5 0x7 +# define R300_TX_FORMAT_Z11Y11X10 0x8 +# define R300_TX_FORMAT_Z10Y11X11 0x9 +# define R300_TX_FORMAT_W4Z4Y4X4 0xA +# define R300_TX_FORMAT_W1Z5Y5X5 0xB +# define R300_TX_FORMAT_W8Z8Y8X8 0xC +# define R300_TX_FORMAT_W2Z10Y10X10 0xD +# define R300_TX_FORMAT_W16Z16Y16X16 0xE +# define R300_TX_FORMAT_DXT1 0xF +# define R300_TX_FORMAT_DXT3 0x10 +# define R300_TX_FORMAT_DXT5 0x11 +# define R300_TX_FORMAT_D3DMFT_CxV8U8 0x12 /* no swizzle */ +# define R300_TX_FORMAT_A8R8G8B8 0x13 /* no swizzle */ +# define R300_TX_FORMAT_B8G8_B8G8 0x14 /* no swizzle */ +# define R300_TX_FORMAT_G8R8_G8B8 0x15 /* no swizzle */ +# define R300_TX_FORMAT_VYUY422 0x14 /* no swizzle */ +# define R300_TX_FORMAT_YVYU422 0x15 /* no swizzle */ +# define R300_TX_FORMAT_X24_Y8 0x1e +# define R300_TX_FORMAT_X32 0x1e + /* Floating point formats */ + /* Note - hardware supports both 16 and 32 bit floating point */ +# define R300_TX_FORMAT_FL_I16 0x18 +# define R300_TX_FORMAT_FL_I16A16 0x19 +# define R300_TX_FORMAT_FL_R16G16B16A16 0x1A +# define R300_TX_FORMAT_FL_I32 0x1B +# define R300_TX_FORMAT_FL_I32A32 0x1C +# define R300_TX_FORMAT_FL_R32G32B32A32 0x1D + /* alpha modes, convenience mostly */ + /* if you have alpha, pick constant appropriate to the + number of channels (1 for I8, 2 for I8A8, 4 for R8G8B8A8, etc */ +# define R300_TX_FORMAT_ALPHA_1CH 0x000 +# define R300_TX_FORMAT_ALPHA_2CH 0x200 +# define R300_TX_FORMAT_ALPHA_4CH 0x600 +# define R300_TX_FORMAT_ALPHA_NONE 0xA00 + /* Swizzling */ + /* constants */ +# define R300_TX_FORMAT_X 0 +# define R300_TX_FORMAT_Y 1 +# define R300_TX_FORMAT_Z 2 +# define R300_TX_FORMAT_W 3 +# define R300_TX_FORMAT_ZERO 4 +# define R300_TX_FORMAT_ONE 5 + /* 2.0*Z, everything above 1.0 is set to 0.0 */ +# define R300_TX_FORMAT_CUT_Z 6 + /* 2.0*W, everything above 1.0 is set to 0.0 */ +# define R300_TX_FORMAT_CUT_W 7 + +# define R300_TX_FORMAT_B_SHIFT 18 +# define R300_TX_FORMAT_G_SHIFT 15 +# define R300_TX_FORMAT_R_SHIFT 12 +# define R300_TX_FORMAT_A_SHIFT 9 + + /* Convenience macro to take care of layout and swizzling */ +# define R300_EASY_TX_FORMAT(B, G, R, A, FMT) ( \ + ((R300_TX_FORMAT_##B)<mmio + reg)) +#define RegRead32(reg) (Reg32(reg)) +#define RegWrite32(reg, value) (Reg32(reg) = value) + +typedef enum { + kNul, + kStr, + kPtr, + kCst +} type_t; + +typedef enum { + CHIP_FAMILY_UNKNOW, + CHIP_FAMILY_RS600, + CHIP_FAMILY_RS690, + CHIP_FAMILY_RS740, + CHIP_FAMILY_R600, /* r600 */ + CHIP_FAMILY_RV610, + CHIP_FAMILY_RV630, + CHIP_FAMILY_RV670, + CHIP_FAMILY_RV620, + CHIP_FAMILY_RV635, + CHIP_FAMILY_RS780, + CHIP_FAMILY_RS880, + CHIP_FAMILY_RV770, /* r700 */ + CHIP_FAMILY_RV730, + CHIP_FAMILY_RV710, + CHIP_FAMILY_RV740, + CHIP_FAMILY_CEDAR, /* evergreen */ + CHIP_FAMILY_REDWOOD, + CHIP_FAMILY_JUNIPER, + CHIP_FAMILY_CYPRESS, + CHIP_FAMILY_HEMLOCK, + CHIP_FAMILY_LAST +} chip_family_t; + +static const char *chip_family_name[] = { + "UNKNOW", + "RS600", + "RS690", + "RS740", + /* r600 */ + "R600", + "RV610", + "RV630", + "RV670", + "RV620", + "RV635", + "RS780", + "RS880", + /* r700 */ + "RV770", + "RV730", + "RV710", + "RV740", + /* evergreen */ + "Cedar", // RV810 + "Redwood", // RV830 + "Juniper", // RV840 + "Cypress", // RV870 + "Hemlock", +}; + +typedef struct { + const char *name; + uint8_t ports; +} card_config_t; + +static card_config_t card_configs[] = { + {NULL, 0}, + {"Alopias", 2}, + {"Alouatta", 4}, + {"Baboon", 3}, + {"Cardinal", 2}, + {"Caretta", 1}, + {"Colobus", 2}, + {"Douc", 2}, + {"Eulemur", 3}, + {"Flicker", 3}, + {"Galago", 2}, + {"Gliff", 3}, + {"Hoolock", 3}, + {"Hypoprion", 2}, + {"Iago", 2}, + {"Kakapo", 3}, + {"Kipunji", 4}, + {"Lamna", 2}, + {"Langur", 3}, + {"Megalodon", 3}, + {"Motmot", 2}, + {"Nomascus", 5}, + {"Orangutan", 2}, + {"Peregrine", 2}, + {"Quail", 3}, + {"Raven", 3}, + {"Shrike", 3}, + {"Sphyrna", 1}, + {"Triakis", 2}, + {"Uakari", 4}, + {"Vervet", 4}, + {"Zonalis", 6} +}; + +typedef enum { + kNull, + kAlopias, + kAlouatta, + kBaboon, + kCardinal, + kCaretta, + kColobus, + kDouc, + kEulemur, + kFlicker, + kGalago, + kGliff, + kHoolock, + kHypoprion, + kIago, + kKakapo, + kKipunji, + kLamna, + kLangur, + kMegalodon, + kMotmot, + kNomascus, + kOrangutan, + kPeregrine, + kQuail, + kRaven, + kShrike, + kSphyrna, + kTriakis, + kUakari, + kVervet, + kZonalis, + kCfgEnd +} config_name_t; + +typedef struct { + uint16_t device_id; + uint32_t subsys_id; + chip_family_t chip_family; + const char *model_name; + config_name_t cfg_name; +} radeon_card_info_t; + +static radeon_card_info_t radeon_cards[] = { + /* Earlier cards are not supported */ + { 0x9400, 0x30001002, CHIP_FAMILY_R600, "ATI Radeon HD 2900 PRO", kNull }, + { 0x9400, 0x25521002, CHIP_FAMILY_R600, "ATI Radeon HD 2900 XT", kNull }, + + { 0x9440, 0x24401682, CHIP_FAMILY_RV770, "ATI Radeon HD 4870", kMotmot }, + { 0x9440, 0x24411682, CHIP_FAMILY_RV770, "ATI Radeon HD 4870", kMotmot }, + { 0x9440, 0x24441682, CHIP_FAMILY_RV770, "ATI Radeon HD 4870", kMotmot }, + { 0x9440, 0x24451682, CHIP_FAMILY_RV770, "ATI Radeon HD 4870", kMotmot }, + + { 0x9441, 0x24401682, CHIP_FAMILY_RV770, "ATI Radeon HD 4870 X2", kMotmot }, + + { 0x9442, 0x24701682, CHIP_FAMILY_RV770, "ATI Radeon HD 4850", kMotmot }, + { 0x9442, 0x24711682, CHIP_FAMILY_RV770, "ATI Radeon HD 4850", kMotmot }, + { 0x9442, 0x080110B0, CHIP_FAMILY_RV770, "ATI Radeon HD 4850", kMotmot }, + { 0x9442, 0xE104174B, CHIP_FAMILY_RV770, "ATI Radeon HD 4850", kMotmot }, + + { 0x944A, 0x30001682, CHIP_FAMILY_RV770, "ATI Radeon HD 4800 Series", kMotmot }, + { 0x944A, 0x30001043, CHIP_FAMILY_RV770, "ATI Radeon HD 4800 Series", kMotmot }, + { 0x944A, 0x30001458, CHIP_FAMILY_RV770, "ATI Radeon HD 4800 Series", kMotmot }, + { 0x944A, 0x30001462, CHIP_FAMILY_RV770, "ATI Radeon HD 4800 Series", kMotmot }, + { 0x944A, 0x30001545, CHIP_FAMILY_RV770, "ATI Radeon HD 4800 Series", kMotmot }, + { 0x944A, 0x30001787, CHIP_FAMILY_RV770, "ATI Radeon HD 4800 Series", kMotmot }, + { 0x944A, 0x3000174B, CHIP_FAMILY_RV770, "ATI Radeon HD 4800 Series", kMotmot }, + { 0x944A, 0x300017AF, CHIP_FAMILY_RV770, "ATI Radeon HD 4800 Series", kMotmot }, + + { 0x944C, 0x24801682, CHIP_FAMILY_RV770, "ATI Radeon HD 4830", kMotmot }, + { 0x944C, 0x24811682, CHIP_FAMILY_RV770, "ATI Radeon HD 4830", kMotmot }, + + { 0x944E, 0x3260174B, CHIP_FAMILY_RV770, "ATI Radeon HD 4810 Series", kMotmot }, + { 0x944E, 0x3261174B, CHIP_FAMILY_RV770, "ATI Radeon HD 4810 series", kMotmot }, + { 0x944E, 0x30001787, CHIP_FAMILY_RV770, "ATI Radeon HD 4730 Series", kMotmot }, + { 0x944E, 0x30101787, CHIP_FAMILY_RV770, "ATI Radeon HD 4810 Series", kMotmot }, + { 0x944E, 0x31001787, CHIP_FAMILY_RV770, "ATI Radeon HD 4820", kMotmot }, + + { 0x9490, 0x30501787, CHIP_FAMILY_RV730, "ATI Radeon HD 4710", kNull }, + { 0x9490, 0x4710174B, CHIP_FAMILY_RV730, "ATI Radeon HD 4710", kNull }, + { 0x9490, 0x300017AF, CHIP_FAMILY_RV730, "ATI Radeon HD 4710", kNull }, + + { 0x9498, 0x30501787, CHIP_FAMILY_RV730, "ATI Radeon HD 4700", kNull }, + { 0x9498, 0x31001787, CHIP_FAMILY_RV730, "ATI Radeon HD 4720", kNull }, + { 0x9498, 0x24511682, CHIP_FAMILY_RV730, "ATI Radeon HD 4650", kNull }, + { 0x9498, 0x24521682, CHIP_FAMILY_RV730, "ATI Radeon HD 4650", kNull }, + { 0x9498, 0x24541682, CHIP_FAMILY_RV730, "ATI Radeon HD 4650", kNull }, + { 0x9498, 0x29331682, CHIP_FAMILY_RV730, "ATI Radeon HD 4670", kNull }, + { 0x9498, 0x29341682, CHIP_FAMILY_RV730, "ATI Radeon HD 4670", kNull }, + { 0x9498, 0x21CF1458, CHIP_FAMILY_RV730, "ATI Radeon HD 4600 Series", kNull }, + + { 0x94B3, 0x29001682, CHIP_FAMILY_RV740, "ATI Radeon HD 4770", kFlicker }, + { 0x94B3, 0x1170174B, CHIP_FAMILY_RV740, "ATI Radeon HD 4770", kFlicker }, + { 0x94B3, 0x10020D00, CHIP_FAMILY_RV740, "ATI Radeon HD 4770", kFlicker }, + + { 0x94C1, 0x10021002, CHIP_FAMILY_RV610, "ATI Radeon HD 2400 Pro", kNull }, + { 0x94C1, 0x0D021002, CHIP_FAMILY_RV610, "ATI Radeon HD 2400 XT", kNull }, + { 0x94C1, 0x0D021028, CHIP_FAMILY_RV610, "ATI Radeon HD 2400 Pro", kNull }, + { 0x94C1, 0x0D021028, CHIP_FAMILY_RV610, "ATI Radeon HD 2400 XT", kNull }, + { 0x94C1, 0x21741458, CHIP_FAMILY_RV610, "ATI Radeon HD 2400 XT", kNull }, + { 0x94C1, 0x10401462, CHIP_FAMILY_RV610, "ATI Radeon HD 2400 XT", kNull }, + { 0x94C1, 0x10331462, CHIP_FAMILY_RV610, "ATI Radeon HD 2400 XT", kNull }, + { 0x94C1, 0x10331462, CHIP_FAMILY_RV610, "ATI Radeon HD 2400 XT", kNull }, + { 0x94C1, 0x11101462, CHIP_FAMILY_RV610, "ATI Radeon HD 2400 XT", kNull }, + + { 0x94C3, 0x37161642, CHIP_FAMILY_RV610, "ATI Radeon HD 2400 PRO", kNull }, + { 0x94C3, 0x30001642, CHIP_FAMILY_RV610, "ATI Radeon HD 3410", kNull }, + { 0x94C3, 0x03421002, CHIP_FAMILY_RV610, "ATI Radeon HD 2400 PRO", kNull }, + { 0x94C3, 0x30001025, CHIP_FAMILY_RV610, "ATI Radeon HD 2350 Series", kNull }, + { 0x94C3, 0x04021028, CHIP_FAMILY_RV610, "ATI Radeon HD 2400", kNull }, + { 0x94C3, 0x03021028, CHIP_FAMILY_RV610, "ATI Radeon HD 2400 PRO", kNull }, + { 0x94C3, 0x04021028, CHIP_FAMILY_RV610, "ATI Radeon HD 2400 PRO", kNull }, + { 0x94C3, 0x216A1458, CHIP_FAMILY_RV610, "ATI Radeon HD 2400 PRO", kNull }, + { 0x94C3, 0x21721458, CHIP_FAMILY_RV610, "ATI Radeon HD 2400 PRO", kNull }, + { 0x94C3, 0x30001458, CHIP_FAMILY_RV610, "ATI Radeon HD 3410", kNull }, + { 0x94C3, 0x11041462, CHIP_FAMILY_RV610, "ATI Radeon HD 2400", kNull }, + { 0x94C3, 0x10411462, CHIP_FAMILY_RV610, "ATI Radeon HD 2400", kNull }, + { 0x94C3, 0x11051462, CHIP_FAMILY_RV610, "ATI Radeon HD 2400", kNull }, + { 0x94C3, 0x10321462, CHIP_FAMILY_RV610, "ATI Radeon HD 2400 PRO", kNull }, + { 0x94C3, 0x30001462, CHIP_FAMILY_RV610, "ATI Radeon HD 3410", kNull }, + { 0x94C3, 0x3000148C, CHIP_FAMILY_RV610, "ATI Radeon HD 2350 Series", kNull }, + { 0x94C3, 0x2247148C, CHIP_FAMILY_RV610, "ATI Radeon HD 2400 LE", kNull }, + { 0x94C3, 0x3000174B, CHIP_FAMILY_RV610, "ATI Radeon HD 2350 Series", kNull }, + { 0x94C3, 0xE400174B, CHIP_FAMILY_RV610, "ATI Radeon HD 2400 PRO", kNull }, + { 0x94C3, 0xE370174B, CHIP_FAMILY_RV610, "ATI Radeon HD 2400 PRO", kNull }, + { 0x94C3, 0xE400174B, CHIP_FAMILY_RV610, "ATI Radeon HD 2400 PRO", kNull }, + { 0x94C3, 0xE370174B, CHIP_FAMILY_RV610, "ATI Radeon HD 2400 PRO", kNull }, + { 0x94C3, 0xE400174B, CHIP_FAMILY_RV610, "ATI Radeon HD 2400 PRO", kNull }, + { 0x94C3, 0x203817AF, CHIP_FAMILY_RV610, "ATI Radeon HD 2400", kNull }, + { 0x94C3, 0x30001787, CHIP_FAMILY_RV610, "ATI Radeon HD 2350 Series", kNull }, + { 0x94C3, 0x22471787, CHIP_FAMILY_RV610, "ATI Radeon HD 2400 LE", kNull }, + { 0x94C3, 0x01011A93, CHIP_FAMILY_RV610, "Qimonda Radeon HD 2400 PRO", kNull }, + + + { 0x9501, 0x30001002, CHIP_FAMILY_RV670, "ATI Radeon HD 3690", kNull }, + { 0x9501, 0x25421002, CHIP_FAMILY_RV670, "ATI Radeon HD 3870", kNull }, + { 0x9501, 0x4750174B, CHIP_FAMILY_RV670, "ATI Radeon HD 4750", kNull }, + { 0x9501, 0x3000174B, CHIP_FAMILY_RV670, "Sapphire Radeon HD 3690", kNull }, + { 0x9501, 0x30001787, CHIP_FAMILY_RV670, "ATI Radeon HD 3690", kNull }, + + { 0x9505, 0x30001002, CHIP_FAMILY_RV670, "ATI Radeon HD 3690", kNull }, + { 0x9505, 0x25421002, CHIP_FAMILY_RV670, "ATI Radeon HD 3850", kNull }, + { 0x9505, 0x30011043, CHIP_FAMILY_RV670, "ATI Radeon HD 4730", kNull }, + { 0x9505, 0x3000148C, CHIP_FAMILY_RV670, "ATI Radeon HD 3850", kNull }, + { 0x9505, 0x3002148C, CHIP_FAMILY_RV670, "ATI Radeon HD 4730", kNull }, + { 0x9505, 0x3001148C, CHIP_FAMILY_RV670, "ATI Radeon HD 4730", kNull }, + { 0x9505, 0x3003148C, CHIP_FAMILY_RV670, "ATI Radeon HD 4750", kNull }, + { 0x9505, 0x3004148C, CHIP_FAMILY_RV670, "ATI Radeon HD 4750", kNull }, + { 0x9505, 0x4730174B, CHIP_FAMILY_RV670, "ATI Radeon HD 4730", kNull }, + { 0x9505, 0x3010174B, CHIP_FAMILY_RV670, "ATI Radeon HD 4750", kNull }, + { 0x9505, 0x3001174B, CHIP_FAMILY_RV670, "ATI Radeon HD 4750", kNull }, + { 0x9505, 0x3000174B, CHIP_FAMILY_RV670, "Sapphire Radeon HD 3690", kNull }, + { 0x9505, 0x30001787, CHIP_FAMILY_RV670, "ATI Radeon HD 3690", kNull }, + { 0x9505, 0x301017AF, CHIP_FAMILY_RV670, "ATI Radeon HD 4750", kNull }, + + { 0x9540, 0x4590174B, CHIP_FAMILY_RV710, "ATI Radeon HD 4590", kNull }, + { 0x9540, 0x30501787, CHIP_FAMILY_RV710, "ATI Radeon HD 4590", kNull }, + + { 0x954F, 0x29201682, CHIP_FAMILY_RV710, "ATI Radeon HD 4550", kNull }, + { 0x954F, 0x29211682, CHIP_FAMILY_RV710, "ATI Radeon HD 4550", kNull }, + { 0x954F, 0x30901682, CHIP_FAMILY_RV710, "XFX Radeon HD 4570", kNull }, + { 0x954F, 0x4450174B, CHIP_FAMILY_RV710, "ATI Radeon HD 4450", kNull }, + { 0x954F, 0x3000174B, CHIP_FAMILY_RV710, "ATI Radeon HD 4520", kNull }, + { 0x954F, 0x30501787, CHIP_FAMILY_RV710, "ATI Radeon HD 4450", kNull }, + { 0x954F, 0x31001787, CHIP_FAMILY_RV710, "ATI Radeon HD 4520", kNull }, + { 0x954F, 0x4570174B, CHIP_FAMILY_RV710, "Sapphire Radeon HD4570", kNull }, + { 0x954F, 0x301017AF, CHIP_FAMILY_RV710, "ATI Radeon HD 4450", kNull }, + + { 0x9552, 0x3000148C, CHIP_FAMILY_RV710, "ATI Radeon HD 4300/4500 Series", kNull }, + { 0x9552, 0x3000174B, CHIP_FAMILY_RV710, "ATI Radeon HD 4300/4500 Series", kNull }, + { 0x9552, 0x30001787, CHIP_FAMILY_RV710, "ATI Radeon HD 4300/4500 Series", kNull }, + { 0x9552, 0x300017AF, CHIP_FAMILY_RV710, "ATI Radeon HD 4300/4500 Series", kNull }, + + { 0x9581, 0x95811002, CHIP_FAMILY_RV630, "ATI Radeon HD 3600 Series", kNull }, + { 0x9581, 0x3000148C, CHIP_FAMILY_RV630, "ATI Radeon HD 3600 Series", kNull }, + + { 0x9583, 0x3000148C, CHIP_FAMILY_RV630, "ATI Radeon HD 3600 Series", kNull }, + { 0x9588, 0x01021A93, CHIP_FAMILY_RV630, "Qimonda Radeon HD 2600 XT", kNull }, + + { 0x9589, 0x30001462, CHIP_FAMILY_RV630, "ATI Radeon HD 3610", kNull }, + { 0x9589, 0x30001642, CHIP_FAMILY_RV630, "ATI Radeon HD 3610", kNull }, + { 0x9589, 0x0E41174B, CHIP_FAMILY_RV630, "ATI Radeon HD 3600 Series", kNull }, + { 0x9589, 0x30001787, CHIP_FAMILY_RV630, "ATI Radeon HD 3600 Series", kNull }, + { 0x9589, 0x01001A93, CHIP_FAMILY_RV630, "Qimonda Radeon HD 2600 PRO", kNull }, + + { 0x9591, 0x2303148C, CHIP_FAMILY_RV635, "ATI Radeon HD 3600 Series", kNull }, + + { 0x9598, 0xB3831002, CHIP_FAMILY_RV635, "ATI All-in-Wonder HD", kNull }, + { 0x9598, 0x30011043, CHIP_FAMILY_RV635, "ATI Radeon HD 4570", kNull }, + { 0x9598, 0x30001043, CHIP_FAMILY_RV635, "HD3730", kNull }, + { 0x9598, 0x3000148C, CHIP_FAMILY_RV635, "ATI Radeon HD 3730", kNull }, + { 0x9598, 0x3031148C, CHIP_FAMILY_RV635, "ATI Radeon HD 4570", kNull }, + { 0x9598, 0x3001148C, CHIP_FAMILY_RV635, "ATI Radeon HD 4580", kNull }, + { 0x9598, 0x30011545, CHIP_FAMILY_RV635, "VisionTek Radeon HD 2600 Pro", kNull }, + { 0x9598, 0x30001545, CHIP_FAMILY_RV635, "VisionTek Radeon HD 2600 XT", kNull }, + { 0x9598, 0x4570174B, CHIP_FAMILY_RV635, "ATI Radeon HD 4570", kNull }, + { 0x9598, 0x4580174B, CHIP_FAMILY_RV635, "ATI Radeon HD 4580", kNull }, + { 0x9598, 0x4610174B, CHIP_FAMILY_RV635, "ATI Radeon HD 4610", kNull }, + { 0x9598, 0x3000174B, CHIP_FAMILY_RV635, "Sapphire Radeon HD 3730", kNull }, + { 0x9598, 0x3001174B, CHIP_FAMILY_RV635, "Sapphire Radeon HD 3750", kNull }, + { 0x9598, 0x301017AF, CHIP_FAMILY_RV635, "ATI Radeon HD 4570", kNull }, + { 0x9598, 0x301117AF, CHIP_FAMILY_RV635, "ATI Radeon HD 4580", kNull }, + { 0x9598, 0x300117AF, CHIP_FAMILY_RV635, "ATI Radeon HD3750", kNull }, + { 0x9598, 0x30501787, CHIP_FAMILY_RV635, "ATI Radeon HD 4610", kNull }, + + { 0x95C0, 0x3000148C, CHIP_FAMILY_RV620, "ATI Radeon HD 3550", kNull }, + { 0x95C0, 0xE3901745, CHIP_FAMILY_RV620, "ATI Radeon HD 3550", kNull }, + { 0x95C0, 0x3002174B, CHIP_FAMILY_RV620, "ATI Radeon HD 3570", kNull }, + { 0x95C0, 0x3020174B, CHIP_FAMILY_RV620, "ATI Radeon HD 4250", kNull }, + { 0x95C0, 0x3000174B, CHIP_FAMILY_RV620, "Sapphire Radeon HD 3550", kNull }, + + { 0x95C5, 0x3000148C, CHIP_FAMILY_RV620, "ATI Radeon HD 3450", kNull }, + { 0x95C5, 0x3001148C, CHIP_FAMILY_RV620, "ATI Radeon HD 3550", kNull }, + { 0x95C5, 0x3002148C, CHIP_FAMILY_RV620, "ATI Radeon HD 4230", kNull }, + { 0x95C5, 0x3033148C, CHIP_FAMILY_RV620, "ATI Radeon HD 4230", kNull }, + { 0x95C5, 0x3003148C, CHIP_FAMILY_RV620, "ATI Radeon HD 4250", kNull }, + { 0x95C5, 0x3032148C, CHIP_FAMILY_RV620, "ATI Radeon HD 4250", kNull }, + { 0x95C5, 0x3010174B, CHIP_FAMILY_RV620, "ATI Radeon HD 4250", kNull }, + { 0x95C5, 0x4250174B, CHIP_FAMILY_RV620, "ATI Radeon HD 4250", kNull }, + { 0x95C5, 0x30501787, CHIP_FAMILY_RV620, "ATI Radeon HD 4250", kNull }, + { 0x95C5, 0x301017AF, CHIP_FAMILY_RV620, "ATI Radeon HD 4230", kNull }, + { 0x95C5, 0x01051A93, CHIP_FAMILY_RV620, "Qimonda Radeon HD 3450", kNull }, + { 0x95C5, 0x01041A93, CHIP_FAMILY_RV620, "Qimonda Radeon HD 3450", kNull }, + + /* Evergreen */ + { 0x6898, 0x032E1043, CHIP_FAMILY_CYPRESS, "ATI Radeon HD 5870", kUakari }, + { 0x6898, 0xE140174B, CHIP_FAMILY_CYPRESS, "ATI Radeon HD 5870", kUakari }, + { 0x6898, 0x29611682, CHIP_FAMILY_CYPRESS, "ATI Radeon HD 5870", kUakari }, + { 0x6898, 0x0B001002, CHIP_FAMILY_CYPRESS, "ATI Radeon HD 5870", kZonalis }, + { 0x6898, 0x00D0106B, CHIP_FAMILY_CYPRESS, "ATI Radeon HD 5870", kLangur }, + + { 0x6899, 0x21E41458, CHIP_FAMILY_CYPRESS, "ATI Radeon HD 5850", kUakari }, + { 0x6899, 0x200A1787, CHIP_FAMILY_CYPRESS, "ATI Radeon HD 5850", kUakari }, + { 0x6899, 0x22901787, CHIP_FAMILY_CYPRESS, "ATI Radeon HD 5850", kUakari }, + { 0x6899, 0xE140174B, CHIP_FAMILY_CYPRESS, "ATI Radeon HD 5850", kUakari }, + + { 0x689C, 0x03521043, CHIP_FAMILY_HEMLOCK, "ASUS ARES", kUakari }, + { 0x689C, 0x039E1043, CHIP_FAMILY_HEMLOCK, "ASUS EAH5870 Series", kUakari }, + { 0x689C, 0x30201682, CHIP_FAMILY_HEMLOCK, "ATI Radeon HD 5970", kUakari }, + + { 0x68B8, 0xE147174B, CHIP_FAMILY_JUNIPER, "ATI Radeon HD 5770", kVervet }, + { 0x68B8, 0x21D71458, CHIP_FAMILY_JUNIPER, "ATI Radeon HD 5770", kVervet }, + { 0x68B8, 0x1482174B, CHIP_FAMILY_JUNIPER, "ATI Radeon HD 5770", kVervet }, + { 0x68B8, 0x29901682, CHIP_FAMILY_JUNIPER, "ATI Radeon HD 5770", kVervet }, + { 0x68B8, 0x29911682, CHIP_FAMILY_JUNIPER, "ATI Radeon HD 5770", kVervet }, + { 0x68B8, 0x200B1787, CHIP_FAMILY_JUNIPER, "ATI Radeon HD 5770", kVervet }, + { 0x68B8, 0x22881787, CHIP_FAMILY_JUNIPER, "ATI Radeon HD 5770", kVervet }, + { 0x68B8, 0x00CF106B, CHIP_FAMILY_JUNIPER, "ATI Radeon HD 5770", kHoolock }, + + { 0x68D8, 0x301117AF, CHIP_FAMILY_REDWOOD, "ATI Radeon HD 5690", kNull }, + { 0x68D8, 0x301017AF, CHIP_FAMILY_REDWOOD, "ATI Radeon HD 5730", kNull }, + { 0x68D8, 0x30001787, CHIP_FAMILY_REDWOOD, "ATI Radeon HD 5730", kNull }, + { 0x68D8, 0x5690174B, CHIP_FAMILY_REDWOOD, "ATI Radeon HD 5690", kNull }, + { 0x68D8, 0x5730174B, CHIP_FAMILY_REDWOOD, "ATI Radeon HD 5730", kNull }, + { 0x68D8, 0x21D91458, CHIP_FAMILY_REDWOOD, "ATI Radeon HD 5670", kBaboon }, + { 0x68D8, 0x03561043, CHIP_FAMILY_REDWOOD, "ATI Radeon HD 5670", kBaboon }, + { 0x68D8, 0xE151174B, CHIP_FAMILY_REDWOOD, "ATI Radeon HD 5670", kBaboon }, + { 0x68D9, 0x301017AF, CHIP_FAMILY_REDWOOD, "ATI Radeon HD 5630", kNull }, + { 0x68DA, 0x301017AF, CHIP_FAMILY_REDWOOD, "ATI Radeon HD 5630", kNull }, + { 0x68DA, 0x30001787, CHIP_FAMILY_REDWOOD, "ATI Radeon HD 5630", kNull }, + { 0x68DA, 0x5630174B, CHIP_FAMILY_REDWOOD, "ATI Radeon HD 5630", kNull }, + + { 0x68F9, 0x301317AF, CHIP_FAMILY_CEDAR, "ATI Radeon HD 5470", kNull }, + { 0x68F9, 0x301117AF, CHIP_FAMILY_CEDAR, "ATI Radeon HD 5470", kNull }, + { 0x68F9, 0x301217AF, CHIP_FAMILY_CEDAR, "ATI Radeon HD 5490", kNull }, + { 0x68F9, 0x30001787, CHIP_FAMILY_CEDAR, "ATI Radeon HD 5470", kNull }, + { 0x68F9, 0x30021787, CHIP_FAMILY_CEDAR, "ATI Radeon HD 5490", kNull }, + { 0x68F9, 0x30011787, CHIP_FAMILY_CEDAR, "ATI Radeon HD 5530", kNull }, + { 0x68F9, 0x5470174B, CHIP_FAMILY_CEDAR, "ATI Radeon HD 5470", kNull }, + { 0x68F9, 0x5490174B, CHIP_FAMILY_CEDAR, "ATI Radeon HD 5490", kNull }, + { 0x68F9, 0x5530174B, CHIP_FAMILY_CEDAR, "ATI Radeon HD 5530", kNull }, + + /* standard/default models */ + { 0x9400, 0x00000000, CHIP_FAMILY_R600, "ATI Radeon HD 2900 XT", kNull }, + { 0x9405, 0x00000000, CHIP_FAMILY_R600, "ATI Radeon HD 2900 GT", kNull }, + { 0x9440, 0x00000000, CHIP_FAMILY_RV770, "ATI Radeon HD 4800 Series", kMotmot }, + { 0x9441, 0x00000000, CHIP_FAMILY_RV770, "ATI Radeon HD 4870 X2", kMotmot }, + { 0x9442, 0x00000000, CHIP_FAMILY_RV770, "ATI Radeon HD 4800 Series", kMotmot }, + { 0x9443, 0x00000000, CHIP_FAMILY_RV770, "ATI Radeon HD 4850 X2", kMotmot }, + { 0x944C, 0x00000000, CHIP_FAMILY_RV770, "ATI Radeon HD 4800 Series", kMotmot }, + { 0x944E, 0x00000000, CHIP_FAMILY_RV770, "ATI Radeon HD 4700 Series", kMotmot }, + { 0x944E, 0x00000000, CHIP_FAMILY_RV770, "ATI Radeon HD 4700 Series", kMotmot }, + { 0x9450, 0x00000000, CHIP_FAMILY_RV770, "AMD FireStream 9270", kMotmot }, + { 0x9452, 0x00000000, CHIP_FAMILY_RV770, "AMD FireStream 9250", kMotmot }, + { 0x9460, 0x00000000, CHIP_FAMILY_RV770, "ATI Radeon HD 4800 Series", kMotmot }, + { 0x9462, 0x00000000, CHIP_FAMILY_RV770, "ATI Radeon HD 4800 Series", kMotmot }, + { 0x9490, 0x00000000, CHIP_FAMILY_RV730, "ATI Radeon HD 4600 Series", kFlicker }, + { 0x9498, 0x00000000, CHIP_FAMILY_RV730, "ATI Radeon HD 4600 Series", kFlicker }, + { 0x94B3, 0x00000000, CHIP_FAMILY_RV740, "ATI Radeon HD 4770", kFlicker }, + { 0x94B4, 0x00000000, CHIP_FAMILY_RV740, "ATI Radeon HD 4700 Series", kFlicker }, + { 0x94B5, 0x00000000, CHIP_FAMILY_RV740, "ATI Radeon HD 4770", kFlicker }, + { 0x94C1, 0x00000000, CHIP_FAMILY_RV610, "ATI Radeon HD 2400 Series", kIago }, + { 0x94C3, 0x00000000, CHIP_FAMILY_RV610, "ATI Radeon HD 2400 Series", kIago }, + { 0x94C7, 0x00000000, CHIP_FAMILY_RV610, "ATI Radeon HD 2350", kIago }, + { 0x94CC, 0x00000000, CHIP_FAMILY_RV610, "ATI Radeon HD 2400 Series", kIago }, + + { 0x9501, 0x00000000, CHIP_FAMILY_RV670, "ATI Radeon HD 3800 Series", kMegalodon }, + { 0x9505, 0x00000000, CHIP_FAMILY_RV670, "ATI Radeon HD 3800 Series", kMegalodon }, + { 0x9507, 0x00000000, CHIP_FAMILY_RV670, "ATI Radeon HD 3830", kMegalodon }, + { 0x950F, 0x00000000, CHIP_FAMILY_RV670, "ATI Radeon HD 3870 X2", kMegalodon }, + { 0x9513, 0x00000000, CHIP_FAMILY_RV670, "ATI Radeon HD 3850 X2", kMegalodon }, + { 0x9519, 0x00000000, CHIP_FAMILY_RV670, "AMD FireStream 9170", kMegalodon }, + { 0x9540, 0x00000000, CHIP_FAMILY_RV710, "ATI Radeon HD 4550", kNull }, + { 0x954F, 0x00000000, CHIP_FAMILY_RV710, "ATI Radeon HD 4300/4500 Series", kNull }, + { 0x9588, 0x00000000, CHIP_FAMILY_RV630, "ATI Radeon HD 2600 XT", kLamna }, + { 0x9589, 0x00000000, CHIP_FAMILY_RV630, "ATI Radeon HD 2600 PRO", kLamna }, + { 0x958A, 0x00000000, CHIP_FAMILY_RV630, "ATI Radeon HD 2600 X2 Series", kLamna }, + { 0x9598, 0x00000000, CHIP_FAMILY_RV635, "ATI Radeon HD 3600 Series", kMegalodon }, + { 0x95C0, 0x00000000, CHIP_FAMILY_RV620, "ATI Radeon HD 3400 Series", kIago }, + { 0x95C5, 0x00000000, CHIP_FAMILY_RV620, "ATI Radeon HD 3400 Series", kIago }, + + { 0x9610, 0x00000000, CHIP_FAMILY_RS780, "ATI Radeon HD 3200 Graphics", kNull }, + { 0x9611, 0x00000000, CHIP_FAMILY_RS780, "ATI Radeon 3100 Graphics", kNull }, + { 0x9614, 0x00000000, CHIP_FAMILY_RS780, "ATI Radeon HD 3300 Graphics", kNull }, + { 0x9616, 0x00000000, CHIP_FAMILY_RS780, "AMD 760G", kNull }, + + { 0x9710, 0x00000000, CHIP_FAMILY_RS880, "ATI Radeon HD 4200", kNull }, + { 0x9715, 0x00000000, CHIP_FAMILY_RS880, "ATI Radeon HD 4250", kNull }, + { 0x9714, 0x00000000, CHIP_FAMILY_RS880, "ATI Radeon HD 4290", kNull }, + + + { 0x688D, 0x00000000, CHIP_FAMILY_CYPRESS, "AMD FireStream 9350", kUakari }, + + { 0x6898, 0x00000000, CHIP_FAMILY_CYPRESS, "ATI Radeon HD 5800 Series", kUakari }, + { 0x6899, 0x00000000, CHIP_FAMILY_CYPRESS, "ATI Radeon HD 5800 Series", kUakari }, + { 0x689E, 0x00000000, CHIP_FAMILY_CYPRESS, "ATI Radeon HD 5800 Series", kUakari }, + { 0x689C, 0x00000000, CHIP_FAMILY_HEMLOCK, "ATI Radeon HD 5900 Series", kUakari }, + + { 0x68B9, 0x00000000, CHIP_FAMILY_JUNIPER, "ATI Radeon HD 5600 Series", kVervet }, + { 0x68B8, 0x00000000, CHIP_FAMILY_JUNIPER, "ATI Radeon HD 5700 Series", kVervet }, + { 0x68BE, 0x00000000, CHIP_FAMILY_JUNIPER, "ATI Radeon HD 5700 Series", kVervet }, + + { 0x68D8, 0x00000000, CHIP_FAMILY_REDWOOD, "ATI Radeon HD 5600 Series", kBaboon }, + { 0x68D9, 0x00000000, CHIP_FAMILY_REDWOOD, "ATI Radeon HD 5500 Series", kBaboon }, + { 0x68DA, 0x00000000, CHIP_FAMILY_REDWOOD, "ATI Radeon HD 5500 Series", kBaboon }, + + { 0x68F9, 0x00000000, CHIP_FAMILY_CEDAR, "ATI Radeon HD 5400 Series", kNull }, + + { 0x0000, 0x00000000, CHIP_FAMILY_UNKNOW, NULL, kNull } +}; + + +typedef struct { + struct DevPropDevice *device; + radeon_card_info_t *info; + pci_dt_t *pci_dev; + uint8_t *fb; + uint8_t *mmio; + uint8_t *io; + uint8_t *rom; + uint32_t rom_size; + uint32_t vram_size; + uint8_t ports; + uint32_t flags; + bool posted; +} card_t; +card_t *card; + +/* Flags */ +#define MKFLAG(n) (1 << n) +#define FLAGTRUE MKFLAG(0) +#define EVERGREEN MKFLAG(1) + +static uint8_t atN = 0; + +typedef struct { + type_t type; + uint32_t size; + uint8_t *data; +} value_t; + +static value_t aty_name; +static value_t aty_nameparent; +//static value_t aty_model; + +#define DATVAL(x) {kPtr, sizeof(x), (uint8_t *)x} +#define STRVAL(x) {kStr, sizeof(x), (uint8_t *)x} +#define BYTVAL(x) {kCst, 1, (uint8_t *)x} +#define WRDVAL(x) {kCst, 2, (uint8_t *)x} +#define DWRVAL(x) {kCst, 4, (uint8_t *)x} +#define QWRVAL(x) {kCst, 8, (uint8_t *)x} +#define NULVAL {kNul, 0, (uint8_t *)NULL} + +bool get_bootdisplay_val(value_t *val); +bool get_vrammemory_val(value_t *val); +bool get_name_val(value_t *val); +bool get_nameparent_val(value_t *val); +bool get_model_val(value_t *val); +bool get_conntype_val(value_t *val); +bool get_vrammemsize_val(value_t *val); +bool get_binimage_val(value_t *val); +bool get_romrevision_val(value_t *val); +bool get_deviceid_val(value_t *val); +bool get_mclk_val(value_t *val); +bool get_sclk_val(value_t *val); +bool get_refclk_val(value_t *val); +bool get_platforminfo_val(value_t *val); +bool get_vramtotalsize_val(value_t *val); + +typedef struct { + uint32_t flags; + bool all_ports; + char *name; + bool (*get_value)(value_t *val); + value_t default_val; +} dev_prop_t; + +dev_prop_t ati_devprop_list[] = { + {FLAGTRUE, false, "@0,AAPL,boot-display", get_bootdisplay_val, NULVAL }, +// {FLAGTRUE, false, "@0,ATY,EFIDisplay", NULL, STRVAL("TMDSA") }, + +// {FLAGTRUE, true, "@0,AAPL,vram-memory", get_vrammemory_val, NULVAL }, +// {FLAGTRUE, true, "@0,compatible", get_name_val, NULVAL }, +// {FLAGTRUE, true, "@0,connector-type", get_conntype_val, NULVAL }, +// {FLAGTRUE, true, "@0,device_type", NULL, STRVAL("display") }, +// {FLAGTRUE, false, "@0,display-connect-flags", NULL, DWRVAL((uint32_t)0) }, +// {FLAGTRUE, true, "@0,display-type", NULL, STRVAL("NONE") }, + {FLAGTRUE, true, "@0,name", get_name_val, NULVAL }, +// {FLAGTRUE, true, "@0,VRAM,memsize", get_vrammemsize_val, NULVAL }, + +// {FLAGTRUE, false, "AAPL,aux-power-connected", NULL, DWRVAL((uint32_t)1) }, +// {FLAGTRUE, false, "AAPL,backlight-control", NULL, DWRVAL((uint32_t)0) }, + {FLAGTRUE, false, "ATY,bin_image", get_binimage_val, NULVAL }, + {FLAGTRUE, false, "ATY,Copyright", NULL, STRVAL("Copyright AMD Inc. All Rights Reserved. 2005-2010") }, + {FLAGTRUE, false, "ATY,Card#", get_romrevision_val, NULVAL }, + {FLAGTRUE, false, "ATY,VendorID", NULL, WRDVAL((uint16_t)0x1002) }, + {FLAGTRUE, false, "ATY,DeviceID", get_deviceid_val, NULVAL }, + +// {FLAGTRUE, false, "ATY,MCLK", get_mclk_val, NULVAL }, +// {FLAGTRUE, false, "ATY,SCLK", get_sclk_val, NULVAL }, +// {FLAGTRUE, false, "ATY,RefCLK", get_refclk_val, DWRVAL((uint32_t)0x0a8c) }, + +// {FLAGTRUE, false, "ATY,PlatformInfo", get_platforminfo_val, NULVAL }, + + {FLAGTRUE, false, "name", get_nameparent_val, NULVAL }, + {FLAGTRUE, false, "device_type", get_nameparent_val, NULVAL }, + {FLAGTRUE, false, "model", get_model_val, STRVAL("ATI Radeon") }, +// {FLAGTRUE, false, "VRAM,totalsize", get_vramtotalsize_val, NULVAL }, + + {FLAGTRUE, false, NULL, NULL, NULVAL } +}; + +bool get_bootdisplay_val(value_t *val) +{ + static uint32_t v = 0; + + if (v) + return false; + + if (!card->posted) + return false; + + v = 1; + val->type = kCst; + val->size = 4; + val->data = (uint8_t *)&v; + + return true; +} + +bool get_vrammemory_val(value_t *val) +{ + return false; +} + +bool get_name_val(value_t *val) +{ + val->type = aty_name.type; + val->size = aty_name.size; + val->data = aty_name.data; + + return true; +} + +bool get_nameparent_val(value_t *val) +{ + val->type = aty_nameparent.type; + val->size = aty_nameparent.size; + val->data = aty_nameparent.data; + + return true; +} + +bool get_model_val(value_t *val) +{ + if (!card->info->model_name) + return false; + + val->type = kStr; + val->size = strlen(card->info->model_name) + 1; + val->data = (uint8_t *)card->info->model_name; + + return true; +} + +bool get_conntype_val(value_t *val) +{ +/* +Connector types: +0x4 : DisplayPort +0x400: DL DVI-I +0x800: HDMI +*/ + return false; +} + +bool get_vrammemsize_val(value_t *val) +{ + static int idx = -1; + static uint64_t memsize; + + idx++; + memsize = ((uint64_t)card->vram_size << 32); + if (idx == 0) + memsize = memsize | (uint64_t)card->vram_size; + + val->type = kCst; + val->size = 8; + val->data = (uint8_t *)&memsize; + + return true; +} + +bool get_binimage_val(value_t *val) +{ + if (!card->rom) + return false; + + val->type = kPtr; + val->size = card->rom_size; + val->data = card->rom; + + return true; +} + +bool get_romrevision_val(value_t *val) +{ + uint8_t *rev; + if (!card->rom) + return false; + + rev = card->rom + *(uint8_t *)(card->rom + OFFSET_TO_GET_ATOMBIOS_STRINGS_START); + + val->type = kPtr; + val->size = strlen((char *)rev); + val->data = malloc(val->size); + + if (!val->data) + return false; + + memcpy(val->data, rev, val->size); + + return true; +} + +bool get_deviceid_val(value_t *val) +{ + val->type = kCst; + val->size = 2; + val->data = (uint8_t *)&card->pci_dev->device_id; + + return true; +} + +bool get_mclk_val(value_t *val) +{ + return false; +} + +bool get_sclk_val(value_t *val) +{ + return false; +} + +bool get_refclk_val(value_t *val) +{ + return false; +} + +bool get_platforminfo_val(value_t *val) +{ + val->data = malloc(0x80); + if (!val->data) + return false; + + bzero(val->data, 0x80); + + val->type = kPtr; + val->size = 0x80; + val->data[0] = 1; + + return true; +} + +bool get_vramtotalsize_val(value_t *val) +{ + val->type = kCst; + val->size = 4; + val->data = (uint8_t *)&card->vram_size; + + return true; +} + +void free_val(value_t *val) +{ + if (val->type == kPtr) + free(val->data); + bzero(val, sizeof(value_t)); +} + +void devprop_add_list(dev_prop_t devprop_list[]) +{ + value_t *val = malloc(sizeof(value_t)); + int i, pnum; + for (i = 0; devprop_list[i].name != NULL; i++) + if ((devprop_list[i].flags == FLAGTRUE) || (devprop_list[i].flags | card->flags)) + if (devprop_list[i].get_value && devprop_list[i].get_value(val)) + { + devprop_add_value(card->device, devprop_list[i].name, val->data, val->size); + free_val(val); + if (devprop_list[i].all_ports) + { + for (pnum = 1; pnum < card->ports; pnum++) + { + if (devprop_list[i].get_value(val)) + { + devprop_list[i].name[1] = 0x30 + pnum; // convert to ascii + devprop_add_value(card->device, devprop_list[i].name, val->data, val->size); + free_val(val); + } + } + devprop_list[i].name[1] = 0x30; // write back our "@0," for a next possible card + } + } + else + { + if (devprop_list[i].default_val.type != kNul) + devprop_add_value(card->device, devprop_list[i].name, + devprop_list[i].default_val.type == kCst ? + (uint8_t *)&(devprop_list[i].default_val.data) : devprop_list[i].default_val.data, + devprop_list[i].default_val.size); + + if (devprop_list[i].all_ports) + { + for (pnum = 1; pnum < card->ports; pnum++) + { + if (devprop_list[i].default_val.type != kNul) + { + devprop_list[i].name[1] = 0x30 + pnum; // convert to ascii + devprop_add_value(card->device, devprop_list[i].name, + devprop_list[i].default_val.type == kCst ? + (uint8_t *)&(devprop_list[i].default_val.data) : devprop_list[i].default_val.data, + devprop_list[i].default_val.size); + } + } + devprop_list[i].name[1] = 0x30; // write back our "@0," for a next possible card + } + } + + free(val); +} + + +bool validate_rom(option_rom_header_t *rom_header, pci_dt_t *pci_dev) +{ + option_rom_pci_header_t *rom_pci_header; + + if (rom_header->signature != 0xaa55) + return false; + + rom_pci_header = (option_rom_pci_header_t *)((uint8_t *)rom_header + rom_header->pci_header_offset); + + if (rom_pci_header->signature != 0x52494350) + return false; + + if (rom_pci_header->vendor_id != pci_dev->vendor_id || rom_pci_header->device_id != pci_dev->device_id) + return false; + + return true; +} + +bool load_vbios_file(const char *key, uint16_t vendor_id, uint16_t device_id, uint32_t subsys_id) +{ + int fd; + char file_name[24]; + bool do_load = false; + + getBoolForKey(key, &do_load, &bootInfo->bootConfig); + if (!do_load) + return false; + + sprintf(file_name, "/Extra/%04x_%04x_%08x.rom", vendor_id, device_id, subsys_id); + if ((fd = open_bvdev("bt(0,0)", file_name, 0)) < 0) + return false; + + card->rom_size = file_size(fd); + card->rom = malloc(card->rom_size); + if (!card->rom) + return false; + + read(fd, (char *)card->rom, card->rom_size); + + if (!validate_rom((option_rom_header_t *)card->rom, card->pci_dev)) + { + card->rom_size = 0; + card->rom = 0; + return false; + } + + card->rom_size = ((option_rom_header_t *)card->rom)->rom_size * 512; + + close(fd); + + return true; +} + +void get_vram_size(void) +{ + chip_family_t chip_family = card->info->chip_family; + + card->vram_size = 0; + + if (chip_family >= CHIP_FAMILY_CEDAR) + /* size in MB on evergreen */ + /* XXX watch for overflow!!! */ + card->vram_size = RegRead32(R600_CONFIG_MEMSIZE) * 1024 * 1024; + else + if (chip_family >= CHIP_FAMILY_R600) + card->vram_size = RegRead32(R600_CONFIG_MEMSIZE); +} + +bool read_vbios(bool from_pci) +{ + option_rom_header_t *rom_addr; + + if (from_pci) + { + rom_addr = (option_rom_header_t *)(pci_config_read32(card->pci_dev->dev.addr, PCI_ROM_ADDRESS) & ~0x7ff); + verbose(" @0x%x", rom_addr); + } + else + rom_addr = (option_rom_header_t *)0xc0000; + + if (!validate_rom(rom_addr, card->pci_dev)) + return false; + + card->rom_size = rom_addr->rom_size * 512; + if (!card->rom_size) + return false; + + card->rom = malloc(card->rom_size); + if (!card->rom) + return false; + + memcpy(card->rom, (void *)rom_addr, card->rom_size); + + return true; +} + +bool read_disabled_vbios(void) +{ + bool ret = false; + chip_family_t chip_family = card->info->chip_family; + + if (chip_family >= CHIP_FAMILY_RV770) + { + uint32_t viph_control = RegRead32(RADEON_VIPH_CONTROL); + uint32_t bus_cntl = RegRead32(RADEON_BUS_CNTL); + uint32_t d1vga_control = RegRead32(AVIVO_D1VGA_CONTROL); + uint32_t d2vga_control = RegRead32(AVIVO_D2VGA_CONTROL); + uint32_t vga_render_control = RegRead32(AVIVO_VGA_RENDER_CONTROL); + uint32_t rom_cntl = RegRead32(R600_ROM_CNTL); + uint32_t cg_spll_func_cntl = 0; + uint32_t cg_spll_status; + + /* disable VIP */ + RegWrite32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); + + /* enable the rom */ + RegWrite32(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM)); + + /* Disable VGA mode */ + RegWrite32(AVIVO_D1VGA_CONTROL, (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | AVIVO_DVGA_CONTROL_TIMING_SELECT))); + RegWrite32(AVIVO_D2VGA_CONTROL, (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | AVIVO_DVGA_CONTROL_TIMING_SELECT))); + RegWrite32(AVIVO_VGA_RENDER_CONTROL, (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); + + if (chip_family == CHIP_FAMILY_RV730) + { + cg_spll_func_cntl = RegRead32(R600_CG_SPLL_FUNC_CNTL); + + /* enable bypass mode */ + RegWrite32(R600_CG_SPLL_FUNC_CNTL, (cg_spll_func_cntl | R600_SPLL_BYPASS_EN)); + + /* wait for SPLL_CHG_STATUS to change to 1 */ + cg_spll_status = 0; + while (!(cg_spll_status & R600_SPLL_CHG_STATUS)) + cg_spll_status = RegRead32(R600_CG_SPLL_STATUS); + + RegWrite32(R600_ROM_CNTL, (rom_cntl & ~R600_SCK_OVERWRITE)); + } + else + RegWrite32(R600_ROM_CNTL, (rom_cntl | R600_SCK_OVERWRITE)); + + ret = read_vbios(true); + + /* restore regs */ + if (chip_family == CHIP_FAMILY_RV730) + { + RegWrite32(R600_CG_SPLL_FUNC_CNTL, cg_spll_func_cntl); + + /* wait for SPLL_CHG_STATUS to change to 1 */ + cg_spll_status = 0; + while (!(cg_spll_status & R600_SPLL_CHG_STATUS)) + cg_spll_status = RegRead32(R600_CG_SPLL_STATUS); + } + RegWrite32(RADEON_VIPH_CONTROL, viph_control); + RegWrite32(RADEON_BUS_CNTL, bus_cntl); + RegWrite32(AVIVO_D1VGA_CONTROL, d1vga_control); + RegWrite32(AVIVO_D2VGA_CONTROL, d2vga_control); + RegWrite32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); + RegWrite32(R600_ROM_CNTL, rom_cntl); + } + else + if (chip_family >= CHIP_FAMILY_R600) + { + uint32_t viph_control = RegRead32(RADEON_VIPH_CONTROL); + uint32_t bus_cntl = RegRead32(RADEON_BUS_CNTL); + uint32_t d1vga_control = RegRead32(AVIVO_D1VGA_CONTROL); + uint32_t d2vga_control = RegRead32(AVIVO_D2VGA_CONTROL); + uint32_t vga_render_control = RegRead32(AVIVO_VGA_RENDER_CONTROL); + uint32_t rom_cntl = RegRead32(R600_ROM_CNTL); + uint32_t general_pwrmgt = RegRead32(R600_GENERAL_PWRMGT); + uint32_t low_vid_lower_gpio_cntl = RegRead32(R600_LOW_VID_LOWER_GPIO_CNTL); + uint32_t medium_vid_lower_gpio_cntl = RegRead32(R600_MEDIUM_VID_LOWER_GPIO_CNTL); + uint32_t high_vid_lower_gpio_cntl = RegRead32(R600_HIGH_VID_LOWER_GPIO_CNTL); + uint32_t ctxsw_vid_lower_gpio_cntl = RegRead32(R600_CTXSW_VID_LOWER_GPIO_CNTL); + uint32_t lower_gpio_enable = RegRead32(R600_LOWER_GPIO_ENABLE); + + /* disable VIP */ + RegWrite32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); + + /* enable the rom */ + RegWrite32(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM)); + + /* Disable VGA mode */ + RegWrite32(AVIVO_D1VGA_CONTROL, (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | AVIVO_DVGA_CONTROL_TIMING_SELECT))); + RegWrite32(AVIVO_D2VGA_CONTROL, (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | AVIVO_DVGA_CONTROL_TIMING_SELECT))); + RegWrite32(AVIVO_VGA_RENDER_CONTROL, (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); + RegWrite32(R600_ROM_CNTL, ((rom_cntl & ~R600_SCK_PRESCALE_CRYSTAL_CLK_MASK) | (1 << R600_SCK_PRESCALE_CRYSTAL_CLK_SHIFT) | R600_SCK_OVERWRITE)); + RegWrite32(R600_GENERAL_PWRMGT, (general_pwrmgt & ~R600_OPEN_DRAIN_PADS)); + RegWrite32(R600_LOW_VID_LOWER_GPIO_CNTL, (low_vid_lower_gpio_cntl & ~0x400)); + RegWrite32(R600_MEDIUM_VID_LOWER_GPIO_CNTL, (medium_vid_lower_gpio_cntl & ~0x400)); + RegWrite32(R600_HIGH_VID_LOWER_GPIO_CNTL, (high_vid_lower_gpio_cntl & ~0x400)); + RegWrite32(R600_CTXSW_VID_LOWER_GPIO_CNTL, (ctxsw_vid_lower_gpio_cntl & ~0x400)); + RegWrite32(R600_LOWER_GPIO_ENABLE, (lower_gpio_enable | 0x400)); + + ret = read_vbios(true); + + /* restore regs */ + RegWrite32(RADEON_VIPH_CONTROL, viph_control); + RegWrite32(RADEON_BUS_CNTL, bus_cntl); + RegWrite32(AVIVO_D1VGA_CONTROL, d1vga_control); + RegWrite32(AVIVO_D2VGA_CONTROL, d2vga_control); + RegWrite32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); + RegWrite32(R600_ROM_CNTL, rom_cntl); + RegWrite32(R600_GENERAL_PWRMGT, general_pwrmgt); + RegWrite32(R600_LOW_VID_LOWER_GPIO_CNTL, low_vid_lower_gpio_cntl); + RegWrite32(R600_MEDIUM_VID_LOWER_GPIO_CNTL, medium_vid_lower_gpio_cntl); + RegWrite32(R600_HIGH_VID_LOWER_GPIO_CNTL, high_vid_lower_gpio_cntl); + RegWrite32(R600_CTXSW_VID_LOWER_GPIO_CNTL, ctxsw_vid_lower_gpio_cntl); + RegWrite32(R600_LOWER_GPIO_ENABLE, lower_gpio_enable); + + } + + return ret; +} + +bool radeon_card_posted(void) +{ + uint32_t reg; + + /* first check CRTCs */ + reg = RegRead32(RADEON_CRTC_GEN_CNTL) | RegRead32(RADEON_CRTC2_GEN_CNTL); + if (reg & RADEON_CRTC_EN) + return true; + + /* then check MEM_SIZE, in case something turned the crtcs off */ + reg = RegRead32(R600_CONFIG_MEMSIZE); + if (reg) + return true; + + return false; +} +#if 0 +bool devprop_add_pci_config_space(void) +{ + int offset; + + uint8_t *config_space = malloc(0x100); + if (!config_space) + return false; + + for (offset = 0; offset < 0x100; offset += 4) + config_space[offset / 4] = pci_config_read32(card->pci_dev->dev.addr, offset); + + devprop_add_value(card->device, "ATY,PCIConfigSpace", config_space, 0x100); + free(config_space); + return true; +} +#endif + +static bool init_card(pci_dt_t *pci_dev) +{ + const char *fb_name; + char name[24]; + char name_parent[24]; + int i; + bool add_vbios = true; + + card = malloc(sizeof(card_t)); + if (!card) + return false; + bzero(card, sizeof(card_t)); + + card->pci_dev = pci_dev; + + for (i = 0; radeon_cards[i].device_id ; i++) + if (radeon_cards[i].device_id == pci_dev->device_id) + { + card->info = &radeon_cards[i]; + if ((radeon_cards[i].subsys_id == 0x00000000) || + (radeon_cards[i].subsys_id == pci_dev->subsys_id.subsys_id)) + break; + } + + if (!card->info->device_id || !card->info->cfg_name) + { + printf("Unsupported card!\n"); + return false; + } + + + card->fb = (uint8_t *)(pci_config_read32(pci_dev->dev.addr, PCI_BASE_ADDRESS_0) & ~0x0f); + card->mmio = (uint8_t *)(pci_config_read32(pci_dev->dev.addr, PCI_BASE_ADDRESS_2) & ~0x0f); + card->io = (uint8_t *)(pci_config_read32(pci_dev->dev.addr, PCI_BASE_ADDRESS_4) & ~0x03); + + verbose("Framebuffer @0x%08X MMIO @0x%08X I/O Port @0x%08X ROM Addr @0x%08X\n", + card->fb, card->mmio, card->io, pci_config_read32(pci_dev->dev.addr, PCI_ROM_ADDRESS)); + + card->posted = radeon_card_posted(); + verbose("ATI card %s, ", card->posted ? "POSTed" : "non-POSTed"); + + get_vram_size(); + + getBoolForKey(kATYbinimage, &add_vbios, &bootInfo->bootConfig); + + if (add_vbios) + if (!load_vbios_file(kUseAtiROM, pci_dev->vendor_id, pci_dev->device_id, pci_dev->subsys_id.subsys_id)) + { + verbose("reading VBIOS from %s", card->posted ? "legacy space" : "PCI ROM"); + if (card->posted) + read_vbios(false); + else + read_disabled_vbios(); + verbose("\n"); + } + + card->ports = 2; // default + + if (card->info->chip_family >= CHIP_FAMILY_CEDAR) + { + card->flags |= EVERGREEN; + card->ports = 3; + } + + atN = 0; + + fb_name = getStringForKey(kAtiConfig, &bootInfo->bootConfig); + if (!fb_name) + { + fb_name = card_configs[card->info->cfg_name].name; + card->ports = card_configs[card->info->cfg_name].ports; + } + else + { + for (i = 0; i < kCfgEnd; i++) + if (strcmp(fb_name, card_configs[i].name) == 0) + card->ports = card_configs[i].ports; + } + + sprintf(name, "ATY,%s", fb_name); + aty_name.type = kStr; + aty_name.size = strlen(name) + 1; + aty_name.data = (uint8_t *)name; + + sprintf(name_parent, "ATY,%sParent", fb_name); + aty_nameparent.type = kStr; + aty_nameparent.size = strlen(name_parent) + 1; + aty_nameparent.data = (uint8_t *)name_parent; + + return true; +} + +bool setup_ati_devprop(pci_dt_t *ati_dev) +{ + char *devicepath; + + if (!init_card(ati_dev)) + return false; + + /* ------------------------------------------------- */ + /* Find a better way to do this (in device_inject.c) */ + if (!string) + string = devprop_create_string(); + + devicepath = get_pci_dev_path(ati_dev); + card->device = devprop_add_device(string, devicepath); + if (!card->device) + return false; + /* ------------------------------------------------- */ + +#if 0 + uint64_t fb = (uint32_t)card->fb; + uint64_t mmio = (uint32_t)card->mmio; + uint64_t io = (uint32_t)card->io; + devprop_add_value(card->device, "ATY,FrameBufferOffset", &fb, 8); + devprop_add_value(card->device, "ATY,RegisterSpaceOffset", &mmio, 8); + devprop_add_value(card->device, "ATY,IOSpaceOffset", &io, 8); +#endif + + devprop_add_list(ati_devprop_list); + + /* ------------------------------------------------- */ + /* Find a better way to do this (in device_inject.c) */ + stringdata = malloc(string->length); + memcpy(stringdata, (uint8_t*)devprop_generate_string(string), string->length); + stringlength = string->length; + /* ------------------------------------------------- */ + + verbose("ATI %s %s %dMB (%s) [%04x:%04x] (subsys [%04x:%04x]):: %s\n", + chip_family_name[card->info->chip_family], card->info->model_name, + (uint32_t)(card->vram_size / (1024 * 1024)), card_configs[card->info->cfg_name].name, + ati_dev->vendor_id, ati_dev->device_id, + ati_dev->subsys_id.subsys.vendor_id, ati_dev->subsys_id.subsys.device_id, + devicepath); + + free(card); + + return true; +} + Index: branches/slice/rev749/modules/ATI5000Enabler/ATIEnabler.c =================================================================== --- branches/slice/rev749/modules/ATI5000Enabler/ATIEnabler.c (revision 0) +++ branches/slice/rev749/modules/ATI5000Enabler/ATIEnabler.c (revision 1169) @@ -0,0 +1,52 @@ +/* + * ATIEnabler Module + * Enabled many nvidia and ati cards to be used out of the box in + * OS X. This was converted from boot2 code to a boot2 module. + * + */ + +#include "libsaio.h" +#include "pci.h" +#include "bootstruct.h" +//#include "nvidia.h" +#include "ati5.h" +//#include "gma.h" +#include "modules.h" + + +#define kATIEnabler "ATIEnabler" + + +void ATIEnabler_hook(void* arg1, void* arg2, void* arg3, void* arg4); + +void ATIEnabler_start() +{ + register_hook_callback("PCIDevice", &ATIEnabler_hook); +} + + +void ATIEnabler_hook(void* arg1, void* arg2, void* arg3, void* arg4) +{ + pci_dt_t* current = arg1; + if(current && current->class_id == PCI_CLASS_DISPLAY_VGA) + { + char *devicepath = get_pci_dev_path(current); + + bool do_gfx_devprop = true; + getBoolForKey(kATIEnabler, &do_gfx_devprop, &bootInfo->bootConfig); + + if (do_gfx_devprop) + { + switch (current->vendor_id) + { + case PCI_VENDOR_ID_ATI: + verbose("ATI VGA Controller [%04x:%04x] :: %s \n", + current->vendor_id, current->device_id, devicepath); + setup_ati_devprop(current); + break; + + } + } + + } +} Index: branches/slice/rev749/modules/ATI5000Enabler/ati5.h =================================================================== --- branches/slice/rev749/modules/ATI5000Enabler/ati5.h (revision 0) +++ branches/slice/rev749/modules/ATI5000Enabler/ati5.h (revision 1169) @@ -0,0 +1,46 @@ +/* + * ATI injector + * + * Copyright (C) 2010 Kabyl + * + * ATI injector is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ATI driver and injector is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ATI injector. If not, see . + */ + /* + * Alternatively you can choose to comply with APSL + */ + + +#ifndef __LIBSAIO_ATI_H +#define __LIBSAIO_ATI_H + +bool setup_ati_devprop(pci_dt_t *ati_dev); + +struct ati_chipsets_t { + unsigned device; + char *name; +}; + +struct ati_data_key { + uint32_t size; + char *name; + uint8_t data[]; +}; + +#define REG8(reg) ((volatile uint8_t *)regs)[(reg)] +#define REG16(reg) ((volatile uint16_t *)regs)[(reg) >> 1] +#define REG32R(reg) ((volatile uint32_t *)regs)[(reg) >> 2] +#define REG32W(reg, val) ((volatile uint32_t *)regs)[(reg) >> 2] = (val) + + +#endif /* !__LIBSAIO_ATI_H */ Index: branches/slice/rev749/modules/ATI5000Enabler/Makefile =================================================================== --- branches/slice/rev749/modules/ATI5000Enabler/Makefile (revision 0) +++ branches/slice/rev749/modules/ATI5000Enabler/Makefile (revision 1169) @@ -0,0 +1,41 @@ +MODULE_NAME = ATI5000Enabler +MODULE_VERSION = "1.0.0" +MODULE_COMPAT_VERSION = "1.0.0" +MODULE_START = _$(MODULE_NAME)_start +MODULE_DEPENDENCIES = + +DIR = ATI5000Enabler + +MODULE_OBJS = ati5.o ATIEnabler.o + +OPTIM = -Os -Oz +DEBUG = -DNOTHING +#DEBUG = -DDEBUG_HELLO_WORLD=1 +CFLAGS = $(RC_CFLAGS) $(OPTIM) $(MORECPP) -arch i386 -g -Wmost \ + -D__ARCHITECTURE__=\"i386\" -DSAIO_INTERNAL_USER \ + -DRCZ_COMPRESSED_FILE_SUPPORT $(DEBUG) \ + -fno-builtin $(OMIT_FRAME_POINTER_CFLAG) \ + -mpreferred-stack-boundary=2 -fno-align-functions -fno-stack-protector \ + -march=pentium4 -msse2 -mfpmath=sse -msoft-float -fno-common + +DEFINES= +CONFIG = hd +INC = -I. -I.. -I$(SYMROOT) -I$(UTILDIR) -I$(LIBSADIR) -I$(LIBSAIODIR) -I$(BOOT2DIR) +LIBS= + +VPATH = $(OBJROOT):$(SYMROOT) + +SFILES = +CFILES = +HFILES = +EXPORTED_HFILES = +INSTALLED_HFILES = +OTHERFILES = Makefile +ALLSRC = $(SFILES) $(CFILES) \ + $(HFILES) $(OTHERFILES) +DIRS_NEEDED = $(OBJROOT) $(SYMROOT) + +all embedtheme optionrom: dylib + + +include ../MakeInc.dir Index: branches/slice/rev749/modules/Makefile =================================================================== --- branches/slice/rev749/modules/Makefile (revision 0) +++ branches/slice/rev749/modules/Makefile (revision 1169) @@ -0,0 +1,64 @@ + +# Makefile for i386 boot program +# define FLOPPY and SMALL using DEFINES macro as necessary + +CFLAGS= -O $(MORECPP) -arch i386 -g -static +DEFINES= +CONFIG = hd +LIBDIR = libsa +INC = -I. -I$(LIBDIR) +ifneq "" "$(wildcard /bin/mkdirs)" + MKDIRS = /bin/mkdirs +else + MKDIRS = /bin/mkdir -p +endif +AS = as +LD = ld + +# +# these paths are only valid in subdirectories of this directory +# +OBJROOT=`pwd`/../../obj/i386/modules/ +SYMROOT=`pwd`/../../sym/i386/modules/ +DSTROOT=`pwd`/../../dst/i386/modules/ +SRCROOT=/tmp + +VPATH = $(OBJROOT):$(SYMROOT) + +# The order of building is important. +SUBDIRS = klibc uClibc++ Resolution KernelPatcher GUI KextPatcher GraphicsEnabler HPET USBFix Memory Networking NetbookInstaller NVRAM ATI5000Enabler +#SUBDIRS = HelloWorld ACPIPatcher + +all embedtheme optionrom tags debug install installhdrs: objroot_dirs lazydylib1.o + @for i in ${SUBDIRS}; \ + do \ + echo ================= make $@ for $$i =================; \ + ( cd $$i; $(MKDIRS) $(OBJROOT)/$$i; ${MAKE} \ + "OBJROOT=$(OBJROOT)/$$i" \ + "SYMROOT=$(SYMROOT)" \ + "DSTROOT=$(DSTROOT)" \ + "SRCROOT=$(SRCROOT)" \ + "RC_ARCHS=$(RC_ARCHS)" \ + "RC_KANJI=$(RC_KANJI)" \ + "JAPANESE=$(JAPANESE)" \ + "RC_CFLAGS=$(RC_CFLAGS)" $@ \ + ) || exit $$?; \ + done + +objroot_dirs: + @rm -rf $(OBJROOT) + @mkdir $(OBJROOT) &> /dev/null + @rm -rf module_includes + @mkdir module_includes + + +%.o: %.c + @echo "\t[CC] $<" + @$(CC) $(CPPFLAGS) $(CFLAGS) $(DEFINES) -c "$<" $(INC) -o "$(OBJROOT)/$@" + +%.o: %.cpp + @echo "\t[CPP] $<" + @$(CPP) $(CPPFLAGS) $(CFLAGS) $(DEFINES) -c "$<" $(INC) -o "$(OBJROOT)/$@" + +installsrc: + tar cf - . | (cd ${SRCROOT}; tar xfBp -) Index: branches/slice/rev749/Users_Guide0.5.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: branches/slice/rev749/Users_Guide0.5.pdf ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Index: branches/slice/rev749/Resources/Italian.lproj/Description.html =================================================================== --- branches/slice/rev749/Resources/Italian.lproj/Description.html (revision 0) +++ branches/slice/rev749/Resources/Italian.lproj/Description.html (revision 1169) @@ -0,0 +1,29 @@ + + + + + + + + + +

Chameleon ¨ la combinazione di diverse parti del boot loader.
ˆ basato sulle modifiche di David Elliott sull'implementazione "EFI" al progetto della Apple sul boot-132.
Chameleon presenta le seguenti caratteristiche principali:

+
+

Nuove caratteristiche di Chameleon 2.0

+
+

- Interfaccia grafica completamente personalizzabile per dare maggiori colori al Darwin Bootloader.

+

- Avviare DVD retail semplicemente caricando una immagine ramdisk senza l'utilizzo di programmi aggiuntivi.

+

- Ibernazione. Godetevi nel riprendere il vostro Mac OS X con un'immagine di anteprima.

+

- Sovrascrittura dle SMBIOS per personalizzare i valori dell'SMBIOS.

+

- Sovrascrittura della tabella DSDT, potendo selezionare una ottimizzata che risolve svariate problematiche.

+
+

- Iniezione delle Proprit  delle Periferiche con stringhe EFI in device-properties.

+

- boot0 / boot1h ibrido per dischi partizionati in MBR e GPT.

+

- Riconoscimento automatico della frequenza anche sui recenti processori AMD.

+

- Supporta il RAID software di Apple.

+
+

Per maggiori informazioni, visita : http://chameleon.osx86.hu

+ + \ No newline at end of file Index: branches/slice/rev749/Resources/Italian.lproj/Localizable.strings =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: branches/slice/rev749/Resources/Italian.lproj/Localizable.strings ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Index: branches/slice/rev749/Resources/Italian.lproj/Welcome.rtfd/TXT.rtf =================================================================== --- branches/slice/rev749/Resources/Italian.lproj/Welcome.rtfd/TXT.rtf (revision 0) +++ branches/slice/rev749/Resources/Italian.lproj/Welcome.rtfd/TXT.rtf (revision 1169) @@ -0,0 +1,25 @@ +{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf320 +{\fonttbl\f0\fnil\fcharset0 LucidaGrande;} +{\colortbl;\red255\green255\blue255;\red65\green78\blue255;} +\margl1440\margr1440\vieww13160\viewh11700\viewkind0 +\pard\ri0\qc + +\f0\b\fs72 \cf0 Chameleon +\fs50 \ + +\fs26 v%CHAMELEONVERSION% r%CHAMELEONREVISION% +\fs50 \ +\ +\cf2 %CHAMELEONSTAGE%\cf0 \ +\ +\pard\ri0\ql\qnatural + +\fs26 \cf0 Sviluppatori: Crazor, Dense, fassl, fxtentacle, iNDi, JrCs, Kabyl, kaitek, mackerintel, mercurysquad, mozodojo, munky, rekursor, Turbo & zef \ +\ +Grazie a : asereBLN, bumby, cosmolt, dfe, Galaxy, kalyway, Krazubu, netkas, sckevyn, smith@@, THeKiNG, XyZ, blackosx +\b0\fs30 \ +\pard\tx360\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural +\cf0 \ +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\fs26 \cf0 Copyright \'a9 2010} \ No newline at end of file Index: branches/slice/rev749/Resources/Italian.lproj/Conclusion.rtfd/TXT.rtf =================================================================== --- branches/slice/rev749/Resources/Italian.lproj/Conclusion.rtfd/TXT.rtf (revision 0) +++ branches/slice/rev749/Resources/Italian.lproj/Conclusion.rtfd/TXT.rtf (revision 1169) @@ -0,0 +1,34 @@ +{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf320 +{\fonttbl\f0\fnil\fcharset0 LucidaGrande;} +{\colortbl;\red255\green255\blue255;\red65\green78\blue255;\red255\green0\blue0;} +\margl1440\margr1440\vieww11660\viewh12980\viewkind0 +\pard\ri0\qc + +\f0\b\fs72 \cf0 Chameleon +\fs50 \ + +\fs26 v%CHAMELEONVERSION% r%CHAMELEONREVISION% +\fs50 \ +\ +\cf2 %CHAMELEONSTAGE%\cf0 \ +\pard\ri0\ql\qnatural + +\fs26 \cf0 \ +\pard\ri0\qc + +\fs50 \cf3 Installazione terminata! +\b0\fs26 \cf0 \ +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\fs18 \cf0 \ +{\field{\*\fldinst{HYPERLINK "http://chameleon.osx86.hu/"}}{\fldrslt +\fs26 http://chameleon.osx86.hu/}} +\fs26 \ +{\field{\*\fldinst{HYPERLINK "http://forum.voodooprojects.org/index.php"}}{\fldrslt http://forum.voodooprojects.org/index.php}} +\b \ +\pard\tx360\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural + +\b0\fs30 \cf0 \ +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\fs26 \cf0 Copyright \'a9 2010} \ No newline at end of file Index: branches/slice/rev749/Resources/Italian.lproj/License.rtf =================================================================== --- branches/slice/rev749/Resources/Italian.lproj/License.rtf (revision 0) +++ branches/slice/rev749/Resources/Italian.lproj/License.rtf (revision 1169) @@ -0,0 +1,11 @@ +{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf320 +{\fonttbl\f0\fnil\fcharset0 LucidaGrande;} +{\colortbl;\red255\green255\blue255;} +\vieww22060\viewh18360\viewkind0 +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\f0\b\fs20 \cf0 ITALIANO\ + +\b0 \ +EA0401\ +Rev. 4/1/09} \ No newline at end of file Index: branches/slice/rev749/Resources/background.tiff =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: branches/slice/rev749/Resources/background.tiff ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Index: branches/slice/rev749/Resources/Portuguese.lproj/Description.html =================================================================== --- branches/slice/rev749/Resources/Portuguese.lproj/Description.html (revision 0) +++ branches/slice/rev749/Resources/Portuguese.lproj/Description.html (revision 1169) @@ -0,0 +1,29 @@ + + + + + + + + + +

O Chameleon İ um boot loader que combina vĦrios componentes.
Ele İ baseado na implementa§£o de fake EFI feita por David Elliott, adicionada ao projeto boot-132 da Apple.
O Chameleon İ extendido com as seguintes caracter­sticas chave:

+
+

Novos recursos no Chameleon 2.0

+
+

- Interface grĦfica (GUI) totalmente personalizĦvel para trazer algumas cores ao Bootloader Darwin.

+

- Inicializa DVDs retail lendo uma imagem ramdisk diretamente, sem ajuda de nenhum programa adicional.

+

- Hiberna§£o. Aproveite continuar o seu Mac OS X com uma amostra de imagem da tela.

+

- Substitui§£o de SMBIOS para modificar os valores de fĦbrica.

+

- Substitui§£o de DSDT para usar uma tabela modificada que pode resolver diversos problemas.

+
+

- Inje§£o de propriedades de dispositivo atravİs do string device-properties.

+

- boot0 / boot1h h­bridos para discos particionados em MBR e GPT.

+

- Detec§£o automĦtica de FSB mesmo para processadores AMD recentes.

+

- Suporte a Software RAID da Apple.

+
+

Para informa§µes detalhadas visite: http://chameleon.osx86.hu

+ + Index: branches/slice/rev749/Resources/Portuguese.lproj/Localizable.strings =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: branches/slice/rev749/Resources/Portuguese.lproj/Localizable.strings ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Index: branches/slice/rev749/Resources/Portuguese.lproj/Welcome.rtfd/TXT.rtf =================================================================== --- branches/slice/rev749/Resources/Portuguese.lproj/Welcome.rtfd/TXT.rtf (revision 0) +++ branches/slice/rev749/Resources/Portuguese.lproj/Welcome.rtfd/TXT.rtf (revision 1169) @@ -0,0 +1,26 @@ +{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf320 +{\fonttbl\f0\fnil\fcharset0 LucidaGrande;} +{\colortbl;\red255\green255\blue255;\red65\green78\blue255;} +\margl1440\margr1440\vieww11660\viewh12980\viewkind0 +\pard\ri0\qc + +\f0\b\fs72 \cf0 Chameleon +\fs50 \ + +\fs26 v%CHAMELEONVERSION% r%CHAMELEONREVISION% +\fs50 \ +\ +\cf2 %CHAMELEONSTAGE% +\fs26 \cf0 \ +\ +\pard\ri0\ql\qnatural +\cf0 Desenvolvedores: Crazor, Dense, fassl, fxtentacle, iNDi, JrCs, Kabyl, kaitek, mackerintel, mercurysquad, mozodojo, munky, rekursor, Turbo & zef \ +\ +\ +Agradecimentos a: asereBLN, bumby, cosmolt, dfe, Galaxy, kalyway, Krazubu, netkas, sckevyn, smith@@, THeKiNG, XyZ, blackosx\ +\pard\tx360\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural + +\b0\fs30 \cf0 \ +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\fs26 \cf0 Copyright \'a9 2010} \ No newline at end of file Index: branches/slice/rev749/Resources/Portuguese.lproj/Conclusion.rtfd/TXT.rtf =================================================================== --- branches/slice/rev749/Resources/Portuguese.lproj/Conclusion.rtfd/TXT.rtf (revision 0) +++ branches/slice/rev749/Resources/Portuguese.lproj/Conclusion.rtfd/TXT.rtf (revision 1169) @@ -0,0 +1,34 @@ +{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf320 +{\fonttbl\f0\fnil\fcharset0 LucidaGrande;} +{\colortbl;\red255\green255\blue255;\red65\green78\blue255;\red255\green0\blue0;} +\margl1440\margr1440\vieww11660\viewh12980\viewkind0 +\pard\ri0\qc + +\f0\b\fs72 \cf0 Chameleon +\fs50 \ + +\fs26 v%CHAMELEONVERSION% r%CHAMELEONREVISION% +\fs50 \ +\ +\cf2 %CHAMELEONSTAGE%\cf0 \ +\pard\ri0\ql\qnatural + +\fs26 \cf0 \ +\pard\ri0\qc + +\fs50 \cf3 Instala\'e7\'e3o Conclu\'edda! +\b0\fs26 \cf0 \ +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\fs18 \cf0 \ +{\field{\*\fldinst{HYPERLINK "http://chameleon.osx86.hu/"}}{\fldrslt +\fs26 http://chameleon.osx86.hu/}} +\fs26 \ +{\field{\*\fldinst{HYPERLINK "http://forum.voodooprojects.org/index.php"}}{\fldrslt http://forum.voodooprojects.org/index.php}} +\b \ +\pard\tx360\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural + +\b0\fs30 \cf0 \ +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\fs26 \cf0 Copyright \'a9 2010} \ No newline at end of file Index: branches/slice/rev749/Resources/Portuguese.lproj/License.rtf =================================================================== --- branches/slice/rev749/Resources/Portuguese.lproj/License.rtf (revision 0) +++ branches/slice/rev749/Resources/Portuguese.lproj/License.rtf (revision 1169) @@ -0,0 +1,11 @@ +{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf320 +{\fonttbl\f0\fnil\fcharset0 LucidaGrande;} +{\colortbl;\red255\green255\blue255;} +\vieww22060\viewh18360\viewkind0 +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\f0\b\fs20 \cf0 PORTUGUESE\ + +\b0 \ +EA0401\ +Rev. 4/1/09} \ No newline at end of file Index: branches/slice/rev749/Resources/Bulgarian.lproj/Description.html =================================================================== --- branches/slice/rev749/Resources/Bulgarian.lproj/Description.html (revision 0) +++ branches/slice/rev749/Resources/Bulgarian.lproj/Description.html (revision 1169) @@ -0,0 +1,30 @@ + + + + + + + + + +

Chameleon µ şĵħ¸½°Ñ†¸Ñ т р°·ħ¸Ñ‡½¸ boot loader şĵż½µ½Ñ‚¸.
‘°·¸Ñ€°½ µ ½° fake EFI ¸·żÑŠğ½µ½¸µÑ‚ ½° ”µı²¸´ •ığ¸ÑŠÑ‚ ´ħ°²µ½ şÑŠĵ żÑ€µşÑ‚° boot-132 ½° Apple.
Chameleon µ р°·Ñˆ¸Ñ€µ½ със с𵴽¸Ñ‚µ şğюч²¸ фу½şÑ†¸¸:

+
+

²¸ фу½şÑ†¸¸ ² Chameleon 2.0

+
+

- °żÑŠğ½ уżÑ€°²ğяµĵ ³Ñ€°Ñ„¸Ñ‡µ½ ¸½Ñ‚µÑ€Ñ„µıс ·° ´ħ°²Ñ½µ ½° ĥ¸²¸ ц²µÑ‚²µ şÑŠĵ Darwin Bootloader.

+

- Boot-²° retail DVD-т° чрµ· ´¸Ñ€µşÑ‚½ ·°Ñ€µĥ´°½µ ½° ramdisk image ħµ· żĵщ° ½° ´żÑŠğ½¸Ñ‚µğ½¸ żÑ€³Ñ€°ĵ¸.

+

- ¸ħµÑ€½°Ñ†¸Ñ.

+

- SMBIOS ·°ĵµÑÑ‚²°½µ, ·° ´° ħъ´°Ñ‚ ĵ´¸Ñ„¸Ñ†¸Ñ€°½¸ р¸³¸½°ğ½¸Ñ‚µ SMBIOS стı½ÑÑ‚¸.

+

- DSDT ·°ĵµÑÑ‚²°½µ, ·° ´° ħъ´µ ¸·żğ·²°½ ĵ´¸Ñ„¸Ñ†¸Ñ€°½ DSDT, şµÑ‚ рµÑˆ°²° ĵ½ĥµÑÑ‚² żÑ€ħğµĵ¸.

+
+

- ’³Ñ€°ĥ´°½µ ½° сħµ½ÑÑ‚¸Ñ‚µ ½° р°·ğ¸Ñ‡½¸ х°Ñ€´ÑƒµÑ€½¸ устрıст²° żÑÑ€µ´ÑÑ‚²ĵ device-properties стр¸½³²µ.

+

- ¸ħр¸´½¸ boot0 / boot1h ·° MBR ¸ GPT р°·´µğµ½¸ ´¸Ñş²µ..

+

- ²Ñ‚ĵ°Ñ‚¸Ñ‡½ р°·ż·½°²°½µ ½° FSB ·° ½²¸Ñ‚µ AMD żÑ€Ñ†µÑÑ€¸.

+

- Ÿ´´Ñ€ÑŠĥş° ½° Apple Software RAID..

+
+

—° ż²µÑ‡µ ¸½Ñ„Ñ€ĵ°Ñ†¸Ñ żÑµÑ‚µÑ‚µ: http://chameleon.osx86.hu

+ + + Property changes on: branches/slice/rev749/Resources/Bulgarian.lproj/Description.html ___________________________________________________________________ Added: svn:executable + Index: branches/slice/rev749/Resources/Bulgarian.lproj/Localizable.strings =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: branches/slice/rev749/Resources/Bulgarian.lproj/Localizable.strings ___________________________________________________________________ Added: svn:executable + Added: svn:mime-type + application/octet-stream Index: branches/slice/rev749/Resources/Bulgarian.lproj/Welcome.rtfd/TXT.rtf =================================================================== --- branches/slice/rev749/Resources/Bulgarian.lproj/Welcome.rtfd/TXT.rtf (revision 0) +++ branches/slice/rev749/Resources/Bulgarian.lproj/Welcome.rtfd/TXT.rtf (revision 1169) @@ -0,0 +1,26 @@ +{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf320 +{\fonttbl\f0\fnil\fcharset0 LucidaGrande;} +{\colortbl;\red255\green255\blue255;\red65\green78\blue255;} +\margl1440\margr1440\vieww11660\viewh12980\viewkind0 +\pard\ri0\qc + +\f0\b\fs72 \cf0 Chameleon +\fs50 \ + +\fs26 v%CHAMELEONVERSION% r%CHAMELEONREVISION% +\fs50 \ +\ +\cf2 %CHAMELEONSTAGE% +\fs26 \cf0 \ +\pard\ri0\ql\qnatural +\cf0 \ +\uc0\u1056 \u1072 \u1079 \u1088 \u1072 \u1073 \u1086 \u1090 \u1077 \u1085 \u1086 \u1090 : Crazor, Dense, fassl, fxtentacle, iNDi, JrCs, Kabyl, kaitek, mackerintel, mercurysquad, mozodojo, munky, rekursor, Turbo & zef \ +\ +\ +\uc0\u1041 \u1083 \u1072 \u1075 \u1086 \u1076 \u1072 \u1088 \u1085 \u1086 \u1089 \u1090 \u1080 \u1085 \u1072 : asereBLN, bumby, cosmolt, dfe, Galaxy, kalyway, Krazubu, netkas, sckevyn, smith@@, THeKiNG, XyZ, blackosx\ +\pard\tx360\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural + +\b0\fs30 \cf0 \ +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\fs26 \cf0 Copyright \'a9 2010} \ No newline at end of file Index: branches/slice/rev749/Resources/Bulgarian.lproj/Conclusion.rtfd/TXT.rtf =================================================================== --- branches/slice/rev749/Resources/Bulgarian.lproj/Conclusion.rtfd/TXT.rtf (revision 0) +++ branches/slice/rev749/Resources/Bulgarian.lproj/Conclusion.rtfd/TXT.rtf (revision 1169) @@ -0,0 +1,34 @@ +{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf320 +{\fonttbl\f0\fnil\fcharset0 LucidaGrande;} +{\colortbl;\red255\green255\blue255;\red65\green78\blue255;\red255\green0\blue0;} +\margl1440\margr1440\vieww11660\viewh12980\viewkind0 +\pard\ri0\qc + +\f0\b\fs72 \cf0 Chameleon +\fs50 \ + +\fs26 v%CHAMELEONVERSION% r%CHAMELEONREVISION% +\fs50 \ +\ +\cf2 %CHAMELEONSTAGE%\cf0 \ +\pard\ri0\ql\qnatural + +\fs26 \cf0 \ +\pard\ri0\qc + +\fs50 \cf3 \uc0\u1048 \u1085 \u1089 \u1090 \u1072 \u1083 \u1072 \u1094 \u1080 \u1103 \u1090 \u1072 \u1077 \u1079 \u1072 \u1074 \u1098 \u1088 \u1096 \u1077 \u1085 \u1072 ! +\b0\fs26 \cf0 \ +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\fs18 \cf0 \ +{\field{\*\fldinst{HYPERLINK "http://chameleon.osx86.hu/"}}{\fldrslt +\fs26 http://chameleon.osx86.hu/}} +\fs26 \ +{\field{\*\fldinst{HYPERLINK "http://forum.voodooprojects.org/index.php"}}{\fldrslt http://forum.voodooprojects.org/index.php}} +\b \ +\pard\tx360\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural + +\b0\fs30 \cf0 \ +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\fs26 \cf0 Copyright \'a9 2010} \ No newline at end of file Index: branches/slice/rev749/Resources/Bulgarian.lproj/License.rtf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: branches/slice/rev749/Resources/Bulgarian.lproj/License.rtf ___________________________________________________________________ Added: svn:executable + Added: svn:mime-type + application/octet-stream Index: branches/slice/rev749/Resources/French.lproj/Description.html =================================================================== --- branches/slice/rev749/Resources/French.lproj/Description.html (revision 0) +++ branches/slice/rev749/Resources/French.lproj/Description.html (revision 1169) @@ -0,0 +1,37 @@ + + + + + + + + + + + +

Chameleon est une conbinaison de diffİrent composants de boot loader.

+

Il est basİ sur la "fake EFI" implİmentation de David Elliott ajoutİ au projet  Apple's boot-132.

+


+

Chameleon   İtİ amİliorİ avec les fonctions clİ suivantes:

+


+

Les nouvelles fonctionnalitİs de Chameleon 2.0

+


+

- Interface graphique entierement customisable pour apporter un peu de couleur au Darwin Bootloader.

+

- Booter un DVD Retail en chargeant directement une image RAMDISK sans l'aide de programmes tierce.

+

- Hibernation:  Apprİciez  l'affichage d'un apercu d'İcran durant le dİmarrage  apr¨s mise en veille.

+

- SMBIOS override : pour modifier les valeur d'usines du SMBIOS.

+

- DSDT override : Utilisation d'un DSDT modifiİ pouvant rİsoudre quelques problemes .

+


+

- Device Property Injection via device-properties string dans boot.plist.

+

- Hybrid boot0 / boot1h pour disque dur partionnİs en MBR et GPT .

+

- Dİtection du FSB automatique , m¨me pour les CPU AMD rİcents.

+

- Support du Apple Software RAID .

+


+

Pour des informations plus dİtaillİes , visitez : http://chameleon.osx86.hu

+ + Index: branches/slice/rev749/Resources/French.lproj/Localizable.strings =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: branches/slice/rev749/Resources/French.lproj/Localizable.strings ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Index: branches/slice/rev749/Resources/French.lproj/Welcome.rtfd/TXT.rtf =================================================================== --- branches/slice/rev749/Resources/French.lproj/Welcome.rtfd/TXT.rtf (revision 0) +++ branches/slice/rev749/Resources/French.lproj/Welcome.rtfd/TXT.rtf (revision 1169) @@ -0,0 +1,27 @@ +{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf320 +{\fonttbl\f0\fnil\fcharset0 LucidaGrande;} +{\colortbl;\red255\green255\blue255;\red65\green78\blue255;} +\margl1440\margr1440\vieww11660\viewh12980\viewkind0 +\pard\ri0\qc + +\f0\b\fs72 \cf0 Chameleon +\fs50 \ + +\fs26 v%CHAMELEONVERSION% r%CHAMELEONREVISION% +\fs50 \ +\ +\cf2 %CHAMELEONSTAGE%\cf0 \ +\pard\ri0\ql\qnatural + +\fs26 \cf0 \ +\ +Developeurs: Crazor, Dense, fassl, fxtentacle, iNDi, JrCs, Kabyl, kaitek, mackerintel, mercurysquad, mozodojo, munky, rekursor, Turbo & zef \ +\ +\ +Remerciements : asereBLN, bumby, cosmolt, dfe, Galaxy, kalyway, Krazubu, netkas, sckevyn, smith@@, THeKiNG, XyZ, blackosx\ +\pard\tx360\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural + +\b0\fs30 \cf0 \ +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\fs26 \cf0 Copyright \'a9 2010 } \ No newline at end of file Index: branches/slice/rev749/Resources/French.lproj/Conclusion.rtfd/TXT.rtf =================================================================== --- branches/slice/rev749/Resources/French.lproj/Conclusion.rtfd/TXT.rtf (revision 0) +++ branches/slice/rev749/Resources/French.lproj/Conclusion.rtfd/TXT.rtf (revision 1169) @@ -0,0 +1,34 @@ +{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf320 +{\fonttbl\f0\fnil\fcharset0 LucidaGrande;} +{\colortbl;\red255\green255\blue255;\red65\green78\blue255;\red255\green0\blue0;} +\margl1440\margr1440\vieww11660\viewh12980\viewkind0 +\pard\ri0\qc + +\f0\b\fs72 \cf0 Chameleon +\fs50 \ + +\fs26 v%CHAMELEONVERSION% r%CHAMELEONREVISION% +\fs50 \ +\ +\cf2 %CHAMELEONSTAGE%\cf0 \ +\pard\ri0\ql\qnatural + +\fs26 \cf0 \ +\pard\ri0\qc + +\fs50 \cf3 Installation compl\'e8te! +\b0\fs26 \cf0 \ +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\fs18 \cf0 \ +{\field{\*\fldinst{HYPERLINK "http://chameleon.osx86.hu/"}}{\fldrslt +\fs26 http://chameleon.osx86.hu/}} +\fs26 \ +{\field{\*\fldinst{HYPERLINK "http://forum.voodooprojects.org/index.php"}}{\fldrslt http://forum.voodooprojects.org/index.php}} +\b \ +\pard\tx360\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural + +\b0\fs30 \cf0 \ +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\fs26 \cf0 Copyright \'a9 2010} \ No newline at end of file Index: branches/slice/rev749/Resources/French.lproj/License.rtf =================================================================== --- branches/slice/rev749/Resources/French.lproj/License.rtf (revision 0) +++ branches/slice/rev749/Resources/French.lproj/License.rtf (revision 1169) @@ -0,0 +1,13 @@ +{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf430 +{\fonttbl\f0\fnil\fcharset0 LucidaGrande;} +{\colortbl;\red255\green255\blue255;} +\vieww9000\viewh8400\viewkind0 +\pard\ql\qnatural + +\f0\b\fs20 \cf0 FRAN\'c7AIS\ +\pard\qj +\cf0 \ +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\b0 \cf0 EA0401\ +Rev. 4/1/09} \ No newline at end of file Index: branches/slice/rev749/Resources/Spanish.lproj/Description.html =================================================================== --- branches/slice/rev749/Resources/Spanish.lproj/Description.html (revision 0) +++ branches/slice/rev749/Resources/Spanish.lproj/Description.html (revision 1169) @@ -0,0 +1,35 @@ + + + + + + + + + + + +

Camale³n es la combinaci³n de varios  boot loader componentes.
+Esta basado en la implementaci³n EFI falsa de David Elliott agregada al proyecto boot-132 de Apple.
+Camale³n esta extendido con las siguientes caracteristicas:

+


+

Adicionales en Camale³n 2.0

+


+

- GUI  totalmente personalizado para brindarle algo de color al Dawin Bootloader.

+

- Booting DVDs con simplemente cargar una imagen ramdisk sin la ayuda de programas adicionales.

+

- Hibernaci³n. Disfrute reanudar su MAC OS X con una imagen de muestra.

+

- SMBIOS anulado para modificar la fabrica SMBIOS valores.

+

- DSDT anulado para usar un DSDT modificado y arreglado capaz de resolver varios inconvenientes.

+


+

- Injeccion Propiedades del Dispositivo por la cuerda Propiedades del Dispositivo.

+

- Hibrido boot0 / boot1h para discos MBR y GPT divididos.

+

- Codigo de detecci³n FSB automatico para CPUs AMD recientes..

+

- Ayuda RAID para software Apple.

+


+

Para informaci³n mas detallada, visitar : http://chameleon.osx86.hu

+ + Index: branches/slice/rev749/Resources/Spanish.lproj/Localizable.strings =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: branches/slice/rev749/Resources/Spanish.lproj/Localizable.strings ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Index: branches/slice/rev749/Resources/Spanish.lproj/Welcome.rtfd/TXT.rtf =================================================================== --- branches/slice/rev749/Resources/Spanish.lproj/Welcome.rtfd/TXT.rtf (revision 0) +++ branches/slice/rev749/Resources/Spanish.lproj/Welcome.rtfd/TXT.rtf (revision 1169) @@ -0,0 +1,25 @@ +{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf320 +{\fonttbl\f0\fnil\fcharset0 LucidaGrande;} +{\colortbl;\red255\green255\blue255;\red65\green78\blue255;} +\margl1440\margr1440\vieww13160\viewh11700\viewkind0 +\pard\ri0\qc + +\f0\b\fs72 \cf0 Chameleon +\fs50 \ + +\fs26 v%CHAMELEONVERSION% r%CHAMELEONREVISION% +\fs50 \ +\ +\cf2 %CHAMELEONSTAGE%\ +\cf0 \ +\pard\ri0\ql\qnatural + +\fs26 \cf0 Programadores: Crazor, Dense, fassl, fxtentacle, iNDi, JrCs, Kabyl, kaitek, mackerintel, mercurysquad, mozodojo, munky, rekursor, Turbo & zef \ +\ +Gracias's a : asereBLN, bumby, cosmolt, dfe, Galaxy, kalyway, Krazubu, netkas, sckevyn, smith@@, THeKiNG, XyZ, blackosx +\b0\fs30 \ +\pard\tx360\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural +\cf0 \ +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\fs26 \cf0 Copyright \'a9 2010} \ No newline at end of file Index: branches/slice/rev749/Resources/Spanish.lproj/Conclusion.rtfd/TXT.rtf =================================================================== --- branches/slice/rev749/Resources/Spanish.lproj/Conclusion.rtfd/TXT.rtf (revision 0) +++ branches/slice/rev749/Resources/Spanish.lproj/Conclusion.rtfd/TXT.rtf (revision 1169) @@ -0,0 +1,34 @@ +{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf320 +{\fonttbl\f0\fnil\fcharset0 LucidaGrande;} +{\colortbl;\red255\green255\blue255;\red65\green78\blue255;\red255\green0\blue0;} +\margl1440\margr1440\vieww11660\viewh12980\viewkind0 +\pard\ri0\qc + +\f0\b\fs72 \cf0 Chameleon +\fs50 \ + +\fs26 v%CHAMELEONVERSION% r%CHAMELEONREVISION% +\fs50 \ +\ +\cf2 %CHAMELEONSTAGE%\cf0 \ +\pard\ri0\ql\qnatural + +\fs26 \cf0 \ +\pard\ri0\qc + +\fs50 \cf3 Instalaci\'f3n completa! +\b0\fs26 \cf0 \ +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\fs18 \cf0 \ +{\field{\*\fldinst{HYPERLINK "http://chameleon.osx86.hu/"}}{\fldrslt +\fs26 http://chameleon.osx86.hu/}} +\fs26 \ +{\field{\*\fldinst{HYPERLINK "http://forum.voodooprojects.org/index.php"}}{\fldrslt http://forum.voodooprojects.org/index.php}} +\b \ +\pard\tx360\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural + +\b0\fs30 \cf0 \ +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\fs26 \cf0 Copyright \'a9 2010} \ No newline at end of file Index: branches/slice/rev749/Resources/Spanish.lproj/License.rtf =================================================================== --- branches/slice/rev749/Resources/Spanish.lproj/License.rtf (revision 0) +++ branches/slice/rev749/Resources/Spanish.lproj/License.rtf (revision 1169) @@ -0,0 +1,11 @@ +{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf430 +{\fonttbl\f0\fnil\fcharset0 LucidaGrande;} +{\colortbl;\red255\green255\blue255;} +\vieww22060\viewh18360\viewkind0 +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\f0\b\fs20 \cf0 ESPA\'d1OL\ + +\b0 \ +EA0401\ +Rev. 4/1/09} \ No newline at end of file Index: branches/slice/rev749/Resources/English.lproj/Description.html =================================================================== --- branches/slice/rev749/Resources/English.lproj/Description.html (revision 0) +++ branches/slice/rev749/Resources/English.lproj/Description.html (revision 1169) @@ -0,0 +1,34 @@ + + + + + + + + + + + +

Chameleon is combination of various boot loader components.
It is based on David Elliott's fake EFI implementation added to Apple's boot-132 project.
Chameleon is extended with the following key features:

+
+

New features in Chameleon 2.0

+
+

- Fully customizable GUI to bring some color to the Darwin Bootloader.

+

- Booting retail DVDs by directly loading a ramdisk image without help of additional programs.

+

- Hibernation. Enjoy resuming your Mac OS X with a preview image.

+

- SMBIOS override to modify the factory SMBIOS values.

+

- DSDT override to use a modified fixed DSDT which can solve several issues.

+
+

- Device Property Injection via device-properties string.

+

- hybrid boot0 / boot1h for MBR and GPT partitioned disks.

+

- automatic FSB detection code even for recent AMD CPUs.

+

- Apple Software RAID support.

+
+

For detailed information, visit : http://chameleon.osx86.hu

+ + Index: branches/slice/rev749/Resources/English.lproj/Localizable.strings =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: branches/slice/rev749/Resources/English.lproj/Localizable.strings ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Index: branches/slice/rev749/Resources/English.lproj/Welcome.rtfd/TXT.rtf =================================================================== --- branches/slice/rev749/Resources/English.lproj/Welcome.rtfd/TXT.rtf (revision 0) +++ branches/slice/rev749/Resources/English.lproj/Welcome.rtfd/TXT.rtf (revision 1169) @@ -0,0 +1,26 @@ +{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf320 +{\fonttbl\f0\fnil\fcharset0 LucidaGrande;} +{\colortbl;\red255\green255\blue255;\red65\green78\blue255;} +\margl1440\margr1440\vieww11660\viewh12980\viewkind0 +\pard\ri0\qc + +\f0\b\fs72 \cf0 Chameleon +\fs50 \ + +\fs26 v%CHAMELEONVERSION% r%CHAMELEONREVISION% +\fs50 \ +\ +\cf2 %CHAMELEONSTAGE% +\fs26 \cf0 \ +\pard\ri0\ql\qnatural +\cf0 \ +Developers: Crazor, Dense, fassl, fxtentacle, iNDi, JrCs, Kabyl, kaitek, mackerintel, mercurysquad, mozodojo, munky, rekursor, Turbo & zef \ +\ +\ +Thanks to : asereBLN, bumby, cosmolt, dfe, Galaxy, kalyway, Krazubu, netkas, sckevyn, smith@@, THeKiNG, XyZ, blackosx\ +\pard\tx360\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural + +\b0\fs30 \cf0 \ +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\fs26 \cf0 Copyright \'a9 2010} \ No newline at end of file Index: branches/slice/rev749/Resources/English.lproj/Conclusion.rtfd/TXT.rtf =================================================================== --- branches/slice/rev749/Resources/English.lproj/Conclusion.rtfd/TXT.rtf (revision 0) +++ branches/slice/rev749/Resources/English.lproj/Conclusion.rtfd/TXT.rtf (revision 1169) @@ -0,0 +1,34 @@ +{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf320 +{\fonttbl\f0\fnil\fcharset0 LucidaGrande;} +{\colortbl;\red255\green255\blue255;\red65\green78\blue255;\red255\green0\blue0;} +\margl1440\margr1440\vieww11660\viewh12980\viewkind0 +\pard\ri0\qc + +\f0\b\fs72 \cf0 Chameleon +\fs50 \ + +\fs26 v%CHAMELEONVERSION% r%CHAMELEONREVISION% +\fs50 \ +\ +\cf2 %CHAMELEONSTAGE%\cf0 \ +\pard\ri0\ql\qnatural + +\fs26 \cf0 \ +\pard\ri0\qc + +\fs50 \cf3 Installation Complete! +\b0\fs26 \cf0 \ +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\fs18 \cf0 \ +{\field{\*\fldinst{HYPERLINK "http://chameleon.osx86.hu/"}}{\fldrslt +\fs26 http://chameleon.osx86.hu/}} +\fs26 \ +{\field{\*\fldinst{HYPERLINK "http://forum.voodooprojects.org/index.php"}}{\fldrslt http://forum.voodooprojects.org/index.php}} +\b \ +\pard\tx360\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural + +\b0\fs30 \cf0 \ +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\fs26 \cf0 Copyright \'a9 2010} \ No newline at end of file Index: branches/slice/rev749/Resources/English.lproj/License.rtf =================================================================== --- branches/slice/rev749/Resources/English.lproj/License.rtf (revision 0) +++ branches/slice/rev749/Resources/English.lproj/License.rtf (revision 1169) @@ -0,0 +1,11 @@ +{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf430 +{\fonttbl\f0\fnil\fcharset0 LucidaGrande;} +{\colortbl;\red255\green255\blue255;} +\vieww22060\viewh18360\viewkind0 +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\f0\b\fs20 \cf0 ENGLISH\ + +\b0 \ +EA0401\ +Rev. 4/1/09} \ No newline at end of file Index: branches/slice/rev749/Resources/German.lproj/Description.html =================================================================== --- branches/slice/rev749/Resources/German.lproj/Description.html (revision 0) +++ branches/slice/rev749/Resources/German.lproj/Description.html (revision 1169) @@ -0,0 +1,29 @@ + + + + + + + + + +

Chameleon ist eine Kombination verschiedener Bootloader Komponenten.
Als Basis diente David Elliott's fake EFI Implementierung die zu Apple's boot-132 Projekt hinzugefügt wurde.
Chameleon wurde mit folgenden Hauptmerkmalen erweitert:

+
+

Neue Funktionen in Chameleon 2.0

+
+

- Vollständig anpassbare GUI um etwas Farbe in den Darwin Bootloader zu bringen.

+

- Starten von retail DVDs durch direktes Laden eines RAM-Disk Images, ohne zusätzliche Programme zu benötigen .

+

- Ruhezustand. Genießt Mac OS X mit einem Vorschau-Bild aufzuwecken.

+

- SMBIOS Override um vorgegebene SMBIOS Werte anzupassen.

+

- DSDT Override um eine angepasste DSDT, die verschiedene Probleme beheben kann, zu laden.

+
+

- Device Property Injection über device-properties string.

+

- hybrider boot0 / boot1h für MBR und GPT partitionierte Festplatten.

+

- Code zur automatischen FSB Erkennung, selbst für AMD CPUs.

+

- Apple Software RAID Unterstützung.

+
+

Für weitere Informationen besuche: http://chameleon.osx86.hu

+ + \ No newline at end of file Index: branches/slice/rev749/Resources/German.lproj/Localizable.strings =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: branches/slice/rev749/Resources/German.lproj/Localizable.strings ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Index: branches/slice/rev749/Resources/German.lproj/Welcome.rtfd/TXT.rtf =================================================================== --- branches/slice/rev749/Resources/German.lproj/Welcome.rtfd/TXT.rtf (revision 0) +++ branches/slice/rev749/Resources/German.lproj/Welcome.rtfd/TXT.rtf (revision 1169) @@ -0,0 +1,27 @@ +{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf320 +{\fonttbl\f0\fnil\fcharset0 LucidaGrande;} +{\colortbl;\red255\green255\blue255;\red65\green78\blue255;} +\margl1440\margr1440\vieww11660\viewh12980\viewkind0 +\pard\ri0\qc + +\f0\b\fs72 \cf0 Chameleon +\fs50 \ + +\fs26 v%CHAMELEONVERSION% r%CHAMELEONREVISION% +\fs50 \ +\ +\cf2 %CHAMELEONSTAGE%\cf0 \ +\pard\ri0\ql\qnatural + +\fs26 \cf0 \ +\ +Entwickler: Crazor, Dense, fassl, fxtentacle, iNDi, JrCs, Kabyl, kaitek, mackerintel, mercurysquad, mozodojo, munky, rekursor, Turbo & zef \ +\ +\ +Dank : asereBLN, bumby, cosmolt, dfe, Galaxy, kalyway, Krazubu, netkas, sckevyn, smith@@, THeKiNG, XyZ, blackosx\ +\pard\tx360\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural + +\b0\fs30 \cf0 \ +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\fs26 \cf0 Copyright \'a9 2010} \ No newline at end of file Index: branches/slice/rev749/Resources/German.lproj/Conclusion.rtfd/TXT.rtf =================================================================== --- branches/slice/rev749/Resources/German.lproj/Conclusion.rtfd/TXT.rtf (revision 0) +++ branches/slice/rev749/Resources/German.lproj/Conclusion.rtfd/TXT.rtf (revision 1169) @@ -0,0 +1,34 @@ +{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf320 +{\fonttbl\f0\fnil\fcharset0 LucidaGrande;} +{\colortbl;\red255\green255\blue255;\red65\green78\blue255;\red255\green0\blue0;} +\margl1440\margr1440\vieww11660\viewh12980\viewkind0 +\pard\ri0\qc + +\f0\b\fs72 \cf0 Chameleon +\fs50 \ + +\fs26 v%CHAMELEONVERSION% r%CHAMELEONREVISION% +\fs50 \ +\ +\cf2 %CHAMELEONSTAGE%\cf0 \ +\pard\ri0\ql\qnatural + +\fs26 \cf0 \ +\pard\ri0\qc + +\fs50 \cf3 Installation abgeschlossen! +\b0\fs26 \cf0 \ +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\fs18 \cf0 \ +{\field{\*\fldinst{HYPERLINK "http://chameleon.osx86.hu/"}}{\fldrslt +\fs26 http://chameleon.osx86.hu/}} +\fs26 \ +{\field{\*\fldinst{HYPERLINK "http://forum.voodooprojects.org/index.php"}}{\fldrslt http://forum.voodooprojects.org/index.php}} +\b \ +\pard\tx360\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural + +\b0\fs30 \cf0 \ +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\fs26 \cf0 Copyright \'a9 2010} \ No newline at end of file Index: branches/slice/rev749/Resources/German.lproj/License.rtf =================================================================== --- branches/slice/rev749/Resources/German.lproj/License.rtf (revision 0) +++ branches/slice/rev749/Resources/German.lproj/License.rtf (revision 1169) @@ -0,0 +1,13 @@ +{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf430 +{\fonttbl\f0\fnil\fcharset0 LucidaGrande;} +{\colortbl;\red255\green255\blue255;} +\vieww9000\viewh8400\viewkind0 +\deftab720 +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardeftab720\ql\qnatural + +\f0\b\fs20 \cf0 DEUTSCH\ +\ +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\b0 \cf0 EA0401\ +Rev. 4/1/09} \ No newline at end of file Index: branches/slice/rev749/Makefile =================================================================== --- branches/slice/rev749/Makefile (revision 0) +++ branches/slice/rev749/Makefile (revision 1169) @@ -0,0 +1,65 @@ + +# Makefile for i386 boot program +# define FLOPPY and SMALL using DEFINES macro as necessary + +CFLAGS = -O $(MORECPP) -arch i386 -g -static +DEFINES= +CONFIG = hd +LIBDIR = libsa +INC = -I. -I$(LIBDIR) +ifneq "" "$(wildcard /bin/mkdirs)" + MKDIRS = /bin/mkdirs +else + MKDIRS = /bin/mkdir -p +endif +AS = as +LD = ld + +# +# these paths are only valid in subdirectories of this directory +# +OBJROOT=`pwd`/../../obj/i386 +SYMROOT=`pwd`/../../sym/i386 +DSTROOT=`pwd`/../../dst/i386 +SRCROOT=/tmp + +VPATH = $(OBJROOT):$(SYMROOT) + +# The order of building is important. +SUBDIRS = util libsa libsaio boot2 boot1 boot0 cdboot modules + +all embedtheme optionrom tags debug install installhdrs: + @for i in ${SUBDIRS}; \ + do \ + echo ================= make $@ for $$i =================; \ + ( cd $$i; ${MAKE} \ + "OBJROOT=$(OBJROOT)/$$i" \ + "SYMROOT=$(SYMROOT)" \ + "DSTROOT=$(DSTROOT)" \ + "SRCROOT=$(SRCROOT)" \ + "RC_ARCHS=$(RC_ARCHS)" \ + "RC_KANJI=$(RC_KANJI)" \ + "JAPANESE=$(JAPANESE)" \ + "RC_CFLAGS=$(RC_CFLAGS)" $@ \ + ) || exit $$?; \ + done + +modules: + @for i in "modules"; \ + do \ + echo ================= make $@ for $$i =================; \ + ( cd $$i; ${MAKE} \ + "OBJROOT=$(OBJROOT)/$$i" \ + "SYMROOT=$(SYMROOT)" \ + "DSTROOT=$(DSTROOT)" \ + "SRCROOT=$(SRCROOT)" \ + "RC_ARCHS=$(RC_ARCHS)" \ + "RC_KANJI=$(RC_KANJI)" \ + "JAPANESE=$(JAPANESE)" \ + "RC_CFLAGS=$(RC_CFLAGS)" $@ \ + ) || exit $$?; \ + done + + +installsrc: + tar cf - . | (cd ${SRCROOT}; tar xfBp -) Index: branches/slice/rev749/archive/Users_Guide0.4.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: branches/slice/rev749/archive/Users_Guide0.4.pdf ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Index: branches/slice/rev749/archive/UsersGuide-v0.2.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: branches/slice/rev749/archive/UsersGuide-v0.2.pdf ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Index: branches/slice/rev749/archive/Users_Guide_v0.3.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: branches/slice/rev749/archive/Users_Guide_v0.3.pdf ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Index: branches/slice/rev749/MakeInc.dir =================================================================== --- branches/slice/rev749/MakeInc.dir (revision 0) +++ branches/slice/rev749/MakeInc.dir (revision 1169) @@ -0,0 +1,81 @@ +# +# Common makefile targets. +# +# Define these variables (if desired) in directory makefiles: +# DIRS_NEEDED +# INSTALLDIR +# SRCROOT +# +ifneq "" "$(wildcard /bin/mkdirs)" + MKDIRS = /bin/mkdirs +else + MKDIRS = /bin/mkdir -p +endif + +CPP = g++ -fno-exceptions -fno-rtti + + +# Toggle this as to whether you want a frame pointer (%ebp) to be used. It is +# invaluable for debugging the booter. For example using GDB attached to VMware. +# In fact, it's so invaluable that it's now the default. Not only that but the +# compiler seems to generate slightly smaller code and the real<->prot code +# clearly handles it appropriately so I have no idea why Apple omitted it. +#OMIT_FRAME_POINTER_CFLAG=-fomit-frame-pointer +OMIT_FRAME_POINTER_CFLAG= + +installsrc:: $(SRCROOT) + cp $(ALLSRC) $(SRCROOT) + cd $(SRCROOT); chmod a-w $(ALLSRC) + +install:: installhdrs + @if [ -z "$(RC_ARCHS)" -o -n "$(RC_i386)" ]; then \ + $(MAKE) install_i386 OBJROOT=${OBJROOT} \ + SYMROOT=${SYMROOT} DSTROOT=${DSTROOT} \ + SRCROOT=${SRCROOT}; \ + else \ + echo i386 not selected - null build.; \ + fi + +install_i386:: all + +installhdrs:: + +.SUFFIXES: .s .i .c .o + +.c.o .m.o: + @echo "\t[CC] $<" + @$(CC) $(CPPFLAGS) $(CFLAGS) $(DEFINES) -c $(INC) $< -o $(OBJROOT)/$*.o \ + -MD -dependency-file $(OBJROOT)/$*.d + @md -u $(OBJROOT)/Makedep -f -d $(OBJROOT)/$*.d + +$(OBJROOT)/%.o: %.c + @echo "\t[CC] $<" + @$(CC) $(CPPFLAGS) $(CFLAGS) $(DEFINES) -c $(INC) $< -o $(OBJROOT)/$*.o \ + -MD -dependency-file $(OBJROOT)/$*.d + @md -u $(OBJROOT)/Makedep -f -d $(OBJROOT)/$*.d + +$(OBJROOT)/%.o: %.m + @echo "\t[CC] $<" + @$(CC) $(CPPFLAGS) $(CFLAGS) $(DEFINES) -c $(INC) $< -o $(OBJROOT)/$*.o \ + -MD -dependency-file $(OBJROOT)/$*.d + @md -u $(OBJROOT)/Makedep -f -d $(OBJROOT)/$*.d + +#.s.o: +# cc $(INC) -E $< > $(OBJROOT)/$*.o2 +# $(AS) -o $(OBJROOT)/$@ $(OBJROOT)/$*.o2 + +.s.o: + @echo "\t[AS] $<" + @cc $(CPPFLAGS) -c $(INC) -arch i386 -o $(OBJROOT)/$(@F) $< + +boot2.o: + @echo "\t[AS] boot2.s" + @cc $(CPPFLAGS) -Wa,-n -c $(INC) -arch i386 -o $(OBJROOT)/$(@F) boot2.s + +$(OBJROOT)/%.o: %.s + @echo "\t[CC] $<" + @cc $(CPPFLAGS) -c $(INC) -arch i386 -o $(OBJROOT)/$(@F) $< + +$(DIRS_NEEDED) $(INSTALLDIR) $(SRCROOT): + @echo "\t[MKDIR] $@" + @$(MKDIRS) $@ Index: branches/slice/rev749/version =================================================================== --- branches/slice/rev749/version (revision 0) +++ branches/slice/rev749/version (revision 1169) @@ -0,0 +1 @@ +2.5-RC5m \ No newline at end of file Index: branches/slice/rev749/Scripts/HFS/postinstall =================================================================== --- branches/slice/rev749/Scripts/HFS/postinstall (revision 0) +++ branches/slice/rev749/Scripts/HFS/postinstall (revision 1169) @@ -0,0 +1,252 @@ +#!/bin/bash + +diskloader="/usr/standalone/i386/boot0" +partitionloader="/usr/standalone/i386/boot1h" +filesystemloader="/usr/standalone/i386/boot" +bootervolumename="EFI" +booterextensions="Extra/Extensions" + +bootresources="${0%/*}" + +diskmicrocodetype[1]="GRUB,47525542" +diskmicrocodetype[2]="LILO,4c494c4f" + +start () +{ +# $1 volume + +osxvolume="${@}" + +if [ -z "${osxvolume}" ]; then + echo + echo "Cannot find the volume. Exiting." + exit +fi + +bootdev=$( df "${osxvolume}" | sed -n '2p' | awk '{print $1}' ) + +if [ "${bootdev}" = "${bootdev#*disk*s}" ]; then + echo + echo "ERROR Volume does not use slices." + echo "Volume may be stored on a RAID array." + echo + exit +fi + +partitiontable=$( dd 2>/dev/null if=${bootdev%s*} count=1 skip=1 | dd 2>/dev/null count=8 bs=1 | perl -ne '@a=split"";for(@a){printf"%02x",ord}' ) +if [ "${partitiontable:0:16}" == "4546492050415254" ]; then + partitiontable=$( dd 2>/dev/null if=${bootdev%s*} count=1 | dd 2>/dev/null count=64 bs=1 skip=446 | perl -ne '@a=split"";for(@a){printf"%02x",ord}' ) + if [ "${partitiontable:8:2}" == "ee" ]; then + if [ "${partitiontable:40:2}" == "00" ] && [ "${partitiontable:72:2}" == "00" ] && [ "${partitiontable:104:2}" == "00" ]; then + partitiontable="GPT" + else + partitiontable="GPT/MBR" + fi + fi +else + echo + echo "ERROR Volume is not on a GPT partitioned disc." + echo + exit +fi + +echo "${partitiontable} found." + +echo "OS X Volume is ${osxvolume}" +echo "OX X Volume device is ${bootdev}" + +bootvolume="/Volumes/$bootervolumename" +bootdev=${bootdev%s*}s1 +bootrdev=${bootdev/disk/rdisk} +bootdisk=${bootdev%s*} +bootrdisk=${bootdisk/disk/rdisk} +bootslice=${bootdev#*disk*s} + +echo "EFI Volume device is ${bootdev}" +echo "EFI Volume raw device is ${bootrdev}" +echo "EFI Volume slice is ${bootslice}" +echo "Disk device is ${bootdisk}" +echo "Disk raw device is ${bootrdisk}" +echo "Disk loader is ${diskloader}" +echo "Partition loader is ${partitionloader}" +echo "Filesystem loader is ${filesystemloader}" + +} + +checkdiskmicrocodetype () +{ +diskmicrocode=$( dd 2>/dev/null if=${bootdisk} count=1 | dd 2>/dev/null count=1 bs=437 | perl -ne '@a=split"";for(@a){printf"%02x",ord}' ) + +diskmicrocodetypecounter=0 +while [ ${diskmicrocodetypecounter} -lt ${#diskmicrocodetype[@]} ]; do + diskmicrocodetypecounter=$(( ${diskmicrocodetypecounter} + 1 )) + diskmicrocodetypeid=${diskmicrocodetype[${diskmicrocodetypecounter}]#*,} + if [ ! "${diskmicrocode}" = "${diskmicrocode/${diskmicrocodetypeid}/}" ]; then + echo "${diskmicrocodetype[${diskmicrocodetypecounter}]%,*} found." + fi +done +} + +checkdiskmicrocode () +{ +# 1 action ( check or set ) + +diskmicrocode=$( dd 2>/dev/null if=${bootdisk} count=1 | dd 2>/dev/null count=1 bs=437 | perl -ne '@a=split"";for(@a){printf"%02x",ord}' ) +diskmicrocodemd5=$( dd 2>/dev/null if=${bootdisk} count=1 | dd 2>/dev/null count=1 bs=437 | md5 ) + +if [ $( echo "${diskmicrocode}" | awk -F0 '{print NF-1}' ) = 874 ]; then + if [ "${1}" = "set" ]; then + echo "No disk microcode found. Updating." + diskupdate=true + else + echo "No disk microcode found." + fi +else + if [ ${1} = set ]; then + echo "Disk microcode found. Preserving." + else + echo "Disk microcode found." + fi + echo "Disk microcode MD5 is ${diskmicrocodemd5}" +fi +} + +checkdisksignature () +{ +disksignature=$( dd 2>/dev/null if=${bootdisk} count=1 | dd 2>/dev/null count=4 bs=1 skip=440 | perl -ne '@a=split"";for(@a){printf"%02x",ord}' ) + +if [ $( echo "${disksignature}" | awk -F0 '{print NF-1}' ) = 8 ]; then + echo "No disk signature found." +else + echo "Disk signature found." + echo "Disk signature is 0x${disksignature}" +fi +} + +checkpartitionbootcode () +{ +# 1 action ( check or set ) + +partitionbootcode=$( dd if=${bootrdev} count=1 2>/dev/null | perl -ne '@a=split"";for(@a){printf"%02x",ord}' ) +partitionbootcodeextended=$( dd if=${bootrdev} count=1 skip=1 2>/dev/null | perl -ne '@a=split"";for(@a){printf"%02x",ord}' ) + +if [ $( echo "${partitionbootcode}" | awk -F0 '{print NF-1}' ) = 1024 ]; then + if [ "${1}" = "set" ]; then + echo "No partition bootcode found. Updating." + else + echo "No partition bootcode found." + fi +else + if [ "${1}" = "set" ]; then + echo "Partition bootcode found. Overwriting." + else + echo "Partition bootcode found." + fi + if [ $( echo "${partitionbootcodeextended}" | awk -F0 '{print NF-1}' ) = 1024 ]; then + partitionbootcodemd5=$( dd 2>/dev/null if=${bootrdev} count=1 | md5 ) + else + partitionbootcodemd5=$( dd 2>/dev/null if=${bootrdev} count=2 | md5 ) + echo "Partition bootcode is dual sector." + fi + echo "Partition bootcode MD5 is ${partitionbootcodemd5}" +fi +} + +checkpartitionactive () +{ +partitionactive=$( fdisk -d ${bootrdisk} | grep -n "*" | awk -F: '{print $1}') + +if [ -n "${partitionactive}" ]; then + echo "Partition flagged active is ${partitionactive}" +else + echo "No partition flagged active." +fi + +} + +start ${3} + +if [ "$( df | grep ${bootdev} )" ]; then + umount -f ${bootdev} +fi + +if ! [ "$( fstyp ${bootdev} | grep hfs )" ]; then + echo "${bootdev} isn't a HFS partition" + echo "Executing command: newfs_hfs -v ${bootervolumename} ${bootdev}" + newfs_hfs -v "${bootervolumename}" "${bootdev}" +else + echo "${bootdev} is already a HFS partition (skipping)" +fi + +diskupdate=false +checkdiskmicrocodetype +checkdiskmicrocode set +checkdisksignature +checkpartitionbootcode set +checkpartitionactive + +if ${diskupdate}; then + echo "Executing command: fdisk -u -f ${diskloader} -y ${bootdisk}" + fdisk -u -f "${osxvolume}/${diskloader}" -y ${bootdisk} +fi + +echo "Executing command: dd if=${partitionloader} of=${bootrdev}" +dd if="${osxvolume}/${partitionloader}" of=${bootrdev} + +# If table is GPT make the first partition active (BadAxe compatibility). +[ "${partitiontable}" = "GPT" ] && bootslice=1 +if [[ "${partitiontable}" = "GPT" ]]; then + fdisk -e ${bootdisk} <<-MAKEACTIVE + print + flag ${bootslice} + write + y + quit + MAKEACTIVE +fi + +checkdiskmicrocode check +checkdisksignature +checkpartitionbootcode check +checkpartitionactive + +[ -d "${bootvolume}" ] || mkdir -p "${bootvolume}" +echo "Executing command: mount_hfs ${bootdev} ${bootvolume}" +mount_hfs "${bootdev}" "${bootvolume}" + +echo "Executing command: cp ${osxvolume}${filesystemloader} ${bootvolume}/boot" +cp "${osxvolume}${filesystemloader}" "${bootvolume}/boot" + +if ! [ -d "${bootvolume}/Extra/Extensions" ]; then + echo "Executing command: mkdir -p ${bootvolume}/Extra/Extensions" + mkdir -p "${bootvolume}/Extra/Extensions" +fi +# unpack any existing Extensions.mkext already on the booter volume +if [ -e "${bootvolume}/Extra/Extensions.mkext" ]; then + echo "Executing command: mkextunpack -d ${bootvolume}/Extra/Extensions ${bootvolume}/Extra/Extensions.mkext" + mkextunpack -d "${bootvolume}/Extra/Extensions" "${bootvolume}/Extra/Extensions.mkext" + echo "Executing command: rm -R -f ${bootvolume}/Extra/Extensions.mkext" + rm -R -f "${bootvolume}/Extra/Extensions.mkext" +fi + +# copy existing /Extra +if [ -d "${2}/Extra" ]; then + [ -d "${bootvolume}/Extra/Extensions" ] || mkdir -p "${bootvolume}/Extra/Extensions" + echo "Executing command: find ${2}/Extra -name '*.plist' -depth 1 -exec cp -f {} ${bootvolume}/Extra \;" + find "${2}/Extra" -name '*.plist' -depth 1 -exec cp -f {} "${bootvolume}/Extra/" \; + if [ -f "${2}/Extra/Extensions.mkext" ]; then + echo "Executing command: mkextunpack -d ${2}/Extra/Extensions ${2}/Extra/Extensions.mkext" + mkextunpack -d "${bootvolume}/Extra/Extensions" "${2}/Extra/Extensions.mkext" + fi + if [ -d "${2}/Extra/Extensions" ]; then + echo "Executing command: find ${2}/Extra/Extensions -name '*.kext' -depth 1 -exec cp -R {} ${bootvolume}/Extra/Extensions \;" + find "${2}/Extra/Extensions" -name '*.kext' -depth 1 -exec cp -R {} "${bootvolume}/Extra/Extensions" \; + fi +fi + +# setup link for extras +[ -h "${2}/.Chameleon" ] && unlink "${2}/.Chameleon" +echo "Executing command: ln -s /Volumes/${bootervolumename} ${2}/.Chameleon" +ln -s "/Volumes/${bootervolumename}" "${2}/.Chameleon" + +exit Index: branches/slice/rev749/Scripts/Standard/postinstall =================================================================== --- branches/slice/rev749/Scripts/Standard/postinstall (revision 0) +++ branches/slice/rev749/Scripts/Standard/postinstall (revision 1169) @@ -0,0 +1,220 @@ +#!/bin/bash + + +diskloader="boot0" +partitionloader="boot1h" +filesystemloader="boot" + +diskmicrocodetype[1]="GRUB,47525542" +diskmicrocodetype[2]="LILO,4c494c4f" + +start () +{ +# 1 volume + +bootvolume="${@}" +bootresources="${0%/*}" + +if [ -z "${bootvolume}" ]; then + echo + echo "Cannot find the volume. Exiting." + echo + exit +fi + +bootdev=$( df "${bootvolume}" | sed -n '2p' | awk '{print $1}' ) +bootrdev=${bootdev/disk/rdisk} + +if [ "${bootdev}" = "${bootdev#*disk*s}" ]; then + echo + echo "ERROR Volume does not use slices." + echo + exit +fi + +bootdisk=${bootdev%s*} +bootrdisk=${bootdisk/disk/rdisk} +bootslice=${bootdev#*disk*s} + +echo "Volume is ${bootvolume}" +echo "Volume device is ${bootdev}" +echo "Volume raw device is ${bootrdev}" +echo "Volume slice is ${bootslice}" +echo "Disk device is ${bootdisk}" +echo "Disk raw device is ${bootrdisk}" +echo "Disk loader is ${diskloader}" +echo "Partition loader is ${partitionloader}" +echo "Filesystem loader is ${filesystemloader}" +echo "Boot Resources is ${bootresources}" + +} + +checkdiskmicrocodetype () +{ +diskmicrocode=$( dd 2>/dev/null if=${bootdisk} count=1 | dd 2>/dev/null count=1 bs=437 | perl -ne '@a=split"";for(@a){printf"%02x",ord}' ) + +diskmicrocodetypecounter=0 +while [ ${diskmicrocodetypecounter} -lt ${#diskmicrocodetype[@]} ]; do + diskmicrocodetypecounter=$(( ${diskmicrocodetypecounter} + 1 )) + diskmicrocodetypeid=${diskmicrocodetype[${diskmicrocodetypecounter}]#*,} + if [ ! "${diskmicrocode}" = "${diskmicrocode/${diskmicrocodetypeid}/}" ]; then + echo "${diskmicrocodetype[${diskmicrocodetypecounter}]%,*} found." + fi +done +} + +checkdiskmicrocode () +{ +# 1 action ( check or set ) + +diskmicrocode=$( dd 2>/dev/null if=${bootdisk} count=1 | dd 2>/dev/null count=1 bs=437 | perl -ne '@a=split"";for(@a){printf"%02x",ord}' ) +diskmicrocodemd5=$( dd 2>/dev/null if=${bootdisk} count=1 | dd 2>/dev/null count=1 bs=437 | md5 ) + +if [ $( echo "${diskmicrocode}" | awk -F0 '{print NF-1}' ) = 874 ]; then + if [ "${1}" = "set" ]; then + echo "No disk microcode found. Updating." + diskupdate=true + else + echo "No disk microcode found." + fi +else + if [ ${1} = set ]; then + echo "Disk microcode found. Preserving." + else + echo "Disk microcode found." + fi + echo "Disk microcode MD5 is ${diskmicrocodemd5}" +fi +} + +checkdisksignature () +{ +disksignature=$( dd 2>/dev/null if=${bootdisk} count=1 | dd 2>/dev/null count=4 bs=1 skip=440 | perl -ne '@a=split"";for(@a){printf"%02x",ord}' ) + +if [ $( echo "${disksignature}" | awk -F0 '{print NF-1}' ) = 8 ]; then + echo "No disk signature found." +else + echo "Disk signature found." + echo "Disk signature is 0x${disksignature}" +fi +} + +checkpartitionbootcode () +{ +# 1 action ( check or set ) + +partitionbootcode=$( dd if=${bootrdev} count=1 2>/dev/null | perl -ne '@a=split"";for(@a){printf"%02x",ord}' ) +partitionbootcodeextended=$( dd if=${bootrdev} count=1 skip=1 2>/dev/null | perl -ne '@a=split"";for(@a){printf"%02x",ord}' ) + +if [ $( echo "${partitionbootcode}" | awk -F0 '{print NF-1}' ) = 1024 ]; then + if [ "${1}" = "set" ]; then + echo "No partition bootcode found. Updating." + else + echo "No partition bootcode found." + fi +else + if [ "${1}" = "set" ]; then + echo "Partition bootcode found. Overwriting." + else + echo "Partition bootcode found." + fi + if [ $( echo "${partitionbootcodeextended}" | awk -F0 '{print NF-1}' ) = 1024 ]; then + partitionbootcodemd5=$( dd 2>/dev/null if=${bootrdev} count=1 | md5 ) + else + partitionbootcodemd5=$( dd 2>/dev/null if=${bootrdev} count=2 | md5 ) + echo "Partition bootcode is dual sector." + fi + echo "Partition bootcode MD5 is ${partitionbootcodemd5}" +fi +} + +checkpartitionactive () +{ +partitionactive=$( fdisk -d ${bootrdisk} | grep -n "*" | awk -F: '{print $1}') + +if [ -n "${partitionactive}" ]; then + echo "Partition flagged active is ${partitionactive}" +else + echo "No partition flagged active." +fi + +} + +start ${3} + +#partitiontable=$( diskutil list ${bootdisk} | sed -n '3p' | awk '{print $2}' ) +#[ "${partitiontable}" = "GUID_partition_scheme" ] && echo "GPT found." +#[ "${partitiontable}" = "FDisk_partition_scheme" ] && echo "MBR found." +#[ "${partitiontable}" = "Apple_partition_scheme" ] && echo "APT found." && exit + +partitiontable=$( dd 2>/dev/null if=${bootdisk} count=1 skip=1 | dd 2>/dev/null count=8 bs=1 | perl -ne '@a=split"";for(@a){printf"%02x",ord}' ) +if [ "${partitiontable:0:16}" == "4546492050415254" ]; then + partitiontable=$( dd 2>/dev/null if=${bootdisk} count=1 | dd 2>/dev/null count=64 bs=1 skip=446 | perl -ne '@a=split"";for(@a){printf"%02x",ord}' ) + if [ "${partitiontable:8:2}" == "ee" ]; then + if [ "${partitiontable:40:2}" == "00" ] && [ "${partitiontable:72:2}" == "00" ] && [ "${partitiontable:104:2}" == "00" ]; then + partitiontable="GPT" + else + partitiontable="GPT/MBR" + fi + fi +else + partitiontable="MBR" +fi + +echo "${partitiontable} found." + +diskupdate=false + +checkdiskmicrocodetype +checkdiskmicrocode set +checkdisksignature +checkpartitionbootcode set +checkpartitionactive + +if ${diskupdate}; then + echo "Executing command: fdisk -u -f /usr/standalone/i386/${diskloader} -y ${bootdisk}" + fdisk -u -f "${bootvolume}/usr/standalone/i386/${diskloader}" -y ${bootdisk} +fi + +echo "Executing command: dd if=/usr/standalone/i386/${partitionloader} of=${bootrdev}" +dd if="${bootvolume}/usr/standalone/i386/${partitionloader}" of=${bootrdev} + +echo "Executing command: cp /usr/standalone/i386/${filesystemloader} ${bootvolume}" +cp "${bootvolume}/usr/standalone/i386/${filesystemloader}" "${bootvolume}" + +echo "Executing command: ${bootresources}/Tools/SetFile -a V ${bootvolume}/${filesystemloader}" +"${bootresources}/Tools/SetFile" -a V "${bootvolume}/${filesystemloader}" + +# If table is GPT make the first partition active (BadAxe compatibility). +[ "${partitiontable}" = "GPT" ] && bootslice=1 +fdisk -e ${bootdisk} <<-MAKEACTIVE +print +flag ${bootslice} +write +y +quit +MAKEACTIVE + +checkdiskmicrocode check +checkdisksignature +checkpartitionbootcode check +checkpartitionactive + +if ! [ -d "${bootvolume}/Extra/Extensions" ]; then + echo "Executing command: mkdir -p ${bootvolume}/Extra/Extensions" + mkdir -p "${bootvolume}/Extra/Extensions" +fi +# unpack any existing Extensions.mkext already on the booter volume +if [ -f "${2}/Extra/Extensions.mkext" ]; then + echo "Executing command: mkextunpack -d ${2}/Extra/Extensions ${2}/Extra/Extensions.mkext" + mkextunpack -d "${2}/Extra/Extensions" "${2}/Extra/Extensions.mkext" + echo "Executing command: rm -R -f ${2}/Extra/Extensions.mkext" + rm -R -f "${2}/Extra/Extensions.mkext" +fi + +# setup link for extras +[ -h "${2}/.Chameleon" ] && unlink "${2}/.Chameleon" +echo "Executing command: ln -s . ${2}/.Chameleon" +ln -s "." "${2}/.Chameleon" + +exit Index: branches/slice/rev749/Scripts/Post/postinstall =================================================================== --- branches/slice/rev749/Scripts/Post/postinstall (revision 0) +++ branches/slice/rev749/Scripts/Post/postinstall (revision 1169) @@ -0,0 +1,37 @@ +#!/bin/bash + +temp="/tmp/Chameleon" + +# source com.apple.boot.plist +if ! [ -f "${2}/.Chameleon/Extra/com.apple.Boot.plist" ]; then + if [ -f "${2}/Library/Preferences/SystemConfiguration/com.apple.Boot.plist" ]; then + cp -f "${2}/Library/Preferences/SystemConfiguration/com.apple.Boot.plist" "${2}/.Chameleon/Extra" + fi +fi + +# fix kext permissions +find "${2}/.Chameleon/Extra/Extensions" -type f -exec chmod 644 {} \; +find "${2}/.Chameleon/Extra/Extensions" -type d -exec chmod 755 {} \; +chown -R 0:0 "${2}/.Chameleon/Extra/Extensions" + +# build mkext for extras +[ -d "${temp}" ] && rm -R -f "${temp}" +mkdir -p "${temp}/Extensions" +ditto --noextattr --noqtn --arch i386 "${2}/.Chameleon/Extra/Extensions" "${temp}/Extensions" +find "${temp}" -type f -exec chmod 644 {} \; +find "${temp}" -type d -exec chmod 755 {} \; +chown -R 0:0 "${temp}" +kextcache -m "${temp}/Extensions.mkext" "${temp}/Extensions" +cp -f "${temp}/Extensions.mkext" "${2}/.Chameleon/Extra" +rm -R -f "${temp}" + +# remove link for extras install +unlink "${2}/.Chameleon" + +# umount efi partition +if [ -d /Volumes/EFI ]; then + umount -f /Volumes/EFI + rm -R -f /Volumes/EFI +fi + +exit 0 \ No newline at end of file Index: branches/slice/rev749/Scripts/FAT/postinstall =================================================================== --- branches/slice/rev749/Scripts/FAT/postinstall (revision 0) +++ branches/slice/rev749/Scripts/FAT/postinstall (revision 1169) @@ -0,0 +1,265 @@ +#!/bin/bash + +diskloader="/usr/standalone/i386/boot0" +partitionloader="/usr/standalone/i386/boot1f32" +filesystemloader="/usr/standalone/i386/boot" +bootervolumename="EFI" +booterextensions="Extra/Extensions" + +bootresources="${0%/*}" + +diskmicrocodetype[1]="GRUB,47525542" +diskmicrocodetype[2]="LILO,4c494c4f" + +start () +{ +# $1 volume + +osxvolume="${@}" + +if [ -z "${osxvolume}" ]; then + echo + echo "Cannot find the volume. Exiting." + exit +fi + +bootdev=$( df "${osxvolume}" | sed -n '2p' | awk '{print $1}' ) + +if [ "${bootdev}" = "${bootdev#*disk*s}" ]; then + echo + echo "ERROR Volume does not use slices." + echo "Volume may be stored on a RAID array." + echo + exit +fi + +bootuuid=$( diskutil info "$bootdev" | grep Volume\ UUID | awk {'print $3'} ) +partitiontable=$( diskutil list ${bootdev%s*} | sed -n '3p' | awk '{print $2}' ) + +if [ ${partitiontable} != "GUID_partition_scheme" ]; then + echo + echo "ERROR Volume is not on a GPT partitioned disc." + echo + exit +fi + +echo "GPT found." + +echo "OS X Volume is ${osxvolume}" +echo "OX X Volume device is ${bootdev}" +echo "OS X Volume UUID is ${bootuuid}" + + +bootvolume="/Volumes/$bootervolumename" +bootdev=${bootdev%s*}s1 +bootrdev=${bootdev/disk/rdisk} +bootdisk=${bootdev%s*} +bootrdisk=${bootdisk/disk/rdisk} +bootslice=${bootdev#*disk*s} + +echo "EFI Volume device is ${bootdev}" +echo "EFI Volume raw device is ${bootrdev}" +echo "EFI Volume slice is ${bootslice}" +echo "Disk device is ${bootdisk}" +echo "Disk raw device is ${bootrdisk}" +echo "Disk loader is ${diskloader}" +echo "Partition loader is ${partitionloader}" +echo "Filesystem loader is ${filesystemloader}" + +} + +checkdiskmicrocodetype () +{ +diskmicrocode=$( dd 2>/dev/null if=${bootdisk} count=1 | dd 2>/dev/null count=1 bs=437 | perl -ne '@a=split"";for(@a){printf"%02x",ord}' ) + +diskmicrocodetypecounter=0 +while [ ${diskmicrocodetypecounter} -lt ${#diskmicrocodetype[@]} ]; do + diskmicrocodetypecounter=$(( ${diskmicrocodetypecounter} + 1 )) + diskmicrocodetypeid=${diskmicrocodetype[${diskmicrocodetypecounter}]#*,} + if [ ! "${diskmicrocode}" = "${diskmicrocode/${diskmicrocodetypeid}/}" ]; then + echo "${diskmicrocodetype[${diskmicrocodetypecounter}]%,*} found." + fi +done +} + +checkdiskmicrocode () +{ +# 1 action ( check or set ) + +diskmicrocode=$( dd 2>/dev/null if=${bootdisk} count=1 | dd 2>/dev/null count=1 bs=437 | perl -ne '@a=split"";for(@a){printf"%02x",ord}' ) +diskmicrocodemd5=$( dd 2>/dev/null if=${bootdisk} count=1 | dd 2>/dev/null count=1 bs=437 | md5 ) + +if [ $( echo "${diskmicrocode}" | awk -F0 '{print NF-1}' ) = 874 ]; then + if [ "${1}" = "set" ]; then + echo "No disk microcode found. Updating." + diskupdate=true + else + echo "No disk microcode found." + fi +else + if [ ${1} = set ]; then + echo "Disk microcode found. Preserving." + else + echo "Disk microcode found." + fi + echo "Disk microcode MD5 is ${diskmicrocodemd5}" +fi +} + +checkdisksignature () +{ +disksignature=$( dd 2>/dev/null if=${bootdisk} count=1 | dd 2>/dev/null count=4 bs=1 skip=440 | perl -ne '@a=split"";for(@a){printf"%02x",ord}' ) + +if [ $( echo "${disksignature}" | awk -F0 '{print NF-1}' ) = 8 ]; then + echo "No disk signature found." +else + echo "Disk signature found." + echo "Disk signature is 0x${disksignature}" +fi +} + +checkpartitionbootcode () +{ +# 1 action ( check or set ) + +partitionbootcode=$( dd if=${bootrdev} count=1 2>/dev/null | perl -ne '@a=split"";for(@a){printf"%02x",ord}' ) +partitionbootcodeextended=$( dd if=${bootrdev} count=1 skip=1 2>/dev/null | perl -ne '@a=split"";for(@a){printf"%02x",ord}' ) + +if [ $( echo "${partitionbootcode}" | awk -F0 '{print NF-1}' ) = 1024 ]; then + if [ "${1}" = "set" ]; then + echo "No partition bootcode found. Updating." + else + echo "No partition bootcode found." + fi +else + if [ "${1}" = "set" ]; then + echo "Partition bootcode found. Overwriting." + else + echo "Partition bootcode found." + fi + if [ $( echo "${partitionbootcodeextended}" | awk -F0 '{print NF-1}' ) = 1024 ]; then + partitionbootcodemd5=$( dd 2>/dev/null if=${bootrdev} count=1 | md5 ) + else + partitionbootcodemd5=$( dd 2>/dev/null if=${bootrdev} count=2 | md5 ) + echo "Partition bootcode is dual sector." + fi + echo "Partition bootcode MD5 is ${partitionbootcodemd5}" +fi +} + +checkpartitionactive () +{ +partitionactive=$( fdisk -d ${bootrdisk} | grep -n "*" | awk -F: '{print $1}') + +if [ -n "${partitionactive}" ]; then + echo "Partition flagged active is ${partitionactive}" +else + echo "No partition flagged active." +fi + +} + +start ${3} + +if [ "$( df | grep ${bootdev} )" ]; then + umount -f ${bootdev} +fi + +#if [[ `dd if=/dev/disk${1}s1 count=8 bs=1 skip=82 | uuencode -m -|head -n 2|tail -n 1` != "RkFUMzIgICA=" ]]; then +# echo "${bootdev} isn't a FAT32 partition" +# newfs_msdos -v "${bootervolumename}" "${bootdev}" +#fi + +if ! [ "$( fstyp ${bootdev} | grep msdos )" ]; then + echo "${bootdev} isn't a FAT32 partition" + echo "Executing command: newfs_msdos -F 32 ${bootdev}" + newfs_msdos -F 32 "${bootdev}" +else + echo "${bootdev} is already a FAT32 partition (skipping)" +fi + +diskupdate=false +checkdiskmicrocodetype +checkdiskmicrocode set +checkdisksignature +checkpartitionbootcode set +checkpartitionactive + +if ${diskupdate}; then + echo "Executing command: fdisk -u -f ${diskloader} -y ${bootdisk}" + fdisk -u -f "${osxvolume}/${diskloader}" -y ${bootdisk} +fi + +#echo "Executing command: dd if=${partitionloader} of=${bootrdev}" +#dd if="${osxvolume}/${partitionloader}" of=${bootrdev} + +echo "Stage 1" + +echo "Executing command: dd if=${bootrdev} count=1 bs=512 of=/tmp/origbs" +dd if=${bootrdev} count=1 bs=512 of=/tmp/origbs + +echo "Executing command: cp ${osxvolume}/${partitionloader} /tmp/newbs" +cp "${osxvolume}/${partitionloader}" /tmp/newbs + +echo "Executing command: dd if=/tmp/origbs of=/tmp/newbs skip=3 seek=3 bs=1 count=87 conv=notrunc" +dd if=/tmp/origbs of=/tmp/newbs skip=3 seek=3 bs=1 count=87 conv=notrunc + +echo "Executing command: dd of=${bootrdev} count=1 bs=512 if=/tmp/newbs" +dd if=/tmp/newbs of=${bootrdev} count=1 bs=512 + +# If table is MBR make the correct slice active. If table is GPT make the first partition active (BadAxe compatibility). +[ "${partitiontable}" = "GUID_partition_scheme" ] && bootslice=1 +if [[ "${partitiontable}" = "FDisk_partition_scheme" || "${partitiontable}" = "GUID_partition_scheme" ]]; then + fdisk -e ${bootdisk} <<-MAKEACTIVE + print + flag ${bootslice} + write + y + quit + MAKEACTIVE +fi + +checkdiskmicrocode check +checkdisksignature +checkpartitionbootcode check +checkpartitionactive + +[ -d "${bootvolume}" ] || mkdir -p "${bootvolume}" +echo "Executing command: mount_hfs ${bootdev} ${bootvolume}" +mount_msdos -u 0 -g 0 "${bootdev}" "${bootvolume}" + +echo "Executing command: cp ${osxvolume}${filesystemloader} ${bootvolume}/boot" +cp "${osxvolume}${filesystemloader}" "${bootvolume}/boot" + +if ! [ -d "${bootvolume}/Extra/Extensions" ]; then + echo "Executing command: mkdir -p ${bootvolume}/Extra/Extensions" + mkdir -p "${bootvolume}/Extra/Extensions" +fi +# unpack any existing Extensions.mkext already on the booter volume +if [ -e "${bootvolume}/Extra/Extensions.mkext" ]; then + echo "Executing command: mkextunpack -d ${bootvolume}/Extra/Extensions ${bootvolume}/Extra/Extensions.mkext" + mkextunpack -d "${bootvolume}/Extra/Extensions" "${bootvolume}/Extra/Extensions.mkext" + echo "Executing command: rm -R -f ${bootvolume}/Extra/Extensions.mkext" + rm -R -f "${bootvolume}/Extra/Extensions.mkext" +fi + +# copy existing /Extra +if [ -d "${2}/Extra" ]; then + [ -d "${bootvolume}/Extra/Extensions" ] || mkdir -p "${bootvolume}/Extra/Extensions" + echo "Executing command: find ${2}/Extra -name '*.plist' -depth 1 -exec cp -f {} ${bootvolume}/Extra \;" + find "${2}/Extra" -name '*.plist' -depth 1 -exec cp -f {} "${bootvolume}/Extra/" \; + if [ -f "${2}/Extra/Extensions.mkext" ]; then + echo "Executing command: mkextunpack -d ${2}/Extra/Extensions ${2}/Extra/Extensions.mkext" + mkextunpack -d "${bootvolume}/Extra/Extensions" "${2}/Extra/Extensions.mkext" + fi + if [ -d "${2}/Extra/Extensions" ]; then + echo "Executing command: find ${2}/Extra/Extensions -name '*.kext' -depth 1 -exec cp -R {} ${bootvolume}/Extra/Extensions \;" + find "${2}/Extra/Extensions" -name '*.kext' -depth 1 -exec cp -R {} "${bootvolume}/Extra/Extensions" \; + fi +fi + +# setup link for extras +echo "Executing command: ln -s /Volumes/${bootervolumename} ${2}/.Chameleon" +ln -s "/Volumes/${bootervolumename}" "${2}/.Chameleon" + +exit Index: branches/slice/rev749/Scripts/Options/ForceHPET/postinstall =================================================================== --- branches/slice/rev749/Scripts/Options/ForceHPET/postinstall (revision 0) +++ branches/slice/rev749/Scripts/Options/ForceHPET/postinstall (revision 1169) @@ -0,0 +1,169 @@ +#!/bin/bash + +# set com.apple.Boot.plist options + +overide="ForceHPET" +string="y" + +main () +{ + + bootplist="${3}/.Chameleon/Extra/com.apple.Boot.plist" + systemplist="/Library/Preferences/SystemConfiguration/com.apple.Boot.plist" + + bootoptionshdextra[1]="${overide}" + bootoptionshdextra[2]="${string}" + + [ ! -d "${bootplist%/*}" ] && mkdir -p "${bootplist%/*}" + + if [ ! -f "${bootplist}" ]; then + if [ -f "${systemplist}" ]; then + cp -f "${systemplist}" "${bootplist}" + fi + fi + + xmlvalue=$( getxmlvalue ${overide} "${bootplist}" | tr "[:upper:]" "[:lower:]" ) + + case "${xmlvalue:0:1}" in + + y) echo "${overide}=y already set in ${bootplist} skipping." + ;; + + n) echo "${overide}=n is set in ${bootplist} leaving." + ;; + + *) echo "Adding ${overide}=y to ${bootplist}" + array=("${bootoptionshdextra[@]}") + searchfilereplaceline "${bootplist}" "Kernel Flags" "" "" "2" + ;; + esac + + chown "${USER}:20" "${bootplist}" +} + +getxmlvalue () +{ +# 1 xml key +# 2 xml file +if [ -f "${2}" ]; then + local value + while read value; do + if [ ! "${value}" = "${value/${1}/}" ]; then + read value + value="${value#*<}" ; value="<${value}" ; value="${value#*>}" ; value="${value# *}" ; value="${value%%<*}" + echo "$value" + break + fi + done < "${2}" +fi +} + +searchfilereplaceline () +{ + +mv "${1}" "${1}.orig" + +prefunctionifs="${IFS}" + +unset fileinput +unset fileoutput +unset find +unset replace +unset deletelines +unset deletelinesskip +unset insertlinesskip + +fileinput="${1}.orig" +fileoutput="${1}" +find="${2}" +replace="${3}" +deletelines="${4%,*}" +insertlinesskip="${5}" + +matchlinefound="0" + +if [ "${#4}" = "${4#*,}" ]; then + deletelinesskip="0" + else + deletelinesskip="${4#*,}" +fi + +IFS="\n" +while read line +do + { + if [ ! "${line}" = "${line/${find}/}" ]; then + { + # Trim the longest match from the end for <* + xmlelementindent="${line%%<*}" + + # Trim the longest match from the start for *< + xmlelementtemp="${line#*<}" + # Add back in stripped < + xmlelement="<${xmlelementtemp}" + + # Trim the shortest match from the start for < + xmltagtemp="${xmlelement#<}" + # Trim the longest match from the end for >* + xmltag="${xmltagtemp%%>*}" + + # Trim the shortest match from the start for *> + xmltexttemp="${xmlelement#*>}" + # Trim the longest match from the end for <* + xmltext="${xmltexttemp%%<*}" + + if [ "${replace}" ]; then + { + echo "${xmlelementindent}<${xmltag}>${replace}" >>"${fileoutput}" + } + else + { + echo "${line}" >>"${fileoutput}" + } + fi + matchlinefound="1" + + } + else + { + + if [ "${insertlinesskip}" ] && [ "${matchlinefound}" -gt 0 ] && [ "${matchlinefound}" -le "${insertlinesskip}" ]; then + { + if [ "${matchlinefound}" = "${insertlinesskip}" ]; then + { + arraysize=0 + while [ ${arraysize} -lt ${#array[@]} ]; + do + echo "${xmlelementindent}${array[${arraysize}]}" >>"${fileoutput}" + let arraysize="${arraysize}+1" + done + } + fi + } + fi + + if [ "${deletelines}" ] && [ "${matchlinefound}" -gt 0 ] && [ "${matchlinefound}" -lt $((${deletelines}+${deletelinesskip})) ] && [ "${matchlinefound}" -ge ${deletelinesskip} ]; then + { + : + } + else + { + echo "${line}" >>"${fileoutput}" + } + fi + + if [ "${matchlinefound}" -gt 0 ]; then + let matchlinefound="${matchlinefound}+1" + fi + + } + fi + } +done < "${fileinput}" + +IFS=${prefunctionifs} + +rm -f "${fileinput}" +} + +main "${1}" "${2}" "${3}" "${4}" Index: branches/slice/rev749/Scripts/Options/EHCIacquire/postinstall =================================================================== --- branches/slice/rev749/Scripts/Options/EHCIacquire/postinstall (revision 0) +++ branches/slice/rev749/Scripts/Options/EHCIacquire/postinstall (revision 1169) @@ -0,0 +1,169 @@ +#!/bin/bash + +# set com.apple.Boot.plist options + +overide="EHCIacquire" +string="y" + +main () +{ + + bootplist="${3}/.Chameleon/Extra/com.apple.Boot.plist" + systemplist="/Library/Preferences/SystemConfiguration/com.apple.Boot.plist" + + bootoptionshdextra[1]="${overide}" + bootoptionshdextra[2]="${string}" + + [ ! -d "${bootplist%/*}" ] && mkdir -p "${bootplist%/*}" + + if [ ! -f "${bootplist}" ]; then + if [ -f "${systemplist}" ]; then + cp "${systemplist}" "${bootplist}" + fi + fi + + xmlvalue=$( getxmlvalue ${overide} "${bootplist}" | tr "[:upper:]" "[:lower:]" ) + + case "${xmlvalue:0:1}" in + + y) echo "${overide}=y already set in ${bootplist} skipping." + ;; + + n) echo "${overide}=n is set in ${bootplist} leaving." + ;; + + *) echo "Adding ${overide}=${string} to ${bootplist}" + array=("${bootoptionshdextra[@]}") + searchfilereplaceline "${bootplist}" "Kernel Flags" "" "" "2" + ;; + esac + + chown "${USER}:20" "${bootplist}" +} + +getxmlvalue () +{ +# 1 xml key +# 2 xml file +if [ -f "${2}" ]; then + local value + while read value; do + if [ ! "${value}" = "${value/${1}/}" ]; then + read value + value="${value#*<}" ; value="<${value}" ; value="${value#*>}" ; value="${value# *}" ; value="${value%%<*}" + echo "$value" + break + fi + done < "${2}" +fi +} + +searchfilereplaceline () +{ + +mv "${1}" "${1}.orig" + +prefunctionifs="${IFS}" + +unset fileinput +unset fileoutput +unset find +unset replace +unset deletelines +unset deletelinesskip +unset insertlinesskip + +fileinput="${1}.orig" +fileoutput="${1}" +find="${2}" +replace="${3}" +deletelines="${4%,*}" +insertlinesskip="${5}" + +matchlinefound="0" + +if [ "${#4}" = "${4#*,}" ]; then + deletelinesskip="0" + else + deletelinesskip="${4#*,}" +fi + +IFS="\n" +while read line +do + { + if [ ! "${line}" = "${line/${find}/}" ]; then + { + # Trim the longest match from the end for <* + xmlelementindent="${line%%<*}" + + # Trim the longest match from the start for *< + xmlelementtemp="${line#*<}" + # Add back in stripped < + xmlelement="<${xmlelementtemp}" + + # Trim the shortest match from the start for < + xmltagtemp="${xmlelement#<}" + # Trim the longest match from the end for >* + xmltag="${xmltagtemp%%>*}" + + # Trim the shortest match from the start for *> + xmltexttemp="${xmlelement#*>}" + # Trim the longest match from the end for <* + xmltext="${xmltexttemp%%<*}" + + if [ "${replace}" ]; then + { + echo "${xmlelementindent}<${xmltag}>${replace}" >>"${fileoutput}" + } + else + { + echo "${line}" >>"${fileoutput}" + } + fi + matchlinefound="1" + + } + else + { + + if [ "${insertlinesskip}" ] && [ "${matchlinefound}" -gt 0 ] && [ "${matchlinefound}" -le "${insertlinesskip}" ]; then + { + if [ "${matchlinefound}" = "${insertlinesskip}" ]; then + { + arraysize=0 + while [ ${arraysize} -lt ${#array[@]} ]; + do + echo "${xmlelementindent}${array[${arraysize}]}" >>"${fileoutput}" + let arraysize="${arraysize}+1" + done + } + fi + } + fi + + if [ "${deletelines}" ] && [ "${matchlinefound}" -gt 0 ] && [ "${matchlinefound}" -lt $((${deletelines}+${deletelinesskip})) ] && [ "${matchlinefound}" -ge ${deletelinesskip} ]; then + { + : + } + else + { + echo "${line}" >>"${fileoutput}" + } + fi + + if [ "${matchlinefound}" -gt 0 ]; then + let matchlinefound="${matchlinefound}+1" + fi + + } + fi + } +done < "${fileinput}" + +IFS=${prefunctionifs} + +rm -f "${fileinput}" +} + +main "${1}" "${2}" "${3}" "${4}" Index: branches/slice/rev749/Scripts/Options/GUI/postinstall =================================================================== --- branches/slice/rev749/Scripts/Options/GUI/postinstall (revision 0) +++ branches/slice/rev749/Scripts/Options/GUI/postinstall (revision 1169) @@ -0,0 +1,169 @@ +#!/bin/bash + +# set com.apple.Boot.plist options + +overide="GUI" +string="n" + +main () +{ + + bootplist="${3}/.Chameleon/Extra/com.apple.Boot.plist" + systemplist="/Library/Preferences/SystemConfiguration/com.apple.Boot.plist" + + bootoptionshdextra[1]="${overide}" + bootoptionshdextra[2]="${string}" + + [ ! -d "${bootplist%/*}" ] && mkdir -p "${bootplist%/*}" + + if [ ! -f "${bootplist}" ]; then + if [ -f "${systemplist}" ]; then + cp "${systemplist}" "${bootplist}" + fi + fi + + xmlvalue=$( getxmlvalue ${overide} "${bootplist}" | tr "[:upper:]" "[:lower:]" ) + + case "${xmlvalue:0:1}" in + + y) echo "${overide}=y already set in ${bootplist} skipping." + ;; + + n) echo "${overide}=n is set in ${bootplist} leaving." + ;; + + *) echo "Adding ${overide}=${string} to ${bootplist}" + array=("${bootoptionshdextra[@]}") + searchfilereplaceline "${bootplist}" "Kernel Flags" "" "" "2" + ;; + esac + + chown "${USER}:20" "${bootplist}" +} + +getxmlvalue () +{ +# 1 xml key +# 2 xml file +if [ -f "${2}" ]; then + local value + while read value; do + if [ ! "${value}" = "${value/${1}/}" ]; then + read value + value="${value#*<}" ; value="<${value}" ; value="${value#*>}" ; value="${value# *}" ; value="${value%%<*}" + echo "$value" + break + fi + done < "${2}" +fi +} + +searchfilereplaceline () +{ + +mv "${1}" "${1}.orig" + +prefunctionifs="${IFS}" + +unset fileinput +unset fileoutput +unset find +unset replace +unset deletelines +unset deletelinesskip +unset insertlinesskip + +fileinput="${1}.orig" +fileoutput="${1}" +find="${2}" +replace="${3}" +deletelines="${4%,*}" +insertlinesskip="${5}" + +matchlinefound="0" + +if [ "${#4}" = "${4#*,}" ]; then + deletelinesskip="0" + else + deletelinesskip="${4#*,}" +fi + +IFS="\n" +while read line +do + { + if [ ! "${line}" = "${line/${find}/}" ]; then + { + # Trim the longest match from the end for <* + xmlelementindent="${line%%<*}" + + # Trim the longest match from the start for *< + xmlelementtemp="${line#*<}" + # Add back in stripped < + xmlelement="<${xmlelementtemp}" + + # Trim the shortest match from the start for < + xmltagtemp="${xmlelement#<}" + # Trim the longest match from the end for >* + xmltag="${xmltagtemp%%>*}" + + # Trim the shortest match from the start for *> + xmltexttemp="${xmlelement#*>}" + # Trim the longest match from the end for <* + xmltext="${xmltexttemp%%<*}" + + if [ "${replace}" ]; then + { + echo "${xmlelementindent}<${xmltag}>${replace}" >>"${fileoutput}" + } + else + { + echo "${line}" >>"${fileoutput}" + } + fi + matchlinefound="1" + + } + else + { + + if [ "${insertlinesskip}" ] && [ "${matchlinefound}" -gt 0 ] && [ "${matchlinefound}" -le "${insertlinesskip}" ]; then + { + if [ "${matchlinefound}" = "${insertlinesskip}" ]; then + { + arraysize=0 + while [ ${arraysize} -lt ${#array[@]} ]; + do + echo "${xmlelementindent}${array[${arraysize}]}" >>"${fileoutput}" + let arraysize="${arraysize}+1" + done + } + fi + } + fi + + if [ "${deletelines}" ] && [ "${matchlinefound}" -gt 0 ] && [ "${matchlinefound}" -lt $((${deletelines}+${deletelinesskip})) ] && [ "${matchlinefound}" -ge ${deletelinesskip} ]; then + { + : + } + else + { + echo "${line}" >>"${fileoutput}" + } + fi + + if [ "${matchlinefound}" -gt 0 ]; then + let matchlinefound="${matchlinefound}+1" + fi + + } + fi + } +done < "${fileinput}" + +IFS=${prefunctionifs} + +rm -f "${fileinput}" +} + +main "${1}" "${2}" "${3}" "${4}" Index: branches/slice/rev749/Scripts/Options/EthernetBuiltIn/postinstall =================================================================== --- branches/slice/rev749/Scripts/Options/EthernetBuiltIn/postinstall (revision 0) +++ branches/slice/rev749/Scripts/Options/EthernetBuiltIn/postinstall (revision 1169) @@ -0,0 +1,169 @@ +#!/bin/bash + +# set com.apple.Boot.plist options + +overide="EthernetBuiltIn" +string="y" + +main () +{ + + bootplist="${3}/.Chameleon/Extra/com.apple.Boot.plist" + systemplist="/Library/Preferences/SystemConfiguration/com.apple.Boot.plist" + + bootoptionshdextra[1]="${overide}" + bootoptionshdextra[2]="${string}" + + [ ! -d "${bootplist%/*}" ] && mkdir -p "${bootplist%/*}" + + if [ ! -f "${bootplist}" ]; then + if [ -f "${systemplist}" ]; then + cp -f "${systemplist}" "${bootplist}" + fi + fi + + xmlvalue=$( getxmlvalue ${overide} "${bootplist}" | tr "[:upper:]" "[:lower:]" ) + + case "${xmlvalue:0:1}" in + + y) echo "${overide}=y already set in ${bootplist} skipping." + ;; + + n) echo "${overide}=n is set in ${bootplist} leaving." + ;; + + *) echo "Adding ${overide}=y to ${bootplist}" + array=("${bootoptionshdextra[@]}") + searchfilereplaceline "${bootplist}" "Kernel Flags" "" "" "2" + ;; + esac + + chown "${USER}:20" "${bootplist}" +} + +getxmlvalue () +{ +# 1 xml key +# 2 xml file +if [ -f "${2}" ]; then + local value + while read value; do + if [ ! "${value}" = "${value/${1}/}" ]; then + read value + value="${value#*<}" ; value="<${value}" ; value="${value#*>}" ; value="${value# *}" ; value="${value%%<*}" + echo "$value" + break + fi + done < "${2}" +fi +} + +searchfilereplaceline () +{ + +mv "${1}" "${1}.orig" + +prefunctionifs="${IFS}" + +unset fileinput +unset fileoutput +unset find +unset replace +unset deletelines +unset deletelinesskip +unset insertlinesskip + +fileinput="${1}.orig" +fileoutput="${1}" +find="${2}" +replace="${3}" +deletelines="${4%,*}" +insertlinesskip="${5}" + +matchlinefound="0" + +if [ "${#4}" = "${4#*,}" ]; then + deletelinesskip="0" + else + deletelinesskip="${4#*,}" +fi + +IFS="\n" +while read line +do + { + if [ ! "${line}" = "${line/${find}/}" ]; then + { + # Trim the longest match from the end for <* + xmlelementindent="${line%%<*}" + + # Trim the longest match from the start for *< + xmlelementtemp="${line#*<}" + # Add back in stripped < + xmlelement="<${xmlelementtemp}" + + # Trim the shortest match from the start for < + xmltagtemp="${xmlelement#<}" + # Trim the longest match from the end for >* + xmltag="${xmltagtemp%%>*}" + + # Trim the shortest match from the start for *> + xmltexttemp="${xmlelement#*>}" + # Trim the longest match from the end for <* + xmltext="${xmltexttemp%%<*}" + + if [ "${replace}" ]; then + { + echo "${xmlelementindent}<${xmltag}>${replace}" >>"${fileoutput}" + } + else + { + echo "${line}" >>"${fileoutput}" + } + fi + matchlinefound="1" + + } + else + { + + if [ "${insertlinesskip}" ] && [ "${matchlinefound}" -gt 0 ] && [ "${matchlinefound}" -le "${insertlinesskip}" ]; then + { + if [ "${matchlinefound}" = "${insertlinesskip}" ]; then + { + arraysize=0 + while [ ${arraysize} -lt ${#array[@]} ]; + do + echo "${xmlelementindent}${array[${arraysize}]}" >>"${fileoutput}" + let arraysize="${arraysize}+1" + done + } + fi + } + fi + + if [ "${deletelines}" ] && [ "${matchlinefound}" -gt 0 ] && [ "${matchlinefound}" -lt $((${deletelines}+${deletelinesskip})) ] && [ "${matchlinefound}" -ge ${deletelinesskip} ]; then + { + : + } + else + { + echo "${line}" >>"${fileoutput}" + } + fi + + if [ "${matchlinefound}" -gt 0 ]; then + let matchlinefound="${matchlinefound}+1" + fi + + } + fi + } +done < "${fileinput}" + +IFS=${prefunctionifs} + +rm -f "${fileinput}" +} + +main "${1}" "${2}" "${3}" "${4}" Index: branches/slice/rev749/Scripts/Options/ForceWake/postinstall =================================================================== --- branches/slice/rev749/Scripts/Options/ForceWake/postinstall (revision 0) +++ branches/slice/rev749/Scripts/Options/ForceWake/postinstall (revision 1169) @@ -0,0 +1,169 @@ +#!/bin/bash + +# set com.apple.Boot.plist options + +overide="ForceWake" +string="y" + +main () +{ + + bootplist="${3}/.Chameleon/Extra/com.apple.Boot.plist" + systemplist="/Library/Preferences/SystemConfiguration/com.apple.Boot.plist" + + bootoptionshdextra[1]="${overide}" + bootoptionshdextra[2]="${string}" + + [ ! -d "${bootplist%/*}" ] && mkdir -p "${bootplist%/*}" + + if [ ! -f "${bootplist}" ]; then + if [ -f "${systemplist}" ]; then + cp -f "${systemplist}" "${bootplist}" + fi + fi + + xmlvalue=$( getxmlvalue ${overide} "${bootplist}" | tr "[:upper:]" "[:lower:]" ) + + case "${xmlvalue:0:1}" in + + y) echo "${overide}=y already set in ${bootplist} skipping." + ;; + + n) echo "${overide}=n is set in ${bootplist} leaving." + ;; + + *) echo "Adding ${overide}=y to ${bootplist}" + array=("${bootoptionshdextra[@]}") + searchfilereplaceline "${bootplist}" "Kernel Flags" "" "" "2" + ;; + esac + + chown "${USER}:20" "${bootplist}" +} + +getxmlvalue () +{ +# 1 xml key +# 2 xml file +if [ -f "${2}" ]; then + local value + while read value; do + if [ ! "${value}" = "${value/${1}/}" ]; then + read value + value="${value#*<}" ; value="<${value}" ; value="${value#*>}" ; value="${value# *}" ; value="${value%%<*}" + echo "$value" + break + fi + done < "${2}" +fi +} + +searchfilereplaceline () +{ + +mv "${1}" "${1}.orig" + +prefunctionifs="${IFS}" + +unset fileinput +unset fileoutput +unset find +unset replace +unset deletelines +unset deletelinesskip +unset insertlinesskip + +fileinput="${1}.orig" +fileoutput="${1}" +find="${2}" +replace="${3}" +deletelines="${4%,*}" +insertlinesskip="${5}" + +matchlinefound="0" + +if [ "${#4}" = "${4#*,}" ]; then + deletelinesskip="0" + else + deletelinesskip="${4#*,}" +fi + +IFS="\n" +while read line +do + { + if [ ! "${line}" = "${line/${find}/}" ]; then + { + # Trim the longest match from the end for <* + xmlelementindent="${line%%<*}" + + # Trim the longest match from the start for *< + xmlelementtemp="${line#*<}" + # Add back in stripped < + xmlelement="<${xmlelementtemp}" + + # Trim the shortest match from the start for < + xmltagtemp="${xmlelement#<}" + # Trim the longest match from the end for >* + xmltag="${xmltagtemp%%>*}" + + # Trim the shortest match from the start for *> + xmltexttemp="${xmlelement#*>}" + # Trim the longest match from the end for <* + xmltext="${xmltexttemp%%<*}" + + if [ "${replace}" ]; then + { + echo "${xmlelementindent}<${xmltag}>${replace}" >>"${fileoutput}" + } + else + { + echo "${line}" >>"${fileoutput}" + } + fi + matchlinefound="1" + + } + else + { + + if [ "${insertlinesskip}" ] && [ "${matchlinefound}" -gt 0 ] && [ "${matchlinefound}" -le "${insertlinesskip}" ]; then + { + if [ "${matchlinefound}" = "${insertlinesskip}" ]; then + { + arraysize=0 + while [ ${arraysize} -lt ${#array[@]} ]; + do + echo "${xmlelementindent}${array[${arraysize}]}" >>"${fileoutput}" + let arraysize="${arraysize}+1" + done + } + fi + } + fi + + if [ "${deletelines}" ] && [ "${matchlinefound}" -gt 0 ] && [ "${matchlinefound}" -lt $((${deletelines}+${deletelinesskip})) ] && [ "${matchlinefound}" -ge ${deletelinesskip} ]; then + { + : + } + else + { + echo "${line}" >>"${fileoutput}" + } + fi + + if [ "${matchlinefound}" -gt 0 ]; then + let matchlinefound="${matchlinefound}+1" + fi + + } + fi + } +done < "${fileinput}" + +IFS=${prefunctionifs} + +rm -f "${fileinput}" +} + +main "${1}" "${2}" "${3}" "${4}" Index: branches/slice/rev749/Scripts/Options/GraphicsEnabler/postinstall =================================================================== --- branches/slice/rev749/Scripts/Options/GraphicsEnabler/postinstall (revision 0) +++ branches/slice/rev749/Scripts/Options/GraphicsEnabler/postinstall (revision 1169) @@ -0,0 +1,169 @@ +#!/bin/bash + +# set com.apple.Boot.plist options + +overide="GraphicsEnabler" +string="y" + +main () +{ + + bootplist="${3}/.Chameleon/Extra/com.apple.Boot.plist" + systemplist="/Library/Preferences/SystemConfiguration/com.apple.Boot.plist" + + bootoptionshdextra[1]="${overide}" + bootoptionshdextra[2]="${string}" + + [ ! -d "${bootplist%/*}" ] && mkdir -p "${bootplist%/*}" + + if [ ! -f "${bootplist}" ]; then + if [ -f "${systemplist}" ]; then + cp -f "${systemplist}" "${bootplist}" + fi + fi + + xmlvalue=$( getxmlvalue ${overide} "${bootplist}" | tr "[:upper:]" "[:lower:]" ) + + case "${xmlvalue:0:1}" in + + y) echo "${overide}=y already set in ${bootplist} skipping." + ;; + + n) echo "${overide}=n is set in ${bootplist} leaving." + ;; + + *) echo "Adding ${overide}=y to ${bootplist}" + array=("${bootoptionshdextra[@]}") + searchfilereplaceline "${bootplist}" "Kernel Flags" "" "" "2" + ;; + esac + + chown "${USER}:20" "${bootplist}" +} + +getxmlvalue () +{ +# 1 xml key +# 2 xml file +if [ -f "${2}" ]; then + local value + while read value; do + if [ ! "${value}" = "${value/${1}/}" ]; then + read value + value="${value#*<}" ; value="<${value}" ; value="${value#*>}" ; value="${value# *}" ; value="${value%%<*}" + echo "$value" + break + fi + done < "${2}" +fi +} + +searchfilereplaceline () +{ + +mv "${1}" "${1}.orig" + +prefunctionifs="${IFS}" + +unset fileinput +unset fileoutput +unset find +unset replace +unset deletelines +unset deletelinesskip +unset insertlinesskip + +fileinput="${1}.orig" +fileoutput="${1}" +find="${2}" +replace="${3}" +deletelines="${4%,*}" +insertlinesskip="${5}" + +matchlinefound="0" + +if [ "${#4}" = "${4#*,}" ]; then + deletelinesskip="0" + else + deletelinesskip="${4#*,}" +fi + +IFS="\n" +while read line +do + { + if [ ! "${line}" = "${line/${find}/}" ]; then + { + # Trim the longest match from the end for <* + xmlelementindent="${line%%<*}" + + # Trim the longest match from the start for *< + xmlelementtemp="${line#*<}" + # Add back in stripped < + xmlelement="<${xmlelementtemp}" + + # Trim the shortest match from the start for < + xmltagtemp="${xmlelement#<}" + # Trim the longest match from the end for >* + xmltag="${xmltagtemp%%>*}" + + # Trim the shortest match from the start for *> + xmltexttemp="${xmlelement#*>}" + # Trim the longest match from the end for <* + xmltext="${xmltexttemp%%<*}" + + if [ "${replace}" ]; then + { + echo "${xmlelementindent}<${xmltag}>${replace}" >>"${fileoutput}" + } + else + { + echo "${line}" >>"${fileoutput}" + } + fi + matchlinefound="1" + + } + else + { + + if [ "${insertlinesskip}" ] && [ "${matchlinefound}" -gt 0 ] && [ "${matchlinefound}" -le "${insertlinesskip}" ]; then + { + if [ "${matchlinefound}" = "${insertlinesskip}" ]; then + { + arraysize=0 + while [ ${arraysize} -lt ${#array[@]} ]; + do + echo "${xmlelementindent}${array[${arraysize}]}" >>"${fileoutput}" + let arraysize="${arraysize}+1" + done + } + fi + } + fi + + if [ "${deletelines}" ] && [ "${matchlinefound}" -gt 0 ] && [ "${matchlinefound}" -lt $((${deletelines}+${deletelinesskip})) ] && [ "${matchlinefound}" -ge ${deletelinesskip} ]; then + { + : + } + else + { + echo "${line}" >>"${fileoutput}" + } + fi + + if [ "${matchlinefound}" -gt 0 ]; then + let matchlinefound="${matchlinefound}+1" + fi + + } + fi + } +done < "${fileinput}" + +IFS=${prefunctionifs} + +rm -f "${fileinput}" +} + +main "${1}" "${2}" "${3}" "${4}" Index: branches/slice/rev749/Scripts/Options/UHCIreset/postinstall =================================================================== --- branches/slice/rev749/Scripts/Options/UHCIreset/postinstall (revision 0) +++ branches/slice/rev749/Scripts/Options/UHCIreset/postinstall (revision 1169) @@ -0,0 +1,169 @@ +#!/bin/bash + +# set com.apple.Boot.plist options + +overide="UHCIreset" +string="y" + +main () +{ + + bootplist="${3}/.Chameleon/Extra/com.apple.Boot.plist" + systemplist="/Library/Preferences/SystemConfiguration/com.apple.Boot.plist" + + bootoptionshdextra[1]="${overide}" + bootoptionshdextra[2]="${string}" + + [ ! -d "${bootplist%/*}" ] && mkdir -p "${bootplist%/*}" + + if [ ! -f "${bootplist}" ]; then + if [ -f "${systemplist}" ]; then + cp "${systemplist}" "${bootplist}" + fi + fi + + xmlvalue=$( getxmlvalue ${overide} "${bootplist}" | tr "[:upper:]" "[:lower:]" ) + + case "${xmlvalue:0:1}" in + + y) echo "${overide}=y already set in ${bootplist} skipping." + ;; + + n) echo "${overide}=n is set in ${bootplist} leaving." + ;; + + *) echo "Adding ${overide}=y to ${bootplist}" + array=("${bootoptionshdextra[@]}") + searchfilereplaceline "${bootplist}" "Kernel Flags" "" "" "2" + ;; + esac + + chown "${USER}:20" "${bootplist}" +} + +getxmlvalue () +{ +# 1 xml key +# 2 xml file +if [ -f "${2}" ]; then + local value + while read value; do + if [ ! "${value}" = "${value/${1}/}" ]; then + read value + value="${value#*<}" ; value="<${value}" ; value="${value#*>}" ; value="${value# *}" ; value="${value%%<*}" + echo "$value" + break + fi + done < "${2}" +fi +} + +searchfilereplaceline () +{ + +mv "${1}" "${1}.orig" + +prefunctionifs="${IFS}" + +unset fileinput +unset fileoutput +unset find +unset replace +unset deletelines +unset deletelinesskip +unset insertlinesskip + +fileinput="${1}.orig" +fileoutput="${1}" +find="${2}" +replace="${3}" +deletelines="${4%,*}" +insertlinesskip="${5}" + +matchlinefound="0" + +if [ "${#4}" = "${4#*,}" ]; then + deletelinesskip="0" + else + deletelinesskip="${4#*,}" +fi + +IFS="\n" +while read line +do + { + if [ ! "${line}" = "${line/${find}/}" ]; then + { + # Trim the longest match from the end for <* + xmlelementindent="${line%%<*}" + + # Trim the longest match from the start for *< + xmlelementtemp="${line#*<}" + # Add back in stripped < + xmlelement="<${xmlelementtemp}" + + # Trim the shortest match from the start for < + xmltagtemp="${xmlelement#<}" + # Trim the longest match from the end for >* + xmltag="${xmltagtemp%%>*}" + + # Trim the shortest match from the start for *> + xmltexttemp="${xmlelement#*>}" + # Trim the longest match from the end for <* + xmltext="${xmltexttemp%%<*}" + + if [ "${replace}" ]; then + { + echo "${xmlelementindent}<${xmltag}>${replace}" >>"${fileoutput}" + } + else + { + echo "${line}" >>"${fileoutput}" + } + fi + matchlinefound="1" + + } + else + { + + if [ "${insertlinesskip}" ] && [ "${matchlinefound}" -gt 0 ] && [ "${matchlinefound}" -le "${insertlinesskip}" ]; then + { + if [ "${matchlinefound}" = "${insertlinesskip}" ]; then + { + arraysize=0 + while [ ${arraysize} -lt ${#array[@]} ]; + do + echo "${xmlelementindent}${array[${arraysize}]}" >>"${fileoutput}" + let arraysize="${arraysize}+1" + done + } + fi + } + fi + + if [ "${deletelines}" ] && [ "${matchlinefound}" -gt 0 ] && [ "${matchlinefound}" -lt $((${deletelines}+${deletelinesskip})) ] && [ "${matchlinefound}" -ge ${deletelinesskip} ]; then + { + : + } + else + { + echo "${line}" >>"${fileoutput}" + } + fi + + if [ "${matchlinefound}" -gt 0 ]; then + let matchlinefound="${matchlinefound}+1" + fi + + } + fi + } +done < "${fileinput}" + +IFS=${prefunctionifs} + +rm -f "${fileinput}" +} + +main "${1}" "${2}" "${3}" "${4}" Index: branches/slice/rev749/CreditsToMeklort.rtf =================================================================== --- branches/slice/rev749/CreditsToMeklort.rtf (revision 0) +++ branches/slice/rev749/CreditsToMeklort.rtf (revision 1169) @@ -0,0 +1,7 @@ +{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf350 +{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\paperw11900\paperh16840\margl1440\margr1440\vieww9000\viewh8400\viewkind0 +\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural + +\f0\fs24 \cf0 I do not want to compete with Meklort. I just want to propose my numerous changes.} \ No newline at end of file Index: branches/slice/rev749/MakePaths.dir =================================================================== --- branches/slice/rev749/MakePaths.dir (revision 0) +++ branches/slice/rev749/MakePaths.dir (revision 1169) @@ -0,0 +1,9 @@ +# +# Default paths for subdirectories. +# + +OBJROOT=../../obj/i386/$(DIR) +SYMROOT=../../sym/i386 +DSTROOT=../../dst/i386 +SRCROOT=/tmp + Index: branches/slice/rev749/README =================================================================== --- branches/slice/rev749/README (revision 0) +++ branches/slice/rev749/README (revision 1169) @@ -0,0 +1,87 @@ + + Chameleon Boot Loader + ===================== + + What is it? + ----------- + + Chameleon is combination of various boot loader components. It is based + on David Elliott's fake EFI implementation added to Apple's boot-132 + project. Chameleon is extended with the following key features: + + + Features + -------- + + - Device Property Injection via device-properties string in com.apple.Boot.plist + - hybrid boot0+boot1h loaders for both MBR and GPT partitioned disks. + - automatic FSB detection code even for recent AMD CPUs. + - Apple Software RAID support. + - stage2 loader (boot) can be placed as a regular file in the boot + partition's root folder. + + + Installation + ============ + + Normal Install (non-RAID): + -------------------------- + + Suppose that your installation is on /dev/disk0s2 + + - Install boot0 to the MBR: + sudo ./fdisk440 -f boot0 -u -y /dev/rdisk0 + + - Install boot1h to the partition's bootsector: + sudo dd if=boot1h of=/dev/rdisk0s2 + + - Install boot to the partition's root directory: + sudo cp boot / + + No need to use startupfiletool anymore! + + + RAID Install: + ------------- + + Suppose that your installation is on /dev/disk3, which is either a mirror- or a + stripeset consisting of /dev/disk0 and /dev/disk1 + + Mac OS X creates a small helper partition at the end of each RAID member disk, + namely /dev/disk0s3 and /dev/disk1s3 + + - Install boot0 to the MBR of both disks: + sudo ./fdisk440 -f boot0 -u -y /dev/rdisk0 + sudo ./fdisk440 -f boot0 -u -y /dev/rdisk1 + + - Install boot1h to the bootsector of each boot partition: + sudo dd if=boot1h of=/dev/rdisk0s3 + sudo dd if=boot1h of=/dev/rdisk1s3 + + - Install boot to both helper partition's root directories. + diskutil mount disk0s3 + cp boot /Volumes/Boot\ OSX + diskutil unmount disk0s3 + diskutil mount disk1s3 + cp boot /Volumes/Boot\ OSX + diskutil unmount disk1s3 + + Support: + -------- + + If you have any questions, issues etc. feel free to join us + at irc.voodooprojects.org #chameleon + + + Source Code + ----------- + + For downloading the source code please visit the project page at + http://chameleon.osx86.hu + + + Licensing + --------- + + Chameleon is released under the terms and conditions of + Apple Public Source License (see APPLE_LICENSE). Index: branches/slice/rev749/revision =================================================================== --- branches/slice/rev749/revision (revision 0) +++ branches/slice/rev749/revision (revision 1169) @@ -0,0 +1 @@ +676:749 \ No newline at end of file Index: branches/slice/rev749/Kexts/Disabler.kext/Contents/MacOS/Disabler =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: branches/slice/rev749/Kexts/Disabler.kext/Contents/MacOS/Disabler ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Index: branches/slice/rev749/Kexts/Disabler.kext/Contents/Info.plist =================================================================== --- branches/slice/rev749/Kexts/Disabler.kext/Contents/Info.plist (revision 0) +++ branches/slice/rev749/Kexts/Disabler.kext/Contents/Info.plist (revision 1169) @@ -0,0 +1,47 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + Disabler + CFBundleGetInfoString + Kernel Extension Disabler 1.0.1, Copyright Âİ 2008 by Kabyl + CFBundleIdentifier + net.osrom.kext.Disabler + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + Kernel Extension Disabler + CFBundlePackageType + KEXT + CFBundleVersion + 1.0.1 + IOKitPersonalities + + IntelCPUPMDisabler + + CFBundleIdentifier + net.osrom.kext.Disabler + IOClass + Disabler + IOMatchCategory + AppleIntelCPUPowerManagement + IOProbeScore + 1000 + IOProviderClass + IOResources + IOResourceMatch + IOKit + + + OSBundleLibraries + + com.apple.kernel.iokit + 1.1 + + OSBundleRequired + Root + + Index: branches/slice/rev749/Kexts/JMicronATAInjector.kext/Contents/Info.plist =================================================================== --- branches/slice/rev749/Kexts/JMicronATAInjector.kext/Contents/Info.plist (revision 0) +++ branches/slice/rev749/Kexts/JMicronATAInjector.kext/Contents/Info.plist (revision 1169) @@ -0,0 +1,53 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleIdentifier + org.chameleon.plist.JMicronATAInjector + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + JMicron ATA Injector + CFBundlePackageType + KEXT + CFBundleSignature + ???? + CFBundleVersion + 1.0.0 + IOKitPersonalities + + JMicronATA Driver + + CFBundleIdentifier + com.jmicron.JMicronATA + Hardware Vendor + JMicron + IOClass + JMicronATA + IOProviderClass + JMicronATAChannel + + JMicronATA PCI + + CFBundleIdentifier + com.jmicron.JMicronATA + Hardware Vendor + JMicron + IOClass + JMicronATAPCIRoot + IOPCIClassMatch + 0x01010000&0xffff0000 + IOPCIPrimaryMatch + 0x2368197b 0x2360197b&0xfff0ffff + IOProbeScore + 12000 + IOProviderClass + IOPCIDevice + + + OSBundleRequired + Local-Root + + Index: branches/slice/rev749/Kexts/AHCIPortInjector.kext/Contents/Info.plist =================================================================== --- branches/slice/rev749/Kexts/AHCIPortInjector.kext/Contents/Info.plist (revision 0) +++ branches/slice/rev749/Kexts/AHCIPortInjector.kext/Contents/Info.plist (revision 1169) @@ -0,0 +1,382 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleIdentifier + org.chameleon.plist.AHCIPortInjector + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + AHCI Chipsets Injector + CFBundlePackageType + KEXT + CFBundleSignature + ???? + CFBundleVersion + 1.0.0 + IOKitPersonalities + + GenericAHCI + + CFBundleIdentifier + com.apple.driver.AppleAHCIPort + Chipset Name + AHCI Standard Controller + IOClass + AppleAHCI + IOPCIClassMatch + 0x01060100&0xffffff00 + IOProbeScore + 800 + IOProviderClass + IOPCIDevice + Vendor Name + Unknown + + JMicronAHCI + + CFBundleIdentifier + com.apple.driver.AppleAHCIPort + Chipset Name + JMB36x AHCI + IOClass + AppleAHCI + IOPCIPrimaryMatch + 0x2360197b&0xfff0ffff + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Vendor Name + JMicron + + ICH6 ESB2 AHCI + + CFBundleIdentifier + com.apple.driver.AppleAHCIPort + Chipset Name + ESB2 AHCI + IOClass + AppleAHCI + IOPCIPrimaryMatch + 0x26818086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Vendor Name + Intel + + ICH7MAHCI + + CFBundleIdentifier + com.apple.driver.AppleAHCIPort + Chipset Name + ICH7-M AHCI + IOClass + AppleAHCI + IOPCIPrimaryMatch + 0x27c58086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Vendor Name + Intel + + ICH7MRAID + + CFBundleIdentifier + com.apple.driver.AppleAHCIPort + Chipset Name + ICH7-M RAID + IOClass + AppleAHCI + IOPCIPrimaryMatch + 0x27c68086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Vendor Name + Intel + + ICH7RAHCI + + CFBundleIdentifier + com.apple.driver.AppleAHCIPort + Chipset Name + ICH7-R AHCI + IOClass + AppleAHCI + IOPCIPrimaryMatch + 0x27c18086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Vendor Name + Intel + + ICH7RRAID + + CFBundleIdentifier + com.apple.driver.AppleAHCIPort + Chipset Name + ICH7-R RAID + IOClass + AppleAHCI + IOPCIPrimaryMatch + 0x27c38086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Vendor Name + Intel + + ICH8AHCI + + CFBundleIdentifier + com.apple.driver.AppleAHCIPort + Chipset Name + ICH8 AHCI + IOClass + AppleAHCI + IOPCIPrimaryMatch + 0x28248086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Vendor Name + Intel + + ICH8MAHCI + + CFBundleIdentifier + com.apple.driver.AppleAHCIPort + Chipset Name + ICH8-M AHCI + IOClass + AppleICH8AHCI + IOPCIPrimaryMatch + 0x28298086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Vendor Name + Intel + + ICH8MRAID + + CFBundleIdentifier + com.apple.driver.AppleAHCIPort + Chipset Name + ICH8-M RAID + IOClass + AppleAHCI + IOPCIPrimaryMatch + 0x282a8086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Vendor Name + Intel + + ICH8RAHCI + + CFBundleIdentifier + com.apple.driver.AppleAHCIPort + Chipset Name + ICH8-R AHCI + IOClass + AppleAHCI + IOPCIPrimaryMatch + 0x28218086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Vendor Name + Intel + + ICH8RRAID + + CFBundleIdentifier + com.apple.driver.AppleAHCIPort + Chipset Name + ICH8-R RAID + IOClass + AppleAHCI + IOPCIPrimaryMatch + 0x28228086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Vendor Name + Intel + + ICH9AHCI + + CFBundleIdentifier + com.apple.driver.AppleAHCIPort + Chipset Name + ICH9 AHCI + IOClass + AppleAHCI + IOPCIPrimaryMatch + 0x29238086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Vendor Name + Intel + + ICH9MAHCI + + CFBundleIdentifier + com.apple.driver.AppleAHCIPort + Chipset Name + ICH9-M AHCI + IOClass + AppleAHCI + IOPCIPrimaryMatch + 0x29298086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Vendor Name + Intel + + ICH9MRAID + + CFBundleIdentifier + com.apple.driver.AppleAHCIPort + Chipset Name + ICH9-M RAID + IOClass + AppleAHCI + IOPCIPrimaryMatch + 0x292c8086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Vendor Name + Intel + + ICH9RAHCI + + CFBundleIdentifier + com.apple.driver.AppleAHCIPort + Chipset Name + ICH9-R AHCI + IOClass + AppleAHCI + IOPCIPrimaryMatch + 0x29228086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Vendor Name + Intel + + ICH9RRAID + + CFBundleIdentifier + com.apple.driver.AppleAHCIPort + Chipset Name + ICH9-R RAID + IOClass + AppleAHCI + IOPCIPrimaryMatch + 0x29258086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Vendor Name + Intel + + ICH10AHCI + + CFBundleIdentifier + com.apple.driver.AppleAHCIPort + Chipset Name + ICH10 AHCI + IOClass + AppleAHCI + IOPCIPrimaryMatch + 0x3A028086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Vendor Name + Intel + + ICH10RAID + + CFBundleIdentifier + com.apple.driver.AppleAHCIPort + Chipset Name + ICH10 RAID + IOClass + AppleAHCI + IOPCIPrimaryMatch + 0x3A058086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Vendor Name + Intel + + ICH10RAHCI + + CFBundleIdentifier + com.apple.driver.AppleAHCIPort + Chipset Name + ICH10-R AHCI + IOClass + AppleAHCI + IOPCIPrimaryMatch + 0x3A228086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Vendor Name + Intel + + ICH10RRAID + + CFBundleIdentifier + com.apple.driver.AppleAHCIPort + Chipset Name + ICH10-R RAID + IOClass + AppleAHCI + IOPCIPrimaryMatch + 0x3A258086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Vendor Name + Intel + + + OSBundleRequired + Local-Root + + Index: branches/slice/rev749/Kexts/ATAPortInjector.kext/Contents/Info.plist =================================================================== --- branches/slice/rev749/Kexts/ATAPortInjector.kext/Contents/Info.plist (revision 0) +++ branches/slice/rev749/Kexts/ATAPortInjector.kext/Contents/Info.plist (revision 1169) @@ -0,0 +1,596 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleIdentifier + org.chameleon.plist.ATAPortInjector + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ATA Chipsets Injector + CFBundlePackageType + KEXT + CFBundleSignature + ???? + CFBundleVersion + 1.0.0 + IOKitPersonalities + + ESB2 ATA/100 + + CFBundleIdentifier + com.apple.driver.AppleIntelPIIXATA + Controller Name + ESB2 ATA/100 + IOClass + AppleIntelPIIXATARoot + IOPCIPrimaryMatch + 0x269e8086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Supported Transfer Modes + 0x3f061d + + ESB2 Serial ATA + + CFBundleIdentifier + com.apple.driver.AppleIntelPIIXATA + Controller Name + ESB2 SATA + IOClass + AppleIntelPIIXATARoot + IOPCIPrimaryMatch + 0x26808086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Serial ATA + + Supported Transfer Modes + 0x3f061d + + ICH ATA Controller + + CFBundleIdentifier + com.apple.driver.AppleIntelPIIXATA + Controller Name + ICH + IOClass + AppleIntelPIIXATARoot + IOPCIPrimaryMatch + 0x24118086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Supported Transfer Modes + 0x1f061d + + ICH0 ATA Controller + + CFBundleIdentifier + com.apple.driver.AppleIntelPIIXATA + Controller Name + ICH0 + IOClass + AppleIntelPIIXATARoot + IOPCIPrimaryMatch + 0x24218086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Supported Transfer Modes + 0x07061d + + ICH2 ATA/100 Controller + + CFBundleIdentifier + com.apple.driver.AppleIntelPIIXATA + Controller Name + ICH2 ATA/100 + IOClass + AppleIntelPIIXATARoot + IOPCIPrimaryMatch + 0x244A8086 0x244B8086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Supported Transfer Modes + 0x3f061d + + ICH2 ATA/66 Controller + + CFBundleIdentifier + com.apple.driver.AppleIntelPIIXATA + Controller Name + ICH2 ATA/66 + IOClass + AppleIntelPIIXATARoot + IOPCIPrimaryMatch + 0x24418086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Supported Transfer Modes + 0x1f061d + + ICH3 ATA/100 Controller + + CFBundleIdentifier + com.apple.driver.AppleIntelPIIXATA + Controller Name + ICH3 ATA/100 + IOClass + AppleIntelPIIXATARoot + IOPCIPrimaryMatch + 0x248A8086 0x248B8086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Supported Transfer Modes + 0x3f061d + + ICH3 ATA/66 Controller + + CFBundleIdentifier + com.apple.driver.AppleIntelPIIXATA + Controller Name + ICH3 ATA/66 + IOClass + AppleIntelPIIXATARoot + IOPCIClassMatch + 0x01010000&0xffff0000 + IOPCIPrimaryMatch + 0x24818086 0x24008086&0xff00ffff + IOProbeScore + 1800 + IOProviderClass + IOPCIDevice + Supported Transfer Modes + 0x1f061d + + ICH4 ATA/100 Controller + + CFBundleIdentifier + com.apple.driver.AppleIntelPIIXATA + Controller Name + ICH4 ATA/100 + IOClass + AppleIntelPIIXATARoot + IOPCIPrimaryMatch + 0x24CB8086 0x24CA8086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Supported Transfer Modes + 0x3f061d + + ICH5 ATA/100 Controller + + CFBundleIdentifier + com.apple.driver.AppleIntelPIIXATA + Controller Name + ICH5 ATA/100 + IOClass + AppleIntelPIIXATARoot + IOPCIPrimaryMatch + 0x24DB8086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Supported Transfer Modes + 0x3f061d + + ICH5 Serial ATA Controller + + CFBundleIdentifier + com.apple.driver.AppleIntelPIIXATA + Controller Name + ICH5 SATA + IOClass + AppleIntelPIIXATARoot + IOPCIPrimaryMatch + 0x24D18086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Serial ATA + + Supported Transfer Modes + 0x3f061d + + ICH6 ATA/100 Controller + + CFBundleIdentifier + com.apple.driver.AppleIntelPIIXATA + Controller Name + ICH6 ATA/100 + IOClass + AppleIntelPIIXATARoot + IOPCIPrimaryMatch + 0x266f8086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Supported Transfer Modes + 0x3f061d + + ICH6 Serial ATA Controller + + CFBundleIdentifier + com.apple.driver.AppleIntelPIIXATA + Controller Name + ICH6 SATA + IOClass + AppleIntelPIIXATARoot + IOPCIClassMatch + 0x01010000&0xffff0000 + IOPCIPrimaryMatch + 0x26528086 0x26518086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Serial ATA + + Supported Transfer Modes + 0x3f061d + + ICH6-M Serial ATA Controller + + CFBundleIdentifier + com.apple.driver.AppleIntelPIIXATA + Controller Name + ICH6-M SATA + IOClass + AppleIntelPIIXATARoot + IOPCIClassMatch + 0x01010000&0xffff0000 + IOPCIPrimaryMatch + 0x26538086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Serial ATA + + Supported Transfer Modes + 0x3f061d + + ICH7 ATA/100 + + CFBundleIdentifier + com.apple.driver.AppleIntelPIIXATA + Controller Name + ICH7 ATA/100 + IOClass + AppleIntelPIIXATARoot + IOPCIPrimaryMatch + 0x27df8086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Supported Transfer Modes + 0x3f061d + + ICH7 Serial ATA + + CFBundleIdentifier + com.apple.driver.AppleIntelPIIXATA + Controller Name + ICH7 SATA + IOClass + AppleIntelPIIXATARoot + IOPCIPrimaryMatch + 0x27c08086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Serial ATA + + Supported Transfer Modes + 0x3f061d + + ICH7-M Serial ATA + + CFBundleIdentifier + com.apple.driver.AppleIntelPIIXATA + Controller Name + ICH7-M SATA + IOClass + AppleIntelPIIXATARoot + IOPCIPrimaryMatch + 0x27c48086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Serial ATA + + Supported Transfer Modes + 0x3f061d + + ICH8 2 Port Serial ATA + + CFBundleIdentifier + com.apple.driver.AppleIntelPIIXATA + Controller Name + ICH8 2 Port SATA + IOClass + AppleIntelPIIXATARoot + IOPCIPrimaryMatch + 0x28258086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + PCS Port Map + kgGTAZICkwKSBJMEkgiTCA== + Serial ATA + + Supported Transfer Modes + 0x3f061d + + ICH8 ATA/100 + + CFBundleIdentifier + com.apple.driver.AppleIntelPIIXATA + Controller Name + ICH8 ATA/100 + IOClass + AppleIntelPIIXATARoot + IOPCIPrimaryMatch + 0x28508086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Supported Transfer Modes + 0x3f061d + + ICH8 Serial ATA + + CFBundleIdentifier + com.apple.driver.AppleIntelPIIXATA + Controller Name + ICH8 SATA + IOClass + AppleIntelPIIXATARoot + IOPCIPrimaryMatch + 0x28208086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + PCS Port Map + kgGTAZICkwKSBJMEkgiTCA== + Serial ATA + + Supported Transfer Modes + 0x3f061d + + ICH8-M Serial ATA + + CFBundleIdentifier + com.apple.driver.AppleIntelPIIXATA + Controller Name + ICH8-M SATA + IOClass + AppleIntelPIIXATARoot + IOPCIPrimaryMatch + 0x28288086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + PCS Port Map + kgGTAZICkwKSBJMEkgiTCA== + Serial ATA + + Supported Transfer Modes + 0x3f061d + + ICH9 2 Port Serial ATA + + CFBundleIdentifier + com.apple.driver.AppleIntelPIIXATA + Controller Name + ICH9 2PTS SATA + IOClass + AppleIntelPIIXATARoot + IOPCIPrimaryMatch + 0x29218086 0x29268086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + PCS Port Map + kgGTAZICkwKSBJMEkgiTCA== + Serial ATA + + Supported Transfer Modes + 0x3f061d + + ICH9 Serial ATA + + CFBundleIdentifier + com.apple.driver.AppleIntelPIIXATA + Controller Name + ICH9 SATA + IOClass + AppleIntelPIIXATARoot + IOPCIPrimaryMatch + 0x29208086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + PCS Port Map + kgGTAZICkwKSBJMEkgiTCA== + Serial ATA + + Supported Transfer Modes + 0x3f061d + + ICH9-M Serial ATA + + CFBundleIdentifier + com.apple.driver.AppleIntelPIIXATA + Controller Name + ICH9-M SATA + IOClass + AppleIntelPIIXATARoot + IOPCIPrimaryMatch + 0x29288086 0x292d8086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + PCS Port Map + kgGTAZICkwKSBJMEkgiTCA== + Serial ATA + + Supported Transfer Modes + 0x3f061d + + ICH10 2 Port Serial ATA + + CFBundleIdentifier + com.apple.driver.AppleIntelPIIXATA + Controller Name + ICH10 2PTS SATA + IOClass + AppleIntelPIIXATARoot + IOPCIPrimaryMatch + 0x3a068086 0x3a268086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + PCS Port Map + kgGTAZICkwKSBJMEkgiTCA== + Serial ATA + + Supported Transfer Modes + 0x3f061d + + ICH10 Serial ATA + + CFBundleIdentifier + com.apple.driver.AppleIntelPIIXATA + Controller Name + ICH10 SATA + IOClass + AppleIntelPIIXATARoot + IOPCIPrimaryMatch + 0x3a008086 0x3a208086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + PCS Port Map + kgGTAZICkwKSBJMEkgiTCA== + Serial ATA + + Supported Transfer Modes + 0x3f061d + + PIIX ATA Controller + + CFBundleIdentifier + com.apple.driver.AppleIntelPIIXATA + Controller Name + PIIX + IOClass + AppleIntelPIIXATARoot + IOPCIPrimaryMatch + 0x12308086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Shared Channel Timings + + Supported Transfer Modes + 0x00061d + + PIIX3 ATA Controller + + CFBundleIdentifier + com.apple.driver.AppleIntelPIIXATA + Controller Name + PIIX3 + IOClass + AppleIntelPIIXATARoot + IOPCIPrimaryMatch + 0x70108086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Supported Transfer Modes + 0x00061d + + PIIX4 ATA Controller + + CFBundleIdentifier + com.apple.driver.AppleIntelPIIXATA + Controller Name + PIIX4 + IOClass + AppleIntelPIIXATARoot + IOPCIPrimaryMatch + 0x71118086 + IOProbeScore + 2000 + IOProviderClass + IOPCIDevice + Supported Transfer Modes + 0x07061d + + Parallel ATA Channel Driver + + CFBundleIdentifier + com.apple.driver.AppleIntelPIIXATA + IOClass + AppleIntelPIIXPATA + IOProbeScore + 800 + IOProviderClass + AppleIntelPIIXATAChannel + Serial ATA + + + Serial ATA Channel Driver + + CFBundleIdentifier + com.apple.driver.AppleIntelPIIXATA + IOClass + AppleIntelICHxSATA + IOProbeScore + 1000 + IOProviderClass + AppleIntelPIIXATAChannel + Serial ATA + + + + OSBundleRequired + Local-Root + + Index: branches/slice/rev749/Kexts/IOAHCIBlockStorageInjector.kext/Contents/Info.plist =================================================================== --- branches/slice/rev749/Kexts/IOAHCIBlockStorageInjector.kext/Contents/Info.plist (revision 0) +++ branches/slice/rev749/Kexts/IOAHCIBlockStorageInjector.kext/Contents/Info.plist (revision 1169) @@ -0,0 +1,47 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleIdentifier + org.chameleon.plist.IOAHCIBlockStorageInjector + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + IOAHCIBlockStorage Fix + CFBundlePackageType + KEXT + CFBundleSignature + ???? + CFBundleVersion + 1.1.1 + IOKitPersonalities + + AppleAHCIDiskDriver + + CFBundleIdentifier + com.apple.iokit.IOAHCIBlockStorage + IOClass + AppleAHCIDiskDriver + IOProviderClass + IOAHCIDevice + IOProbeScore + 1000 + Physical Interconnect + SATA + Physical Interconnect Location + Internal + Protocol Characteristics + + Physical Interconnect + SATA + Physical Interconnect Location + Internal + + + + OSBundleRequired + Local-Root + + Index: branches/slice/rev749/fdisk =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: branches/slice/rev749/fdisk ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Index: branches/slice/rev749/themeinfo.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: branches/slice/rev749/themeinfo.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Index: branches/slice/rev749/User_Guide_src/install_complete.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: branches/slice/rev749/User_Guide_src/install_complete.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Index: branches/slice/rev749/User_Guide_src/Chameleon 2 v0.5.docx =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: branches/slice/rev749/User_Guide_src/Chameleon 2 v0.5.docx ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Index: branches/slice/rev749/User_Guide_src/install_stand.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: branches/slice/rev749/User_Guide_src/install_stand.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Index: branches/slice/rev749/User_Guide_src/colorchart.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: branches/slice/rev749/User_Guide_src/colorchart.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Index: branches/slice/rev749/User_Guide_src/Chameleon 2 v0.4.xml =================================================================== --- branches/slice/rev749/User_Guide_src/Chameleon 2 v0.4.xml (revision 0) +++ branches/slice/rev749/User_Guide_src/Chameleon 2 v0.4.xml (revision 1169) @@ -0,0 +1,12299 @@ + + +Kevyn ShortellKevyn Shortell202009-03-29T08:05:00Z2009-03-30T07:05:00Z2009-03-30T07:05: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 +RK5CYIJ= +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 +rkJggk== +Chameleon 2.0 Users GuideRevision 0.4Table of ContentsIntroductionPage 2Running the InstallerPage 3Custom InstallPage 4Advanced OptionsPage 6Boot.plist configurationPage 7Custom boot.plist variablesPage 6ThemesPage 8Screen LayoutPage 9Boot devicesPage 8Boot promptPage 9Info boxPage 10MenuPage 11Boot displayPage 12IntroductionChameleon 2.0 the latest version of the of the Chameleon boot loader for OS X on X86 hardware. It is an EFI boot loader that is designed to replace the Darwin and PC_EFI boot loaders. It has several new features including:Graphical User Interface modeCustomizable ImagesSupport for GPT/MBR partition typesRAID supportiVBORw0KGgoAAAANSUhEUgAABAAAAAMACAIAAAA12IJaAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJ +bWFnZVJlYWR5ccllPAABydhJREFUeNrs/WmQZNmVH3b+zzn3vufuseZWmVlZe2FtoFBAA91NtjXZ +UnWTHJFscdE2kmkkcUbkjGnMNF/GZr6MaT7OhzGbxUY2MtkMKaMojc2IklEUF0ndTfRONIAG0I1G +YakqFGqvyj0zItz9vXfvPWc+3OceHpGZ1SDZpDGRJ5DI8vD4uWeEx4vMe+/Z6IUXfx6AmRIxTr6d +vFMBfsCH3Lt37969e/fu3bt3/3D48X0iBnTtNu5cv8vr+927d+/evXv37t27d/+QenrhxZc2tw4P +3jHgvlsN9+7du3fv3r179+7dP0Seq17vEh60jdj4qHv37t27d+/evXv37h9WT7UG4MTuwRQnNwoP +2Gq4d+/evXv37t27d+/+IfN87+4BG6lCY57QSm/uJ9y7d+/evXv37t27d//Q+XUE4FTm0OlEons2 +Ge7du3fv3r179+7du3/4/Lp2+NQe4tSD791kuHfv3r179+7du3fv/uHzTHRv/6BT0QReP6wC9+7d +u3fv3r179+7dP6x+owhYzfAHjQ/YfHPv3r179+7du3fv3v1D5k91AdpE+IPSjNy7d+/evXv37t27 +d/+QeT4ZHcBGhtBm7GB9p7p37969e/fu3bt37/7h9ccRgPUG4kN2EvfdcLh37969e/fu3bt37/5h +8bxZPXDqBu7TWBTu3bt37969e/fu3bt/eD0/aHTwamTA5m1e7Rncu3fv3r179+7du3f/UHr69Gde +uidAcHpqwH0jC+7du3fv3r179+7du3/oPBPdWwd8n8HCpyIL7t27d+/evXv37t27fxj9Zp7Q6ajB +yee6d76Ae/fu3bt37969e/fuHzJPL7z40oMCBA8oH1b37t27d+/evXv37t0/pP6BRcCnthEbH3Xv +3r179+7du3fv3v3D6k9NAlaAYQr6IWeMuXfv3r179+7du3fv/mHyfO/uARupQicbDN3bRtS9e/fu +3bt37969e/cPk19HAE5lDp1OJLpnk+HevXv37t27d+/evfuHz69rh0/tIU49+N5Nhnv37t27d+/e +vXv37h8+z0T39g86FU3g9cMqcO/evXv37t27d+/e/cPqN4qA1Qz3FhN8SIWBe/fu3bt37969e/fu +Hy5/qgvQJsIflGbk3r179+7du3fv3r37h8zfOzd4nSG0GTtY36nu3bt37969e/fu3bt/eP1xBGC9 +gfiQncR9Nxzu3bt37969e/fu3bt/WDxvVg+cuoH7NBaFe/fu3bt37969e/fuH17PDxodvBoZsHmb +V3sG9+7du3fv3r179+7dP5SePv2Zl+4JEJyeGnDfyIJ79+7du3fv3r179+4fOs9E99YB32ew8KnI +gnv37t27d+/evXv37h9Gv5kndDpqcPK57p0v4N69e/fu3bt37969+4fM0wsvvvSgAMEDyofVvXv3 +7t27d+/evXv3D6l/YBHwqW3Exkfdu3fv3r179+7du3f/sPpTk4AVYJiCfsgZY+7du3fv3r179+7d +u3+YPN+7e8BGqtDJBkP3thF17969e/fu3bt37979w+TXEYBTmUOnE4nu2WS4d+/evXv37t27d+/+ +4fPr2uFTe4hTD753k+HevXv37t27d+/evfuHzzPRvf2DTkUTeP2wCty7d+/evXv37t27d/+w+o0i +YDXDvcUEH1Jh4N69e/fu3bt37969+4fLn+oCtInwB6UZuXfv3r179+7du3fv/iHz984NXmcIbcYO +1neqe/fu3bt37969e/fuH15/HAFYbyA+ZCdx3w2He/fu3bt37969e/fuHxbPm9UDp27gPo1F4d69 +e/fu3bt37969+4fX84NGB69GBmze5tWewb179+7du3fv3r179w+lp09/5qV7AgSnpwbcN7Lg3r17 +9+7du3fv3r37h84z0b11wPcZLHwqsuDevXv37t27d+/evfuH0W/mCZ2OGpx8rnvnC7h37969e/fu +3bt37/4h8/TCiy89KEDwgPJhde/evXv37t27d+/e/UPqH1gEfGobsfFR9+7du3fv3r179+7dP6z+ +1CRgBRimoB9yxph79+7du3fv3r179+4fJs/37h6wkSp0ssHQvW1E3bt37969e/fu3bt3/zD5dQTg +VObQ6USiezYZ7t27d+/evXv37t27f/j8unb41B7i1IPv3WS4d+/evXv37t27d+/+4fNMdG//oFPR +BF4/rAL37t27d+/evXv37t0/rH6jCFjNcG8xwYdUGLh37969e/fu3bt37/7h8qe6AG0i/EFpRu7d +u3fv3r179+7du3/I/L1zg9cZQpuxg/Wd6t69e/fu3bt37969+4fXH0cA1huID9lJ3HfD4d69e/fu +3bt37969+4fF82b1wKkbuE9jUbh37969e/fu3bt37/7h9fyg0cGrkQGbt3m1Z3Dv3r179+7du3fv +3v1D6enTn3npngDB6akB940suHfv3r179+7du3fv/qHzTHRvHfB9Bgufiiy4d+/evXv37t27d+/+ +YfSbeUKnowYnn+ve+QLu3bt37969e/fu3bt/yDy98OJLDwoQPKB8WN27d+/e/T9vnokAA+i+XK2C +k89uxV9P9+7du38E/QOLgE9tIzY+6t69e/fu/7nwTLT+pWbETEwA6l3rG8QswsSod65W/8YkdVdQ +lb+e7t27d/+I+FOTgBVgmIJ+yBlj7t27d+/+n6lnluO/1plMbb2spxNn/AaQmZ28E/UeMzsdIIAB +pGZ1L+Gvv3v37t3/CHu+d/eAjVShkw2G7m0j6t69e/fu/1n4elq/Xv2PB/xELExEwkQEJjBBmJgg +zMIUhFfvjr8H4XqDCLR6A1CjByKrfxuINo6O/PV37969+x8pv44AnMocOp1IdM8mw7179+7d/7Pw +dam/XvQDVj+6kc4DItpM7/nQ59d10MDUVlGB+oH1Px6bH4WeDBf498u9e/fuH3a/rh0+tYc49eB7 +Nxnu3bt37/6frl+dxNNxTj+R8HiEX8/+WQJLIBYiIWJhEZbV2T8H4SAhSL3BwiwsIQQiIRLi+ovH +pxoDCFzDAixMAPFxmYF/v9y7d+/+R8PTCy/+/H1TiD5kS+HevXv37v+peqYTif40luqOJ/2mRizH +d9b/jR8CMe7J+8fmHVqMeDzg1zH7H2o1EKAAtOjq7P84JjD6e4oE/Pvl3r179w+d3ywCVjP8EI+E +e/fu3bv/p+eZ1gk/62wfA4iFAV4l+9QP1Y3A2MlnY93PAFhObgPU6k7A6q1Vbo+ZaVnnAtkPtxNY +5wf598u9e/fuHz5/qgvQJsIflGbk3r179+7/MP166W9qLLx56r+x9CciksDrRT8Rg4h5zBfCqh1Q +/d3M6s115x8zU7P6EdP6nm1uBszGJX7dCZjaasMAYON5jmMCOLUf8O+ve/fu3f/z7O9NAbpvucD6 +wVrLBty7d+/e/R+ur6k1IrQCJsxYHfJLXezz+jdiqVlAqw+tHie8Kha2jcb/4/q+9oK29am/qq7D +A5rNsNoQmJmaqmk99TczLQCKKhN9SLnwumS5Jh4VLf79de/evft/3vxxBGD9sA/ZSdx3w+HevXv3 +7v9J/EbOD+ox/6lT/1rrC4CJmZmF1jeISFYdPZmFeAwR4ESbIFot2Mez/HpLtcCsrE79zayoAarl +OCxgZlp0MzVoHRAYI82gzbDA8de4ERSolQN4QAmBXw/u3bt3/8/Y0wsvvvSg0cGnHry6re7du3fv +/g/L33f1DxCLMFld7I/Nf0Rqtx5mCkFgJiHWrYIwmIVA64rhzd/HM//1ql0NpuOC3qyYmqKUvNoM +qGpd9qsptC7/6yPsdJFAXeWvKwo2ggN13NgYInjQruCe18qvB/fu3bv/Z+H5QaODVyMDNm/XR7p3 +7969+z8cvzFvi4SxyvOREESYJAQWFpYYY4wxSAgxtE1omhhCbCaTpgltGydt07aTpm3aSdO0Tds2 +k0k7mbTteLuZTOJ02tZfbRvbSdNO2sm0adsmNrGJTdOEtm1jW2/HJobYxBhijCGMf3YIQaT+4tpR +VABedSAlltpK9NS4Md6cOFb3OeNWh2vX0XX5sl8P7t27d//PztOnP/PSPQGCH3YP4d69e/fu//H8 +6uAf6yledek/9uNnZmGAYgyrU3+OgVkCCwdhIhZh5vF3ZmYi1Acynzr+3ziAH9N3Vin+xQxZ1Uw1 +a1E1s1K0fqSUbGZFVYupqpqqwrQUXbUGKuvK4XtLhMf4QC1oxvFHDKD7FhMDOFkw4NePe/fu3f/T +8mMNwA/ROvTEs7h37969+39sLyzYSPuR8VBcVuW8HAIzCwsJCzPFIHXpH0VYWERYOIgw05gZtNoB +1IICZqZ17g2BAF1l4+iYyYMxvb/Utb2tVv+l5LLeCRQtWqzkrKiVAFAtRe3e3kF12Px4e1zon+4a +tJk19CHFxPfbBvj14969e/d/mP7EHIB1+GDzwQ8uJnDv3r179//InokAo/Gc3oS51vuuB/vymATE +IhyCCDOHEETqjF8J9UMiIswk9QFE4zZgnXCzmgqwWQZQx36Zrvv8qJqVoqalqKlqKVnV6q6glPFd +LVpMSy41ZKBFVeuqvRYNQ0upz1/UVoHm1X5gNW6s9iEtWmsDTs8Z2Lgfm3MG/Ppx7969+38a/sOK +gB9QPqzu3bt37/4fz9cRv6tunlg19WQmlsBEFCTUg/8QhZmDhBhEZMy/H2+LCLOEcWvARPV2Xf2L +CE7m/9QZAHWFbasggKqqFjPSUorW31TVSl34r9+tu4AaC1DLq5SgsqoINoMWVdQT/XG2wHiub6iT +BtY7kHXRcNGxu+g6LLCKJ9CaYaNQ2K8f9+7du/9D9KdTgD5kwvB9mXv37t27/yF9zfwBwKte/Syh +pgCxMBEHkRBYREIQEZYQ64o/xPHUP8ZYl/8hhFolLLVMmJmYRKQWAhDXVqAnqgB0naGjZrBSxrSe +nHPdD5RS6gag1Oyf1X9rP6CcanWAlZoFZKtuoaoG6DhYYEwuqof6dWJxjRJYrSHARtZQGRORdPzP +cRhhDAsUPdkz1K839+7du/9D8icnASvAMAX9kDPG3Lt37979D+XX7T5XZ/8gDgDiuIYfc/lFJDYi +HGIQCRJiqB14xjY8UUKIqx1CLQKoe4aaOCQ1mjA2eQCNrR/qUTzWKfljMbCWYoZSahJQLmolb5z/ +Fy1acs7HuwK1GhfQWjkw5hBBVxEB1Az+VQKQbkYJxsQeA+rYAa3FxOtQwrq7aM0LqsGEugf4IUIB +fr25d+/e/T+Cv88gsM13H5Q/5N69e/fuf3i/mvI7DvaqZ/9Sp3kJM3GIwiSxkSAsITYx1IP/JoYg +IkFCGJtx1qV/jIFZYpB68C9Sn2y9+jeuiUDj8n/8tFCHANR0/KKm9VxeSx4b/pSsYxlw0TzuBsqq +HiCVYrbaDBis6HpMmNZ8n/VCXsdQA1BX9KZkKGPd8RgzyMVgtpozYCWviwrWe4BVMKEonx4q7Neb +e/fu3f8T+NUG4FTm0H0HCH8IcO/evXv39/dYTfTdPPvfXP03TWCWGEUkxFhzf2qzf6mr/ljjAKtu +/DFwjQmwCBOLkIjQ+GTjJDHi4wkDG595PftX1GP7uvyviT01/SeXmuVfshbVnLOqppTNrOQ8dgzS +GjKomUFjRXFZzxUzlFyISHX8U2rEQcc0Hyt1/PBGd9Gx3ehq6nAZc4DqHzD2CBqLicf0Ib/e3Lt3 +7/6fyJ+eA/AHthH9kD2He/fu3bs/5Terflc9f46P62MIteNnjPWUP8T1rxBCCLGpY7ikHv43MYQY +ggjXLCAWWQ0FEGECiJkAEQFRbbpPqwgArfp01mV0yVnHA3uUUm9rXeSXnFU1l5Kzmmou67dx3a9j +jYDW0QJjV6BVwo+OG4zjG7XJqK72HGX1/1x7D6nVGuNcClC7DNW4wlgVoOtagROjhP16c+/evft/ +TE8vvPjzP0TT0BMPc+/evXv3P4xfT/siYiawsClC7dgjvDrEFxZpY4xNXfKHZpzBG5omBpGmaWIc +76+5/yFIDEGCrGcAiAityn6FZX3oT0TEXFNzVp9bzc4xG9fsWtRKzjVNX1cH/WPyTymlaC7FVNO4 +NyhmVu/RcY7AGARYZfGPBQarCgGF0XrIgI5dREsp46K/lFy3AaVoWe0JxlCAmlmpMwo2uwOpFb/e +3Lt37/6fxJ+YA2CGH+KRcO/evXv3f6A/lffPwgBquS/V/p6xNvap6f1SV/9tE2OMMYYYYxNjWN8I +Ept1KGDdC5THSuAaURChMQZgBjDzehswtthfZdWvO3XWk34YdEzp0VVLUNNScslasDru15zKesNQ +aoaP6olUorHMYD1m4HgjUEqpewBTy7WQOJdSshbLte5YNSc1KzlrLUIY6wusrJqEHs8N2GgN5Neb +e/fu3f8j+1NdgDYR/qA0I/fu3bt3f39/qt8/Tlb9BqmLeK5H+zHEGKRpYwihbZsQQoyxaWI9+6+b +gVoeEGOsIwLq4j8EYSKRAEIdE1b/KBwnHdVD+bEkYF2Za6ogKqWe0dsq/V7Lqi/QaidwPCCgRgZq +MYDW43xVVdSV/caR//oG1u+Pe4vjbkKqRXMNMSTNJY97gZJzvbemIZlp0ZSLqeJEw1C7ZwPg16d7 +9+7d/yP4e1OA7lsusH6wAuzevXv37j/Erzt+AhAGERMLEYLIKu9faqfPGGMbY2hCU5N/mhBjE2Ns +mybG0LQxSGjaJoawihGMZ/8hSBAhYhYSESYCqAYZHru0GIbbWXu1rrYDCmglToNMidqbV7cAqsk2 +IJgaiGxM7dfNOECtz625OqYoWhOBcs3JGVf51Y9jxcaKgrG30Grpb6u0/rptWJcTlDym/KScc8ql +aC45pVSKlqyb3UjXJQG1c+g4a6zOIvbrzb179+7/0f192oB+yE7ivhsO9+7du3e/9nXa18lZv3Lq +7J+ZmyaE06v/plkf/DexaUITa/qP1JiAhHHdX+sGWCgGIRIiMPN0arv7V4f8dtj6bldeTfmqWWdm +zJMoZwOdBZ2Fnb36bqNlNpmc25qdD3z+8PYUQM35MVjdFWhZF+Zq0XFeV0pp1cSz1KX82MznxKJf +V13/dRwSVqym9RigRVPOdSFfcs0Aqkf+Zci55JJTTiXnlFMee5HmtK47HvcAJ2uCT/cF8uvTvXv3 +7n8YTy+8+NKDRgfj/o1F1b179+7dP8ivO35u9vwhYgksfCLvv41RgrRt08QQmyYEmUwmMYa2aUIM +bdvEGJuxQiBIYBFpYmQWCSJMFIiNY4xPPn1U+Ju3jr465B/EeCfpNcKiAEyIcmGxSF1XkiINGAYA +Ozk3LFtN3IsSY3P+ycd/Yit+8v3Xz6SSMY70gqrmkmGohbs5l+PxYWOm0LgZMEDru6u64tXiv95e +V/QWHQeNjav/lFLdEuScU0qqmnJOw2oDUHJKRbWksfpYcylm4xSx1XRhBehB6UB+fbp37979g/wY +AXjwDOF7Ywpw7969e/cPOv4nJlMLgU/N+l33/FnV9QYRmUzG/J62iU0Tm7ZtYtO0oa79x7fxkbwq +ARYmMAsLn79Qkr2R6bcXw5dD+24zubPsNGcLTJNmOgzDncO46LucTIGiMIBA2VAMKQOw7W1p6Ynz +uz97dvqz/Z1PlZzHNbyqKtbVvbW3Z9ECg1rJWQGUkmtwQI9n+p7oBFTb/ozpQ6vqYS06pGJaUkop +55xLHvcA4+/DkEopw1DjAapahiHXOEBNGgKwmhpwHATw69O9e/fuf3h/eg7AfdOGHrSHcO/evXv3 +J8/+AZAw0RgHqL06WZjr7N6a+dPEEEJomxib2DRN28TYNE0T27apEYC4av0TxoEAsvo/S2AmYeb9 +89fi1jfefv83Bn3l/IUz04l1w3t9f5eZrMQy7N28dfMoazIIoyiGAaFBVhBDBCIoii6hBQfsTsLz +T5z7c2emnz26fQGwevAPWCmrQ33VUhN6Vj3/dZXoX4rWMcNFFWa1yrcWGOi6VKAUNct5LCQouaSU +cyk55zSkNC79h1oOkIaUc06pDCnVUoGNOICueoPa/ZoC+fXp3r1793+wl4uXnl89bD0tkjaeizae +hbAaKunevXv37jf92Oxz7LxPAJhDXf1vzvqtLf5jCG1bE/2bJoZ20jYxtpO6B2hr/k8tBgg1XyjU +cWAhBAkSds+k81e+cXv5t155/e91w1s7e02MB316//ad5TBgGp+YL+KNG9ezWqGYiymCFpTaAIio +CVNmHnIpBZMQVMvuDqXyzsH8683svb3zi0bOMO2Y8fhGFiSMLUdXYwdYWCQwkYgEqcMMOMg4miCs +JpwFEWaSGvuoxQvENYuJa5kEMwiregkmIpjVWcaA0aqFqY2veB1khvrh+h9VYyLz69O9e/fuf2gv +Fy89t3rYeNfanXwu2ny8e/fu3btfeybQqul+kNqWPwhTXeiGKMyhaVar/3V+f9vEIO1k0rbNesXf +NLFZjQIIsp4EHEKQEGU6iVu7h9Nzf/PO4le69LK0d2czTGdh2d9+9/28WCBGUZ3N5/0wDJlomUox +MMFYzMCIZmCOWijlUgoJQwiLozRpjaRbDq+rvTbZfntr50YuZ3a3pykFlkBkRFy3MyJChLERKcuq +L9E4lGDVpUjCulaZx4W/sBCRCMtYIT32LR2HpgnXJT0TA0br9b5hvE0oxerSv+4BYFZ3XON0A78+ +3bt37/6H8x9WBPyA8mF17969e/drv276SUTCYyyAiSVwGJfCYTz7b0IMoWljE5umbZoYmrZp25ry +E+qNpqkzgJs6A1iCBBEJJBxms3D+8psH/S/f7v8r4cV8jiGXrRmM+OhIDw+wszXZ3j136/b7XacG +7gYtQswGkBbAQiNbaUA/dFY0NjtNmBazYLpc3mmiEbrJlNrGLjwWt7f3hZ7Za39mOPrxgGfv3G7M +zKAEqJZiBq2rblpNBDYQajsgGAympitqJa9nAGspJZdS63xTLrUCOKU0DDmlYRhy3w85pSGlfkhp +qB8sQxpK1to4qJYR1+JkMxQ9XQzg16d79+7df7gPVd+3Z9C9NcUPri1w7969+0fRb477BYyYiUSY +WJiI16v/ICFEjnFs7tk0sXb+aZu2aWI79v1cnf3Xrv/jwK8gAuHQTm37/K9+cPBrQ/muKW7Py90D +xIbacPZofudwDmaSZvdwfnDUqQiyqgVEMWHuOuvmiHKem2d3wqVnzz974cyzbXtm0uxNmq2UB1Xt +l93NO++W9M7Nwy9dffdL0+fIwivX7r7Z8O+18vHp7kt5+ZGa9g8IwyCo/f9jE03VDLVJP8b2PJpS +hpBIKaohcMkonFVNRLhkYU65EOcaLyEiAq9Op4wIINTa4vqcZgEoZmYsasbMRQsxQw2wWni9+W+b +X5/u3bt3/2H+5CRgBRimoB9yxph79+7dP7p+8+yfyVjEFCHUNp08TvsNMmniOPOrjashX7FpY9M0 +bdu27XHmTwg1RNAECbEJIiEEEo5NM9D237oz/9vtzgEgd+7cPrqrRtjd3UkD3Tk4WPQ4d25re/fM +9RvvGNBOaNFZ04ThcJaHnSZevHT2haeufOHS+Y+d3X22lV3CFtAA8XiRDQCq5ebB4q3vvPLf3e1+ +u9l6bW8/9MOdw8Nbk/gnrpz7V4ejj7BN1Eo/dKVk1bJ77iY3d/tu2feHw5Cms70Ypk1sgO1r7+wF +iYx2GGLXlVKyWinZ1CynrKo55yHlUnJOeUgl5zT0Qz+kYRiGIfX9kFIa+qFPaehTqkGBcUTARhDA +an9R2Crk4Nene/fu3f+B/j6DwDbfve+d7t27d+9+3fTzVMt/CQJQ00QibtuwmfdfV/lNbGIT2rad +tG3ThKZtY5SmbgJCWKf9hCjMEmNs4hC2/vbN7m8ZvZ3AJdPdo5wHnNuZUIh3Dw4PFkiKK5fOgfjg +8HrKsEJBZoe3Z+emP/fskz/50Wc+e/nSxwW7QAswDDae1Nd/B7RYFjCQAQYaYHjrg1957e3/XCZv +Qt6RcG0+zyhPPP34H7l05rmDxd1bt99ZLG/0/Y2Cu6GxppnCYjfkfuiZyWw5iXuxeWxn69lZ+5zk +p47uPn3r+s6Qcp3mW3JR1aHOAUg5lzz0tRHQuAfo+z6l3Pd93Qb0/TAMKeWchzSkkkvOKeesqmU9 +IXgcDwzUBkV+fbp37979h/nVBuBU5tB9Bwh/CHDv3r37R8tvHP9DmDebfo5NO6PUBX0I0rTN2Om/ +tvts2rZtmza0bbuuCV4X/oYoIdQcoDCbmcX/5oNbf3+eXtvbP9Olg8NF6joEwdm9rW7o7h6UowXO +XZhO2jDked+r5Zj7x8tw+bOf/HOf+ehLe9tXGLtmUjQIxVWKzFg0W98BDFRgZMbIyEghHLx3+xe/ +/vL/K05eRXw/CKUOTTy7t/ukUOz7g2X3vurhkI0IxGhiJJktFgdFJScW3isphVC2t8+27WP7088j +fbwMz1x7f19Vcy5mmnLJKedS0jDkUuoEgJRS3w39MKzjAEPfDyn1/VgnkHPq+1RU6xyxXNQsazke +D6xW/Pp07969+w/38tjFZ2ra5cYHjt9dPZjW9cWngHv37t0/gp5XD2FmpprxL0xUk39iFBGp3Tub +EGJb53yNPf6bpmknTdMcr/6bplmn/ocIo4GpbG+1Tz9/+6j87bvd3x/ytb4biHaPlouu1xi3AjcG +TX1aDEgZ58+dz3mRhqQlpv7ibvNTf+Zn/3cvPP8np80FYGomsIYoMqGu14lAZET1i69NN40gRExC +qsVs2J3t3bz77rXrX+PQq0IVZomJYmRQWixuLZbKBGHKhRZ9GYY+JVJthc8G3lZbdsNhn+8O+b1l ++t4wXM361vkLQwhnySaq9SW02jIJZiAQwax2/6yBiVVRgWGcL1aHjlHduZCaEUyNiAGr/YKIQObX +s3v37t1/qJeLl56/p3/Q5iOxevBxn1H37t27f8Q9rSpXicBcV/7HbX+YQxMlNE0TQ2zG1X/t8R9r +1/8mrKIBzbrwt9YABMl9utbrN3ny8jz9+mH3ayEeJD3sBjUshlyYEWg/tpOs/WKZ5gssB9vZwWKx +LDn284vPX/6Lv/Cz/9tzu59W3TULsAnQEMYmm6vj//qLjn/VjxmBTAKrWZAzwsMHN7+T9bpaISAE +cOhgB0RDNyzv3DEYJIqCUjZV6jtLJYPmareMOhBYkAaUlJTuFnqrL69Lc+3Jpy/0y3M5EfP4SYyt +PmvruvE1t3q3manVCcQ23lsU602BgWB127AaCAz169m9e/fuP9TLxUvPrT6gZvbgRx7vIdy7d+/+ +UfZc5/3SOvlHavd6Fg4hBJGmCSHEJoYYpK7w1wv9Sdu0TQwxtm3TjkOAQx30FWIQ5hins+ljz37c +rt39u719VXGNpU2p75MprG1pMp0UWjJj2S3mCyw7M2B7uwl0rju69LlP/OV/8Sf+SpQrZhOGwAQg +GLiur2lz9Q+Ax9P2+m+DEchAplqEWlOJU1y/9d1OX23bTIQQwVKGnAw9E5ViXYd+sGGwXMBCsQ0S +LbToehjQROQMJoKSIklUCWnZ3zk4uHHh/JYOF4ZxD0DHk7zqILCxpyfBVm/jpsDGNT9MSx0QVhN/ +rMYO6riAdRDAr2f37t27v6/fTAzizQICQFeP3LwT7t27d+8e4/wvWrX/r8f/QZiZiZlD4BBCbJpY +q4CDjF0+mxhX7T5DiCHUCcEhhhAkNE2UEJpGD45el+aWyCJEIWqHZMYoBgkkTWZO4KMu2XiMT9Qd +bvVHj3/yuX/zj33u3xN63LTlseoLTGBZZX/CAF39OvEvx7jGJgCJiAyck0zCOaLzwARCzBQiOCAr +ht7Atr07MWDooIoYQzudhKa00zhpzwgRlFWjIbTTnXarNWjf9YvlPMQkzZtXD/7m7sXf3tlBkBiD +hCDrF6rOPmvbpok1JyqMk9DqODQZX2URDoHHaWRMxDIOu9H19savZ/fu3bu/v+d7HqkrdPrBqzai +7t27d//o+vEonWu7ejKtK2yumwFmjkFCreUNEgLXJWzTNCJSB36FEN58440vfvFXmiYwUds2df0f +AjNLO0Hc+cZ717508+YNiVcms8cW/fVFr1BszWg6s5yzBBBr/byyAdrODy+d237pj7z478DOlhJg +ZJZYMvFqkT+m/hegrP89gMEMZlpKNqWsuWiXS0/ETJBgjJlgp+8XOWsBE9gMElCAfrBmsrW7v5MB +IyrGi66bz+323eGDq7e65SR1u8t5MIPaUuKwf2avncVUur67WuiqtC/Py9+98NSXZ1sQCSGKCNe+ +p2P0REJYvVzjRiCGuN4uBGERovXctdqKdfxe1Pf9enbv3r37B3le7wlWD+NTO4nNBwPu3bt3/4j7 +VQUVEzGx1INnYpZ6Gs0yHlPXhj41vaeJsW3HLp9NE//BL/36bLIdQghR6qpXhFmIhSVeO+y+kem7 +02kDw2J+cDTPOSEGbprZMGAYUDJKIQBDwtaE0hDJnnvhE39+t302F5GYJSYzhQmgNasHdHwOdJzz +U//DJiF0Sw2BhE04qKGogQtAs8mZPvVakIfSJxXmEACGCHKZz3Z2weizZZOS47J+eopsy17v9GXZ +D/noKB3OS9IkUcMEfVkeHX5QcDvb1+4c/fqVp9/YO8tBpBmnJYQYY+2CGqUGUZoxP0rq/kBCEOFV +0UVgYQaICYDg1Ffo17N79+7d38/zvaGBU41C77nt3r1794+0r4vN2v6/HjkLEwuJcBCuK9UYQ20E +NI71FW5ibNoYgjQx/s///X/7T/6pl0KQtmljjMwUAjOFdtLPy9fn6auQ9yXezPlO1821wApAu6aT +oUcpgJImmCIIYpA0DNNw6eJjz86HRAzYAGRmAcRQDNlQal79xr8FVqtmCVDN/8//5P/xL/7cH/v3 +//JfuXbjWjGoFiIqyIYh61AKDEQsoDYnQUEUQAAqzMNsm+cdjubL+TzBWATSgAI4AAwORNwsjvD+ ++4sbtzIRdnekbSkPNqS07L951P/mdHqzbp9iGKeojTlRUZpmPPVfv54iIsIiHGKoEQAWYRmDACzM +dJzz6teze/fu3d/X86ksoFM3xrYQphtP5N69e/ePqGciNcNxWdXx8T8TE5PIuEINIuO5dQghhKat +2Swxxsgi5y+cC6t8FyISISKJMdDkmyV8FXKzFM22HPTmkMvQoWlCbJqsJRdjgIlThgAhYMhFKM+2 +ioRFzoeL5TwlNmtVNxvj1MBFqMv2dfa/mYHxa7/26//r/+A//MpX/+Ff/X//tS996evCEy0KNpRM +sIPF9W6wxdJgQjY7OMpHC6AWFVPp862dvSkzDo7QJRsGzQmlAAwlqEGzCcd2OmlatkL9EoDsbZ0P +trs8MqObd5a/as0v75+fx1hX9kGEZQyhBAkhxFBvxxgkyPiKynEQoNZgENfmoExEZkb1Dr+e3bt3 +7/5+nk8++DiRaPPp7t1DuHfv3v2j6UVqtv9xHKAe/zNxYB4HgYVxzRpqHvtqwFetDG6ayCy17JeZ +QxDmKCLSXj8avknxNdU7OcGUYcEMyojTQtSlIaahSQOyFs1mhSYhTgJPZ/butS/+xpf/yy7f2N7a +LWXSdwxjtQQ1U4ERjOoXt9oDAFBCAXD+/GPPPPUMQH/mX/pzP/WFPwZQMYWZSLNI1w8X75OFocd8 +MSyXvWYeenS9ZUVSBZdmEs6d3ckZ/YCup8USaUAtjQCQCo4W88WiQ2ERHjo6uFPmCw2yH0PMaQA+ +mPdf2Tn3VTMmFgkcYyNB4irvpy79x0ZJIbCMCUDj71zrL1bbAAIxCR/3vPPr2b179+7v9XwyYeg4 +kQj3Kya4J8HIvXv37h9BXzus1eYzBBATcyCWwPVcmlmYxqrWGGpdQM1hF+HjXJcQQz3AFt7e75N8 +4273W4vh9Zy7nJGHJg9RFdKCg2Wba1HLMWeAsLXFAOcc1BAa6/Jrv/bl//N//8v/6be+89V+WMSW +lOdKR0YASA2GcVQuxtJfGAwMs/LCCy/+4i/+j7/yq7/yN/6L//zCxQtqw7QVpuUyX//6t//Bux98 +M8hW08RuwDAMk8k5Ax8eWbfEMNQXDVs7FCLyAM2cBk4DkUUhJoIaQMREKee+LwYqpblx4+ZQuscu +PMvMfVpyvHW0fPnClbdrAlVtrspEIlQzf0IYAytBZP061lSgWu7LMk5l4I3knzqqwa9n9+7du7/X +y8VLz63C2boKCo8jA4g23713voB79+7dP0K+5v/UfjOrvB9m4RADE8cosQkiEmNcd/6v/X/aJpy4 +M4QY67KWmSXGCAzz8pWF/Z15/3vM6HoMA/bPnCHWxXKYTaVppCgNebEcBmJIwJCpz5pSNrIQYmhI +Mbxz9euvvPmb71z93UV+W9oDYeO4FallZiIzsnEvYFSnaRmMSVTp/IVzzzzzzHTaMs2VbnXdW99+ +45d+/5W/9e6135j338p6VLQQ0Cc1S8ZWsuUCAzgwgWfT7fniaL7EtAUxqRqgHKioCSM2aKIQoxhU +TZpiTGqTdiLGcyqTGANwe3sn7M+evnu3rZMAxjEAWof/mplq0VwKAK1vZuN/YKWYmYKQS6mDxWru +k2r9r1/P7t27d3/C0wsvvnRyGgA2owmbwYKNrYN79+7dP3JeWOq5sjCxjNN/WbhpxiaVbdu2bTOZ +NE3TtG3Ttu1sNm2bOJm0TdtM2rYOA161ug8xxqYttw/feOfaL8/OfHf/sXeOjq7tbO8cHB1psd3d +s8Nwd0iFhQCoIWfrOpiCCGAqsK6DFUBpSNZ1tlwChiZsa9mZtY8/funFy2c/ce7M5QvnLm5NdifT +mcQmSisIDAFYoQoFsOyWXXdnGA7uLN+9ev17b7zzlbuHr56/sJ/yzZt33okNQkQTQISi2N2Vra2t +lOfDUJqGgmBn58IwdL/91buTSLu7xASFtS1YQMD21iSE2PcLEHJSEdMCJNrdp7O7k0Bnh/4Wi+xs +/UQ5+jfuXPt4LiknHVJKQxqGNAzDsuv7oR+6Ydn13bLr+r7vh74fuq5PQ+r7fkgl5ZxSKrkUNbOc +s5rB1HRVB+HXs3v37t2v38K6aGAdO7gnf4jvfQr37t27f/R8HbpFx4lATLUHJdU5wFxzUbiWsYbA +4y5BVn1qeEz4CRKYuEtX373762+888s8ffXi/jPDIkfZXxxp31mMNKSjfigsWPYmAiaUUk+1QYzI +AMAMNYAtABNQjDg8tEW32JpsGS3efu/X337377Agxu3Z9NzW7Nxssj+b7gPCHJkF4KJZ9c6y/2Cx +PEjpoM931Y5ixN65xmhx8+71RW/bgajACBC0DZdsXTe07WxZjo6ObHtbbt66vrd34crlg/evWt9j +a0YE9D3aFqoY+lRKqS+msPUJk0CTrdmwnM9jd2YrgKmUfr58Zzu+t7P7ybt3RQRSpEipQZYgXFgS +89hfNUtm5tr+v85dE6UCgFjYrBQjJlJYLQquewC/nt27d+9+7cNm5hCgRAxT0InGoutnuae1kHv3 +7t0/Op7G+V/MwJgKRMRMJMwsRCREXDcDYyugUPcBvDHlilkktuXa0d9/84PfGPI7KV599klkfj02 +l3KJw+K6MBU1AMyU1eo037rcZ4YKCCAhNhMZG/owgQAWbG3hbtFFf72UOVHXbimLGd+Ypzfnd4Ip +S5iVYlBIaIRbUJbmqpE2kaQlEp1GUsNgmC+tTzaZEgvlbJ1BDCw2LG2+7GZbfdPEshxUY9/3B4fz +J594QvXdW7eVGLMpVKGFALtzUJpYJhMQFWaQQRWTWdstusVR2Wr6ECZHh3PiGxa/T+FzMZxVMxEW +FREVKRIC5xKC5CxEdYPFEkTyOHyBqAAcRFK21XdW63eylAe1xvPr2b1794+uP1U+zACwUUZwqqb4 +njai7t27d/+o+JMNQMckyzr9F4Taib4e9xOBmVhYmKXeWUd9MTEH8PLtO3/znRt/M07fKHS1aW17 +T5JasWEYbhd0xCiKnEsxpAQzFIUqRLhpgwi0wFSZIAwiGEEBEjCjndD5cxQbXaajbKUfdMjImQzE +jU62ODTLyVa/td/Pduft9vU4vdZMFIQ+WTGNDWWzXEwNfQ+1OjCAiNBEaiItlmZA0/DQ23KRDDg6 +6oh46IfFsr/42IX9PTJFP9TtirRxSoApDCgKFrQNUrY7d27lXErBcnmj5IEZoO6o+/r+Y98gWkVR +aot/YSYKwnX+b4xRVhssESGiIMxAECYmIhCRqdZmoADWZcF+Pbt37979cVJrLQIe9wobiUSrLQJt +BBc2Y9/u3bt3/2j5euRfW0zWDpTEJCLCq67/q4aVTYyxiU0t/A1NbGLTxBAkxChxuHr4d4/yl5rZ +naPlzUJ24YJMZ20aErMV7VgsK4jAgftBTWEGFsBgZKVYGkCEWlObC2AggAhaACAEpAwRqsXE/QBh +lhBLIc2mBrNMlCBJNRXLRjYkhECBoQYiqSNiUrKuw3RCk2ksRUMAM1QRAoGgasxjFyAWqNVK3I7Z +9vZ2U1r2HUIgK8YcYiAWVUUIiA3BiAmpQJjYqKRCkttJC3RKXeCdvdmPLeaNGVTNzMqq8LcUK1pK +0VxKvb+UUoqWsioIrin/ZgYC2VgLbFC/nt27d+/+pF8PCj61h+CTVQX3bjLcu3fv/hHy40FyzcyR +jaSg2oOSZdWMkuvZfz3tr60oZTWldjJlmn3j7vI3WLr5vOQSzPjM2XOqw6RpVLXvNGWQIEY2Vc0o +CgogpqIoA2AQgdZ0TqIxAqBQXX12hCAQsemE9vZk0lDX2Z07/XKeSlHVXErpBlsu0NeJXYQmsmbk +TKVQPxRgjA3HBtIixtxMLASIQBgxkAhqo5668YBBC1Qt5XJ4ODcbzuyfI4aqdb11facK4cAMM2gx +EHZ3ds6dmRohhMht03W6NT1jhD4dzhffbrdeJwpEBAKL1LaqLCyhBlJq93+uB/6yenFZuFZorEeA +rd9q9bZfz+7du3e/9ryxB8ADogm8flgF7t27d/9oehqX/jYm/4wN1urxC1HteF//zyxCwlSLVUEk +wk3DzSRRWOZy1Ma9kuj82XbaxtRb34kpQgMtdcFKKRsRCIDWs3CMC2KBCJgIhnGfUccOBMQIU8SA +aStty9NJ2Nvf2t7ipgWJ9YMeHJZlZ7kmyityxnyO5VKXS0vZiMwUKelyoUXRthBCLjWTBmAYMCSt +m40y5kAhK9SgOjbuvHP3cDqdXHxsPw2YTiIBpWRdd+IxBJ4MQ686tDFSEJAu5rh7eDME2d4ilRt3 +D77fTpIIBREmEhEQxp6rteRi9TWHEJhpLLEeB4ExbUxrrvuB+v3y69m9e/fu136zdEA/9JF8z4fc +u3fv/hHytQK43lHPmOtin4mIQYx6KD0eTdctwTinlkIIRFYSz5qP7M4+xpDl8hrJcGZ/WxXQ1koU +RhiXuI2aaYESah2XFaLxTyYFjKFqQ7acaiN8Aeo5OYgBQWjq9KwiYTGZ6fYWJlNIgBr6DnlASZQH +skyR2BQKpIQ0IBeUgjpqIIZ6bk8MEg5FaVBkgxopSG0MRNRfxZAVpdR5wIdbs10O6FM2mKqVnDXX +LkpBeJZzTrk0bdu2O9PJ9mQLR8shJzMl6CHCOxcvXyUaOycRKIis91W1nJpXLZWYGYAQg7Ba7kN4 +/f0dXzW/nt27d+9+02+GBvgk0gfvIdy7d+/+0fTjUvJkd/l6f90H1KAAapNKrkWpRDAjkiHZ/ObT +j599iXUH6HZ2sbe3tZwPEbMmsGnSbGxbOVvJWsbUGhDBQHWRrVpKQU5QG5sC1adnqmVeWDUMTWYD +QUOwENG0NGlo2tL2jNoGUOo6W8x1MUe3tDSgJNNipoiMScNNJCHSLDmTFtbSDj31vZWEUpALckIp +MIOBUOsQCGZgRttgsTxKuTuzv5Wy1aykUuonD2hI2VQ5KxbdkaJrmt22lZKQBgjtNmFnSG8cLa4S +jzOW63l/Lfwd1/11+u+4BahF2Mdjf1en/4KTaa9+Pbt379792t87N3idIXT6was2ou7du3f/yPra +Fod5veKvXThRz6rHdX89rSZe5QTV1SrVh/EMP3Px7E8HwvkzU9O+5AV4AT4oxUpWK1pyru131rMd +VTUlKGCG1S5jtdglIxRQbdYDYdTjbyKQGDGCIDCaiOmEtrZob6/Z35+c2Zvu7TXbWxzEmoDphLZn +NJlSjFRUmSgKqSZoIVLTXjWbkilKwtBZGqwUaP1lMIyfLRlSQiladDmbTNp2nMqrClOYsqpoBhEb +0A+2WB71ac5BJGAYrAwNrC14pxveCzLGUoSFZYytjIf+REECEbgWZ8uY61MX/MIb5XCwMV/Lr2f3 +7t273/DHKUDr0MCpncTmgzdThty7d+/+0fO07qhAqyyg4/U4AYSa+UN1rUpMzGMUYOxsCZB85Mm/ ++Pwz/9L+zmNNjLOpguapKDPaydRM10XGQaiJbDWRJQBA3WbU4/ZS6pbAUD9JMgOywoAQwAH1HwUm +BKnhAgtsQRJTJ7LcmqXtnTKdYjrF1oSaSIEgMCEwKUNjQAgQMhEzszRY1+Hg0A4ObbHA0CEnWu8E +6kp7KBBGKci5m23tBKFiMMCs/mIrnEvquiSESYuUtOsPAN6azaxQtxxSNshNaW5u72XmWNf79Qsf +M/+Fx/5LtfhaZNxzEbHQiWyfMShAGGu4/Xp27969+9HzvaGBzf5B9zQWhXv37t0/ov64lBWr3PKN +fcD6bdWNHjZ+XITNjACQ1S3C4s6Fpy/8W9vTHyPE0EQ1MqAAQy7GbSmWFUpQWFZLiqy1A08E2MZP +Zlzc15UtkTJDeJwIRjyGAmIDDkAABZAAAo7gBhxgjGJopyBBNstqCoNAGmRDNpiRWaNGuUANWS0n +OrzDb7yGN17D4vBM3zc100YVWTEMEELbEoC+TzkvmFkLiMACYpBAKZnNQTb0kMAAFotsWgAJjSgv +OCSRLeWrKd82GIgMEBZmNhitwinr134VbRm/UavbxHTi+7VK2fLr2b179+7HFKATWUCnbqxSKjc7 +B7l37979I+l5nQWE1bIf6yT/Ey2BQDx+7HhrUEsDmBkKIpCe19zM54fLrut7y4o+YzEMg2q2ogRm +KJCKGepUXVhBybneWOUCrTLfNz+f+pUIgoyfc/2zJSBEgMAMCbW0ALFhNbCgaQlAKiBCCBChVDCk +TAim474iDbQ8it/4Bt54w669f5i6oIXVoDb+ocJQtVoh3Q2HIlSzgwBSQyllSF1WbVsyIA8mjJKt +6zKIJtNtDpp1bjYxvHXu0nenE9ROSquaiuMNlqxiLOs92Im8nxoR4VOhAL+e3bt37370fGo22DqR +aPPp7t1DuHfv3v2j5ze7fp5oNV9X3bzK9qlN6kXGTkAgYql9Ow0EEW4a2Xnse0fdG2pdyTpm8dT5 +X7GrZ/F1IVsKVOtxPhmK2biUr83460Sw1cqYxr/wacwRWu8Kjt/WzfsBIgQeE40IUDOqewajklCy +iRhYjRIztJDmJoZzb77TP3mFQXT9dh7SckjZFDXRRgTAcRMhAosAhqw1TwmqVhuGxiASKGcTYQno +eiuaRIKBum4xpMM+3TW7LQJT1CQfAMKyyqoawyzjaz7uq0hWhRm1KgCQ0xsDv57du3fvHmO89N46 +4PuWFZ+ILLh37979I+U32/7UIAAfp/+cGAZQJ1jVabRVrBL364rd1BQod4++z3xoYFgkAQimoWQq +OozJPOMBN5jGul61Oup2POavs3JVDahlAiYBzOOHauktxrjDKlkIJ7cEBFWLsQVRLmBBE5GyMXFR +5IwoMKBP6LswbZ7+3vfuHh3i6Sd3zp0lwHJWU9RhZHUOgAGpjC+naqqftinWE7uYIIJcFAoQDBYj +EdB1/WJ5J6eUi/XDMqVFn+4alZOZP+MQANgqDiBS07FoFf4YwSpHa7X6N7+e3bt3737Tn94obLoP +KSZw7969+0fKr3JIrKac1/XlauqXbJ6yr5JhxvXo8Z6hJgYRCbPacLB4HXy35B6IBGYBrIURCCEQ +E9f1NNWTdYPVNx1X27oKEYwbE4Pq8TSu+qj6wHWgoDIRhEDC9QYApNwHpjZCC7oexACrGtomApI6 +NGHaxvMvv/zB99/of+LzF7f3pnu7euYMWEAUah9OWxX7kkENWgAIQLxKQ1K1nC1nkCAlhUFEUjIz +xIbUtO+HYuDAAIEH09tAHrdTAItg9U7943gcDEAix32R1tu0Vbx7rNXY3L/59ezevXv3x+7kZuBB +0QS4d+/e/SPodXXqv15fEpHWMt/VECoCrTrTk8GYGSBmghnXA3AaE9LPXPpguXwPOCja5TRoMc2o +R/tBwMJqlrLlvOqfA6o3sGp1X0/3bX2cT+PD15/eeATOp9+towNA4zOoWsqm0PGZAeGxo3+MSEkJ ++6JPvfzyrS9/4/Czn57s7cfYHLVbtLuPGMEMVdICEJq42q6Mz9Ou/+jxl4IIpSApiBlgEFKyIVsI +IcZGRAhQGAvm/btXnr66Luk1NVq/1kwh8OYA5lUn0DpzGfdEANbfOL+e3bt3757xIUXAp7YRGx91 +7969+0fOM9E6k4SpTgUel5WmAIGJakN8rDKBcKIpTZ0iTDAzo4P5W4a5kTJb0b5oTRRCbCACVa2H +/UxjB33AckZOUK2N9tdTwI5Pu9fn4ITV9kABjOlDa1yjBKpj0MAMTYQaUgIMUaCFJIAFtw4SMSbN +5W987epvfbn7/Av03LOXsn3AzdGZs5jNEGL90wUAreIVhLovQtFUW5OaotTlOxACmdbpAaYFUCpW +E/1j0+4INyVbyqa66NO1Lt2oK36gVgIQsBqzABy/2uMXSFiPaMaYQOXXs3v37t3f15/ePVCdO38y +f+hUEMG9e/fuHynPY58ZxkYz0LEIlWhj0bk6aN5oTUOrk3Uea4T54uVu0X+/626kXMwAGCME3pVQ +iLQkpGRq4zE8bMz2GWt/merS/3hZj9XZ/3FBwpj2wzLmI9nq2ZixTo1hGZ+k1hOPO4ciZrxcwhQ7 +0wnb/pe//NYXf+32J57l5z+yNej7sSlNAwoWGzQtiJVJal/OnMaq5VWMIpWiaiBebUgIWqyu5FOp +XyJq+lTfDSl1pZSc60xiJc59ujWu8OsLsfpG8HH577q90vgNGvc867DIcRaQX8/u3bt3f+z53t0D +NlKFTkUN7mkj6t69e/c/+r7m/4wNQHnsLWOGzQaUPC5F+URXynXSD8jUlAwwC+93+Z1cBitUtC5T +Q5TdkrtuQCp1IQ4da2dBhJJrLS+BECMTUMoqILE+5zYwQ+REHfA4NtiO4dgAdNUOSBW5wMZnE7AW +KwxQeaw/ev73v8G/9KtHzz7DX/jJC9MtJu4lIjYUBE1LIghRi3WmFgIzQQ0gaxrSAihUUcpxZ1Jh +DAl9byVj9dozgcyw7Eu3WKiNX5YZCLnoEZFR/QLW3VVX/9k85h8LH4hYiInGAgkzYpLjMgy/nt27 +d+/+ZARg3Cscv+lq2uX984fcu3fv/tHxq2LfdffPsbfPelW9ykWvS39bHU6Pj1MzIrCwEIj4+s13 +il0XjiwTVYhQiG2ILQUihjDT6gjbzDZLfmsdbU10WdcDjOtfADSevtPGPNwxBX98Z0zBr9GAOl5A +BExgIcLUVOpaXfjCMH/6rde2f+s3bjx5ET/7Umy37oAOJZAwYsSkJWFIQBACGQjCshrFhRgDMzhM +VGvj09rMtL4syAVllYaUs/ZJS4EpioFICCgZKRdiSmleD7GYmIkxfm6MVRugMT5AJFxrAwBAjYTp +xNJfza9n9+7du9/069rhU3uIEw++3ybDvXv37h85vzkFDKtKUz5O+MG47h8PpE/k6BOghq1dNXp3 +0b3ZDYe5hxUuxUrp+uFOycYEVSPiICwyPknN0mGurXXGDJexrndV2jtuGHTsBbTR+nOdngQmNkXK +IFrtKwpExrW4WTETwp7Yk8s7T969uf87X3klBvzsH3t8upWyDSQQQSkGpRipRhKIlRnMZlZonHQA +MmMBrKRBmWC19sDM1ETQNpAALRhyUrOmDSFSKsjF1CyEQAEGaDHV7tylOY1D1ei4AhtMx9utdcHF ++NLwRur/uPQ/HQTw69m9e/ePumeie/sHnYomnCgudu/evftHzetxHjmtT9yJiZlsI9d/I/nnxLs0 +nskbQ4Z8oLhrdhcow5AJTUnIuV/Mb9aBXzlbP+T6Z+jq9J6ZVGFACKyqJdvm0f/6sF/CiaT/WnJc +9x5jQ1ICr9ry1EnAeV1SHAa1oZ9fXNz+zPzWR3/36z+4s7j1R3/mzOUnhKmNAUEAIARhnmmJwkwE +NYQAImTTccwY0PWZWUpJKZsBusoC6pOVjKJIA1KGKpg5hlZEap1AySohtDEAMFWgTLcOcVxHYXzc ++GesDTCz4/kL65d+3QRjHM+83qf59ezevXv3q3fWFQMf+ki+50Pu3bt3/0h4JtqMAGAjArBOSl+v +9evKfyzMHQsFiJnMSARGb8+77xOHAs3aGJ0n3jIyYy2GEKfT9hwh1gHANfnHDKXYmExPZqalHrQz +jhfDRgQS5nWlLxmIGNaoMQQG46CKsWEoDDljbMVJsBI4X2rLz/DwU4fXL7/8rffe++C1n/3ZMx// +lPT5nRCSgKzAgLYJMTKQCLZKzkftMDF2AarhDwhRVAXT2P1zrNVlIl6VHRuGQQ8O58OQowCErteU +koHNOJdCfDj0d2VsYFTbqo7bACaueVY8zksDERgnmrTW0cjr0gy/nt27d+9+7TdDA3wS6YP3EO7d +u3f/SPmTEYDjNvObB/DjHqC2+xy7Um7EEIgoNkPY+d15enlQJdlq2ieOFqXofog7GWgavnWjfP/V +Pg9bjG2hRlhqP341SECIKGqmCIIgEIIwGCANrBO2UI/gycCEEEAIQxEzMSAD9cs2Qi4gYwLH0FhB +6aItP7off+FM+2dbfeHNH1x95bVf//znt597PsJuhgZFC4mRoIkwGhSHsTESG5sRKUFpVRUNGIIE +qJi2pUBrG9CMrGgaCoK+w5CwmGO+QMrH+ykDiI04EreqYioU7uZ8w8zUlMYBC1yLDUh41V51ff7P +OJV0BawbXax7N/n17N69e/c41RXoZIbQ6Qev24i6d+/e/SPmNyMAul5h1jEAx2vQVXEwMU6vRAlm +OuR05+C1IR1qmQS6/Mp33/0b/+V7X/rqLcI5lJ27t6Z/9+/1f/2/PPzu9+6AtPa9zKmmAI0de8aZ +AwxGRJlYYi1QJIQOlLWoluM/lnhQLKVJwrCCrgMytSGGwBwZKml5jocXd+hff/rCX9ppPw+dvvr6 +119/+7//o3/s4sd/7HHIHSVIGE/xx1jDySJjoMYaDDAiKJCAIec42ZkvF8NgQ0IBCpASjhZ2OLc0 +QLPUeImmcT9QhwcTkUG65SINWZhLXhgGIhaR2klp/K3uro6H/hKt2i/VKWzHRRo6bt6Ix1lofj27 +d+/ePaDHKUD3HSl86sGbKUPu3bt3/+h5IpJ1yS9OnF+fjAicjAwAYJHQzJf9jZQzdPvW9eXvv3x4 +6xZ+8MZyWDbb0+defnneH8mVM+21qyBmDgxQVhhgejxMt8YftHbtpAaojXhgbCQgOQZFUSfrwiBg +zWCCZvRL9IvzNHxmO/zspb1/+cnzfyGUT3eL2be+89VvfOf/8+KP73z6M2fa7ZugBIMQsURiYQbz +OJhrlc+z2gysmw4JhOvLFA8O+6IwtZwoDRgGDB36Af0SQ4eckRMPCcsljubIiWIMw2B3D+YpFRFW +pKJ90QQYFIbVJODVq8oCYhKRVZUw1oBorMxmkRMdkfx6du/evfvxWAkPGiJwOqywuu3evXv3j6I/ +VXO7Xogev2tGq2Py9aTaMS9IAWDr7PeLzXdmF4vKrVt3Jg0++2k8fYVT1hs33l/O7ekrF5668tT2 +jjERjwMH6t/rY1GBBDDX9X3KNDfpSWbAnpZYRwoYwxgFyCXmoQkCy7DSBNpCQWBOvXD6yLnJn/rE +U//ex5/8N89v/9E7N9qb1+df/p1f+8rv/hc/8VPnX/j8duZXit00BsuYTC8MZiMyqXcKqOb/0PHr +UUsLRCAs86Pl3QPNGd0S8yNbzqnvWHNruTVt0xCODuzO7XI0t5TNFLlQKpYKhKiZTqaz7dr4qA74 +AtfggNGq7yeRrccBEBHXDqs0DgMeJzSva7VpnQLk17N79+7djylA9x8dvGoUunmb15sM9+7du390 +fO0CxFQb8I+3MU5ZObE/GFth2iozZWM0L4Dbd24uF8tlNxcO2ztbZ86QAZcf58m0J7l+6TKa2bU4 +efvJK5LLkNIypWSGlMAEZlhZJ3iO6e4GUz0yOgCncd7XujcoJeGsw0QwsZw0oSzPhf7nHt/5D158 +/n//+U/+u09c+iOz9koa+K2rv/urX/lPX3nrr//cn/rkk8+2R93boTFjhAgONcdpYFEeT9rHZj/r +ut7N+EeNUWjGnTt35nP0S3RLWi6o6ygPbd/Ho8P8wdXh3feHazfs8NByAjE3TUMsaShMaCcRQNcf +FMtqPWp1M1Crfuv4yjEOMx7yM5GBUPOCWIiI1NZDwcalPwsDYBK/nt27d+8eQDBTIj65XdCNAgK+ +dw/h3r1794+Or6tGOs7mX6X0HDeZGQ/9ichMx4lUtg4XjHsGM/TpwIxgvL293U5u7p/F+UvhsUvn +C27E1rb2AdY22mMXd0s5NDPAmMez9qIoCjWIrEIPhGIGtrpKNoMWsBwfyQuHstxJNlOLk/Z5HraJ +P/WZH/+Lk/YMwPP53YPDq9977Wu/972/KrM3/sRPf4LCu73enm2hTwgBugojk4F4bCcKOt7SHKfa +0/hqmiIZYOHuQZd6JIVp3SdY7lOx7miuRTGdIESatBQjiKjrUzabtnU+gJqVrNr1d4NsWSxYdWHi +VbBlo+6Xx+P/cejaOHmNCUpMpDUCYGUsAyhF7zke8+vfvXv3j6IP64ShjXt587lWd+qpBCP37t27 +f0Q8MWlRDrw6+183mcE9b6ty4fGw3FSVIGaAWcl9kNlQbt2+82qIR88+fxaQVO5mXTLj/Hna30Xb +MuHQTGvSS+18WWtZicYGmqqAohAXLSIQhhGIkBQlIQgxJn03LAeehSd3pp9+7MwXnrz0Ezdv9N/4 ++rcFZ1NvWZfvf/Dmb3/1f3jt7S8++8lbFx9vgNeHNLQtsoJ4LDaQGiSu6/t171HAAGGshxHnjCAA +0ZCMadL3dOu2DQM0oxSYGjHUkipixO4eNYFChDSkgKoVM1GQcNOEYRiSYXcqIlLUSim1xmAMvKz6 +/hCTsDARM8Fq4XX9p+94CsNqt8Y0VlSjTmX269m9e/fuw6mNwqY7+Vy8+Xj37t27f0R8ratlYSIy +NXBd9x/X+xKR4XSlAI/9QO24JQ2slJRzZxj6IZFgMtXUa58zjI2sjTSJVHSw+gZbNbE8Hu5rCtTk +ezNQaWrjnQQYJEAMTDvDYrtfntuePH/54o9fPPPC4xefnbR7zNvnduOr3736ve+9fv7i7Hvf/9LX +vvm3jN9/4XO70/1YcDAkQGBWz/etbnOsViCMAQagFo4B9QsuBYFQrCYFhcUil8wi8b13DoYFUkIa +IIxhMDU0LabT1am/gMhUbcimhtZAoJLNEDkiaNZipRi3AkCYc13iU4GBmMfm/zXth0iEx7wg4fGj +vO7/SURkoHu6Yvv17969+0fah7U7Hp1I/OBoAty7d+/+0fPjRF0aC3NXiT+rzB/amANQT8h1XHGS +6nELelPNeWGS63iv+fJO38OItqdn+2Gx7LoYhEjr+no9akB1rACuk3dLBhFiBBPSACGKPCk52DBd +dpzm21uTT7/w3M9dufTZc3vPTcIeDEBOuWRNsxn/D//gv3jsir5744uXr9ilx3cK3ln2N8EQIaY2 +lxQEwkX1OL5BFImyqa6+uHEwl6la4EChz3mxyCmhac7fvHn7+nWUhECkGYdLiwFbWzSbSTMxiUoM +XiUR8aqjUMq4e9dU57NZE2JrKGpiJmrrUcpWG4Ay82qgGI+p/8y1NROvGoLWtCsmMqGiICYxKmqA +1SCAX//u3bt/xP0Di4A3thHYTDBy7969+0fH8yq7XHgssqXjbpIk679Rx7Yzto4BMKj2AaLxfjOD +AuCiiiATgQwd2mY6aVqiYpZhIDSqsRYdj30/DTAUPZEFJAIodCAh1tIe3MbBzb3FrY9fff2jr37z +yoWtX/jcJ/+1S2dfjDIzOTIZjhZ653b69ne+9b03f+Xa0X+V43//ic/2F568fTB8q/D7k6kwE1Fs +4iyGqFbMQALm9R6gEB0PQ7OCUsZ636G3lNAtte8Rw+7h3e6dtwcySj1Sz/M55gsEptlsu5kEYmM2 +YiNBEKLax5MoJcvFQDg8wrVrw91bndkkylbKQ85lLHgQWR/5A3UnUCcfc919yXjwzyzEQsJjA1Cm +0wlafv27d+/efTi1e6Ca+3kyf+hUEMG9e/fuHwUvLGomxxn/4+qzVgWs2uDUjPRxBNUYKVivNsel +/7gRmE62F4W0xGFJsK1S5qZm3M/7LmWECAlD7rLJ8dl/vTHW+FrtRFQz8puS4+JQ+u7CNPzYc1d+ +6qnLP/7eu3f/3t/9B7evl36h01nWol0ni8Xt6zff+OZ3fvWVN39pe+/aT/8L59vtw2W6ng3tFCD0 +uYRAIqlLt7PZ9oSLIRdlhioMYC7rFvyqpoZcUKC5IGcreUiDxYYWR/M33yyHB5hOAaMuoesQGKEJ +gOU8xFbX43qVjGGqyKAgTGRpMBYSxqKz998/GPaOLl9+fjqZLY7GTVc9+8dxJ9CxIIBFRGoO0Fgg +IESZiJnVtJ73ExkRwDA1v/7du3fvPmzuBsaHbaQKnYoabKYZuXfv3v2PsBcWACJ10W9EbAoJYFmn +mtR0EyLQqjPm2IFebewcOqYIgczUDJP2yvI6h2aSh65pz4lyt7xDESEgBpSCPiUSqgk/NQuoZquE +GiPIEG4sS+qz9XtUntybfuLKkz95bv8TW5PHt2dn97fKqx+5+uYbb7zxxitPP/PU9Zs3bt66+f03 +vvL2tV8t8vtPfLTs7OS+HM07ixFQcKwdNgEzNUhAI1BoySAB2fG0r1U4g8xQillBn5EzmkjLXgG2 +Et58c7h5C7MplguDUik6maAYlazdsJiwwZAzwGCzwKxMgUFgJa0v5xjxQFTLV2/ocnjzmYsfTIkU +OtYeMPN6mb/KCBJhGER4nf9vdFwHHERyURu3Yf7vnXv37t3DTOXipeeO9wrHb+stAm08HW1Us7l3 +7979j6yvq39iAiC8ajLDwky190wIIkFEREKQIDEGCSGGEGOQwE0TYoxBJIQgIsQsgUUk4lK7dXTr +zncnk11k6fshxsZ0CIyUAIYqNJOYMHHJNmkoJ5hCC5HtcHk8zc+n7gqGZ89u/+mnzv9rT1z84ztb +z4vsqoX58ohFU+m+8jtflsB37y5/79tf/PZb/5c7/d+5cHm4/PiE5G4qcyK0ATBw7eSjACE2gQha +TAQoYB4LjtnAABQEMhNVSQlpoKLoBisFJROoGbrp++/112+YMCyjZCplHFsWA5nVImLrh1UTUSMy +IWtNp4TGLAsb2JipFCQFhZigGbpIbzbyWIvnixaYabFSSs7JDCWrllKK5pTUTIuWosWKFlWFmtYW +TKpW1tULNqZRbdZw+/Xv3r37R9DLYxefWQe11x849ZfjeqLNvcC9e/fuf8R87TdPTKY29puh2myG +mIWYQgxMLEFEOIQQgoQQYgh1PxBjDEHG1X8QFol1HyAcpb186amm2bt584OjozvbO9M+307Zio79 ++4VgZSunAWYw6jpjTKzsDYszpXv86jtR9BPPPfGnLp/7o08+9lONXIJN+j6nIfdDv1gulsvDu4dX +v/29X//uG1+8dfRVar97/srVsxeZ4yLZHQnZYCDU9HgjkBEwThcuRQkUJJasJGOXT1MYg5SKhpSs +67IW5Gxdb0LUJ8yPjHR24/rynXdKkDFkEYSCUBOlbRqiQjSWNNT5ZUWRE3LWUoqVrJa1kFksGbmA +OTJLzjk0XNSGtDiYvyNhNpPnzLSUUouq62pfi5aSS9ZcSlEtJZdiqlqKqqoWK0UN9fR/DMKMk9r8 ++nfv3v2j7eXipedXCPduEdZVU/VhWE26ce/evfsfVc+r85JaYbquOhVhFhZmHs/9OTQxiIQYYpC6 +8A8h1PV/iEFqkCBITVKv/dfScn93+qmnnvnIub3nQjsN3JQSoFvdPOowycNusKcDnbd0dhKet/T4 +TvvZKX/6/O4fRXr2lZeX1l/5yc/9guWzi0VOaZHSIpXlcnn3zp0bV6+/9e1Xfvt7r31xwNee/djh +859cnrt0ZDIQg6gUG4ppbFBT4dfzvNTAAqsFYwQmyWPiP5WCosiZcua+LzCkZAeHZgYt1PcwY7bm +7beXt29qbLh2/WcCj6O6DKQEk0DEiAHbu2EyES02PrNaP+jhkS4WOixKSZOSuB9SKaXWTE+aPYKo +3Rz6a+1kJ+JpLUVNVTXnoqqllJy0qI7r/6L1TjW1okXHfqqmtiqrHgcDm1//7t27f7R92KwYMLu3 +jOC4b+h6B+HevXv3P5KeiWrX/7HQltaVpXUBTwCxiDCzMEvgujHgdZ/Kdbkq2aozUB0SbKu/jksp +80Nphx+fhR9/7LHFL377rz/zzCcuX/rY9et3mzbdunv9vXffe+6ZzwpPAkeDNGEi0go3e8381lMX +v/vKq++/f3NvZ/fw6AZJv1j28/nBzVsf3LrzxjL9QOX1i1fwzHmbbheiG0e9tg2rgtmaYCAIo2Cd +GgpTMI+1xSJQRdFCHA3ISXMpWqhkKsWGwbSoENpAxtACAP3Cbt8ZSjEQus6aQEEoBA6BiMACZk25 +dp2GGmDIxUSY2UBmZCkBCaXg2m2DLaZTmJIEm0xx9jFZHh3u7XJsUuFX7hx96bErL9y42tZZYKtK +AJbAnFiOW4OO1cFWbzOhgJjICExsakym5te/e/fuH3EfNkIDfDzX3bT+K3a/R7p37979j7JftZgZ +V/8Ac+0DShRExmFTIJZxvVnvGGMDXEtqV38ece3FpqWoCMaWQJZyMgtv/uD911595913u7/87/3Z +/dn24dHty+fl6OZXol25cvHJlApRtAIzEIvNDh87f+Nbv/+tl7/19U9+8mPvXn3tYPHuzdvv3jl8 +E3Rz/2x64um4u492Os86FEMQTFsU0xCQMoKgiegGiNStCkBjR/+xyxBgBM2AUQFy0lKoFBuy5QxT +G5YIjEmkYcHMW2yR0ZnNmWk6gx3ZkIxBxUrOYEYzATPaBgbUkoDFIgvDjIJQiMQBTbQggKENFALf +vl3efMeg6DK29vJP/wS1MyMg8t6VK58wnYmYGpkZ86oVaA3U1EhLlvWkYGEpXISpEBnXcWWrQzEG +q+iqralf/+7du38EvVy89NxmyGAjQ2gzdmCrOxUg9+7du//R8/UvSADrzB9iEAXhVbcZrilAYazo +rSW+QUKtAAghBBmzgJqa+xNEWCSIjPlDtVslM8HATFdvffPND37p977zm/PDg0987DNtO2WetnH3 ++vX3nrhyXrUEHrvYa14C3Xxx9ftvfO3l7/xKlz944/2v3p5/K7bvPPFMeuYjw2NPHOzsHkKWhiKM +tsEwQAQSaEhoWzChH9CGsaOoMAioI8okoChygSmpcU7UD3kYbEjWZfQDlh1yggCT2Az9uScv/tzP +/JH/2fbWkzdu3hyGm4slUjYiaEF9GQ0AmTBYQERqaOLY1bSJXKMBZqwFpsaMyRTthHZ3w8ULlz7y +zDOTZnL1+t0XPxOvPGmz1lref/zcnz0T/9zR3cZMS63zNdRsn5JLUR3LAEoZE39U1dTUUlYzVTMC +SlEijGPZxjIAv/7du3f/iHq5eOk5GkfYjOUCJx+PkzUEtM4rcu/evfsfGc+1r+eq4tdgIgwIEURk +nfovzCFyzfuvhb0xyupGCCGwcIxRhGtNcAhhtfInERknihEzGbOYfJD55XZ67ZUf/O7rb35rMm2n +7fTMmfO3bt3pluXy40/mYsSk1M276+9e/dbvf+8fXL3zm5Pdd2e7H1x6qn/iGVy8ovvnFrG9Q5JJ +jBkiYCbTsf+oERRjK0/m9Syv2qiUQKwGVZgiJwwdhoShK91guWA+xzCgJECJlcTi5XP/wosf/Suf +//i/f2by6ccvfHZrv33r7dfmyzumAFEqaAITs5rp6oBdwtjfs1YGa4FEENe6YCERMysFANrGtmaT +EIWke+bZ/NyzTdMMwc49fu7PnZ/8G/18G6SqMDUtaqpFa1GwlVxyXfuXomNlsNYSgVqUXLcDGBNk +YbbaBvj17969+0fVh/Xo4HuzhXD/xqLu3bt3/6Pm1YxX/f659vcHE9VZv6ucIIIIC7NIkI2ggEgt +C2BmEqlTdem48XydDKCr2b5qJABYTc+f/9jerYtPPfXdnb3h+rXf+m9/8R9e2PvCk5f+yOHhMJ8v +7nZ/VLV0/fz27fffevflefcG5Oqzn7Dz58+1M+VwCzwww3iV0lP/CaDa8wbMVGtpm1iXvDCrGf+s +xUzJjOpwsb43IpSMvrea3L9YAoRckDoKgjRgd/rY5z/155+78qfOzD4HQylAmX3i8p/nl+hv/f3/ +2+Hi2t0Da4N0y5LrSIRaRMHgZMyIgZgFQLbCgJmlbCImaFQlCLWNpazvXr3W9dfOnsXjlzjGIdCZ +5y7/xbPhX+nnu0SDGdVdRS2x4HEE2yr7avyGyDovy1bZTUxUQIARw8rmuAbz69+9e/ePpg+nZoOd +urEaRrM5PsC9e/fuf6T8uuv/mPN/fHtM/SeSEJhotdKUutDnILyaP1UHhtFqVjATsciq0hZgYVvV +AhdVZoZpXpz99Ef/zO9+73qy7+zuhdu3jlS/9spbXysGNfvvvvg3ZtPJkPuSbHefd85j/8yknRSS +uQIgkMAYpQBgGAlZCGbrWcQWxZAxwACDFqhCiaAhq1lBKVoUWqxLqGv6oUMppopSoAXIJGjSonn+ +2Z/+2NP/4qee/3lL+yVnjElEvFim6zfvgJpGtpvYAbFplkNnURAEplCFFtJsqlZKkUAxiJZch9YT +mdkQY6sl3L7ZDUW3tvHsc7S3B4VNI66c/7kLk3+zO9gyS0AgpHUvCxHJOdexYMDYsGkczcbjL+Gg +Ysi1WJjMUIxqFUbt8erXv3v37h9ZT5/+zEsnSwew3kPc9+2eUgP37t27f7g9rxf+QBCuhb/CYBaq +q/wxmZ9XTT9DkBCaEEViDLGJMcamaWoP0LZt2iaGEJs2xhhjHIeCxRhEJMZIRDEGZhah6Q7f6X/p +5e/+vcXwLoXbKavmnWV/nQNCmCy6ro1RRJoYFb3a0DTcNg0HNhRQEc4cDIAwalWvak3Ct/FvfkCN +TAFQKVYSTDkXK5ly0ZRNsw0ZqQAFRNCEOt5LEMogF899/mPP/dTnPvFvTZuz4yJe6maJ37v7lV/5 +h3/ju69/8fBwub3Fs9ne4eFcbVj2dWYwtIAYswnVfPsQ0DRoI2ezotZEzGYEotu3bdnZ9gxXHm/P +PRZjO48ttrcx4bNPnPkrcvSv5py1aC5acs655Jz7vk8p9/0wpKHrhqHvl93QLbu+77u+77q+64e+ +64eU0pD6PuVc6v9SyoCN7UHH3qB+/bt37/5R9HLx0vM40SUU9wwROC4muCfByL179+4fbr/K/KEx +4YcItqr6DSJMEsaEn7Hnf035iRKYQwy1AiCGIMIhSC0A4FXdgKyy/+sYgbHGgHk8qmYumXemH3nq +qSt9f3T11rcmrYKHgjydyVCGpsFkxn3qICnGEkPt2Q8YzMQKQHXQ1fiVmRJQl/tssNp+RwtyQSnI +CX1n/WBdb31nfY++t35ASkgJOSMn5AQUKonO7nz0uSf/2B//yX/3k8/+AtlM1XQVXMg4+Ob3/7+/ +8eW/evXGl7Z2hNiWg3ZDv7U1IaQgY6KOMJlRzsaGEEiEjFDMYNTGIGyHc5svrJngyhX6yHN7O3vB +cLS/fyGKXP9gOLhjz17+E7p8rqbsm6qZqaF2+x/HAWidCZDr7K+xDGAcEaamVsahAGNVsNVv/Ik6 +YP95ce/e/aPo5eKl51YPG+9auw8pJnDv3r37Hw3PxMRsarWdJ3HNVrcQhIiYQ034qZ1/JHAt/o21 +BxCzrBb9QUKQWgQcxgLhdW3A2JOeCcxCwgyCMJvBoJq5lSvnLzw/2zm6destRc/EBRTYolAINm0l +a1GzGEFsRdWQgQzKpqYFJSNlaIECalbLD1QpZ+o7lIJS0HXWddYPyANKoiFbTpQHGsYjfwBIiTTR +1uT8j330T3zhU//OZz/5F7aaj5QMG6doEYhKeO3L3/yPv/r7/wni1cm2KsqkDVvbcvN2vn5z2N2i +rdk0pZwSInMpMAUxajcjFooizNwPOJobMc6e5aeflLPnzbifzIYL557qFvbqK7fffdsWR/noLl16 +7OPb0wvDkFTrF6VqCkMeh/1azlnNchongZV1M6CipZSsY08g1VVRBo1pQLDaoch/Xty7d/8oenrh +xZceFCC4XzThwwIK7t27d//QeV41/+FaM8qhhgIkCBOt+vjU5j912K+EGOLYCCjEGJsYQhwHAccg +McbYxNoXKMYQQ4gxisi6LVCtGRBhCYEIqw5D1EyXtw9ee/fGr9xZ/PJhd7UVS0pFbX9//2h+OJQs +MrbTUYJqTftZBXMFALIhEBQoGWYgQyoCUlVd9kgJBGihbg5hKcW6XkmQBptOkAtaaj/2zJ/89Ef+ +5cvnX4y0X0uZj7tGmC3sW7/5jf/4zQ9+dWeP+6WShFTy4RFY1YbHf+wjf+bu4cuvvv5V6KxbLIis +GwoxJJowBQEoqFqxHCJ2d3Dp0vbufgO+w8G2t3gy2795I7/6yt00YDZprWSzcvHCZz/7Y3/qfPun +F4eSNZekKaeUchpSynkYUt/3fU376YbVjb7vh+WySykPQxrSkFMehlRUyzhAeLUdWEUF/OfFvXv3 +j5o/nQL0oG3Eqadw7969+x8Bz2P3/3XrT6kfEa6BgRAC19yeVfYPi0gIXPsAxdVdQeqRfwhRQu0W +GkKtGF7FAAgEZiZa1ayuR4WN1aumuW3DpQu7f2Q62zm3f25x1JcyaMlH887MiJAzmRETilrJSAVa +qI7XHRJSghXkjCEhJ2hBUR566gdLyUpBGpATug4EXi71aKGzWdRCs2a2t33hyYs/8TNf+F/85Mf/ +l2e2P8o0NSsA6rm7mTJTb9/9rd/9T9668St7ZzD0gM2EtpZdN4l7T1744z/3hf/oxY/+wuUzn33v +vdcXRzdFsiIzIUbsbm23TXs0H44WJTR67jw9cYWeeGJvNjPD4WzK+3tnmrD7vVevv/GDjgkEnk4e +09LzVJNee+2N3yrW7c8+jSJmxYzMTMemn1ZWb1p0dfxf369pQaZ1xa9WSv1ayGxsArpqBuo/L+7d +u3/k/GYKEAAlYpjiZP7QqSCCe/fu3f9o+LUkorF/J60HfrEEAbiu5GWd1BM48Dj8S2Td7F+CkASp +zX/qxIBVCtA4LHjVL2isBMCq3dCqDoENCoCZt5pPPnb+0237VBP2F8uDrrtNDBGeNTswmS+SZjLj +vrc0YMjICWndyadH6sd7crIuabe0fkDqkRJKBoz6wZpAbSshhOmkmR+ppsdf+sn/8NnHfp4oqqpa +Abi+MGYKkPKNb3z3r735wd85tx+PDjPKXulnR3fTY/uf++xH/vJPvfCXtporpehksv/45c9du/nK +7aPXwwQSEBvM5+nu3UEau/Q4X7yCx843O3tbJB2FfmdnMpudvX1bf+/3rt26BjIiYDaj5fJgOg2a +gRJ2treu3X6jy0dntz4OtGlIdQNQV/irtP9yvB9Yv1e0FM2laM2LGg/9rWYAAUYg858X9+7dP5J+ +3ACcCBBsbB3GPCG6TxmBe/fu3T/Uflz6n+j+KXXuLxEHCcwUxtQd5rHSV2IYj/tDYGau+f7ENEJh +CaEu9EVkbEo5DgkAkax2HVYDAcJMIDPUUuS65FZVTVt7s0+cO/Opc7s/ef7clb6jYSjzxWIYSurD +cm5aGi2UeyuJNUMzaaKSqSQyZcukmYaEvq8t3ygP1C+oZLKCreksyGR5lA7vlrfe7l99Pb3x5rXv +v/a9W7dvP375sbbZhRGAogqgwAgY0s33r3/19Vdf+/1vDaT01vf7c9uf//yP/aWf+PS/fenMj2sJ +BjBxycN0svfsUz/B8eDuwetDKd1gJNg9g8efxIWLtLvLsdFmgrZtJ+1WLvH171//zncWfYdZQ5N2 +mrPm3mAUggImAYqUMS/29q3DNy5eeiLgbMlF1WrVr6rm8eDfxghALnmV6lO0jHUDNfGnbgDGOmCC +jRMU/OfFvXv3j5pfbwBOpQeN75566s0iYvfu3bt/qD1vHJzUlv9AjQMwM0nN/WfiMXO/Hv+Pp/oh +BJEQQqjNgmqqfy0FliC8DiMIMzGIanKRyCoXSGTsBXQ6FoGxlT1KKWalbcP5/dnnnn/6CxfOfzwP +ZzRtCx4z3e2WaXG0GAbSjDxQGigNVAbKA6UOw4B+iTxg0rQBuwFXWnry/JlPPPvk5564/Im7t28d +Ht25c7vcuWsRtL9P+zuTqx98cOPmm1/+nV9aLK8+9tjlrdmeFhRVBmspTdgLYTYM82+9/MbvfL38 +9It/+l/9M//HKxc/I5gWHQywosQEkLDA6NU3v/T6298ixtY2PXaZHr9CO/vUtIiNhcZYioStu3f1 +u9+9dfVdBEEbIIHbuPvExRdnk4/kga9dv8VExJZK2d7GouuX6Y2uP3ryqWdSt5NTMbNaClxyUdWc +tdRun3k1B3j135zLeh6wmsF0nJw2NgLynxf37t0/cj6sNgqnxonxqaqCe+aNuXfv3v2PgLdVBtBx +cmRt1FMX5LxODBojA8fJQswEq2n9ta1nbTJpqspB6u3akWe8DeRSIhGMSikATIkiESAEVRVhVQBK +Bggz1GBQNuMyv7TNj3/+oz/H4eDWwesfXHtrsPdJFnfu3Oj7RUqdqhpy3/dtOw3SNu1ka7oTZIp8 +icPO9uzs3u6Fs2f2zu7vJruzODh6+513L5ylyCYEo0YLf/T5/Q+uvj+/iy/+xqtf+d3/6ud+9l// +3Cf/p1uzC6VkEKWs53Z+8qPP3fzzf+Hub/3DL3/uM3960u6ZGYiYohZl4ZQP333vzdff/+1X3v67 +dw6/f+Hi1mTaz3ZzbKxtWAKFoO0ETdsc3G2///3b77+rmsAgMIiw3U72di589Mk/8dzjf+H64be+ +9s3/9t1rX3v37TdmO9QtsbNHky1cPfjNr3+HX3zuLy2OtgxjgcKqDeoqt//ENxM1q6pGM8xARAZi +sjptrX7cf17cu3f/qHl64cWfv2918D136j1P6t69e/cPsV/P/xIGEdf8HyKWwMIcY2CW2r+nZvvH +Jq6b/6xa/ksQGXv+hCCBg4RQHxiEhWPNExKOIRBzqJ2FasoQi4QAsxAEgIiM+Uion0z9H6z+hT3O +cawxBAahbZpma76YL4ahLyUBZGallBAkSIhNbNpplNnRXWI5sRw2xWH65pe+8tfeeufl+Xz53vu3 +3r+G6zfwE5996qWf+YVr126//uY3b95+uZngmSe/8Gd//v9w/swzNTRRdzLXjn7z++/9199++e3P +/9hf/sIL/5NuOLp269WrV1+5ffv2tVuv3F6+etS9t7tjW7uYbttsSiDb3toyU2ZMpzs5D++9s3jn +neHWgc0mCIyUaGtKW9tbkfD5F/78C8/+rxZHE1WdTOmt9779u9/9xS99/W9zM8y20uNXbHuPotCV +/V84E/7CsJylVIZh6Lp+GIauG4Zh6Lt+2fXdsksp9X0ahqHv+34oueSUUsklFzUtZlb0uAuQ/7y4 +d+/+UfMBwOoDWk9zVgHpB+4h3Lt37/5HxKuxnAgIrA6PWQ1CoBo5pfH4H8CqcdAYDViHBerpMh33 +zBxXliAmM1UVIi0FzAAYbApQPZAWAlSVRaxYCHWoLwFQBRNWU4oZALPU7JXlcuj7CNoLIGEd/+xY +h/9CE3UJHbCYHxAzzFR5WC6Xy9vFDrIe3nxfrr0Vl4vhznUuc2CpB1fbrfDR5x+fUH/+xnsfNFu3 +bt7+nf/ff/u/+Yt/9j+6/NiPq9nQD1dv/f61O6+++oPvvn/z2t/7tf/TF7/012NjBYtsV4MMMNvZ +5Wce32onxuGIIzWtzeJW38nO7IndnScPDxbvvvHWtWuUFmUqxQoA7O3uijCTLrvFfLnohwHWmpXF +EZ3f/dhLP/HRTzz7c7/4W3/1Oz/4rbPnsHcee/t0sPxyo19o8IkxAADAaFXiZgCYyVAjA7bKg13F +BmqkZh0u8J8X9+7dP5I+bIZJN/7p0vov3f0e6d69e/c/Kp5PJouMh+/EQuv4ALHVrj1ExCJEEBnX +6PXuurJkqRuFWswLEMwUELP6PmxcnNfW+kyMOnggCDNMVVNftKTOMKQh5wxFGedeqWouKGVIw3yx +OLT5ohzNby37m323mC/mXbfIw5A1932npeRiJVnJpjYv9n7uzXRP85Q0hpZAcw55fnB798y5aftk +Y0+fbY+e/ei50rV/7T/+r4WbZmLZLl4/vPvsp2bN5O4v/dr/fXvyws3r3Rtvf+v20Q8uXCKEAcGm +Wwcd3U2KIGFn65zE+WzWTdtG6XAypRBp0hIzaUmXL3zh0tmfvnz+C8t5emzrnffPfrDsDw/773/v +9d/KaZgvusVy2NrCbIqrN759+PgHE57BpBZDp3ywf44/9okz7W7z9HNoJoNmPP34z0z18TsfKKzO +O4ZBV2lWMF0398fGIEzc841G3QP4z4t79+4fQR/ueeSJDKHNBxNx/ah79+7dP+y+/gVpaiTjur+u +420VTa0TE3GclwOpx8erkgCMqecjouMlPtVOk0SytdVGob4f+n6R+pRLKkVJkXPKOeecVW0WaRiG +5XLZLftl1w0pa7K+75aLxZCGflj2XaelKGzo+vnRAkDJhUhE2CixSBBmIQ4hsjBxbCdNZIQAmkTZ +ASjIVgwtIEGExIhsMp0MwwATkiARpSBsbV0+X0QAtmbyzNXre2+/8tuf+Mylnf3hnXf/x6vvlbK8 +sBueXdzozlxsJ9Nb3Nw2LhzQNmjbjsNyMomTSdtOrJ32akYw0sefOPszT5z/V2J+5vADAXB576OX +90BEr737P3zr5W9kS5bSbNsmM0xmuLP4TrPzAzt8PkS8dfVrN27/4Ob8d967/rXzF+STnzrXD+9H +TJ9+4k9v6S+kxTnDvFZcmOl49m+mZnWkQz3fV6zKMFb1GFrKZsBn8x9F/3lx7979o+PphRd//tQG +4gEDxvCgpCL37t27f+j8qsh37AHKNTmfiYWDCLHEIHWqVxPrcC9pmnH0bwhSu3+uhwET8ZVL+3uz +aT90w5BSP6ScSs4iZLA8DCmlfujTMKhmSyWVYsWKas66OJrnkkAmwgQ1IzPRXAoGCSAS06YMIhTB +AHdFjzgkzTEnYSKDrnYjRhyEiUhgALEgCLcomcQIaigiwgwOsYkxl1SrmVMR5tjExqwnTsujw2a6 +O+Th3fe/1ezd+NTnnmmm+sFbenTtygcfHH3/re8keuvck3rucZy/GGOrzTQ3UwsR29MwbWbCYE4i +kwtnX/z4c38aRz+9PGzNwAFkKMWITBUUD3/lK//X33/ll7nVprV2Ws6cRRmwP/m4DJ+/ev2NuP0B +T96Ks3JmbwfgQFtndp/++NN/8uiDz964ilxyGnJKaRhSX8sA+qHvh2XXpZS6ru+HNPRDX0cBDzml +nGuPoKJWJ4QZTK1o8Z8X9+7dP4I+rKsB7s0WOvXg1W337t27/1HwaibrFJExFLDqCsqn8kWIiGDj +Rwk0pp7DAKjq2f3Zk5fOUS69IEdJUYZB+mEoKQ3DYDlbShEcYixmYI4araCUUgT7O7uqRTWZFUMp +JRllVTZtSwmmZEWsJbNklokY2FEtHANviaoBRlR/QY0IpkrM0k4mbZhaCSUvlfqU5n231EJ7exdn +052+HyaT/dn29PDu3Vw4hiiCdrKVUx9gGcO5ve2+f+rarYjuWWnv0LDYnZwLj4vR7itvZBuYh1mD +7a1Zlsnt7R2NLRSlnR3uzB4j/dhnPvGvNeUnj65up6zAQOCSAAoEMiMQBGc++tyn3rv9K1ljLpL7 +xfUPUlG6qd89t/f+/qWt6V6WMDU+2t5qt+Knzu/8C9vhxWuvTfs+GVLt6L/+fTzghxHRanqx1fyp +daugUylADzj+958X9+7dPxI+VH3vdqHeqFlEq9v1ke7du3f/0HuQ8OgN60lg41+O6xu2eh4bx/ce +540QiGhVTXX3cPn6W9efuXxORLIpKDOzEFmQ1homaUiGlA0E8GCJSI05xmgGIstZ1cSMAQ4hmPZa +zIiVhRDqACsggEIbA0hKSloMZKWUlAcyijFMJtNm0nbLbtF1ZJjGuLM1bdqtxUIWC4UFtBMrRkSz +2dZsOjUzMppNp4t+CRqIm6HXbsi7588mu/P+1Zd/8O53Hr/yvLEdHeLs+WdvXY+3b1///rvf1ojL +z5y9eHm6dxZxMm9abRvMpphOwv7k8zev4dvf+uDwjTeffvIjFy7sEswQx3+MgNlenh8tDg7vpPLO +1bvfuXO4ZLY+4+w+TSa0fwbTKWs5bALYtnbaT1+++Mmd6TOT8LEbb5+7WSd+5WwKLTqOAy5astaO +PnUumNbXq+gq56eWAut6H7DeDaxrBfznxb1794+ap09/5qV7AgR6sm/o/SML7t27d//w+s0UIKmt +/EmExx6gEiRwiM3YAzTEICJNDBIkjjlAEmNkphBiDBKCMPNnPvlMI5yGIZech1RyLiWXIZVckMqQ +0zD0ylAb51OlIfXDADOu08WY62E2GVnWOsaKQEVLHUMGgqppKSXnOtw25zz0vTDv7O62k0ld82Yt +psbMMUaWkHPWoswUmwhQnYKrRVNOVjS0IU6pmbaqXIMPQ7lxZ/79m3e+HRp98skX2+aM6XSxiDdu +zb/92m/Nh6tPPR8vXonT7WFnG23k2YS2J1uzdjfq+be+t/Xdb926+sFyflSe+cjz2/tnL1++Arau +70GFwzJsHR0t7xwc3b559DKQzpzldord3RAkNw0kYDIJxHk7fvLpC3+mzD87bS+k5dZ8viiatVgu +JadcShlSKrkMw1BTgPo+9X0/9EPXD33XDUPq+mEYUgWllJRyLiWlXHt/llX4QK34z4t79+4fQT/W +APwQrUNPPIt79+7dP9S+7gFWNQDGIrUGoM7xDVGET9QAhBBilBjrFIDjGoBaghtiCEFmk/ZTz10R +oVxySrnkbKWkfkj9kIdBTVWtH7o09F3X931Xx4G17STGIBJAlHMuwyAhCLGZDcOQc95sNkrjaHcj +IhauZ9pWuxmZpVJUtX6SRKTQVBRMIQQAwoFDAGPaNtPZzu7e3nTvHIiJTESatr929avvXv+tRDfN +lhza55758WnzxH/93/xnd+/Od8408+E9jvbYJZpsUzO1SYsCOrt1cS9+ojvauX0t6WI7HUnpJ6nE +mzdvS6vv3PjOweKdvXM72/s70mrGnSHfiDPMZnT2TBSx2VajtmgnaFq0cbudbA394dkzTz2+/W/o +3Z/t+/Gk30xTUjPLOZdSUkopl5RS3w85567rhyH1fV8HAgx96oe+71PdX6WUh5RLzrkWAFjJudSx +Ces5AP7z4t69+0fNh408IT0VPjgZRDhRXOzevXv3D7Xf6AJEAK1rAOrflqoQPvUXqAEoRUXGvH+I +jB1mCHU1uez6b7/x3sefvhSIhVmJVBUwVS0wAoKwNU0Z0tAPw7ITCU3TTJp27DRkYGZrp6ql5iHV +wAARG5SJhQUwNTO1rGVIiZmbttVSChBCmG5txRgsNE0IbdtK20ym06Zp2ulk0s6U1n/hU91CAFBT +GMxsGGa7+3/8+U9+9L0Pvg/ImbOXBeduX9/6hT+7/3sv//Ltw689sS8UDWwULLQQoSfO/PGZvCDp +8VxIUp8XWZd3hkUXmq393dlsd8rN7NW38dr3v7t3+f2nnguTGfa2eDqz2QwNZ9CWELZ3t/f3Jl13 +Uy13y8NlPw9ye5a6ZjDTwSBmlouZWdGSSzFVVS2llFLMoKWYaSlFa0ykaNFS6m3TolbTg+qR/3rj +V+/0nxf37t0/sj5sbB3uPzLgnmIC9+7du3/ofc2rWaf+r2+MJQGr8gAzU5gAZqaGwHWxb3XyV+30 +Px6qmAXirh9u3plfeWw/a2GmsnpyZq4rzihCsy1h7ibTnDMM/XIpEoIwxcgkRhbjpI71ZQm1zyWM +zZBLMYBAIcZ2sjPb227aqYWGiUMT2xDa6WwymZTxb/zNEQeWFEDZLIY9WepAIMDsg3cuMi4CuP1B +AcCk58589jOf3L1xdO7W3d9RWsaG23b7wrmP7+98vEmfyYvzWXR63i6fx91bt+5e/+DGu2+/9dY7 +Z85fZJpsbz02a88sBzsfsbuXpzuIDbantjebMp6fTi8/+cSzi/8/e38eL8lZ3ffjZ3mql7vf2Uej +ZTQarWhhF2AWIW8Ygw0mxIbEOGCMv3aMIXa85PXy8o1XcBzHSbzEeInzS2wnNtiJg78x3g3IBmSh +BSEJSWgdafaZu3d31XPO+f3xVFVXd98ZCYKQRvc0w6hv97truqvqVp/znM/5nPyhz9z9F8Q2iBvt +Ns5OZ1H6KytL21uqhqWaX1VUVBTMRDWmAF9VNYpqmRQkax8zVUtJQFL/p2NYHVAxNbXSwFWHPR7+ +++K8885vLf6MTcBjacRYEcF55513/tznDRouQAZCyACgBqRmVIb3KaZkwnTHCMxA1QSFgSFF6oiG +KAYMcGJpdWW9f/F525kCdBi5CKEdJRaxsBhB1QyyTjeEDFQVIM9zEeEQkjENIxQSOcuIyRDbITBS +d3Z2ZmqK253ImQEwUmhlSYAURRAp2eEQUa6mFtEAidS0ymVQUxBsUE4ZbtQu6ppAahVQ0zT/WA3E +4NSxSHDevvl/fNkFN3Kr1x9MLR1tTcUpWp5Z6Q0IB4hmBsQ8szg/u7i466KLLnrOfR/72P+3ClnW +Bu4+dM3z8MJLoDNjc/O0ML+7jXvmO8/fPvPiordvut8FfSjYfcsrD01PY0AoiqKw1T0719rW21hv +q0jp8VPdVMTMynZfURGVGMs7ElNfcL26r6JaGgWZaDo9hlmQ/74477zzW5YPY9lDmo4IQ6nQJkUE +55133vlnBY/1kj8AIFElCjIoTUJN1FjByNSUjMDMQFWViZIQSBAZWc3Q1FQFqJ/nUfVzjx7dt2tx +28z0AEmDgLD2LI9SxCKKFFIQkSKpxGxmupvxII8G1M6YQzY9Ozs7N2PUHqgmf6JS+p/KDUm6gxDF +0mQxYlQ1NEDWKsAHUE3vsHptynbqj1tVAEYNMlXHHTPVjBBkHfvrO+q93N8AwD6CCSgAAqBIBAQE +AcouuPTgwZUdn/nsX2S0tnd/7M7A7r1z3c5cxjsee2Rp++xF2/a/OV9vI8D6OrQ6F5238IoTJx+1 +rqSBa4Cy1r9/5+Jp7u2NhQGAlNG+SvL4KeU+KtW6v6iKihkk/U9KB9JIYE1OoJo+vlTVm2Sf6r8v +zjvv/BblwyYtAo3UYaxqsJntqPPOO+/8OcnXcwDUgNFMRTGglRJ/4nTXkoDfUhJgqkqEqqaoqKpE +lIoACCioDGBEKgpEWRaQCQIWfZEoigCBjbKZ9iwxnzq9TkQZ8/T0VLc7FYFjLJItkQGs5oCYIxKi +lrJ9REI0ADBQU2aOGlNbsERI6QHEYRxfjizA4Y9WTckt94hpWQCxYRI06pk/rJCkNKBOmZCq8chg +gJiKDwDARAB26njrude9bt/F21bXHpyeBoBef6PfW+bDj/HpY7uOxAFv3LzvghdRxoja74Upft5C +99Z8cG+7K1FkugvHT3/yuZe+oVjfNxiASIxRzKDU+FvKBCyWRQBR0TRTOXUCSBRVVbHklGQq6T2r +SNpJZiailAoi/vvivPPOb02+mgQ8ZhU07hw00VbsvPPOO39u87UTKACkGcDVMOBkB5TsfZiZsyzZ +/ATOOAuBmbJk3JMFZg6BiEprIERkouQKSkwzU+2kQEnxe/IdylrtVivb6OVlYA+AWNYfhl4/iIAj +Y1zqOgBgtcZfrvdA3dELlUdQY1dUC94G9VOb9AGUaYOOvXykSaD+F4mqgWj1e8AqSSlBYp6ZhY3+ +WsaAgP1+f+nUvUcfOdHi7e126/HHT+zde8lFV1xBgQCBML/zwd86sfFn8zt7nWkztmB43YG3Fyff +sL5KIpIM/qNITP5KMeZFLNKQ30Ec5P3BoNjU/yfN/y2KVCowS39bOSDMf1+cd975Lcvzrt37sVzI +qZ/AxoU9vbiegDMOOO+8886fo7ylyLsRtpoZlWkBEhKkBRNCBCKi1Ms7NA9lMgOmCkFI7vspVE+i +mzyPYqZqoiCGoqYGMcogj2AGycPTINkQDQfbJuuaaqZVUrxYJWlPM25FxCpGDZI4plz8VhUp9TEi +5f2kn0mxdAqoRSTGqKppvlZ1q0hVUY3pBaXGRmNaYi+tdkQkai3Hr4bvqoEZiMhgYLFgkXZRZGDd +men989suzHt5u9Wdm5kaFP0jjzw2t7gNmVWIO2tHT34mdDbaHSBCjdYJ2+LGNVIEqSovyelHRKOk +zypFobEookiMMUYpYl5EjbH+QBal3FGShh9IXfQA898X5513fgvzvHvPJRU0XMhpvLJe5Smvm4jo +vPPOO//s4KvY38qZYIRmyJTW6qGM6xEAgZiqxe0qM8DhinwpiCGsFtrTP9+04rFqIR9TUytYZfBT +Bf6QxgKbqkGK+dNzMWoV69cxv2jqRaiH32od7msZ9KupWrV2nhQylWomShXEl3AZ69dJQn0bSw5G +/i1JzdBmwzdizbzFDAGSDAfAVA2JF3buNjPtb7Tb1s9XThw9vLhjNxJNT808cuSmuQXNZUDErRaQ +dWz9K8Bayf4/9QCoqMQoUaOIRIkxFkURi1iUlQEpiiiiMaaWYBGJqbk5vTMEEFGwcvnfz3/nnXd+ +y/Kh2TFgNtlGMPQNbVScnXfeeeefDbyakZYqoBSwVkqYdCUlQlVBJpOoBIgIKqSEIkooiIhogoIC +ZgyIwAACiBhF2UzQQjAFJCY0IyJTRWIAS8UHaor1k/AHqb5wa+3Po2g2sniT/hmodPy1mU9D2VJq +eUrZT/mDpk9plSqoHGVQKX1gQv8DTbFR9d+R5AfrdAgpvX/CVBVJNRMEMCIzIaIoGqbnZkJr7dj9 +3S4dP7F+1623XfX8F0ZZ2Ll40er6w/PbENAQod97/ILz+8cenUmyHalGAVQlkLLmUXUFi6iWMw20 +ahC2kq5sP0HNkNDU/Px33nnntzgfGld3qr9ZKtdk2uyVzjvvvPPPEr4pcwdEU0BSNUZTQk59wQAa +IyKKGIIgkUZBQhFFEKm098kJR8DM2KwwDgxAhCoCiCCqgdlUAZFSS0C6Tic30jKCTjUAoabgHsfk +/gBQTiFAHPHyrwoNtcclVPG9Qun3afUT1kgM6kSh4pvRfr39FPdX76RqA6hbaRGQuJpXTMiERFxW +VQCSTqpMPhC41ZndeyAefWBxsXPo0KmH7vvMFdc9/9ILb/jk3Z8g1mixEGPqU+sRkcUoaWBvkkKZ +iEkpW9Lk8VmXHEr/H5O6oFI2OxuYJvdPrEoxfv4777zzW5rn3XsONEsGDYVQs3Zg1YP1wpjzzjvv +/LOBTyN465C6DLqremkS9hBSfb9ZXkUaBuKIjR7basxwuR5vAGZl+2mypEw6fjUDq9XzpRaoltmU +E27LGbdaqXRULVaKnKTYiUntUt2KmMQ7MUZRifVz6ZEoUsQixlgUlcYnRokSo5SPJOmMSBTJC0nP +i6bNatlQm7Y28vakqf8RtUq4LwCQRE3lRwVQVYPQnppfXz2VtfK7bv2HVjaftfdbPCTZIxAAEIgo +Ft1tsy9YXY5WefrHWIuWJBYxRimKIsbqoxUxxmoqQBQdvjmDsg0ARDT5LPn577zzzm9lfigB2nSk +cDNjSFmF88477/yzi8eJtXYVJcRyUZkMVBUFFDEJgYbNA0XkwABAZABgbKRmgcnMNI3/RTATRCJi +AlFABEU1KHsMYgQq/TXLf50Im2vw9Rp/SjOGWUrD4acS85g1VvGxUvhAufg/VARNrvqr6dg2mwv/ +ozqgVKoAolL+w5zuARJx6p8gJCIhImJEUFFiqvqnCRUJURGQeG7nBcVjK9u37fiHm/7iO17wzpmF +6+44dNNUl80sj7nixv7L4uOPGoBK2eJsZUeyVAMBhlmTWPlImmVgZlpqnap3bmaEqOVsYD//nXfe ++a3Lh9ohaFItBJsbizrvvPPOP3t4NSNEEWWmklZAghRYIpuKIAIqxigIEBEDgGAEAMhCab1vJilC +D2DRmMiYUYU5pJBaRCSVEZJGhggRVMqRXrUNfyXvSYs0UJUXRoLyOitQszpJqEYWaGX6WWUCMGwA +qHobShTSRIG6JaBOJ4bR/6j7J6a3R0OTUmx6JCEgMjNhMlTFwIwspSxIiBkJKcmEjAgJQTRrTe+7 +4MDqcrF+/6GHHrz70udfYI8SYxDMTaDXXzlx8rTqdKXrH6r9k/xHVKzqoVYDNdVUUSnzhDTQLWV0 +2tD/+PnvvPPOb3U+jM0GG7tTfbs0xwc477zzzj+reIXS/NMsXUEtLVsDGIACgBUAGZgxkppEgACI +AAIAFjit/QOAEhkYIglKMKNKIJS6YgU1BczlWIByAkA5bgyJUkdvGXY31/nL0HwYkaulQL8R0Nf9 +vnUdIBnvlD3EWjcIlA+CNSoGZRpQjg2u/sWRNKAhfUK0apZkWu0v6wCUvFEJmZmIhISoeiCQacoE +mAiYiJgJMc+llS3OzO7Ye+GFN3/ik3suee7enc9ZKe7iDAxBYm91/aRqF6DUS5W6qcoc1Qxq96Fq +1d/QTBWqGkD5GQlRDapZyH7+O++881udx6uvvXG0KACTUwNGW8HUeeedd/5ZxtfafuJK20KAGAiR +Q1rPDsTIxCFjJmIOgYkDMQXOOBARp7iXquCWqJwbQJXDDwIADb1Fa9c2aob7Q+kPomlT0JmEOgaA +dTGgXvJvrOtXNqPDwV6N3GAoFoIGUA8Ls7OYAKX3h43RCWnqGSDWn5TKAWhETEyMhCGUsiCmwIFq +LOVFREjMOMgPPXDf0eN3Xf2Sue0Xn3r4xP9pzRgYtHD/YusbVw49z0Bjoaoay8FeMc+LvLwVeVHk +eTEY5EVR5HmMscjzZAoaJabRwbFsERad+ER+/jvvvPNbkQ9jiUKdQ0w8qJsJjJx33nnnnw28Wl0E +MDFgAlAEMgVAMWIoYswgEGoswAIARICgYMagpsrMle6fmVTL6L/yyIQk+4Hh6N/aTwcBZEJrb41p +vaBqUM0pq1flq5C+/CzJ56da+Ne6YlDmBmniGJQmoVV6MOwcwOFmR/5ttZQdAUAzabFqIlpa/4cq +/CdEYk4JADMTc0hvJoSgpGqcsgI2RkQiIAOM0u12pmbnptYXH7j/YZ4N09mOfn6cMxBd39g4ZWqi +Yoa1+CdF9WqWsh0VheEHrWapjfgjWfVBmg0Afv4777zzW5cPDZ2QjpUPztJM4Lzzzjv/LONrIVCV +EACoJIdLFSQmVSkK4GAQwcopXcHMAoeyEzUQEZpytfJPgMDMSTZTNdBSGeJv0nwMqkpEVsXrMIzI +DQDTRK2G7KfZy1uG8XU7r6ohlrr/es1fRlRDZjrsEa4yj4YMqZF0JNm/gVXVi3IyGhEQlGlPym04 +hMCMFEMIRBICE7GqMnMwiyAcyNSQkDlVOHBto3/+RReuLB8ueLHoFZ2pXf3iOAD0+yf27eX53XOf +ve0koJa9v6Jm5YAzTf2+OGxzrjuAS+1Wpfk300Yzg5//zjvv/Fbn8ZrrbjxTgWCzasLZCgrOO++8 +8+c0n/x4sPwPEgIxQfoLkuAnqVuQiZN8JZR6FwxJAJRU8UyIEIiRquX/8ipchfxVtaEpta+TgXoq +8Ka9vPX6/QjcmO1VTRBOoiAbegDhhPd/cxBY2ixs3gEMAATDqkXZB4w4bAMgzJhTJpAqAIEZiUJg +rqoBgZm4dAoiTqqqqpQAyIPTJ5c/P71jaW7PQ+tws2aa9/DCHa9fDG+6584emMRopWdpEYuiyIsi +xpiUP0VRDAZFkReDPC+KKFHy5FcaRZKd6tBsFfz8d955550/YxPwWBoxtgnnnXfe+Wcfr0CEkByB +AEDUEA0p+ViaigKAmrGRMaBSMDBTRiUls6RrYSIkLbt+y2XyWvRPdRqAmwbZTcMfUx0qggDFxpf/ +oZK2NEf+jjxraja0D0rFgeqFYCZl6aOWADXaC6xRpcBmSlBlL8kOiBhTEwAzSRQi4iT1ZxEiDkFV +iCgLmQZTEQ6swsTERirGoZQOMXNozzLM2SAO1jXMzERYYYZ+vrw2WFFlA4tp6oCqppFgOozry/nA +UFU/oPyM1ZciVPtq8yZgP/+dd975rcY3JUAAoIgEpjCqHxorIjjvvPPOP1v55ApqakCGSFE0AKUc +IBnwVFdSIIYoysZGRmAqqiEQGysJlikEStkCXLpmVrWFMyzSVCvx6Q0MHxl2BozG9zayhF92A9Rr +/zCaCZQbFwNCqJoBYp1FqMKmxqPVDOCRgcRICIBMCEXSAlFdFVFVqdIANVMhDsEMgqkyq2m5y4yJ +DMAEjQlVDQJ1WvOrK8vt+ekWTRewwgFE1zf6q6bz6ZOJqorY2OyDYZKDzfX9dKCsWvNHKveqn//O +O++882GTAkEjdRg1GNrUdtR55513/lnFp+CYFIEMEUWNzIhBBQCYSZN/v6gFZjNhK8cIAIIKCBEi +xJj6XamW/IzF/aMqoOHSPjRcehqJQSnTL9e2TU2xGd+nt42VkkeGE6+SDX7qByiDe6gcMlN3b4U1 +WhHEiDG9ahg9l5lALZeimEyNRJAwSPL9ZGIJzCkNyEyVQ7LvTEmIKqmaCllmiKjKITAYpvfT61Nv +nYqcOYIGMIOoG7G3GmUGQETSm8c03tdM1ar2X22kAlVvtIqpARKm0o2p+fed88477/xIBaBa1oKx +H8c212widt55551/tvLlYokaECCCGoKUhptJB8RmxBTFSFGROSCIJS8hACVGRhWpu34VkcsL8tmX +/xtilUY+kIZ2pWbgYayuo728UA8IU6sD/VolVD9bFQMUAKTMBIY1gfrWNMycmAeM1RRgQtLkc6Rk +xMqkKGiZVqop48zKRX8zVUtuScYMCERcbz0Qc7DZ2VmS2fUlndqxyHQ4j6A6yPs9U1VQNVBJ/xMr +3f8hZRXVfkh7qNw59XvW0fTGz3/nnXfe+VA3BY/mDTTWVTCRWDjvvPPOP5v5qg6QWoOtnA4sMbUF +J+E5AEIgsAiRFAnQAiMAmpFWHj/ESQWkmGJdGkaiw7C00ZKLWEp+tJ7oBc3AvSnsKWN3KHt/R+sG +jUC/vGc2FsqrGBJY5RzU/OfOFPqXUwoI0xADpjTcgJGUlQSNA4KZMnAZjZuKtlKrQYrZq+6FkIGp +WmAmFlSNamR9LbrFRW2e3dB7iG2ld+SKK+H0Q7OPHVoCMEnjgKvhxw3zz+bbtrG0qpoCVic5fv47 +77zzW50PdV1gVDzUrCZQc0nMeeedd36L8I31eAACBSQEU0MSUUYEQouFVcN9lRALTSPElCgNF0NV +NAMirEx9YLIGkMQ5Tf1PvYTfFOrUQXkJaOns2eRFrbn9Rj/ASFNBbfypMrY6DpsNA0tfG1iO2kUk +LbOBtJYkakxoxEhqRkrGZqpkWVCFEDgHyMAAgkFMQTsHNjBmVjMlIeXAnKstLi6sL+drq8u4EBCj +SC90+sQi5QRgME3jgNMkACv9PQ3ST9qYiwyNQcvpMxKiqPj577zzzjsfmh0DZnDmV1JjCch55513 +fkvwqSe4jozFABHIAFGAUAwQGdRAERGNk0OOEqIpSpLKIyDhmPvkE2YCDVWPSqNC0MwEhhWDak09 +9blaNeSrIQQqZTATwb2UfkRncMds+BRJSh2QyAyiGAASM4CRproAqRkIGnMIZoVZMFOzrG7V1ZCB +GVefpFy6Z2YANhMAIAJuzy8tP9heWZ+az9QimPX6q3kclCqg5PuTegCgdDBSq0clVAnMyMQ0gNKC +CU3Nz3/nnXfeeagHgUH1RdWAoDlaDDaxEXXeeeedf/bzosJEaaEZCc1MAcGU02WURIwQgcAkplAY +yzIAYulBKemlozKaKrwWTTKV8WX+yYX8USHQiNAlJSoqm75EASz98428oh4joGNBf1VDwGayUi78 +I1jVHIAIKhEJowASsVmaghDFAAKSpW8YjAVAVr0fTGb80KpVTJzidUE0MEQ6ebrf6czm/cdncc5U +iIpBvp4Xg9L/E0rxv4g2JxlXsw5SdlAPSLaqAjDSKeHnv/POO+88795zwEwbfWlaz6pvcFY9mIZE +Ou+8885vIb504EcsJwRX9xFBVBHKyDaJd2rTHlMzTbE8AJhKEsRb+YzVkhUbLpJLKWwHs3KxW6yc +eFtq6EGHyneQKFba/6iKApZa+2SaCZVJTh0oq1mSDqUqgVWVAa2l9GOVCrXaWrOsLYhB2iHVYLFk +DWSG6aOkHAkB0tjiJGEyQEKEZHdEiOVeQkRL8hws9zyY2s5tC8eX79m2JxoMVGKnc976yQvWl83A +RNRUowiYiURVk1gOBY7ljIBSGqRWqYRUyixGDRDVz2fnnXfeeVDevedAvQ6UuNHXQ/PFZSHVeeed +d37r8WXsas3uXUxCHlFFwLQIDWhmqNVYLk2RtTbcKtVEFAFUVUTLZzUFrcM/ZYxuZgYqaim6FwWs +cgYt5e9QzfptCn5ShqDJUAjAhq5Bm0l9tBTRqFrZVFxrasbuA0DKIbDRjVDG/tiQN0E1LYxSPpCe +NjAEtNqxv4z/R97b6ZUNwCOLOwvDjaj9TntX78SBjbXkJWpS+v+oiIqIqcVYhv4iEqOamaRZAVru +/NFP7eez884773w10QY2GSIAY9Xh6r7zzjvv/BbltWozFdFSb2ImagAo1cq8aVq3F5VoJmYiKjGK +qImmv80MoqT5tVA9LjFK4s1EJapE05g2lXoBtKwJaPojZUBsohZF1UDN1EC0Xs4fEcmU71nLDKQs +KWipjdFaR1RlIOnfG71fSvDLgkD5QtCU40hMO0NVJaqoSjm818RUJRYxeXiKFBJVJabnpYgxxiJG +EREVDYFb2WKvl6F1mUCL9SIOUrivZauvxigpSZJm8mNjDdCjGU5DN+Xns/POO7/Feapng40R6U61 +oKONDTnvvPPOb2l+qNTXhprHTLSMv6UyqFEpQ9UUwafcQCUOM4TyjppakvHEKjOoHS7TA+lPirar +LMJErUwjAIaOmONRfnkntRmkrVcRP9TBffOjnX3/NBOD9NlVKkG+mkrU4XyCMsqXqGJWfjhRNZEo +YqaiUWL6Z8tFfRUinupuy9cyti4aqOVFUZTJT2oDBhvvc7Dhj7UdavX+y3FgzeV/P5+dd975Lc7j +1dfeOOZ5VzsEbXqb9Mhz3nnnnd+yPBMPC6yEI/KgCZefupW2Gs5VOtOcYeOWjH3GHj6Lb0/Ts6ha +zpendP9Q1S6MlAaDQfoPIjERIhFj4BACETJnRERZFpg4BGZmDsyIIQtMBIghMCEtbpu/6Hx45Mj/ +Oe/SwfLgk7MzB4587htXTkxb7QQkqlJWD/IoEqUoYlFEkZjnIhqrrCN5h4pUyis9g8Opn8/OO+/8 +VuPLiQCjRhA0WS8Yqyw477zzzjuffEKHK+ip+Xa4PG4NVdBQkJN06mm1XrRqz5XmC7SqCUBzIb+5 +/cYqfqnMqR9prvE/1fsn1RAgaaJKB56ykCBVgSCKxJhW/UupvprGKEn4I2YSpYiiqjFKFFlf2zh8 +dCPQAmmbAA2jiqhKuV+0mgJcjgE2ERn+q1CXQcaypvILz89n55133vnhc9hoBqi50W1R8/XOO++8 +8843+aZWvnztMHaHZhAPALX4vn58jG+uVaeF/DFdPpRal2fE/qkrD0kLVLkdWWW+WYbsZW+AaCxi +svK3pBFKWUF5k41e//ixlen2Lo0EFNSimqiCiJSL+WqqkrKksg+hGgYsVT9DWgiz0hgV6z4HP5+d +d95551MCoGOJQtMoFDZpJnDeeeedd/5s/NgyfCOar+9gc016U350af+Zvn90E8GSNvqiVWLZNy2q +mlqeVVJrb5UDpCzAVGTHjh1zsztUKaOpFPen8kHp/mNqho0uiUr9L0rVgGSVpvS/vuPnp/POO+88 +wVmagMfSiMazzjvvvPPOf8G8qDSbbseW88/1z1s9YLUQKGU0oial5MkkJhWPaSqBiFXe/SpRijIb +EBE5vdQ7vRIR2RTbsMOUkqVpWTZIRkCq6eWmmuYnqELD56e8PzoL2c9P55133nkw0/HsAZFgQj80 +VkRw3nnnnXfe+TE+tSXXOUBdGCjdgcwANIqpamXpI1E0iiTbfhWNqcPXdHll/fjxDQ5TgBRwB1oo +HYLSi6WM/lO0n/4jBohl40EV9yM0hivX7dF+vJx33nnnaTJ7gIZUaKxqMGEj6rzzzjvvvPM6WRCo +JgaoWikGEk2upSpiMUosxUBW9vWWcwNM1WIRW60MgDOeJ2wBoqgme1VVsKaySJKsKCbbpOYssrT2 +37RF8uPlvPPOOz9SAShzhcalu3QJPYN+yHnnnXfeeefH+KEbkhkAVsZHAo2uYImmJmZQNf6KaJRq +wK9EiRIVgDkDZYQu8wwBDUN/HS7/Wzk+wNBgODkhTV2o3slkJuDHy3nnnXe+7h0eyyFGXrxZkuG8 +884777zzm/ATRYA0KljTJDRL0b+KqsWoVo4NlnJgmKopSJSs1SGaBphqZ/McMpXUI1yODzO1JAiS +ykTJqtHMCkMFkjUcmfx4Oe+8887XPCFO+geNVRNGmoudd9555513/kx8MuOvgm+UZHhq1hgPbBIr +O0+zFNBXncFQdgiozc8udDvzKDOBZ1QpqppBFJUo9cjjcjBC+m+58K+1BAiGs9jMj5fzzjvvfJNv +1gX0rK+kiaecd9555513fpLHag2+nA9gKirS6A62tHQfRSWqgqlKqgOomqiIxmPHV2PkEOanOjum +uh0VjVaOCxCpmoFNVQXMJKa+4vr9JMV/XYFAP17OO++8800er7nuq2DiZqaIY4WDTYcMO++88847 +7zxMDpxnTgtMSAiIiMSIyIQASExMSMQhECIRIQBmgYgDMSJiYDaDV35lZ8ceOXlk6rN36PLSBhiW +Mh+tZwuUI8TSnTj8W0UVSp0RmJmIwhlufrycd975LchPzg2uFULNjKF+UJ133nnnnXf+7DwhmpR2 +nA1LUBFNAqFSFhTFRNUMkEAMVEViVDEVQYQsTGc8f+RI/9TJNTCI5RyB4SzgpB4qTUWtfDJtH6qu +gHSfEP14Oe+8887X/FACtOlI4bEXNyVDzjvvvPPOO78pr2aAtRAIUicAANX+nbUrKFT6n6TsSaG9 +mBYxMnYIp6an51QtZQrJJVRK9Y+Uo78MUhZhpfcPVP8sEGLD/NOPl/POO+98yVOze2DsDmxiLArO +O++88847/+T4OvpGMzOVlBtoCvTFpPL+F1URlahipskXKApxRtgFCFGiiolGNY2iKhalMNWo5Sxh +gHIiQG0A2mgAqEsBfrycd95558v7dKbRwZVRaPM+1UmG884777zzzp+F1zQKQE2lxlJjbprXW4pz +RK2aG5CmBGgS8ZtqpzWThS4BV2kBxCKqiqqgQSznh5laPWSgkhaJmA6FQI0lMD9ezjvvvPMEAHj1 +tTdOtA7oZDtXM29w3nnnnXfe+SfkAYBSFzAAIhAiIiARADGlxuD0PBIxEiIiEyEiMZji133ddXOL +7XvuPnrXZx4lppRIlOY+ZqYmYgDlbGEp54iVQ4dr79GyY6AcSebHy3nnnXceoHYB2rSDePTBka04 +77zzzjvv/BPyhKhmzJQs+StHIKxzAEREqvMBTstUnMyAEAAg5Q+1p7+ZqVQzBUxF01SBujVYRQ1A +Y5RKd2RjZQA/Xs4777zzTZ3QeNXgLM0EzjvvvPPOO/+EvJoRYvLugcbiPYBq2bxrplq2AcSoYmZQ +REkWnmnhPkmAJGoskuOnRkmTgZP0X5P4p47+Tev5AynwRz9ezjvvvPNNHq+57sYzFQjOYCyqzjvv +vPPOO/8k+RSLV0KgNBYAzIA4AEBdByCmVDGoigKpYkAABoZazRSrLEQBADRKkv0nJ1AzSwmAytD3 +P+UAjSZgP17OO++882duAh5LIxrPOu+888477/yT5UWlDNuHunxARNOY6gBl7B5LO/+Ypv1GkWgx +iqgpaLINVUuKf1MRiSKmWr3QzGKUtPwPkPRD1oz+/Xg577zzzg9TgtFJwApAYAr4JGeMOe+88847 +7/wT86kAkEoB9Xjg8suJeDgwODUFlw0DqAZc9gDU2y+zCQCoRwqYWUozUqNwSipgxADUj5fzzjvv +/JCnyewBGlKhUYOhSRtR55133nnnnX8y/DCOVykbAOoH0pDgUsijpa1n8vUX1Sha/63lLGCTqLXu +X3TE8TNF/0MZkO9/55133vlRvq4AjCmHxoVEE0mG884777zzzn8BfC3iR0pDK7GqDAAxVZMsEcAI +kajyqBirAFSdwSnQVwOzSmI07DMeJgNJduT733nnnXe+yde9w2M5xNiLJ5MM55133nnnnf8C+KTS +SdPBoPTxLAP1JO1XiWmel6glqx9VlbTyL6pSWgAl3U9dMaijf60aDIbvxsT3v/POO+/8JE+Ik/5B +Y9UEql+WAOedd955553/InitF+kbzvy1oB8RVSKApowAANVA1KKUOp8U4qvVob+qxLq3OBn/QyX+ +UTPf/84777zzm/ONJmA1gycaH9C8Oe+888477/wXw9OwA7i0BwUAQisbhQGs1AXV31sKQKZabyNN ++EpBf20MCqO+n77/nXfeeec35cdcgJoQPJHMyHnnnXfeeee/SL6ZA5haw/wHGotY5aJ+bRlUbaSW ++I/8WNn+qO9/55133vmz8DRaHYCGQqhZO6gfVOedd955553/v+e18vkxbej4RdWg+jNc2K+8PssG +AAAQtXqGQPlyHat0+/533nnnnd+cH1YA6gTiLJnEpgmH884777zzzn/RPDVW95MiqC4IpMaAM2xz +ZNU/bURUfH8677zzzj8hT83ugbE7sImxKDjvvPPOO+/8l5DXaoxXqgaM2flbdVPR5n0AME1zf8sU +Qs18fzrvvPPOPxmezjQ6uBoZ0LxPdWnVeeedd95557+EfB35ayXpkcr3J91J6UF1PzX7lqv+pTDI +96fzzjvv/JPj8eprb5woEIy3T21aWXDeeeedd975p4ivp4Y1RwiP3TYT/Pj+dN55551/Yp4QJ/uA +NxksPFZZcN5555133vmnjlcbuv4njVD1iKUJYLXgx/en88477/wXyjd1QuNVg9FtTc4XcN555513 +3nnnnXfeeefPMR6vue7GMxUIztA+rM4777zzzjvvvPPOO+/8OcqfsQl4LI1oPOu8884777zzzjvv +vPPOn6v82CRgBSAwBXySM8acd95555133nnnnXfe+XOJp8nsARpSoVGDoUkbUeedd95555133nnn +nXf+XOLrCsCYcmhcSDSRZDjvvPPOO++8884777zz5x5f9w6P5RBjL55MMpx33nnnnXfeeeedd975 +c48nxEn/oLFqAtUvS4DzzjvvvPPOO++88847f67yjSZgNYPJZoKzdBg477zzzjvvvPPOO++88+cW +P+YC1ITgiWRGzjvvvPPOO++888477/w5xk/ODa4VQs3aQf2gOu+8884777zzzjvvvPPnLj+sANQJ +xFkyiU0TDuedd95555133nnnnXf+XOGp2T0wdgc2MRYF55133nnnnXfeeeedd/7c5elMo4OrkQHN ++1TlDM4777zzzjvvvPPOO+/8Ocnj1dfeOFEgGJ8asGllwXnnnXfeeeedd955550/53hCnOwD3mSw +8FhlwXnnnXfeeeedd955550/F/mmTmi8ajC6rcn5As4777zzzjvvvPPOO+/8OcbjNdfdeKYCwRna +h9V555133nnnnXfeeeedP0f5MzYBj6URjWedd95555133nnnnXfe+XOVH5sErAAEpoBPcsaY8847 +77zzzjvvvPPOO38u8TSZPUBDKjRqMDRpI+q8884777zzzjvvvPPOn0t8XQEYUw6NC4kmkgznnXfe +eeedd9555513/tzj697hsRxi7MWTSYbzzjvvvPPOO++88847f+7xhDjpHzRWTaD6ZQlw3nnnnXfe +eeedd955589VvtEErGYw2Uxwlg4D55133nnnnXfeeeedd/7c4sdcgJoQPJHMyHnnnXfeeeedd955 +550/x/jJucG1QqhZO6gfVOedd95555133nnnnXf+3OWHFYA6gThLJrFpwuG8884777zzzjvvvPPO +nys8NbsHxu7AJsai4LzzzjvvvPPOO++8886fuzydaXRwNTKgeZ+qnMF555133nnnnXfeeeedPyd5 +vPraGycKBONTAzatLDjvvPPOO++8884777zz5xxPiJN9wJsMFh6rLDjvvPPOO++8884777zz5yLf +1AmNVw1GtzU5X8B555133nnnnXfeeeedP8d4vOa6G89UIDhD+7A677zzzjvvvPPOO++88+cof8Ym +4LE0ovGs884777zzzjvvvPPOO3+u8mOTgBWAwBTwSc4Yc95555133nnnnXfeeefPJZ4mswdoSIVG +DYYmbUSdd95555133nnnnXfe+XOJrysAY8qhcSHRRJLhvPPOO++8884777zzzp97fN07PJZDjL14 +Mslw3nnnnXfeeeedd9555889nhAn/YPGqglUvywBzjvvvPPOO++888477/y5yjeagNUMJpsJztJh +4LzzzjvvvPPOO++8886fW/yYC1ATgieSGTnvvPPOO++8884777zz5xg/OTe4Vgg1awf1g+q88847 +77zzzjvvvPPOn7v8sAJQJxBnySQ2TTicd95555133nnnnXfe+XOFp2b3wNgd2MRYFJx33nnnnXfe +eeedd975c5enM40OrkYGNO9TlTM477zzzjvvvPPOO++88+ckj1dfe+NEgWB8asCmlQXnnXfeeeed +d9555513/pzjCXGyD3iTwcJjlQXnnXfeeeedd9555513/lzkmzqh8arB6LYm5ws477zzzjvvvPPO +O++88+cYj9dcd+OZCgRnaB9W55133nnnnXfeeeedd/4c5c/YBDyWRjSedd5555133nnnnXfeeefP +VX5sErACEJgCPskZY84777zzzjvvvPPOO+/8ucTTZPYADanQqMHQpI2o884777zzzjvvvPPOO38u +8XUFYEw5NC4kmkgynHfeeeedd95555133vlzj697h8dyiLEXTyYZzjvvvPPOO++888477/y5xxPi +pH/QWDWB6pclwHnnnXfeeeedd955550/V/lGE7CawWQzwVk6DJx33nnnnXfeeeedd975c4sfcwFq +QvBEMiPnnXfeeeedd9555513/hzj8Zrrvmr0lZu2CzQLB+S886O87N2z44rLD+zdu/vgpQf2nbdn +lAcAQCzvI5Z/18/W989R/vHDR+6/74HDh4/e87kHjhw9WT3r54/zzjvvvPPOO/8M5YcVgPplZ8kk +Nk04nN+y/PRU+3Wvu/HVN3zFFVdc2u1OiYiqiCiOBdGbb98SVt85R3kkZOIQwsbG+j333PfXf3PT +hz/8V+sbAz9/nHfeeeedd975ZyaP11x345lGB4+9uLqvzjvPjG/55te94x3/ZG5udmOj9/DDj9x+ ++2cff/zxo0ePr66uWlo2Hw2mn0xgfc7xiDg7O7t7947zztt33XXPufDCC6anp1ZWVv/zf/6d3/nd +/60Gfv4477zzzjvvvPPPNL6sAEymC83NTeYQzm9lfufOhd/4wL/ZuXPn0tLSX/7VRz/84f/z0EOH +YiGAKCqEBABqShVf3R/e6kcm7pyTPCKaSqvduuiifa973dfd+OpXLi4uHD9+/F3f+QNHjy35+eO8 +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 +Hbs6t+/ssCJ9HADwV41X4u6r6M++rM9kExM1NmQPOKB99eo1d939+5J8Ahecf64VVxDVule2WbPD +okV3PffMA5d+4nxEGPz3IgBc960fxjJDsj/VfOlZQ9VTce7802KbQzKC0xi+7ls3W/M4APz7//uQ +zDfh/xG8k1xSk5MesUI8qC4yLLzwZfxTT6+wu7cxo1t37e7cl/YTczTarL3/fW//3GcvPe20s62C +NrFLU4gVKsDauUFi3jrz2Kbi/le/YqyUq6Hs9wLA6NEtvX3bbPvjxrUDwK6duwFUctG3LqAVTwKZ +P0PwVa8B/uWX18ycWTYiFe2PHt3S21ew/LhxYwBg185d1TaoOA+J7we2/fed89bPffbShaeevWt3 +J3Nydg1Mxf7IKlU237iG2y4P1n8Z338Mr4e832sM1pDjFQV/H3Xk/IrT4xiP66//2rvPuqjUglz/ +vfNxGMD113/NuvsjRgvsNVd/sRQA8LeNV+37ccj1GZ5//mUAOOrIQ+fNP+T662+JbQI/u+1XALDu +lS1xf5YufXnu/NPaRzdffvklNnupzWU0uA1Kv/Nd5/3qlz+28UI8iFt/7etJNX9v5fXs6y/ar7jg +/HOv+9bNMt+Ef9X56rrBsYdQch7HB0l44Qfje/sK1nq++MG75s8/KA481wrmz5/pODphGOWqN5Hh +1Vp1c/kCopo2dUIkpzq6iq/pFly25lrXkeuv/5rj6Or+x6v2lV+51mJaY8XvtSbja67+og2jqa9L +2WeDfa6Uf3XyuSXzYe989c475r9y1XXxiFS0nxwRAGioj0dkddzEWe95s23zkkv+xR6x+5J4dhUK +BYDE7NKqZDxlAKDy/uzu7AaA009fYGPyFMKtt1xXkvRkfP/ZfPnBKp65Qj3MTHbRiMfLvqxn18JT +jk5WLAGAaVMn2NSNdtt62GEHyfXfdx4RrO/KjBnTrfY9VsPPmDHdxgP8VeNl777TTjvF3n1aJe++ +va/PO3Z1AMDHPvbhC84/1x60QQgl+aRy/dmxq9OafY4/7g21fm+Z7LF23ZbY47TcAkBDrCcVjk8V +13P+/JmjRzXGH73jHW+yKiqZb8L/I3gHEkncLVchSVRIFcILPwT/qcu+cs9dE2fMmF7ttnHYEacn +nuJYarbSJdc+d//8p3vj9R0AnnvmgTmHLlBaV/DVWuTkwvrcc6tsa88980B8/KqvXXfHnfclV+2l +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 +gO8XHh4eHr43350CFHZJYcPB+pQheHh4eFN7xsivCK8/4HYHvAElKs7W3OR3tgc87oDb4e9wBKKi +LREJ3OUXTq/qVwVjwu9X3O5AR4fX6fBEiEBbu8Pj8V5SfSZljK+tPXj06LHc3Ey9/7KpuWj6TYMH +Dbxr8UIiWrliSWlJ4azZi2bNXlRaUrhyxV2h3QXB8u+//+dEtLH89ezcsvZ2J75feHh4ePi+PQ/t +GjBMFBqyDQ8PD98fPBEL+BWvJ9Dh8kTEWhwu9WSDx+OVDofi8orkodEDkiM9buHzqy6v6nIFnO1e +V4fX1eFra3E5zjmsqt/l8gopL6k++flTGhtP79lTm583JSkxjjFOJIno8KH6ltb2mj178/OmEFFJ +cUHNnr0NjWcaGu01e/aWlhR1lc90ZUoyvvD9wsPDw8Nf2PPelg7WNrS/NV3bPBhkwMPDw5vdWzjz +u72u9jah+Jg14vgRZ3u74nQpXlUOGhkTGWttbvW5XKrLqbgcfr9fdfpka1ugucnVfN6jetUIUp0d +7kuqT1rq8PHjx+VNzRk/YVxKypD09DTtt3SwR8LhcGq39cOGDXU4nFr9HQ5nSsqQpMQ43R2/DB7Y +8xkPvl94eHh4+At73vPg7kQifXGhMQQ8PDy86T3jfleH0t5qs1LHeVfbGWf7OZfX5Y+J4qpfOX/O +42hX2tsVZ4fwq9zZoTaddZ/5oqO11dfhUpiqRnC13eG6pPpMnZpLRFddnT9mTKrd3pSWNir4zEbz +aakjzje3EJHd3hQfH6fVPz4+zm5vam1zMsa6YgAW/IWO7xceHh4e/lI975kw1P0MicINJghJMIKH +h4c3q7dw7nE4hc+nejxue5Onqdl3vi3gdLV/4fjiaHtTQ0fzWY+j2d/W7GtqaDtT39J+3u33KB0e +f0uHP4IUn9vt8XovqT7jxqU9//zLty74wYKF99bXf64NA9DeSk0dnpmRXlAwbfdHNURie1V1ft6U +0WnD01JT8qbmbq+qJqJz55snTEjPzEhfuvQ2fd7PwcNH7famnJxMfL/w8PDw8BfjjYGC3vU5eA4e +Hh7e3D4i0jZiYGQs+VvPnm9qONt6xt7x5fmOL863NJ5vPtnS0tDecqK16Yj9/GenW4+fdbe0+lrb +3K0tnvY2R0uTJeDocLR7XJ5Lqk9OTubHn/xN8zU1e/PzpmiT9tjtTVdfk79589rq6t2bNr9NxJ96 +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 +Chameleon can be installed on any BIOS bootable device such as USB flash drives, hard drives, and of course off a cd-rom.Installing ChameleonChameleon 2.0 includes it’s own installer package which will install the required boot loader components as well as the new themes onto a hard drive or other bootable device. Once the install is complete you will need to reboot your computer to use the new boot loader featuresTo get started, double click on the Chameleon Installer.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 +Click “Continue” and you will be given the option of selecting, “Install” using the default settings, “Customize” to pick addition options or “Change Install Location” to pick a different volume to install to.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 +fr8lz+TQ0NC2bdtue9vb/uVf/mV/f/8iPqUqEgodbSkvBL3ki561az5widXddPnFF7H5BVbzaOf8 +BKUT7v5X3/zQm+aROJKsKQRkRP/7v//7xBNPvNOd7nSjG93okEMOwWasKRBmqyzg/PnPf/7Vr371 +rW9966KLLj799HufccYZSwGOm8/ZShJ2tBWZVd90F7H5BVat7acbzi3v/7TS8Xd91Lc+8uZupENm +zSIwOTn5tre97aqrrnrCE55w5zvfOfrrti0BO8eHz775zW++973vPfjgg5/1rGcNDg62lVwIs4M1 +jd+lFdi103QX3vwCq9b20yXnlvcLU9olVGtYTA/YNddc87KXveywww8rl+wssnrtuMBZ7YKt8Gbh +mACv1arV2pVXXvGGN7xhw4YNz3zmM3tmTfWLrOF22qbqa6TpLkrzC6wW8qje4n5PrdRnrshu0xaD +tcYRmJ6eZlL3oosuesUrXrF169bqdLVWSl+cNisaTWemdZgtTaNSBqZbtmw58/Fnnv36s//nf/6H +md5KZZF3JMhqkp2yDyM68zNk1IHbdGlCuDk1m9T6bFIEN4/md6BgpQoKGcrMhV/5nV/Zj9+JXCBW +s6mu8Co9W1zw1zgCtLm9e/d+/etfv8997oKYn60AABNXSURBVMMYi3UUAKHjVt8tvxuIfv7zn3/1 +q1/97W9/y7Tncccdx94cFly7SbgUMp/73OcOP/zwW93qVouoHKBAg+ccApTwN23eBGhf+cpX7nGP +e2zatKl7rLov1VLo7D73FS658KbLNMx55533y1/+EpyPP/54Wuxd73rXLmvN2+fVV19Nj3/LW97y +Zje72Vx/qX/9139917ve9YMf/KDL7BbY/BaOVaGc7Ey83vWud5vb3KbAX3gwR+a+973vXe5yl5e8 +5CVzUrtArGbLC7WL/L48W07BPxAR4L3vy1/+Mk8F3QH0+PjY8PCI9Qupb+hyVPpP//RPb3zTGx/x +iEfc4ua32Llz54c+9KEf/uCHZ5999pwAueyyyzBRRx111JxStRWmADzkN7/ZzdvGzo9pUzs8TMlR +zrHRMXxA+8UvfsE7xP3vf/+BgYH5aY5U80NggU33ggsuOOtvz+K17z6n36e/0v+db3/n7W9/+w++ +361to3mPj48fcb0jXvziFw8PD5Nw48aN3VekVk3vZNP25tqNW2DzWyBWrSX853/+Z147bnXLub2t +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 +Custom InstallIf you select Customize you have the option of selecting different themes or variables to be passed at boot time to the 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 +nTBQml1rxFu8DJedZUCz0B43btzDDz/M0/PPP3/BggWpVOo73/nO1772NdK8/PLLP//5zxOJRCAQ +ePHFF2V6UtbW1nKg9K233soys30uCiGysbFxn332YTXKHDR48OBnn332iiuugAk+55xzjj322GJq +A5y777479V533XU/+tGP/FpWrlx58cUX19XVUfu1114Lx/zJJ5/84Ac/+PKXv/yHP/yhqqqKSY30 +s2fPPvfcc8877zzK7KKW4hpVeKulAIOt+ENg+ShH3RNPPHH00UdDFsbhT3/602eeeYax+vWvf51b +1BkwoAcccMCVV175wx/+8MADDzziiCOI//GPf/zaa6+R5cwzz+STIcBwZZRi8DJ37lwGpByTG5nU +bTq4kWsvro65Zc2aNe+///7kyZOJh+wslKEzrD+E+vDDD4lMp9PHHXccH/V7771HZEVFBVTda6+9 +eLS+HSF9ce09CPfUf0MPqlJZePf2wuUtNwUjy6PBSGsCUyEb50SIcxN4TEhpzS2ts1pasb8dUG7W +NjaGgnokbLamcolsCkVmsmB2C+56eSH4HTG4LJ0O1bU0Dq4uKQlF5n7eAIjqlgYy57Pu6nob5Sje +dJE34EpX7I1hOMKJFt4CYbnXhafEwLCSmD/BfdoaJ6QBq0H867JFpjDA2i8Dm5qa+OZvv/32M844 +g6ff/va3x48fz/gGBRncVHLRRRcxF5x++ul8EqbJUW24AfZaWlqYVhj0iIU7zPWrX/3qoIMOIi+f +zUMPPZRh808uxwTEJ1RaWvqlL33pkEMOKV77UywK/t/+9rdHHXUUEl3SUAslh8Pha665ZptttgE1 +EQftsMMO6FreeecdCn/llVeY40488UQaTztB1rPOOotlbxe1qJGrKAAFGGz+h7B48eLPPvsMgGQs +3XfffYcddhgJ4FDfffddvothw4aR2LKse++9l2HGcpOMq1evZvwT+Mc//lFfX//CCy+0trYec8wx +DOlRo0bx9He/+91dd90VCoUOPfRQPpzicb5x6F/cwY1TY2e1RCKRSy+9FOto1iXMMCRjRQ6JoJ6U +oqPBkaQj5he/+AVEjkajrLOffPJJEq9vR0jfWUu6GW/JibWbqVWy3lCgPvVMXeruoJXRHSuRz6bz +Hts4bVuP2/lsPocREIa1wYhWVa7hoYqKsnmvNcFhKx7iWRhKoiortWRcy7naiKHRgdaw1+ct1ANa +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 +OptionsEHCIacquireCan fix some rare USB issues on boot.ForceWakeCleans the hibernate image on resumeGUIGUI bootloader on or ofUHCIresetReset USB for some rare USB issues on bootThemes Default theme and Twilight are offered as for you to use ExtrasKexts for AHCI and Intel PIIXATA will get installed into /ExtraFinishing Chameleon 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 +AIiiN1GskHUrjUTiV1y6fmQg9+6L5k6eWdO9Pi2wtqUy6EohJTrEzEplNr0vWkSoy9QxEVO29tgy +lMdZQQhDIPihRSvvHPjVdzcdcWrnSWd2oosIqCZIgP3eCaBUhPrM5+xuWwoCGB7gkx0TkQkqXowZ +dvLIl7c6D9TiLRV9Q1P+YnOTLpevTbAip8snkGksZdoNKVkPmR9LD2JUOa4jKEAUjBSkWYuEfI6d +1nA4pwqBkDXNMqkWqCkbFwchwz9qFOia2Mkjxo0Uf6v2iUTE98BqcWq6WgY9UoyKVQVlBZCG4uKW +BJOGJECiDzmbcJCY+CFOz8awmdKa00RFxkYM8zMYSuOZZTzbaomyErkysEtZbxGl2K/Iz03D9wFZ +Ahmhw3b2JNAJJKeBUyRX0FaCBPK8PJHDEE178AKlXPlRA6UEVMG8ufOOHfuHrVu3bti6YfNQ1+p1 +6/oK/QPFwZHSWDKQyvFV09czUhusaQjWtYSb20Ktc+tmTe2YMqN9Bjvl4jR205MresarcOSWyCbC +hARedAnsNByl/3zNNdfw4yGCW5Xv+tjYGD8hAulnn302X/Rntm7evHlYovvuu++JJ5546KGHYqFe +ccUVb33rWzdv3vzRj370zjvv5Od3+umnX3jhhXQ2Kf7LX/7yxz/+8X333ce89vPOO+/d73735Zdf +DvSC2a9//etPPvlkcl599dWXf+fSM97WMaM92fVU8hMXrJy3Z8OcPRpv+sVG1M7xp0/f5wjZx9df +tWnNY8M9G9OdUxNLDms5/IQOFNqPv7pmdCifHitc/J5HTztn+p771197xaYtmzPvuXg+MzozmdKd +v9l67239g1uzOGYPOrpt6T+0xRPBvp7Mdz+5btbCurl71d36q15qOeaMSfsua8ZkQQmiW1Hu7H1P +pdyODBemhELT59Zi3skSKgVYQ/nrH25e++hYJBrcZ1nLiW+crNU1Ji3X7FxX3T9yw1XdWzalmzti +J541ZdEBjVADyVfc2Penm/v6e7O1DZFDj2/b68DG667oSieLd1y/5aE/DV5w6QJpXvb7tWNhKKK5 +uPzBo8bcK3m57RacZf1iWnHSqbqMrxhVhnCCBHPCAZYy0bhFfYMuRHgtFbhVp0F3yixDjSlYyeZ8 +tsa2hC2y+V0yM5AvZB2zAdHm9rLBp8ZKPBWEgzrCoYMCuqsmq8gQjrgyg2SGdrSOQKWWS3FDFoNA +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 +If you see this screen, you’re done with the install and everything has installed. All you need to do now is reboot and watch your computer load the new Chameleon and enjoy the extra features that it has over the previous versions!BootingChameleon is setup to automatically boot your operating system with the default settings but has the ability to pass variables to the kernel. You can pass startup options to the kernel by pressing any key when you see the boot logo and the type them to be sent to the operating system after you hit enter.Advanced OptionsAdvanced startup options use the following syntax: [device]<kernel> [arguments]Example arguments includedevice: rd= device name> rd=*<IODeviceTree path> (Device name sample rd=/dev/disk0s2)(Device tree sample rd=*/PCI0@0/CHN0@0/@0:1)Kernel: Sometimes you need to use a different kernel for testing, or you need to use the old one after an install that didn’t work the way you wanted it too =)kernel: kernel name Example: mach_kernel.voodooFlags allow you pass arguments without having to make them a permanent config settings. Examples of valid flags are:-f This forces rebuilding of extensions cache-sBoots into a single user command line mode-vVerbose, boots in text mode showing all debug info and errors-xBoots into safe mode "Graphics Mode"="1024x768x32" : Tells VESA to boot with this resolution, the x32 is bit depth and is only compatible with VESA 3.0 and uprd=disk0s1: Tells Darwin to boot from a certain partition specified in BSD format. Disk 0 specifies first HDD and s1 specifies first partition as 0 is the MBR.cpus=1: Tells the system how many CPUs or cores to use, useful for Core Duo users.platform=X86PC: Can be used if problems with normal booting, platform=ACPI: another option if normal booting fails-legacy - Boots OS X in 32bit mode rather than 64bit if 64bit is used due to a 64bit processoridehalt=0 - May stop stutteringkernel debug flags (e.g. debug=0x144) io=0xffffffff defined in IOKit/IOKitDebug.h)Example: mach_kernel rd=disk0s1 -v "Graphics Mode"="1024x768x32@85"If the computer won't start up properly, you may be able to start it up using safe mode. Use the startup command “-x” to start up in safe mode, which ignores all cached driver files.Example: -x -vSpecial booter commands: ?memory Displays information about the computer's memory ?video Displays VESA video modes supported by the computer's BIOS. ?norescan Leaves CD-ROM rescan mode.Additional useful command-line options: config=<file> Use an alternate Boot.plist file.Boot.plistOptions useful in the com.apple.Boot.plist file:"Boot Graphics"=Yes|NoUse graphics mode or text mode when starting."Quiet Boot"=Yes|NoUse quiet boot mode (no messages or prompt).Timeout=8Number of seconds to pause at the boot: prompt."Instant Menu"=YesForce displaying the partition selection menu. GUI=NoDisable the GUI (enabled by default).USBBusFix=YesEnable the EHCI and UHCI fixes (disabled by default). EHCIacquire=YesEnable the EHCI fix (disabled by default).UHCIreset=YesEnable the UHCI fix (disabled by default).Wake=NoDisable wake up after hibernation (enabled by default). ForceWake=YesForce using the sleepimage (disabled by default). WakeImage=<file>Use an alternate sleepimage file (default path is /private/var/vm/sleepimage).DropSSDT=YesSkip the SSDT tables while relocating the ACPI tables.DSDT=<file>Use an alternate DSDT.aml file (default paths are /DSDT.aml or /Extra/DSDT.aml).Rescan=YesEnable CD-ROM rescan mode."Rescan Prompt"=YesPrompts for enable CD-ROM rescan mode.ThemesChameleon 2 lets you create or customize the boot loader themes! You can edit the file in /Extra/Themes/Default/theme.plist. The following variables are changeable in the theme.plist to customize your theme.Images and ColorChameleon 2 has user replaceable images, and colors that you can customize. The images are saved in the /Extra/Themes/Default folder. All images must be in .png format .You can change the color of all the text and other widgets by using RGB color codes. Below is a basic color code chart but the full RGB color pallet is supported.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 +Screen Set the display dimensions to use when in the graphic user interface, will attempt to find the closest one available.screen_width <key>screen_width</key><string>1024</string>1024 pixels wide screenscreen_height <key>screen_height</key><string>768</string>768 pixels high screenscreen_bgcolor <key>screen_bgcolor</key><string>#222334</string>web format #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 +iI83H53NOgKpq9L+XdBOWNjh3eR1BpZbBERABERABEQgFgH/vaBjXSl/ERABERABERCBhAlIgBNG +pwtFQAREQAREIHECEuDE2elKERABERABEUiYgAQ4YXS6UAREQAREQAQSJyABTpydrhQBERABERCB +hAlIgBNGpwtFQAREQAREIHECEuDE2elKERABERABEUiYQHzrgBNORheKQA4TcK/Tz+HMKmsiIALJ +IqAWcLJIKh4REAEREAERiIOABDgOWAoqAiIgAiIgAskiIAFOFknFIwIiIAIiIAJxEJAAxwFLQUVA +BERABEQgWQQkwMkiqXjyhQDfBMuXrCYjn8KVDIqKIzcJaBZ0bparcpVSAhKVlOJV5CKQJwTUAs6T +glY2RUAEREAEwkVAAhyu8pA1IiACIiACeUJAApwnBa1sioAIiIAIhIuABDhc5SFrREAEREAE8oRA +fAJ88ODBw4cP5wkaZVMEREAEREAEUkcgDgHet2/fzJkzv//+e00BTV15KGYREAEREIE8IRCHAO/a +tetf//rXF198IQHOk8qhbIqACIiACKSOQBwCXKRIkbJly5YsWTJ11ihmERABERABEcgTAnEIcNGi +RevWrVutWjVawGoE50n9UDZFQAREQARSRCDQTlhMvNq0adPy5ctLly7NSPCcOXNw1K5du0qVKjSL +U2SZohUBERABERCBHCbgL8A0dpctW/a3v/1t+vTpR48eZSS4cuXKFSpU6NSp08UXX9y4cWNpcA7X +D2VNBERABEQgRQT8BXj37t3vvvvu1KlTzzzzzHLlyk2aNKlNmzbHHHPMe++9R2v4z3/+c61atVJk +nKIVAREQAREQgVwl4C/AmzdvXrBgQf/+/YcPH24obN++/Y9//GPr1q1feeWVxYsXV69eXY3gXK0f +ypcIiIAIiECKCPhPwjp06BD6Wq9ePTPxitHfVatWrVu3rmnTpvRIMzZ85MiRFBmnaEVABERABEQg +Vwn4t4ArVarEzOePP/64bdu2pUqVmjt3btWqVZkR/f7772/dupWzav7mauVQvkRABERABFJHwF+A +K1as+Lvf/W7evHl33XUXY8D79+8fOHAgf5kL3bVr15YtW0qAU1c8ilkEREAERCBXCRQKsqKXruYv +v/ySqVjbtm1jKtZpp522fv36FStWoL6sRPJAU6hQoYizQZKLuMT7MA1JeBugsyIgAiIgAjlMIHUq +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 +NSYNSdi05AgtAVWD0BZNRgxTfcgI9lxNNHXVyX8WdK4yVb5EQAREQAREIIMEJMAZhK+kRUAEREAE +8peABDh/y145FwEREAERyCABCXAG4StpERABERCB/CUgAc7fslfORUAEREAEMkhAApxB+EpaBERA +BEQgfwlIgPO37JVzERABERCBDBKQAGcQvpIWAREQARHIXwIS4Pwte+VcBERABEQggwQkwBmEr6RF +QAREQATyl4AEOH/LXjkXAREQARHIIAEJcAbhK2kREAEREIH8JSABzt+yV85FQAREQAQySEACnEH4 +SloEREAERCB/CUiA87fslXMREAEREIEMEpAAZxC+kg4FgcOHDx84cCAUpsgIERCBfCIgAc6n0lZe +oxEYMWJE69ato50J5FeqVKmRI0cGCpr6QFWqVHnooYcSTmfx4sU//fSTuTxU+Uo4R7pQBMJMoGiY +jZNtIhB+AhdeeGHz5s3Db2cQC2+77bbdu3dPnTqVwLmUryB5VxgRSD8BCXD6mSvFnCLwz3/+M6fy +85/M5Gq+/pM//ReBzBNQF3Tmy0AWpJ8AncYdf/s9/PDDR48edRrw4Ycf9u7du169emeddZZpC3L2 +T3/60+WXX+4MxuGdd96Jz7nnnvvOO++YU7/++uujjz7aokWLWrVqDRky5IsvvrCXRI3Wno3q+OWX +X+655x5iO/bYY0lux44dNljA2GIFi2onBs+cOfObb7459dRTd+3a5cwX6T799NNt2rQpV65c+/bt +J06caC05/fTTp0yZ8vjjj5944olNmjS54YYbGFO3Z41j586d/fv3J3Ja2PQWtGrVatSoUTaMdwxP +PfUUKfbs2XP06NFwvvXWW+2FcohA1hPgVkzdz00n6WmlIYmk26wIk04grmpw0003FSpU6A9/+MNf +/vKXyr/9UA5j0quvvsqpLl26oBAXXXRR0aJFx48fz6kHH3yQJFatWmWCrVixgsNXXnmFw5IlSyK6 +xp+YixQp8j//8z/I1QknnFC6dOmff/6ZU7GiNVdF/Xvw4MHGjRt36NCBVG6//fbatWsjVCakR2zk +BlN9g0W1k4SOP/74Ro0akZ19+/Y584UBoOCFY8yYMZdeeil5x2FSIRiXtGzZEqUEKaceeOCBiBxt +3rwZf5OFZ5999pJLLuHwscce843hlltuKVasGC8fGFy+fPmaNWu2bds2IvKoh8Qf8YsaTJ4iEIRA +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 +CIiACCSTgAQ4mTQVlwiIgAiIgAgEJBDfJCx2V+YjB9WqVWN35YAJKJgIiIAIiIAIiICbQCAB3rdv +34cffvjKK6+sWrVq79695cuXR4D5iP1FF11Urlw5d6TyEQEREAEREAER8Cbgvxf0/v37x48f/+ij +jzZp0uTkk0+uVasWX+6bN2/ep59+OmjQID7HyzeFYqXhnpOc9GVCaUgiVu7kLwIiIAIikPMEUqcy +/i3grVu3zp07t3fv3vfcc0+JEiWKFi2KiPJ79dVX0eBFixaddNJJfPIv58tAGRQBERABERCBJBLw +EU6EdufOnXQ7t2vXjs/dlypVqlixYsWLF0eJO3XqVKRIkQ0bNhw+fDiJBikqERABERABEcgHAj4C +TNO7cuXKjPjOnDlz8+bNe/bsQYyRZHqhv/76a6SXCVm0ifOBlPIoAiIgAiIgAkkk4D8GjMrS1Xzf +ffeRKr3NzMDatGnT4sWLly5deu21115zzTUaA05ieSgqERABERCBUBFI3RiwvwADgo7oBQsWvPji +i9999x0zomnyVq1alSnQZ511VpkyZTxIpc5um2gakrBpySECIiACIpBvBFKnMoEE2In7yJEjDP06 +fTzcqbPbJpqGJGxacoiACIiACOQbgdSpjM8YsBt0cPV1XysfERABERABERABQyBuARY4ERABERAB +ERCBghOQABecoWIQAREQAREQgbgJSIDjRqYLREAEREAERKDgBCTABWeoGERABERABEQgbgIS4LiR +6QIREAEREAERKDgBCXDBGSoGERABERABEYibgAQ4bmS6QAREQAREQAQKTkACXHCGikEEREAEREAE +4iYgAY4bmS4QAREQAREQgYITkAAXnKFiEAEREAEREIG4CUiA40amC0RABERABESg4AQkwAVnqBhE +QAREQAREIG4CEuC4kekCERABERABESg4AQlwwRkqBhEQAREQARGIm4AEOG5kukAEREAEREAECk5A +AlxwhopBBERABERABOImUDTuK3SBCGQ5gUKFCmV5DnLf/F9//TX3M6kc5j0BtYDzvgrkGQCpb1YU +uIopK4pJRhaQgL8A8yp66NChAiajy0VABERABERABJwE/Lug9+/fP3v27OXLl3fq1KlZs2ZcvH79 ++nnz5lWoUOGEE04oUaKEMzq5RUAEREAEREAEghDwbwHv3bv3k08+GTFixMiRI7/88ksi3b59+0cf +ffTAAw988MEH+/btC5KMwoiACIiACIiACDgJ+Asw/c979uypUaPGgQMHXnnlla1btx5zzDGnn346 +LeD33ntvxYoVR48edcYotwiIgAiIgAiIgC8BfwFmDLh48eI9evS4+uqrt23b9u2335YrV65nz55D +hgzZsWPHsmXLjhw54puMAohAaAlQw3P1t3nzZrB/+OGH4c9gaKuHDBOB1BHwF2DSZkZimTJlOnTo +0LFjxy+++GLXrl3FihWrWbMm/c80jrm3U2efYhaB9BDYuXNn//79Z86cedtttzVv3rxVq1ajRo2y +SZ911ln09zz33HMtWrSg1wf/p59+uk2bNryMtm/ffuLEiTYkjqeeegpPXlJHjx79zjvv3Hrrreas +OxKksXfv3vXq1ePU1KlTbSS//PLLPffcQ1rHHnvs5ZdfzpuuORXL314Y1UHWiISOq+OPP/6xxx6z +NyydW08++eRpp52GARdeeOHLL79sL3ebak55U6JjbMqUKY8//viJJ57YpEmTG2644fDhwzbOWFhs +ADlEIO8I+L4ar1279sYbb/zLX/5CyPnz55977rl33HEHD44//vGPXbt2/fzzz2kBx4rETTNWyIT9 +05BEwrbpwhASiFVhTGOxdu3aqMizzz57ySWXENLIFbmoXLkyL6CFCxfmLJMQb7/99qJFi955551j +xoy59NJLCYnDZPaWW27h9RTBu+mmm8qXL897atu2bc2piEheffVVXm27dOmC0l900UVEOH78eEIe +PHiwcePGJMeIDwkZkzz8TeRR/5pMYQZaji5eccUVmHr//febwFhYunTpP/zhD6+99tpll13GqX/+ +85/mVISpNnJvSiVLlmzUqFHLli3RWqIlQmaKmGs9sJgABI742UTlEIHMEoiomRwmyx7/iBBgbp67 +7rqLJHk0MBXrpJNOon1w3HHHcXdt2rTJw5TU2W0TTUMSNi05coBArApjpKVdu3Y02kw2L7744ooV +K7IKgEMEqWzZskuWLMG9atUqJv8PHz7c0jjvvPMQWiZD0EJlvObBBx80p4iTC2kom0NnJHQdcQlJ +OCOhhcohSwwwcsKECeYUUyB508WMWP42BrfDZKpfv37YZs7yAo0eM7OSw1NOOYV2tvEnAK3tq666 +yhw6TTU+5q83JQSYhRJ0jJnAnTt3plMBtzcWEzhWuZiz+isCGSSQusrpvwyJ2/Xss882y43Mq33r +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 +IAIhJCABDmGhyCQREAEREIHcJyABzv0yVg5FQAREQARCSEACHMJCkUkiIAIiIAK5T0ACnPtlrByK +gAiIgAiEkIAEOISFIpNEQAREQARyn4AEOPfLWDkUAREQAREIIQEJcAgLRSaJgAiIgAjkPgEJcO6X +sXIoAiIgAiIQQgIS4BAWikwSAREQARHIfQJxCPDR3365j0Q5FAEREAEREIHUEwgqwEeOHPnll1++ +/PLLnTt3pt4qpSACIiACIiACOU4gqAAfPHjw888/HzFixOTJk7dv357jVJQ9ERABERABEUgxgaIB +4z98+PCaNWvWr18/bdo0BLhXr14NGzYsVKhQwMsVTAREQAREQAREwEkgaAu4aNGixYsX79GjR79+ +/RYuXPj666/PnTsXVXbGJbcIiIAIiIAIiEBAAv4tYFR23bp1ixcvZgx427ZttWrVatas2Ycffjhv +3ryzzz67b9++VapUUVM4IG4FEwEREAEREAFDwF+A9+7di9yOHTt206ZNuA8cOFCqVClaw0uWLPn7 +3/9et27drl27FilSREBFQAREQAREQASCE/AX4BIlSpx00knEOHv2bKZAX3zxxbgLFy7MoqRff/1V +I8HBWSukCIiACIiACFgChRBRexDVQQDWIB06dOinn35avXp1t27dypYty5AwAkzvNG1fj+avu2va +N7moNnh4piEJj9R1SgREQAREILcJpE5l/AXYkF26dOnUqVMZCUZ3GfStWbNmhw4dWrVq5c09dXbb +dNOQhE1Ljpwk4K5COZnNrM5U0l/cs5qGjE8zAfcjIlkV0l+Aaf5+9913f/3rX1euXFm5cmV6pGny +bt26FcfVV1/ds2dPxoNj4Uid3TbFNCRh05Ij9wi460/u5TE3cpSsR15u0FAu0knA/ZRIVm30HwNm +3Pejjz5iBfBll13WoEGD8uXL0x29cePGcePGvfvuu40bNz722GPTyUJpiYAIiIAIiEAOEPAX4C1b +ttD2ZbnRhRdeSGOX5u9ve0IfZS70Sy+9RNd0vXr1GBLOARbKggiIgAiIgAikjYC/cDLhmQY4HdEo +rjELH34VKlSgKYx/2mxVQiIgAiIgAiKQMwT8BbhatWrsvPH222/T8GXWFVOgd+zYsWrVqvfee69G +jRrHHXecxyzonMGkjIiACIiACIhAcgn4T8JitHn58uXsPfnpp5/u27cPud2/fz9t36ZNm15zzTVd +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 +EAEREAERyDcCqVMZfwE+cuTI999/zzKkZcuWMeJLFzSt2G3btjEefM0113Tv3p21SbHKI3V22xTT +kIRNSw4REAEREIF8I5A6lYmpnRYxM61o+/7yyy+DBg1q2LAhO2+wKxbzn8eNGzdhwoRjjz0WTxtY +DhEQAREQAREQgSAE/AV48+bN9D+z8HfgwIHFixdnzjM7ctAspgXMmuCff/6ZkWCPRnAQIxRGBERA +BERABPKNgL8Am1VGSC9bQBs6+PCrUaMGK4D5JX1eVb6VgfIrAiIgAiKQhwT8Bbhy5crsPfnmm2/S +8G3Xrh0NXwaAV65cSf8zS4TpglbzNw/rjbIsAiIgAiJQQAL+k7DQXaZfvfrqq5988sn+/fuR2337 +9jEM3KxZs2uvvbZr165My4plROrGrm2KaUjCpiWHCIiACIhAvhFIncr4CzCs0eANGzawFwfjwXwZ +CcVlKhZt3yZNmnioLxemzm5bA9KQhE1LDhEQAREQgXwjkDqVCSTABjcTr8yPnTfMMLDbrIiCcQdI ++oBxGpKIyJQORUAEREAE8odA6lTGfwzYUjaiaw/lEAEREAEREAERSJiAtnFOGJ0uFAEREAEREIHE +CUiAE2enK0VABERABEQgYQIS4ITR6UIREAEREAERSJyABDhxdrpSBERABERABBImIAFOGJ0uFAER +EAEREIHECUiAE2enK0VABERABEQgYQIS4ITR6UIREAEREAERSJyABDhxdrpSBERABERABBImIAFO +GJ0uFAEREAEREIHECUiAE2enK0VABERABEQgYQIS4ITR6UIREAEREAERSJyABDhxdrpSBERABERA +BBImIAFOGJ0uFAEREAEREIHECUiAE2enK0VABERABEQgYQIS4ITR6UIREAEREAERSJyABDhxdrpS +BERABERABBImIAFOGJ0uFAEREAEREIHECUiAE2enK0VABERABEQgYQIS4ITR6UIREAEREAERSJyA +BDhxdrpSBERABERABBImIAFOGJ0uFAEREAEREIHECUiAE2enK0VABERABEQgYQIS4ITR6UIREAER +EAERSJyABDhxdrpSBERABERABBImIAFOGJ0uFAEREAEREIHECQQV4KNHj+7du/fAgQOJJ6UrRUAE +REAEREAE/kOg6H8cXv/37ds3f/78H3/8sUKFCt26dStSpMjq1av5W79+/dKlS3tdqXMiIAIiIAIi +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 +dVWwJbMUAAAAAElFTkSuQmCC +The Chameleon screen layoutBackground Set the position of background.png within the screenbackground_pos_x<key>background_pos_x</key><string>-0</string>0 pixels from reverse origin along the x axisbackground_pos_y <key>background_pos_y</key><string>-0</string>0 pixels from reverse origin along the y axisLogoSet the position of logo.png within the screenlogo_pos_x <key>logo_pos_x</key><string>0</string>0 pixels from origin along the x axislogo_pos_y <key>logo_pos_y</key><string>0</string>0 pixels from origin along the y axisDevices Set the position of the device list within the screendevices_pos_x <key>devices_pos_x</key><string></string>blank to center on the x axisdevices_pos_y <key>logo_pos_y</key><string></string>blank to center on the y axisdevices_max_visible <key>devices_max_visible</key>maximum number of devices visible<string>4</string>devices_icon_spacing <key>devices_icon_spacing</key>spaces between the drive icons<string>20</string>devices_layout <key>devices_layout</key><string>horizontal</string>horizontal or vertical listdevices_bgcolor <key>devices_bgcolor</key><string>#000000</string>web format #RRGGBBdevices_transparency <key>devices_transparency</key><string>128</string>0 (Opaque) -> 255 (Transparent)Boot prompt Set the position of the boot prompt within the screenbootprompt_pos_x <key>bootprompt_pos_x</key><string></string>blank to center on the x axisbootprompt_pos_y <key>bootprompt_pos_y</key><string></string>blank to center on the y axisbootprompt_width <key>bootprompt_width</key><string>-20</string>20 pixels less than the screen's width windowbootprompt_height <key>bootprompt_height</key><string>20</string>20 pixel high windowbootprompt_textmargin_h <key>bootprompt_textmargin_h</key>8 pixel horizontal text margin left and right<string>8</string>bootprompt_textmargin_v <key>bootprompt_textmargin_v</key>4 px vertical text margin both top and bottom<string>4</string>bootprompt_bgcolor <key>bootprompt_bgcolor</key><string>0x333445</string>web format #RRGGBBbootprompt_transparency <key>bootprompt_transparency</key><string>0</string>0 (Opaque) -> 255 (Transparent)Info box Set the position of the info box within the screeninfobox_pos_x <key>infobox_pos_x</key><string></string>blank to center on the x axisinfobox_pos_y <key>infobox_pos_y</key><string></string>blank center on the y axisinfobox_width <key>infobox_width</key><string>550</string>550 pixels wideinfobox_height <key>infobox_height</key><string>406</string>406 pixels highinfobox_bgcolor <key>infobox_bgcolor</key><string>#333445</string>web format #RRGGBBinfobox_transparency <key>infobox_transparency</key><string>64</string>0 (Opaque) -> 255 (Transparent)Menu Set the position of the pop up menu within the screenmenu_pos_x <key>menu_pos_x</key><string></string>center on the x axismenu_pos_y <key>menu_pos_y</key><string></string>center on the y axismenu_bgcolor <key>menu_bgcolor</key><string>#111223</string>web format #RRGGBBmenu_transparency <key>menu_transparency</key><string>0</string>0 (Opaque) -> 255 (Transparent)Boot DisplaySet the display dimensions to use when booting the kernel, will attempt to find the closest one available.boot_width <key>boot_width</key><string>1280</string>1280 pixels wide screenboot_height <key>boot_height</key><string>1024</string>1024 pixels tall screenGetting in touchChameleon homepagehttp://chameleon.osx86.hu/E-mail : voodoo@mercurysquad.comHope you guys like the bootloader!We appreciate your feedback and supportPAGE PAGE 1 \ No newline at end of file Index: branches/slice/rev749/User_Guide_src/install_start.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: branches/slice/rev749/User_Guide_src/install_start.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Index: branches/slice/rev749/User_Guide_src/install_cust.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: branches/slice/rev749/User_Guide_src/install_cust.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Index: branches/slice/rev749/User_Guide_src/install_dest.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: branches/slice/rev749/User_Guide_src/install_dest.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Index: branches/slice/rev749/User_Guide_src/screen_format.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: branches/slice/rev749/User_Guide_src/screen_format.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Index: branches/slice/rev749/User_Guide_src/chameleon.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: branches/slice/rev749/User_Guide_src/chameleon.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Index: branches/slice/rev749/User_Guide_src/xnulogo.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: branches/slice/rev749/User_Guide_src/xnulogo.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Index: branches/slice/rev749/TODO =================================================================== --- branches/slice/rev749/TODO (revision 0) +++ branches/slice/rev749/TODO (revision 1169) @@ -0,0 +1,101 @@ +TODO List for Chameleon Boot Loader +==================================== +31.01.2011 Slice +- linux detection +- proper bootArgs when starting from CD + +27.12.2010 Slice +- numerous errors, mistakes, reservation, non-finished codes... Spaghetti sources! +- kernelcache never used (adler32 is wrong?) -- resolved +- more careful CPU detection +- readNVRAM is wrong -- resolved +- graphicsEnabler for X3100 is not good +- ATI Radeon enabler is not perfect + + +16.12.2010 Slice +- I want to implement NVRAM for use with nvram, bless, StartupDisk.prefPane, and with VoodooHDA in future. +1. Write a script rc.shutdown.local and place it into /etc +<-------------- +#!/bin/sh +nvram -p >nvram.inf +echo Hello! NVRAM is saved! +--------------> +2. Read and interpret nvram.inf to place variables into /options node +3. Prepare some other boot-time variables in the node (platform-uuid, BootOrder, FirmwareFeatures, efi-boot-device and so on) +4. Implement boot flag -c to clear growing amount of nvram savings. + +- ATI GraphicsEnabler is not perfect. +1. ATY,SCLK, ATY,MCLK, ATY,RefCLK must be read from VideoBIOS but not constant values. Excluded! +2. FakeDeviceID needed + +- Intel GraphicsEnabler needs to be corrected by calculating LCD info. Done! +-------------------------------------------------------------------------------------------------------- +- Integrate Prasys current work on options and quick shortcut modified version of 18seven + +- Add autodetection of efistring algorythm to enabke graphics enabler to beanbled by default while not conflicting whith other efi string overriden content + (original idea of Galaxy) + +- Add a more sophisticated acpi loading mechanism to enable loading custom acpi tables when dsdtdrop=y + Here's a specification to think about: + First we must care about if a forced DSDT full path has been specified (was the pb smith had in + his first tries) and take it for the DSDT path as is. + Then we have the case where no DSDT path was set where we run our usual DSDT search algorithm to find this file. + In the latter case, the file has to be named DSDT.aml and be in one of the / /Extra or bt(0,0)/Extra directory. + + Now a first idea to implement correctly the acpi tables loading would be: + + Whatever the path was hardcoded in the DSDT option or was automatically found, we extract the path part of + the DSDT file that has been successfully found and we run a loop to enumerate all other acpi files in the same directory. + Now for each acpi file found, we should compare the name with an existing acpi table found in the system that + we would normally load and replace this usual injection by the content of the file. + + Once DropDSDT=y is set, no other acpi table than dsdt is loaded, then it is the responsability of user + to provide any other acpi table. + +- Add a new module capable of writing proprietary Chameleon data to ioreg: + Using the DT__xxx() API, we will create a set of functions to write + to log info, chameleon boot info to be retrieved by helper applications... + the only public function for log info purpose of this module would be: + logMessageToIOREG(...); // var args printf style format + flushLogToIOREG(); // store a unique log info property to the ioreg + + The preferred internal behavior of the log info ioreg buffer + would be to store the messages in a consolidated buffer then only write once, + this buffer (i.e just before call the kernel) with flushLogToIOREG(); + The other public function for writing chameleon boot info data would be: + + verbose() should incorporate a call to logMessageToIOREG() + to permit helper applications to extract + this log info (i.e: the chameleon system pref pane) + +- Add API for displaying and logging messages like: + + void verbose(...) + { + ... + logMessageToIOREG("%s: %sn", title, s); + + } + + void display_and_log( const char* title, const char* msg) + { + printf("%s: %sn", title, s); + logMessageToIOREG(title,s); + } + + void deprecated(const char * s) + { + display_and_log("WARNING: Deprecated option",s); + sleep(1); + } + + void error_message(const char * s) + { + display_and_log("ERROR",s); + getc(); + } + + - Case unsensitive parsing for the bootConfig options: + should help the common/novice user to setup more easily. + Index: branches/slice/rev749/rc.shutdown.local =================================================================== --- branches/slice/rev749/rc.shutdown.local (revision 0) +++ branches/slice/rev749/rc.shutdown.local (revision 1169) @@ -0,0 +1,5 @@ +#!/bin/sh +# (c) Slice 2010 +nvram -p >nvram.inf +echo Hello! NVRAM is saved! + Index: branches/slice/rev749/cdboot/cdboot.s =================================================================== --- branches/slice/rev749/cdboot/cdboot.s (revision 0) +++ branches/slice/rev749/cdboot/cdboot.s (revision 1169) @@ -0,0 +1,596 @@ +; Copyright (c) 2003 Apple Computer, Inc. All rights reserved. +; +; @APPLE_LICENSE_HEADER_START@ +; +; Portions Copyright (c) 2003 Apple Computer, Inc. All Rights +; Reserved. This file contains Original Code and/or Modifications of +; Original Code as defined in and that are subject to the Apple Public +; Source License Version 2.0 (the "License"). You may not use this file +; except in compliance with the License. Please obtain a copy of the +; License at http://www.apple.com/publicsource and read it before using +; this file. +; +; The Original Code and all software distributed under the License are +; distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER +; EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +; INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the +; License for the specific language governing rights and limitations +; under the License. +; +; @APPLE_LICENSE_HEADER_END@ + +; +; This version of cdboot loads 256k of data. +; +; Modifications by Tamás Kosárszky on 2008-10-20 +; + +; +; Set to 1 to enable obscure debug messages. +; +DEBUG EQU 0 + +; +; Set to 1 to enable unused code. +; +UNUSED EQU 0 + +; +; Set to 1 to enable verbose mode. +; +VERBOSE EQU 1 + +; +; Various constants. +; +NULL EQU 0 +CR EQU 0x0D +LF EQU 0x0A + +; +; Macros. +; +%macro jmpabs 1 + push WORD %1 + ret +%endmacro + +%macro DebugCharMacro 1 + pushad + mov al, %1 + call print_char + call getc + popad +%endmacro + +%macro DebugPauseMacro 0 + push ax + call getc + pop ax +%endmacro + +%macro PrintCharMacro 1 + pushad + mov al, %1 + call print_char + popad +%endmacro + +%macro PutCharMacro 1 + call print_char +%endmacro + +%macro PrintHexMacro 1 + call print_hex +%endmacro + +%macro PrintString 1 + mov si, %1 + call print_string +%endmacro + +%macro LogString 1 + mov di, %1 + call log_string +%endmacro + +%if DEBUG + %define DebugChar(x) DebugCharMacro x + %define DebugPause(x) DebugPauseMacro + %define PrintChar(x) PrintCharMacro x + %define PutChar(x) PutCharMacro + %define PrintHex(x) PrintHexMacro x +%else + %define DebugChar(x) + %define DebugPause(x) + %define PrintChar(x) + %define PutChar(x) + %define PrintHex(x) +%endif + +maxSectorCount EQU 8 ; maximum sector count for readSectors +CDBootSizeMagic EQU 0xDEADFACE ; indicates if the size field was not specificed + ; at build time. +kSectorBytes EQU 2048 ; sector size in bytes +kBoot2Size EQU 65024 ; default load size for boot2 +kBoot2MaxSize EQU 458240 ; max size for boot2 +kBoot2Address EQU 0x0200 ; boot2 load address +kBoot2Segment EQU 0x2000 ; boot2 load segment + +kBoot0Stack EQU 0xFFF0 ; boot0 stack pointer + +kReadBuffer EQU 0x1000 ; disk data buffer address + +kVolSectorOffset EQU 0x47 ; offset in buffer of sector number + ; in volume descriptor +kBootSectorOffset EQU 0x28 ; offset in boot catalog + ; of sector number to load boot file +kBootCountOffset EQU 0x26 ; offset in boot catalog + ; of number of sectors to read +kCDBootSizeOffset EQU 2048 - 4 ; the file size can be found at the + ; last dword of this sector. + +;-------------------------------------------------------------------------- +; Start of text segment. + + SEGMENT .text + + ORG 0x7C00 + +;-------------------------------------------------------------------------- +; Boot code is loaded at 0:7C00h. +; + +start: + cli + jmp 0:start1 + times 8-($-$$) nop ; Put boot information table at offset 8 + +; El Torito boot information table, filled in by the +; mkisofs -boot-info-table option, if used. +bi_pvd: dd 0 ; LBA of primary volume descriptor +bi_file: dd 0 ; LBA of boot file +bi_length: dd 0 ; Length of boot file +bi_csum: dd 0 ; Checksum of boot file +bi_reserved: times 10 dd 0 ; Reserved + +start1: + xor ax, ax ; zero %ax + mov ss, ax ; setup the + mov sp, kBoot0Stack ; stack + sti + cld ; increment SI after each lodsb call + mov ds, ax ; setup the + mov es, ax ; data segments + +%if VERBOSE + LogString(init_str) +%endif + + ;; BIOS boot drive is in DL + mov [gBIOSDriveNumber], dl ; save BIOS drive number + + DebugChar('!') + DebugPause() + +%if DEBUG + mov eax, [kBoot2LoadAddr] + call print_hex + call getc +%endif + + ;; + ;; The BIOS likely didn't load the rest of the booter, + ;; so we have to fetch it ourselves. + ;; + mov edx, kReadBuffer + mov al, 1 + mov ecx, 17 + call readLBA + jc NEAR error + + DebugChar('A') + + mov ecx, [kReadBuffer + kVolSectorOffset] + +%if DEBUG + mov eax, ecx + call print_hex + DebugPause() +%endif + + mov al, 1 + call readLBA + jc error + + ;; Now we have the boot catalog in the buffer. + ;; Really we should look at the validation entry, but oh well. + + DebugChar('B') + + mov ecx, [kReadBuffer + kBootSectorOffset] + mov al, 1 + call readLBA ; reading this boot sector + + inc ecx ; skip the first sector which is what we are in + +%if DEBUG + mov eax, ecx + call print_hex + DebugPause() +%endif + + ; + ; Testing cdboot size + ; + + mov eax, [kReadBuffer + kCDBootSizeOffset] + or eax, eax + jz .useDefaultSize ; use the default size if zero + cmp eax, CDBootSizeMagic + je .useDefaultSize ; use the default size if equals to magic + cmp eax, kBoot2MaxSize + jbe .calcSectors ; use the actual size + +.useDefaultSize: + + mov eax, kBoot2Size + +%if VERBOSE + LogString(defaultsize_str) +%endif + +.calcSectors: + +%if VERBOSE + LogString(size_str) + call print_hex +%endif + + add eax, kSectorBytes - 1 ; adjust size before unit conversion + shr eax, 11 ; convert file size to CD sector unit + +%if VERBOSE + LogString(read_str) + call print_hex +%endif + +%if VERBOSE + LogString(loading_str) +%endif + + mov edx, (kBoot2Segment << 4) + kBoot2Address + call readSectors + jc error + + DebugChar('C') + +%if DEBUG + mov eax, [es:kBoot2Address] + call print_hex + DebugPause() +%endif + + DebugChar('X') + DebugPause() + + ;; Jump to newly-loaded booter + +%if VERBOSE + LogString(done_str) +%endif + +%if UNUSED + LogString(keypress_str) + call getc +%endif + + mov dl, [gBIOSDriveNumber] ; load BIOS drive number + jmp kBoot2Segment:kBoot2Address + +error: + +%if VERBOSE + LogString(error_str) +%endif + +.loop: + hlt + jmp .loop + +;; +;; Support functions +;; + +;-------------------------------------------------------------------------- +; readSectors - Reads more than 127 sectors using LBA addressing. +; +; Arguments: +; AX = number of 2048-byte sectors to read (valid from 1-320). +; EDX = pointer to where the sectors should be stored. +; ECX = sector offset in partition +; +; Returns: +; CF = 0 success +; 1 error +; +readSectors: + pushad + mov bx, ax + +.loop: + mov al, '.' + call print_char + xor eax, eax ; EAX = 0 + mov al, bl ; assume we reached the last block. + cmp bx, maxSectorCount ; check if we really reached the last block + jb .readBlock ; yes, BX < MaxSectorCount + mov al, maxSectorCount ; no, read MaxSectorCount + +.readBlock: + call readLBA + jc .exit + sub bx, ax ; decrease remaning sectors with the read amount + jz .exit ; exit if no more sectors left to be loaded + add ecx, eax ; adjust LBA sector offset + shl eax, 11 ; convert CD sectors to bytes + add edx, eax ; adjust target memory location + jmp .loop ; read remaining sectors + +.exit: + popad + ret + +;-------------------------------------------------------------------------- +; readLBA - Read sectors from a partition using LBA addressing. +; +; Arguments: +; AL = number of 512-byte sectors to read (valid from 1-127). +; EDX = pointer to where the sectors should be stored. +; ECX = sector offset in partition +; [gBIOSDriveNumber] = drive number (0x80 + unit number) +; +; Returns: +; CF = 0 success +; 1 error +; +readLBA: + pushad ; save all registers + push es ; save ES + mov bp, sp ; save current SP + + ; + ; Convert EDX to segment:offset model and set ES:BX + ; + ; Some BIOSes do not like offset to be negative while reading + ; from hard drives. This usually leads to "boot1: error" when trying + ; to boot from hard drive, while booting normally from USB flash. + ; The routines, responsible for this are apparently different. + ; Thus we split linear address slightly differently for these + ; capricious BIOSes to make sure offset is always positive. + ; + + mov bx, dx ; save offset to BX + and bh, 0x0f ; keep low 12 bits + shr edx, 4 ; adjust linear address to segment base + xor dl, dl ; mask low 8 bits + mov es, dx ; save segment to ES + + ; + ; Create the Disk Address Packet structure for the + ; INT13/F42 (Extended Read Sectors) on the stack. + ; + + ; push DWORD 0 ; offset 12, upper 32-bit LBA + push ds ; For sake of saving memory, + push ds ; push DS register, which is 0. + + push ecx + + push es ; offset 6, memory segment + + push bx ; offset 4, memory offset + + xor ah, ah ; offset 3, must be 0 + push ax ; offset 2, number of sectors + + push WORD 16 ; offset 0-1, packet size + + ; + ; INT13 Func 42 - Extended Read Sectors + ; + ; Arguments: + ; AH = 0x42 + ; [gBIOSDriveNumber] = drive number (0x80 + unit number) + ; DS:SI = pointer to Disk Address Packet + ; + ; Returns: + ; AH = return status (sucess is 0) + ; carry = 0 success + ; 1 error + ; + ; Packet offset 2 indicates the number of sectors read + ; successfully. + ; + mov dl, [gBIOSDriveNumber] ; load BIOS drive number + mov si, sp + mov ah, 0x42 + int 0x13 + + jnc .exit + + DebugChar('R') ; indicate INT13/F42 error + + ; + ; Issue a disk reset on error. + ; Should this be changed to Func 0xD to skip the diskette controller + ; reset? + ; + +%if VERBOSE + LogString(readerror_str) + mov eax, ecx + call print_hex +%endif + + xor ax, ax ; Func 0 + int 0x13 ; INT 13 + stc ; set carry to indicate error + +.exit: + mov sp, bp ; restore SP + pop es ; restore ES + popad + ret + +;-------------------------------------------------------------------------- +; Write a string with 'cdboot: ' prefix to the console. +; +; Arguments: +; ES:DI pointer to a NULL terminated string. +; +; Clobber list: +; DI +; +log_string: + pushad + + push di + mov si, log_title_str + call print_string + + pop si + call print_string + + popad + + ret + +;------------------------------------------------------------------------- +; Write a string to the console. +; +; Arguments: +; DS:SI pointer to a NULL terminated string. +; +; Clobber list: +; AX, BX, SI +; +print_string: + mov bx, 1 ; BH=0, BL=1 (blue) + +.loop: + lodsb ; load a byte from DS:SI into AL + cmp al, 0 ; Is it a NULL? + je .exit ; yes, all done + mov ah, 0xE ; INT10 Func 0xE + int 0x10 ; display byte in tty mode + jmp .loop + +.exit: + ret + +;%if DEBUG + +;-------------------------------------------------------------------------- +; Write the 4-byte value to the console in hex. +; +; Arguments: +; EAX = Value to be displayed in hex. +; +print_hex: + pushad + mov cx, WORD 4 + bswap eax +.loop: + push ax + ror al, 4 + call print_nibble ; display upper nibble + pop ax + call print_nibble ; display lower nibble + ror eax, 8 + loop .loop + +%if UNUSED + mov al, 10 ; carriage return + call print_char + mov al, 13 + call print_char +%endif ; UNUSED + + popad + ret + +print_nibble: + and al, 0x0f + add al, '0' + cmp al, '9' + jna .print_ascii + add al, 'A' - '9' - 1 +.print_ascii: + call print_char + ret + +;-------------------------------------------------------------------------- +; getc - wait for a key press +; +getc: + pushad + mov ah, 0 + int 0x16 + popad + ret + +;-------------------------------------------------------------------------- +; Write a ASCII character to the console. +; +; Arguments: +; AL = ASCII character. +; +print_char: + pushad + mov bx, 1 ; BH=0, BL=1 (blue) + mov ah, 0x0e ; bios INT 10, Function 0xE + int 0x10 ; display byte in tty mode + popad + ret + +;-------------------------------------------------------------------------- +; Static data. +; + +%if VERBOSE +log_title_str db CR, LF, 'cdboot: ', NULL +init_str db 'init', NULL +defaultsize_str db 'using default size', NULL +size_str db 'file size: ', NULL +read_str db 'reading sectors: ', NULL +loading_str db 'loading', NULL +done_str db 'done', NULL +readerror_str db 'BIOS disk read error at sector: ', NULL +error_str db 'error', NULL +%endif + +%if UNUSED +keypress_str db 'Press any key to continue...', NULL +%endif + + +;; Pad this file to a size of 2048 bytes (one CD sector). +pad: + times 2044-($-$$) db 0 + +CDBootSize dd CDBootSizeMagic + +;; Location of loaded boot2 code. +kBoot2LoadAddr equ $ + +; +; Global variables +; + + ABSOLUTE kReadBuffer + kSectorBytes + +gBIOSDriveNumber resw 1 + +; END Index: branches/slice/rev749/cdboot/cdboothdd.s =================================================================== --- branches/slice/rev749/cdboot/cdboothdd.s (revision 0) +++ branches/slice/rev749/cdboot/cdboothdd.s (revision 1169) @@ -0,0 +1,502 @@ +; Copyright (c) 2003 Apple Computer, Inc. All rights reserved. +; +; @APPLE_LICENSE_HEADER_START@ +; +; Portions Copyright (c) 2003 Apple Computer, Inc. All Rights +; Reserved. This file contains Original Code and/or Modifications of +; Original Code as defined in and that are subject to the Apple Public +; Source License Version 2.0 (the "License"). You may not use this file +; except in compliance with the License. Please obtain a copy of the +; License at http://www.apple.com/publicsource and read it before using +; this file. +; +; The Original Code and all software distributed under the License are +; distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER +; EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +; INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the +; License for the specific language governing rights and limitations +; under the License. +; +; @APPLE_LICENSE_HEADER_END@ + +; +; This version of cdboot loads the MBR of bios drive 0x80. +; +; Modifications by Tamás Kosárszky on 2009-03-30 +; + +; +; Set to 1 to enable obscure debug messages. +; +DEBUG EQU 0 + +; +; Set to 1 to enable unused code. +; +UNUSED EQU 0 + +; +; Set to 1 to enable verbose mode. +; +VERBOSE EQU 1 + +; +; Various constants. +; +NULL EQU 0 +CR EQU 0x0D +LF EQU 0x0A + +; +; Macros. +; +%macro jmpabs 1 + push WORD %1 + ret +%endmacro + +%macro DebugCharMacro 1 + pushad + mov al, %1 + call print_char + call getc + popad +%endmacro + +%macro DebugPauseMacro 0 + push ax + call getc + pop ax +%endmacro + +%macro PrintCharMacro 1 + pushad + mov al, %1 + call print_char + popad +%endmacro + +%macro PutCharMacro 1 + call print_char +%endmacro + +%macro PrintHexMacro 1 + call print_hex +%endmacro + +%macro PrintString 1 + mov si, %1 + call print_string +%endmacro + +%macro LogString 1 + mov di, %1 + call log_string +%endmacro + +%if DEBUG + %define DebugChar(x) DebugCharMacro x + %define DebugPause(x) DebugPauseMacro + %define PrintChar(x) PrintCharMacro x + %define PutChar(x) PutCharMacro + %define PrintHex(x) PrintHexMacro x +%else + %define DebugChar(x) + %define DebugPause(x) + %define PrintChar(x) + %define PutChar(x) + %define PrintHex(x) +%endif + +kBoot0Segment EQU 0x0000 +kBoot0Stack EQU 0xFFF0 ; boot0 stack pointer +kBoot0LoadAddr EQU 0x7C00 ; boot0 load address +kBoot0RelocAddr EQU 0xE000 ; boot0 relocated address +kSectorBytes EQU 2048 ; sector size in bytes +maxSectorCount EQU 32 ; maximum sector count for readSectors + +;-------------------------------------------------------------------------- +; Start of text segment. + + SEGMENT .text + + ORG kBoot0RelocAddr + +;-------------------------------------------------------------------------- +; Boot code is loaded at 0:7C00h. +; + +start: + cli + jmp start1 + times 8-($-$$) nop ; Put boot information table at offset 8 + +; El Torito boot information table, filled in by the +; mkisofs -boot-info-table option, if used. +bi_pvd: dd 0 ; LBA of primary volume descriptor +bi_file: dd 0 ; LBA of boot file +bi_length: dd 0 ; Length of boot file +bi_csum: dd 0 ; Checksum of boot file +bi_reserved: times 10 dd 0 ; Reserved + +;-------------------------------------------------------------------------- + +start1: + ; + ; Set up the stack to grow down from kBoot0Segment:kBoot0Stack. + ; Interrupts should be off while the stack is being manipulated. + ; + cli ; interrupts off + xor ax, ax ; zero ax + mov ss, ax ; ss <- 0 + mov sp, kBoot0Stack ; sp <- top of stack + sti ; reenable interrupts + + mov es, ax ; es <- 0 + mov ds, ax ; ds <- 0 + + ; + ; Relocate boot0 code. + ; + mov si, kBoot0LoadAddr ; si <- source + mov di, kBoot0RelocAddr ; di <- destination + cld ; auto-increment SI and/or DI registers + mov cx, kSectorBytes/2 ; copy 256 words + repnz movsw ; repeat string move (word) operation + + ; + ; Code relocated, jump to start_reloc in relocated location. + ; + jmp kBoot0Segment:start_reloc + +;-------------------------------------------------------------------------- +; Start execution from the relocated location. +; +start_reloc: + +%if VERBOSE + LogString(init_str) +%endif + +%if VERBOSE + LogString(read_str) +%endif + + ; forcing BIOS Int 13h operations to use drive 0x80 + mov WORD [gBIOSDriveNumber], 0x80 ; save BIOS drive number + mov al, 1 + mov edx, kBoot0LoadAddr ; load MBR code to 0x7C00 + mov ecx, 0 ; load sector 0 of drive 0x80 + call readLBA + +%if VERBOSE + LogString(done_str) +%endif + +%if UNUSED + LogString(keypress_str) + call getc +%endif + + ; Jump to newly-loaded booter + mov dl, [gBIOSDriveNumber] ; load BIOS drive number + jmp kBoot0Segment:kBoot0LoadAddr + +error: + +%if VERBOSE + LogString(error_str) +%endif + +.loop: + hlt + jmp .loop + +;; +;; Support functions +;; + +;-------------------------------------------------------------------------- +; readSectors - Reads more than 127 sectors using LBA addressing. +; +; Arguments: +; AX = number of 2048-byte sectors to read (valid from 1-320). +; EDX = pointer to where the sectors should be stored. +; ECX = sector offset in partition +; +; Returns: +; CF = 0 success +; 1 error +; +readSectors: + pushad + mov bx, ax + +.loop: + mov al, '.' + call print_char + xor eax, eax ; EAX = 0 + mov al, bl ; assume we reached the last block. + cmp bx, maxSectorCount ; check if we really reached the last block + jb .readBlock ; yes, BX < MaxSectorCount + mov al, maxSectorCount ; no, read MaxSectorCount + +.readBlock: + call readLBA + jc .exit + sub bx, ax ; decrease remaning sectors with the read amount + jz .exit ; exit if no more sectors left to be loaded + add ecx, eax ; adjust LBA sector offset + shl eax, 11 ; convert CD sectors to bytes + add edx, eax ; adjust target memory location + jmp .loop ; read remaining sectors + +.exit: + popad + ret + +;-------------------------------------------------------------------------- +; readLBA - Read sectors from a partition using LBA addressing. +; +; Arguments: +; AL = number of 512-byte sectors to read (valid from 1-127). +; EDX = pointer to where the sectors should be stored. +; ECX = sector offset in partition +; [gBIOSDriveNumber] = drive number (0x80 + unit number) +; +; Returns: +; CF = 0 success +; 1 error +; +readLBA: + pushad ; save all registers + push es ; save ES + mov bp, sp ; save current SP + + ; + ; Convert EDX to segment:offset model and set ES:BX + ; + ; Some BIOSes do not like offset to be negative while reading + ; from hard drives. This usually leads to "boot1: error" when trying + ; to boot from hard drive, while booting normally from USB flash. + ; The routines, responsible for this are apparently different. + ; Thus we split linear address slightly differently for these + ; capricious BIOSes to make sure offset is always positive. + ; + + mov bx, dx ; save offset to BX + and bh, 0x0f ; keep low 12 bits + shr edx, 4 ; adjust linear address to segment base + xor dl, dl ; mask low 8 bits + mov es, dx ; save segment to ES + + ; + ; Create the Disk Address Packet structure for the + ; INT13/F42 (Extended Read Sectors) on the stack. + ; + + ; push DWORD 0 ; offset 12, upper 32-bit LBA + push ds ; For sake of saving memory, + push ds ; push DS register, which is 0. + + push ecx + + push es ; offset 6, memory segment + + push bx ; offset 4, memory offset + + xor ah, ah ; offset 3, must be 0 + push ax ; offset 2, number of sectors + + push WORD 16 ; offset 0-1, packet size + + ; + ; INT13 Func 42 - Extended Read Sectors + ; + ; Arguments: + ; AH = 0x42 + ; [gBIOSDriveNumber] = drive number (0x80 + unit number) + ; DS:SI = pointer to Disk Address Packet + ; + ; Returns: + ; AH = return status (sucess is 0) + ; carry = 0 success + ; 1 error + ; + ; Packet offset 2 indicates the number of sectors read + ; successfully. + ; + mov dl, [gBIOSDriveNumber] ; load BIOS drive number + mov si, sp + mov ah, 0x42 + int 0x13 + + jnc .exit + + DebugChar('R') ; indicate INT13/F42 error + + ; + ; Issue a disk reset on error. + ; Should this be changed to Func 0xD to skip the diskette controller + ; reset? + ; + +%if VERBOSE + LogString(readerror_str) + mov eax, ecx + call print_hex +%endif + + xor ax, ax ; Func 0 + int 0x13 ; INT 13 + stc ; set carry to indicate error + +.exit: + mov sp, bp ; restore SP + pop es ; restore ES + popad + ret + +;-------------------------------------------------------------------------- +; Write a string with 'cdboot: ' prefix to the console. +; +; Arguments: +; ES:DI pointer to a NULL terminated string. +; +; Clobber list: +; DI +; +log_string: + pushad + + push di + mov si, log_title_str + call print_string + + pop si + call print_string + + popad + + ret + +;------------------------------------------------------------------------- +; Write a string to the console. +; +; Arguments: +; DS:SI pointer to a NULL terminated string. +; +; Clobber list: +; AX, BX, SI +; +print_string: + mov bx, 1 ; BH=0, BL=1 (blue) + +.loop: + lodsb ; load a byte from DS:SI into AL + cmp al, 0 ; Is it a NULL? + je .exit ; yes, all done + mov ah, 0xE ; INT10 Func 0xE + int 0x10 ; display byte in tty mode + jmp .loop + +.exit: + ret + +;%if DEBUG + +;-------------------------------------------------------------------------- +; Write the 4-byte value to the console in hex. +; +; Arguments: +; EAX = Value to be displayed in hex. +; +print_hex: + pushad + mov cx, WORD 4 + bswap eax +.loop: + push ax + ror al, 4 + call print_nibble ; display upper nibble + pop ax + call print_nibble ; display lower nibble + ror eax, 8 + loop .loop + +%if UNUSED + mov al, 10 ; carriage return + call print_char + mov al, 13 + call print_char +%endif ; UNUSED + + popad + ret + +print_nibble: + and al, 0x0f + add al, '0' + cmp al, '9' + jna .print_ascii + add al, 'A' - '9' - 1 +.print_ascii: + call print_char + ret + +;-------------------------------------------------------------------------- +; getc - wait for a key press +; +getc: + pushad + mov ah, 0 + int 0x16 + popad + ret + +;-------------------------------------------------------------------------- +; Write a ASCII character to the console. +; +; Arguments: +; AL = ASCII character. +; +print_char: + pushad + mov bx, 1 ; BH=0, BL=1 (blue) + mov ah, 0x0e ; bios INT 10, Function 0xE + int 0x10 ; display byte in tty mode + popad + ret + +;-------------------------------------------------------------------------- +; Static data. +; + +%if VERBOSE +log_title_str db CR, LF, 'cdboot: ', NULL +init_str db 'init', NULL +read_str db 'reading MBR from device 0x80', NULL +done_str db 'done', NULL +readerror_str db 'BIOS disk read error at sector: ', NULL +error_str db 'error', NULL +%endif + +%if UNUSED +keypress_str db 'Press any key to continue...', NULL +%endif + + +;; Pad this file to a size of 2048 bytes (one CD sector). +pad: + times 2048-($-$$) db 0 + +; +; Global variables +; + + ABSOLUTE kBoot0RelocAddr + kSectorBytes + +gBIOSDriveNumber resw 1 + +; END Index: branches/slice/rev749/cdboot/Makefile =================================================================== --- branches/slice/rev749/cdboot/Makefile (revision 0) +++ branches/slice/rev749/cdboot/Makefile (revision 1169) @@ -0,0 +1,28 @@ + +DIR = cdboot +include ../MakePaths.dir + +NASM = $(shell which nasm) +#/Developer/usr/bin/nasm +INSTALLDIR = $(DSTROOT)/usr/standalone/i386 +DIRS_NEEDED = $(SYMROOT) + +all embedtheme optionrom: $(DIRS_NEEDED) cdboot + +cdboot: cdboot.s $(SYMROOT)/boot Makefile $(NASM) + @echo "\t[NASM] cdboot.s" + @$(NASM) cdboot.s -o $(SYMROOT)/cdboot + @dd if=$(SYMROOT)/boot of=$(SYMROOT)/cdboot conv=sync bs=2k seek=1 &> /dev/null + + @# Update cdboot with boot file size info + @stat -f%z $(SYMROOT)/boot \ + | perl -ane "print pack('V',@F[0]);" \ + | dd of=$(SYMROOT)/cdboot bs=1 count=4 seek=2044 conv=notrunc &> /dev/null + +install_i386:: all $(INSTALLDIR) + cp $(SYMROOT)/cdboot $(INSTALLDIR) + cd $(INSTALLDIR); chmod u+w cdboot + +include ../MakeInc.dir + +#dependencies Index: branches/slice/rev749/util/bdmesg.c =================================================================== --- branches/slice/rev749/util/bdmesg.c (revision 0) +++ branches/slice/rev749/util/bdmesg.c (revision 1169) @@ -0,0 +1,38 @@ +/* + * BooterLog Dump Tool, part of the Chameleon Boot Loader Project + * + * Copyright 2010 by Islam M. Ahmed Zaid. All rights reserved. + * + */ + +#include +#include +#include +#include + +#include "IOKit/IOKitLib.h" + + +int main(int argc, char *argv[]) +{ + io_registry_entry_t root = IORegistryEntryFromPath(kIOMasterPortDefault, "IOService:/"); + if (!root) + { + printf("IORegistryEntry \"IOIOService:/\" not found.\n"); + return 0; + } + + CFTypeRef bootLog = IORegistryEntryCreateCFProperty(root, CFSTR("boot-log"), kCFAllocatorDefault, 0); + if (!bootLog) + { + printf("\"boot-log\" property not found.\n"); + return 0; + } + //CFShow(bootLog); + const UInt8 *msglog = CFDataGetBytePtr((CFDataRef)bootLog); + if (msglog) + printf("%s\n", msglog); + + return 0; +} + Index: branches/slice/rev749/util/Makefile.old =================================================================== --- branches/slice/rev749/util/Makefile.old (revision 0) +++ branches/slice/rev749/util/Makefile.old (revision 1169) @@ -0,0 +1,41 @@ +# +# Until I can remove the dependency on the appkit, +# we'll just keep the generated files in this directory +# and install them directly, rather than generating them again. +# + +DIR = util +include ../MakePaths.dir + +VPATH = $(OBJROOT):$(SYMROOT) + +INSTALLDIR = $(DSTROOT)/usr/standalone/i386 +LOCALBIN = $(DSTROOT)/usr/local/bin + +OPTIM = -Os -Oz +CFLAGS = $(RC_CFLAGS) $(OPTIM) -Wmost -Werror -g +LDFLAGS = +CFILES = machOconv.c +ALLSRC = $(CFILES) $(MFILES) $(HFILES) $(EXPORT_HFILES) + +PROGRAMS = machOconv bdmesg + +OUTFILES = $(PROGRAMS) + +DIRS_NEEDED = $(OBJROOT) $(SYMROOT) $(LANGDIR) + +all embedtheme optionrom: $(DIRS_NEEDED) $(PROGRAMS) + +machOconv: machOconv.o + @echo "\t[LD] $@" + @$(CC) $(CFLAGS) $(LDFLAGS) $(DEFINES) -o $(SYMROOT)/$(@F) machOconv.o + +bdmesg: bdmesg.o + @echo "\t[LD] $@" + @$(CC) $(CFLAGS) $(LDFLAGS) -framework IOKit -framework CoreFoundation -mmacosx-version-min=10.5 -o $(SYMROOT)/$(@F) bdmesg.o + +include ../MakeInc.dir + +#dependencies +-include $(OBJROOT)/Makedep + Index: branches/slice/rev749/util/Makefile =================================================================== --- branches/slice/rev749/util/Makefile (revision 0) +++ branches/slice/rev749/util/Makefile (revision 1169) @@ -0,0 +1,41 @@ +# +# Until I can remove the dependency on the appkit, +# we'll just keep the generated files in this directory +# and install them directly, rather than generating them again. +# + +DIR = util +include ../MakePaths.dir + +VPATH = $(OBJROOT):$(SYMROOT) + +INSTALLDIR = $(DSTROOT)/usr/standalone/i386 +LOCALBIN = $(DSTROOT)/usr/local/bin + +OPTIM = -Os -Oz +CFLAGS = $(RC_CFLAGS) $(OPTIM) -Wmost -Werror -g +LDFLAGS = +CFILES = machOconv.c +ALLSRC = $(CFILES) $(MFILES) $(HFILES) $(EXPORT_HFILES) + +PROGRAMS = machOconv bdmesg + +OUTFILES = $(PROGRAMS) + +DIRS_NEEDED = $(OBJROOT) $(SYMROOT) $(LANGDIR) + +all embedtheme optionrom: $(DIRS_NEEDED) $(PROGRAMS) + +machOconv: machOconv.o + @echo "\t[LD] $@" + @$(CC) $(CFLAGS) $(LDFLAGS) $(DEFINES) -o $(SYMROOT)/$(@F) machOconv.o + +bdmesg: bdmesg.o + @echo "\t[LD] $@" + @$(CC) $(CFLAGS) $(LDFLAGS) -framework IOKit -framework CoreFoundation -mmacosx-version-min=10.5 -o $(SYMROOT)/$(@F) bdmesg.o + +include ../MakeInc.dir + +#dependencies +-include $(OBJROOT)/Makedep + Index: branches/slice/rev749/util/machOconv.c =================================================================== --- branches/slice/rev749/util/machOconv.c (revision 0) +++ branches/slice/rev749/util/machOconv.c (revision 1169) @@ -0,0 +1,158 @@ +/* + * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 2.0 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int infile, outfile; + +struct mach_header mh; +void * cmds; + +static bool swap_ends; + +static unsigned long swap( + unsigned long x +) +{ + if (swap_ends) + return OSSwapInt32(x); + else + return x; +} + +int +main(int argc, char *argv[]) +{ + kern_return_t result; + vm_address_t data; + int nc, ncmds; + char * cp; + + if (argc == 2) { + infile = open(argv[1], O_RDONLY); + if (infile < 0) + goto usage; + outfile = fileno(stdout); + } + else if (argc == 3) { + infile = open(argv[1], O_RDONLY); + if (infile < 0) + goto usage; + outfile = open(argv[2], O_WRONLY|O_CREAT|O_TRUNC, 0644); + if (outfile < 0) + goto usage; + } + else { +usage: + fprintf(stderr, "usage: machOconv inputfile [outputfile]\n"); + exit(1); + } + + nc = read(infile, &mh, sizeof (mh)); + if (nc < 0) { + perror("read mach header"); + exit(1); + } + if (nc < (int)sizeof (mh)) { + fprintf(stderr, "read mach header: premature EOF %d\n", nc); + exit(1); + } + if (mh.magic == MH_MAGIC) + swap_ends = false; + else if (mh.magic == MH_CIGAM) + swap_ends = true; + else { + fprintf(stderr, "bad magic number %lx\n", (unsigned long)mh.magic); + exit(1); + } + + cmds = calloc(swap(mh.sizeofcmds), sizeof (char)); + if (cmds == 0) { + fprintf(stderr, "alloc load commands: no memory\n"); + exit(1); + } + nc = read(infile, cmds, swap(mh.sizeofcmds)); + if (nc < 0) { + perror("read load commands"); + exit(1); + } + if (nc < (int)swap(mh.sizeofcmds)) { + fprintf(stderr, "read load commands: premature EOF %d\n", nc); + exit(1); + } + + for ( ncmds = swap(mh.ncmds), cp = cmds; + ncmds > 0; ncmds--) { + bool isDATA; + unsigned vmsize; + +#define lcp ((struct load_command *)cp) + switch(swap(lcp->cmd)) { + + case LC_SEGMENT: +#define scp ((struct segment_command *)cp) + isDATA = (strcmp(scp->segname, "__DATA") == 0); + if (isDATA) + vmsize = swap(scp->filesize); + else + vmsize = swap(scp->vmsize); + result = vm_allocate(mach_task_self(), &data, vmsize, true); + if (result != KERN_SUCCESS) { + mach_error("vm_allocate segment data", result); + exit(1); + } + + lseek(infile, swap(scp->fileoff), L_SET); + nc = read(infile, (void *)data, swap(scp->filesize)); + if (nc < 0) { + perror("read segment data"); + exit(1); + } + if (nc < (int)swap(scp->filesize)) { + fprintf(stderr, "read segment data: premature EOF %d\n", nc); + exit(1); + } + + nc = write(outfile, (void *)data, vmsize); + if (nc < (int)vmsize) { + perror("write segment data"); + exit(1); + } + + vm_deallocate(mach_task_self(), data, vmsize); + break; + } + + cp += swap(lcp->cmdsize); + } + + exit(0); +} Index: branches/slice/doc/themeinfo.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: branches/slice/doc/Users_Guide0.5.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: branches/slice/doc/BootHelp.txt =================================================================== --- branches/slice/doc/BootHelp.txt (revision 1168) +++ branches/slice/doc/BootHelp.txt (revision 1169) @@ -1,119 +0,0 @@ -The boot: prompt waits for you to type advanced startup options. -If you don't type anything, the computer continues starting up normally. It -uses the kernel and configuration files on the startup device, which it also -uses as the root device. - -Advanced startup options use the following syntax: - - [device] [arguments] - -Example arguments include - - device: rd= (e.g. rd=disk0s2) - rd=* (e.g. rd=*/PCI0@0/CHN0@0/@0:1) - - kernel: kernel name (e.g. "mach_kernel" - must be in "/" ) - - flags: -v (verbose) -s (single user mode) - -x (safe mode) -f (ignore caches) - -F (ignore "Kernel Flags" specified in boot configuration file) - - "Graphics Mode"="WIDTHxHEIGHTxDEPTH" (e.g. "1024x768x32") - - kernel flags (e.g. debug=0x144) - io=0xffffffff (defined in IOKit/IOKitDebug.h) - -Example: mach_kernel rd=disk0s1 -v "Graphics Mode"="1920x1200x32" - -If the computer won't start up properly, you may be able to start it up -using safe mode. Type -x to start up in safe mode, which ignores all -cached driver files. - -Special booter hotkeys: - F5 Rescans optical drive. - F10 Scans and displays all BIOS accessible drives. - -Special booter commands: - ?memory Displays information about the computer's memory. - ?video Displays VESA video modes supported by the computer's BIOS. - ?norescan Leaves optical drive rescan mode. - -Additional useful command-line options: - config= Use an alternate Boot.plist file. - -Options useful in the com.apple.Boot.plist file: - Wait=Yes|No Prompt for a key press before starting the kernel. - "Quiet Boot"=Yes|No Use quiet boot mode (no messages or prompt). - Timeout=8 Number of seconds to pause at the boot: prompt. - "Instant Menu"=Yes Force displaying the partition selection menu. - - "Default Partition" Sets the default boot partition, - =hd(x,y)|UUID|"Label" Specified as a disk/partition pair, an UUID, or a - label enclosed in quotes. - - "Hide Partition" Remove unwanted partition(s) from the boot menu. - =partition Specified, possibly multiple times, as hd(x,y), an - [;partition2 ...] UUID or label enclosed in quotes. - - "Rename Partition" Rename partition(s) for the boot menu. - =partition Where partition is hd(x,y), UUID or label enclosed - [;partition2 in quotes. The alias can optionally be quoted too. - ...] - - GUI=No Disable the GUI (enabled by default). - "Boot Banner"=Yes|No Show boot banner in GUI mode (enabled by default). - "Legacy Logo"=Yes|No Use the legacy grey apple logo (disabled by default). - - DropSSDT=Yes Skip the SSDT tables while relocating the ACPI tables. - DSDT= Use an alternate DSDT.aml file - (default path: /DSDT.aml /Extra/DSDT.aml bt(0,0)/Extra/DSDT.aml). - - GenerateCStates=Yes Enable auto generation of Processor (C-States) and/or - GeneratePStates=Yes Performance (P-States) power states. - - EnableC2State=Yes Enable specific Processor power states, - EnableC3State=Yes C2, C3, C4. - EnableC4State=Yes - - - PciRoot= Use an alternate value for PciRoot (default value 0). - - GraphicsEnabler=Yes|No Automatic device-properties generation for gfx cards. - UseAtiROM=Yes|No Use an alternate Ati ROM image - (path: /Extra/_.rom) - UseNvidiaROM=Yes|No Use an alternate Nvidia ROM image - (path: /Extra/_.rom) - VBIOS=Yes|No Inject VBIOS to device-properties. - - EthernetBuiltIn=Yes|No Automatic "built-in"=yes device-properties generation - for ethernet interfaces. - - USBBusFix=Yes Enable all USB fixes below: - EHCIacquire=Yes Enable the EHCI fix (disabled by default). - UHCIreset=Yes Enable the UHCI fix (disabled by default). - USBLegacyOff=Yes Enable the USB Legacy fix (disabled by default). - - ForceHPET=Yes|No Force Enable HPET. - - Wake=No Disable wake up after hibernation (default: enabled). - ForceWake=Yes Force using the sleepimage (disabled by default). - WakeImage= Use an alternate sleepimage file. - (default path is /private/var/vm/sleepimage). - - SMBIOS= Use an alternate SMBIOS.plist file - (default path: /Extra/SMBIOS.plist bt(0,0)/Extra/SMBIOS.plist). - - SMBIOSdefaults=No Don't use the Default values for SMBIOS overriding - if smbios.plist doesn't exist, factory - values are kept. - - "Scan Single Drive" Scan the drive only where the booter got loaded from. - =Yes|No Fix rescan pbs when using a DVD reader in AHCI mode. - Rescan=Yes Enable CD-ROM rescan mode. - "Rescan Prompt"=Yes Prompts for enable CD-ROM rescan mode. - SystemId= Set manually the system id UUID, - SMUUID in smbios config (reserved field) isn't used. - SystemType= Set the system type where n is between 0..6 - (default =1 (Desktop) - md0= Load raw img file into memory for use as XNU's md0 - ramdisk. /Extra/Postboot.img is used otherwise. Index: branches/slice/doc/README =================================================================== --- branches/slice/doc/README (revision 1168) +++ branches/slice/doc/README (revision 1169) @@ -1,87 +0,0 @@ - - Chameleon Boot Loader - ===================== - - What is it? - ----------- - - Chameleon is combination of various boot loader components. It is based - on David Elliott's fake EFI implementation added to Apple's boot-132 - project. Chameleon is extended with the following key features: - - - Features - -------- - - - Device Property Injection via device-properties string in com.apple.Boot.plist - - hybrid boot0+boot1h loaders for both MBR and GPT partitioned disks. - - automatic FSB detection code even for recent AMD CPUs. - - Apple Software RAID support. - - stage2 loader (boot) can be placed as a regular file in the boot - partition's root folder. - - - Installation - ============ - - Normal Install (non-RAID): - -------------------------- - - Suppose that your installation is on /dev/disk0s2 - - - Install boot0 to the MBR: - sudo ./fdisk440 -f boot0 -u -y /dev/rdisk0 - - - Install boot1h to the partition's bootsector: - sudo dd if=boot1h of=/dev/rdisk0s2 - - - Install boot to the partition's root directory: - sudo cp boot / - - No need to use startupfiletool anymore! - - - RAID Install: - ------------- - - Suppose that your installation is on /dev/disk3, which is either a mirror- or a - stripeset consisting of /dev/disk0 and /dev/disk1 - - Mac OS X creates a small helper partition at the end of each RAID member disk, - namely /dev/disk0s3 and /dev/disk1s3 - - - Install boot0 to the MBR of both disks: - sudo ./fdisk440 -f boot0 -u -y /dev/rdisk0 - sudo ./fdisk440 -f boot0 -u -y /dev/rdisk1 - - - Install boot1h to the bootsector of each boot partition: - sudo dd if=boot1h of=/dev/rdisk0s3 - sudo dd if=boot1h of=/dev/rdisk1s3 - - - Install boot to both helper partition's root directories. - diskutil mount disk0s3 - cp boot /Volumes/Boot\ OSX - diskutil unmount disk0s3 - diskutil mount disk1s3 - cp boot /Volumes/Boot\ OSX - diskutil unmount disk1s3 - - Support: - -------- - - If you have any questions, issues etc. feel free to join us - at irc.voodooprojects.org #chameleon - - - Source Code - ----------- - - For downloading the source code please visit the project page at - http://chameleon.osx86.hu - - - Licensing - --------- - - Chameleon is released under the terms and conditions of - Apple Public Source License (see APPLE_LICENSE). Index: branches/slice/i386/MakeInc.dir =================================================================== --- branches/slice/i386/MakeInc.dir (revision 1168) +++ branches/slice/i386/MakeInc.dir (revision 1169) @@ -1,81 +0,0 @@ -# -# Common makefile targets. -# -# Define these variables (if desired) in directory makefiles: -# DIRS_NEEDED -# INSTALLDIR -# SRCROOT -# -ifneq "" "$(wildcard /bin/mkdirs)" - MKDIRS = /bin/mkdirs -else - MKDIRS = /bin/mkdir -p -endif - -CPP = g++ -fno-exceptions -fno-rtti - - -# Toggle this as to whether you want a frame pointer (%ebp) to be used. It is -# invaluable for debugging the booter. For example using GDB attached to VMware. -# In fact, it's so invaluable that it's now the default. Not only that but the -# compiler seems to generate slightly smaller code and the real<->prot code -# clearly handles it appropriately so I have no idea why Apple omitted it. -#OMIT_FRAME_POINTER_CFLAG=-fomit-frame-pointer -OMIT_FRAME_POINTER_CFLAG= - -installsrc:: $(SRCROOT) - cp $(ALLSRC) $(SRCROOT) - cd $(SRCROOT); chmod a-w $(ALLSRC) - -install:: installhdrs - @if [ -z "$(RC_ARCHS)" -o -n "$(RC_i386)" ]; then \ - $(MAKE) install_i386 OBJROOT=${OBJROOT} \ - SYMROOT=${SYMROOT} DSTROOT=${DSTROOT} \ - SRCROOT=${SRCROOT}; \ - else \ - echo i386 not selected - null build.; \ - fi - -install_i386:: all - -installhdrs:: - -.SUFFIXES: .s .i .c .o - -.c.o .m.o: - @echo "\t[CC] $<" - @$(CC) $(CPPFLAGS) $(CFLAGS) $(DEFINES) -c $(INC) $< -o $(OBJROOT)/$*.o \ - -MD -dependency-file $(OBJROOT)/$*.d - @md -u $(OBJROOT)/Makedep -f -d $(OBJROOT)/$*.d - -$(OBJROOT)/%.o: %.c - @echo "\t[CC] $<" - @$(CC) $(CPPFLAGS) $(CFLAGS) $(DEFINES) -c $(INC) $< -o $(OBJROOT)/$*.o \ - -MD -dependency-file $(OBJROOT)/$*.d - @md -u $(OBJROOT)/Makedep -f -d $(OBJROOT)/$*.d - -$(OBJROOT)/%.o: %.m - @echo "\t[CC] $<" - @$(CC) $(CPPFLAGS) $(CFLAGS) $(DEFINES) -c $(INC) $< -o $(OBJROOT)/$*.o \ - -MD -dependency-file $(OBJROOT)/$*.d - @md -u $(OBJROOT)/Makedep -f -d $(OBJROOT)/$*.d - -#.s.o: -# cc $(INC) -E $< > $(OBJROOT)/$*.o2 -# $(AS) -o $(OBJROOT)/$@ $(OBJROOT)/$*.o2 - -.s.o: - @echo "\t[AS] $<" - @cc $(CPPFLAGS) -c $(INC) -arch i386 -o $(OBJROOT)/$(@F) $< - -boot2.o: - @echo "\t[AS] boot2.s" - @cc $(CPPFLAGS) -Wa,-n -c $(INC) -arch i386 -o $(OBJROOT)/$(@F) boot2.s - -$(OBJROOT)/%.o: %.s - @echo "\t[CC] $<" - @cc $(CPPFLAGS) -c $(INC) -arch i386 -o $(OBJROOT)/$(@F) $< - -$(DIRS_NEEDED) $(INSTALLDIR) $(SRCROOT): - @echo "\t[MKDIR] $@" - @$(MKDIRS) $@ Index: branches/slice/i386/MakePaths.dir =================================================================== --- branches/slice/i386/MakePaths.dir (revision 1168) +++ branches/slice/i386/MakePaths.dir (revision 1169) @@ -1,9 +0,0 @@ -# -# Default paths for subdirectories. -# - -OBJROOT=../../obj/i386/$(DIR) -SYMROOT=../../sym/i386 -DSTROOT=../../dst/i386 -SRCROOT=/tmp - Index: branches/slice/i386/Makefile =================================================================== --- branches/slice/i386/Makefile (revision 1168) +++ branches/slice/i386/Makefile (revision 1169) @@ -1,65 +0,0 @@ - -# Makefile for i386 boot program -# define FLOPPY and SMALL using DEFINES macro as necessary - -CFLAGS = -O $(MORECPP) -arch i386 -g -static -DEFINES= -CONFIG = hd -LIBDIR = libsa -INC = -I. -I$(LIBDIR) -ifneq "" "$(wildcard /bin/mkdirs)" - MKDIRS = /bin/mkdirs -else - MKDIRS = /bin/mkdir -p -endif -AS = as -LD = ld - -# -# these paths are only valid in subdirectories of this directory -# -OBJROOT=`pwd`/../../obj/i386 -SYMROOT=`pwd`/../../sym/i386 -DSTROOT=`pwd`/../../dst/i386 -SRCROOT=/tmp - -VPATH = $(OBJROOT):$(SYMROOT) - -# The order of building is important. -SUBDIRS = util libsa libsaio boot2 boot1 boot0 cdboot modules - -all embedtheme optionrom tags debug install installhdrs: - @for i in ${SUBDIRS}; \ - do \ - echo ================= make $@ for $$i =================; \ - ( cd $$i; ${MAKE} \ - "OBJROOT=$(OBJROOT)/$$i" \ - "SYMROOT=$(SYMROOT)" \ - "DSTROOT=$(DSTROOT)" \ - "SRCROOT=$(SRCROOT)" \ - "RC_ARCHS=$(RC_ARCHS)" \ - "RC_KANJI=$(RC_KANJI)" \ - "JAPANESE=$(JAPANESE)" \ - "RC_CFLAGS=$(RC_CFLAGS)" $@ \ - ) || exit $$?; \ - done - -modules: - @for i in "modules"; \ - do \ - echo ================= make $@ for $$i =================; \ - ( cd $$i; ${MAKE} \ - "OBJROOT=$(OBJROOT)/$$i" \ - "SYMROOT=$(SYMROOT)" \ - "DSTROOT=$(DSTROOT)" \ - "SRCROOT=$(SRCROOT)" \ - "RC_ARCHS=$(RC_ARCHS)" \ - "RC_KANJI=$(RC_KANJI)" \ - "JAPANESE=$(JAPANESE)" \ - "RC_CFLAGS=$(RC_CFLAGS)" $@ \ - ) || exit $$?; \ - done - - -installsrc: - tar cf - . | (cd ${SRCROOT}; tar xfBp -) Index: branches/slice/etc/rc.shutdown.local =================================================================== --- branches/slice/etc/rc.shutdown.local (revision 1168) +++ branches/slice/etc/rc.shutdown.local (revision 1169) @@ -1,5 +0,0 @@ -#!/bin/sh -# (c) Slice 2010 -nvram -p >nvram.inf -echo Hello! NVRAM is saved! - Index: branches/slice/etc/rc.local =================================================================== --- branches/slice/etc/rc.local (revision 1168) +++ branches/slice/etc/rc.local (revision 1169) @@ -1,6 +0,0 @@ -#!/bin/bash -cat bdmesg.log >bdmesg.lo1 -date "+DATE: %Y-%m-%d TIME: %H:%M:%S%n" >> bdmesg.lo1 -bdmesg >>bdmesg.lo1 -tail -n 500 bdmesg.lo1 >bdmesg.log -rm bdmesg.lo1 \ No newline at end of file Index: branches/slice/package/Distribution =================================================================== --- branches/slice/package/Distribution (revision 1168) +++ branches/slice/package/Distribution (revision 1169) @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - Chameleon_title - - Index: branches/slice/package/fdisk =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: branches/slice/package/buildpkg =================================================================== --- branches/slice/package/buildpkg (revision 1168) +++ branches/slice/package/buildpkg (revision 1169) @@ -1,292 +0,0 @@ -#!/bin/bash - -# $1 Path to store built package - -packagesidentity="org.chameleon" - -packagename="Chameleon" - -pkgroot="${0%/*}" - -#version=$( grep I386BOOT_CHAMELEONVERSION sym/i386/vers.h | awk '{ print $3 }' | tr -d '\"' ) -version=$( cat version ) -stage=${version##*-} -revision=$( grep I386BOOT_CHAMELEONREVISION sym/i386/vers.h | awk '{ print $3 }' | tr -d '\"' ) -builddate=$( grep I386BOOT_BUILDDATE sym/i386/vers.h | awk '{ print $3,$4 }' | tr -d '\"' ) -timestamp=$( date -j -f "%Y-%m-%d %H:%M:%S" "${builddate}" "+%s" ) - -distributioncount=0 -xmlindent=0 - -indent[0]="\t" -indent[1]="\t\t" -indent[2]="\t\t\t" -indent[3]="\t\t\t\t" - -main () -{ - -# clean up the destination path - - rm -R -f "${1}" - - echo "Building $packagename Install Package v${version%%-*} $stage r$revision $builddate" - - outline[$((outlinecount++))]="${indent[$xmlindent]}" - -# build core package - - mkdir -p ${1}/Core/Root/usr/sbin - mkdir -p ${1}/Core/Root/usr/local/bin - mkdir -p ${1}/Core/Root/usr/standalone/i386 - cp -f ${1%/*}/i386/boot ${1}/Core/Root/usr/standalone/i386 - cp -f ${1%/*}/i386/boot0 ${1}/Core/Root/usr/standalone/i386 - cp -f ${1%/*}/i386/boot1f32 ${1}/Core/Root/usr/standalone/i386 - cp -f ${1%/*}/i386/boot1h ${1}/Core/Root/usr/standalone/i386 - cp -f ${1%/*}/i386/boot1he ${1}/Core/Root/usr/standalone/i386 - cp -f ${1%/*}/i386/boot1hp ${1}/Core/Root/usr/standalone/i386 - cp -f ${1%/*}/i386/cdboot ${1}/Core/Root/usr/standalone/i386 - cp -f ${1%/*}/i386/chain0 ${1}/Core/Root/usr/standalone/i386 - fixperms "${1}/Core/Root/" - cp -f ${pkgroot}/fdisk ${1}/Core/Root/usr/sbin - local coresize=$( du -hkc "${1}/Core/Root" | tail -n1 | awk {'print $1'} ) - buildpackage "${1}/Core" "/" "0" "start_visible=\"false\" start_selected=\"true\"" - -# build standard package - - mkdir -p ${1}/Standard/Root - mkdir -p ${1}/Standard/Scripts/Tools - cp -f ${pkgroot}/Scripts/Standard/* ${1}/Standard/Scripts - ditto --arch i386 `which SetFile` ${1}/Standard/Scripts/Tools/SetFile - buildpackage "${1}/Standard" "/" "${coresize}" "start_enabled=\"true\" start_selected=\"upgrade_allowed()\" selected=\"exclusive(choices['EnhancedHFS']) && exclusive(choices['EnhancedFAT'])\"" - -# build efi fat32 package - - mkdir -p ${1}/EnhancedFAT/Root - mkdir -p ${1}/EnhancedFAT/Scripts/Tools - cp -f ${pkgroot}/Scripts/FAT/* ${1}/EnhancedFAT/Scripts - ditto --arch i386 `which SetFile` ${1}/EnhancedFAT/Scripts/Tools/SetFile - buildpackage "${1}/EnhancedFAT" "/" "${coresize}" "start_visible=\"systemHasGPT()\" start_selected=\"false\" selected=\"exclusive(choices['Standard']) && exclusive(choices['EnhancedHFS'])\"" - -# build efi hfs package - - mkdir -p ${1}/EnhancedHFS/Root - mkdir -p ${1}/EnhancedHFS/Scripts/Tools - cp -f ${pkgroot}/Scripts/HFS/* ${1}/EnhancedHFS/Scripts - ditto --arch i386 `which SetFile` ${1}/EnhancedHFS/Scripts/Tools/SetFile - buildpackage "${1}/EnhancedHFS" "/" "${coresize}" "start_visible=\"systemHasGPT()\" start_selected=\"false\" selected=\"exclusive(choices['Standard']) && exclusive(choices['EnhancedFAT'])\"" - -# build options packages - - outline[$((outlinecount++))]="${indent[$xmlindent]}\t" - choices[$((choicescount++))]="\n\n" - ((xmlindent++)) - packagesidentity="org.chameleon" - options=($( find "${pkgroot}/Scripts/Options" -type d -depth 1 -not -name '.svn' )) - for (( i = 0 ; i < ${#options[@]} ; i++ )) - do - mkdir -p "${1}/${options[$i]##*/}/Root" - mkdir -p "${1}/${options[$i]##*/}/Scripts" - - ditto --noextattr --noqtn "${options[$i]}/postinstall" "${1}/${options[$i]##*/}/Scripts/postinstall" - - buildpackage "${1}/${options[$i]##*/}" "/" "" "start_selected=\"false\"" - done - ((xmlindent--)) - outline[$((outlinecount++))]="${indent[$xmlindent]}\t" - -# build theme packages - - outline[$((outlinecount++))]="${indent[$xmlindent]}\t" - choices[$((choicescount++))]="\n\n" - ((xmlindent++)) - packagesidentity="org.chameleon.theme" - artwork="${1%/*}" - themes=($( find "${artwork%/*}/artwork/themes" -type d -depth 1 -not -name '.svn' )) - for (( i = 0 ; i < ${#themes[@]} ; i++ )) - do - theme=$( echo ${themes[$i]##*/} | awk 'BEGIN{OFS=FS=""}{$1=toupper($1);print}' ) - mkdir -p "${1}/${theme}/Root/" - ditto --noextattr --noqtn "${themes[$i]}" "${1}/${themes[$i]##*/}/Root/${theme}" - find "${1}/${themes[$i]##*/}" -name '.DS_Store' -or -name '.svn' -exec rm -R {} \+ - find "${1}/${themes[$i]##*/}" -type f -exec chmod 644 {} \+ - - buildpackage "${1}/${theme}" "/.Chameleon/Extra/Themes" "" - rm -R -f "${1}/${i##*/}" - done - - ((xmlindent--)) - outline[$((outlinecount++))]="${indent[$xmlindent]}\t" - - outline[$((outlinecount++))]="${indent[$xmlindent]}\t" - choices[$((choicescount++))]="\n\n" - - ((xmlindent++)) - -# build kext packages - - outline[$((outlinecount++))]="${indent[$xmlindent]}\t" - choices[$((choicescount++))]="\n\n" - ((xmlindent++)) - packagesidentity="org.chameleon" - kexts=($( find "${pkgroot}/Kexts" -type d -name '*.kext' -depth 1 )) - for (( i = 0 ; i < ${#kexts[@]} ; i++ )) - do - filename="${kexts[$i]##*/}" - mkdir -p "${1}/${filename%.kext}/Root/" - ditto --noextattr --noqtn --arch i386 "${kexts[$i]}" "${1}/${filename%.kext}/Root/${filename}" - find "${1}/${filename%.kext}" -name '.DS_Store' -or -name '.svn' -exec rm -R -f {} \; 2>/dev/null - fixperms "${1}/${filename%.kext}/Root/" - chown 501:20 "${1}/${filename%.kext}/Root/" - buildpackage "${1}/${filename%.kext}" "/.Chameleon/Extra/Extensions" "" - rm -R -f "${1}/${filename%.kext}" - done - - ((xmlindent--)) - outline[$((outlinecount++))]="${indent[$xmlindent]}\t" - - ((xmlindent--)) - outline[$((outlinecount++))]="${indent[$xmlindent]}\t" - -# build post install package - - mkdir -p ${1}/Post/Root - mkdir -p ${1}/Post/Scripts - cp -f ${pkgroot}/Scripts/Post/* ${1}/Post/Scripts - buildpackage "${1}/Post" "/" "" "start_visible=\"false\" start_selected=\"true\"" - outline[$((outlinecount++))]="${indent[$xmlindent]}" - -# build meta package - - makedistribution "${1}" "${2}" "${3}" "${4}" "${5}" - -# clean up - - rm -R -f "${1}" - -} - -fixperms () -{ - # $1 path - find "${1}" -type f -exec chmod 644 {} \; - find "${1}" -type d -exec chmod 755 {} \; - chown -R 0:0 "${1}" -} - -buildpackage () -{ -# $1 Path to package to build containing Root and or Scripts -# $2 Install Location -# $3 Size -# $4 Options - -if [ -d "${1}/Root" ] && [ "${1}/Scripts" ]; then - - local packagename="${1##*/}" - local identifier=$( echo ${packagesidentity}.${packagename//_/.} | tr [:upper:] [:lower:] ) - find "${1}" -name '.DS_Store' -delete - local filecount=$( find "${1}/Root" | wc -l ) - if [ "${3}" ]; then - local installedsize="${3}" - else - local installedsize=$( du -hkc "${1}/Root" | tail -n1 | awk {'print $1'} ) - fi - local header="\n\n" - header+="\t\n" - rm -R -f "${1}/Temp" - - [ -d "${1}/Temp" ] || mkdir -m 777 "${1}/Temp" - [ -d "${1}/Root" ] && mkbom "${1}/Root" "${1}/Temp/Bom" - - if [ -d "${1}/Scripts" ]; then - header+="\t\n" - for script in $( find "${1}/Scripts" -type f \( -name 'pre*' -or -name 'post*' \) ) - do - header+="\t\t<${script##*/} file=\"./${script##*/}\"/>\n" - done - header+="\t\n" - chown -R 0:0 "${1}/Scripts" - pushd "${1}/Scripts" >/dev/null - find . -print | cpio -o -z -H cpio > "../Temp/Scripts" - popd >/dev/null - fi - - header+="" - echo -e "${header}" > "${1}/Temp/PackageInfo" - pushd "${1}/Root" >/dev/null - find . -print | cpio -o -z -H cpio > "../Temp/Payload" - popd >/dev/null - pushd "${1}/Temp" >/dev/null - - xar -c -f "${1%/*}/${packagename// /}.pkg" --compression none . - - popd >/dev/null - - outline[$((outlinecount++))]="${indent[$xmlindent]}\t" - - if [ "${4}" ]; then - local choiceoptions="${indent[$xmlindent]}${4}\n" - fi - choices[$((choicescount++))]="\n\t#${packagename// /}.pkg\n\n" - - rm -R -f "${1}" -fi -} - -makedistribution () -{ - rm -f "${1%/*}/${packagename// /}"*.pkg - - find "${1}" -type f -name '*.pkg' -depth 1 | while read component - do - mkdir -p "${1}/${packagename}/${component##*/}" - pushd "${1}/${packagename}/${component##*/}" >/dev/null - xar -x -f "${1%}/${component##*/}" - popd >/dev/null - done - - ditto --noextattr --noqtn "${pkgroot}/Distribution" "${1}/${packagename}/Distribution" - ditto --noextattr --noqtn "${pkgroot}/Resources" "${1}/${packagename}/Resources" - - find "${1}/${packagename}/Resources" -type d -name '.svn' -exec rm -R -f {} \; 2>/dev/null - - for (( i=0; i < ${#outline[*]} ; i++)); - do - echo -e "${outline[$i]}" >> "${1}/${packagename}/Distribution" - done - - for (( i=0; i < ${#choices[*]} ; i++)); - do - echo -e "${choices[$i]}" >> "${1}/${packagename}/Distribution" - done - - echo "" >> "${1}/${packagename}/Distribution" - - perl -i -p -e "s/%CHAMELEONVERSION%/${version%%-*}/g" `find "${1}/${packagename}/Resources" -type f` - perl -i -p -e "s/%CHAMELEONREVISION%/${revision}/g" `find "${1}/${packagename}/Resources" -type f` - - stage=${stage/RC/Release Candidate } - stage=${stage/FINAL/2.0 Final} - perl -i -p -e "s/%CHAMELEONSTAGE%/${stage}/g" `find "${1}/${packagename}/Resources" -type f` - - find "${1}/${packagename}" -name '.DS_Store' -delete - pushd "${1}/${packagename}" >/dev/null - xar -c -f "${1%/*}/${packagename// /}-${version}-r${revision}.pkg" --compression none . - popd >/dev/null - - md5=$( md5 "${1%/*}/${packagename// /}-${version}-r${revision}.pkg" | awk {'print $4'} ) - echo "MD5 (${packagename// /}-${version}-r${revision}.pkg) = ${md5}" > "${1%/*}/${packagename// /}-${version}-r${revision}.pkg.md5" -} - -main "${1}" "${2}" "${3}" "${4}" "${5}" - Index: branches/slice/package/smbios.plist =================================================================== --- branches/slice/package/smbios.plist (revision 1168) +++ branches/slice/package/smbios.plist (revision 1169) @@ -1,48 +0,0 @@ - - - - - SMbiosversion - MP31.88Z.00C1.B00.0802091544 - SMmanufacter - Apple Inc. - SMproductname - MacPro3,1 - SMsystemversion - 1.0 - SMserial - W87234JHYA4 - SMexternalclock - 333 - SMmaximalclock - 3000 - SMmemtype - 19 - SMmemspeed - 800 - SMmemmanufacter_1 - 0xAD00000000000000 - SMmemserial_1 - 0x00001020 - SMmempart_1 - 0x48594D503131325336344350362D59352020 - SMmemmanufacter_2 - 0xAD00000000000000 - SMmemserial_2 - 0x00003021 - SMmempart_2 - 0x48594D503131325336344350362D59352020 - SMmemmanufacter_3 - 0xAD00000000000000 - SMmemserial_3 - 0x00003021 - SMmempart_3 - 0x48594D503131325336344350362D59352020 - SMmemmanufacter_4 - 0xAD00000000000000 - SMmemserial_4 - 0x00003021 - SMmempart_4 - 0x48594D503131325336344350362D59352020 - -