ipxe-precise-1.0.0+git-2.55f6c88/0000775000175000017500000000000011701704160015025 5ustar sergesergeipxe-precise-1.0.0+git-2.55f6c88/README0000664000175000017500000000016111701704160015703 0ustar sergesergeiPXE README File Quick start guide: cd src make For any more detailed instructions, see http://ipxe.org ipxe-precise-1.0.0+git-2.55f6c88/COPYING0000664000175000017500000004307611701704160016072 0ustar sergeserge 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. ipxe-precise-1.0.0+git-2.55f6c88/COPYRIGHTS0000664000175000017500000000105611701704160016445 0ustar sergesergeIn general iPXE files are licensed under the GPL. For historical reasons, individual files may contain their own licence declarations. Most builds of iPXE do not contain all iPXE code (in particular, most builds will include only one driver), and so the overall licence can vary depending on what target you are building. The resultant applicable licence(s) for any particular build can be determined by using "make bin/xxxxxxx.yyy.licence"; for example: make bin/rtl8139.rom.licence to determine the resultant licence(s) for the build bin/rtl8139.rom ipxe-precise-1.0.0+git-2.55f6c88/src/0000775000175000017500000000000011701704160015614 5ustar sergesergeipxe-precise-1.0.0+git-2.55f6c88/src/libgcc/0000775000175000017500000000000011701704160017037 5ustar sergesergeipxe-precise-1.0.0+git-2.55f6c88/src/libgcc/__divdi3.c0000664000175000017500000000051511701704160020664 0ustar sergeserge/* * arch/i386/libgcc/__divdi3.c */ #include "libgcc.h" __libgcc int64_t __divdi3(int64_t num, int64_t den) { int minus = 0; int64_t v; if ( num < 0 ) { num = -num; minus = 1; } if ( den < 0 ) { den = -den; minus ^= 1; } v = __udivmoddi4(num, den, NULL); if ( minus ) v = -v; return v; } ipxe-precise-1.0.0+git-2.55f6c88/src/libgcc/__udivdi3.c0000664000175000017500000000023711701704160021052 0ustar sergeserge/* * arch/i386/libgcc/__divdi3.c */ #include "libgcc.h" __libgcc uint64_t __udivdi3(uint64_t num, uint64_t den) { return __udivmoddi4(num, den, NULL); } ipxe-precise-1.0.0+git-2.55f6c88/src/libgcc/__moddi3.c0000664000175000017500000000053211701704160020660 0ustar sergeserge/* * arch/i386/libgcc/__moddi3.c */ #include "libgcc.h" __libgcc int64_t __moddi3(int64_t num, int64_t den) { int minus = 0; int64_t v; if ( num < 0 ) { num = -num; minus = 1; } if ( den < 0 ) { den = -den; minus ^= 1; } (void) __udivmoddi4(num, den, (uint64_t *)&v); if ( minus ) v = -v; return v; } ipxe-precise-1.0.0+git-2.55f6c88/src/libgcc/libgcc.h0000664000175000017500000000070411701704160020434 0ustar sergeserge#ifndef _LIBGCC_H #define _LIBGCC_H #include #include extern __libgcc uint64_t __udivmoddi4 ( uint64_t num, uint64_t den, uint64_t *rem ); extern __libgcc uint64_t __udivdi3 (uint64_t num, uint64_t den ); extern __libgcc uint64_t __umoddi3 ( uint64_t num, uint64_t den ); extern __libgcc int64_t __divdi3 ( int64_t num, int64_t den ); extern __libgcc int64_t __moddi3 ( int64_t num, int64_t den ); #endif /* _LIBGCC_H */ ipxe-precise-1.0.0+git-2.55f6c88/src/libgcc/__udivmoddi4.c0000664000175000017500000000111311701704160021545 0ustar sergeserge#include "libgcc.h" __libgcc uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t *rem_p) { uint64_t quot = 0, qbit = 1; if ( den == 0 ) { return 1/((unsigned)den); /* Intentional divide by zero, without triggering a compiler warning which would abort the build */ } /* Left-justify denominator and count shift */ while ( (int64_t)den >= 0 ) { den <<= 1; qbit <<= 1; } while ( qbit ) { if ( den <= num ) { num -= den; quot += qbit; } den >>= 1; qbit >>= 1; } if ( rem_p ) *rem_p = num; return quot; } ipxe-precise-1.0.0+git-2.55f6c88/src/libgcc/icc.c0000664000175000017500000000024611701704160017743 0ustar sergeserge/* * Intel's compiler creates an implicit call to this function at the * start of main(). * */ void __libgcc __intel_new_proc_init ( void ) { /* Do nothing */ } ipxe-precise-1.0.0+git-2.55f6c88/src/libgcc/memcpy.c0000664000175000017500000000111211701704160020470 0ustar sergeserge/** @file * * gcc sometimes likes to insert implicit calls to memcpy(). * Unfortunately, there doesn't seem to be any way to prevent it from * doing this, or to force it to use the optimised memcpy() as seen by * C code; it insists on inserting a symbol reference to "memcpy". We * therefore include wrapper functions just to keep gcc happy. * */ #include void * gcc_implicit_memcpy ( void *dest, const void *src, size_t len ) asm ( "memcpy" ); void * gcc_implicit_memcpy ( void *dest, const void *src, size_t len ) { return memcpy ( dest, src, len ); } ipxe-precise-1.0.0+git-2.55f6c88/src/libgcc/__umoddi3.c0000664000175000017500000000027111701704160021045 0ustar sergeserge/* * arch/i386/libgcc/__umoddi3.c */ #include "libgcc.h" __libgcc uint64_t __umoddi3(uint64_t num, uint64_t den) { uint64_t v; (void) __udivmoddi4(num, den, &v); return v; } ipxe-precise-1.0.0+git-2.55f6c88/src/tests/0000775000175000017500000000000011701704160016756 5ustar sergesergeipxe-precise-1.0.0+git-2.55f6c88/src/tests/gdbstub_test.S0000664000175000017500000000156211701704160021577 0ustar sergeserge .arch i386 .section ".data", "aw", @progbits watch_me: .long 0xfeedbeef .section ".text", "ax", @progbits .code32 gdbstub_test: /* 1. Read registers test */ movl $0xea010203, %eax movl $0xeb040506, %ebx movl $0xec070809, %ecx movl $0xed0a0b0c, %edx movl $0x510d0e0f, %esi movl $0xd1102030, %edi int $3 /* 2. Write registers test */ int $3 /* 3. Read memory test */ subl $8, %esp movl $0x11223344, 4(%esp) movw $0x5566, 2(%esp) movb $0x77, (%esp) int $3 /* 4. Write memory test */ int $3 addl $8, %esp /* 5. Step test */ int $3 nop /* 6. Access watch test */ movl $0x600d0000, %ecx movl watch_me, %eax movl $0xbad00000, %ecx int $3 movl $0x600d0001, %ecx movl %eax, watch_me movl $0xbad00001, %ecx int $3 /* 7. Write watch test */ movl $0x600d0002, %ecx movl %eax, watch_me movl $0xbad00002, %ecx int $3 1: jmp 1b ipxe-precise-1.0.0+git-2.55f6c88/src/tests/linebuf_test.c0000664000175000017500000000161611701704160021611 0ustar sergeserge#include #include #include #include static const char data1[] = "Hello world\r\n" "This is a reasonably nice set of lines\n" "with not many different terminators\r\n\r\n" "There should be exactly one blank line above\n" "and this line should never appear at all since it has no terminator"; void linebuf_test ( void ) { struct line_buffer linebuf; const char *data = data1; size_t len = ( sizeof ( data1 ) - 1 /* be mean; strip the NUL */ ); ssize_t frag_len; char *line; memset ( &linebuf, 0, sizeof ( linebuf ) ); while ( len ) { frag_len = line_buffer ( &linebuf, data, len ); if ( frag_len < 0 ) { printf ( "line_buffer() failed: %s\n", strerror ( frag_len ) ); return; } data += frag_len; len -= frag_len; if ( ( line = buffered_line ( &linebuf ) ) ) printf ( "\"%s\"\n", line ); } empty_line_buffer ( &linebuf ); } ipxe-precise-1.0.0+git-2.55f6c88/src/tests/list_test.c0000664000175000017500000003066511701704160021146 0ustar sergeserge/* * Copyright (C) 2011 Michael Brown . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); /** @file * * List function tests * */ /* Forcibly enable assertions for list_check() */ #undef NDEBUG #include #include #include #include #include /** A list test structure */ struct list_test { /** List element */ struct list_head list; /** Label */ char label; }; /** List test elements */ static struct list_test list_tests[] = { { .label = '0' }, { .label = '1' }, { .label = '2' }, { .label = '3' }, { .label = '4' }, { .label = '5' }, { .label = '6' }, { .label = '7' }, { .label = '8' }, { .label = '9' }, }; /** Test list */ static LIST_HEAD ( test_list ); /** * Check list contents are as expected * * @v list Test list * @v expected Expected contents * @v ok List contents are as expected */ static int list_check_contents ( struct list_head *list, const char *expected ) { struct list_test *entry; size_t num_entries = 0; /* Determine size of list */ list_for_each_entry ( entry, list, list ) num_entries++; { char found[ num_entries + 1 ]; char found_rev[ num_entries + 1 ]; char *tmp; /* Build up list content string */ tmp = found; list_for_each_entry ( entry, list, list ) *(tmp++) = entry->label; *tmp = '\0'; /* Sanity check reversed list */ tmp = &found_rev[ sizeof ( found_rev ) - 1 ]; *tmp = '\0'; list_for_each_entry_reverse ( entry, list, list ) *(--tmp) = entry->label; if ( strcmp ( found, found_rev ) != 0 ) { printf ( "FAILURE: list reversal mismatch (forward " "\"%s\", reverse \"%s\")\n", found, found_rev ); return 0; } /* Compare against expected content */ if ( strcmp ( found, expected ) == 0 ) { return 1; } else { printf ( "FAILURE: expected \"%s\", got \"%s\"\n", expected, found ); return 0; } } } /** * Report list test result * * @v list Test list * @v expected Expected contents */ #define list_contents_ok( list, expected ) do { \ ok ( list_check_contents ( (list), (expected) ) ); \ } while ( 0 ) /** * Perform list self-test * */ static void list_test_exec ( void ) { struct list_head *list = &test_list; struct list_head target_list; struct list_head *target = &target_list; /* Test initialiser and list_empty() */ ok ( list_empty ( list ) ); list_contents_ok ( list, "" ); /* Test list_add(), list_add_tail() and list_del() */ INIT_LIST_HEAD ( list ); list_contents_ok ( list, "" ); list_add ( &list_tests[4].list, list ); /* prepend */ list_contents_ok ( list, "4" ); list_add ( &list_tests[2].list, list ); /* prepend */ list_contents_ok ( list, "24" ); list_add_tail ( &list_tests[7].list, list ); /* append */ list_contents_ok ( list, "247" ); list_add ( &list_tests[1].list, &list_tests[4].list ); /* after */ list_contents_ok ( list, "2417" ); list_add_tail ( &list_tests[8].list, &list_tests[7].list ); /* before */ list_contents_ok ( list, "24187" ); list_del ( &list_tests[4].list ); /* delete middle */ list_contents_ok ( list, "2187" ); list_del ( &list_tests[2].list ); /* delete first */ list_contents_ok ( list, "187" ); list_del ( &list_tests[7].list ); /* delete last */ list_contents_ok ( list, "18" ); list_del ( &list_tests[1].list ); /* delete all */ list_del ( &list_tests[8].list ); /* delete all */ list_contents_ok ( list, "" ); ok ( list_empty ( list ) ); /* Test list_is_singular() */ INIT_LIST_HEAD ( list ); ok ( ! list_is_singular ( list ) ); list_add ( &list_tests[1].list, list ); ok ( list_is_singular ( list ) ); list_add ( &list_tests[3].list, list ); ok ( ! list_is_singular ( list ) ); list_del ( &list_tests[1].list ); ok ( list_is_singular ( list ) ); /* Test list_is_last() */ INIT_LIST_HEAD ( list ); list_add_tail ( &list_tests[6].list, list ); ok ( list_is_last ( &list_tests[6].list, list ) ); list_add_tail ( &list_tests[4].list, list ); ok ( list_is_last ( &list_tests[4].list, list ) ); ok ( ! list_is_last ( &list_tests[6].list, list ) ); /* Test list_cut_position() - empty list */ INIT_LIST_HEAD ( list ); INIT_LIST_HEAD ( target ); list_cut_position ( target, list, list ); list_contents_ok ( list, "" ); list_contents_ok ( target, "" ); /* Test list_cut_position() - singular list, move nothing */ INIT_LIST_HEAD ( list ); INIT_LIST_HEAD ( target ); list_add_tail ( &list_tests[4].list, list ); list_cut_position ( target, list, list ); list_contents_ok ( list, "4" ); list_contents_ok ( target, "" ); /* Test list_cut_position() - singular list, move singular entry */ INIT_LIST_HEAD ( list ); INIT_LIST_HEAD ( target ); list_add_tail ( &list_tests[9].list, list ); list_cut_position ( target, list, &list_tests[9].list ); list_contents_ok ( list, "" ); list_contents_ok ( target, "9" ); /* Test list_cut_position() - multi-entry list, move nothing */ INIT_LIST_HEAD ( list ); list_add_tail ( &list_tests[3].list, list ); list_add_tail ( &list_tests[2].list, list ); list_add_tail ( &list_tests[7].list, list ); INIT_LIST_HEAD ( target ); list_cut_position ( target, list, list ); list_contents_ok ( list, "327" ); list_contents_ok ( target, "" ); /* Test list_cut_position() - multi-entry list, move some */ INIT_LIST_HEAD ( list ); INIT_LIST_HEAD ( target ); list_add_tail ( &list_tests[8].list, list ); list_add_tail ( &list_tests[0].list, list ); list_add_tail ( &list_tests[9].list, list ); list_add_tail ( &list_tests[3].list, list ); list_add_tail ( &list_tests[2].list, list ); list_cut_position ( target, list, &list_tests[0].list ); list_contents_ok ( list, "932" ); list_contents_ok ( target, "80" ); /* Test list_cut_position() - multi-entry list, move everything */ INIT_LIST_HEAD ( list ); INIT_LIST_HEAD ( target ); list_add_tail ( &list_tests[3].list, list ); list_add_tail ( &list_tests[5].list, list ); list_add_tail ( &list_tests[4].list, list ); list_add_tail ( &list_tests[7].list, list ); list_add_tail ( &list_tests[1].list, list ); list_cut_position ( target, list, &list_tests[1].list ); list_contents_ok ( list, "" ); list_contents_ok ( target, "35471" ); /* Test list_splice() - empty list */ INIT_LIST_HEAD ( list ); INIT_LIST_HEAD ( target ); list_splice ( list, target ); list_contents_ok ( list, "" ); list_contents_ok ( target, "" ); /* Test list_splice() - both lists empty */ INIT_LIST_HEAD ( list ); INIT_LIST_HEAD ( target ); list_splice ( list, target ); list_contents_ok ( target, "" ); /* Test list_splice() - source list empty */ INIT_LIST_HEAD ( list ); INIT_LIST_HEAD ( target ); list_add_tail ( &list_tests[1].list, target ); list_add_tail ( &list_tests[3].list, target ); list_splice ( list, &list_tests[1].list ); list_contents_ok ( target, "13" ); /* Test list_splice() - destination list empty */ INIT_LIST_HEAD ( list ); INIT_LIST_HEAD ( target ); list_add_tail ( &list_tests[6].list, list ); list_add_tail ( &list_tests[5].list, list ); list_add_tail ( &list_tests[2].list, list ); list_splice ( list, target ); list_contents_ok ( target, "652" ); /* Test list_splice() - both lists non-empty */ INIT_LIST_HEAD ( list ); INIT_LIST_HEAD ( target ); list_add_tail ( &list_tests[8].list, list ); list_add_tail ( &list_tests[4].list, list ); list_add_tail ( &list_tests[5].list, list ); list_add_tail ( &list_tests[1].list, target ); list_add_tail ( &list_tests[9].list, target ); list_splice ( list, &list_tests[1].list ); list_contents_ok ( target, "18459" ); /* Test list_splice_tail() - both lists empty */ INIT_LIST_HEAD ( list ); INIT_LIST_HEAD ( target ); list_splice_tail ( list, target ); list_contents_ok ( target, "" ); /* Test list_splice_tail() - source list empty */ INIT_LIST_HEAD ( list ); INIT_LIST_HEAD ( target ); list_add_tail ( &list_tests[5].list, target ); list_splice_tail ( list, &list_tests[5].list ); list_contents_ok ( target, "5" ); /* Test list_splice_tail() - destination list empty */ INIT_LIST_HEAD ( list ); INIT_LIST_HEAD ( target ); list_add_tail ( &list_tests[2].list, list ); list_add_tail ( &list_tests[1].list, list ); list_add_tail ( &list_tests[0].list, list ); list_splice_tail ( list, target ); list_contents_ok ( target, "210" ); /* Test list_splice_tail() - both lists non-empty */ INIT_LIST_HEAD ( list ); INIT_LIST_HEAD ( target ); list_add_tail ( &list_tests[9].list, list ); list_add_tail ( &list_tests[5].list, list ); list_add_tail ( &list_tests[7].list, list ); list_add_tail ( &list_tests[2].list, target ); list_add_tail ( &list_tests[4].list, target ); list_splice_tail ( list, &list_tests[2].list ); list_contents_ok ( target, "95724" ); /* Test list_splice_init() */ INIT_LIST_HEAD ( list ); INIT_LIST_HEAD ( target ); list_add_tail ( &list_tests[4].list, list ); list_add_tail ( &list_tests[1].list, target ); list_splice_init ( list, target ); ok ( list_empty ( list ) ); list_contents_ok ( list, "" ); list_contents_ok ( target, "41" ); /* Test list_splice_tail_init() */ INIT_LIST_HEAD ( list ); INIT_LIST_HEAD ( target ); list_add_tail ( &list_tests[3].list, list ); list_add_tail ( &list_tests[2].list, list ); list_add_tail ( &list_tests[5].list, target ); list_splice_tail_init ( list, &list_tests[5].list ); ok ( list_empty ( list ) ); list_contents_ok ( list, "" ); list_contents_ok ( target, "325" ); /* Test list_entry() */ INIT_LIST_HEAD ( &list_tests[3].list ); // for list_check() ok ( list_entry ( &list_tests[3].list, struct list_test, list ) == &list_tests[3] ); /* Test list_first_entry() */ INIT_LIST_HEAD ( list ); list_add_tail ( &list_tests[9].list, list ); list_add_tail ( &list_tests[5].list, list ); list_add_tail ( &list_tests[6].list, list ); ok ( list_first_entry ( list, struct list_test, list ) == &list_tests[9] ); list_del ( &list_tests[9].list ); ok ( list_first_entry ( list, struct list_test, list ) == &list_tests[5] ); /* Test list_for_each() */ INIT_LIST_HEAD ( list ); list_add_tail ( &list_tests[6].list, list ); list_add_tail ( &list_tests[7].list, list ); list_add_tail ( &list_tests[3].list, list ); { char *expected = "673"; struct list_head *pos; struct list_test *entry; list_for_each ( pos, list ) { entry = list_entry ( pos, struct list_test, list ); ok ( entry->label == *(expected++) ); } } /* list_for_each_entry() and list_for_each_entry_reverse() are * already tested as part of list_contents_ok() */ /* Test list_for_each_entry_safe() */ INIT_LIST_HEAD ( list ); list_add_tail ( &list_tests[2].list, list ); list_add_tail ( &list_tests[4].list, list ); list_add_tail ( &list_tests[1].list, list ); { char *expected = "241"; struct list_test *pos; struct list_test *tmp; list_for_each_entry_safe ( pos, tmp, list, list ) { list_contents_ok ( list, expected ); list_del ( &pos->list ); expected++; list_contents_ok ( list, expected ); } } ok ( list_empty ( list ) ); /* Test list_contains() and list_contains_entry() */ INIT_LIST_HEAD ( list ); INIT_LIST_HEAD ( &list_tests[3].list ); list_add ( &list_tests[8].list, list ); list_add ( &list_tests[5].list, list ); ok ( list_contains ( &list_tests[8].list, list ) ); ok ( list_contains_entry ( &list_tests[8], list, list ) ); ok ( list_contains ( &list_tests[5].list, list ) ); ok ( list_contains_entry ( &list_tests[5], list, list ) ); ok ( ! list_contains ( &list_tests[3].list, list ) ); ok ( ! list_contains_entry ( &list_tests[3], list, list ) ); /* Test list_check_contains_entry() */ INIT_LIST_HEAD ( list ); list_add ( &list_tests[4].list, list ); list_add ( &list_tests[0].list, list ); list_add ( &list_tests[3].list, list ); list_check_contains_entry ( &list_tests[4], list, list ); list_check_contains_entry ( &list_tests[0], list, list ); list_check_contains_entry ( &list_tests[3], list, list ); } /** List self-test */ struct self_test list_test __self_test = { .name = "list", .exec = list_test_exec, }; ipxe-precise-1.0.0+git-2.55f6c88/src/tests/comboot/0000775000175000017500000000000011701704160020420 5ustar sergesergeipxe-precise-1.0.0+git-2.55f6c88/src/tests/comboot/version.asm0000664000175000017500000000337711701704160022621 0ustar sergeserge bits 16 org 100h _start: ; first check for SYSLINUX mov ah, 30h int 21h cmp eax, 59530000h jne .not_syslinux cmp ebx, 4c530000h jne .not_syslinux cmp ecx, 4e490000h jne .not_syslinux cmp edx, 58550000h jne .not_syslinux ; now get syslinux version mov ax, 0001h int 22h push cx push dx push di push si push es ; print version string mov dx, str_version mov ah, 09h int 21h pop es pop bx push es mov ax, 0002h int 22h ; print copyright string mov dx, str_copyright mov ah, 09h int 21h pop es pop bx mov ax, 0002h int 22h ; print syslinux derivative id mov dx, str_derivative mov ah, 09h int 21h pop ax call print_hex_byte ; print version number mov dx, str_version_num mov ah, 09h int 21h pop cx push cx mov ax, cx and ax, 0FFh call print_dec_word mov dl, '.' mov ah, 02h int 21h pop cx mov ax, cx shr ax, 8 call print_dec_word ret .not_syslinux: mov dx, str_not_syslinux mov ah, 09h int 21h ret ; input: al = byte to print in hex print_hex_byte: push ax shr al, 4 call print_hex_nybble pop ax call print_hex_nybble ret ; input: bottom half of al = nybble to print in hex print_hex_nybble: push ax mov bl, al and bx, 1111b mov dl, [str_hex + bx] mov ah, 02h int 21h pop ax ret str_hex: db "01234567890abcdef" ; input: ax = word to print print_dec_word: mov cx, 10 mov word [.count], 0 .loop: xor dx, dx div cx inc word [.count] push dx test ax, ax jnz .loop .print: pop dx add dx, '0' mov ah, 02h int 21h dec word [.count] jnz .print ret .count: dw 0 str_not_syslinux: db "Not SYSLINUX or derivative (running on DOS?)$" str_version: db "Version: $" str_copyright: db 10, "Copyright: $" str_derivative: db 10, "Derivative ID: 0x$" str_version_num: db 10, "Version number: $" ipxe-precise-1.0.0+git-2.55f6c88/src/tests/comboot/shuffle-simple.asm0000664000175000017500000000105411701704160024045 0ustar sergeserge bits 16 org 100h jmp start shuffle_start: push 0xB800 pop es mov cx, 80*24*2 mov ax, 'AA' xor di, di rep stosw .lbl: jmp .lbl shuffle_end: nop shuffle_len equ (shuffle_end - shuffle_start + 1) start: ; calculate physical address of shuffled part xor eax, eax push ds pop ax shl eax, 4 add ax, shuffle_start mov dword [source], eax mov ax, 0012h mov di, shuffle_descriptors mov cx, num_shuffle_descriptors mov ebp, 0x7c00 int 22h int3 shuffle_descriptors: dd 0x7C00 source: dd 0 dd shuffle_len num_shuffle_descriptors equ 1 ipxe-precise-1.0.0+git-2.55f6c88/src/tests/memcpy_test.c0000664000175000017500000000473211701704160021461 0ustar sergeserge#include /* * This file exists for testing the compilation of memcpy() with the * various constant-length optimisations. * */ #define __regparm __attribute__ (( regparm(3) )) void __regparm memcpy_0 ( void *dest, void *src ) { memcpy ( dest, src, 0 ); } void __regparm memcpy_1 ( void *dest, void *src ) { memcpy ( dest, src, 1 ); } void __regparm memcpy_2 ( void *dest, void *src ) { memcpy ( dest, src, 2 ); } void __regparm memcpy_3 ( void *dest, void *src ) { memcpy ( dest, src, 3 ); } void __regparm memcpy_4 ( void *dest, void *src ) { memcpy ( dest, src, 4 ); } void __regparm memcpy_5 ( void *dest, void *src ) { memcpy ( dest, src, 5 ); } void __regparm memcpy_6 ( void *dest, void *src ) { memcpy ( dest, src, 6 ); } void __regparm memcpy_7 ( void *dest, void *src ) { memcpy ( dest, src, 7 ); } void __regparm memcpy_8 ( void *dest, void *src ) { memcpy ( dest, src, 8 ); } void __regparm memcpy_9 ( void *dest, void *src ) { memcpy ( dest, src, 9 ); } void __regparm memcpy_10 ( void *dest, void *src ) { memcpy ( dest, src, 10 ); } void __regparm memcpy_11 ( void *dest, void *src ) { memcpy ( dest, src, 11 ); } void __regparm memcpy_12 ( void *dest, void *src ) { memcpy ( dest, src, 12 ); } void __regparm memcpy_13 ( void *dest, void *src ) { memcpy ( dest, src, 13 ); } void __regparm memcpy_14 ( void *dest, void *src ) { memcpy ( dest, src, 14 ); } void __regparm memcpy_15 ( void *dest, void *src ) { memcpy ( dest, src, 15 ); } void __regparm memcpy_16 ( void *dest, void *src ) { memcpy ( dest, src, 16 ); } void __regparm memcpy_17 ( void *dest, void *src ) { memcpy ( dest, src, 17 ); } void __regparm memcpy_18 ( void *dest, void *src ) { memcpy ( dest, src, 18 ); } void __regparm memcpy_19 ( void *dest, void *src ) { memcpy ( dest, src, 19 ); } void __regparm memcpy_20 ( void *dest, void *src ) { memcpy ( dest, src, 20 ); } void __regparm memcpy_21 ( void *dest, void *src ) { memcpy ( dest, src, 21 ); } void __regparm memcpy_22 ( void *dest, void *src ) { memcpy ( dest, src, 22 ); } void __regparm memcpy_23 ( void *dest, void *src ) { memcpy ( dest, src, 23 ); } void __regparm memcpy_24 ( void *dest, void *src ) { memcpy ( dest, src, 24 ); } void __regparm memcpy_25 ( void *dest, void *src ) { memcpy ( dest, src, 25 ); } void __regparm memcpy_26 ( void *dest, void *src ) { memcpy ( dest, src, 26 ); } void __regparm memcpy_27 ( void *dest, void *src ) { memcpy ( dest, src, 27 ); } void __regparm memcpy_28 ( void *dest, void *src ) { memcpy ( dest, src, 28 ); } ipxe-precise-1.0.0+git-2.55f6c88/src/tests/gdbstub_test.gdb0000775000175000017500000000513111701704160022130 0ustar sergeserge#!/usr/bin/gdb -x # Test suite for GDB remote debugging # Run: # make bin/ipxe.hd.tmp # make # gdb # (gdb) target remote :TCPPORT # OR # (gdb) target remote udp:IP:UDPPORT # (gdb) source tests/gdbstub_test.gdb define ipxe_load_symbols file bin/ipxe.hd.tmp end define ipxe_assert if $arg0 != $arg1 echo FAIL $arg2\n else echo PASS $arg2\n end end define ipxe_start_tests jump gdbstub_test end define ipxe_test_regs_read ipxe_assert $eax 0xea010203 "ipxe_test_regs_read eax" ipxe_assert $ebx 0xeb040506 "ipxe_test_regs_read ebx" ipxe_assert $ecx 0xec070809 "ipxe_test_regs_read ecx" ipxe_assert $edx 0xed0a0b0c "ipxe_test_regs_read edx" ipxe_assert $esi 0x510d0e0f "ipxe_test_regs_read esi" ipxe_assert $edi 0xd1102030 "ipxe_test_regs_read edi" end define ipxe_test_regs_write set $eax = 0xea112233 set $ebx = 0xeb445566 set $ecx = 0xec778899 set $edx = 0xedaabbcc set $esi = 0x51ddeeff set $edi = 0xd1010203 c ipxe_assert $eax 0xea112233 "ipxe_test_regs_write eax" ipxe_assert $ebx 0xeb445566 "ipxe_test_regs_write ebx" ipxe_assert $ecx 0xec778899 "ipxe_test_regs_write ecx" ipxe_assert $edx 0xedaabbcc "ipxe_test_regs_write edx" ipxe_assert $esi 0x51ddeeff "ipxe_test_regs_write esi" ipxe_assert $edi 0xd1010203 "ipxe_test_regs_write edi" # This assumes segment selectors are always 0x10 or 0x8 (for code). ipxe_assert $cs 0x08 "ipxe_test_regs_write cs" ipxe_assert $ds 0x10 "ipxe_test_regs_write ds" end define ipxe_test_mem_read c ipxe_assert ({int}($esp+4)) 0x11223344 "ipxe_test_mem_read int" ipxe_assert ({short}($esp+2)) 0x5566 "ipxe_test_mem_read short" ipxe_assert ({char}($esp)) 0x77 "ipxe_test_mem_read char" end define ipxe_test_mem_write set ({int}($esp+4)) = 0xaabbccdd set ({short}($esp+2)) = 0xeeff set ({char}($esp)) = 0x99 c ipxe_assert ({int}($esp+4)) 0xaabbccdd "ipxe_test_mem_write int" ipxe_assert ({short}($esp+2)) (short)0xeeff "ipxe_test_mem_write short" ipxe_assert ({char}($esp)) (char)0x99 "ipxe_test_mem_write char" end define ipxe_test_step c si ipxe_assert ({char}($eip-1)) (char)0x90 "ipxe_test_step" # nop = 0x90 end define ipxe_test_awatch awatch watch_me c ipxe_assert $ecx 0x600d0000 "ipxe_test_awatch read" if $ecx == 0x600d0000 c end c ipxe_assert $ecx 0x600d0001 "ipxe_test_awatch write" if $ecx == 0x600d0001 c end delete end define ipxe_test_watch watch watch_me c ipxe_assert $ecx 0x600d0002 "ipxe_test_watch" if $ecx == 0x600d0002 c end delete end ipxe_load_symbols ipxe_start_tests ipxe_test_regs_read ipxe_test_regs_write ipxe_test_mem_read ipxe_test_mem_write ipxe_test_step ipxe_test_awatch ipxe_test_watch ipxe-precise-1.0.0+git-2.55f6c88/src/tests/umalloc_test.c0000664000175000017500000000074211701704160021620 0ustar sergeserge#include #include #include #include void umalloc_test ( void ) { struct memory_map memmap; userptr_t bob; userptr_t fred; printf ( "Before allocation:\n" ); get_memmap ( &memmap ); bob = umalloc ( 1234 ); bob = urealloc ( bob, 12345 ); fred = umalloc ( 999 ); printf ( "After allocation:\n" ); get_memmap ( &memmap ); ufree ( bob ); ufree ( fred ); printf ( "After freeing:\n" ); get_memmap ( &memmap ); } ipxe-precise-1.0.0+git-2.55f6c88/src/tests/bofm_test.c0000664000175000017500000001077011701704160021111 0ustar sergeserge/* * Copyright (C) 2011 Michael Brown . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include #include #include #include #include #include /** @file * * IBM BladeCenter Open Fabric Manager (BOFM) tests * */ /** Harvest test table */ static struct { struct bofm_global_header header; struct bofm_section_header en_header; struct bofm_en en; struct bofm_section_header done; } __attribute__ (( packed )) bofmtab_harvest = { .header = { .magic = BOFM_IOAA_MAGIC, .action = BOFM_ACTION_HVST, .version = 0x01, .level = 0x01, .length = sizeof ( bofmtab_harvest ), .profile = "Harvest test profile", }, .en_header = { .magic = BOFM_EN_MAGIC, .length = sizeof ( bofmtab_harvest.en ), }, .en = { .options = ( BOFM_EN_MAP_PFA | BOFM_EN_USAGE_HARVEST | BOFM_EN_RQ_HVST_ACTIVE ), .mport = 1, }, .done = { .magic = BOFM_DONE_MAGIC, }, }; /** Update test table */ static struct { struct bofm_global_header header; struct bofm_section_header en_header; struct bofm_en en; struct bofm_section_header done; } __attribute__ (( packed )) bofmtab_update = { .header = { .magic = BOFM_IOAA_MAGIC, .action = BOFM_ACTION_UPDT, .version = 0x01, .level = 0x01, .length = sizeof ( bofmtab_update ), .profile = "Update test profile", }, .en_header = { .magic = BOFM_EN_MAGIC, .length = sizeof ( bofmtab_update.en ), }, .en = { .options = ( BOFM_EN_MAP_PFA | BOFM_EN_EN_A | BOFM_EN_USAGE_ENTRY ), .mport = 1, .mac_a = { 0x02, 0x00, 0x69, 0x50, 0x58, 0x45 }, }, .done = { .magic = BOFM_DONE_MAGIC, }, }; /** * Perform BOFM test * * @v pci PCI device */ void bofm_test ( struct pci_device *pci ) { int bofmrc; printf ( "BOFMTEST using " PCI_FMT "\n", PCI_ARGS ( pci ) ); /* Perform harvest test */ printf ( "BOFMTEST performing harvest\n" ); bofmtab_harvest.en.busdevfn = pci->busdevfn; DBG_HDA ( 0, &bofmtab_harvest, sizeof ( bofmtab_harvest ) ); bofmrc = bofm ( virt_to_user ( &bofmtab_harvest ), pci ); printf ( "BOFMTEST harvest result %08x\n", bofmrc ); if ( bofmtab_harvest.en.options & BOFM_EN_HVST ) { printf ( "BOFMTEST harvested MAC address %s\n", eth_ntoa ( &bofmtab_harvest.en.mac_a ) ); } else { printf ( "BOFMTEST failed to harvest a MAC address\n" ); } DBG_HDA ( 0, &bofmtab_harvest, sizeof ( bofmtab_harvest ) ); /* Perform update test */ printf ( "BOFMTEST performing update\n" ); bofmtab_update.en.busdevfn = pci->busdevfn; DBG_HDA ( 0, &bofmtab_update, sizeof ( bofmtab_update ) ); bofmrc = bofm ( virt_to_user ( &bofmtab_update ), pci ); printf ( "BOFMTEST update result %08x\n", bofmrc ); if ( bofmtab_update.en.options & BOFM_EN_CSM_SUCCESS ) { printf ( "BOFMTEST updated MAC address to %s\n", eth_ntoa ( &bofmtab_update.en.mac_a ) ); } else { printf ( "BOFMTEST failed to update MAC address\n" ); } DBG_HDA ( 0, &bofmtab_update, sizeof ( bofmtab_update ) ); } /** * Perform BOFM test at initialisation time * */ static void bofm_test_init ( void ) { struct pci_device pci; int busdevfn = -1; int rc; /* Uncomment the following line and specify the correct PCI * bus:dev.fn address in order to perform a BOFM test at * initialisation time. */ // busdevfn = PCI_BUSDEVFN ( , , ); /* Skip test if no PCI bus:dev.fn is defined */ if ( busdevfn < 0 ) return; /* Initialise PCI device */ memset ( &pci, 0, sizeof ( pci ) ); pci_init ( &pci, busdevfn ); if ( ( rc = pci_read_config ( &pci ) ) != 0 ) { printf ( "BOFMTEST could not create " PCI_FMT " device: %s\n", PCI_ARGS ( &pci ), strerror ( rc ) ); return; } /* Perform test */ bofm_test ( &pci ); } /** BOFM test initialisation function */ struct init_fn bofm_test_init_fn __init_fn ( INIT_NORMAL ) = { .initialise = bofm_test_init, }; ipxe-precise-1.0.0+git-2.55f6c88/src/tests/test.c0000664000175000017500000000654511701704160020113 0ustar sergeserge/* * Copyright (C) 2011 Michael Brown . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); /** @file * * Self-test infrastructure * */ /* Forcibly enable assertions */ #undef NDEBUG #include #include #include #include #include /** Current self-test set */ static struct self_test *current_tests; /** * Report test result * * @v success Test succeeded * @v file Test code file * @v line Test code line */ void test_ok ( int success, const char *file, unsigned int line ) { /* Sanity check */ assert ( current_tests != NULL ); /* Increment test counter */ current_tests->total++; /* Report failure if applicable */ if ( ! success ) { current_tests->failures++; printf ( "FAILURE: \"%s\" test failed at %s line %d\n", current_tests->name, file, line ); } } /** * Run self-test set * */ static void run_tests ( struct self_test *tests ) { unsigned int old_assertion_failures = assertion_failures; /* Sanity check */ assert ( current_tests == NULL ); /* Record current test set */ current_tests = tests; /* Run tests */ tests->exec(); /* Clear current test set */ current_tests = NULL; /* Record number of assertion failures */ tests->assertion_failures = ( assertion_failures - old_assertion_failures ); /* Print test set summary */ if ( tests->failures || tests->assertion_failures ) { printf ( "FAILURE: \"%s\" %d of %d tests failed", tests->name, tests->failures, tests->total ); if ( tests->assertion_failures ) { printf ( " with %d assertion failures", tests->assertion_failures ); } printf ( "\n" ); } else { printf ( "OK: \"%s\" %d tests passed\n", tests->name, tests->total ); } } /** * Run all self-tests * */ static void test_init ( void ) { struct self_test *tests; unsigned int failures = 0; unsigned int assertions = 0; unsigned int total = 0; /* Run all compiled-in self-tests */ printf ( "Starting self-tests\n" ); for_each_table_entry ( tests, SELF_TESTS ) run_tests ( tests ); /* Print overall summary */ for_each_table_entry ( tests, SELF_TESTS ) { total += tests->total; failures += tests->failures; assertions += tests->assertion_failures; } if ( failures || assertions ) { printf ( "FAILURE: %d of %d tests failed", failures, total ); if ( assertions ) { printf ( " with %d assertion failures", assertions ); } printf ( "\n" ); } else { printf ( "OK: all %d tests passed\n", total ); } /* Lock system */ while ( 1 ) {} } /** Self-test initialisation function */ struct init_fn test_init_fn __init_fn ( INIT_NORMAL ) = { .initialise = test_init, }; /* Drag in all applicable self-tests */ REQUIRE_OBJECT ( list_test ); ipxe-precise-1.0.0+git-2.55f6c88/src/tests/uri_test.c0000664000175000017500000000657311701704160020773 0ustar sergeserge#include #include #include #include #include #include #define URI_MAX_LEN 1024 struct uri_test { const char *base_uri_string; const char *relative_uri_string; const char *resolved_uri_string; }; static struct uri_test uri_tests[] = { { "http://www.fensystems.co.uk", "", "http://www.fensystems.co.uk/" }, { "http://ipxe.org/wiki/page1", "page2", "http://ipxe.org/wiki/page2" }, { "http://ipxe.org/wiki/page1", "../page3", "http://ipxe.org/page3" }, { "tftp://192.168.0.1/", "/tftpboot/vmlinuz", "tftp://192.168.0.1/tftpboot/vmlinuz" }, { "ftp://the%41nswer%3d:%34ty%32wo@ether%62oot.org:8080/p%41th/foo", "to?%41=b#%43d", "ftp://theAnswer%3d:4ty2wo@ipxe.org:8080/path/to?a=b#cd" }, #if 0 "http://www.ipxe.org/wiki", "mailto:bob@nowhere.com", "ftp://joe:secret@insecure.org:8081/hidden/path/to?what=is#this", #endif }; static int test_parse_unparse ( const char *uri_string ) { char buf[URI_MAX_LEN]; struct uri *uri = NULL; int rc; /* Parse and unparse URI */ uri = parse_uri ( uri_string ); if ( ! uri ) { rc = -ENOMEM; goto done; } unparse_uri ( buf, sizeof ( buf ), uri, URI_ALL ); /* Compare result */ if ( strcmp ( buf, uri_string ) != 0 ) { printf ( "Unparse of \"%s\" produced \"%s\"\n", uri_string, buf ); rc = -EINVAL; goto done; } rc = 0; done: uri_put ( uri ); if ( rc ) { printf ( "URI parse-unparse of \"%s\" failed: %s\n", uri_string, strerror ( rc ) ); } return rc; } static int test_resolve ( const char *base_uri_string, const char *relative_uri_string, const char *resolved_uri_string ) { struct uri *base_uri = NULL; struct uri *relative_uri = NULL; struct uri *resolved_uri = NULL; char buf[URI_MAX_LEN]; int rc; /* Parse URIs */ base_uri = parse_uri ( base_uri_string ); if ( ! base_uri ) { rc = -ENOMEM; goto done; } relative_uri = parse_uri ( relative_uri_string ); if ( ! relative_uri ) { rc = -ENOMEM; goto done; } /* Resolve URI */ resolved_uri = resolve_uri ( base_uri, relative_uri ); if ( ! resolved_uri ) { rc = -ENOMEM; goto done; } /* Compare result */ unparse_uri ( buf, sizeof ( buf ), resolved_uri, URI_ALL ); if ( strcmp ( buf, resolved_uri_string ) != 0 ) { printf ( "Resolution of \"%s\"+\"%s\" produced \"%s\"\n", base_uri_string, relative_uri_string, buf ); rc = -EINVAL; goto done; } rc = 0; done: uri_put ( base_uri ); uri_put ( relative_uri ); uri_put ( resolved_uri ); if ( rc ) { printf ( "URI resolution of \"%s\"+\"%s\" failed: %s\n", base_uri_string, relative_uri_string, strerror ( rc ) ); } return rc; } int uri_test ( void ) { unsigned int i; struct uri_test *uri_test; int rc; int overall_rc = 0; for ( i = 0 ; i < ( sizeof ( uri_tests ) / sizeof ( uri_tests[0] ) ) ; i++ ) { uri_test = &uri_tests[i]; rc = test_parse_unparse ( uri_test->base_uri_string ); if ( rc != 0 ) overall_rc = rc; rc = test_parse_unparse ( uri_test->relative_uri_string ); if ( rc != 0 ) overall_rc = rc; rc = test_parse_unparse ( uri_test->resolved_uri_string ); if ( rc != 0 ) overall_rc = rc; rc = test_resolve ( uri_test->base_uri_string, uri_test->relative_uri_string, uri_test->resolved_uri_string ); if ( rc != 0 ) overall_rc = rc; } if ( overall_rc ) printf ( "URI tests failed: %s\n", strerror ( overall_rc ) ); return overall_rc; } ipxe-precise-1.0.0+git-2.55f6c88/src/bin/0000775000175000017500000000000011701704160016364 5ustar sergesergeipxe-precise-1.0.0+git-2.55f6c88/src/bin/.gitignore0000664000175000017500000000000211701704160020344 0ustar sergeserge* ipxe-precise-1.0.0+git-2.55f6c88/src/interface/0000775000175000017500000000000011701704160017554 5ustar sergesergeipxe-precise-1.0.0+git-2.55f6c88/src/interface/linux/0000775000175000017500000000000011701704160020713 5ustar sergesergeipxe-precise-1.0.0+git-2.55f6c88/src/interface/linux/linux_umalloc.c0000664000175000017500000001042011701704160023727 0ustar sergeserge/* * Copyright (C) 2010 Piotr Jaroszyński * * 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ FILE_LICENCE(GPL2_OR_LATER); #include /** @file * * iPXE user memory allocation API for linux * */ #include #include #include /** Special address returned for empty allocations */ #define NOWHERE ((void *)-1) /** Poison to make the metadata more unique */ #define POISON 0xa5a5a5a5 #define min(a,b) (((a)<(b))?(a):(b)) /** Metadata stored at the beginning of all allocations */ struct metadata { unsigned poison; size_t size; }; #define SIZE_MD (sizeof(struct metadata)) /** Simple realloc which passes most of the work to mmap(), mremap() and munmap() */ static void * linux_realloc(void *ptr, size_t size) { struct metadata md = {0, 0}; struct metadata * mdptr = NULL; DBG2("linux_realloc(%p, %zd)\n", ptr, size); /* Check whether we have a valid pointer */ if (ptr != NULL && ptr != NOWHERE) { mdptr = ptr - SIZE_MD; VALGRIND_MAKE_MEM_DEFINED(mdptr, SIZE_MD); md = *mdptr; VALGRIND_MAKE_MEM_NOACCESS(mdptr, SIZE_MD); /* Check for poison in the metadata */ if (md.poison != POISON) { DBG("linux_realloc bad poison: 0x%x (expected 0x%x)\n", md.poison, POISON); return NULL; } } else { /* Handle NOWHERE as NULL */ ptr = NULL; } /* * At this point, ptr is either NULL or pointing to a region allocated by us. * In the latter case mdptr is pointing to a valid metadata, otherwise it is NULL. */ /* Handle deallocation or allocation of size 0 */ if (size == 0) { if (mdptr) { if (linux_munmap(mdptr, md.size)) DBG("linux_realloc munmap failed: %s\n", linux_strerror(linux_errno)); VALGRIND_FREELIKE_BLOCK(ptr, sizeof(*mdptr)); } return NOWHERE; } if (ptr) { char *vbits = NULL; if (RUNNING_ON_VALGRIND > 0) vbits = linux_realloc(NULL, min(size, md.size)); /* prevent an unused variable warning when building w/o valgrind support */ #ifndef NVALGRIND VALGRIND_GET_VBITS(ptr, vbits, min(size, md.size)); #endif VALGRIND_FREELIKE_BLOCK(ptr, SIZE_MD); mdptr = linux_mremap(mdptr, md.size + SIZE_MD, size + SIZE_MD, MREMAP_MAYMOVE); if (mdptr == MAP_FAILED) { DBG("linux_realloc mremap failed: %s\n", linux_strerror(linux_errno)); return NULL; } ptr = ((void *)mdptr) + SIZE_MD; VALGRIND_MALLOCLIKE_BLOCK(ptr, size, SIZE_MD, 0); /* prevent an unused variable warning when building w/o valgrind support */ #ifndef NVALGRIND VALGRIND_SET_VBITS(ptr, vbits, min(size, md.size)); #endif if (RUNNING_ON_VALGRIND > 0) linux_realloc(vbits, 0); } else { mdptr = linux_mmap(NULL, size + SIZE_MD, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (mdptr == MAP_FAILED) { DBG("linux_realloc mmap failed: %s\n", linux_strerror(linux_errno)); return NULL; } ptr = ((void *)mdptr) + SIZE_MD; VALGRIND_MALLOCLIKE_BLOCK(ptr, size, SIZE_MD, 0); } /* Update the metadata */ VALGRIND_MAKE_MEM_DEFINED(mdptr, SIZE_MD); mdptr->poison = POISON; mdptr->size = size; VALGRIND_MAKE_MEM_NOACCESS(mdptr, SIZE_MD); // VALGRIND_MALLOCLIKE_BLOCK ignores redzones currently, make our own VALGRIND_MAKE_MEM_NOACCESS(ptr + size, SIZE_MD); return ptr; } /** * Reallocate external memory * * @v old_ptr Memory previously allocated by umalloc(), or UNULL * @v new_size Requested size * @ret new_ptr Allocated memory, or UNULL * * Calling realloc() with a new size of zero is a valid way to free a * memory block. */ static userptr_t linux_urealloc(userptr_t old_ptr, size_t new_size) { return (userptr_t)linux_realloc((void *)old_ptr, new_size); } PROVIDE_UMALLOC(linux, urealloc, linux_urealloc); ipxe-precise-1.0.0+git-2.55f6c88/src/interface/linux/linux_smbios.c0000664000175000017500000000216611701704160023577 0ustar sergeserge/* * Copyright (C) 2010 Piotr Jaroszyński * * 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ FILE_LICENCE(GPL2_OR_LATER); #include #include /** * Find SMBIOS * * Not implemented currently. * * @v smbios SMBIOS entry point descriptor structure to fill in * @ret rc Return status code */ static int linux_find_smbios(struct smbios *smbios __unused) { return -ENODEV; } PROVIDE_SMBIOS(linux, find_smbios, linux_find_smbios); ipxe-precise-1.0.0+git-2.55f6c88/src/interface/linux/linux_timer.c0000664000175000017500000000376311701704160023427 0ustar sergeserge/* * Copyright (C) 2010 Piotr Jaroszyński * * 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ FILE_LICENCE(GPL2_OR_LATER); #include #include /** @file * * iPXE timer API for linux * */ /** * Delay for a fixed number of microseconds * * @v usecs Number of microseconds for which to delay */ static void linux_udelay(unsigned long usecs) { linux_usleep(usecs); } /** * Get number of ticks per second * * @ret ticks_per_sec Number of ticks per second */ static unsigned long linux_ticks_per_sec(void) { return 1000; } /** * Get current system time in ticks * * linux doesn't provide an easy access to jiffies so implement it by measuring * the time since the first call to this function. * * @ret ticks Current time, in ticks */ static unsigned long linux_currticks(void) { static struct timeval start; static int initialized = 0; if (! initialized) { linux_gettimeofday(&start, NULL); initialized = 1; } struct timeval now; linux_gettimeofday(&now, NULL); unsigned long ticks = (now.tv_sec - start.tv_sec) * linux_ticks_per_sec(); ticks += (now.tv_usec - start.tv_usec) / (long)(1000000 / linux_ticks_per_sec()); return ticks; } PROVIDE_TIMER(linux, udelay, linux_udelay); PROVIDE_TIMER(linux, currticks, linux_currticks); PROVIDE_TIMER(linux, ticks_per_sec, linux_ticks_per_sec); ipxe-precise-1.0.0+git-2.55f6c88/src/interface/linux/linux_nap.c0000664000175000017500000000201311701704160023050 0ustar sergeserge/* * Copyright (C) 2010 Piotr Jaroszyński * * 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 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. */ FILE_LICENCE(GPL2_OR_LATER); #include #include /** @file * * iPXE CPU sleeping API for linux * */ /** * Sleep until next CPU interrupt * */ static void linux_cpu_nap(void) { linux_usleep(0); } PROVIDE_NAP(linux, cpu_nap, linux_cpu_nap); ipxe-precise-1.0.0+git-2.55f6c88/src/interface/linux/linux_console.c0000664000175000017500000000660411701704160023746 0ustar sergeserge/* * Copyright (C) 2010 Piotr Jaroszyński * * 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ FILE_LICENCE(GPL2_OR_LATER); /** @file * * Linux console implementation. * */ #include #include #include #include #include #include static void linux_console_putchar(int c) { /* write to stdout */ if (linux_write(1, &c, 1) != 1) DBG("linux_console write failed (%s)\n", linux_strerror(linux_errno)); } static int linux_console_getchar() { char c; /* read from stdin */ if (linux_read(0, &c, 1) < 0) { DBG("linux_console read failed (%s)\n", linux_strerror(linux_errno)); return 0; } /* backspace seems to be returned as ascii del, map it here */ if (c == 0x7f) return KEY_BACKSPACE; else return c; } static int linux_console_iskey() { struct pollfd pfd; pfd.fd = 0; pfd.events = POLLIN; /* poll for data to be read on stdin */ if (linux_poll(&pfd, 1, 0) == -1) { DBG("linux_console poll failed (%s)\n", linux_strerror(linux_errno)); return 0; } if (pfd.revents & POLLIN) return 1; else return 0; } struct console_driver linux_console __console_driver = { .disabled = 0, .putchar = linux_console_putchar, .getchar = linux_console_getchar, .iskey = linux_console_iskey, }; static int linux_tcgetattr(int fd, struct termios *termios_p) { return linux_ioctl(fd, TCGETS, termios_p); } static int linux_tcsetattr(int fd, int optional_actions, const struct termios *termios_p) { unsigned long int cmd; switch (optional_actions) { case TCSANOW: cmd = TCSETS; break; case TCSADRAIN: cmd = TCSETSW; break; case TCSAFLUSH: cmd = TCSETSF; break; default: linux_errno = EINVAL; return -1; } return linux_ioctl(fd, cmd, termios_p); } /** Saved termios attributes */ static struct termios saved_termios; /** Setup the terminal for our use */ static void linux_console_startup(void) { struct termios t; if (linux_tcgetattr(0, &t)) { DBG("linux_console tcgetattr failed (%s)", linux_strerror(linux_errno)); return; } saved_termios = t; /* Disable canonical mode and echo. Let readline handle that */ t.c_lflag &= ~(ECHO | ICANON); /* stop ^C from sending a signal */ t.c_cc[VINTR] = 0; if (linux_tcsetattr(0, TCSAFLUSH, &t)) DBG("linux_console tcsetattr failed (%s)", linux_strerror(linux_errno)); } /** Restores original terminal attributes on shutdown */ static void linux_console_shutdown(int flags __unused) { if (linux_tcsetattr(0, TCSAFLUSH, &saved_termios)) DBG("linux_console tcsetattr failed (%s)", linux_strerror(linux_errno)); } struct startup_fn linux_console_startup_fn __startup_fn(STARTUP_EARLY) = { .startup = linux_console_startup, .shutdown = linux_console_shutdown, }; ipxe-precise-1.0.0+git-2.55f6c88/src/interface/linux/linux_uaccess.c0000664000175000017500000000244311701704160023727 0ustar sergeserge/* * Copyright (C) 2010 Piotr Jaroszyński * * 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 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. */ FILE_LICENCE(GPL2_OR_LATER); #include /** @file * * iPXE user access API for linux * */ PROVIDE_UACCESS_INLINE(linux, phys_to_user); PROVIDE_UACCESS_INLINE(linux, user_to_phys); PROVIDE_UACCESS_INLINE(linux, virt_to_user); PROVIDE_UACCESS_INLINE(linux, user_to_virt); PROVIDE_UACCESS_INLINE(linux, userptr_add); PROVIDE_UACCESS_INLINE(linux, memcpy_user); PROVIDE_UACCESS_INLINE(linux, memmove_user); PROVIDE_UACCESS_INLINE(linux, memset_user); PROVIDE_UACCESS_INLINE(linux, strlen_user); PROVIDE_UACCESS_INLINE(linux, memchr_user); ipxe-precise-1.0.0+git-2.55f6c88/src/interface/bofm/0000775000175000017500000000000011701704160020477 5ustar sergesergeipxe-precise-1.0.0+git-2.55f6c88/src/interface/bofm/bofm.c0000664000175000017500000002225011701704160021567 0ustar sergeserge/* * Copyright (C) 2011 Michael Brown . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include #include #include #include #include /** @file * * IBM BladeCenter Open Fabric Manager (BOFM) * */ /** List of BOFM devices */ static LIST_HEAD ( bofmdevs ); /** * Register BOFM device * * @v bofm BOFM device * @ret rc Return status code */ int bofm_register ( struct bofm_device *bofm ) { list_add ( &bofm->list, &bofmdevs ); DBG ( "BOFM: " PCI_FMT " registered using driver \"%s\"\n", PCI_ARGS ( bofm->pci ), bofm->pci->id->name ); return 0; } /** * Unregister BOFM device * * @v bofm BOFM device */ void bofm_unregister ( struct bofm_device *bofm ) { list_del ( &bofm->list ); DBG ( "BOFM: " PCI_FMT " unregistered\n", PCI_ARGS ( bofm->pci ) ); } /** * Find BOFM device matching PCI bus:dev.fn address * * @v busdevfn PCI bus:dev.fn address * @ret bofm BOFM device, or NULL */ static struct bofm_device * bofm_find_busdevfn ( unsigned int busdevfn ) { struct bofm_device *bofm; list_for_each_entry ( bofm, &bofmdevs, list ) { if ( bofm->pci->busdevfn == busdevfn ) return bofm; } return NULL; } /** * Find BOFM driver for PCI device * * @v pci PCI device * @ret rc Return status code */ int bofm_find_driver ( struct pci_device *pci ) { struct pci_driver *driver; struct pci_device_id *id; unsigned int i; for_each_table_entry ( driver, BOFM_DRIVERS ) { for ( i = 0 ; i < driver->id_count ; i++ ) { id = &driver->ids[i]; if ( ( id->vendor == pci->vendor ) && ( id->device == pci->device ) ) { pci_set_driver ( pci, driver, id ); return 0; } } } return -ENOENT; } /** * Probe PCI device for BOFM driver * * @v pci PCI device * @ret rc Return status code */ static int bofm_probe ( struct pci_device *pci ) { int rc; /* Probe device */ if ( ( rc = pci_probe ( pci ) ) != 0 ) { DBG ( "BOFM: " PCI_FMT " could not load driver: %s\n", PCI_ARGS ( pci ), strerror ( rc ) ); return rc; } return 0; } /** * Remove PCI device * * @v pci PCI device */ static void bofm_remove ( struct pci_device *pci ) { /* Note that the IBM BIOS may re-read the expansion ROM after * the BOFM initialisation call. The BOFM driver must ensure * that the card is left in a state in which expansion ROM * reads will succeed. (For example, if a card contains an * embedded CPU that may issue reads to the same underlying * flash device, and these reads are not locked against reads * via the expansion ROM BAR, then the CPU must be stopped.) * * If this is not done, then occasional corrupted reads from * the expansion ROM will be seen, and the BIOS may complain * about a ROM checksum error. */ pci_remove ( pci ); DBG ( "BOFM: " PCI_FMT " removed\n", PCI_ARGS ( pci ) ); } /** * Locate BOFM table section * * @v bofmtab BOFM table * @v len Length of BOFM table * @v magic Section magic * @v bofmsec BOFM section header to fill in * @ret offset Offset to section, or 0 if not found */ static size_t bofm_locate_section ( userptr_t bofmtab, size_t len, uint32_t magic, struct bofm_section_header *bofmsec ) { size_t offset = sizeof ( struct bofm_global_header ); while ( offset < len ) { copy_from_user ( bofmsec, bofmtab, offset, sizeof ( *bofmsec ) ); if ( bofmsec->magic == magic ) return offset; if ( bofmsec->magic == BOFM_DONE_MAGIC ) break; offset += ( sizeof ( *bofmsec ) + bofmsec->length ); } return 0; } /** * Process BOFM Ethernet parameter entry * * @v bofm BOFM device * @v en EN parameter entry * @ret rc Return status code */ static int bofm_en ( struct bofm_device *bofm, struct bofm_en *en ) { uint8_t mac[6]; int rc; /* Retrieve current MAC address */ if ( ( rc = bofm->op->harvest ( bofm, en->mport, mac ) ) != 0 ) { DBG ( "BOFM: " PCI_FMT " mport %d could not harvest: %s\n", PCI_ARGS ( bofm->pci ), en->mport, strerror ( rc ) ); return rc; } /* Harvest MAC address if necessary */ if ( en->options & BOFM_EN_RQ_HVST_MASK ) { DBG ( "BOFM: " PCI_FMT " mport %d harvested MAC %s\n", PCI_ARGS ( bofm->pci ), en->mport, eth_ntoa ( mac ) ); memcpy ( en->mac_a, mac, sizeof ( en->mac_a ) ); en->options |= ( BOFM_EN_EN_A | BOFM_EN_HVST ); } /* Mark as changed if necessary */ if ( ( en->options & BOFM_EN_EN_A ) && ( memcmp ( en->mac_a, mac, sizeof ( en->mac_a ) ) != 0 ) ) { DBG ( "BOFM: " PCI_FMT " mport %d MAC %s", PCI_ARGS ( bofm->pci ), en->mport, eth_ntoa ( mac ) ); DBG ( " changed to %s\n", eth_ntoa ( en->mac_a ) ); en->options |= BOFM_EN_CHG_CHANGED; } /* Apply MAC address if necessary */ if ( ( en->options & BOFM_EN_EN_A ) && ( en->options & BOFM_EN_USAGE_ENTRY ) && ( ! ( en->options & BOFM_EN_USAGE_HARVEST ) ) ) { DBG ( "BOFM: " PCI_FMT " mport %d applied MAC %s\n", PCI_ARGS ( bofm->pci ), en->mport, eth_ntoa ( en->mac_a ) ); memcpy ( mac, en->mac_a, sizeof ( mac ) ); } /* Store MAC address */ if ( ( rc = bofm->op->update ( bofm, en->mport, mac ) ) != 0 ) { DBG ( "BOFM: " PCI_FMT " mport %d could not update: %s\n", PCI_ARGS ( bofm->pci ), en->mport, strerror ( rc ) ); return rc; } return 0; } /** * Process BOFM table * * @v bofmtab BOFM table * @v pci PCI device * @ret bofmrc BOFM return status */ int bofm ( userptr_t bofmtab, struct pci_device *pci ) { struct bofm_global_header bofmhdr; struct bofm_section_header bofmsec; struct bofm_en en; struct bofm_device *bofm; size_t en_region_offset; size_t en_offset; int skip; int rc; int bofmrc; /* Read BOFM structure */ copy_from_user ( &bofmhdr, bofmtab, 0, sizeof ( bofmhdr ) ); if ( bofmhdr.magic != BOFM_IOAA_MAGIC ) { DBG ( "BOFM: invalid table signature " BOFM_MAGIC_FMT "\n", BOFM_MAGIC_ARGS ( bofmhdr.magic ) ); bofmrc = BOFM_ERR_INVALID_ACTION; goto err_bad_signature; } DBG ( "BOFM: " BOFM_MAGIC_FMT " (profile \"%s\")\n", BOFM_MAGIC_ARGS ( bofmhdr.action ), bofmhdr.profile ); /* Determine whether or not we should skip normal POST * initialisation. */ switch ( bofmhdr.action ) { case BOFM_ACTION_UPDT: case BOFM_ACTION_DFLT: case BOFM_ACTION_HVST: skip = BOFM_SKIP_INIT; break; case BOFM_ACTION_PARM: case BOFM_ACTION_NONE: skip = 0; break; default: DBG ( "BOFM: invalid action " BOFM_MAGIC_FMT "\n", BOFM_MAGIC_ARGS ( bofmhdr.action ) ); bofmrc = BOFM_ERR_INVALID_ACTION; goto err_bad_action; } /* Find BOFM driver */ if ( ( rc = bofm_find_driver ( pci ) ) != 0 ) { DBG ( "BOFM: " PCI_FMT " has no driver\n", PCI_ARGS ( pci ) ); bofmrc = BOFM_ERR_DEVICE_ERROR; goto err_find_driver; } /* Probe driver for PCI device */ if ( ( rc = bofm_probe ( pci ) ) != 0 ) { bofmrc = BOFM_ERR_DEVICE_ERROR; goto err_probe; } /* Locate EN section, if present */ en_region_offset = bofm_locate_section ( bofmtab, bofmhdr.length, BOFM_EN_MAGIC, &bofmsec ); if ( ! en_region_offset ) { DBG ( "BOFM: No EN section found\n" ); bofmrc = ( BOFM_SUCCESS | skip ); goto err_no_en_section; } /* Iterate through EN entries */ for ( en_offset = ( en_region_offset + sizeof ( bofmsec ) ) ; en_offset < ( en_region_offset + sizeof ( bofmsec ) + bofmsec.length ) ; en_offset += sizeof ( en ) ) { copy_from_user ( &en, bofmtab, en_offset, sizeof ( en ) ); DBG2 ( "BOFM: EN entry found:\n" ); DBG2_HDA ( en_offset, &en, sizeof ( en ) ); if ( ( en.options & BOFM_EN_MAP_MASK ) != BOFM_EN_MAP_PFA ) { DBG ( "BOFM: slot %d port %d has no PCI mapping\n", en.slot, ( en.port + 1 ) ); continue; } DBG ( "BOFM: slot %d port %d%s is " PCI_FMT " mport %d\n", en.slot, ( en.port + 1 ), ( ( en.slot || en.port ) ? "" : "(?)" ), PCI_BUS ( en.busdevfn ), PCI_SLOT ( en.busdevfn ), PCI_FUNC ( en.busdevfn ), en.mport ); bofm = bofm_find_busdevfn ( en.busdevfn ); if ( ! bofm ) { DBG ( "BOFM: " PCI_FMT " mport %d ignored\n", PCI_BUS ( en.busdevfn ), PCI_SLOT ( en.busdevfn ), PCI_FUNC ( en.busdevfn ), en.mport ); continue; } if ( ( rc = bofm_en ( bofm, &en ) ) == 0 ) { en.options |= BOFM_EN_CSM_SUCCESS; } else { en.options |= BOFM_EN_CSM_FAILED; } DBG2 ( "BOFM: EN entry after processing:\n" ); DBG2_HDA ( en_offset, &en, sizeof ( en ) ); copy_to_user ( bofmtab, en_offset, &en, sizeof ( en ) ); } bofmrc = ( BOFM_SUCCESS | skip ); err_no_en_section: bofm_remove ( pci ); err_probe: err_find_driver: err_bad_action: err_bad_signature: return bofmrc; } ipxe-precise-1.0.0+git-2.55f6c88/src/interface/smbios/0000775000175000017500000000000011701704160021050 5ustar sergesergeipxe-precise-1.0.0+git-2.55f6c88/src/interface/smbios/smbios_settings.c0000664000175000017500000001325711701704160024440 0ustar sergeserge/* * Copyright (C) 2008 Michael Brown . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include #include #include #include #include /** SMBIOS settings tag magic number */ #define SMBIOS_TAG_MAGIC 0x5B /* "SmBios" */ /** * Construct SMBIOS empty tag * * @ret tag SMBIOS setting tag */ #define SMBIOS_EMPTY_TAG ( SMBIOS_TAG_MAGIC << 24 ) /** * Construct SMBIOS raw-data tag * * @v _type SMBIOS structure type number * @v _structure SMBIOS structure data type * @v _field Field within SMBIOS structure data type * @ret tag SMBIOS setting tag */ #define SMBIOS_RAW_TAG( _type, _structure, _field ) \ ( ( SMBIOS_TAG_MAGIC << 24 ) | \ ( (_type) << 16 ) | \ ( offsetof ( _structure, _field ) << 8 ) | \ ( sizeof ( ( ( _structure * ) 0 )->_field ) ) ) /** * Construct SMBIOS string tag * * @v _type SMBIOS structure type number * @v _structure SMBIOS structure data type * @v _field Field within SMBIOS structure data type * @ret tag SMBIOS setting tag */ #define SMBIOS_STRING_TAG( _type, _structure, _field ) \ ( ( SMBIOS_TAG_MAGIC << 24 ) | \ ( (_type) << 16 ) | \ ( offsetof ( _structure, _field ) << 8 ) ) /** * Check applicability of SMBIOS setting * * @v settings Settings block * @v setting Setting * @ret applies Setting applies within this settings block */ static int smbios_applies ( struct settings *settings __unused, struct setting *setting ) { unsigned int tag_magic; /* Check tag magic */ tag_magic = ( setting->tag >> 24 ); return ( tag_magic == SMBIOS_TAG_MAGIC ); } /** * Fetch value of SMBIOS setting * * @v settings Settings block, or NULL to search all blocks * @v setting Setting to fetch * @v data Buffer to fill with setting data * @v len Length of buffer * @ret len Length of setting data, or negative error */ static int smbios_fetch ( struct settings *settings __unused, struct setting *setting, void *data, size_t len ) { struct smbios_structure structure; unsigned int tag_magic; unsigned int tag_type; unsigned int tag_offset; unsigned int tag_len; int rc; /* Split tag into type, offset and length */ tag_magic = ( setting->tag >> 24 ); tag_type = ( ( setting->tag >> 16 ) & 0xff ); tag_offset = ( ( setting->tag >> 8 ) & 0xff ); tag_len = ( setting->tag & 0xff ); assert ( tag_magic == SMBIOS_TAG_MAGIC ); /* Find SMBIOS structure */ if ( ( rc = find_smbios_structure ( tag_type, &structure ) ) != 0 ) return rc; { uint8_t buf[structure.header.len]; /* Read SMBIOS structure */ if ( ( rc = read_smbios_structure ( &structure, buf, sizeof ( buf ) ) ) != 0 ) return rc; if ( tag_len == 0 ) { /* String */ return read_smbios_string ( &structure, buf[tag_offset], data, len ); } else { /* Raw data */ if ( len > tag_len ) len = tag_len; memcpy ( data, &buf[tag_offset], len ); return tag_len; } } } /** SMBIOS settings operations */ static struct settings_operations smbios_settings_operations = { .applies = smbios_applies, .fetch = smbios_fetch, }; /** SMBIOS settings */ static struct settings smbios_settings = { .refcnt = NULL, .tag_magic = SMBIOS_EMPTY_TAG, .siblings = LIST_HEAD_INIT ( smbios_settings.siblings ), .children = LIST_HEAD_INIT ( smbios_settings.children ), .op = &smbios_settings_operations, }; /** Initialise SMBIOS settings */ static void smbios_init ( void ) { int rc; if ( ( rc = register_settings ( &smbios_settings, NULL, "smbios" ) ) != 0 ) { DBG ( "SMBIOS could not register settings: %s\n", strerror ( rc ) ); return; } } /** SMBIOS settings initialiser */ struct init_fn smbios_init_fn __init_fn ( INIT_NORMAL ) = { .initialise = smbios_init, }; /** UUID setting obtained via SMBIOS */ struct setting uuid_setting __setting ( SETTING_HOST ) = { .name = "uuid", .description = "UUID", .tag = SMBIOS_RAW_TAG ( SMBIOS_TYPE_SYSTEM_INFORMATION, struct smbios_system_information, uuid ), .type = &setting_type_uuid, }; /** Other SMBIOS named settings */ struct setting smbios_named_settings[] __setting ( SETTING_HOST_EXTRA ) = { { .name = "manufacturer", .description = "Manufacturer", .tag = SMBIOS_STRING_TAG ( SMBIOS_TYPE_SYSTEM_INFORMATION, struct smbios_system_information, manufacturer ), .type = &setting_type_string, }, { .name = "product", .description = "Product name", .tag = SMBIOS_STRING_TAG ( SMBIOS_TYPE_SYSTEM_INFORMATION, struct smbios_system_information, product ), .type = &setting_type_string, }, { .name = "serial", .description = "Serial number", .tag = SMBIOS_STRING_TAG ( SMBIOS_TYPE_SYSTEM_INFORMATION, struct smbios_system_information, serial ), .type = &setting_type_string, }, { .name = "asset", .description = "Asset tag", .tag = SMBIOS_STRING_TAG ( SMBIOS_TYPE_ENCLOSURE_INFORMATION, struct smbios_enclosure_information, asset_tag ), .type = &setting_type_string, }, }; ipxe-precise-1.0.0+git-2.55f6c88/src/interface/smbios/smbios.c0000664000175000017500000001200111701704160022502 0ustar sergeserge/* * Copyright (C) 2007 Michael Brown . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include #include #include #include /** @file * * System Management BIOS * */ /** SMBIOS entry point descriptor */ static struct smbios smbios = { .address = UNULL, }; /** * Find SMBIOS strings terminator * * @v offset Offset to start of strings * @ret offset Offset to strings terminator, or 0 if not found */ static size_t find_strings_terminator ( size_t offset ) { size_t max_offset = ( smbios.len - 2 ); uint16_t nulnul; for ( ; offset <= max_offset ; offset++ ) { copy_from_user ( &nulnul, smbios.address, offset, 2 ); if ( nulnul == 0 ) return ( offset + 1 ); } return 0; } /** * Find specific structure type within SMBIOS * * @v type Structure type to search for * @v structure SMBIOS structure descriptor to fill in * @ret rc Return status code */ int find_smbios_structure ( unsigned int type, struct smbios_structure *structure ) { unsigned int count = 0; size_t offset = 0; size_t strings_offset; size_t terminator_offset; int rc; /* Find SMBIOS */ if ( ( smbios.address == UNULL ) && ( ( rc = find_smbios ( &smbios ) ) != 0 ) ) return rc; assert ( smbios.address != UNULL ); /* Scan through list of structures */ while ( ( ( offset + sizeof ( structure->header ) ) < smbios.len ) && ( count < smbios.count ) ) { /* Read next SMBIOS structure header */ copy_from_user ( &structure->header, smbios.address, offset, sizeof ( structure->header ) ); /* Determine start and extent of strings block */ strings_offset = ( offset + structure->header.len ); if ( strings_offset > smbios.len ) { DBG ( "SMBIOS structure at offset %zx with length " "%x extends beyond SMBIOS\n", offset, structure->header.len ); return -ENOENT; } terminator_offset = find_strings_terminator ( strings_offset ); if ( ! terminator_offset ) { DBG ( "SMBIOS structure at offset %zx has " "unterminated strings section\n", offset ); return -ENOENT; } structure->strings_len = ( terminator_offset - strings_offset); DBG ( "SMBIOS structure at offset %zx has type %d, length %x, " "strings length %zx\n", offset, structure->header.type, structure->header.len, structure->strings_len ); /* If this is the structure we want, return */ if ( structure->header.type == type ) { structure->offset = offset; return 0; } /* Move to next SMBIOS structure */ offset = ( terminator_offset + 1 ); count++; } DBG ( "SMBIOS structure type %d not found\n", type ); return -ENOENT; } /** * Copy SMBIOS structure * * @v structure SMBIOS structure descriptor * @v data Buffer to hold SMBIOS structure * @v len Length of buffer * @ret rc Return status code */ int read_smbios_structure ( struct smbios_structure *structure, void *data, size_t len ) { assert ( smbios.address != UNULL ); if ( len > structure->header.len ) len = structure->header.len; copy_from_user ( data, smbios.address, structure->offset, len ); return 0; } /** * Find indexed string within SMBIOS structure * * @v structure SMBIOS structure descriptor * @v index String index * @v data Buffer for string * @v len Length of string buffer * @ret rc Length of string, or negative error */ int read_smbios_string ( struct smbios_structure *structure, unsigned int index, void *data, size_t len ) { size_t strings_start = ( structure->offset + structure->header.len ); size_t strings_end = ( strings_start + structure->strings_len ); size_t offset; size_t string_len; assert ( smbios.address != UNULL ); /* String numbers start at 1 (0 is used to indicate "no string") */ if ( ! index ) return -ENOENT; for ( offset = strings_start ; offset < strings_end ; offset += ( string_len + 1 ) ) { /* Get string length. This is known safe, since the * smbios_strings struct is constructed so as to * always end on a string boundary. */ string_len = strlen_user ( smbios.address, offset ); if ( --index == 0 ) { /* Copy string, truncating as necessary. */ if ( len > string_len ) len = string_len; copy_from_user ( data, smbios.address, offset, len ); return string_len; } } DBG ( "SMBIOS string index %d not found\n", index ); return -ENOENT; } ipxe-precise-1.0.0+git-2.55f6c88/src/interface/efi/0000775000175000017500000000000011701704160020317 5ustar sergesergeipxe-precise-1.0.0+git-2.55f6c88/src/interface/efi/efi_strings.c0000664000175000017500000001002511701704160022775 0ustar sergeserge/* * Copyright (C) 2011 Michael Brown . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include #include /** Context used by efi_vsnprintf() and friends */ struct efi_sputc_context { /** printf context */ struct printf_context ctx; /** Buffer for formatted string (used by efi_printf_sputc()) */ wchar_t *buf; /** Buffer length (used by efi_printf_sputc()) * * Note that this is a number of wide characters, not a number * of bytes. */ size_t max_wlen; }; /** * Write wide character to buffer * * @v ctx Context * @v c Character */ static void efi_printf_sputc ( struct printf_context *ctx, unsigned int c ) { struct efi_sputc_context * sctx = container_of ( ctx, struct efi_sputc_context, ctx ); if ( ctx->len < sctx->max_wlen ) sctx->buf[ctx->len] = c; } /** * Write a formatted string to a wide-character buffer * * @v wbuf Buffer into which to write the string * @v wsize Size of buffer (in wide characters) * @v fmt Format string * @v args Arguments corresponding to the format string * @ret wlen Length of formatted string (in wide characters) * * If the buffer is too small to contain the string, the returned * length is the length that would have been written had enough space * been available. */ int efi_vsnprintf ( wchar_t *wbuf, size_t wsize, const char *fmt, va_list args ) { struct efi_sputc_context sctx; size_t wlen; size_t wend; /* Hand off to vcprintf */ sctx.ctx.handler = efi_printf_sputc; sctx.buf = wbuf; sctx.max_wlen = wsize; wlen = vcprintf ( &sctx.ctx, fmt, args ); /* Add trailing NUL */ if ( wsize ) { wend = wsize - 1; if ( wlen < wend ) wend = wlen; wbuf[wend] = '\0'; } return wlen; } /** * Write a formatted string to a buffer * * @v wbuf Buffer into which to write the string * @v wsize Size of buffer (in wide characters) * @v fmt Format string * @v ... Arguments corresponding to the format string * @ret wlen Length of formatted string (in wide characters) */ int efi_snprintf ( wchar_t *wbuf, size_t wsize, const char *fmt, ... ) { va_list args; int i; va_start ( args, fmt ); i = efi_vsnprintf ( wbuf, wsize, fmt, args ); va_end ( args ); return i; } /** * Version of efi_vsnprintf() that accepts a signed buffer size * * @v wbuf Buffer into which to write the string * @v swsize Size of buffer (in wide characters) * @v fmt Format string * @v args Arguments corresponding to the format string * @ret wlen Length of formatted string (in wide characters) */ int efi_vssnprintf ( wchar_t *wbuf, ssize_t swsize, const char *fmt, va_list args ) { /* Treat negative buffer size as zero buffer size */ if ( swsize < 0 ) swsize = 0; /* Hand off to vsnprintf */ return efi_vsnprintf ( wbuf, swsize, fmt, args ); } /** * Version of efi_vsnprintf() that accepts a signed buffer size * * @v wbuf Buffer into which to write the string * @v swsize Size of buffer (in wide characters) * @v fmt Format string * @v ... Arguments corresponding to the format string * @ret wlen Length of formatted string (in wide characters) */ int efi_ssnprintf ( wchar_t *wbuf, ssize_t swsize, const char *fmt, ... ) { va_list args; int len; /* Hand off to vssnprintf */ va_start ( args, fmt ); len = efi_vssnprintf ( wbuf, swsize, fmt, args ); va_end ( args ); return len; } ipxe-precise-1.0.0+git-2.55f6c88/src/interface/efi/efi_console.c0000664000175000017500000001701511701704160022754 0ustar sergeserge/* * Copyright (C) 2008 Michael Brown . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include #include #include #define ATTR_BOLD 0x08 #define ATTR_FCOL_MASK 0x07 #define ATTR_FCOL_BLACK 0x00 #define ATTR_FCOL_BLUE 0x01 #define ATTR_FCOL_GREEN 0x02 #define ATTR_FCOL_CYAN 0x03 #define ATTR_FCOL_RED 0x04 #define ATTR_FCOL_MAGENTA 0x05 #define ATTR_FCOL_YELLOW 0x06 #define ATTR_FCOL_WHITE 0x07 #define ATTR_BCOL_MASK 0x70 #define ATTR_BCOL_BLACK 0x00 #define ATTR_BCOL_BLUE 0x10 #define ATTR_BCOL_GREEN 0x20 #define ATTR_BCOL_CYAN 0x30 #define ATTR_BCOL_RED 0x40 #define ATTR_BCOL_MAGENTA 0x50 #define ATTR_BCOL_YELLOW 0x60 #define ATTR_BCOL_WHITE 0x70 #define ATTR_DEFAULT ATTR_FCOL_WHITE /** Current character attribute */ static unsigned int efi_attr = ATTR_DEFAULT; /** * Handle ANSI CUP (cursor position) * * @v count Parameter count * @v params[0] Row (1 is top) * @v params[1] Column (1 is left) */ static void efi_handle_cup ( unsigned int count __unused, int params[] ) { EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *conout = efi_systab->ConOut; int cx = ( params[1] - 1 ); int cy = ( params[0] - 1 ); if ( cx < 0 ) cx = 0; if ( cy < 0 ) cy = 0; conout->SetCursorPosition ( conout, cx, cy ); } /** * Handle ANSI ED (erase in page) * * @v count Parameter count * @v params[0] Region to erase */ static void efi_handle_ed ( unsigned int count __unused, int params[] __unused ) { EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *conout = efi_systab->ConOut; /* We assume that we always clear the whole screen */ assert ( params[0] == ANSIESC_ED_ALL ); conout->ClearScreen ( conout ); } /** * Handle ANSI SGR (set graphics rendition) * * @v count Parameter count * @v params List of graphic rendition aspects */ static void efi_handle_sgr ( unsigned int count, int params[] ) { EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *conout = efi_systab->ConOut; static const uint8_t efi_attr_fcols[10] = { ATTR_FCOL_BLACK, ATTR_FCOL_RED, ATTR_FCOL_GREEN, ATTR_FCOL_YELLOW, ATTR_FCOL_BLUE, ATTR_FCOL_MAGENTA, ATTR_FCOL_CYAN, ATTR_FCOL_WHITE, ATTR_FCOL_WHITE, ATTR_FCOL_WHITE /* defaults */ }; static const uint8_t efi_attr_bcols[10] = { ATTR_BCOL_BLACK, ATTR_BCOL_RED, ATTR_BCOL_GREEN, ATTR_BCOL_YELLOW, ATTR_BCOL_BLUE, ATTR_BCOL_MAGENTA, ATTR_BCOL_CYAN, ATTR_BCOL_WHITE, ATTR_BCOL_BLACK, ATTR_BCOL_BLACK /* defaults */ }; unsigned int i; int aspect; for ( i = 0 ; i < count ; i++ ) { aspect = params[i]; if ( aspect == 0 ) { efi_attr = ATTR_DEFAULT; } else if ( aspect == 1 ) { efi_attr |= ATTR_BOLD; } else if ( aspect == 22 ) { efi_attr &= ~ATTR_BOLD; } else if ( ( aspect >= 30 ) && ( aspect <= 39 ) ) { efi_attr &= ~ATTR_FCOL_MASK; efi_attr |= efi_attr_fcols[ aspect - 30 ]; } else if ( ( aspect >= 40 ) && ( aspect <= 49 ) ) { efi_attr &= ~ATTR_BCOL_MASK; efi_attr |= efi_attr_bcols[ aspect - 40 ]; } } conout->SetAttribute ( conout, efi_attr ); } /** EFI console ANSI escape sequence handlers */ static struct ansiesc_handler efi_ansiesc_handlers[] = { { ANSIESC_CUP, efi_handle_cup }, { ANSIESC_ED, efi_handle_ed }, { ANSIESC_SGR, efi_handle_sgr }, { 0, NULL } }; /** EFI console ANSI escape sequence context */ static struct ansiesc_context efi_ansiesc_ctx = { .handlers = efi_ansiesc_handlers, }; /** * Print a character to EFI console * * @v character Character to be printed */ static void efi_putchar ( int character ) { EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *conout = efi_systab->ConOut; wchar_t wstr[] = { character, 0 }; /* Intercept ANSI escape sequences */ character = ansiesc_process ( &efi_ansiesc_ctx, character ); if ( character < 0 ) return; conout->OutputString ( conout, wstr ); } /** * Pointer to current ANSI output sequence * * While we are in the middle of returning an ANSI sequence for a * special key, this will point to the next character to return. When * not in the middle of such a sequence, this will point to a NUL * (note: not "will be NULL"). */ static const char *ansi_input = ""; /** Mapping from EFI scan codes to ANSI escape sequences */ static const char *ansi_sequences[] = { [SCAN_UP] = "[A", [SCAN_DOWN] = "[B", [SCAN_RIGHT] = "[C", [SCAN_LEFT] = "[D", [SCAN_HOME] = "[H", [SCAN_END] = "[F", [SCAN_INSERT] = "[2~", /* EFI translates an incoming backspace via the serial console * into a SCAN_DELETE. There's not much we can do about this. */ [SCAN_DELETE] = "[3~", [SCAN_PAGE_UP] = "[5~", [SCAN_PAGE_DOWN] = "[6~", /* EFI translates some (but not all) incoming escape sequences * via the serial console into equivalent scancodes. When it * doesn't recognise a sequence, it helpfully(!) translates * the initial ESC and passes the remainder through verbatim. * Treating SCAN_ESC as equivalent to an empty escape sequence * works around this bug. */ [SCAN_ESC] = "", }; /** * Get ANSI escape sequence corresponding to EFI scancode * * @v scancode EFI scancode * @ret ansi_seq ANSI escape sequence, if any, otherwise NULL */ static const char * scancode_to_ansi_seq ( unsigned int scancode ) { if ( scancode < ( sizeof ( ansi_sequences ) / sizeof ( ansi_sequences[0] ) ) ) { return ansi_sequences[scancode]; } return NULL; } /** * Get character from EFI console * * @ret character Character read from console */ static int efi_getchar ( void ) { EFI_SIMPLE_TEXT_INPUT_PROTOCOL *conin = efi_systab->ConIn; const char *ansi_seq; EFI_INPUT_KEY key; EFI_STATUS efirc; /* If we are mid-sequence, pass out the next byte */ if ( *ansi_input ) return *(ansi_input++); /* Read key from real EFI console */ if ( ( efirc = conin->ReadKeyStroke ( conin, &key ) ) != 0 ) { DBG ( "EFI could not read keystroke: %s\n", efi_strerror ( efirc ) ); return 0; } DBG2 ( "EFI read key stroke with unicode %04x scancode %04x\n", key.UnicodeChar, key.ScanCode ); /* If key has a Unicode representation, return it */ if ( key.UnicodeChar ) return key.UnicodeChar; /* Otherwise, check for a special key that we know about */ if ( ( ansi_seq = scancode_to_ansi_seq ( key.ScanCode ) ) ) { /* Start of escape sequence: return ESC (0x1b) */ ansi_input = ansi_seq; return 0x1b; } return 0; } /** * Check for character ready to read from EFI console * * @ret True Character available to read * @ret False No character available to read */ static int efi_iskey ( void ) { EFI_BOOT_SERVICES *bs = efi_systab->BootServices; EFI_SIMPLE_TEXT_INPUT_PROTOCOL *conin = efi_systab->ConIn; EFI_STATUS efirc; /* If we are mid-sequence, we are always ready */ if ( *ansi_input ) return 1; /* Check to see if the WaitForKey event has fired */ if ( ( efirc = bs->CheckEvent ( conin->WaitForKey ) ) == 0 ) return 1; return 0; } struct console_driver efi_console __console_driver = { .putchar = efi_putchar, .getchar = efi_getchar, .iskey = efi_iskey, }; ipxe-precise-1.0.0+git-2.55f6c88/src/interface/efi/efi_snp.c0000664000175000017500000011614211701704160022113 0ustar sergeserge/* * Copyright (C) 2008 Michael Brown . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /** @file * * iPXE EFI SNP interface * */ /** An SNP device */ struct efi_snp_device { /** List of SNP devices */ struct list_head list; /** The underlying iPXE network device */ struct net_device *netdev; /** The underlying EFI PCI device */ struct efi_pci_device *efipci; /** EFI device handle */ EFI_HANDLE handle; /** The SNP structure itself */ EFI_SIMPLE_NETWORK_PROTOCOL snp; /** The SNP "mode" (parameters) */ EFI_SIMPLE_NETWORK_MODE mode; /** Outstanding TX packet count (via "interrupt status") * * Used in order to generate TX completions. */ unsigned int tx_count_interrupts; /** Outstanding TX packet count (via "recycled tx buffers") * * Used in order to generate TX completions. */ unsigned int tx_count_txbufs; /** Outstanding RX packet count (via "interrupt status") */ unsigned int rx_count_interrupts; /** Outstanding RX packet count (via WaitForPacket event) */ unsigned int rx_count_events; /** The network interface identifier */ EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL nii; /** HII configuration access protocol */ EFI_HII_CONFIG_ACCESS_PROTOCOL hii; /** HII package list */ EFI_HII_PACKAGE_LIST_HEADER *package_list; /** HII handle */ EFI_HII_HANDLE hii_handle; /** Device name */ wchar_t name[ sizeof ( ( ( struct net_device * ) NULL )->name ) ]; /** The device path * * This field is variable in size and must appear at the end * of the structure. */ EFI_DEVICE_PATH_PROTOCOL path; }; /** EFI simple network protocol GUID */ static EFI_GUID efi_simple_network_protocol_guid = EFI_SIMPLE_NETWORK_PROTOCOL_GUID; /** EFI device path protocol GUID */ static EFI_GUID efi_device_path_protocol_guid = EFI_DEVICE_PATH_PROTOCOL_GUID; /** EFI network interface identifier GUID */ static EFI_GUID efi_nii_protocol_guid = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID; /** EFI network interface identifier GUID (extra special version) */ static EFI_GUID efi_nii31_protocol_guid = { /* At some point, it seems that someone decided to change the * GUID. Current EFI builds ignore the older GUID, older EFI * builds ignore the newer GUID, so we have to expose both. */ 0x1ACED566, 0x76ED, 0x4218, { 0xBC, 0x81, 0x76, 0x7F, 0x1F, 0x97, 0x7A, 0x89 } }; /** List of SNP devices */ static LIST_HEAD ( efi_snp_devices ); /** * Set EFI SNP mode based on iPXE net device parameters * * @v snp SNP interface */ static void efi_snp_set_mode ( struct efi_snp_device *snpdev ) { struct net_device *netdev = snpdev->netdev; EFI_SIMPLE_NETWORK_MODE *mode = &snpdev->mode; struct ll_protocol *ll_protocol = netdev->ll_protocol; unsigned int ll_addr_len = ll_protocol->ll_addr_len; mode->HwAddressSize = ll_addr_len; mode->MediaHeaderSize = ll_protocol->ll_header_len; mode->MaxPacketSize = netdev->max_pkt_len; mode->ReceiveFilterMask = ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST | EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST ); assert ( ll_addr_len <= sizeof ( mode->CurrentAddress ) ); memcpy ( &mode->CurrentAddress, netdev->ll_addr, ll_addr_len ); memcpy ( &mode->BroadcastAddress, netdev->ll_broadcast, ll_addr_len ); ll_protocol->init_addr ( netdev->hw_addr, &mode->PermanentAddress ); mode->IfType = ntohs ( ll_protocol->ll_proto ); mode->MacAddressChangeable = TRUE; mode->MediaPresentSupported = TRUE; mode->MediaPresent = ( netdev_link_ok ( netdev ) ? TRUE : FALSE ); } /** * Poll net device and count received packets * * @v snpdev SNP device */ static void efi_snp_poll ( struct efi_snp_device *snpdev ) { struct io_buffer *iobuf; unsigned int before = 0; unsigned int after = 0; unsigned int arrived; /* We have to report packet arrivals, and this is the easiest * way to fake it. */ list_for_each_entry ( iobuf, &snpdev->netdev->rx_queue, list ) before++; netdev_poll ( snpdev->netdev ); list_for_each_entry ( iobuf, &snpdev->netdev->rx_queue, list ) after++; arrived = ( after - before ); snpdev->rx_count_interrupts += arrived; snpdev->rx_count_events += arrived; } /** * Change SNP state from "stopped" to "started" * * @v snp SNP interface * @ret efirc EFI status code */ static EFI_STATUS EFIAPI efi_snp_start ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) { struct efi_snp_device *snpdev = container_of ( snp, struct efi_snp_device, snp ); DBGC2 ( snpdev, "SNPDEV %p START\n", snpdev ); snpdev->mode.State = EfiSimpleNetworkStarted; return 0; } /** * Change SNP state from "started" to "stopped" * * @v snp SNP interface * @ret efirc EFI status code */ static EFI_STATUS EFIAPI efi_snp_stop ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) { struct efi_snp_device *snpdev = container_of ( snp, struct efi_snp_device, snp ); DBGC2 ( snpdev, "SNPDEV %p STOP\n", snpdev ); snpdev->mode.State = EfiSimpleNetworkStopped; return 0; } /** * Open the network device * * @v snp SNP interface * @v extra_rx_bufsize Extra RX buffer size, in bytes * @v extra_tx_bufsize Extra TX buffer size, in bytes * @ret efirc EFI status code */ static EFI_STATUS EFIAPI efi_snp_initialize ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, UINTN extra_rx_bufsize, UINTN extra_tx_bufsize ) { struct efi_snp_device *snpdev = container_of ( snp, struct efi_snp_device, snp ); int rc; DBGC2 ( snpdev, "SNPDEV %p INITIALIZE (%ld extra RX, %ld extra TX)\n", snpdev, ( ( unsigned long ) extra_rx_bufsize ), ( ( unsigned long ) extra_tx_bufsize ) ); if ( ( rc = netdev_open ( snpdev->netdev ) ) != 0 ) { DBGC ( snpdev, "SNPDEV %p could not open %s: %s\n", snpdev, snpdev->netdev->name, strerror ( rc ) ); return RC_TO_EFIRC ( rc ); } snpdev->mode.State = EfiSimpleNetworkInitialized; return 0; } /** * Reset the network device * * @v snp SNP interface * @v ext_verify Extended verification required * @ret efirc EFI status code */ static EFI_STATUS EFIAPI efi_snp_reset ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ext_verify ) { struct efi_snp_device *snpdev = container_of ( snp, struct efi_snp_device, snp ); int rc; DBGC2 ( snpdev, "SNPDEV %p RESET (%s extended verification)\n", snpdev, ( ext_verify ? "with" : "without" ) ); netdev_close ( snpdev->netdev ); snpdev->mode.State = EfiSimpleNetworkStarted; if ( ( rc = netdev_open ( snpdev->netdev ) ) != 0 ) { DBGC ( snpdev, "SNPDEV %p could not reopen %s: %s\n", snpdev, snpdev->netdev->name, strerror ( rc ) ); return RC_TO_EFIRC ( rc ); } snpdev->mode.State = EfiSimpleNetworkInitialized; return 0; } /** * Shut down the network device * * @v snp SNP interface * @ret efirc EFI status code */ static EFI_STATUS EFIAPI efi_snp_shutdown ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) { struct efi_snp_device *snpdev = container_of ( snp, struct efi_snp_device, snp ); DBGC2 ( snpdev, "SNPDEV %p SHUTDOWN\n", snpdev ); netdev_close ( snpdev->netdev ); snpdev->mode.State = EfiSimpleNetworkStarted; return 0; } /** * Manage receive filters * * @v snp SNP interface * @v enable Receive filters to enable * @v disable Receive filters to disable * @v mcast_reset Reset multicast filters * @v mcast_count Number of multicast filters * @v mcast Multicast filters * @ret efirc EFI status code */ static EFI_STATUS EFIAPI efi_snp_receive_filters ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, UINT32 enable, UINT32 disable, BOOLEAN mcast_reset, UINTN mcast_count, EFI_MAC_ADDRESS *mcast ) { struct efi_snp_device *snpdev = container_of ( snp, struct efi_snp_device, snp ); unsigned int i; DBGC2 ( snpdev, "SNPDEV %p RECEIVE_FILTERS %08x&~%08x%s %ld mcast\n", snpdev, enable, disable, ( mcast_reset ? " reset" : "" ), ( ( unsigned long ) mcast_count ) ); for ( i = 0 ; i < mcast_count ; i++ ) { DBGC2_HDA ( snpdev, i, &mcast[i], snpdev->netdev->ll_protocol->ll_addr_len ); } /* Lie through our teeth, otherwise MNP refuses to accept us */ return 0; } /** * Set station address * * @v snp SNP interface * @v reset Reset to permanent address * @v new New station address * @ret efirc EFI status code */ static EFI_STATUS EFIAPI efi_snp_station_address ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN reset, EFI_MAC_ADDRESS *new ) { struct efi_snp_device *snpdev = container_of ( snp, struct efi_snp_device, snp ); struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol; DBGC2 ( snpdev, "SNPDEV %p STATION_ADDRESS %s\n", snpdev, ( reset ? "reset" : ll_protocol->ntoa ( new ) ) ); /* Set the MAC address */ if ( reset ) new = &snpdev->mode.PermanentAddress; memcpy ( snpdev->netdev->ll_addr, new, ll_protocol->ll_addr_len ); /* MAC address changes take effect only on netdev_open() */ if ( netdev_is_open ( snpdev->netdev ) ) { DBGC ( snpdev, "SNPDEV %p MAC address changed while net " "devive open\n", snpdev ); } return 0; } /** * Get (or reset) statistics * * @v snp SNP interface * @v reset Reset statistics * @v stats_len Size of statistics table * @v stats Statistics table * @ret efirc EFI status code */ static EFI_STATUS EFIAPI efi_snp_statistics ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN reset, UINTN *stats_len, EFI_NETWORK_STATISTICS *stats ) { struct efi_snp_device *snpdev = container_of ( snp, struct efi_snp_device, snp ); EFI_NETWORK_STATISTICS stats_buf; DBGC2 ( snpdev, "SNPDEV %p STATISTICS%s", snpdev, ( reset ? " reset" : "" ) ); /* Gather statistics */ memset ( &stats_buf, 0, sizeof ( stats_buf ) ); stats_buf.TxGoodFrames = snpdev->netdev->tx_stats.good; stats_buf.TxDroppedFrames = snpdev->netdev->tx_stats.bad; stats_buf.TxTotalFrames = ( snpdev->netdev->tx_stats.good + snpdev->netdev->tx_stats.bad ); stats_buf.RxGoodFrames = snpdev->netdev->rx_stats.good; stats_buf.RxDroppedFrames = snpdev->netdev->rx_stats.bad; stats_buf.RxTotalFrames = ( snpdev->netdev->rx_stats.good + snpdev->netdev->rx_stats.bad ); if ( *stats_len > sizeof ( stats_buf ) ) *stats_len = sizeof ( stats_buf ); if ( stats ) memcpy ( stats, &stats_buf, *stats_len ); /* Reset statistics if requested to do so */ if ( reset ) { memset ( &snpdev->netdev->tx_stats, 0, sizeof ( snpdev->netdev->tx_stats ) ); memset ( &snpdev->netdev->rx_stats, 0, sizeof ( snpdev->netdev->rx_stats ) ); } return 0; } /** * Convert multicast IP address to MAC address * * @v snp SNP interface * @v ipv6 Address is IPv6 * @v ip IP address * @v mac MAC address * @ret efirc EFI status code */ static EFI_STATUS EFIAPI efi_snp_mcast_ip_to_mac ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ipv6, EFI_IP_ADDRESS *ip, EFI_MAC_ADDRESS *mac ) { struct efi_snp_device *snpdev = container_of ( snp, struct efi_snp_device, snp ); struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol; const char *ip_str; int rc; ip_str = ( ipv6 ? "(IPv6)" /* FIXME when we have inet6_ntoa() */ : inet_ntoa ( *( ( struct in_addr * ) ip ) ) ); DBGC2 ( snpdev, "SNPDEV %p MCAST_IP_TO_MAC %s\n", snpdev, ip_str ); /* Try to hash the address */ if ( ( rc = ll_protocol->mc_hash ( ( ipv6 ? AF_INET6 : AF_INET ), ip, mac ) ) != 0 ) { DBGC ( snpdev, "SNPDEV %p could not hash %s: %s\n", snpdev, ip_str, strerror ( rc ) ); return RC_TO_EFIRC ( rc ); } return 0; } /** * Read or write non-volatile storage * * @v snp SNP interface * @v read Operation is a read * @v offset Starting offset within NVRAM * @v len Length of data buffer * @v data Data buffer * @ret efirc EFI status code */ static EFI_STATUS EFIAPI efi_snp_nvdata ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN read, UINTN offset, UINTN len, VOID *data ) { struct efi_snp_device *snpdev = container_of ( snp, struct efi_snp_device, snp ); DBGC2 ( snpdev, "SNPDEV %p NVDATA %s %lx+%lx\n", snpdev, ( read ? "read" : "write" ), ( ( unsigned long ) offset ), ( ( unsigned long ) len ) ); if ( ! read ) DBGC2_HDA ( snpdev, offset, data, len ); return EFI_UNSUPPORTED; } /** * Read interrupt status and TX recycled buffer status * * @v snp SNP interface * @v interrupts Interrupt status, or NULL * @v txbufs Recycled transmit buffer address, or NULL * @ret efirc EFI status code */ static EFI_STATUS EFIAPI efi_snp_get_status ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, UINT32 *interrupts, VOID **txbufs ) { struct efi_snp_device *snpdev = container_of ( snp, struct efi_snp_device, snp ); DBGC2 ( snpdev, "SNPDEV %p GET_STATUS", snpdev ); /* Poll the network device */ efi_snp_poll ( snpdev ); /* Interrupt status. In practice, this seems to be used only * to detect TX completions. */ if ( interrupts ) { *interrupts = 0; /* Report TX completions once queue is empty; this * avoids having to add hooks in the net device layer. */ if ( snpdev->tx_count_interrupts && list_empty ( &snpdev->netdev->tx_queue ) ) { *interrupts |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT; snpdev->tx_count_interrupts--; } /* Report RX */ if ( snpdev->rx_count_interrupts ) { *interrupts |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT; snpdev->rx_count_interrupts--; } DBGC2 ( snpdev, " INTS:%02x", *interrupts ); } /* TX completions. It would be possible to design a more * idiotic scheme for this, but it would be a challenge. * According to the UEFI header file, txbufs will be filled in * with a list of "recycled transmit buffers" (i.e. completed * TX buffers). Observant readers may care to note that * *txbufs is a void pointer. Precisely how a list of * completed transmit buffers is meant to be represented as an * array of voids is left as an exercise for the reader. * * The only users of this interface (MnpDxe/MnpIo.c and * PxeBcDxe/Bc.c within the EFI dev kit) both just poll until * seeing a non-NULL result return in txbufs. This is valid * provided that they do not ever attempt to transmit more * than one packet concurrently (and that TX never times out). */ if ( txbufs ) { if ( snpdev->tx_count_txbufs && list_empty ( &snpdev->netdev->tx_queue ) ) { *txbufs = "Which idiot designed this API?"; snpdev->tx_count_txbufs--; } else { *txbufs = NULL; } DBGC2 ( snpdev, " TX:%s", ( *txbufs ? "some" : "none" ) ); } DBGC2 ( snpdev, "\n" ); return 0; } /** * Start packet transmission * * @v snp SNP interface * @v ll_header_len Link-layer header length, if to be filled in * @v len Length of data buffer * @v data Data buffer * @v ll_src Link-layer source address, if specified * @v ll_dest Link-layer destination address, if specified * @v net_proto Network-layer protocol (in host order) * @ret efirc EFI status code */ static EFI_STATUS EFIAPI efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, UINTN ll_header_len, UINTN len, VOID *data, EFI_MAC_ADDRESS *ll_src, EFI_MAC_ADDRESS *ll_dest, UINT16 *net_proto ) { struct efi_snp_device *snpdev = container_of ( snp, struct efi_snp_device, snp ); struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol; struct io_buffer *iobuf; size_t ll_headroom; int rc; EFI_STATUS efirc; DBGC2 ( snpdev, "SNPDEV %p TRANSMIT %p+%lx", snpdev, data, ( ( unsigned long ) len ) ); if ( ll_header_len ) { if ( ll_src ) { DBGC2 ( snpdev, " src %s", ll_protocol->ntoa ( ll_src ) ); } if ( ll_dest ) { DBGC2 ( snpdev, " dest %s", ll_protocol->ntoa ( ll_dest ) ); } if ( net_proto ) { DBGC2 ( snpdev, " proto %04x", *net_proto ); } } DBGC2 ( snpdev, "\n" ); /* Sanity checks */ if ( ll_header_len ) { if ( ll_header_len != ll_protocol->ll_header_len ) { DBGC ( snpdev, "SNPDEV %p TX invalid header length " "%ld\n", snpdev, ( ( unsigned long ) ll_header_len ) ); efirc = EFI_INVALID_PARAMETER; goto err_sanity; } if ( len < ll_header_len ) { DBGC ( snpdev, "SNPDEV %p invalid packet length %ld\n", snpdev, ( ( unsigned long ) len ) ); efirc = EFI_BUFFER_TOO_SMALL; goto err_sanity; } if ( ! ll_dest ) { DBGC ( snpdev, "SNPDEV %p TX missing destination " "address\n", snpdev ); efirc = EFI_INVALID_PARAMETER; goto err_sanity; } if ( ! net_proto ) { DBGC ( snpdev, "SNPDEV %p TX missing network " "protocol\n", snpdev ); efirc = EFI_INVALID_PARAMETER; goto err_sanity; } if ( ! ll_src ) ll_src = &snpdev->mode.CurrentAddress; } /* Allocate buffer */ ll_headroom = ( MAX_LL_HEADER_LEN - ll_header_len ); iobuf = alloc_iob ( ll_headroom + len ); if ( ! iobuf ) { DBGC ( snpdev, "SNPDEV %p TX could not allocate %ld-byte " "buffer\n", snpdev, ( ( unsigned long ) len ) ); efirc = EFI_DEVICE_ERROR; goto err_alloc_iob; } iob_reserve ( iobuf, ll_headroom ); memcpy ( iob_put ( iobuf, len ), data, len ); /* Create link-layer header, if specified */ if ( ll_header_len ) { iob_pull ( iobuf, ll_header_len ); if ( ( rc = ll_protocol->push ( snpdev->netdev, iobuf, ll_dest, ll_src, htons ( *net_proto ) )) != 0 ){ DBGC ( snpdev, "SNPDEV %p TX could not construct " "header: %s\n", snpdev, strerror ( rc ) ); efirc = RC_TO_EFIRC ( rc ); goto err_ll_push; } } /* Transmit packet */ if ( ( rc = netdev_tx ( snpdev->netdev, iob_disown ( iobuf ) ) ) != 0){ DBGC ( snpdev, "SNPDEV %p TX could not transmit: %s\n", snpdev, strerror ( rc ) ); efirc = RC_TO_EFIRC ( rc ); goto err_tx; } /* Record transmission as outstanding */ snpdev->tx_count_interrupts++; snpdev->tx_count_txbufs++; return 0; err_tx: err_ll_push: free_iob ( iobuf ); err_alloc_iob: err_sanity: return efirc; } /** * Receive packet * * @v snp SNP interface * @v ll_header_len Link-layer header length, if to be filled in * @v len Length of data buffer * @v data Data buffer * @v ll_src Link-layer source address, if specified * @v ll_dest Link-layer destination address, if specified * @v net_proto Network-layer protocol (in host order) * @ret efirc EFI status code */ static EFI_STATUS EFIAPI efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, UINTN *ll_header_len, UINTN *len, VOID *data, EFI_MAC_ADDRESS *ll_src, EFI_MAC_ADDRESS *ll_dest, UINT16 *net_proto ) { struct efi_snp_device *snpdev = container_of ( snp, struct efi_snp_device, snp ); struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol; struct io_buffer *iobuf; const void *iob_ll_dest; const void *iob_ll_src; uint16_t iob_net_proto; unsigned int iob_flags; int rc; EFI_STATUS efirc; DBGC2 ( snpdev, "SNPDEV %p RECEIVE %p(+%lx)", snpdev, data, ( ( unsigned long ) *len ) ); /* Poll the network device */ efi_snp_poll ( snpdev ); /* Dequeue a packet, if one is available */ iobuf = netdev_rx_dequeue ( snpdev->netdev ); if ( ! iobuf ) { DBGC2 ( snpdev, "\n" ); efirc = EFI_NOT_READY; goto out_no_packet; } DBGC2 ( snpdev, "+%zx\n", iob_len ( iobuf ) ); /* Return packet to caller */ memcpy ( data, iobuf->data, iob_len ( iobuf ) ); *len = iob_len ( iobuf ); /* Attempt to decode link-layer header */ if ( ( rc = ll_protocol->pull ( snpdev->netdev, iobuf, &iob_ll_dest, &iob_ll_src, &iob_net_proto, &iob_flags ) ) != 0 ) { DBGC ( snpdev, "SNPDEV %p could not parse header: %s\n", snpdev, strerror ( rc ) ); efirc = RC_TO_EFIRC ( rc ); goto out_bad_ll_header; } /* Return link-layer header parameters to caller, if required */ if ( ll_header_len ) *ll_header_len = ll_protocol->ll_header_len; if ( ll_src ) memcpy ( ll_src, iob_ll_src, ll_protocol->ll_addr_len ); if ( ll_dest ) memcpy ( ll_dest, iob_ll_dest, ll_protocol->ll_addr_len ); if ( net_proto ) *net_proto = ntohs ( iob_net_proto ); efirc = 0; out_bad_ll_header: free_iob ( iobuf ); out_no_packet: return efirc; } /** * Poll event * * @v event Event * @v context Event context */ static VOID EFIAPI efi_snp_wait_for_packet ( EFI_EVENT event, VOID *context ) { EFI_BOOT_SERVICES *bs = efi_systab->BootServices; struct efi_snp_device *snpdev = context; DBGCP ( snpdev, "SNPDEV %p WAIT_FOR_PACKET\n", snpdev ); /* Do nothing unless the net device is open */ if ( ! netdev_is_open ( snpdev->netdev ) ) return; /* Poll the network device */ efi_snp_poll ( snpdev ); /* Fire event if packets have been received */ if ( snpdev->rx_count_events != 0 ) { DBGC2 ( snpdev, "SNPDEV %p firing WaitForPacket event\n", snpdev ); bs->SignalEvent ( event ); snpdev->rx_count_events--; } } /** SNP interface */ static EFI_SIMPLE_NETWORK_PROTOCOL efi_snp_device_snp = { .Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION, .Start = efi_snp_start, .Stop = efi_snp_stop, .Initialize = efi_snp_initialize, .Reset = efi_snp_reset, .Shutdown = efi_snp_shutdown, .ReceiveFilters = efi_snp_receive_filters, .StationAddress = efi_snp_station_address, .Statistics = efi_snp_statistics, .MCastIpToMac = efi_snp_mcast_ip_to_mac, .NvData = efi_snp_nvdata, .GetStatus = efi_snp_get_status, .Transmit = efi_snp_transmit, .Receive = efi_snp_receive, }; /****************************************************************************** * * Human Interface Infrastructure * ****************************************************************************** */ /** EFI configuration access protocol GUID */ static EFI_GUID efi_hii_config_access_protocol_guid = EFI_HII_CONFIG_ACCESS_PROTOCOL_GUID; /** EFI HII database protocol */ static EFI_HII_DATABASE_PROTOCOL *efihii; EFI_REQUIRE_PROTOCOL ( EFI_HII_DATABASE_PROTOCOL, &efihii ); /** Local base GUID used for our EFI SNP formset */ #define EFI_SNP_FORMSET_GUID_BASE \ { 0xc4f84019, 0x6dfd, 0x4a27, \ { 0x9b, 0x94, 0xb7, 0x2e, 0x1f, 0xbc, 0xad, 0xca } } /** Form identifiers used for our EFI SNP HII */ enum efi_snp_hii_form_id { EFI_SNP_FORM = 0x0001, /**< The only form */ }; /** String identifiers used for our EFI SNP HII */ enum efi_snp_hii_string_id { /* Language name */ EFI_SNP_LANGUAGE_NAME = 0x0001, /* Formset */ EFI_SNP_FORMSET_TITLE, EFI_SNP_FORMSET_HELP, /* Product name */ EFI_SNP_PRODUCT_PROMPT, EFI_SNP_PRODUCT_HELP, EFI_SNP_PRODUCT_TEXT, /* Version */ EFI_SNP_VERSION_PROMPT, EFI_SNP_VERSION_HELP, EFI_SNP_VERSION_TEXT, /* Driver */ EFI_SNP_DRIVER_PROMPT, EFI_SNP_DRIVER_HELP, EFI_SNP_DRIVER_TEXT, /* Device */ EFI_SNP_DEVICE_PROMPT, EFI_SNP_DEVICE_HELP, EFI_SNP_DEVICE_TEXT, /* End of list */ EFI_SNP_MAX_STRING_ID }; /** EFI SNP formset */ struct efi_snp_formset { EFI_HII_PACKAGE_HEADER Header; EFI_IFR_FORM_SET_TYPE(1) FormSet; EFI_IFR_GUID_CLASS Class; EFI_IFR_GUID_SUBCLASS SubClass; EFI_IFR_FORM Form; EFI_IFR_TEXT ProductText; EFI_IFR_TEXT VersionText; EFI_IFR_TEXT DriverText; EFI_IFR_TEXT DeviceText; EFI_IFR_END EndForm; EFI_IFR_END EndFormSet; } __attribute__ (( packed )) efi_snp_formset = { .Header = { .Length = sizeof ( efi_snp_formset ), .Type = EFI_HII_PACKAGE_FORMS, }, .FormSet = EFI_IFR_FORM_SET ( EFI_SNP_FORMSET_GUID_BASE, EFI_SNP_FORMSET_TITLE, EFI_SNP_FORMSET_HELP, typeof ( efi_snp_formset.FormSet ), EFI_HII_PLATFORM_SETUP_FORMSET_GUID ), .Class = EFI_IFR_GUID_CLASS ( EFI_NETWORK_DEVICE_CLASS ), .SubClass = EFI_IFR_GUID_SUBCLASS ( 0x03 ), .Form = EFI_IFR_FORM ( EFI_SNP_FORM, EFI_SNP_FORMSET_TITLE ), .ProductText = EFI_IFR_TEXT ( EFI_SNP_PRODUCT_PROMPT, EFI_SNP_PRODUCT_HELP, EFI_SNP_PRODUCT_TEXT ), .VersionText = EFI_IFR_TEXT ( EFI_SNP_VERSION_PROMPT, EFI_SNP_VERSION_HELP, EFI_SNP_VERSION_TEXT ), .DriverText = EFI_IFR_TEXT ( EFI_SNP_DRIVER_PROMPT, EFI_SNP_DRIVER_HELP, EFI_SNP_DRIVER_TEXT ), .DeviceText = EFI_IFR_TEXT ( EFI_SNP_DEVICE_PROMPT, EFI_SNP_DEVICE_HELP, EFI_SNP_DEVICE_TEXT ), .EndForm = EFI_IFR_END(), .EndFormSet = EFI_IFR_END(), }; /** * Generate EFI SNP string * * @v wbuf Buffer * @v swlen Size of buffer (in wide characters) * @v snpdev SNP device * @ret wlen Length of string (in wide characters) */ static int efi_snp_string ( wchar_t *wbuf, ssize_t swlen, enum efi_snp_hii_string_id id, struct efi_snp_device *snpdev ) { struct net_device *netdev = snpdev->netdev; struct device *dev = netdev->dev; switch ( id ) { case EFI_SNP_LANGUAGE_NAME: return efi_ssnprintf ( wbuf, swlen, "English" ); case EFI_SNP_FORMSET_TITLE: return efi_ssnprintf ( wbuf, swlen, "%s (%s)", ( PRODUCT_NAME[0] ? PRODUCT_NAME : PRODUCT_SHORT_NAME ), netdev_addr ( netdev ) ); case EFI_SNP_FORMSET_HELP: return efi_ssnprintf ( wbuf, swlen, "Configure " PRODUCT_SHORT_NAME ); case EFI_SNP_PRODUCT_PROMPT: return efi_ssnprintf ( wbuf, swlen, "Name" ); case EFI_SNP_PRODUCT_HELP: return efi_ssnprintf ( wbuf, swlen, "Firmware product name" ); case EFI_SNP_PRODUCT_TEXT: return efi_ssnprintf ( wbuf, swlen, "%s", ( PRODUCT_NAME[0] ? PRODUCT_NAME : PRODUCT_SHORT_NAME ) ); case EFI_SNP_VERSION_PROMPT: return efi_ssnprintf ( wbuf, swlen, "Version" ); case EFI_SNP_VERSION_HELP: return efi_ssnprintf ( wbuf, swlen, "Firmware version" ); case EFI_SNP_VERSION_TEXT: return efi_ssnprintf ( wbuf, swlen, VERSION ); case EFI_SNP_DRIVER_PROMPT: return efi_ssnprintf ( wbuf, swlen, "Driver" ); case EFI_SNP_DRIVER_HELP: return efi_ssnprintf ( wbuf, swlen, "Firmware driver" ); case EFI_SNP_DRIVER_TEXT: return efi_ssnprintf ( wbuf, swlen, "%s", dev->driver_name ); case EFI_SNP_DEVICE_PROMPT: return efi_ssnprintf ( wbuf, swlen, "Device" ); case EFI_SNP_DEVICE_HELP: return efi_ssnprintf ( wbuf, swlen, "Hardware device" ); case EFI_SNP_DEVICE_TEXT: return efi_ssnprintf ( wbuf, swlen, "%s", dev->name ); default: assert ( 0 ); return 0; } } /** * Generate EFI SNP string package * * @v strings String package header buffer * @v max_len Buffer length * @v snpdev SNP device * @ret len Length of string package */ static int efi_snp_strings ( EFI_HII_STRING_PACKAGE_HDR *strings, size_t max_len, struct efi_snp_device *snpdev ) { static const char language[] = "en-us"; void *buf = strings; ssize_t remaining = max_len; size_t hdrsize; EFI_HII_SIBT_STRING_UCS2_BLOCK *string; ssize_t wremaining; size_t string_wlen; unsigned int id; EFI_HII_STRING_BLOCK *end; size_t len; /* Calculate header size */ hdrsize = ( offsetof ( typeof ( *strings ), Language ) + sizeof ( language ) ); buf += hdrsize; remaining -= hdrsize; /* Fill in strings */ for ( id = 1 ; id < EFI_SNP_MAX_STRING_ID ; id++ ) { string = buf; if ( remaining >= ( ( ssize_t ) sizeof ( string->Header ) ) ) string->Header.BlockType = EFI_HII_SIBT_STRING_UCS2; buf += offsetof ( typeof ( *string ), StringText ); remaining -= offsetof ( typeof ( *string ), StringText ); wremaining = ( remaining / ( ( ssize_t ) sizeof ( string->StringText[0] ))); assert ( ! ( ( remaining <= 0 ) && ( wremaining > 0 ) ) ); string_wlen = efi_snp_string ( string->StringText, wremaining, id, snpdev ); buf += ( ( string_wlen + 1 /* wNUL */ ) * sizeof ( string->StringText[0] ) ); remaining -= ( ( string_wlen + 1 /* wNUL */ ) * sizeof ( string->StringText[0] ) ); } /* Fill in end marker */ end = buf; if ( remaining >= ( ( ssize_t ) sizeof ( *end ) ) ) end->BlockType = EFI_HII_SIBT_END; buf += sizeof ( *end ); remaining -= sizeof ( *end ); /* Calculate overall length */ len = ( max_len - remaining ); /* Fill in string package header */ if ( strings ) { memset ( strings, 0, sizeof ( *strings ) ); strings->Header.Length = len; strings->Header.Type = EFI_HII_PACKAGE_STRINGS; strings->HdrSize = hdrsize; strings->StringInfoOffset = hdrsize; strings->LanguageName = EFI_SNP_LANGUAGE_NAME; memcpy ( strings->Language, language, sizeof ( language ) ); } return len; } /** * Generate EFI SNP package list * * @v snpdev SNP device * @ret package_list Package list, or NULL on error * * The package list is allocated using malloc(), and must eventually * be freed by the caller. */ static EFI_HII_PACKAGE_LIST_HEADER * efi_snp_package_list ( struct efi_snp_device *snpdev ) { size_t strings_len = efi_snp_strings ( NULL, 0, snpdev ); struct { EFI_HII_PACKAGE_LIST_HEADER header; struct efi_snp_formset formset; union { EFI_HII_STRING_PACKAGE_HDR strings; uint8_t pad[strings_len]; } __attribute__ (( packed )) strings; EFI_HII_PACKAGE_HEADER end; } __attribute__ (( packed )) *package_list; /* Allocate package list */ package_list = zalloc ( sizeof ( *package_list ) ); if ( ! package_list ) return NULL; /* Create a unique GUID for this package list and formset */ efi_snp_formset.FormSet.FormSet.Guid.Data1++; /* Populate package list */ memcpy ( &package_list->header.PackageListGuid, &efi_snp_formset.FormSet.FormSet.Guid, sizeof ( package_list->header.PackageListGuid ) ); package_list->header.PackageLength = sizeof ( *package_list ); memcpy ( &package_list->formset, &efi_snp_formset, sizeof ( package_list->formset ) ); efi_snp_strings ( &package_list->strings.strings, sizeof ( package_list->strings ), snpdev ); package_list->end.Length = sizeof ( package_list->end ); package_list->end.Type = EFI_HII_PACKAGE_END; return &package_list->header; } /** * Fetch configuration * * @v hii HII configuration access protocol * @v request Configuration to fetch * @ret progress Progress made through configuration to fetch * @ret results Query results * @ret efirc EFI status code */ static EFI_STATUS EFIAPI efi_snp_hii_extract_config ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii, EFI_STRING request, EFI_STRING *progress, EFI_STRING *results __unused ) { struct efi_snp_device *snpdev = container_of ( hii, struct efi_snp_device, hii ); DBGC ( snpdev, "SNPDEV %p ExtractConfig\n", snpdev ); *progress = request; return EFI_INVALID_PARAMETER; } /** * Store configuration * * @v hii HII configuration access protocol * @v config Configuration to store * @ret progress Progress made through configuration to store * @ret efirc EFI status code */ static EFI_STATUS EFIAPI efi_snp_hii_route_config ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii, EFI_STRING config, EFI_STRING *progress ) { struct efi_snp_device *snpdev = container_of ( hii, struct efi_snp_device, hii ); DBGC ( snpdev, "SNPDEV %p RouteConfig\n", snpdev ); *progress = config; return EFI_INVALID_PARAMETER; } /** * Handle form actions * * @v hii HII configuration access protocol * @v action Form browser action * @v question_id Question ID * @v type Type of value * @v value Value * @ret action_request Action requested by driver * @ret efirc EFI status code */ static EFI_STATUS EFIAPI efi_snp_hii_callback ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii, EFI_BROWSER_ACTION action __unused, EFI_QUESTION_ID question_id __unused, UINT8 type __unused, EFI_IFR_TYPE_VALUE *value __unused, EFI_BROWSER_ACTION_REQUEST *action_request __unused ) { struct efi_snp_device *snpdev = container_of ( hii, struct efi_snp_device, hii ); DBGC ( snpdev, "SNPDEV %p Callback\n", snpdev ); return EFI_UNSUPPORTED; } /** HII configuration access protocol */ static EFI_HII_CONFIG_ACCESS_PROTOCOL efi_snp_device_hii = { .ExtractConfig = efi_snp_hii_extract_config, .RouteConfig = efi_snp_hii_route_config, .Callback = efi_snp_hii_callback, }; /****************************************************************************** * * iPXE network driver * ****************************************************************************** */ /** * Locate SNP device corresponding to network device * * @v netdev Network device * @ret snp SNP device, or NULL if not found */ static struct efi_snp_device * efi_snp_demux ( struct net_device *netdev ) { struct efi_snp_device *snpdev; list_for_each_entry ( snpdev, &efi_snp_devices, list ) { if ( snpdev->netdev == netdev ) return snpdev; } return NULL; } /** * Create SNP device * * @v netdev Network device * @ret rc Return status code */ static int efi_snp_probe ( struct net_device *netdev ) { EFI_BOOT_SERVICES *bs = efi_systab->BootServices; struct efi_pci_device *efipci; struct efi_snp_device *snpdev; EFI_DEVICE_PATH_PROTOCOL *path_end; MAC_ADDR_DEVICE_PATH *macpath; size_t path_prefix_len = 0; EFI_STATUS efirc; int rc; /* Find EFI PCI device */ efipci = efipci_find ( netdev->dev ); if ( ! efipci ) { DBG ( "SNP skipping non-PCI device %s\n", netdev->name ); rc = 0; goto err_no_pci; } /* Calculate device path prefix length */ path_end = efi_devpath_end ( efipci->path ); path_prefix_len = ( ( ( void * ) path_end ) - ( ( void * ) efipci->path ) ); /* Allocate the SNP device */ snpdev = zalloc ( sizeof ( *snpdev ) + path_prefix_len + sizeof ( *macpath ) ); if ( ! snpdev ) { rc = -ENOMEM; goto err_alloc_snp; } snpdev->netdev = netdev_get ( netdev ); snpdev->efipci = efipci; /* Sanity check */ if ( netdev->ll_protocol->ll_addr_len > sizeof ( EFI_MAC_ADDRESS ) ) { DBGC ( snpdev, "SNPDEV %p cannot support link-layer address " "length %d for %s\n", snpdev, netdev->ll_protocol->ll_addr_len, netdev->name ); rc = -ENOTSUP; goto err_ll_addr_len; } /* Populate the SNP structure */ memcpy ( &snpdev->snp, &efi_snp_device_snp, sizeof ( snpdev->snp ) ); snpdev->snp.Mode = &snpdev->mode; if ( ( efirc = bs->CreateEvent ( EVT_NOTIFY_WAIT, TPL_NOTIFY, efi_snp_wait_for_packet, snpdev, &snpdev->snp.WaitForPacket ) ) != 0 ){ DBGC ( snpdev, "SNPDEV %p could not create event: %s\n", snpdev, efi_strerror ( efirc ) ); rc = EFIRC_TO_RC ( efirc ); goto err_create_event; } /* Populate the SNP mode structure */ snpdev->mode.State = EfiSimpleNetworkStopped; efi_snp_set_mode ( snpdev ); /* Populate the NII structure */ snpdev->nii.Revision = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION; strncpy ( snpdev->nii.StringId, "iPXE", sizeof ( snpdev->nii.StringId ) ); /* Populate the HII configuration access structure */ memcpy ( &snpdev->hii, &efi_snp_device_hii, sizeof ( snpdev->hii ) ); /* Populate the device name */ efi_snprintf ( snpdev->name, ( sizeof ( snpdev->name ) / sizeof ( snpdev->name[0] ) ), "%s", netdev->name ); /* Populate the device path */ memcpy ( &snpdev->path, efipci->path, path_prefix_len ); macpath = ( ( ( void * ) &snpdev->path ) + path_prefix_len ); path_end = ( ( void * ) ( macpath + 1 ) ); memset ( macpath, 0, sizeof ( *macpath ) ); macpath->Header.Type = MESSAGING_DEVICE_PATH; macpath->Header.SubType = MSG_MAC_ADDR_DP; macpath->Header.Length[0] = sizeof ( *macpath ); memcpy ( &macpath->MacAddress, netdev->ll_addr, sizeof ( macpath->MacAddress ) ); macpath->IfType = ntohs ( netdev->ll_protocol->ll_proto ); memset ( path_end, 0, sizeof ( *path_end ) ); path_end->Type = END_DEVICE_PATH_TYPE; path_end->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE; path_end->Length[0] = sizeof ( *path_end ); /* Install the SNP */ if ( ( efirc = bs->InstallMultipleProtocolInterfaces ( &snpdev->handle, &efi_simple_network_protocol_guid, &snpdev->snp, &efi_device_path_protocol_guid, &snpdev->path, &efi_nii_protocol_guid, &snpdev->nii, &efi_nii31_protocol_guid, &snpdev->nii, &efi_hii_config_access_protocol_guid, &snpdev->hii, NULL ) ) != 0 ) { DBGC ( snpdev, "SNPDEV %p could not install protocols: " "%s\n", snpdev, efi_strerror ( efirc ) ); rc = EFIRC_TO_RC ( efirc ); goto err_install_protocol_interface; } /* Add as child of PCI device */ if ( ( efirc = efipci_child_add ( efipci, snpdev->handle ) ) != 0 ) { DBGC ( snpdev, "SNPDEV %p could not become child of " PCI_FMT ": %s\n", snpdev, PCI_ARGS ( &efipci->pci ), efi_strerror ( efirc ) ); rc = EFIRC_TO_RC ( efirc ); goto err_efipci_child_add; } /* Create HII package list */ snpdev->package_list = efi_snp_package_list ( snpdev ); if ( ! snpdev->package_list ) { DBGC ( snpdev, "SNPDEV %p could not create HII package list\n", snpdev ); rc = -ENOMEM; goto err_create_hii; } /* Add HII packages */ if ( ( efirc = efihii->NewPackageList ( efihii, snpdev->package_list, snpdev->handle, &snpdev->hii_handle ) ) != 0 ) { DBGC ( snpdev, "SNPDEV %p could not add HII packages: %s\n", snpdev, efi_strerror ( efirc ) ); rc = EFIRC_TO_RC ( efirc ); goto err_register_hii; } /* Add to list of SNP devices */ list_add ( &snpdev->list, &efi_snp_devices ); DBGC ( snpdev, "SNPDEV %p installed for %s as device %p\n", snpdev, netdev->name, snpdev->handle ); return 0; efihii->RemovePackageList ( efihii, snpdev->hii_handle ); err_register_hii: free ( snpdev->package_list ); err_create_hii: efipci_child_del ( efipci, snpdev->handle ); err_efipci_child_add: bs->UninstallMultipleProtocolInterfaces ( snpdev->handle, &efi_simple_network_protocol_guid, &snpdev->snp, &efi_device_path_protocol_guid, &snpdev->path, &efi_nii_protocol_guid, &snpdev->nii, &efi_nii31_protocol_guid, &snpdev->nii, &efi_hii_config_access_protocol_guid, &snpdev->hii, NULL ); err_install_protocol_interface: bs->CloseEvent ( snpdev->snp.WaitForPacket ); err_create_event: err_ll_addr_len: netdev_put ( netdev ); free ( snpdev ); err_alloc_snp: err_no_pci: return rc; } /** * Handle SNP device or link state change * * @v netdev Network device */ static void efi_snp_notify ( struct net_device *netdev __unused ) { /* Nothing to do */ } /** * Destroy SNP device * * @v netdev Network device */ static void efi_snp_remove ( struct net_device *netdev ) { EFI_BOOT_SERVICES *bs = efi_systab->BootServices; struct efi_snp_device *snpdev; /* Locate SNP device */ snpdev = efi_snp_demux ( netdev ); if ( ! snpdev ) { DBG ( "SNP skipping non-SNP device %s\n", netdev->name ); return; } /* Uninstall the SNP */ efihii->RemovePackageList ( efihii, snpdev->hii_handle ); free ( snpdev->package_list ); efipci_child_del ( snpdev->efipci, snpdev->handle ); list_del ( &snpdev->list ); bs->UninstallMultipleProtocolInterfaces ( snpdev->handle, &efi_simple_network_protocol_guid, &snpdev->snp, &efi_device_path_protocol_guid, &snpdev->path, &efi_nii_protocol_guid, &snpdev->nii, &efi_nii31_protocol_guid, &snpdev->nii, &efi_hii_config_access_protocol_guid, &snpdev->hii, NULL ); bs->CloseEvent ( snpdev->snp.WaitForPacket ); netdev_put ( snpdev->netdev ); free ( snpdev ); } /** SNP driver */ struct net_driver efi_snp_driver __net_driver = { .name = "SNP", .probe = efi_snp_probe, .notify = efi_snp_notify, .remove = efi_snp_remove, }; ipxe-precise-1.0.0+git-2.55f6c88/src/interface/efi/efi_io.c0000664000175000017500000001340311701704160021716 0ustar sergeserge/* * Copyright (C) 2008 Michael Brown . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include #include #include /** @file * * iPXE I/O API for EFI * */ /** CPU I/O protocol */ static EFI_CPU_IO_PROTOCOL *cpu_io; EFI_REQUIRE_PROTOCOL ( EFI_CPU_IO_PROTOCOL, &cpu_io ); /** Maximum address that can be used for port I/O */ #define MAX_PORT_ADDRESS 0xffff /** * Determine whether or not address is a port I/O address * * @v io_addr I/O address * @v is_port I/O address is a port I/O address */ #define IS_PORT_ADDRESS(io_addr) \ ( ( ( intptr_t ) (io_addr) ) <= MAX_PORT_ADDRESS ) /** * Determine EFI CPU I/O width code * * @v size Size of value * @ret width EFI width code * * Someone at Intel clearly gets paid by the number of lines of code * they write. No-one should ever be able to make I/O this * convoluted. The EFI_CPU_IO_PROTOCOL_WIDTH enum is my favourite * idiocy. */ static EFI_CPU_IO_PROTOCOL_WIDTH efi_width ( size_t size ) { switch ( size ) { case 1 : return EfiCpuIoWidthFifoUint8; case 2 : return EfiCpuIoWidthFifoUint16; case 4 : return EfiCpuIoWidthFifoUint32; case 8 : return EfiCpuIoWidthFifoUint64; default : assert ( 0 ); /* I wonder what this will actually do... */ return EfiCpuIoWidthMaximum; } } /** * Read from device * * @v io_addr I/O address * @v size Size of value * @ret data Value read */ unsigned long long efi_ioread ( volatile void *io_addr, size_t size ) { EFI_CPU_IO_PROTOCOL_IO_MEM read; unsigned long long data = 0; EFI_STATUS efirc; read = ( IS_PORT_ADDRESS ( io_addr ) ? cpu_io->Io.Read : cpu_io->Mem.Read ); if ( ( efirc = read ( cpu_io, efi_width ( size ), ( intptr_t ) io_addr, 1, ( void * ) &data ) ) != 0 ) { DBG ( "EFI I/O read at %p failed: %s\n", io_addr, efi_strerror ( efirc ) ); return -1ULL; } return data; } /** * Write to device * * @v data Value to write * @v io_addr I/O address * @v size Size of value */ void efi_iowrite ( unsigned long long data, volatile void *io_addr, size_t size ) { EFI_CPU_IO_PROTOCOL_IO_MEM write; EFI_STATUS efirc; write = ( IS_PORT_ADDRESS ( io_addr ) ? cpu_io->Io.Write : cpu_io->Mem.Write ); if ( ( efirc = write ( cpu_io, efi_width ( size ), ( intptr_t ) io_addr, 1, ( void * ) &data ) ) != 0 ) { DBG ( "EFI I/O write at %p failed: %s\n", io_addr, efi_strerror ( efirc ) ); } } /** * String read from device * * @v io_addr I/O address * @v data Data buffer * @v size Size of values * @v count Number of values to read */ void efi_ioreads ( volatile void *io_addr, void *data, size_t size, unsigned int count ) { EFI_CPU_IO_PROTOCOL_IO_MEM read; EFI_STATUS efirc; read = ( IS_PORT_ADDRESS ( io_addr ) ? cpu_io->Io.Read : cpu_io->Mem.Read ); if ( ( efirc = read ( cpu_io, efi_width ( size ), ( intptr_t ) io_addr, count, ( void * ) data ) ) != 0 ) { DBG ( "EFI I/O string read at %p failed: %s\n", io_addr, efi_strerror ( efirc ) ); } } /** * String write to device * * @v io_addr I/O address * @v data Data buffer * @v size Size of values * @v count Number of values to write */ void efi_iowrites ( volatile void *io_addr, const void *data, size_t size, unsigned int count ) { EFI_CPU_IO_PROTOCOL_IO_MEM write; EFI_STATUS efirc; write = ( IS_PORT_ADDRESS ( io_addr ) ? cpu_io->Io.Write : cpu_io->Mem.Write ); if ( ( efirc = write ( cpu_io, efi_width ( size ), ( intptr_t ) io_addr, count, ( void * ) data ) ) != 0 ) { DBG ( "EFI I/O write at %p failed: %s\n", io_addr, efi_strerror ( efirc ) ); } } /** * Wait for I/O-mapped operation to complete * */ static void efi_iodelay ( void ) { /* Write to non-existent port. Probably x86-only. */ outb ( 0, 0x80 ); } /** * Get memory map * * Can't be done on EFI so return an empty map * * @v memmap Memory map to fill in */ static void efi_get_memmap ( struct memory_map *memmap ) { memmap->count = 0; } PROVIDE_IOAPI_INLINE ( efi, phys_to_bus ); PROVIDE_IOAPI_INLINE ( efi, bus_to_phys ); PROVIDE_IOAPI_INLINE ( efi, ioremap ); PROVIDE_IOAPI_INLINE ( efi, iounmap ); PROVIDE_IOAPI_INLINE ( efi, io_to_bus ); PROVIDE_IOAPI_INLINE ( efi, readb ); PROVIDE_IOAPI_INLINE ( efi, readw ); PROVIDE_IOAPI_INLINE ( efi, readl ); PROVIDE_IOAPI_INLINE ( efi, readq ); PROVIDE_IOAPI_INLINE ( efi, writeb ); PROVIDE_IOAPI_INLINE ( efi, writew ); PROVIDE_IOAPI_INLINE ( efi, writel ); PROVIDE_IOAPI_INLINE ( efi, writeq ); PROVIDE_IOAPI_INLINE ( efi, inb ); PROVIDE_IOAPI_INLINE ( efi, inw ); PROVIDE_IOAPI_INLINE ( efi, inl ); PROVIDE_IOAPI_INLINE ( efi, outb ); PROVIDE_IOAPI_INLINE ( efi, outw ); PROVIDE_IOAPI_INLINE ( efi, outl ); PROVIDE_IOAPI_INLINE ( efi, insb ); PROVIDE_IOAPI_INLINE ( efi, insw ); PROVIDE_IOAPI_INLINE ( efi, insl ); PROVIDE_IOAPI_INLINE ( efi, outsb ); PROVIDE_IOAPI_INLINE ( efi, outsw ); PROVIDE_IOAPI_INLINE ( efi, outsl ); PROVIDE_IOAPI ( efi, iodelay, efi_iodelay ); PROVIDE_IOAPI_INLINE ( efi, mb ); PROVIDE_IOAPI ( efi, get_memmap, efi_get_memmap ); ipxe-precise-1.0.0+git-2.55f6c88/src/interface/efi/efi_timer.c0000664000175000017500000000635311701704160022435 0ustar sergeserge/* * Copyright (C) 2008 Michael Brown . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include #include #include #include /** @file * * iPXE timer API for EFI * */ /** Scale factor to apply to CPU timer 0 * * The timer is scaled down in order to ensure that reasonable values * for "number of ticks" don't exceed the size of an unsigned long. */ #define EFI_TIMER0_SHIFT 12 /** Calibration time */ #define EFI_CALIBRATE_DELAY_MS 1 /** CPU protocol */ static EFI_CPU_ARCH_PROTOCOL *cpu_arch; EFI_REQUIRE_PROTOCOL ( EFI_CPU_ARCH_PROTOCOL, &cpu_arch ); /** * Delay for a fixed number of microseconds * * @v usecs Number of microseconds for which to delay */ static void efi_udelay ( unsigned long usecs ) { EFI_BOOT_SERVICES *bs = efi_systab->BootServices; EFI_STATUS efirc; if ( ( efirc = bs->Stall ( usecs ) ) != 0 ) { DBG ( "EFI could not delay for %ldus: %s\n", usecs, efi_strerror ( efirc ) ); /* Probably screwed */ } } /** * Get current system time in ticks * * @ret ticks Current time, in ticks */ static unsigned long efi_currticks ( void ) { UINT64 time; EFI_STATUS efirc; /* Read CPU timer 0 (TSC) */ if ( ( efirc = cpu_arch->GetTimerValue ( cpu_arch, 0, &time, NULL ) ) != 0 ) { DBG ( "EFI could not read CPU timer: %s\n", efi_strerror ( efirc ) ); /* Probably screwed */ return -1UL; } return ( time >> EFI_TIMER0_SHIFT ); } /** * Get number of ticks per second * * @ret ticks_per_sec Number of ticks per second */ static unsigned long efi_ticks_per_sec ( void ) { static unsigned long ticks_per_sec = 0; /* Calibrate timer, if necessary. EFI does nominally provide * the timer speed via the (optional) TimerPeriod parameter to * the GetTimerValue() call, but it gets the speed slightly * wrong. By up to three orders of magnitude. Not helpful. */ if ( ! ticks_per_sec ) { unsigned long start; unsigned long elapsed; DBG ( "Calibrating EFI timer with a %d ms delay\n", EFI_CALIBRATE_DELAY_MS ); start = currticks(); mdelay ( EFI_CALIBRATE_DELAY_MS ); elapsed = ( currticks() - start ); ticks_per_sec = ( elapsed * ( 1000 / EFI_CALIBRATE_DELAY_MS )); DBG ( "EFI CPU timer calibrated at %ld ticks in %d ms (%ld " "ticks/sec)\n", elapsed, EFI_CALIBRATE_DELAY_MS, ticks_per_sec ); } return ticks_per_sec; } PROVIDE_TIMER ( efi, udelay, efi_udelay ); PROVIDE_TIMER ( efi, currticks, efi_currticks ); PROVIDE_TIMER ( efi, ticks_per_sec, efi_ticks_per_sec ); ipxe-precise-1.0.0+git-2.55f6c88/src/interface/efi/efi_bofm.c0000664000175000017500000002643611701704160022244 0ustar sergeserge/* * Copyright (C) 2011 Michael Brown . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include #include #include #include /** @file * * IBM BladeCenter Open Fabric Manager (BOFM) EFI interface * */ /*************************************************************************** * * EFI BOFM definitions * *************************************************************************** * * Taken from the BOFM UEFI Vendor Specification document * */ #define IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL_GUID \ { 0x03207ce2, 0xd9c7, 0x11dc, \ { 0xa9, 0x4d, 0x00, 0x19, 0x7d, 0x89, 0x02, 0x38 } } #define IBM_BOFM_DRIVER_CONFIGURATION2_PROTOCOL_GUID \ { 0xe82a9763, 0x0584, 0x4e41, \ { 0xbb, 0x39, 0xe0, 0xcd, 0xb8, 0xc1, 0xf0, 0xfc } } typedef struct { UINT8 Id; UINT8 ResultByte; } __attribute__ (( packed )) BOFM_EPID_Results_t; typedef struct { UINT8 Version; UINT8 Level; UINT16 Length; UINT8 Checksum; UINT8 Profile[32]; UINT8 GlobalOption0; UINT8 GlobalOption1; UINT8 GlobalOption2; UINT8 GlobalOption3; UINT32 SequenceStamp; UINT8 Regions[911]; // For use by BOFM Driver UINT32 Reserved1; } __attribute__ (( packed )) BOFM_Parameters_t; typedef struct { UINT32 Reserved1; UINT8 Version; UINT8 Level; UINT8 Checksum; UINT32 SequenceStamp; UINT8 SUIDResults; UINT8 EntryResults[32]; UINT8 Reserved2; UINT8 Reserved3; UINT8 FCTgtResults[2]; UINT8 SASTgtResults[2]; BOFM_EPID_Results_t EPIDResults[2]; UINT8 Results4[10]; } __attribute__ (( packed )) BOFM_Results_t; typedef struct { UINT32 Signature; UINT32 SubSignature; BOFM_Parameters_t Parameters; BOFM_Results_t Results; } __attribute__ (( packed )) BOFM_DataStructure_t; #define IBM_BOFM_TABLE BOFM_DataStructure_t typedef struct _IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL; typedef struct _IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL2 IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL2; typedef EFI_STATUS ( EFIAPI *IBM_BOFM_DRIVER_CONFIGURATION_SUPPORT ) ( IN IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL *This, EFI_HANDLE ControllerHandle, UINT8 SupporttedOptions, UINT8 iSCSI_Parameter_Version, UINT8 BOFM_Parameter_Version ); typedef EFI_STATUS ( EFIAPI *IBM_BOFM_DRIVER_CONFIGURATION_STATUS ) ( IN IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL *This, EFI_HANDLE ControllerHandle, BOOLEAN ResetRequired, UINT8 BOFMReturnCode ); typedef EFI_STATUS ( EFIAPI *IBM_BOFM_DRIVER_CONFIGURATION_STATUS2 ) ( IN IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL2 *This, EFI_HANDLE ControllerHandle, BOOLEAN ResetRequired, UINT8 BOFMReturnCode ); struct _IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL { IBM_BOFM_TABLE BofmTable; IBM_BOFM_DRIVER_CONFIGURATION_STATUS SetStatus; IBM_BOFM_DRIVER_CONFIGURATION_SUPPORT RegisterSupport; }; struct _IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL2 { UINT32 Signature; UINT32 Reserved1; UINT64 Reserved2; IBM_BOFM_DRIVER_CONFIGURATION_STATUS2 SetStatus; IBM_BOFM_DRIVER_CONFIGURATION_SUPPORT RegisterSupport; IBM_BOFM_TABLE BofmTable; }; /*************************************************************************** * * EFI BOFM interface * *************************************************************************** */ /** BOFM1 protocol GUID */ static EFI_GUID bofm1_protocol_guid = IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL_GUID; /** BOFM2 protocol GUID */ static EFI_GUID bofm2_protocol_guid = IBM_BOFM_DRIVER_CONFIGURATION2_PROTOCOL_GUID; /** * Check if device is supported * * @v driver EFI driver * @v device EFI device * @v child Path to child device, if any * @ret efirc EFI status code */ static EFI_STATUS EFIAPI efi_bofm_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device, EFI_DEVICE_PATH_PROTOCOL *child ) { struct efi_driver *efidrv = container_of ( driver, struct efi_driver, driver ); EFI_BOOT_SERVICES *bs = efi_systab->BootServices; union { IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL *bofm1; void *interface; } bofm1; struct efi_pci_device *efipci; EFI_STATUS efirc; int rc; DBGCP ( efidrv, "EFIBOFM DRIVER_SUPPORTED %p (%p)\n", device, child ); /* Create corresponding PCI device, if any */ efipci = efipci_create ( efidrv, device ); if ( ! efipci ) { efirc = EFI_UNSUPPORTED; goto err_not_pci; } /* Look for a BOFM driver */ if ( ( rc = bofm_find_driver ( &efipci->pci ) ) != 0 ) { DBGCP ( efidrv, "EFIBOFM " PCI_FMT " has no driver\n", PCI_ARGS ( &efipci->pci ) ); efirc = EFI_UNSUPPORTED; goto err_no_driver; } /* Locate BOFM protocol */ if ( ( efirc = bs->LocateProtocol ( &bofm1_protocol_guid, NULL, &bofm1.interface ) ) != 0 ) { DBGC ( efidrv, "EFIBOFM " PCI_FMT " cannot find BOFM " "protocol\n", PCI_ARGS ( &efipci->pci ) ); efirc = EFI_UNSUPPORTED; goto err_not_bofm; } /* Register support for this device */ if ( ( efirc = bofm1.bofm1->RegisterSupport ( bofm1.bofm1, device, 0x04 /* Can change MAC */, 0x00 /* No iSCSI */, 0x02 /* Version */ ))!=0){ DBGC ( efidrv, "EFIBOFM " PCI_FMT " could not register " "support: %s\n", PCI_ARGS ( &efipci->pci ), efi_strerror ( efirc ) ); goto err_cannot_register; } DBGC ( efidrv, "EFIBOFM " PCI_FMT " is supported by driver \"%s\"\n", PCI_ARGS ( &efipci->pci ), efipci->pci.id->name ); /* Destroy temporary PCI device */ efipci_destroy ( efidrv, efipci ); return 0; err_cannot_register: err_not_bofm: err_no_driver: efipci_destroy ( efidrv, efipci ); err_not_pci: return efirc; } /** * Attach driver to device * * @v driver EFI driver * @v device EFI device * @v child Path to child device, if any * @ret efirc EFI status code */ static EFI_STATUS EFIAPI efi_bofm_start ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device, EFI_DEVICE_PATH_PROTOCOL *child ) { struct efi_driver *efidrv = container_of ( driver, struct efi_driver, driver ); EFI_BOOT_SERVICES *bs = efi_systab->BootServices; union { IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL *bofm1; void *interface; } bofm1; union { IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL2 *bofm2; void *interface; } bofm2; struct efi_pci_device *efipci; IBM_BOFM_TABLE *bofmtab; IBM_BOFM_TABLE *bofmtab2; EFI_STATUS efirc; int bofmrc; DBGCP ( efidrv, "EFIBOFM DRIVER_START %p (%p)\n", device, child ); /* Create corresponding PCI device */ efipci = efipci_create ( efidrv, device ); if ( ! efipci ) { efirc = EFI_OUT_OF_RESOURCES; goto err_create; } /* Enable PCI device */ if ( ( efirc = efipci_enable ( efipci ) ) != 0 ) goto err_enable; /* Locate BOFM protocol */ if ( ( efirc = bs->LocateProtocol ( &bofm1_protocol_guid, NULL, &bofm1.interface ) ) != 0 ) { DBGC ( efidrv, "EFIBOFM " PCI_FMT " cannot find BOFM " "protocol\n", PCI_ARGS ( &efipci->pci ) ); goto err_locate_bofm; } bofmtab = &bofm1.bofm1->BofmTable; DBGC ( efidrv, "EFIBOFM " PCI_FMT " found version 1 BOFM table at " "%p+%04x\n", PCI_ARGS ( &efipci->pci ), bofmtab, bofmtab->Parameters.Length ); /* Locate BOFM2 protocol, if available */ if ( ( efirc = bs->LocateProtocol ( &bofm2_protocol_guid, NULL, &bofm2.interface ) ) == 0 ) { bofmtab2 = &bofm2.bofm2->BofmTable; DBGC ( efidrv, "EFIBOFM " PCI_FMT " found version 2 BOFM table " "at %p+%04x\n", PCI_ARGS ( &efipci->pci ), bofmtab2, bofmtab2->Parameters.Length ); assert ( bofm2.bofm2->RegisterSupport == bofm1.bofm1->RegisterSupport ); } else { DBGC ( efidrv, "EFIBOFM " PCI_FMT " cannot find BOFM2 " "protocol\n", PCI_ARGS ( &efipci->pci ) ); /* Not a fatal error; may be a BOFM1-only system */ bofmtab2 = NULL; } /* Process BOFM table */ DBGC2 ( efidrv, "EFIBOFM " PCI_FMT " version 1 before processing:\n", PCI_ARGS ( &efipci->pci ) ); DBGC2_HD ( efidrv, bofmtab, bofmtab->Parameters.Length ); if ( bofmtab2 ) { DBGC2 ( efidrv, "EFIBOFM " PCI_FMT " version 2 before " "processing:\n", PCI_ARGS ( &efipci->pci ) ); DBGC2_HD ( efidrv, bofmtab2, bofmtab2->Parameters.Length ); } bofmrc = bofm ( virt_to_user ( bofmtab2 ? bofmtab2 : bofmtab ), &efipci->pci ); DBGC ( efidrv, "EFIBOFM " PCI_FMT " status %08x\n", PCI_ARGS ( &efipci->pci ), bofmrc ); DBGC2 ( efidrv, "EFIBOFM " PCI_FMT " version 1 after processing:\n", PCI_ARGS ( &efipci->pci ) ); DBGC2_HD ( efidrv, bofmtab, bofmtab->Parameters.Length ); if ( bofmtab2 ) { DBGC2 ( efidrv, "EFIBOFM " PCI_FMT " version 2 after " "processing:\n", PCI_ARGS ( &efipci->pci ) ); DBGC2_HD ( efidrv, bofmtab2, bofmtab2->Parameters.Length ); } /* Return BOFM status */ if ( bofmtab2 ) { if ( ( efirc = bofm2.bofm2->SetStatus ( bofm2.bofm2, device, FALSE, bofmrc ) ) != 0){ DBGC ( efidrv, "EFIBOFM " PCI_FMT " could not set " "BOFM2 status: %s\n", PCI_ARGS ( &efipci->pci ), efi_strerror ( efirc ) ); goto err_set_status; } } else { if ( ( efirc = bofm1.bofm1->SetStatus ( bofm1.bofm1, device, FALSE, bofmrc ) ) != 0){ DBGC ( efidrv, "EFIBOFM " PCI_FMT " could not set " "BOFM status: %s\n", PCI_ARGS ( &efipci->pci ), efi_strerror ( efirc ) ); goto err_set_status; } } /* Destroy the PCI device anyway; we have no further use for it */ efipci_destroy ( efidrv, efipci ); /* BOFM (ab)uses the "start" method to mean "process and exit" */ return EFI_NOT_READY; err_set_status: err_locate_bofm: err_enable: efipci_destroy ( efidrv, efipci ); err_create: return efirc; } /** * Detach driver from device * * @v driver EFI driver * @v device EFI device * @v num_children Number of child devices * @v children List of child devices * @ret efirc EFI status code */ static EFI_STATUS EFIAPI efi_bofm_stop ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device, UINTN num_children, EFI_HANDLE *children ) { struct efi_driver *efidrv = container_of ( driver, struct efi_driver, driver ); DBGCP ( efidrv, "EFIBOFM DRIVER_STOP %p (%ld %p)\n", device, ( ( unsigned long ) num_children ), children ); return 0; } /** EFI BOFM driver */ static struct efi_driver efi_bofm_driver = EFI_DRIVER_INIT ( "BOFM", efi_bofm_supported, efi_bofm_start, efi_bofm_stop ); /** * Install EFI BOFM driver * */ static void efi_bofm_driver_init ( void ) { struct efi_driver *efidrv = &efi_bofm_driver; EFI_STATUS efirc; /* Install driver */ if ( ( efirc = efi_driver_install ( efidrv ) ) != 0 ) { DBGC ( efidrv, "EFIBOFM could not install driver: %s\n", efi_strerror ( efirc ) ); return; } DBGC ( efidrv, "EFIBOFM driver installed\n" ); } /** EFI BOFM startup function */ struct startup_fn startup_bofm __startup_fn ( STARTUP_EARLY ) = { .startup = efi_bofm_driver_init, }; ipxe-precise-1.0.0+git-2.55f6c88/src/interface/efi/efi_umalloc.c0000664000175000017500000000615311701704160022747 0ustar sergeserge/* * Copyright (C) 2008 Michael Brown . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include /** @file * * iPXE user memory allocation API for EFI * */ /** Equivalent of NOWHERE for user pointers */ #define UNOWHERE ( ~UNULL ) /** * Reallocate external memory * * @v old_ptr Memory previously allocated by umalloc(), or UNULL * @v new_size Requested size * @ret new_ptr Allocated memory, or UNULL * * Calling realloc() with a new size of zero is a valid way to free a * memory block. */ static userptr_t efi_urealloc ( userptr_t old_ptr, size_t new_size ) { EFI_BOOT_SERVICES *bs = efi_systab->BootServices; EFI_PHYSICAL_ADDRESS phys_addr; unsigned int new_pages, old_pages; userptr_t new_ptr = UNOWHERE; size_t old_size; EFI_STATUS efirc; /* Allocate new memory if necessary. If allocation fails, * return without touching the old block. */ if ( new_size ) { new_pages = ( EFI_SIZE_TO_PAGES ( new_size ) + 1 ); if ( ( efirc = bs->AllocatePages ( AllocateAnyPages, EfiBootServicesData, new_pages, &phys_addr ) ) != 0 ) { DBG ( "EFI could not allocate %d pages: %s\n", new_pages, efi_strerror ( efirc ) ); return UNULL; } assert ( phys_addr != 0 ); new_ptr = phys_to_user ( phys_addr + EFI_PAGE_SIZE ); copy_to_user ( new_ptr, -EFI_PAGE_SIZE, &new_size, sizeof ( new_size ) ); DBG ( "EFI allocated %d pages at %llx\n", new_pages, phys_addr ); } /* Copy across relevant part of the old data region (if any), * then free it. Note that at this point either (a) new_ptr * is valid, or (b) new_size is 0; either way, the memcpy() is * valid. */ if ( old_ptr && ( old_ptr != UNOWHERE ) ) { copy_from_user ( &old_size, old_ptr, -EFI_PAGE_SIZE, sizeof ( old_size ) ); memcpy_user ( new_ptr, 0, old_ptr, 0, ( (old_size < new_size) ? old_size : new_size )); old_pages = ( EFI_SIZE_TO_PAGES ( old_size ) + 1 ); phys_addr = user_to_phys ( old_ptr, -EFI_PAGE_SIZE ); if ( ( efirc = bs->FreePages ( phys_addr, old_pages ) ) != 0 ){ DBG ( "EFI could not free %d pages at %llx: %s\n", old_pages, phys_addr, efi_strerror ( efirc ) ); /* Not fatal; we have leaked memory but successfully * allocated (if asked to do so). */ } DBG ( "EFI freed %d pages at %llx\n", old_pages, phys_addr ); } return new_ptr; } PROVIDE_UMALLOC ( efi, urealloc, efi_urealloc ); ipxe-precise-1.0.0+git-2.55f6c88/src/interface/efi/efi_smbios.c0000664000175000017500000000346311701704160022610 0ustar sergeserge/* * Copyright (C) 2008 Michael Brown . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include #include /** @file * * iPXE SMBIOS API for EFI * */ /** SMBIOS configuration table */ static struct smbios_entry *smbios_entry; EFI_USE_TABLE ( SMBIOS_TABLE, &smbios_entry, 0 ); /** * Find SMBIOS * * @v smbios SMBIOS entry point descriptor structure to fill in * @ret rc Return status code */ static int efi_find_smbios ( struct smbios *smbios ) { if ( ! smbios_entry ) { DBG ( "No SMBIOS table provided\n" ); return -ENODEV; } if ( smbios_entry->signature != SMBIOS_SIGNATURE ) { DBG ( "Invalid SMBIOS signature\n" ); return -ENODEV; } smbios->address = phys_to_user ( smbios_entry->smbios_address ); smbios->len = smbios_entry->smbios_len; smbios->count = smbios_entry->smbios_count; DBG ( "Found SMBIOS v%d.%d entry point at %p (%x+%zx)\n", smbios_entry->major, smbios_entry->minor, smbios_entry, smbios_entry->smbios_address, smbios->len ); return 0; } PROVIDE_SMBIOS ( efi, find_smbios, efi_find_smbios ); ipxe-precise-1.0.0+git-2.55f6c88/src/interface/efi/efi_pci.c0000664000175000017500000003400311701704160022061 0ustar sergeserge/* * Copyright (C) 2008 Michael Brown . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include #include #include #include #include #include #include /** @file * * iPXE PCI I/O API for EFI * */ /****************************************************************************** * * iPXE PCI API * ****************************************************************************** */ /** PCI root bridge I/O protocol */ static EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *efipci; EFI_REQUIRE_PROTOCOL ( EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL, &efipci ); static unsigned long efipci_address ( struct pci_device *pci, unsigned long location ) { return EFI_PCI_ADDRESS ( PCI_BUS ( pci->busdevfn ), PCI_SLOT ( pci->busdevfn ), PCI_FUNC ( pci->busdevfn ), EFIPCI_OFFSET ( location ) ); } int efipci_read ( struct pci_device *pci, unsigned long location, void *value ) { EFI_STATUS efirc; if ( ( efirc = efipci->Pci.Read ( efipci, EFIPCI_WIDTH ( location ), efipci_address ( pci, location ), 1, value ) ) != 0 ) { DBG ( "EFIPCI config read from " PCI_FMT " offset %02lx " "failed: %s\n", PCI_ARGS ( pci ), EFIPCI_OFFSET ( location ), efi_strerror ( efirc ) ); return -EIO; } return 0; } int efipci_write ( struct pci_device *pci, unsigned long location, unsigned long value ) { EFI_STATUS efirc; if ( ( efirc = efipci->Pci.Write ( efipci, EFIPCI_WIDTH ( location ), efipci_address ( pci, location ), 1, &value ) ) != 0 ) { DBG ( "EFIPCI config write to " PCI_FMT " offset %02lx " "failed: %s\n", PCI_ARGS ( pci ), EFIPCI_OFFSET ( location ), efi_strerror ( efirc ) ); return -EIO; } return 0; } PROVIDE_PCIAPI_INLINE ( efi, pci_num_bus ); PROVIDE_PCIAPI_INLINE ( efi, pci_read_config_byte ); PROVIDE_PCIAPI_INLINE ( efi, pci_read_config_word ); PROVIDE_PCIAPI_INLINE ( efi, pci_read_config_dword ); PROVIDE_PCIAPI_INLINE ( efi, pci_write_config_byte ); PROVIDE_PCIAPI_INLINE ( efi, pci_write_config_word ); PROVIDE_PCIAPI_INLINE ( efi, pci_write_config_dword ); /****************************************************************************** * * EFI PCI device instantiation * ****************************************************************************** */ /** EFI PCI I/O protocol GUID */ static EFI_GUID efi_pci_io_protocol_guid = EFI_PCI_IO_PROTOCOL_GUID; /** EFI device path protocol GUID */ static EFI_GUID efi_device_path_protocol_guid = EFI_DEVICE_PATH_PROTOCOL_GUID; /** EFI PCI devices */ static LIST_HEAD ( efi_pci_devices ); /** * Create EFI PCI device * * @v efidrv EFI driver * @v device EFI device * @ret efipci EFI PCI device, or NULL */ struct efi_pci_device * efipci_create ( struct efi_driver *efidrv, EFI_HANDLE device ) { EFI_BOOT_SERVICES *bs = efi_systab->BootServices; struct efi_pci_device *efipci; union { EFI_PCI_IO_PROTOCOL *pci_io; void *interface; } pci_io; union { EFI_DEVICE_PATH_PROTOCOL *path; void *interface; } path; UINTN pci_segment, pci_bus, pci_dev, pci_fn; EFI_STATUS efirc; int rc; /* Allocate PCI device */ efipci = zalloc ( sizeof ( *efipci ) ); if ( ! efipci ) goto err_zalloc; efipci->device = device; efipci->efidrv = efidrv; /* See if device is a PCI device */ if ( ( efirc = bs->OpenProtocol ( device, &efi_pci_io_protocol_guid, &pci_io.interface, efidrv->driver.DriverBindingHandle, device, EFI_OPEN_PROTOCOL_BY_DRIVER )) !=0 ){ DBGCP ( efipci, "EFIPCI device %p is not a PCI device\n", device ); goto err_open_protocol; } efipci->pci_io = pci_io.pci_io; /* Get PCI bus:dev.fn address */ if ( ( efirc = pci_io.pci_io->GetLocation ( pci_io.pci_io, &pci_segment, &pci_bus, &pci_dev, &pci_fn ) ) != 0 ) { DBGC ( efipci, "EFIPCI device %p could not get PCI " "location: %s\n", device, efi_strerror ( efirc ) ); goto err_get_location; } DBGC2 ( efipci, "EFIPCI device %p is PCI %04lx:%02lx:%02lx.%lx\n", device, ( ( unsigned long ) pci_segment ), ( ( unsigned long ) pci_bus ), ( ( unsigned long ) pci_dev ), ( ( unsigned long ) pci_fn ) ); /* Populate PCI device */ pci_init ( &efipci->pci, PCI_BUSDEVFN ( pci_bus, pci_dev, pci_fn ) ); if ( ( rc = pci_read_config ( &efipci->pci ) ) != 0 ) { DBGC ( efipci, "EFIPCI " PCI_FMT " cannot read PCI " "configuration: %s\n", PCI_ARGS ( &efipci->pci ), strerror ( rc ) ); goto err_pci_read_config; } /* Retrieve device path */ if ( ( efirc = bs->OpenProtocol ( device, &efi_device_path_protocol_guid, &path.interface, efidrv->driver.DriverBindingHandle, device, EFI_OPEN_PROTOCOL_BY_DRIVER )) !=0 ){ DBGC ( efipci, "EFIPCI " PCI_FMT " has no device path\n", PCI_ARGS ( &efipci->pci ) ); goto err_no_device_path; } efipci->path = path.path; /* Add to list of PCI devices */ list_add ( &efipci->list, &efi_pci_devices ); return efipci; bs->CloseProtocol ( device, &efi_device_path_protocol_guid, efidrv->driver.DriverBindingHandle, device ); err_no_device_path: err_pci_read_config: err_get_location: bs->CloseProtocol ( device, &efi_pci_io_protocol_guid, efidrv->driver.DriverBindingHandle, device ); err_open_protocol: free ( efipci ); err_zalloc: return NULL; } /** * Enable EFI PCI device * * @v efipci EFI PCI device * @ret efirc EFI status code */ EFI_STATUS efipci_enable ( struct efi_pci_device *efipci ) { EFI_PCI_IO_PROTOCOL *pci_io = efipci->pci_io; EFI_STATUS efirc; /* Enable device */ if ( ( efirc = pci_io->Attributes ( pci_io, EfiPciIoAttributeOperationSet, EFI_PCI_DEVICE_ENABLE, NULL ) ) != 0 ) { DBGC ( efipci, "EFIPCI " PCI_FMT " could not be enabled: %s\n", PCI_ARGS ( &efipci->pci ), efi_strerror ( efirc ) ); return efirc; } return 0; } /** * Find EFI PCI device by EFI device * * @v device EFI device * @ret efipci EFI PCI device, or NULL */ struct efi_pci_device * efipci_find_efi ( EFI_HANDLE device ) { struct efi_pci_device *efipci; list_for_each_entry ( efipci, &efi_pci_devices, list ) { if ( efipci->device == device ) return efipci; } return NULL; } /** * Find EFI PCI device by iPXE device * * @v dev Device * @ret efipci EFI PCI device, or NULL */ struct efi_pci_device * efipci_find ( struct device *dev ) { struct efi_pci_device *efipci; list_for_each_entry ( efipci, &efi_pci_devices, list ) { if ( &efipci->pci.dev == dev ) return efipci; } return NULL; } /** * Add EFI device as child of EFI PCI device * * @v efipci EFI PCI device * @v device EFI child device * @ret efirc EFI status code */ EFI_STATUS efipci_child_add ( struct efi_pci_device *efipci, EFI_HANDLE device ) { EFI_BOOT_SERVICES *bs = efi_systab->BootServices; struct efi_driver *efidrv = efipci->efidrv; union { EFI_PCI_IO_PROTOCOL *pci_io; void *interface; } pci_io; EFI_STATUS efirc; /* Re-open the PCI_IO_PROTOCOL */ if ( ( efirc = bs->OpenProtocol ( efipci->device, &efi_pci_io_protocol_guid, &pci_io.interface, efidrv->driver.DriverBindingHandle, device, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ) ) != 0 ) { DBGC ( efipci, "EFIPCI " PCI_FMT " could not add child: %s\n", PCI_ARGS ( &efipci->pci ), efi_strerror ( efirc ) ); return efirc; } return 0; } /** * Remove EFI device as child of PCI device * * @v efipci EFI PCI device * @v device EFI child device * @ret efirc EFI status code */ void efipci_child_del ( struct efi_pci_device *efipci, EFI_HANDLE device ) { EFI_BOOT_SERVICES *bs = efi_systab->BootServices; struct efi_driver *efidrv = efipci->efidrv; bs->CloseProtocol ( efipci->device, &efi_pci_io_protocol_guid, efidrv->driver.DriverBindingHandle, device ); } /** * Destroy EFI PCI device * * @v efidrv EFI driver * @v efipci EFI PCI device */ void efipci_destroy ( struct efi_driver *efidrv, struct efi_pci_device *efipci ) { EFI_BOOT_SERVICES *bs = efi_systab->BootServices; list_del ( &efipci->list ); bs->CloseProtocol ( efipci->device, &efi_device_path_protocol_guid, efidrv->driver.DriverBindingHandle, efipci->device ); bs->CloseProtocol ( efipci->device, &efi_pci_io_protocol_guid, efidrv->driver.DriverBindingHandle, efipci->device ); free ( efipci ); } /****************************************************************************** * * EFI PCI driver * ****************************************************************************** */ /** * Check to see if driver supports a device * * @v driver EFI driver * @v device EFI device * @v child Path to child device, if any * @ret efirc EFI status code */ static EFI_STATUS EFIAPI efipci_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device, EFI_DEVICE_PATH_PROTOCOL *child ) { struct efi_driver *efidrv = container_of ( driver, struct efi_driver, driver ); struct efi_pci_device *efipci; EFI_STATUS efirc; int rc; DBGCP ( efidrv, "EFIPCI DRIVER_SUPPORTED %p (%p)\n", device, child ); /* Create temporary corresponding PCI device, if any */ efipci = efipci_create ( efidrv, device ); if ( ! efipci ) { /* Non-PCI devices are simply unsupported */ efirc = EFI_UNSUPPORTED; goto err_not_pci; } /* Look for a driver */ if ( ( rc = pci_find_driver ( &efipci->pci ) ) != 0 ) { DBGCP ( efipci, "EFIPCI " PCI_FMT " has no driver\n", PCI_ARGS ( &efipci->pci ) ); efirc = EFI_UNSUPPORTED; goto err_no_driver; } DBGC ( efipci, "EFIPCI " PCI_FMT " is supported by driver \"%s\"\n", PCI_ARGS ( &efipci->pci ), efipci->pci.id->name ); /* Destroy temporary PCI device */ efipci_destroy ( efidrv, efipci ); return 0; err_no_driver: efipci_destroy ( efidrv, efipci ); err_not_pci: return efirc; } /** * Attach driver to device * * @v driver EFI driver * @v device EFI device * @v child Path to child device, if any * @ret efirc EFI status code */ static EFI_STATUS EFIAPI efipci_start ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device, EFI_DEVICE_PATH_PROTOCOL *child ) { struct efi_driver *efidrv = container_of ( driver, struct efi_driver, driver ); struct efi_pci_device *efipci; EFI_STATUS efirc; int rc; DBGC ( efidrv, "EFIPCI DRIVER_START %p (%p)\n", device, child ); /* Create corresponding PCI device */ efipci = efipci_create ( efidrv, device ); if ( ! efipci ) { efirc = EFI_OUT_OF_RESOURCES; goto err_create; } /* Find driver */ if ( ( rc = pci_find_driver ( &efipci->pci ) ) != 0 ) { DBGC ( efipci, "EFIPCI " PCI_FMT " has no driver\n", PCI_ARGS ( &efipci->pci ) ); efirc = RC_TO_EFIRC ( rc ); goto err_find_driver; } /* Enable PCI device */ if ( ( efirc = efipci_enable ( efipci ) ) != 0 ) goto err_enable; /* Probe driver */ if ( ( rc = pci_probe ( &efipci->pci ) ) != 0 ) { DBGC ( efipci, "EFIPCI " PCI_FMT " could not probe driver " "\"%s\": %s\n", PCI_ARGS ( &efipci->pci ), efipci->pci.id->name, strerror ( rc ) ); efirc = RC_TO_EFIRC ( rc ); goto err_probe; } return 0; pci_remove ( &efipci->pci ); err_probe: err_enable: err_find_driver: efipci_destroy ( efidrv, efipci ); err_create: return efirc; } /** * Detach driver from device * * @v driver EFI driver * @v device EFI device * @v pci PCI device * @v num_children Number of child devices * @v children List of child devices * @ret efirc EFI status code */ static EFI_STATUS EFIAPI efipci_stop ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device, UINTN num_children, EFI_HANDLE *children ) { struct efi_driver *efidrv = container_of ( driver, struct efi_driver, driver ); struct efi_pci_device *efipci; DBGC ( efidrv, "EFIPCI DRIVER_STOP %p (%ld %p)\n", device, ( ( unsigned long ) num_children ), children ); /* Find PCI device */ efipci = efipci_find_efi ( device ); if ( ! efipci ) { DBGC ( efidrv, "EFIPCI device %p not started!\n", device ); return EFI_INVALID_PARAMETER; } /* Remove device */ pci_remove ( &efipci->pci ); /* Delete EFI PCI device */ efipci_destroy ( efidrv, efipci ); return 0; } /** EFI PCI driver */ static struct efi_driver efipci_driver = EFI_DRIVER_INIT ( "PCI", efipci_supported, efipci_start, efipci_stop ); /** * Install EFI PCI driver * */ static void efipci_driver_startup ( void ) { struct efi_driver *efidrv = &efipci_driver; EFI_STATUS efirc; /* Install driver */ if ( ( efirc = efi_driver_install ( efidrv ) ) != 0 ) { DBGC ( efidrv, "EFIPCI could not install driver: %s\n", efi_strerror ( efirc ) ); return; } DBGC ( efidrv, "EFIPCI driver installed\n" ); } /** * Shut down EFI PCI driver * * @v booting System is shutting down for OS boot */ static void efipci_driver_shutdown ( int booting __unused ) { struct efi_driver *efidrv = &efipci_driver; struct efi_pci_device *efipci; struct efi_pci_device *tmp; /* Shut down any remaining devices */ list_for_each_entry_safe ( efipci, tmp, &efi_pci_devices, list ) { DBGC ( efipci, "EFIPCI " PCI_FMT " still active at shutdown; " "forcing close\n", PCI_ARGS ( &efipci->pci ) ); pci_remove ( &efipci->pci ); efipci_destroy ( efidrv, efipci ); } } /** EFI PCI startup function */ struct startup_fn startup_pci __startup_fn ( STARTUP_NORMAL ) = { .startup = efipci_driver_startup, .shutdown = efipci_driver_shutdown, }; ipxe-precise-1.0.0+git-2.55f6c88/src/interface/efi/efi_strerror.c0000664000175000017500000000232611701704160023173 0ustar sergeserge/* * Copyright (C) 2008 Michael Brown . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include /** @file * * iPXE error message formatting for EFI * */ /** * Format EFI status code * * @v efirc EFI status code * @v efi_strerror EFI status code string */ const char * efi_strerror ( EFI_STATUS efirc ) { static char errbuf[32]; if ( ! efirc ) return "No error"; snprintf ( errbuf, sizeof ( errbuf ), "Error %lld", ( unsigned long long ) ( efirc ^ MAX_BIT ) ); return errbuf; } ipxe-precise-1.0.0+git-2.55f6c88/src/interface/efi/efi_driver.c0000664000175000017500000000763011701704160022607 0ustar sergeserge/* * Copyright (C) 2011 Michael Brown . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include #include #include #include #include #include /** @file * * EFI driver interface * */ /** EFI driver binding protocol GUID */ static EFI_GUID efi_driver_binding_protocol_guid = EFI_DRIVER_BINDING_PROTOCOL_GUID; /** EFI component name protocol GUID */ static EFI_GUID efi_component_name2_protocol_guid = EFI_COMPONENT_NAME2_PROTOCOL_GUID; /** * Find end of device path * * @v path Path to device * @ret path_end End of device path */ EFI_DEVICE_PATH_PROTOCOL * efi_devpath_end ( EFI_DEVICE_PATH_PROTOCOL *path ) { while ( path->Type != END_DEVICE_PATH_TYPE ) { path = ( ( ( void * ) path ) + /* There's this amazing new-fangled thing known as * a UINT16, but who wants to use one of those? */ ( ( path->Length[1] << 8 ) | path->Length[0] ) ); } return path; } /** * Look up driver name * * @v wtf Component name protocol * @v language Language to use * @v driver_name Driver name to fill in * @ret efirc EFI status code */ static EFI_STATUS EFIAPI efi_driver_get_driver_name ( EFI_COMPONENT_NAME2_PROTOCOL *wtf, CHAR8 *language __unused, CHAR16 **driver_name ) { struct efi_driver *efidrv = container_of ( wtf, struct efi_driver, wtf ); *driver_name = efidrv->wname; return 0; } /** * Look up controller name * * @v wtf Component name protocol * @v device Device * @v child Child device, or NULL * @v language Language to use * @v driver_name Device name to fill in * @ret efirc EFI status code */ static EFI_STATUS EFIAPI efi_driver_get_controller_name ( EFI_COMPONENT_NAME2_PROTOCOL *wtf __unused, EFI_HANDLE device __unused, EFI_HANDLE child __unused, CHAR8 *language __unused, CHAR16 **controller_name __unused ) { /* Just let EFI use the default Device Path Name */ return EFI_UNSUPPORTED; } /** * Install EFI driver * * @v efidrv EFI driver * @ret efirc EFI status code */ EFI_STATUS efi_driver_install ( struct efi_driver *efidrv ) { EFI_BOOT_SERVICES *bs = efi_systab->BootServices; EFI_DRIVER_BINDING_PROTOCOL *driver = &efidrv->driver; EFI_COMPONENT_NAME2_PROTOCOL *wtf = &efidrv->wtf; EFI_STATUS efirc; /* Configure driver binding protocol */ driver->ImageHandle = efi_image_handle; /* Configure component name protocol */ wtf->GetDriverName = efi_driver_get_driver_name; wtf->GetControllerName = efi_driver_get_controller_name; wtf->SupportedLanguages = "en"; /* Fill in driver name */ efi_snprintf ( efidrv->wname, ( sizeof ( efidrv->wname ) / sizeof ( efidrv->wname[0] ) ), PRODUCT_SHORT_NAME " - %s", efidrv->name ); /* Install driver */ if ( ( efirc = bs->InstallMultipleProtocolInterfaces ( &driver->DriverBindingHandle, &efi_driver_binding_protocol_guid, driver, &efi_component_name2_protocol_guid, wtf, NULL ) ) != 0 ) { DBGC ( efidrv, "EFIDRV %s could not install protocol: %s\n", efidrv->name, efi_strerror ( efirc ) ); return efirc; } DBGC ( efidrv, "EFIDRV %s installed\n", efidrv->name ); return 0; } ipxe-precise-1.0.0+git-2.55f6c88/src/interface/efi/efi_init.c0000664000175000017500000001144411701704160022255 0ustar sergeserge/* * Copyright (C) 2008 Michael Brown . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include #include #include /** Image handle passed to entry point */ EFI_HANDLE efi_image_handle; /** Loaded image protocol for this image */ EFI_LOADED_IMAGE_PROTOCOL *efi_loaded_image; /** System table passed to entry point */ EFI_SYSTEM_TABLE *efi_systab; /** EFI loaded image protocol GUID */ static EFI_GUID efi_loaded_image_protocol_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID; /** Event used to signal shutdown */ static EFI_EVENT efi_shutdown_event; /** * Shut down in preparation for booting an OS. * * This hook gets called at ExitBootServices time in order to make * sure that everything is properly shut down before the OS takes * over. */ static EFIAPI void efi_shutdown_hook ( EFI_EVENT event __unused, void *context __unused ) { shutdown_boot(); } /** * Look up EFI configuration table * * @v guid Configuration table GUID * @ret table Configuration table, or NULL */ static void * efi_find_table ( EFI_GUID *guid ) { unsigned int i; for ( i = 0 ; i < efi_systab->NumberOfTableEntries ; i++ ) { if ( memcmp ( &efi_systab->ConfigurationTable[i].VendorGuid, guid, sizeof ( *guid ) ) == 0 ) return efi_systab->ConfigurationTable[i].VendorTable; } return NULL; } /** * Initialise EFI environment * * @v image_handle Image handle * @v systab System table * @ret efirc EFI return status code */ EFI_STATUS efi_init ( EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *systab ) { EFI_BOOT_SERVICES *bs; struct efi_protocol *prot; struct efi_config_table *tab; EFI_STATUS efirc; void *loaded_image; /* Store image handle and system table pointer for future use */ efi_image_handle = image_handle; efi_systab = systab; /* Sanity checks */ if ( ! systab ) return EFI_NOT_AVAILABLE_YET; if ( ! systab->ConOut ) return EFI_NOT_AVAILABLE_YET; if ( ! systab->BootServices ) { DBGC ( systab, "EFI provided no BootServices entry point\n" ); return EFI_NOT_AVAILABLE_YET; } if ( ! systab->RuntimeServices ) { DBGC ( systab, "EFI provided no RuntimeServices entry " "point\n" ); return EFI_NOT_AVAILABLE_YET; } DBGC ( systab, "EFI handle %p systab %p\n", image_handle, systab ); bs = systab->BootServices; efirc = bs->OpenProtocol ( image_handle, &efi_loaded_image_protocol_guid, &loaded_image, image_handle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if ( efirc ) { DBGC ( systab, "Could not get loaded image protocol" ); return efirc; } efi_loaded_image = loaded_image; DBG ( "Image base address = %p\n", efi_loaded_image->ImageBase ); /* Look up used protocols */ for_each_table_entry ( prot, EFI_PROTOCOLS ) { if ( ( efirc = bs->LocateProtocol ( &prot->u.guid, NULL, prot->protocol ) ) == 0 ) { DBGC ( systab, "EFI protocol %s is at %p\n", uuid_ntoa ( &prot->u.uuid ), *(prot->protocol)); } else { DBGC ( systab, "EFI does not provide protocol %s\n", uuid_ntoa ( &prot->u.uuid ) ); /* All protocols are required */ return efirc; } } /* Look up used configuration tables */ for_each_table_entry ( tab, EFI_CONFIG_TABLES ) { if ( ( *(tab->table) = efi_find_table ( &tab->u.guid ) ) ) { DBGC ( systab, "EFI configuration table %s is at %p\n", uuid_ntoa ( &tab->u.uuid ), *(tab->table) ); } else { DBGC ( systab, "EFI does not provide configuration " "table %s\n", uuid_ntoa ( &tab->u.uuid ) ); if ( tab->required ) return EFI_NOT_AVAILABLE_YET; } } /* EFI is perfectly capable of gracefully shutting down any * loaded devices if it decides to fall back to a legacy boot. * For no particularly comprehensible reason, it doesn't * bother doing so when ExitBootServices() is called. */ if ( ( efirc = bs->CreateEvent ( EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK, efi_shutdown_hook, NULL, &efi_shutdown_event ) ) != 0 ) { DBGC ( systab, "EFI could not create ExitBootServices event: " "%s\n", efi_strerror ( efirc ) ); return efirc; } return 0; } ipxe-precise-1.0.0+git-2.55f6c88/src/interface/efi/efi_uaccess.c0000664000175000017500000000250411701704160022735 0ustar sergeserge/* * Copyright (C) 2008 Michael Brown . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include /** @file * * iPXE user access API for EFI * */ PROVIDE_UACCESS_INLINE ( efi, phys_to_user ); PROVIDE_UACCESS_INLINE ( efi, user_to_phys ); PROVIDE_UACCESS_INLINE ( efi, virt_to_user ); PROVIDE_UACCESS_INLINE ( efi, user_to_virt ); PROVIDE_UACCESS_INLINE ( efi, userptr_add ); PROVIDE_UACCESS_INLINE ( efi, memcpy_user ); PROVIDE_UACCESS_INLINE ( efi, memmove_user ); PROVIDE_UACCESS_INLINE ( efi, memset_user ); PROVIDE_UACCESS_INLINE ( efi, strlen_user ); PROVIDE_UACCESS_INLINE ( efi, memchr_user ); ipxe-precise-1.0.0+git-2.55f6c88/src/hci/0000775000175000017500000000000011701704160016357 5ustar sergesergeipxe-precise-1.0.0+git-2.55f6c88/src/hci/wireless_errors.c0000664000175000017500000001234211701704160021756 0ustar sergeserge/* * Copyright (C) 2009 Joshua Oreman . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include /* Record errors as though they come from the 802.11 stack */ #undef ERRFILE #define ERRFILE ERRFILE_net80211 /** All 802.11 errors */ struct errortab wireless_errors[] __errortab = { __einfo_errortab ( EINFO_EINVAL_PKT_TOO_SHORT ), __einfo_errortab ( EINFO_EINVAL_PKT_VERSION ), __einfo_errortab ( EINFO_EINVAL_PKT_NOT_DATA ), __einfo_errortab ( EINFO_EINVAL_PKT_NOT_FROMDS ), __einfo_errortab ( EINFO_EINVAL_PKT_LLC_HEADER ), __einfo_errortab ( EINFO_EINVAL_CRYPTO_REQUEST ), __einfo_errortab ( EINFO_EINVAL_ACTIVE_SCAN ), __einfo_errortab ( EINFO_ECONNREFUSED_FAILURE ), __einfo_errortab ( EINFO_ECONNREFUSED_CAPAB_UNSUPP ), __einfo_errortab ( EINFO_ECONNREFUSED_REASSOC_INVALID ), __einfo_errortab ( EINFO_ECONNREFUSED_ASSOC_DENIED ), __einfo_errortab ( EINFO_ECONNREFUSED_AUTH_ALGO_UNSUPP ), __einfo_errortab ( EINFO_ECONNREFUSED_AUTH_SEQ_INVALID ), __einfo_errortab ( EINFO_ECONNREFUSED_AUTH_CHALL_INVALID ), __einfo_errortab ( EINFO_ECONNREFUSED_AUTH_TIMEOUT ), __einfo_errortab ( EINFO_ECONNREFUSED_ASSOC_NO_ROOM ), __einfo_errortab ( EINFO_ECONNREFUSED_ASSOC_NEED_RATE ), __einfo_errortab ( EINFO_ECONNREFUSED_ASSOC_NEED_SHORT_PMBL ), __einfo_errortab ( EINFO_ECONNREFUSED_ASSOC_NEED_PBCC ), __einfo_errortab ( EINFO_ECONNREFUSED_ASSOC_NEED_CHAN_AGILITY ), __einfo_errortab ( EINFO_ECONNREFUSED_ASSOC_NEED_SPECTRUM_MGMT ), __einfo_errortab ( EINFO_ECONNREFUSED_ASSOC_BAD_POWER ), __einfo_errortab ( EINFO_ECONNREFUSED_ASSOC_BAD_CHANNELS ), __einfo_errortab ( EINFO_ECONNREFUSED_ASSOC_NEED_SHORT_SLOT ), __einfo_errortab ( EINFO_ECONNREFUSED_ASSOC_NEED_DSSS_OFDM ), __einfo_errortab ( EINFO_EHOSTUNREACH_QOS_FAILURE ), __einfo_errortab ( EINFO_EHOSTUNREACH_QOS_NO_ROOM ), __einfo_errortab ( EINFO_EHOSTUNREACH_LINK_IS_HORRIBLE ), __einfo_errortab ( EINFO_EHOSTUNREACH_ASSOC_NEED_QOS ), __einfo_errortab ( EINFO_EHOSTUNREACH_REQUEST_DECLINED ), __einfo_errortab ( EINFO_EHOSTUNREACH_REQUEST_INVALID ), __einfo_errortab ( EINFO_EHOSTUNREACH_TS_NOT_CREATED_AGAIN ), __einfo_errortab ( EINFO_EHOSTUNREACH_INVALID_IE ), __einfo_errortab ( EINFO_EHOSTUNREACH_GROUP_CIPHER_INVALID ), __einfo_errortab ( EINFO_EHOSTUNREACH_PAIR_CIPHER_INVALID ), __einfo_errortab ( EINFO_EHOSTUNREACH_AKMP_INVALID ), __einfo_errortab ( EINFO_EHOSTUNREACH_RSN_VERSION_UNSUPP ), __einfo_errortab ( EINFO_EHOSTUNREACH_RSN_CAPAB_INVALID ), __einfo_errortab ( EINFO_EHOSTUNREACH_CIPHER_REJECTED ), __einfo_errortab ( EINFO_EHOSTUNREACH_TS_NOT_CREATED_WAIT ), __einfo_errortab ( EINFO_EHOSTUNREACH_DIRECT_LINK_FORBIDDEN ), __einfo_errortab ( EINFO_EHOSTUNREACH_DEST_NOT_PRESENT ), __einfo_errortab ( EINFO_EHOSTUNREACH_DEST_NOT_QOS ), __einfo_errortab ( EINFO_EHOSTUNREACH_ASSOC_LISTEN_TOO_HIGH ), __einfo_errortab ( EINFO_ECONNRESET_UNSPECIFIED ), __einfo_errortab ( EINFO_ECONNRESET_AUTH_NO_LONGER_VALID ), __einfo_errortab ( EINFO_ECONNRESET_LEAVING ), __einfo_errortab ( EINFO_ECONNRESET_INACTIVITY ), __einfo_errortab ( EINFO_ECONNRESET_OUT_OF_RESOURCES ), __einfo_errortab ( EINFO_ECONNRESET_NEED_AUTH ), __einfo_errortab ( EINFO_ECONNRESET_NEED_ASSOC ), __einfo_errortab ( EINFO_ECONNRESET_LEAVING_TO_ROAM ), __einfo_errortab ( EINFO_ECONNRESET_REASSOC_INVALID ), __einfo_errortab ( EINFO_ECONNRESET_BAD_POWER ), __einfo_errortab ( EINFO_ECONNRESET_BAD_CHANNELS ), __einfo_errortab ( EINFO_ECONNRESET_INVALID_IE ), __einfo_errortab ( EINFO_ECONNRESET_MIC_FAILURE ), __einfo_errortab ( EINFO_ECONNRESET_4WAY_TIMEOUT ), __einfo_errortab ( EINFO_ECONNRESET_GROUPKEY_TIMEOUT ), __einfo_errortab ( EINFO_ECONNRESET_4WAY_INVALID ), __einfo_errortab ( EINFO_ECONNRESET_GROUP_CIPHER_INVALID ), __einfo_errortab ( EINFO_ECONNRESET_PAIR_CIPHER_INVALID ), __einfo_errortab ( EINFO_ECONNRESET_AKMP_INVALID ), __einfo_errortab ( EINFO_ECONNRESET_RSN_VERSION_INVALID ), __einfo_errortab ( EINFO_ECONNRESET_RSN_CAPAB_INVALID ), __einfo_errortab ( EINFO_ECONNRESET_8021X_FAILURE ), __einfo_errortab ( EINFO_ECONNRESET_CIPHER_REJECTED ), __einfo_errortab ( EINFO_ENETRESET_QOS_UNSPECIFIED ), __einfo_errortab ( EINFO_ENETRESET_QOS_OUT_OF_RESOURCES ), __einfo_errortab ( EINFO_ENETRESET_LINK_IS_HORRIBLE ), __einfo_errortab ( EINFO_ENETRESET_INVALID_TXOP ), __einfo_errortab ( EINFO_ENETRESET_REQUESTED_LEAVING ), __einfo_errortab ( EINFO_ENETRESET_REQUESTED_NO_USE ), __einfo_errortab ( EINFO_ENETRESET_REQUESTED_NEED_SETUP ), __einfo_errortab ( EINFO_ENETRESET_REQUESTED_TIMEOUT ), __einfo_errortab ( EINFO_ENETRESET_CIPHER_UNSUPPORTED ), }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/strerror.c0000664000175000017500000000621411701704160020410 0ustar sergeserge#include #include #include #include /** @file * * Error descriptions. * * The error numbers used by Etherboot are a superset of those defined * by the PXE specification version 2.1. See errno.h for a listing of * the error values. * * To save space in ROM images, error string tables are optional. Use * the ERRORMSG_XXX options in config.h to select which error string * tables you want to include. If an error string table is omitted, * strerror() will simply return the text "Error 0x". * */ FILE_LICENCE ( GPL2_OR_LATER ); /** * Find error description * * @v errno Error number * @ret errortab Error description, or NULL */ static struct errortab * find_error ( int errno ) { struct errortab *errortab; for_each_table_entry ( errortab, ERRORTAB ) { if ( errortab->errno == errno ) return errortab; } return NULL; } /** * Find closest error description * * @v errno Error number * @ret errortab Error description, or NULL * * */ static struct errortab * find_closest_error ( int errno ) { struct errortab *errortab; /* First, look for an exact match */ if ( ( errortab = find_error ( errno ) ) != NULL ) return errortab; /* Second, try masking off the iPXE-specific bit and seeing if * we have an entry for the generic POSIX error message. */ if ( ( errortab = find_error ( errno & 0x7f0000ff ) ) != NULL ) return errortab; return NULL; } /** * Retrieve string representation of error number. * * @v errno/rc Error number or return status code * @ret strerror Pointer to error text * * If the error is not found in the linked-in error tables, generates * a generic "Error 0x" message. * * The pointer returned by strerror() is valid only until the next * call to strerror(). * */ const char * strerror ( int errno ) { static char errbuf[64]; struct errortab *errortab; /* Allow for strerror(rc) as well as strerror(errno) */ if ( errno < 0 ) errno = -errno; /* Find the error description, if one exists */ errortab = find_closest_error ( errno ); /* Construct the error message */ if ( errortab ) { snprintf ( errbuf, sizeof ( errbuf ), "%s (http://ipxe.org/%08x)", errortab->text, errno ); } else { snprintf ( errbuf, sizeof ( errbuf ), "Error %#08x (http://ipxe.org/%08x)", errno, errno ); } return errbuf; } /* Do not include ERRFILE portion in the numbers in the error table */ #undef ERRFILE #define ERRFILE 0 /** The most common errors */ struct errortab common_errors[] __errortab = { __einfo_errortab ( EINFO_ENOERR ), __einfo_errortab ( EINFO_EACCES ), __einfo_errortab ( EINFO_ECANCELED ), __einfo_errortab ( EINFO_ECONNRESET ), __einfo_errortab ( EINFO_EINVAL ), __einfo_errortab ( EINFO_EIO ), __einfo_errortab ( EINFO_ENETUNREACH ), __einfo_errortab ( EINFO_ENODEV ), __einfo_errortab ( EINFO_ENOENT ), __einfo_errortab ( EINFO_ENOEXEC ), __einfo_errortab ( EINFO_ENOMEM ), __einfo_errortab ( EINFO_ENOSPC ), __einfo_errortab ( EINFO_ENOTCONN ), __einfo_errortab ( EINFO_ENOTSUP ), __einfo_errortab ( EINFO_EPERM ), __einfo_errortab ( EINFO_ERANGE ), __einfo_errortab ( EINFO_ETIMEDOUT ), }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/linux_args.c0000664000175000017500000000771511701704160020710 0ustar sergeserge/* * Copyright (C) 2010 Piotr Jaroszyński * * 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ FILE_LICENCE(GPL2_OR_LATER); #include #include #include #include #include #include #include #include /** Saved argc */ static int saved_argc = 0; /** Saved argv */ static char ** saved_argv; /** * Save argc and argv for later access. * * To be called by linuxprefix */ __asmcall void save_args(int argc, char **argv) { saved_argc = argc; saved_argv = argv; } /** Supported command-line options */ static struct option options[] = { {"net", 1, 0, 'n'}, {"settings", 1, 0, 's'}, {0, 0, 0, 0} }; /** * Parse k1=v1[,k2=v2]* into linux_settings */ static int parse_kv(char *kv, struct list_head *list) { char *token; char *name; char *value; struct linux_setting *setting; while ((token = strsep(&kv, ",")) != NULL) { name = strsep(&token, "="); if (name == NULL) continue; value = token; if (value == NULL) { DBG("Bad parameter: '%s'\n", name); continue; } setting = malloc(sizeof(*setting)); if (! setting) return -1; setting->name = name; setting->value = value; setting->applied = 0; list_add(&setting->list, list); } return 0; } /** * Parse --net arguments * * Format is --net driver_name[,name=value]* */ static int parse_net_args(char *args) { char *driver; struct linux_device_request *dev_request; int rc; driver = strsep(&args, ","); if (strlen(driver) == 0) { printf("Missing driver name"); return -1; } dev_request = malloc(sizeof(*dev_request)); dev_request->driver = driver; INIT_LIST_HEAD(&dev_request->settings); list_add_tail(&dev_request->list, &linux_device_requests); /* Parse rest of the settings */ rc = parse_kv(args, &dev_request->settings); if (rc) printf("Parsing net settings failed"); return rc; } /** * Parse --settings arguments * * Format is --settings name=value[,name=value]* */ static int parse_settings_args(char *args) { return parse_kv(args, &linux_global_settings); } /** Parse passed command-line arguments */ void linux_args_parse() { int c; int rc; reset_getopt(); while (1) { int option_index = 0; c = getopt_long(saved_argc, saved_argv, "", options, &option_index); if (c == -1) break; switch (c) { case 'n': if ((rc = parse_net_args(optarg)) != 0) return; break; case 's': if ((rc = parse_settings_args(optarg)) != 0) return; break; default: return; } } return; } /** Clean up requests and settings */ void linux_args_cleanup(int flags __unused) { struct linux_device_request *request; struct linux_device_request *rtmp; struct linux_setting *setting; struct linux_setting *stmp; /* Clean up requests and their settings */ list_for_each_entry_safe(request, rtmp, &linux_device_requests, list) { list_for_each_entry_safe(setting, stmp, &request->settings, list) { list_del(&setting->list); free(setting); } list_del(&request->list); free(request); } /* Clean up global settings */ list_for_each_entry_safe(setting, stmp, &linux_global_settings, list) { list_del(&setting->list); free(setting); } } struct startup_fn startup_linux_args __startup_fn(STARTUP_EARLY) = { .startup = linux_args_parse, .shutdown = linux_args_cleanup, }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/commands/0000775000175000017500000000000011701704160020160 5ustar sergesergeipxe-precise-1.0.0+git-2.55f6c88/src/hci/commands/image_cmd.c0000664000175000017500000002205211701704160022232 0ustar sergeserge/* * Copyright (C) 2007 Michael Brown . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include #include #include #include #include #include #include /** @file * * Image management commands * */ /** "imgfetch" options */ struct imgfetch_options { /** Image name */ const char *name; }; /** "imgfetch" option list */ static struct option_descriptor imgfetch_opts[] = { OPTION_DESC ( "name", 'n', required_argument, struct imgfetch_options, name, parse_string ), }; /** "imgfetch" command descriptor */ static struct command_descriptor imgfetch_cmd = COMMAND_DESC ( struct imgfetch_options, imgfetch_opts, 1, MAX_ARGUMENTS, "[--name ] [...]" ); /** * The "imgfetch" and friends command body * * @v argc Argument count * @v argv Argument list * @v cmd Command descriptor * @v action_name Action name (for error messages) * @v action Action to take upon a successful download * @ret rc Return status code */ static int imgfetch_core_exec ( int argc, char **argv, const char *action_name, int ( * action ) ( struct image *image ) ) { struct imgfetch_options opts; char *uri_string; char *cmdline = NULL; int rc; /* Parse options */ if ( ( rc = parse_options ( argc, argv, &imgfetch_cmd, &opts ) ) != 0 ) goto err_parse_options; /* Parse URI string */ uri_string = argv[optind]; /* Parse command line */ if ( argv[ optind + 1 ] != NULL ) { cmdline = concat_args ( &argv[ optind + 1 ] ); if ( ! cmdline ) { rc = -ENOMEM; goto err_cmdline; } } /* Fetch the image */ if ( ( rc = imgdownload_string ( uri_string, opts.name, cmdline, action ) ) != 0 ) { printf ( "Could not %s %s: %s\n", action_name, uri_string, strerror ( rc ) ); goto err_imgdownload; } /* Free command line */ free ( cmdline ); return 0; err_imgdownload: free ( cmdline ); err_cmdline: err_parse_options: return rc; } /** * The "imgfetch"/"module" command * * @v argc Argument count * @v argv Argument list * @ret rc Return status code */ static int imgfetch_exec ( int argc, char **argv ) { return imgfetch_core_exec ( argc, argv, "fetch", NULL ); } /** * The "kernel" command * * @v argc Argument count * @v argv Argument list * @ret rc Return status code */ static int kernel_exec ( int argc, char **argv ) { return imgfetch_core_exec ( argc, argv, "select", image_select ); } /** * The "chain" command * * @v argc Argument count * @v argv Argument list * @ret rc Return status code */ static int chain_exec ( int argc, char **argv) { return imgfetch_core_exec ( argc, argv, "boot", image_exec ); } /** "imgselect" options */ struct imgselect_options {}; /** "imgselect" option list */ static struct option_descriptor imgselect_opts[] = {}; /** "imgselect" command descriptor */ static struct command_descriptor imgselect_cmd = COMMAND_DESC ( struct imgselect_options, imgselect_opts, 1, 1, "" ); /** * The "imgselect" command * * @v argc Argument count * @v argv Argument list * @ret rc Return status code */ static int imgselect_exec ( int argc, char **argv ) { struct imgselect_options opts; struct image *image; int rc; /* Parse options */ if ( ( rc = parse_options ( argc, argv, &imgselect_cmd, &opts ) ) != 0 ) return rc; /* Parse image name */ if ( ( rc = parse_image ( argv[optind], &image ) ) != 0 ) return rc; /* Load image */ if ( ( rc = imgselect ( image ) ) != 0 ) { printf ( "Could not select %s: %s\n", image->name, strerror ( rc ) ); return rc; } return 0; } /** "imgargs" options */ struct imgargs_options {}; /** "imgargs" option list */ static struct option_descriptor imgargs_opts[] = {}; /** "imgargs" command descriptor */ static struct command_descriptor imgargs_cmd = COMMAND_DESC ( struct imgargs_options, imgargs_opts, 1, MAX_ARGUMENTS, " [...]" ); /** * The "imgargs" command body * * @v argc Argument count * @v argv Argument list * @ret rc Return status code */ static int imgargs_exec ( int argc, char **argv ) { struct imgargs_options opts; struct image *image; char *cmdline = NULL; int rc; /* Parse options */ if ( ( rc = parse_options ( argc, argv, &imgargs_cmd, &opts ) ) != 0 ) goto err_parse_options; /* Parse image name */ if ( ( rc = parse_image ( argv[optind], &image ) ) != 0 ) goto err_parse_image; /* Parse command line */ if ( argv[ optind + 1 ] != NULL ) { cmdline = concat_args ( &argv[ optind + 1 ] ); if ( ! cmdline ) { rc = -ENOMEM; goto err_cmdline; } } /* Set command line */ if ( ( rc = image_set_cmdline ( image, cmdline ) ) != 0 ) goto err_set_cmdline; /* Free command line */ free ( cmdline ); return 0; err_set_cmdline: free ( cmdline ); err_cmdline: err_parse_image: err_parse_options: return rc; } /** "imgexec" options */ struct imgexec_options {}; /** "imgexec" option list */ static struct option_descriptor imgexec_opts[] = {}; /** "imgexec" command descriptor */ static struct command_descriptor imgexec_cmd = COMMAND_DESC ( struct imgexec_options, imgexec_opts, 0, 1, "[]" ); /** * The "imgexec" command * * @v argc Argument count * @v argv Argument list * @ret rc Return status code */ static int imgexec_exec ( int argc, char **argv ) { struct imgexec_options opts; struct image *image; int rc; /* Parse options */ if ( ( rc = parse_options ( argc, argv, &imgexec_cmd, &opts ) ) != 0 ) return rc; /* Parse image name */ if ( optind < argc ) { if ( ( rc = parse_image ( argv[optind], &image ) ) != 0 ) return rc; } else { image = imgautoselect(); if ( ! image ) { rc = -ENOTTY; printf ( "No image selected: %s\n", strerror ( rc ) ); return rc; } } /* Execute image */ if ( ( rc = imgexec ( image ) ) != 0 ) { printf ( "Could not execute %s: %s\n", image->name, strerror ( rc ) ); return rc; } return 0; } /** "imgstat" options */ struct imgstat_options {}; /** "imgstat" option list */ static struct option_descriptor imgstat_opts[] = {}; /** "imgstat" command descriptor */ static struct command_descriptor imgstat_cmd = COMMAND_DESC ( struct imgstat_options, imgstat_opts, 0, 0, "" ); /** * The "imgstat" command * * @v argc Argument count * @v argv Argument list * @ret rc Return status code */ static int imgstat_exec ( int argc, char **argv ) { struct imgstat_options opts; struct image *image; int rc; /* Parse options */ if ( ( rc = parse_options ( argc, argv, &imgstat_cmd, &opts ) ) != 0 ) return rc; /* Show status of all images */ for_each_image ( image ) { imgstat ( image ); } return 0; } /** "imgfree" options */ struct imgfree_options {}; /** "imgfree" option list */ static struct option_descriptor imgfree_opts[] = {}; /** "imgfree" command descriptor */ static struct command_descriptor imgfree_cmd = COMMAND_DESC ( struct imgfree_options, imgfree_opts, 0, 1, "[]" ); /** * The "imgfree" command * * @v argc Argument count * @v argv Argument list * @ret rc Return status code */ static int imgfree_exec ( int argc, char **argv ) { struct imgfree_options opts; struct image *image; struct image *tmp; int rc; /* Parse options */ if ( ( rc = parse_options ( argc, argv, &imgfree_cmd, &opts ) ) != 0 ) return rc; if ( optind < argc ) { /* Free specified image */ if ( ( rc = parse_image ( argv[optind], &image ) ) != 0 ) return rc; imgfree ( image ); } else { /* Free all images */ list_for_each_entry_safe ( image, tmp, &images, list ) { imgfree ( image ); } } return 0; } /** Image management commands */ struct command image_commands[] __command = { { .name = "imgfetch", .exec = imgfetch_exec, }, { .name = "module", .exec = imgfetch_exec, /* synonym for "imgfetch" */ }, { .name = "initrd", .exec = imgfetch_exec, /* synonym for "imgfetch" */ }, { .name = "kernel", .exec = kernel_exec, }, { .name = "chain", .exec = chain_exec, }, { .name = "imgselect", .exec = imgselect_exec, }, { .name = "imgload", /* synonym for "imgselect" */ .exec = imgselect_exec, }, { .name = "imgargs", .exec = imgargs_exec, }, { .name = "imgexec", .exec = imgexec_exec, }, { .name = "boot", /* synonym for "imgexec" */ .exec = imgexec_exec, }, { .name = "imgstat", .exec = imgstat_exec, }, { .name = "imgfree", .exec = imgfree_exec, }, }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/commands/login_cmd.c0000664000175000017500000000337211701704160022264 0ustar sergeserge/* * Copyright (C) 2010 Michael Brown . * * 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 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. */ #include #include #include #include #include FILE_LICENCE ( GPL2_OR_LATER ); /** @file * * Login commands * */ /** "login" options */ struct login_options {}; /** "login" option list */ static struct option_descriptor login_opts[] = {}; /** "login" command descriptor */ static struct command_descriptor login_cmd = COMMAND_DESC ( struct login_options, login_opts, 0, 0, "" ); /** * "login" command * * @v argc Argument count * @v argv Argument list * @ret rc Return status code */ static int login_exec ( int argc, char **argv ) { struct login_options opts; int rc; /* Parse options */ if ( ( rc = parse_options ( argc, argv, &login_cmd, &opts ) ) != 0 ) return rc; /* Show login UI */ if ( ( rc = login_ui() ) != 0 ) { printf ( "Could not set credentials: %s\n", strerror ( rc ) ); return rc; } return 0; } /** Login commands */ struct command login_command __command = { .name = "login", .exec = login_exec, }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/commands/autoboot_cmd.c0000664000175000017500000000303211701704160023001 0ustar sergeserge/* * Copyright (C) 2010 Michael Brown . * * 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 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. */ #include #include #include #include #include #include #include FILE_LICENCE ( GPL2_OR_LATER ); /** @file * * Booting commands * */ /** "autoboot" command descriptor */ static struct command_descriptor autoboot_cmd = COMMAND_DESC ( struct ifcommon_options, ifcommon_opts, 0, MAX_ARGUMENTS, "[...]" ); /** * "autoboot" command * * @v argc Argument count * @v argv Argument list * @ret rc Return status code */ static int autoboot_exec ( int argc, char **argv ) { return ifcommon_exec ( argc, argv, &autoboot_cmd, netboot, 0 ); } /** Booting commands */ struct command autoboot_commands[] __command = { { .name = "autoboot", .exec = autoboot_exec, }, }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/commands/ifmgmt_cmd.c0000664000175000017500000001030311701704160022427 0ustar sergeserge/* * Copyright (C) 2007 Michael Brown . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include #include #include #include #include #include /** @file * * Network interface management commands * */ /** "if" command options */ struct option_descriptor ifcommon_opts[0]; /** * Execute if command * * @v argc Argument count * @v argv Argument list * @v cmd Command descriptor * @v payload Command to execute * @v verb Verb describing the action of the command * @ret rc Return status code */ int ifcommon_exec ( int argc, char **argv, struct command_descriptor *cmd, int ( * payload ) ( struct net_device * ), int stop_on_first_success ) { struct ifcommon_options opts; struct net_device *netdev; int rc; /* Parse options */ if ( ( rc = parse_options ( argc, argv, cmd, &opts ) ) != 0 ) return rc; if ( optind != argc ) { /* Treat arguments as a list of interfaces to try */ while ( optind != argc ) { if ( ( rc = parse_netdev ( argv[optind++], &netdev ) ) != 0 ) { continue; } if ( ( ( rc = payload ( netdev ) ) == 0 ) && stop_on_first_success ) { return 0; } } } else { /* Try all interfaces */ rc = -ENODEV; for_each_netdev ( netdev ) { if ( ( ( rc = payload ( netdev ) ) == 0 ) && stop_on_first_success ) { return 0; } } } return rc; } /** "ifopen" command descriptor */ static struct command_descriptor ifopen_cmd = COMMAND_DESC ( struct ifcommon_options, ifcommon_opts, 0, MAX_ARGUMENTS, "[...]" ); /** * "ifopen" payload * * @v netdev Network device * @ret rc Return status code */ static int ifopen_payload ( struct net_device *netdev ) { return ifopen ( netdev ); } /** * The "ifopen" command * * @v argc Argument count * @v argv Argument list * @ret rc Return status code */ static int ifopen_exec ( int argc, char **argv ) { return ifcommon_exec ( argc, argv, &ifopen_cmd, ifopen_payload, 0 ); } /** "ifclose" command descriptor */ static struct command_descriptor ifclose_cmd = COMMAND_DESC ( struct ifcommon_options, ifcommon_opts, 0, MAX_ARGUMENTS, "[...]" ); /** * "ifclose" payload * * @v netdev Network device * @ret rc Return status code */ static int ifclose_payload ( struct net_device *netdev ) { ifclose ( netdev ); return 0; } /** * The "ifclose" command * * @v argc Argument count * @v argv Argument list * @ret rc Return status code */ static int ifclose_exec ( int argc, char **argv ) { return ifcommon_exec ( argc, argv, &ifclose_cmd, ifclose_payload, 0 ); } /** "ifstat" command descriptor */ static struct command_descriptor ifstat_cmd = COMMAND_DESC ( struct ifcommon_options, ifcommon_opts, 0, MAX_ARGUMENTS, "[...]" ); /** * "ifstat" payload * * @v netdev Network device * @ret rc Return status code */ static int ifstat_payload ( struct net_device *netdev ) { ifstat ( netdev ); return 0; } /** * The "ifstat" command * * @v argc Argument count * @v argv Argument list * @ret rc Return status code */ static int ifstat_exec ( int argc, char **argv ) { return ifcommon_exec ( argc, argv, &ifstat_cmd, ifstat_payload, 0 ); } /** Interface management commands */ struct command ifmgmt_commands[] __command = { { .name = "ifopen", .exec = ifopen_exec, }, { .name = "ifclose", .exec = ifclose_exec, }, { .name = "ifstat", .exec = ifstat_exec, }, }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/commands/gdbstub_cmd.c0000664000175000017500000000500111701704160022575 0ustar sergeserge/* * Copyright (C) 2008 Stefan Hajnoczi . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include #include #include #include #include /** @file * * GDB stub command * */ /** * Parse GDB transport name * * @v text Text * @ret trans GDB transport * @ret rc Return status code */ static int parse_gdb_transport ( const char *text, struct gdb_transport **trans ) { /* Sanity check */ assert ( text != NULL ); /* Find transport */ *trans = find_gdb_transport ( text ); if ( ! *trans ) { printf ( "\"%s\": no such transport (is it compiled in?)\n", text ); return -ENOTSUP; } return 0; } /** "gdbstub" options */ struct gdbstub_options {}; /** "gdbstub" option list */ static struct option_descriptor gdbstub_opts[] = {}; /** "gdbstub" command descriptor */ static struct command_descriptor gdbstub_cmd = COMMAND_DESC ( struct gdbstub_options, gdbstub_opts, 1, MAX_ARGUMENTS, " [...]" ); /** * The "gdbstub" command * * @v argc Argument count * @v argv Argument list * @ret rc Return status code */ static int gdbstub_exec ( int argc, char **argv ) { struct gdbstub_options opts; struct gdb_transport *trans; int rc; /* Parse options */ if ( ( rc = parse_options ( argc, argv, &gdbstub_cmd, &opts ) ) != 0 ) return rc; /* Parse transport name */ if ( ( rc = parse_gdb_transport ( argv[optind++], &trans ) ) != 0 ) return rc; /* Initialise transport */ if ( trans->init ) { if ( ( rc = trans->init ( argc - optind, &argv[optind] ) ) != 0 ) { return rc; } } /* Enter GDB stub */ gdbstub_start ( trans ); return 0; } /** GDB stub commands */ struct command gdbstub_commands[] __command = { { .name = "gdbstub", .exec = gdbstub_exec, }, }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/commands/lotest_cmd.c0000664000175000017500000000473411701704160022471 0ustar sergeserge/* * Copyright (C) 2010 Michael Brown . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include #include #include #include #include #include #include /** @file * * Loopback testing commands * */ /** "lotest" options */ struct lotest_options { /** MTU */ unsigned int mtu; }; /** "lotest" option list */ static struct option_descriptor lotest_opts[] = { OPTION_DESC ( "mtu", 'm', required_argument, struct lotest_options, mtu, parse_integer ), }; /** "lotest" command descriptor */ static struct command_descriptor lotest_cmd = COMMAND_DESC ( struct lotest_options, lotest_opts, 2, 2, "[--mtu ] " "" ); /** * "lotest" command * * @v argc Argument count * @v argv Argument list * @ret rc Return status code */ static int lotest_exec ( int argc, char **argv ) { struct lotest_options opts; struct net_device *sender; struct net_device *receiver; int rc; /* Parse options */ if ( ( rc = parse_options ( argc, argv, &lotest_cmd, &opts ) ) != 0 ) return rc; /* Parse sending interface name */ if ( ( rc = parse_netdev ( argv[optind], &sender ) ) != 0 ) return rc; /* Parse receiving interface name */ if ( ( rc = parse_netdev ( argv[ optind + 1 ], &receiver ) ) != 0 ) return rc; /* Use default MTU if none specified */ if ( ! opts.mtu ) opts.mtu = ETH_MAX_MTU; /* Perform loopback test */ if ( ( rc = loopback_test ( sender, receiver, opts.mtu ) ) != 0 ) { printf ( "Test failed: %s\n", strerror ( rc ) ); return rc; } return 0; } /** Loopback testing commands */ struct command lotest_command __command = { .name = "lotest", .exec = lotest_exec, }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/commands/config_cmd.c0000664000175000017500000000467711701704160022432 0ustar sergeserge/* * Copyright (C) 2010 Michael Brown . * * 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 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. */ #include #include #include #include #include #include #include #include FILE_LICENCE ( GPL2_OR_LATER ); /** @file * * Configuration UI commands * */ /** "config" options */ struct config_options {}; /** "config" option list */ static struct option_descriptor config_opts[] = {}; /** "config" command descriptor */ static struct command_descriptor config_cmd = COMMAND_DESC ( struct config_options, config_opts, 0, 1, "[]" ); /** * Parse settings scope name * * @v text Text * @ret value Integer value * @ret rc Return status code */ static int parse_settings ( const char *text, struct settings **value ) { /* Sanity check */ assert ( text != NULL ); /* Parse scope name */ *value = find_settings ( text ); if ( ! *value ) { printf ( "\"%s\": no such scope\n", text ); return -EINVAL; } return 0; } /** * "config" command * * @v argc Argument count * @v argv Argument list * @ret rc Return status code */ static int config_exec ( int argc, char **argv ) { struct config_options opts; struct settings *settings; int rc; /* Parse options */ if ( ( rc = parse_options ( argc, argv, &config_cmd, &opts ) ) != 0 ) return rc; /* Parse settings option, if present */ if ( ( rc = parse_settings ( ( ( optind < argc ) ? argv[optind] : "" ), &settings ) ) != 0 ) return rc; /* Run settings UI */ if ( ( rc = settings_ui ( settings ) ) != 0 ) { printf ( "Could not save settings: %s\n", strerror ( rc ) ); return rc; } return 0; } /** Configuration UI commands */ struct command config_command __command = { .name = "config", .exec = config_exec, }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/commands/iwmgmt_cmd.c0000664000175000017500000000501111701704160022450 0ustar sergeserge/* * Copyright (C) 2009 Joshua Oreman . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include #include #include #include /** @file * * Wireless interface management commands * */ /** "iwstat" command descriptor */ static struct command_descriptor iwstat_cmd = COMMAND_DESC ( struct ifcommon_options, ifcommon_opts, 0, MAX_ARGUMENTS, "[...]" ); /** * "iwstat" payload * * @v netdev Network device * @ret rc Return status code */ static int iwstat_payload ( struct net_device *netdev ) { struct net80211_device *dev = net80211_get ( netdev ); if ( dev ) iwstat ( dev ); return 0; } /** * The "iwstat" command * * @v argc Argument count * @v argv Argument list * @ret rc Return status code */ static int iwstat_exec ( int argc, char **argv ) { return ifcommon_exec ( argc, argv, &iwstat_cmd, iwstat_payload, 0 ); } /** "iwlist" command descriptor */ static struct command_descriptor iwlist_cmd = COMMAND_DESC ( struct ifcommon_options, ifcommon_opts, 0, MAX_ARGUMENTS, "[...]" ); /** * "iwlist" payload * * @v netdev Network device * @ret rc Return status code */ static int iwlist_payload ( struct net_device *netdev ) { struct net80211_device *dev = net80211_get ( netdev ); if ( dev ) return iwlist ( dev ); return 0; } /** * The "iwlist" command * * @v argc Argument count * @v argv Argument list * @ret rc Return status code */ static int iwlist_exec ( int argc, char **argv ) { return ifcommon_exec ( argc, argv, &iwlist_cmd, iwlist_payload, 0 ); } /** Wireless interface management commands */ struct command iwmgmt_commands[] __command = { { .name = "iwstat", .exec = iwstat_exec, }, { .name = "iwlist", .exec = iwlist_exec, }, }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/commands/route_cmd.c0000664000175000017500000000325111701704160022306 0ustar sergeserge/* * Copyright (C) 2007 Michael Brown . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include #include #include /** @file * * Routing table management commands * */ /** "route" options */ struct route_options {}; /** "route" option list */ static struct option_descriptor route_opts[] = {}; /** "route" command descriptor */ static struct command_descriptor route_cmd = COMMAND_DESC ( struct route_options, route_opts, 0, 0, "" ); /** * The "route" command * * @v argc Argument count * @v argv Argument list * @ret rc Return status code */ static int route_exec ( int argc, char **argv ) { struct route_options opts; int rc; /* Parse options */ if ( ( rc = parse_options ( argc, argv, &route_cmd, &opts ) ) != 0 ) return rc; route(); return 0; } /** Routing table management commands */ struct command route_commands[] __command = { { .name = "route", .exec = route_exec, }, }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/commands/vlan_cmd.c0000664000175000017500000000656011701704160022116 0ustar sergeserge/* * Copyright (C) 2010 Michael Brown . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include #include #include #include #include #include /** @file * * VLAN commands * */ /** "vcreate" options */ struct vcreate_options { /** VLAN tag */ unsigned int tag; /** VLAN default priority */ unsigned int priority; }; /** "vcreate" option list */ static struct option_descriptor vcreate_opts[] = { OPTION_DESC ( "tag", 't', required_argument, struct vcreate_options, tag, parse_integer ), OPTION_DESC ( "priority", 'p', required_argument, struct vcreate_options, priority, parse_integer ), }; /** "vcreate" command descriptor */ static struct command_descriptor vcreate_cmd = COMMAND_DESC ( struct vcreate_options, vcreate_opts, 1, 1, "--tag [--priority ] " "" ); /** * "vcreate" command * * @v argc Argument count * @v argv Argument list * @ret rc Return status code */ static int vcreate_exec ( int argc, char **argv ) { struct vcreate_options opts; struct net_device *trunk; int rc; /* Parse options */ if ( ( rc = parse_options ( argc, argv, &vcreate_cmd, &opts ) ) != 0 ) return rc; /* Parse trunk interface */ if ( ( rc = parse_netdev ( argv[optind], &trunk ) ) != 0 ) return rc; /* Create VLAN device */ if ( ( rc = vlan_create ( trunk, opts.tag, opts.priority ) ) != 0 ) { printf ( "Could not create VLAN device: %s\n", strerror ( rc ) ); return rc; } return 0; } /** "vdestroy" options */ struct vdestroy_options {}; /** "vdestroy" option list */ static struct option_descriptor vdestroy_opts[] = {}; /** "vdestroy" command descriptor */ static struct command_descriptor vdestroy_cmd = COMMAND_DESC ( struct vdestroy_options, vdestroy_opts, 1, 1, "" ); /** * "vdestroy" command * * @v argc Argument count * @v argv Argument list * @ret rc Return status code */ static int vdestroy_exec ( int argc, char **argv ) { struct vdestroy_options opts; struct net_device *netdev; int rc; /* Parse options */ if ( ( rc = parse_options ( argc, argv, &vdestroy_cmd, &opts ) ) != 0 ) return rc; /* Parse trunk interface */ if ( ( rc = parse_netdev ( argv[optind], &netdev ) ) != 0 ) return rc; /* Destroy VLAN device */ if ( ( rc = vlan_destroy ( netdev ) ) != 0 ) { printf ( "Could not destroy VLAN device: %s\n", strerror ( rc ) ); return rc; } return 0; } /** VLAN commands */ struct command vlan_commands[] __command = { { .name = "vcreate", .exec = vcreate_exec, }, { .name = "vdestroy", .exec = vdestroy_exec, }, }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/commands/dhcp_cmd.c0000664000175000017500000000632411701704160022072 0ustar sergeserge/* * Copyright (C) 2007 Michael Brown . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /** @file * * DHCP management commands * */ /** "dhcp" command descriptor */ static struct command_descriptor dhcp_cmd = COMMAND_DESC ( struct ifcommon_options, ifcommon_opts, 0, MAX_ARGUMENTS, "[...]" ); /** * Execute "dhcp" command for a network device * * @v netdev Network device * @ret rc Return status code */ static int dhcp_payload ( struct net_device *netdev ) { int rc; if ( ( rc = dhcp ( netdev ) ) != 0 ) { printf ( "Could not configure %s: %s\n", netdev->name, strerror ( rc ) ); /* Close device on failure, to avoid memory exhaustion */ netdev_close ( netdev ); return rc; } return 0; } /** * The "dhcp" command * * @v argc Argument count * @v argv Argument list * @ret rc Return status code */ static int dhcp_exec ( int argc, char **argv ) { return ifcommon_exec ( argc, argv, &dhcp_cmd, dhcp_payload, 1 ); } /** "pxebs" options */ struct pxebs_options {}; /** "pxebs" option list */ static struct option_descriptor pxebs_opts[] = {}; /** "pxebs" command descriptor */ static struct command_descriptor pxebs_cmd = COMMAND_DESC ( struct pxebs_options, pxebs_opts, 2, 2, " " ); /** * The "pxebs" command * * @v argc Argument count * @v argv Argument list * @ret rc Return status code */ static int pxebs_exec ( int argc, char **argv ) { struct pxebs_options opts; struct net_device *netdev; unsigned int pxe_type; int rc; /* Parse options */ if ( ( rc = parse_options ( argc, argv, &pxebs_cmd, &opts ) ) != 0 ) return rc; /* Parse net device name */ if ( ( rc = parse_netdev ( argv[optind], &netdev ) ) != 0 ) return rc; /* Parse boot server type */ if ( ( rc = parse_integer ( argv[ optind + 1 ], &pxe_type ) ) != 0 ) return rc; /* Perform Boot Server Discovery */ if ( ( rc = pxebs ( netdev, pxe_type ) ) != 0 ) { printf ( "Could not discover boot server on %s: %s\n", netdev->name, strerror ( rc ) ); return rc; } return 0; } /** DHCP management commands */ struct command dhcp_commands[] __command = { { .name = "dhcp", .exec = dhcp_exec, }, { .name = "pxebs", .exec = pxebs_exec, }, }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/commands/time_cmd.c0000664000175000017500000000365411701704160022115 0ustar sergeserge/* * Copyright (C) 2009 Daniel Verkamp . * * 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 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. * * March-19-2009 @ 02:44: Added sleep command. * Shao Miller . */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include #include #include #include #include /** @file * * Time commands * */ /** "time" options */ struct time_options {}; /** "time" option list */ static struct option_descriptor time_opts[] = {}; /** "time" command descriptor */ static struct command_descriptor time_cmd = COMMAND_DESC ( struct time_options, time_opts, 1, MAX_ARGUMENTS, "" ); /** * "time" command * * @v argc Argument count * @v argv Argument list * @ret rc Return status code */ static int time_exec ( int argc, char **argv ) { struct time_options opts; unsigned long start; int secs; int rc; /* Parse options */ if ( ( rc = parse_options ( argc, argv, &time_cmd, &opts ) ) != 0 ) return rc; start = currticks(); rc = execv ( argv[1], argv + 1 ); secs = (currticks() - start) / ticks_per_sec(); printf ( "%s: %ds\n", argv[0], secs ); return rc; } /** "time" command */ struct command time_command __command = { .name = "time", .exec = time_exec, }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/commands/sanboot_cmd.c0000664000175000017500000001112211701704160022611 0ustar sergeserge/* * Copyright (C) 2010 Michael Brown . * * 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 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. */ #include #include #include #include #include #include #include #include #include FILE_LICENCE ( GPL2_OR_LATER ); /** @file * * SAN commands * */ /** "sanboot" options */ struct sanboot_options { /** Drive number */ unsigned int drive; /** Do not describe SAN device */ int no_describe; /** Keep SAN device */ int keep; }; /** "sanboot" option list */ static struct option_descriptor sanboot_opts[] = { OPTION_DESC ( "drive", 'd', required_argument, struct sanboot_options, drive, parse_integer ), OPTION_DESC ( "no-describe", 'n', no_argument, struct sanboot_options, no_describe, parse_flag ), OPTION_DESC ( "keep", 'k', no_argument, struct sanboot_options, keep, parse_flag ), }; /** "sanhook" command descriptor */ static struct command_descriptor sanhook_cmd = COMMAND_DESC ( struct sanboot_options, sanboot_opts, 1, 1, "[--drive ] [--no-describe] " ); /** "sanboot" command descriptor */ static struct command_descriptor sanboot_cmd = COMMAND_DESC ( struct sanboot_options, sanboot_opts, 0, 1, "[--drive ] [--no-describe] [--keep] " "[]" ); /** "sanunhook" command descriptor */ static struct command_descriptor sanunhook_cmd = COMMAND_DESC ( struct sanboot_options, sanboot_opts, 0, 0, "[--drive ]" ); /** * The "sanboot", "sanhook" and "sanunhook" commands * * @v argc Argument count * @v argv Argument list * @v default_flags Default set of flags for uriboot() * @v no_root_path_flags Additional flags to apply if no root path is present * @ret rc Return status code */ static int sanboot_core_exec ( int argc, char **argv, struct command_descriptor *cmd, int default_flags, int no_root_path_flags ) { struct sanboot_options opts; const char *root_path; struct uri *uri; int flags; int rc; /* Initialise options */ memset ( &opts, 0, sizeof ( opts ) ); opts.drive = san_default_drive(); /* Parse options */ if ( ( rc = reparse_options ( argc, argv, cmd, &opts ) ) != 0 ) goto err_parse_options; /* Parse root path, if present */ if ( argc > optind ) { root_path = argv[optind]; uri = parse_uri ( root_path ); if ( ! uri ) { rc = -ENOMEM; goto err_parse_uri; } } else { root_path = NULL; uri = NULL; } /* Construct flags */ flags = default_flags; if ( opts.no_describe ) flags |= URIBOOT_NO_SAN_DESCRIBE; if ( opts.keep ) flags |= URIBOOT_NO_SAN_UNHOOK; if ( ! root_path ) flags |= no_root_path_flags; /* Boot from root path */ if ( ( rc = uriboot ( NULL, uri, opts.drive, flags ) ) != 0 ) goto err_uriboot; err_uriboot: uri_put ( uri ); err_parse_uri: err_parse_options: return rc; } /** * The "sanhook" command * * @v argc Argument count * @v argv Argument list * @ret rc Return status code */ static int sanhook_exec ( int argc, char **argv ) { return sanboot_core_exec ( argc, argv, &sanhook_cmd, ( URIBOOT_NO_SAN_BOOT | URIBOOT_NO_SAN_UNHOOK ), 0 ); } /** * The "sanboot" command * * @v argc Argument count * @v argv Argument list * @ret rc Return status code */ static int sanboot_exec ( int argc, char **argv ) { return sanboot_core_exec ( argc, argv, &sanboot_cmd, 0, URIBOOT_NO_SAN_UNHOOK ); } /** * The "sanunhook" command * * @v argc Argument count * @v argv Argument list * @ret rc Return status code */ static int sanunhook_exec ( int argc, char **argv ) { return sanboot_core_exec ( argc, argv, &sanunhook_cmd, ( URIBOOT_NO_SAN_DESCRIBE | URIBOOT_NO_SAN_BOOT ), 0 ); } /** SAN commands */ struct command sanboot_commands[] __command = { { .name = "sanhook", .exec = sanhook_exec, }, { .name = "sanboot", .exec = sanboot_exec, }, { .name = "sanunhook", .exec = sanunhook_exec, }, }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/commands/digest_cmd.c0000664000175000017500000000570511701704160022435 0ustar sergeserge/* * Copyright (C) 2009 Daniel Verkamp . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include #include #include #include #include #include #include #include /** @file * * Digest commands * */ /** "digest" options */ struct digest_options {}; /** "digest" option list */ static struct option_descriptor digest_opts[] = {}; /** "digest" command descriptor */ static struct command_descriptor digest_cmd = COMMAND_DESC ( struct digest_options, digest_opts, 1, MAX_ARGUMENTS, " [...]" ); /** * The "digest" command * * @v argc Argument count * @v argv Argument list * @v digest Digest algorithm * @ret rc Return status code */ static int digest_exec ( int argc, char **argv, struct digest_algorithm *digest ) { struct digest_options opts; struct image *image; uint8_t digest_ctx[digest->ctxsize]; uint8_t digest_out[digest->digestsize]; uint8_t buf[128]; size_t offset; size_t len; size_t frag_len; int i; unsigned j; int rc; /* Parse options */ if ( ( rc = parse_options ( argc, argv, &digest_cmd, &opts ) ) != 0 ) return rc; for ( i = optind ; i < argc ; i++ ) { /* find image */ if ( ( rc = parse_image ( argv[i], &image ) ) != 0 ) continue; offset = 0; len = image->len; /* calculate digest */ digest_init ( digest, digest_ctx ); while ( len ) { frag_len = len; if ( frag_len > sizeof ( buf ) ) frag_len = sizeof ( buf ); copy_from_user ( buf, image->data, offset, frag_len ); digest_update ( digest, digest_ctx, buf, frag_len ); len -= frag_len; offset += frag_len; } digest_final ( digest, digest_ctx, digest_out ); for ( j = 0 ; j < sizeof ( digest_out ) ; j++ ) printf ( "%02x", digest_out[j] ); printf ( " %s\n", image->name ); } return 0; } static int md5sum_exec ( int argc, char **argv ) { return digest_exec ( argc, argv, &md5_algorithm ); } static int sha1sum_exec ( int argc, char **argv ) { return digest_exec ( argc, argv, &sha1_algorithm ); } struct command md5sum_command __command = { .name = "md5sum", .exec = md5sum_exec, }; struct command sha1sum_command __command = { .name = "sha1sum", .exec = sha1sum_exec, }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/commands/nvo_cmd.c0000664000175000017500000001237311701704160021757 0ustar sergeserge/* * Copyright (C) 2010 Michael Brown . * * 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 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. */ #include #include #include #include #include #include #include #include #include #include FILE_LICENCE ( GPL2_OR_LATER ); /** @file * * Non-volatile option commands * */ /** "show" options */ struct show_options {}; /** "show" option list */ static struct option_descriptor show_opts[] = {}; /** "show" command descriptor */ static struct command_descriptor show_cmd = COMMAND_DESC ( struct show_options, show_opts, 1, 1, "" ); /** * "show" command * * @v argc Argument count * @v argv Argument list * @ret rc Return status code */ static int show_exec ( int argc, char **argv ) { struct show_options opts; const char *name; char name_buf[32]; char value_buf[256]; int rc; /* Parse options */ if ( ( rc = parse_options ( argc, argv, &show_cmd, &opts ) ) != 0 ) return rc; /* Parse setting name */ name = argv[optind]; /* Fetch setting */ if ( ( rc = fetchf_named_setting ( name, name_buf, sizeof ( name_buf ), value_buf, sizeof ( value_buf ) ) ) < 0 ) { printf ( "Could not find \"%s\": %s\n", name, strerror ( rc ) ); return rc; } /* Print setting value */ printf ( "%s = %s\n", name_buf, value_buf ); return 0; } /** "set", "clear", and "read" options */ struct set_core_options {}; /** "set", "clear", and "read" option list */ static struct option_descriptor set_core_opts[] = {}; /** "set" command descriptor */ static struct command_descriptor set_cmd = COMMAND_DESC ( struct set_core_options, set_core_opts, 1, MAX_ARGUMENTS, " " ); /** "clear" and "read" command descriptor */ static struct command_descriptor clear_read_cmd = COMMAND_DESC ( struct set_core_options, set_core_opts, 1, 1, "" ); /** * "set", "clear", and "read" command * * @v argc Argument count * @v argv Argument list * @v cmd Command descriptor * @v get_value Method to obtain setting value * @ret rc Return status code */ static int set_core_exec ( int argc, char **argv, struct command_descriptor *cmd, int ( * get_value ) ( char **args, char **value ) ) { struct set_core_options opts; const char *name; char *value; int rc; /* Parse options */ if ( ( rc = parse_options ( argc, argv, cmd, &opts ) ) != 0 ) goto err_parse_options; /* Parse setting name */ name = argv[optind]; /* Parse setting value */ if ( ( rc = get_value ( &argv[ optind + 1 ], &value ) ) != 0 ) goto err_get_value; /* Determine total length of command line */ if ( ( rc = storef_named_setting ( name, value ) ) != 0 ) { printf ( "Could not %s \"%s\": %s\n", argv[0], name, strerror ( rc ) ); goto err_store; } free ( value ); return 0; err_store: free ( value ); err_get_value: err_parse_options: return rc; } /** * Get setting value for "set" command * * @v args Remaining arguments * @ret value Setting value * @ret rc Return status code */ static int set_value ( char **args, char **value ) { *value = concat_args ( args ); if ( ! *value ) return -ENOMEM; return 0; } /** * "set" command * * @v argc Argument count * @v argv Argument list * @ret rc Return status code */ static int set_exec ( int argc, char **argv ) { return set_core_exec ( argc, argv, &set_cmd, set_value ); } /** * Get setting value for "clear" command * * @v args Remaining arguments * @ret value Setting value * @ret rc Return status code */ static int clear_value ( char **args __unused, char **value ) { *value = NULL; return 0; } /** * "clear" command * * @v argc Argument count * @v argv Argument list * @ret rc Return status code */ static int clear_exec ( int argc, char **argv ) { return set_core_exec ( argc, argv, &clear_read_cmd, clear_value ); } /** * Get setting value for "read" command * * @ret value Setting value * @ret rc Return status code */ static int read_value ( char **args __unused, char **value ) { *value = readline ( NULL ); if ( ! *value ) return -ENOMEM; return 0; } /** * "read" command * * @v argc Argument count * @v argv Argument list * @ret rc Return status code */ static int read_exec ( int argc, char **argv ) { return set_core_exec ( argc, argv, &clear_read_cmd, read_value ); } /** Non-volatile option commands */ struct command nvo_commands[] __command = { { .name = "show", .exec = show_exec, }, { .name = "set", .exec = set_exec, }, { .name = "clear", .exec = clear_exec, }, { .name = "read", .exec = read_exec, }, }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/commands/fcmgmt_cmd.c0000664000175000017500000001174711701704160022436 0ustar sergeserge/* * Copyright (C) 2010 Michael Brown . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include #include #include #include #include #include #include #include /** @file * * Fibre Channel management commands * */ /** * Parse Fibre Channel port name * * @v text Text * @ret port Fibre Channel port * @ret rc Return status code */ static int parse_fc_port ( const char *text, struct fc_port **port ) { /* Sanity check */ assert ( text != NULL ); /* Find Fibre Channel port */ *port = fc_port_find ( text ); if ( ! *port ) { printf ( "\"%s\": no such port\n", text ); return -ENODEV; } return 0; } /** * Parse Fibre Channel port ID * * @v text Text * @ret port_id Fibre Channel port ID * @ret rc Return status code */ static int parse_fc_port_id ( const char *text, struct fc_port_id *port_id ) { int rc; /* Sanity check */ assert ( text != NULL ); /* Parse port ID */ if ( ( rc = fc_id_aton ( text, port_id ) ) != 0 ) { printf ( "\"%s\": invalid port ID\n", text ); return -EINVAL; } return 0; } /** * Parse Fibre Channel ELS handler name * * @v text Text * @ret handler Fibre Channel ELS handler * @ret rc Return status code */ static int parse_fc_els_handler ( const char *text, struct fc_els_handler **handler ) { for_each_table_entry ( (*handler), FC_ELS_HANDLERS ) { if ( strcasecmp ( (*handler)->name, text ) == 0 ) return 0; } printf ( "\"%s\": unrecognised ELS\n", text ); return -ENOENT; } /** "fcstat" options */ struct fcstat_options {}; /** "fcstat" option list */ static struct option_descriptor fcstat_opts[] = {}; /** "fcstat" command descriptor */ static struct command_descriptor fcstat_cmd = COMMAND_DESC ( struct fcstat_options, fcstat_opts, 0, 0, "" ); /** * The "fcstat" command * * @v argc Argument count * @v argv Argument list * @ret rc Return status code */ static int fcstat_exec ( int argc, char **argv ) { struct fcstat_options opts; struct fc_port *port; struct fc_peer *peer; int rc; /* Parse options */ if ( ( rc = parse_options ( argc, argv, &fcstat_cmd, &opts ) ) != 0 ) return rc; list_for_each_entry ( port, &fc_ports, list ) fcportstat ( port ); list_for_each_entry ( peer, &fc_peers, list ) fcpeerstat ( peer ); return 0; } /** "fcels" options */ struct fcels_options { /** Fibre Channel port */ struct fc_port *port; /** Fibre Channel peer port ID */ struct fc_port_id peer_port_id; }; /** "fcels" option list */ static struct option_descriptor fcels_opts[] = { OPTION_DESC ( "port", 'p', required_argument, struct fcels_options, port, parse_fc_port ), OPTION_DESC ( "id", 'i', required_argument, struct fcels_options, peer_port_id, parse_fc_port_id ), }; /** "fcels" command descriptor */ static struct command_descriptor fcels_cmd = COMMAND_DESC ( struct fcels_options, fcels_opts, 1, 1, "[--port ] [--id ] " ); /** * The "fcels" command * * @v argc Argument count * @v argv Argument list * @ret rc Return status code */ static int fcels_exec ( int argc, char **argv ) { struct fcels_options opts; struct fc_els_handler *handler; struct fc_port_id *id; int rc; /* Parse options */ if ( ( rc = parse_options ( argc, argv, &fcels_cmd, &opts ) ) != 0 ) return rc; /* Parse ELS handler */ if ( ( rc = parse_fc_els_handler ( argv[optind], &handler ) ) != 0 ) return rc; /* Use first port if no port specified */ if ( ! opts.port ) { opts.port = list_first_entry ( &fc_ports, struct fc_port, list ); if ( ! opts.port ) { printf ( "No ports\n" ); return -ENODEV; } } /* Use link peer port ID if no peer port ID specified */ id = &opts.peer_port_id; if ( memcmp ( id, &fc_empty_port_id, sizeof ( *id ) ) == 0 ) { if ( fc_link_ok ( &opts.port->link ) && ! ( opts.port->flags & FC_PORT_HAS_FABRIC ) ) { id = &opts.port->ptp_link_port_id; } else { id = &fc_f_port_id; } } /** Issue ELS */ if ( ( rc = fcels ( opts.port, id, handler ) ) != 0 ) return rc; return 0; } /** Fibre Channel management commands */ struct command fcmgmt_commands[] __command = { { .name = "fcstat", .exec = fcstat_exec, }, { .name = "fcels", .exec = fcels_exec, }, }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/mucurses/0000775000175000017500000000000011701704160020225 5ustar sergesergeipxe-precise-1.0.0+git-2.55f6c88/src/hci/mucurses/wininit.c0000664000175000017500000000113711701704160022054 0ustar sergeserge#include #include /** @file * * MuCurses initialisation functions * */ FILE_LICENCE ( GPL2_OR_LATER ); /** * Initialise console environment * * @ret *win return pointer to stdscr */ WINDOW *initscr ( void ) { /* determine console size */ /* initialise screen */ stdscr->scr->init( stdscr->scr ); stdscr->height = LINES; stdscr->width = COLS; move ( 0, 0 ); return stdscr; } /** * Finalise console environment * */ int endwin ( void ) { attrset ( 0 ); color_set ( 0, NULL ); mvprintw ( ( LINES - 1 ), 0, "\n" ); stdscr->scr->exit( stdscr->scr ); return OK; } ipxe-precise-1.0.0+git-2.55f6c88/src/hci/mucurses/print_nadv.c0000664000175000017500000000110511701704160022532 0ustar sergeserge#include #include "mucurses.h" #include "cursor.h" /** @file * * MuCurses printing functions (no cursor advance) * */ /** * Add string of single-byte characters and renditions to a window * * @v *win window to be rendered in * @v *chstr pointer to first chtype in "string" * @v n max number of chars from chstr to render * @ret rc return status code */ int waddchnstr ( WINDOW *win, const chtype *chstr, int n ) { struct cursor_pos pos; _store_curs_pos( win, &pos ); _wputchstr( win, chstr, NOWRAP, n ); _restore_curs_pos( win, &pos ); return OK; } ipxe-precise-1.0.0+git-2.55f6c88/src/hci/mucurses/kb.c0000664000175000017500000000475411701704160020777 0ustar sergeserge#include #include #include #include "mucurses.h" /** @file * * MuCurses keyboard input handling functions */ #define INPUT_DELAY 200 // half-blocking delay timer resolution (ms) #define INPUT_DELAY_TIMEOUT 1000 // half-blocking delay timeout int m_delay; /* < 0 : blocking read 0 : non-blocking read > 0 : timed blocking read */ bool m_echo; bool m_cbreak; static int _wgetc ( WINDOW *win ) { int timer, c; if ( win == NULL ) return ERR; timer = INPUT_DELAY_TIMEOUT; while ( ! win->scr->peek( win->scr ) ) { if ( m_delay == 0 ) // non-blocking read return ERR; if ( timer > 0 ) { // time-limited blocking read if ( m_delay > 0 ) timer -= INPUT_DELAY; mdelay( INPUT_DELAY ); } else { return ERR; } // non-blocking read } c = win->scr->getc( win->scr ); if ( m_echo && ( c >= 32 && c <= 126 ) ) // printable ASCII characters _wputch( win, (chtype) ( c | win->attrs ), WRAP ); return c; } /** * Pop a character from the FIFO into a window * * @v *win window in which to echo input * @ret c char from input stream */ int wgetch ( WINDOW *win ) { int c; c = _wgetc( win ); if ( m_echo ) { if ( c >= KEY_MIN ) { switch(c) { case KEY_LEFT : case KEY_BACKSPACE : _wcursback( win ); wdelch( win ); break; default : beep(); break; } } else { _wputch( win, (chtype)( c | win->attrs ), WRAP ); } } return c; } /** * Read at most n characters from the FIFO into a window * * @v *win window in which to echo input * @v *str pointer to string in which to store result * @v n maximum number of characters to read into string (inc. NUL) * @ret rc return status code */ int wgetnstr ( WINDOW *win, char *str, int n ) { char *_str; int c; if ( n == 0 ) { str = '\0'; return OK; } _str = str; while ( ( c = _wgetc( win ) ) != ERR ) { /* termination enforcement - don't let us go past the end of the allocated buffer... */ if ( n == 0 && ( c >= 32 && c <= 126 ) ) { _wcursback( win ); wdelch( win ); } else { if ( c >= KEY_MIN ) { switch(c) { case KEY_LEFT : case KEY_BACKSPACE : _wcursback( win ); wdelch( win ); break; case KEY_ENTER : *_str = '\0'; return OK; default : beep(); break; } } if ( c >= 32 && c <= 126 ) { *(_str++) = c; n--; } } } return ERR; } /** * */ int echo ( void ) { m_echo = TRUE; return OK; } /** * */ int noecho ( void ) { m_echo = FALSE; return OK; } ipxe-precise-1.0.0+git-2.55f6c88/src/hci/mucurses/clear.c0000664000175000017500000000307111701704160021460 0ustar sergeserge#include #include "mucurses.h" #include "cursor.h" /** @file * * MuCurses clearing functions * */ FILE_LICENCE ( GPL2_OR_LATER ); /** * Clear a window to the bottom from current cursor position * * @v *win subject window * @ret rc return status code */ int wclrtobot ( WINDOW *win ) { struct cursor_pos pos; _store_curs_pos( win, &pos ); do { _wputc( win, ' ', WRAP ); } while ( win->curs_y + win->curs_x ); _restore_curs_pos( win, &pos ); return OK; } /** * Clear a window to the end of the current line * * @v *win subject window * @ret rc return status code */ int wclrtoeol ( WINDOW *win ) { struct cursor_pos pos; _store_curs_pos( win, &pos ); while ( ( win->curs_y - pos.y ) == 0 ) { _wputc( win, ' ', WRAP ); } _restore_curs_pos( win, &pos ); return OK; } /** * Delete character under the cursor in a window * * @v *win subject window * @ret rc return status code */ int wdelch ( WINDOW *win ) { _wputc( win, ' ', NOWRAP ); _wcursback( win ); return OK; } /** * Delete line under a window's cursor * * @v *win subject window * @ret rc return status code */ int wdeleteln ( WINDOW *win ) { struct cursor_pos pos; _store_curs_pos( win, &pos ); /* let's just set the cursor to the beginning of the line and let wclrtoeol do the work :) */ wmove( win, win->curs_y, 0 ); wclrtoeol( win ); _restore_curs_pos( win, &pos ); return OK; } /** * Completely clear a window * * @v *win subject window * @ret rc return status code */ int werase ( WINDOW *win ) { wmove( win, 0, 0 ); wclrtobot( win ); return OK; } ipxe-precise-1.0.0+git-2.55f6c88/src/hci/mucurses/print.c0000664000175000017500000000336611701704160021535 0ustar sergeserge#include #include #include #include #include "mucurses.h" /** @file * * MuCurses printing functions * */ FILE_LICENCE ( GPL2_OR_LATER ); /** * Add a single-byte character and rendition to a window and advance * the cursor * * @v *win window to be rendered in * @v ch character to be added at cursor * @ret rc return status code */ int waddch ( WINDOW *win, const chtype ch ) { _wputch( win, ch, WRAP ); return OK; } /** * Add string of single-byte characters to a window * * @v *win window to be rendered in * @v *str standard c-style string * @v n max number of chars from string to render * @ret rc return status code */ int waddnstr ( WINDOW *win, const char *str, int n ) { _wputstr( win, str, WRAP, n ); return OK; } struct printw_context { struct printf_context ctx; WINDOW *win; }; static void _printw_handler ( struct printf_context *ctx, unsigned int c ) { struct printw_context *wctx = container_of ( ctx, struct printw_context, ctx ); _wputch( wctx->win, c | wctx->win->attrs, WRAP ); } /** * Print formatted output in a window * * @v *win subject window * @v *fmt formatted string * @v varglist argument list * @ret rc return status code */ int vw_printw ( WINDOW *win, const char *fmt, va_list varglist ) { struct printw_context wctx; wctx.win = win; wctx.ctx.handler = _printw_handler; vcprintf ( &(wctx.ctx), fmt, varglist ); return OK; } /** * Print formatted output to a window * * @v *win subject window * @v *fmt formatted string * @v ... string arguments * @ret rc return status code */ int wprintw ( WINDOW *win, const char *fmt, ... ) { va_list args; int i; va_start ( args, fmt ); i = vw_printw ( win, fmt, args ); va_end ( args ); return i; } ipxe-precise-1.0.0+git-2.55f6c88/src/hci/mucurses/colour.c0000664000175000017500000000260211701704160021674 0ustar sergeserge#include FILE_LICENCE ( GPL2_OR_LATER ); struct colour_pair { short fcol; short bcol; }; static struct colour_pair cpairs[COLOUR_PAIRS] = { [0] = { COLOUR_WHITE, COLOUR_BLACK }, }; /** * Identify the RGB components of a given colour value * * @v colour colour value * @v *red address to store red component * @v *green address to store green component * @v *blue address to store blue component * @ret rc return status code */ int colour_content ( short colour, short *red, short *green, short *blue ) { *red = ( ( colour & COLOUR_RED ) ? 1 : 0 ); *green = ( ( colour & COLOUR_GREEN ) ? 1 : 0 ); *blue = ( ( colour & COLOUR_BLUE ) ? 1 : 0 ); return OK; } /** * Initialise colour pair * * @v pair colour pair number * @v fcol foreground colour * @v bcol background colour */ int init_pair ( short pair, short fcol, short bcol ) { struct colour_pair *cpair; if ( ( pair < 1 ) || ( pair >= COLOUR_PAIRS ) ) return ERR; cpair = &cpairs[pair]; cpair->fcol = fcol; cpair->bcol = bcol; return OK; } /** * Get colours of colour pair * * @v pair colour pair number * @ret fcol foreground colour * @ret bcol background colour */ int pair_content ( short pair, short *fcol, short *bcol ) { struct colour_pair *cpair; if ( ( pair < 0 ) || ( pair >= COLOUR_PAIRS ) ) return ERR; cpair = &cpairs[pair]; *fcol = cpair->fcol; *bcol = cpair->bcol; return OK; } ipxe-precise-1.0.0+git-2.55f6c88/src/hci/mucurses/mucurses.c0000664000175000017500000000625511701704160022247 0ustar sergeserge#include #include #include "mucurses.h" /** @file * * MuCurses core functions * */ FILE_LICENCE ( GPL2_OR_LATER ); static void _wupdcurs ( WINDOW *win ) __nonnull; void _wputch ( WINDOW *win, chtype ch, int wrap ) __nonnull; void _wputc ( WINDOW *win, char c, int wrap ) __nonnull; void _wcursback ( WINDOW *win ) __nonnull; void _wputchstr ( WINDOW *win, const chtype *chstr, int wrap, int n ) __nonnull; void _wputstr ( WINDOW *win, const char *str, int wrap, int n ) __nonnull; int wmove ( WINDOW *win, int y, int x ) __nonnull; WINDOW _stdscr = { .attrs = A_DEFAULT, .ori_y = 0, .ori_x = 0, .curs_y = 0, .curs_x = 0, .scr = &_ansi_screen, }; /* * Primitives */ /** * Update cursor position * * @v *win window in which to update position */ static void _wupdcurs ( WINDOW *win ) { win->scr->movetoyx ( win->scr, win->ori_y + win->curs_y, win->ori_x + win->curs_x ); } /** * Write a single character rendition to a window * * @v *win window in which to write * @v ch character rendition to write * @v wrap wrap "switch" */ void _wputch ( WINDOW *win, chtype ch, int wrap ) { /* make sure we set the screen cursor to the right position first! */ _wupdcurs(win); win->scr->putc(win->scr, ch); if ( ++(win->curs_x) - win->width == 0 ) { if ( wrap == WRAP ) { win->curs_x = 0; /* specification says we should really scroll, but we have no buffer to scroll with, so we can only overwrite back at the beginning of the window */ if ( ++(win->curs_y) - win->height == 0 ) win->curs_y = 0; } else { (win->curs_x)--; } } } /** * Write a single character to a window * * @v *win window in which to write * @v c character rendition to write * @v wrap wrap "switch" */ void _wputc ( WINDOW *win, char c, int wrap ) { _wputch ( win, ( c | win->attrs ), wrap ); } /** * Retreat the cursor back one position (useful for a whole host of * ops) * * @v *win window in which to retreat */ void _wcursback ( WINDOW *win ) { if ( win->curs_x == 0 ) { if ( win->curs_y == 0 ) win->curs_y = win->height - 1; win->curs_x = win->width = 1; } else { win->curs_x--; } _wupdcurs(win); } /** * Write a chtype string to a window * * @v *win window in which to write * @v *chstr chtype string * @v wrap wrap "switch" * @v n write at most n chtypes */ void _wputchstr ( WINDOW *win, const chtype *chstr, int wrap, int n ) { for ( ; *chstr && n-- ; chstr++ ) { _wputch(win,*chstr,wrap); } } /** * Write a standard c-style string to a window * * @v *win window in which to write * @v *str string * @v wrap wrap "switch" * @v n write at most n chars from *str */ void _wputstr ( WINDOW *win, const char *str, int wrap, int n ) { for ( ; *str && n-- ; str++ ) { _wputc ( win, *str, wrap ); } } /** * Move a window's cursor to the specified position * * @v *win window to be operated on * @v y Y position * @v x X position * @ret rc return status code */ int wmove ( WINDOW *win, int y, int x ) { /* chech for out-of-bounds errors */ if ( ( (unsigned)y >= win->height ) || ( (unsigned)x >= win->width ) ) { return ERR; } win->curs_y = y; win->curs_x = x; _wupdcurs(win); return OK; } ipxe-precise-1.0.0+git-2.55f6c88/src/hci/mucurses/cursor.h0000664000175000017500000000142311701704160021713 0ustar sergeserge#ifndef CURSOR_H #define CURSOR_H /** @file * * MuCurses cursor implementation specific header file * */ FILE_LICENCE ( GPL2_OR_LATER ); struct cursor_pos { unsigned int y, x; }; /** * Restore cursor position from encoded backup variable * * @v *win window on which to operate * @v *pos pointer to struct in which original cursor position is stored */ static inline void _restore_curs_pos ( WINDOW *win, struct cursor_pos *pos ) { wmove ( win, pos->y, pos->x ); } /** * Store cursor position for later restoration * * @v *win window on which to operate * @v *pos pointer to struct in which to store cursor position */ static inline void _store_curs_pos ( WINDOW *win, struct cursor_pos *pos ) { pos->y = win->curs_y; pos->x = win->curs_x; } #endif /* CURSOR_H */ ipxe-precise-1.0.0+git-2.55f6c88/src/hci/mucurses/alert.c0000664000175000017500000000030511701704160021476 0ustar sergeserge#include #include /** @file * * MuCurses alert functions * */ /** * Audible signal * * @ret rc return status code */ int beep ( void ) { printf("\a"); return OK; } ipxe-precise-1.0.0+git-2.55f6c88/src/hci/mucurses/winattrs.c0000664000175000017500000000547611701704160022260 0ustar sergeserge#include /** @file * * MuCurses window attribute functions * */ FILE_LICENCE ( GPL2_OR_LATER ); /** * Get the background rendition attributes for a window * * @v *win subject window * @ret ch chtype rendition representation */ inline chtype getbkgd ( WINDOW *win ) { return win->attrs; } /** * Turn off attributes in a window * * @v win subject window * @v attrs attributes to enable * @ret rc return status code */ int wattroff ( WINDOW *win, int attrs ) { win->attrs &= ~attrs; return OK; } /** * Turn on attributes in a window * * @v win subject window * @v attrs attributes to enable * @ret rc return status code */ int wattron ( WINDOW *win, int attrs ) { win->attrs |= attrs; return OK; } /** * Set attributes in a window * * @v win subject window * @v attrs attributes to enable * @ret rc return status code */ int wattrset ( WINDOW *win, int attrs ) { win->attrs = ( attrs | ( win->attrs & A_COLOR ) ); return OK; } /** * Get attributes and colour pair information * * @v *win window to obtain information from * @v *attrs address in which to store attributes * @v *pair address in which to store colour pair * @v *opts undefined (for future implementation) * @ret rc return status cude */ int wattr_get ( WINDOW *win, attr_t *attrs, short *pair, void *opts __unused ) { *attrs = win->attrs & A_ATTRIBUTES; *pair = PAIR_NUMBER ( win->attrs ); return OK; } /** * Turn off attributes in a window * * @v *win subject window * @v attrs attributes to toggle * @v *opts undefined (for future implementation) * @ret rc return status code */ int wattr_off ( WINDOW *win, attr_t attrs, void *opts __unused ) { wattroff( win, attrs ); return OK; } /** * Turn on attributes in a window * * @v *win subject window * @v attrs attributes to toggle * @v *opts undefined (for future implementation) * @ret rc return status code */ int wattr_on ( WINDOW *win, attr_t attrs, void *opts __unused ) { wattron( win, attrs ); return OK; } /** * Set attributes and colour pair information in a window * * @v *win subject window * @v attrs attributes to set * @v cpair colour pair to set * @v *opts undefined (for future implementation) * @ret rc return status code */ int wattr_set ( WINDOW *win, attr_t attrs, short cpair, void *opts __unused ) { wattrset( win, attrs | COLOUR_PAIR ( cpair ) ); return OK; } /** * Set colour pair for a window * * @v *win subject window * @v colour_pair_number colour pair integer * @v *opts undefined (for future implementation) * @ret rc return status code */ int wcolour_set ( WINDOW *win, short colour_pair_number, void *opts __unused ) { if ( ( unsigned short )colour_pair_number > COLOUR_PAIRS ) return ERR; win->attrs = ( ( win->attrs & A_ATTRIBUTES ) | COLOUR_PAIR ( colour_pair_number ) ); return OK; } ipxe-precise-1.0.0+git-2.55f6c88/src/hci/mucurses/windows.c0000664000175000017500000000710511701704160022066 0ustar sergeserge#include #include #include #include "mucurses.h" /** @file * * MuCurses windows instance functions * */ /** * Delete a window * * @v *win pointer to window being deleted * @ret rc return status code */ int delwin ( WINDOW *win ) { if ( win == NULL ) return ERR; /* I think we should blank the region covered by the window - ncurses doesn't do this, but they have a buffer, so they may just be deleting from an offscreen context whereas we are guaranteed to be deleting something onscreen */ wmove( win, 0, 0 ); chtype killch = (chtype)' '; do { _wputch( win, killch, WRAP ); } while ( win->curs_x + win->curs_y ); free( win ); wmove ( stdscr, 0, 0 ); return OK; } /** * Create a new derived window * * @v parent parent window * @v nlines window height * @v ncols window width * @v begin_y window y origin (relative to parent) * @v begin_x window x origin (relative to parent) * @ret ptr return pointer to child window */ WINDOW *derwin ( WINDOW *parent, int nlines, int ncols, int begin_y, int begin_x ) { WINDOW *child; if ( parent == NULL ) return NULL; if ( ( child = malloc( sizeof( WINDOW ) ) ) == NULL ) return NULL; if ( ( (unsigned)ncols > parent->width ) || ( (unsigned)nlines > parent->height ) ) return NULL; child->ori_y = parent->ori_y + begin_y; child->ori_x = parent->ori_x + begin_x; child->height = nlines; child->width = ncols; child->parent = parent; child->scr = parent->scr; return child; } /** * Create a duplicate of the specified window * * @v orig original window * @ret ptr pointer to duplicate window */ WINDOW *dupwin ( WINDOW *orig ) { WINDOW *copy; if ( orig == NULL ) return NULL; if ( ( copy = malloc( sizeof( WINDOW ) ) ) == NULL ) return NULL; copy->scr = orig->scr; copy->attrs = orig->attrs; copy->ori_y = orig->ori_y; copy->ori_x = orig->ori_x; copy->curs_y = orig->curs_y; copy->curs_x = orig->curs_x; copy->height = orig->height; copy->width = orig->width; return copy; } /** * Move window origin to specified coordinates * * @v *win window to move * @v y Y position * @v x X position * @ret rc return status code */ int mvwin ( WINDOW *win, int y, int x ) { if ( win == NULL ) return ERR; if ( ( ( (unsigned)y + win->height ) > LINES ) || ( ( (unsigned)x + win->width ) > COLS ) ) return ERR; win->ori_y = y; win->ori_x = x; return OK; } /** * Create new WINDOW * * @v nlines number of lines * @v ncols number of columns * @v begin_y column origin * @v begin_x line origin * @ret *win return pointer to new window */ WINDOW *newwin ( int nlines, int ncols, int begin_y, int begin_x ) { WINDOW *win; if ( ( win = malloc( sizeof(WINDOW) ) ) == NULL ) return NULL; if ( ( (unsigned)( begin_y + nlines ) > stdscr->height ) && ( (unsigned)( begin_x + ncols ) > stdscr->width ) ) return NULL; win->ori_y = begin_y; win->ori_x = begin_x; win->height = nlines; win->width = ncols; win->scr = stdscr->scr; win->parent = stdscr; return win; } /** * Create a new sub-window * * @v orig parent window * @v nlines window height * @v ncols window width * @v begin_y window y origin (absolute) * @v begin_x window x origin (absolute) * @ret ptr return pointer to child window */ WINDOW *subwin ( WINDOW *parent, int nlines, int ncols, int begin_y, int begin_x ) { WINDOW *child; if ( parent == NULL ) return NULL; if ( ( child = malloc( sizeof( WINDOW ) ) ) == NULL ) return NULL; child = newwin( nlines, ncols, begin_y, begin_x ); child->parent = parent; child->scr = parent->scr; return child; } ipxe-precise-1.0.0+git-2.55f6c88/src/hci/mucurses/widgets/0000775000175000017500000000000011701704160021673 5ustar sergesergeipxe-precise-1.0.0+git-2.55f6c88/src/hci/mucurses/widgets/editbox.c0000664000175000017500000000532211701704160023477 0ustar sergeserge/* * Copyright (C) 2006 Michael Brown . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include /** @file * * Editable text box widget * */ #define EDITBOX_MIN_CHARS 3 /** * Initialise text box widget * * @v box Editable text box widget * @v buf Text buffer * @v len Size of text buffer * @v win Containing window * @v row Row * @v col Starting column * @v width Width * @v flags Flags */ void init_editbox ( struct edit_box *box, char *buf, size_t len, WINDOW *win, unsigned int row, unsigned int col, unsigned int width, unsigned int flags ) { memset ( box, 0, sizeof ( *box ) ); init_editstring ( &box->string, buf, len ); box->string.cursor = strlen ( buf ); box->win = ( win ? win : stdscr ); box->row = row; box->col = col; box->width = width; box->flags = flags; } /** * Draw text box widget * * @v box Editable text box widget * */ void draw_editbox ( struct edit_box *box ) { size_t width = box->width; char buf[ width + 1 ]; signed int cursor_offset, underflow, overflow, first; size_t len; /* Adjust starting offset so that cursor remains within box */ cursor_offset = ( box->string.cursor - box->first ); underflow = ( EDITBOX_MIN_CHARS - cursor_offset ); overflow = ( cursor_offset - ( width - 1 ) ); first = box->first; if ( underflow > 0 ) { first -= underflow; if ( first < 0 ) first = 0; } else if ( overflow > 0 ) { first += overflow; } box->first = first; cursor_offset = ( box->string.cursor - first ); /* Construct underscore-padded string portion */ memset ( buf, '_', width ); buf[width] = '\0'; len = ( strlen ( box->string.buf ) - first ); if ( len > width ) len = width; if ( box->flags & EDITBOX_STARS ) { memset ( buf, '*', len ); } else { memcpy ( buf, ( box->string.buf + first ), len ); } /* Print box content and move cursor */ if ( ! box->win ) box->win = stdscr; mvwprintw ( box->win, box->row, box->col, "%s", buf ); wmove ( box->win, box->row, ( box->col + cursor_offset ) ); } ipxe-precise-1.0.0+git-2.55f6c88/src/hci/mucurses/mucurses.h0000664000175000017500000000111411701704160022241 0ustar sergeserge#ifndef _MUCURSES_H #define _MUCURSES_H /** @file * * MuCurses core implementation specific header file * */ FILE_LICENCE ( GPL2_OR_LATER ); #define WRAP 0 #define NOWRAP 1 extern SCREEN _ansi_screen; extern void _wputch ( WINDOW *win, chtype ch, int wrap ) __nonnull; extern void _wputc ( WINDOW *win, char c, int wrap ) __nonnull; extern void _wputchstr ( WINDOW *win, const chtype *chstr, int wrap, int n ) __nonnull; extern void _wputstr ( WINDOW *win, const char *str, int wrap, int n ) __nonnull; extern void _wcursback ( WINDOW *win ) __nonnull; #endif /* _MUCURSES_H */ ipxe-precise-1.0.0+git-2.55f6c88/src/hci/mucurses/ansi_screen.c0000664000175000017500000000366611701704160022675 0ustar sergeserge#include #include #include FILE_LICENCE ( GPL2_OR_LATER ); static void ansiscr_reset(struct _curses_screen *scr) __nonnull; static void ansiscr_movetoyx(struct _curses_screen *scr, unsigned int y, unsigned int x) __nonnull; static void ansiscr_putc(struct _curses_screen *scr, chtype c) __nonnull; unsigned short _COLS = 80; unsigned short _LINES = 24; static void ansiscr_reset ( struct _curses_screen *scr ) { /* Reset terminal attributes and clear screen */ scr->attrs = 0; scr->curs_x = 0; scr->curs_y = 0; printf ( "\033[0m" ); } static void ansiscr_movetoyx ( struct _curses_screen *scr, unsigned int y, unsigned int x ) { if ( ( x != scr->curs_x ) || ( y != scr->curs_y ) ) { /* ANSI escape sequence to update cursor position */ printf ( "\033[%d;%dH", ( y + 1 ), ( x + 1 ) ); scr->curs_x = x; scr->curs_y = y; } } static void ansiscr_putc ( struct _curses_screen *scr, chtype c ) { unsigned int character = ( c & A_CHARTEXT ); attr_t attrs = ( c & ( A_ATTRIBUTES | A_COLOR ) ); int bold = ( attrs & A_BOLD ); attr_t cpair = PAIR_NUMBER ( attrs ); short fcol; short bcol; /* Update attributes if changed */ if ( attrs != scr->attrs ) { scr->attrs = attrs; pair_content ( cpair, &fcol, &bcol ); /* ANSI escape sequence to update character attributes */ printf ( "\033[0;%d;3%d;4%dm", ( bold ? 1 : 22 ), fcol, bcol ); } /* Print the actual character */ putchar ( character ); /* Update expected cursor position */ if ( ++(scr->curs_x) == _COLS ) { scr->curs_x = 0; ++scr->curs_y; } } static int ansiscr_getc ( struct _curses_screen *scr __unused ) { return getchar(); } static bool ansiscr_peek ( struct _curses_screen *scr __unused ) { return iskey(); } SCREEN _ansi_screen = { .init = ansiscr_reset, .exit = ansiscr_reset, .movetoyx = ansiscr_movetoyx, .putc = ansiscr_putc, .getc = ansiscr_getc, .peek = ansiscr_peek, }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/mucurses/slk.c0000664000175000017500000001707011701704160021167 0ustar sergeserge#include #include #include #include #include #include "mucurses.h" #include "cursor.h" /** @file * * Soft label key functions */ #define MIN_SPACE_SIZE 2 #define SLK_MAX_LABEL_LEN 8 #define SLK_MAX_NUM_LABELS 12 #define SLK_MAX_NUM_SPACES 2 struct _softlabel { // label string char label[SLK_MAX_LABEL_LEN]; /* Format of soft label 0: left justify 1: centre justify 2: right justify */ unsigned int fmt; }; struct _softlabelkeys { struct _softlabel fkeys[SLK_MAX_NUM_LABELS]; attr_t attrs; /* Soft label layout format 0: 3-2-3 1: 4-4 2: 4-4-4 3: 4-4-4 with index line */ unsigned int fmt; unsigned int max_label_len; unsigned int maj_space_len; unsigned int num_labels; unsigned int num_spaces; unsigned int spaces[SLK_MAX_NUM_SPACES]; struct cursor_pos saved_cursor; attr_t saved_attrs; short saved_pair; }; static struct _softlabelkeys *slks; /* I either need to break the primitives here, or write a collection of functions specifically for SLKs that directly access the screen functions - since this technically isn't part of stdscr, I think this should be ok... */ static void _enter_slk ( void ) { _store_curs_pos ( stdscr, &slks->saved_cursor ); wattr_get ( stdscr, &slks->saved_attrs, &slks->saved_pair, NULL ); LINES++; wmove ( stdscr, LINES, 0 ); wattrset ( stdscr, slks->attrs ); } static void _leave_slk ( void ) { LINES--; wattr_set ( stdscr, slks->saved_attrs, slks->saved_pair, NULL ); _restore_curs_pos ( stdscr, &slks->saved_cursor ); } static void _print_label ( struct _softlabel sl ) { int space_ch; char str[SLK_MAX_LABEL_LEN + 1]; assert ( slks->max_label_len <= SLK_MAX_LABEL_LEN ); space_ch = ' '; // protect against gaps in the soft label keys array if ( sl.label == NULL ) { memset( str, space_ch, (size_t)(slks->max_label_len) ); } else { /* we need to pad the label with varying amounts of leading pad depending on the format of the label */ if ( sl.fmt == 1 ) { memset( str, space_ch, (size_t)(slks->max_label_len - strlen(sl.label)) / 2 ); } if ( sl.fmt == 2 ) { memset( str, space_ch, (size_t)(slks->max_label_len - strlen(sl.label)) ); } strcat(str,sl.label); // post-padding memset(str+strlen(str), space_ch, (size_t)(slks->max_label_len - strlen(str)) ); } // print the formatted label _wputstr ( stdscr, str, NOWRAP, slks->max_label_len ); } /** * Return the attribute used for the soft function keys * * @ret attrs the current attributes of the soft function keys */ attr_t slk_attr ( void ) { return ( slks == NULL ? 0 : slks->attrs ); } /** * Turn off soft function key attributes * * @v attrs attribute bit mask * @ret rc return status code */ int slk_attroff ( const chtype attrs ) { if ( slks == NULL ) return ERR; slks->attrs &= ~( attrs & A_ATTRIBUTES ); return OK; } /** * Turn on soft function key attributes * * @v attrs attribute bit mask * @ret rc return status code */ int slk_attron ( const chtype attrs ) { if ( slks == NULL ) return ERR; slks->attrs |= ( attrs & A_ATTRIBUTES ); return OK; } /** * Set soft function key attributes * * @v attrs attribute bit mask * @ret rc return status code */ int slk_attrset ( const chtype attrs ) { if ( slks == NULL ) return ERR; slks->attrs = ( attrs & A_ATTRIBUTES ); return OK; } /** * Turn off soft function key attributes * * @v attrs attribute bit mask * @v *opts undefined (for future implementation) * @ret rc return status code */ int slk_attr_off ( const attr_t attrs, void *opts __unused ) { return slk_attroff( attrs ); } /** * Turn on soft function key attributes * * @v attrs attribute bit mask * @v *opts undefined (for future implementation) * @ret rc return status code */ int slk_attr_on ( attr_t attrs, void *opts __unused ) { return slk_attron( attrs ); } /** * Set soft function key attributes * * @v attrs attribute bit mask * @v colour_pair_number colour pair integer * @v *opts undefined (for future implementation) * @ret rc return status code */ int slk_attr_set ( const attr_t attrs, short colour_pair_number, void *opts __unused ) { if ( slks == NULL ) return ERR; if ( ( unsigned short )colour_pair_number > COLORS ) return ERR; slks->attrs = ( (unsigned short)colour_pair_number << CPAIR_SHIFT ) | ( attrs & A_ATTRIBUTES ); return OK; } /** * Clear the soft function key labels from the screen * * @ret rc return status code */ int slk_clear ( void ) { if ( slks == NULL ) return ERR; _enter_slk(); wclrtoeol ( stdscr ); _leave_slk(); return OK; } /** * Set soft label colour pair */ int slk_colour ( short colour_pair_number ) { if ( slks == NULL ) return ERR; if ( ( unsigned short )colour_pair_number > COLORS ) return ERR; slks->attrs = ( (unsigned short)colour_pair_number << CPAIR_SHIFT ) | ( slks->attrs & A_ATTRIBUTES ); return OK; } /** * Initialise the soft function keys * * @v fmt format of keys * @ret rc return status code */ int slk_init ( int fmt ) { unsigned short nmaj, nmin, nblocks, available_width; if ( (unsigned)fmt > 3 ) { return ERR; } /* There seems to be no API call to free this data structure... */ if ( ! slks ) slks = calloc(1,sizeof(*slks)); if ( ! slks ) return ERR; slks->attrs = A_DEFAULT; slks->fmt = fmt; switch(fmt) { case 0: nblocks = 8; nmaj = 2; nmin = 5; slks->spaces[0] = 2; slks->spaces[1] = 4; break; case 1: nblocks = 8; nmaj = 1; nmin = 6; slks->spaces[0] = 3; break; case 2: // same allocations as format 3 case 3: nblocks = 12; nmaj = 2; nmin = 9; slks->spaces[0] = 3; slks->spaces[1] = 7; break; default: nblocks = 0; nmaj = 0; nmin = 0; break; } // determine maximum label length and major space size available_width = COLS - ( ( MIN_SPACE_SIZE * nmaj ) + nmin ); slks->max_label_len = available_width / nblocks; slks->maj_space_len = MIN_SPACE_SIZE + ( available_width % nblocks ) / nmaj; slks->num_spaces = nmaj; slks->num_labels = nblocks; // strip a line from the screen LINES -= 1; return OK; } /** * Return the label for the specified soft key * * @v labnum soft key identifier * @ret label return label */ char* slk_label ( int labnum ) { if ( slks == NULL ) return NULL; return slks->fkeys[labnum].label; } /** * Restore soft function key labels to the screen * * @ret rc return status code */ int slk_restore ( void ) { unsigned int i, j, pos_x, *next_space, *last_space; chtype space_ch; if ( slks == NULL ) return ERR; pos_x = 0; _enter_slk(); space_ch = (chtype)' ' | slks->attrs; next_space = &(slks->spaces[0]); last_space = &(slks->spaces[slks->num_spaces-1]); for ( i = 0; i < slks->num_labels ; i++ ) { _print_label( slks->fkeys[i] ); pos_x += slks->max_label_len; if ( i == *next_space ) { for ( j = 0; j < slks->maj_space_len; j++, pos_x++ ) _wputch ( stdscr, space_ch, NOWRAP ); if ( next_space < last_space ) next_space++; } else { if ( pos_x < COLS ) _wputch ( stdscr, space_ch, NOWRAP ); pos_x++; } } _leave_slk(); return OK; } /** * Configure specified soft key * * @v labnum soft label position to configure * @v *label string to use as soft key label * @v fmt justification format of label * @ret rc return status code */ int slk_set ( int labnum, const char *label, int fmt ) { if ( slks == NULL ) return ERR; if ( (unsigned short)labnum >= slks->num_labels ) return ERR; if ( (unsigned short)fmt >= 3 ) return ERR; strncpy(slks->fkeys[labnum].label, label, sizeof(slks->fkeys[labnum].label)); slks->fkeys[labnum].fmt = fmt; return OK; } ipxe-precise-1.0.0+git-2.55f6c88/src/hci/mucurses/edging.c0000664000175000017500000000461711701704160021636 0ustar sergeserge#include #include "mucurses.h" #include "cursor.h" /** @file * * MuCurses edging functions * */ /** * Draw borders from single-byte characters and renditions around a * window * * @v *win window to be bordered * @v verch vertical chtype * @v horch horizontal chtype * @ret rc return status code */ int box ( WINDOW *win, chtype verch, chtype horch ) { chtype corner = '+' | win->attrs; /* default corner character */ return wborder( win, verch, verch, horch, horch, corner, corner, corner, corner ); } /** * Draw borders from single-byte characters and renditions around a * window * * @v *win window to be bordered * @v ls left side * @v rs right side * @v ts top * @v bs bottom * @v tl top left corner * @v tr top right corner * @v bl bottom left corner * @v br bottom right corner * @ret rc return status code */ int wborder ( WINDOW *win, chtype ls, chtype rs, chtype ts, chtype bs, chtype tl, chtype tr, chtype bl, chtype br ) { struct cursor_pos pos; _store_curs_pos( win, &pos ); wmove(win,0,0); _wputch(win,tl,WRAP); while ( ( win->width - 1 ) - win->curs_x ) { _wputch(win,ts,WRAP); } _wputch(win,tr,WRAP); while ( ( win->height - 1 ) - win->curs_y ) { _wputch(win,ls,WRAP); wmove(win,win->curs_y,(win->width)-1); _wputch(win,rs,WRAP); } _wputch(win,bl,WRAP); while ( ( win->width -1 ) - win->curs_x ) { _wputch(win,bs,WRAP); } _wputch(win,br,NOWRAP); /* do not wrap last char to leave cursor in last position */ _restore_curs_pos( win, &pos ); return OK; } /** * Create a horizontal line in a window * * @v *win subject window * @v ch rendition and character * @v n max number of chars (wide) to render * @ret rc return status code */ int whline ( WINDOW *win, chtype ch, int n ) { struct cursor_pos pos; _store_curs_pos ( win, &pos ); while ( ( win->curs_x - win->width ) && n-- ) { _wputch ( win, ch, NOWRAP ); } _restore_curs_pos ( win, &pos ); return OK; } /** * Create a vertical line in a window * * @v *win subject window * @v ch rendition and character * @v n max number of chars (high) to render * @ret rc return status code */ int wvline ( WINDOW *win, chtype ch, int n ) { struct cursor_pos pos; _store_curs_pos ( win, &pos ); while ( ( win->curs_y - win->height ) && n-- ) { _wputch ( win, ch, NOWRAP ); wmove( win, ++(win->curs_y), pos.x); } _restore_curs_pos ( win, &pos ); return OK; } ipxe-precise-1.0.0+git-2.55f6c88/src/hci/readline.c0000664000175000017500000001740611701704160020316 0ustar sergeserge/* * Copyright (C) 2006 Michael Brown . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include #include #include #include #include /** @file * * Minimal readline * */ #define READLINE_MAX 256 /** * Synchronise console with edited string * * @v string Editable string */ static void sync_console ( struct edit_string *string ) { unsigned int mod_start = string->mod_start; unsigned int mod_end = string->mod_end; unsigned int cursor = string->last_cursor; size_t len = strlen ( string->buf ); /* Expand region back to old cursor position if applicable */ if ( mod_start > string->last_cursor ) mod_start = string->last_cursor; /* Expand region forward to new cursor position if applicable */ if ( mod_end < string->cursor ) mod_end = string->cursor; /* Backspace to start of region */ while ( cursor > mod_start ) { putchar ( '\b' ); cursor--; } /* Print modified region */ while ( cursor < mod_end ) { putchar ( ( cursor >= len ) ? ' ' : string->buf[cursor] ); cursor++; } /* Backspace to new cursor position */ while ( cursor > string->cursor ) { putchar ( '\b' ); cursor--; } } /** * Locate history entry * * @v history History buffer * @v depth Depth within history buffer * @ret entry History entry */ static struct readline_history_entry * history_entry ( struct readline_history *history, unsigned int depth ) { unsigned int offset; offset = ( ( history->next - depth ) % ( sizeof ( history->entries ) / sizeof ( history->entries[0] ) ) ); return &history->entries[offset]; } /** * Read string from history buffer * * @v history History buffer * @v depth Depth within history buffer * @ret string String */ static const char * history_fetch ( struct readline_history *history, unsigned int depth ) { struct readline_history_entry *entry; /* Return the temporary copy if it exists, otherwise return * the persistent copy. */ entry = history_entry ( history, depth ); return ( entry->temp ? entry->temp : entry->string ); } /** * Write temporary string copy to history buffer * * @v history History buffer * @v depth Depth within history buffer * @v string String */ static void history_store ( struct readline_history *history, unsigned int depth, const char *string ) { struct readline_history_entry *entry; char *temp; /* Create temporary copy of string */ temp = strdup ( string ); if ( ! temp ) { /* Just discard the string; there's nothing we can do */ DBGC ( history, "READLINE %p could not store string\n", history ); return; } /* Store temporary copy */ entry = history_entry ( history, depth ); free ( entry->temp ); entry->temp = temp; } /** * Move to new history depth * * @v history History buffer * @v offset Offset by which to change depth * @v old_string String (possibly modified) at current depth * @ret new_string String at new depth, or NULL for no movement */ static const char * history_move ( struct readline_history *history, int offset, const char *old_string ) { unsigned int new_depth = ( history->depth + offset ); const char * new_string = history_fetch ( history, new_depth ); /* Depth checks */ if ( new_depth > READLINE_HISTORY_MAX_DEPTH ) return NULL; if ( ! new_string ) return NULL; /* Store temporary copy of old string at current depth */ history_store ( history, history->depth, old_string ); /* Update depth */ history->depth = new_depth; /* Return new string */ return new_string; } /** * Append new history entry * * @v history History buffer * @v string String */ static void history_append ( struct readline_history *history, const char *string ) { struct readline_history_entry *entry; /* Store new entry */ entry = history_entry ( history, 0 ); assert ( entry->string == NULL ); entry->string = strdup ( string ); if ( ! entry->string ) { /* Just discard the string; there's nothing we can do */ DBGC ( history, "READLINE %p could not append string\n", history ); return; } /* Increment history position */ history->next++; /* Prepare empty "next" slot */ entry = history_entry ( history, 0 ); free ( entry->string ); entry->string = NULL; } /** * Clean up history after editing * * @v history History buffer */ static void history_cleanup ( struct readline_history *history ) { struct readline_history_entry *entry; unsigned int i; /* Discard any temporary strings */ for ( i = 0 ; i < ( sizeof ( history->entries ) / sizeof ( history->entries[0] ) ) ; i++ ) { entry = &history->entries[i]; free ( entry->temp ); entry->temp = NULL; } /* Reset depth */ history->depth = 0; /* Sanity check */ entry = history_entry ( history, 0 ); assert ( entry->string == NULL ); } /** * Free history buffer * * @v history History buffer */ void history_free ( struct readline_history *history ) { struct readline_history_entry *entry; unsigned int i; /* Discard any temporary strings */ for ( i = 0 ; i < ( sizeof ( history->entries ) / sizeof ( history->entries[0] ) ) ; i++ ) { entry = &history->entries[i]; assert ( entry->temp == NULL ); free ( entry->string ); } } /** * Read line from console (with history) * * @v prompt Prompt string * @v history History buffer, or NULL for no history * @ret line Line read from console (excluding terminating newline) * * The returned line is allocated with malloc(); the caller must * eventually call free() to release the storage. */ char * readline_history ( const char *prompt, struct readline_history *history ) { char buf[READLINE_MAX]; struct edit_string string; int key; int move_by; const char *new_string; char *line; /* Display prompt, if applicable */ if ( prompt ) printf ( "%s", prompt ); /* Initialise editable string */ memset ( &string, 0, sizeof ( string ) ); init_editstring ( &string, buf, sizeof ( buf ) ); buf[0] = '\0'; while ( 1 ) { /* Handle keypress */ key = edit_string ( &string, getkey ( 0 ) ); sync_console ( &string ); move_by = 0; switch ( key ) { case CR: case LF: line = strdup ( buf ); if ( ! line ) printf ( "\nOut of memory" ); goto done; case CTRL_C: line = NULL; goto done; case KEY_UP: move_by = 1; break; case KEY_DOWN: move_by = -1; break; default: /* Do nothing */ break; } /* Handle history movement, if applicable */ if ( move_by && history ) { new_string = history_move ( history, move_by, buf ); if ( new_string ) { replace_string ( &string, new_string ); sync_console ( &string ); } } } done: putchar ( '\n' ); if ( history ) { if ( line && line[0] ) history_append ( history, line ); history_cleanup ( history ); } return line; } /** * Read line from console * * @v prompt Prompt string * @ret line Line read from console (excluding terminating newline) * * The returned line is allocated with malloc(); the caller must * eventually call free() to release the storage. */ char * readline ( const char *prompt ) { return readline_history ( prompt, NULL ); } ipxe-precise-1.0.0+git-2.55f6c88/src/hci/editstring.c0000664000175000017500000001305311701704160020701 0ustar sergeserge/* * Copyright (C) 2006 Michael Brown . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include #include /** @file * * Editable strings * */ static void insert_delete ( struct edit_string *string, size_t delete_len, const char *insert_text ) __attribute__ (( nonnull (1) )); static void insert_character ( struct edit_string *string, unsigned int character ) __nonnull; static void delete_character ( struct edit_string *string ) __nonnull; static void backspace ( struct edit_string *string ) __nonnull; static void kill_eol ( struct edit_string *string ) __nonnull; /** * Insert and/or delete text within an editable string * * @v string Editable string * @v delete_len Length of text to delete from current cursor position * @v insert_text Text to insert at current cursor position, or NULL */ static void insert_delete ( struct edit_string *string, size_t delete_len, const char *insert_text ) { size_t old_len, max_delete_len, insert_len, max_insert_len, new_len; /* Calculate lengths */ old_len = strlen ( string->buf ); assert ( string->cursor <= old_len ); max_delete_len = ( old_len - string->cursor ); if ( delete_len > max_delete_len ) delete_len = max_delete_len; insert_len = ( insert_text ? strlen ( insert_text ) : 0 ); max_insert_len = ( ( string->len - 1 ) - ( old_len - delete_len ) ); if ( insert_len > max_insert_len ) insert_len = max_insert_len; new_len = ( old_len - delete_len + insert_len ); /* Fill in edit history */ string->mod_start = string->cursor; string->mod_end = ( ( new_len > old_len ) ? new_len : old_len ); /* Move data following the cursor */ memmove ( ( string->buf + string->cursor + insert_len ), ( string->buf + string->cursor + delete_len ), ( max_delete_len + 1 - delete_len ) ); /* Copy inserted text to cursor position */ memcpy ( ( string->buf + string->cursor ), insert_text, insert_len ); string->cursor += insert_len; } /** * Insert character at current cursor position * * @v string Editable string * @v character Character to insert */ static void insert_character ( struct edit_string *string, unsigned int character ) { char insert_text[2] = { character, '\0' }; insert_delete ( string, 0, insert_text ); } /** * Delete character at current cursor position * * @v string Editable string */ static void delete_character ( struct edit_string *string ) { insert_delete ( string, 1, NULL ); } /** * Delete character to left of current cursor position * * @v string Editable string */ static void backspace ( struct edit_string *string ) { if ( string->cursor > 0 ) { string->cursor--; delete_character ( string ); } } /** * Delete to end of line * * @v string Editable string */ static void kill_eol ( struct edit_string *string ) { insert_delete ( string, ~( ( size_t ) 0 ), NULL ); } /** * Replace editable string * * @v string Editable string * @v replacement Replacement string */ void replace_string ( struct edit_string *string, const char *replacement ) { string->cursor = 0; insert_delete ( string, ~( ( size_t ) 0 ), replacement ); } /** * Edit editable string * * @v string Editable string * @v key Key pressed by user * @ret key Key returned to application, or zero * * Handles keypresses and updates the content of the editable string. * Basic line editing facilities (delete/insert/cursor) are supported. * If edit_string() understands and uses the keypress it will return * zero, otherwise it will return the original key. * * This function does not update the display in any way. * * The string's edit history will be updated to allow the caller to * efficiently bring the display into sync with the string content. */ int edit_string ( struct edit_string *string, int key ) { int retval = 0; size_t len = strlen ( string->buf ); /* Prepare edit history */ string->last_cursor = string->cursor; string->mod_start = string->cursor; string->mod_end = string->cursor; /* Interpret key */ if ( ( key >= 0x20 ) && ( key <= 0x7e ) ) { /* Printable character; insert at current position */ insert_character ( string, key ); } else switch ( key ) { case KEY_BACKSPACE: /* Backspace */ backspace ( string ); break; case KEY_DC: case CTRL_D: /* Delete character */ delete_character ( string ); break; case CTRL_K: /* Delete to end of line */ kill_eol ( string ); break; case KEY_HOME: case CTRL_A: /* Start of line */ string->cursor = 0; break; case KEY_END: case CTRL_E: /* End of line */ string->cursor = len; break; case KEY_LEFT: case CTRL_B: /* Cursor left */ if ( string->cursor > 0 ) string->cursor--; break; case KEY_RIGHT: case CTRL_F: /* Cursor right */ if ( string->cursor < len ) string->cursor++; break; default: retval = key; break; } return retval; } ipxe-precise-1.0.0+git-2.55f6c88/src/hci/tui/0000775000175000017500000000000011701704160017160 5ustar sergesergeipxe-precise-1.0.0+git-2.55f6c88/src/hci/tui/settings_ui.c0000664000175000017500000003342711701704160021672 0ustar sergeserge/* * Copyright (C) 2006 Michael Brown . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include #include #include #include #include #include #include #include /** @file * * Option configuration console * */ /* Colour pairs */ #define CPAIR_NORMAL 1 #define CPAIR_SELECT 2 #define CPAIR_EDIT 3 #define CPAIR_ALERT 4 #define CPAIR_URL 5 /* Screen layout */ #define TITLE_ROW 1 #define SETTINGS_LIST_ROW 3 #define SETTINGS_LIST_COL 1 #define SETTINGS_LIST_ROWS 15 #define INFO_ROW 19 #define ALERT_ROW 22 #define INSTRUCTION_ROW 22 #define INSTRUCTION_PAD " " /** Layout of text within a setting widget */ struct setting_row_text { char start[0]; char pad1[1]; char name[15]; char pad2[1]; char value[60]; char pad3[1]; char nul; } __attribute__ (( packed )); /** A setting row widget */ struct setting_row_widget { /** Target configuration settings block * * Valid only for rows that lead to new settings blocks. */ struct settings *settings; /** Configuration setting * * Valid only for rows that represent individual settings. */ struct setting *setting; /** Screen row */ unsigned int row; /** Screen column */ unsigned int col; /** Edit box widget used for editing setting */ struct edit_box editbox; /** Editing in progress flag */ int editing; /** Setting originates from this block flag */ int originates_here; /** Buffer for setting's value */ char value[256]; /* enough size for a DHCP string */ }; /** A settings widget */ struct setting_widget { /** Settings block */ struct settings *settings; /** Number of rows */ unsigned int num_rows; /** Current row index */ unsigned int current; /** Index of the first visible row, for scrolling. */ unsigned int first_visible; /** Active row */ struct setting_row_widget row; }; /** * Select a setting row * * @v widget Setting widget * @v index Index of setting row * @ret count Number of settings rows */ static unsigned int select_setting_row ( struct setting_widget *widget, unsigned int index ) { struct settings *settings; struct settings *origin; struct setting *setting; unsigned int count = 0; /* Initialise structure */ memset ( &widget->row, 0, sizeof ( widget->row ) ); widget->current = index; widget->row.row = ( SETTINGS_LIST_ROW + index - widget->first_visible ); widget->row.col = SETTINGS_LIST_COL; /* Include parent settings block, if applicable */ if ( widget->settings->parent && ( count++ == index ) ) { widget->row.settings = widget->settings->parent; snprintf ( widget->row.value, sizeof ( widget->row.value ), "../" ); } /* Include any child settings blocks, if applicable */ list_for_each_entry ( settings, &widget->settings->children, siblings ){ if ( count++ == index ) { widget->row.settings = settings; snprintf ( widget->row.value, sizeof ( widget->row.value ), "%s/", settings->name ); } } /* Include any applicable settings */ for_each_table_entry ( setting, SETTINGS ) { if ( ! setting_applies ( widget->settings, setting ) ) continue; if ( count++ == index ) { widget->row.setting = setting; /* Read current setting value */ fetchf_setting ( widget->settings, widget->row.setting, widget->row.value, sizeof ( widget->row.value ) ); /* Check setting's origin */ origin = fetch_setting_origin ( widget->settings, widget->row.setting ); widget->row.originates_here = ( origin == widget->settings ); } } /* Initialise edit box */ init_editbox ( &widget->row.editbox, widget->row.value, sizeof ( widget->row.value ), NULL, widget->row.row, ( widget->row.col + offsetof ( struct setting_row_text, value ) ), sizeof ( ( ( struct setting_row_text * ) NULL )->value ), 0 ); return count; } static size_t string_copy ( char *dest, const char *src, size_t len ) { size_t src_len; src_len = strlen ( src ); if ( len > src_len ) len = src_len; memcpy ( dest, src, len ); return len; } /** * Draw setting row * * @v widget Setting widget */ static void draw_setting_row ( struct setting_widget *widget ) { struct setting_row_text text; unsigned int curs_offset; char *value; /* Fill row with spaces */ memset ( &text, ' ', sizeof ( text ) ); text.nul = '\0'; /* Construct row content */ if ( widget->row.settings ) { /* Construct space-padded name */ curs_offset = ( offsetof ( typeof ( text ), name ) + string_copy ( text.name, widget->row.value, sizeof ( text.name ) ) ); } else { /* Construct dot-padded name */ memset ( text.name, '.', sizeof ( text.name ) ); string_copy ( text.name, widget->row.setting->name, sizeof ( text.name ) ); /* Construct space-padded value */ value = widget->row.value; if ( ! *value ) value = ""; curs_offset = ( offsetof ( typeof ( text ), value ) + string_copy ( text.value, value, sizeof ( text.value ) ) ); } /* Print row */ if ( widget->row.originates_here || widget->row.settings ) attron ( A_BOLD ); mvprintw ( widget->row.row, widget->row.col, "%s", text.start ); attroff ( A_BOLD ); move ( widget->row.row, widget->row.col + curs_offset ); } /** * Edit setting widget * * @v widget Setting widget * @v key Key pressed by user * @ret key Key returned to application, or zero */ static int edit_setting ( struct setting_widget *widget, int key ) { assert ( widget->row.setting != NULL ); widget->row.editing = 1; return edit_editbox ( &widget->row.editbox, key ); } /** * Save setting widget value back to configuration settings * * @v widget Setting widget */ static int save_setting ( struct setting_widget *widget ) { assert ( widget->row.setting != NULL ); return storef_setting ( widget->settings, widget->row.setting, widget->row.value ); } /** * Print message centred on specified row * * @v row Row * @v fmt printf() format string * @v args printf() argument list */ static void vmsg ( unsigned int row, const char *fmt, va_list args ) { char buf[COLS]; size_t len; len = vsnprintf ( buf, sizeof ( buf ), fmt, args ); mvprintw ( row, ( ( COLS - len ) / 2 ), "%s", buf ); } /** * Print message centred on specified row * * @v row Row * @v fmt printf() format string * @v .. printf() arguments */ static void msg ( unsigned int row, const char *fmt, ... ) { va_list args; va_start ( args, fmt ); vmsg ( row, fmt, args ); va_end ( args ); } /** * Clear message on specified row * * @v row Row */ static void clearmsg ( unsigned int row ) { move ( row, 0 ); clrtoeol(); } /** * Print alert message * * @v fmt printf() format string * @v args printf() argument list */ static void valert ( const char *fmt, va_list args ) { clearmsg ( ALERT_ROW ); color_set ( CPAIR_ALERT, NULL ); vmsg ( ALERT_ROW, fmt, args ); sleep ( 2 ); color_set ( CPAIR_NORMAL, NULL ); clearmsg ( ALERT_ROW ); } /** * Print alert message * * @v fmt printf() format string * @v ... printf() arguments */ static void alert ( const char *fmt, ... ) { va_list args; va_start ( args, fmt ); valert ( fmt, args ); va_end ( args ); } /** * Draw title row * * @v widget Setting widget */ static void draw_title_row ( struct setting_widget *widget ) { const char *name; clearmsg ( TITLE_ROW ); name = settings_name ( widget->settings ); attron ( A_BOLD ); msg ( TITLE_ROW, "iPXE configuration settings%s%s", ( name[0] ? " - " : "" ), name ); attroff ( A_BOLD ); } /** * Draw information row * * @v widget Setting widget */ static void draw_info_row ( struct setting_widget *widget ) { struct settings *origin; char buf[32]; /* Draw nothing unless this row represents a setting */ clearmsg ( INFO_ROW ); clearmsg ( INFO_ROW + 1 ); if ( ! widget->row.setting ) return; /* Determine a suitable setting name */ origin = fetch_setting_origin ( widget->settings, widget->row.setting ); if ( ! origin ) origin = widget->settings; setting_name ( origin, widget->row.setting, buf, sizeof ( buf ) ); /* Draw row */ attron ( A_BOLD ); msg ( INFO_ROW, "%s - %s", buf, widget->row.setting->description ); attroff ( A_BOLD ); color_set ( CPAIR_URL, NULL ); msg ( ( INFO_ROW + 1 ), "http://ipxe.org/cfg/%s", widget->row.setting->name ); color_set ( CPAIR_NORMAL, NULL ); } /** * Draw instruction row * * @v widget Setting widget */ static void draw_instruction_row ( struct setting_widget *widget ) { clearmsg ( INSTRUCTION_ROW ); if ( widget->row.editing ) { msg ( INSTRUCTION_ROW, "Enter - accept changes" INSTRUCTION_PAD "Ctrl-C - discard changes" ); } else { msg ( INSTRUCTION_ROW, "%sCtrl-X - exit configuration utility", ( widget->row.originates_here ? "Ctrl-D - delete setting" INSTRUCTION_PAD : "" ) ); } } /** * Reveal setting row * * @v widget Setting widget * @v index Index of setting row */ static void reveal_setting_row ( struct setting_widget *widget, unsigned int index ) { unsigned int i; /* Simply return if setting N is already on-screen. */ if ( index - widget->first_visible < SETTINGS_LIST_ROWS ) return; /* Jump scroll to make the specified setting row visible. */ while ( widget->first_visible < index ) widget->first_visible += SETTINGS_LIST_ROWS; while ( widget->first_visible > index ) widget->first_visible -= SETTINGS_LIST_ROWS; /* Draw ellipses before and/or after the settings list to * represent any invisible settings. */ mvaddstr ( SETTINGS_LIST_ROW - 1, SETTINGS_LIST_COL + 1, widget->first_visible > 0 ? "..." : " " ); mvaddstr ( SETTINGS_LIST_ROW + SETTINGS_LIST_ROWS, SETTINGS_LIST_COL + 1, ( ( widget->first_visible + SETTINGS_LIST_ROWS ) < widget->num_rows ? "..." : " " ) ); /* Draw visible settings. */ for ( i = 0; i < SETTINGS_LIST_ROWS; i++ ) { if ( ( widget->first_visible + i ) < widget->num_rows ) { select_setting_row ( widget, widget->first_visible + i ); draw_setting_row ( widget ); } else { clearmsg ( SETTINGS_LIST_ROW + i ); } } } /** * Reveal setting row * * @v widget Setting widget * @v settings Settings block */ static void init_widget ( struct setting_widget *widget, struct settings *settings ) { widget->settings = settings; widget->num_rows = select_setting_row ( widget, 0 ); widget->first_visible = SETTINGS_LIST_ROWS; draw_title_row ( widget ); reveal_setting_row ( widget, 0 ); select_setting_row ( widget, 0 ); } static int main_loop ( struct settings *settings ) { struct setting_widget widget; int redraw = 1; int move; unsigned int next; int key; int rc; /* Print initial screen content */ color_set ( CPAIR_NORMAL, NULL ); memset ( &widget, 0, sizeof ( widget ) ); init_widget ( &widget, settings ); while ( 1 ) { /* Redraw rows if necessary */ if ( redraw ) { draw_info_row ( &widget ); draw_instruction_row ( &widget ); color_set ( ( widget.row.editing ? CPAIR_EDIT : CPAIR_SELECT ), NULL ); draw_setting_row ( &widget ); color_set ( CPAIR_NORMAL, NULL ); redraw = 0; } if ( widget.row.editing ) { /* Sanity check */ assert ( widget.row.setting != NULL ); /* Redraw edit box */ color_set ( CPAIR_EDIT, NULL ); draw_editbox ( &widget.row.editbox ); color_set ( CPAIR_NORMAL, NULL ); /* Process keypress */ key = edit_setting ( &widget, getkey ( 0 ) ); switch ( key ) { case CR: case LF: if ( ( rc = save_setting ( &widget ) ) != 0 ) alert ( " %s ", strerror ( rc ) ); /* Fall through */ case CTRL_C: select_setting_row ( &widget, widget.current ); redraw = 1; break; default: /* Do nothing */ break; } } else { /* Process keypress */ key = getkey ( 0 ); move = 0; switch ( key ) { case KEY_DOWN: if ( widget.current < ( widget.num_rows - 1 ) ) move = +1; break; case KEY_UP: if ( widget.current > 0 ) move = -1; break; case CTRL_D: if ( ! widget.row.setting ) break; if ( ( rc = delete_setting ( widget.settings, widget.row.setting ) ) != 0 ) { alert ( " %s ", strerror ( rc ) ); } select_setting_row ( &widget, widget.current ); redraw = 1; break; case CTRL_X: return 0; case CR: case LF: if ( widget.row.settings ) { init_widget ( &widget, widget.row.settings ); redraw = 1; } /* Fall through */ default: if ( widget.row.setting ) { edit_setting ( &widget, key ); redraw = 1; } break; } if ( move ) { next = ( widget.current + move ); draw_setting_row ( &widget ); redraw = 1; reveal_setting_row ( &widget, next ); select_setting_row ( &widget, next ); } } } } int settings_ui ( struct settings *settings ) { int rc; initscr(); start_color(); init_pair ( CPAIR_NORMAL, COLOR_WHITE, COLOR_BLUE ); init_pair ( CPAIR_SELECT, COLOR_WHITE, COLOR_RED ); init_pair ( CPAIR_EDIT, COLOR_BLACK, COLOR_CYAN ); init_pair ( CPAIR_ALERT, COLOR_WHITE, COLOR_RED ); init_pair ( CPAIR_URL, COLOR_CYAN, COLOR_BLUE ); color_set ( CPAIR_NORMAL, NULL ); erase(); rc = main_loop ( settings ); endwin(); return rc; } ipxe-precise-1.0.0+git-2.55f6c88/src/hci/tui/login_ui.c0000664000175000017500000000663511701704160021143 0ustar sergeserge/* * Copyright (C) 2009 Michael Brown . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); /** @file * * Login UI * */ #include #include #include #include #include #include #include #include /* Colour pairs */ #define CPAIR_NORMAL 1 #define CPAIR_LABEL 2 #define CPAIR_EDITBOX 3 /* Screen layout */ #define USERNAME_LABEL_ROW 8 #define USERNAME_ROW 10 #define PASSWORD_LABEL_ROW 14 #define PASSWORD_ROW 16 #define LABEL_COL 36 #define EDITBOX_COL 30 #define EDITBOX_WIDTH 20 int login_ui ( void ) { char username[64]; char password[64]; struct edit_box username_box; struct edit_box password_box; struct edit_box *current_box = &username_box; int key; int rc = -EINPROGRESS; /* Fetch current setting values */ fetch_string_setting ( NULL, &username_setting, username, sizeof ( username ) ); fetch_string_setting ( NULL, &password_setting, password, sizeof ( password ) ); /* Initialise UI */ initscr(); start_color(); init_pair ( CPAIR_NORMAL, COLOR_WHITE, COLOR_BLACK ); init_pair ( CPAIR_LABEL, COLOR_WHITE, COLOR_BLACK ); init_pair ( CPAIR_EDITBOX, COLOR_WHITE, COLOR_BLUE ); init_editbox ( &username_box, username, sizeof ( username ), NULL, USERNAME_ROW, EDITBOX_COL, EDITBOX_WIDTH, 0 ); init_editbox ( &password_box, password, sizeof ( password ), NULL, PASSWORD_ROW, EDITBOX_COL, EDITBOX_WIDTH, EDITBOX_STARS ); /* Draw initial UI */ erase(); color_set ( CPAIR_LABEL, NULL ); mvprintw ( USERNAME_LABEL_ROW, LABEL_COL, "Username:" ); mvprintw ( PASSWORD_LABEL_ROW, LABEL_COL, "Password:" ); color_set ( CPAIR_EDITBOX, NULL ); draw_editbox ( &username_box ); draw_editbox ( &password_box ); /* Main loop */ while ( rc == -EINPROGRESS ) { draw_editbox ( current_box ); key = getkey ( 0 ); switch ( key ) { case KEY_DOWN: current_box = &password_box; break; case KEY_UP: current_box = &username_box; break; case TAB: current_box = ( ( current_box == &username_box ) ? &password_box : &username_box ); break; case KEY_ENTER: if ( current_box == &username_box ) { current_box = &password_box; } else { rc = 0; } break; case CTRL_C: case ESC: rc = -ECANCELED; break; default: edit_editbox ( current_box, key ); break; } } /* Terminate UI */ color_set ( CPAIR_NORMAL, NULL ); erase(); endwin(); if ( rc != 0 ) return rc; /* Store settings */ if ( ( rc = store_setting ( NULL, &username_setting, username, strlen ( username ) ) ) != 0 ) return rc; if ( ( rc = store_setting ( NULL, &password_setting, password, strlen ( password ) ) ) != 0 ) return rc; return 0; } ipxe-precise-1.0.0+git-2.55f6c88/src/hci/keymap/0000775000175000017500000000000011701704160017645 5ustar sergesergeipxe-precise-1.0.0+git-2.55f6c88/src/hci/keymap/keymap_uk.c0000664000175000017500000000056711701704160022006 0ustar sergeserge/** @file * * "uk" keyboard mapping * * This file is automatically generated; do not edit * */ FILE_LICENCE ( PUBLIC_DOMAIN ); #include /** "uk" keyboard mapping */ struct key_mapping uk_mapping[] __keymap = { { 0x22, 0x40 }, /* '"' => '@' */ { 0x40, 0x22 }, /* '@' => '"' */ { 0x5c, 0x23 }, /* '\\' => '#' */ { 0x7c, 0x7e }, /* '|' => '~' */ }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/keymap/keymap_mk.c0000664000175000017500000000035611701704160021772 0ustar sergeserge/** @file * * "mk" keyboard mapping * * This file is automatically generated; do not edit * */ FILE_LICENCE ( PUBLIC_DOMAIN ); #include /** "mk" keyboard mapping */ struct key_mapping mk_mapping[] __keymap = { }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/keymap/keymap_us.c0000664000175000017500000000035611701704160022012 0ustar sergeserge/** @file * * "us" keyboard mapping * * This file is automatically generated; do not edit * */ FILE_LICENCE ( PUBLIC_DOMAIN ); #include /** "us" keyboard mapping */ struct key_mapping us_mapping[] __keymap = { }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/keymap/keymap_cf.c0000664000175000017500000000104211701704160021744 0ustar sergeserge/** @file * * "cf" keyboard mapping * * This file is automatically generated; do not edit * */ FILE_LICENCE ( PUBLIC_DOMAIN ); #include /** "cf" keyboard mapping */ struct key_mapping cf_mapping[] __keymap = { { 0x23, 0x2f }, /* '#' => '/' */ { 0x3c, 0x27 }, /* '<' => '\'' */ { 0x3e, 0x2e }, /* '>' => '.' */ { 0x40, 0x22 }, /* '@' => '"' */ { 0x5c, 0x3c }, /* '\\' => '<' */ { 0x5e, 0x3f }, /* '^' => '?' */ { 0x60, 0x23 }, /* '`' => '#' */ { 0x7c, 0x3e }, /* '|' => '>' */ { 0x7e, 0x7c }, /* '~' => '|' */ }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/keymap/keymap_gr.c0000664000175000017500000000035611701704160021773 0ustar sergeserge/** @file * * "gr" keyboard mapping * * This file is automatically generated; do not edit * */ FILE_LICENCE ( PUBLIC_DOMAIN ); #include /** "gr" keyboard mapping */ struct key_mapping gr_mapping[] __keymap = { }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/keymap/keymap_mt.c0000664000175000017500000000063411701704160022002 0ustar sergeserge/** @file * * "mt" keyboard mapping * * This file is automatically generated; do not edit * */ FILE_LICENCE ( PUBLIC_DOMAIN ); #include /** "mt" keyboard mapping */ struct key_mapping mt_mapping[] __keymap = { { 0x22, 0x40 }, /* '"' => '@' */ { 0x23, 0x04 }, /* '#' => Ctrl-D */ { 0x40, 0x22 }, /* '@' => '"' */ { 0x5c, 0x23 }, /* '\\' => '#' */ { 0x7c, 0x7e }, /* '|' => '~' */ }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/keymap/keymap_et.c0000664000175000017500000000136011701704160021767 0ustar sergeserge/** @file * * "et" keyboard mapping * * This file is automatically generated; do not edit * */ FILE_LICENCE ( PUBLIC_DOMAIN ); #include /** "et" keyboard mapping */ struct key_mapping et_mapping[] __keymap = { { 0x26, 0x2f }, /* '&' => '/' */ { 0x28, 0x29 }, /* '(' => ')' */ { 0x29, 0x3d }, /* ')' => '=' */ { 0x2a, 0x28 }, /* '*' => '(' */ { 0x2d, 0x2b }, /* '-' => '+' */ { 0x2f, 0x2d }, /* '/' => '-' */ { 0x3c, 0x3b }, /* '<' => ';' */ { 0x3e, 0x3a }, /* '>' => ':' */ { 0x3f, 0x5f }, /* '?' => '_' */ { 0x40, 0x22 }, /* '@' => '"' */ { 0x5c, 0x27 }, /* '\\' => '\'' */ { 0x5e, 0x26 }, /* '^' => '&' */ { 0x5f, 0x3f }, /* '_' => '?' */ { 0x7c, 0x2a }, /* '|' => '*' */ { 0x7f, 0x1b }, /* 0x7f => 0x1b */ }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/keymap/keymap_az.c0000664000175000017500000000104111701704160021765 0ustar sergeserge/** @file * * "az" keyboard mapping * * This file is automatically generated; do not edit * */ FILE_LICENCE ( PUBLIC_DOMAIN ); #include /** "az" keyboard mapping */ struct key_mapping az_mapping[] __keymap = { { 0x23, 0x27 }, /* '#' => '\'' */ { 0x24, 0x3b }, /* '$' => ';' */ { 0x26, 0x3f }, /* '&' => '?' */ { 0x2f, 0x2e }, /* '/' => '.' */ { 0x3a, 0x49 }, /* ':' => 'I' */ { 0x3f, 0x2c }, /* '?' => ',' */ { 0x40, 0x22 }, /* '@' => '"' */ { 0x5e, 0x3a }, /* '^' => ':' */ { 0x7c, 0x2f }, /* '|' => '/' */ }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/keymap/keymap_sr.c0000664000175000017500000000164311701704160022007 0ustar sergeserge/** @file * * "sr" keyboard mapping * * This file is automatically generated; do not edit * */ FILE_LICENCE ( PUBLIC_DOMAIN ); #include /** "sr" keyboard mapping */ struct key_mapping sr_mapping[] __keymap = { { 0x19, 0x1a }, /* Ctrl-Y => Ctrl-Z */ { 0x1a, 0x19 }, /* Ctrl-Z => Ctrl-Y */ { 0x26, 0x2f }, /* '&' => '/' */ { 0x28, 0x29 }, /* '(' => ')' */ { 0x29, 0x3d }, /* ')' => '=' */ { 0x2a, 0x28 }, /* '*' => '(' */ { 0x2b, 0x2a }, /* '+' => '*' */ { 0x2d, 0x27 }, /* '-' => '\'' */ { 0x2f, 0x2d }, /* '/' => '-' */ { 0x3c, 0x3b }, /* '<' => ';' */ { 0x3d, 0x2b }, /* '=' => '+' */ { 0x3e, 0x3a }, /* '>' => ':' */ { 0x3f, 0x5f }, /* '?' => '_' */ { 0x40, 0x22 }, /* '@' => '"' */ { 0x59, 0x5a }, /* 'Y' => 'Z' */ { 0x5a, 0x59 }, /* 'Z' => 'Y' */ { 0x5e, 0x26 }, /* '^' => '&' */ { 0x5f, 0x3f }, /* '_' => '?' */ { 0x79, 0x7a }, /* 'y' => 'z' */ { 0x7a, 0x79 }, /* 'z' => 'y' */ }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/keymap/keymap_no.c0000664000175000017500000000653011701704160021777 0ustar sergeserge/** @file * * "no" keyboard mapping * * This file is automatically generated; do not edit * */ FILE_LICENCE ( PUBLIC_DOMAIN ); #include /** "no" keyboard mapping */ struct key_mapping no_mapping[] __keymap = { { 0x02, 0x18 }, /* Ctrl-B => Ctrl-X */ { 0x03, 0x0a }, /* Ctrl-C => Ctrl-J */ { 0x04, 0x05 }, /* Ctrl-D => Ctrl-E */ { 0x06, 0x15 }, /* Ctrl-F => Ctrl-U */ { 0x07, 0x09 }, /* Ctrl-G => Ctrl-I */ { 0x08, 0x04 }, /* Ctrl-H => Ctrl-D */ { 0x0a, 0x08 }, /* Ctrl-J => Ctrl-H */ { 0x0b, 0x14 }, /* Ctrl-K => Ctrl-T */ { 0x0c, 0x0e }, /* Ctrl-L => Ctrl-N */ { 0x0e, 0x02 }, /* Ctrl-N => Ctrl-B */ { 0x0f, 0x12 }, /* Ctrl-O => Ctrl-R */ { 0x10, 0x0c }, /* Ctrl-P => Ctrl-L */ { 0x12, 0x10 }, /* Ctrl-R => Ctrl-P */ { 0x13, 0x0f }, /* Ctrl-S => Ctrl-O */ { 0x14, 0x19 }, /* Ctrl-T => Ctrl-Y */ { 0x15, 0x07 }, /* Ctrl-U => Ctrl-G */ { 0x16, 0x0b }, /* Ctrl-V => Ctrl-K */ { 0x18, 0x11 }, /* Ctrl-X => Ctrl-Q */ { 0x19, 0x06 }, /* Ctrl-Y => Ctrl-F */ { 0x22, 0x5f }, /* '"' => '_' */ { 0x26, 0x2f }, /* '&' => '/' */ { 0x27, 0x2d }, /* '\'' => '-' */ { 0x28, 0x29 }, /* '(' => ')' */ { 0x29, 0x3d }, /* ')' => '=' */ { 0x2a, 0x28 }, /* '*' => '(' */ { 0x2b, 0x60 }, /* '+' => '`' */ { 0x2c, 0x77 }, /* ',' => 'w' */ { 0x2d, 0x2b }, /* '-' => '+' */ { 0x2e, 0x76 }, /* '.' => 'v' */ { 0x2f, 0x7a }, /* '/' => 'z' */ { 0x3a, 0x53 }, /* ':' => 'S' */ { 0x3b, 0x73 }, /* ';' => 's' */ { 0x3c, 0x57 }, /* '<' => 'W' */ { 0x3d, 0x5c }, /* '=' => '\\' */ { 0x3e, 0x56 }, /* '>' => 'V' */ { 0x3f, 0x5a }, /* '?' => 'Z' */ { 0x40, 0x22 }, /* '@' => '"' */ { 0x42, 0x58 }, /* 'B' => 'X' */ { 0x43, 0x4a }, /* 'C' => 'J' */ { 0x44, 0x45 }, /* 'D' => 'E' */ { 0x45, 0x3a }, /* 'E' => ':' */ { 0x46, 0x55 }, /* 'F' => 'U' */ { 0x47, 0x49 }, /* 'G' => 'I' */ { 0x48, 0x44 }, /* 'H' => 'D' */ { 0x49, 0x43 }, /* 'I' => 'C' */ { 0x4a, 0x48 }, /* 'J' => 'H' */ { 0x4b, 0x54 }, /* 'K' => 'T' */ { 0x4c, 0x4e }, /* 'L' => 'N' */ { 0x4e, 0x42 }, /* 'N' => 'B' */ { 0x4f, 0x52 }, /* 'O' => 'R' */ { 0x50, 0x4c }, /* 'P' => 'L' */ { 0x52, 0x50 }, /* 'R' => 'P' */ { 0x53, 0x4f }, /* 'S' => 'O' */ { 0x54, 0x59 }, /* 'T' => 'Y' */ { 0x55, 0x47 }, /* 'U' => 'G' */ { 0x56, 0x4b }, /* 'V' => 'K' */ { 0x57, 0x3b }, /* 'W' => ';' */ { 0x58, 0x51 }, /* 'X' => 'Q' */ { 0x59, 0x46 }, /* 'Y' => 'F' */ { 0x5b, 0x27 }, /* '[' => '\'' */ { 0x5c, 0x3c }, /* '\\' => '<' */ { 0x5d, 0x7e }, /* ']' => '~' */ { 0x5e, 0x26 }, /* '^' => '&' */ { 0x5f, 0x3f }, /* '_' => '?' */ { 0x60, 0x7c }, /* '`' => '|' */ { 0x62, 0x78 }, /* 'b' => 'x' */ { 0x63, 0x6a }, /* 'c' => 'j' */ { 0x64, 0x65 }, /* 'd' => 'e' */ { 0x65, 0x2e }, /* 'e' => '.' */ { 0x66, 0x75 }, /* 'f' => 'u' */ { 0x67, 0x69 }, /* 'g' => 'i' */ { 0x68, 0x64 }, /* 'h' => 'd' */ { 0x69, 0x63 }, /* 'i' => 'c' */ { 0x6a, 0x68 }, /* 'j' => 'h' */ { 0x6b, 0x74 }, /* 'k' => 't' */ { 0x6c, 0x6e }, /* 'l' => 'n' */ { 0x6e, 0x62 }, /* 'n' => 'b' */ { 0x6f, 0x72 }, /* 'o' => 'r' */ { 0x70, 0x6c }, /* 'p' => 'l' */ { 0x72, 0x70 }, /* 'r' => 'p' */ { 0x73, 0x6f }, /* 's' => 'o' */ { 0x74, 0x79 }, /* 't' => 'y' */ { 0x75, 0x67 }, /* 'u' => 'g' */ { 0x76, 0x6b }, /* 'v' => 'k' */ { 0x77, 0x2c }, /* 'w' => ',' */ { 0x78, 0x71 }, /* 'x' => 'q' */ { 0x79, 0x66 }, /* 'y' => 'f' */ { 0x7b, 0x2a }, /* '{' => '*' */ { 0x7c, 0x3e }, /* '|' => '>' */ { 0x7d, 0x5e }, /* '}' => '^' */ }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/keymap/keymap_pt.c0000664000175000017500000000132211701704160022000 0ustar sergeserge/** @file * * "pt" keyboard mapping * * This file is automatically generated; do not edit * */ FILE_LICENCE ( PUBLIC_DOMAIN ); #include /** "pt" keyboard mapping */ struct key_mapping pt_mapping[] __keymap = { { 0x1c, 0x1d }, /* 0x1c => 0x1d */ { 0x1d, 0x1b }, /* 0x1d => 0x1b */ { 0x22, 0x5e }, /* '"' => '^' */ { 0x27, 0x7e }, /* '\'' => '~' */ { 0x2f, 0x3b }, /* '/' => ';' */ { 0x3f, 0x3a }, /* '?' => ':' */ { 0x5b, 0x27 }, /* '[' => '\'' */ { 0x5c, 0x5d }, /* '\\' => ']' */ { 0x5d, 0x5b }, /* ']' => '[' */ { 0x60, 0x27 }, /* '`' => '\'' */ { 0x7b, 0x60 }, /* '{' => '`' */ { 0x7c, 0x7d }, /* '|' => '}' */ { 0x7d, 0x7b }, /* '}' => '{' */ { 0x7e, 0x22 }, /* '~' => '"' */ }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/keymap/keymap_de.c0000664000175000017500000000243611701704160021754 0ustar sergeserge/** @file * * "de" keyboard mapping * * This file is automatically generated; do not edit * */ FILE_LICENCE ( PUBLIC_DOMAIN ); #include /** "de" keyboard mapping */ struct key_mapping de_mapping[] __keymap = { { 0x19, 0x1a }, /* Ctrl-Y => Ctrl-Z */ { 0x1a, 0x19 }, /* Ctrl-Z => Ctrl-Y */ { 0x22, 0x7d }, /* '"' => '}' */ { 0x26, 0x2f }, /* '&' => '/' */ { 0x27, 0x5d }, /* '\'' => ']' */ { 0x28, 0x29 }, /* '(' => ')' */ { 0x29, 0x3d }, /* ')' => '=' */ { 0x2a, 0x28 }, /* '*' => '(' */ { 0x2b, 0x60 }, /* '+' => '`' */ { 0x2d, 0x5c }, /* '-' => '\\' */ { 0x2f, 0x2d }, /* '/' => '-' */ { 0x3a, 0x7b }, /* ':' => '{' */ { 0x3b, 0x5b }, /* ';' => '[' */ { 0x3c, 0x3b }, /* '<' => ';' */ { 0x3d, 0x27 }, /* '=' => '\'' */ { 0x3e, 0x3a }, /* '>' => ':' */ { 0x3f, 0x5f }, /* '?' => '_' */ { 0x40, 0x22 }, /* '@' => '"' */ { 0x59, 0x5a }, /* 'Y' => 'Z' */ { 0x5a, 0x59 }, /* 'Z' => 'Y' */ { 0x5b, 0x40 }, /* '[' => '@' */ { 0x5c, 0x23 }, /* '\\' => '#' */ { 0x5d, 0x2b }, /* ']' => '+' */ { 0x5e, 0x26 }, /* '^' => '&' */ { 0x5f, 0x3f }, /* '_' => '?' */ { 0x60, 0x5e }, /* '`' => '^' */ { 0x79, 0x7a }, /* 'y' => 'z' */ { 0x7a, 0x79 }, /* 'z' => 'y' */ { 0x7b, 0x5c }, /* '{' => '\\' */ { 0x7c, 0x27 }, /* '|' => '\'' */ { 0x7d, 0x2a }, /* '}' => '*' */ }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/keymap/keymap_dk.c0000664000175000017500000000142011701704160021752 0ustar sergeserge/** @file * * "dk" keyboard mapping * * This file is automatically generated; do not edit * */ FILE_LICENCE ( PUBLIC_DOMAIN ); #include /** "dk" keyboard mapping */ struct key_mapping dk_mapping[] __keymap = { { 0x26, 0x2f }, /* '&' => '/' */ { 0x28, 0x29 }, /* '(' => ')' */ { 0x29, 0x3d }, /* ')' => '=' */ { 0x2a, 0x28 }, /* '*' => '(' */ { 0x2b, 0x60 }, /* '+' => '`' */ { 0x2d, 0x2b }, /* '-' => '+' */ { 0x2f, 0x2d }, /* '/' => '-' */ { 0x3c, 0x3b }, /* '<' => ';' */ { 0x3e, 0x3a }, /* '>' => ':' */ { 0x3f, 0x5f }, /* '?' => '_' */ { 0x40, 0x22 }, /* '@' => '"' */ { 0x5c, 0x27 }, /* '\\' => '\'' */ { 0x5e, 0x26 }, /* '^' => '&' */ { 0x5f, 0x3f }, /* '_' => '?' */ { 0x7c, 0x2a }, /* '|' => '*' */ { 0x7d, 0x5e }, /* '}' => '^' */ }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/keymap/keymap_ua.c0000664000175000017500000000035611701704160021770 0ustar sergeserge/** @file * * "ua" keyboard mapping * * This file is automatically generated; do not edit * */ FILE_LICENCE ( PUBLIC_DOMAIN ); #include /** "ua" keyboard mapping */ struct key_mapping ua_mapping[] __keymap = { }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/keymap/keymap_al.c0000664000175000017500000000150011701704160021747 0ustar sergeserge/** @file * * "al" keyboard mapping * * This file is automatically generated; do not edit * */ FILE_LICENCE ( PUBLIC_DOMAIN ); #include /** "al" keyboard mapping */ struct key_mapping al_mapping[] __keymap = { { 0x19, 0x1a }, /* Ctrl-Y => Ctrl-Z */ { 0x1a, 0x19 }, /* Ctrl-Z => Ctrl-Y */ { 0x22, 0x7b }, /* '"' => '{' */ { 0x27, 0x5b }, /* '\'' => '[' */ { 0x3c, 0x3b }, /* '<' => ';' */ { 0x3e, 0x3a }, /* '>' => ':' */ { 0x40, 0x22 }, /* '@' => '"' */ { 0x59, 0x5a }, /* 'Y' => 'Z' */ { 0x5a, 0x59 }, /* 'Z' => 'Y' */ { 0x5c, 0x5d }, /* '\\' => ']' */ { 0x5d, 0x40 }, /* ']' => '@' */ { 0x60, 0x5c }, /* '`' => '\\' */ { 0x79, 0x7a }, /* 'y' => 'z' */ { 0x7a, 0x79 }, /* 'z' => 'y' */ { 0x7c, 0x7d }, /* '|' => '}' */ { 0x7d, 0x27 }, /* '}' => '\'' */ { 0x7e, 0x7c }, /* '~' => '|' */ }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/keymap/keymap_ru.c0000664000175000017500000000035611701704160022011 0ustar sergeserge/** @file * * "ru" keyboard mapping * * This file is automatically generated; do not edit * */ FILE_LICENCE ( PUBLIC_DOMAIN ); #include /** "ru" keyboard mapping */ struct key_mapping ru_mapping[] __keymap = { }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/keymap/keymap_lt.c0000664000175000017500000000035611701704160022002 0ustar sergeserge/** @file * * "lt" keyboard mapping * * This file is automatically generated; do not edit * */ FILE_LICENCE ( PUBLIC_DOMAIN ); #include /** "lt" keyboard mapping */ struct key_mapping lt_mapping[] __keymap = { }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/keymap/keymap_by.c0000664000175000017500000000035611701704160021775 0ustar sergeserge/** @file * * "by" keyboard mapping * * This file is automatically generated; do not edit * */ FILE_LICENCE ( PUBLIC_DOMAIN ); #include /** "by" keyboard mapping */ struct key_mapping by_mapping[] __keymap = { }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/keymap/keymap_il.c0000664000175000017500000000035611701704160021767 0ustar sergeserge/** @file * * "il" keyboard mapping * * This file is automatically generated; do not edit * */ FILE_LICENCE ( PUBLIC_DOMAIN ); #include /** "il" keyboard mapping */ struct key_mapping il_mapping[] __keymap = { }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/keymap/keymap_pl.c0000664000175000017500000000035611701704160021776 0ustar sergeserge/** @file * * "pl" keyboard mapping * * This file is automatically generated; do not edit * */ FILE_LICENCE ( PUBLIC_DOMAIN ); #include /** "pl" keyboard mapping */ struct key_mapping pl_mapping[] __keymap = { }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/keymap/keymap_nl.c0000664000175000017500000000156611701704160022000 0ustar sergeserge/** @file * * "nl" keyboard mapping * * This file is automatically generated; do not edit * */ FILE_LICENCE ( PUBLIC_DOMAIN ); #include /** "nl" keyboard mapping */ struct key_mapping nl_mapping[] __keymap = { { 0x26, 0x5f }, /* '&' => '_' */ { 0x28, 0x29 }, /* '(' => ')' */ { 0x29, 0x27 }, /* ')' => '\'' */ { 0x2a, 0x28 }, /* '*' => '(' */ { 0x2b, 0x7e }, /* '+' => '~' */ { 0x2d, 0x2f }, /* '-' => '/' */ { 0x2f, 0x2d }, /* '/' => '-' */ { 0x3b, 0x2b }, /* ';' => '+' */ { 0x3c, 0x3b }, /* '<' => ';' */ { 0x3e, 0x3a }, /* '>' => ':' */ { 0x3f, 0x3d }, /* '?' => '=' */ { 0x40, 0x22 }, /* '@' => '"' */ { 0x5c, 0x3c }, /* '\\' => '<' */ { 0x5d, 0x2a }, /* ']' => '*' */ { 0x5e, 0x26 }, /* '^' => '&' */ { 0x5f, 0x3f }, /* '_' => '?' */ { 0x60, 0x40 }, /* '`' => '@' */ { 0x7c, 0x3e }, /* '|' => '>' */ { 0x7d, 0x7c }, /* '}' => '|' */ }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/keymap/keymap_hu.c0000664000175000017500000000160111701704160021771 0ustar sergeserge/** @file * * "hu" keyboard mapping * * This file is automatically generated; do not edit * */ FILE_LICENCE ( PUBLIC_DOMAIN ); #include /** "hu" keyboard mapping */ struct key_mapping hu_mapping[] __keymap = { { 0x19, 0x1a }, /* Ctrl-Y => Ctrl-Z */ { 0x1a, 0x19 }, /* Ctrl-Z => Ctrl-Y */ { 0x21, 0x27 }, /* '!' => '\'' */ { 0x23, 0x2b }, /* '#' => '+' */ { 0x24, 0x21 }, /* '$' => '!' */ { 0x26, 0x3d }, /* '&' => '=' */ { 0x28, 0x29 }, /* '(' => ')' */ { 0x2a, 0x28 }, /* '*' => '(' */ { 0x2f, 0x2d }, /* '/' => '-' */ { 0x3c, 0x3f }, /* '<' => '?' */ { 0x3e, 0x3a }, /* '>' => ':' */ { 0x3f, 0x5f }, /* '?' => '_' */ { 0x40, 0x22 }, /* '@' => '"' */ { 0x59, 0x5a }, /* 'Y' => 'Z' */ { 0x5a, 0x59 }, /* 'Z' => 'Y' */ { 0x5e, 0x2f }, /* '^' => '/' */ { 0x60, 0x30 }, /* '`' => '0' */ { 0x79, 0x7a }, /* 'y' => 'z' */ { 0x7a, 0x79 }, /* 'z' => 'y' */ }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/keymap/keymap_fi.c0000664000175000017500000000200111701704160021746 0ustar sergeserge/** @file * * "fi" keyboard mapping * * This file is automatically generated; do not edit * */ FILE_LICENCE ( PUBLIC_DOMAIN ); #include /** "fi" keyboard mapping */ struct key_mapping fi_mapping[] __keymap = { { 0x22, 0x5b }, /* '"' => '[' */ { 0x26, 0x2f }, /* '&' => '/' */ { 0x27, 0x7b }, /* '\'' => '{' */ { 0x28, 0x29 }, /* '(' => ')' */ { 0x29, 0x3d }, /* ')' => '=' */ { 0x2a, 0x28 }, /* '*' => '(' */ { 0x2b, 0x60 }, /* '+' => '`' */ { 0x2d, 0x2b }, /* '-' => '+' */ { 0x2f, 0x2d }, /* '/' => '-' */ { 0x3a, 0x5c }, /* ':' => '\\' */ { 0x3b, 0x7c }, /* ';' => '|' */ { 0x3c, 0x3b }, /* '<' => ';' */ { 0x3d, 0x27 }, /* '=' => '\'' */ { 0x3e, 0x3a }, /* '>' => ':' */ { 0x3f, 0x5f }, /* '?' => '_' */ { 0x40, 0x22 }, /* '@' => '"' */ { 0x5b, 0x7d }, /* '[' => '}' */ { 0x5c, 0x27 }, /* '\\' => '\'' */ { 0x5e, 0x26 }, /* '^' => '&' */ { 0x5f, 0x3f }, /* '_' => '?' */ { 0x7b, 0x5d }, /* '{' => ']' */ { 0x7c, 0x2a }, /* '|' => '*' */ { 0x7d, 0x5e }, /* '}' => '^' */ }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/keymap/keymap_es.c0000664000175000017500000000131311701704160021764 0ustar sergeserge/** @file * * "es" keyboard mapping * * This file is automatically generated; do not edit * */ FILE_LICENCE ( PUBLIC_DOMAIN ); #include /** "es" keyboard mapping */ struct key_mapping es_mapping[] __keymap = { { 0x26, 0x2f }, /* '&' => '/' */ { 0x28, 0x29 }, /* '(' => ')' */ { 0x29, 0x3d }, /* ')' => '=' */ { 0x2a, 0x28 }, /* '*' => '(' */ { 0x2d, 0x27 }, /* '-' => '\'' */ { 0x2f, 0x2d }, /* '/' => '-' */ { 0x3c, 0x3b }, /* '<' => ';' */ { 0x3e, 0x3a }, /* '>' => ':' */ { 0x3f, 0x5f }, /* '?' => '_' */ { 0x40, 0x22 }, /* '@' => '"' */ { 0x5d, 0x2b }, /* ']' => '+' */ { 0x5e, 0x26 }, /* '^' => '&' */ { 0x5f, 0x3f }, /* '_' => '?' */ { 0x7d, 0x2a }, /* '}' => '*' */ }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/keymap/keymap_wo.c0000664000175000017500000000312711701704160022007 0ustar sergeserge/** @file * * "wo" keyboard mapping * * This file is automatically generated; do not edit * */ FILE_LICENCE ( PUBLIC_DOMAIN ); #include /** "wo" keyboard mapping */ struct key_mapping wo_mapping[] __keymap = { { 0x01, 0x11 }, /* Ctrl-A => Ctrl-Q */ { 0x11, 0x01 }, /* Ctrl-Q => Ctrl-A */ { 0x17, 0x1a }, /* Ctrl-W => Ctrl-Z */ { 0x1a, 0x17 }, /* Ctrl-Z => Ctrl-W */ { 0x21, 0x31 }, /* '!' => '1' */ { 0x23, 0x33 }, /* '#' => '3' */ { 0x24, 0x34 }, /* '$' => '4' */ { 0x25, 0x35 }, /* '%' => '5' */ { 0x26, 0x37 }, /* '&' => '7' */ { 0x28, 0x39 }, /* '(' => '9' */ { 0x29, 0x30 }, /* ')' => '0' */ { 0x2a, 0x38 }, /* '*' => '8' */ { 0x2c, 0x3b }, /* ',' => ';' */ { 0x2d, 0x29 }, /* '-' => ')' */ { 0x2e, 0x3a }, /* '.' => ':' */ { 0x2f, 0x21 }, /* '/' => '!' */ { 0x31, 0x26 }, /* '1' => '&' */ { 0x33, 0x22 }, /* '3' => '"' */ { 0x34, 0x27 }, /* '4' => '\'' */ { 0x35, 0x28 }, /* '5' => '(' */ { 0x36, 0x2d }, /* '6' => '-' */ { 0x38, 0x5f }, /* '8' => '_' */ { 0x3a, 0x4d }, /* ':' => 'M' */ { 0x3b, 0x6d }, /* ';' => 'm' */ { 0x3c, 0x2e }, /* '<' => '.' */ { 0x3e, 0x2f }, /* '>' => '/' */ { 0x40, 0x32 }, /* '@' => '2' */ { 0x41, 0x51 }, /* 'A' => 'Q' */ { 0x4d, 0x3f }, /* 'M' => '?' */ { 0x51, 0x41 }, /* 'Q' => 'A' */ { 0x57, 0x5a }, /* 'W' => 'Z' */ { 0x5a, 0x57 }, /* 'Z' => 'W' */ { 0x5d, 0x24 }, /* ']' => '$' */ { 0x5e, 0x36 }, /* '^' => '6' */ { 0x61, 0x71 }, /* 'a' => 'q' */ { 0x6d, 0x2c }, /* 'm' => ',' */ { 0x71, 0x61 }, /* 'q' => 'a' */ { 0x77, 0x7a }, /* 'w' => 'z' */ { 0x7a, 0x77 }, /* 'z' => 'w' */ { 0x7e, 0x25 }, /* '~' => '%' */ }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/keymap/keymap_sg.c0000664000175000017500000000216011701704160021767 0ustar sergeserge/** @file * * "sg" keyboard mapping * * This file is automatically generated; do not edit * */ FILE_LICENCE ( PUBLIC_DOMAIN ); #include /** "sg" keyboard mapping */ struct key_mapping sg_mapping[] __keymap = { { 0x19, 0x1a }, /* Ctrl-Y => Ctrl-Z */ { 0x1a, 0x19 }, /* Ctrl-Z => Ctrl-Y */ { 0x21, 0x2b }, /* '!' => '+' */ { 0x23, 0x2a }, /* '#' => '*' */ { 0x24, 0x34 }, /* '$' => '4' */ { 0x26, 0x2f }, /* '&' => '/' */ { 0x28, 0x29 }, /* '(' => ')' */ { 0x29, 0x3d }, /* ')' => '=' */ { 0x2a, 0x28 }, /* '*' => '(' */ { 0x2b, 0x60 }, /* '+' => '`' */ { 0x2d, 0x27 }, /* '-' => '\'' */ { 0x2f, 0x2d }, /* '/' => '-' */ { 0x3c, 0x3b }, /* '<' => ';' */ { 0x3d, 0x5e }, /* '=' => '^' */ { 0x3e, 0x3a }, /* '>' => ':' */ { 0x3f, 0x5f }, /* '?' => '_' */ { 0x40, 0x22 }, /* '@' => '"' */ { 0x59, 0x5a }, /* 'Y' => 'Z' */ { 0x5a, 0x59 }, /* 'Z' => 'Y' */ { 0x5c, 0x24 }, /* '\\' => '$' */ { 0x5e, 0x26 }, /* '^' => '&' */ { 0x5f, 0x3f }, /* '_' => '?' */ { 0x79, 0x7a }, /* 'y' => 'z' */ { 0x7a, 0x79 }, /* 'z' => 'y' */ { 0x7c, 0x24 }, /* '|' => '$' */ { 0x7d, 0x21 }, /* '}' => '!' */ }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/keymap/keymap_bg.c0000664000175000017500000000035611701704160021753 0ustar sergeserge/** @file * * "bg" keyboard mapping * * This file is automatically generated; do not edit * */ FILE_LICENCE ( PUBLIC_DOMAIN ); #include /** "bg" keyboard mapping */ struct key_mapping bg_mapping[] __keymap = { }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/keymap/keymap_cz.c0000664000175000017500000000120611701704160021772 0ustar sergeserge/** @file * * "cz" keyboard mapping * * This file is automatically generated; do not edit * */ FILE_LICENCE ( PUBLIC_DOMAIN ); #include /** "cz" keyboard mapping */ struct key_mapping cz_mapping[] __keymap = { { 0x21, 0x2b }, /* '!' => '+' */ { 0x2d, 0x3d }, /* '-' => '=' */ { 0x2f, 0x2d }, /* '/' => '-' */ { 0x31, 0x2b }, /* '1' => '+' */ { 0x3c, 0x2c }, /* '<' => ',' */ { 0x3e, 0x2e }, /* '>' => '.' */ { 0x3f, 0x2d }, /* '?' => '-' */ { 0x5d, 0x29 }, /* ']' => ')' */ { 0x5f, 0x3d }, /* '_' => '=' */ { 0x60, 0x3b }, /* '`' => ';' */ { 0x7d, 0x29 }, /* '}' => ')' */ { 0x7e, 0x3b }, /* '~' => ';' */ }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/keymap/keymap_th.c0000664000175000017500000000035611701704160021776 0ustar sergeserge/** @file * * "th" keyboard mapping * * This file is automatically generated; do not edit * */ FILE_LICENCE ( PUBLIC_DOMAIN ); #include /** "th" keyboard mapping */ struct key_mapping th_mapping[] __keymap = { }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/keymap/keymap_it.c0000664000175000017500000000146211701704160021776 0ustar sergeserge/** @file * * "it" keyboard mapping * * This file is automatically generated; do not edit * */ FILE_LICENCE ( PUBLIC_DOMAIN ); #include /** "it" keyboard mapping */ struct key_mapping it_mapping[] __keymap = { { 0x26, 0x2f }, /* '&' => '/' */ { 0x28, 0x29 }, /* '(' => ')' */ { 0x29, 0x3d }, /* ')' => '=' */ { 0x2a, 0x28 }, /* '*' => '(' */ { 0x2b, 0x5e }, /* '+' => '^' */ { 0x2d, 0x27 }, /* '-' => '\'' */ { 0x2f, 0x2d }, /* '/' => '-' */ { 0x3c, 0x3b }, /* '<' => ';' */ { 0x3e, 0x3a }, /* '>' => ':' */ { 0x3f, 0x5f }, /* '?' => '_' */ { 0x40, 0x22 }, /* '@' => '"' */ { 0x5d, 0x2b }, /* ']' => '+' */ { 0x5e, 0x26 }, /* '^' => '&' */ { 0x5f, 0x3f }, /* '_' => '?' */ { 0x60, 0x5c }, /* '`' => '\\' */ { 0x7d, 0x2a }, /* '}' => '*' */ { 0x7e, 0x7c }, /* '~' => '|' */ }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/keymap/keymap_fr.c0000664000175000017500000000402411701704160021766 0ustar sergeserge/** @file * * "fr" keyboard mapping * * This file is automatically generated; do not edit * */ FILE_LICENCE ( PUBLIC_DOMAIN ); #include /** "fr" keyboard mapping */ struct key_mapping fr_mapping[] __keymap = { { 0x01, 0x11 }, /* Ctrl-A => Ctrl-Q */ { 0x11, 0x01 }, /* Ctrl-Q => Ctrl-A */ { 0x17, 0x1a }, /* Ctrl-W => Ctrl-Z */ { 0x1a, 0x17 }, /* Ctrl-Z => Ctrl-W */ { 0x21, 0x31 }, /* '!' => '1' */ { 0x22, 0x25 }, /* '"' => '%' */ { 0x23, 0x33 }, /* '#' => '3' */ { 0x24, 0x34 }, /* '$' => '4' */ { 0x25, 0x35 }, /* '%' => '5' */ { 0x26, 0x37 }, /* '&' => '7' */ { 0x27, 0x7c }, /* '\'' => '|' */ { 0x28, 0x39 }, /* '(' => '9' */ { 0x29, 0x30 }, /* ')' => '0' */ { 0x2a, 0x38 }, /* '*' => '8' */ { 0x2c, 0x3b }, /* ',' => ';' */ { 0x2d, 0x29 }, /* '-' => ')' */ { 0x2e, 0x3a }, /* '.' => ':' */ { 0x2f, 0x21 }, /* '/' => '!' */ { 0x30, 0x40 }, /* '0' => '@' */ { 0x31, 0x26 }, /* '1' => '&' */ { 0x32, 0x7b }, /* '2' => '{' */ { 0x33, 0x22 }, /* '3' => '"' */ { 0x34, 0x27 }, /* '4' => '\'' */ { 0x35, 0x28 }, /* '5' => '(' */ { 0x36, 0x2d }, /* '6' => '-' */ { 0x37, 0x7d }, /* '7' => '}' */ { 0x38, 0x5f }, /* '8' => '_' */ { 0x39, 0x2f }, /* '9' => '/' */ { 0x3a, 0x4d }, /* ':' => 'M' */ { 0x3b, 0x6d }, /* ';' => 'm' */ { 0x3c, 0x2e }, /* '<' => '.' */ { 0x3e, 0x2f }, /* '>' => '/' */ { 0x3f, 0x5c }, /* '?' => '\\' */ { 0x40, 0x32 }, /* '@' => '2' */ { 0x41, 0x51 }, /* 'A' => 'Q' */ { 0x4d, 0x3f }, /* 'M' => '?' */ { 0x51, 0x41 }, /* 'Q' => 'A' */ { 0x57, 0x5a }, /* 'W' => 'Z' */ { 0x5a, 0x57 }, /* 'Z' => 'W' */ { 0x5b, 0x5e }, /* '[' => '^' */ { 0x5c, 0x2a }, /* '\\' => '*' */ { 0x5d, 0x24 }, /* ']' => '$' */ { 0x5e, 0x36 }, /* '^' => '6' */ { 0x5f, 0x5d }, /* '_' => ']' */ { 0x60, 0x2a }, /* '`' => '*' */ { 0x61, 0x71 }, /* 'a' => 'q' */ { 0x6d, 0x2c }, /* 'm' => ',' */ { 0x71, 0x61 }, /* 'q' => 'a' */ { 0x77, 0x7a }, /* 'w' => 'z' */ { 0x7a, 0x77 }, /* 'z' => 'w' */ { 0x7b, 0x3c }, /* '{' => '<' */ { 0x7c, 0x23 }, /* '|' => '#' */ { 0x7d, 0x3e }, /* '}' => '>' */ }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/keymap/keymap_ro.c0000664000175000017500000000035611701704160022003 0ustar sergeserge/** @file * * "ro" keyboard mapping * * This file is automatically generated; do not edit * */ FILE_LICENCE ( PUBLIC_DOMAIN ); #include /** "ro" keyboard mapping */ struct key_mapping ro_mapping[] __keymap = { }; ipxe-precise-1.0.0+git-2.55f6c88/src/hci/shell.c0000664000175000017500000000576611701704160017650 0ustar sergeserge/* * Copyright (C) 2006 Michael Brown . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include #include #include #include #include #include #include /** @file * * Minimal command shell * */ /** The shell prompt string */ static const char shell_prompt[] = "iPXE> "; /** * "help" command * * @v argc Argument count * @v argv Argument list * @ret rc Return status code */ static int help_exec ( int argc __unused, char **argv __unused ) { struct command *command; unsigned int hpos = 0; printf ( "\nAvailable commands:\n\n" ); for_each_table_entry ( command, COMMANDS ) { hpos += printf ( " %s", command->name ); if ( hpos > ( 16 * 4 ) ) { printf ( "\n" ); hpos = 0; } else { while ( hpos % 16 ) { printf ( " " ); hpos++; } } } printf ( "\n\nType \" --help\" for further information\n\n" ); return 0; } /** "help" command */ struct command help_command __command = { .name = "help", .exec = help_exec, }; /** * Start command shell * */ int shell ( void ) { struct readline_history history; char *line; int rc = 0; /* Initialise shell history */ memset ( &history, 0, sizeof ( history ) ); /* Read and execute commands */ do { line = readline_history ( shell_prompt, &history ); if ( line ) { rc = system ( line ); free ( line ); } } while ( ! shell_stopped ( SHELL_STOP_COMMAND_SEQUENCE ) ); /* Discard shell history */ history_free ( &history ); return rc; } /** "shell" options */ struct shell_options {}; /** "shell" option list */ static struct option_descriptor shell_opts[] = {}; /** "shell" command descriptor */ static struct command_descriptor shell_cmd = COMMAND_DESC ( struct shell_options, shell_opts, 0, 0, "" ); /** * "shell" command * * @v argc Argument count * @v argv Argument list * @ret rc Return status code */ static int shell_exec ( int argc, char **argv ) { struct shell_options opts; int rc; /* Parse options */ if ( ( rc = parse_options ( argc, argv, &shell_cmd, &opts ) ) != 0 ) return rc; /* Start shell */ if ( ( rc = shell() ) != 0 ) return rc; return 0; } /** "shell" command */ struct command shell_command __command = { .name = "shell", .exec = shell_exec, }; ipxe-precise-1.0.0+git-2.55f6c88/src/config/0000775000175000017500000000000011701704160017061 5ustar sergesergeipxe-precise-1.0.0+git-2.55f6c88/src/config/sanboot.h0000664000175000017500000000034511701704160020701 0ustar sergeserge#ifndef CONFIG_SANBOOT_H #define CONFIG_SANBOOT_H /** @file * * sanboot API configuration * */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #endif /* CONFIG_SANBOOT_H */ ipxe-precise-1.0.0+git-2.55f6c88/src/config/serial.h0000664000175000017500000000151411701704160020512 0ustar sergeserge#ifndef CONFIG_SERIAL_H #define CONFIG_SERIAL_H /** @file * * Serial port configuration * * These options affect the operation of the serial console. They * take effect only if the serial console is included using the * CONSOLE_SERIAL option. * */ FILE_LICENCE ( GPL2_OR_LATER ); #define COM1 0x3f8 #define COM2 0x2f8 #define COM3 0x3e8 #define COM4 0x2e8 #define COMCONSOLE COM1 /* I/O port address */ /* Keep settings from a previous user of the serial port (e.g. lilo or * LinuxBIOS), ignoring COMSPEED, COMDATA, COMPARITY and COMSTOP. */ #undef COMPRESERVE #ifndef COMPRESERVE #define COMSPEED 115200 /* Baud rate */ #define COMDATA 8 /* Data bits */ #define COMPARITY 0 /* Parity: 0=None, 1=Odd, 2=Even */ #define COMSTOP 1 /* Stop bits */ #endif #include #endif /* CONFIG_SERIAL_H */ ipxe-precise-1.0.0+git-2.55f6c88/src/config/config_net80211.c0000664000175000017500000000155311701704160021740 0ustar sergeserge/* * 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, or (at * your option) any later version. */ FILE_LICENCE ( GPL2_OR_LATER ); #include /** @file * * 802.11 configuration options * */ /* * Drag in 802.11-specific commands * */ #ifdef IWMGMT_CMD REQUIRE_OBJECT ( iwmgmt_cmd ); #endif /* * Drag in 802.11 error message tables * */ #ifdef ERRMSG_80211 REQUIRE_OBJECT ( wireless_errors ); #endif /* * Drag in 802.11 cryptosystems and handshaking protocols * */ #ifdef CRYPTO_80211_WEP REQUIRE_OBJECT ( wep ); #endif #ifdef CRYPTO_80211_WPA2 #define CRYPTO_80211_WPA REQUIRE_OBJECT ( wpa_ccmp ); #endif #ifdef CRYPTO_80211_WPA REQUIRE_OBJECT ( wpa_psk ); REQUIRE_OBJECT ( wpa_tkip ); #endif ipxe-precise-1.0.0+git-2.55f6c88/src/config/nap.h0000664000175000017500000000036211701704160020011 0ustar sergeserge#ifndef CONFIG_NAP_H #define CONFIG_NAP_H /** @file * * CPU sleeping * */ FILE_LICENCE ( GPL2_OR_LATER ); #include //#undef NAP_PCBIOS //#define NAP_NULL #include #endif /* CONFIG_NAP_H */ ipxe-precise-1.0.0+git-2.55f6c88/src/config/defaults/0000775000175000017500000000000011701704160020670 5ustar sergesergeipxe-precise-1.0.0+git-2.55f6c88/src/config/defaults/efi.h0000664000175000017500000000067111701704160021610 0ustar sergeserge#ifndef CONFIG_DEFAULTS_EFI_H #define CONFIG_DEFAULTS_EFI_H /** @file * * Configuration defaults for EFI * */ #define UACCESS_EFI #define IOAPI_EFI #define PCIAPI_EFI #define CONSOLE_EFI #define TIMER_EFI #define NAP_EFIX86 #define UMALLOC_EFI #define SMBIOS_EFI #define SANBOOT_NULL #define BOFM_EFI #define IMAGE_EFI /* EFI image support */ #define IMAGE_SCRIPT /* iPXE script image support */ #endif /* CONFIG_DEFAULTS_EFI_H */ ipxe-precise-1.0.0+git-2.55f6c88/src/config/defaults/pcbios.h0000664000175000017500000000205511701704160022322 0ustar sergeserge#ifndef CONFIG_DEFAULTS_PCBIOS_H #define CONFIG_DEFAULTS_PCBIOS_H /** @file * * Configuration defaults for PCBIOS * */ FILE_LICENCE ( GPL2_OR_LATER ); #define UACCESS_LIBRM #define IOAPI_X86 #define PCIAPI_PCBIOS #define TIMER_PCBIOS #define CONSOLE_PCBIOS #define NAP_PCBIOS #define UMALLOC_MEMTOP #define SMBIOS_PCBIOS #define SANBOOT_PCBIOS #define IMAGE_ELF /* ELF image support */ #define IMAGE_MULTIBOOT /* MultiBoot image support */ #define IMAGE_PXE /* PXE image support */ #define IMAGE_SCRIPT /* iPXE script image support */ #define IMAGE_BZIMAGE /* Linux bzImage image support */ #define IMAGE_COMBOOT /* SYSLINUX COMBOOT image support */ #define PXE_STACK /* PXE stack in iPXE - required for PXELINUX */ #define PXE_MENU /* PXE menu booting */ #define SANBOOT_PROTO_ISCSI /* iSCSI protocol */ #define SANBOOT_PROTO_AOE /* AoE protocol */ #define SANBOOT_PROTO_IB_SRP /* Infiniband SCSI RDMA protocol */ #define SANBOOT_PROTO_FCP /* Fibre Channel protocol */ #define REBOOT_CMD /* Reboot command */ #endif /* CONFIG_DEFAULTS_PCBIOS_H */ ipxe-precise-1.0.0+git-2.55f6c88/src/config/defaults/linux.h0000664000175000017500000000053711701704160022205 0ustar sergeserge#ifndef CONFIG_DEFAULTS_LINUX_H #define CONFIG_DEFAULTS_LINUX_H /** @file * * Configuration defaults for linux * */ #define CONSOLE_LINUX #define TIMER_LINUX #define UACCESS_LINUX #define UMALLOC_LINUX #define NAP_LINUX #define SMBIOS_LINUX #define SANBOOT_NULL #define DRIVERS_LINUX #define IMAGE_SCRIPT #endif /* CONFIG_DEFAULTS_LINUX_H */ ipxe-precise-1.0.0+git-2.55f6c88/src/config/config_romprefix.c0000664000175000017500000000073611701704160022573 0ustar sergeserge/* * 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, or (at * your option) any later version. */ FILE_LICENCE ( GPL2_OR_LATER ); #include /** @file * * ROM prefix configuration options * */ /* * Provide UNDI loader if PXE stack is requested * */ #ifdef PXE_STACK REQUIRE_OBJECT ( undiloader ); #endif ipxe-precise-1.0.0+git-2.55f6c88/src/config/config_infiniband.c0000664000175000017500000000073211701704160022655 0ustar sergeserge/* * 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, or (at * your option) any later version. */ FILE_LICENCE ( GPL2_OR_LATER ); #include /** @file * * Infiniband configuration options * */ /* * Drag in Infiniband-specific protocols */ #ifdef SANBOOT_PROTO_IB_SRP REQUIRE_OBJECT ( ib_srp ); #endif ipxe-precise-1.0.0+git-2.55f6c88/src/config/config_fc.c0000664000175000017500000000111011701704160021133 0ustar sergeserge/* * 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, or (at * your option) any later version. */ FILE_LICENCE ( GPL2_OR_LATER ); #include /** @file * * Fibre Channel configuration options * */ /* * Drag in Fibre Channel-specific commands * */ #ifdef FCMGMT_CMD REQUIRE_OBJECT ( fcmgmt_cmd ); #endif /* * Drag in Fibre Channel-specific protocols */ #ifdef SANBOOT_PROTO_FCP REQUIRE_OBJECT ( fcp ); #endif ipxe-precise-1.0.0+git-2.55f6c88/src/config/sideband.h0000664000175000017500000000036511701704160021007 0ustar sergeserge#ifndef CONFIG_SIDEBAND_H #define CONFIG_SIDEBAND_H /** @file * * Sideband access by platform firmware * */ FILE_LICENCE ( GPL2_OR_LATER ); //#define CONFIG_BOFM /* IBM's BladeCenter Open Fabric Manager */ #endif /* CONFIG_SIDEBAND_H */ ipxe-precise-1.0.0+git-2.55f6c88/src/config/config_ethernet.c0000664000175000017500000000100611701704160022365 0ustar sergeserge/* * 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, or (at * your option) any later version. */ FILE_LICENCE ( GPL2_OR_LATER ); #include /** @file * * Ethernet configuration options * */ /* * Drag in Ethernet-specific protocols */ #ifdef SANBOOT_PROTO_AOE REQUIRE_OBJECT ( aoe ); #endif #ifdef NET_PROTO_FCOE REQUIRE_OBJECT ( fcoe ); #endif ipxe-precise-1.0.0+git-2.55f6c88/src/config/ioapi.h0000664000175000017500000000051511701704160020334 0ustar sergeserge#ifndef CONFIG_IOAPI_H #define CONFIG_IOAPI_H /** @file * * I/O API configuration * */ FILE_LICENCE ( GPL2_OR_LATER ); #include //#undef PCIAPI_PCBIOS /* Access via PCI BIOS */ //#define PCIAPI_DIRECT /* Direct access via Type 1 accesses */ #include #endif /* CONFIG_IOAPI_H */ ipxe-precise-1.0.0+git-2.55f6c88/src/config/config.c0000664000175000017500000001314711701704160020500 0ustar sergeserge/* * 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, or (at * your option) any later version. */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include /** @file * * Configuration options * * This file contains macros that pull various objects into the link * based on definitions in configuration header files. Ideally it * should be the only place in iPXE where one might need to use #ifdef * for compile-time options. * * In the fairly common case where an object should only be considered * for inclusion if the subsystem it depends on is present, its * configuration macros should be placed in a file named * config_subsystem.c, where @e subsystem is the * object basename of the main source file for that subsystem. The * build system will pull in that file if @c subsystem.c is included * in the final iPXE executable built. */ /* * Build ID string calculations * */ #undef XSTR #undef STR #define XSTR(s) STR(s) #define STR(s) #s #ifdef BUILD_SERIAL #include "config/.buildserial.h" #define BUILD_SERIAL_STR " #" XSTR(BUILD_SERIAL_NUM) #else #define BUILD_SERIAL_STR "" #endif #ifdef BUILD_ID #define BUILD_ID_STR " " BUILD_ID #else #define BUILD_ID_STR "" #endif #if defined(BUILD_ID) || defined(BUILD_SERIAL) #define BUILD_STRING " [build" BUILD_ID_STR BUILD_SERIAL_STR "]" #else #define BUILD_STRING "" #endif /* * Drag in all requested console types * */ #ifdef CONSOLE_PCBIOS REQUIRE_OBJECT ( bios_console ); #endif #ifdef CONSOLE_SERIAL REQUIRE_OBJECT ( serial_console ); #endif #ifdef CONSOLE_DIRECT_VGA REQUIRE_OBJECT ( video_subr ); #endif #ifdef CONSOLE_BTEXT REQUIRE_OBJECT ( btext ); #endif #ifdef CONSOLE_PC_KBD REQUIRE_OBJECT ( pc_kbd ); #endif #ifdef CONSOLE_SYSLOG REQUIRE_OBJECT ( syslog ); #endif #ifdef CONSOLE_EFI REQUIRE_OBJECT ( efi_console ); #endif #ifdef CONSOLE_LINUX REQUIRE_OBJECT ( linux_console ); #endif /* * Drag in all requested network protocols * */ #ifdef NET_PROTO_IPV4 REQUIRE_OBJECT ( ipv4 ); #endif /* * Drag in all requested PXE support * */ #ifdef PXE_MENU REQUIRE_OBJECT ( pxemenu ); #endif #ifdef PXE_STACK REQUIRE_OBJECT ( pxe_call ); #endif /* * Drag in all requested download protocols * */ #ifdef DOWNLOAD_PROTO_TFTP REQUIRE_OBJECT ( tftp ); #endif #ifdef DOWNLOAD_PROTO_HTTP REQUIRE_OBJECT ( http ); #endif #ifdef DOWNLOAD_PROTO_HTTPS REQUIRE_OBJECT ( https ); #endif #ifdef DOWNLOAD_PROTO_FTP REQUIRE_OBJECT ( ftp ); #endif #ifdef DOWNLOAD_PROTO_TFTM REQUIRE_OBJECT ( tftm ); #endif #ifdef DOWNLOAD_PROTO_SLAM REQUIRE_OBJECT ( slam ); #endif /* * Drag in all requested SAN boot protocols * */ #ifdef SANBOOT_PROTO_ISCSI REQUIRE_OBJECT ( iscsi ); #endif /* * Drag in all requested resolvers * */ #ifdef DNS_RESOLVER REQUIRE_OBJECT ( dns ); #endif /* * Drag in all requested image formats * */ #ifdef IMAGE_NBI REQUIRE_OBJECT ( nbi ); #endif #ifdef IMAGE_ELF REQUIRE_OBJECT ( elfboot ); #endif #ifdef IMAGE_FREEBSD REQUIRE_OBJECT ( freebsd ); #endif #ifdef IMAGE_MULTIBOOT REQUIRE_OBJECT ( multiboot ); #endif #ifdef IMAGE_AOUT REQUIRE_OBJECT ( aout ); #endif #ifdef IMAGE_WINCE REQUIRE_OBJECT ( wince ); #endif #ifdef IMAGE_PXE REQUIRE_OBJECT ( pxe_image ); #endif #ifdef IMAGE_SCRIPT REQUIRE_OBJECT ( script ); #endif #ifdef IMAGE_BZIMAGE REQUIRE_OBJECT ( bzimage ); #endif #ifdef IMAGE_ELTORITO REQUIRE_OBJECT ( eltorito ); #endif #ifdef IMAGE_COMBOOT REQUIRE_OBJECT ( comboot ); REQUIRE_OBJECT ( com32 ); REQUIRE_OBJECT ( comboot_call ); REQUIRE_OBJECT ( com32_call ); REQUIRE_OBJECT ( com32_wrapper ); REQUIRE_OBJECT ( comboot_resolv ); #endif #ifdef IMAGE_EFI REQUIRE_OBJECT ( efi_image ); #endif /* * Drag in all requested commands * */ #ifdef AUTOBOOT_CMD REQUIRE_OBJECT ( autoboot_cmd ); #endif #ifdef NVO_CMD REQUIRE_OBJECT ( nvo_cmd ); #endif #ifdef CONFIG_CMD REQUIRE_OBJECT ( config_cmd ); #endif #ifdef IFMGMT_CMD REQUIRE_OBJECT ( ifmgmt_cmd ); #endif /* IWMGMT_CMD is brought in by net80211.c if requested */ #ifdef ROUTE_CMD REQUIRE_OBJECT ( route_cmd ); #endif #ifdef IMAGE_CMD REQUIRE_OBJECT ( image_cmd ); #endif #ifdef DHCP_CMD REQUIRE_OBJECT ( dhcp_cmd ); #endif #ifdef SANBOOT_CMD REQUIRE_OBJECT ( sanboot_cmd ); #endif #ifdef LOGIN_CMD REQUIRE_OBJECT ( login_cmd ); #endif #ifdef TIME_CMD REQUIRE_OBJECT ( time_cmd ); #endif #ifdef DIGEST_CMD REQUIRE_OBJECT ( digest_cmd ); #endif #ifdef PXE_CMD REQUIRE_OBJECT ( pxe_cmd ); #endif #ifdef LOTEST_CMD REQUIRE_OBJECT ( lotest_cmd ); #endif #ifdef VLAN_CMD REQUIRE_OBJECT ( vlan_cmd ); #endif #ifdef REBOOT_CMD REQUIRE_OBJECT ( reboot_cmd ); #endif /* * Drag in miscellaneous objects * */ #ifdef NULL_TRAP REQUIRE_OBJECT ( nulltrap ); #endif #ifdef GDBSERIAL REQUIRE_OBJECT ( gdbidt ); REQUIRE_OBJECT ( gdbserial ); REQUIRE_OBJECT ( gdbstub_cmd ); #endif #ifdef GDBUDP REQUIRE_OBJECT ( gdbidt ); REQUIRE_OBJECT ( gdbudp ); REQUIRE_OBJECT ( gdbstub_cmd ); #endif /* * Drag in objects that are always required, but not dragged in via * symbol dependencies. * */ REQUIRE_OBJECT ( device ); REQUIRE_OBJECT ( embedded ); /* linux drivers aren't picked up by the parserom utility so drag them in here */ #ifdef DRIVERS_LINUX REQUIRE_OBJECT ( tap ); #endif /* * Drag in relevant BOFM entry points */ #ifdef CONFIG_BOFM #ifdef BOFM_EFI REQUIRE_OBJECT ( efi_bofm ); #endif /* BOFM_EFI */ #endif /* CONFIG_BOFM */ /* * Drag in selected keyboard map */ #define REQUIRE_KEYMAP_OBJECT( _map ) REQUIRE_OBJECT ( keymap_ ## _map ) #define REQUIRE_KEYMAP( _map ) REQUIRE_KEYMAP_OBJECT ( _map ) REQUIRE_KEYMAP ( KEYBOARD_MAP ); ipxe-precise-1.0.0+git-2.55f6c88/src/config/console.h0000664000175000017500000000124611701704160020677 0ustar sergeserge#ifndef CONFIG_CONSOLE_H #define CONFIG_CONSOLE_H /** @file * * Console configuration * * These options specify the console types that Etherboot will use for * interaction with the user. * */ FILE_LICENCE ( GPL2_OR_LATER ); #include //#define CONSOLE_PCBIOS /* Default BIOS console */ //#define CONSOLE_SERIAL /* Serial port */ //#define CONSOLE_DIRECT_VGA /* Direct access to VGA card */ //#define CONSOLE_BTEXT /* Who knows what this does? */ //#define CONSOLE_PC_KBD /* Direct access to PC keyboard */ //#define CONSOLE_SYSLOG /* Syslog console */ #define KEYBOARD_MAP us #include #endif /* CONFIG_CONSOLE_H */ ipxe-precise-1.0.0+git-2.55f6c88/src/config/isa.h0000664000175000017500000000054211701704160020007 0ustar sergeserge#ifndef CONFIG_ISA_H #define CONFIG_ISA_H /** @file * * ISA probe address configuration * * You can override the list of addresses that will be probed by any * ISA drivers. * */ #undef ISA_PROBE_ADDRS /* e.g. 0x200, 0x300 */ #undef ISA_PROBE_ONLY /* Do not probe any other addresses */ #include #endif /* CONFIG_ISA_H */ ipxe-precise-1.0.0+git-2.55f6c88/src/config/umalloc.h0000664000175000017500000000036411701704160020671 0ustar sergeserge#ifndef CONFIG_UMALLOC_H #define CONFIG_UMALLOC_H /** @file * * User memory allocation API configuration * */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #endif /* CONFIG_UMALLOC_H */ ipxe-precise-1.0.0+git-2.55f6c88/src/config/local/0000775000175000017500000000000011701704160020153 5ustar sergesergeipxe-precise-1.0.0+git-2.55f6c88/src/config/local/.gitignore0000664000175000017500000000000211701704160022133 0ustar sergeserge* ipxe-precise-1.0.0+git-2.55f6c88/src/config/general.h0000664000175000017500000001073211701704160020652 0ustar sergeserge#ifndef CONFIG_GENERAL_H #define CONFIG_GENERAL_H /** @file * * General configuration * */ FILE_LICENCE ( GPL2_OR_LATER ); #include /* * Branding * * Vendors may use these strings to add their own branding to iPXE. * PRODUCT_NAME is displayed prior to any iPXE branding in startup * messages, and PRODUCT_SHORT_NAME is used where a brief product * label is required (e.g. in BIOS boot selection menus). * * To minimise end-user confusion, it's probably a good idea to either * make PRODUCT_SHORT_NAME a substring of PRODUCT_NAME or leave it as * "iPXE". * */ #define PRODUCT_NAME "" #define PRODUCT_SHORT_NAME "iPXE" /* * Timer configuration * */ #define BANNER_TIMEOUT 20 /* Tenths of a second for which the shell banner should appear */ /* * Network protocols * */ #define NET_PROTO_IPV4 /* IPv4 protocol */ #undef NET_PROTO_FCOE /* Fibre Channel over Ethernet protocol */ /* * PXE support * */ //#undef PXE_STACK /* PXE stack in iPXE - you want this! */ //#undef PXE_MENU /* PXE menu booting */ /* * Download protocols * */ #define DOWNLOAD_PROTO_TFTP /* Trivial File Transfer Protocol */ #define DOWNLOAD_PROTO_HTTP /* Hypertext Transfer Protocol */ #undef DOWNLOAD_PROTO_HTTPS /* Secure Hypertext Transfer Protocol */ #undef DOWNLOAD_PROTO_FTP /* File Transfer Protocol */ #undef DOWNLOAD_PROTO_TFTM /* Multicast Trivial File Transfer Protocol */ #undef DOWNLOAD_PROTO_SLAM /* Scalable Local Area Multicast */ /* * SAN boot protocols * */ //#undef SANBOOT_PROTO_ISCSI /* iSCSI protocol */ //#undef SANBOOT_PROTO_AOE /* AoE protocol */ //#undef SANBOOT_PROTO_IB_SRP /* Infiniband SCSI RDMA protocol */ //#undef SANBOOT_PROTO_FCP /* Fibre Channel protocol */ /* * 802.11 cryptosystems and handshaking protocols * */ #define CRYPTO_80211_WEP /* WEP encryption (deprecated and insecure!) */ #define CRYPTO_80211_WPA /* WPA Personal, authenticating with passphrase */ #define CRYPTO_80211_WPA2 /* Add support for stronger WPA cryptography */ /* * Name resolution modules * */ #define DNS_RESOLVER /* DNS resolver */ /* * Image types * * Etherboot supports various image formats. Select whichever ones * you want to use. * */ //#define IMAGE_NBI /* NBI image support */ //#define IMAGE_ELF /* ELF image support */ //#define IMAGE_FREEBSD /* FreeBSD kernel image support */ //#define IMAGE_MULTIBOOT /* MultiBoot image support */ //#define IMAGE_AOUT /* a.out image support */ //#define IMAGE_WINCE /* WinCE image support */ //#define IMAGE_PXE /* PXE image support */ //#define IMAGE_SCRIPT /* iPXE script image support */ //#define IMAGE_BZIMAGE /* Linux bzImage image support */ //#define IMAGE_COMBOOT /* SYSLINUX COMBOOT image support */ //#define IMAGE_EFI /* EFI image support */ /* * Command-line commands to include * */ #define AUTOBOOT_CMD /* Automatic booting */ #define NVO_CMD /* Non-volatile option storage commands */ #define CONFIG_CMD /* Option configuration console */ #define IFMGMT_CMD /* Interface management commands */ #define IWMGMT_CMD /* Wireless interface management commands */ #define FCMGMT_CMD /* Fibre Channel management commands */ #define ROUTE_CMD /* Routing table management commands */ #define IMAGE_CMD /* Image management commands */ #define DHCP_CMD /* DHCP management commands */ #define SANBOOT_CMD /* SAN boot commands */ #define LOGIN_CMD /* Login command */ //#define TIME_CMD /* Time commands */ //#define DIGEST_CMD /* Image crypto digest commands */ //#define LOTEST_CMD /* Loopback testing commands */ //#define VLAN_CMD /* VLAN commands */ //#define PXE_CMD /* PXE commands */ //#define REBOOT_CMD /* Reboot command */ /* * ROM-specific options * */ #undef NONPNP_HOOK_INT19 /* Hook INT19 on non-PnP BIOSes */ /* * Error message tables to include * */ #undef ERRMSG_80211 /* All 802.11 error descriptions (~3.3kb) */ /* * Obscure configuration options * * You probably don't need to touch these. * */ #define NETDEV_DISCARD_RATE 0 /* Drop every N packets (0=>no drop) */ #undef BUILD_SERIAL /* Include an automatic build serial * number. Add "bs" to the list of * make targets. For example: * "make bin/rtl8139.dsk bs" */ #undef BUILD_ID /* Include a custom build ID string, * e.g "test-foo" */ #undef NULL_TRAP /* Attempt to catch NULL function calls */ #undef GDBSERIAL /* Remote GDB debugging over serial */ #undef GDBUDP /* Remote GDB debugging over UDP * (both may be set) */ #include #endif /* CONFIG_GENERAL_H */ ipxe-precise-1.0.0+git-2.55f6c88/src/config/.gitignore0000664000175000017500000000001711701704160021047 0ustar sergeserge.buildserial.* ipxe-precise-1.0.0+git-2.55f6c88/src/config/timer.h0000664000175000017500000000040711701704160020353 0ustar sergeserge#ifndef CONFIG_TIMER_H #define CONFIG_TIMER_H /** @file * * Timer configuration. * */ FILE_LICENCE ( GPL2_OR_LATER ); #include //#undef TIMER_PCBIOS //#define TIMER_RDTSC #include #endif /* CONFIG_TIMER_H */ ipxe-precise-1.0.0+git-2.55f6c88/src/config/defaults.h0000664000175000017500000000033311701704160021040 0ustar sergeserge#ifndef CONFIG_DEFAULTS_H #define CONFIG_DEFAULTS_H FILE_LICENCE ( GPL2_OR_LATER ); #define CONFIG_DEFAULTS(_platform) #include CONFIG_DEFAULTS(PLATFORM) #endif /* CONFIG_DEFAULTS_H */ ipxe-precise-1.0.0+git-2.55f6c88/src/image/0000775000175000017500000000000011701704160016676 5ustar sergesergeipxe-precise-1.0.0+git-2.55f6c88/src/image/elf.c0000664000175000017500000001070611701704160017614 0ustar sergeserge/* * Copyright (C) 2007 Michael Brown . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); /** * @file * * ELF image format * * A "pure" ELF image is not a bootable image. There are various * bootable formats based upon ELF (e.g. Multiboot), which share * common ELF-related functionality. */ #include #include #include #include #include #include typedef Elf32_Ehdr Elf_Ehdr; typedef Elf32_Phdr Elf_Phdr; typedef Elf32_Off Elf_Off; /** * Load ELF segment into memory * * @v image ELF file * @v phdr ELF program header * @v ehdr ELF executable header * @ret entry Entry point, if found * @ret rc Return status code */ static int elf_load_segment ( struct image *image, Elf_Phdr *phdr, Elf_Ehdr *ehdr, physaddr_t *entry ) { physaddr_t dest; userptr_t buffer; unsigned long e_offset; int rc; /* Do nothing for non-PT_LOAD segments */ if ( phdr->p_type != PT_LOAD ) return 0; /* Check segment lies within image */ if ( ( phdr->p_offset + phdr->p_filesz ) > image->len ) { DBGC ( image, "ELF %p segment outside image\n", image ); return -ENOEXEC; } /* Find start address: use physical address for preference, * fall back to virtual address if no physical address * supplied. */ dest = phdr->p_paddr; if ( ! dest ) dest = phdr->p_vaddr; if ( ! dest ) { DBGC ( image, "ELF %p segment loads to physical address 0\n", image ); return -ENOEXEC; } buffer = phys_to_user ( dest ); DBGC ( image, "ELF %p loading segment [%x,%x) to [%x,%x,%x)\n", image, phdr->p_offset, ( phdr->p_offset + phdr->p_filesz ), phdr->p_paddr, ( phdr->p_paddr + phdr->p_filesz ), ( phdr->p_paddr + phdr->p_memsz ) ); /* Verify and prepare segment */ if ( ( rc = prep_segment ( buffer, phdr->p_filesz, phdr->p_memsz ) ) != 0 ) { DBGC ( image, "ELF %p could not prepare segment: %s\n", image, strerror ( rc ) ); return rc; } /* Copy image to segment */ memcpy_user ( buffer, 0, image->data, phdr->p_offset, phdr->p_filesz ); /* Set execution address, if it lies within this segment */ if ( ( e_offset = ( ehdr->e_entry - dest ) ) < phdr->p_filesz ) { *entry = ehdr->e_entry; DBGC ( image, "ELF %p found physical entry point at %lx\n", image, *entry ); } else if ( ( e_offset = ( ehdr->e_entry - phdr->p_vaddr ) ) < phdr->p_filesz ) { if ( ! *entry ) { *entry = ( dest + e_offset ); DBGC ( image, "ELF %p found virtual entry point at %lx" " (virt %lx)\n", image, *entry, ( ( unsigned long ) ehdr->e_entry ) ); } } return 0; } /** * Load ELF image into memory * * @v image ELF file * @ret entry Entry point * @ret rc Return status code */ int elf_load ( struct image *image, physaddr_t *entry ) { Elf_Ehdr ehdr; Elf_Phdr phdr; Elf_Off phoff; unsigned int phnum; int rc; /* Read ELF header */ copy_from_user ( &ehdr, image->data, 0, sizeof ( ehdr ) ); if ( memcmp ( &ehdr.e_ident[EI_MAG0], ELFMAG, SELFMAG ) != 0 ) { DBGC ( image, "ELF %p has invalid signature\n", image ); return -ENOEXEC; } /* Invalidate entry point */ *entry = 0; /* Read ELF program headers */ for ( phoff = ehdr.e_phoff , phnum = ehdr.e_phnum ; phnum ; phoff += ehdr.e_phentsize, phnum-- ) { if ( phoff > image->len ) { DBGC ( image, "ELF %p program header %d outside " "image\n", image, phnum ); return -ENOEXEC; } copy_from_user ( &phdr, image->data, phoff, sizeof ( phdr ) ); if ( ( rc = elf_load_segment ( image, &phdr, &ehdr, entry ) ) != 0 ) { return rc; } } /* Check for a valid execution address */ if ( ! *entry ) { DBGC ( image, "ELF %p entry point %lx outside image\n", image, ( ( unsigned long ) ehdr.e_entry ) ); return -ENOEXEC; } return 0; } ipxe-precise-1.0.0+git-2.55f6c88/src/image/script.c0000664000175000017500000001741211701704160020353 0ustar sergeserge/* * Copyright (C) 2007 Michael Brown . * * 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 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. */ FILE_LICENCE ( GPL2_OR_LATER ); /** * @file * * iPXE scripts * */ #include #include #include #include #include #include #include #include #include #include #include #include /** Offset within current script * * This is a global in order to allow goto_exec() to update the * offset. */ static size_t script_offset; /** * Process script lines * * @v image Script * @v process_line Line processor * @v terminate Termination check * @ret rc Return status code */ static int process_script ( struct image *image, int ( * process_line ) ( const char *line ), int ( * terminate ) ( int rc ) ) { off_t eol; size_t len; int rc; script_offset = 0; do { /* Find length of next line, excluding any terminating '\n' */ eol = memchr_user ( image->data, script_offset, '\n', ( image->len - script_offset ) ); if ( eol < 0 ) eol = image->len; len = ( eol - script_offset ); /* Copy line, terminate with NUL, and execute command */ { char cmdbuf[ len + 1 ]; copy_from_user ( cmdbuf, image->data, script_offset, len ); cmdbuf[len] = '\0'; DBG ( "$ %s\n", cmdbuf ); /* Move to next line */ script_offset += ( len + 1 ); /* Process line */ rc = process_line ( cmdbuf ); if ( terminate ( rc ) ) return rc; } } while ( script_offset < image->len ); return rc; } /** * Terminate script processing on shell exit or command failure * * @v rc Line processing status * @ret terminate Terminate script processing */ static int terminate_on_exit_or_failure ( int rc ) { return ( shell_stopped ( SHELL_STOP_COMMAND_SEQUENCE ) || ( rc != 0 ) ); } /** * Execute script line * * @v line Line of script * @ret rc Return status code */ static int script_exec_line ( const char *line ) { int rc; /* Skip label lines */ if ( line[0] == ':' ) return 0; /* Execute command */ if ( ( rc = system ( line ) ) != 0 ) return rc; return 0; } /** * Execute script * * @v image Script * @ret rc Return status code */ static int script_exec ( struct image *image ) { size_t saved_offset; int rc; /* Temporarily de-register image, so that a "boot" command * doesn't throw us into an execution loop. */ unregister_image ( image ); /* Preserve state of any currently-running script */ saved_offset = script_offset; /* Process script */ rc = process_script ( image, script_exec_line, terminate_on_exit_or_failure ); /* Restore saved state */ script_offset = saved_offset; /* Re-register image (unless we have been replaced) */ if ( ! image->replacement ) register_image ( image ); return rc; } /** * Probe script image * * @v image Script * @ret rc Return status code */ static int script_probe ( struct image *image ) { static const char ipxe_magic[] = "#!ipxe"; static const char gpxe_magic[] = "#!gpxe"; linker_assert ( sizeof ( ipxe_magic ) == sizeof ( gpxe_magic ), magic_size_mismatch ); char test[ sizeof ( ipxe_magic ) - 1 /* NUL */ + 1 /* terminating space */]; /* Sanity check */ if ( image->len < sizeof ( test ) ) { DBG ( "Too short to be a script\n" ); return -ENOEXEC; } /* Check for magic signature */ copy_from_user ( test, image->data, 0, sizeof ( test ) ); if ( ! ( ( ( memcmp ( test, ipxe_magic, sizeof ( test ) - 1 ) == 0 ) || ( memcmp ( test, gpxe_magic, sizeof ( test ) - 1 ) == 0 )) && isspace ( test[ sizeof ( test ) - 1 ] ) ) ) { DBG ( "Invalid magic signature\n" ); return -ENOEXEC; } return 0; } /** Script image type */ struct image_type script_image_type __image_type ( PROBE_NORMAL ) = { .name = "script", .probe = script_probe, .exec = script_exec, }; /** "goto" options */ struct goto_options {}; /** "goto" option list */ static struct option_descriptor goto_opts[] = {}; /** "goto" command descriptor */ static struct command_descriptor goto_cmd = COMMAND_DESC ( struct goto_options, goto_opts, 1, 1, "