diff --git a/COPYING b/COPYING new file mode 100644 index 0000000000..dc63aaca03 --- /dev/null +++ b/COPYING @@ -0,0 +1,340 @@ + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program 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 of the License, or + (at your option) any later version. + + This program 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 program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/src/arch/i386/boot/linuxbios_table.c b/src/arch/i386/boot/linuxbios_table.c index 6d7c51593c..c56f6263bf 100644 --- a/src/arch/i386/boot/linuxbios_table.c +++ b/src/arch/i386/boot/linuxbios_table.c @@ -1,8 +1,11 @@ +#include #include #include #include #include #include +#include + struct lb_header *lb_table_init(unsigned long addr) { @@ -73,28 +76,58 @@ struct lb_memory *lb_memory(struct lb_header *header) struct lb_mainboard *lb_mainboard(struct lb_header *header) { -#define __STR(X) #X -#define STR(X) __STR(X) - static const char vendor[] = STR(MAINBOARD_VENDOR); - static const char part_number[] = STR(MAINBOARD_PART_NUMBER); struct lb_record *rec; struct lb_mainboard *mainboard; rec = lb_new_record(header); mainboard = (struct lb_mainboard *)rec; mainboard->tag = LB_TAG_MAINBOARD; - mainboard->size = sizeof(*mainboard) + - sizeof(vendor) + sizeof(part_number); + + mainboard->size = (sizeof(*mainboard) + + strlen(mainboard_vendor) + 1 + + strlen(mainboard_part_number) + 1 + + 3) & ~3; + mainboard->vendor_idx = 0; - mainboard->part_number_idx = sizeof(vendor); + mainboard->part_number_idx = strlen(mainboard_vendor) + 1; + memcpy(mainboard->strings + mainboard->vendor_idx, - vendor, sizeof(vendor)); + mainboard_vendor, strlen(mainboard_vendor) + 1); memcpy(mainboard->strings + mainboard->part_number_idx, - part_number, sizeof(part_number)); -#undef STR -#undef __STR + mainboard_part_number, strlen(mainboard_part_number) + 1); + return mainboard; } +void lb_strings(struct lb_header *header) +{ + static const struct { + uint32_t tag; + const uint8_t *string; + } strings[] = { + { LB_TAG_VERSION, linuxbios_version, }, + { LB_TAG_EXTRA_VERSION, linuxbios_extra_version, }, + { LB_TAG_BUILD, linuxbios_build, }, + { LB_TAG_COMPILE_TIME, linuxbios_compile_time, }, + { LB_TAG_COMPILE_BY, linuxbios_compile_by, }, + { LB_TAG_COMPILE_HOST, linuxbios_compile_host, }, + { LB_TAG_COMPILE_DOMAIN, linuxbios_compile_domain, }, + { LB_TAG_COMPILER, linuxbios_compiler, }, + { LB_TAG_LINKER, linuxbios_linker, }, + { LB_TAG_ASSEMBLER, linuxbios_assembler, }, + }; + int i; + for(i = 0; i < sizeof(strings)/sizeof(strings[0]); i++) { + struct lb_string *rec; + size_t len; + rec = lb_new_record(header); + len = strlen(strings[i].string); + rec->tag = strings[i].tag; + rec->size = (sizeof(*rec) + len + 1 + 3) & ~3; + memcpy(rec->string, strings[i].string, len+1); + } + +} + /* Some version of gcc have problems with 64 bit types so * take an unsigned long instead of a uint64_t for now. */ @@ -109,6 +142,19 @@ void lb_memory_range(struct lb_memory *mem, mem->size += sizeof(mem->map[0]); } +static void lb_memory_rangek(struct lb_memory *mem, + uint32_t type, unsigned long startk, unsigned long endk) +{ + int entries; + entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]); + mem->map[entries].start = startk; + mem->map[entries].start <<= 10; + mem->map[entries].size = endk - startk; + mem->map[entries].size <<= 10; + mem->map[entries].type = type; + mem->size += sizeof(mem->map[0]); +} + static void lb_reserve_table_memory(struct lb_header *head) { struct lb_record *last_rec; @@ -173,14 +219,16 @@ struct lb_memory *get_lb_mem(void) unsigned long write_linuxbios_table( unsigned long *processor_map, - unsigned long totalram, + struct mem_range *ram, unsigned long low_table_start, unsigned long low_table_end, - unsigned long rom_table_start, unsigned long rom_table_end) + unsigned long rom_table_startk, unsigned long rom_table_endk) { + unsigned long table_size; + struct mem_range *ramp; struct lb_header *head; struct lb_memory *mem; struct lb_record *rec_dest, *rec_src; - + head = lb_table_init(low_table_end); low_table_end = (unsigned long)head; #if HAVE_OPTION_TABLE == 1 @@ -191,18 +239,40 @@ unsigned long write_linuxbios_table( #endif mem = lb_memory(head); mem_ranges = mem; + /* I assume there is always ram at address 0 */ /* Reserve our tables in low memory */ - lb_memory_range(mem, LB_MEM_RESERVED, low_table_start, low_table_end - low_table_start); - lb_memory_range(mem, LB_MEM_RAM, low_table_end, 640*1024 - low_table_end); - /* Reserve the whole dos BIOS reserved area, we can probably do - * better but it isn't too important right now + table_size = (low_table_end - low_table_start); + lb_memory_range(mem, LB_MEM_TABLE, 0, table_size); + lb_memory_range(mem, LB_MEM_RAM, table_size, (ram[0].sizek << 10) - table_size); + /* Reserving pci memory mapped space will keep the kernel from booting seeing + * any pci resources. */ - lb_memory_range(mem, LB_MEM_RESERVED, 0x000a0000, 0x00060000); - /* Now show all of memory */ - lb_memory_range(mem, LB_MEM_RAM, 0x00100000, (totalram - 1024) << 10); + for(ramp = &ram[1]; ramp->sizek; ramp++) { + unsigned long startk, endk; + startk = ramp->basek; + endk = startk + ramp->sizek; + if ((startk < rom_table_startk) && (endk > rom_table_startk)) { + lb_memory_rangek(mem, LB_MEM_RAM, startk, rom_table_startk); + startk = rom_table_startk; + } + if ((startk == rom_table_startk) && (endk > startk)) { + unsigned long tend; + tend = rom_table_endk; + if (tend > endk) { + tend = endk; + } + lb_memory_rangek(mem, LB_MEM_TABLE, rom_table_startk, tend); + startk = tend; + } + if (endk > startk) { + lb_memory_rangek(mem, LB_MEM_RAM, startk, endk); + } + } /* Record our motheboard */ lb_mainboard(head); + /* Record our various random string information */ + lb_strings(head); low_table_end = lb_table_fini(head); diff --git a/src/arch/i386/config/crt0.base b/src/arch/i386/config/crt0.base index 91b2cd002b..73f22e1ba2 100644 --- a/src/arch/i386/config/crt0.base +++ b/src/arch/i386/config/crt0.base @@ -124,6 +124,6 @@ __main: jmp .Lhlt .section ".rom.data" -str_after_ram: .string "Ram Initialize?\r\n" -str_pre_main: .string "before main\r\n" +str_after_ram: .string "Copying LinuxBIOS to ram.\r\n" +str_pre_main: .string "Jumping to LinuxBIOS.\r\n" .previous diff --git a/src/arch/i386/include/arch/boot/boot.h b/src/arch/i386/include/arch/boot/boot.h index 0b9ef3b491..3ff51c3082 100644 --- a/src/arch/i386/include/arch/boot/boot.h +++ b/src/arch/i386/include/arch/boot/boot.h @@ -1,7 +1,6 @@ #ifndef ASM_I386_BOOT_H #define ASM_I386_BOOT_H -#define UBE32 #define ELF_CLASS ELFCLASS32 #define ELF_DATA ELFDATA2LSB #define ELF_ARCH EM_386 diff --git a/src/arch/i386/include/arch/i386_subr.h b/src/arch/i386/include/arch/i386_subr.h index 4a6c2c4c73..c2a9ae12b6 100644 --- a/src/arch/i386/include/arch/i386_subr.h +++ b/src/arch/i386/include/arch/i386_subr.h @@ -1,7 +1,8 @@ #ifndef I386_SUBR_H #define I386_SUBR_H -void cache_on(unsigned long totalram); +struct mem_range; +void cache_on(struct mem_range *mem); void interrupts_on(void); #endif /* I386_SUBR_H */ diff --git a/src/arch/i386/lib/console.inc b/src/arch/i386/lib/console.inc index f1133508ee..985d414460 100644 --- a/src/arch/i386/lib/console.inc +++ b/src/arch/i386/lib/console.inc @@ -2,8 +2,22 @@ jmp console0 -console_test: .string "\r\n\r\nLinuxBIOS starting...\r\n" +#define __STR(X) #X +#define STR(X) __STR(X) +#ifndef LINUXBIOS_EXTRA_VERSION +#define LINUXBIOS_EXTRA_VERSION +#endif + +console_test: + .ascii "\r\n\r\nLinuxBIOS-" + .ascii STR(LINUXBIOS_VERSION) + .ascii STR(LINUXBIOS_EXTRA_VERSION) + .ascii " " + .ascii STR(LINUXBIOS_BUILD) + .asciz " starting...\r\n" + +#undef STR /* uses: ax, dx */ #if defined(SERIAL_CONSOLE) #define __CONSOLE_INLINE_TX_AL TTYS0_TX_AL @@ -229,7 +243,7 @@ console_test: .string "\r\n\r\nLinuxBIOS starting...\r\n" #define CONSOLE_SPEW_TX_STRING(string) __CONSOLE_TX_STRING(string) #define CONSOLE_SPEW_INLINE_TX_STRING(string) __CONSOLE_INLINE_TX_STRING(string) -#if ASM_CONSOLE_LOGLEVEL <= BIOS_SPEW +#if ASM_CONSOLE_LOGLEVEL <= BIOS_EMERG #undef CONSOLE_EMERG_TX_CHAR #undef CONSOLE_EMERG_INLINE_TX_CHAR #undef CONSOLE_EMERG_TX_HEX8 diff --git a/src/arch/i386/lib/hardwaremain.c b/src/arch/i386/lib/hardwaremain.c index fa70f3ef9a..0387582787 100644 --- a/src/arch/i386/lib/hardwaremain.c +++ b/src/arch/i386/lib/hardwaremain.c @@ -42,6 +42,8 @@ static char rcsid[] = "$Id$"; #include #include #include +#include +#include #include #include #include @@ -76,7 +78,7 @@ static char rcsid[] = "$Id$"; */ static unsigned long processor_map[MAX_CPUS]; -static unsigned long cpu_initialize(unsigned long totalram) +static unsigned long cpu_initialize(struct mem_range *mem) { /* Because we busy wait at the printk spinlock. * It is important to keep the number of printed messages @@ -87,10 +89,10 @@ static unsigned long cpu_initialize(unsigned long totalram) printk_notice("Initializing CPU #%d\n", processor_id); /* some cpus need a fixup done. This is the hook for doing that. */ - cpufixup(totalram); + cpufixup(mem); /* Turn on caching if we haven't already */ - cache_on(totalram); + cache_on(mem); display_cpuid(); mtrr_check(); @@ -105,16 +107,18 @@ static unsigned long cpu_initialize(unsigned long totalram) return processor_id; } -static unsigned long get_ramsize(void) + +static struct mem_range *get_ramsize(void) { - unsigned long totalram; - totalram = sizeram(); - // can't size just yet ... - // mainboard totalram sizing may not be up yet. If it is not ready, - // take a default of 64M - if (!totalram) - totalram = 64 * 1024; - return totalram; + static struct mem_range *mem = 0; + if (!mem) { + mem = sizeram(); + } + if (!mem) { + printk_err("No memory size information!\n"); + for(;;); + } + return mem; } #ifdef SMP @@ -123,14 +127,14 @@ static atomic_t active_cpus = ATOMIC_INIT(1); void secondary_cpu_init(void) { - unsigned long totalram; + struct mem_range *mem; unsigned long id; int index; atomic_inc(&active_cpus); printk_debug(__FUNCTION__ "\n"); - totalram = get_ramsize(); - id = cpu_initialize(totalram); + mem = get_ramsize(); + id = cpu_initialize(mem); index = processor_index(id); printk_debug(__FUNCTION__ " %d/%u\n", index, id); processor_map[index] = CPU_ENABLED; @@ -153,7 +157,7 @@ static void wait_for_other_cpus(void) } active_count = atomic_read(&active_cpus); } - for (i = 0; i < MAX_CPUS; i++) { + for(i = 0; i < MAX_CPUS; i++) { if (!(processor_map[i] & CPU_ENABLED)) { printk_err("CPU %d/%u did not initialize!\n", i, initial_apicid[i]); @@ -185,7 +189,7 @@ static void remove_logical_cpus(void) #endif /* SMP */ -void write_tables(unsigned long totalram) +void write_tables(struct mem_range *mem) { unsigned long low_table_start, low_table_end; unsigned long rom_table_start, rom_table_end; @@ -193,7 +197,7 @@ void write_tables(unsigned long totalram) rom_table_start = 0xf0000; rom_table_end = 0xf0000; /* Start low addr at 16 bytes instead of 0 because of a buglet - * in the generic linux bunzip code, as it tests for the a20 line. + * in the generic linux unzip code, as it tests for the a20 line. */ low_table_start = 0; low_table_end = 16; @@ -202,6 +206,7 @@ void write_tables(unsigned long totalram) check_pirq_routing_table(); /* This table must be betweeen 0xf0000 & 0x100000 */ rom_table_end = copy_pirq_routing_table(rom_table_end); + rom_table_end = (rom_table_end + 1023) & ~1023; /* copy the smp block to address 0 */ post_code(0x96); @@ -214,9 +219,9 @@ void write_tables(unsigned long totalram) low_table_end = 0x500; } /* The linuxbios table must be in 0-4K or 960K-1M */ - write_linuxbios_table(processor_map, totalram, + write_linuxbios_table(processor_map, mem, low_table_start, low_table_end, - rom_table_start, rom_table_end); + rom_table_start >> 10, rom_table_end >> 10); } void hardwaremain(int boot_complete) @@ -244,8 +249,9 @@ void hardwaremain(int boot_complete) * things, so that the other work can use the PciRead* and PciWrite* * functions. */ - unsigned long totalram = 0; - extern void linuxbiosmain(unsigned long membase, unsigned long totalram); + struct mem_range *mem, *tmem; + unsigned long totalmem; + extern void linuxbiosmain(struct mem_range *mem); // we don't call post code for this one -- since serial post could cause real // trouble. @@ -254,8 +260,9 @@ void hardwaremain(int boot_complete) displayinit(); post_code(0x39); - - printk_notice("LinuxBIOS %s...\n", (boot_complete) ? "rebooting" : "booting"); + printk_notice("LinuxBIOS-%s%s %s %s...\n", + linuxbios_version, linuxbios_extra_version, linuxbios_build, + (boot_complete)?"rebooting":"booting"); post_code(0x40); @@ -278,12 +285,17 @@ void hardwaremain(int boot_complete) // So you really need to run this before you size ram. framebuffer_on(); - totalram = get_ramsize(); + mem = get_ramsize(); post_code(0x70); - printk_info("totalram: %ldM\n", totalram/1024); + totalmem = 0; + for(tmem = mem; tmem->sizek; tmem++) { + totalmem += tmem->sizek; + } + printk_info("totalram: %ldM\n", + (totalmem + 512) >> 10); /* Round to the nearest meg */ /* Fully initialize the cpu before configuring the bus */ - boot_cpu = cpu_initialize(totalram); + boot_cpu = cpu_initialize(mem); boot_index = processor_index(boot_cpu); printk_spew("BOOT CPU is %d\n", boot_cpu); processor_map[boot_index] = CPU_BOOTPROCESSOR|CPU_ENABLED; @@ -378,14 +390,14 @@ void hardwaremain(int boot_complete) /* Now that we have collected all of our information * write our configuration tables. */ - write_tables(totalram); + write_tables(mem); #ifdef LINUXBIOS printk_info("Jumping to linuxbiosmain()...\n"); // we could go to argc, argv, for main but it seems like overkill. post_code(0xed); - linuxbiosmain(0, totalram); + linuxbiosmain(mem); #endif /* LINUXBIOS */ } @@ -393,6 +405,3 @@ void hardwaremain(int boot_complete) - - - diff --git a/src/arch/i386/lib/i386_subr.c b/src/arch/i386/lib/i386_subr.c index 0fa1e16f2d..84305bc06c 100644 --- a/src/arch/i386/lib/i386_subr.c +++ b/src/arch/i386/lib/i386_subr.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -13,7 +14,7 @@ #define APIC 1 #endif -void cache_on(unsigned long totalram) +void cache_on(struct mem_range *mem) { post_code(0x60); printk_info("Enabling cache..."); @@ -32,7 +33,7 @@ void cache_on(unsigned long totalram) #if defined(i686) // totalram here is in linux sizing, i.e. units of KB. // set_mtrr is responsible for getting it into the right units! - setup_mtrrs(totalram); + setup_mtrrs(mem); #endif post_code(0x6A); diff --git a/src/config/Config b/src/config/Config index f9ab408cee..32c4c3f19a 100644 --- a/src/config/Config +++ b/src/config/Config @@ -1,5 +1,7 @@ ## This is Architecture independant part of the makefile +option LINUXBIOS_VERSION=1.0.0 + option CROSS_COMPILE= makedefine CC:=$(CROSS_COMPILE)gcc @@ -14,6 +16,15 @@ makedefine CFLAGS := $(CPU_OPT) $(CPPFLAGS) -Os -nostdinc -nostdlib -fno-builtin makedefine HOSTCC:=gcc makedefine HOSTCFLAGS:= -Os -Wall +option LINUXBIOS_BUILD = $(shell date) +option LINUXBIOS_COMPILE_TIME = $(shell date +%T) +option LINUXBIOS_COMPILE_BY = $(shell whoami) +option LINUXBIOS_COMPILE_HOST = $(shell hostname) +option LINUXBIOS_COMPILE_DOMAIN = $(shell dnsdomainname) +option LINUXBIOS_COMPILER = $(shell $(CC) $(CFLAGS) -v 2>&1 | tail -1) +option LINUXBIOS_LINKER = $(shell $(CC) -Wl,-v 2>&1 | grep version | tail -1) +option LINUXBIOS_ASSEMBLER = $(shell touch dummy.s ; $(CC) -c -Wa,-v dummy.s 2>&1; rm -f dummy.s dummy.o ) + makerule ldscript.ld : ldoptions $(LDSUBSCRIPTS-1) ; echo "INCLUDE ldoptions" > $@ ; for file in $(LDSUBSCRIPTS-1) ; do echo "INCLUDE $$file" >> $@ ; done makerule cpuflags : Makefile.settings ; perl -e 'print "CPUFLAGS :=\n"; foreach $$var (split(" ", $$ENV{VARIABLES})) { if (exists($$ENV{$$var})) { print "CPUFLAGS += -D$$var" . (length($$ENV{$$var})?"=\x27$$ENV{$$var}\x27":"") ."\n"} else { print "CPUFLAGS += -U$$var\n"} }' > $@ @@ -34,6 +45,8 @@ addaction linuxbios.a ar cr linuxbios.a $(OBJECTS-1) option CRT0=$(TOP)/src/arch/$(ARCH)/config/crt0.base makerule crt0.S: $(CRT0) ; cp $< $@ +# Force crt0.s (which has build time version code in it to rebuild every time) +makedefine .PHONY : crt0.s makerule crt0.s: crt0.S crt0_includes.h $(CRT0_INCLUDES); @echo "$(CPP) ... $< > $@ " addaction crt0.s @$(CPP) $(CPPFLAGS) -I$(TOP)/src $< > $@.new && mv $@.new $@ diff --git a/src/cpu/i786/disable_sse.inc b/src/cpu/i786/disable_sse.inc new file mode 100644 index 0000000000..e81490d17f --- /dev/null +++ b/src/cpu/i786/disable_sse.inc @@ -0,0 +1,23 @@ + /* + * Put the processor back into a reset state + * with respect to the xmm registers. + */ + + pxor %xmm0, %xmm0 + pxor %xmm1, %xmm1 + pxor %xmm2, %xmm2 + pxor %xmm3, %xmm3 + pxor %xmm4, %xmm4 + pxor %xmm5, %xmm5 + pxor %xmm6, %xmm6 + pxor %xmm7, %xmm7 + + /* Disable floating point emulation */ + movl %cr0, %eax + andl $~(1<<2), %eax + movl %eax, %cr0 + + /* Disable sse instructions */ + movl %cr4, %eax + andl $~(3<<9), %eax + movl %eax, %cr4 diff --git a/src/cpu/i786/enable_sse.inc b/src/cpu/i786/enable_sse.inc new file mode 100644 index 0000000000..dcd1b67935 --- /dev/null +++ b/src/cpu/i786/enable_sse.inc @@ -0,0 +1,13 @@ + /* + * Enable the use of the xmm registers + */ + + /* Disable floating point emulation */ + movl %cr0, %eax + andl $~(1<<2), %eax + movl %eax, %cr0 + + /* Enable sse instructions */ + movl %cr4, %eax + orl $(1<<9), %eax + movl %eax, %cr4 diff --git a/src/cpu/p5/Config b/src/cpu/p5/Config index c74aff5855..758a6902ac 100644 --- a/src/cpu/p5/Config +++ b/src/cpu/p5/Config @@ -1,3 +1,4 @@ option i586=1 object cpuid.o +object delay_tsc.o #object tsc.o diff --git a/src/cpu/p6/microcode.c b/src/cpu/p6/microcode.c index 53b9d0ccf2..4e0b4361e6 100644 --- a/src/cpu/p6/microcode.c +++ b/src/cpu/p6/microcode.c @@ -334,7 +334,7 @@ static void display_cpuid_update_microcode(void) } } -void p6_cpufixup(unsigned long totalram) +void p6_cpufixup(struct mem_range *mem) { printk_info("Updating microcode\n"); display_cpuid_update_microcode(); diff --git a/src/cpu/p6/mtrr.c b/src/cpu/p6/mtrr.c index 0fe8d8ff03..de1af8650c 100644 --- a/src/cpu/p6/mtrr.c +++ b/src/cpu/p6/mtrr.c @@ -29,6 +29,7 @@ static char rcsid[] = "$Id$"; #endif +#include #include #include #include @@ -43,120 +44,6 @@ static unsigned int mtrr_msr[] = { MTRRfix4K_E0000_MSR, MTRRfix4K_E8000_MSR, MTRRfix4K_F0000_MSR, MTRRfix4K_F8000_MSR, }; -#ifndef HAVE_MTRR_TABLE - -/* We want to cache memory as efficiently as possible. - */ -#define MTRR_TYPE_RAM MTRR_TYPE_WRBACK -/* We can't use Write Combining on a legacy frame buffer because - * it is incompatible with EGA 16 color video modes... - */ -#define MTRR_TYPE_FB MTRR_TYPE_UNCACHABLE -/* For areas that are supposed to cover roms it makes no - * sense to cache writes. - */ -#define MTRR_TYPE_ROM MTRR_TYPE_WRPROT - - -#ifdef MEMORY_HOLE -#define RAM MTRR_TYPE_RAM -#define FB MTRR_TYPE_FB -#define ROM MTRR_TYPE_ROM -#else -#define RAM MTRR_TYPE_RAM -#define FB MTRR_TYPE_RAM -#define ROM MTRR_TYPE_RAM -#endif /* MEMORY_HOLE */ - -#ifdef MTRR_ONLY_TOP_64K_FLASH - -// This is for boards that only support flash in low memory at 0xf0000 -// and above, such as the technoland sbc 710. This type of board -// is so common that we put it here instead of in the sbc710 mainboard.c - -static unsigned char fixed_mtrr_values[][4] = { - /* MTRRfix64K_00000_MSR, defines memory range from 0KB to 512 KB, each byte cover 64KB area */ - {RAM, RAM, RAM, RAM}, {RAM, RAM, RAM, RAM}, - - /* MTRRfix16K_80000_MSR, defines memory range from 512KB to 640KB, each byte cover 16KB area */ - {RAM, RAM, RAM, RAM}, {RAM, RAM, RAM, RAM}, - - /* MTRRfix16K_A0000_MSR, defines memory range from A0000 to C0000, each byte cover 16KB area */ - {FB, FB, FB, FB}, {FB, FB, FB, FB}, - - /* MTRRfix4K_C0000_MSR, defines memory range from C0000 to C8000, each byte cover 4KB area */ - {FB, FB, FB, FB}, {FB, FB, FB, FB}, - - /* MTRRfix4K_C8000_MSR, defines memory range from C8000 to D0000, each byte cover 4KB area */ - {FB, FB, FB, FB}, {FB, FB, FB, FB}, - - /* MTRRfix4K_D0000_MSR, defines memory range from D0000 to D8000, each byte cover 4KB area */ - {FB, FB, FB, FB}, {FB, FB, FB, FB}, - - /* MTRRfix4K_D8000_MSR, defines memory range from D8000 to E0000, each byte cover 4KB area */ - {FB, FB, FB, FB}, {FB, FB, FB, FB}, - - /* MTRRfix4K_E0000_MSR, defines memory range from E0000 to E8000, each byte cover 4KB area */ - {FB, FB, FB, FB}, {FB, FB, FB, FB}, - - /* MTRRfix4K_E8000_MSR, defines memory range from E8000 to F0000, each byte cover 4KB area */ - {FB, FB, FB, FB}, {FB, FB, FB, FB}, - - /* MTRRfix4K_F0000_MSR, defines memory range from F0000 to F8000, each byte cover 4KB area */ - {ROM, ROM, ROM, ROM}, {ROM, ROM, ROM, ROM}, - - /* MTRRfix4K_F8000_MSR, defines memory range from F8000 to 100000, each byte cover 4KB area */ - {ROM, ROM, ROM, ROM}, {ROM, ROM, ROM, ROM}, -}; -#else - -static unsigned char fixed_mtrr_values[][4] = { - /* MTRRfix64K_00000_MSR, defines memory range from 0KB to 512 KB, each byte cover 64KB area */ - {RAM, RAM, RAM, RAM}, {RAM, RAM, RAM, RAM}, - - /* MTRRfix16K_80000_MSR, defines memory range from 512KB to 640KB, each byte cover 16KB area */ - {RAM, RAM, RAM, RAM}, {RAM, RAM, RAM, RAM}, - - /* MTRRfix16K_A0000_MSR, defines memory range from A0000 to C0000, each byte cover 16KB area */ - {FB, FB, FB, FB}, {FB, FB, FB, FB}, - - /* MTRRfix4K_C0000_MSR, defines memory range from C0000 to C8000, each byte cover 4KB area */ - {ROM, ROM, ROM, ROM}, {ROM, ROM, ROM, ROM}, - - /* MTRRfix4K_C8000_MSR, defines memory range from C8000 to D0000, each byte cover 4KB area */ - {ROM, ROM, ROM, ROM}, {ROM, ROM, ROM, ROM}, - - /* MTRRfix4K_D0000_MSR, defines memory range from D0000 to D8000, each byte cover 4KB area */ - {ROM, ROM, ROM, ROM}, {ROM, ROM, ROM, ROM}, - - /* MTRRfix4K_D8000_MSR, defines memory range from D8000 to E0000, each byte cover 4KB area */ - {ROM, ROM, ROM, ROM}, {ROM, ROM, ROM, ROM}, - - /* MTRRfix4K_E0000_MSR, defines memory range from E0000 to E8000, each byte cover 4KB area */ - {ROM, ROM, ROM, ROM}, {ROM, ROM, ROM, ROM}, - - /* MTRRfix4K_E8000_MSR, defines memory range from E8000 to F0000, each byte cover 4KB area */ - {ROM, ROM, ROM, ROM}, {ROM, ROM, ROM, ROM}, - - /* MTRRfix4K_F0000_MSR, defines memory range from F0000 to F8000, each byte cover 4KB area */ - {ROM, ROM, ROM, ROM}, {ROM, ROM, ROM, ROM}, - - /* MTRRfix4K_F8000_MSR, defines memory range from F8000 to 100000, each byte cover 4KB area */ - {ROM, ROM, ROM, ROM}, {ROM, ROM, ROM, ROM}, -}; - -#endif - -#undef FB -#undef RAM -#undef ROM -#undef MTRR_TYPE_RAM -#undef MTRR_TYPE_FB -#undef MTRR_TYPE_ROM - -#else -extern unsigned char fixed_mtrr_values[][4]; -#endif static void intel_enable_fixed_mtrr(void) { @@ -176,24 +63,25 @@ static void intel_enable_var_mtrr(void) wrmsr(MTRRdefType_MSR, low, high); } -/* setting fixed mtrr, you can do some experiments with different memory type - defined in the table "fixed_mtrr_values" */ -static void intel_set_fixed_mtrr(void) -{ - unsigned int i; - unsigned long low, high; - - for (i = 0; i < arraysize(mtrr_msr); i++) { - low = *(unsigned long *) fixed_mtrr_values[i*2]; - high = *(unsigned long *) fixed_mtrr_values[i*2+1]; - wrmsr(mtrr_msr[i], low, high); - } -} /* setting variable mtrr, comes from linux kernel source */ -static void intel_set_var_mtrr(unsigned int reg, unsigned long base, unsigned long size, unsigned char type) +static void intel_set_var_mtrr(unsigned int reg, unsigned long basek, unsigned long sizek, unsigned char type) { unsigned int tmp; + unsigned long base_high, base_low; + unsigned long mask_high, mask_low; + + base_high = basek >> 22; + base_low = basek << 10; + + if (sizek < 4*1024*1024) { + mask_high = 0x0F; + mask_low = ~((sizek << 10) -1); + } + else { + mask_high = 0x0F & (~((sizek >> 22) -1)); + mask_low = 0; + } if (reg >= 8) return; @@ -208,14 +96,14 @@ static void intel_set_var_mtrr(unsigned int reg, unsigned long base, unsigned lo "movl %0, %%cr0\n\t" "wbinvd\n\t":"=r" (tmp)::"memory"); - if (size == 0) { + if (sizek == 0) { /* The invalid bit is kept in the mask, so we simply clear the relevant mask register to disable a range. */ wrmsr (MTRRphysMask_MSR (reg), 0, 0); } else { /* Bit 32-35 of MTRRphysMask should be set to 1 */ - wrmsr (MTRRphysBase_MSR (reg), base | type, 0); - wrmsr (MTRRphysMask_MSR (reg), ~(size - 1) | 0x800, 0x0F); + wrmsr (MTRRphysBase_MSR(reg), base_low | type, base_high); + wrmsr (MTRRphysMask_MSR(reg), mask_low | 0x800, mask_high); } // turn cache back on. @@ -262,7 +150,7 @@ void set_var_mtrr(unsigned int reg, unsigned long base, unsigned long size, unsi } /* fms: find most sigificant bit set, stolen from Linux Kernel Source. */ -static __inline__ unsigned int fms(unsigned int x) +static inline unsigned int fms(unsigned int x) { int r; @@ -273,6 +161,18 @@ static __inline__ unsigned int fms(unsigned int x) return r; } +/* fms: find least sigificant bit set */ +static inline unsigned int fls(unsigned int x) +{ + int r; + + __asm__("bsfl %1,%0\n\t" + "jnz 1f\n\t" + "movl $32,%0\n" + "1:" : "=r" (r) : "g" (x)); + return r; +} + /* setting up variable and fixed mtrr * * From Intel Vol. III Section 9.12.4, the Range Size and Base Alignment has some kind of requirement: @@ -299,81 +199,152 @@ static __inline__ unsigned int fms(unsigned int x) #define OS_MTRRS 2 #define MTRRS (BIOS_MTRRS + OS_MTRRS) -void setup_mtrrs(unsigned long ramsizeK) + +static void set_fixed_mtrrs(unsigned int first, unsigned int last, unsigned char type) { - unsigned int reg = 0; - unsigned long range_wb, range_uc; - unsigned long rambase; - unsigned long romendK; - - printk_debug("\n"); - rambase = 0; - - while (ramsizeK != 0 && reg < BIOS_MTRRS) { - post_code(0x60 + reg); - - range_wb = 1 << (fms(ramsizeK - 1) + 1); - range_uc = range_wb - ramsizeK; - - if ((range_uc == 0) || ((ramsizeK % range_uc) == 0)) { - printk_debug("Setting variable MTRR %d, base: %4dMB, range: %4dMB, type: WB\n", - reg, rambase >> 10, range_wb >> 10); - intel_set_var_mtrr(reg++, rambase * 1024, range_wb * 1024, - MTRR_TYPE_WRBACK); - rambase += ramsizeK; - - if (range_uc) { - printk_debug("Setting variable MTRR %d, base: %4dMB, range: %4dMB, type: UC\n", - reg, rambase >> 10, range_uc >> 10); - intel_set_var_mtrr(reg++, rambase * 1024, range_uc * 1024, - MTRR_TYPE_UNCACHABLE); + unsigned int i; + unsigned int fixed_msr = NUM_FIXED_RANGES >> 3; + unsigned long low, high; + low = high = 0; /* Shut up gcc */ + for(i = first; i < last; i++) { + /* When I switch to a new msr read it in */ + if (fixed_msr != i >> 3) { + /* But first write out the old msr */ + if (fixed_msr < (NUM_FIXED_RANGES >> 3)) { + wrmsr(mtrr_msr[fixed_msr], low, high); } - ramsizeK = 0; /* effectivly a break */ + fixed_msr = i>>3; + rdmsr(mtrr_msr[fixed_msr], low, high); + } + if ((i & 7) < 4) { + low &= ~(0xff << ((i&3)*8)); + low |= type << ((i&3)*8); } else { - range_wb >>= 1; - - printk_debug("Setting variable MTRR %d, base: %4dMB, range: %4dMB, type: WB\n", - reg, rambase >> 10, range_wb >> 10); - intel_set_var_mtrr(reg++, rambase * 1024, range_wb * 1024, - MTRR_TYPE_WRBACK); - - rambase += range_wb; - ramsizeK -= range_wb; + high &= ~(0xff << ((i&3)*8)); + high |= type << ((i&3)*8); } } - printk_debug("DONE variable MTRRs\n"); -#if defined(XIP_ROM_SIZE) && defined(XIP_ROM_BASE) -#if XIP_ROM_SIZE < 4096 -#error XIP_ROM_SIZE must be at least 4K -#endif -#if XIP_ROM_SIZE & (XIP_ROM_SIZE -1) -#error XIP_ROM_SIZE must be a power of two -#endif -#if XIP_ROM_BASE & (XIP_ROM_SIZE -1) -#error XIP_ROM_BASE must be a multiple of XIP_ROM_SIZE -#endif - /* I assume that XIP_ROM_SIZE is a power of two - * and that XIP_ROM_BASE is power of tow aligned. - */ - romendK = (XIP_ROM_BASE + XIP_ROM_SIZE) >>10; - if ((reg < BIOS_MTRRS) && - ((XIP_ROM_BASE > rambase) || (romendK > rambase))) { - intel_set_var_mtrr(reg++, XIP_ROM_BASE, XIP_ROM_SIZE, - MTRR_TYPE_WRPROT); + /* Write out the final msr */ + if (fixed_msr < (NUM_FIXED_RANGES >> 3)) { + wrmsr(mtrr_msr[fixed_msr], low, high); } -#endif /* XIP_ROM_SIZE && XIP_ROM_BASE */ +} + +static unsigned fixed_mtrr_index(unsigned long addrk) +{ + unsigned index; + index = (addrk - 0) >> 6; + if (index >= 8) { + index = ((addrk - 8*64) >> 4) + 8; + } + if (index >= 24) { + index = ((addrk - (8*64 + 16*16)) >> 2) + 24; + } + if (index > NUM_FIXED_RANGES) { + index = NUM_FIXED_RANGES; + } + return index; +} + +static unsigned int range_to_mtrr(unsigned int reg, + unsigned long range_startk, unsigned long range_sizek) +{ + if (!range_sizek || (reg >= BIOS_MTRRS)) { + return reg; + } + while(range_sizek) { + unsigned long max_align, align; + unsigned long sizek; + /* Compute the maximum size I can make a range */ + max_align = fls(range_startk); + align = fms(range_sizek); + if (align > max_align) { + align = max_align; + } + sizek = 1 << align; + printk_debug("Setting variable MTRR %d, base: %4dMB, range: %4dMB, type WB\n", + reg, range_startk >>10, sizek >> 10); + intel_set_var_mtrr(reg++, range_startk, sizek, MTRR_TYPE_WRBACK); + range_startk += sizek; + range_sizek -= sizek; + if (reg >= BIOS_MTRRS) + break; + } + return reg; +} + +void setup_mtrrs(struct mem_range *mem) +{ + /* Try this the simple way of incrementally adding together + * mtrrs. If this doesn't work out we can get smart again + * and clear out the mtrrs. + */ + struct mem_range *memp; + unsigned long range_startk, range_sizek; + unsigned int reg; + + printk_debug("\n"); + /* Initialized the fixed_mtrrs to uncached */ + printk_debug("Setting fixed MTRRs(%d-%d) type: UC\n", + 0, NUM_FIXED_RANGES); + set_fixed_mtrrs(0, NUM_FIXED_RANGES, MTRR_TYPE_UNCACHABLE); + + /* Now see which of the fixed mtrrs cover ram. + */ + for(memp = mem; memp->sizek; memp++) { + unsigned int start_mtrr; + unsigned int last_mtrr; + start_mtrr = fixed_mtrr_index(memp->basek); + last_mtrr = fixed_mtrr_index(memp->basek + memp->sizek); + if (start_mtrr >= NUM_FIXED_RANGES) { + break; + } + printk_debug("Setting fixed MTRRs(%d-%d) type: WB\n", + start_mtrr, last_mtrr); + set_fixed_mtrrs(start_mtrr, last_mtrr, MTRR_TYPE_WRBACK); + } + printk_debug("DONE fixed MTRRs\n"); + /* Cache as many memory areas as possible */ + /* FIXME is there an algorithm for computing the optimal set of mtrrs? + * In some cases it is definitely possible to do better. + */ + range_startk = 0; + range_sizek = 0; + reg = 0; + for (memp = mem; memp->sizek; memp++) { + /* See if I can merge with the last range + * Either I am below 1M and the fixed mtrrs handle it, or + * the ranges touch. + */ + if ((memp->basek <= 1024) || (range_startk + range_sizek == memp->basek)) { + unsigned long endk = memp->basek + memp->sizek; + range_sizek = endk - range_startk; + continue; + } + /* Write the range mtrrs */ + if (range_sizek != 0) { + reg = range_to_mtrr(reg, range_startk, range_sizek); + range_startk = 0; + range_sizek = 0; + if (reg >= BIOS_MTRRS) + break; + } + /* Allocate an msr */ + range_startk = memp->basek; + range_sizek = memp->sizek; + } + /* Write the last range */ + reg = range_to_mtrr(reg, range_startk, range_sizek); + printk_debug("DONE variable MTRRs\n"); printk_debug("Clear out the extra MTRR's\n"); /* Clear out the extra MTRR's */ while(reg < MTRRS) { intel_set_var_mtrr(reg++, 0, 0, 0); } - printk_debug("call intel_set_fixed_mtrr()\n"); - intel_set_fixed_mtrr(); - /* enable fixed MTRR */ printk_debug("call intel_enable_fixed_mtrr()\n"); intel_enable_fixed_mtrr(); printk_debug("call intel_enable_var_mtrr()\n"); intel_enable_var_mtrr(); - printk_debug("Leave " __FUNCTION__ "\n"); + printk_debug("Leave %s\n", __FUNCTION__); } diff --git a/src/include/boot/linuxbios_table.h b/src/include/boot/linuxbios_table.h index f653c6fa93..42c0a07dac 100644 --- a/src/include/boot/linuxbios_table.h +++ b/src/include/boot/linuxbios_table.h @@ -3,10 +3,12 @@ #include +struct mem_range; + /* This file holds function prototypes for building the linuxbios table. */ unsigned long write_linuxbios_table( unsigned long *processor_map, - unsigned long totalram, + struct mem_range *ram, unsigned long low_table_start, unsigned long low_table_end, unsigned long rom_table_start, unsigned long rom_table_end); @@ -17,7 +19,7 @@ struct lb_record *lb_next_record(struct lb_record *rec); struct lb_record *lb_new_record(struct lb_header *header); struct lb_memory *lb_memory(struct lb_header *header); void lb_memory_range(struct lb_memory *mem, - uint32_t type, unsigned long start, unsigned long size); + uint32_t type, unsigned long startk, unsigned long sizek); struct lb_mainboard *lb_mainboard(struct lb_header *header); unsigned long lb_table_fini(struct lb_header *header); diff --git a/src/include/boot/linuxbios_tables.h b/src/include/boot/linuxbios_tables.h index 0e5ddbb404..7ac5ded9dc 100644 --- a/src/include/boot/linuxbios_tables.h +++ b/src/include/boot/linuxbios_tables.h @@ -61,8 +61,9 @@ struct lb_memory_range { uint64_t start; uint64_t size; uint32_t type; -#define LB_MEM_RAM 1 -#define LB_MEM_RESERVED 2 +#define LB_MEM_RAM 1 /* Memory anyone can use */ +#define LB_MEM_RESERVED 2 /* Don't use this memory region */ +#define LB_MEM_TABLE 16 /* Ram configuration tables are kept in */ }; @@ -88,7 +89,21 @@ struct lb_mainboard { uint8_t strings[0]; }; - +#define LB_TAG_VERSION 0x0004 +#define LB_TAG_EXTRA_VERSION 0x0005 +#define LB_TAG_BUILD 0x0006 +#define LB_TAG_COMPILE_TIME 0x0007 +#define LB_TAG_COMPILE_BY 0x0008 +#define LB_TAG_COMPILE_HOST 0x0009 +#define LB_TAG_COMPILE_DOMAIN 0x000a +#define LB_TAG_COMPILER 0x000b +#define LB_TAG_LINKER 0x000c +#define LB_TAG_ASSEMBLER 0x000d +struct lb_string { + uint32_t tag; + uint32_t size; + uint8_t string[0]; +}; /* The following structures are for the cmos definitions table */ #define LB_TAG_CMOS_OPTION_TABLE 200 diff --git a/src/include/cpu/cpufixup.h b/src/include/cpu/cpufixup.h index b7413ec742..a464d664c1 100644 --- a/src/include/cpu/cpufixup.h +++ b/src/include/cpu/cpufixup.h @@ -1,19 +1,21 @@ #ifndef CPU_CPUFIXUP_H #define CPU_CPUFIXUP_H +struct mem_range; + #include #include #ifdef CPU_FIXUP # if defined(k7) -# define cpufixup(totalram) k7_cpufixup(totalram) +# define cpufixup(mem) k7_cpufixup(mem) # elif defined(i786) -# define cpufixup(totalram) p6_cpufixup(totalram) +# define cpufixup(mem) p6_cpufixup(mem) # elif defined(i686) -# define cpufixup(totalram) p6_cpufixup(totalram) +# define cpufixup(mem) p6_cpufixup(mem) # endif #else -# define cpufixup(totalram) do {} while(0) +# define cpufixup(mem) do {} while(0) #endif #endif /* CPU_CPUFIXUP_H */ diff --git a/src/include/cpu/k7/cpufixup.h b/src/include/cpu/k7/cpufixup.h index b4d8335a62..0e3db3d655 100644 --- a/src/include/cpu/k7/cpufixup.h +++ b/src/include/cpu/k7/cpufixup.h @@ -1,6 +1,6 @@ #ifndef CPU_K7_CPUFIXUP_H #define CPU_K7_CPUFIXUP_H -void k7_cpufixup(unsigned long totalram); +void k7_cpufixup(struct mem_range *mem); #endif /* CPU_K7_CPUFIXUP_H */ diff --git a/src/include/cpu/p6/cpufixup.h b/src/include/cpu/p6/cpufixup.h index 0b21209702..aabc8710ae 100644 --- a/src/include/cpu/p6/cpufixup.h +++ b/src/include/cpu/p6/cpufixup.h @@ -5,6 +5,6 @@ #define CPU_FIXUP #endif -void p6_cpufixup(unsigned long totalram); +void p6_cpufixup(struct mem_range *mem); #endif /* CPU_P6_CPUFIXUP_H */ diff --git a/src/include/cpu/p6/mtrr.h b/src/include/cpu/p6/mtrr.h index 573bc536c4..16af10b81b 100644 --- a/src/include/cpu/p6/mtrr.h +++ b/src/include/cpu/p6/mtrr.h @@ -35,7 +35,8 @@ void set_var_mtrr(unsigned int reg, unsigned long base, unsigned long size, unsigned char type); #if defined(INTEL_PPRO_MTRR) -void setup_mtrrs(unsigned long ramsizeK); +struct mem_range; +void setup_mtrrs(struct mem_range *mem); #endif #endif /* ASSEMBLY */ diff --git a/src/include/mem.h b/src/include/mem.h new file mode 100644 index 0000000000..e2b495c86a --- /dev/null +++ b/src/include/mem.h @@ -0,0 +1,11 @@ +#ifndef MEM_H +#define MEM_H + +struct mem_range { + unsigned long basek; + unsigned long sizek; +}; + +/* mem_range arrays are non-overlapping, in ascending order and null terminated */ + +#endif /* MEM_H */ diff --git a/src/include/northbridge/amd/amd76x.h b/src/include/northbridge/amd/amd76x.h new file mode 100644 index 0000000000..cb33754bbc --- /dev/null +++ b/src/include/northbridge/amd/amd76x.h @@ -0,0 +1,6 @@ +#ifndef AMD76X_H +#define AMD76X_H + +void amd76x_setup_pci_arbiter(void); + +#endif /* AMD76X_H */ diff --git a/src/include/part/sizeram.h b/src/include/part/sizeram.h index 0312cb2a1f..50a44f3e82 100644 --- a/src/include/part/sizeram.h +++ b/src/include/part/sizeram.h @@ -1,6 +1,7 @@ #ifndef PART_SIZERAM_H #define PART_SIZERAM_H -unsigned long sizeram(void); +struct mem_rang; +struct mem_range *sizeram(void); #endif /* PART_SIZERAM_H */ diff --git a/src/include/string.h b/src/include/string.h index dbaa1ecd17..dbb67751e4 100644 --- a/src/include/string.h +++ b/src/include/string.h @@ -10,18 +10,22 @@ //extern inline int strlen(char *src) { int i = 0; while (*src++) i++; return i;} -static inline size_t strnlen(const char *src, size_t max) { - int i = 0; - if (max<0) { - while (*src++) - i++; - return i; - } - else { - while ((*src++) && (i < max)) - i++; - return i; - } +static inline size_t strnlen(const char *src, size_t max) +{ + size_t i = 0; + while((*src++) && (i < max)) { + i++; + } + return i; +} + +static inline size_t strlen(const char *src) +{ + size_t i = 0; + while(*src++) { + i++; + } + return i; } extern void *memcpy(void *dest, const void *src, size_t n); diff --git a/src/include/version.h b/src/include/version.h new file mode 100644 index 0000000000..223b9a3f75 --- /dev/null +++ b/src/include/version.h @@ -0,0 +1,22 @@ +#ifndef VERSION_H +#define VERSION_H + +/* Motherboard Information */ +extern const char mainboard_vendor[]; +extern const char mainboard_part_number[]; + +/* LinuxBIOS Version */ +extern const char linuxbios_version[]; +extern const char linuxbios_extra_version[]; +extern const char linuxbios_build[]; + +/* When LinuxBIOS was compiled */ +extern const char linuxbios_compile_time[]; +extern const char linuxbios_compile_by[]; +extern const char linuxbios_compile_host[]; +extern const char linuxbios_compile_domain[]; +extern const char linuxbios_compiler[]; +extern const char linuxbios_linker[]; +extern const char linuxbios_assembler[]; + +#endif /* VERSION_H */ diff --git a/src/lib/Config b/src/lib/Config index 60b426f155..3d3870168e 100644 --- a/src/lib/Config +++ b/src/lib/Config @@ -16,4 +16,7 @@ object do_inflate.o object floppy_subr.o BOOT_FLOPPY object delay.o object fallback_boot.o HAVE_FALLBACK_BOOT -object compute_ip_checksum.o \ No newline at end of file +object compute_ip_checksum.o +object version.o +# Force version.o to recompile every time +makedefine .PHONY : version.o \ No newline at end of file diff --git a/src/lib/compute_ip_checksum.c b/src/lib/compute_ip_checksum.c index ab41f97437..0b8eb90f85 100644 --- a/src/lib/compute_ip_checksum.c +++ b/src/lib/compute_ip_checksum.c @@ -3,54 +3,34 @@ unsigned long compute_ip_checksum(void *addr, unsigned long length) { - uint16_t *ptr; + uint8_t *ptr; + volatile union { + uint8_t byte[2]; + uint16_t word; + } value; unsigned long sum; - unsigned long len; - unsigned long laddr; - /* compute an ip style checksum */ - laddr = (unsigned long )addr; + unsigned long i; + /* In the most straight forward way possible, + * compute an ip style checksum. + */ sum = 0; - if (laddr & 1) { - uint16_t buffer; - unsigned char *ptr; - /* copy the first byte into a 2 byte buffer. - * This way automatically handles the endian question - * of which byte (low or high) the last byte goes in. - */ - buffer = 0; - ptr = addr; - memcpy(&buffer, ptr, 1); - sum += buffer; - if (sum > 0xFFFF) - sum -= 0xFFFF; - length -= 1; - addr = ptr +1; - - } - len = length >> 1; ptr = addr; - while (len--) { - sum += *(ptr++); - if (sum > 0xFFFF) - sum -= 0xFFFF; + for(i = 0; i < length; i++) { + unsigned long value; + value = ptr[i]; + if (i & 1) { + value <<= 8; + } + /* Add the new value */ + sum += value; + /* Wrap around the carry */ + if (sum > 0xFFFF) { + sum = (sum + (sum >> 16)) & 0xFFFF; + } } - addr = ptr; - if (length & 1) { - uint16_t buffer; - unsigned char *ptr; - /* copy the last byte into a 2 byte buffer. - * This way automatically handles the endian question - * of which byte (low or high) the last byte goes in. - */ - buffer = 0; - ptr = addr; - memcpy(&buffer, ptr, 1); - sum += buffer; - if (sum > 0xFFFF) - sum -= 0xFFFF; - } - return (~sum) & 0xFFFF; - + value.byte[0] = sum & 0xff; + value.byte[1] = (sum >> 8) & 0xff; + return (~value.word) & 0xFFFF; } unsigned long add_ip_checksums(unsigned long offset, unsigned long sum, unsigned long new) diff --git a/src/lib/linuxpci.c b/src/lib/linuxpci.c index f8033cd342..e47934e5ed 100644 --- a/src/lib/linuxpci.c +++ b/src/lib/linuxpci.c @@ -139,11 +139,11 @@ void pci_get_size(struct pci_dev *dev, unsigned long reg, unsigned long addr) // This incidentally catches the common case where registers // read back as 0 for both address and size. if (addr == size) { - printk_debug(__FUNCTION__ + printk_spew(__FUNCTION__ "dev_fn 0x%x, register %d, read-only" " SO, ignoring it\n", dev->devfn, reg); - printk_debug("addr was 0x%x, size was 0x%x\n",addr,size); + printk_spew("addr was 0x%x, size was 0x%x\n",addr,size); type = 0; size = 0; } diff --git a/src/lib/newpci.c b/src/lib/newpci.c index 7b75af9042..61dee907c3 100644 --- a/src/lib/newpci.c +++ b/src/lib/newpci.c @@ -21,7 +21,7 @@ static char rcsid[] = "$Id$"; #define ONEMEG (1 << 20) -#define PCI_MEM_START 0x80000000 +#define PCI_MEM_START 0xC0000000 #define PCI_IO_START 0x1000 // historical functions, sometimes very useful. diff --git a/src/northbridge/acer/m1631/northbridge.c b/src/northbridge/acer/m1631/northbridge.c index b9acb8096f..786ca62a43 100644 --- a/src/northbridge/acer/m1631/northbridge.c +++ b/src/northbridge/acer/m1631/northbridge.c @@ -1,3 +1,5 @@ +#include +#include #include #include @@ -25,7 +27,7 @@ void refresh_set(int turn_it_on) // printk_info( __FUNCTION__ "refresh is now 0x%lx\n", ref); } // FIX ME! -unsigned long sizeram() +static unsigned long __sizeram(void) { extern void cache_disable(void), cache_enable(void); int i; @@ -177,7 +179,21 @@ unsigned long sizeram() cache_enable(); return 0; //64*1024*1024; } - +struct mem_range *sizeram(void) +{ + static struct mem_range mem[3]; + mem[0].basek = 0; + mem[0].sizek = 640; + mem[1].basek = 1024; + mem[1].sizek = __sizeram(); + mem[2].basek = 0; + mem[2].sizek = 0; + if (mem[1].sizek == 0) { + mem[1].sizek = 64*1024; + } + mem[1].sizek -= mem[1].basek; + return &mem; +} #ifdef HAVE_FRAMEBUFFER diff --git a/src/northbridge/amd/amd76x/northbridge.c b/src/northbridge/amd/amd76x/northbridge.c index 86c630eccb..ba93f9b7c3 100644 --- a/src/northbridge/amd/amd76x/northbridge.c +++ b/src/northbridge/amd/amd76x/northbridge.c @@ -1,14 +1,23 @@ +#include #include #include #include -unsigned long sizeram(void) +struct mem_range *sizeram(void) { + static struct mem_range mem[3]; u32 size; /* Use the PCI top memory register */ pcibios_read_config_dword(0, 0, 0x9c, &size); /* Convert size in bytes to size in K */ size = size >> 10; - return size; + + mem[0].basek = 0; + mem[0].sizek = 640; + mem[1].basek = 1024; + mem[1].sizek = size - mem[1].basek; + mem[2].basek = 0; + mem[2].sizke = 0; + return &mem; } diff --git a/src/northbridge/amd/amd76x/raminit.inc b/src/northbridge/amd/amd76x/raminit.inc index 1b4a64a819..73507d2df0 100644 --- a/src/northbridge/amd/amd76x/raminit.inc +++ b/src/northbridge/amd/amd76x/raminit.inc @@ -1803,7 +1803,7 @@ spd_set_dram_timing_out: * Arguments: %bl device on the smbus to read from * %esi an initially zeroed copy of the * DRAM mode register. - * %ebp Pointer to infomration that varies by memory bus speed + * %ebp Pointer to information that varies by memory bus speed * * Results: cf clear * %esi updated with dimm with setting diff --git a/src/northbridge/intel/430tx/northbridge.c b/src/northbridge/intel/430tx/northbridge.c index eb97080494..1afb0919bc 100644 --- a/src/northbridge/intel/430tx/northbridge.c +++ b/src/northbridge/intel/430tx/northbridge.c @@ -1,8 +1,11 @@ +#include +#include #include -unsigned long sizeram() +struct mem_range *sizeram(void) { + static struct mem_range mem[3]; /* * Code for the BX/GX and TX are almost the same */ @@ -28,7 +31,13 @@ unsigned long sizeram() totalmem = 0x20000000UL; } - return totalmem; + mem[0].basek = 0; + mem[0].sizek = 640; + mem[1].basek = 1024; + mem[1].sizek = totalmem - mem[1].basek; + mem[2].basek = 0; + mem[2].sizek = 0; + return &mem; } diff --git a/src/northbridge/intel/440bx/northbridge.c b/src/northbridge/intel/440bx/northbridge.c index 8454d5160b..9f32b51fb5 100644 --- a/src/northbridge/intel/440bx/northbridge.c +++ b/src/northbridge/intel/440bx/northbridge.c @@ -1,8 +1,11 @@ +#include +#include #include -unsigned long sizeram() +struct mem_range *sizeram(void) { + static struct mem_range mem[3]; /* * This is written for BX but should work also for GX. */ @@ -24,7 +27,14 @@ unsigned long sizeram() totalmem = 0x80000000UL; } - return totalmem; + mem[0].basek = 0; + mem[0].sizek = 640; + mem[1].basek = 1024; + mem[1].sizek = totalmem - mem[1].basek; + mem[2].basek = 0; + mem[2].sizek = 0; + + return &mem; } diff --git a/src/northbridge/intel/440gx/northbridge.c b/src/northbridge/intel/440gx/northbridge.c index 54984db9cd..b2818ef176 100644 --- a/src/northbridge/intel/440gx/northbridge.c +++ b/src/northbridge/intel/440gx/northbridge.c @@ -1,3 +1,5 @@ +#include +#include #include #include #include @@ -29,7 +31,7 @@ dumpramregs(struct pci_dev *pcidev) } -unsigned long sizeram() +struct mem_range *sizeram(void) { /* * This is written for BX but should work also for GX. @@ -53,7 +55,13 @@ unsigned long sizeram() } dumpramregs(pcidev); - return totalmem; + mem[0].basek = 0; + mem[0].sizek = 640; + mem[1].basek = 1024; + mem[1].sizek = totalmem - mem[1].basek; + mem[2].basek = 0; + mem[2].sizek = 0; + return &mem; } diff --git a/src/northbridge/intel/82815ep/northbridge.c b/src/northbridge/intel/82815ep/northbridge.c index 5e4d94fd52..1e385f5d70 100644 --- a/src/northbridge/intel/82815ep/northbridge.c +++ b/src/northbridge/intel/82815ep/northbridge.c @@ -6,6 +6,8 @@ */ +#include +#include #include #include @@ -19,8 +21,9 @@ static int DRP_sizetbl[] = { 256, 256, 256, 512 }; -unsigned long sizeram() +struct mem_range *sizeram(void) { + static struct mem_range mem[3]; unsigned long totalmem, curmem; unsigned char regval; @@ -46,7 +49,13 @@ unsigned long sizeram() printk_info("DIMM2 - size = %ldM\n", curmem ); totalmem += curmem; - return totalmem * 1024; + mem[0].basek = 0; + mem[0].sizek = 640; + mem[1].basek = 1024; + mem[1].sizek = totalmem*1024 - mem[1].basek; + mem[2].basek = 0; + mem[2].sizek = 0; + return &mem; } diff --git a/src/northbridge/intel/82830/northbridge.c b/src/northbridge/intel/82830/northbridge.c index 43a0c9ac15..7c3078c54b 100644 --- a/src/northbridge/intel/82830/northbridge.c +++ b/src/northbridge/intel/82830/northbridge.c @@ -3,11 +3,14 @@ Intel 830 sizing. */ +#include +#include #include #include -unsigned long sizeram() +struct mem_range *sizeram(void) { + static struct mem_range mem[3]; unsigned long totalmem; unsigned char regval; @@ -23,7 +26,14 @@ unsigned long sizeram() totalmem += regval * 32; } - return totalmem * 1024; + + mem[0].basek = 0; + mem[0].sizek = 640; + mem[1].basek = 1024; + mem[1].sizek = totalmem*1024 - mem[1].basek; + mem[2].basek = 0; + mem[2].sizek = 0; + return &mem; } diff --git a/src/northbridge/intel/82860/northbridge.c b/src/northbridge/intel/82860/northbridge.c index a48150a9ec..96a2db1068 100644 --- a/src/northbridge/intel/82860/northbridge.c +++ b/src/northbridge/intel/82860/northbridge.c @@ -1,9 +1,10 @@ +#include #include #include #include #include -unsigned long sizeram(void) +struct mem_range *sizeram(void) { unsigned long size; unsigned short word; @@ -13,6 +14,12 @@ unsigned long sizeram(void) pcibios_read_config_word(0, 0, 0xc4, &word); /* Convert size in 64K bytes to size in K bytes */ size = word << 6; - return size; + mem[0].basek = 0; + mem[0].sizek = 640; + mem[1].basek = 1024; + mem[1].sizek = size - mem[1].basek; + mem[2].basek = 0; + mem[2].sizek = 0; + return &mem; } diff --git a/src/northbridge/intel/E7500/northbridge.c b/src/northbridge/intel/E7500/northbridge.c index 5f137e3d7e..b6915aafca 100644 --- a/src/northbridge/intel/E7500/northbridge.c +++ b/src/northbridge/intel/E7500/northbridge.c @@ -1,18 +1,45 @@ +#include #include #include #include #include -unsigned long sizeram(void) +struct mem_range *sizeram(void) { - unsigned long size; - unsigned short word; + static struct mem_range mem[4]; + uint16_t tolm, remapbase, remaplimit; + uint8_t drb; - /* Read TOLM */ - /* How should we handle > 4GB of ram? */ - pcibios_read_config_word(0, 0, 0xc4, &word); - /* Convert size in 128K bytes to size in K bytes */ - size = word << 5; - return size; - + /* FIXME do some of the configuration here instead of + * just reading it all out, and reporting it. + */ + /* Read the ram configruation registers */ + pcibios_read_config_word(0, 0, 0xc4, &tolm); + pcibios_read_config_word(0, 0, 0xc6, &remapbase); + remapbase &= 0x1FF; + pcibios_read_config_word(0, 0, 0xc8, &remaplimit); + remaplimit &= 0x1FF; + pcibios_read_config_byte(0, 0, 0x67, &drb); + + mem[0].basek = 0; + mem[0].sizek = 640; + mem[1].basek = 768; + /* Convert size in 64K bytes to size in K bytes */ + mem[1].sizek = (tolm << 6) - mem[1].basek; + mem[2].basek = 0; + mem[2].sizek = 0; + if ((drb << 16) > (tolm << 6)) { + mem[2].basek = 4096*1024; + mem[2].sizek = (drb << 16) - mem[2].basek; + /* I know that the remap window always immediately follows + * the real top of memory. + */ + if (remapbase < remaplimit) { + mem[2].sizek = (remaplimit << 16) - mem[2].basek; + } + } + mem[3].basek = 0; + mem[3].sizek = 0; + + return &mem; } diff --git a/src/northbridge/micron/21PAD/northbridge.c b/src/northbridge/micron/21PAD/northbridge.c index 5ddfa4e8eb..e8c110cfe2 100644 --- a/src/northbridge/micron/21PAD/northbridge.c +++ b/src/northbridge/micron/21PAD/northbridge.c @@ -1,9 +1,12 @@ +#include +#include #include #include #include -unsigned long sizeram() +struct mem_range *sizeram(void) { + static struct mem_range mem[3]; //unsigned long totalmemKB = 1024*1024; struct pci_dev *pcidev; unsigned long totalmemKB = 0 ,memfound = 0; @@ -64,9 +67,14 @@ unsigned long sizeram() pci_read_config_byte(pcidev,(0x80+i),&value); } } - - return totalmemKB; - //return 1024*1024; + + mem[0].basek = 0; + mem[0].sizek = 640; + mem[1].basek = 1024; + mem[1].sizek = totalmemKB - mem[1].basek; + mem[2].basek = 0; + mem[2].sizek = 0; + return &mem; } diff --git a/src/northbridge/nsc/gx1/northbridge.c b/src/northbridge/nsc/gx1/northbridge.c index 4162530829..5280b3d8e6 100644 --- a/src/northbridge/nsc/gx1/northbridge.c +++ b/src/northbridge/nsc/gx1/northbridge.c @@ -6,6 +6,8 @@ Do chipset setup for a National Semiconductor GX1 CPU. */ +#include +#include #include #include #include @@ -58,8 +60,9 @@ static unsigned long adjust_video_memory(unsigned long mem_size) return mem_size; } -unsigned long sizeram() +struct mem_range *sizeram(void) { + static struct mem_range mem[3]; u32 mem_bank_cfg; unsigned mem_size; @@ -71,7 +74,13 @@ unsigned long sizeram() mem_size = adjust_video_memory(mem_size); - return mem_size; + mem[0].basek = 0; + mem[0].sizek = 640; + mem[1].basek = 1024; + mem[1].sizek = mem_size - mem[1].basek; + mem[2].basek = 0; + mem[2].sizek = 0; + return &mem; } /* diff --git a/src/northbridge/via/vt694/northbridge.c b/src/northbridge/via/vt694/northbridge.c index 692de36ee8..36c94317da 100644 --- a/src/northbridge/via/vt694/northbridge.c +++ b/src/northbridge/via/vt694/northbridge.c @@ -1,9 +1,11 @@ +#include +#include #include #include #include -unsigned long sizeram() +static unsigned long __sizeram(void) { unsigned long totalmem; unsigned char bank, mem, prevmem; @@ -52,13 +54,21 @@ unsigned long sizeram() return totalmem; } - -/* -unsigned long sizeram() +struct mem_range *sizeram(void) { - return 0; + static struct mem_range mem[3]; + mem[0].basek = 0; + mem[0].sizek = 640; + mem[1].basek = 1024; + mem[1].sizek = __sizeram(); + mem[2].basek = 0; + mem[2].sizek = 0; + if (mem[1].sizek == 0) { + mem[1].sizek = 64*1024; + } + mem[1].sizek -= mem[1].basek; + return &mem; } -*/ #ifdef HAVE_FRAMEBUFFER void framebuffer_on() diff --git a/src/northbridge/via/vt8601/northbridge.c b/src/northbridge/via/vt8601/northbridge.c index 692de36ee8..36c94317da 100644 --- a/src/northbridge/via/vt8601/northbridge.c +++ b/src/northbridge/via/vt8601/northbridge.c @@ -1,9 +1,11 @@ +#include +#include #include #include #include -unsigned long sizeram() +static unsigned long __sizeram(void) { unsigned long totalmem; unsigned char bank, mem, prevmem; @@ -52,13 +54,21 @@ unsigned long sizeram() return totalmem; } - -/* -unsigned long sizeram() +struct mem_range *sizeram(void) { - return 0; + static struct mem_range mem[3]; + mem[0].basek = 0; + mem[0].sizek = 640; + mem[1].basek = 1024; + mem[1].sizek = __sizeram(); + mem[2].basek = 0; + mem[2].sizek = 0; + if (mem[1].sizek == 0) { + mem[1].sizek = 64*1024; + } + mem[1].sizek -= mem[1].basek; + return &mem; } -*/ #ifdef HAVE_FRAMEBUFFER void framebuffer_on() diff --git a/src/northsouthbridge/NSC/scx200/northbridge.c b/src/northsouthbridge/NSC/scx200/northbridge.c index f04ed37c34..10f2f46013 100644 --- a/src/northsouthbridge/NSC/scx200/northbridge.c +++ b/src/northsouthbridge/NSC/scx200/northbridge.c @@ -5,6 +5,8 @@ Do chipset setup for a National Semiconductor SCx200 CPU. */ +#include +#include #include #include #include @@ -26,8 +28,9 @@ static unsigned calc_dimm(int index, unsigned cfg) } } -unsigned long sizeram() +struct mem_range *sizeram(void) { + static struct mem_range mem[3]; u32 mem_bank_cfg; unsigned mem_size; @@ -37,7 +40,13 @@ unsigned long sizeram() mem_size += calc_dimm(0, mem_bank_cfg); mem_size += calc_dimm(1, mem_bank_cfg >> 16); - return mem_size; + mem[0].basek = 0; + mem[0].sizek = 640; + mem[1].basek = 1024; + mem[1].sizek = mem_size - mem[1].basek; + mem[2].basek = 0; + mem[2].sizek = 0; + return &mem; } /* diff --git a/src/northsouthbridge/sis/540/northbridge.c b/src/northsouthbridge/sis/540/northbridge.c index 6ccce42d57..4c993f8b1f 100644 --- a/src/northsouthbridge/sis/540/northbridge.c +++ b/src/northsouthbridge/sis/540/northbridge.c @@ -11,6 +11,8 @@ static char rcsid[] = #endif +#include +#include #include #include #include @@ -37,7 +39,7 @@ const static int ramsizes[16] = #define SIS630_BANK1 0x61 #define SIS630_BANK2 0x62 #define SIS630_DIMM_LOCATION_FOR_SMA 0x65 -unsigned long sizeram() +static unsigned long __sizeram(void) { struct pci_dev *pcidev; unsigned int dimm_slot, dimm_reg, sides; @@ -95,6 +97,22 @@ unsigned long sizeram() return total_size; } +struct mem_range *sizeram(void) +{ + static struct mem_range mem[3]; + mem[0].basek = 0; + mem[0].sizek = 640; + mem[1].basek = 1024; + mem[1].sizek = __sizeram(); + mem[2].basek = 0; + mem[2].sizek = 0; + if (mem[1].sizek == 0) { + mem[1].sizek = 64*1024; + } + mem[1].sizek -= mem[1].basek; + return &mem; +} + #ifdef HAVE_FRAMEBUFFER void framebuffer_on() { diff --git a/src/northsouthbridge/sis/550/northbridge.c b/src/northsouthbridge/sis/550/northbridge.c index ade4c1a42d..25023e7449 100644 --- a/src/northsouthbridge/sis/550/northbridge.c +++ b/src/northsouthbridge/sis/550/northbridge.c @@ -11,6 +11,8 @@ static char rcsid[] = #endif +#include +#include #include #include #include @@ -37,7 +39,7 @@ const static int ramsizes[16] = #define SIS630_BANK1 0x61 #define SIS630_BANK2 0x62 #define SIS630_DIMM_LOCATION_FOR_SMA 0x65 -unsigned long sizeram() +static unsigned long __sizeram(void) { struct pci_dev *pcidev; unsigned int dimm_slot, dimm_reg, sides; @@ -92,6 +94,23 @@ unsigned long sizeram() return total_size; } +struct mem_range *sizeram(void) +{ + static struct mem_range mem[3]; + mem[0].basek = 0; + mem[0].sizek = 640; + mem[1].basek = 1024; + mem[1].sizek = __sizeram(); + mem[2].basek = 0; + mem[2].sizek = 0; + if (mem[1].sizek == 0) { + mem[1].sizek = 64*1024; + } + mem[1].sizek -= mem[1].basek; + return &mem; +} + + #ifdef HAVE_FRAMEBUFFER void framebuffer_on() { diff --git a/src/northsouthbridge/sis/630/northbridge.c b/src/northsouthbridge/sis/630/northbridge.c index 247f1fe791..b271efa64c 100644 --- a/src/northsouthbridge/sis/630/northbridge.c +++ b/src/northsouthbridge/sis/630/northbridge.c @@ -11,6 +11,8 @@ static char rcsid[] = #endif +#include +#include #include #include #include @@ -37,7 +39,7 @@ const static int ramsizes[16] = #define SIS630_BANK1 0x61 #define SIS630_BANK2 0x62 #define SIS630_DIMM_LOCATION_FOR_SMA 0x65 -unsigned long sizeram() +static unsigned long __sizeram(void) { struct pci_dev *pcidev; unsigned int dimm_slot, dimm_reg, sides; @@ -92,6 +94,23 @@ unsigned long sizeram() return total_size; } +struct mem_range *sizeram(void) +{ + static struct mem_range mem[3]; + mem[0].basek = 0; + mem[0].sizek = 640; + mem[1].basek = 1024; + mem[1].sizek = __sizeram(); + mem[2].basek = 0; + mem[2].sizek = 0; + if (mem[1].sizek == 0) { + mem[1].sizek = 64*1024; + } + mem[1].sizek -= mem[1].basek; + return &mem; +} + + #ifdef HAVE_FRAMEBUFFER void framebuffer_on() { diff --git a/src/northsouthbridge/sis/635/northbridge.c b/src/northsouthbridge/sis/635/northbridge.c index 8d4ae9a9ac..f01a98a144 100644 --- a/src/northsouthbridge/sis/635/northbridge.c +++ b/src/northsouthbridge/sis/635/northbridge.c @@ -23,6 +23,8 @@ * */ +#include +#include #include #include #include @@ -49,8 +51,7 @@ const static int ramsizes[16] = #define SIS635_BANK1 0x61 #define SIS635_BANK2 0x62 #define SIS635_BANK3 0x63 -unsigned -long sizeram() +static unsigned long __sizeram(void) { struct pci_dev *pcidev; unsigned int dimm_slot, dimm_reg, sides; @@ -87,6 +88,24 @@ long sizeram() return total_size; } + +struct mem_range *sizeram(void) +{ + static struct mem_range mem[3]; + mem[0].basek = 0; + mem[0].sizek = 640; + mem[1].basek = 1024; + mem[1].sizek = __sizeram(); + mem[2].basek = 0; + mem[2].sizek = 0; + if (mem[1].sizek == 0) { + mem[1].sizek = 64*1024; + } + mem[1].sizek -= mem[1].basek; + return &mem; +} + + #ifdef HAVE_FRAMEBUFFER void framebuffer_on() { diff --git a/src/northsouthbridge/sis/730/northbridge.c b/src/northsouthbridge/sis/730/northbridge.c index 63fe3eb5e2..e8bdddd39d 100644 --- a/src/northsouthbridge/sis/730/northbridge.c +++ b/src/northsouthbridge/sis/730/northbridge.c @@ -1,6 +1,5 @@ /* -<<<<<<< northbridge.c - * southbridge.c: Norththbridge Initialization For SiS 730 + * northbridge.c: Norththbridge Initialization For SiS 730 * * Copyright 2002 Silicon Integrated Systems Corp. * @@ -28,6 +27,8 @@ static char rcsid[] = #endif +#include +#include #include #include #include @@ -56,7 +57,7 @@ const static int ramsizes[16] = #define SIS630_DIMM_LOCATION_FOR_SMA 0x65 #define MAX_DIMM_SLOTS 3 -unsigned long sizeram() +static unsigned long __sizeram(void) { struct pci_dev *pcidev; unsigned int dimm_slot, dimm_reg, sides; @@ -111,6 +112,22 @@ unsigned long sizeram() return total_size; } +struct mem_range *sizeram(void) +{ + static struct mem_range mem[3]; + mem[0].basek = 0; + mem[0].sizek = 640; + mem[1].basek = 1024; + mem[1].sizek = __sizeram(); + mem[2].basek = 0; + mem[2].sizek = 0; + if (mem[1].sizek == 0) { + mem[1].sizek = 64*1024; + } + mem[1].sizek -= mem[1].basek; + return &mem; +} + #ifdef HAVE_FRAMEBUFFER void framebuffer_on() { diff --git a/src/northsouthbridge/sis/735/northbridge.c b/src/northsouthbridge/sis/735/northbridge.c index 4366d8b826..1435d1b318 100644 --- a/src/northsouthbridge/sis/735/northbridge.c +++ b/src/northsouthbridge/sis/735/northbridge.c @@ -23,6 +23,8 @@ * */ +#include +#include #include #include #include @@ -49,8 +51,7 @@ const static int ramsizes[16] = #define SIS735_BANK1 0x61 #define SIS735_BANK2 0x62 #define SIS735_BANK3 0x63 -unsigned -long sizeram() +static unsigned long __sizeram(void) { struct pci_dev *pcidev; unsigned int dimm_slot, dimm_reg, sides; @@ -87,6 +88,22 @@ long sizeram() return total_size; } +struct mem_range *sizeram(void) +{ + static struct mem_range mem[3]; + mem[0].basek = 0; + mem[0].sizek = 640; + mem[1].basek = 1024; + mem[1].sizek = __sizeram(); + mem[2].basek = 0; + mem[2].sizek = 0; + if (mem[1].sizek == 0) { + mem[1].sizek = 64*1024; + } + mem[1].sizek -= mem[1].basek; + return &mem; +} + #ifdef HAVE_FRAMEBUFFER void framebuffer_on() { diff --git a/src/pc80/mc146818rtc.c b/src/pc80/mc146818rtc.c index 513f47b676..b39ee514c4 100644 --- a/src/pc80/mc146818rtc.c +++ b/src/pc80/mc146818rtc.c @@ -236,7 +236,7 @@ int get_option(void *dest, char *name) } } if(!found) { - printk_err("ERR: No cmos option '%s'\n", name); + printk_err("ERROR: No cmos option '%s'\n", name); return(-2); } diff --git a/src/ram/dump_northbridge.inc b/src/ram/dump_northbridge.inc index 4d120c5996..60fbe12381 100644 --- a/src/ram/dump_northbridge.inc +++ b/src/ram/dump_northbridge.inc @@ -12,36 +12,27 @@ dn_after: .string "After setting values: \r\n" .previous - dumpnorth: +dumpnorth: mov %esp, %ebp CONSOLE_INFO_TX_STRING($dn_banner) xorl %ecx, %ecx 1: - CONSOLE_INFO_TX_HEX32(%ecx) - CONSOLE_INFO_TX_CHAR($'-') - movl %ecx, %eax + CONSOLE_INFO_TX_HEX8(%cl) + CONSOLE_INFO_TX_CHAR($':') + CONSOLE_INFO_TX_CHAR($' ') - PCI_READ_CONFIG_DWORD -#if 0 - CONSOLE_INFO_TX_HEX32(%eax) -#else - CONSOLE_INFO_TX_HEX8(%al) +2: movl %ecx, %eax - PCI_READ_CONFIG_DWORD - shrl $8,%eax + PCI_READ_CONFIG_BYTE CONSOLE_INFO_TX_HEX8(%al) - movl %ecx, %eax - PCI_READ_CONFIG_DWORD - shrl $16,%eax - CONSOLE_INFO_TX_HEX8(%al) - movl %ecx, %eax - PCI_READ_CONFIG_DWORD - shrl $24,%eax - CONSOLE_INFO_TX_HEX8(%al) -#endif + CONSOLE_INFO_TX_CHAR($' ') + + incl %ecx + testb $0xf, %cl + jnz 2b + CONSOLE_INFO_TX_CHAR($'\r') CONSOLE_INFO_TX_CHAR($'\n') - addl $0x4, %ecx cmpl $256, %ecx jne 1b CONSOLE_INFO_TX_STRING($dn_done) diff --git a/src/sdram/generic_cache_linuxbios.inc b/src/sdram/generic_cache_linuxbios.inc new file mode 100644 index 0000000000..097a5bc812 --- /dev/null +++ b/src/sdram/generic_cache_linuxbios.inc @@ -0,0 +1,24 @@ + /* enable caching for 0 - 16M using a variable mtrr + * This should be all we need to get good performance out of LinuxBIOS. + */ + + /* Disable the cache while we set up a new MTRR over memory */ + movl %cr0, %eax + orl $0x40000000, %eax + movl %eax, %cr0 + + movl $0x200, %ecx /* mtrr[0] physical base register */ + movl $0x00000000, %edx + movl $0x00000006, %eax + wrmsr + + movl $0x201, %ecx /* mtrr[0] physical mask register */ + movl $0x0000000f, %edx + movl $0xff000800, %eax + wrmsr + + /* Reenable the cache now that the mtrr is set up */ + movl %cr0, %eax + andl $0x9fffffff, %eax + movl %eax, %cr0 + diff --git a/src/sdram/generic_dump_spd.inc b/src/sdram/generic_dump_spd.inc index b8ae911f10..5f0faf8e56 100644 --- a/src/sdram/generic_dump_spd.inc +++ b/src/sdram/generic_dump_spd.inc @@ -8,15 +8,14 @@ dump_spd_reg_dimm: CONSOLE_DEBUG_TX_CHAR($'m') CONSOLE_DEBUG_TX_CHAR($'m') CONSOLE_DEBUG_TX_CHAR($' ') - movb %bl, %al - CALLSP(ttys0_tx_hex8) + CONSOLE_DEBUG_TX_HEX8(%bl) CONSOLE_DEBUG_TX_CHAR($'\r') CONSOLE_DEBUG_TX_CHAR($'\n') dump_spd_reg_byte: CALLSP(smbus_read_byte) jz dump_spd_reg_next_dimm - CALLSP(ttys0_tx_hex8) + CONSOLE_DEBUG_TX_HEX8(%al) CONSOLE_DEBUG_TX_CHAR($' ') incb %bh testb $0x0F, %bh diff --git a/src/sdram/generic_sdram.inc b/src/sdram/generic_sdram.inc index 8aaae1adee..e9b2af3356 100644 --- a/src/sdram/generic_sdram.inc +++ b/src/sdram/generic_sdram.inc @@ -7,11 +7,14 @@ ram_4: .string "Ram4\r\n" ram_5: .string "Ram5\r\n" ram_6: .string "Ram6\r\n" +no_memory_str: .string "ERROR: No memory!" +crlf: .string "\r\n" -no_memory_str: .string "No memory!\r\n" - -no_memory: CONSOLE_DEBUG_TX_STRING($no_memory_str) -1: hlt /* stick here.. */ +no_memory: CONSOLE_ERR_TX_STRING($no_memory_str) +mem_stop: + CONSOLE_ERR_TX_STRING($crlf) +1: + hlt /* stick here.. */ jmp 1b ram_initialize: diff --git a/src/southbridge/intel/82801ca/82801.h b/src/southbridge/intel/82801ca/82801.h index d4f2652e66..a436833607 100644 --- a/src/southbridge/intel/82801ca/82801.h +++ b/src/southbridge/intel/82801ca/82801.h @@ -38,3 +38,16 @@ #define SMBUS_BUS 0 #define SMBUS_DEVFN ((0x1f << 3) + 3) +#define SMBUS_IO_BASE 0x1000 + +#define SMBHSTSTAT 0x0 +#define SMBHSTCTL 0x2 +#define SMBHSTCMD 0x3 +#define SMBXMITADD 0x4 +#define SMBHSTDAT0 0x5 +#define SMBHSTDAT1 0x6 +#define SMBBLKDAT 0x7 +#define SMBTRNSADD 0x9 +#define SMBSLVDATA 0xa +#define SMLINK_PIN_CTL 0xe +#define SMBUS_PIN_CTL 0xf diff --git a/src/southbridge/intel/82801ca/ich3_smbus.c b/src/southbridge/intel/82801ca/ich3_smbus.c index ab890b668f..57e28744c3 100644 --- a/src/southbridge/intel/82801ca/ich3_smbus.c +++ b/src/southbridge/intel/82801ca/ich3_smbus.c @@ -4,21 +4,6 @@ #include #include "82801.h" - -#define SMBUS_IO_BASE 0x1000 - -#define SMBHSTSTAT 0x0 -#define SMBHSTCTL 0x2 -#define SMBHSTCMD 0x3 -#define SMBXMITADD 0x4 -#define SMBHSTDAT0 0x5 -#define SMBHSTDAT1 0x6 -#define SMBBLKDAT 0x7 -#define SMBTRNSADD 0x9 -#define SMBSLVDATA 0xa -#define SMLINK_PIN_CTL 0xe -#define SMBUS_PIN_CTL 0xf - void smbus_setup(void) { pcibios_write_config_dword(SMBUS_BUS, SMBUS_DEVFN, 0x20, SMBUS_IO_BASE | 1); diff --git a/src/southbridge/intel/82801ca/smbus.inc b/src/southbridge/intel/82801ca/smbus.inc index ad0808680a..bfe175ef62 100644 --- a/src/southbridge/intel/82801ca/smbus.inc +++ b/src/southbridge/intel/82801ca/smbus.inc @@ -1,65 +1,43 @@ -/* Useful macros PCIBUS, and SMBUS functions for getting DRAM going. */ -/* courtesy Eric Biederman of linuxnetworx.com */ +/* + * Copyright (C) 2002 Eric Biederman + */ -#define CS_WRITE_BYTE(addr, byte) \ - movl $addr, %eax ; \ - movl $byte, %edx ; \ - PCI_WRITE_CONFIG_BYTE - -#define CS_WRITE_WORD(addr, word) \ - movl $addr, %eax ; \ - movl $word, %ecx ; \ - PCI_WRITE_CONFIG_WORD - -#define CS_WRITE_LONG(addr, dword) \ - movl $addr, %eax ; \ - movl $dword, %ecx ; \ - PCI_WRITE_CONFIG_DWORD - -#define DEVFN(device, function) (((device) << 3) + (function)) -#ifndef CONFIG_ADDR -#define CONFIG_ADDR(bus,devfn,where) (((bus) << 16) | ((devfn) << 8) | (where)) -#endif +#include "82801.h" /* jump around these subrs */ -jmp smbus_pcibus_end - -/* generic SMB routines that work for many systems. The only one that might - * not work is the enable_smbus. - * you have to define PM_FUNCTION for this to work. - */#define SMBUS_IO_BASE 0xf00 -#define SMBHSTSTAT 0 -#define SMBHSTCTL 2 -#define SMBHSTCMD 3 -#define SMBHSTADD 4 -#define SMBHSTDAT0 5 -#define SMBHSTDAT1 6 -#define SMBBLKDAT 7 - -enable_smbus: - /* put the SMBUS at port 0xf00 */ - CS_WRITE_LONG(PM_DEVFN+ 0x90, SMBUS_IO_BASE|1) /* iobase addr */ - CS_WRITE_BYTE(PM_DEVFN + 0xd2, (0x4 << 1) | 1) /* smbus enable */ - CS_WRITE_WORD(PM_DEVFN + 0x4, 1) /* iospace enable */ - RET_LABEL(enable_smbus) +jmp smbus_end /* - * Routine: setup_smbus + * Routine: smbus_setup * Arguments: none * Results: none - * Trashed: eax, edx + * Trashed: eax, edx, ecx * Effects: The smbus is enabled */ -setup_smbus: - xor %eax,%eax - movl $(SMBUS_IO_BASE +SMBHSTSTAT), %edx - outb %al, %dx - RET_LABEL(setup_smbus) -#define SMBUS_MEM_DEVICE_0 (0xa << 3) -#define SMBUS_MEM_DEVICE_1 (SMBUS_MEM_DEVICE_0 +1) -#define SMBUS_MEM_DEVICE_2 (SMBUS_MEM_DEVICE_0 +2) -#define SMBUS_MEM_DEVICE_3 (SMBUS_MEM_DEVICE_0 +3) +smbus_setup: + /* set smbus iobase */ + movl $((SMBUS_DEVFN << 8) + 0x20), %eax + movl $(SMBUS_IO_BASE | 1), %ecx + PCI_WRITE_CONFIG_DWORD + + /* Set smbus enable */ + movl $((SMBUS_DEVFN << 8) + 0x40), %eax + movl $1, %edx + PCI_WRITE_CONFIG_BYTE + + /* Set smbus iospace enable */ + movl $((SMBUS_DEVFN << 8) + 0x4), %eax + movl $1, %ecx + PCI_WRITE_CONFIG_WORD + + /* Diable interrupt generation */ + movl $(SMBUS_IO_BASE + SMBHSTCTL), %edx + xorl %eax, %eax + outb %al, %dx + + RET_LABEL(smbus_setup) + /* * Routine: smbus_wait_until_ready @@ -69,10 +47,10 @@ setup_smbus: * Effects: Upon return the smbus is ready to accept commands */ smbus_wait_until_ready: - movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx -1: inb %dx, %al - testb $1, %al - jnz 1b + movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx +1: inb %dx, %al + testb $1, %al + jnz 1b RET_LABEL(smbus_wait_until_ready) /* @@ -83,16 +61,16 @@ smbus_wait_until_ready: * Effects: Upon return the smbus has completed it's most recent transation */ smbus_wait_until_done: - movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx -1: inb %dx, %al - testb $1, %al - jnz 1b -2: testb $0xFE, %al - jnz 3f - inb %dx, %al - testb $0xFE, %al - jz 2b -3: RET_LABEL(smbus_wait_until_done) + movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx +1: inb %dx, %al + testb $1, %al + jnz 1b + jmp 3f +2: + inb %dx, %al +3: testb $~((1<<6)|(1<<0)), %al + jz 2b + RET_LABEL(smbus_wait_until_done) /* @@ -119,414 +97,65 @@ smbus_read_byte: /* poll until the smbus is ready for commands */ CALL_LABEL(smbus_wait_until_ready) - /* clear any lingering errors, so that the transaction will run */ - movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx - inb %dx, %al - outb %al, %dx + /* setup transaction */ + /* disable interrupts */ + movl $(SMBUS_IO_BASE + SMBHSTCTL), %edx + inb %dx, %al + andb $0xFE, %al + outb %al, %dx /* set the device I'm talking to */ - movl $(SMBUS_IO_BASE + SMBHSTADD), %edx - movb %bl /* device */, %al - shlb $1, %al - orb $1, %al - outb %al, %dx + movl $(SMBUS_IO_BASE + SMBXMITADD), %edx + movb %bl /* device */, %al + shlb $1, %al + orb $1, %al + outb %al, %dx /* set the command address... */ - movl $(SMBUS_IO_BASE + SMBHSTCMD), %edx - movb %bh /* address */, %al - outb %al, %dx + movl $(SMBUS_IO_BASE + SMBHSTCMD), %edx + movb %bh /* address */, %al + outb %al, %dx - /* clear the data byte */ - movl $(SMBUS_IO_BASE + SMBHSTDAT0), %edx - xorl %eax, %eax - outb %al, %dx + /* setup for a byte data read */ + movl $(SMBUS_IO_BASE + SMBHSTCTL), %edx + inb %dx, %al + andb $0xE3, %al + orb $(0x2 << 2), %al + outb %al, %dx + + /* clear any lingering errors, so the transaction will run */ + movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx + inb %dx, %al + outb %al, %dx + + /* clear the data byte... */ + movl $(SMBUS_IO_BASE + SMBHSTDAT0), %edx + xorl %eax, %eax + outb %al, %dx /* start a byte read, with interrupts disabled */ - movl $(SMBUS_IO_BASE + SMBHSTCTL), %edx - movl $((0x2 << 2) | (1 << 6)), %eax - outb %al, %dx + movl $(SMBUS_IO_BASE + SMBHSTCTL), %edx + inb %dx, %al + orb $0x40, %al + outb %al, %dx /* poll for transaction completion */ CALL_LABEL(smbus_wait_until_done) /* read the results and see if we succeded */ - movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx - inb %dx, %al - testb $0x02, %al - jz 1f + movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx + inb %dx, %al + andb $~(1 << 6), %al /* Ignore the In Use Status... */ + cmpb $0x02, %al + sete %al + testb %al, %al + jz 1f + movl $(SMBUS_IO_BASE + SMBHSTDAT0), %edx inb %dx, %al 1: RETSP -/* now for code to actually do the deed. Eric did such a good job that - * this stuff is basically generic. - */ - /* - * Routine: spd_set_drb - * Arguments: None - * - * Trashed: %eax, %ebx, %ecx, %edx, %esi, %edi, %ebp, %esp, %eflags - * Effects: Uses serial presence detect to set the - * DRB registers which holds the ending memory address assigned - * to each DIMM. - * Notes: %ebp holds the currently detected end of memory. - * %ebx holds the configuration port & SMBUS_MEM_DEVICE for - * the current iteration through the loop. - * %edi holds the memory size for the first side of the DIMM. - * %esi holds the memory size for the second side of the DIMM. - * memory size is represent as a power of 2. - * An unset memory size is represented as -1 ie. 0xFFFFFFFF - */ - -spd_set_drb: - xorl %ebp, %ebp /* clear the memory address */ - movl $((DRAM_CONFIG_PORT << 16) |SMBUS_MEM_DEVICE_0), %ebx -spd_set_drb_loop_top: - // set -1 power-of-two for side 1 (called bank0 in most chipset docs) - xorl %edi, %edi - subl $1, %edi - // set -1 power-of-two for side 2 (called bank1 in most chipset docs) - xorl %esi, %esi - subl $1, %esi - - movb $3, %bh /* rows */ - CALLSP(smbus_read_byte) - // If it's zero, then we just set current %ebp into the row - // end register - jz 20f - andl $0xf, %eax - addl %eax, %edi - - movb $4, %bh /* columns */ - CALLSP(smbus_read_byte) - andl $0xf, %eax - addl %eax, %edi - - movb $17, %bh /* banks */ - CALLSP(smbus_read_byte) - andl $0xff, %eax - bsrl %eax, %ecx - addl %ecx, %edi - - /* Get the module data width and convert it to a power of two */ - movb $7, %bh /* (high byte) */ - CALLSP(smbus_read_byte) - andl $0xff, %eax - movl %eax, %ecx - shll $8, %ecx - - movb $6, %bh /* (low byte) */ - CALLSP(smbus_read_byte) - andl $0xff, %eax - orl %eax, %ecx - bsrl %ecx, %eax - addl %eax, %edi - - /* now I have the ram size in bits as a power of two (less 1) */ - // It is less 1 since we started with -1 above. - // OK, BITS as power of two (but minus 1) - // So, e.g., 8 MB is 64 Mb, 64 Mb is 26 bits. Subtract - // (26-1) or 25 - subl $25, %edi /* Make it multiples of 8MB */ - - /* side two */ - movb $5, %bh /* number of physical banks */ - CALLSP(smbus_read_byte) - cmp $1, %al - // it's only one bank - jbe 20f - // It's two banks. So assign edi to esi - /* for now only handle the symmetrical case */ - // it's two banks, assume however that they're the same size. - // it's stupid to have any other kind, right? - movl %edi, %esi -20: - /* Compute the end address for the DRB register */ - // If it is >= 8, i.e. >= 2^8 or 256, skip it. - // >= 8 is a bogus value. - cmpl $8, %edi - jae 21f - movl $1, %eax - movl %edi, %ecx - shll %cl, %eax - // increment row-end by the size of this DIMM half - addl %eax, %ebp -21: - /* Write the comuputed value for the first half of the DIMM */ - movl %ebp, %edx /* value to write into %edx */ - movl %ebx, %eax - shrl $16, %eax /* port address into %eax */ - PCI_WRITE_CONFIG_BYTE - - /* Compute the end address for the DRB register */ - cmpl $8, %esi - jae 30f - mov $1, %eax - movl %esi, %ecx - shll %cl, %eax - addl %eax, %ebp -30: - /* Write the comuputed value for the second half of the DIMM */ - movl %ebp, %edx /* value to write into %edx */ - movl %ebx, %eax - shrl $16, %eax /* port address into %eax */ - addl $1, %eax /* The second half uses one port high */ - PCI_WRITE_CONFIG_BYTE - - addl $0x00020001, %ebx /* increment the smbus device & the config port */ - cmpb $LAST_SMBUS_MEM_DEVICE, %bl /* see if I have reached the end */ - jbe spd_set_drb_loop_top - - /* o.k. I'm done return now */ - RET_LABEL(spd_set_drb) - - /* - * Routine: spd_set_dramc - * Arguments: None - * - * Trashed: %eax, %ebx, %edx, %esp, %eflags - * Effects: Uses serial presence detect to set the - * DRAMC register, which records if ram is registerd or not, - * and controls the refresh rate. - * The refresh rate is not set here, as memory refresh - * cannot be enbaled until after memory is initialized. - * see spd_enable_refresh. - * Notes: - * FIXME: Check for illegal/unsupported ram configurations and abort - * FIXME: won't work with non-contiguous DRAM size regs (like VIA) - * need an indirect pointer to an array of reg #s - */ - -spd_set_dramc: - /* auto detect if ram is registered or not. */ - /* The DRAMC register also contorls the refresh rate but we can't - * set that here because we must leave refresh disabled. - * see: spd_enable_refresh - */ - /* Find the first dimm and assume the rest are the same */ - /* Load the smbus device and port int %ebx */ - movl $((21 << 8) | SMBUS_MEM_DEVICE_0), %ebx -1: CALLSP(smbus_read_byte) - jz 2f - andl $0x12, %eax - jmp spd_set_dramc_out - -2: addl $1, %ebx /* increment the device */ - cmpb $LAST_SMBUS_MEM_DEVICE, %bl - jbe 1b - /* We couldn't find anything we must have no memory */ - jmp no_memory - -spd_set_dramc_out: - testb $0x12, %al - jz 2f - movl REGISTERED_DRAM, %eax - jmp 1f -2: movl NONREGISTERED_DRAM, %eax -1: movl %eax, %edx - movl REGISTERED_DRAM_REGISTER, %eax - PCI_WRITE_CONFIG_BYTE - RET_LABEL(spd_set_dramc) - - - - /* - * Routine: spd_read_refresh - * Arguments: None - * - * Trashed: %eax, %ebx, %ecx, %edx, %esp, %eflags - * Effects: Uses serial presence detect to find refresh rates. - * returns the rate in %eax - * It's up to you to set hardware up. - * FIXME: Check for illegal/unsupported ram configurations and abort - */ - - -spd_read_refresh: - /* Find the first dimm and assume the rest are the same */ - /* Load the smbus device and port int %ebx */ - movl $((12 << 8) | SMBUS_MEM_DEVICE_0), %ebx -1: CALLSP(smbus_read_byte) - jz 2f - andl $0x7f, %eax - jmp spd_enable_refresh_out - -2: addl $1, %ebx /* increment the device */ - cmpb $LAST_SMBUS_MEM_DEVICE, %bl - jbe 1b - /* We couldn't find anything we must have no memory */ - xorl %eax, %eax -spd_enable_refresh_out: - RET_LABEL(spd_enable_refresh) - - /* - * Routine: spd_set_rps - * Arguments: None - * - * Trashed: %eax, %ebx, %ecx, %edx, %esi, %edi, %esp, %eflags - * Effects: Uses serial presence detect to set the row size - * on a given DIMM - * Notes: %esi accumulates the row sizes of all of the DIMMs - * %ecx holds the current bit into into %esi - * %bl holds the current SMBUS device - * FIXME: Check for illegal/unsupported ram configurations and abort - */ - -spd_set_rps: - /* The RPS register holds the size of a ``page'' of DRAM on each DIMM */ - /* default all page sizes to 2KB */ - xorl %esi, %esi - /* Index into %esi of bit to set */ - movl $0 , %ecx - /* Load the smbus device into %ebx */ - movl $SMBUS_MEM_DEVICE_0, %ebx - -1: movb $3, %bh - CALLSP(smbus_read_byte) /* row address bits */ - jz 2f - andl $0xf, %eax - movl %eax, %edi - /* I now have the row page size as a power of 2 */ - subl $11, %edi /* Now make it in multiples of 2Kb */ - jbe 2f - /* FIXME: do something with page sizes greather than 8KB!! */ - shll %cl, %edi - orl %edi, %esi - /* side two */ - movb $5, %bh - CALLSP(smbus_read_byte) /* number of physical banks */ - cmp $1, %al - jbe 2f - /* for now only handle the symmtrical case */ - shll $2, %edi - shll %cl, %edi - orl %edi, %esi - -2: addl $1, %ebx /* increment the device */ - addl $4, %ecx /* increment the shift count */ - cmpb $LAST_SMBUS_MEM_DEVICE, %bl - jbe 1b - - movl $0x7f, %eax -/* I'm not sure what we should do here. Do nothing. */ -/* PCI_WRITE_CONFIG_WORD*/ - RET_LABEL(spd_set_rps) - - /* - * Routine: spd_set_pgpol - * Arguments: None - * - * Trashed: %eax, %ebx, %ecx, %edx, %esi, %esp, %eflags - * Effects: Uses serial presence detect to set the number of banks - * on a given DIMM - * Notes: %esi accumulates the banks sizes of all of the DIMMs - * %ecx holds the current bit into into %esi - * %bl holds the current SMBUS device - * FIXME: Check for illegal/unsupported ram configurations and abort - */ - -spd_set_pgpol: - /* The PGPOL register stores the number of logical banks per DIMM, - * and number of clocks the DRAM controller waits in the idle - * state. - */ - /* default all bank counts 2 */ - xorl %esi, %esi - /* Index into %esi of bit to set */ - movl $0 , %ecx - /* Load the smbus device into %ebx */ - movl $SMBUS_MEM_DEVICE_0, %ebx - -1: movb $17, %bh - CALLSP(smbus_read_byte) /* logical banks */ - jz 2f - cmp $0x4, %eax - jl 2f - movl $0x1, %eax - shll %cl, %eax - orl %eax, %esi - /* side two */ - movb $5, %bh - CALLSP(smbus_read_byte) /* number of physical banks */ - cmp $1, %al - jbe 2f - /* for now only handle the symmtrical case */ - movl $0x2, %eax - shll %cl, %eax - orl %eax, %esi - -2: addl $1, %ebx /* increment the device */ - addl $2, %ecx /* increment the shift count */ - cmpb $LAST_SMBUS_MEM_DEVICE, %bl - jbe 1b - - shll $8, %esi - orl $0x7, %esi /* 32 clocks idle time */ - movl %esi, %ecx - movl $0x78, %eax -/* I'm unclear on the concept for non-intel devices */ -/* PCI_WRITE_CONFIG_WORD*/ - RET_LABEL(spd_set_pgpol) - - - - /* - * Routine: spd_enable_nbxcfg - * Arguments: None - * - * Trashed: %eax, %ebx, %ecx, %edx, %esi, %esp, %eflags - * Effects: Uses serial presence detect to set the - * ECC support flags in the NBXCFG register - * Notes: %esi accumulates the ECC support of the individual DIMMs. - * %ecx holds the bit that should be flipped for the current DIMM. - * %bl holds the smbus device that corresponds to the current DIMM. - * FIXME: Check for illegal/unsupported ram configurations and abort - */ - -spd_set_nbxcfg: - /* say all dimms have no ECC support */ - movl $0xFF, %esi - /* Index into %esi of bit to set */ - movl $0 , %ecx - /* Load the smbus device into %ebx */ - movl $SMBUS_MEM_DEVICE_0, %ebx - -1: movb $11, %bh - CALLSP(smbus_read_byte) /* module error correction type */ - jz 2f - cmp $0x2, %eax /* 0 == None, 1 == Parity, 2 == ECC */ - jne 2f - movl $0x1, %eax - shll %cl, %eax - xorl %eax, %esi - - /* side two */ - movb $5, %bh - CALLSP(smbus_read_byte) /* number of physical banks */ - cmp $1, %al - jbe 2f - /* The only is the symmtrical case */ - movl $0x2, %eax - shll %cl, %eax - xorl %eax, %esi - -2: addl $1, %ebx /* increment the device */ - addl $2, %ecx /* increment the shift count */ - cmpb $LAST_SMBUS_MEM_DEVICE, %bl - jbe 1b - - movl %esi, %edx -/* at some point, we need to indicate how to turn ECC on. Not yet. - movl $0x53, %eax - PCI_WRITE_CONFIG_BYTE - */ - RET_LABEL(spd_set_nbxcfg) - - - -smbus_pcibus_end: -CALL_LABEL(enable_smbus) -CALL_LABEL(setup_smbus) - +smbus_end: +CALL_LABEL(smbus_setup) diff --git a/src/southbridge/intel/82801ca/watchdog_disable.inc b/src/southbridge/intel/82801ca/watchdog_disable.inc new file mode 100644 index 0000000000..c95895824b --- /dev/null +++ b/src/southbridge/intel/82801ca/watchdog_disable.inc @@ -0,0 +1,9 @@ +/* Disable the TCO watch dog timer in the southbridge */ +/* bridge 0, device 1f, function 0, byte d4, bit 1 */ + + movl $0x8000f8d4,%eax + movl $0x0cf8,%edx + outl %eax,%dx + movl $0x0cfc,%edx + movb $2,%al + outb %al,%dx diff --git a/src/superio/winbond/w83627hf/setup_serial.inc b/src/superio/winbond/w83627hf/setup_serial.inc index a2c0251e8d..911aabee58 100644 --- a/src/superio/winbond/w83627hf/setup_serial.inc +++ b/src/superio/winbond/w83627hf/setup_serial.inc @@ -19,30 +19,31 @@ outb %al, $(SIO_BASE) #define SIO_WRITE_CONFIG(value, reg) \ - movb $reg, %al ; \ + movb reg, %al ; \ outb %al, $(SIO_INDEX) ; \ - movb $value, %al ; \ + movb value, %al ; \ outb %al, $(SIO_DATA) -#define SIO_READ_CONFIG(value, reg) \ - movb $reg, %al ; \ +#define SIO_READ_CONFIG(reg) \ + movb reg, %al ; \ outb %al, $(SIO_INDEX) ; \ - inb %al, $(SIO_DATA) + inb $(SIO_DATA), %al #define SIO_SET_LOGICAL_DEVICE(device) \ - SIO_WRITE_CONFIG(device, 0x07) + SIO_WRITE_CONFIG(device, $0x07) + /* Enable pnp */ SIO_ENTER_PNP_MODE() #if defined(SIO_SYSTEM_CLK_INPUT) /* Setup up the clock input */ - SIO_WRITE_CONFIG((0x84 | SIO_SYSTEM_CLK_INPUT), 0x24) + SIO_WRITE_CONFIG($(0x84 | SIO_SYSTEM_CLK_INPUT), $0x24) #endif /* enable serial 1 */ - SIO_SET_LOGICAL_DEVICE(COM1_DEVICE) - SIO_WRITE_CONFIG(1, 0x30) - SIO_WRITE_CONFIG(0x3, 0x60) - SIO_WRITE_CONFIG(0xf8, 0x61) + SIO_SET_LOGICAL_DEVICE($COM1_DEVICE) + SIO_WRITE_CONFIG($1, $0x30) + SIO_WRITE_CONFIG($0x3, $0x60) + SIO_WRITE_CONFIG($0xf8, $0x61) SIO_EXIT_PNP_MODE() diff --git a/util/config/NLBConfig.py b/util/config/NLBConfig.py index 145886501a..8802bab566 100644 --- a/util/config/NLBConfig.py +++ b/util/config/NLBConfig.py @@ -373,7 +373,7 @@ def nsuperio(dir, superio_commands): superio_decls = superio_decls + decl; superio_devices.append("&superio_" + superio_decl_name); # note that we're using the new interface - option(dir, "USE_NEW_SUPERIO_INTERFACE") + option(dir, "USE_NEW_SUPERIO_INTERFACE=1") numsuperio = numsuperio + 1 @@ -705,6 +705,10 @@ def option(dir, option): value = "" if m and m.group(1): (key, value) = m.groups() + else: + warning("Invalid option specifcation: %s assuming you meant %s=1" % + (option, option) ) + value = "1" m = option_re.match(key) if not m: fatal("Invalid option name: %s" % (key)) diff --git a/util/lb-dump/dump_lb_table.c b/util/lb-dump/dump_lb_table.c index 59afb1253d..90ed034e2b 100644 --- a/util/lb-dump/dump_lb_table.c +++ b/util/lb-dump/dump_lb_table.c @@ -12,22 +12,36 @@ void print_lb_records(struct lb_record *rec, struct lb_record *last, unsigned lo unsigned long compute_checksum(void *addr, unsigned long length) { - unsigned short *ptr; + uint8_t *ptr; + volatile union { + uint8_t byte[2]; + uint16_t word; + } value; unsigned long sum; - unsigned long len; - /* Assumes len is a multiple of two, and addr is 2 byte aligned. */ - /* compute an ip style checksum */ + unsigned long i; + /* In the most straight forward way possible, + * compute an ip style checksum. + */ sum = 0; - len = length >> 1; ptr = addr; - while (len--) { - sum += *(ptr++); - if (sum > 0xFFFF) - sum -= 0xFFFF; + for(i = 0; i < length; i++) { + unsigned long value; + value = ptr[i]; + if (i & 1) { + value <<= 8; + } + /* Add the new value */ + sum += value; + /* Wrap around the carry */ + if (sum > 0xFFFF) { + sum = (sum + (sum >> 16)) & 0xFFFF; + } } - return (~sum) & 0xFFFF; - + value.byte[0] = sum & 0xff; + value.byte[1] = (sum >> 8) & 0xff; + return (~value.word) & 0xFFFF; } + #define for_each_lbrec(head, rec) \ for(rec = (struct lb_record *)(((char *)head) + sizeof(*head)); \ (((char *)rec) < (((char *)head) + sizeof(*head) + head->table_bytes)) && \ @@ -157,8 +171,17 @@ void print_mainboard(struct lb_record *ptr, unsigned long addr) rec = (struct lb_mainboard *)ptr; max_size = rec->size - sizeof(*rec); printf("vendor: %.*s part number: %.*s\n", - max_size - rec->vendor_idx, rec->strings + rec->vendor_idx, - max_size - rec->vendor_idx, rec->strings + rec->part_number_idx); + max_size - rec->vendor_idx, rec->strings + rec->vendor_idx, + max_size - rec->part_number_idx, rec->strings + rec->part_number_idx); +} + +void print_string(struct lb_record *ptr, unsigned long addr) +{ + struct lb_string *rec; + int max_size; + rec = (struct lb_string *)ptr; + max_size = rec->size - sizeof(*rec); + printf("%.*s\n", max_size, rec->string); } void print_option_table(struct lb_record *ptr, unsigned long addr) @@ -213,6 +236,16 @@ struct { { LB_TAG_MEMORY, "Memory", print_memory }, { LB_TAG_HWRPB, "HWRPB", nop_print }, { LB_TAG_MAINBOARD, "Mainboard", print_mainboard }, + { LB_TAG_VERSION, "Version", print_string }, + { LB_TAG_EXTRA_VERSION, "Extra Version", print_string }, + { LB_TAG_BUILD, "Build", print_string }, + { LB_TAG_COMPILE_TIME, "Compile Time", print_string }, + { LB_TAG_COMPILE_BY, "Compile By", print_string }, + { LB_TAG_COMPILE_HOST, "Compile Host", print_string }, + { LB_TAG_COMPILE_DOMAIN, "Compile Domain", print_string }, + { LB_TAG_COMPILER, "Compiler", print_string }, + { LB_TAG_LINKER, "Linker", print_string }, + { LB_TAG_ASSEMBLER, "Assembler", print_string }, { LB_TAG_CMOS_OPTION_TABLE, "CMOS option table", print_option_table }, { LB_TAG_OPTION, "Option", print_option }, { LB_TAG_OPTION_ENUM, "Option Enumeration", print_option_enumeration }, diff --git a/util/mkelfImage/News b/util/mkelfImage/News new file mode 100644 index 0000000000..3f7b7f7f50 --- /dev/null +++ b/util/mkelfImage/News @@ -0,0 +1,5 @@ +1.14 + +- Use much less complex ld magic +- Fix a small bug in the LinuxBIOS checksum verification code +